diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp index d70aa77cdf7..ae0f5362ce4 100644 --- a/src/plugins/bineditor/bineditorplugin.cpp +++ b/src/plugins/bineditor/bineditorplugin.cpp @@ -97,21 +97,20 @@ public: return type == TypeRemoved ? BehaviorSilent : IDocument::reloadBehavior(state, type); } - OpenResult open(QString *errorString, const FilePath &filePath, - const FilePath &realFilePath) final + OpenResult open(const FilePath &filePath, const FilePath &realFilePath) final { QTC_CHECK(filePath == realFilePath); // The bineditor can do no autosaving - return openImpl(errorString, filePath); + return openImpl(filePath); } - OpenResult openImpl(QString *errorString, const FilePath &filePath, quint64 offset = 0); + OpenResult openImpl(const FilePath &filePath, quint64 offset = 0); void provideData(quint64 address); void provideNewRange(quint64 offset) { if (filePath().exists()) - openImpl(nullptr, filePath(), offset); + openImpl(filePath(), offset); } bool isModified() const final; @@ -2119,36 +2118,27 @@ bool BinEditorDocument::setContents(const QByteArray &contents) return true; } -IDocument::OpenResult BinEditorDocument::openImpl(QString *errorString, const FilePath &filePath, quint64 offset) +IDocument::OpenResult BinEditorDocument::openImpl(const FilePath &filePath, quint64 offset) { const qint64 size = filePath.fileSize(); if (size < 0) { QString msg = Tr::tr("Cannot open %1: %2").arg(filePath.toUserOutput(), Tr::tr("File Error")); // FIXME: Was: file.errorString(), but we don't have a file anymore. - if (errorString) - *errorString = msg; - else - QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg); - return OpenResult::ReadError; + QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg); + return {OpenResult::ReadError, msg}; } if (size == 0) { QString msg = Tr::tr("The Binary Editor cannot open empty files."); - if (errorString) - *errorString = msg; - else - QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg); - return OpenResult::CannotHandle; + QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg); + return {OpenResult::CannotHandle, msg}; } if (size / 16 >= qint64(1) << 31) { // The limit is 2^31 lines (due to QText* interfaces) * 16 bytes per line. QString msg = Tr::tr("The file is too big for the Binary Editor (max. 32GB)."); - if (errorString) - *errorString = msg; - else - QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg); - return OpenResult::CannotHandle; + QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg); + return {OpenResult::CannotHandle, msg}; } if (offset >= quint64(size)) @@ -2189,10 +2179,9 @@ Result<> BinEditorDocument::reload(ReloadFlag flag, ChangeType type) return ResultOk; emit aboutToReload(); clear(); - QString errorString; - const bool success = (openImpl(&errorString, filePath()) == OpenResult::Success); - emit reloadFinished(success); - return makeResult(success, errorString); + const OpenResult result = openImpl(filePath()); + emit reloadFinished(result.code == OpenResult::Success); + return result; } Result<> BinEditorDocument::saveImpl(const FilePath &filePath, bool autoSave) diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index d15e50fc8df..3d2ac617bc7 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -140,8 +140,7 @@ void ClangFormatConfigWidget::initEditor() Core::IEditorFactory *factory = factories.takeFirst(); m_editor.reset(factory->createEditor()); - QString errorString; - m_editor->document()->open(&errorString, m_config->filePath(), m_config->filePath()); + m_editor->document()->open(m_config->filePath(), m_config->filePath()); m_editor->widget()->adjustSize(); invokeMethodForLanguageClientManager("documentOpened", @@ -273,9 +272,8 @@ void ClangFormatConfigWidget::reopenClangFormatDocument() { GuardLocker locker(m_ignoreChanges); - QString errorString; - if (m_editor->document()->open(&errorString, m_config->filePath(), m_config->filePath()) - == Core::IDocument::OpenResult::Success) { + if (m_editor->document()->open(m_config->filePath(), m_config->filePath()).code + == Core::IDocument::OpenResult::Success) { invokeMethodForLanguageClientManager("documentOpened", Q_ARG(Core::IDocument *, m_editor->document())); } diff --git a/src/plugins/compilerexplorer/compilerexplorereditor.cpp b/src/plugins/compilerexplorer/compilerexplorereditor.cpp index 2ea71e12f4b..6020e1a65bb 100644 --- a/src/plugins/compilerexplorer/compilerexplorereditor.cpp +++ b/src/plugins/compilerexplorer/compilerexplorereditor.cpp @@ -147,11 +147,11 @@ private: class JsonSettingsDocument : public Core::IDocument { Q_OBJECT + public: JsonSettingsDocument(QUndoStack *undoStack); - OpenResult open(QString *errorString, - const Utils::FilePath &filePath, + OpenResult open(const Utils::FilePath &filePath, const Utils::FilePath &realFilePath) override; Result<> saveImpl(const Utils::FilePath &filePath, bool autoSave) override; @@ -380,26 +380,19 @@ JsonSettingsDocument::JsonSettingsDocument(QUndoStack *undoStack) m_ceSettings.setUndoStack(undoStack); } -Core::IDocument::OpenResult JsonSettingsDocument::open(QString *errorString, - const FilePath &filePath, - const FilePath &realFilePath) +IDocument::OpenResult JsonSettingsDocument::open(const FilePath &filePath, + const FilePath &realFilePath) { if (!filePath.isReadableFile()) return OpenResult::ReadError; - auto contents = realFilePath.fileContents(); - if (!contents) { - if (errorString) - *errorString = contents.error(); - return OpenResult::ReadError; - } + Result contents = realFilePath.fileContents(); + if (!contents) + return {OpenResult::ReadError, contents.error()}; - auto result = storeFromJson(*contents); - if (!result) { - if (errorString) - *errorString = result.error(); - return OpenResult::ReadError; - } + Result result = storeFromJson(*contents); + if (!result) + return {OpenResult::ReadError, result.error()}; setFilePath(filePath); diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index ceed445d0d9..3985f1ac16f 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -903,15 +903,14 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file factory = factories.isEmpty() ? nullptr : factories.takeFirst(); continue; } - IDocument::OpenResult openResult = editor->document()->open(&errorString, - filePath, - realFp); - if (openResult == IDocument::OpenResult::Success) + IDocument::OpenResult openResult = editor->document()->open(filePath, realFp); + if (openResult.code == IDocument::OpenResult::Success) break; + errorString = openResult.error; overrideCursor.reset(); delete editor; editor = nullptr; - if (openResult == IDocument::OpenResult::ReadError) { + if (openResult.code == IDocument::OpenResult::ReadError) { QMessageBox msgbox(QMessageBox::Critical, ::Core::Tr::tr("File Error"), ::Core::Tr::tr("Could not open \"%1\" for reading. " @@ -924,7 +923,7 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file return nullptr; } // can happen e.g. when trying to open an completely empty .qrc file - QTC_CHECK(openResult == IDocument::OpenResult::CannotHandle); + QTC_CHECK(openResult.code == IDocument::OpenResult::CannotHandle); } else { QTC_ASSERT(factory->isExternalEditor(), factory = factories.isEmpty() ? nullptr : factories.takeFirst(); @@ -3019,7 +3018,7 @@ void EditorManager::runWithTemporaryEditor(const Utils::FilePath &filePath, if (!editor) continue; editor->document()->setTemporary(true); - if (editor->document()->open(nullptr, filePath, filePath) != IDocument::OpenResult::Success) + if (editor->document()->open(filePath, filePath).code != IDocument::OpenResult::Success) continue; callback(editor.get()); break; diff --git a/src/plugins/coreplugin/idocument.cpp b/src/plugins/coreplugin/idocument.cpp index fe1ab0d8995..3774e2ad929 100644 --- a/src/plugins/coreplugin/idocument.cpp +++ b/src/plugins/coreplugin/idocument.cpp @@ -315,9 +315,8 @@ Id IDocument::id() const \sa shouldAutoSave() \sa setFilePath() */ -IDocument::OpenResult IDocument::open(QString *errorString, const Utils::FilePath &filePath, const Utils::FilePath &realFilePath) +IDocument::OpenResult IDocument::open(const FilePath &filePath, const FilePath &realFilePath) { - Q_UNUSED(errorString) Q_UNUSED(filePath) Q_UNUSED(realFilePath) return OpenResult::CannotHandle; @@ -808,4 +807,9 @@ QString IDocument::uniqueDisplayName() const return d->uniqueDisplayName; } +IDocument::OpenResult::operator Result<>() const +{ + return makeResult(code == Success, error); +} + } // namespace Core diff --git a/src/plugins/coreplugin/idocument.h b/src/plugins/coreplugin/idocument.h index 58a903464a7..b28ef20094f 100644 --- a/src/plugins/coreplugin/idocument.h +++ b/src/plugins/coreplugin/idocument.h @@ -26,10 +26,23 @@ class CORE_EXPORT IDocument : public QObject Q_OBJECT public: - enum class OpenResult { - Success, - ReadError, - CannotHandle + class OpenResult + { + public: + enum Code { + Success, + ReadError, + CannotHandle + }; + + OpenResult() = default; + OpenResult(Code code) : code(code) {} + OpenResult(Code code, const QString &error) : code(code), error(error) {} + + operator Utils::Result<>() const; + + Code code; + QString error; }; // This enum must match the indexes of the reloadBehavior widget @@ -66,7 +79,7 @@ public: void setId(Utils::Id id); Utils::Id id() const; - virtual OpenResult open(QString *errorString, const Utils::FilePath &filePath, const Utils::FilePath &realFilePath); + virtual OpenResult open(const Utils::FilePath &filePath, const Utils::FilePath &realFilePath); Utils::Result<> save(const Utils::FilePath &filePath = {}, bool autoSave = false); diff --git a/src/plugins/cppeditor/cpppointerdeclarationformatter_test.cpp b/src/plugins/cppeditor/cpppointerdeclarationformatter_test.cpp index e6c9fc4f624..39c11c65f95 100644 --- a/src/plugins/cppeditor/cpppointerdeclarationformatter_test.cpp +++ b/src/plugins/cppeditor/cpppointerdeclarationformatter_test.cpp @@ -82,9 +82,8 @@ public: // Open file QScopedPointer editor(TextEditor::createPlainTextEditor()); - QString error; - editor->document()->open(&error, document->filePath(), document->filePath()); - QVERIFY(error.isEmpty()); + Core::IDocument::OpenResult res = editor->document()->open(document->filePath(), document->filePath()); + QVERIFY(res.error.isEmpty()); // Set cursor position QTextCursor cursor = editor->textCursor(); diff --git a/src/plugins/designer/formwindowfile.cpp b/src/plugins/designer/formwindowfile.cpp index d238a4002a4..b3b1bf10c17 100644 --- a/src/plugins/designer/formwindowfile.cpp +++ b/src/plugins/designer/formwindowfile.cpp @@ -19,10 +19,10 @@ #include #include +using namespace Core; using namespace Utils; -namespace Designer { -namespace Internal { +namespace Designer::Internal { FormWindowFile::FormWindowFile(QDesignerFormWindowInterface *form, QObject *parent) : m_formWindow(form) @@ -43,9 +43,8 @@ FormWindowFile::FormWindowFile(QDesignerFormWindowInterface *form, QObject *pare m_resourceHandler, &ResourceHandler::updateResources); } -Core::IDocument::OpenResult FormWindowFile::open(QString *errorString, - const Utils::FilePath &filePath, - const Utils::FilePath &realFilePath) +IDocument::OpenResult FormWindowFile::open(const FilePath &filePath, + const FilePath &realFilePath) { if (Designer::Constants::Internal::debug) qDebug() << "FormWindowFile::open" << filePath.toUserOutput(); @@ -57,21 +56,22 @@ Core::IDocument::OpenResult FormWindowFile::open(QString *errorString, return OpenResult::ReadError; QString contents; - Utils::TextFileFormat::ReadResult readResult = read(filePath.absoluteFilePath(), - &contents, - errorString); + QString errorString; + TextFileFormat::ReadResult readResult = read(filePath.absoluteFilePath(), + &contents, + &errorString); if (readResult == Utils::TextFileFormat::ReadEncodingError) - return OpenResult::CannotHandle; + return {OpenResult::CannotHandle, errorString}; if (readResult != Utils::TextFileFormat::ReadSuccess) - return OpenResult::ReadError; + return {OpenResult::ReadError, errorString}; form->setFileName(filePath.absoluteFilePath().toUrlishString()); const QByteArray contentsBA = contents.toUtf8(); QBuffer str; str.setData(contentsBA); str.open(QIODevice::ReadOnly); - if (!form->setContents(&str, errorString)) - return OpenResult::CannotHandle; + if (!form->setContents(&str, &errorString)) + return {OpenResult::CannotHandle, errorString}; form->setDirty(filePath != realFilePath); syncXmlFromFormWindow(); @@ -201,11 +201,9 @@ Result<> FormWindowFile::reload(ReloadFlag flag, ChangeType type) return ResultOk; } else { emit aboutToReload(); - QString errorString; - const bool success - = (open(&errorString, filePath(), filePath()) == OpenResult::Success); - emit reloadFinished(success); - return makeResult(success, errorString); + const OpenResult result = open(filePath(), filePath()); + emit reloadFinished(result.code == OpenResult::Success); + return result; } } @@ -269,5 +267,4 @@ void FormWindowFile::slotFormWindowRemoved(QDesignerFormWindowInterface *w) m_formWindow = nullptr; } -} // namespace Internal -} // namespace Designer +} // namespace Designer::Internal diff --git a/src/plugins/designer/formwindowfile.h b/src/plugins/designer/formwindowfile.h index 289b338cec6..2a74c766518 100644 --- a/src/plugins/designer/formwindowfile.h +++ b/src/plugins/designer/formwindowfile.h @@ -26,7 +26,7 @@ public: ~FormWindowFile() override { } // IDocument - OpenResult open(QString *errorString, const Utils::FilePath &filePath, + OpenResult open(const Utils::FilePath &filePath, const Utils::FilePath &realFilePath) override; QByteArray contents() const override; bool setContents(const QByteArray &contents) override; diff --git a/src/plugins/diffeditor/diffeditordocument.cpp b/src/plugins/diffeditor/diffeditordocument.cpp index 62176d3618b..fa9fc47bcfa 100644 --- a/src/plugins/diffeditor/diffeditordocument.cpp +++ b/src/plugins/diffeditor/diffeditordocument.cpp @@ -262,28 +262,26 @@ Result<> DiffEditorDocument::reload(ReloadFlag flag, ChangeType type) Q_UNUSED(type) if (flag == FlagIgnore) return ResultOk; - QString errorString; - bool success = open(&errorString, filePath(), filePath()) == OpenResult::Success; - return makeResult(success, errorString); + return open(filePath(), filePath()); } -Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const FilePath &filePath, - const FilePath &realFilePath) +IDocument::OpenResult DiffEditorDocument::open(const FilePath &filePath, const FilePath &realFilePath) { QTC_CHECK(filePath == realFilePath); // does not support autosave beginReload(); QString patch; - ReadResult readResult = read(filePath, &patch, errorString); + QString errorString; + ReadResult readResult = read(filePath, &patch, &errorString); if (readResult == TextFileFormat::ReadIOError || readResult == TextFileFormat::ReadMemoryAllocationError) { - return OpenResult::ReadError; + return {OpenResult::ReadError, errorString}; } const std::optional> fileDataList = DiffUtils::readPatch(patch); bool ok = fileDataList.has_value(); if (!ok) { - *errorString = Tr::tr("Could not parse patch file \"%1\". " - "The content is not of unified diff format.") + errorString = Tr::tr("Could not parse patch file \"%1\". " + "The content is not of unified diff format.") .arg(filePath.toUserOutput()); } else { setTemporary(false); @@ -295,7 +293,9 @@ Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const endReload(ok); if (!ok && readResult == TextFileFormat::ReadEncodingError) ok = selectEncoding(); - return ok ? OpenResult::Success : OpenResult::CannotHandle; + if (!ok) + return {OpenResult::CannotHandle, errorString}; + return OpenResult::Success; } bool DiffEditorDocument::selectEncoding() diff --git a/src/plugins/diffeditor/diffeditordocument.h b/src/plugins/diffeditor/diffeditordocument.h index 7a736ff929b..5c03c5ec01a 100644 --- a/src/plugins/diffeditor/diffeditordocument.h +++ b/src/plugins/diffeditor/diffeditordocument.h @@ -62,7 +62,7 @@ public: bool isSaveAsAllowed() const override; void reload(); Utils::Result<> reload(ReloadFlag flag, ChangeType type) override; - OpenResult open(QString *errorString, const Utils::FilePath &filePath, + OpenResult open(const Utils::FilePath &filePath, const Utils::FilePath &realFilePath) override; bool selectEncoding(); State state() const { return m_state; } diff --git a/src/plugins/imageviewer/imageviewerfile.cpp b/src/plugins/imageviewer/imageviewerfile.cpp index 9eeee463951..b11b6a1a992 100644 --- a/src/plugins/imageviewer/imageviewerfile.cpp +++ b/src/plugins/imageviewer/imageviewerfile.cpp @@ -25,6 +25,7 @@ #include #endif +using namespace Core; using namespace Utils; namespace ImageViewer::Internal { @@ -63,18 +64,15 @@ ImageViewerFile::~ImageViewerFile() cleanUp(); } -Core::IDocument::OpenResult ImageViewerFile::open(QString *errorString, - const Utils::FilePath &filePath, - const Utils::FilePath &realfilePath) +IDocument::OpenResult ImageViewerFile::open(const FilePath &filePath, const FilePath &realfilePath) { QTC_CHECK(filePath == realfilePath); // does not support auto save - OpenResult success = openImpl(errorString, filePath); - emit openFinished(success == OpenResult::Success); - return success; + OpenResult res = openImpl(filePath); + emit openFinished(res.code == OpenResult::Success); + return res; } -Core::IDocument::OpenResult ImageViewerFile::openImpl(QString *errorString, - const Utils::FilePath &filePath) +IDocument::OpenResult ImageViewerFile::openImpl(const FilePath &filePath) { cleanUp(); @@ -84,11 +82,8 @@ Core::IDocument::OpenResult ImageViewerFile::openImpl(QString *errorString, const QString &fileName = filePath.toUrlishString(); QByteArray format = QImageReader::imageFormat(fileName); // if it is impossible to recognize a file format - file will not be open correctly - if (format.isEmpty()) { - if (errorString) - *errorString = Tr::tr("Image format not supported."); - return OpenResult::CannotHandle; - } + if (format.isEmpty()) + return {OpenResult::CannotHandle, Tr::tr("Image format not supported.")}; #ifndef QT_NO_SVG if (format.startsWith("svg")) { @@ -97,9 +92,7 @@ Core::IDocument::OpenResult ImageViewerFile::openImpl(QString *errorString, if (!bound.isValid() || (qFuzzyIsNull(bound.width()) && qFuzzyIsNull(bound.height()))) { delete m_tempSvgItem; m_tempSvgItem = nullptr; - if (errorString) - *errorString = Tr::tr("Failed to read SVG image."); - return OpenResult::CannotHandle; + return {OpenResult::CannotHandle, Tr::tr("Failed to read SVG image.")}; } m_type = TypeSvg; emit imageSizeChanged(m_tempSvgItem->boundingRect().size().toSize()); @@ -110,11 +103,9 @@ Core::IDocument::OpenResult ImageViewerFile::openImpl(QString *errorString, // force reading movie/image data, so we can catch completely invalid movies/images early: m_movie->jumpToNextFrame(); if (!m_movie->isValid()) { - if (errorString) - *errorString = Tr::tr("Failed to read image."); delete m_movie; m_movie = nullptr; - return OpenResult::CannotHandle; + return {OpenResult::CannotHandle, Tr::tr("Failed to read image.")}; } m_type = TypeMovie; connect(m_movie, &QMovie::resized, this, &ImageViewerFile::imageSizeChanged); @@ -122,11 +113,9 @@ Core::IDocument::OpenResult ImageViewerFile::openImpl(QString *errorString, } else { m_pixmap = new QPixmap(fileName); if (m_pixmap->isNull()) { - if (errorString) - *errorString = Tr::tr("Failed to read image."); delete m_pixmap; m_pixmap = nullptr; - return OpenResult::CannotHandle; + return {OpenResult::CannotHandle, Tr::tr("Failed to read image.")}; } m_type = TypePixmap; emit imageSizeChanged(m_pixmap->size()); @@ -146,17 +135,15 @@ Core::IDocument::ReloadBehavior ImageViewerFile::reloadBehavior(ChangeTrigger st return BehaviorAsk; } -Result<> ImageViewerFile::reload(Core::IDocument::ReloadFlag flag, - Core::IDocument::ChangeType type) +Result<> ImageViewerFile::reload(IDocument::ReloadFlag flag, IDocument::ChangeType type) { Q_UNUSED(type) if (flag == FlagIgnore) return ResultOk; emit aboutToReload(); - QString errorString; - bool success = (openImpl(&errorString, filePath()) == OpenResult::Success); - emit reloadFinished(success); - return makeResult(success, errorString); + const OpenResult result = openImpl(filePath()); + emit reloadFinished( result.code == OpenResult::Success); + return result; } QMovie *ImageViewerFile::movie() const diff --git a/src/plugins/imageviewer/imageviewerfile.h b/src/plugins/imageviewer/imageviewerfile.h index e4cc432651d..ea562341107 100644 --- a/src/plugins/imageviewer/imageviewerfile.h +++ b/src/plugins/imageviewer/imageviewerfile.h @@ -35,8 +35,7 @@ public: ImageViewerFile(); ~ImageViewerFile() override; - OpenResult open(QString *errorString, const Utils::FilePath &filePath, - const Utils::FilePath &realFilePath) override; + OpenResult open(const Utils::FilePath &filePath, const Utils::FilePath &realFilePath) override; ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override; Utils::Result<> reload(ReloadFlag flag, ChangeType type) override; @@ -55,7 +54,7 @@ signals: private: void cleanUp(); - OpenResult openImpl(QString *errorString, const Utils::FilePath &filePath); + OpenResult openImpl(const Utils::FilePath &filePath); ImageType m_type = TypeInvalid; #ifndef QT_NO_SVG diff --git a/src/plugins/modeleditor/modeldocument.cpp b/src/plugins/modeleditor/modeldocument.cpp index 3497d597f5b..980feff3fe3 100644 --- a/src/plugins/modeleditor/modeldocument.cpp +++ b/src/plugins/modeleditor/modeldocument.cpp @@ -19,10 +19,10 @@ using namespace Utils; -namespace ModelEditor { -namespace Internal { +namespace ModelEditor::Internal { -class ModelDocument::ModelDocumentPrivate { +class ModelDocument::ModelDocumentPrivate +{ public: ExtDocumentController *documentController = nullptr; }; @@ -42,13 +42,12 @@ ModelDocument::~ModelDocument() delete d; } -Core::IDocument::OpenResult ModelDocument::open(QString *errorString, - const FilePath &filePath, +Core::IDocument::OpenResult ModelDocument::open(const FilePath &filePath, const FilePath &realFilePath) { Q_UNUSED(filePath) - OpenResult result = load(errorString, realFilePath); + OpenResult result = load(realFilePath); return result; } @@ -112,7 +111,7 @@ ExtDocumentController *ModelDocument::documentController() const return d->documentController; } -Core::IDocument::OpenResult ModelDocument::load(QString *errorString, const FilePath &fileName) +Core::IDocument::OpenResult ModelDocument::load(const FilePath &fileName) { d->documentController = ModelEditorPlugin::modelsManager()->createModel(this); connect(d->documentController, &qmt::DocumentController::changed, this, &IDocument::changed); @@ -121,11 +120,11 @@ Core::IDocument::OpenResult ModelDocument::load(QString *errorString, const File d->documentController->loadProject(fileName); setFilePath(d->documentController->projectController()->project()->fileName()); } catch (const qmt::FileNotFoundException &ex) { - *errorString = ex.errorMessage(); - return OpenResult::ReadError; + return {OpenResult::ReadError, ex.errorMessage()}; } catch (const qmt::Exception &ex) { - *errorString = Tr::tr("Could not open \"%1\" for reading: %2.").arg(fileName.toUserOutput(), ex.errorMessage()); - return OpenResult::CannotHandle; + return {OpenResult::CannotHandle, + Tr::tr("Could not open \"%1\" for reading: %2.") + .arg(fileName.toUserOutput(), ex.errorMessage())}; } FilePath configPath = d->documentController->projectController()->project()->configPath(); @@ -143,5 +142,4 @@ Core::IDocument::OpenResult ModelDocument::load(QString *errorString, const File return OpenResult::Success; } -} // namespace Internal -} // namespace ModelEditor +} // namespace ModelEditor::Internal diff --git a/src/plugins/modeleditor/modeldocument.h b/src/plugins/modeleditor/modeldocument.h index f36a32db80c..d6a06594db0 100644 --- a/src/plugins/modeleditor/modeldocument.h +++ b/src/plugins/modeleditor/modeldocument.h @@ -8,8 +8,7 @@ namespace qmt { class Uid; } -namespace ModelEditor { -namespace Internal { +namespace ModelEditor::Internal { class ExtDocumentController; @@ -27,8 +26,7 @@ signals: void contentSet(); public: - OpenResult open(QString *errorString, - const Utils::FilePath &filePath, + OpenResult open(const Utils::FilePath &filePath, const Utils::FilePath &realFilePath) override; bool shouldAutoSave() const override; bool isModified() const override; @@ -37,7 +35,7 @@ public: ExtDocumentController *documentController() const; - OpenResult load(QString *errorString, const Utils::FilePath &fileName); + OpenResult load(const Utils::FilePath &fileName); protected: Utils::Result<> saveImpl(const Utils::FilePath &filePath, bool autoSave) override; @@ -46,5 +44,4 @@ private: ModelDocumentPrivate *d; }; -} // namespace Internal -} // namespace ModelEditor +} // namespace ModelEditor::Internal diff --git a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp index dae3bd562aa..c8e74c8c9ac 100644 --- a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp +++ b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp @@ -1081,7 +1081,7 @@ Core::IDocument::OpenResult ResourceModel::reload() { beginResetModel(); Core::IDocument::OpenResult result = m_resource_file.load(); - if (result == Core::IDocument::OpenResult::Success) + if (result.code == Core::IDocument::OpenResult::Success) setDirty(false); endResetModel(); return result; diff --git a/src/plugins/resourceeditor/resourceeditor.cpp b/src/plugins/resourceeditor/resourceeditor.cpp index 297cf682933..463927b64c8 100644 --- a/src/plugins/resourceeditor/resourceeditor.cpp +++ b/src/plugins/resourceeditor/resourceeditor.cpp @@ -48,8 +48,7 @@ class ResourceEditorDocument final : public IDocument public: ResourceEditorDocument(QObject *parent = nullptr); - OpenResult open(QString *errorString, const FilePath &filePath, - const FilePath &realFilePath) final; + OpenResult open(const FilePath &filePath, const FilePath &realFilePath) final; QString plainText() const { return m_model.contents(); } QByteArray contents() const final { return m_model.contents().toUtf8(); } bool setContents(const QByteArray &contents) final; @@ -180,8 +179,7 @@ ResourceEditorImpl::~ResourceEditorImpl() delete m_toolBar; } -IDocument::OpenResult ResourceEditorDocument::open(QString *errorString, - const FilePath &filePath, +IDocument::OpenResult ResourceEditorDocument::open(const FilePath &filePath, const FilePath &realFilePath) { if (debugResourceEditorW) @@ -192,9 +190,8 @@ IDocument::OpenResult ResourceEditorDocument::open(QString *errorString, m_model.setFilePath(realFilePath); OpenResult openResult = m_model.reload(); - if (openResult != OpenResult::Success) { - if (errorString) - *errorString = m_model.errorMessage(); + if (openResult.code != OpenResult::Success) { + openResult.error = m_model.errorMessage(); setBlockDirtyChanged(false); emit loaded(false); return openResult; @@ -249,7 +246,7 @@ bool ResourceEditorDocument::setContents(const QByteArray &contents) const FilePath originalFileName = m_model.filePath(); m_model.setFilePath(saver.filePath()); - const bool success = (m_model.reload() == OpenResult::Success); + const bool success = (m_model.reload().code == OpenResult::Success); m_model.setFilePath(originalFileName); m_shouldAutoSave = false; if (debugResourceEditorW) @@ -286,10 +283,9 @@ Result<> ResourceEditorDocument::reload(ReloadFlag flag, ChangeType type) if (flag == FlagIgnore) return ResultOk; emit aboutToReload(); - QString errorString; - const bool success = (open(&errorString, filePath(), filePath()) == OpenResult::Success); - emit reloadFinished(success); - return makeResult(success, errorString); + const OpenResult result = open(filePath(), filePath()); + emit reloadFinished(result.code == OpenResult::Success); + return result; } void ResourceEditorDocument::dirtyChanged(bool dirty) diff --git a/src/plugins/resourceeditor/resourcenode.cpp b/src/plugins/resourceeditor/resourcenode.cpp index d27a7cb992c..5411ac9a0f7 100644 --- a/src/plugins/resourceeditor/resourcenode.cpp +++ b/src/plugins/resourceeditor/resourcenode.cpp @@ -121,7 +121,7 @@ static bool addFilesToResource(const FilePath &resourceFile, *notAdded = filePaths; ResourceFile file(resourceFile); - if (file.load() != IDocument::OpenResult::Success) + if (file.load().code != IDocument::OpenResult::Success) return false; int index = file.indexOfPrefix(prefix, lang); @@ -272,7 +272,7 @@ static void compressTree(FolderNode *n) void ResourceTopLevelNode::addInternalNodes() { ResourceFile file(filePath(), m_contents); - if (file.load() != IDocument::OpenResult::Success) + if (file.load().code != IDocument::OpenResult::Success) return; QMap folderNodes; @@ -382,7 +382,7 @@ RemovedFilesFromProject ResourceTopLevelNode::removeFiles(const FilePaths &fileP bool ResourceTopLevelNode::addPrefix(const QString &prefix, const QString &lang) { ResourceFile file(filePath()); - if (file.load() != IDocument::OpenResult::Success) + if (file.load().code != IDocument::OpenResult::Success) return false; int index = file.addPrefix(prefix, lang); if (index == -1) @@ -395,7 +395,7 @@ bool ResourceTopLevelNode::addPrefix(const QString &prefix, const QString &lang) bool ResourceTopLevelNode::removePrefix(const QString &prefix, const QString &lang) { ResourceFile file(filePath()); - if (file.load() != IDocument::OpenResult::Success) + if (file.load().code != IDocument::OpenResult::Success) return false; for (int i = 0; i < file.prefixCount(); ++i) { if (file.prefix(i) == prefix @@ -411,7 +411,7 @@ bool ResourceTopLevelNode::removePrefix(const QString &prefix, const QString &la bool ResourceTopLevelNode::removeNonExistingFiles() { ResourceFile file(filePath()); - if (file.load() != IDocument::OpenResult::Success) + if (file.load().code != IDocument::OpenResult::Success) return false; QFileInfo fi; @@ -490,7 +490,7 @@ RemovedFilesFromProject ResourceFolderNode::removeFiles(const FilePaths &filePat if (notRemoved) *notRemoved = filePaths; ResourceFile file(m_topLevelNode->filePath()); - if (file.load() != IDocument::OpenResult::Success) + if (file.load().code != IDocument::OpenResult::Success) return RemovedFilesFromProject::Error; int index = file.indexOfPrefix(m_prefix, m_lang); if (index == -1) @@ -518,7 +518,8 @@ bool ResourceFolderNode::canRenameFile(const FilePath &oldFilePath, const FilePa bool fileEntryExists = false; ResourceFile file(m_topLevelNode->filePath()); - int index = (file.load() != IDocument::OpenResult::Success) ? -1 :file.indexOfPrefix(m_prefix, m_lang); + int index = (file.load().code != IDocument::OpenResult::Success) + ? -1 : file.indexOfPrefix(m_prefix, m_lang); if (index != -1) { for (int j = 0; j < file.fileCount(index); ++j) { if (file.file(index, j) == oldFilePath.toUrlishString()) { @@ -534,7 +535,7 @@ bool ResourceFolderNode::canRenameFile(const FilePath &oldFilePath, const FilePa bool ResourceFolderNode::renameFiles(const FilePairs &filesToRename, FilePaths *notRenamed) { ResourceFile file(m_topLevelNode->filePath()); - if (file.load() != IDocument::OpenResult::Success) + if (file.load().code != IDocument::OpenResult::Success) return false; int index = file.indexOfPrefix(m_prefix, m_lang); if (index == -1) @@ -566,7 +567,7 @@ bool ResourceFolderNode::renameFiles(const FilePairs &filesToRename, FilePaths * bool ResourceFolderNode::renamePrefix(const QString &prefix, const QString &lang) { ResourceFile file(m_topLevelNode->filePath()); - if (file.load() != IDocument::OpenResult::Success) + if (file.load().code != IDocument::OpenResult::Success) return false; int index = file.indexOfPrefix(m_prefix, m_lang); if (index == -1) diff --git a/src/plugins/scxmleditor/scxmleditordocument.cpp b/src/plugins/scxmleditor/scxmleditordocument.cpp index 3102e8008b5..4eff969c391 100644 --- a/src/plugins/scxmleditor/scxmleditordocument.cpp +++ b/src/plugins/scxmleditor/scxmleditordocument.cpp @@ -18,7 +18,8 @@ using namespace Utils; using namespace ScxmlEditor::Common; -using namespace ScxmlEditor::Internal; + +namespace ScxmlEditor::Internal { ScxmlEditorDocument::ScxmlEditorDocument(MainWidget *designWidget, QObject *parent) : m_designWidget(designWidget) @@ -34,9 +35,8 @@ ScxmlEditorDocument::ScxmlEditorDocument(MainWidget *designWidget, QObject *pare }); } -Core::IDocument::OpenResult ScxmlEditorDocument::open(QString *errorString, - const Utils::FilePath &filePath, - const Utils::FilePath &realFilePath) +Core::IDocument::OpenResult ScxmlEditorDocument::open(const FilePath &filePath, + const FilePath &realFilePath) { Q_UNUSED(realFilePath) @@ -47,10 +47,8 @@ Core::IDocument::OpenResult ScxmlEditorDocument::open(QString *errorString, return OpenResult::ReadError; const FilePath &absoluteFilePath = filePath.absoluteFilePath(); - if (!m_designWidget->load(absoluteFilePath.toUrlishString())) { - *errorString = m_designWidget->errorMessage(); - return OpenResult::ReadError; - } + if (!m_designWidget->load(absoluteFilePath.toUrlishString())) + return {OpenResult::ReadError, m_designWidget->errorMessage()}; setFilePath(absoluteFilePath); @@ -137,3 +135,5 @@ void ScxmlEditorDocument::syncXmlFromDesignWidget() { document()->setPlainText(designWidgetContents()); } + +} // namespace ScxmlEditor::Internal diff --git a/src/plugins/scxmleditor/scxmleditordocument.h b/src/plugins/scxmleditor/scxmleditordocument.h index ba4cfc42d6a..70d93d2ab72 100644 --- a/src/plugins/scxmleditor/scxmleditordocument.h +++ b/src/plugins/scxmleditor/scxmleditordocument.h @@ -13,9 +13,7 @@ QT_FORWARD_DECLARE_CLASS(QDesignerFormWindowInterface) namespace ScxmlEditor { -namespace Common { -class MainWidget; -} // namespace Common +namespace Common { class MainWidget; } namespace Internal { @@ -27,9 +25,7 @@ public: explicit ScxmlEditorDocument(Common::MainWidget *designWidget, QObject *parent = nullptr); // IDocument - OpenResult open(QString *errorString, - const Utils::FilePath &filePath, - const Utils::FilePath &realFilePath) override; + OpenResult open(const Utils::FilePath &filePath, const Utils::FilePath &realFilePath) override; bool shouldAutoSave() const override; bool isSaveAsAllowed() const override; bool isModified() const override; diff --git a/src/plugins/squish/objectsmapdocument.cpp b/src/plugins/squish/objectsmapdocument.cpp index 53c5cba6e56..7146e10bba0 100644 --- a/src/plugins/squish/objectsmapdocument.cpp +++ b/src/plugins/squish/objectsmapdocument.cpp @@ -11,10 +11,10 @@ #include #include +using namespace Core; using namespace Utils; -namespace Squish { -namespace Internal { +namespace Squish::Internal { static const char kItemSeparator = '\n'; static const char kPropertySeparator = '\t'; @@ -28,12 +28,11 @@ ObjectsMapDocument::ObjectsMapDocument() connect(m_contentModel, &ObjectsMapModel::modelChanged, this, [this] { setModified(true); }); } -Core::IDocument::OpenResult ObjectsMapDocument::open(QString *errorString, - const Utils::FilePath &fileName, - const Utils::FilePath &realFileName) +IDocument::OpenResult ObjectsMapDocument::open(const FilePath &fileName, + const FilePath &realFileName) { - OpenResult result = openImpl(errorString, fileName, realFileName); - if (result == OpenResult::Success) { + OpenResult result = openImpl(fileName, realFileName); + if (result.code == OpenResult::Success) { setFilePath(fileName); setModified(fileName != realFileName); } @@ -72,19 +71,18 @@ void ObjectsMapDocument::setModified(bool modified) emit changed(); } -Result<> ObjectsMapDocument::reload(Core::IDocument::ReloadFlag flag, - Core::IDocument::ChangeType type) +Result<> ObjectsMapDocument::reload(IDocument::ReloadFlag flag, IDocument::ChangeType type) { Q_UNUSED(type) if (flag == FlagIgnore) return ResultOk; emit aboutToReload(); - QString errorString; - const bool success = (openImpl(&errorString, filePath(), filePath()) == OpenResult::Success); + const OpenResult result = openImpl(filePath(), filePath()); + const bool success = result.code == OpenResult::Success; if (success) setModified(false); emit reloadFinished(success); - return makeResult(success, errorString); + return result; } bool ObjectsMapDocument::buildObjectsMapTree(const QByteArray &contents) @@ -175,36 +173,31 @@ QByteArray ObjectsMapDocument::contents() const return result; } -Core::IDocument::OpenResult ObjectsMapDocument::openImpl(QString *error, - const Utils::FilePath &fileName, - const Utils::FilePath &realFileName) +IDocument::OpenResult ObjectsMapDocument::openImpl(const FilePath &fileName, + const FilePath &realFileName) { if (fileName.isEmpty()) return OpenResult::CannotHandle; QByteArray text; if (realFileName.fileName() == "objects.map") { - Utils::FileReader reader; - if (!reader.fetch(realFileName, error)) - return OpenResult::ReadError; + FileReader reader; + if (const Result<> res = reader.fetch(realFileName); !res) + return {OpenResult::ReadError, res.error()}; text = reader.text(); } else { - const Utils::FilePath base = settings().squishPath(); + const FilePath base = settings().squishPath(); if (base.isEmpty()) { - if (error) - error->append(Tr::tr("Incomplete Squish settings. " - "Missing Squish installation path.")); - return OpenResult::ReadError; - } - const Utils::FilePath exe = base.pathAppended("lib/exec/objectmaptool").withExecutableSuffix(); - if (!exe.isExecutableFile()) { - if (error) - error->append(Tr::tr("objectmaptool not found.")); - return OpenResult::ReadError; + return {OpenResult::ReadError, Tr::tr("Incomplete Squish settings. " + "Missing Squish installation path.")}; } + const FilePath exe = base.pathAppended("lib/exec/objectmaptool").withExecutableSuffix(); + if (!exe.isExecutableFile()) + return {OpenResult::ReadError, Tr::tr("objectmaptool not found.")}; - Utils::Process objectMapReader; + + Process objectMapReader; objectMapReader.setCommand({exe, {"--scriptMap", "--mode", "read", "--scriptedObjectMapPath", realFileName.toUserOutput()}}); objectMapReader.setUtf8Codec(); @@ -212,11 +205,8 @@ Core::IDocument::OpenResult ObjectsMapDocument::openImpl(QString *error, objectMapReader.waitForFinished(); text = objectMapReader.cleanedStdOut().toUtf8(); } - if (!setContents(text)) { - if (error) - error->append(Tr::tr("Failure while parsing objects.map content.")); - return OpenResult::ReadError; - } + if (!setContents(text)) + return {OpenResult::ReadError, Tr::tr("Failure while parsing objects.map content.")}; return OpenResult::Success; } @@ -244,5 +234,4 @@ bool ObjectsMapDocument::writeFile(const Utils::FilePath &fileName) const return objectMapWriter.result() == Utils::ProcessResult::FinishedWithSuccess; } -} // namespace Internal -} // namespace Squish +} // namespace Squish::Internal diff --git a/src/plugins/squish/objectsmapdocument.h b/src/plugins/squish/objectsmapdocument.h index f24b47c4f61..b8355464ecc 100644 --- a/src/plugins/squish/objectsmapdocument.h +++ b/src/plugins/squish/objectsmapdocument.h @@ -7,8 +7,7 @@ #include -namespace Squish { -namespace Internal { +namespace Squish::Internal { class ObjectsMapModel; @@ -18,8 +17,7 @@ class ObjectsMapDocument : public Core::IDocument public: ObjectsMapDocument(); - OpenResult open(QString *errorString, - const Utils::FilePath &fileName, + OpenResult open(const Utils::FilePath &fileName, const Utils::FilePath &realFileName) override; Utils::FilePath fallbackSaveAsPath() const override; QString fallbackSaveAsFileName() const override; @@ -37,8 +35,7 @@ protected: Utils::Result<> saveImpl(const Utils::FilePath &fileName, bool autoSave) override; private: - OpenResult openImpl(QString *error, - const Utils::FilePath &fileName, + OpenResult openImpl(const Utils::FilePath &fileName, const Utils::FilePath &realFileName); bool buildObjectsMapTree(const QByteArray &contents); bool writeFile(const Utils::FilePath &fileName) const; @@ -48,5 +45,4 @@ private: bool m_isModified; }; -} // namespace Internal -} // namespace Squish +} // namespace Squish::Internal diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index d2567b3bbf5..4e23e9a7512 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -754,31 +754,29 @@ bool TextDocument::isModified() const return d->m_document.isModified(); } -Core::IDocument::OpenResult TextDocument::open(QString *errorString, - const Utils::FilePath &filePath, - const Utils::FilePath &realFilePath) +IDocument::OpenResult TextDocument::open(const FilePath &filePath, const FilePath &realFilePath) { emit aboutToOpen(filePath, realFilePath); - OpenResult success = openImpl(errorString, filePath, realFilePath, /*reload =*/ false); - if (success == OpenResult::Success) { + OpenResult result = openImpl(filePath, realFilePath, /*reload =*/ false); + if (result.code == OpenResult::Success) { setMimeType(Utils::mimeTypeForFile(filePath, MimeMatchMode::MatchDefaultAndRemote).name()); setTabSettings(d->m_tabSettings); emit openFinishedSuccessfully(); } - return success; + return result; } -Core::IDocument::OpenResult TextDocument::openImpl(QString *errorString, - const Utils::FilePath &filePath, - const Utils::FilePath &realFilePath, - bool reload) +IDocument::OpenResult TextDocument::openImpl(const FilePath &filePath, + const FilePath &realFilePath, + bool reload) { QStringList content; + QString errorString; - ReadResult readResult = Utils::TextFileFormat::ReadIOError; + ReadResult readResult = TextFileFormat::ReadIOError; if (!filePath.isEmpty()) { - readResult = read(realFilePath, &content, errorString); + readResult = read(realFilePath, &content, &errorString); const int chunks = content.size(); // Don't call setUndoRedoEnabled(true) when reload is true and filenames are different, @@ -829,7 +827,7 @@ Core::IDocument::OpenResult TextDocument::openImpl(QString *errorString, setFilePath(filePath); } if (readResult == Utils::TextFileFormat::ReadIOError) - return OpenResult::ReadError; + return {OpenResult::ReadError, errorString}; return OpenResult::Success; } @@ -853,15 +851,13 @@ Result<> TextDocument::reload(const FilePath &realFilePath) if (documentLayout) documentLayout->documentAboutToReload(this); // removes text marks non-permanently - QString errorString; - bool success = openImpl(&errorString, filePath(), realFilePath, /*reload =*/true) - == OpenResult::Success; + const OpenResult result = openImpl(filePath(), realFilePath, /*reload =*/true); if (documentLayout) documentLayout->documentReloaded(this); // re-adds text marks - emit reloadFinished(success); + emit reloadFinished(result.code == OpenResult::Success); - return makeResult(success, errorString); + return result; } bool TextDocument::setPlainText(const QString &text) diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 3d5b8ea9baf..65285dc1c83 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -117,8 +117,7 @@ public: void setFallbackSaveAsPath(const Utils::FilePath &fallbackSaveAsPath); void setFallbackSaveAsFileName(const QString &fallbackSaveAsFileName); - OpenResult open(QString *errorString, const Utils::FilePath &filePath, - const Utils::FilePath &realFilePath) override; + OpenResult open(const Utils::FilePath &filePath, const Utils::FilePath &realFilePath) override; virtual Utils::Result<> reload(); Utils::Result<> reload(const Utils::FilePath &realFilePath); @@ -170,8 +169,7 @@ protected: virtual void slotCodeStyleSettingsChanged(); // Used in CppEditorDocumet private: - OpenResult openImpl(QString *errorString, - const Utils::FilePath &filePath, + OpenResult openImpl(const Utils::FilePath &filePath, const Utils::FilePath &realFileName, bool reload); void cleanWhitespace(QTextCursor &cursor, bool inEntireDocument, bool cleanIndentation); diff --git a/src/plugins/vcsbase/submiteditorfile.cpp b/src/plugins/vcsbase/submiteditorfile.cpp index ca5601a8002..be85fed0cd9 100644 --- a/src/plugins/vcsbase/submiteditorfile.cpp +++ b/src/plugins/vcsbase/submiteditorfile.cpp @@ -27,15 +27,14 @@ SubmitEditorFile::SubmitEditorFile(VcsBaseSubmitEditor *editor) : this, &IDocument::contentsChanged); } -IDocument::OpenResult SubmitEditorFile::open(QString *errorString, const FilePath &filePath, - const FilePath &realFilePath) +IDocument::OpenResult SubmitEditorFile::open(const FilePath &filePath, const FilePath &realFilePath) { if (filePath.isEmpty()) return OpenResult::ReadError; FileReader reader; - if (!reader.fetch(realFilePath, errorString)) - return OpenResult::ReadError; + if (const Result<> res = reader.fetch(realFilePath); !res) + return {OpenResult::ReadError, res.error()}; const QString text = QString::fromLocal8Bit(reader.text()); if (!m_editor->setFileContents(text.toUtf8())) diff --git a/src/plugins/vcsbase/submiteditorfile.h b/src/plugins/vcsbase/submiteditorfile.h index de9741a1fdf..398138d6dee 100644 --- a/src/plugins/vcsbase/submiteditorfile.h +++ b/src/plugins/vcsbase/submiteditorfile.h @@ -17,8 +17,8 @@ class SubmitEditorFile : public Core::IDocument public: explicit SubmitEditorFile(VcsBaseSubmitEditor *editor); - OpenResult open(QString *errorString, const Utils::FilePath &filePath, - const Utils::FilePath &realFilePath) override; + OpenResult open(const Utils::FilePath &filePath, const Utils::FilePath &realFilePath) override; + QByteArray contents() const override; bool setContents(const QByteArray &contents) override;