[okular] [Bug 402017] Cannot save PDF when loaded file has been deleted

Göktuğ Kayaalp bugzilla_noreply at kde.org
Sat Apr 17 23:19:36 BST 2021


https://bugs.kde.org/show_bug.cgi?id=402017

--- Comment #64 from Göktuğ Kayaalp <self at gkayaalp.com> ---
I too have encountered this bug a lot, as recent as this morning where I
almost lost a PDF I had tracked down.  I’m not knowledgeable in Qt or
C++, but I’m looking around in the codebase nevertheless, in the hopes
that I spot something useful. I see that, in document_p.h, there’s this
definition

    QVector<Page *> m_pagesVector;

which probably does hold the data necessary to save even if the original
document is gone.

Now, as an Emacs user I observe the following patterns:

- A file that looks like ‘.#<filename>’ is created, this is a lock
  file, used to prevent simultaneous editing

- Emacs listens on the target file ‘<filename>’ using file system
  notification libraries. If you edit a buffer that visits a file that
  has been edited outside of Emacs, it will query you, asking you to
  either confirm the edit, cancel the edit, or to ‘revert the buffer’
  before editing, which means to update the contents of the buffer
  re-reading the file from disk.

- When enabled, Emacs writes backup files after each save, which look
  like, without customisations, ‘<filename>~’.  This is governed by a
  variety of environment and in-Emacs variables, but the created file
  contains the version of the edited file as it was before it was saved,
  e.g.:
  - open file.txt, containing "hi"
  - append ", john"
  - save
  - file.txt~ is created, containing "hi"
  - file.txt  is overwritten, containing "hi, john"

- The contents of a buffer is separate from the contents of the file,
  the data is spared in memory even if the file is deleted, so you can
  save a buffer into a file regardless.

I doubt it’s desirable to copy this wholesale to Okular, but the
following could be done:

- Upon opening a file, it’s wholly read into a buffer as a string of
  bytes, which acts as a buffer between the Document class, and the on
  disk file. This would ensure that data is always in memory, but
  without taking up too much space, as indicated in the 53rd comment in
  the thread:

Phil 2020-08-21 11:35:55 UTC writes:
> Note: Okular takes 800 MB to render a 5.4 MB file I'm reading; keeping
> it all in memory would require *at most* 0.7 % more memory. Why not do
> that if memory is available?
(https://bugs.kde.org/show_bug.cgi?id=402017#c53)

- Okular keeps tabs on the file through filesystem notification
  libraries like inotify, kqueue, etc., and alerts the user if the
  file on disk is changed, asking them to take action.

- If the user has enabled auto-reloading the files, Okular filters for
  deletion events and apparently destructive events (i.e. new contents
  of the file do not constitute a valid document, or file is deleted, or
  new file is empty, or user does not have read/write permissions
  anymore), and the user is again queried as to what to do.

- When the user attempts to exit the application, Okular checks if the
  file is somehow destroyed or modified, and offers the user one last
  chance to record the file as it appears in Okular.

- These queries would look like the example modal below, with slight
  variation depending on the triggering event:

,----
| The file ‘/home/u/some.pdf’ has been modified outside Okular.  Before
| further modifications, you need to decide how to respond to these
| changes.
| 
| [_S_ave as a copy...]  [_C_ancel]  [Edit anyways...]  [Overwrite]
`----

- ‘Save as a copy...’ means the document as it currently is in Okular is
  saved under a new name, and Okular switches to that file for the
  current document.

- ‘Cancel’ cancels the attempted modification by the user.

- ‘Edit anyways...’ allows the user to continue editing the document,
  without creating a copy.  The user is responsible to ‘Save’ or ‘Save
  as...’ the document later.  This option is dangerous, so does not
  present a mnemonic keyboard shortcut.

- ‘Overwrite’ will overwrite the file the current document targets with
  the contents of the document as they currently appear in Okular.  This
  option too does not get a mnemonic keyboard shortcut, as it’s
  destructive.

The above would perfectly remedy the problem at hand, and below are some
possible enhancements:

- ‘VERSION_CONTROL’ and ‘SIMPLE_BACKUP_SUFFIX’ could be respected, as
  they appear in "(coreutils) Backup options" info manual
 
(https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html),
  accompanied by options in the Okular’s preferences system itself

- Even if the above is not set, Okular could preemptively store copies
  of files in a known temporary location like ~/.cache and/or /tmp; and
  use lock files and file notifications to prevent alterations to
  documents it’s displaying.

Even if this whole thing is too much, Okular keeping the binary source
file data in memory along with the costly object tree that it uses to
render the file could help with the case that bites the users most
frequently: download file through browser, which saves it in a tmp dir,
and if you exit the browser before you save a copy in okular, the
browser will remove the tmp dir, leading to this problem.

Hope this was useful as a user perspective, comparing it with software
that handles this more gracefully.  I doubt I could contribute any code
in reasonable time without extensive guidance, but I’m totally willing
to help with testing any attempts.

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the Okular-devel mailing list