diff options
author | Eike Ziller <eike.ziller@qt.io> | 2020-08-21 15:43:24 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2020-08-28 08:46:23 +0000 |
commit | cfebe5a9da85078c4dcf1500a69c212517e2c35d (patch) | |
tree | 474ce09361b0c0eae7f877a43e0f880e85b8d02f | |
parent | 30c55c063d9946de319821f52db6643a9375dc43 (diff) |
Complete documentation on IDocument
Change-Id: I72a62beaf6c8de0d2ae39a1c3c833708ca27b03f
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
-rw-r--r-- | src/plugins/coreplugin/idocument.cpp | 475 | ||||
-rw-r--r-- | src/plugins/coreplugin/idocument.h | 1 |
2 files changed, 420 insertions, 56 deletions
diff --git a/src/plugins/coreplugin/idocument.cpp b/src/plugins/coreplugin/idocument.cpp index 3e5f51cef7..4f4294d01a 100644 --- a/src/plugins/coreplugin/idocument.cpp +++ b/src/plugins/coreplugin/idocument.cpp @@ -37,25 +37,175 @@ \inheaderfile coreplugin/idocument.h \inmodule QtCreator - \brief The IDocument class describes a document that can be saved and reloaded. + \brief The IDocument class describes a document that can be saved and + reloaded. - The most common use for implementing an IDocument subclass, is as a document for an IEditor - implementation. Multiple editors can work in the same document instance, so the IDocument - subclass should hold all data and functions that are independent from the specific - IEditor instance, for example the content, highlighting information, the name of the - corresponding file, and functions for saving and reloading the file. + The class has two use cases. - Each IDocument subclass works only with the corresponding IEditor subclasses that it - was designed to work with. + \section1 Handling External Modifications + + You can implement IDocument and register instances in DocumentManager to + let it handle external modifications of a file. When the file specified with + filePath() has changed externally, the DocumentManager asks the + corresponding IDocument instance what to do via reloadBehavior(). If that + returns \c IDocument::BehaviorAsk, the user is asked if the file should be + reloaded from disk. If the user requests the reload or reloadBehavior() + returns \c IDocument::BehaviorSilent, the DocumentManager calls reload() + to initiate a reload of the file from disk. + + Core functions: setFilePath(), reload(), reloadBehavior(). + + If the content of the document can change in \QC, diverging from the + content on disk: isModified(), save(), isSaveAsAllowed(), + fallbackSaveAsPath(), fallbackSaveAsFileName(). + + \section1 Editor Document + + The most common use case for implementing an IDocument subclass is as a + document for an IEditor implementation. Multiple editor instances can work + on the same document instance, for example if the document is visible in + multiple splits simultaneously. So the IDocument subclass should hold all + data that is independent from the specific IEditor instance, for example + the content and highlighting information. + + Each IDocument subclass is only required to work with the corresponding + IEditor subclasses that it was designed to work with. + + An IDocument can either be backed by a file, or solely represent some data + in memory. Documents backed by a file are automatically added to the + DocumentManager by the EditorManager. + + Core functions: setId(), isModified(), contents(), setContents(). + + If the content of the document is backed by a file: open(), save(), + setFilePath(), mimeType(), shouldAutoSave(), setSuspendAllowed(), and + everything from \l{Handling External Modifications}. + + If the content of the document is not backed by a file: + setPreferredDisplayName(), setTemporary(). \ingroup mainclasses */ /*! - \fn QString Core::IDocument::filePath() const - Returns the absolute path of the file that this document refers to. May be empty for - non-file documents. - \sa setFilePath() + \enum IDocument::OpenResult + + The OpenResult enum describes whether a file was successfully opened. + + \value Success + The file was read successfully and can be handled by this document + type. + \value ReadError + The file could not be opened for reading, either because it does not + exist or because of missing permissions. + \value CannotHandle + This document type could not handle the file content. +*/ + +/*! + \enum IDocument::ReloadSetting + + \internal +*/ + +/*! + \enum IDocument::ChangeTrigger + + The ChangeTrigger enum describes whether a file was changed from \QC + internally or from the outside. + + \value TriggerInternal + The file was changed by \QC. + \value TriggerExternal + The file was changed from the outside. + + \sa IDocument::reloadBehavior() +*/ + +/*! + \enum IDocument::ChangeType + + The ChangeType enum describes the way in which the file changed. + + \value TypeContents + The contents of the file changed. + \value TypePermissions + The file permissions changed. + \value TypeRemoved + The file was removed. + + \sa IDocument::reloadBehavior() + \sa IDocument::reload() +*/ + +/*! + \enum IDocument::ReloadFlag + + The ReloadFlag enum describes if a file should be reloaded from disk. + + \value FlagReload + The file should be reloaded. + \value FlagIgnore + The file should not be reloaded, but the document state should + reflect the change. + + \sa IDocument::reload() +*/ + +/*! + \fn Core::IDocument::changed() + + This signal is emitted when the document's meta data, like file name or + modified state, changes. + + \sa isModified() + \sa filePath() + \sa displayName() +*/ + +/*! + \fn Core::IDocument::contentsChanged() + + This signal is emitted when the document's content changes. + + \sa contents() +*/ + +/*! + \fn Core::IDocument::mimeTypeChanged() + + This signal is emitted when the document content's MIME type changes. + + \sa mimeType() +*/ + +/*! + \fn Core::IDocument::aboutToReload() + + This signal is emitted before the document is reloaded from the backing + file. + + \sa reload() +*/ + +/*! + \fn Core::IDocument::reloadFinished(bool success) + + This signal is emitted after the document is reloaded from the backing + file, or if reloading failed. + + The success state is passed in \a success. + + \sa reload() +*/ + +/*! + \fn Core::IDocument::filePathChanged(const Utils::FilePath &oldName, const Utils::FilePath &newName) + + This signal is emitted after the file path changed from \a oldName to \a + newName. + + \sa filePath() */ using namespace Utils; @@ -86,22 +236,51 @@ public: } // namespace Internal +/*! + Creates an IDocument with \a parent. + + \note Using the \a parent for ownership of the document is generally a + bad idea if the IDocument is intended for use with IEditor. It is better to + use shared ownership in that case. +*/ IDocument::IDocument(QObject *parent) : QObject(parent), d(new Internal::IDocumentPrivate) { } +/*! + Destroys the IDocument. + If there was an auto save file for this document, it is removed. + + \sa shouldAutoSave() +*/ IDocument::~IDocument() { removeAutoSaveFile(); delete d; } +/*! + \fn void IDocument::setId(Utils::Id id) + + Sets the ID for this document type to \a id. This is coupled with the + corresponding IEditor implementation and the \l{IEditorFactory::id()}{id()} + of the IEditorFactory. If the IDocument implementation only works with a + single IEditor type, this is preferably set in the IDocuments's + constructor. + + \sa id() +*/ void IDocument::setId(Id id) { d->id = id; } +/*! + Returns the ID for this document type. + + \sa setId() +*/ Id IDocument::id() const { QTC_CHECK(d->id.isValid()); @@ -109,30 +288,30 @@ Id IDocument::id() const } /*! - \enum IDocument::OpenResult - The OpenResult enum describes whether a file was successfully opened. + The open() method is used to load the contents of a file when a document is + opened in an editor. - \value Success - The file was read successfully and can be handled by this document type. - \value ReadError - The file could not be opened for reading, either because it does not exist or - because of missing permissions. - \value CannotHandle - This document type could not handle the file content. -*/ + If the document is opened from an auto save file, \a realFileName is the + name of the auto save file that should be loaded, and \a fileName is the + file name of the resulting file. In that case, the contents of the auto + save file should be loaded, the file name of the IDocument should be set to + \a fileName, and the document state be set to modified. -/*! - * Used to load a file if this document is part of an IEditor implementation, when the editor - * is opened. - * If the editor is opened from an auto save file, \a realFileName is the name of the auto save - * that should be loaded, and \a fileName is the file name of the resulting file. - * In that case, the contents of the auto save file should be loaded, the file name of the - * IDocument should be set to \a fileName, and the document state be set to modified. - * If the editor is opened from a regular file, \a fileName and \a realFileName are the same. - * Use \a errorString to return an error message, if this document cannot handle the - * file contents. - * Returns whether the file was opened and read successfully. - */ + If the editor is opened from a regular file, \a fileName and \a + realFileName are the same. + + Use \a errorString to return an error message if this document cannot + handle the file contents. + + Returns whether the file was opened and read successfully. + + The default implementation does nothing and returns + CannotHandle. + + \sa EditorManager::open() + \sa shouldAutoSave() + \sa setFilePath() +*/ IDocument::OpenResult IDocument::open(QString *errorString, const QString &fileName, const QString &realFileName) { Q_UNUSED(errorString) @@ -141,6 +320,21 @@ IDocument::OpenResult IDocument::open(QString *errorString, const QString &fileN return OpenResult::CannotHandle; } +/*! + Saves the contents of the document to the \a fileName on disk. + + If \a autoSave is \c true, the saving is done for an auto-save, so the + document should avoid cleanups or other operations that it does for + user-requested saves. + + Use \a errorString to return an error message if saving failed. + + Returns whether saving was successful. + + The default implementation does nothing and returns \c false. + + \sa shouldAutoSave() +*/ bool IDocument::save(QString *errorString, const QString &fileName, bool autoSave) { Q_UNUSED(errorString) @@ -150,21 +344,28 @@ bool IDocument::save(QString *errorString, const QString &fileName, bool autoSav } /*! - * Returns the current contents of the document. The base implementation returns an empty - * QByteArray. - */ + Returns the current contents of the document. The default implementation + returns an empty QByteArray. + + \sa setContents() + \sa contentsChanged() +*/ QByteArray IDocument::contents() const { return QByteArray(); } /*! - Used for example by EditorManager::openEditorWithContents() to set - the \a contents of this document. + The setContents() method is for example used by + EditorManager::openEditorWithContents() to set the \a contents of this + document. Returns whether setting the contents was successful. - The base implementation does nothing and returns false. + The default implementation does nothing and returns false. + + \sa contents() + \sa EditorManager::openEditorWithContents() */ bool IDocument::setContents(const QByteArray &contents) { @@ -172,20 +373,67 @@ bool IDocument::setContents(const QByteArray &contents) return false; } +/*! + Returns the absolute path of the file that this document refers to. May be + empty for documents that are not backed by a file. + + \sa setFilePath() +*/ const Utils::FilePath &IDocument::filePath() const { return d->filePath; } -IDocument::ReloadBehavior IDocument::reloadBehavior(ChangeTrigger state, ChangeType type) const +/*! + The reloadBehavior() method is used by the DocumentManager to ask what to + do if the file backing this document has changed on disk. + + The \a trigger specifies if the change was triggered by some operation in + \QC. The \a type specifies if the file changed permissions or contents, or + was removed completely. + + Returns whether the user should be asked or the document should be + reloaded silently. + + The default implementation requests a silent reload if only the permissions + changed or if the contents have changed but the \a trigger is internal and + the document is not modified. + + \sa isModified() +*/ +IDocument::ReloadBehavior IDocument::reloadBehavior(ChangeTrigger trigger, ChangeType type) const { if (type == TypePermissions) return BehaviorSilent; - if (type == TypeContents && state == TriggerInternal && !isModified()) + if (type == TypeContents && trigger == TriggerInternal && !isModified()) return BehaviorSilent; return BehaviorAsk; } +/*! + Reloads the document from the backing file when that changed on disk. + + If \a flag is FlagIgnore the file should not actually be loaded, but the + document should reflect the change in its \l{isModified()}{modified state}. + + The \a type specifies whether only the file permissions changed or if the + contents of the file changed. + + Use \a errorString to return an error message, if this document cannot + handle the file contents. + + Returns if the file was reloaded successfully. + + The default implementation does nothing and returns \c true. + + Subclasses should emit aboutToReload() before, and reloadFinished() after + reloading the file. + + \sa isModified() + \sa aboutToReload() + \sa reloadFinished() + \sa changed() +*/ bool IDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type) { Q_UNUSED(errorString) @@ -194,35 +442,84 @@ bool IDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type) return true; } +/*! + \internal +*/ void IDocument::checkPermissions() { } +/*! + Returns whether the document should automatically be saved at a user-defined + interval. + + The default implementation returns \c false. +*/ bool IDocument::shouldAutoSave() const { return false; } +/*! + Returns whether the document has been modified after it was loaded from a + file. + + The default implementation returns \c false. Re-implementations should emit + changed() when this property changes. + + \sa changed() +*/ bool IDocument::isModified() const { return false; } +/*! + Returns whether the document may be saved under a different file name. + + The default implementation returns \c false. + + \sa save() +*/ bool IDocument::isSaveAsAllowed() const { return false; } +/*! + Returns whether the document may be suspended. + + The EditorManager can automatically suspend editors and its corresponding + documents if the document is backed by a file, is not modified, and is not + temporary. Suspended IEditor and IDocument instances are deleted and + removed from memory, but are still visually accessible as if the document + was still opened in \QC. + + The default is \c false. + + \sa setSuspendAllowed() + \sa isModified() + \sa isTemporary() +*/ bool IDocument::isSuspendAllowed() const { return d->isSuspendAllowed; } +/*! + Sets whether the document may be suspended to \a value. + + \sa isSuspendAllowed() +*/ void IDocument::setSuspendAllowed(bool value) { d->isSuspendAllowed = value; } +/*! + Returns whether the file backing this document is read-only, or \c false if + the document is not backed by a file. +*/ bool IDocument::isFileReadOnly() const { if (filePath().isEmpty()) @@ -231,8 +528,12 @@ bool IDocument::isFileReadOnly() const } /*! - Returns if the document is a temporary that should for example not be considered - when saving/restoring the session state, recent files, etc. Defaults to false. + Returns if the document is temporary, and should for example not be + considered when saving or restoring the session state, or added to the recent + files list. + + The default is \c false. + \sa setTemporary() */ bool IDocument::isTemporary() const @@ -241,7 +542,8 @@ bool IDocument::isTemporary() const } /*! - Sets if the document is \a temporary. + Sets whether the document is \a temporary. + \sa isTemporary() */ void IDocument::setTemporary(bool temporary) @@ -249,21 +551,49 @@ void IDocument::setTemporary(bool temporary) d->temporary = temporary; } +/*! + Returns a path to use for the \uicontrol{Save As} file dialog in case the + document is not backed by a file. + + \sa fallbackSaveAsFileName() +*/ QString IDocument::fallbackSaveAsPath() const { return QString(); } +/*! + Returns a file name to use for the \uicontrol{Save As} file dialog in case + the document is not backed by a file. + + \sa fallbackSaveAsPath() +*/ QString IDocument::fallbackSaveAsFileName() const { return QString(); } +/*! + Returns the MIME type of the document content, if applicable. + + Subclasses should set this with setMimeType() after setting or loading + content. + + The default MIME type is empty. + + \sa setMimeType() + \sa mimeTypeChanged() +*/ QString IDocument::mimeType() const { return d->mimeType; } +/*! + Sets the MIME type of the document content to \a mimeType. + + \sa mimeType() +*/ void IDocument::setMimeType(const QString &mimeType) { if (d->mimeType != mimeType) { @@ -272,6 +602,9 @@ void IDocument::setMimeType(const QString &mimeType) } } +/*! + \internal +*/ bool IDocument::autoSave(QString *errorString, const QString &fileName) { if (!save(errorString, fileName, true)) @@ -282,6 +615,9 @@ bool IDocument::autoSave(QString *errorString, const QString &fileName) static const char kRestoredAutoSave[] = "RestoredAutoSave"; +/*! + \internal +*/ void IDocument::setRestoredFrom(const QString &name) { d->autoSaveName = name; @@ -292,6 +628,9 @@ void IDocument::setRestoredFrom(const QString &name) infoBar()->addInfo(info); } +/*! + \internal +*/ void IDocument::removeAutoSaveFile() { if (!d->autoSaveName.isEmpty()) { @@ -304,16 +643,26 @@ void IDocument::removeAutoSaveFile() } } +/*! + \internal +*/ bool IDocument::hasWriteWarning() const { return d->hasWriteWarning; } +/*! + \internal +*/ void IDocument::setWriteWarning(bool has) { d->hasWriteWarning = has; } +/*! + Returns the document's Utils::InfoBar, which is shown at the top of an + editor. +*/ Utils::InfoBar *IDocument::infoBar() { if (!d->infoBar) @@ -322,10 +671,13 @@ Utils::InfoBar *IDocument::infoBar() } /*! - Set absolute file path for this file to \a filePath. Can be empty. - The default implementation sets the file name and sends filePathChanged() and changed() - signals. Can be reimplemented by subclasses to do more. + Sets the absolute \a filePath of the file that backs this document. The + default implementation sets the file name and sends the filePathChanged() and + changed() signals. + \sa filePath() + \sa filePathChanged() + \sa changed() */ void IDocument::setFilePath(const Utils::FilePath &filePath) { @@ -338,10 +690,10 @@ void IDocument::setFilePath(const Utils::FilePath &filePath) } /*! - Returns the string to display for this document, in the open document combo - box and pane, for example. + Returns the string to display for this document, for example in the + \uicontrol{Open Documents} view and the documents drop down. - The returned string has the following priority: + The display name is one of the following, in order: \list 1 \li Unique display name set by the document model @@ -350,6 +702,8 @@ void IDocument::setFilePath(const Utils::FilePath &filePath) \endlist \sa setPreferredDisplayName() + \sa filePath() + \sa changed() */ QString IDocument::displayName() const { @@ -357,11 +711,10 @@ QString IDocument::displayName() const } /*! - Sets the string that is displayed for this document, e.g. in the open document combo box - and pane, to \a name. Defaults to the file name of the file path for this document. - You can reset the display name to the default by passing an empty string. + Sets the preferred display \a name for this document. + + \sa preferredDisplayName() \sa displayName() - \sa filePath() */ void IDocument::setPreferredDisplayName(const QString &name) { @@ -371,6 +724,15 @@ void IDocument::setPreferredDisplayName(const QString &name) emit changed(); } +/*! + Returns the preferred display name for this document. + + The default preferred display name is empty, which means that the display + name is preferably the file name of the file backing this document. + + \sa setPreferredDisplayName() + \sa displayName() +*/ QString IDocument::preferredDisplayName() const { return d->preferredDisplayName; @@ -394,6 +756,9 @@ void IDocument::setUniqueDisplayName(const QString &name) d->uniqueDisplayName = name; } +/*! + \internal +*/ QString IDocument::uniqueDisplayName() const { return d->uniqueDisplayName; diff --git a/src/plugins/coreplugin/idocument.h b/src/plugins/coreplugin/idocument.h index c2a7e90cf8..66a95a8b49 100644 --- a/src/plugins/coreplugin/idocument.h +++ b/src/plugins/coreplugin/idocument.h @@ -88,7 +88,6 @@ public: void setId(Utils::Id id); Utils::Id id() const; - // required to be re-implemented for documents of IEditors virtual OpenResult open(QString *errorString, const QString &fileName, const QString &realFileName); virtual bool save(QString *errorString, const QString &fileName = QString(), bool autoSave = false); |