From 7e82a674ae57c4f1b6304ca29fe8ee023e5817f8 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 3 Jun 2019 13:59:46 +0200 Subject: [PATCH 01/28] WorkingDirectoryAspect: Fix UI tab order Change-Id: Ie70f582a1dcadb5f6d07a37f6ac06e5a4cd8d545 Reviewed-by: hjk --- src/plugins/projectexplorer/runconfigurationaspects.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp index 697b4567584..fe890b3a294 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.cpp +++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp @@ -141,11 +141,6 @@ WorkingDirectoryAspect::WorkingDirectoryAspect() void WorkingDirectoryAspect::addToConfigurationLayout(QFormLayout *layout) { QTC_CHECK(!m_chooser); - m_resetButton = new QToolButton(layout->parentWidget()); - m_resetButton->setToolTip(tr("Reset to Default")); - m_resetButton->setIcon(Utils::Icons::RESET.icon()); - connect(m_resetButton.data(), &QAbstractButton::clicked, this, &WorkingDirectoryAspect::resetPath); - m_chooser = new PathChooser(layout->parentWidget()); m_chooser->setHistoryCompleter(settingsKey()); m_chooser->setExpectedKind(Utils::PathChooser::Directory); @@ -158,6 +153,10 @@ void WorkingDirectoryAspect::addToConfigurationLayout(QFormLayout *layout) m_resetButton->setEnabled(m_workingDirectory != m_defaultWorkingDirectory); }); + m_resetButton = new QToolButton(layout->parentWidget()); + m_resetButton->setToolTip(tr("Reset to Default")); + m_resetButton->setIcon(Utils::Icons::RESET.icon()); + connect(m_resetButton.data(), &QAbstractButton::clicked, this, &WorkingDirectoryAspect::resetPath); m_resetButton->setEnabled(m_workingDirectory != m_defaultWorkingDirectory); if (m_envAspect) { From 5a7b0e9fcf9407839186876c3dae31957ce35a37 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 22 May 2019 08:53:06 +0200 Subject: [PATCH 02/28] Revert "Work around OpenGL issue in macOS 10.14.4" Fixed in macOS 10.14.5 This reverts commit 4bdfaafc4246771bf1cbc87968287f5af5098362. Task-number: QTCREATORBUG-22215 Change-Id: I33c0965e22d61a9a745ed05dd330f6e938ceb3e1 Reviewed-by: Alessandro Portale (cherry picked from commit 9645687e539bd0ea286fb4136329458c3db3694e) --- src/app/app-Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/app-Info.plist b/src/app/app-Info.plist index 2e2614b34a6..5893f062a8a 100644 --- a/src/app/app-Info.plist +++ b/src/app/app-Info.plist @@ -194,6 +194,8 @@ NSPrincipalClass NSApplication + NSSupportsAutomaticGraphicsSwitching + CFBundleDocumentTypes From d6848fc83105d331cab3c63ffc3cd5e45d2f75e9 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 9 Apr 2019 15:03:54 +0200 Subject: [PATCH 03/28] ProjectExplorer: Allow text filtering in issues pane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTCREATORBUG-21893 Fixes: QTCREATORBUG-22083 Change-Id: Ida227ce21d90fc2487cf3009e957eedeec507fd0 Reviewed-by: AndrĂ© Hartmann --- src/plugins/coreplugin/ioutputpane.h | 1 + src/plugins/projectexplorer/taskmodel.cpp | 7 ++++++- src/plugins/projectexplorer/taskwindow.cpp | 10 +++++++++- src/plugins/projectexplorer/taskwindow.h | 2 ++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreplugin/ioutputpane.h b/src/plugins/coreplugin/ioutputpane.h index 506ecddf5fb..40c6401b379 100644 --- a/src/plugins/coreplugin/ioutputpane.h +++ b/src/plugins/coreplugin/ioutputpane.h @@ -100,6 +100,7 @@ protected: void setupFilterUi(const QString &historyKey); QString filterText() const; void setFilteringEnabled(bool enable); + QWidget *filterWidget() const { return m_filterOutputLineEdit; } void setZoomButtonsEnabled(bool enabled); diff --git a/src/plugins/projectexplorer/taskmodel.cpp b/src/plugins/projectexplorer/taskmodel.cpp index 3baac2c8418..c3fac880e21 100644 --- a/src/plugins/projectexplorer/taskmodel.cpp +++ b/src/plugins/projectexplorer/taskmodel.cpp @@ -362,9 +362,14 @@ bool TaskFilterModel::filterAcceptsTask(const Task &task) const break; } - if (m_categoryIds.contains(task.category)) + if (accept && m_categoryIds.contains(task.category)) accept = false; + if (accept && !filterRegExp().isEmpty() && !task.file.toString().contains(filterRegExp()) + && !task.description.contains(filterRegExp())) { + accept = false; + } + return accept; } diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp index 0ae486a695b..8f8e96cfb70 100644 --- a/src/plugins/projectexplorer/taskwindow.cpp +++ b/src/plugins/projectexplorer/taskwindow.cpp @@ -289,6 +289,9 @@ TaskWindow::TaskWindow() : d(std::make_unique()) d->m_categoriesButton->setMenu(d->m_categoriesMenu); + setupFilterUi("IssuesPane.Filter"); + setFilteringEnabled(true); + TaskHub *hub = TaskHub::instance(); connect(hub, &TaskHub::categoryAdded, this, &TaskWindow::addCategory); connect(hub, &TaskHub::taskAdded, this, &TaskWindow::addTask); @@ -355,7 +358,7 @@ void TaskWindow::delayedInitialization() QList TaskWindow::toolBarWidgets() const { - return {d->m_filterWarningsButton, d->m_categoriesButton}; + return {d->m_filterWarningsButton, d->m_categoriesButton, filterWidget()}; } QWidget *TaskWindow::outputWidget(QWidget *) @@ -664,6 +667,11 @@ void TaskWindow::goToPrev() triggerDefaultHandler(currentIndex); } +void TaskWindow::updateFilter() +{ + d->m_filter->setFilterRegExp(filterText()); +} + bool TaskWindow::canNavigate() const { return true; diff --git a/src/plugins/projectexplorer/taskwindow.h b/src/plugins/projectexplorer/taskwindow.h index 290927b47bb..efefb72658f 100644 --- a/src/plugins/projectexplorer/taskwindow.h +++ b/src/plugins/projectexplorer/taskwindow.h @@ -82,6 +82,8 @@ signals: void tasksCleared(); private: + void updateFilter() override; + void addCategory(Core::Id categoryId, const QString &displayName, bool visible); void addTask(const ProjectExplorer::Task &task); void removeTask(const ProjectExplorer::Task &task); From 34341ffc3079f5c4251bc621a3dff0f25fd72ae0 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 3 Jun 2019 08:48:33 +0200 Subject: [PATCH 04/28] Debugger: Improve perspective geometry persistence Setting sizes on dock widgets one-by-one to restore previous layouts does not work, as each triggers a delayed update taking other (at that time "wrong" sizes) into account. So store the layout as a whole, per-perspective. Task-number: QTCREATORBUG-21669 Change-Id: I854cd175297b4ba1e53b404fcaa20092d216cec0 Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggermainwindow.cpp | 27 +++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index 9fe1a7e546a..ca206d6e178 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -161,6 +161,9 @@ public: QList> m_perspectives; QSet m_persistentChangedDocks; + + QHash m_lastPerspectiveStates; + QHash m_lastTypePerspectiveStates; }; DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent) @@ -431,10 +434,11 @@ void DebuggerMainWindow::restorePersistentSettings() qCDebug(perspectivesLog) << "RESTORE PERSISTENT"; QSettings *settings = ICore::settings(); settings->beginGroup(MAINWINDOW_KEY); - const bool res = theMainWindow->restoreState(settings->value(STATE_KEY).toByteArray(), - SettingsVersion); - if (!res) - qCDebug(perspectivesLog) << "NO READABLE PERSISTENT SETTINGS FOUND, ASSUMING NEW CLEAN SETTINGS"; + + const QHash states = settings->value(STATE_KEY).toHash(); + theMainWindow->d->m_lastTypePerspectiveStates.clear(); + for (const QString &type : states.keys()) + theMainWindow->d->m_lastTypePerspectiveStates.insert(type, states.value(type).toByteArray()); theMainWindow->setAutoHideTitleBars(settings->value(AUTOHIDE_TITLEBARS_KEY, true).toBool()); theMainWindow->showCentralWidget(settings->value(SHOW_CENTRALWIDGET_KEY, true).toBool()); @@ -497,10 +501,14 @@ void DebuggerMainWindow::savePersistentSettings() theMainWindow->d->m_persistentChangedDocks = changedDocks; qCDebug(perspectivesLog) << "CHANGED DOCKS:" << changedDocks; + QVariantHash states; + for (const QString &type : theMainWindow->d->m_lastTypePerspectiveStates.keys()) + states.insert(type, QVariant::fromValue(theMainWindow->d->m_lastTypePerspectiveStates.value(type))); + QSettings *settings = ICore::settings(); settings->beginGroup(MAINWINDOW_KEY); settings->setValue(CHANGED_DOCK_KEY, QStringList(changedDocks.toList())); - settings->setValue(STATE_KEY, theMainWindow->saveState(SettingsVersion)); + settings->setValue(STATE_KEY, states); settings->setValue(AUTOHIDE_TITLEBARS_KEY, theMainWindow->autoHideTitleBars()); settings->setValue(SHOW_CENTRALWIDGET_KEY, theMainWindow->isCentralWidgetShown()); settings->endGroup(); @@ -941,6 +949,13 @@ void PerspectivePrivate::restoreLayout() << (active == op.visibleByDefault ? "DEFAULT USER" : "*** NON-DEFAULT USER"); } } + + QByteArray state; + if (theMainWindow->d->m_lastTypePerspectiveStates.contains(settingsId())) + state = theMainWindow->d->m_lastTypePerspectiveStates.value(settingsId()); + if (theMainWindow->d->m_lastPerspectiveStates.contains(m_id)) + state = theMainWindow->d->m_lastPerspectiveStates.value(m_id); + theMainWindow->restoreState(state); } void PerspectivePrivate::saveLayout() @@ -960,6 +975,8 @@ void PerspectivePrivate::saveLayout() << (active == op.visibleByDefault ? "DEFAULT USER" : "*** NON-DEFAULT USER"); } } + theMainWindow->d->m_lastPerspectiveStates.insert(m_id, theMainWindow->saveState()); + theMainWindow->d->m_lastTypePerspectiveStates.insert(settingsId(), theMainWindow->saveState()); } QString PerspectivePrivate::settingsId() const From 0dc533ad670260a7e11ad36ec932c98614f7ca6d Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 3 Jun 2019 14:04:30 +0200 Subject: [PATCH 05/28] Fix Windows build build with namespaced Qt For real this time. Amends 8dd8d68bdc. Fixes: QTCREATORBUG-22305 Change-Id: I61133f76b7e39a2b0168f8a6c19721231d443807 Reviewed-by: Christian Stenger --- src/shared/proparser/registry.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shared/proparser/registry.cpp b/src/shared/proparser/registry.cpp index 960b6f8e580..12c268ae2be 100644 --- a/src/shared/proparser/registry.cpp +++ b/src/shared/proparser/registry.cpp @@ -29,6 +29,8 @@ #include #include "registry_p.h" +QT_BEGIN_NAMESPACE + namespace QMakeInternal { #ifdef Q_OS_WIN32 @@ -156,3 +158,4 @@ QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, unsigned l } // namespace QMakeInternal +QT_END_NAMESPACE From 2f7ca2ce44a1f0131dd99105315df8ba7e3623a0 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 4 Jun 2019 13:37:45 +0200 Subject: [PATCH 06/28] CPlusPlus: Avoid a few deprecation warnings The alternatives have been around since 2012. Change-Id: I0aa15d59efe8a547e2ad622ffda689746960d48c Reviewed-by: Nikolai Kosjar --- src/libs/cplusplus/CppDocument.cpp | 3 +-- src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp | 5 ++--- tests/auto/cplusplus/ast/tst_ast.cpp | 2 +- tests/auto/cplusplus/c99/tst_c99.cpp | 5 ++--- tests/auto/cplusplus/cxx11/tst_cxx11.cpp | 5 ++--- tests/auto/cplusplus/semantic/tst_semantic.cpp | 2 +- tests/auto/cplusplus/translationunit/tst_translationunit.cpp | 2 +- 7 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index c029c60dcaa..73cc06f26ad 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -228,8 +228,7 @@ public: if (fileName != doc->fileName()) return; - QString message; - message.vsprintf(format, ap); + const QString message = QString::vasprintf(format, ap); #ifndef DO_NOT_DUMP_ALL_PARSER_ERRORS { diff --git a/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp b/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp index 59aab237ec1..ad69adae56f 100644 --- a/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp +++ b/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp @@ -423,12 +423,11 @@ public: static const char *const pretty[] = {"warning", "error", "fatal"}; - QString str; - str.sprintf("%s:%d:%d: When parsing as %s: %s: ", fileName->chars(), line, column, + QString str = QString::asprintf("%s:%d:%d: When parsing as %s: %s: ", fileName->chars(), line, column, parseModeToString(m_parseMode).toUtf8().constData(), pretty[level]); m_errorString->append(str.toUtf8()); - str.vsprintf(format, ap); + str += QString::vasprintf(format, ap); m_errorString->append(str.toUtf8()); m_errorString->append('\n'); } diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 0cf9c7a5609..e444a4b8e5e 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -97,7 +97,7 @@ public: { ++errorCount; - qDebug() << fileName->chars()<<':'<chars()<<':'<chars(), line, column, pretty[level]); + QString str = QString::asprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]); errors->append(str.toUtf8()); - str.vsprintf(format, ap); + str += QString::vasprintf(format, ap); errors->append(str.toUtf8()); errors->append('\n'); diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp index 108d93f18f7..abef7cc1e17 100644 --- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp +++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp @@ -85,11 +85,10 @@ class tst_cxx11: public QObject static const char *const pretty[] = {"warning", "error", "fatal"}; - QString str; - str.sprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]); + QString str = QString::asprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]); errors->append(str.toUtf8()); - str.vsprintf(format, ap); + str += QString::vasprintf(format, ap); errors->append(str.toUtf8()); errors->append('\n'); diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 3904558efcd..e13795154bf 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -120,7 +120,7 @@ public: ++errorCount; #ifndef NO_PARSER_OR_SEMANTIC_ERROR_MESSAGES - qDebug() << fileName->chars()<<':'<chars()<<':'<chars() << ':' << line << ':' << column - << ' ' << QString().vsprintf(format, ap); + << ' ' << QString::vasprintf(format, ap); } } m_diagnosticClient; }; From e261f6779f983c589678e2924e4e042a1597a5da Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 4 Apr 2019 15:33:23 +0200 Subject: [PATCH 07/28] Doc: Update guidelines to improve the quality of screenshots in docs Use resolution 1366x768 for taking screen shots and don't resize them. Fixes: QTCREATORBUG-16076 Change-Id: Iecb5eb86586579d7d381824fcbc4b873809952e2 Reviewed-by: Brook Cronin Reviewed-by: hjk --- doc/api/qtcreator-documentation.qdoc | 30 +++++++++------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/doc/api/qtcreator-documentation.qdoc b/doc/api/qtcreator-documentation.qdoc index 28e1b32fdc4..1d54a869128 100644 --- a/doc/api/qtcreator-documentation.qdoc +++ b/doc/api/qtcreator-documentation.qdoc @@ -165,18 +165,14 @@ the \QC Manual, observe the guidelines listed in this section when taking screen shots. - To make the images look similar regardless of the operating system they were - taken on, you are asked to adjust their size to 75%. This makes the screen - shots hard to read, but they are provided more as reassurance for users that - they are in the correct place in the UI than as an actual source of - information. To make sure that no important information is lost, always - place example values also in the text. + \note Do not rely on screen shots present reasonable example values to + users, but always place example values also in the text. \list - \li Use the screen resolution of 1024x768 (this is available on all - screens). + \li Use the screen resolution of 1366x768 (available on the most + commonly used screens, as of this writing). - \li Use the aspect ratio of 4:3. + \li Use the aspect ratio of 16:9. \li Open the application in the maximum size on full screen. @@ -185,9 +181,6 @@ \li Include only the part of the screen that you need (you can crop the image also in the screen capture tool). - \li In the screen capture tool, open the screen shot and adjust its size - to 75%. - \li To highlight parts of the screen shot, use the images of numbers that are stored in \c{doc\images\numbers} in the \QC repository. @@ -212,13 +205,8 @@ \c doc\images\numbers directory (or in the \c qtdoc module sources in \c doc\images\numbers). - To use the numbers: - - \list - \li Take a screenshot as described above. - \li After resizing the screenshot, copy-paste the number images on - the screenshot to the places that you want to refer to from text. - \endlist + To use the numbers, copy-paste the number images on the screenshot to the + places that you want to refer to from text. \section2 Optimizing Images @@ -234,8 +222,8 @@ You can use a web service, such as \l{https://tinypng.com}, or an image optimization tool to shrink the images. For example, you can use the Radical - Image Optimization Tool (RIOT) on Windows (very efficient) or ImageOptim on - \macos (much less efficient), or some other tool available on Linux. + Image Optimization Tool (RIOT) or OptiPNG on Windows, ImageOptim on + \macos, or some other tool available on Linux. With ImageOptim, you simply drag and drop the image files to the application. The following section describes the settings to use for RIOT. From 6178e871da150c0791c819ecb85a7ed245867eef Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 4 Jun 2019 18:23:55 +0200 Subject: [PATCH 08/28] SSH: Add missing return statement Change-Id: Ic109b0b5a022ea462532fbf21736ee7124168608 Reviewed-by: hjk --- src/libs/ssh/sshconnection.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/ssh/sshconnection.cpp b/src/libs/ssh/sshconnection.cpp index 703d20932ca..91d8446db97 100644 --- a/src/libs/ssh/sshconnection.cpp +++ b/src/libs/ssh/sshconnection.cpp @@ -348,8 +348,10 @@ void SshConnection::doConnectToHost() .arg(sshBinary.toUserOutput())); return; } - if (!d->sharingEnabled) + if (!d->sharingEnabled) { emitConnected(); + return; + } d->masterSocketDir.reset(new QTemporaryDir); if (!d->masterSocketDir->isValid()) { emitError(tr("Cannot establish SSH connection: Failed to create temporary " From 2f0510b1716dafe5a32c796765ef741ff2efaf03 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 4 Jun 2019 10:54:41 +0200 Subject: [PATCH 09/28] StudioWelcome: Register help for Qt Quick Controls 2 Change-Id: I76402eb0026ae6c892ce69a1af38f966a5ca9854 Reviewed-by: Tim Jenssen --- src/plugins/studiowelcome/studiowelcomeplugin.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index 99520c558d5..1064b5cf1b1 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -44,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -281,6 +283,16 @@ WelcomeMode::WelcomeMode() #endif setWidget(m_modeWidget); + + QStringList designStudioQchPathes = {Core::HelpManager::documentationPath() + + "/qtdesignstudio.qch", + Core::HelpManager::documentationPath() + "/qtquick.qch", + Core::HelpManager::documentationPath() + + "/qtquickcontrols.qch"}; + + Core::HelpManager::registerDocumentation( + Utils::filtered(designStudioQchPathes, + [](const QString &path) { return QFileInfo::exists(path); })); } WelcomeMode::~WelcomeMode() From ab838b9739f8cf8be9854519e404a97bf235c7b4 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 4 Jun 2019 11:14:06 +0200 Subject: [PATCH 10/28] StudioWelcome: Add some adjustments Change-Id: Ia208b56cbeb378a4763314cc1bf398f864c36d93 Reviewed-by: Tim Jenssen --- .../studiowelcome/qml/splashscreen/Welcome_splash.qml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml b/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml index 2ef36045f27..338a6864b83 100644 --- a/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml +++ b/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml @@ -42,8 +42,8 @@ Image { Image { id: logo - x: 16 - y: 18 + x: 14 + y: 8 width: 76 height: 66 fillMode: Image.PreserveAspectFit @@ -52,8 +52,10 @@ Image { Text { id: qt_design_studio - x: 14 + x: 13 y: 93 + width: 250 + height: 55 color: "#4cd265" text: qsTr("Qt Design Studio") font.pixelSize: 36 From e9cde9d6ad58c7607a197d3a945b19e07dbd43ff Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 4 Jun 2019 10:58:23 +0200 Subject: [PATCH 11/28] StudioWelcome: Expose community edition property Change-Id: I173576bfaa2ae77f8bf5ee477b1952a30c7de75a Reviewed-by: Tim Jenssen --- .../mockData/projectmodel/ProjectModel.qml | 2 ++ src/plugins/studiowelcome/studiowelcomeplugin.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml b/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml index d0524f3b465..bca1783d422 100644 --- a/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml +++ b/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml @@ -26,6 +26,8 @@ import QtQuick 2.0 ListModel { + + property bool communityVersion: true ListElement { displayName: "Project 01" prettyFilePath: "my_file_1" diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index 1064b5cf1b1..864acf4e83f 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -67,6 +67,8 @@ class ProjectModel : public QAbstractListModel public: enum { FilePathRole = Qt::UserRole+1, PrettyFilePathRole }; + Q_PROPERTY(bool communityVersion MEMBER m_communityVersion NOTIFY communityVersionChanged) + explicit ProjectModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent) const override; @@ -104,6 +106,12 @@ public: } public slots: void resetProjects(); + +signals: + void communityVersionChanged(); + +private: + bool m_communityVersion = false; }; ProjectModel::ProjectModel(QObject *parent) @@ -113,6 +121,12 @@ ProjectModel::ProjectModel(QObject *parent) &ProjectExplorer::ProjectExplorerPlugin::recentProjectsChanged, this, &ProjectModel::resetProjects); + +#ifdef LICENSECHECKER + if (!Utils::findOrDefault(ExtensionSystem::PluginManager::plugins(), + Utils::equal(&ExtensionSystem::PluginSpec::name, QString("LicenseChecker")))) + m_communityVersion = true; +#endif } int ProjectModel::rowCount(const QModelIndex &) const From 737a64aa2449ef6f5ca99b2f80acbff5ad9558d8 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 4 Jun 2019 10:49:55 +0200 Subject: [PATCH 12/28] QmlDesigner: Increase mouse area to include text label Change-Id: Id7c87f8dd1cb68338293fae78a73a5298584462e Reviewed-by: Tim Jenssen --- .../studiowelcome/qml/welcomepage/HoverOverDesaturate.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml b/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml index 823d9407e66..e160a1f70e3 100644 --- a/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml +++ b/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml @@ -66,6 +66,7 @@ Item { x: 17 y: 12 height: 125 + anchors.bottomMargin: -label.height anchors.fill: parent hoverEnabled: true onHoveredChanged: { From 8e2e9662112cb09a7d6b3524c472d0978a4c4eb3 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 4 Jun 2019 11:45:54 +0200 Subject: [PATCH 13/28] StudioWelcome: Fix checkbox Change-Id: I6dbbe507c91c6357aed70ddc8db923a712266234 Reviewed-by: Tim Jenssen --- .../qml/splashscreen/NoShowCheckbox.qml | 48 +++++++++++++++++++ .../qml/splashscreen/Welcome_splash.qml | 28 +++-------- 2 files changed, 54 insertions(+), 22 deletions(-) create mode 100644 src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml diff --git a/src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml b/src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml new file mode 100644 index 00000000000..d2f7454f093 --- /dev/null +++ b/src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.7 +import QtQuick.Timeline 1.0 +import QtQuick.Controls 2.12 +import welcome 1.0 + +CheckBox { + id: do_not_show_checkBox + width: 268 + height: 40 + text: qsTr("Don't show this again") + spacing: 12 + + + contentItem: Text { + text:do_not_show_checkBox.text + font.family: "titillium web" + color: "#ffffff" + font.pointSize: 24 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + leftPadding: do_not_show_checkBox.indicator.width + do_not_show_checkBox.spacing + } +} diff --git a/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml b/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml index 338a6864b83..09c2e7757e9 100644 --- a/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml +++ b/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml @@ -182,30 +182,14 @@ Image { } } - Text { - id: do_not_show_text - x: 42 - y: 432 - width: 143 - height: 31 - color: "#ffffff" - text: qsTr("Don't show this again") - font.wordSpacing: 0 - font.pixelSize: 12 - font.family: StudioFonts.titilliumWeb_light - wrapMode: Text.WordWrap + NoShowCheckbox { + id: do_not_show_checkBox + x: -47 + y: 430 + padding: 0 + scale: 0.5 } - CheckBox { - id: do_not_show_checkBox - x: 7 - y: 421 - width: 34 - height: 40 - text: qsTr("") - scale: 0.5 - font.pointSize: 9 - } RowLayout { x: 16 From e34b41934d68430c58107a700e3730595e88075d Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 15 May 2019 13:56:03 +0200 Subject: [PATCH 14/28] Output panes: Respect filter options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The UI elements for case sensitivity and regexp behavior had not been doing anything until now. Change-Id: Ie210103984fda64d4249c56f9a5b21200132108f Reviewed-by: AndrĂ© Hartmann --- src/plugins/coreplugin/ioutputpane.h | 4 ++- .../coreplugin/messageoutputwindow.cpp | 2 +- src/plugins/coreplugin/outputpanemanager.cpp | 4 ++- src/plugins/coreplugin/outputwindow.cpp | 33 ++++++------------- src/plugins/coreplugin/outputwindow.h | 6 +--- src/plugins/projectexplorer/appoutputpane.cpp | 9 +++-- .../projectexplorer/compileoutputwindow.cpp | 3 +- src/plugins/projectexplorer/taskmodel.cpp | 29 ++++++++++++++-- src/plugins/projectexplorer/taskmodel.h | 8 +++++ src/plugins/projectexplorer/taskwindow.cpp | 2 +- 10 files changed, 61 insertions(+), 39 deletions(-) diff --git a/src/plugins/coreplugin/ioutputpane.h b/src/plugins/coreplugin/ioutputpane.h index 40c6401b379..d219e2aefff 100644 --- a/src/plugins/coreplugin/ioutputpane.h +++ b/src/plugins/coreplugin/ioutputpane.h @@ -99,6 +99,8 @@ signals: protected: void setupFilterUi(const QString &historyKey); QString filterText() const; + bool filterUsesRegexp() const { return m_filterRegexp; } + Qt::CaseSensitivity filterCaseSensitivity() const { return m_filterCaseSensitivity; } void setFilteringEnabled(bool enable); QWidget *filterWidget() const { return m_filterOutputLineEdit; } @@ -119,7 +121,7 @@ private: QAction *m_filterActionCaseSensitive = nullptr; Utils::FancyLineEdit *m_filterOutputLineEdit = nullptr; bool m_filterRegexp = false; - bool m_filterCaseSensitive = false; + Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive; }; } // namespace Core diff --git a/src/plugins/coreplugin/messageoutputwindow.cpp b/src/plugins/coreplugin/messageoutputwindow.cpp index 70bef5dc114..60092829537 100644 --- a/src/plugins/coreplugin/messageoutputwindow.cpp +++ b/src/plugins/coreplugin/messageoutputwindow.cpp @@ -146,7 +146,7 @@ bool MessageOutputWindow::canNavigate() const void MessageOutputWindow::updateFilter() { - m_widget->setFilterText(filterText()); + m_widget->updateFilterProperties(filterText(), filterCaseSensitivity(), filterUsesRegexp()); } } // namespace Internal diff --git a/src/plugins/coreplugin/outputpanemanager.cpp b/src/plugins/coreplugin/outputpanemanager.cpp index 5bee2fb5f75..951fed419b0 100644 --- a/src/plugins/coreplugin/outputpanemanager.cpp +++ b/src/plugins/coreplugin/outputpanemanager.cpp @@ -195,6 +195,7 @@ void IOutputPane::filterOutputButtonClicked() void IOutputPane::setRegularExpressions(bool regularExpressions) { m_filterRegexp = regularExpressions; + updateFilter(); } Id IOutputPane::filterRegexpActionId() const @@ -209,7 +210,8 @@ Id IOutputPane::filterCaseSensitivityActionId() const void IOutputPane::setCaseSensitive(bool caseSensitive) { - m_filterCaseSensitive = caseSensitive; + m_filterCaseSensitivity = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; + updateFilter(); } namespace Internal { diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp index 2759777863f..2b5de1b2b6f 100644 --- a/src/plugins/coreplugin/outputwindow.cpp +++ b/src/plugins/coreplugin/outputwindow.cpp @@ -284,15 +284,16 @@ void OutputWindow::setHighlightTextColor(const QColor &textColor) d->highlightTextColor = textColor; } -QString OutputWindow::filterText() const -{ - return d->filterText; -} - -void OutputWindow::setFilterText(const QString &filterText) +void OutputWindow::updateFilterProperties(const QString &filterText, + Qt::CaseSensitivity caseSensitivity, bool isRegexp) { + FilterModeFlags flags; + flags.setFlag(FilterModeFlag::CaseSensitive, caseSensitivity == Qt::CaseSensitive) + .setFlag(FilterModeFlag::RegExp, isRegexp); + if (d->filterMode == flags && d->filterText == filterText) + return; + d->lastFilteredBlock = {}; if (d->filterText != filterText) { - d->lastFilteredBlock = {}; const bool filterTextWasEmpty = d->filterText.isEmpty(); d->filterText = filterText; @@ -313,23 +314,9 @@ void OutputWindow::setFilterText(const QString &filterText) setPalette(pal); setReadOnly(true); } - - filterNewContent(); - } -} - -OutputWindow::FilterModeFlags OutputWindow::filterMode() const -{ - return d->filterMode; -} - -void OutputWindow::setFilterMode(OutputWindow::FilterModeFlag filterMode, bool enabled) -{ - if (d->filterMode.testFlag(filterMode) != enabled) { - d->filterMode.setFlag(filterMode, enabled); - d->lastFilteredBlock = {}; - filterNewContent(); } + d->filterMode = flags; + filterNewContent(); } void OutputWindow::filterNewContent() diff --git a/src/plugins/coreplugin/outputwindow.h b/src/plugins/coreplugin/outputwindow.h index 99c49a4cc18..03760cbce3e 100644 --- a/src/plugins/coreplugin/outputwindow.h +++ b/src/plugins/coreplugin/outputwindow.h @@ -79,11 +79,7 @@ public: void setHighlightBgColor(const QColor &bgColor); void setHighlightTextColor(const QColor &textColor); - QString filterText() const; - void setFilterText(const QString &filterText); - - FilterModeFlags filterMode() const; - void setFilterMode(FilterModeFlag filterMode, bool enabled); + void updateFilterProperties(const QString &filterText, Qt::CaseSensitivity caseSensitivity, bool regexp); signals: void wheelZoom(); diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index c9d88ec5132..948780aabcb 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -372,8 +372,10 @@ void AppOutputPane::setFocus() void AppOutputPane::updateFilter() { const int index = currentIndex(); - if (index != -1) - m_runControlTabs.at(index).window->setFilterText(filterText()); + if (index != -1) { + m_runControlTabs.at(index).window->updateFilterProperties( + filterText(), filterCaseSensitivity(), filterUsesRegexp()); + } } void AppOutputPane::createNewOutputWindow(RunControl *rc) @@ -703,7 +705,8 @@ void AppOutputPane::tabChanged(int i) const int index = indexOf(m_tabWidget->widget(i)); if (i != -1 && index != -1) { const RunControlTab &controlTab = m_runControlTabs[index]; - controlTab.window->setFilterText(filterText()); + controlTab.window->updateFilterProperties(filterText(), filterCaseSensitivity(), + filterUsesRegexp()); enableButtons(controlTab.runControl); } else { enableDefaultButtons(); diff --git a/src/plugins/projectexplorer/compileoutputwindow.cpp b/src/plugins/projectexplorer/compileoutputwindow.cpp index c1f1d86ca73..3d19bd9514a 100644 --- a/src/plugins/projectexplorer/compileoutputwindow.cpp +++ b/src/plugins/projectexplorer/compileoutputwindow.cpp @@ -356,7 +356,8 @@ void CompileOutputWindow::setSettings(const CompileOutputSettings &settings) void CompileOutputWindow::updateFilter() { - m_outputWindow->setFilterText(filterText()); + m_outputWindow->updateFilterProperties(filterText(), filterCaseSensitivity(), + filterUsesRegexp()); } void CompileOutputWindow::loadSettings() diff --git a/src/plugins/projectexplorer/taskmodel.cpp b/src/plugins/projectexplorer/taskmodel.cpp index c3fac880e21..8fcc48e7378 100644 --- a/src/plugins/projectexplorer/taskmodel.cpp +++ b/src/plugins/projectexplorer/taskmodel.cpp @@ -341,6 +341,25 @@ void TaskFilterModel::setFilterIncludesWarnings(bool b) invalidateFilter(); } +void TaskFilterModel::updateFilterProperties(const QString &filterText, + Qt::CaseSensitivity caseSensitivity, bool isRegexp) +{ + if (filterText == m_filterText && m_filterCaseSensitivity == caseSensitivity + && m_filterStringIsRegexp == isRegexp) { + return; + } + m_filterText = filterText; + m_filterCaseSensitivity = caseSensitivity; + m_filterStringIsRegexp = isRegexp; + if (m_filterStringIsRegexp) { + m_filterRegexp.setPattern(m_filterText); + m_filterRegexp.setPatternOptions(m_filterCaseSensitivity == Qt::CaseInsensitive + ? QRegularExpression::CaseInsensitiveOption + : QRegularExpression::NoPatternOption); + } + invalidateFilter(); +} + bool TaskFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { Q_UNUSED(source_parent); @@ -365,9 +384,13 @@ bool TaskFilterModel::filterAcceptsTask(const Task &task) const if (accept && m_categoryIds.contains(task.category)) accept = false; - if (accept && !filterRegExp().isEmpty() && !task.file.toString().contains(filterRegExp()) - && !task.description.contains(filterRegExp())) { - accept = false; + if (accept && !m_filterText.isEmpty()) { + const auto accepts = [this](const QString &s) { + return m_filterStringIsRegexp ? m_filterRegexp.isValid() && s.contains(m_filterRegexp) + : s.contains(m_filterText, m_filterCaseSensitivity); + }; + if (!accepts(task.file.toString()) && !accepts(task.description)) + accept = false; } return accept; diff --git a/src/plugins/projectexplorer/taskmodel.h b/src/plugins/projectexplorer/taskmodel.h index f48e66d5d37..b1044a32347 100644 --- a/src/plugins/projectexplorer/taskmodel.h +++ b/src/plugins/projectexplorer/taskmodel.h @@ -28,6 +28,7 @@ #include #include +#include #include "task.h" @@ -143,6 +144,9 @@ public: bool hasFile(const QModelIndex &index) const { return taskModel()->hasFile(mapToSource(index)); } + void updateFilterProperties(const QString &filterText, Qt::CaseSensitivity caseSensitivity, + bool isRegex); + private: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; bool filterAcceptsTask(const Task &task) const; @@ -151,7 +155,11 @@ private: bool m_includeUnknowns; bool m_includeWarnings; bool m_includeErrors; + bool m_filterStringIsRegexp = false; + Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive; QList m_categoryIds; + QString m_filterText; + QRegularExpression m_filterRegexp; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp index 8f8e96cfb70..7a98d0fd33e 100644 --- a/src/plugins/projectexplorer/taskwindow.cpp +++ b/src/plugins/projectexplorer/taskwindow.cpp @@ -669,7 +669,7 @@ void TaskWindow::goToPrev() void TaskWindow::updateFilter() { - d->m_filter->setFilterRegExp(filterText()); + d->m_filter->updateFilterProperties(filterText(), filterCaseSensitivity(), filterUsesRegexp()); } bool TaskWindow::canNavigate() const From c1802108bffb2d2064b93f867704cf0b9384e62b Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 4 Jun 2019 10:54:25 +0200 Subject: [PATCH 15/28] Doc: Describe context-menu in "Open Documents" sidebar view The menu contains a wide selection of items in addition to the currently described Pin item. Change-Id: Ibe03686282448ba429e13c4e7e3ae4d92d7659a6 Reviewed-by: Christian Kandeler --- doc/src/howto/creator-sidebar-views.qdoc | 26 +++++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/doc/src/howto/creator-sidebar-views.qdoc b/doc/src/howto/creator-sidebar-views.qdoc index d92a1067b57..4461c14be75 100644 --- a/doc/src/howto/creator-sidebar-views.qdoc +++ b/doc/src/howto/creator-sidebar-views.qdoc @@ -196,16 +196,6 @@ files, as well as compare the selected file with the currently open file in the diff editor. For more information, see \l{Comparing Files}. - \section1 Viewing Open Documents - - To see a list of open documents, switch to the \uicontrol {Open Documents} - view. By right-clicking an open document, you can: - - \list - \li Pin files to ensure they stay at the top of the list and are not - closed when \uicontrol {Close All} is used. - \endlist - \section1 Viewing the File System If you cannot see a file in the \uicontrol Projects view, switch to the @@ -274,6 +264,22 @@ \endlist + \section1 Viewing Open Documents + + To see a list of open documents, switch to the \uicontrol {Open Documents} + view. You can use the context-menu to perform some of the functions also + available in the \uicontrol File menu and in the context menu in the + \uicontrol {File System} view. + + In addition, you can: + + \list + \li Copy the full path of the file or just the filename to the + clipboard. + \li Pin files to ensure they stay at the top of the list and are not + closed when \uicontrol {Close All} is used. + \endlist + \section1 Viewing Defined Types and Symbols The \uicontrol Outline view shows an overview of defined types and other From c911be190fe7ee5a05a3424b95076fb06c70e3bc Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 27 May 2019 09:07:40 +0200 Subject: [PATCH 16/28] AutoTest: Fix handling of test output messages Send all results after they have been created instead of relying on having some further output that might send an old result that had been created but not sent yet. Change-Id: I0c64b702712509264ee5e86a6af15d6411839f43 Reviewed-by: David Schulz --- src/plugins/autotest/boost/boosttestoutputreader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/autotest/boost/boosttestoutputreader.cpp b/src/plugins/autotest/boost/boosttestoutputreader.cpp index c174fe3b595..03699e92dff 100644 --- a/src/plugins/autotest/boost/boosttestoutputreader.cpp +++ b/src/plugins/autotest/boost/boosttestoutputreader.cpp @@ -117,9 +117,6 @@ void BoostTestOutputReader::sendCompleteInformation() void BoostTestOutputReader::handleMessageMatch(const QRegularExpressionMatch &match) { - if (m_result != ResultType::Invalid) - sendCompleteInformation(); - m_fileName = constructSourceFilePath(m_buildDir, match.captured(1)); m_lineNumber = match.captured(2).toInt(); @@ -176,6 +173,9 @@ void BoostTestOutputReader::handleMessageMatch(const QRegularExpressionMatch &ma m_result = ResultType::Skip; m_description = content; } + + if (m_result != ResultType::Invalid) // we got a new result + sendCompleteInformation(); } void BoostTestOutputReader::processOutputLine(const QByteArray &outputLineWithNewLine) From 218c1e37699423cca7131ea32d97209bbc63980d Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 3 Jun 2019 15:43:16 +0200 Subject: [PATCH 17/28] QmlDesigner: Add multi-selection to property editor This implements basic multi selection for the property editor. The property editor shows the most common type. Values in the property editor show the values of the item that was selected first. Task-number: QDS-324 Change-Id: I5f03fa5aa9cfb0a0abaf285a29bf5f7e931635e5 Reviewed-by: Tim Jenssen --- .../QtQuick/ItemPane.qml | 4 + .../propertyeditorqmlbackend.cpp | 55 ++++++++++---- .../propertyeditor/propertyeditorqmlbackend.h | 7 +- .../propertyeditor/propertyeditorview.cpp | 73 ++++++++++++++----- .../propertyeditor/propertyeditorview.h | 3 + .../propertyeditor/qmlmodelnodeproxy.cpp | 31 ++++++++ .../propertyeditor/qmlmodelnodeproxy.h | 9 ++- 7 files changed, 145 insertions(+), 37 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml index 5c7f0302a39..2dbbbff76bb 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml @@ -76,6 +76,7 @@ Rectangle { typeLineEdit.forceActiveFocus() } tooltip: qsTr("Change the type of this item.") + enabled: !modelNodeBackend.multiSelection } ExpressionTextField { @@ -118,15 +119,18 @@ Rectangle { Layout.fillWidth: true showTranslateCheckBox: false showExtendedFunctionButton: false + enabled: !modelNodeBackend.multiSelection } // workaround: without this item the lineedit does not shrink to the // right size after resizing to a wider width Image { + visible: !modelNodeBackend.multiSelection Layout.preferredWidth: 16 Layout.preferredHeight: 16 source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked" ToolTipArea { + enabled: !modelNodeBackend.multiSelection anchors.fill: parent onClicked: toogleExportAlias() tooltip: qsTr("Toggles whether this item is exported as an alias property of the root item.") diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index 284b6948ee0..40c5cfda6e9 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -281,13 +282,17 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q setupLayoutAttachedProperties(qmlObjectNode, propertyEditor); + // model node + m_backendModelNode.setup(qmlObjectNode.modelNode()); + context()->setContextProperty(QLatin1String("modelNodeBackend"), &m_backendModelNode); + // className auto valueObject = qobject_cast(variantToQObject(m_backendValuesPropertyMap.value(QLatin1String("className")))); if (!valueObject) valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap); valueObject->setName("className"); valueObject->setModelNode(qmlObjectNode.modelNode()); - valueObject->setValue(qmlObjectNode.modelNode().simplifiedTypeName()); + valueObject->setValue(m_backendModelNode.simplifiedTypeName()); QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged); m_backendValuesPropertyMap.insert(QLatin1String("className"), QVariant::fromValue(valueObject)); @@ -296,7 +301,7 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q if (!valueObject) valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap); valueObject->setName("id"); - valueObject->setValue(qmlObjectNode.id()); + valueObject->setValue(m_backendModelNode.nodeId()); QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged); m_backendValuesPropertyMap.insert(QLatin1String("id"), QVariant::fromValue(valueObject)); @@ -310,10 +315,6 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q qCInfo(propertyEditorBenchmark) << "anchors:" << time.elapsed(); - // model node - m_backendModelNode.setup(qmlObjectNode.modelNode()); - context()->setContextProperty(QLatin1String("modelNodeBackend"), &m_backendModelNode); - qCInfo(propertyEditorBenchmark) << "context:" << time.elapsed(); contextObject()->setSpecificsUrl(qmlSpecificsFile); @@ -402,7 +403,7 @@ QString PropertyEditorQmlBackend::propertyEditorResourcesPath() { QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, const NodeMetaInfo &superType, - const QmlObjectNode &objectNode) + const QmlObjectNode &node) { if (!templateConfiguration() || !templateConfiguration()->isValid()) return QString(); @@ -411,7 +412,7 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, QString qmlTemplate = imports.join(QLatin1Char('\n')) + QLatin1Char('\n'); qmlTemplate += QStringLiteral("Section {\n"); - qmlTemplate += QStringLiteral("caption: \"%1\"\n").arg(objectNode.modelNode().simplifiedTypeName()); + qmlTemplate += QStringLiteral("caption: \"%1\"\n").arg(QString::fromUtf8(type.simplifiedTypeName())); qmlTemplate += QStringLiteral("SectionLayout {\n"); QList orderedList = type.propertyNames(); @@ -429,8 +430,8 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, TypeName typeName = type.propertyTypeName(name); //alias resolution only possible with instance - if (typeName == "alias" && objectNode.isValid()) - typeName = objectNode.instanceType(name); + if (typeName == "alias" && node.isValid()) + typeName = node.instanceType(name); if (!superType.hasProperty(name) && type.propertyIsWritable(name) && !name.contains(".")) { foreach (const QmlJS::SimpleReaderNode::Ptr &node, templateConfiguration()->children()) @@ -469,6 +470,34 @@ TypeName PropertyEditorQmlBackend::fixTypeNameForPanes(const TypeName &typeName) return fixedTypeName; } +static NodeMetaInfo findCommonSuperClass(const NodeMetaInfo &first, const NodeMetaInfo &second) +{ + for (const NodeMetaInfo &info : first.superClasses()) { + if (second.isSubclassOf(info.typeName())) + return info; + } + return first; +} + +NodeMetaInfo PropertyEditorQmlBackend::findCommonAncestor(const ModelNode &node) +{ + QTC_ASSERT(node.isValid(), return {}); + QTC_ASSERT(node.metaInfo().isValid(), return {}); + + AbstractView *view = node.view(); + + if (view->selectedModelNodes().count() > 1) { + NodeMetaInfo commonClass = node.metaInfo(); + for (const ModelNode ¤tNode : view->selectedModelNodes()) { + if (currentNode.metaInfo().isValid() && !currentNode.isSubclassOf(commonClass.typeName(), -1, -1)) + commonClass = findCommonSuperClass(currentNode.metaInfo(), commonClass); + } + return commonClass; + } + + return node.metaInfo(); +} + TypeName PropertyEditorQmlBackend::qmlFileName(const NodeMetaInfo &nodeInfo) { const TypeName fixedTypeName = fixTypeNameForPanes(nodeInfo.typeName()); @@ -526,10 +555,10 @@ void PropertyEditorQmlBackend::setValueforLayoutAttachedProperties(const QmlObje setValue(qmlObjectNode, name, properDefaultLayoutAttachedProperties(qmlObjectNode, propertyName)); } -QUrl PropertyEditorQmlBackend::getQmlUrlForModelNode(const ModelNode &modelNode, TypeName &className) +QUrl PropertyEditorQmlBackend::getQmlUrlForMetaInfo(const NodeMetaInfo &metaInfo, TypeName &className) { - if (modelNode.isValid()) { - foreach (const NodeMetaInfo &info, modelNode.metaInfo().classHierarchy()) { + if (metaInfo.isValid()) { + foreach (const NodeMetaInfo &info, metaInfo.classHierarchy()) { QUrl fileUrl = fileToUrl(locateQmlFile(info, QString::fromUtf8(qmlFileName(info)))); if (fileUrl.isValid()) { className = info.typeName(); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h index a0012a1cc17..51279a1fc64 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h @@ -68,11 +68,10 @@ public: PropertyEditorValue *propertyValueForName(const QString &propertyName); static QString propertyEditorResourcesPath(); - static QString templateGeneration(const NodeMetaInfo &type, const NodeMetaInfo &superType, - const QmlObjectNode &objectNode); + static QString templateGeneration(const NodeMetaInfo &type, const NodeMetaInfo &superType, const QmlObjectNode &node); static QUrl getQmlFileUrl(const TypeName &relativeTypeName, const NodeMetaInfo &info = NodeMetaInfo()); - static QUrl getQmlUrlForModelNode(const ModelNode &modelNode, TypeName &className); + static QUrl getQmlUrlForMetaInfo(const NodeMetaInfo &modelNode, TypeName &className); static bool checkIfUrlExists(const QUrl &url); @@ -83,6 +82,8 @@ public: void setupLayoutAttachedProperties(const QmlObjectNode &qmlObjectNode, PropertyEditorView *propertyEditor); + static NodeMetaInfo findCommonAncestor(const ModelNode &node); + private: void createPropertyEditorValue(const QmlObjectNode &qmlObjectNode, const PropertyName &name, const QVariant &value, diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp index 0467355bf43..d0c98c896ff 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp @@ -213,20 +213,13 @@ void PropertyEditorView::changeValue(const QString &name) castedValue = QVariant(newColor); } - try { - if (!value->value().isValid()) { //reset - qmlObjectNode.removeProperty(propertyName); - } else { - if (castedValue.isValid() && !castedValue.isNull()) { - m_locked = true; - qmlObjectNode.setVariantProperty(propertyName, castedValue); - m_locked = false; - } + if (!value->value().isValid()) { //reset + removePropertyFromModel(propertyName); + } else { + if (castedValue.isValid() && !castedValue.isNull()) { + commitVariantValueToModel(propertyName, castedValue); } } - catch (const RewritingException &e) { - e.showException(); - } } void PropertyEditorView::changeExpression(const QString &propertyName) @@ -446,13 +439,16 @@ void PropertyEditorView::resetView() void PropertyEditorView::setupQmlBackend() { TypeName specificsClassName; - QUrl qmlFile(PropertyEditorQmlBackend::getQmlUrlForModelNode(m_selectedNode, specificsClassName)); + + const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(m_selectedNode); + + const QUrl qmlFile(PropertyEditorQmlBackend::getQmlUrlForMetaInfo(commonAncestor, specificsClassName)); QUrl qmlSpecificsFile; TypeName diffClassName; - if (m_selectedNode.isValid()) { - diffClassName = m_selectedNode.metaInfo().typeName(); - foreach (const NodeMetaInfo &metaInfo, m_selectedNode.metaInfo().classHierarchy()) { + if (commonAncestor.isValid()) { + diffClassName = commonAncestor.typeName(); + foreach (const NodeMetaInfo &metaInfo, commonAncestor.classHierarchy()) { if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsFile)) break; qmlSpecificsFile = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName() + "Specifics", metaInfo); @@ -465,8 +461,8 @@ void PropertyEditorView::setupQmlBackend() QString specificQmlData; - if (m_selectedNode.isValid() && m_selectedNode.metaInfo().isValid() && diffClassName != m_selectedNode.type()) - specificQmlData = PropertyEditorQmlBackend::templateGeneration(m_selectedNode.metaInfo(), model()->metaInfo(diffClassName), m_selectedNode); + if (commonAncestor.isValid() && m_selectedNode.metaInfo().isValid() && diffClassName != m_selectedNode.type()) + specificQmlData = PropertyEditorQmlBackend::templateGeneration(commonAncestor, model()->metaInfo(diffClassName), m_selectedNode); PropertyEditorQmlBackend *currentQmlBackend = m_qmlBackendHash.value(qmlFile.toString()); @@ -515,14 +511,51 @@ void PropertyEditorView::setupQmlBackend() } +void PropertyEditorView::commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value) +{ + m_locked = true; + try { + RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::commitVariantValueToMode"); + + for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) { + if (QmlObjectNode::isValidQmlObjectNode(node)) + QmlObjectNode(node).setVariantProperty(propertyName, value); + } + transaction.commit(); + } + catch (const RewritingException &e) { + e.showException(); + } + m_locked = false; +} + +void PropertyEditorView::removePropertyFromModel(const PropertyName &propertyName) +{ + m_locked = true; + try { + RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::removePropertyFromModel"); + + for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) { + if (QmlObjectNode::isValidQmlObjectNode(node)) + QmlObjectNode(node).removeProperty(propertyName); + } + + transaction.commit(); + } + catch (const RewritingException &e) { + e.showException(); + } + m_locked = false; +} + void PropertyEditorView::selectedNodesChanged(const QList &selectedNodeList, const QList &lastSelectedNodeList) { Q_UNUSED(lastSelectedNodeList); - if (selectedNodeList.isEmpty() || selectedNodeList.count() > 1) + if (selectedNodeList.isEmpty()) select(ModelNode()); - else if (m_selectedNode != selectedNodeList.constFirst()) + else select(selectedNodeList.constFirst()); } diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h index 85bd8286f52..e7f57cf1868 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h @@ -110,6 +110,9 @@ private: //functions void delayedResetView(); void setupQmlBackend(); + void commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value); + void removePropertyFromModel(const PropertyName &propertyName); + private: //variables ModelNode m_selectedNode; QWidget *m_parent; diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp index 6f56b055c88..934c2846911 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp @@ -23,6 +23,7 @@ ** ****************************************************************************/ +#include "abstractview.h" #include "qmlmodelnodeproxy.h" #include @@ -66,4 +67,34 @@ ModelNode QmlModelNodeProxy::modelNode() const return m_qmlItemNode.modelNode(); } +bool QmlModelNodeProxy::multiSelection() const +{ + if (!m_qmlItemNode.isValid()) + return false; + + return m_qmlItemNode.view()->selectedModelNodes().count() > 1; +} + +QString QmlModelNodeProxy::nodeId() const +{ + if (!m_qmlItemNode.isValid()) + return {}; + + if (multiSelection()) + return tr("multiselection"); + + return m_qmlItemNode.id(); +} + +QString QmlModelNodeProxy::simplifiedTypeName() const +{ + if (!m_qmlItemNode.isValid()) + return {}; + + if (multiSelection()) + return tr("multiselection"); + + return m_qmlItemNode.simplifiedTypeName(); +} + } diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h index 0a735833552..6037f32752a 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h +++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h @@ -35,7 +35,8 @@ class QmlModelNodeProxy : public QObject { Q_OBJECT - Q_PROPERTY(QmlDesigner::ModelNode modelNode READ modelNode NOTIFY modelNodeChanged) + Q_PROPERTY(QmlDesigner::ModelNode modelNode READ modelNode NOTIFY modelNodeChanged) + Q_PROPERTY(bool multiSelection READ multiSelection NOTIFY modelNodeChanged) public: explicit QmlModelNodeProxy(QObject *parent = nullptr); @@ -51,6 +52,12 @@ public: ModelNode modelNode() const; + bool multiSelection() const; + + QString nodeId() const; + + QString simplifiedTypeName() const; + signals: void modelNodeChanged(); void selectionToBeChanged(); From 7016aa5c02411d3ac313324f34ce39f86107fae3 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 4 Jun 2019 16:45:28 +0200 Subject: [PATCH 18/28] QmlDesigner: Add live preview Task-number: QDS-376 Change-Id: I38d110c414b14d6a75a66a5c989f63d57d2cdf02 Reviewed-by: Alessandro Portale --- src/plugins/qmldesigner/qmldesigner.pro | 2 +- .../qmlpreviewplugin/images/live_preview.png | Bin 0 -> 198 bytes .../images/live_preview@2x.png | Bin 0 -> 424 bytes .../qmlpreviewplugin/qmlpreview.metainfo | 2 + .../qmlpreviewplugin/qmlpreviewactions.cpp | 303 ++++++++++++++++++ .../qmlpreviewplugin/qmlpreviewactions.h | 135 ++++++++ .../qmlpreviewplugin/qmlpreviewplugin.cpp | 173 ++++++++++ .../qmlpreviewplugin/qmlpreviewplugin.h | 69 ++++ .../qmlpreviewplugin/qmlpreviewplugin.pri | 10 + .../qmlpreviewplugin/qmlpreviewplugin.pro | 18 ++ .../qmlpreviewplugin/qmlpreviewplugin.qrc | 7 + 11 files changed, 718 insertions(+), 1 deletion(-) create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview.png create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview@2x.png create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc diff --git a/src/plugins/qmldesigner/qmldesigner.pro b/src/plugins/qmldesigner/qmldesigner.pro index 039c228fe5a..1986677fac3 100644 --- a/src/plugins/qmldesigner/qmldesigner.pro +++ b/src/plugins/qmldesigner/qmldesigner.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS = qmldesignerplugin.pro qtquickplugin componentsplugin +SUBDIRS = qmldesignerplugin.pro qtquickplugin componentsplugin qmlpreviewplugin diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview.png b/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..b56467d4eac6ca1b8994936f8d2f3e320d8ed65c GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)Rq^m@8DhDd~`_V49AWFX

