Skip to content

Prevent empty TextDocument::url()

KDevelop ensures uniqueness of its IDocument URLs by assigning the "/Untitled" or "/Untitled (N)" paths to untitled documents' URLs, where N is a unique number.

Recently implemented BreakpointModel code assumes and asserts that only an untitled KTextEditor::Document's URL is empty and that an IDocument URL is never empty.

These assumptions and assertions are broken in the following two scenarios:

  1. Open a document, modify, then reload it. Press the "Save" button in the Close Document dialog that appears.

At this point KTextEditor::DocumentPrivate::closeUrl() calls ReadOnlyPart::setUrl(QUrl()), which emits the documentUrlChanged() signal. Then the ReadOnlyPart::openUrl() call, which had invoked closeUrl(), calls setUrl(url), which emits documentUrlChanged() again, and thus restores the original document URL.

ReadOnlyPart::closeUrl() does not call setUrl() when invoked by openUrl(), because the m_closeUrlFromOpenUrl flag suppresses it. A similar flag should be introduced in KTextEditor::DocumentPrivate to prevent the problematic and pointless URL change to empty and back to the original value.

  1. Open a document, then delete the document's file externally. Press the "Close File" button in the prompt that appears above the editor.

At this point ReadOnlyPart::closeUrl() calls setUrl(QUrl()), which emits the documentUrlChanged() signal. Then the KTextEditor::DocumentPrivate::onModOnHdClose() call, which had invoked closeUrl(), schedules an invocation of KTextEditor::Application::closeDocument(), which closes the corresponding TextDocument in KDevelop. Even with this commit's workaround, there is a brief inconsistency between the TextDocument's and its KTextEditor::Document's URLs, which can cause bugs in KDevelop.

Instead of unconditionally calling closeUrl() and only then informing KDevelop about it, onModOnHdClose() should emit a signal similar to ReadWritePart::sigQueryClose() before closeUrl(). KDevelop could then abort closing in onModOnHdClose() and invoke IDocument::close() instead. IDocument::close() eventually destroys the KTextEditor::DocumentPrivate object without calling closeUrl() first, in which case ~ReadOnlyPart() calls ReadOnlyPart::closeUrl() and the documentUrlChanged() signal is not emitted.

Work most issues around by ignoring the problematic renaming to empty in TextDocument::documentUrlChanged() until KDevelop depends on a fixed KTextEditor version.

Merge request reports