diff options
| author | Eike Ziller <eike.ziller@qt.io> | 2020-08-31 14:49:19 +0200 |
|---|---|---|
| committer | Eike Ziller <eike.ziller@qt.io> | 2020-08-31 14:49:19 +0200 |
| commit | 6477a07654bdd498282953d8fc85c2a3e74086af (patch) | |
| tree | 36b13e6aa306247a2a80a03058e4581b466cabba /src | |
| parent | b5e2485fbfc510c43185f94f17c88dec17416ca6 (diff) | |
| parent | e8eafd85eea5201504d305fcdc68ba324bbd4715 (diff) | |
| download | qt-creator-6477a07654bdd498282953d8fc85c2a3e74086af.tar.gz | |
Merge remote-tracking branch 'origin/4.13' into master
Conflicts:
cmake/QtCreatorIDEBranding.cmake
qbs/modules/qtc/qtc.qbs
qtcreator_ide_branding.pri
src/plugins/clangtools/virtualfilesystemoverlay.h
src/plugins/mesonprojectmanager/project/buildoptions/mesonbuildstepconfigwidget.ui
src/plugins/qmldesigner/designercore/model/abstractview.cpp
Change-Id: I5013bd8fdd28d79cdea74380bec01d4c106adfaf
Diffstat (limited to 'src')
64 files changed, 867 insertions, 202 deletions
diff --git a/src/plugins/android/androidservicewidget.h b/src/plugins/android/androidservicewidget.h index cc30003b65..7a80234e4d 100644 --- a/src/plugins/android/androidservicewidget.h +++ b/src/plugins/android/androidservicewidget.h @@ -29,8 +29,10 @@ #include <QString> #include <QWidget> +QT_BEGIN_NAMESPACE class QPushButton; class QTableView; +QT_END_NAMESPACE namespace Android { namespace Internal { diff --git a/src/plugins/coreplugin/corepluginunittestfiles.pri b/src/plugins/coreplugin/corepluginunittestfiles.pri index f2ec908f26..891168759a 100644 --- a/src/plugins/coreplugin/corepluginunittestfiles.pri +++ b/src/plugins/coreplugin/corepluginunittestfiles.pri @@ -2,12 +2,10 @@ DEFINES += CORE_STATIC_LIBRARY HEADERS += \ $$PWD/coreicons.h \ - $$PWD/id.h \ $$PWD/find/ifindfilter.h \ $$PWD/locator/ilocatorfilter.h SOURCES += \ $$PWD/coreicons.cpp \ - $$PWD/id.cpp \ $$PWD/find/ifindfilter.cpp \ $$PWD/locator/ilocatorfilter.cpp diff --git a/src/plugins/coreplugin/icontext.h b/src/plugins/coreplugin/icontext.h index 8884dd3198..792217edb9 100644 --- a/src/plugins/coreplugin/icontext.h +++ b/src/plugins/coreplugin/icontext.h @@ -27,7 +27,8 @@ #include "core_global.h" #include "helpitem.h" -#include "id.h" + +#include <utils/id.h> #include <QList> #include <QObject> 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); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index ac8d095c16..65c343f358 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -3801,10 +3801,12 @@ void GdbEngine::setEnvironmentVariables() // imitate the weird windows gdb behavior of setting the case of the path environment // variable name to an all uppercase PATH const QString name = isWindowsPath(item.name) ? "PATH" : item.name; - if (item.operation == EnvironmentItem::Unset) + if (item.operation == EnvironmentItem::Unset + || item.operation == EnvironmentItem::SetDisabled) { runCommand({"unset environment " + name}); - else + } else { runCommand({"-gdb-set environment " + name + '=' + item.value}); + } } } diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 03c6bdf7fa..f7026b2815 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -151,7 +151,7 @@ void LldbEngine::runCommand(const DebuggerCommand &command) } showMessage(msg, LogInput); m_commandForToken[currentToken()] = cmd; - m_lldbProc.write("script theDumper." + function.toUtf8() + "\n"); + executeCommand("script theDumper." + function.toUtf8()); } void LldbEngine::debugLastCommand() @@ -168,6 +168,13 @@ void LldbEngine::handleAttachedToCore() updateLocals(); } +void LldbEngine::executeCommand(const QByteArray &command) +{ + // For some reason, sometimes LLDB misses the first character of the next command on Windows + // if passing only 1 LF. + m_lldbProc.write(command + "\n\n"); +} + void LldbEngine::shutdownInferior() { QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); @@ -228,13 +235,13 @@ void LldbEngine::setupEngine() const QByteArray dumperSourcePath = ICore::resourcePath().toLocal8Bit() + "/debugger/"; - m_lldbProc.write("script sys.path.insert(1, '" + dumperSourcePath + "')\n"); + executeCommand("script sys.path.insert(1, '" + dumperSourcePath + "')"); // This triggers reportState("enginesetupok") or "enginesetupfailed": - m_lldbProc.write("script from lldbbridge import *\n"); + executeCommand("script from lldbbridge import *"); QString commands = nativeStartupCommands(); if (!commands.isEmpty()) - m_lldbProc.write(commands.toLocal8Bit() + '\n'); + executeCommand(commands.toLocal8Bit()); const QString path = stringSetting(ExtraDumperFile); diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 6c5b3c2c21..e33db0e963 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -131,6 +131,7 @@ private: void runCommand(const DebuggerCommand &cmd) override; void debugLastCommand() override; void handleAttachedToCore(); + void executeCommand(const QByteArray &command); private: DebuggerCommand m_lastDebuggableCommand; diff --git a/src/plugins/help/filtersettingspage.h b/src/plugins/help/filtersettingspage.h index 6d98f096d8..469df0d23d 100644 --- a/src/plugins/help/filtersettingspage.h +++ b/src/plugins/help/filtersettingspage.h @@ -32,7 +32,9 @@ #ifndef HELP_NEW_FILTER_ENGINE #include "ui_filtersettingspage.h" #else +QT_BEGIN_NAMESPACE class QHelpFilterSettingsWidget; +QT_END_NAMESPACE #endif namespace Help { diff --git a/src/plugins/mesonprojectmanager/project/buildoptions/mesonbuildsettingswidget.h b/src/plugins/mesonprojectmanager/project/buildoptions/mesonbuildsettingswidget.h index d3b9ab5118..68f677c41f 100644 --- a/src/plugins/mesonprojectmanager/project/buildoptions/mesonbuildsettingswidget.h +++ b/src/plugins/mesonprojectmanager/project/buildoptions/mesonbuildsettingswidget.h @@ -32,12 +32,12 @@ #include <QTimer> #include <QWidget> -namespace Ui { -class MesonBuildSettingsWidget; -} namespace MesonProjectManager { namespace Internal { + +namespace Ui { class MesonBuildSettingsWidget; } + class MesonBuildConfiguration; class MesonBuildSettingsWidget : public ProjectExplorer::NamedWidget { diff --git a/src/plugins/mesonprojectmanager/project/buildoptions/mesonbuildsettingswidget.ui b/src/plugins/mesonprojectmanager/project/buildoptions/mesonbuildsettingswidget.ui index f5a80ee047..6efac5a04f 100644 --- a/src/plugins/mesonprojectmanager/project/buildoptions/mesonbuildsettingswidget.ui +++ b/src/plugins/mesonprojectmanager/project/buildoptions/mesonbuildsettingswidget.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>MesonBuildSettingsWidget</class> - <widget class="QWidget" name="MesonBuildSettingsWidget"> + <class>MesonProjectManager::Internal::MesonBuildSettingsWidget</class> + <widget class="QWidget" name="MesonProjectManager::Internal::MesonBuildSettingsWidget"> <property name="geometry"> <rect> <x>0</x> diff --git a/src/plugins/mesonprojectmanager/settings/general/generalsettingswidget.h b/src/plugins/mesonprojectmanager/settings/general/generalsettingswidget.h index cf0da678e5..d16e6ec755 100644 --- a/src/plugins/mesonprojectmanager/settings/general/generalsettingswidget.h +++ b/src/plugins/mesonprojectmanager/settings/general/generalsettingswidget.h @@ -30,12 +30,11 @@ #include <QTabWidget> #include <QWidget> -namespace Ui { -class GeneralSettingsWidget; -} - namespace MesonProjectManager { namespace Internal { + +namespace Ui { class GeneralSettingsWidget; } + class GeneralSettingsWidget final : public Core::IOptionsPageWidget { Q_DECLARE_TR_FUNCTIONS(MesonProjectManager::Internal::GeneralSettingsWidget) diff --git a/src/plugins/mesonprojectmanager/settings/general/generalsettingswidget.ui b/src/plugins/mesonprojectmanager/settings/general/generalsettingswidget.ui index 8f44e3df74..6323bf302e 100644 --- a/src/plugins/mesonprojectmanager/settings/general/generalsettingswidget.ui +++ b/src/plugins/mesonprojectmanager/settings/general/generalsettingswidget.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>GeneralSettingsWidget</class> - <widget class="QWidget" name="GeneralSettingsWidget"> + <class>MesonProjectManager::Internal::GeneralSettingsWidget</class> + <widget class="QWidget" name="MesonProjectManager::Internal::GeneralSettingsWidget"> <property name="geometry"> <rect> <x>0</x> diff --git a/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.h b/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.h index 9a692b00c1..988add23be 100644 --- a/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.h +++ b/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.h @@ -29,13 +29,10 @@ #include "utils/optional.h" #include <QWidget> -namespace Ui { -class ToolItemSettings; -} - namespace MesonProjectManager { namespace Internal { +namespace Ui { class ToolItemSettings; } class ToolTreeItem; class ToolItemSettings : public QWidget diff --git a/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.ui b/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.ui index 60a93dca1a..5e1b2a5953 100644 --- a/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.ui +++ b/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>ToolItemSettings</class> - <widget class="QWidget" name="ToolItemSettings"> + <class>MesonProjectManager::Internal::ToolItemSettings</class> + <widget class="QWidget" name="MesonProjectManager::Internal::ToolItemSettings"> <property name="geometry"> <rect> <x>0</x> diff --git a/src/plugins/mesonprojectmanager/settings/tools/toolssettingswidget.h b/src/plugins/mesonprojectmanager/settings/tools/toolssettingswidget.h index 9c1bd5231f..26739e88b9 100644 --- a/src/plugins/mesonprojectmanager/settings/tools/toolssettingswidget.h +++ b/src/plugins/mesonprojectmanager/settings/tools/toolssettingswidget.h @@ -34,13 +34,11 @@ #include <QTabWidget> #include <QWidget> - -namespace Ui { -class ToolsSettingsWidget; -} - namespace MesonProjectManager { namespace Internal { + +namespace Ui { class ToolsSettingsWidget; } + class ToolTreeItem; class ToolsSettingsWidget final : public Core::IOptionsPageWidget { diff --git a/src/plugins/mesonprojectmanager/settings/tools/toolssettingswidget.ui b/src/plugins/mesonprojectmanager/settings/tools/toolssettingswidget.ui index 7cc3da0b83..ed6409ab13 100644 --- a/src/plugins/mesonprojectmanager/settings/tools/toolssettingswidget.ui +++ b/src/plugins/mesonprojectmanager/settings/tools/toolssettingswidget.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>ToolsSettingsWidget</class> - <widget class="QWidget" name="MesonToolConfigWidget"> + <class>MesonProjectManager::Internal::ToolsSettingsWidget</class> + <widget class="QWidget" name="MesonProjectManager::Internal::ToolSettingsWidget"> <property name="geometry"> <rect> <x>0</x> diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp index cc8c0fdb57..94299bc5df 100644 --- a/src/plugins/projectexplorer/buildstep.cpp +++ b/src/plugins/projectexplorer/buildstep.cpp @@ -265,9 +265,11 @@ QString BuildStep::fallbackWorkingDirectory() const void BuildStep::setupOutputFormatter(OutputFormatter *formatter) { - for (const Utils::Id id : buildConfiguration()->customParsers()) { - if (Internal::CustomParser * const parser = Internal::CustomParser::createFromId(id)) - formatter->addLineParser(parser); + if (qobject_cast<BuildConfiguration *>(parent()->parent())) { + for (const Utils::Id id : buildConfiguration()->customParsers()) { + if (Internal::CustomParser * const parser = Internal::CustomParser::createFromId(id)) + formatter->addLineParser(parser); + } } Utils::FileInProjectFinder fileFinder; fileFinder.setProjectDirectory(project()->projectDirectory()); diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp index eeab711e30..07ea3cd1b8 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp +++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp @@ -75,7 +75,7 @@ static FilePath defaultBuildDirectory(const FilePath &projectFilePath, const Kit // QbsBuildConfiguration: // --------------------------------------------------------------------------- -QbsBuildConfiguration::QbsBuildConfiguration(Target *target, Core::Id id) +QbsBuildConfiguration::QbsBuildConfiguration(Target *target, Utils::Id id) : BuildConfiguration(target, id) { setConfigWidgetHasFrame(true); diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h index e036b68558..e2b38132b5 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h +++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h @@ -62,7 +62,7 @@ class QbsBuildConfiguration final : public ProjectExplorer::BuildConfiguration Q_OBJECT friend class ProjectExplorer::BuildConfigurationFactory; - QbsBuildConfiguration(ProjectExplorer::Target *target, Core::Id id); + QbsBuildConfiguration(ProjectExplorer::Target *target, Utils::Id id); ~QbsBuildConfiguration() final; public: diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp index 062f48e15b..49f46ae7d1 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp +++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp @@ -136,7 +136,7 @@ private: // QbsBuildStep: // -------------------------------------------------------------------- -QbsBuildStep::QbsBuildStep(BuildStepList *bsl, Core::Id id) : +QbsBuildStep::QbsBuildStep(BuildStepList *bsl, Utils::Id id) : BuildStep(bsl, id) { setDisplayName(tr("Qbs Build")); diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.h b/src/plugins/qbsprojectmanager/qbsbuildstep.h index d257662bdb..cdb0f94b1d 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildstep.h +++ b/src/plugins/qbsprojectmanager/qbsbuildstep.h @@ -51,7 +51,7 @@ public: ExpandVariables }; - QbsBuildStep(ProjectExplorer::BuildStepList *bsl, Core::Id id); + QbsBuildStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id); ~QbsBuildStep() override; QVariantMap qbsConfiguration(VariableHandling variableHandling) const; diff --git a/src/plugins/qbsprojectmanager/qbscleanstep.cpp b/src/plugins/qbsprojectmanager/qbscleanstep.cpp index 922e586117..209ec759c1 100644 --- a/src/plugins/qbsprojectmanager/qbscleanstep.cpp +++ b/src/plugins/qbsprojectmanager/qbscleanstep.cpp @@ -49,7 +49,7 @@ namespace Internal { // QbsCleanStep: // -------------------------------------------------------------------- -QbsCleanStep::QbsCleanStep(BuildStepList *bsl, Core::Id id) +QbsCleanStep::QbsCleanStep(BuildStepList *bsl, Utils::Id id) : BuildStep(bsl, id) { setDisplayName(tr("Qbs Clean")); diff --git a/src/plugins/qbsprojectmanager/qbscleanstep.h b/src/plugins/qbsprojectmanager/qbscleanstep.h index 0fcde0a4d0..d9fd6c489d 100644 --- a/src/plugins/qbsprojectmanager/qbscleanstep.h +++ b/src/plugins/qbsprojectmanager/qbscleanstep.h @@ -41,7 +41,7 @@ class QbsCleanStep : public ProjectExplorer::BuildStep Q_OBJECT public: - QbsCleanStep(ProjectExplorer::BuildStepList *bsl, Core::Id id); + QbsCleanStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id); ~QbsCleanStep() override; QbsBuildStepData stepData() const; diff --git a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp index f42ead0049..085caa8a7b 100644 --- a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp +++ b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp @@ -61,7 +61,7 @@ const char QBS_KEEP_GOING[] = "Qbs.DryKeepGoing"; // QbsInstallStep: // -------------------------------------------------------------------- -QbsInstallStep::QbsInstallStep(BuildStepList *bsl, Core::Id id) +QbsInstallStep::QbsInstallStep(BuildStepList *bsl, Utils::Id id) : BuildStep(bsl, id) { setDisplayName(tr("Qbs Install")); @@ -89,16 +89,16 @@ QbsInstallStep::~QbsInstallStep() bool QbsInstallStep::init() { - QTC_ASSERT(!buildSystem()->isParsing() && !m_session, return false); + QTC_ASSERT(!target()->buildSystem()->isParsing() && !m_session, return false); return true; } void QbsInstallStep::doRun() { - m_session = static_cast<QbsBuildSystem *>(buildSystem())->session(); + m_session = static_cast<QbsBuildSystem *>(target()->buildSystem())->session(); QJsonObject request; - request.insert("type", "install"); + request.insert("type", "install-project"); request.insert("install-root", installRoot()); request.insert("clean-install-root", m_cleanInstallRoot->value()); request.insert("keep-going", m_keepGoing->value()); @@ -128,7 +128,7 @@ QString QbsInstallStep::installRoot() const const QbsBuildConfiguration *QbsInstallStep::buildConfig() const { - return static_cast<QbsBuildConfiguration *>(buildConfiguration()); + return static_cast<QbsBuildConfiguration *>(target()->activeBuildConfiguration()); } void QbsInstallStep::installDone(const ErrorInfo &error) diff --git a/src/plugins/qbsprojectmanager/qbsinstallstep.h b/src/plugins/qbsprojectmanager/qbsinstallstep.h index 35fb5db531..f414c105aa 100644 --- a/src/plugins/qbsprojectmanager/qbsinstallstep.h +++ b/src/plugins/qbsprojectmanager/qbsinstallstep.h @@ -42,7 +42,7 @@ class QbsInstallStep : public ProjectExplorer::BuildStep Q_OBJECT public: - QbsInstallStep(ProjectExplorer::BuildStepList *bsl, Core::Id id); + QbsInstallStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id); ~QbsInstallStep() override; QString installRoot() const; diff --git a/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp b/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp index b75c019ef2..84129f846c 100644 --- a/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp +++ b/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp @@ -163,9 +163,9 @@ void QbsProfilesSettingsWidget::refreshKitsList() m_ui.propertiesView->setModel(nullptr); m_model.reload(); m_ui.profileValueLabel->clear(); - Core::Id currentId; + Utils::Id currentId; if (m_ui.kitsComboBox->count() > 0) - currentId = Core::Id::fromSetting(m_ui.kitsComboBox->currentData()); + currentId = Utils::Id::fromSetting(m_ui.kitsComboBox->currentData()); m_ui.kitsComboBox->clear(); int newCurrentIndex = -1; QList<Kit *> validKits = KitManager::kits(); @@ -191,7 +191,7 @@ void QbsProfilesSettingsWidget::displayCurrentProfile() m_ui.propertiesView->setModel(nullptr); if (m_ui.kitsComboBox->currentIndex() == -1) return; - const Core::Id kitId = Core::Id::fromSetting(m_ui.kitsComboBox->currentData()); + const Utils::Id kitId = Utils::Id::fromSetting(m_ui.kitsComboBox->currentData()); const Kit * const kit = KitManager::kit(kitId); QTC_ASSERT(kit, return); const QString profileName = QbsProfileManager::ensureProfileForKit(kit); diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index f45083fe8a..ba15c00675 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -40,7 +40,6 @@ #include <coreplugin/documentmanager.h> #include <coreplugin/icontext.h> #include <coreplugin/icore.h> -#include <coreplugin/id.h> #include <coreplugin/iversioncontrol.h> #include <coreplugin/messagemanager.h> #include <coreplugin/progressmanager/progressmanager.h> diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h index 13f9803c25..4786f36981 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.h +++ b/src/plugins/qbsprojectmanager/qbsproject.h @@ -35,6 +35,7 @@ #include <projectexplorer/task.h> #include <utils/environment.h> +#include <utils/id.h> #include <QFutureWatcher> #include <QHash> @@ -92,7 +93,7 @@ public: const QString &filePath, const QString &newFilePath) final; QStringList filesGeneratedFrom(const QString &sourceFile) const final; - QVariant additionalData(Core::Id id) const final; + QVariant additionalData(Utils::Id id) const final; bool isProjectEditable() const; bool addFilesToProduct(const QStringList &filePaths, diff --git a/src/plugins/qbsprojectmanager/qbssession.cpp b/src/plugins/qbsprojectmanager/qbssession.cpp index 56df0c20a7..7485aa3b90 100644 --- a/src/plugins/qbsprojectmanager/qbssession.cpp +++ b/src/plugins/qbsprojectmanager/qbssession.cpp @@ -268,7 +268,7 @@ QString QbsSession::errorString(QbsSession::Error error) case Error::QbsFailedToStart: return tr("The qbs process failed to start."); case Error::ProtocolError: - return tr("The qbs process sent invalid data."); + return tr("The qbs process sent unexpected data."); case Error::VersionMismatch: return tr("The qbs API level is not compatible with " "what %1 expects.").arg(Core::Constants::IDE_DISPLAY_NAME); @@ -536,6 +536,15 @@ void QbsSession::handlePacket(const QJsonObject &packet) } else if (type == "run-environment") { d->reply = packet; d->eventLoop.quit(); + } else if (type == "protocol-error") { + const ErrorInfo errorInfo = ErrorInfo(packet.value("error").toObject()); + + // TODO: This loop occurs a lot. Factor it out. + for (const ErrorInfoItem &item : errorInfo.items) { + TaskHub::addTask(BuildSystemTask(Task::Error, item.description, + item.filePath, item.line)); + } + setError(Error::ProtocolError); } } diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h index e452fff6bc..197a91b5ab 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h @@ -39,9 +39,6 @@ class QListView; class QPlainTextEdit; QT_END_NAMESPACE -namespace Ui { -class AssetExportDialog; -} namespace Utils { class OutputFormatter; @@ -52,6 +49,7 @@ class Task; } namespace QmlDesigner { +namespace Ui { class AssetExportDialog; } class FilePathModel; class AssetExportDialog : public QDialog diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui index a4e7ec91d9..0f51525b6b 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>AssetExportDialog</class> - <widget class="QDialog" name="AssetExportDialog"> + <class>QmlDesigner::AssetExportDialog</class> + <widget class="QDialog" name="QmlDesigner::AssetExportDialog"> <property name="geometry"> <rect> <x>0</x> diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp index 1ea1e09e92..b975c228e6 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp @@ -32,6 +32,8 @@ #include "utils/qtcassert.h" #include "utils/runextensions.h" #include "variantproperty.h" +#include "projectexplorer/session.h" +#include "projectexplorer/project.h" #include <QCryptographicHash> #include <QDir> @@ -239,7 +241,10 @@ void AssetExporter::writeMetadata() const return; } - Utils::FilePath metadataPath = m_exportPath.pathAppended(m_exportPath.fileName() + ".metadata"); + auto const startupProject = ProjectExplorer::SessionManager::startupProject(); + QTC_ASSERT(startupProject, return); + const QString projectName = startupProject->displayName(); + Utils::FilePath metadataPath = m_exportPath.pathAppended(projectName + ".metadata"); ExportNotification::addInfo(tr("Writing metadata to file %1."). arg(metadataPath.toUserOutput())); makeParentPath(metadataPath); diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp index e45e48ca0d..5c42411443 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp @@ -95,8 +95,10 @@ void AssetExporterPlugin::onExport() return; FilePathModel model(startupProject); - QString exportDirName = startupProject->displayName() + "_export"; - auto exportDir = startupProject->projectFilePath().parentDir().pathAppended(exportDirName); + auto exportDir = startupProject->projectFilePath().parentDir(); + if (!exportDir.parentDir().isEmpty()) + exportDir = exportDir.parentDir(); + exportDir = exportDir.pathAppended(startupProject->displayName() + "_export"); AssetExporter assetExporter(m_view, startupProject); AssetExportDialog assetExporterDialog(exportDir, assetExporter, model); assetExporterDialog.exec(); diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporterview.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexporterview.cpp index 0b0cf575a1..6e5212818d 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexporterview.cpp +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporterview.cpp @@ -62,7 +62,7 @@ bool AssetExporterView::loadQmlFile(const Utils::FilePath &path, uint timeoutSec setState(LoadState::Busy); m_retryCount = std::max(MinRetry, static_cast<int>((timeoutSecs * 1000) / RetryIntervalMs)); - m_currentEditor = Core::EditorManager::openEditor(path.toString(), Core::Id(), + m_currentEditor = Core::EditorManager::openEditor(path.toString(), Utils::Id(), Core::EditorManager::DoNotMakeVisible); Core::ModeManager::activateMode(Core::Constants::MODE_DESIGN); Core::ModeManager::setFocusToCurrentMode(); @@ -154,8 +154,10 @@ void AssetExporterView::handleTimerTimeout() } +QT_BEGIN_NAMESPACE QDebug operator<<(QDebug os, const QmlDesigner::AssetExporterView::LoadState &s) { os << static_cast<std::underlying_type<QmlDesigner::AssetExporterView::LoadState>::type>(s); return os; } +QT_END_NAMESPACE diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporterview.h b/src/plugins/qmldesigner/assetexporterplugin/assetexporterview.h index 46c2c77071..9efbc19cec 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexporterview.h +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporterview.h @@ -83,4 +83,6 @@ private: } +QT_BEGIN_NAMESPACE QDebug operator<<(QDebug os, const QmlDesigner::AssetExporterView::LoadState &s); +QT_END_NAMESPACE diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp index c119dfdca1..21add0a752 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp @@ -38,7 +38,8 @@ namespace QmlDesigner { -AnnotationEditor::AnnotationEditor(QObject *) +AnnotationEditor::AnnotationEditor(QObject *parent) + : QObject(parent) { } @@ -55,9 +56,9 @@ void AnnotationEditor::registerDeclarativeType() void AnnotationEditor::showWidget() { m_dialog = new AnnotationEditorDialog(Core::ICore::dialogParent(), - modelNode().validId(), - modelNode().customId(), - modelNode().annotation()); + m_modelNode.id(), + m_modelNode.customId(), + m_modelNode.annotation()); QObject::connect(m_dialog, &AnnotationEditorDialog::accepted, this, &AnnotationEditor::acceptedClicked); diff --git a/src/plugins/qmldesigner/components/componentcore/theme.h b/src/plugins/qmldesigner/components/componentcore/theme.h index 880a1d05ca..f6a1df97cc 100644 --- a/src/plugins/qmldesigner/components/componentcore/theme.h +++ b/src/plugins/qmldesigner/components/componentcore/theme.h @@ -103,9 +103,13 @@ public: fontStyleItalic, fontStyleStrikethrough, fontStyleUnderline, + gridView, idAliasOff, idAliasOn, + listView, mergeCells, + minus, + plus, redo, splitColumns, splitRows, diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp index 04c6c343dc..2fd2364596 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp +++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp @@ -268,15 +268,11 @@ ModelNode ConnectionModel::getTargetNodeForConnection(const ModelNode &connectio const QString bindExpression = bindingProperty.expression(); if (bindingProperty.isValid()) { - if (bindExpression == QLatin1String("parent")) { - result = connection.parentProperty().parentModelNode(); - } else if (bindExpression.contains(".")) { + if (bindExpression.contains(".")) { QStringList substr = bindExpression.split("."); const QString itemId = substr.constFirst(); if (substr.size() > 1) { - const ModelNode aliasParent = (itemId == QLatin1String("parent") - ? connection.parentProperty().parentModelNode() - : connectionView()->modelNodeForId(itemId)); + const ModelNode aliasParent = connectionView()->modelNodeForId(itemId); substr.removeFirst(); //remove id, only alias pieces left const QString aliasBody = substr.join("."); if (aliasParent.isValid() && aliasParent.hasBindingProperty(aliasBody.toUtf8())) { @@ -303,7 +299,7 @@ void ConnectionModel::addConnection() NodeMetaInfo nodeMetaInfo = connectionView()->model()->metaInfo("QtQuick.Connections"); if (nodeMetaInfo.isValid()) { - connectionView()->executeInTransaction("ConnectionModel::addConnection", [=](){ + connectionView()->executeInTransaction("ConnectionModel::addConnection", [=, &rootModelNode](){ ModelNode newNode = connectionView()->createModelNode("QtQuick.Connections", nodeMetaInfo.majorVersion(), nodeMetaInfo.minorVersion()); @@ -316,19 +312,14 @@ void ConnectionModel::addConnection() else rootModelNode.nodeAbstractProperty(rootModelNode.metaInfo().defaultPropertyName()).reparentHere(newNode); - if (QmlItemNode(selectedNode).isFlowActionArea()) - source = selectedNode.validId() + ".trigger()"; - - if (QmlVisualNode(selectedNode).isFlowTransition()) + if (QmlItemNode(selectedNode).isFlowActionArea() || QmlVisualNode(selectedNode).isFlowTransition()) source = selectedNode.validId() + ".trigger()"; if (!connectionView()->selectedModelNodes().constFirst().id().isEmpty()) - newNode.bindingProperty("target").setExpression(selectedNode.id()); - else - newNode.bindingProperty("target").setExpression(QLatin1String("parent")); + newNode.bindingProperty("target").setExpression(selectedNode.validId()); } else { rootModelNode.nodeAbstractProperty(rootModelNode.metaInfo().defaultPropertyName()).reparentHere(newNode); - newNode.bindingProperty("target").setExpression(QLatin1String("parent")); + newNode.bindingProperty("target").setExpression(rootModelNode.validId()); } newNode.signalHandlerProperty("onClicked").setSource(source); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index 96dda07c51..1a9f165483 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -234,12 +234,12 @@ void FormEditorView::createFormEditorWidget() connect(m_formEditorWidget->resetAction(), &QAction::triggered, this, &FormEditorView::resetNodeInstanceView); } -void FormEditorView::temporaryBlockView() +void FormEditorView::temporaryBlockView(int duration) { m_formEditorWidget->graphicsView()->setUpdatesEnabled(false); static auto timer = new QTimer(qApp); timer->setSingleShot(true); - timer->start(1000); + timer->start(duration); connect(timer, &QTimer::timeout, this, [this]() { m_formEditorWidget->graphicsView()->setUpdatesEnabled(true); @@ -496,6 +496,11 @@ void FormEditorView::customNotification(const AbstractView * /*view*/, const QSt m_formEditorWidget->zoomAction()->zoomOut(); } +void FormEditorView::currentStateChanged(const ModelNode & /*node*/) +{ + temporaryBlockView(100); +} + AbstractFormEditorTool *FormEditorView::currentTool() const { return m_currentTool; diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h index d6a479e847..64c1f2a435 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h @@ -84,7 +84,12 @@ public: void documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings) override; - void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override; + void customNotification(const AbstractView *view, + const QString &identifier, + const QList<ModelNode> &nodeList, + const QList<QVariant> &data) override; + + void currentStateChanged(const ModelNode &node) override; // FormEditorView WidgetInfo widgetInfo() override; @@ -134,7 +139,7 @@ private: void removeNodeFromScene(const QmlItemNode &qmlItemNode); void hideNodeFromScene(const QmlItemNode &qmlItemNode); void createFormEditorWidget(); - void temporaryBlockView(); + void temporaryBlockView(int duration = 1000); void resetNodeInstanceView(); QPointer<FormEditorWidget> m_formEditorWidget; diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp index 74fa9d3b73..c09516cbf8 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp @@ -283,7 +283,7 @@ void FormEditorWidget::changeBackgound(const QColor &color) } } -void FormEditorWidget::registerActionAsCommand(QAction *action, Core::Id id, const QKeySequence &keysequence) +void FormEditorWidget::registerActionAsCommand(QAction *action, Utils::Id id, const QKeySequence &keysequence) { Core::Context context(Constants::C_QMLFORMEDITOR); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h index b2f50de6c0..b32c95916a 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h @@ -97,7 +97,7 @@ private: void changeRootItemWidth(const QString &widthText); void changeRootItemHeight(const QString &heightText); void changeBackgound(const QColor &color); - void registerActionAsCommand(QAction *action, Core::Id id, const QKeySequence &keysequence); + void registerActionAsCommand(QAction *action, Utils::Id id, const QKeySequence &keysequence); QPointer<FormEditorView> m_formEditorView; QPointer<FormEditorGraphicsView> m_graphicsView; diff --git a/src/plugins/qmldesigner/components/importmanager/importswidget.cpp b/src/plugins/qmldesigner/components/importmanager/importswidget.cpp index 650033a42d..4d8f134d90 100644 --- a/src/plugins/qmldesigner/components/importmanager/importswidget.cpp +++ b/src/plugins/qmldesigner/components/importmanager/importswidget.cpp @@ -99,12 +99,16 @@ void ImportsWidget::setPossibleImports(QList<Import> possibleImports) QList<Import> filteredImports; - const QStringList mcuWhiteList = {"QtQuick", "QtQuick.Controls"}; + const QStringList mcuWhiteList = {"QtQuick", "QtQuick.Controls", "QtQuick.Timeline"}; + const QStringList mcuBlackList = {"FlowView"}; if (isQtForMCUs) { - filteredImports = Utils::filtered(possibleImports, [mcuWhiteList](const Import &import) { - return mcuWhiteList.contains(import.url()) || !import.url().startsWith("Qt"); - }); + filteredImports = Utils::filtered(possibleImports, + [mcuWhiteList, mcuBlackList](const Import &import) { + return (mcuWhiteList.contains(import.url()) + || !import.url().startsWith("Qt")) + && !mcuBlackList.contains(import.url()); + }); } else { filteredImports = possibleImports; } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp index ea2e472f43..82306a5ab7 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp @@ -113,6 +113,8 @@ void ItemLibraryView::importsChanged(const QList<Import> &addedImports, const QL for (ModelNode node : slConnectors) node.destroy(); + + resetPuppet(); } } } diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index cf51c1a022..f86b377933 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -526,6 +526,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in const QString targetPropertyName = hints.forceNonDefaultProperty(); bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber, targetPropertyName.toUtf8()); + bool moveNodesAfter = true; if (foundTarget) { if (!NodeHints::fromItemLibraryEntry(itemLibraryEntry).canBeDroppedInNavigator()) @@ -569,16 +570,43 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in } insertIntoList("effects", targetEnv); } else if (newModelNode.isSubclassOf("QtQuick3D.Material")) { - // Insert material dropped to a model node into the materials list of the model - ModelNode targetModel; - if (targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Model")) + if (targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Model")) { + // Insert material dropped to a model node into the materials list of the model + ModelNode targetModel; targetModel = targetProperty.parentModelNode(); - insertIntoList("materials", targetModel); + insertIntoList("materials", targetModel); + } + } else { + const bool isShader = newModelNode.isSubclassOf("QtQuick3D.Shader"); + if (isShader || newModelNode.isSubclassOf("QtQuick3D.Command")) { + if (targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass")) { + // Shaders and commands inserted into a Pass will be added to proper list. + // They are also moved to the same level as the pass, as passes don't + // allow child nodes (QTBUG-86219). + ModelNode targetModel; + targetModel = targetProperty.parentModelNode(); + if (isShader) + insertIntoList("shaders", targetModel); + else + insertIntoList("commands", targetModel); + NodeAbstractProperty parentProp = targetProperty.parentProperty(); + if (parentProp.isValid()) { + targetProperty = parentProp; + targetModel = targetProperty.parentModelNode(); + targetRowNumber = rowCount(indexForModelNode(targetModel)); + + // Move node to new parent within the same transaction as we don't + // want undo to place the node under invalid parent + moveNodesAfter = false; + moveNodesInteractive(targetProperty, {newQmlObjectNode}, targetRowNumber, false); + } + } + } } } }); - if (newQmlObjectNode.isValid() && targetProperty.isNodeListProperty()) { + if (moveNodesAfter && newQmlObjectNode.isValid() && targetProperty.isNodeListProperty()) { QList<ModelNode> newModelNodeList; newModelNodeList.append(newQmlObjectNode); @@ -606,9 +634,8 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i ModelNode newModelNode; - if (targetNode.isSubclassOf("QtQuick3D.DefaultMaterial")) { - // if dropping an image on a default material, create a texture instead of image - m_view->executeInTransaction("QmlItemNode::createQmlItemNode", [&] { + auto createTextureNode = [&](const NodeAbstractProperty &targetProp) -> bool { + if (targetProp.isValid()) { // create a texture item lib ItemLibraryEntry itemLibraryEntry; itemLibraryEntry.setName("Texture"); @@ -621,11 +648,33 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i itemLibraryEntry.addProperty(prop, type, val); // create a texture - newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {}, targetProperty, false); + newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {}, targetProp, false); + return newModelNode.isValid(); + } + return false; + }; - // set the texture to parent material's diffuseMap property - // TODO: allow the user to choose which map property to set the texture for - targetNode.bindingProperty("diffuseMap").setExpression(newModelNode.validId()); + if (targetNode.isSubclassOf("QtQuick3D.Material")) { + // if dropping an image on a default material, create a texture instead of image + m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryImageDrop", [&] { + if (createTextureNode(targetProperty)) { + // Automatically set the texture to default property + // TODO: allow the user to choose which map property to set the texture for (QDS-2326) + if (targetNode.isSubclassOf("QtQuick3D.DefaultMaterial")) + targetNode.bindingProperty("diffuseMap").setExpression(newModelNode.validId()); + else if (targetNode.isSubclassOf("QtQuick3D.PrincipledMaterial")) + targetNode.bindingProperty("baseColorMap").setExpression(newModelNode.validId()); + } + }); + } else if (targetNode.isSubclassOf("QtQuick3D.TextureInput")) { + // If dropping an image on a TextureInput, create a texture on the same level as + // TextureInput, as the TextureInput doesn't support Texture children (QTBUG-86219) + m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryImageDrop", [&] { + NodeAbstractProperty parentProp = targetProperty.parentProperty(); + if (createTextureNode(parentProp)) { + // Automatically set the texture to texture property + targetNode.bindingProperty("texture").setExpression(newModelNode.validId()); + } }); } else if (targetNode.isSubclassOf("QtQuick3D.Texture")) { // if dropping an image on a texture, set the texture source @@ -643,11 +692,14 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i } } -void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList<ModelNode> &modelNodes, int targetIndex) +void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProperty, + const QList<ModelNode> &modelNodes, + int targetIndex, + bool executeInTransaction) { QTC_ASSERT(m_view, return); - m_view->executeInTransaction("NavigatorTreeModel::moveNodesInteractive",[&parentProperty, modelNodes, targetIndex](){ + auto doMoveNodesInteractive = [&parentProperty, modelNodes, targetIndex](){ const TypeName propertyQmlType = parentProperty.parentModelNode().metaInfo().propertyTypeName(parentProperty.name()); foreach (const ModelNode &modelNode, modelNodes) { if (modelNode.isValid() @@ -665,7 +717,12 @@ void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProper } } } - }); + }; + + if (executeInTransaction) + m_view->executeInTransaction("NavigatorTreeModel::moveNodesInteractive", doMoveNodesInteractive); + else + doMoveNodesInteractive(); } Qt::DropActions NavigatorTreeModel::supportedDropActions() const diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h index 15e89d3636..3289a19b31 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h @@ -92,7 +92,8 @@ public: void resetModel() override; private: - void moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList<ModelNode> &modelNodes, int targetIndex); + void moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList<ModelNode> &modelNodes, + int targetIndex, bool executeInTransaction = true); void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); void handleItemLibraryImageDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp index e9a4930a44..2058aef198 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp @@ -321,7 +321,7 @@ void NavigatorView::changeToComponent(const QModelIndex &index) const ModelNode doubleClickNode = modelNodeForIndex(index); if (doubleClickNode.metaInfo().isFileComponent()) Core::EditorManager::openEditor(doubleClickNode.metaInfo().componentFileName(), - Core::Id(), Core::EditorManager::DoNotMakeVisible); + Utils::Id(), Core::EditorManager::DoNotMakeVisible); } } diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp index 98470133ac..5af09f624a 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp @@ -261,19 +261,36 @@ bool PropertyEditorValue::isTranslated() const return false; } +static bool itemOrImage(const QmlDesigner::NodeMetaInfo &metaInfo) +{ + if (!metaInfo.isValid()) + return false; + + if (metaInfo.isSubclassOf("QtQuick.Image") || metaInfo.isSubclassOf("QtQuick.Text")) + return true; + + return false; +} + bool PropertyEditorValue::isAvailable() const { - const QList<QByteArray> mcuProperties = {"layer", "opacity", "rotation", "scale", "gradient", - "transformOrigin", "smooth", "antialiasing", "border"}; + const QList<QByteArray> mcuProperties = {"layer", "opacity", "gradient", "smooth", "antialiasing"}; + + const QList<QByteArray> mcuTransformProperties = {"rotation", "scale", "transformOrigin"}; + const QList<QByteArray> list = name().split('.'); const QByteArray pureName = list.first(); - QmlDesigner::DesignDocument *designDocument = - QmlDesigner::QmlDesignerPlugin::instance()->documentManager().currentDesignDocument(); - + QmlDesigner::DesignDocument *designDocument = QmlDesigner::QmlDesignerPlugin::instance() + ->documentManager() + .currentDesignDocument(); - if (designDocument && designDocument->isQtForMCUsProject()) - return !mcuProperties.contains(pureName); + if (designDocument && designDocument->isQtForMCUsProject()) { + if (mcuProperties.contains(pureName)) + return false; + if (mcuTransformProperties.contains(pureName) && !itemOrImage(m_modelNode.metaInfo())) + return false; + } return true; } diff --git a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp index af04bb676a..eda25ec9b8 100644 --- a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp +++ b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp @@ -38,6 +38,8 @@ #include <QTextTable> #include <QScopeGuard> #include <QPointer> +#include <QTextTableFormat> +#include <QPainter> #include <utils/stylehelper.h> @@ -85,6 +87,27 @@ static void cursorEditBlock(QTextCursor& cursor, std::function<void()> f) { cursor.endEditBlock(); } +static QPixmap drawColorBox(const QColor& color, const QSize& size, int borderWidth = 4) +{ + if (size.isEmpty()) { + return {}; + } + + QPixmap result(size); + + const QColor borderColor = QApplication::palette("QWidget").color(QPalette::Normal, + QPalette::Button); + + result.fill(color); + QPainter painter(&result); + QPen pen(borderColor); + pen.setWidth(borderWidth); + painter.setPen(pen); + painter.drawRect(QRect(QPoint(0,0), size)); + + return result; +} + RichTextEditor::RichTextEditor(QWidget *parent) : QWidget(parent) , ui(new Ui::RichTextEditor) @@ -214,8 +237,7 @@ void RichTextEditor::fontChanged(const QFont &f) void RichTextEditor::colorChanged(const QColor &c) { - QPixmap colorBox(ui->tableBar->iconSize()); - colorBox.fill(c); + QPixmap colorBox(drawColorBox(c, ui->tableBar->iconSize())); m_actionTextColor->setIcon(colorBox); } @@ -436,8 +458,7 @@ void RichTextEditor::setupListActions() void RichTextEditor::setupFontActions() { - QPixmap colorBox(ui->tableBar->iconSize()); - colorBox.fill(ui->textEdit->textColor()); + QPixmap colorBox(drawColorBox(ui->textEdit->textColor(), ui->tableBar->iconSize())); m_actionTextColor = ui->toolBar->addAction(colorBox, tr("&Color..."), [this]() { QColor col = QColorDialog::getColor(ui->textEdit->textColor(), this); @@ -507,7 +528,20 @@ void RichTextEditor::setupTableActions() m_actionCreateTable = ui->tableBar->addAction(createTableIcon, tr("Create Table"), [this]() { QTextCursor cursor = ui->textEdit->textCursor(); cursorEditBlock(cursor, [&] () { - cursor.insertTable(1,1); + //format table cells to look a bit better: + QTextTableFormat tableFormat; + tableFormat.setCellSpacing(2.0); + tableFormat.setCellPadding(2.0); + tableFormat.setBorder(1.0); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + tableFormat.setBorderCollapse(true); +#endif + + cursor.insertTable(1, 1, tableFormat); + + //move cursor into the first cell of the table: + ui->textEdit->setTextCursor(cursor); }); }); m_actionCreateTable->setCheckable(false); diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp index f2a83d0518..1828317a9e 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp @@ -249,4 +249,19 @@ bool StatesEditorModel::hasDefaultState() const return m_statesEditorView->hasDefaultState(); } +void StatesEditorModel::setAnnotation(int internalNodeId) +{ + m_statesEditorView->setAnnotation(internalNodeId); +} + +void StatesEditorModel::removeAnnotation(int internalNodeId) +{ + m_statesEditorView->removeAnnotation(internalNodeId); +} + +bool StatesEditorModel::hasAnnotation(int internalNodeId) const +{ + return m_statesEditorView->hasAnnotation(internalNodeId); +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h index 97c4c6a9ec..65c1385e89 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h @@ -67,6 +67,9 @@ public: Q_INVOKABLE void setStateAsDefault(int internalNodeId); Q_INVOKABLE void resetDefaultState(); Q_INVOKABLE bool hasDefaultState() const; + Q_INVOKABLE void setAnnotation(int internalNodeId); + Q_INVOKABLE void removeAnnotation(int internalNodeId); + Q_INVOKABLE bool hasAnnotation(int internalNodeId) const; void reset(); diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp index 55ebe91a76..3a15283663 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp @@ -31,6 +31,7 @@ #include <QDebug> #include <QRegularExpression> #include <cmath> +#include <memory> #include <nodemetainfo.h> @@ -40,6 +41,7 @@ #include <qmlitemnode.h> #include <qmlstate.h> +#include <annotationeditor/annotationeditor.h> namespace QmlDesigner { @@ -51,7 +53,8 @@ namespace QmlDesigner { StatesEditorView::StatesEditorView(QObject *parent) : AbstractView(parent), m_statesEditorModel(new StatesEditorModel(this)), - m_lastIndex(-1) + m_lastIndex(-1), + m_editor(nullptr) { Q_ASSERT(m_statesEditorModel); // base state @@ -59,6 +62,8 @@ StatesEditorView::StatesEditorView(QObject *parent) : StatesEditorView::~StatesEditorView() { + if (m_editor) + delete m_editor; delete m_statesEditorWidget.data(); } @@ -274,6 +279,8 @@ void StatesEditorView::setWhenCondition(int internalNodeId, const QString &condi return; m_block = true; + auto guard = [this](int* p) { m_block = false; delete p; }; + std::unique_ptr<int, decltype(guard)> scopeGuard(new int, guard); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -285,8 +292,6 @@ void StatesEditorView::setWhenCondition(int internalNodeId, const QString &condi e.showException(); } } - - m_block = false; } void StatesEditorView::resetWhenCondition(int internalNodeId) @@ -295,6 +300,8 @@ void StatesEditorView::resetWhenCondition(int internalNodeId) return; m_block = true; + auto guard = [this](int* p) { m_block = false; delete p; }; + std::unique_ptr<int, decltype(guard)> scopeGuard(new int, guard); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -306,8 +313,6 @@ void StatesEditorView::resetWhenCondition(int internalNodeId) e.showException(); } } - - m_block = false; } void StatesEditorView::setStateAsDefault(int internalNodeId) @@ -316,6 +321,8 @@ void StatesEditorView::setStateAsDefault(int internalNodeId) return; m_block = true; + auto guard = [this](int* p) { m_block = false; delete p; }; + std::unique_ptr<int, decltype(guard)> scopeGuard(new int, guard); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -327,8 +334,6 @@ void StatesEditorView::setStateAsDefault(int internalNodeId) e.showException(); } } - - m_block = false; } void StatesEditorView::resetDefaultState() @@ -337,6 +342,8 @@ void StatesEditorView::resetDefaultState() return; m_block = true; + auto guard = [this](int* p) { m_block = false; delete p; }; + std::unique_ptr<int, decltype(guard)> scopeGuard(new int, guard); try { if (rootModelNode().hasProperty("state")) @@ -345,8 +352,6 @@ void StatesEditorView::resetDefaultState() } catch (const RewritingException &e) { e.showException(); } - - m_block = false; } bool StatesEditorView::hasDefaultState() const @@ -354,6 +359,70 @@ bool StatesEditorView::hasDefaultState() const return rootModelNode().hasProperty("state"); } +void StatesEditorView::setAnnotation(int internalNodeId) +{ + if (m_block) + return; + + m_block = true; + auto guard = [this](int* p) { m_block = false; delete p; }; + std::unique_ptr<int, decltype(guard)> scopeGuard(new int, guard); + + if (hasModelNodeForInternalId(internalNodeId)) { + QmlModelState state(modelNodeForInternalId(internalNodeId)); + try { + if (state.isValid()) { + ModelNode modelNode = state.modelNode(); + + if (modelNode.isValid()) { + if (!m_editor) + m_editor = new AnnotationEditor(this); + + m_editor->setModelNode(modelNode); + m_editor->showWidget(); + } + } + + } catch (const RewritingException &e) { + e.showException(); + } + } +} + +void StatesEditorView::removeAnnotation(int internalNodeId) +{ + if (m_block) + return; + + m_block = true; + auto guard = [this](int* p) { m_block = false; delete p; }; + std::unique_ptr<int, decltype(guard)> scopeGuard(new int, guard); + + if (hasModelNodeForInternalId(internalNodeId)) { + QmlModelState state(modelNodeForInternalId(internalNodeId)); + try { + if (state.isValid()) { + state.removeAnnotation(); + } + + } catch (const RewritingException &e) { + e.showException(); + } + } +} + +bool StatesEditorView::hasAnnotation(int internalNodeId) const +{ + if (hasModelNodeForInternalId(internalNodeId)) { + QmlModelState state(modelNodeForInternalId(internalNodeId)); + if (state.isValid()) { + return state.hasAnnotation(); + } + } + + return false; +} + void StatesEditorView::modelAttached(Model *model) { if (model == AbstractView::model()) @@ -444,7 +513,12 @@ void StatesEditorView::bindingPropertiesChanged(const QList<BindingProperty> &pr void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty> &propertyList, AbstractView::PropertyChangeFlags /*propertyChange*/) { + if (m_block) + return; + m_block = true; + auto guard = [this](int* p) { m_block = false; delete p; }; + std::unique_ptr<int, decltype(guard)> scopeGuard(new int, guard); for (const VariantProperty &property : propertyList) { if (property.name() == "name" && QmlModelState::isValidQmlModelState(property.parentModelNode())) @@ -452,8 +526,6 @@ void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty> &pr else if (property.name() == "state" && property.parentModelNode().isRootNode()) resetModel(); } - - m_block = false; } void StatesEditorView::currentStateChanged(const ModelNode &node) diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h index 66ab998e04..44b4a3a380 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h @@ -33,6 +33,7 @@ namespace QmlDesigner { class StatesEditorModel; class StatesEditorWidget; +class AnnotationEditor; class StatesEditorView : public AbstractView { Q_OBJECT @@ -47,6 +48,9 @@ public: void setStateAsDefault(int internalNodeId); void resetDefaultState(); bool hasDefaultState() const; + void setAnnotation(int internalNodeId); + void removeAnnotation(int internalNodeId); + bool hasAnnotation(int internalNodeId) const; bool validStateName(const QString &name) const; QString currentStateName() const; void setCurrentState(const QmlModelState &state); @@ -102,6 +106,7 @@ private: QPointer<StatesEditorWidget> m_statesEditorWidget; int m_lastIndex; bool m_block = false; + QPointer<AnnotationEditor> m_editor; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp index 7d11f57cb3..60ca96e93e 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp @@ -84,7 +84,7 @@ static int controlWidth(QToolBar *bar, QObject *control) return 0; } -static QAction *createAction(const Core::Id &id, +static QAction *createAction(const Utils::Id &id, const QIcon &icon, const QString &name, const QKeySequence &shortcut) diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditortoolbar.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditortoolbar.cpp index af19629234..726472d149 100644 --- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditortoolbar.cpp +++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditortoolbar.cpp @@ -85,7 +85,7 @@ static int controlWidth(QToolBar *bar, QObject *control) return 0; } -static QAction *createAction(const Core::Id &id, +static QAction *createAction(const Utils::Id &id, const QIcon &icon, const QString &name, const QKeySequence &shortcut) diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorwidget.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorwidget.cpp index 5d27b4c969..87133e6861 100644 --- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorwidget.cpp +++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorwidget.cpp @@ -325,7 +325,7 @@ void TransitionEditorWidget::init() m_graphicsScene->setWidth(m_graphicsView->viewport()->width()); - m_toolbar->setScaleFactor(0); + m_toolbar->setScaleFactor(40); m_toolbar->setCurrentTransition(transition); @@ -335,7 +335,7 @@ void TransitionEditorWidget::init() m_toolbar->setDuration(duration); - m_graphicsScene->setRulerScaling(0); + m_graphicsScene->setRulerScaling(40); } void TransitionEditorWidget::updateData(const ModelNode &transition) diff --git a/src/plugins/qmldesigner/designercore/include/qmlstate.h b/src/plugins/qmldesigner/designercore/include/qmlstate.h index 156e441615..7c43ac8776 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlstate.h +++ b/src/plugins/qmldesigner/designercore/include/qmlstate.h @@ -34,6 +34,8 @@ namespace QmlDesigner { class AbstractViewAbstractVieweGroup; class QmlObjectNode; class QmlModelStateGroup; +class Annotation; +class AnnotationEditor; class QMLDESIGNERCORE_EXPORT QmlModelState : public QmlModelNodeFacade { @@ -72,6 +74,12 @@ public: void setAsDefault(); bool isDefault() const; + void setAnnotation(const Annotation &annotation, const QString &id); + Annotation annotation() const; + QString annotationName() const; + bool hasAnnotation() const; + void removeAnnotation(); + protected: void addChangeSetIfNotExists(const ModelNode &node); static QmlModelState createBaseState(const AbstractView *view); diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index 66dc5ffce9..42e890fec9 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -508,9 +508,13 @@ QString AbstractView::generateNewId(const QString &prefixName) const { QString fixedPrefix = firstCharToLower(prefixName); fixedPrefix.remove(' '); + + bool forceSuffix = false; + if (!ModelNode::isValidId(fixedPrefix)) - return generateNewId("element"); - int counter = 1; + forceSuffix = true; + + int counter = 0; /* First try just the prefixName without number as postfix, then continue with 2 and further as postfix * until id does not already exist. @@ -520,11 +524,14 @@ QString AbstractView::generateNewId(const QString &prefixName) const */ QString newId = QString(QStringLiteral("%1")).arg(firstCharToLower(prefixName)); + if (forceSuffix) + QString(QStringLiteral("%1%2")).arg(firstCharToLower(prefixName)).arg(1); + newId.remove(QRegularExpression(QStringLiteral("[^a-zA-Z0-9_]"))); while (!ModelNode::isValidId(newId) || hasId(newId) || rootModelNode().hasProperty(newId.toUtf8()) || newId == "item") { counter += 1; - newId = QString(QStringLiteral("%1%2")).arg(firstCharToLower(prefixName)).arg(counter - 1); + newId = QString(QStringLiteral("%1%2")).arg(firstCharToLower(prefixName)).arg(counter); newId.remove(QRegularExpression(QStringLiteral("[^a-zA-Z0-9_]"))); } diff --git a/src/plugins/qmldesigner/designercore/model/qmlstate.cpp b/src/plugins/qmldesigner/designercore/model/qmlstate.cpp index 89bbec351e..ea15ba1d81 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlstate.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlstate.cpp @@ -32,6 +32,7 @@ #include "bindingproperty.h" #include "qmlchangeset.h" #include "qmlitemnode.h" +#include "annotation.h" #include <utils/qtcassert.h> @@ -304,6 +305,43 @@ bool QmlModelState::isDefault() const return false; } +void QmlModelState::setAnnotation(const Annotation &annotation, const QString &id) +{ + if (modelNode().isValid()) { + modelNode().setCustomId(id); + modelNode().setAnnotation(annotation); + } +} + +Annotation QmlModelState::annotation() const +{ + if (modelNode().isValid()) + return modelNode().annotation(); + return {}; +} + +QString QmlModelState::annotationName() const +{ + if (modelNode().isValid()) + return modelNode().customId(); + return {}; +} + +bool QmlModelState::hasAnnotation() const +{ + if (modelNode().isValid()) + return modelNode().hasAnnotation() || modelNode().hasCustomId(); + return false; +} + +void QmlModelState::removeAnnotation() +{ + if (modelNode().isValid()) { + modelNode().removeCustomId(); + modelNode().removeAnnotation(); + } +} + QmlModelState QmlModelState::createBaseState(const AbstractView *view) { QmlModelState qmlModelState(view->rootModelNode()); diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index d17bf5a10c..bd7d09af31 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -246,9 +246,9 @@ void DesignModeWidget::setup() const QString undockUnicode = Theme::getIconUnicode(Theme::Icon::adsDetach); const QString fontName = "qtds_propertyIconFont.ttf"; + const QIcon closeIcon = Utils::StyleHelper::getIconFromIconFont(fontName, closeUnicode, 28, 28, buttonColor); const QIcon menuIcon = Utils::StyleHelper::getIconFromIconFont(fontName, menuUnicode, 28, 28, buttonColor); const QIcon undockIcon = Utils::StyleHelper::getIconFromIconFont(fontName, undockUnicode, 28, 28, buttonColor); - const QIcon closeIcon = Utils::StyleHelper::getIconFromIconFont(fontName, closeUnicode, 28, 28, buttonColor); auto closeIconNormal = Utils::StyleHelper::IconFontHelper(closeUnicode, tabColor, diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index e1ebfc0a3f..4550d8a4ea 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -110,7 +110,7 @@ static void openFileComponent(const ModelNode &modelNode) { QmlDesignerPlugin::instance()->viewManager().nextFileIsCalledInternally(); Core::EditorManager::openEditor(modelNode.metaInfo().componentFileName(), - Core::Id(), Core::EditorManager::DoNotMakeVisible); + Utils::Id(), Core::EditorManager::DoNotMakeVisible); } static void openFileComponentForDelegate(const ModelNode &modelNode) @@ -136,7 +136,7 @@ static void openComponentSourcePropertyOfLoader(const ModelNode &modelNode) componentModelNode = modelNode.nodeListProperty("component").toModelNodeList().constFirst(); } - Core::EditorManager::openEditor(componentModelNode.metaInfo().componentFileName(), Core::Id(), Core::EditorManager::DoNotMakeVisible); + Core::EditorManager::openEditor(componentModelNode.metaInfo().componentFileName(), Utils::Id(), Core::EditorManager::DoNotMakeVisible); } static void openSourcePropertyOfLoader(const ModelNode &modelNode) @@ -146,7 +146,7 @@ static void openSourcePropertyOfLoader(const ModelNode &modelNode) QString componentFileName = modelNode.variantProperty("source").value().toString(); QFileInfo fileInfo(modelNode.model()->fileUrl().toLocalFile()); - Core::EditorManager::openEditor(fileInfo.absolutePath() + "/" + componentFileName, Core::Id(), Core::EditorManager::DoNotMakeVisible); + Core::EditorManager::openEditor(fileInfo.absolutePath() + "/" + componentFileName, Utils::Id(), Core::EditorManager::DoNotMakeVisible); } diff --git a/src/plugins/winrt/winrtpackagedeploymentstep.cpp b/src/plugins/winrt/winrtpackagedeploymentstep.cpp index 1a45fb92a0..5e7acefaf9 100644 --- a/src/plugins/winrt/winrtpackagedeploymentstep.cpp +++ b/src/plugins/winrt/winrtpackagedeploymentstep.cpp @@ -225,7 +225,9 @@ bool WinRtPackageDeploymentStep::init() return false; } params->setCommandLine(windeployqt); - params->setEnvironment(buildEnvironment()); + params->setEnvironment(target()->activeBuildConfiguration() + ? target()->activeBuildConfiguration()->environment() + : Environment::systemEnvironment()); return AbstractProcessStep::init(); } diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 3b816f01cd..f6b2d3c5f3 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -71,8 +71,11 @@ QStringList ProFileEvaluator::values(const QString &variableName) const const ProStringList &values = d->values(ProKey(variableName)); QStringList ret; ret.reserve(values.size()); - foreach (const ProString &str, values) - ret << d->m_option->expandEnvVars(str.toQString()); + for (const ProString &str : values) { + const QString expanded = d->m_option->expandEnvVars(str.toQString()); + if (!expanded.isEmpty() || str.isEmpty()) + ret << expanded; + } return ret; } |