z=h>#!#yZUH3G+I^J+ZVLCp+F?FO)j)R`oo^O z14$1HqjWWeOZV3}@7^xRKl|3*4S&D<-6_A9QQmp^*-5+o_kbMe>FVdQ&MBb@0O;*Z A4FCWD literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview@2x.png b/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..93c49a04eb8902c2ef924968fd1e0d71d444ab99 GIT binary patch literal 424 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(3rd`}n05R2Z{$!oi$8AaUA zFY#Vzkl4YqaM7xe-Zk1GXOxc|aSI74>3GGwhATK+=@Uz#ciaM%w6k5IlN}W8wk2sy z=Cc*u?Wty;x^CB_g8F^GV{% z)%ks@b~J*cdPiDKXFXqocr@-&SyT)N(Qzs*H&FM^1hrCxpG}K&$k0p&PC}S zk7an#=UsX?@fS;u^0QZJ&jdcY%@xiSmAx2lZu_HRvwD^E*7F`4Ihvhl)W7A^@!8x9Uj_aDRpR>U)<(Pi`^wflD>j!}mbTM%+OnIE4i%kUmb+zdZ-4UV f*EfIc`QKgdZeQ|t-JD6HpeXQk^>bP0l+XkK#%96c literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo new file mode 100644 index 00000000000..5bfe70cffdf --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo @@ -0,0 +1,2 @@ +MetaInfo { +} diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp new file mode 100644 index 00000000000..1fe99825c37 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp @@ -0,0 +1,303 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "qmlpreviewplugin.h" +#include "qmlpreviewactions.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace QmlDesigner { + +using namespace ProjectExplorer; + +const Utils::Icon previewIcon({ + {":/qmlpreviewplugin/images/live_preview.png", Utils::Theme::IconsBaseColor}}); + +static void handleAction(const SelectionContext &context) +{ + if (context.view()->isAttached()) { + if (context.toggled()) { + ProjectExplorerPlugin::runStartupProject(Constants::QML_PREVIEW_RUN_MODE); + QmlPreviewPlugin::setQmlFile(); + } else { + QmlPreviewPlugin::stopAllRunControls(); + } + } +} + +QmlPreviewAction::QmlPreviewAction() : ModelNodeAction("LivePreview", + "Live Preview", + previewIcon.icon(), + QmlPreviewPlugin::tr("Show Live Preview"), + ComponentCoreConstants::qmlPreviewCategory, + QKeySequence("Alt+p"), + 20, + &handleAction, + &SelectionContextFunctors::always) +{ + if (!QmlPreviewPlugin::getPreviewPlugin()) + defaultAction()->setVisible(false); + + defaultAction()->setCheckable(true); +} + +void QmlPreviewAction::updateContext() +{ + if (selectionContext().view()->isAttached()) + QmlPreviewPlugin::setQmlFile(); + + defaultAction()->setSelectionContext(selectionContext()); +} + +ActionInterface::Type QmlPreviewAction::type() const +{ + return ToolBarAction; +} + +ZoomPreviewAction::ZoomPreviewAction() + : m_zoomAction(new ZoomAction(nullptr)) +{ + QObject::connect(m_zoomAction.get(), &ZoomAction::zoomLevelChanged, [=](float d) { + QmlPreviewPlugin::setZoomFactor(d); + }); + if (!QmlPreviewPlugin::getPreviewPlugin()) + m_zoomAction->setVisible(false); +} + +ZoomPreviewAction::~ZoomPreviewAction() += default; + +QAction *ZoomPreviewAction::action() const +{ + return m_zoomAction.get(); +} + +QByteArray ZoomPreviewAction::category() const +{ + return ComponentCoreConstants::qmlPreviewCategory; +} + +QByteArray ZoomPreviewAction::menuId() const +{ + return QByteArray(); +} + +int ZoomPreviewAction::priority() const +{ + return 19; +} + +ActionInterface::Type ZoomPreviewAction::type() const +{ + return ToolBarAction; +} + +void ZoomPreviewAction::currentContextChanged(const SelectionContext &) +{} + +quint16 FpsLabelAction::lastValidFrames = 0; +QList> FpsLabelAction::fpsHandlerLabelList; + +FpsLabelAction::FpsLabelAction(QObject *parent) + : QWidgetAction(parent) +{ +} + +void FpsLabelAction::fpsHandler(quint16 fpsValues[8]) +{ + quint16 frames = fpsValues[0]; + if (frames != 0) + lastValidFrames = frames; + QString fpsText("%1 FPS"); + if (lastValidFrames == 0 || (frames == 0 && lastValidFrames < 2)) + fpsText = fpsText.arg("--"); + else + fpsText = fpsText.arg(lastValidFrames); + for (QPointer label : fpsHandlerLabelList) { + if (label) + label->setText(fpsText); + } +} + +void FpsLabelAction::cleanFpsCounter() +{ + lastValidFrames = 0; + quint16 nullInitialized[8] = {0}; + fpsHandler(nullInitialized); +} + +QWidget *FpsLabelAction::createWidget(QWidget *parent) +{ + auto label = new QLabel(parent); + auto originList = fpsHandlerLabelList; + fpsHandlerLabelList.clear(); + fpsHandlerLabelList.append(label); + for (const auto &labelPointer : originList) { + if (labelPointer) + fpsHandlerLabelList.append(labelPointer); + } + + return label; +} + +void FpsLabelAction::refreshFpsLabel(quint16 frames) +{ + for (const auto &labelPointer : fpsHandlerLabelList) { + if (labelPointer) + labelPointer->setText(QString("%1 FPS").arg(frames)); + } +} + +FpsAction::FpsAction() : m_fpsLabelAction(new FpsLabelAction(nullptr)) +{} + +QAction *FpsAction::action() const +{ + return m_fpsLabelAction.get(); +} + +QByteArray FpsAction::category() const +{ + return ComponentCoreConstants::qmlPreviewCategory; +} + +QByteArray FpsAction::menuId() const +{ + return QByteArray(); +} + +int FpsAction::priority() const +{ + return 19; +} + +ActionInterface::Type FpsAction::type() const +{ + return ToolBarAction; +} + +void FpsAction::currentContextChanged(const SelectionContext &) +{} + +SwitchLanguageComboboxAction::SwitchLanguageComboboxAction(QObject *parent) + : QWidgetAction(parent) +{ + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::startupProjectChanged, + this, + &SwitchLanguageComboboxAction::refreshProjectLocales); +} + +QWidget *SwitchLanguageComboboxAction::createWidget(QWidget *parent) +{ + QPointer comboBox = new QComboBox(parent); + comboBox->setToolTip(tr("Switch the language used by preview.")); + connect(comboBox, QOverload::of(&QComboBox::currentIndexChanged), [this, comboBox](int index) { + if (index == 0) + emit currentLocaleChanged(""); + else + emit currentLocaleChanged(comboBox->currentText()); + }); + + auto refreshComboBoxFunction = [this, comboBox] (ProjectExplorer::Project *project) { + if (comboBox) { + refreshProjectLocales(project); + comboBox->clear(); + comboBox->addItem(tr("Default")); + comboBox->addItems(m_localeStrings); + } + }; + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::startupProjectChanged, + refreshComboBoxFunction); + + if (auto project = SessionManager::startupProject()) + refreshComboBoxFunction(project); + + return comboBox; +} + +void SwitchLanguageComboboxAction::refreshProjectLocales(Project *project) +{ + if (!project) + return; + m_localeStrings.clear(); + const auto projectDirectory = project->rootProjectDirectory().toFileInfo().absoluteFilePath(); + const QDir languageDirectory(projectDirectory + "/i18n"); + const auto qmFiles = languageDirectory.entryList({"qml_*.qm"}); + m_localeStrings = Utils::transform(qmFiles, [](const QString &qmFile) { + const int localeStartPosition = qmFile.lastIndexOf("_") + 1; + const int localeEndPosition = qmFile.size() - QString(".qm").size(); + const QString locale = qmFile.left(localeEndPosition).mid(localeStartPosition); + return locale; + }); +} + +SwitchLanguageAction::SwitchLanguageAction() + : m_switchLanguageAction(new SwitchLanguageComboboxAction(nullptr)) +{ + QObject::connect(m_switchLanguageAction.get(), &SwitchLanguageComboboxAction::currentLocaleChanged, + &QmlPreviewPlugin::setLanguageLocale); +} + +QAction *SwitchLanguageAction::action() const +{ + return m_switchLanguageAction.get(); +} + +QByteArray SwitchLanguageAction::category() const +{ + return ComponentCoreConstants::qmlPreviewCategory; +} + +QByteArray SwitchLanguageAction::menuId() const +{ + return QByteArray(); +} + +int SwitchLanguageAction::priority() const +{ + return 10; +} + +ActionInterface::Type SwitchLanguageAction::type() const +{ + return ToolBarAction; +} + +void SwitchLanguageAction::currentContextChanged(const SelectionContext &) +{} + + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h new file mode 100644 index 00000000000..8a71ee07c29 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include + +#include + +#include +#include + +QT_FORWARD_DECLARE_CLASS(QAction) +QT_FORWARD_DECLARE_CLASS(QLabel) + + +namespace QmlPreview { +using QmlPreviewFpsHandler = void (*)(quint16 *); +} + +namespace ProjectExplorer { +class Project; +} + +namespace QmlDesigner { +class ZoomAction; + +class QmlPreviewAction : public ModelNodeAction +{ +public: + QmlPreviewAction(); + + void updateContext() override; + + Type type() const override; +}; + +class ZoomPreviewAction : public ActionInterface +{ +public: + ZoomPreviewAction(); + ~ZoomPreviewAction() override; + QAction *action() const override; + QByteArray category() const override; + QByteArray menuId() const override; + int priority() const override; + Type type() const override; + void currentContextChanged(const SelectionContext &) override; + +private: + std::unique_ptr m_zoomAction; +}; + +class FpsLabelAction : public QWidgetAction +{ +public: + explicit FpsLabelAction(QObject *parent = nullptr); + static void fpsHandler(quint16 fpsValues[8]); + static void cleanFpsCounter(); +protected: + QWidget *createWidget(QWidget *parent) override; +private: + static void refreshFpsLabel(quint16 frames); + static QPointer m_labelInstance; + static QList> fpsHandlerLabelList; + static quint16 lastValidFrames; +}; + +class FpsAction : public ActionInterface +{ +public: + FpsAction(); + QAction *action() const override; + QByteArray category() const override; + QByteArray menuId() const override; + int priority() const override; + Type type() const override; + void currentContextChanged(const SelectionContext &) override; +private: + std::unique_ptr m_fpsLabelAction; +}; + +class SwitchLanguageComboboxAction : public QWidgetAction +{ + Q_OBJECT +public: + explicit SwitchLanguageComboboxAction(QObject *parent = nullptr); +signals: + void currentLocaleChanged(const QString& string); +protected: + QWidget *createWidget(QWidget *parent) override; +private: + void refreshProjectLocales(ProjectExplorer::Project *project); + QStringList m_localeStrings; +}; + +class SwitchLanguageAction : public ActionInterface +{ +public: + SwitchLanguageAction(); + QAction *action() const override; + QByteArray category() const override; + QByteArray menuId() const override; + int priority() const override; + Type type() const override; + void currentContextChanged(const SelectionContext &) override; +private: + std::unique_ptr m_switchLanguageAction; +}; + +} // namespace QmlDesigner +Q_DECLARE_METATYPE(QmlPreview::QmlPreviewFpsHandler); diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp new file mode 100644 index 00000000000..5a3c1c4e090 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "qmlpreviewplugin.h" +#include "qmlpreviewactions.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace QmlPreview { +using QmlPreviewRunControlList = QList; +} + +Q_DECLARE_METATYPE(QmlPreview::QmlPreviewRunControlList) + +namespace QmlDesigner { +static QObject *s_previewPlugin = nullptr; + +QmlPreviewPlugin::QmlPreviewPlugin() +{ + DesignerActionManager &designerActionManager = + QmlDesignerPlugin::instance()->designerActionManager(); + auto previewAction = new QmlPreviewAction(); + designerActionManager.addDesignerAction(new ActionGroup( + QString(), + ComponentCoreConstants::qmlPreviewCategory, + ComponentCoreConstants::priorityQmlPreviewCategory, + &SelectionContextFunctors::always)); + s_previewPlugin = getPreviewPlugin(); + + if (s_previewPlugin) { + bool connected = connect(s_previewPlugin, SIGNAL(runningPreviewsChanged(const QmlPreviewRunControlList &)), + this, SLOT(handleRunningPreviews())); + QTC_ASSERT(connected, qWarning() << "something wrong with the runningPreviewsChanged signal"); + } + + designerActionManager.addDesignerAction(previewAction); + + auto zoomAction = new ZoomPreviewAction; + designerActionManager.addDesignerAction(zoomAction); + + auto separator = new SeperatorDesignerAction(ComponentCoreConstants::qmlPreviewCategory, 0); + designerActionManager.addDesignerAction(separator); + + m_previewToggleAction = previewAction->defaultAction(); + + if (s_previewPlugin) { + auto fpsAction = new FpsAction; + designerActionManager.addDesignerAction(fpsAction); + s_previewPlugin->setProperty("fpsHandler", QVariant::fromValue(FpsLabelAction::fpsHandler)); + auto switchLanguageAction = new SwitchLanguageAction; + designerActionManager.addDesignerAction(switchLanguageAction); + } +} + +QString QmlPreviewPlugin::pluginName() const +{ + return QLatin1String("QmlPreviewPlugin"); +} + +void QmlPreviewPlugin::stopAllRunControls() +{ + QTC_ASSERT(s_previewPlugin, return); + + const QVariant variant = s_previewPlugin->property("runningPreviews"); + auto runControls = variant.value(); + + for (ProjectExplorer::RunControl *runControl : runControls) + runControl->initiateStop(); + +} + +void QmlPreviewPlugin::handleRunningPreviews() +{ + QTC_ASSERT(s_previewPlugin, return); + + const QVariant variant = s_previewPlugin->property("runningPreviews"); + if (variant.isValid()) { + // the QmlPreview::QmlPreviewRunControlList type have to be available and used in the qmlpreview plugin + QTC_ASSERT(variant.canConvert(), return); + auto runControls = variant.value(); + m_previewToggleAction->setChecked(!runControls.isEmpty()); + if (runControls.isEmpty()) + FpsLabelAction::cleanFpsCounter(); + } +} + +QString QmlPreviewPlugin::metaInfo() const +{ + return QLatin1String(":/qmlpreviewplugin/qmlpreview.metainfo"); +} + +void QmlPreviewPlugin::setQmlFile() +{ + if (s_previewPlugin) { + const Utils::FileName qmlFileName = + QmlDesignerPlugin::instance()->currentDesignDocument()->fileName(); + s_previewPlugin->setProperty("previewedFile", qmlFileName.toString()); + } +} + +float QmlPreviewPlugin::zoomFactor() +{ + QVariant zoomFactorVariant = 1.0; + if (s_previewPlugin && !s_previewPlugin->property("zoomFactor").isNull()) + zoomFactorVariant = s_previewPlugin->property("zoomFactor"); + return zoomFactorVariant.toFloat(); +} + +void QmlPreviewPlugin::setZoomFactor(float zoomFactor) +{ + if (s_previewPlugin) + s_previewPlugin->setProperty("zoomFactor", zoomFactor); +} + +void QmlPreviewPlugin::setLanguageLocale(const QString &locale) +{ + if (s_previewPlugin) + s_previewPlugin->setProperty("locale", locale); +} + +QObject *QmlPreviewPlugin::getPreviewPlugin() +{ + auto pluginIt = std::find_if(ExtensionSystem::PluginManager::plugins().begin(), + ExtensionSystem::PluginManager::plugins().end(), + [](const ExtensionSystem::PluginSpec *p) { + return p->name() == "QmlPreview"; + }); + + if (pluginIt != ExtensionSystem::PluginManager::plugins().constEnd()) + return (*pluginIt)->plugin(); + + return nullptr; +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h new file mode 100644 index 00000000000..7f50d76696d --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +#include + +QT_FORWARD_DECLARE_CLASS(QAction) + +namespace QmlDesigner { + +class QmlPreviewPlugin : public QObject, QmlDesigner::IWidgetPlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QmlDesignerPlugin" FILE "qmlpreviewplugin.json") + + Q_DISABLE_COPY(QmlPreviewPlugin) + Q_INTERFACES(QmlDesigner::IWidgetPlugin) + +public: + QmlPreviewPlugin(); + ~QmlPreviewPlugin() override = default; + + QString metaInfo() const override; + QString pluginName() const override; + + static void stopAllRunControls(); + static void setQmlFile(); + static QObject *getPreviewPlugin(); + + static float zoomFactor(); + static void setZoomFactor(float zoomFactor); + static void setLanguageLocale(const QString &locale); +signals: + void fpsChanged(quint16 frames); + +private slots: + void handleRunningPreviews(); + +private: + QAction *m_previewToggleAction = nullptr; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri new file mode 100644 index 00000000000..1808b692668 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri @@ -0,0 +1,10 @@ +QT *= qml quick core + +VPATH += $$PWD + +SOURCES += qmlpreviewplugin.cpp +HEADERS += qmlpreviewplugin.h +SOURCES += qmlpreviewactions.cpp +HEADERS += qmlpreviewactions.h + +RESOURCES += qmlpreviewplugin.qrc diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro new file mode 100644 index 00000000000..56eadb58a58 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro @@ -0,0 +1,18 @@ +TARGET = qmlpreviewplugin +TEMPLATE = lib +CONFIG += plugin + +include(../../../../qtcreator.pri)\ + +include (../designercore/iwidgetplugin.pri) +include (../qmldesigner_dependencies.pri) + +LIBS += -L$$IDE_PLUGIN_PATH +LIBS += -l$$qtLibraryName(QmlDesigner) +LIBS += -l$$qtLibraryName(Extensionsystem) +LIBS += -l$$qtLibraryName(Core) +LIBS += -l$$qtLibraryName(ProjectExplorer) +LIBS += -l$$qtLibraryName(Utils) + +include(qmlpreviewplugin.pri) +include(../plugindestdir.pri) diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc new file mode 100644 index 00000000000..3f8cc2a0772 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc @@ -0,0 +1,7 @@ + + + qmlpreview.metainfo + images/live_preview.png + images/live_preview@2x.png + + From 1927813ab1e31af2a4756b223a5111a9ea109d15 Mon Sep 17 00:00:00 2001 From: Aleksei German Date: Tue, 9 Apr 2019 17:59:33 +0200 Subject: [PATCH 19/28] QtDesignStudio Color Editor update Palettes, Favorite colors, Recent colors, changed layout. Change-Id: I6fca962923a3e7a230edebdab5a30bd0847c8ba9 Reviewed-by: Thomas Hartmann --- .../imports/HelperWidgets/ColorButton.qml | 255 +++++++++---- .../HelperWidgets/ColorCheckButton.qml | 57 ++- .../imports/HelperWidgets/ColorEditor.qml | 342 +++++++++++++----- .../imports/HelperWidgets/ColorLine.qml | 53 +++ .../imports/HelperWidgets/GradientLine.qml | 9 + .../HelperWidgets/SimpleColorPalette.qml | 113 ++++++ .../imports/HelperWidgets/qmldir | 2 + .../propertyeditor/gradientmodel.cpp | 25 +- .../components/propertyeditor/gradientmodel.h | 2 + .../propertyeditor/propertyeditor.pri | 10 +- .../quick2propertyeditorview.cpp | 2 + .../propertyeditor/simplecolorpalette.cpp | 113 ++++++ .../propertyeditor/simplecolorpalette.h | 75 ++++ .../simplecolorpalettemodel.cpp | 146 ++++++++ .../propertyeditor/simplecolorpalettemodel.h | 77 ++++ .../simplecolorpalettesingleton.cpp | 185 ++++++++++ .../simplecolorpalettesingleton.h | 72 ++++ .../designercore/model/texttomodelmerger.cpp | 9 + src/plugins/qmldesigner/designersettings.cpp | 1 + src/plugins/qmldesigner/designersettings.h | 1 + src/plugins/qmldesigner/qmldesignerplugin.qbs | 6 + 21 files changed, 1365 insertions(+), 190 deletions(-) create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml index 203e692a82f..c7d6435ad10 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml @@ -82,6 +82,9 @@ Item { lightnessSlider.value = lightness alphaSlider.value = alpha + redSlider.value = (color.r * 255) + greenSlider.value = (color.g * 255) + blueSlider.value = (color.b * 255) block = false } @@ -242,7 +245,6 @@ Item { anchors.margins: 6 y: 4 height: parent.height - 8 - //value: colorButton.hue onValueChanged: { if (colorButton.hue !== value) colorButton.hue = value @@ -250,101 +252,194 @@ Item { onClicked: colorButton.clicked() } - Column { + Row { anchors.left: hueSlider.right anchors.margins: colorButton.sliderMargins spacing: 10 - Row { - z: 3 - spacing: 4 - Label { - text: "H:" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter + Column { + + spacing: 10 + + Row { + z: 3 + spacing: 1 + Label { + text: "R" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: redSlider + width: 64 + + stepSize: 1 + minimumValue: 0 + maximumValue: 255 + decimals: 0 + + onValueChanged: { + if (color.r !== value && !colorButton.block) { + color.r = (value / 255.0) + colorButton.clicked() + } + } + } } - DoubleSpinBox { - id: hueSlider2 - //value: colorButton.hue - onValueChanged: { - if (colorButton.hue !== value && !colorButton.block) { - colorButton.hue = value - colorButton.clicked() + + Row { + z: 2 + spacing: 1 + Controls.Label { + text: "G" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + + DoubleSpinBox { + id: greenSlider + width: 64 + + stepSize: 1 + minimumValue: 0 + maximumValue: 255 + decimals: 0 + + onValueChanged: { + if (color.g !== value && !colorButton.block) { + color.g = (value / 255.0) + colorButton.clicked() + } + } + } + } + + Row { + z: 1 + spacing: 1 + Controls.Label { + text: "B" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: blueSlider + width: 64 + + stepSize: 1 + minimumValue: 0 + maximumValue: 255 + decimals: 0 + + onValueChanged: { + if (color.b !== value && !colorButton.block) { + color.b = (value / 255.0) + colorButton.clicked() + } + } + } + } + + Row { + z: 0 + spacing: 1 + Controls.Label { + text: "A" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + + DoubleSpinBox { + id: alphaSlider + width: 64 + onValueChanged: { + if (colorButton.alpha !== value && !colorButton.block) { + colorButton.alpha = value + colorButton.clicked() + } } } } } - Row { - z: 2 - spacing: 4 - Controls.Label { - text: "S:" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter + Column { + + spacing: 10 + Row { + z: 3 + spacing: 1 + Label { + text: "H" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: hueSlider2 + width: 64 + onValueChanged: { + if (colorButton.hue !== value && !colorButton.block) { + colorButton.hue = value + colorButton.clicked() + } + } + } } - DoubleSpinBox { - id: saturationSlider - //value: colorButton.saturation - onValueChanged: { - if (colorButton.saturation !== value && !colorButton.block) { - colorButton.saturation = value - colorButton.clicked() + Row { + z: 2 + spacing: 1 + Controls.Label { + text: "S" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + + DoubleSpinBox { + id: saturationSlider + width: 64 + onValueChanged: { + if (colorButton.saturation !== value && !colorButton.block) { + colorButton.saturation = value + colorButton.clicked() + } + } + } + } + + Row { + z: 1 + spacing: 1 + Controls.Label { + text: "L" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: lightnessSlider + width: 64 + onValueChanged: { + if (colorButton.lightness !== value && !colorButton.block) { + colorButton.lightness = value + colorButton.clicked() + } } } } } - - Row { - z: 1 - spacing: 4 - Controls.Label { - text: "L:" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - } - DoubleSpinBox { - id: lightnessSlider - //value: colorButton.lightness - onValueChanged: { - if (colorButton.lightness !== value && !colorButton.block) { - colorButton.lightness = value - colorButton.clicked() - } - } - } - } - - Row { - z: 0 - spacing: 4 - Controls.Label { - text: "A:" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - } - - DoubleSpinBox { - id: alphaSlider - //value: colorButton.alpha - onValueChanged: { - if (colorButton.alpha !== value && !colorButton.block) { - colorButton.alpha = value - colorButton.clicked() - } - } - } - } - } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml index 941d705abd0..5f094dc00d9 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml @@ -25,19 +25,54 @@ import QtQuick 2.1 -Rectangle { - id: checkBox - width: 18 - height: 18 - - border.color: "black" - border.width: 1 - +Item { + id: colorCheckButtonRoot property bool checked: false + property alias buttonColor: checkBox.color + width: 30 + height: 24 - MouseArea { - anchors.fill: parent - onClicked: checkBox.checked = !checkBox.checked + + Rectangle { + id: backgroundBox + width: 24 + height: 24 + anchors.right: parent.right + + color: "white" + border.color: "white" + border.width: 1 + + Rectangle { + id: checkBox + width: 22 + height: 22 + anchors.centerIn: parent + + border.color: "black" + border.width: 1 + } } + Image { + id: arrowImage + width: 8 + height: 4 + source: "image://icons/down-arrow" + anchors.verticalCenter: parent.verticalCenter + anchors.right: backgroundBox.left + anchors.rightMargin: 2 + opacity: colorToolTip.containsMouse ? 1 : 0.8 + rotation: colorCheckButtonRoot.checked ? 0.0 : 270.0 + } + + ToolTipArea { + id: colorToolTip + + onClicked: checked = !checked + hoverEnabled: true + anchors.fill: parent + anchors.leftMargin: -arrowImage.width + tooltip: qsTr("Toggle color picker view") + } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml index e2a1ba2b90d..31d8d263b6c 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml @@ -38,7 +38,7 @@ Column { property bool supportGradient: false - property alias caption: label.text + property string caption: "Color" property variant backendValue @@ -50,8 +50,14 @@ Column { property alias transparent: transparentButton.checked + property color originalColor + function isNotInGradientMode() { - return (buttonRow.checkedIndex !== 1) + return (buttonRow.checkedIndex === 0 || transparent) + } + + function resetShapeColor() { + colorEditor.backendValue.resetValue() } onValueChanged: colorEditor.color = colorEditor.value @@ -73,7 +79,7 @@ Column { if (!gradientLine.isInValidState) return; - if (supportGradient && gradientLine.hasGradient) { + if (colorEditor.supportGradient && gradientLine.hasGradient) { textField.text = convertColorToString(color) gradientLine.currentColor = color } @@ -84,22 +90,27 @@ Column { } } + ColorLine { + visible: { + return (colorEditor.supportGradient && isNotInGradientMode()) + } + currentColor: colorEditor.color + width: parent.width + } + GradientLine { property bool isInValidState: false visible: { - if (colorEditor.shapeGradients) { - return buttonRow.checkedIndex > 0 && buttonRow.checkedIndex < 4 - } else { - return buttonRow.checkedIndex === 1 - } + return !(isNotInGradientMode()) } id: gradientLine width: parent.width onCurrentColorChanged: { - if (supportGradient && gradientLine.hasGradient) + if (colorEditor.supportGradient && gradientLine.hasGradient) { colorEditor.color = gradientLine.currentColor + } } onHasGradientChanged: { @@ -125,11 +136,21 @@ Column { buttonRow.initalChecked = 1 } colorEditor.color = gradientLine.currentColor + } else if (colorEditor.transparent) { + buttonRow.initalChecked = 4 } else { buttonRow.initalChecked = 0 colorEditor.color = colorEditor.value } + buttonRow.checkedIndex = buttonRow.initalChecked + colorEditor.originalColor = colorEditor.color + } + + onSelectedNodeChanged: { + if (colorEditor.supportGradient && gradientLine.hasGradient) { + colorEditor.originalColor = gradientLine.currentColor + } } Connections { @@ -137,18 +158,26 @@ Column { onSelectionToBeChanged: { colorEditorTimer.stop() gradientLine.isInValidState = false + if (colorEditor.originalColor !== colorEditor.color) { + if (colorEditor.color != "#ffffff" + && colorEditor.color != "#000000" + && colorEditor.color != "#00000000") { + colorPalette.addColorToPalette(colorEditor.color) + } + } } } Connections { target: modelNodeBackend onSelectionChanged: { - if (supportGradient && gradientLine.hasGradient) { + if (colorEditor.supportGradient && gradientLine.hasGradient) { colorEditor.color = gradientLine.currentColor gradientLine.currentColor = color textField.text = colorEditor.color } gradientLine.isInValidState = true + colorEditor.originalColor = colorEditor.color } } @@ -156,29 +185,21 @@ Column { SectionLayout { width: parent.width + columnSpacing: 0 + rowSpacing: checkButton.checked ? 8 : 2 rows: 5 + //spacer 1 Item { - height: 0 - width: 2 - } - - Item { - height: 0 - width: 2 - } - - Label { - id: label - text: "Color" + height: 6 } SecondColumnLayout { ColorCheckButton { id: checkButton - color: colorEditor.color + buttonColor: colorEditor.color } LineEdit { @@ -217,64 +238,30 @@ Column { iconSource: "images/icon_color_solid.png" onClicked: { - if (colorEditor.supportGradient) - gradientLine.deleteGradient() + gradientLine.deleteGradient() textField.text = colorEditor.color - colorEditor.backendValue.resetValue() + colorEditor.resetShapeColor() } tooltip: qsTr("Solid Color") } ButtonRowButton { - visible: supportGradient + visible: colorEditor.supportGradient iconSource: "images/icon_color_gradient.png" onClicked: { - colorEditor.backendValue.resetValue() - if (colorEditor.shapeGradients) { - gradientLine.deleteGradient() + colorEditor.resetShapeColor() + + if (colorEditor.shapeGradients) gradientLine.gradientTypeName = "LinearGradient" + else + gradientLine.gradientTypeName = "Gradient" + + if (gradientLine.hasGradient) + gradientLine.updateGradient() + else { + gradientLine.deleteGradient() + gradientLine.addGradient() } - gradientLine.addGradient() - } - - GradientPresetList { - id: presetList - visible: false - - function applyPreset() { - if (presetList.gradientData.presetType == 0) { - gradientLine.setPresetByID(presetList.gradientData.presetID); - } - else if (presetList.gradientData.presetType == 1) { - gradientLine.setPresetByStops( - presetList.gradientData.stops, - presetList.gradientData.colors, - presetList.gradientData.stopsCount); - } - else { console.log("INVALID GRADIENT TYPE: " + presetList.gradientData.presetType); } - } - - onApply: { - if (presetList.gradientData.stopsCount > 0) { - applyPreset(); - } - } - - onSaved: { - gradientLine.savePreset(); - presetList.updatePresets(); - } - - onAccepted: { //return key - if (presetList.gradientData.stopsCount > 0) { - applyPreset(); - } - } - - } - - onDoubleClicked: { - presetList.open() } tooltip: qsTr("Linear Gradient") @@ -345,15 +332,18 @@ Column { } } ButtonRowButton { - visible: supportGradient && colorEditor.shapeGradients + visible: colorEditor.supportGradient && colorEditor.shapeGradients iconSource: "images/icon_color_radial_gradient.png" onClicked: { - colorEditor.backendValue.resetValue() - if (colorEditor.shapeGradients) { + colorEditor.resetShapeColor() + gradientLine.gradientTypeName = "RadialGradient" + + if (gradientLine.hasGradient) + gradientLine.updateGradient() + else { gradientLine.deleteGradient() - gradientLine.gradientTypeName = "RadialGradient" + gradientLine.addGradient() } - gradientLine.addGradient() } tooltip: qsTr("Radial Gradient") @@ -442,18 +432,21 @@ Column { } } ButtonRowButton { - visible: supportGradient && colorEditor.shapeGradients + visible: colorEditor.supportGradient && colorEditor.shapeGradients iconSource: "images/icon_color_conical_gradient.png" onClicked: { - colorEditor.backendValue.resetValue() - if (colorEditor.shapeGradients) { + colorEditor.resetShapeColor() + gradientLine.gradientTypeName = "ConicalGradient" + + if (gradientLine.hasGradient) + gradientLine.updateGradient() + else { gradientLine.deleteGradient() - gradientLine.gradientTypeName = "ConicalGradient" + gradientLine.addGradient() } - gradientLine.addGradient() } - tooltip: qsTr("Concial Gradient") + tooltip: qsTr("Conical Gradient") GradientPopupIndicator { @@ -513,18 +506,104 @@ Column { id: transparentButton iconSource: "images/icon_color_none.png" onClicked: { + gradientLine.deleteGradient() + colorEditor.resetShapeColor() colorEditor.color = "#00000000" - if (colorEditor.supportGradient) - gradientLine.deleteGradient() } tooltip: qsTr("Transparent") } } + Rectangle { + id: gradientPickerButton + width: 20 + height: 20 + visible: colorEditor.supportGradient + + color: "white" + border.color: "white" + border.width: 1 + + ToolTipArea { + anchors.fill: parent + id: toolTipArea + tooltip: qsTr("Gradient Picker Dialog") + } + + GradientPresetList { + id: presetList + visible: false + + function applyPreset() { + if (presetList.gradientData.presetType == 0) { + gradientLine.setPresetByID(presetList.gradientData.presetID); + } + else if (presetList.gradientData.presetType == 1) { + gradientLine.setPresetByStops( + presetList.gradientData.stops, + presetList.gradientData.colors, + presetList.gradientData.stopsCount); + } + else { + console.log("INVALID GRADIENT TYPE: " + + presetList.gradientData.presetType); + } + } + + onApply: { + if (presetList.gradientData.stopsCount > 0) { + applyPreset(); + } + } + + onSaved: { + gradientLine.savePreset(); + presetList.updatePresets(); + } + + onAccepted: { //return key + if (presetList.gradientData.stopsCount > 0) { + applyPreset(); + } + } + } + + Rectangle { + width: 18 + height: 18 + anchors.centerIn: parent + color: "steelblue" + + border.color: "black" + border.width: 1 + + MouseArea { + anchors.fill: parent + onClicked: { + presetList.open() + } + } + } + } + ExpandingSpacer { } } + //empty spacer 2 + Item { + height: 6 + } + + Item { + height: 6 + } + + //spacer 3 + Item { + height: 6 + } + ColorButton { property color bindedColor: colorEditor.color @@ -536,24 +615,101 @@ Column { enabled: !colorEditor.transparent opacity: checkButton.checked ? 1 : 0 id: colorButton - width: 116 - height: checkButton.checked ? 116 : 0 - Layout.preferredWidth: 116 - Layout.preferredHeight: checkButton.checked ? 116 : 0 + Layout.preferredWidth: 124 + Layout.preferredHeight: checkButton.checked ? 124 : 0 - sliderMargins: Math.max(0, label.width - colorButton.width) + 4 + sliderMargins: 4 onClicked: colorEditor.color = colorButton.color } - SecondColumnLayout { + //empty spacer 4 + Item { height: 2 } + Item { height: 2 } + + //spacer 5 + Item { + height: 4 } Item { - height: 4 - width :4 - } + id: colorBoxes + Layout.preferredWidth: 134 + Layout.preferredHeight: checkButton.checked ? 70 : 0 + visible: checkButton.checked + + + SecondColumnLayout { + spacing: 16 + RowLayout { + spacing: 2 + Column { + spacing: 5 + Text { + text: qsTr("Original") + color: "#eee" + } + Rectangle { + id: originalColorRectangle + color: colorEditor.originalColor + height: 40 + width: 67 + + border.width: 1 + border.color: "#555555" + + MouseArea { + anchors.fill: parent + onClicked: { + if (!colorEditor.transparent) + colorEditor.color = colorEditor.originalColor + } + } + } + } + + Column { + spacing: 5 + Text { + text: qsTr("New") + color: "#eee" + } + Rectangle { + id: newColorRectangle + color: colorEditor.color + height: 40 + width: 67 + + border.width: 1 + border.color: "#555555" + } + } + } + + Column { + spacing: 5 + Text { + text: qsTr("Recent") + color: "#eee" + elide: Text.ElideRight + } + + SimpleColorPalette { + id: colorPalette + + clickable: !colorEditor.transparent + + onSelectedColorChanged: { + colorEditor.color = colorPalette.selectedColor; + } + } + } + + ExpandingSpacer { + } + } + } } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml new file mode 100644 index 00000000000..c7256ba8929 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.1 +import HelperWidgets 2.0 +import QtQuick.Controls.Private 1.0 // showing a ToolTip + +Item { + width: 300 + height: 60 + + property alias currentColor : colorLine.color + + Column { + anchors.fill: parent + + Item { + width: 1 + height: 40 + } + Rectangle { + height: 16 + width: parent.width + border.color: "#555555" + border.width: 1 + + id: colorLine + color: "white" + } + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml index 8db236176f7..f1886ada433 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml @@ -40,6 +40,8 @@ Item { property alias gradientPropertyName: gradientModel.gradientPropertyName property alias gradientTypeName: gradientModel.gradientTypeName + signal selectedNodeChanged + onHasGradientChanged: { colorLine.invalidate() } @@ -75,6 +77,10 @@ Item { gradientModel.savePreset() } + function updateGradient() { + gradientModel.updateGradient() + } + Connections { target: modelNodeBackend onSelectionChanged: { @@ -105,6 +111,7 @@ Item { gradientModel.lock() currentColor = repeater.itemAt(index).item.color gradientModel.unlock() + selectedNodeChanged() } function invalidate() { @@ -134,6 +141,7 @@ Item { height: 40 anchors.left: parent.left anchors.right: parent.right + cursorShape: Qt.PointingHandCursor onClicked: { var currentPosition = mouseX / colorLine.effectiveWidth @@ -321,6 +329,7 @@ Item { drag.maximumX: colorLine.effectiveWidth drag.minimumY: !readOnly ? 0 : 20 drag.maximumY: 20 + cursorShape: Qt.PointingHandCursor // using pressed property instead of drag.active which was not working onExited: { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml new file mode 100644 index 00000000000..c6b6acf2429 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 2.5 +import HelperWidgets 2.0 +import QtQuick.Controls.Private 1.0 // showing a ToolTip + +Item { + property color selectedColor + property bool clickable : true + + + width: 200 + height: 40 + enabled: clickable + + function addColorToPalette(colorCode) + { + paletteModel.addItem(colorCode) + } + + Component { + id: colorItemDelegate + + + Rectangle { + id: backgroundColor + property var favorite : isFavorite + height: 27 + width: 27 + border.color: (backgroundColor.favorite ? "#ffd700" : "#555555") + border.width: (backgroundColor.favorite ? 2 : 1) + color: "white" + radius: 0 + + Rectangle { + id: colorRectangle + width: 25 + height: 25 + anchors.centerIn: parent + color: colorCode + + border.color: "black" + border.width: 1 + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + onClicked: { + if ((mouse.button === Qt.LeftButton) && clickable) + selectedColor = colorRectangle.color + } + onPressed: { + if (mouse.button === Qt.RightButton) + contextMenu.popup() + } + } + Menu { + id: contextMenu + modal: true + closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape + MenuItem { + text: (backgroundColor.favorite + ? qsTr("Remove from Favorites") + : qsTr("Add to Favorites")) + onTriggered: { + paletteModel.toggleFavorite(index) + } + } + + Overlay.modal: Rectangle { + color: "transparent" + } + } + } + } + + SimpleColorPaletteModel { id: paletteModel } + ListView { + id: colorPaletteView + model: paletteModel + delegate: colorItemDelegate + orientation: Qt.Horizontal + anchors.fill: parent + clip: true + interactive: false + spacing: 2 + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir index 43e4da76368..9480f1d9a3a 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir @@ -9,6 +9,7 @@ CheckBox 2.0 CheckBox.qml ColorButton 2.0 ColorButton.qml ColorCheckButton 2.0 ColorCheckButton.qml ColorEditor 2.0 ColorEditor.qml +ColorLine 2.0 ColorLine.qml ColorLogic 2.0 ColorLogic.qml ComboBox 2.0 ComboBox.qml CustomCheckBoxStyle 2.0 CustomCheckBoxStyle.qml @@ -33,6 +34,7 @@ ScrollView 2.0 ScrollView.qml SecondColumnLayout 2.0 SecondColumnLayout.qml Section 2.0 Section.qml SectionLayout 2.0 SectionLayout.qml +SimpleColorPalette 2.0 SimpleColorPalette.qml DoubleSpinBox 2.0 DoubleSpinBox.qml SpinBox 2.0 SpinBox.qml StandardTextSection 2.0 StandardTextSection.qml diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp index 5aadf8dad5f..5728c594d48 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp @@ -181,7 +181,7 @@ void GradientModel::addGradient() setupModel(); if (m_gradientTypeName != "Gradient") - QTimer::singleShot(100, [this](){ view()->resetPuppet(); }); /*Unfortunately required */ + QTimer::singleShot(1000, [this](){ view()->resetPuppet(); }); /*Unfortunately required */ emit hasGradientChanged(); emit gradientTypeChanged(); } @@ -534,19 +534,20 @@ void GradientModel::setPresetByStops(const QList &stopsPositions, QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction( QByteArrayLiteral("GradientModel::setCustomPreset")); - //delete an old gradient without rewriter transaction deleteGradientNode(false); - //create a new gradient: if (!m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) { try { + + if (m_gradientTypeName != "Gradient") + ensureShapesImport(); + QmlDesigner::ModelNode gradientNode = createGradientNode(); m_itemNode.modelNode() .nodeProperty(gradientPropertyName().toUtf8()) .reparentHere(gradientNode); - //create stops and give them positions and colors based on value for (int i = 0; i < stopsCount; i++) { QmlDesigner::ModelNode gradientStopNode = createGradientStopNode(); gradientStopNode.variantProperty("position").setValue(stopsPositions.at(i)); @@ -560,6 +561,9 @@ void GradientModel::setPresetByStops(const QList &stopsPositions, } setupModel(); + if (m_gradientTypeName != "Gradient") + QTimer::singleShot(200, [this]() { view()->resetPuppet(); }); /*Unfortunately required */ + emit hasGradientChanged(); emit gradientTypeChanged(); } @@ -586,3 +590,16 @@ void GradientModel::savePreset() items.append(item); GradientPresetCustomListModel::storePresets(filename, items); } + +void GradientModel::updateGradient() +{ + QList stops; + QList colors; + int stopsCount = rowCount(); + for (int i = 0; i < stopsCount; i++) { + stops.append(getPosition(i)); + colors.append(getColor(i).name(QColor::HexArgb)); + } + + setPresetByStops(stops, colors, stopsCount); +} diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h index d5fb3aea2a9..0cc1a3c4ae5 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h +++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h @@ -77,6 +77,8 @@ public: Q_INVOKABLE void savePreset(); + Q_INVOKABLE void updateGradient(); + signals: void anchorBackendChanged(); void hasGradientChanged(); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri index 9d53bda311d..b32a744016f 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri @@ -15,7 +15,10 @@ SOURCES += propertyeditorview.cpp \ gradientpresetitem.cpp \ gradientpresetlistmodel.cpp \ gradientpresetdefaultlistmodel.cpp \ - gradientpresetcustomlistmodel.cpp + gradientpresetcustomlistmodel.cpp \ + simplecolorpalette.cpp \ + simplecolorpalettemodel.cpp \ + simplecolorpalettesingleton.cpp HEADERS += propertyeditorview.h \ qmlanchorbindingproxy.h \ @@ -32,6 +35,9 @@ HEADERS += propertyeditorview.h \ gradientpresetitem.h \ gradientpresetlistmodel.h \ gradientpresetdefaultlistmodel.h \ - gradientpresetcustomlistmodel.h + gradientpresetcustomlistmodel.h \ + simplecolorpalette.h \ + simplecolorpalettemodel.h \ + simplecolorpalettesingleton.h QT += qml quick diff --git a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp index f9b42cf8eb8..862d16ba22f 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp @@ -30,6 +30,7 @@ #include "gradientmodel.h" #include "gradientpresetdefaultlistmodel.h" #include "gradientpresetcustomlistmodel.h" +#include "simplecolorpalettemodel.h" #include "qmlanchorbindingproxy.h" #include "theme.h" @@ -52,6 +53,7 @@ void Quick2PropertyEditorView::registerQmlTypes() GradientModel::registerDeclarativeType(); GradientPresetDefaultListModel::registerDeclarativeType(); GradientPresetCustomListModel::registerDeclarativeType(); + SimpleColorPaletteModel::registerDeclarativeType(); Internal::QmlAnchorBindingProxy::registerDeclarativeType(); } } diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp new file mode 100644 index 00000000000..7fada3f0d38 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "simplecolorpalette.h" + +#include "designersettings.h" + +#include + +namespace QmlDesigner { + +PaletteColor::PaletteColor() + : m_color(QColor()) + , m_colorCode(QColor().name()) + , m_isFavorite(false) +{} + +PaletteColor::PaletteColor(const QString &colorCode) + : m_color(colorCode) + , m_colorCode(colorCode) + , m_isFavorite(false) +{} + +PaletteColor::PaletteColor(const QColor &value) + : m_color(color) + , m_colorCode(color.name(QColor::HexArgb)) + , m_isFavorite(false) +{} + +QVariant PaletteColor::getProperty(Property id) const +{ + QVariant out; + + switch (id) { + case objectNameRole: + out.setValue(QString()); + break; + case colorRole: + out.setValue(color()); + break; + case colorCodeRole: + out.setValue(colorCode()); + break; + case isFavoriteRole: + out.setValue(isFavorite()); + break; + default: + qWarning() << "PaletteColor Property switch default case"; + break; //replace with assert before switch? + } + + return out; +} + +QColor PaletteColor::color() const +{ + return m_color; +} + +void PaletteColor::setColor(const QColor &value) +{ + m_color = value; + m_colorCode = m_color.name(QColor::HexArgb); +} + +QString PaletteColor::colorCode() const +{ + return m_colorCode; +} + +bool PaletteColor::isFavorite() const +{ + return m_isFavorite; +} + +void PaletteColor::setFavorite(bool favorite) +{ + m_isFavorite = favorite; +} + +bool PaletteColor::toggleFavorite() +{ + return m_isFavorite = !m_isFavorite; +} + +bool PaletteColor::operator==(const PaletteColor &other) const +{ + return (m_color == other.m_color); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h new file mode 100644 index 00000000000..342c9832e71 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace QmlDesigner { + +class PaletteColor +{ + Q_GADGET + + Q_PROPERTY(QColor color READ color FINAL) + Q_PROPERTY(QString colorCode READ colorCode FINAL) + Q_PROPERTY(bool isFavorite READ isFavorite FINAL) +public: + PaletteColor(); + PaletteColor(const QString &colorCode); + PaletteColor(const QColor &value); + ~PaletteColor() = default; + + enum Property { + objectNameRole = 0, + colorRole = 1, + colorCodeRole = 2, + isFavoriteRole = 3 + }; + + QVariant getProperty(Property id) const; + + QColor color() const; + void setColor(const QColor &value); + + QString colorCode() const; + + bool isFavorite() const; + void setFavorite(bool favorite); + bool toggleFavorite(); + + bool operator==(const PaletteColor &other) const; + +private: + QColor m_color; + QString m_colorCode; + bool m_isFavorite; +}; + +} // namespace QmlDesigner + +Q_DECLARE_METATYPE(QmlDesigner::PaletteColor) diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp new file mode 100644 index 00000000000..b3207f0006d --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "simplecolorpalettemodel.h" +#include "simplecolorpalette.h" +#include "simplecolorpalettesingleton.h" + +#include "designersettings.h" + +#include +#include +#include +#include + +namespace QmlDesigner { + +SimpleColorPaletteModel::SimpleColorPaletteModel(QObject *parent) + : QAbstractListModel(parent) +{ + connect(&SimpleColorPaletteSingleton::getInstance(), + &SimpleColorPaletteSingleton::paletteChanged, + this, + &SimpleColorPaletteModel::setPalette); + m_roleNames = {{static_cast(PaletteColor::Property::objectNameRole), "objectName"}, + {static_cast(PaletteColor::Property::colorRole), "color"}, + {static_cast(PaletteColor::Property::colorCodeRole), "colorCode"}, + {static_cast(PaletteColor::Property::isFavoriteRole), "isFavorite"}}; + + setPalette(); +} + +SimpleColorPaletteModel::~SimpleColorPaletteModel() +{ + clearItems(); +} + +int SimpleColorPaletteModel::rowCount(const QModelIndex & /*parent*/) const +{ + return m_items.count(); +} + +QVariant SimpleColorPaletteModel::data(const QModelIndex &index, int role) const +{ + if (index.isValid() && (index.row() >= 0) && (index.row() < m_items.count())) { + if (m_roleNames.contains(role)) { + QVariant value = m_items.at(index.row()) + .getProperty(static_cast(role)); + if (auto model = qobject_cast(value.value())) + return QVariant::fromValue(model); + + return value; + } + + qWarning() << Q_FUNC_INFO << "invalid role requested"; + return QVariant(); + } + + qWarning() << Q_FUNC_INFO << "invalid index requested"; + return QVariant(); +} + +QHash SimpleColorPaletteModel::roleNames() const +{ + return m_roleNames; +} + +void SimpleColorPaletteModel::clearItems() +{ + beginResetModel(); + m_items.clear(); + endResetModel(); +} + +void SimpleColorPaletteModel::addItem(const QString &item) +{ + PaletteColor palette(item); + addItem(palette); +} + +void SimpleColorPaletteModel::addItem(const PaletteColor &item) +{ + SimpleColorPaletteSingleton::getInstance().addItem(item); +} + +const QList &SimpleColorPaletteModel::items() const +{ + return m_items; +} + +void SimpleColorPaletteModel::sortItems() +{ + SimpleColorPaletteSingleton::getInstance().sortItems(); +} + +void SimpleColorPaletteModel::registerDeclarativeType() +{ + qmlRegisterType("HelperWidgets", 2, 0, "SimpleColorPaletteModel"); +} + +void SimpleColorPaletteModel::toggleFavorite(int id) +{ + SimpleColorPaletteSingleton::getInstance().toggleFavorite(id); +} + +void SimpleColorPaletteModel::setPalette() +{ + beginResetModel(); + m_items = SimpleColorPaletteSingleton::getInstance().getItems(); + m_favoriteOffset = SimpleColorPaletteSingleton::getInstance().getFavoriteOffset(); + m_paletteSize = SimpleColorPaletteSingleton::getInstance().getPaletteSize(); + endResetModel(); +} + +bool SimpleColorPaletteModel::read() +{ + return SimpleColorPaletteSingleton::getInstance().readPalette(); +} + +void SimpleColorPaletteModel::write() +{ + SimpleColorPaletteSingleton::getInstance().writePalette(); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h new file mode 100644 index 00000000000..3ed2cc8a31d --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace QmlDesigner { + +class PaletteColor; + +class SimpleColorPaletteModel : public QAbstractListModel +{ + Q_OBJECT +public: + explicit SimpleColorPaletteModel(QObject *parent = nullptr); + ~SimpleColorPaletteModel() override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash roleNames() const override; + + void clearItems(); + Q_INVOKABLE void addItem(const QString &item); + void addItem(const PaletteColor &item); + + const QList &items() const; + + void sortItems(); + + static void registerDeclarativeType(); + + Q_INVOKABLE void toggleFavorite(int id); + + bool read(); + void write(); + +private slots: + void setPalette(); + +private: + void enqueue(const PaletteColor &item); + +private: + int m_paletteSize; + int m_favoriteOffset; + QList m_items; + QHash m_roleNames; +}; + +} // namespace QmlDesigner + +QML_DECLARE_TYPE(QmlDesigner::SimpleColorPaletteModel) diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp new file mode 100644 index 00000000000..ccea50bbf25 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "simplecolorpalettesingleton.h" +#include "simplecolorpalette.h" + +#include "designersettings.h" + +#include +#include + +namespace QmlDesigner { + +SimpleColorPaletteSingleton::SimpleColorPaletteSingleton() + : m_items() + , m_favoriteOffset(0) +{ + if (!readPalette()) { + for (int i = 0; i < m_paletteSize; i++) + m_items.append(PaletteColor()); + } +} + +SimpleColorPaletteSingleton &SimpleColorPaletteSingleton::getInstance() +{ + static SimpleColorPaletteSingleton singleton; + + return singleton; +} + +void SimpleColorPaletteSingleton::addItem(const PaletteColor &item) +{ + if (m_favoriteOffset >= m_paletteSize) + return; + + if (item.isFavorite()) { + int contains = m_items.indexOf(item); + if (contains != -1) { + if (m_items.at(contains).isFavorite()) + return; + else + m_items.removeAt(contains); + } + m_items.insert(0, item); + m_favoriteOffset++; + } else if (m_items.contains(item)) + return; + else + m_items.insert(m_favoriteOffset, item); + + while (m_items.size() > m_paletteSize) { + m_items.removeLast(); + } + + writePalette(); + + emit paletteChanged(); +} + +QList SimpleColorPaletteSingleton::getItems() const +{ + return m_items; +} + +int SimpleColorPaletteSingleton::getPaletteSize() const +{ + return m_paletteSize; +} + +int SimpleColorPaletteSingleton::getFavoriteOffset() const +{ + return m_favoriteOffset; +} + +void SimpleColorPaletteSingleton::sortItems() +{ + auto itemSort = [](const PaletteColor &first, const PaletteColor &second) { + return (static_cast(first.isFavorite()) < static_cast(second.isFavorite())); + }; + + std::sort(m_items.begin(), m_items.end(), itemSort); + + emit paletteChanged(); +} + +void SimpleColorPaletteSingleton::toggleFavorite(int id) +{ + bool toggleResult = m_items[id].toggleFavorite(); + + if (toggleResult) { + m_favoriteOffset++; + m_items.move(id, 0); + } else { + m_favoriteOffset--; + m_items.move(id, m_favoriteOffset); + } + + if (m_favoriteOffset < 0) + m_favoriteOffset = 0; + else if (m_favoriteOffset > m_paletteSize) + m_favoriteOffset = m_paletteSize; + + emit paletteChanged(); +} + +bool SimpleColorPaletteSingleton::readPalette() +{ + QList proxy; + const QStringList stringData = QmlDesigner::DesignerSettings::getValue( + QmlDesigner::DesignerSettingsKey::SIMPLE_COLOR_PALETTE_CONTENT) + .toStringList(); + + int favCounter = 0; + + for (int i = 0; i < stringData.size(); i++) { + const QStringList strsep = stringData.at(i).split(";"); + if (strsep.size() != 2) { + continue; + } + PaletteColor colorItem(strsep.at(0)); + bool isFav = static_cast(strsep.at(1).toInt()); + colorItem.setFavorite(isFav); + if (isFav) + favCounter++; + proxy.append(colorItem); + } + + if (proxy.size() == 0) { + return false; + } + + while (proxy.size() > m_paletteSize) { + proxy.removeLast(); + } + while (proxy.size() < m_paletteSize) { + proxy.append(PaletteColor()); + } + + m_items.clear(); + m_items = proxy; + m_favoriteOffset = favCounter; + + return true; +} + +void SimpleColorPaletteSingleton::writePalette() +{ + QStringList output; + QString subres; + + for (int i = 0; i < m_items.size(); i++) { + subres = m_items.at(i).color().name(QColor::HexArgb); + subres += ";"; + subres += QString::number(static_cast(m_items.at(i).isFavorite())); + output.push_back(subres); + subres.clear(); + } + + QmlDesigner::DesignerSettings::setValue( + QmlDesigner::DesignerSettingsKey::SIMPLE_COLOR_PALETTE_CONTENT, output); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h new file mode 100644 index 00000000000..004feea5325 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +namespace QmlDesigner { + +class PaletteColor; + +class SimpleColorPaletteSingleton : public QObject +{ + Q_OBJECT +public: + static SimpleColorPaletteSingleton &getInstance(); + + bool readPalette(); + void writePalette(); + + void addItem(const PaletteColor &item); + QList getItems() const; + + int getPaletteSize() const; + int getFavoriteOffset() const; + + void sortItems(); + + void toggleFavorite(int id); + + SimpleColorPaletteSingleton(const SimpleColorPaletteSingleton &) = delete; + void operator=(const SimpleColorPaletteSingleton &) = delete; + +signals: + void paletteChanged(); + +private: + SimpleColorPaletteSingleton(); + +private: + QList m_items; + const int m_paletteSize = 6; + int m_favoriteOffset; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index c86336d5509..b9b82f5714f 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -372,6 +372,13 @@ bool smartVeryFuzzyCompare(const QVariant &value1, const QVariant &value2) return false; } +bool smartColorCompare(const QVariant &value1, const QVariant &value2) +{ + if ((value1.type() == QVariant::Color) || (value2.type() == QVariant::Color)) + return value1.value().rgba() == value2.value().rgba(); + return false; +} + bool equals(const QVariant &a, const QVariant &b) { if (a.canConvert() && b.canConvert()) @@ -380,6 +387,8 @@ bool equals(const QVariant &a, const QVariant &b) return true; if (smartVeryFuzzyCompare(a, b)) return true; + if (smartColorCompare(a, b)) + return true; return false; } diff --git a/src/plugins/qmldesigner/designersettings.cpp b/src/plugins/qmldesigner/designersettings.cpp index 7df99bd59bb..5870927d529 100644 --- a/src/plugins/qmldesigner/designersettings.cpp +++ b/src/plugins/qmldesigner/designersettings.cpp @@ -76,6 +76,7 @@ void DesignerSettings::fromSettings(QSettings *settings) restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, true); restoreValue(settings, DesignerSettingsKey::STANDALONE_MODE, false); restoreValue(settings, DesignerSettingsKey::ENABLE_TIMELINEVIEW, false); + restoreValue(settings, DesignerSettingsKey::SIMPLE_COLOR_PALETTE_CONTENT, QStringList()); settings->endGroup(); settings->endGroup(); diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h index bdaa22bb4b2..410abc267e2 100644 --- a/src/plugins/qmldesigner/designersettings.h +++ b/src/plugins/qmldesigner/designersettings.h @@ -65,6 +65,7 @@ const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These setti const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */ const char STANDALONE_MODE[] = "StandAloneMode"; const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView"; +const char SIMPLE_COLOR_PALETTE_CONTENT[] = "SimpleColorPaletteContent"; } class DesignerSettings : public QHash diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index 6a2379ea05e..600fcab3fe9 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -588,6 +588,12 @@ Project { "propertyeditor/qmlanchorbindingproxy.h", "propertyeditor/qmlmodelnodeproxy.cpp", "propertyeditor/qmlmodelnodeproxy.h", + "propertyeditor/simplecolorpalette.cpp", + "propertyeditor/simplecolorpalette.h", + "propertyeditor/simplecolorpalettemodel.cpp", + "propertyeditor/simplecolorpalettemodel.h", + "propertyeditor/simplecolorpalettesingleton.cpp", + "propertyeditor/simplecolorpalettesingleton.h", "resources/resources.qrc", "stateseditor/stateseditorimageprovider.cpp", "stateseditor/stateseditorimageprovider.h", From 22be712f477dfee6b5eba149c2451acd106204b2 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Wed, 5 Jun 2019 10:39:44 +0200 Subject: [PATCH 20/28] QmlDesigner: Add new controls for property editor Adds new controls for the property editor based on Controls 2. Change-Id: Ice54ead5d774a7ce54282e442cb26cb970a4be1b Reviewed-by: Thomas Hartmann --- .../imports/HelperWidgets/SpinBox.qml | 96 +++-- .../imports/StudioControls/AbstractButton.qml | 119 ++++++ .../StudioControls/ActionIndicator.qml | 129 +++++++ .../imports/StudioControls/Button.qml | 39 ++ .../imports/StudioControls/ButtonGroup.qml | 31 ++ .../imports/StudioControls/ButtonRow.qml | 52 +++ .../imports/StudioControls/CheckBox.qml | 159 ++++++++ .../imports/StudioControls/CheckIndicator.qml | 138 +++++++ .../imports/StudioControls/ComboBox.qml | 254 +++++++++++++ .../imports/StudioControls/ComboBoxInput.qml | 159 ++++++++ .../imports/StudioControls/ContextMenu.qml | 92 +++++ .../StudioControls/ExpandingSpacer.qml | 31 ++ .../imports/StudioControls/ItemDelegate.qml | 31 ++ .../imports/StudioControls/Menu.qml | 63 ++++ .../imports/StudioControls/MenuItem.qml | 86 +++++ .../imports/StudioControls/MenuSeparator.qml | 46 +++ .../imports/StudioControls/ScrollBar.qml | 63 ++++ .../imports/StudioControls/ScrollView.qml | 62 ++++ .../StudioControls/SecondColumnLayout.qml | 32 ++ .../imports/StudioControls/Section.qml | 130 +++++++ .../imports/StudioControls/SectionLabel.qml | 53 +++ .../imports/StudioControls/SectionLayout.qml | 34 ++ .../imports/StudioControls/Slider.qml | 293 +++++++++++++++ .../imports/StudioControls/SliderPopup.qml | 89 +++++ .../imports/StudioControls/SpinBox.qml | 343 ++++++++++++++++++ .../StudioControls/SpinBoxIndicator.qml | 130 +++++++ .../imports/StudioControls/SpinBoxInput.qml | 215 +++++++++++ .../imports/StudioControls/TextArea.qml | 144 ++++++++ .../imports/StudioControls/TextField.qml | 175 +++++++++ .../StudioControls/TranslationIndicator.qml | 120 ++++++ .../imports/StudioControls/qmldir | 29 ++ .../imports/StudioTheme/Constants.qml | 75 ++++ .../imports/StudioTheme/Values.qml | 124 +++++++ .../imports/StudioTheme/icons.ttf | Bin 0 -> 4300 bytes .../imports/StudioTheme/qmldir | 2 + 35 files changed, 3609 insertions(+), 29 deletions(-) create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml index cc50509cc0e..7fcc2956d55 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml @@ -24,42 +24,80 @@ ****************************************************************************/ import QtQuick 2.1 -import QtQuick.Controls 1.1 as Controls import QtQuick.Controls.Styles 1.1 +import StudioControls 1.0 as StudioControls -Controls.SpinBox { - id: spinBox +Item { + id: wrapper - property color textColor: colorLogic.textColor - property variant backendValue; + property alias decimals: spinBox.decimals + property alias hasSlider: spinBox.hasSlider - implicitWidth: 74 + property real minimumValue + property real maximumValue + property real stepSize - ExtendedFunctionButton { - x: 4 - anchors.verticalCenter: parent.verticalCenter - backendValue: spinBox.backendValue - visible: spinBox.enabled + property alias backendValue: spinBox.backendValue + + Component.onCompleted: { + // TODO minimumValue/maximumValue convertion... + // TODO step size convertion... } - ColorLogic { - id: colorLogic - backendValue: spinBox.backendValue - onValueFromBackendChanged: { - spinBox.value = valueFromBackend; + width: 100 + implicitHeight: spinBox.height + + StudioControls.SpinBox { + id: spinBox + + property real properValue: value / factor + + from: minimumValue * factor + to: maximumValue * factor + + width: wrapper.width + //height: wrapper.height + +// property color textColor: colorLogic.textColor + property variant backendValue; + + //implicitWidth: 74 +/* + ExtendedFunctionButton { + x: 4 + anchors.verticalCenter: parent.verticalCenter + backendValue: spinBox.backendValue + visible: spinBox.enabled } +*/ + /* + icon: extend.glyph + Extn2 { + glyph: + } + */ + + textColor: colorLogic.textColor + + ColorLogic { + id: colorLogic + backendValue: spinBox.backendValue + onValueFromBackendChanged: { + spinBox.value = valueFromBackend * factor; + } + } + + property bool hasSlider: false + + //height: hasSlider ? 32 : implicitHeight + + onCompressedValueModified: { + if (backendValue.value !== properValue) + backendValue.value = properValue; + } + /* + style: CustomSpinBoxStyle { + } + */ } - - property bool hasSlider: false - - height: hasSlider ? 32 : implicitHeight - - onValueChanged: { - if (backendValue.value !== value) - backendValue.value = value; - } - - style: CustomSpinBoxStyle { - } - } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml new file mode 100644 index 00000000000..3241eb405d5 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.AbstractButton { + id: myButton + + property alias buttonIcon: buttonIcon.text + property alias backgroundVisible: buttonBackground.visible + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + height: StudioTheme.Values.height + width: StudioTheme.Values.height + z: myButton.checked ? 10 : 3 + activeFocusOnTab: false // TODO Decision pending. Focus for AbstractButtons? + + background: Rectangle { + id: buttonBackground + color: myButton.checked ? StudioTheme.Values.themeControlBackgroundChecked : StudioTheme.Values.themeControlBackground + border.color: myButton.checked ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + } + + indicator: Item { + x: 0 + y: 0 + implicitWidth: myButton.width + implicitHeight: myButton.height + + T.Label { + id: buttonIcon + color: StudioTheme.Values.themeTextColor + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.myIconFontSize + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors.fill: parent + renderType: Text.QtRendering + } + } + + states: [ + State { + name: "default" + when: myButton.enabled && !myButton.hovered && !myButton.pressed + && !myButton.checked + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeControlBackground + } + PropertyChanges { + target: myButton + z: 3 + } + }, + State { + name: "hovered" + when: myButton.hovered && !myButton.pressed + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeHoverHighlight + } + }, + State { + name: "pressed" + when: myButton.hovered && myButton.pressed + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeControlBackgroundPressed + border.color: StudioTheme.Values.themeInteraction + } + PropertyChanges { + target: myButton + z: 10 + } + }, + State { + name: "disabled" + when: !myButton.enabled + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: buttonIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml new file mode 100644 index 00000000000..4bc550e252e --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Rectangle { + id: actionIndicator + + property Item myControl + + property alias icon: actionIndicatorIcon + + property bool hover: false + property bool pressed: false + + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + state: "default" + + implicitWidth: StudioTheme.Values.height + implicitHeight: StudioTheme.Values.height + + T.Label { + id: actionIndicatorIcon + anchors.fill: parent + text: StudioTheme.Constants.actionIcon + color: StudioTheme.Values.themeTextColor + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.myIconFontSize + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + + MouseArea { + id: actionIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: actionIndicator.hover = containsMouse + } + + states: [ + State { + name: "default" + when: myControl.enabled && !actionIndicator.hover + && !actionIndicator.pressed && !myControl.hover + && !myControl.activeFocus && !myControl.drag + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "hovered" + when: actionIndicator.hover && !actionIndicator.pressed + && !myControl.activeFocus && !myControl.drag + PropertyChanges { + target: actionIndicatorIcon + scale: 1.2 + } + }, + State { + name: "globalHover" + when: myControl.hover && !actionIndicator.hover + && !actionIndicator.pressed && !myControl.activeFocus + && !myControl.drag + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: myControl.activeFocus + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "drag" + when: myControl.drag + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeFocusDrag + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: actionIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml new file mode 100644 index 00000000000..40713d3ed13 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +ButtonRow { + id: myButtonRow + + property alias buttonIcon: myAbstractButton.buttonIcon + property alias checkable: myAbstractButton.checkable + + AbstractButton { + id: myAbstractButton + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml new file mode 100644 index 00000000000..1b233c590bc --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T + +T.ButtonGroup { + +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml new file mode 100644 index 00000000000..614847f3408 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Row { + // TODO When using Item as root it won't react to outer layout + id: myButtonGroup + + property alias actionIcon: actionIndicator.icon + + //property bool hover: myCheckBox.hovered // TODO + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + ActionIndicator { + id: actionIndicator + myControl: myButtonGroup // TODO global hover issue. Can be solved with extra property in ActionIndicator + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + spacing: -StudioTheme.Values.border // TODO Which one is better? Spacing vs. layout function. ALso depends on root item +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml new file mode 100644 index 00000000000..5eb17ed81be --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.CheckBox { + id: myCheckBox + + property alias actionIcon: actionIndicator.icon + + property bool hover: myCheckBox.hovered // TODO two underscores + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property alias labelVisible: checkBoxLabel.visible + + font.pixelSize: StudioTheme.Values.myFontSize + + height: StudioTheme.Values.height + width: StudioTheme.Values.height * 5 + + spacing: StudioTheme.Values.checkBoxSpacing + hoverEnabled: true + activeFocusOnTab: false // TODO Decision pending. Focus for CheckBoxes? + + contentItem: T.Label { + id: checkBoxLabel + leftPadding: 0 + rightPadding: 0 + + width: 20 // TODO Not working + elide: Text.ElideRight + + verticalAlignment: Text.AlignVCenter + text: myCheckBox.text + font: myCheckBox.font + color: StudioTheme.Values.themeTextColor + } + + ActionIndicator { + id: actionIndicator + myControl: myCheckBox // TODO global hover issue. Can be solved with extra property in ActionIndicator + + x: checkBoxLabel.visible ? checkBoxLabel.contentWidth + + (myCheckBox.spacing + * StudioTheme.Values.scaleFactor) : 0 // TODO scale factor + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + indicator: Rectangle { + id: checkBoxBackground + x: actionIndicator.x + actionIndicator.width + - (actionIndicator.visible ? StudioTheme.Values.border : 0) + y: 0 + z: 5 + implicitWidth: StudioTheme.Values.height + implicitHeight: StudioTheme.Values.height + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + + T.Label { + id: checkBoxIcon + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + text: StudioTheme.Constants.tickIcon + visible: myCheckBox.checkState === Qt.Checked + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderControlSizeMulti + font.family: StudioTheme.Constants.iconFont.family + } + + /* + // Tristate only + Rectangle { + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + width: 16 + height: 3 + color: myCheckBox.palette.text + visible: myCheckBox.checkState === Qt.PartiallyChecked + } +*/ + } + + states: [ + State { + name: "default" + when: myCheckBox.enabled && !myCheckBox.hovered + && !myCheckBox.pressed + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeControlBackground + } + }, + State { + name: "hovered" + when: myCheckBox.hovered && !myCheckBox.pressed + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeHoverHighlight + } + }, + State { + name: "pressed" + when: myCheckBox.hovered && myCheckBox.pressed + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myCheckBox.enabled + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: checkBoxIcon + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: checkBoxLabel + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml new file mode 100644 index 00000000000..73788710bdb --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Rectangle { + id: checkIndicator + + property T.Control myControl + property T.Popup myPopup + + property bool hover: false + property bool checked: false + + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + state: "default" + + Connections { + target: myPopup + onClosed: checkIndicator.checked = false + onOpened: checkIndicator.checked = true + } + + MouseArea { + id: checkIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: checkIndicator.hover = checkIndicatorMouseArea.containsMouse + onPressed: { + myControl.forceActiveFocus() // TODO + myPopup.opened ? myPopup.close() : myPopup.open() + } + } + + T.Label { + id: checkIndicatorIcon + anchors.fill: parent + color: StudioTheme.Values.themeTextColor + text: StudioTheme.Constants.upDownSquare2 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: StudioTheme.Values.sliderControlSizeMulti + font.family: StudioTheme.Constants.iconFont.family + } + + states: [ + State { + name: "default" + when: myControl.enabled && !(checkIndicator.hover + || myControl.hover) + && !checkIndicator.checked && !myControl.activeFocus + && !myControl.drag + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "hovered" + when: (checkIndicator.hover || myControl.hover) + && !checkIndicator.checked && !myControl.activeFocus + && !myControl.drag + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "checked" + when: checkIndicator.checked + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "edit" + when: myControl.activeFocus && !checkIndicator.checked + && !(checkIndicator.hover && myControl.hover) + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "drag" + when: myControl.drag && !checkIndicator.checked + && !(checkIndicator.hover && myControl.hover) + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeFocusDrag + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: checkIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml new file mode 100644 index 00000000000..a2c15add0bf --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Window 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ComboBox { + id: myComboBox + + property alias actionIcon: actionIndicator.icon + + property bool hover: false // This property is used to indicate the global hover state + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property string __lastAcceptedText: "" + signal compressedActivated + + width: StudioTheme.Values.squareComponentWidth * 5 + height: StudioTheme.Values.height + + leftPadding: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + rightPadding: popupIndicator.width - StudioTheme.Values.border + font.pixelSize: StudioTheme.Values.myFontSize + wheelEnabled: false + + onFocusChanged: { + if (!focus) + comboBoxPopup.close() + } + + ActionIndicator { + id: actionIndicator + myControl: myComboBox + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + contentItem: ComboBoxInput { + id: comboBoxInput + myControl: myComboBox + text: myComboBox.editText + } + + indicator: CheckIndicator { + id: popupIndicator + myControl: myComboBox + myPopup: myComboBox.popup + x: comboBoxInput.x + comboBoxInput.width - StudioTheme.Values.border + y: 0 + width: StudioTheme.Values.squareComponentWidth + height: StudioTheme.Values.height + } + + background: Rectangle { + id: comboBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + width: myComboBox.width + height: myComboBox.height + } + + // Set the initial value for __lastAcceptedText + Component.onCompleted: __lastAcceptedText = myComboBox.editText + + onAccepted: { + if (myComboBox.editText != __lastAcceptedText) { + var pos = find(myComboBox.editText) + activated(pos) + } + __lastAcceptedText = myComboBox.editText + } + + Timer { + id: myTimer + repeat: false + running: false + interval: 100 + onTriggered: myComboBox.compressedActivated() + } + + onActivated: myTimer.restart() + + delegate: ItemDelegate { + id: myItemDelegate + + width: comboBoxPopup.width - comboBoxPopup.leftPadding - comboBoxPopup.rightPadding + - (comboBoxPopupScrollBar.visible ? comboBoxPopupScrollBar.contentItem.implicitWidth + + 2 : 0) // TODO Magic number + height: StudioTheme.Values.height - 2 * StudioTheme.Values.border + padding: 0 + + contentItem: Text { + leftPadding: itemDelegateIconArea.width + text: modelData + color: StudioTheme.Values.themeTextColor + font: myComboBox.font + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + + Item { + id: itemDelegateIconArea + width: myItemDelegate.height + height: myItemDelegate.height + + T.Label { + id: itemDelegateIcon + text: StudioTheme.Constants.tickIcon + color: myItemDelegate.highlighted ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeInteraction + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + visible: myComboBox.currentIndex === index ? true : false + anchors.fill: parent + renderType: Text.NativeRendering + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + + highlighted: myComboBox.highlightedIndex === index + + background: Rectangle { + id: itemDelegateBackground + x: 0 + y: 0 + width: myItemDelegate.width + height: myItemDelegate.height + color: myItemDelegate.highlighted ? StudioTheme.Values.themeInteraction : "transparent" + } + } + + popup: T.Popup { + id: comboBoxPopup + x: comboBoxInput.x + y: myComboBox.height - StudioTheme.Values.border + width: comboBoxInput.width + popupIndicator.width - StudioTheme.Values.border + // TODO Setting the height on the popup solved the problem with the popup of height 0, + // but it has the problem that it sometimes extend over the border of the actual window + // and is then cut off. + height: Math.min(contentItem.implicitHeight + comboBoxPopup.topPadding + + comboBoxPopup.bottomPadding, + myComboBox.Window.height - topMargin - bottomMargin, + StudioTheme.Values.maxComboBoxPopupHeight) + padding: StudioTheme.Values.border + margins: 0 // If not defined margin will be -1 + closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent + + contentItem: ListView { + clip: true + implicitHeight: contentHeight + model: myComboBox.popup.visible ? myComboBox.delegateModel : null + currentIndex: myComboBox.highlightedIndex + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar { + id: comboBoxPopupScrollBar + } + } + + background: Rectangle { + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeInteraction + border.width: StudioTheme.Values.border + } + + enter: Transition { + } + exit: Transition { + } + } + + states: [ + State { + name: "default" + when: !myComboBox.hover && !myComboBox.activeFocus + PropertyChanges { + target: myComboBox + wheelEnabled: false + } + PropertyChanges { + target: comboBoxInput + selectByMouse: false + } + PropertyChanges { + target: comboBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "focus" + when: myComboBox.activeFocus && !myComboBox.editable + PropertyChanges { + target: myComboBox + wheelEnabled: true + } + PropertyChanges { + target: comboBoxInput + focus: true + } + }, + State { + name: "edit" + when: myComboBox.activeFocus && myComboBox.editable + PropertyChanges { + target: myComboBox + wheelEnabled: true + } + PropertyChanges { + target: comboBoxInput + selectByMouse: true + } + PropertyChanges { + target: comboBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + } + ] + + Keys.onPressed: { + if (event.key === Qt.Key_Escape) + myComboBox.focus = false + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml new file mode 100644 index 00000000000..06e6ecb2b68 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +TextInput { + id: textInput + + property T.Control myControl + + property bool edit: false + property bool drag: false + + z: 2 + font: myControl.font + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignVCenter + leftPadding: StudioTheme.Values.inputHorizontalPadding + rightPadding: StudioTheme.Values.inputHorizontalPadding + + readOnly: !myControl.editable + validator: myControl.validator + inputMethodHints: myControl.inputMethodHints + selectByMouse: false + activeFocusOnPress: false + clip: true + + Rectangle { + id: textInputArea + x: 0 + y: 0 + z: -1 + width: textInput.width + height: StudioTheme.Values.height + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + } + + TapHandler { + id: tapHandler + acceptedDevices: PointerDevice.Mouse + enabled: true + onTapped: { + if (textInput.readOnly) { + if (myControl.popup.opened) { + myControl.popup.close() + } else { + myControl.popup.open() + myControl.forceActiveFocus() + } + } else { + textInput.forceActiveFocus() + } + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + // Sets the global hover + onContainsMouseChanged: myControl.hover = containsMouse + onPressed: mouse.accepted = false + } + + states: [ + State { + name: "default" + when: myControl.enabled && !textInput.activeFocus + && !mouseArea.containsMouse && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.PointingHandCursor + } + }, + State { + name: "hovered" + when: myControl.hover && !textInput.activeFocus && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "focus" + when: textInput.activeFocus && !myControl.editable + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "edit" + when: textInput.activeFocus && myControl.editable + extend: "focus" + PropertyChanges { + target: tapHandler + enabled: false + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.IBeamCursor + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml new file mode 100644 index 00000000000..ba5fec19e2a --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Controls 2.12 as Controls2 + +Menu { + id: contextMenu + + property Item myTextEdit + + Controls2.Action { + text: "Undo" + enabled: myTextEdit.canUndo + onTriggered: myTextEdit.undo() + shortcut: StandardKey.Undo + } + Controls2.Action { + text: "Redo" + enabled: myTextEdit.canRedo + onTriggered: myTextEdit.redo() + shortcut: StandardKey.Redo + } + + MenuSeparator { + } + + Controls2.Action { + text: "Copy" + enabled: myTextEdit.selectedText !== "" + onTriggered: myTextEdit.copy() + shortcut: StandardKey.Copy + } + Controls2.Action { + text: "Cut" + enabled: myTextEdit.selectedText !== "" && !myTextEdit.readOnly + onTriggered: myTextEdit.cut() + shortcut: StandardKey.Cut + } + Controls2.Action { + text: "Paste" + enabled: myTextEdit.canPaste + onTriggered: myTextEdit.paste() + shortcut: StandardKey.Paste + } + Controls2.Action { + text: "Delete" + enabled: myTextEdit.selectedText !== "" + onTriggered: myTextEdit.remove(myTextEdit.selectionStart, + myTextEdit.selectionEnd) + shortcut: StandardKey.Delete + } + Controls2.Action { + text: "Clear" + enabled: myTextEdit.text !== "" + onTriggered: myTextEdit.clear() + shortcut: StandardKey.DeleteCompleteLine + } + + MenuSeparator { + } + + Controls2.Action { + text: "Select All" + enabled: myTextEdit.text !== "" + && myTextEdit.selectedText !== myTextEdit.text + onTriggered: myTextEdit.selectAll() + shortcut: StandardKey.SelectAll + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml new file mode 100644 index 00000000000..9e48128c493 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 + +Item { + Layout.fillWidth: true +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml new file mode 100644 index 00000000000..c2190c5d838 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T + +T.ItemDelegate { + +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml new file mode 100644 index 00000000000..f9db27c6ac0 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Window 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Menu { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + + font.family: StudioTheme.Constants.font.family + font.pixelSize: StudioTheme.Values.myFontSize + + margins: 0 + overlap: 1 + padding: 0 + + delegate: MenuItem { + } + + contentItem: ListView { + model: control.contentModel + interactive: Window.window ? contentHeight > Window.window.height : false + clip: false + currentIndex: control.currentIndex + } + + background: Rectangle { + implicitWidth: contentItem.childrenRect.width + implicitHeight: contentItem.childrenRect.height + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml new file mode 100644 index 00000000000..b9a36f11352 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.MenuItem { + id: control + + property int labelSpacing: StudioTheme.Values.contextMenuLabelSpacing + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max( + implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + padding: 0 + spacing: 0 + horizontalPadding: StudioTheme.Values.contextMenuHorizontalPadding + + contentItem: Item { + id: menuItem + + width: control.menu.width + height: StudioTheme.Values.height + + Text { + id: textLabel + text: control.text + font: control.font + color: control.enabled ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeTextColorDisabled + anchors.verticalCenter: parent.verticalCenter + } + + Text { + id: shortcutLabel + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: shortcut.nativeText + font: control.font + color: textLabel.color + + Shortcut { + id: shortcut + property int shortcutWorkaround: control.action.shortcut + sequence: shortcutWorkaround + } + } + } + + background: Rectangle { + implicitWidth: textLabel.implicitWidth + control.labelSpacing + shortcutLabel.implicitWidth + + control.leftPadding + control.rightPadding // TODO + implicitHeight: StudioTheme.Values.height + x: StudioTheme.Values.border + y: StudioTheme.Values.border + width: control.width - (StudioTheme.Values.border * 2) + height: control.height - (StudioTheme.Values.border * 2) + color: control.down ? control.palette.midlight : control.highlighted ? StudioTheme.Values.themeInteraction : "transparent" + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml new file mode 100644 index 00000000000..4e226f5c584 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.MenuSeparator { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + padding: 0 + verticalPadding: padding + + contentItem: Rectangle { + implicitWidth: 10 + implicitHeight: StudioTheme.Values.border + color: StudioTheme.Values.themeControlOutline + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml new file mode 100644 index 00000000000..886e92206b4 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ScrollBar { + id: control + + // This needs to be set, when using T.ScrollBar + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + active: true + interactive: true + visible: control.size < 1.0 || T.ScrollBar.AlwaysOn + + snapMode: T.ScrollBar.SnapAlways // TODO + policy: T.ScrollBar.AsNeeded + + padding: 1 // TODO 0 + size: 1.0 + position: 1.0 + //orientation: Qt.Vertical + + contentItem: Rectangle { + id: controlHandle + implicitWidth: 4 + implicitHeight: 4 + radius: width / 2 // TODO 0 + color: StudioTheme.Values.themeScrollBarHandle + } + + background: Rectangle { + id: controlTrack + color: StudioTheme.Values.themeScrollBarTrack + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml new file mode 100644 index 00000000000..bf1b3937b9b --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ScrollView { + id: control + + property alias horizontalThickness: horizontalScrollBar.height + property alias verticalThickness: verticalScrollBar.width + property bool bothVisible: verticalScrollBar.visible + && horizontalScrollBar.visible + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + + ScrollBar.vertical: ScrollBar { + id: verticalScrollBar + parent: control + x: control.width - width - StudioTheme.Values.border + y: StudioTheme.Values.border + height: control.availableHeight - 2 * StudioTheme.Values.border + - (bothVisible ? horizontalThickness : 0) + active: control.ScrollBar.horizontal.active + } + + ScrollBar.horizontal: ScrollBar { + id: horizontalScrollBar + parent: control + x: StudioTheme.Values.border + y: control.height - height - StudioTheme.Values.border + width: control.availableWidth - 2 * StudioTheme.Values.border + - (bothVisible ? verticalThickness : 0) + active: control.ScrollBar.vertical.active + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml new file mode 100644 index 00000000000..d5c917f5ce3 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 + +RowLayout { + Layout.fillWidth: true + spacing: 4 +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml new file mode 100644 index 00000000000..98a163a3228 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import StudioTheme 1.0 as StudioTheme + +Item { + id: section + property alias caption: label.text + property int leftPadding: 8 + property int topPadding: 4 + property int rightPadding: 0 + + property int animationDuration: 0 + + property bool expanded: true + + clip: true + + Rectangle { + id: header + height: StudioTheme.Values.height + + anchors.left: parent.left + anchors.right: parent.right + + color: StudioTheme.Values.themeControlBackground + + SectionLabel { + id: label + anchors.verticalCenter: parent.verticalCenter + color: StudioTheme.Values.themeTextColor + x: 22 + //font.bold: true + font.pixelSize: StudioTheme.Values.myFontSize + // TODO font size? + } + + SectionLabel { + id: arrow + width: StudioTheme.Values.spinControlIconSizeMulti + height: StudioTheme.Values.spinControlIconSizeMulti + text: StudioTheme.Constants.upDownSquare2 + color: StudioTheme.Values.themeTextColor + renderType: Text.NativeRendering + anchors.left: parent.left + anchors.leftMargin: 4 + anchors.verticalCenter: parent.verticalCenter + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + font.family: StudioTheme.Constants.iconFont.family + Behavior on rotation { + NumberAnimation { + easing.type: Easing.OutCubic + duration: animationDuration + } + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + section.animationDuration = 120 + section.expanded = !section.expanded + if (!section.expanded) // TODO + section.forceActiveFocus() + } + } + } + + default property alias __content: row.children + + readonly property alias contentItem: row + + implicitHeight: Math.round(row.height + header.height) + + Row { + id: row + anchors.left: parent.left + anchors.leftMargin: leftPadding + anchors.right: parent.right + anchors.rightMargin: rightPadding + anchors.top: header.bottom + anchors.topMargin: topPadding + } + + Behavior on implicitHeight { + NumberAnimation { + easing.type: Easing.OutCubic + duration: animationDuration + } + } + + states: [ + State { + name: "Collapsed" + when: !section.expanded + PropertyChanges { + target: section + implicitHeight: header.height + } + PropertyChanges { + target: arrow + rotation: -90 + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml new file mode 100644 index 00000000000..73fec21ce05 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Label { + id: label + + //property alias tooltip: toolTipArea.tooltip + // workaround because PictureSpecifics.qml still use this + //property alias toolTip: toolTipArea.tooltip + + width: Math.max(Math.min(240, parent.width - 220), 80) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.myFontSize // TODO + elide: Text.ElideRight + + Layout.preferredWidth: width + Layout.minimumWidth: width + Layout.maximumWidth: width +/* + ToolTipArea { + id: toolTipArea + anchors.fill: parent + tooltip: label.text + } +*/ +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml new file mode 100644 index 00000000000..22054feebb4 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 + +GridLayout { + columns: 2 + columnSpacing: 12 + rowSpacing: 4 + width: parent.width - 16 +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml new file mode 100644 index 00000000000..955d73d6c72 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml @@ -0,0 +1,293 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Shapes 1.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Slider { + id: slider + + property int decimals: 0 + property bool labels: true + property bool tickMarks: false + property real tickMarkStepSize: 0.0 // StepSize bug QTBUG-76136 + property real tickMarkWidth: 1.0 + property real tickMarkHeight: 4.0 + readonly property int tickMarkCount: tickMarkStepSize + !== 0.0 ? (to - from) / tickMarkStepSize + 1 : 0 + readonly property real tickMarkSpacing: tickMarkCount + !== 0 ? (sliderTrack.width - tickMarkWidth + * tickMarkCount) / (tickMarkCount - 1) : 0.0 + + property string __activeColor: StudioTheme.Values.themeSliderActiveTrack + property string __inactiveColor: StudioTheme.Values.themeSliderInactiveTrack + + property bool hover: false // This property is used to indicate the global hover state + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitHandleWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitHandleHeight + topPadding + bottomPadding, + StudioTheme.Values.height) + padding: 0 + leftPadding: actionIndicator.width + - (actionIndicatorVisible ? StudioTheme.Values.border + - StudioTheme.Values.sliderPadding : 0) + + wheelEnabled: false + + ActionIndicator { + id: actionIndicator + myControl: slider + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + handle: Rectangle { + id: sliderHandle + x: slider.leftPadding + (slider.visualPosition * slider.availableWidth) + - sliderHandle.width / 2 + y: slider.topPadding + slider.availableHeight / 2 - sliderHandle.height / 2 + z: 20 + implicitWidth: StudioTheme.Values.sliderHandleWidth + implicitHeight: StudioTheme.Values.sliderHandleHeight + color: StudioTheme.Values.themeSliderHandle + + Shape { + id: sliderHandleLabelPointer + + property real __width: StudioTheme.Values.sliderPointerWidth + property real __height: StudioTheme.Values.sliderPointerHeight + property bool antiAlias: true + + layer.enabled: antiAlias + layer.smooth: antiAlias + layer.textureSize: Qt.size(width * 2, height * 2) + + implicitWidth: __width + implicitHeight: __height + + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: sliderHandleLabelBackground.bottom + + ShapePath { + id: sliderHandleLabelPointerPath + strokeColor: "transparent" + strokeWidth: 0 + fillColor: StudioTheme.Values.themeInteraction + + startX: 0 + startY: 0 + + PathLine { + x: sliderHandleLabelPointer.__width + y: 0 + } + PathLine { + x: sliderHandleLabelPointer.__width / 2 + y: sliderHandleLabelPointer.__height + } + } + } + + Rectangle { + id: sliderHandleLabelBackground + x: -(sliderHandleLabelBackground.width / 2) + (sliderHandle.width / 2) + width: makeEven( + sliderHandleLabel.width + StudioTheme.Values.inputHorizontalPadding) + height: sliderHandleLabel.height + anchors.bottom: parent.top + anchors.bottomMargin: StudioTheme.Values.sliderMargin + color: StudioTheme.Values.themeInteraction + + Text { + id: sliderHandleLabel + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + text: Number.parseFloat(slider.value).toFixed(slider.decimals) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderFontSize + } + } + } + + function makeEven(value) { + var v = Math.round(value) + return (v % 2 === 0) ? v : v + 1 + } + + background: Rectangle { + id: sliderTrack + x: slider.leftPadding + y: slider.topPadding + slider.availableHeight / 2 - height / 2 + width: slider.availableWidth + height: StudioTheme.Values.sliderTrackHeight + color: __inactiveColor + + Rectangle { + width: slider.visualPosition * parent.width + height: parent.height + color: __activeColor + } + } + + Item { + id: tickmarkBounds + x: sliderTrack.x + y: sliderTrack.y + + Text { + id: tickmarkFromLabel + x: 0 + y: StudioTheme.Values.sliderPadding + text: Number.parseFloat(slider.from).toFixed(slider.decimals) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderFontSize + visible: slider.labels + } + + Text { + id: tickmarkToLabel + x: slider.availableWidth - width + y: StudioTheme.Values.sliderPadding + text: Number.parseFloat(slider.to).toFixed(slider.decimals) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderFontSize + visible: slider.labels + } + + Row { + id: tickmarkRow + spacing: tickMarkSpacing + visible: slider.tickMarks + + Repeater { + id: tickmarkRepeater + model: tickMarkCount + delegate: Rectangle { + implicitWidth: tickMarkWidth + implicitHeight: StudioTheme.Values.sliderTrackHeight + color: x < (slider.visualPosition + * slider.availableWidth) ? __inactiveColor : __activeColor + } + } + } + } + + MouseArea { + id: mouseArea + x: actionIndicator.width + y: 0 + width: slider.width - actionIndicator.width + height: slider.height + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + // Sets the global hover + onContainsMouseChanged: slider.hover = containsMouse + onPressed: mouse.accepted = false + } + + states: [ + State { + name: "default" + when: slider.enabled && !slider.hover && !slider.activeFocus + PropertyChanges { + target: slider + wheelEnabled: false + } + }, + State { + name: "hovered" + when: slider.enabled && slider.hover && !slider.activeFocus + PropertyChanges { + target: slider + __activeColor: StudioTheme.Values.themeSliderActiveTrackHover + __inactiveColor: StudioTheme.Values.themeSliderInactiveTrackHover + } + PropertyChanges { + target: sliderHandle + color: StudioTheme.Values.themeSliderHandleHover + } + }, + State { + name: "focus" + when: slider.enabled && slider.activeFocus + PropertyChanges { + target: slider + wheelEnabled: true + __activeColor: StudioTheme.Values.themeSliderActiveTrackFocus + __inactiveColor: StudioTheme.Values.themeSliderInactiveTrackFocus + } + PropertyChanges { + target: sliderHandle + color: StudioTheme.Values.themeSliderHandleFocus + } + }, + State { + name: "disabled" + when: !slider.enabled + PropertyChanges { + target: tickmarkFromLabel + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: tickmarkToLabel + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: sliderHandleLabel + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: slider + __activeColor: StudioTheme.Values.themeControlBackgroundDisabled + __inactiveColor: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: sliderHandleLabelBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: sliderHandleLabelPointerPath + fillColor: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: sliderHandle + color: StudioTheme.Values.themeControlBackgroundDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml new file mode 100644 index 00000000000..27e8185da3a --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Popup { + id: sliderPopup + + property T.Control myControl + + dim: false + + closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent + + background: Rectangle { + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeInteraction + } + + contentItem: T.Slider { + id: slider + anchors.fill: parent + + bottomPadding: 0 + topPadding: 0 + rightPadding: 3 + leftPadding: 3 + + from: myControl.from + value: myControl.value + to: myControl.to + + focusPolicy: Qt.NoFocus + + handle: Rectangle { + x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width) + y: slider.topPadding + slider.availableHeight / 2 - height / 2 + width: StudioTheme.Values.sliderHandleWidth + height: StudioTheme.Values.sliderHandleHeight + radius: 0 + color: slider.pressed ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline + } + + background: Rectangle { + x: slider.leftPadding + y: slider.topPadding + slider.availableHeight / 2 - height / 2 + width: slider.availableWidth + height: StudioTheme.Values.sliderTrackHeight + radius: 0 + color: StudioTheme.Values.themeSliderInactiveTrack + + Rectangle { + width: slider.visualPosition * parent.width + height: parent.height + color: StudioTheme.Values.themeSliderActiveTrack + radius: 0 + } + } + + onMoved: { + myControl.value = value + myControl.valueModified() + } + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml new file mode 100644 index 00000000000..c7269b9d341 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml @@ -0,0 +1,343 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.SpinBox { + id: mySpinBox + +property alias textColor: spinBoxInput.color + + property alias actionIcon: actionIndicator.icon + + property int decimals: 0 + property int factor: Math.pow(10, decimals) + + property real defaultStepSize: 1 + property real minStepSize: 1 + property real maxStepSize: 10 + + property bool edit: false + property bool hover: false // This property is used to indicate the global hover state + property bool drag: false + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property bool spinBoxIndicatorVisible: true + property real __spinBoxIndicatorWidth: StudioTheme.Values.smallRectWidth - 2 + * StudioTheme.Values.border + property real __spinBoxIndicatorHeight: StudioTheme.Values.height / 2 + - StudioTheme.Values.border + + property alias sliderIndicatorVisible: sliderIndicator.visible + property real __sliderIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __sliderIndicatorHeight: StudioTheme.Values.height + + signal compressedValueModified + + // Use custom wheel handling due to bugs + property bool __wheelEnabled: false + wheelEnabled: false + + width: StudioTheme.Values.squareComponentWidth * 5 + height: StudioTheme.Values.height + + leftPadding: spinBoxIndicatorDown.x + spinBoxIndicatorDown.width + - (spinBoxIndicatorVisible ? 0 : StudioTheme.Values.border) + rightPadding: sliderIndicator.width - (sliderIndicatorVisible ? StudioTheme.Values.border : 0) + + font.pixelSize: StudioTheme.Values.myFontSize + editable: true + validator: mySpinBox.decimals ? doubleValidator : intValidator + + DoubleValidator { + id: doubleValidator + locale: mySpinBox.locale.name + notation: DoubleValidator.StandardNotation + decimals: mySpinBox.decimals + bottom: Math.min(mySpinBox.from, mySpinBox.to) / factor + top: Math.max(mySpinBox.from, mySpinBox.to) / factor + } + + IntValidator { + id: intValidator + locale: mySpinBox.locale.name + bottom: Math.min(mySpinBox.from, mySpinBox.to) + top: Math.max(mySpinBox.from, mySpinBox.to) + } + + Connections { + target: spinBoxInput + onActiveFocusChanged: mySpinBox.edit = spinBoxInput.activeFocus + } + + ActionIndicator { + id: actionIndicator + myControl: mySpinBox + + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + up.indicator: SpinBoxIndicator { + id: spinBoxIndicatorUp + myControl: mySpinBox + + visible: spinBoxIndicatorVisible + //hover: mySpinBox.up.hovered // TODO QTBUG-74688 + pressed: mySpinBox.up.pressed + iconFlip: -1 + + x: actionIndicator.width + (actionIndicator.visible ? 0 : StudioTheme.Values.border) + y: StudioTheme.Values.border + width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0 + height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0 + } + + down.indicator: SpinBoxIndicator { + id: spinBoxIndicatorDown + myControl: mySpinBox + + visible: spinBoxIndicatorVisible + //hover: mySpinBox.down.hovered // TODO QTBUG-74688 + pressed: mySpinBox.down.pressed + + x: actionIndicator.width + (actionIndicatorVisible ? 0 : StudioTheme.Values.border) + y: spinBoxIndicatorUp.y + spinBoxIndicatorUp.height + width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0 + height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0 + } + + contentItem: SpinBoxInput { + id: spinBoxInput + myControl: mySpinBox + } + + background: Rectangle { + id: spinBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + width: mySpinBox.width + height: mySpinBox.height + } + + CheckIndicator { + id: sliderIndicator + myControl: mySpinBox + myPopup: sliderPopup + + x: spinBoxInput.x + spinBoxInput.width - StudioTheme.Values.border + width: sliderIndicator.visible ? __sliderIndicatorWidth : 0 + height: sliderIndicator.visible ? __sliderIndicatorHeight : 0 + } + + SliderPopup { + id: sliderPopup + myControl: mySpinBox + + x: spinBoxInput.x + y: StudioTheme.Values.height - StudioTheme.Values.border + width: spinBoxInput.width + sliderIndicator.width - StudioTheme.Values.border + height: StudioTheme.Values.sliderHeight + + enter: Transition { + } + exit: Transition { + } + } + + textFromValue: function (value, locale) { + return Number(value / factor).toLocaleString(locale, 'f', + mySpinBox.decimals) + } + + valueFromText: function (text, locale) { + return Number.fromLocaleString(locale, text) * factor + } + + states: [ + State { + name: "default" + when: mySpinBox.enabled && !mySpinBox.hover + && !mySpinBox.activeFocus && !mySpinBox.drag + PropertyChanges { + target: mySpinBox + __wheelEnabled: false + } + PropertyChanges { + target: spinBoxInput + selectByMouse: false + } + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: spinBoxInput.activeFocus + PropertyChanges { + target: mySpinBox + __wheelEnabled: true + } + PropertyChanges { + target: spinBoxInput + selectByMouse: true + } + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "drag" + when: mySpinBox.drag + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !mySpinBox.enabled + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeControlOutlineDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + } + ] + + onActiveFocusChanged: { + if (mySpinBox.activeFocus) + // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason) + spinBoxInput.selectAll() + + if (sliderPopup.opened && !activeFocus) + sliderPopup.close() + } + + onFocusChanged: { + // FIX: This is a temporary fix for QTBUG-74239 + var currValue = mySpinBox.value + + if (!spinBoxInput.acceptableInput) + mySpinBox.value = clamp(valueFromText(spinBoxInput.text, + mySpinBox.locale), + mySpinBox.validator.bottom * factor, + mySpinBox.validator.top * factor) + else + mySpinBox.value = valueFromText(spinBoxInput.text, mySpinBox.locale) + + if (spinBoxInput.text !== mySpinBox.displayText) + spinBoxInput.text = mySpinBox.displayText + + if (mySpinBox.value !== currValue) + mySpinBox.valueModified() + } + + onDisplayTextChanged: { + spinBoxInput.text = mySpinBox.displayText + } + + Timer { + id: myTimer + repeat: false + running: false + interval: 100 + onTriggered: mySpinBox.compressedValueModified() + } + + onValueModified: myTimer.restart() + + Keys.onPressed: { + if (event.key === Qt.Key_Up || event.key === Qt.Key_Down) { + event.accepted = true + + mySpinBox.stepSize = defaultStepSize + + if (event.modifiers & Qt.ControlModifier) + mySpinBox.stepSize = minStepSize + + if (event.modifiers & Qt.ShiftModifier) + mySpinBox.stepSize = maxStepSize + + var val = mySpinBox.valueFromText(spinBoxInput.text, + mySpinBox.locale) + if (mySpinBox.value !== val) + mySpinBox.value = val + + var curValue = mySpinBox.value + + if (event.key === Qt.Key_Up) + mySpinBox.increase() + else + mySpinBox.decrease() + + if (curValue !== mySpinBox.value) + mySpinBox.valueModified() + } + + if (event.key === Qt.Key_Escape) + mySpinBox.focus = false + + // FIX: This is a temporary fix for QTBUG-74239 + if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { + var currValue = mySpinBox.value + + if (!spinBoxInput.spinBoxInput) + mySpinBox.value = clamp(valueFromText(spinBoxInput.text, + mySpinBox.locale), + mySpinBox.validator.bottom * factor, + mySpinBox.validator.top * factor) + else + mySpinBox.value = valueFromText(spinBoxInput.text, + mySpinBox.locale) + + if (spinBoxInput.text !== mySpinBox.displayText) + spinBoxInput.text = mySpinBox.displayText + + if (mySpinBox.value !== currValue) + mySpinBox.valueModified() + } + } + + function clamp(v, lo, hi) { + if (v < lo || v > hi) + return Math.min(Math.max(lo, v), hi) + + return v + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml new file mode 100644 index 00000000000..ab1e90f3860 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Rectangle { + id: spinBoxIndicator + + property T.Control myControl + + property bool hover: false + property bool pressed: false + + property alias iconFlip: spinBoxIndicatorIconScale.yScale + + color: StudioTheme.Values.themeControlBackground + border.width: 0 + + // This MouseArea is a workaround to avoid some hover state related bugs + // when using the actual signal 'up.hovered'. QTBUG-74688 + MouseArea { + id: spinBoxIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: spinBoxIndicator.hover = containsMouse + onPressed: mouse.accepted = false + } + + T.Label { + id: spinBoxIndicatorIcon + text: StudioTheme.Constants.upDownSquare2 + color: StudioTheme.Values.themeTextColor + renderType: Text.NativeRendering + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + font.family: StudioTheme.Constants.iconFont.family + anchors.fill: parent + transform: Scale { + id: spinBoxIndicatorIconScale + origin.x: 0 + origin.y: spinBoxIndicatorIcon.height / 2 + yScale: 1 + } + } + + states: [ + State { + name: "default" + when: myControl.enabled && !(spinBoxIndicator.hover + || myControl.hover) + && !spinBoxIndicator.pressed && !myControl.edit + && !myControl.drag + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackground + } + }, + State { + name: "hovered" + when: (spinBoxIndicator.hover || myControl.hover) + && !spinBoxIndicator.pressed && !myControl.edit + && !myControl.drag + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeHoverHighlight + } + }, + State { + name: "pressed" + when: spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "edit" + when: myControl.edit + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeFocusEdit + } + }, + State { + name: "drag" + when: myControl.drag + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeFocusDrag + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml new file mode 100644 index 00000000000..599f6fd5b5f --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +TextInput { + id: textInput + + property T.Control myControl + + property bool edit: false + property bool drag: false + + z: 2 + font: myControl.font + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + + horizontalAlignment: Qt.AlignRight + verticalAlignment: Qt.AlignVCenter + leftPadding: StudioTheme.Values.inputHorizontalPadding + rightPadding: StudioTheme.Values.inputHorizontalPadding + + readOnly: !myControl.editable + validator: myControl.validator + inputMethodHints: myControl.inputMethodHints + selectByMouse: false + activeFocusOnPress: false + clip: true + + // TextInput foucs needs to be set to activeFocus whenever it changes, + // otherwise TextInput will get activeFocus whenever the parent SpinBox gets + // activeFocus. This will lead to weird side effects. + onActiveFocusChanged: textInput.focus = activeFocus + + Rectangle { + id: textInputArea + + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + + x: 0 + y: 0 + z: -1 + width: textInput.width + height: StudioTheme.Values.height + } + + DragHandler { + id: dragHandler + target: null + acceptedDevices: PointerDevice.Mouse + enabled: true + + property int initialValue: 0 + + onActiveChanged: { + if (active) { + initialValue = myControl.value + mouseArea.cursorShape = Qt.ClosedHandCursor + myControl.drag = true + } else { + mouseArea.cursorShape = Qt.PointingHandCursor + myControl.drag = false + } + } + onTranslationChanged: { + var curValue = myControl.value + myControl.value = initialValue + translation.x + + if (curValue !== myControl.value) + myControl.valueModified() + } + } + + TapHandler { + id: tapHandler + acceptedDevices: PointerDevice.Mouse + enabled: true + onTapped: { + textInput.forceActiveFocus() + textInput.deselect() // QTBUG-75862 + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + // Sets the global hover + onContainsMouseChanged: myControl.hover = containsMouse + onPressed: mouse.accepted = false + onWheel: { + if (!myControl.__wheelEnabled) + return + + var val = myControl.valueFromText(textInput.text, myControl.locale) + if (myControl.value !== val) + myControl.value = val + + var curValue = myControl.value + myControl.value += wheel.angleDelta.y / 120 + + if (curValue !== myControl.value) + myControl.valueModified() + } + } + + states: [ + State { + name: "default" + when: myControl.enabled && !textInput.activeFocus + && !mouseArea.containsMouse && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: dragHandler + enabled: true + } + PropertyChanges { + target: tapHandler + enabled: true + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.PointingHandCursor + } + }, + State { + name: "hovered" + when: myControl.hover && !textInput.activeFocus && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: textInput.activeFocus + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + PropertyChanges { + target: dragHandler + enabled: false + } + PropertyChanges { + target: tapHandler + enabled: false + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.IBeamCursor + } + }, + State { + name: "drag" + when: myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusDrag + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml new file mode 100644 index 00000000000..7432d00bb0f --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +TextField { + id: myTextField + + property real relativePopupX: 0 // TODO Maybe call it leftPadding + property real popupWidth: myTextField.width + property string txtStorage + + property int temp: 0 + + T.Popup { + id: popup + x: relativePopupX + y: myTextField.height - StudioTheme.Values.border + width: popupWidth + height: scrollView.height + background: Rectangle { + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + border.width: StudioTheme.Values.border + } + + contentItem: ScrollView { + id: scrollView + padding: 0 + height: Math.min(textAreaPopup.contentHeight + scrollView.topPadding + + scrollView.bottomPadding, + StudioTheme.Values.maxTextAreaPopupHeight) + ScrollBar.horizontal.policy: ScrollBar.AlwaysOn + ScrollBar.vertical.policy: ScrollBar.AlwaysOn + + T.TextArea { + id: textAreaPopup + padding: 10 + width: textAreaPopup.contentWidth + textAreaPopup.leftPadding + + textAreaPopup.rightPadding + anchors.fill: parent + font.pixelSize: StudioTheme.Values.myFontSize + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + selectByMouse: true + persistentSelection: textAreaPopup.focus + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + cursorShape: Qt.IBeamCursor + acceptedButtons: Qt.RightButton + onPressed: contextMenu.popup(textAreaPopup) + } + } + } + + ContextMenu { + id: contextMenu + myTextEdit: textAreaPopup + } + + AbstractButton { + id: acceptButton + x: popup.width - acceptButton.width + y: popup.height - StudioTheme.Values.border + width: Math.round(StudioTheme.Values.smallRectWidth) + height: Math.round(StudioTheme.Values.smallRectWidth) + buttonIcon: StudioTheme.Constants.tickIcon + } + + AbstractButton { + id: discardButton + x: popup.width - acceptButton.width - discardButton.width + StudioTheme.Values.border + y: popup.height - StudioTheme.Values.border + width: Math.round(StudioTheme.Values.smallRectWidth) + height: Math.round(StudioTheme.Values.smallRectWidth) + buttonIcon: StudioTheme.Constants.closeCross + } + + Component.onCompleted: { + storeAndFormatTextInput(myTextField.text) + } + + onOpened: { + textAreaPopup.text = txtStorage + myTextField.clear() + } + + onClosed: { + storeAndFormatTextInput(textAreaPopup.text) + myTextField.forceActiveFocus() + textAreaPopup.deselect() + } + } + + function storeAndFormatTextInput(inputText) { + txtStorage = inputText + var pos = txtStorage.search(/\n/g) + var sliceAt = Math.min(pos, 15) + myTextField.text = txtStorage.slice(0, sliceAt).padEnd(sliceAt + 3, '.') + } + + Keys.onPressed: { + if (event.key === Qt.Key_Escape) { + if (popup.opened) + popup.close() + else + myTextField.focus = false + } + + if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) + && !popup.opened) { + popup.open() + textAreaPopup.forceActiveFocus() + } + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml new file mode 100644 index 00000000000..df3677f410f --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.TextField { + id: myTextField + + property alias actionIcon: actionIndicator.icon + + property bool edit: false + property bool hover: false // This property is used to indicate the global hover state + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property alias translationIndicatorVisible: translationIndicator.visible + property real __translationIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __translationIndicatorHeight: StudioTheme.Values.height + + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignVCenter + + font.pixelSize: StudioTheme.Values.myFontSize + + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + + readOnly: false + selectByMouse: true + persistentSelection: focus // QTBUG-73807 + clip: true + + height: StudioTheme.Values.height + implicitHeight: StudioTheme.Values.height + width: StudioTheme.Values.height * 5 + + leftPadding: StudioTheme.Values.inputHorizontalPadding + actionIndicator.width + - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + rightPadding: StudioTheme.Values.inputHorizontalPadding + translationIndicator.width + - (translationIndicatorVisible ? StudioTheme.Values.border : 0) + + onActiveFocusChanged: myTextField.edit = myTextField.activeFocus + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + cursorShape: Qt.PointingHandCursor + onContainsMouseChanged: myTextField.hover = containsMouse // Sets the global hover + onPressed: { + if (mouse.button === Qt.RightButton) + contextMenu.popup(myTextField) + + mouse.accepted = false + } + } + + onPersistentSelectionChanged: { + if (!persistentSelection) + myTextField.deselect() + } + + ContextMenu { + id: contextMenu + myTextEdit: myTextField + } + + ActionIndicator { + id: actionIndicator + myControl: myTextField + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + background: Rectangle { + id: textFieldBackground + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + anchors.fill: parent + } + + TranslationIndicator { + id: translationIndicator + myControl: myTextField + x: myTextField.width - translationIndicator.width + width: translationIndicator.visible ? __translationIndicatorWidth : 0 + height: translationIndicator.visible ? __translationIndicatorHeight : 0 + } + + states: [ + State { + name: "default" + when: myTextField.enabled && !myTextField.hover + && !myTextField.activeFocus + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.PointingHandCursor + } + }, + State { + name: "hovered" + when: myTextField.hover && !myTextField.activeFocus + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: myTextField.activeFocus + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.IBeamCursor + } + }, + State { + name: "disabled" + when: !myTextField.enabled + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + } + ] + + Keys.onPressed: { + if (event.key === Qt.Key_Escape) + myTextField.focus = false + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml new file mode 100644 index 00000000000..17c29a82b6b --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Item { + id: translationIndicator + + property Item myControl + + property bool hover: false + property bool pressed: false + + state: "default" + + Rectangle { + id: translationIndicatorBackground + color: StudioTheme.Values.themeColumnBackground // TODO create extra variable, this one is used + border.color: StudioTheme.Values.themeTranslationIndicatorBorder + + anchors.centerIn: parent + + width: matchParity(translationIndicator.height, + StudioTheme.Values.smallRectWidth) + height: matchParity(translationIndicator.height, + StudioTheme.Values.smallRectWidth) + + function matchParity(root, value) { + // TODO maybe not necessary + var v = Math.round(value) + + if (root % 2 == 0) + // even + return (v % 2 == 0) ? v : v - 1 + else + // odd + return (v % 2 == 0) ? v - 1 : v + } + + MouseArea { + id: translationIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: translationIndicator.hover = containsMouse + onPressed: mouse.accepted = true // TODO + } + } + + T.Label { + id: translationIndicatorIcon + text: "tr" + color: StudioTheme.Values.themeTextColor + font.family: StudioTheme.Constants.font.family + font.pixelSize: StudioTheme.Values.myIconFontSize + font.italic: true + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors.fill: parent + } + + states: [ + State { + name: "default" + when: myControl.enabled && !translationIndicator.hover + && !translationIndicator.pressed && !myControl.hover + && !myControl.edit && !myControl.drag + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeColumnBackground + border.color: StudioTheme.Values.themeTranslationIndicatorBorder + } + }, + State { + name: "hovered" + when: translationIndicator.hover && !translationIndicator.pressed + && !myControl.edit && !myControl.drag && !myControl.drag + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeFocusDrag // TODO + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: translationIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir new file mode 100644 index 00000000000..02acf99dff5 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir @@ -0,0 +1,29 @@ +AbstractButton 1.0 AbstractButton.qml +ActionIndicator 1.0 ActionIndicator.qml +Button 1.0 Button.qml +ButtonGroup 1.0 ButtonGroup.qml +ButtonRow 1.0 ButtonRow.qml +CheckBox 1.0 CheckBox.qml +CheckIndicator 1.0 CheckIndicator.qml +ComboBox 1.0 ComboBox.qml +ComboBoxInput 1.0 ComboBoxInput.qml +ContextMenu 1.0 ContextMenu.qml +ExpandingSpacer 1.0 ExpandingSpacer.qml +ItemDelegate 1.0 ItemDelegate.qml +Menu 1.0 Menu.qml +MenuItem 1.0 MenuItem.qml +MenuSeparator 1.0 MenuSeparator.qml +ScrollBar 1.0 ScrollBar.qml +ScrollView 1.0 ScrollView.qml +SecondColumnLayout 1.0 SecondColumnLayout.qml +Section 1.0 Section.qml +SectionLabel 1.0 SectionLabel.qml +SectionLayout 1.0 SectionLayout.qml +Slider 1.0 Slider.qml +SliderPopup 1.0 SliderPopup.qml +SpinBox 1.0 SpinBox.qml +SpinBoxIndicator 1.0 SpinBoxIndicator.qml +SpinBoxInput 1.0 SpinBoxInput.qml +TextArea 1.0 TextArea.qml +TextField 1.0 TextField.qml +TranslationIndicator 1.0 TranslationIndicator.qml diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml new file mode 100644 index 00000000000..b3b4c58041a --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +pragma Singleton +import QtQuick 2.10 + +QtObject { + readonly property int width: 1920 + readonly property int height: 1080 + readonly property FontLoader mySystemFont: FontLoader { + name: "Arial" + } + readonly property FontLoader controlIcons: FontLoader { + source: "icons.ttf" + } + + readonly property string actionIcon: "\u0021" + readonly property string anchorBottom: "\u0022" + readonly property string anchorFill: "\u0023" + readonly property string anchorLeft: "\u0024" + readonly property string anchorRight: "\u0025" + readonly property string anchorTop: "\u0026" + readonly property string centerHorizontal: "\u0027" + readonly property string centerVertical: "\u0028" + readonly property string closeCross: "\u0029" + readonly property string fontStyleBold: "\u002A" + readonly property string fontStyleItalic: "\u002B" + readonly property string fontStyleStrikethrough: "\u002C" + readonly property string fontStyleUnderline: "\u002D" + readonly property string textAlignCenter: "\u002E" + readonly property string textAlignLeft: "\u002F" + readonly property string textAlignRight: "\u0030" + readonly property string tickIcon: "\u0031" + readonly property string upDownIcon: "\u0032" + readonly property string upDownSquare2: "\u0033" + + readonly property font iconFont: Qt.font({ + "family": controlIcons.name, + "pixelSize": 12 + }) + + readonly property font font: Qt.font({ + "family": mySystemFont.name, + "pointSize": Qt.application.font.pixelSize + }) + + readonly property font largeFont: Qt.font({ + "family": mySystemFont.name, + "pointSize": Qt.application.font.pixelSize * 1.6 + }) + + readonly property color backgroundColor: "#c2c2c2" +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml new file mode 100644 index 00000000000..2055572e448 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +pragma Singleton +import QtQuick 2.12 + +QtObject { + id: values + + property real baseHeight: 20 + property real baseFont: 12 + property real baseIconFont: 10 + + property real scaleFactor: 1 + + property real height: Math.round(values.baseHeight * values.scaleFactor) + property real myFontSize: Math.round(values.baseFont * values.scaleFactor) + property real myIconFontSize: Math.round(values.baseIconFont * values.scaleFactor) + + property real squareComponentWidth: values.height + property real smallRectWidth: values.height / 2 * 1.5 + + property real inputWidth: values.height * 4 + + property real sliderHeight: values.height / 2 * 1.5 // TODO:Have a look at -> sliderAreaHeight: Data.Values.height/2*1.5 + + property real sliderControlSize: 12 + property real sliderControlSizeMulti: sliderControlSize * scaleFactor + + property real spinControlIconSize: 8 + property real spinControlIconSizeMulti: spinControlIconSize * scaleFactor + + property real sliderTrackHeight: values.height / 4 + property real sliderHandleHeight: values.sliderTrackHeight * 2 + property real sliderHandleWidth: values.sliderTrackHeight + property real sliderFontSize: Math.round(8 * values.scaleFactor) + property real sliderPadding: Math.round(6 * values.scaleFactor) + property real sliderMargin: Math.round(3 * values.scaleFactor) + + property real sliderPointerWidth: Math.round(7 * values.scaleFactor) + property real sliderPointerHeight: Math.round(2 * values.scaleFactor) + + property real checkBoxSpacing: 6 // TODO Does look strange with scale factor applied + + property real columnWidth: 225 + (175 * (values.scaleFactor * 2)) + + property real marginTopBottom: 4 + property real border: 1 + + property real maxComboBoxPopupHeight: 300 + property real maxTextAreaPopupHeight: 150 + + property real contextMenuLabelSpacing: 30 + property real contextMenuHorizontalPadding: 6 + + property real inputHorizontalPadding: Math.round(4 * values.scaleFactor) + + // Theme Colors + + // Dark Theme Defaults + property string themeControlBackground: "#242424" + property string themeControlOutline: "#404040" + property string themeTextColor: "#ffffff" + + property string themePanelBackground: "#2a2a2a" + property string themeHoverHighlight: "#313131" + property string themeColumnBackground: "#363636" + property string themeFocusEdit: "#606060" + property string themeFocusDrag: "#565656" + + property string themeControlBackgroundPressed: "#606060" + property string themeControlBackgroundChecked: "#565656" + + property string themeInteraction: "#029de0" + + property string themeSliderActiveTrack: "#606060" + property string themeSliderInactiveTrack: "#404040" + property string themeSliderHandle: "#505050" + + property string themeSliderActiveTrackHover: "#7f7f7f" + property string themeSliderInactiveTrackHover: "#505050" + property string themeSliderHandleHover: "#606060" + + property string themeSliderActiveTrackFocus: "#aaaaaa" + property string themeSliderInactiveTrackFocus: "#606060" + property string themeSliderHandleFocus: values.themeInteraction + + // NEW NEW NEW NEW NEW + property string themeControlBackgroundDisabled: "#363636" + property string themeControlOutlineDisabled: "#404040" + property string themeTextColorDisabled: "#606060" + + property string themeTextSelectionColor: "#029de0" + property string themeTextSelectedTextColor: "#ffffff" + + property string themeScrollBarTrack: "#404040" + property string themeScrollBarHandle: "#505050" + + property string themeControlBackgroundInteraction: "#404040" // TODO Name. Right now themeFocusEdit is used for all 'edit' states. Is that correct? Different color! + + property string themeTranslationIndicatorBorder: "#7f7f7f" +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d2bd44ad4ac760c93f8abf081d30aa11c7924633 GIT binary patch literal 4300 zcmZQzWME+6WoTevW(aU|3-RshkD0*0Ah3affkDPUSl=itE^!$H17idO14BY`ZeoE= zfQcvr1LGS821cjkvJwRbMW#vy24({W1_qY&#NvYg{~4GW7z9=@FfeeW=TxR$kKV9| zfq^-Nfq^q3BQ-HaqWD1v0|Uby1_lPRjEvMot`GlbGB7ZTFfcHvWaO4q@GfLBW?*34 z!N9;^l9QjDDD5ICz`($4!oa|wmz!8oz!1mK$iTp8!N9K-?)y$G0 z_cAbnL>U-B`j{pE+c89e)c?t2uLg-gN?0batYH8}wju)qqZZRF24)6!2EC1p4Ei>k*jX6f z8f|1_y<@Y9nTg@85yM7ikT5GqcoRDt;~$$%j39AiK}A7zV?kv_M$Q+~sjKa){%)&xOW+rM%Y$8nWe*OB#^Xu3CvXGFn5T;xIg8v0G zu4P>N_ecmx1QZp_4Cep6nHMv2GYBv!Fz7Has46O{nF^Yi87mrzi3*DFF)}K#i3*B{ z87mr@nF^YyDGMtqsX?Sg*q9am&Q#FTQ(#J0)DuZyPg7521wc88KNqpOiyKm|IQGWmKJ8p5SIB9&&9*V#lr=13mXIXe`n^q%%TkZ z4Dt-x4CV~Z4E_uZtf($xLw67Z#KB(LYN-)^LUE zDKe#l6#Sj3s0R-3nV>jfN*9*-^MVr;DO_A^f3|?iEM^7@+`)7h)g6#Hm6jG}WB^Ah zN$!B9LrB~c3=eap7)4HodeHE|NQGN*2g)8;tbpQ$>;GKldrZ3-Ky{Fjm278 zx+f$2w?SBj>E2%@8DXXdVHrjnE*`Fb7eLX)Xu!q8#b^Lx{=2|v0K&pDGJkVHOko)r zP#$4sNd51`+{`S7P>}<+P z`e0IBkI|k{U60X@QJ&GN!Y!crE6r z&nV8Qc3a$0TwLt-BXKct2k}R*#2xe*#b13CXVi5RXJBSn_dk$1hM5&yyU8*z2!qNi z5jJ)?Mo~~yF)E818=0CggD5jolXZ+GQzq+M+Sx3c^sk*UYt@>Zj13#?Y?xWgTm0ix zq*5Zg+L-wt6&C)hd2Zxf1S+c;h5p+yZDQsJm(>ic!p7W;=Em%dLW}n;=GNV>bBO8a zUu$OmLy$U|?|(bQ&uA_Na)r8@IyAMasjHcqC>qH#va2a8 ziHeAeiHnId@8T5}=6xpn?{`>}Hs^xS_3C1V|JXof3ZtUDh!rDyM7ajX64#BInl-L^ zj8?)@LOMRbMcBMWmpI7^@d-%@^9$(Z-4SB-6>0O5k&zYvRqzZ<45I)2m@hLkGjKD= zLdsB3q5wILQN$Qjlp70*u(7i#sF?~HGjIOW1hS90j#o(NZ^_=oLu|h+vDVH2u8;mQYd9)64r;0b(Q5v$ zH}fWLZsv{5+}wYnn3r*L|M3TL89@3(7_^zMFe#zxV?N3K&+MNWH#g%|5M~nR{%6K` ziks)3Hi!!<6dCv!*1_7R3@GzP~*{lo# zjA>9d8v_sHL{O`k1=K!w0JUiu7+E+O7#SoOlA+>E415e-P&P9|0K+0En}tDwQ5MQ( zWl&&rfwI{cBpAyXoEh>N3K%LGiWo8((it)sN*ELvG#HW@G#L~aj2H|U3>hpLbilqS zV#sI6XUJwyU~pytvGW)*8S)qyobwARi!#$QN)$AbH5H5u3@vpOoQm@EvlX0+^7AtD z7#K1ck{R+D@)+E}WC?>FLkU9(LmC4^W^#U>TYg@NUP(zB149r)DnmL$DMJoJB0~`a zLr`jZX-;Ah16&(Odl5rALn_#1dJF~(3Jg{Z3OJ32$Qm(NGUzgxFzCX4!vM0$)Fw_0|UeVtqexs6bVjVNQ4+zl!=jvk(rT&k(H5+k)4r)k&}^& zk(-f+k(ZH=k)Kh3QIJuHQJ7JLFEP0!Ge6HWIX_RYxGY^DF)ukIzsM=Sq$EEVB)|s| zaLdfeLE`$Prj>xW{1Dk7P*j8Xybyj!egTLllAM}Xl3L`EUzAyupI4FyHbDp?7?xU8 zl9>z<;!DoSFHUtX$}cVkX%kG#&npQosmw`r%Fjswi3r0*JWCRDGLu1KQgE^0lA_G) z)RK&%{L=Ickdzo)Dl{)8wJ0YuFBK##T#{N*;+T_}p63j97f4JHE(Y_G5L^WAE1r_f x*8R?)*g@{g0|2ffPJjRa literal 0 HcmV?d00001 diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir new file mode 100644 index 00000000000..b768fe63a2b --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir @@ -0,0 +1,2 @@ +singleton Values 1.0 Values.qml +singleton Constants 1.0 Constants.qml From a18d3d1f9a3f14dedb140b1626f553c974e6190f Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Wed, 5 Jun 2019 15:58:01 +0200 Subject: [PATCH 21/28] QmlDesigner: Add ExtendedFunctionLogic Also a couple of smaller fixes on MenuItem and some changes in ActionIndicator alias properties. Change-Id: Ib8e30074f0c2934925ab3958afa106a904a0ecdd Reviewed-by: Thomas Hartmann --- .../HelperWidgets/ExtendedFunctionLogic.qml | 207 ++++++++++++++++++ .../imports/HelperWidgets/SpinBox.qml | 73 +++--- .../StudioControls/ActionIndicator.qml | 3 + .../imports/StudioControls/MenuItem.qml | 4 +- .../imports/StudioControls/SpinBox.qml | 6 +- 5 files changed, 251 insertions(+), 42 deletions(-) create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml new file mode 100644 index 00000000000..59b7d58bc0a --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.1 +import StudioControls 1.0 as StudioControls +import StudioTheme 1.0 as StudioTheme + + +Item { + id: extendedFunctionButton + + property variant backendValue + property bool isBoundBackend: backendValue.isBound + property string backendExpression: backendValue.expression + + property string glyph: StudioTheme.Constants.actionIcon + property string color: StudioTheme.Constants.themeTextColor + property alias menuLoader: menuLoader + + signal reseted + + function show() { + menuLoader.show() + } + + function setIcon() { + extendedFunctionButton.color = StudioTheme.Values.themeTextColor + if (backendValue === null) { + extendedFunctionButton.glyph = StudioTheme.Constants.actionIcon + } else if (backendValue.isBound) { + if (backendValue.isTranslated) { + // translations are a special case + extendedFunctionButton.glyph = StudioTheme.Constants.actionIcon + } else { + extendedFunctionButton.glyph = StudioTheme.Constants.closeCross + extendedFunctionButton.color = StudioTheme.Values.themeInteraction + } + } else { + if (backendValue.complexNode !== null + && backendValue.complexNode.exists) { + + } else { + extendedFunctionButton.glyph = StudioTheme.Constants.actionIcon + } + } + } + + onBackendValueChanged: { + setIcon() + } + + onIsBoundBackendChanged: { + setIcon() + } + + onBackendExpressionChanged: { + setIcon() + } + + Loader { + id: menuLoader + + active: false + + function show() { + active = true + item.popup() + } + + sourceComponent: Component { + StudioControls.Menu { + id: menu + + onAboutToShow: { + exportMenuItem.checked = backendValue.hasPropertyAlias() + exportMenuItem.enabled = !backendValue.isAttachedProperty() + } + + StudioControls.MenuItem { + text: qsTr("Reset") + onTriggered: { + transaction.start() + backendValue.resetValue() + backendValue.resetValue() + transaction.end() + extendedFunctionButton.reseted() + } + } + StudioControls.MenuItem { + text: qsTr("Set Binding") + onTriggered: expressionDialogLoader.show() + } + StudioControls.MenuItem { + id: exportMenuItem + text: qsTr("Export Property as Alias") + onTriggered: { + if (checked) + backendValue.exportPopertyAsAlias() + else + backendValue.removeAliasExport() + } + checkable: true + } + + StudioControls.MenuItem { + text: qsTr("Insert Keyframe") + enabled: hasActiveTimeline + onTriggered: insertKeyframe(backendValue.name) + } + } + } + } + + Loader { + id: expressionDialogLoader + parent: itemPane + anchors.fill: parent + + visible: false + active: visible + + function show() { + expressionDialogLoader.visible = true + } + + sourceComponent: Component { + Item { + id: expressionDialog + anchors.fill: parent + + Component.onCompleted: { + textField.text = backendValue.expression + textField.forceActiveFocus() + } + + Rectangle { + anchors.fill: parent + color: Theme.qmlDesignerBackgroundColorDarker() + opacity: 0.6 + } + + MouseArea { + anchors.fill: parent + onDoubleClicked: expressionDialog.visible = false + } + + Rectangle { + x: 4 + Component.onCompleted: { + var pos = itemPane.mapFromItem( + extendedFunctionButton.parent, 0, 0) + y = pos.y + 2 + } + + width: parent.width - 8 + height: 260 + + radius: 2 + color: Theme.qmlDesignerBackgroundColorDarkAlternate() + border.color: Theme.qmlDesignerBorderColor() + + Label { + x: 8 + y: 6 + font.bold: true + text: qsTr("Binding Editor") + } + ExpressionTextField { + id: textField + onRejected: expressionDialogLoader.visible = false + onAccepted: { + backendValue.expression = textField.text.trim() + expressionDialogLoader.visible = false + } + anchors.fill: parent + anchors.leftMargin: 8 + anchors.rightMargin: 8 + anchors.topMargin: 24 + anchors.bottomMargin: 32 + } + } + } + } + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml index 7fcc2956d55..ed35be506f3 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml @@ -33,71 +33,68 @@ Item { property alias decimals: spinBox.decimals property alias hasSlider: spinBox.hasSlider - property real minimumValue - property real maximumValue - property real stepSize + property real minimumValue: 0.0 + property real maximumValue: 99 + property real stepSize: 1.0 property alias backendValue: spinBox.backendValue - Component.onCompleted: { - // TODO minimumValue/maximumValue convertion... - // TODO step size convertion... - } - width: 100 implicitHeight: spinBox.height + property bool __initialized: false + + Component.onCompleted: { + wrapper.__initialized = true + + convert("stepSize", stepSize) + convert("from", minimumValue) + convert("to", maximumValue) + } + + onStepSizeChanged: convert("stepSize", stepSize) + onMinimumValueChanged: convert("from", minimumValue) + onMaximumValueChanged: convert("to", maximumValue) + + function convert(target, value) { + if (!wrapper.__initialized) + return + spinBox[target] = Math.round(value * spinBox.factor) + } + StudioControls.SpinBox { id: spinBox - property real properValue: value / factor + property real realValue: value / factor + property variant backendValue + property bool hasSlider: false from: minimumValue * factor to: maximumValue * factor - width: wrapper.width - //height: wrapper.height -// property color textColor: colorLogic.textColor - property variant backendValue; - - //implicitWidth: 74 -/* - ExtendedFunctionButton { - x: 4 - anchors.verticalCenter: parent.verticalCenter + ExtendedFunctionLogic { + id: extFuncLogic backendValue: spinBox.backendValue - visible: spinBox.enabled } -*/ - /* - icon: extend.glyph - Extn2 { - glyph: - } - */ - textColor: colorLogic.textColor + actionIndicator.icon.color: extFuncLogic.color + actionIndicator.icon.text: extFuncLogic.glyph + actionIndicator.onClicked: extFuncLogic.show() ColorLogic { id: colorLogic backendValue: spinBox.backendValue onValueFromBackendChanged: { - spinBox.value = valueFromBackend * factor; + spinBox.value = valueFromBackend * spinBox.factor; } } - property bool hasSlider: false - - //height: hasSlider ? 32 : implicitHeight + textColor: colorLogic.textColor onCompressedValueModified: { - if (backendValue.value !== properValue) - backendValue.value = properValue; + if (backendValue.value !== realValue) + backendValue.value = realValue; } - /* - style: CustomSpinBoxStyle { - } - */ } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml index 4bc550e252e..e263f9337aa 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml @@ -44,6 +44,8 @@ Rectangle { implicitWidth: StudioTheme.Values.height implicitHeight: StudioTheme.Values.height + signal clicked + T.Label { id: actionIndicatorIcon anchors.fill: parent @@ -60,6 +62,7 @@ Rectangle { anchors.fill: parent hoverEnabled: true onContainsMouseChanged: actionIndicator.hover = containsMouse + onClicked: actionIndicator.clicked() } states: [ diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml index b9a36f11352..ff3c1396794 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml @@ -26,6 +26,7 @@ import QtQuick 2.12 import QtQuick.Templates 2.12 as T import StudioTheme 1.0 as StudioTheme +import QtQuick.Controls 2.12 T.MenuItem { id: control @@ -42,6 +43,7 @@ T.MenuItem { padding: 0 spacing: 0 horizontalPadding: StudioTheme.Values.contextMenuHorizontalPadding + action: Action {} contentItem: Item { id: menuItem @@ -67,7 +69,7 @@ T.MenuItem { Shortcut { id: shortcut - property int shortcutWorkaround: control.action.shortcut + property int shortcutWorkaround: control.action.shortcut ? control.action.shortcut : 0 sequence: shortcutWorkaround } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml index c7269b9d341..ef98c0f9ffd 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml @@ -30,9 +30,8 @@ import StudioTheme 1.0 as StudioTheme T.SpinBox { id: mySpinBox -property alias textColor: spinBoxInput.color - - property alias actionIcon: actionIndicator.icon + property alias textColor: spinBoxInput.color + property alias actionIndicator: actionIndicator property int decimals: 0 property int factor: Math.pow(10, decimals) @@ -158,6 +157,7 @@ property alias textColor: spinBoxInput.color x: spinBoxInput.x + spinBoxInput.width - StudioTheme.Values.border width: sliderIndicator.visible ? __sliderIndicatorWidth : 0 height: sliderIndicator.visible ? __sliderIndicatorHeight : 0 + visible: false // reasonable default } SliderPopup { From 029884c80eefa0dc8fc0c4d67c4dff34051afd5b Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 5 Jun 2019 16:28:52 +0200 Subject: [PATCH 22/28] QmlDesigner: Use studio controls for property editor * CheckBox * ComboBox * LineEdit Adjusting some details in property editor. Change-Id: I8f9d6ef87c187f5a3be7c5fb368a1813e6dba92c Reviewed-by: Thomas Hartmann --- .../QtQuick/RectangleSpecifics.qml | 4 +- .../imports/HelperWidgets/CheckBox.qml | 23 ++- .../imports/HelperWidgets/ComboBox.qml | 25 ++-- .../HelperWidgets/ExtendedFunctionLogic.qml | 2 +- .../imports/HelperWidgets/Label.qml | 3 + .../imports/HelperWidgets/LineEdit.qml | 131 +++++------------- .../imports/HelperWidgets/Section.qml | 2 + .../imports/HelperWidgets/SpinBox.qml | 4 +- .../imports/HelperWidgets/TabView.qml | 2 + .../imports/StudioControls/CheckBox.qml | 3 +- .../imports/StudioControls/ComboBox.qml | 4 +- .../imports/StudioControls/TextField.qml | 4 +- .../StudioControls/TranslationIndicator.qml | 18 +++ 13 files changed, 97 insertions(+), 128 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml index 143f950b380..65704972975 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml @@ -73,7 +73,7 @@ Column { SpinBox { backendValue: backendValues.border_width hasSlider: true - Layout.preferredWidth: 80 + Layout.preferredWidth: 120 } ExpandingSpacer { @@ -86,7 +86,7 @@ Column { SpinBox { backendValue: backendValues.radius hasSlider: true - Layout.preferredWidth: 80 + Layout.preferredWidth: 120 minimumValue: 0 maximumValue: Math.min(backendValues.height.value, backendValues.width.value) / 2 } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml index d69490d53ad..48d8ffaa53d 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml @@ -24,26 +24,25 @@ ****************************************************************************/ import QtQuick 2.1 -import QtQuick.Controls 1.1 as Controls +import StudioControls 1.0 as Controls import QtQuick.Controls.Styles 1.1 Controls.CheckBox { - id: checkBox - property color textColor: colorLogic.textColor - - opacity: enabled ? 1 : 0.5 - property variant backendValue + property string tooltip - ExtendedFunctionButton { - x: 22 - anchors.verticalCenter: parent.verticalCenter + ExtendedFunctionLogic { + id: extFuncLogic backendValue: checkBox.backendValue - visible: checkBox.enabled } + actionIndicator.icon.color: extFuncLogic.color + actionIndicator.icon.text: extFuncLogic.glyph + actionIndicator.onClicked: extFuncLogic.show() + + labelColor: colorLogic.textColor ColorLogic { id: colorLogic backendValue: checkBox.backendValue @@ -58,8 +57,4 @@ Controls.CheckBox { backendValue.value = checkBox.checked; } - style: CustomCheckBoxStyle { - } - - } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml index 08f76b4f252..18f30dce1c3 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml @@ -24,7 +24,7 @@ ****************************************************************************/ import QtQuick 2.1 -import QtQuick.Controls 1.1 as Controls +import StudioControls 1.0 as Controls import QtQuick.Controls.Styles 1.1 Controls.ComboBox { @@ -32,7 +32,7 @@ Controls.ComboBox { property variant backendValue - property color textColor: colorLogic.textColor + labelColor: colorLogic.textColor property string scope: "Qt" property bool useInteger: false @@ -45,6 +45,15 @@ Controls.ComboBox { property bool block: false + ExtendedFunctionLogic { + id: extFuncLogic + backendValue: comboBox.backendValue + } + + actionIndicator.icon.color: extFuncLogic.color + actionIndicator.icon.text: extFuncLogic.glyph + actionIndicator.onClicked: extFuncLogic.show() + ColorLogic { id: colorLogic backendValue: comboBox.backendValue @@ -84,7 +93,7 @@ Controls.ComboBox { } } - onCurrentTextChanged: { + onActivated: { if (!__isCompleted) return; @@ -106,14 +115,4 @@ Controls.ComboBox { __isCompleted = true; } - style: CustomComboBoxStyle { - textColor: comboBox.textColor - } - - ExtendedFunctionButton { - x: 2 - anchors.verticalCenter: parent.verticalCenter - backendValue: comboBox.backendValue - visible: comboBox.enabled - } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml index 59b7d58bc0a..f6fdf3d2cbc 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml @@ -26,7 +26,7 @@ import QtQuick 2.1 import StudioControls 1.0 as StudioControls import StudioTheme 1.0 as StudioTheme - +import QtQuickDesignerTheme 1.0 Item { id: extendedFunctionButton diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml index 8498f838ac6..23901e8dc92 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml @@ -28,6 +28,7 @@ import QtQuick.Controls 1.1 as Controls import QtQuick.Layouts 1.0 import QtQuick.Controls.Private 1.0 import QtQuickDesignerTheme 1.0 +import StudioTheme 1.0 as StudioTheme Controls.Label { id: label @@ -40,6 +41,8 @@ Controls.Label { color: Theme.color(Theme.PanelTextColorLight) elide: Text.ElideRight + font.pixelSize: StudioTheme.Values.myFontSize + Layout.preferredWidth: width Layout.minimumWidth: width Layout.maximumWidth: width diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml index c4ff04b7f12..18b25924b3f 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml @@ -24,24 +24,20 @@ ****************************************************************************/ import QtQuick 2.2 -import QtQuick.Controls 1.1 as Controls +import StudioControls 1.0 as Controls import QtQuick.Controls.Styles 1.0 import QtQuickDesignerTheme 1.0 Controls.TextField { - - Controls.Action { - //Workaround to avoid that "Delete" deletes the item. - shortcut: "Delete" - } - id: lineEdit + property variant backendValue property color borderColor: "#222" property color highlightColor: "orange" - property color textColor: colorLogic.textColor + color: colorLogic.textColor property bool showTranslateCheckBox: true + translationIndicatorVisible: showTranslateCheckBox property bool writeValueManually: false @@ -58,19 +54,21 @@ Controls.TextField { if (translateFunction() === "qsTranslate") { backendValue.expression = translateFunction() + "(\"" + backendValue.getTranslationContext() - + "\", " + "\"" + trCheckbox.escapeString(text) + "\")" + + "\", " + "\"" + escapeString(text) + "\")" } else { - backendValue.expression = translateFunction() + "(\"" + trCheckbox.escapeString(text) + "\")" + backendValue.expression = translateFunction() + "(\"" + escapeString(text) + "\")" } } - ExtendedFunctionButton { - x: 4 - anchors.verticalCenter: parent.verticalCenter + ExtendedFunctionLogic { + id: extFuncLogic backendValue: lineEdit.backendValue - visible: lineEdit.enabled && showExtendedFunctionButton } + actionIndicator.icon.color: extFuncLogic.color + actionIndicator.icon.text: extFuncLogic.glyph + actionIndicator.onClicked: extFuncLogic.show() + ColorLogic { id: colorLogic backendValue: lineEdit.backendValue @@ -102,7 +100,6 @@ Controls.TextField { } onEditingFinished: { - if (writeValueManually) return @@ -118,87 +115,35 @@ Controls.TextField { __dirty = false } - style: TextFieldStyle { + property bool isTranslated: colorLogic.backendValue.isTranslated - selectionColor: Theme.color(Theme.PanelTextColorLight) - selectedTextColor: Theme.color(Theme.PanelTextColorMid) - textColor: lineEdit.textColor - placeholderTextColor: Theme.color(Theme.PanelTextColorMid) - - padding.top: 2 - padding.bottom: 2 - padding.left: 18 - padding.right: lineEdit.showTranslateCheckBox ? 16 : 1 - background: Rectangle { - implicitWidth: 100 - implicitHeight: 24 - color: Theme.qmlDesignerBackgroundColorDarker() - border.color: Theme.qmlDesignerBorderColor() + translationIndicator.onClicked: { + if (translationIndicator.checked) { + setTranslateExpression() + } else { + var textValue = lineEdit.text + lineEdit.backendValue.value = textValue } + colorLogic.evaluate(); } - Controls.CheckBox { - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - id: trCheckbox - - - property bool isTranslated: colorLogic.backendValue.isTranslated - property bool backendValueValue: colorLogic.backendValue.value - - onIsTranslatedChanged: { - checked = lineEdit.backendValue.isTranslated - } - - onBackendValueValueChanged: { - checked = lineEdit.backendValue.isTranslated - } - - onClicked: { - if (trCheckbox.checked) { - setTranslateExpression() - } else { - var textValue = lineEdit.text - lineEdit.backendValue.value = textValue - } - colorLogic.evaluate(); - } - - function escapeString(string) { - var str = string; - str = str.replace(/\\/g, "\\\\"); - str.replace(/\"/g, "\\\""); - str = str.replace(/\t/g, "\\t"); - str = str.replace(/\r/g, "\\r"); - str = str.replace(/\n/g, '\\n'); - return str; - } - - visible: showTranslateCheckBox - - - style: CheckBoxStyle { - spacing: 8 - indicator: Item { - implicitWidth: 15 - implicitHeight: 15 - x: 7 - y: 1 - Rectangle { - anchors.fill: parent - border.color: Theme.qmlDesignerBorderColor() - color: Theme.qmlDesignerBackgroundColorDarker() - opacity: control.hovered || control.pressed ? 1 : 0.75 - } - Image { - x: 1 - y: 1 - width: 13 - height: 13 - source: "image://icons/tr" - opacity: control.checked ? 1 : 0.3; - } - } - } + property variant backendValueValueInternal: backendValue.value + onBackendValueValueInternalChanged: { + lineEdit.translationIndicator.checked = lineEdit.backendValue.isTranslated } + + onIsTranslatedChanged: { + lineEdit.translationIndicator.checked = lineEdit.backendValue.isTranslated + } + + function escapeString(string) { + var str = string; + str = str.replace(/\\/g, "\\\\"); + str.replace(/\"/g, "\\\""); + str = str.replace(/\t/g, "\\t"); + str = str.replace(/\r/g, "\\r"); + str = str.replace(/\n/g, '\\n'); + return str; + } + } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml index b7c2664bdc6..10b09287b71 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml @@ -27,6 +27,7 @@ import QtQuick 2.1 import QtQuick.Controls 1.1 as Controls import QtQuick.Layouts 1.0 import QtQuickDesignerTheme 1.0 +import StudioTheme 1.0 as StudioTheme Item { id: section @@ -54,6 +55,7 @@ Item { color: Theme.color(Theme.PanelTextColorLight) x: 22 font.bold: true + font.pixelSize: StudioTheme.Values.myFontSize } Image { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml index ed35be506f3..d30fa6ad5ad 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml @@ -39,7 +39,7 @@ Item { property alias backendValue: spinBox.backendValue - width: 100 + width: 120 implicitHeight: spinBox.height property bool __initialized: false @@ -60,7 +60,7 @@ Item { if (!wrapper.__initialized) return spinBox[target] = Math.round(value * spinBox.factor) - } + } StudioControls.SpinBox { id: spinBox diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml index 22c1923fad9..b5e0ac02214 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml @@ -27,6 +27,7 @@ import QtQuick 2.1 import QtQuick.Controls 1.0 as Controls import QtQuick.Controls.Styles 1.1 import QtQuickDesignerTheme 1.0 +import StudioTheme 1.0 as StudioTheme Controls.TabView { id: root @@ -42,6 +43,7 @@ Controls.TabView { Text { id: text font.bold: true + font.pixelSize: StudioTheme.Values.myFontSize anchors.centerIn: parent anchors.verticalCenterOffset: -1 text: styleData.title diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml index 5eb17ed81be..2f122a7b89d 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml @@ -30,7 +30,7 @@ import StudioTheme 1.0 as StudioTheme T.CheckBox { id: myCheckBox - property alias actionIcon: actionIndicator.icon + property alias actionIndicator: actionIndicator property bool hover: myCheckBox.hovered // TODO two underscores @@ -39,6 +39,7 @@ T.CheckBox { property real __actionIndicatorHeight: StudioTheme.Values.height property alias labelVisible: checkBoxLabel.visible + property alias labelColor: checkBoxLabel.color font.pixelSize: StudioTheme.Values.myFontSize diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml index a2c15add0bf..3ee5a02b7cd 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml @@ -31,7 +31,9 @@ import StudioTheme 1.0 as StudioTheme T.ComboBox { id: myComboBox - property alias actionIcon: actionIndicator.icon + property alias actionIndicator: actionIndicator + + property alias labelColor: comboBoxInput.color property bool hover: false // This property is used to indicate the global hover state diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml index df3677f410f..3525bfa41bc 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml @@ -30,7 +30,9 @@ import StudioTheme 1.0 as StudioTheme T.TextField { id: myTextField - property alias actionIcon: actionIndicator.icon + property alias actionIndicator: actionIndicator + + property alias translationIndicator: translationIndicator property bool edit: false property bool hover: false // This property is used to indicate the global hover state diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml index 17c29a82b6b..7b08347879b 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml @@ -34,6 +34,9 @@ Item { property bool hover: false property bool pressed: false + property bool checked: false + + signal clicked state: "default" @@ -67,6 +70,10 @@ Item { hoverEnabled: true onContainsMouseChanged: translationIndicator.hover = containsMouse onPressed: mouse.accepted = true // TODO + onClicked: { + translationIndicator.checked = !translationIndicator.checked + translationIndicator.clicked() + } } } @@ -88,12 +95,23 @@ Item { when: myControl.enabled && !translationIndicator.hover && !translationIndicator.pressed && !myControl.hover && !myControl.edit && !myControl.drag + && !translationIndicator.checked PropertyChanges { target: translationIndicatorBackground color: StudioTheme.Values.themeColumnBackground border.color: StudioTheme.Values.themeTranslationIndicatorBorder } }, + State { + name: "checked" + when: translationIndicator.checked + + PropertyChanges { + target: translationIndicatorBackground + //color: StudioTheme.Values.themeFocusDrag // TODO + color: "red" + } + }, State { name: "hovered" when: translationIndicator.hover && !translationIndicator.pressed From 7d7dc55055c593c44dfaf720b9c8f195661e3f37 Mon Sep 17 00:00:00 2001 From: Aleksei German Date: Wed, 5 Jun 2019 17:02:14 +0200 Subject: [PATCH 23/28] QtDesignStudio Fix for Palette Change-Id: I78f41db19bd1eeb4c2cf775bad4c9e7461ad9d3d Reviewed-by: Thomas Hartmann --- .../components/propertyeditor/simplecolorpalette.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp index 7fada3f0d38..c88d83aa0a5 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp @@ -43,7 +43,7 @@ PaletteColor::PaletteColor(const QString &colorCode) , m_isFavorite(false) {} -PaletteColor::PaletteColor(const QColor &value) +PaletteColor::PaletteColor(const QColor &color) : m_color(color) , m_colorCode(color.name(QColor::HexArgb)) , m_isFavorite(false) From 221885d98640845e910fdb1b3a1f8579df421777 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 5 Jun 2019 17:23:10 +0200 Subject: [PATCH 24/28] QmlDesigner: Add missing json Change-Id: I3be9222a80fd335fa6e0a20b541cedfa08e5964c Reviewed-by: Thomas Hartmann --- .../qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json new file mode 100644 index 00000000000..72a2c270874 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json @@ -0,0 +1,6 @@ +{ + "Vendor" : "The Qt Company Ltd", + "Category" : "Qt Quick", + "Description" : "Plugin for integrating QmlPreview into QmlDesigner", + "Url" : "http://www.qt.io" +} From f48361912b4b827d1110140f0ebc6d39d5b17520 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 5 Jun 2019 17:26:44 +0200 Subject: [PATCH 25/28] QmlDesigner: Fix duplication Change-Id: Id21eddf67f0a24de9dfde95d6cf5ed96ab4dc0ec Reviewed-by: Tim Jenssen --- .../components/propertyeditor/gradientmodel.cpp | 9 +++++++-- .../components/propertyeditor/gradientmodel.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp index 5728c594d48..471ec2abd4d 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp @@ -181,7 +181,7 @@ void GradientModel::addGradient() setupModel(); if (m_gradientTypeName != "Gradient") - QTimer::singleShot(1000, [this](){ view()->resetPuppet(); }); /*Unfortunately required */ + resetPuppet(); /*Unfortunately required */ emit hasGradientChanged(); emit gradientTypeChanged(); } @@ -437,6 +437,11 @@ QmlDesigner::AbstractView *GradientModel::view() const return m_itemNode.view(); } +void GradientModel::resetPuppet() +{ + QTimer::singleShot(1000, [this]() { view()->resetPuppet(); }); +} + QmlDesigner::ModelNode GradientModel::createGradientNode() { QByteArray fullTypeName = m_gradientTypeName.toUtf8(); @@ -562,7 +567,7 @@ void GradientModel::setPresetByStops(const QList &stopsPositions, setupModel(); if (m_gradientTypeName != "Gradient") - QTimer::singleShot(200, [this]() { view()->resetPuppet(); }); /*Unfortunately required */ + resetPuppet(); /*Unfortunately required */ emit hasGradientChanged(); emit gradientTypeChanged(); diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h index 0cc1a3c4ae5..c54526838e8 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h +++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h @@ -108,6 +108,7 @@ private: void setupGradientProperties(const QmlDesigner::ModelNode &gradient); QmlDesigner::Model *model() const; QmlDesigner::AbstractView *view() const; + void resetPuppet(); }; QML_DECLARE_TYPE(GradientModel) From 064161313dcfab97aa042c4f9caee788a5cf6058 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Wed, 5 Jun 2019 17:55:26 +0200 Subject: [PATCH 26/28] QmlDesigner: Fix linux build Change-Id: I07d77b5423c6846dae83d35b758daad4cbc2b265 Reviewed-by: Thomas Hartmann --- .../components/propertyeditor/simplecolorpalettesingleton.h | 3 +-- src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h index 004feea5325..77ad2b0732a 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h @@ -30,11 +30,10 @@ #include #include #include +#include namespace QmlDesigner { -class PaletteColor; - class SimpleColorPaletteSingleton : public QObject { Q_OBJECT diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro index 56eadb58a58..ec8c9b1d636 100644 --- a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro @@ -9,7 +9,7 @@ include (../qmldesigner_dependencies.pri) LIBS += -L$$IDE_PLUGIN_PATH LIBS += -l$$qtLibraryName(QmlDesigner) -LIBS += -l$$qtLibraryName(Extensionsystem) +LIBS += -l$$qtLibraryName(ExtensionSystem) LIBS += -l$$qtLibraryName(Core) LIBS += -l$$qtLibraryName(ProjectExplorer) LIBS += -l$$qtLibraryName(Utils) From 5344d41689c835db1a4b9ce48caafc6203554d76 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 5 Jun 2019 18:04:40 +0200 Subject: [PATCH 27/28] QmlDesigner: Some cleanup Change-Id: I58bbfab2ba0c1054ba4f36603f54b1a8b8572132 Reviewed-by: Thomas Hartmann --- .../imports/HelperWidgets/ColorEditor.qml | 2 -- .../propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml index 31d8d263b6c..8bbb5698efb 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml @@ -25,9 +25,7 @@ import QtQuick 2.1 import QtQuick.Layouts 1.0 -import QtQuick.Controls 1.0 as Controls import QtQuickDesignerTheme 1.0 -import QtQuick.Controls.Styles 1.1 Column { id: colorEditor diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml index d30fa6ad5ad..196974d1038 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml @@ -60,7 +60,7 @@ Item { if (!wrapper.__initialized) return spinBox[target] = Math.round(value * spinBox.factor) - } + } StudioControls.SpinBox { id: spinBox From 337e8c71c8fe083b3881ef7da506628a82ebcdf0 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 5 Jun 2019 18:02:31 +0200 Subject: [PATCH 28/28] QmlDesigner: Add more space Change-Id: I56c13be32d9dcb4fca43cd6577b2b06ffd71eaf8 Reviewed-by: Thomas Hartmann --- .../propertyEditorQmlSources/QtQuick/AdvancedSection.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml index d68e021d7f6..3cf02f122eb 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml @@ -55,7 +55,7 @@ Section { minimumValue: 0.01 stepSize: 0.1 maximumValue: 10 - Layout.preferredWidth: 80 + Layout.preferredWidth: 100 } ExpandingSpacer { } @@ -70,7 +70,7 @@ Section { decimals: 2 minimumValue: -360 maximumValue: 360 - Layout.preferredWidth: 80 + Layout.preferredWidth: 100 } ExpandingSpacer { } @@ -84,7 +84,7 @@ Section { hasSlider: true minimumValue: -100 maximumValue: 100 - Layout.preferredWidth: 80 + Layout.preferredWidth: 100 } ExpandingSpacer { }