저널링

버전 1.19.0부터 PDF 문서를 업데이트할 때 저널링이 가능합니다.

저널링은 PDF에 대한 변경 사항을 되돌리거나 다시 적용 할 수 있게 하는 로깅 메커니즘입니다. 현대 데이터베이스 시스템의 LUW “Logical Units of Work”와 유사하게, 일련의 업데이트를 “작업”으로 그룹화할 수 있습니다. MuPDF 저널링에서 작업은 LUW의 역할을 합니다.

참고

데이터베이스 시스템의 LUW 구현과 달리, MuPDF 저널링은 문서별 수준 에서 발생합니다. 여러 PDF에 걸친 동시 업데이트는 지원되지 않습니다. 여기서는 자체 로직을 구축해야 합니다.

  • 저널링은 문서 메서드를 통해 활성화 해야 합니다. 기존 문서나 새 문서 모두에서 저널링이 가능합니다. 저널링은 파일을 닫는 경우에만 비활성화 할 수 있습니다.

  • 활성화되면 모든 변경은 작업 내에서 발생해야 합니다. 그렇지 않으면 예외가 발생합니다. 작업은 문서 메서드를 통해 시작되고 중지됩니다. 이 두 호출 사이에 발생하는 업데이트는 LUW를 형성하므로 집합적으로 롤백하거나 다시 적용할 수 있으며, MuPDF 용어로는 각각 “실행 취소” 및 “다시 실행”입니다.

  • 언제든지 저널링 상태를 쿼리할 수 있습니다: 저널링이 활성화되어 있는지, 몇 개의 작업이 기록되었는지, “실행 취소” 또는 “다시 실행”이 가능한지, 저널 내 현재 위치 등입니다.

  • 저널은 파일에 저장 하거나 파일에서 로드 할 수 있습니다. 이것들은 문서 메서드입니다.

  • 저널 파일을 로드할 때 문서와의 호환성이 확인되며, 성공 시 저널링이 자동으로 활성화됩니다.

  • 저널링 중인 기존 PDF의 경우 특별한 새 저장 메서드인 Document.save_snapshot() 를 사용할 수 있습니다. 이것은 지금까지의 모든 저널링된 업데이트를 포함하는 특별한 증분 저장을 수행합니다. 저널이 동시에 저장되면(문서 스냅샷 직후) 문서와 저널이 동기화되어 나중에 작업을 실행 취소하거나 다시 실행하거나 저널링된 업데이트를 계속하는 데 함께 사용할 수 있습니다. 마치 중단이 없었던 것처럼.

  • 스냅샷 PDF는 모든 측면에서 유효한 PDF이며 완전히 사용 가능합니다. 하지만 저널 파일을 사용하지 않고 문서가 어떤 방식으로든 변경되면 동기화가 해제되고 저널이 사용 불가능해집니다.

  • 스냅샷 파일은 증분 업데이트처럼 구조화됩니다. 그럼에도 불구하고 내부 저널링 로직은 저장이 새 파일에 발생해야 합니다. 따라서 사용자는 원본 PDF(예: original.pdf)와 스냅샷 세트(예: original-snap1.pdf / original-snap1.log, original-snap2.pdf / original-snap2.log 등) 간의 인식 가능한 관계를 지원하는 파일 명명 규칙을 개발해야 합니다.

예제 세션 1

설명:

  • 새 PDF를 만들고 저널링을 활성화합니다. 그런 다음 페이지와 일부 텍스트 줄을 추가합니다. 각각을 별도의 작업으로 수행합니다.

  • 저널 내에서 이동하며 이러한 업데이트를 실행 취소하고 다시 실행하며 상태와 파일 결과를 표시합니다:

    >>> import pymupdf
    >>> doc=pymupdf.open()
    >>> doc.journal_enable()
    
    >>> # try update without an operation:
    >>> page = doc.new_page()
    mupdf: No journalling operation started
    ... omitted lines
    RuntimeError: No journalling operation started
    
    >>> doc.journal_start_op("op1")
    >>> page = doc.new_page()
    >>> doc.journal_stop_op()
    
    >>> doc.journal_start_op("op2")
    >>> page.insert_text((100,100), "Line 1")
    >>> doc.journal_stop_op()
    
    >>> doc.journal_start_op("op3")
    >>> page.insert_text((100,120), "Line 2")
    >>> doc.journal_stop_op()
    
    >>> doc.journal_start_op("op4")
    >>> page.insert_text((100,140), "Line 3")
    >>> doc.journal_stop_op()
    
    >>> # show position in journal
    >>> doc.journal_position()
    (4, 4)
    >>> # 4 operations recorded - positioned at bottom
    >>> # what can we do?
    >>> doc.journal_can_do()
    {'undo': True, 'redo': False}
    >>> # currently only undos are possible. Print page content:
    >>> print(page.get_text())
    Line 1
    Line 2
    Line 3
    
    >>> # undo last insert:
    >>> doc.journal_undo()
    >>> # show combined status again:
    >>> doc.journal_position();doc.journal_can_do()
    (3, 4)
    {'undo': True, 'redo': True}
    >>> print(page.get_text())
    Line 1
    Line 2
    
    >>> # our position is now second to last
    >>> # last text insertion was reverted
    >>> # but we can redo / move forward as well:
    >>> doc.journal_redo()
    >>> # our combined status:
    >>> doc.journal_position();doc.journal_can_do()
    (4, 4)
    {'undo': True, 'redo': False}
    >>> print(page.get_text())
    Line 1
    Line 2
    Line 3
    >>> # line 3 has appeared again!
    

예제 세션 2

설명:

  • 이전과 유사하지만 일부 작업을 실행 취소한 후 다른 업데이트를 추가합니다. 이것은 다음을 유발합니다:

    • 실행 취소된 저널 항목의 영구 제거

    • 새 업데이트 작업이 새로운 마지막 항목이 됩니다.

    >>> doc=pymupdf.open()
    >>> doc.journal_enable()
    >>> doc.journal_start_op("Page insert")
    >>> page=doc.new_page()
    >>> doc.journal_stop_op()
    >>> for i in range(5):
            doc.journal_start_op(f"insert-{i}")
            page.insert_text((100, 100 + 20*i), f"text line {i}")
            doc.journal_stop_op()
    
    >>> # combined status info:
    >>> doc.journal_position();doc.journal_can_do()
    (6, 6)
    {'undo': True, 'redo': False}
    
    >>> for i in range(3):  # revert last three operations
            doc.journal_undo()
    >>> doc.journal_position();doc.journal_can_do()
    (3, 6)
    {'undo': True, 'redo': True}
    
    >>> # now do a different update:
    >>> doc.journal_start_op("Draw some line")
    >>> page.draw_line((100,150), (300,150))
    Point(300.0, 150.0)
    >>> doc.journal_stop_op()
    >>> doc.journal_position();doc.journal_can_do()
    (4, 4)
    {'undo': True, 'redo': False}
    
    >>> # this has changed the journal:
    >>> # previous last 3 text line operations were removed, and
    >>> # we have only 4 operations: drawing the line is the new last one
    

This software is provided AS-IS with no warranty, either express or implied. This software is distributed under license and may not be copied, modified or distributed except as expressly authorized under the terms of that license. Refer to licensing information at artifex.com or contact Artifex Software Inc., 39 Mesa Street, Suite 108A, San Francisco CA 94129, United States for further information.