From 71c5f9e52b8326f9d01a59c4e30d6609424149de Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 26 Feb 2021 16:27:49 +0200 Subject: [PATCH 01/22] EditorManager: Do not switch mode in response to editor closing Switching to design mode when in process of closing editor can result in state where there is no active text editor for a document, which is required to properly initialize design mode. This happens when the next editor to be activated targets the same document as the closed editor, i.e. when the last open document is used in split view. To prevent design mode initialization crash, we block changing to design mode in response to editor closing, if the new editor targets the same document as the closed editor. Fixes: QDS-3763 Change-Id: I2bd325b805d3e526778f8cdd8e583e87b8c93a24 Reviewed-by: Eike Ziller --- src/plugins/coreplugin/editormanager/editormanager.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index d6019f628cc..d914326e0ec 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -1730,9 +1730,8 @@ bool EditorManagerPrivate::closeEditors(const QList &editors, CloseFla if (editor == viewCurrentEditor && view == views.last()) { // Avoid removing the globally current editor from its view, // set a new current editor before. - const EditorManager::OpenEditorFlags flags = view != currentView - ? EditorManager::DoNotChangeCurrentEditor - : EditorManager::NoFlags; + EditorManager::OpenEditorFlags flags = view != currentView + ? EditorManager::DoNotChangeCurrentEditor : EditorManager::NoFlags; const QList viewEditors = view->editors(); IEditor *newCurrent = viewEditors.size() > 1 ? viewEditors.at(viewEditors.size() - 2) : nullptr; @@ -1748,6 +1747,10 @@ bool EditorManagerPrivate::closeEditors(const QList &editors, CloseFla const QList documents = DocumentModel::entries(); if (!documents.isEmpty()) { if (IDocument *document = documents.last()->document) { + // Do not auto-switch to design mode if the new editor will be for + // the same document as the one that was closed. + if (view == currentView && document == editor->document()) + flags = EditorManager::DoNotSwitchToDesignMode; activateEditorForDocument(view, document, flags); } } From ac24d4357c077b4ff1bcefc0d9b1c196d5afe4c3 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 12 Mar 2021 16:31:44 +0100 Subject: [PATCH 02/22] QmlDesigner: Fix puppet crash Limit the depth of recursion. There can be cycles. Task-number: QDS-3877 Change-Id: I10a1c7033b956244308e87aae6897f0040e0bc22 Reviewed-by: Mahmoud Badri --- .../qmlprivategate/qmlprivategate_56.cpp | 77 ++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate_56.cpp b/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate_56.cpp index fa4f4bd7c2b..467e85c3b15 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate_56.cpp +++ b/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate_56.cpp @@ -58,11 +58,86 @@ bool isPropertyBlackListed(const QmlDesigner::PropertyName &propertyName) return QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName); } +static void addToPropertyNameListIfNotBlackListed( + PropertyNameList *propertyNameList, const QQuickDesignerSupport::PropertyName &propertyName) +{ + if (!QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName)) + propertyNameList->append(propertyName); +} + +PropertyNameList allPropertyNamesInline(QObject *object, + const PropertyName &baseName, + QObjectList *inspectedObjects, + int depth = 0) +{ + QQuickDesignerSupport::PropertyNameList propertyNameList; + + QObjectList localObjectList; + + if (inspectedObjects == nullptr) + inspectedObjects = &localObjectList; + + if (depth > 2) + return propertyNameList; + + if (!inspectedObjects->contains(object)) + inspectedObjects->append(object); + + const QMetaObject *metaObject = object->metaObject(); + + QStringList deferredPropertyNames; + const int namesIndex = metaObject->indexOfClassInfo("DeferredPropertyNames"); + if (namesIndex != -1) { + QMetaClassInfo classInfo = metaObject->classInfo(namesIndex); + deferredPropertyNames = QString::fromUtf8(classInfo.value()).split(QLatin1Char(',')); + } + + for (int index = 0; index < metaObject->propertyCount(); ++index) { + QMetaProperty metaProperty = metaObject->property(index); + QQmlProperty declarativeProperty(object, QString::fromUtf8(metaProperty.name())); + if (declarativeProperty.isValid() + && declarativeProperty.propertyTypeCategory() == QQmlProperty::Object) { + if (declarativeProperty.name() != QLatin1String("parent") + && !deferredPropertyNames.contains(declarativeProperty.name())) { + QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read()); + if (childObject) + propertyNameList.append( + allPropertyNamesInline(childObject, + baseName + + QQuickDesignerSupport::PropertyName( + metaProperty.name()) + + '.', + inspectedObjects, + depth + 1)); + } + } else if (QQmlGadgetPtrWrapper *valueType + = QQmlGadgetPtrWrapper::instance(qmlEngine(object), metaProperty.userType())) { + valueType->setValue(metaProperty.read(object)); + propertyNameList.append(baseName + + QQuickDesignerSupport::PropertyName(metaProperty.name())); + propertyNameList.append( + allPropertyNamesInline(valueType, + baseName + + QQuickDesignerSupport::PropertyName(metaProperty.name()) + + '.', + inspectedObjects, + depth + 1)); + } else { + addToPropertyNameListIfNotBlackListed(&propertyNameList, + baseName + + QQuickDesignerSupport::PropertyName( + metaProperty.name())); + } + } + + return propertyNameList; +} + PropertyNameList allPropertyNames(QObject *object, const PropertyName &baseName, QObjectList *inspectedObjects) { - return QQuickDesignerSupportProperties::allPropertyNames(object, baseName, inspectedObjects); + return allPropertyNamesInline(object, baseName, inspectedObjects); } PropertyNameList propertyNameListForWritableProperties(QObject *object, From 5fbef6c060bd437f2e749f240031576aafdbd942 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Thu, 11 Mar 2021 22:49:39 +0200 Subject: [PATCH 03/22] QmlDesigner: Add all Quick3DAssets under 1 import section Fixes: QDS-3866 Change-Id: I3aad4aee0d6c388446b459e558d87f68b204de59 Reviewed-by: Thomas Hartmann --- .../itemlibrary/itemlibraryimport.cpp | 22 ++++++++++++++++--- .../itemlibrary/itemlibraryimport.h | 2 ++ .../itemlibrary/itemlibrarymodel.cpp | 22 ++++++++++++++----- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp index d0a87013dd8..a2b1073594e 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp @@ -41,6 +41,9 @@ QString ItemLibraryImport::importName() const if (m_sectionType == SectionType::User) return userComponentsTitle(); + if (m_sectionType == SectionType::Quick3DAssets) + return quick3DAssetsTitle(); + if (m_sectionType == SectionType::Unimported) return unimportedComponentsTitle(); @@ -55,6 +58,9 @@ QString ItemLibraryImport::importUrl() const if (m_sectionType == SectionType::User) return userComponentsTitle(); + if (m_sectionType == SectionType::Quick3DAssets) + return quick3DAssetsTitle(); + if (m_sectionType == SectionType::Unimported) return unimportedComponentsTitle(); @@ -71,10 +77,13 @@ QString ItemLibraryImport::sortingName() const if (m_sectionType == SectionType::User) return "_"; // user components always come first - if (m_sectionType == SectionType::Unimported) - return "zzzzzz"; // Unimported components always come last + if (m_sectionType == SectionType::Quick3DAssets) + return "__"; // Quick3DAssets come second - if (!hasCategories()) // imports with no categories are at the bottom of the list + if (m_sectionType == SectionType::Unimported) + return "zzzzzz"; // Unimported components come last + + if (!hasCategories()) // imports with no categories come before last return "zzzzz_" + importName(); return importName(); @@ -188,6 +197,13 @@ QString ItemLibraryImport::userComponentsTitle() return tr("My Components"); } +// static +QString ItemLibraryImport::quick3DAssetsTitle() +{ + return tr("My 3D Components"); +} + +// static QString ItemLibraryImport::unimportedComponentsTitle() { return tr("All Other Components"); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h index ed60c1cffe2..982e47df70e 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h @@ -48,6 +48,7 @@ public: enum class SectionType { Default, User, + Quick3DAssets, Unimported }; @@ -75,6 +76,7 @@ public: void expandCategories(bool expand = true); static QString userComponentsTitle(); + static QString quick3DAssetsTitle(); static QString unimportedComponentsTitle(); SectionType sectionType() const; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp index e7276750386..66483939016 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp @@ -216,24 +216,32 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model) for (const Import &import : model->imports()) { if (import.isLibraryImport() && import.url() != projectName) { bool addNew = true; - ItemLibraryImport *oldImport = importHash.value(import.url()); - if (oldImport && oldImport->importEntry().url() == import.url()) { + bool isQuick3DAsset = import.url().startsWith("Quick3DAssets."); + QString importUrl = isQuick3DAsset ? ItemLibraryImport::quick3DAssetsTitle() : import.url(); + ItemLibraryImport *oldImport = importHash.value(importUrl); + if (oldImport && oldImport->sectionType() == ItemLibraryImport::SectionType::Quick3DAssets + && isQuick3DAsset) { + addNew = false; // add only 1 Quick3DAssets import section + } else if (oldImport && oldImport->importEntry().url() == import.url()) { // Retain the higher version if multiples exist if (compareVersions(oldImport->importEntry().version(), import.version())) addNew = false; else delete oldImport; } + if (addNew) { - ItemLibraryImport *itemLibImport = new ItemLibraryImport(import, this); - importHash.insert(import.url(), itemLibImport); + auto sectionType = isQuick3DAsset ? ItemLibraryImport::SectionType::Quick3DAssets + : ItemLibraryImport::SectionType::Default; + ItemLibraryImport *itemLibImport = new ItemLibraryImport(import, this, sectionType); + importHash.insert(importUrl, itemLibImport); } } } for (const auto itemLibImport : qAsConst(importHash)) { m_importList.append(itemLibImport); - itemLibImport->setImportExpanded(loadExpandedState(itemLibImport->importEntry().url())); + itemLibImport->setImportExpanded(loadExpandedState(itemLibImport->importUrl())); } const QList itemLibEntries = itemLibraryInfo->entries(); @@ -280,6 +288,8 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model) m_importList.append(importSection); importSection->setImportExpanded(loadExpandedState(catName)); } + } else if (catName == "My Quick3D Components") { + importSection = importByUrl(ItemLibraryImport::quick3DAssetsTitle()); } else { if (catName.startsWith("Qt Quick - ")) catName = catName.mid(11); // remove "Qt Quick - " @@ -354,6 +364,8 @@ ItemLibraryImport *ItemLibraryModel::importByUrl(const QString &importUrl) const || (importUrl.isEmpty() && itemLibraryImport->importUrl() == "QtQuick") || (importUrl == ItemLibraryImport::userComponentsTitle() && itemLibraryImport->sectionType() == ItemLibraryImport::SectionType::User) + || (importUrl == ItemLibraryImport::quick3DAssetsTitle() + && itemLibraryImport->sectionType() == ItemLibraryImport::SectionType::Quick3DAssets) || (importUrl == ItemLibraryImport::unimportedComponentsTitle() && itemLibraryImport->sectionType() == ItemLibraryImport::SectionType::Unimported)) { return itemLibraryImport; From af184fdd4c5e77048bf876f18ed8355fff5595e1 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Thu, 11 Mar 2021 10:05:55 +0100 Subject: [PATCH 04/22] CMake Wizards: Add Qt 6 specific static qml plugin importing For Qml / Qt Quick projects to work with static Qt builds, the application targets need to link to the static Qml plugins, which is done by calling qt_import_qml_plugins. Starting with Qt 6.1 and CMake 3.18+ that will be done automatically in qt_add_application via qt_finalize_executable, as per c71c48f5125c116f01f615f51f10e4f2877b2b1d But for Qt 6.0 and lower CMake versions, we need to call qt_import_qml_plugins manually, thus we include it in the Qt Quick wizard template so that it works with all Qt 6 versions and lower CMake versions. Amends b72c1d11e610340ef86188c964f3a7f8adda1ae9. Task-number: QTCREATORBUG-23574 Change-Id: Id8db3352ecbb8441eda9f5c9638c7ea6ac1fee96 Reviewed-by: Eike Ziller --- .../wizards/projects/qtquickapplication/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt index aeefa3af1f8..067ecb4f0a8 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt @@ -76,3 +76,7 @@ set_target_properties(%{ProjectName} PROPERTIES MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} ) + +if(QT_VERSION_MAJOR EQUAL 6) + qt_import_qml_plugins(%{ProjectName}) +endif() From 2aead8b3e4513eda90140841528966b6926948bf Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Mon, 15 Mar 2021 09:02:09 +0100 Subject: [PATCH 05/22] McuSupport: detect fallback lib when desktop kit missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The library filename has changed in recent versions of the SDK, which was causing false negatives. Fixes: QTCREATORBUG-25469 Change-Id: Ie98c75a57efc5384262dbfd17f729b34cdd5f577 Reviewed-by: Erik Verbruggen Reviewed-by: Alessandro Portale Reviewed-by: Dawid Śliwa --- src/plugins/mcusupport/mcusupportsdk.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp index 75a2d115336..b0e1395bae4 100644 --- a/src/plugins/mcusupport/mcusupportsdk.cpp +++ b/src/plugins/mcusupport/mcusupportsdk.cpp @@ -593,13 +593,18 @@ void targetsAndPackages(const Utils::FilePath &dir, QVector *packa }); if (!hasDesktopDescription) { - Utils::FilePath desktopLib; - if (Utils::HostOsInfo::isWindowsHost()) - desktopLib = dir / "lib/QulQuickUltralite_QT_32bpp_Windows_Release.lib"; - else - desktopLib = dir / "lib/libQulQuickUltralite_QT_32bpp_Linux_Debug.a"; + QVector desktopLibs; + if (Utils::HostOsInfo::isWindowsHost()) { + desktopLibs << dir / "lib/QulQuickUltralite_QT_32bpp_Windows_Release.lib"; // older versions of QUL (<1.5?) + desktopLibs << dir / "lib/QulQuickUltralitePlatform_QT_32bpp_Windows_msvc_Release.lib"; // newer versions of QUL + } else { + desktopLibs << dir / "lib/libQulQuickUltralite_QT_32bpp_Linux_Debug.a"; // older versions of QUL (<1.5?) + desktopLibs << dir / "lib/libQulQuickUltralitePlatform_QT_32bpp_Linux_gnu_Debug.a"; // newer versions of QUL + } - if (desktopLib.exists()) { + if (Utils::anyOf(desktopLibs, [](const Utils::FilePath &desktopLib) { + return desktopLib.exists(); }) + ) { McuTargetDescription desktopDescription; desktopDescription.qulVersion = descriptions.empty() ? McuSupportOptions::minimalQulVersion().toString() @@ -613,8 +618,10 @@ void targetsAndPackages(const Utils::FilePath &dir, QVector *packa descriptions.prepend(desktopDescription); } else { if (dir.exists()) - printMessage(McuTarget::tr("Skipped creating fallback desktop kit: Could not find %1.") - .arg(QDir::toNativeSeparators(desktopLib.fileNameWithPathComponents(1))), + printMessage(McuTarget::tr("Skipped creating fallback desktop kit: Could not find any of %1.") + .arg(Utils::transform(desktopLibs, [](const auto &path) { + return QDir::toNativeSeparators(path.fileNameWithPathComponents(1)); + }).toList().join(" or ")), false); } } From 9d9ac537e8686a1625785fa0954049b356c07772 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 15 Mar 2021 12:38:19 +0100 Subject: [PATCH 06/22] Don't waste horizontal space in Open Documents view Make sure that the column that we reserve for the X close button is really just 16 pixels wide. Fixes: QTCREATORBUG-23894 Change-Id: Idc2755debfc3a6fb898ea3abd2a882249f7820c1 Reviewed-by: David Schulz --- src/plugins/coreplugin/opendocumentstreeview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/coreplugin/opendocumentstreeview.cpp b/src/plugins/coreplugin/opendocumentstreeview.cpp index 7861199bdd6..c6994c221b4 100644 --- a/src/plugins/coreplugin/opendocumentstreeview.cpp +++ b/src/plugins/coreplugin/opendocumentstreeview.cpp @@ -128,6 +128,7 @@ void OpenDocumentsTreeView::setModel(QAbstractItemModel *model) header()->setStretchLastSection(false); header()->setSectionResizeMode(0, QHeaderView::Stretch); header()->setSectionResizeMode(1, QHeaderView::Fixed); + header()->setMinimumSectionSize(0); header()->resizeSection(1, 16); } From 3ab93592c35c4bb9f87be809ce858e6ba48003c1 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 9 Mar 2021 13:53:34 +0100 Subject: [PATCH 07/22] CppLocatorData: Don't use recursive mutex Don't use recursive mutex in CppLocatorData class, as this is more expensive to construct than simple QMutex. Refactor the code so that every call to flushPendingDocument() is done with already locked m_pendingDocumentsMutex. This eliminates the need for recursive mutex. Remove unused allIndexItems() method. Change-Id: Ic7cb45bc3301d83768e69ee52f84ae159cb731a5 Reviewed-by: Eike Ziller --- src/plugins/cpptools/cpplocatordata.cpp | 10 ---------- src/plugins/cpptools/cpplocatordata.h | 6 +++--- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/plugins/cpptools/cpplocatordata.cpp b/src/plugins/cpptools/cpplocatordata.cpp index be2b948a96b..3154f66ddba 100644 --- a/src/plugins/cpptools/cpplocatordata.cpp +++ b/src/plugins/cpptools/cpplocatordata.cpp @@ -86,7 +86,6 @@ void CppLocatorData::onAboutToRemoveFiles(const QStringList &files) void CppLocatorData::flushPendingDocument(bool force) const { // TODO: move this off the UI thread and into a future. - QMutexLocker locker(&m_pendingDocumentsMutex); if (!force && m_pendingDocuments.size() < MaxPendingDocuments) return; if (m_pendingDocuments.isEmpty()) @@ -98,12 +97,3 @@ void CppLocatorData::flushPendingDocument(bool force) const m_pendingDocuments.clear(); m_pendingDocuments.reserve(MaxPendingDocuments); } - -QList CppLocatorData::allIndexItems( - const QHash> &items) const -{ - QList result; - for (const QList &subItems : items) - result.append(subItems); - return result; -} diff --git a/src/plugins/cpptools/cpplocatordata.h b/src/plugins/cpptools/cpplocatordata.h index b41bce07bfb..f8c853471f6 100644 --- a/src/plugins/cpptools/cpplocatordata.h +++ b/src/plugins/cpptools/cpplocatordata.h @@ -46,8 +46,8 @@ class CppLocatorData : public QObject public: void filterAllFiles(IndexItem::Visitor func) const { - flushPendingDocument(true); QMutexLocker locker(&m_pendingDocumentsMutex); + flushPendingDocument(true); QHash infosByFile = m_infosByFile; locker.unlock(); for (auto i = infosByFile.constBegin(), ei = infosByFile.constEnd(); i != ei; ++i) @@ -60,13 +60,13 @@ public slots: void onAboutToRemoveFiles(const QStringList &files); private: + // Ensure to protect every call to this method with m_pendingDocumentsMutex void flushPendingDocument(bool force) const; - QList allIndexItems(const QHash> &items) const; mutable SearchSymbols m_search; mutable QHash m_infosByFile; - mutable QRecursiveMutex m_pendingDocumentsMutex; + mutable QMutex m_pendingDocumentsMutex; mutable QVector m_pendingDocuments; }; From 38756f1c7a1716258068613159251e4b05af52fa Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 9 Mar 2021 15:59:09 +0100 Subject: [PATCH 08/22] QmlDesigner: Use Theme::DScontrolBackground instead of BackgroundColorDarkAlternate The color role qmlDesignerBackgroundColorDarkAlternate is deprecated. Change-Id: Ic6ab5883c980b83c3d47830ab51b805936007547 Reviewed-by: Knud Dollereder Reviewed-by: Thomas Hartmann --- .../qmldesigner/components/curveeditor/curveeditormodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp index 8b0a0357b1c..ab3caa3966e 100644 --- a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp +++ b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp @@ -73,7 +73,7 @@ CurveEditorStyle CurveEditorModel::style() const out.timeAxisHeight = 60; out.timeOffsetLeft = 10; out.timeOffsetRight = 10; - out.rangeBarColor = QmlDesigner::Theme::instance()->qmlDesignerBackgroundColorDarkAlternate(); + out.rangeBarColor = QmlDesigner::Theme::getColor(Theme::DScontrolBackground); out.rangeBarCapsColor = QmlDesigner::Theme::getColor( QmlDesigner::Theme::QmlDesigner_HighlightColor); out.valueAxisWidth = 60; From 92da864a8664f59fa7472426d18d01452f028424 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 9 Mar 2021 16:00:37 +0100 Subject: [PATCH 09/22] QmlDesigner: Replace deprecated color roles in timeline and transition editor The color roles qmlDesignerBackgroundColorDarkAlternate and qmlDesignerBackgroundColorDarker are deprecated. Change-Id: I0c7cabe0eacbcab57a037caa83c338791930420c Reviewed-by: Knud Dollereder Reviewed-by: Thomas Hartmann --- .../components/timelineeditor/timelinecontrols.cpp | 2 +- .../components/timelineeditor/timelineplaceholder.cpp | 5 ++--- .../components/timelineeditor/timelinepropertyitem.cpp | 5 ++--- .../components/timelineeditor/timelinesectionitem.cpp | 7 +++---- .../transitioneditor/transitioneditorpropertyitem.cpp | 5 ++--- .../transitioneditor/transitioneditorsectionitem.cpp | 6 +++--- 6 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp index f0b58d91c98..21f5af9eff4 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp @@ -63,7 +63,7 @@ FloatControl::FloatControl() setMinimum(std::numeric_limits::lowest()); setMaximum(std::numeric_limits::max()); - QColor bg = Theme::instance()->qmlDesignerBackgroundColorDarkAlternate(); + QColor bg = Theme::getColor(Theme::DScontrolBackground); auto p = palette(); p.setColor(QPalette::Text, Theme::instance()->color(Utils::Theme::PanelTextColorLight)); diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineplaceholder.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineplaceholder.cpp index 7e7cb69fc97..afcc448115c 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelineplaceholder.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelineplaceholder.cpp @@ -51,9 +51,8 @@ TimelinePlaceholder *TimelinePlaceholder::create(QGraphicsScene * /*parentScene* void TimelinePlaceholder::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { painter->save(); - static const QColor penColor = Theme::instance()->qmlDesignerBackgroundColorDarker(); - static const QColor backgroundColor = Theme::instance() - ->qmlDesignerBackgroundColorDarkAlternate(); + static const QColor penColor = Theme::getColor(Theme::BackgroundColorDark); + static const QColor backgroundColor = Theme::getColor(Theme::DScontrolBackground); static const QColor backgroundColorSection = Theme::getColor(Theme::BackgroundColorDark); painter->fillRect(0, 0, size().width(), size().height(), backgroundColor); diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp index 9aef430dea6..fa1d258c28a 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp @@ -368,10 +368,9 @@ void TimelinePropertyItem::paint(QPainter *painter, const QStyleOptionGraphicsIt { painter->save(); - static const QColor penColor = Theme::instance()->qmlDesignerBackgroundColorDarker(); + static const QColor penColor = Theme::getColor(Theme::BackgroundColorDark); static const QColor textColor = Theme::getColor(Theme::PanelTextColorLight); - static const QColor backgroundColor = Theme::instance() - ->qmlDesignerBackgroundColorDarkAlternate(); + static const QColor backgroundColor = Theme::getColor(Theme::DScontrolBackground); static const QPixmap keyframe = TimelineIcons::KEYFRAME.pixmap(); static const QPixmap isKeyframe = TimelineIcons::IS_KEYFRAME.pixmap(); diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp index 1cff8012353..9176e6ef9d1 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp @@ -255,7 +255,7 @@ void TimelineSectionItem::paint(QPainter *painter, painter->save(); const QColor textColor = Theme::getColor(Theme::PanelTextColorLight); - const QColor penColor = Theme::instance()->qmlDesignerBackgroundColorDarker(); + const QColor penColor = Theme::getColor(Theme::BackgroundColorDark); QColor brushColor = Theme::getColor(Theme::BackgroundColorDark); int fillOffset = 0; @@ -273,7 +273,7 @@ void TimelineSectionItem::paint(QPainter *painter, 0, size().width() - TimelineConstants::sectionWidth, size().height(), - Theme::instance()->qmlDesignerBackgroundColorDarkAlternate()); + Theme::getColor(Theme::DScontrolBackground)); painter->setPen(penColor); drawLine(painter, @@ -640,8 +640,7 @@ qreal TimelineRulerSectionItem::endFrame() const void TimelineRulerSectionItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { - static const QColor backgroundColor = Theme::instance() - ->qmlDesignerBackgroundColorDarkAlternate(); + static const QColor backgroundColor = Theme::getColor(Theme::DScontrolBackground); static const QColor penColor = Theme::getColor(Theme::PanelTextColorLight); static const QColor highlightColor = Theme::instance()->Theme::qmlDesignerButtonColor(); static const QColor handleColor = Theme::getColor(Theme::QmlDesigner_HighlightColor); diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorpropertyitem.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorpropertyitem.cpp index f5b7b45b05e..7e5555100ea 100644 --- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorpropertyitem.cpp +++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorpropertyitem.cpp @@ -121,10 +121,9 @@ void TransitionEditorPropertyItem::paint(QPainter *painter, { painter->save(); - static const QColor penColor = Theme::instance()->qmlDesignerBackgroundColorDarker(); + static const QColor penColor = Theme::getColor(Theme::BackgroundColorDark); static const QColor textColor = Theme::getColor(Theme::PanelTextColorLight); - static const QColor backgroundColor = Theme::instance() - ->qmlDesignerBackgroundColorDarkAlternate(); + static const QColor backgroundColor = Theme::getColor(Theme::DScontrolBackground); painter->fillRect(0, 0, TimelineConstants::sectionWidth, size().height(), backgroundColor); painter->fillRect(TimelineConstants::textIndentationProperties - 4, diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorsectionitem.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorsectionitem.cpp index 7172465e0d5..7206a73b35f 100644 --- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorsectionitem.cpp +++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorsectionitem.cpp @@ -302,8 +302,8 @@ void TransitionEditorSectionItem::paint(QPainter *painter, painter->save(); const QColor textColor = Theme::getColor(Theme::PanelTextColorLight); - const QColor penColor = Theme::instance()->qmlDesignerBackgroundColorDarker(); - QColor brushColor = Theme::getColor(Theme::BackgroundColorDark); + const QColor penColor = Theme::getColor(Theme::BackgroundColorDark); + QColor brushColor = Theme::getColor(Theme::DScontrolBackground); int fillOffset = 0; if (isSelected()) { @@ -320,7 +320,7 @@ void TransitionEditorSectionItem::paint(QPainter *painter, 0, size().width() - TimelineConstants::sectionWidth, size().height(), - Theme::instance()->qmlDesignerBackgroundColorDarkAlternate()); + Theme::getColor(Theme::DScontrolBackground)); painter->setPen(penColor); drawLine(painter, From ef25cfac59fa511d44d4a71c62ac9b36b9c281b9 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 15 Mar 2021 15:46:25 +0100 Subject: [PATCH 10/22] Utils: Do not add extra space for user display of command lines ... that do not have parameters. Change-Id: I2ea20267bc18826e4017a356f6bc13f4b0172f3c Reviewed-by: Eike Ziller --- src/libs/utils/fileutils.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index ee9b20a4bb0..7a67cfb4d52 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -121,7 +121,10 @@ void CommandLine::addArgs(const QString &inArgs, RawType) QString CommandLine::toUserOutput() const { - return m_executable.toUserOutput() + ' ' + m_arguments; + QString res = m_executable.toUserOutput(); + if (!m_arguments.isEmpty()) + res += ' ' + m_arguments; + return res; } QStringList CommandLine::splitArguments(OsType osType) const From 412b6616728b778159f2d0d6fe422c91569b61d1 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 25 Feb 2021 11:57:43 +0100 Subject: [PATCH 11/22] Squish: Correct hitting "Do Not Show Again" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original implementation just made it work for the common use case. If the order or the selected buttons differed from the common case this failed. Beside this it is later on more easily to extend. Change-Id: I581b0af2579fa728a81b9946028ade5559f17fd8 Reviewed-by: Robert Löhning --- tests/system/objects.map | 1 - tests/system/shared/qtcreator.py | 12 ++++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/system/objects.map b/tests/system/objects.map index 1c016aea443..817db13c37c 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -2,7 +2,6 @@ :*Qt Creator.Cancel Build_QToolButton {text='Cancel Build' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :*Qt Creator.Clear_QToolButton {text='Clear' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :*Qt Creator.Continue_Core::Internal::FancyToolButton {name='Debug.Button' toolTip?='Continue *' type='Core::Internal::FancyToolButton' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} -:*Qt Creator.Do Not Show Again_QToolButton {text='Do Not Show Again' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :*Qt Creator.Find_Find::Internal::FindToolBar {name='Core__Internal__FindWidget' type='Core::Internal::FindToolBar' visible='1' window=':Qt Creator_Core::Internal::MainWindow' windowTitle='Find'} :*Qt Creator.FormEditorStack_Designer::Internal::FormEditorStack {name='FormEditorStack' type='Designer::Internal::FormEditorStack' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :*Qt Creator.Interrupt_Core::Internal::FancyToolButton {name='Debug.Button' toolTip='Interrupt' type='Core::Internal::FancyToolButton' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} diff --git a/tests/system/shared/qtcreator.py b/tests/system/shared/qtcreator.py index 9ecec40a207..d78da01d925 100644 --- a/tests/system/shared/qtcreator.py +++ b/tests/system/shared/qtcreator.py @@ -54,6 +54,14 @@ source("../../shared/clang.py") source("../../shared/welcome.py") source("../../shared/workarounds.py") # include this at last + +def __closeInfoBarEntry__(leftButtonText): + toolButton = ("text='%s' type='QToolButton' unnamed='1' visible='1' " + "window=':Qt Creator_Core::Internal::MainWindow'") + doNotShowAgain = toolButton % "Do Not Show Again" + leftWidget = "leftWidget={%s}" % (toolButton % leftButtonText) + clickButton(waitForObject("{%s %s}" % (doNotShowAgain, leftWidget))) + # additionalParameters must be a list or tuple of strings or None def startQC(additionalParameters=None, withPreparedSettingsPath=True, closeLinkToQt=True, cancelTour=True): global SettingsPath @@ -69,9 +77,9 @@ def startQC(additionalParameters=None, withPreparedSettingsPath=True, closeLinkT if closeLinkToQt or cancelTour: progressBarWait(3000) # wait for the "Updating documentation" progress bar if closeLinkToQt: - clickButton(waitForObject(":*Qt Creator.Do Not Show Again_QToolButton")) + __closeInfoBarEntry__("Link with Qt") if cancelTour: - clickButton(waitForObject(":*Qt Creator.Do Not Show Again_QToolButton")) + __closeInfoBarEntry__("Take UI Tour") return appContext; def startedWithoutPluginError(): From da53e3f9941a5210e56ca7362c64a234ba446cca Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 12 Mar 2021 13:44:52 +0100 Subject: [PATCH 12/22] Squish: Allow automatically created kits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linking to Qt makes the respective configured kits become auto detected and these have a fixed Qt. The Qt version combo box for these kits is disabled on the Kits page, so be more relaxed when checking kits page. Change-Id: Ieb7e22b47bd5e5c5603e85dc0ddf2421427e85d6 Reviewed-by: Robert Löhning --- tests/system/shared/utils.py | 2 +- tests/system/suite_general/tst_default_settings/test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/shared/utils.py b/tests/system/shared/utils.py index e3adb5c49d5..e31ed30c200 100644 --- a/tests/system/shared/utils.py +++ b/tests/system/shared/utils.py @@ -367,7 +367,7 @@ def getConfiguredKits(): # end of internal function for iterateQtVersions def __setQtVersionForKit__(kit, kitName, kitsQtVersionName): mouseClick(waitForObjectItem(":BuildAndRun_QTreeView", kit)) - qtVersionStr = str(waitForObject(":Kits_QtVersion_QComboBox").currentText) + qtVersionStr = str(waitForObjectExists(":Kits_QtVersion_QComboBox").currentText) kitsQtVersionName[kitName] = qtVersionStr # end of internal function for iterate kits diff --git a/tests/system/suite_general/tst_default_settings/test.py b/tests/system/suite_general/tst_default_settings/test.py index 9a15e2b8fae..4db29858bb7 100644 --- a/tests/system/suite_general/tst_default_settings/test.py +++ b/tests/system/suite_general/tst_default_settings/test.py @@ -149,7 +149,7 @@ def __qtFunc__(it, foundQt, qmakePath): def __kitFunc__(it, foundQt, foundCompNames): global currentSelectedTreeItem, warningOrError - qtVersionStr = str(waitForObject(":Kits_QtVersion_QComboBox").currentText) + qtVersionStr = str(waitForObjectExists(":Kits_QtVersion_QComboBox").currentText) test.compare(it, "Desktop (default)", "Verifying whether default Desktop kit has been created.") if foundQt: test.compare(qtVersionStr, foundQt, "Verifying if Qt versions match.") From 06a754cc74d9969238ce81335877ef1b0efce68d Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 15 Mar 2021 15:14:08 +0100 Subject: [PATCH 13/22] Debugger: Add more information about the debugee when debugging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: QTCREATORBUG-25159 Change-Id: Ic462c8bb4d9f4f7163dbb9fcc13adce4c7172564 Reviewed-by: Leena Miettinen Reviewed-by: André Hartmann --- src/plugins/debugger/debuggerengine.cpp | 5 +++++ src/plugins/debugger/debuggerengine.h | 3 +++ src/plugins/debugger/debuggerruncontrol.cpp | 10 ++++++++-- src/plugins/debugger/gdb/gdbengine.cpp | 7 +++++-- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 656b4d9c0dc..7f306bb8a59 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -920,6 +920,11 @@ QString DebuggerEngine::stateName(int s) # undef SN } +void DebuggerEngine::notifyExitCode(int code) +{ + d->m_runParameters.exitCode = code; +} + void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const { showMessage(msg, StatusBar, timeout); diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index 50162002fde..59b0c26c059 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -197,6 +197,8 @@ public: Utils::MacroExpander *macroExpander = nullptr; + Utils::optional exitCode = {}; + // For Debugger testing. int testCase = 0; @@ -381,6 +383,7 @@ public: static QString stateName(int s); + void notifyExitCode(int code); void notifyInferiorPid(const Utils::ProcessHandle &pid); qint64 inferiorPid() const; diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index d10e13938a6..c350651acf4 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -738,7 +738,8 @@ void DebuggerRunTool::start() } } - appendMessage(tr("Debugging starts"), NormalMessageFormat); + appendMessage(tr("Debugging %1 ...").arg(m_runParameters.inferior.commandLine().toUserOutput()), + NormalMessageFormat); QString debuggerName = m_engine->objectName(); if (m_engine2) debuggerName += ' ' + m_engine2->objectName(); @@ -782,7 +783,12 @@ void DebuggerRunTool::handleEngineFinished(DebuggerEngine *engine) { engine->prepareForRestart(); if (--d->engineStopsNeeded == 0) { - appendMessage(tr("Debugging has finished"), NormalMessageFormat); + QString cmd = m_runParameters.inferior.commandLine().toUserOutput(); + QString msg = engine->runParameters().exitCode // Main engine. + ? tr("Debugging of %1 has finished with exit code %2.") + .arg(cmd).arg(engine->runParameters().exitCode.value()) + : tr("Debugging of %1 has finished.").arg(cmd); + appendMessage(msg, NormalMessageFormat); reportStopped(); } } diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 3d5c6c07188..df2d6511aa2 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1134,8 +1134,9 @@ void GdbEngine::handleStopResponse(const GdbMi &data) // qDebug() << state()); QString msg; if (reason == "exited") { - msg = tr("Application exited with exit code %1") - .arg(data["exit-code"].toString()); + const int exitCode = data["exit-code"].toInt(); + notifyExitCode(exitCode); + msg = tr("Application exited with exit code %1").arg(exitCode); } else if (reason == "exited-signalled" || reason == "signal-received") { msg = tr("Application exited after receiving signal %1") .arg(data["signal-name"].toString()); @@ -1712,6 +1713,8 @@ void GdbEngine::handleThreadGroupExited(const GdbMi &result) { QString groupId = result["id"].data(); if (threadsHandler()->notifyGroupExited(groupId)) { + const int exitCode = result["exit-code"].toInt(); + notifyExitCode(exitCode); if (m_rerunPending) m_rerunPending = false; else From 2756794b4fd7cdae60026cf2a8031fcca1578c95 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 15 Mar 2021 10:31:40 +0100 Subject: [PATCH 14/22] Utils: Drop deprecated Utils::FilePath::{setFilePath,filePath} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I730dfb716f744bbcb62dedf611e93c0d2d358247 Reviewed-by: Thomas Hartmann Reviewed-by: Robert Löhning Reviewed-by: Eike Ziller --- src/libs/utils/pathchooser.h | 4 ---- src/plugins/android/androidsettingswidget.cpp | 2 +- src/plugins/cvs/settingspage.cpp | 2 +- .../mesonprojectmanager/settings/tools/toolitemsettings.cpp | 2 +- .../qmldesigner/assetexporterplugin/assetexportdialog.cpp | 4 ++-- src/plugins/subversion/settingspage.cpp | 2 +- 6 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index 2b00bb3ba4e..3b4a83095ca 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -153,8 +153,6 @@ public: // Deprecated. Use filePath().toString() or better suitable conversions. QString path() const { return filePath().toString(); } - // Deprecated. Use filePath() - FilePath fileName() const { return filePath(); } // this sets the placeHolderText to defaultValue and enables to use this as // input value during validation if the real value is empty @@ -179,8 +177,6 @@ signals: public slots: void setPath(const QString &); - // Deprecated: Use setFilePath() - void setFileName(const FilePath &path) { setFilePath(path); } void setFilePath(const FilePath &); private: diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index fd25d12ae1d..51b837af0f7 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -600,7 +600,7 @@ void AndroidSettingsWidget::onSdkPathChanged() FilePath currentOpenSslPath = m_androidConfig.openSslLocation(); if (currentOpenSslPath.isEmpty() || !currentOpenSslPath.exists()) currentOpenSslPath = sdkPath.pathAppended("android_openssl"); - m_ui.openSslPathChooser->setFileName(currentOpenSslPath); + m_ui.openSslPathChooser->setFilePath(currentOpenSslPath); // Package reload will trigger validateSdk. m_sdkManager.reloadPackages(); } diff --git a/src/plugins/cvs/settingspage.cpp b/src/plugins/cvs/settingspage.cpp index 8aae51fa590..82f9cad8863 100644 --- a/src/plugins/cvs/settingspage.cpp +++ b/src/plugins/cvs/settingspage.cpp @@ -64,7 +64,7 @@ CvsSettingsPageWidget::CvsSettingsPageWidget(const std::function &onAppl m_ui.commandPathChooser->setPromptDialogTitle(tr("CVS Command")); const VcsBaseClientSettings &s = *settings; - m_ui.commandPathChooser->setFileName(s.binaryPath()); + m_ui.commandPathChooser->setFilePath(s.binaryPath()); m_ui.rootLineEdit->setText(s.stringValue(CvsSettings::cvsRootKey)); m_ui.diffOptionsLineEdit->setText(s.stringValue(CvsSettings::diffOptionsKey)); m_ui.timeOutSpinBox->setValue(s.intValue(CvsSettings::timeoutKey)); diff --git a/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.cpp b/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.cpp index 2bf9b22648f..a1ba99d360c 100644 --- a/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.cpp +++ b/src/plugins/mesonprojectmanager/settings/tools/toolitemsettings.cpp @@ -57,7 +57,7 @@ void ToolItemSettings::load(ToolTreeItem *item) ui->mesonNameLineEdit->setDisabled(item->isAutoDetected()); ui->mesonNameLineEdit->setText(item->name()); ui->mesonPathChooser->setDisabled(item->isAutoDetected()); - ui->mesonPathChooser->setFileName(item->executable()); + ui->mesonPathChooser->setFilePath(item->executable()); m_currentId = item->id(); } else { m_currentId = Utils::nullopt; diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp index 86c9d53b41c..0c6a8a46f78 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp @@ -80,7 +80,7 @@ AssetExportDialog::AssetExportDialog(const Utils::FilePath &exportPath, { m_ui->setupUi(this); - m_ui->exportPath->setFileName(exportPath); + m_ui->exportPath->setFilePath(exportPath); m_ui->exportPath->setPromptDialogTitle(tr("Choose Export Path")); m_ui->exportPath->lineEdit()->setReadOnly(true); m_ui->exportPath->addButton(tr("Open"), this, [this]() { @@ -153,7 +153,7 @@ void AssetExportDialog::onExport() TaskHub::clearTasks(Constants::TASK_CATEGORY_ASSET_EXPORT); m_exportLogs->clear(); - m_assetExporter.exportQml(m_filePathModel.files(), m_ui->exportPath->fileName(), + m_assetExporter.exportQml(m_filePathModel.files(), m_ui->exportPath->filePath(), m_exportAssetsCheck->isChecked(), m_perComponentExportCheck->isChecked()); } diff --git a/src/plugins/subversion/settingspage.cpp b/src/plugins/subversion/settingspage.cpp index e714dfcde9a..2ee4aaad5c4 100644 --- a/src/plugins/subversion/settingspage.cpp +++ b/src/plugins/subversion/settingspage.cpp @@ -69,7 +69,7 @@ SubversionSettingsPageWidget::SubversionSettingsPageWidget(const std::functionsetPromptDialogTitle(tr("Subversion Command")); SubversionSettings &s = *m_settings; - m_ui.pathChooser->setFileName(s.binaryPath()); + m_ui.pathChooser->setFilePath(s.binaryPath()); m_ui.usernameLineEdit->setText(s.stringValue(SubversionSettings::userKey)); m_ui.passwordLineEdit->setText(s.stringValue(SubversionSettings::passwordKey)); m_ui.userGroupBox->setChecked(s.boolValue(SubversionSettings::useAuthenticationKey)); From 8400a3d6e39b3efeb31468cd6a8e6346a812d44f Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Thu, 4 Mar 2021 12:32:08 +0100 Subject: [PATCH 15/22] iOS: Refactor the ios tool Move classes into logical compilation units Task-number: QTCREATORBUG-24672 Change-Id: Ia7c0866fa16dca0df05fc70418f8142ff74a5d59 Reviewed-by: hjk Reviewed-by: Eike Ziller --- src/tools/iostool/CMakeLists.txt | 7 +- src/tools/iostool/gdbrunner.cpp | 73 ++ src/tools/iostool/gdbrunner.h | 48 ++ src/tools/iostool/iosdevicemanager.cpp | 512 +------------- src/tools/iostool/iosdevicemanager.h | 13 +- src/tools/iostool/iostool.cpp | 432 ++++++++++++ src/tools/iostool/iostool.h | 88 +++ src/tools/iostool/iostool.pro | 13 +- src/tools/iostool/iostool.qbs | 13 +- src/tools/iostool/iostooltypes.h | 38 ++ src/tools/iostool/main.cpp | 912 +------------------------ src/tools/iostool/mobiledevicelib.cpp | 350 ++++++++++ src/tools/iostool/mobiledevicelib.h | 184 +++++ src/tools/iostool/relayserver.cpp | 342 ++++++++++ src/tools/iostool/relayserver.h | 136 ++++ 15 files changed, 1750 insertions(+), 1411 deletions(-) create mode 100644 src/tools/iostool/gdbrunner.cpp create mode 100644 src/tools/iostool/gdbrunner.h create mode 100644 src/tools/iostool/iostool.cpp create mode 100644 src/tools/iostool/iostool.h create mode 100644 src/tools/iostool/iostooltypes.h create mode 100644 src/tools/iostool/mobiledevicelib.cpp create mode 100644 src/tools/iostool/mobiledevicelib.h create mode 100644 src/tools/iostool/relayserver.cpp create mode 100644 src/tools/iostool/relayserver.h diff --git a/src/tools/iostool/CMakeLists.txt b/src/tools/iostool/CMakeLists.txt index 8e465e56b6f..230f5b91f43 100644 --- a/src/tools/iostool/CMakeLists.txt +++ b/src/tools/iostool/CMakeLists.txt @@ -11,8 +11,13 @@ add_qtc_executable(iostool ${FWSystemConfiguration} SOURCES Info.plist - main.cpp + gdbrunner.cpp gdbrunner.h iosdevicemanager.cpp iosdevicemanager.h + iostool.cpp iostool.h + iostooltypes.h + main.cpp + mobiledevicelib.cpp mobiledevicelib.h + relayserver.cpp relayserver.h ) if (TARGET iostool) diff --git a/src/tools/iostool/gdbrunner.cpp b/src/tools/iostool/gdbrunner.cpp new file mode 100644 index 00000000000..1234a472c3f --- /dev/null +++ b/src/tools/iostool/gdbrunner.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 "gdbrunner.h" + +#include "iostool.h" + +#ifdef Q_OS_UNIX +#include +#include +#endif + +namespace Ios { + +GdbRunner::GdbRunner(IosTool *iosTool, int gdbFd) : + QObject(nullptr), + m_iosTool(iosTool), + m_gdbFd(gdbFd) +{ +} + +void GdbRunner::run() +{ + { + QMutexLocker l(&m_iosTool->m_xmlMutex); + if (!m_iosTool->splitAppOutput) { + m_iosTool->out.writeStartElement(QLatin1String("app_output")); + m_iosTool->inAppOutput = true; + } + m_iosTool->outFile.flush(); + } + Ios::IosDeviceManager::instance()->processGdbServer(m_gdbFd); + { + QMutexLocker l(&m_iosTool->m_xmlMutex); + if (!m_iosTool->splitAppOutput) { + m_iosTool->inAppOutput = false; + m_iosTool->out.writeEndElement(); + } + m_iosTool->outFile.flush(); + } + close(m_gdbFd); + m_iosTool->doExit(); + emit finished(); +} + +void GdbRunner::stop(int phase) +{ + Ios::IosDeviceManager::instance()->stopGdbServer(m_gdbFd, phase); +} + +} diff --git a/src/tools/iostool/gdbrunner.h b/src/tools/iostool/gdbrunner.h new file mode 100644 index 00000000000..27eea4beaf4 --- /dev/null +++ b/src/tools/iostool/gdbrunner.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 + +namespace Ios { +class IosTool; +class GdbRunner: public QObject +{ + Q_OBJECT + +public: + GdbRunner(IosTool *iosTool, int gdbFd); + void stop(int phase); + void run(); + +signals: + void finished(); + +private: + IosTool *m_iosTool; + int m_gdbFd; +}; +} diff --git a/src/tools/iostool/iosdevicemanager.cpp b/src/tools/iostool/iosdevicemanager.cpp index 7003710d9d1..1d9b1874ce1 100644 --- a/src/tools/iostool/iosdevicemanager.cpp +++ b/src/tools/iostool/iosdevicemanager.cpp @@ -24,45 +24,27 @@ ****************************************************************************/ #include "iosdevicemanager.h" -#include + +#include "mobiledevicelib.h" + #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* // annoying to import, do without -#include -*/ -/* standard calling convention under Win32 is __stdcall */ -/* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */ -/* _WIN32 symbol is defined by the compiler even though it's NOT compiling code for Windows32 */ -#if defined(_WIN32) && !defined(EFI32) && !defined(EFI64) -#define MDEV_API __stdcall -#else -#define MDEV_API -#endif - -#include -#include -#include -#include - #include #include +#include +#include +#include #include #include +#include +#include +#include +#include +#include #include -#ifdef MOBILE_DEV_DIRECT_LINK -#include "MobileDevice.h" -#endif +#include + +#include static const bool debugGdbServer = false; static const bool debugAll = false; @@ -82,72 +64,7 @@ enum ADNCI_MSG { }; #endif -extern "C" { -typedef unsigned int ServiceSocket; // match_port_t (i.e. natural_t) or socket (on windows, i.e sock_t) -typedef unsigned int *ServiceConnRef; -typedef unsigned int am_res_t; // mach_error_t -#ifndef MOBILE_DEV_DIRECT_LINK -class AMDeviceNotification; -typedef const AMDeviceNotification *AMDeviceNotificationRef; -class AMDevice; - -struct AMDeviceNotificationCallbackInfo { - AMDevice *_device; - unsigned int _message; - AMDeviceNotification *_subscription; -}; - -enum DeviceInterfaceType { - UNKNOWN = 0, - WIRED, - WIFI -}; - -typedef void (MDEV_API *AMDeviceNotificationCallback)(AMDeviceNotificationCallbackInfo *, void *); -typedef am_res_t (MDEV_API *AMDeviceInstallApplicationCallback)(CFDictionaryRef, void *); -typedef mach_error_t (MDEV_API *AMDeviceSecureInstallApplicationCallback)(CFDictionaryRef, int); - - -typedef AMDevice *AMDeviceRef; -#endif -typedef void (MDEV_API *AMDeviceMountImageCallback)(CFDictionaryRef, int); - - - -typedef void (MDEV_API *AMDSetLogLevelPtr)(int); -typedef am_res_t (MDEV_API *AMDeviceNotificationSubscribePtr)(AMDeviceNotificationCallback, - unsigned int, unsigned int, void *, - const AMDeviceNotification **); -typedef am_res_t (MDEV_API *AMDeviceNotificationUnsubscribePtr)(void *); -typedef int (MDEV_API* AMDeviceGetInterfaceTypePtr)(AMDeviceRef device); -typedef CFPropertyListRef (MDEV_API *AMDeviceCopyValuePtr)(AMDeviceRef,CFStringRef,CFStringRef); -typedef unsigned int (MDEV_API *AMDeviceGetConnectionIDPtr)(AMDeviceRef); -typedef CFStringRef (MDEV_API *AMDeviceCopyDeviceIdentifierPtr)(AMDeviceRef); -typedef am_res_t (MDEV_API *AMDeviceConnectPtr)(AMDeviceRef); -typedef am_res_t (MDEV_API *AMDevicePairPtr)(AMDeviceRef); -typedef am_res_t (MDEV_API *AMDeviceIsPairedPtr)(AMDeviceRef); -typedef am_res_t (MDEV_API *AMDeviceValidatePairingPtr)(AMDeviceRef); -typedef am_res_t (MDEV_API *AMDeviceStartSessionPtr)(AMDeviceRef); -typedef am_res_t (MDEV_API *AMDeviceStopSessionPtr)(AMDeviceRef); -typedef am_res_t (MDEV_API *AMDeviceDisconnectPtr)(AMDeviceRef); -typedef am_res_t (MDEV_API *AMDeviceMountImagePtr)(AMDeviceRef, CFStringRef, CFDictionaryRef, - AMDeviceMountImageCallback, void *); -typedef am_res_t (MDEV_API *AMDeviceUninstallApplicationPtr)(ServiceSocket, CFStringRef, CFDictionaryRef, - AMDeviceInstallApplicationCallback, - void*); -typedef am_res_t (MDEV_API *AMDeviceLookupApplicationsPtr)(AMDeviceRef, CFDictionaryRef, CFDictionaryRef *); -typedef char * (MDEV_API *AMDErrorStringPtr)(am_res_t); -typedef CFStringRef (MDEV_API *MISCopyErrorStringForErrorCodePtr)(am_res_t); -typedef am_res_t (MDEV_API *USBMuxConnectByPortPtr)(unsigned int, int, ServiceSocket*); -// secure Api's -typedef am_res_t (MDEV_API *AMDeviceSecureStartServicePtr)(AMDeviceRef, CFStringRef, unsigned int *, ServiceConnRef *); -typedef int (MDEV_API *AMDeviceSecureTransferPathPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int); -typedef int (MDEV_API *AMDeviceSecureInstallApplicationPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int); -typedef int (MDEV_API *AMDServiceConnectionGetSocketPtr)(ServiceConnRef); - - -} // extern C } // anonymous namespace @@ -155,82 +72,9 @@ namespace Ios { namespace Internal { static const am_res_t kAMDMobileImageMounterImageMountFailed = 0xe8000076; +static const QString DebugServiceName = "com.apple.debugserver"; +static const QString DebugSecureServiceName = "com.apple.debugserver.DVTSecureSocketProxy"; -class MobileDeviceLib { -public : - MobileDeviceLib(); - - bool load(); - bool isLoaded(); - QStringList errors(); -// - - void setLogLevel(int i) ; - am_res_t deviceNotificationSubscribe(AMDeviceNotificationCallback callback, - unsigned int v1, unsigned int v2, void *v3, - const AMDeviceNotification **handle); - am_res_t deviceNotificationUnsubscribe(void *handle); - int deviceGetInterfaceType(AMDeviceRef device); - CFPropertyListRef deviceCopyValue(AMDeviceRef,CFStringRef,CFStringRef); - unsigned int deviceGetConnectionID(AMDeviceRef); - CFStringRef deviceCopyDeviceIdentifier(AMDeviceRef); - am_res_t deviceConnect(AMDeviceRef); - am_res_t devicePair(AMDeviceRef); - am_res_t deviceIsPaired(AMDeviceRef); - am_res_t deviceValidatePairing(AMDeviceRef); - am_res_t deviceStartSession(AMDeviceRef); - am_res_t deviceStopSession(AMDeviceRef); - am_res_t deviceDisconnect(AMDeviceRef); - am_res_t deviceMountImage(AMDeviceRef, CFStringRef, CFDictionaryRef, - AMDeviceMountImageCallback, void *); - am_res_t deviceUninstallApplication(int, CFStringRef, CFDictionaryRef, - AMDeviceInstallApplicationCallback, - void*); - am_res_t deviceLookupApplications(AMDeviceRef, CFDictionaryRef, CFDictionaryRef *); - char *errorString(am_res_t error); - CFStringRef misErrorStringForErrorCode(am_res_t error); - am_res_t connectByPort(unsigned int connectionId, int port, ServiceSocket *resFd); - - void addError(const QString &msg); - void addError(const char *msg); - - // Secure API's - am_res_t deviceSecureStartService(AMDeviceRef, CFStringRef, ServiceConnRef *); - int deviceConnectionGetSocket(ServiceConnRef); - int deviceSecureTransferApplicationPath(int, AMDeviceRef, CFURLRef, - CFDictionaryRef, AMDeviceSecureInstallApplicationCallback callback, int); - int deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, - CFDictionaryRef options, AMDeviceSecureInstallApplicationCallback callback, int arg); - - QStringList m_errors; -private: - QLibrary lib; - QList deps; - AMDSetLogLevelPtr m_AMDSetLogLevel; - AMDeviceNotificationSubscribePtr m_AMDeviceNotificationSubscribe; - AMDeviceNotificationUnsubscribePtr m_AMDeviceNotificationUnsubscribe; - AMDeviceGetInterfaceTypePtr m_AMDeviceGetInterfaceType; - AMDeviceCopyValuePtr m_AMDeviceCopyValue; - AMDeviceGetConnectionIDPtr m_AMDeviceGetConnectionID; - AMDeviceCopyDeviceIdentifierPtr m_AMDeviceCopyDeviceIdentifier; - AMDeviceConnectPtr m_AMDeviceConnect; - AMDevicePairPtr m_AMDevicePair; - AMDeviceIsPairedPtr m_AMDeviceIsPaired; - AMDeviceValidatePairingPtr m_AMDeviceValidatePairing; - AMDeviceStartSessionPtr m_AMDeviceStartSession; - AMDeviceStopSessionPtr m_AMDeviceStopSession; - AMDeviceDisconnectPtr m_AMDeviceDisconnect; - AMDeviceMountImagePtr m_AMDeviceMountImage; - AMDeviceSecureStartServicePtr m_AMDeviceSecureStartService; - AMDeviceSecureTransferPathPtr m_AMDeviceSecureTransferPath; - AMDeviceSecureInstallApplicationPtr m_AMDeviceSecureInstallApplication; - AMDServiceConnectionGetSocketPtr m_AMDServiceConnectionGetSocket; - AMDeviceUninstallApplicationPtr m_AMDeviceUninstallApplication; - AMDeviceLookupApplicationsPtr m_AMDeviceLookupApplications; - AMDErrorStringPtr m_AMDErrorString; - MISCopyErrorStringForErrorCodePtr m_MISCopyErrorStringForErrorCode; - USBMuxConnectByPortPtr m_USBMuxConnectByPort; -}; static QString mobileDeviceErrorString(MobileDeviceLib *lib, am_res_t code) { @@ -262,7 +106,7 @@ static QString mobileDeviceErrorString(MobileDeviceLib *lib, am_res_t code) return s; } -qint64 toBuildNumber(const QString &versionStr) +static qint64 toBuildNumber(const QString &versionStr) { QString buildNumber; const QRegularExpression re("\\s\\((\\X+)\\)"); @@ -498,7 +342,7 @@ DeviceSession::~DeviceSession() namespace { // ------- callbacks -------- -extern "C" void deviceNotificationCallback(AMDeviceNotificationCallbackInfo *info, void *user) +extern "C" void deviceNotificationCallback(Ios::AMDeviceNotificationCallbackInfo *info, void *user) { if (info == 0) Ios::Internal::IosDeviceManagerPrivate::instance()->addError(QLatin1String("null info in deviceNotificationCallback")); @@ -526,7 +370,7 @@ extern "C" void deviceNotificationCallback(AMDeviceNotificationCallbackInfo *inf } } -extern "C" void deviceAvailableSessionCallback(QString deviceId, AMDeviceRef device, void *userData) +extern "C" void deviceAvailableSessionCallback(QString deviceId, Ios::AMDeviceRef device, void *userData) { if (debugAll) qDebug() << "deviceAvailableSessionCallback" << QThread::currentThread(); @@ -538,7 +382,7 @@ extern "C" void deviceAvailableSessionCallback(QString deviceId, AMDeviceRef dev session->internalDeviceAvailableCallback(deviceId, device); } -extern "C" am_res_t appTransferSessionCallback(CFDictionaryRef dict, void *userData) +extern "C" Ios::am_res_t appTransferSessionCallback(CFDictionaryRef dict, void *userData) { if (debugAll) { qDebug() << "appTransferSessionCallback" << QThread::currentThread(); @@ -584,7 +428,7 @@ extern "C" mach_error_t appSecureTransferSessionCallback(CFDictionaryRef dict, i return 0; } -extern "C" am_res_t appInstallSessionCallback(CFDictionaryRef dict, void *userData) +extern "C" Ios::am_res_t appInstallSessionCallback(CFDictionaryRef dict, void *userData) { if (debugAll) { qDebug() << "appInstallSessionCallback" << QThread::currentThread(); @@ -616,9 +460,10 @@ bool IosDeviceManagerPrivate::watchDevices() { if (!m_lib.load()) addError(QLatin1String("Error loading MobileDevice.framework")); - if (!m_lib.errors().isEmpty()) + if (!m_lib.errors().isEmpty()) { foreach (const QString &msg, m_lib.errors()) addError(msg); + } m_lib.setLogLevel(5); am_res_t e = m_lib.deviceNotificationSubscribe(&deviceNotificationCallback, 0, 0, 0, &m_notification); @@ -1655,318 +1500,7 @@ void DevInfoSession::deviceCallbackReturned() // ------- MobileDeviceLib implementation -------- -MobileDeviceLib::MobileDeviceLib() { } -bool MobileDeviceLib::load() -{ -#ifdef MOBILE_DEV_DIRECT_LINK - m_AMDSetLogLevel = &AMDSetLogLevel; - m_AMDeviceNotificationSubscribe = &AMDeviceNotificationSubscribe; - //m_AMDeviceNotificationUnsubscribe = &AMDeviceNotificationUnsubscribe; - m_AMDeviceCopyValue = &AMDeviceCopyValue; - m_AMDeviceGetConnectionID = &AMDeviceGetConnectionID; - m_AMDeviceCopyDeviceIdentifier = &AMDeviceCopyDeviceIdentifier; - m_AMDeviceConnect = &AMDeviceConnect; - //m_AMDevicePair = &AMDevicePair; - m_AMDeviceIsPaired = &AMDeviceIsPaired; - m_AMDeviceValidatePairing = &AMDeviceValidatePairing; - m_AMDeviceStartSession = &AMDeviceStartSession; - m_AMDeviceStopSession = &AMDeviceStopSession; - m_AMDeviceDisconnect = &AMDeviceDisconnect; - m_AMDeviceMountImage = &AMDeviceMountImage; - m_AMDeviceStartService = &AMDeviceStartService; - m_AMDeviceTransferApplication = &AMDeviceTransferApplication; - m_AMDeviceInstallApplication = &AMDeviceInstallApplication; - //m_AMDeviceUninstallApplication = &AMDeviceUninstallApplication; - //m_AMDeviceLookupApplications = &AMDeviceLookupApplications; - m_USBMuxConnectByPort = &USBMuxConnectByPort; -#else - QLibrary *libAppleFSCompression = new QLibrary(QLatin1String("/System/Library/PrivateFrameworks/AppleFSCompression.framework/AppleFSCompression")); - if (!libAppleFSCompression->load()) - addError("MobileDevice dependency AppleFSCompression failed to load"); - deps << libAppleFSCompression; - QLibrary *libBom = new QLibrary(QLatin1String("/System/Library/PrivateFrameworks/Bom.framework/Bom")); - if (!libBom->load()) - addError("MobileDevice dependency Bom failed to load"); - deps << libBom; - lib.setFileName(QLatin1String("/System/Library/PrivateFrameworks/MobileDevice.framework/MobileDevice")); - if (!lib.load()) - return false; - m_AMDSetLogLevel = reinterpret_cast(lib.resolve("AMDSetLogLevel")); - if (m_AMDSetLogLevel == 0) - addError("MobileDeviceLib does not define AMDSetLogLevel"); - m_AMDeviceNotificationSubscribe = reinterpret_cast(lib.resolve("AMDeviceNotificationSubscribe")); - if (m_AMDeviceNotificationSubscribe == 0) - addError("MobileDeviceLib does not define AMDeviceNotificationSubscribe"); - m_AMDeviceNotificationUnsubscribe = reinterpret_cast(lib.resolve("AMDeviceNotificationUnsubscribe")); - if (m_AMDeviceNotificationUnsubscribe == 0) - addError("MobileDeviceLib does not define AMDeviceNotificationUnsubscribe"); - m_AMDeviceGetInterfaceType = reinterpret_cast(lib.resolve("AMDeviceGetInterfaceType")); - if (m_AMDeviceGetInterfaceType == 0) - addError("MobileDeviceLib does not define AMDeviceGetInterfaceType"); - m_AMDeviceCopyValue = reinterpret_cast(lib.resolve("AMDeviceCopyValue")); - if (m_AMDSetLogLevel == 0) - addError("MobileDeviceLib does not define AMDSetLogLevel"); - m_AMDeviceGetConnectionID = reinterpret_cast(lib.resolve("AMDeviceGetConnectionID")); - if (m_AMDeviceGetConnectionID == 0) - addError("MobileDeviceLib does not define AMDeviceGetConnectionID"); - m_AMDeviceCopyDeviceIdentifier = reinterpret_cast(lib.resolve("AMDeviceCopyDeviceIdentifier")); - if (m_AMDeviceCopyDeviceIdentifier == 0) - addError("MobileDeviceLib does not define AMDeviceCopyDeviceIdentifier"); - m_AMDeviceConnect = reinterpret_cast(lib.resolve("AMDeviceConnect")); - if (m_AMDeviceConnect == 0) - addError("MobileDeviceLib does not define AMDeviceConnect"); - m_AMDevicePair = reinterpret_cast(lib.resolve("AMDevicePair")); - if (m_AMDevicePair == 0) - addError("MobileDeviceLib does not define AMDevicePair"); - m_AMDeviceIsPaired = reinterpret_cast(lib.resolve("AMDeviceIsPaired")); - if (m_AMDeviceIsPaired == 0) - addError("MobileDeviceLib does not define AMDeviceIsPaired"); - m_AMDeviceValidatePairing = reinterpret_cast(lib.resolve("AMDeviceValidatePairing")); - if (m_AMDeviceValidatePairing == 0) - addError("MobileDeviceLib does not define AMDeviceValidatePairing"); - m_AMDeviceStartSession = reinterpret_cast(lib.resolve("AMDeviceStartSession")); - if (m_AMDeviceStartSession == 0) - addError("MobileDeviceLib does not define AMDeviceStartSession"); - m_AMDeviceStopSession = reinterpret_cast(lib.resolve("AMDeviceStopSession")); - if (m_AMDeviceStopSession == 0) - addError("MobileDeviceLib does not define AMDeviceStopSession"); - m_AMDeviceDisconnect = reinterpret_cast(lib.resolve("AMDeviceDisconnect")); - if (m_AMDeviceDisconnect == 0) - addError("MobileDeviceLib does not define AMDeviceDisconnect"); - m_AMDeviceMountImage = reinterpret_cast(lib.resolve("AMDeviceMountImage")); - if (m_AMDeviceMountImage == 0) - addError("MobileDeviceLib does not define AMDeviceMountImage"); - m_AMDeviceSecureStartService = reinterpret_cast(lib.resolve("AMDeviceSecureStartService")); - if (m_AMDeviceSecureStartService == 0) - addError("MobileDeviceLib does not define AMDeviceSecureStartService"); - m_AMDeviceSecureTransferPath = reinterpret_cast(lib.resolve("AMDeviceSecureTransferPath")); - if (m_AMDeviceSecureTransferPath == 0) - addError("MobileDeviceLib does not define AMDeviceSecureTransferPath"); - m_AMDeviceSecureInstallApplication = reinterpret_cast(lib.resolve("AMDeviceSecureInstallApplication")); - if (m_AMDeviceSecureInstallApplication == 0) - addError("MobileDeviceLib does not define AMDeviceSecureInstallApplication"); - m_AMDServiceConnectionGetSocket = reinterpret_cast(lib.resolve("AMDServiceConnectionGetSocket")); - if (m_AMDServiceConnectionGetSocket == nullptr) - addError("MobileDeviceLib does not define AMDServiceConnectionGetSocket"); - m_AMDeviceUninstallApplication = reinterpret_cast(lib.resolve("AMDeviceUninstallApplication")); - if (m_AMDeviceUninstallApplication == 0) - addError("MobileDeviceLib does not define AMDeviceUninstallApplication"); - m_AMDeviceLookupApplications = reinterpret_cast(lib.resolve("AMDeviceLookupApplications")); - if (m_AMDeviceLookupApplications == 0) - addError("MobileDeviceLib does not define AMDeviceLookupApplications"); - m_AMDErrorString = reinterpret_cast(lib.resolve("AMDErrorString")); - if (m_AMDErrorString == 0) - addError("MobileDeviceLib does not define AMDErrorString"); - m_MISCopyErrorStringForErrorCode = reinterpret_cast(lib.resolve("MISCopyErrorStringForErrorCode")); - if (m_MISCopyErrorStringForErrorCode == 0) - addError("MobileDeviceLib does not define MISCopyErrorStringForErrorCode"); - m_USBMuxConnectByPort = reinterpret_cast(lib.resolve("USBMuxConnectByPort")); - if (m_USBMuxConnectByPort == 0) - addError("MobileDeviceLib does not define USBMuxConnectByPort"); -#endif - return true; -} - -bool MobileDeviceLib::isLoaded() -{ - return lib.isLoaded(); -} - -QStringList MobileDeviceLib::errors() -{ - return m_errors; -} - -void MobileDeviceLib::setLogLevel(int i) -{ - if (m_AMDSetLogLevel) - m_AMDSetLogLevel(i); -} - -am_res_t MobileDeviceLib::deviceNotificationSubscribe(AMDeviceNotificationCallback callback, - unsigned int v1, unsigned int v2, void *callbackArgs, - const AMDeviceNotification **handle) -{ - if (m_AMDeviceNotificationSubscribe) - return m_AMDeviceNotificationSubscribe(callback,v1,v2,callbackArgs,handle); - return -1; -} - -am_res_t MobileDeviceLib::deviceNotificationUnsubscribe(void *handle) -{ - if (m_AMDeviceNotificationUnsubscribe) - return m_AMDeviceNotificationUnsubscribe(handle); - return -1; -} - -int MobileDeviceLib::deviceGetInterfaceType(AMDeviceRef device) -{ - if (m_AMDeviceGetInterfaceType) - return m_AMDeviceGetInterfaceType(device); - return DeviceInterfaceType::UNKNOWN; -} - -CFPropertyListRef MobileDeviceLib::deviceCopyValue(AMDeviceRef device,CFStringRef group,CFStringRef key) -{ - if (m_AMDeviceCopyValue) - return m_AMDeviceCopyValue(device, group, key); - return 0; -} - -unsigned int MobileDeviceLib::deviceGetConnectionID(AMDeviceRef device) -{ - if (m_AMDeviceGetConnectionID) - return m_AMDeviceGetConnectionID(device); - return -1; -} - -CFStringRef MobileDeviceLib::deviceCopyDeviceIdentifier(AMDeviceRef device) -{ - if (m_AMDeviceCopyDeviceIdentifier) - return m_AMDeviceCopyDeviceIdentifier(device); - return 0; -} - -am_res_t MobileDeviceLib::deviceConnect(AMDeviceRef device) -{ - if (m_AMDeviceConnect) - return m_AMDeviceConnect(device); - return -1; -} - -am_res_t MobileDeviceLib::devicePair(AMDeviceRef device) -{ - if (m_AMDevicePair) - return m_AMDevicePair(device); - return -1; -} - -am_res_t MobileDeviceLib::deviceIsPaired(AMDeviceRef device) -{ - if (m_AMDeviceIsPaired) - return m_AMDeviceIsPaired(device); - return -1; -} - -am_res_t MobileDeviceLib::deviceValidatePairing(AMDeviceRef device) -{ - if (m_AMDeviceValidatePairing) - return m_AMDeviceValidatePairing(device); - return -1; -} - -am_res_t MobileDeviceLib::deviceStartSession(AMDeviceRef device) -{ - if (m_AMDeviceStartSession) - return m_AMDeviceStartSession(device); - return -1; -} - -am_res_t MobileDeviceLib::deviceStopSession(AMDeviceRef device) -{ - if (m_AMDeviceStopSession) - return m_AMDeviceStopSession(device); - return -1; -} - -am_res_t MobileDeviceLib::deviceDisconnect(AMDeviceRef device) -{ - if (m_AMDeviceDisconnect) - return m_AMDeviceDisconnect(device); - return -1; -} - -am_res_t MobileDeviceLib::deviceMountImage(AMDeviceRef device, CFStringRef imagePath, - CFDictionaryRef options, - AMDeviceMountImageCallback callback, - void *callbackExtraArgs) -{ - if (m_AMDeviceMountImage) - return m_AMDeviceMountImage(device, imagePath, options, callback, callbackExtraArgs); - return -1; -} - -am_res_t MobileDeviceLib::deviceUninstallApplication(int serviceFd, CFStringRef bundleId, - CFDictionaryRef options, - AMDeviceInstallApplicationCallback callback, - void *callbackExtraArgs) -{ - if (m_AMDeviceUninstallApplication) - return m_AMDeviceUninstallApplication(serviceFd, bundleId, options, callback, callbackExtraArgs); - return -1; -} - -am_res_t MobileDeviceLib::deviceLookupApplications(AMDeviceRef device, CFDictionaryRef options, - CFDictionaryRef *res) -{ - if (m_AMDeviceLookupApplications) - return m_AMDeviceLookupApplications(device, options, res); - return -1; -} - -char *MobileDeviceLib::errorString(am_res_t error) -{ - if (m_AMDErrorString) - return m_AMDErrorString(error); - return 0; -} - -CFStringRef MobileDeviceLib::misErrorStringForErrorCode(am_res_t error) -{ - if (m_MISCopyErrorStringForErrorCode) - return m_MISCopyErrorStringForErrorCode(error); - return NULL; -} - -am_res_t MobileDeviceLib::connectByPort(unsigned int connectionId, int port, ServiceSocket *resFd) -{ - if (m_USBMuxConnectByPort) - return m_USBMuxConnectByPort(connectionId, port, resFd); - return -1; -} - -void MobileDeviceLib::addError(const QString &msg) -{ - qDebug() << "MobileDeviceLib ERROR:" << msg; - m_errors << QLatin1String("MobileDeviceLib ERROR:") << msg; -} - -void MobileDeviceLib::addError(const char *msg) -{ - addError(QLatin1String(msg)); -} - -am_res_t MobileDeviceLib::deviceSecureStartService(AMDeviceRef device, CFStringRef serviceName, ServiceConnRef *fdRef) -{ - if (m_AMDeviceSecureStartService) - return m_AMDeviceSecureStartService(device, serviceName, nullptr, fdRef); - return 0; -} - -int MobileDeviceLib::deviceSecureTransferApplicationPath(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef dict, AMDeviceSecureInstallApplicationCallback callback, int args) -{ - int returnCode = -1; - if (m_AMDeviceSecureTransferPath) - returnCode = m_AMDeviceSecureTransferPath(zero, device, url, dict, callback, args); - return returnCode; -} - -int MobileDeviceLib::deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, AMDeviceSecureInstallApplicationCallback callback, int arg) -{ - int returnCode = -1; - if (m_AMDeviceSecureInstallApplication) { - returnCode = m_AMDeviceSecureInstallApplication(zero, device, url, options, callback, arg); - } - return returnCode; -} - -int MobileDeviceLib::deviceConnectionGetSocket(ServiceConnRef ref) { - int fd = 0; - if (m_AMDServiceConnectionGetSocket) - fd = m_AMDServiceConnectionGetSocket(ref); - return fd; -} void CommandSession::internalDeviceAvailableCallback(QString deviceId, AMDeviceRef device) { diff --git a/src/tools/iostool/iosdevicemanager.h b/src/tools/iostool/iosdevicemanager.h index 5d6c489b7d6..a16403010a9 100644 --- a/src/tools/iostool/iosdevicemanager.h +++ b/src/tools/iostool/iosdevicemanager.h @@ -25,17 +25,12 @@ #pragma once +#include "iostooltypes.h" + #include #include #include #include -#include -#include -#include -#include -#include - -#include namespace Ios { namespace Internal { @@ -43,13 +38,13 @@ class DevInfoSession; class IosDeviceManagerPrivate; } // namespace Internal -typedef unsigned int ServiceSocket; class DeviceSession; class IosDeviceManager : public QObject { Q_OBJECT + public: typedef QMap Dict; enum OpStatus { @@ -72,6 +67,7 @@ public: int processGdbServer(int fd); void stopGdbServer(int fd, int phase); QStringList errors(); + signals: void deviceAdded(const QString &deviceId); void deviceRemoved(const QString &deviceId); @@ -85,6 +81,7 @@ signals: void deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &info); void appOutput(const QString &output); void errorMsg(const QString &msg); + private: friend class Internal::IosDeviceManagerPrivate; friend class Internal::DevInfoSession; diff --git a/src/tools/iostool/iostool.cpp b/src/tools/iostool/iostool.cpp new file mode 100644 index 00000000000..9123dcec73a --- /dev/null +++ b/src/tools/iostool/iostool.cpp @@ -0,0 +1,432 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 "iostool.h" + +#include "relayserver.h" +#include "gdbrunner.h" + +#include +#include +#include +#include + +namespace Ios { + +IosTool::IosTool(QObject *parent): + QObject(parent), + maxProgress(0), + opLeft(0), + debug(false), + inAppOutput(false), + splitAppOutput(true), + appOp(IosDeviceManager::None), + outFile(), + out(&outFile), + gdbServer(0), + qmlServer(0) +{ + outFile.open(stdout, QIODevice::WriteOnly, QFileDevice::DontCloseHandle); + out.setAutoFormatting(true); +} + +IosTool::~IosTool() +{ +} + +void IosTool::run(const QStringList &args) +{ + IosDeviceManager *manager = IosDeviceManager::instance(); + QString deviceId; + QString bundlePath; + bool deviceInfo = false; + bool printHelp = false; + int timeout = 1000; + QStringList extraArgs; + + out.writeStartDocument(); + out.writeStartElement(QLatin1String("query_result")); + for (int iarg = 1; iarg < args.size(); ++iarg) { + const QString &arg = args[iarg]; + if (arg == QLatin1String("-i") || arg == QLatin1String("--id")) { + if (++iarg == args.size()) { + writeMsg(QStringLiteral("missing device id value after ") + arg); + printHelp = true; + } + deviceId = args.value(iarg); + } else if (arg == QLatin1String("-b") || arg == QLatin1String("--bundle")) { + if (++iarg == args.size()) { + writeMsg(QStringLiteral("missing bundle path after ") + arg); + printHelp = true; + } + bundlePath = args.value(iarg); + } else if (arg == QLatin1String("--install")) { + appOp = IosDeviceManager::AppOp(appOp | IosDeviceManager::Install); + } else if (arg == QLatin1String("--run")) { + appOp = IosDeviceManager::AppOp(appOp | IosDeviceManager::Run); + } else if (arg == QLatin1String("--noninteractive")) { + // ignored for compatibility + } else if (arg == QLatin1String("-v") || arg == QLatin1String("--verbose")) { + m_echoRelays = true; + } else if (arg == QLatin1String("-d") || arg == QLatin1String("--debug")) { + appOp = IosDeviceManager::AppOp(appOp | IosDeviceManager::Run); + debug = true; + } else if (arg == QLatin1String("--device-info")) { + deviceInfo = true; + } else if (arg == QLatin1String("-t") || arg == QLatin1String("--timeout")) { + if (++iarg == args.size()) { + writeMsg(QStringLiteral("missing timeout value after ") + arg); + printHelp = true; + } + bool ok = false; + int tOut = args.value(iarg).toInt(&ok); + if (ok && tOut > 0) { + timeout = tOut; + } else { + writeMsg("timeout value should be an integer"); + printHelp = true; + } + } else if (arg == QLatin1String("-a") || arg == QLatin1String("--args")) { + extraArgs = args.mid(iarg + 1, args.size() - iarg - 1); + iarg = args.size(); + } else if (arg == QLatin1String("-h") || arg == QLatin1String("--help")) { + printHelp = true; + } else { + writeMsg(QString::fromLatin1("unexpected argument \"%1\"").arg(arg)); + } + } + if (printHelp) { + out.writeStartElement(QLatin1String("msg")); + out.writeCharacters(QLatin1String("iostool [--id ] [--bundle ] [--install] [--run] [--debug]\n")); + out.writeCharacters(QLatin1String(" [--device-info] [--timeout ] [--verbose]\n")); // to do pass in env as stub does + out.writeCharacters(QLatin1String(" [--args ]")); + out.writeEndElement(); + doExit(-1); + return; + } + outFile.flush(); + connect(manager, &IosDeviceManager::isTransferringApp, this, &IosTool::isTransferringApp); + connect(manager, &IosDeviceManager::didTransferApp, this, &IosTool::didTransferApp); + connect(manager, &IosDeviceManager::didStartApp, this, &IosTool::didStartApp); + connect(manager, &IosDeviceManager::deviceInfo, this, &IosTool::deviceInfo); + connect(manager, &IosDeviceManager::appOutput, this, &IosTool::appOutput); + connect(manager, &IosDeviceManager::errorMsg, this, &IosTool::errorMsg); + manager->watchDevices(); + const QRegularExpression qmlPortRe(QLatin1String("-qmljsdebugger=port:([0-9]+)")); + for (const QString &arg : extraArgs) { + const QRegularExpressionMatch match = qmlPortRe.match(arg); + if (match.hasMatch()) { + bool ok; + int qmlPort = match.captured(1).toInt(&ok); + if (ok && qmlPort > 0 && qmlPort <= 0xFFFF) + m_qmlPort = match.captured(1); + break; + } + } + if (deviceInfo) { + if (!bundlePath.isEmpty()) + writeMsg("--device-info overrides --bundle"); + ++opLeft; + manager->requestDeviceInfo(deviceId, timeout); + } else if (!bundlePath.isEmpty()) { + switch (appOp) { + case IosDeviceManager::None: + break; + case IosDeviceManager::Install: + case IosDeviceManager::Run: + ++opLeft; + break; + case IosDeviceManager::InstallAndRun: + opLeft += 2; + break; + } + maxProgress = 200; + manager->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout); + } + if (opLeft == 0) + doExit(0); +} + +void IosTool::stopXml(int errorCode) +{ + QMutexLocker l(&m_xmlMutex); + out.writeEmptyElement(QLatin1String("exit")); + out.writeAttribute(QLatin1String("code"), QString::number(errorCode)); + out.writeEndElement(); // result element (hopefully) + out.writeEndDocument(); + outFile.flush(); +} + +void IosTool::doExit(int errorCode) +{ + stopXml(errorCode); + QCoreApplication::exit(errorCode); // sometime does not really exit + exit(errorCode); +} + +void IosTool::isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress, + const QString &info) +{ + Q_UNUSED(bundlePath) + Q_UNUSED(deviceId) + QMutexLocker l(&m_xmlMutex); + out.writeStartElement(QLatin1String("status")); + out.writeAttribute(QLatin1String("progress"), QString::number(progress)); + out.writeAttribute(QLatin1String("max_progress"), QString::number(maxProgress)); + out.writeCharacters(info); + out.writeEndElement(); + outFile.flush(); +} + +void IosTool::didTransferApp(const QString &bundlePath, const QString &deviceId, + IosDeviceManager::OpStatus status) +{ + Q_UNUSED(bundlePath) + Q_UNUSED(deviceId) + { + QMutexLocker l(&m_xmlMutex); + if (status == IosDeviceManager::Success) { + out.writeStartElement(QLatin1String("status")); + out.writeAttribute(QLatin1String("progress"), QString::number(maxProgress)); + out.writeAttribute(QLatin1String("max_progress"), QString::number(maxProgress)); + out.writeCharacters(QLatin1String("App Transferred")); + out.writeEndElement(); + } + out.writeEmptyElement(QLatin1String("app_transfer")); + out.writeAttribute(QLatin1String("status"), + (status == IosDeviceManager::Success) ? + QLatin1String("SUCCESS") : + QLatin1String("FAILURE")); + //out.writeCharacters(QString()); // trigger a complete closing of the empty element + outFile.flush(); + } + if (status != IosDeviceManager::Success || --opLeft == 0) + doExit((status == IosDeviceManager::Success) ? 0 : -1); +} + +void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId, + IosDeviceManager::OpStatus status, int gdbFd, + DeviceSession *deviceSession) +{ + Q_UNUSED(bundlePath) + Q_UNUSED(deviceId) + { + QMutexLocker l(&m_xmlMutex); + out.writeEmptyElement(QLatin1String("app_started")); + out.writeAttribute(QLatin1String("status"), + (status == IosDeviceManager::Success) ? + QLatin1String("SUCCESS") : + QLatin1String("FAILURE")); + //out.writeCharacters(QString()); // trigger a complete closing of the empty element + outFile.flush(); + } + if (status != IosDeviceManager::Success || appOp == IosDeviceManager::Install) { + doExit(); + return; + } + if (gdbFd <= 0) { + writeMsg("no gdb connection"); + doExit(-2); + return; + } + if (appOp != IosDeviceManager::InstallAndRun && appOp != IosDeviceManager::Run) { + writeMsg(QString::fromLatin1("unexpected appOp value %1").arg(appOp)); + doExit(-3); + return; + } + if (deviceSession) { + int qmlPort = deviceSession->qmljsDebugPort(); + if (qmlPort) { + qmlServer = new GenericRelayServer(this, qmlPort, deviceSession); + qmlServer->startServer(); + } + } + if (debug) { + gdbServer = new SingleRelayServer(this, gdbFd); + if (!gdbServer->startServer()) { + doExit(-4); + return; + } + } + { + QMutexLocker l(&m_xmlMutex); + out.writeStartElement(QLatin1String("server_ports")); + out.writeAttribute(QLatin1String("gdb_server"), + QString::number(gdbServer ? gdbServer->serverPort() : -1)); + out.writeAttribute(QLatin1String("qml_server"), + QString::number(qmlServer ? qmlServer->serverPort() : -1)); + out.writeEndElement(); + outFile.flush(); + } + if (!debug) { + gdbRunner = new GdbRunner(this, gdbFd); + // we should not stop the event handling of the main thread + // all output moves to the new thread (other option would be to signal it back) + QThread *gdbProcessThread = new QThread(); + gdbRunner->moveToThread(gdbProcessThread); + QObject::connect(gdbProcessThread, &QThread::started, gdbRunner, &GdbRunner::run); + QObject::connect(gdbRunner, &GdbRunner::finished, gdbProcessThread, &QThread::quit); + QObject::connect(gdbProcessThread, &QThread::finished, + gdbProcessThread, &QObject::deleteLater); + gdbProcessThread->start(); + + new std::thread([this]() -> void { readStdin();}); + } +} + +void IosTool::writeMsg(const char *msg) +{ + writeMsg(QString::fromLatin1(msg)); +} + +void IosTool::writeMsg(const QString &msg) +{ + QMutexLocker l(&m_xmlMutex); + out.writeStartElement(QLatin1String("msg")); + writeTextInElement(msg); + out.writeCharacters(QLatin1String("\n")); + out.writeEndElement(); + outFile.flush(); +} + +void IosTool::writeMaybeBin(const QString &extraMsg, const char *msg, quintptr len) +{ + char *buf2 = new char[len * 2 + 4]; + buf2[0] = '['; + const char toHex[] = "0123456789abcdef"; + for (quintptr i = 0; i < len; ++i) { + buf2[2 * i + 1] = toHex[(0xF & (msg[i] >> 4))]; + buf2[2 * i + 2] = toHex[(0xF & msg[i])]; + } + buf2[2 * len + 1] = ']'; + buf2[2 * len + 2] = ' '; + buf2[2 * len + 3] = 0; + + QMutexLocker l(&m_xmlMutex); + out.writeStartElement(QLatin1String("msg")); + out.writeCharacters(extraMsg); + out.writeCharacters(QLatin1String(buf2)); + for (quintptr i = 0; i < len; ++i) { + if (msg[i] < 0x20 || msg[i] > 0x7f) + buf2[i] = '_'; + else + buf2[i] = msg[i]; + } + buf2[len] = 0; + out.writeCharacters(QLatin1String(buf2)); + delete[] buf2; + out.writeEndElement(); + outFile.flush(); +} + +void IosTool::deviceInfo(const QString &deviceId, const IosDeviceManager::Dict &devInfo) +{ + Q_UNUSED(deviceId) + { + QMutexLocker l(&m_xmlMutex); + out.writeTextElement(QLatin1String("device_id"), deviceId); + out.writeStartElement(QLatin1String("device_info")); + for (auto i = devInfo.cbegin(); i != devInfo.cend(); ++i) { + out.writeStartElement(QLatin1String("item")); + out.writeTextElement(QLatin1String("key"), i.key()); + out.writeTextElement(QLatin1String("value"), i.value()); + out.writeEndElement(); + } + out.writeEndElement(); + outFile.flush(); + } + doExit(); +} + +void IosTool::writeTextInElement(const QString &output) +{ + const QRegularExpression controlCharRe(QLatin1String("[\x01-\x08]|\x0B|\x0C|[\x0E-\x1F]|\\0000")); + int pos = 0; + int oldPos = 0; + + while ((pos = output.indexOf(controlCharRe, pos)) != -1) { + QMutexLocker l(&m_xmlMutex); + out.writeCharacters(output.mid(oldPos, pos - oldPos)); + out.writeEmptyElement(QLatin1String("control_char")); + out.writeAttribute(QLatin1String("code"), QString::number(output.at(pos).toLatin1())); + pos += 1; + oldPos = pos; + } + out.writeCharacters(output.mid(oldPos, output.length() - oldPos)); +} + +void IosTool::appOutput(const QString &output) +{ + QMutexLocker l(&m_xmlMutex); + if (!inAppOutput) + out.writeStartElement(QLatin1String("app_output")); + writeTextInElement(output); + if (!inAppOutput) + out.writeEndElement(); + outFile.flush(); +} + +void IosTool::readStdin() +{ + int c = getchar(); + if (c == 'k') { + QMetaObject::invokeMethod(this, "stopGdbRunner"); + errorMsg(QLatin1String("iostool: Killing inferior.\n")); + } else if (c != EOF) { + errorMsg(QLatin1String("iostool: Unexpected character in stdin, stop listening.\n")); + } +} + +void IosTool::errorMsg(const QString &msg) +{ + writeMsg(msg); +} + +void IosTool::stopGdbRunner() +{ + if (gdbRunner) { + gdbRunner->stop(0); + QTimer::singleShot(100, this, &IosTool::stopGdbRunner2); + } +} + +void IosTool::stopGdbRunner2() +{ + if (gdbRunner) + gdbRunner->stop(1); +} + +void IosTool::stopRelayServers(int errorCode) +{ + if (echoRelays()) + writeMsg("gdbServerStops"); + if (qmlServer) + qmlServer->stopServer(); + if (gdbServer) + gdbServer->stopServer(); + doExit(errorCode); +} + +} diff --git a/src/tools/iostool/iostool.h b/src/tools/iostool/iostool.h new file mode 100644 index 00000000000..24e78c66810 --- /dev/null +++ b/src/tools/iostool/iostool.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 "iosdevicemanager.h" + +#include +#include +#include +#include + +namespace Ios { +class GdbRunner; +class SingleRelayServer; +class GenericRelayServer; + +class IosTool: public QObject +{ + Q_OBJECT + +public: + IosTool(QObject *parent = 0); + virtual ~IosTool(); + void run(const QStringList &args); + void doExit(int errorCode = 0); + void writeMsg(const char *msg); + void writeMsg(const QString &msg); + void stopXml(int errorCode); + void writeTextInElement(const QString &output); + void stopRelayServers(int errorCode = 0); + void writeMaybeBin(const QString &extraMsg, const char *msg, quintptr len); + void errorMsg(const QString &msg); + Q_INVOKABLE void stopGdbRunner(); + bool echoRelays() const { return m_echoRelays; } + +private: + void stopGdbRunner2(); + void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress, + const QString &info); + void didTransferApp(const QString &bundlePath, const QString &deviceId, + Ios::IosDeviceManager::OpStatus status); + void didStartApp(const QString &bundlePath, const QString &deviceId, + IosDeviceManager::OpStatus status, int gdbFd, + DeviceSession *deviceSession); + void deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &info); + void appOutput(const QString &output); + void readStdin(); + + QRecursiveMutex m_xmlMutex; + int maxProgress; + int opLeft; + bool debug; + bool inAppOutput; + bool splitAppOutput; // as QXmlStreamReader reports the text attributes atomically it is better to split + Ios::IosDeviceManager::AppOp appOp; + QFile outFile; + QString m_qmlPort; + QXmlStreamWriter out; + SingleRelayServer *gdbServer; + GenericRelayServer *qmlServer; + GdbRunner *gdbRunner; + bool m_echoRelays = false; + friend class GdbRunner; +}; +} diff --git a/src/tools/iostool/iostool.pro b/src/tools/iostool/iostool.pro index 4ecd607ac22..da866fbffff 100644 --- a/src/tools/iostool/iostool.pro +++ b/src/tools/iostool/iostool.pro @@ -24,10 +24,19 @@ RPATH_BASE = $$DESTDIR include(../../rpath.pri) SOURCES += main.cpp \ - iosdevicemanager.cpp + gdbrunner.cpp \ + iosdevicemanager.cpp \ + iostool.cpp \ + mobiledevicelib.cpp \ + relayserver.cpp HEADERS += \ - iosdevicemanager.h + gdbrunner.h \ + iosdevicemanager.h \ + iostool.h \ + iostooltypes.h \ + mobiledevicelib.h \ + relayserver.h DISTFILES += Info.plist diff --git a/src/tools/iostool/iostool.qbs b/src/tools/iostool/iostool.qbs index 1d5e282104b..a39ace4dba1 100644 --- a/src/tools/iostool/iostool.qbs +++ b/src/tools/iostool/iostool.qbs @@ -12,9 +12,18 @@ QtcTool { files: [ "Info.plist", - "main.cpp", + "gdbrunner.cpp", + "gdbrunner.h", "iosdevicemanager.cpp", - "iosdevicemanager.h" + "iosdevicemanager.h", + "iostool.cpp", + "iostool.h", + "iostooltypes.h", + "main.cpp", + "mobiledevicelib.cpp", + "mobiledevicelib.h", + "relayserver.cpp", + "relayserver.h" ] cpp.frameworks: base.concat(["CoreFoundation", "CoreServices", "IOKit", "Security", "SystemConfiguration"]) diff --git a/src/tools/iostool/iostooltypes.h b/src/tools/iostool/iostooltypes.h new file mode 100644 index 00000000000..766afe143d2 --- /dev/null +++ b/src/tools/iostool/iostooltypes.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 + + +extern "C" { +typedef unsigned int ServiceSocket; // match_port_t (i.e. natural_t) or socket (on windows, i.e sock_t) +typedef unsigned int *ServiceConnRef; +} // extern C diff --git a/src/tools/iostool/main.cpp b/src/tools/iostool/main.cpp index c8bf5658166..a453010eb92 100644 --- a/src/tools/iostool/main.cpp +++ b/src/tools/iostool/main.cpp @@ -23,881 +23,10 @@ ** ****************************************************************************/ -#include "iosdevicemanager.h" +#include "iostool.h" -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#ifdef Q_OS_UNIX -#include -#include -#endif -#include - -// avoid utils dependency -#define QTC_CHECK(cond) if (cond) {} else { qWarning() << "assert failed " << #cond << " " \ - << __FILE__ << ":" << __LINE__; } do {} while (0) - -static bool echoRelays = false; - -class IosTool; -class RelayServer; -class GenericRelayServer; - -class Relayer: public QObject -{ - Q_OBJECT -public: - Relayer(RelayServer *parent, QTcpSocket *clientSocket); - ~Relayer(); - void setClientSocket(QTcpSocket *clientSocket); - bool startRelay(int serverFileDescriptor); - - void handleSocketHasData(int socket); - void handleClientHasData(); - void handleClientHasError(QAbstractSocket::SocketError error); -protected: - IosTool *iosTool(); - RelayServer *server(); - Ios::ServiceSocket m_serverFileDescriptor; - QTcpSocket *m_clientSocket; - QSocketNotifier *m_serverNotifier; -}; - -class RemotePortRelayer: public Relayer -{ - Q_OBJECT -public: - static const int reconnectMsecDelay = 500; - static const int maxReconnectAttempts = 2*60*5; // 5 min - RemotePortRelayer(GenericRelayServer *parent, QTcpSocket *clientSocket); - void tryRemoteConnect(); -signals: - void didConnect(GenericRelayServer *serv); -private: - QTimer m_remoteConnectTimer; -}; - -class RelayServer: public QObject -{ - Q_OBJECT -public: - RelayServer(IosTool *parent); - ~RelayServer(); - bool startServer(); - void stopServer(); - quint16 serverPort(); - IosTool *iosTool(); - - void handleNewRelayConnection(); - void removeRelayConnection(Relayer *relayer); -protected: - virtual void newRelayConnection() = 0; - - QTcpServer m_ipv4Server; - QTcpServer m_ipv6Server; - quint16 m_port = 0; - QList m_connections; -}; - -class SingleRelayServer: public RelayServer -{ - Q_OBJECT -public: - SingleRelayServer(IosTool *parent, int serverFileDescriptor); -protected: - void newRelayConnection() override; -private: - int m_serverFileDescriptor; -}; - -class GenericRelayServer: public RelayServer { - Q_OBJECT -public: - GenericRelayServer(IosTool *parent, int remotePort, - Ios::DeviceSession *deviceSession); -protected: - void newRelayConnection() override; -private: - int m_remotePort; - Ios::DeviceSession *m_deviceSession; - friend class RemotePortRelayer; -}; - -class GdbRunner: public QObject -{ - Q_OBJECT -public: - GdbRunner(IosTool *iosTool, int gdbFd); - void stop(int phase); - void run(); -signals: - void finished(); -private: - IosTool *m_iosTool; - int m_gdbFd; -}; - -class IosTool: public QObject -{ - Q_OBJECT -public: - IosTool(QObject *parent = 0); - virtual ~IosTool(); - void run(const QStringList &args); - void doExit(int errorCode = 0); - void writeMsg(const char *msg); - void writeMsg(const QString &msg); - void stopXml(int errorCode); - void writeTextInElement(const QString &output); - void stopRelayServers(int errorCode = 0); - void writeMaybeBin(const QString &extraMsg, const char *msg, quintptr len); - void errorMsg(const QString &msg); - Q_INVOKABLE void stopGdbRunner(); -private: - void stopGdbRunner2(); - void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress, - const QString &info); - void didTransferApp(const QString &bundlePath, const QString &deviceId, - Ios::IosDeviceManager::OpStatus status); - void didStartApp(const QString &bundlePath, const QString &deviceId, - Ios::IosDeviceManager::OpStatus status, int gdbFd, - Ios::DeviceSession *deviceSession); - void deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &info); - void appOutput(const QString &output); - void readStdin(); - - QRecursiveMutex m_xmlMutex; - int maxProgress; - int opLeft; - bool debug; - bool inAppOutput; - bool splitAppOutput; // as QXmlStreamReader reports the text attributes atomically it is better to split - Ios::IosDeviceManager::AppOp appOp; - QFile outFile; - QString m_qmlPort; - QXmlStreamWriter out; - SingleRelayServer *gdbServer; - GenericRelayServer *qmlServer; - GdbRunner *gdbRunner; - friend class GdbRunner; -}; - -Relayer::Relayer(RelayServer *parent, QTcpSocket *clientSocket) : - QObject(parent), m_serverFileDescriptor(0), m_clientSocket(0), m_serverNotifier(0) -{ - setClientSocket(clientSocket); -} - -Relayer::~Relayer() -{ - if (m_serverFileDescriptor > 0) { - ::close(m_serverFileDescriptor); - m_serverFileDescriptor = -1; - if (m_serverNotifier) - delete m_serverNotifier; - } - if (m_clientSocket->isOpen()) - m_clientSocket->close(); - delete m_clientSocket; -} - -void Relayer::setClientSocket(QTcpSocket *clientSocket) -{ - QTC_CHECK(!m_clientSocket); - m_clientSocket = clientSocket; - if (m_clientSocket) { -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - const auto errorOccurred = QOverload::of(&QAbstractSocket::error); -#else - const auto errorOccurred = &QAbstractSocket::errorOccurred; -#endif - connect(m_clientSocket, errorOccurred, this, &Relayer::handleClientHasError); - connect(m_clientSocket, &QAbstractSocket::disconnected, - this, [this](){server()->removeRelayConnection(this);}); - } -} - -bool Relayer::startRelay(int serverFileDescriptor) -{ - QTC_CHECK(!m_serverFileDescriptor); - m_serverFileDescriptor = serverFileDescriptor; - if (!m_clientSocket || m_serverFileDescriptor <= 0) - return false; - fcntl(serverFileDescriptor,F_SETFL, fcntl(serverFileDescriptor, F_GETFL) | O_NONBLOCK); - connect(m_clientSocket, &QIODevice::readyRead, this, &Relayer::handleClientHasData); - m_serverNotifier = new QSocketNotifier(m_serverFileDescriptor, QSocketNotifier::Read, this); - connect(m_serverNotifier, &QSocketNotifier::activated, this, &Relayer::handleSocketHasData); - // no way to check if an error did happen? - if (m_clientSocket->bytesAvailable() > 0) - handleClientHasData(); - return true; -} - -void Relayer::handleSocketHasData(int socket) -{ - m_serverNotifier->setEnabled(false); - char buf[255]; - while (true) { - qptrdiff rRead = read(socket, &buf, sizeof(buf)-1); - if (rRead == -1) { - if (errno == EINTR) - continue; - if (errno == EAGAIN) { - m_serverNotifier->setEnabled(true); - return; - } - iosTool()->errorMsg(qt_error_string(errno)); - close(socket); - iosTool()->stopRelayServers(-1); - return; - } - if (rRead == 0) { - iosTool()->stopRelayServers(0); - return; - } - if (echoRelays) { - iosTool()->writeMaybeBin(QString::fromLatin1("%1 serverReplies:") - .arg((quintptr)(void *)this), buf, rRead); - } - qint64 pos = 0; - while (true) { - qint64 writtenNow = m_clientSocket->write(buf + int(pos), rRead); - if (writtenNow == -1) { - iosTool()->writeMsg(m_clientSocket->errorString()); - iosTool()->stopRelayServers(-1); - return; - } - if (writtenNow < rRead) { - pos += writtenNow; - rRead -= qptrdiff(writtenNow); - } else { - break; - } - } - m_clientSocket->flush(); - } -} - -void Relayer::handleClientHasData() -{ - char buf[255]; - while (true) { - qint64 toRead = m_clientSocket->bytesAvailable(); - if (qint64(sizeof(buf)-1) < toRead) - toRead = sizeof(buf)-1; - qint64 rRead = m_clientSocket->read(buf, toRead); - if (rRead == -1) { - iosTool()->errorMsg(m_clientSocket->errorString()); - iosTool()->stopRelayServers(); - return; - } - if (rRead == 0) { - if (!m_clientSocket->isOpen()) - iosTool()->stopRelayServers(); - return; - } - int pos = 0; - int irep = 0; - if (echoRelays) { - iosTool()->writeMaybeBin(QString::fromLatin1("%1 clientAsks:") - .arg((quintptr)(void *)this), buf, rRead); - } - while (true) { - qptrdiff written = write(m_serverFileDescriptor, buf + pos, rRead); - if (written == -1) { - if (errno == EINTR) - continue; - if (errno == EAGAIN) { - if (++irep > 10) { - sleep(1); - irep = 0; - } - continue; - } - iosTool()->errorMsg(qt_error_string(errno)); - iosTool()->stopRelayServers(); - return; - } - if (written == 0) { - iosTool()->stopRelayServers(); - return; - } - if (written < rRead) { - pos += written; - rRead -= written; - } else { - break; - } - } - } -} - -void Relayer::handleClientHasError(QAbstractSocket::SocketError error) -{ - iosTool()->errorMsg(tr("iOS Debugging connection to creator failed with error %1").arg(error)); - server()->removeRelayConnection(this); -} - -IosTool *Relayer::iosTool() -{ - return (server() ? server()->iosTool() : 0); -} - -RelayServer *Relayer::server() -{ - return qobject_cast(parent()); -} - -RemotePortRelayer::RemotePortRelayer(GenericRelayServer *parent, QTcpSocket *clientSocket) : - Relayer(parent, clientSocket) -{ - m_remoteConnectTimer.setSingleShot(true); - m_remoteConnectTimer.setInterval(reconnectMsecDelay); - connect(&m_remoteConnectTimer, &QTimer::timeout, this, &RemotePortRelayer::tryRemoteConnect); -} - -void RemotePortRelayer::tryRemoteConnect() -{ - iosTool()->errorMsg(QLatin1String("tryRemoteConnect")); - if (m_serverFileDescriptor > 0) - return; - Ios::ServiceSocket ss; - GenericRelayServer *grServer = qobject_cast(server()); - if (!grServer) - return; - if (grServer->m_deviceSession->connectToPort(grServer->m_remotePort, &ss)) { - if (ss > 0) { - iosTool()->errorMsg(QString::fromLatin1("tryRemoteConnect *succeeded* on remote port %1") - .arg(grServer->m_remotePort)); - startRelay(ss); - emit didConnect(grServer); - return; - } - } - iosTool()->errorMsg(QString::fromLatin1("tryRemoteConnect *failed* on remote port %1") - .arg(grServer->m_remotePort)); - m_remoteConnectTimer.start(); -} - -RelayServer::RelayServer(IosTool *parent): - QObject(parent) -{ } - -RelayServer::~RelayServer() -{ - stopServer(); -} - -bool RelayServer::startServer() -{ - QTC_CHECK(!m_ipv4Server.isListening()); - QTC_CHECK(!m_ipv6Server.isListening()); - - connect(&m_ipv4Server, &QTcpServer::newConnection, - this, &RelayServer::handleNewRelayConnection); - connect(&m_ipv6Server, &QTcpServer::newConnection, - this, &RelayServer::handleNewRelayConnection); - - m_port = 0; - if (m_ipv4Server.listen(QHostAddress(QHostAddress::LocalHost), 0)) - m_port = m_ipv4Server.serverPort(); - if (m_ipv6Server.listen(QHostAddress(QHostAddress::LocalHostIPv6), m_port)) - m_port = m_ipv6Server.serverPort(); - - return m_port > 0; -} - -void RelayServer::stopServer() -{ - foreach (Relayer *connection, m_connections) - delete connection; - if (m_ipv4Server.isListening()) - m_ipv4Server.close(); - if (m_ipv6Server.isListening()) - m_ipv6Server.close(); -} - -quint16 RelayServer::serverPort() -{ - return m_port; -} - -IosTool *RelayServer::iosTool() -{ - return qobject_cast(parent()); -} - -void RelayServer::handleNewRelayConnection() -{ - iosTool()->errorMsg(QLatin1String("handleNewRelayConnection")); - newRelayConnection(); -} - -void RelayServer::removeRelayConnection(Relayer *relayer) -{ - m_connections.removeAll(relayer); - relayer->deleteLater(); -} - -SingleRelayServer::SingleRelayServer(IosTool *parent, - int serverFileDescriptor) : - RelayServer(parent) -{ - m_serverFileDescriptor = serverFileDescriptor; - if (m_serverFileDescriptor > 0) - fcntl(m_serverFileDescriptor, F_SETFL, fcntl(m_serverFileDescriptor, F_GETFL, 0) | O_NONBLOCK); -} - -void SingleRelayServer::newRelayConnection() -{ - QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections() - ? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection(); - if (m_connections.size() > 0) { - delete clientSocket; - return; - } - if (clientSocket) { - Relayer *newConnection = new Relayer(this, clientSocket); - m_connections.append(newConnection); - newConnection->startRelay(m_serverFileDescriptor); - } -} - -GenericRelayServer::GenericRelayServer(IosTool *parent, int remotePort, - Ios::DeviceSession *deviceSession) : - RelayServer(parent), - m_remotePort(remotePort), - m_deviceSession(deviceSession) -{ - parent->errorMsg(QLatin1String("created qml server")); -} - - -void GenericRelayServer::newRelayConnection() -{ - QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections() - ? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection(); - if (clientSocket) { - iosTool()->errorMsg(QString::fromLatin1("setting up relayer for new connection")); - RemotePortRelayer *newConnection = new RemotePortRelayer(this, clientSocket); - m_connections.append(newConnection); - newConnection->tryRemoteConnect(); - } -} - -IosTool::IosTool(QObject *parent): - QObject(parent), - maxProgress(0), - opLeft(0), - debug(false), - inAppOutput(false), - splitAppOutput(true), - appOp(Ios::IosDeviceManager::None), - outFile(), - out(&outFile), - gdbServer(0), - qmlServer(0) -{ - outFile.open(stdout, QIODevice::WriteOnly, QFileDevice::DontCloseHandle); - out.setAutoFormatting(true); -} - -IosTool::~IosTool() -{ -} - -void IosTool::run(const QStringList &args) -{ - Ios::IosDeviceManager *manager = Ios::IosDeviceManager::instance(); - QString deviceId; - QString bundlePath; - bool deviceInfo = false; - bool printHelp = false; - int timeout = 1000; - QStringList extraArgs; - - out.writeStartDocument(); - out.writeStartElement(QLatin1String("query_result")); - for (int iarg = 1; iarg < args.size(); ++iarg) { - const QString &arg = args[iarg]; - if (arg == QLatin1String("-i") || arg == QLatin1String("--id")) { - if (++iarg == args.size()) { - writeMsg(QStringLiteral("missing device id value after ") + arg); - printHelp = true; - } - deviceId = args.value(iarg); - } else if (arg == QLatin1String("-b") || arg == QLatin1String("--bundle")) { - if (++iarg == args.size()) { - writeMsg(QStringLiteral("missing bundle path after ") + arg); - printHelp = true; - } - bundlePath = args.value(iarg); - } else if (arg == QLatin1String("--install")) { - appOp = Ios::IosDeviceManager::AppOp(appOp | Ios::IosDeviceManager::Install); - } else if (arg == QLatin1String("--run")) { - appOp = Ios::IosDeviceManager::AppOp(appOp | Ios::IosDeviceManager::Run); - } else if (arg == QLatin1String("--noninteractive")) { - // ignored for compatibility - } else if (arg == QLatin1String("-v") || arg == QLatin1String("--verbose")) { - echoRelays = true; - } else if (arg == QLatin1String("-d") || arg == QLatin1String("--debug")) { - appOp = Ios::IosDeviceManager::AppOp(appOp | Ios::IosDeviceManager::Run); - debug = true; - } else if (arg == QLatin1String("--device-info")) { - deviceInfo = true; - } else if (arg == QLatin1String("-t") || arg == QLatin1String("--timeout")) { - if (++iarg == args.size()) { - writeMsg(QStringLiteral("missing timeout value after ") + arg); - printHelp = true; - } - bool ok = false; - int tOut = args.value(iarg).toInt(&ok); - if (ok && tOut > 0) { - timeout = tOut; - } else { - writeMsg("timeout value should be an integer"); - printHelp = true; - } - } else if (arg == QLatin1String("-a") || arg == QLatin1String("--args")) { - extraArgs = args.mid(iarg + 1, args.size() - iarg - 1); - iarg = args.size(); - } else if (arg == QLatin1String("-h") || arg == QLatin1String("--help")) { - printHelp = true; - } else { - writeMsg(QString::fromLatin1("unexpected argument \"%1\"").arg(arg)); - } - } - if (printHelp) { - out.writeStartElement(QLatin1String("msg")); - out.writeCharacters(QLatin1String("iostool [--id ] [--bundle ] [--install] [--run] [--debug]\n")); - out.writeCharacters(QLatin1String(" [--device-info] [--timeout ] [--verbose]\n")); // to do pass in env as stub does - out.writeCharacters(QLatin1String(" [--args ]")); - out.writeEndElement(); - doExit(-1); - return; - } - outFile.flush(); - connect(manager,&Ios::IosDeviceManager::isTransferringApp, this, &IosTool::isTransferringApp); - connect(manager,&Ios::IosDeviceManager::didTransferApp, this, &IosTool::didTransferApp); - connect(manager,&Ios::IosDeviceManager::didStartApp, this, &IosTool::didStartApp); - connect(manager,&Ios::IosDeviceManager::deviceInfo, this, &IosTool::deviceInfo); - connect(manager,&Ios::IosDeviceManager::appOutput, this, &IosTool::appOutput); - connect(manager,&Ios::IosDeviceManager::errorMsg, this, &IosTool::errorMsg); - manager->watchDevices(); - const QRegularExpression qmlPortRe(QLatin1String("-qmljsdebugger=port:([0-9]+)")); - for (const QString &arg : extraArgs) { - const QRegularExpressionMatch match = qmlPortRe.match(arg); - if (match.hasMatch()) { - bool ok; - int qmlPort = match.captured(1).toInt(&ok); - if (ok && qmlPort > 0 && qmlPort <= 0xFFFF) - m_qmlPort = match.captured(1); - break; - } - } - if (deviceInfo) { - if (!bundlePath.isEmpty()) - writeMsg("--device-info overrides --bundle"); - ++opLeft; - manager->requestDeviceInfo(deviceId, timeout); - } else if (!bundlePath.isEmpty()) { - switch (appOp) { - case Ios::IosDeviceManager::None: - break; - case Ios::IosDeviceManager::Install: - case Ios::IosDeviceManager::Run: - ++opLeft; - break; - case Ios::IosDeviceManager::InstallAndRun: - opLeft += 2; - break; - } - maxProgress = 200; - manager->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout); - } - if (opLeft == 0) - doExit(0); -} - -void IosTool::stopXml(int errorCode) -{ - QMutexLocker l(&m_xmlMutex); - out.writeEmptyElement(QLatin1String("exit")); - out.writeAttribute(QLatin1String("code"), QString::number(errorCode)); - out.writeEndElement(); // result element (hopefully) - out.writeEndDocument(); - outFile.flush(); -} - -void IosTool::doExit(int errorCode) -{ - stopXml(errorCode); - QCoreApplication::exit(errorCode); // sometime does not really exit - exit(errorCode); -} - -void IosTool::isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress, - const QString &info) -{ - Q_UNUSED(bundlePath) - Q_UNUSED(deviceId) - QMutexLocker l(&m_xmlMutex); - out.writeStartElement(QLatin1String("status")); - out.writeAttribute(QLatin1String("progress"), QString::number(progress)); - out.writeAttribute(QLatin1String("max_progress"), QString::number(maxProgress)); - out.writeCharacters(info); - out.writeEndElement(); - outFile.flush(); -} - -void IosTool::didTransferApp(const QString &bundlePath, const QString &deviceId, - Ios::IosDeviceManager::OpStatus status) -{ - Q_UNUSED(bundlePath) - Q_UNUSED(deviceId) - { - QMutexLocker l(&m_xmlMutex); - if (status == Ios::IosDeviceManager::Success) { - out.writeStartElement(QLatin1String("status")); - out.writeAttribute(QLatin1String("progress"), QString::number(maxProgress)); - out.writeAttribute(QLatin1String("max_progress"), QString::number(maxProgress)); - out.writeCharacters(QLatin1String("App Transferred")); - out.writeEndElement(); - } - out.writeEmptyElement(QLatin1String("app_transfer")); - out.writeAttribute(QLatin1String("status"), - (status == Ios::IosDeviceManager::Success) ? - QLatin1String("SUCCESS") : - QLatin1String("FAILURE")); - //out.writeCharacters(QString()); // trigger a complete closing of the empty element - outFile.flush(); - } - if (status != Ios::IosDeviceManager::Success || --opLeft == 0) - doExit((status == Ios::IosDeviceManager::Success) ? 0 : -1); -} - -void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId, - Ios::IosDeviceManager::OpStatus status, int gdbFd, - Ios::DeviceSession *deviceSession) -{ - Q_UNUSED(bundlePath) - Q_UNUSED(deviceId) - { - QMutexLocker l(&m_xmlMutex); - out.writeEmptyElement(QLatin1String("app_started")); - out.writeAttribute(QLatin1String("status"), - (status == Ios::IosDeviceManager::Success) ? - QLatin1String("SUCCESS") : - QLatin1String("FAILURE")); - //out.writeCharacters(QString()); // trigger a complete closing of the empty element - outFile.flush(); - } - if (status != Ios::IosDeviceManager::Success || appOp == Ios::IosDeviceManager::Install) { - doExit(); - return; - } - if (gdbFd <= 0) { - writeMsg("no gdb connection"); - doExit(-2); - return; - } - if (appOp != Ios::IosDeviceManager::InstallAndRun && appOp != Ios::IosDeviceManager::Run) { - writeMsg(QString::fromLatin1("unexpected appOp value %1").arg(appOp)); - doExit(-3); - return; - } - if (deviceSession) { - int qmlPort = deviceSession->qmljsDebugPort(); - if (qmlPort) { - qmlServer = new GenericRelayServer(this, qmlPort, deviceSession); - qmlServer->startServer(); - } - } - if (debug) { - gdbServer = new SingleRelayServer(this, gdbFd); - if (!gdbServer->startServer()) { - doExit(-4); - return; - } - } - { - QMutexLocker l(&m_xmlMutex); - out.writeStartElement(QLatin1String("server_ports")); - out.writeAttribute(QLatin1String("gdb_server"), - QString::number(gdbServer ? gdbServer->serverPort() : -1)); - out.writeAttribute(QLatin1String("qml_server"), - QString::number(qmlServer ? qmlServer->serverPort() : -1)); - out.writeEndElement(); - outFile.flush(); - } - if (!debug) { - gdbRunner = new GdbRunner(this, gdbFd); - // we should not stop the event handling of the main thread - // all output moves to the new thread (other option would be to signal it back) - QThread *gdbProcessThread = new QThread(); - gdbRunner->moveToThread(gdbProcessThread); - QObject::connect(gdbProcessThread, &QThread::started, gdbRunner, &GdbRunner::run); - QObject::connect(gdbRunner, &GdbRunner::finished, gdbProcessThread, &QThread::quit); - QObject::connect(gdbProcessThread, &QThread::finished, - gdbProcessThread, &QObject::deleteLater); - gdbProcessThread->start(); - - new std::thread([this]() -> void { readStdin();}); - } -} - -void IosTool::writeMsg(const char *msg) -{ - writeMsg(QString::fromLatin1(msg)); -} - -void IosTool::writeMsg(const QString &msg) -{ - QMutexLocker l(&m_xmlMutex); - out.writeStartElement(QLatin1String("msg")); - writeTextInElement(msg); - out.writeCharacters(QLatin1String("\n")); - out.writeEndElement(); - outFile.flush(); -} - -void IosTool::writeMaybeBin(const QString &extraMsg, const char *msg, quintptr len) -{ - char *buf2 = new char[len * 2 + 4]; - buf2[0] = '['; - const char toHex[] = "0123456789abcdef"; - for (quintptr i = 0; i < len; ++i) { - buf2[2 * i + 1] = toHex[(0xF & (msg[i] >> 4))]; - buf2[2 * i + 2] = toHex[(0xF & msg[i])]; - } - buf2[2 * len + 1] = ']'; - buf2[2 * len + 2] = ' '; - buf2[2 * len + 3] = 0; - - QMutexLocker l(&m_xmlMutex); - out.writeStartElement(QLatin1String("msg")); - out.writeCharacters(extraMsg); - out.writeCharacters(QLatin1String(buf2)); - for (quintptr i = 0; i < len; ++i) { - if (msg[i] < 0x20 || msg[i] > 0x7f) - buf2[i] = '_'; - else - buf2[i] = msg[i]; - } - buf2[len] = 0; - out.writeCharacters(QLatin1String(buf2)); - delete[] buf2; - out.writeEndElement(); - outFile.flush(); -} - -void IosTool::deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &devInfo) -{ - Q_UNUSED(deviceId) - { - QMutexLocker l(&m_xmlMutex); - out.writeTextElement(QLatin1String("device_id"), deviceId); - out.writeStartElement(QLatin1String("device_info")); - for (auto i = devInfo.cbegin(); i != devInfo.cend(); ++i) { - out.writeStartElement(QLatin1String("item")); - out.writeTextElement(QLatin1String("key"), i.key()); - out.writeTextElement(QLatin1String("value"), i.value()); - out.writeEndElement(); - } - out.writeEndElement(); - outFile.flush(); - } - doExit(); -} - -void IosTool::writeTextInElement(const QString &output) -{ - const QRegularExpression controlCharRe(QLatin1String("[\x01-\x08]|\x0B|\x0C|[\x0E-\x1F]|\\0000")); - int pos = 0; - int oldPos = 0; - - while ((pos = output.indexOf(controlCharRe, pos)) != -1) { - QMutexLocker l(&m_xmlMutex); - out.writeCharacters(output.mid(oldPos, pos - oldPos)); - out.writeEmptyElement(QLatin1String("control_char")); - out.writeAttribute(QLatin1String("code"), QString::number(output.at(pos).toLatin1())); - pos += 1; - oldPos = pos; - } - out.writeCharacters(output.mid(oldPos, output.length() - oldPos)); -} - -void IosTool::appOutput(const QString &output) -{ - QMutexLocker l(&m_xmlMutex); - if (!inAppOutput) - out.writeStartElement(QLatin1String("app_output")); - writeTextInElement(output); - if (!inAppOutput) - out.writeEndElement(); - outFile.flush(); -} - -void IosTool::readStdin() -{ - int c = getchar(); - if (c == 'k') { - QMetaObject::invokeMethod(this, "stopGdbRunner"); - errorMsg(QLatin1String("iostool: Killing inferior.\n")); - } else if (c != EOF) { - errorMsg(QLatin1String("iostool: Unexpected character in stdin, stop listening.\n")); - } -} - -void IosTool::errorMsg(const QString &msg) -{ - writeMsg(msg); -} - -void IosTool::stopGdbRunner() -{ - if (gdbRunner) { - gdbRunner->stop(0); - QTimer::singleShot(100, this, &IosTool::stopGdbRunner2); - } -} - -void IosTool::stopGdbRunner2() -{ - if (gdbRunner) - gdbRunner->stop(1); -} - -void IosTool::stopRelayServers(int errorCode) -{ - if (echoRelays) - writeMsg("gdbServerStops"); - if (qmlServer) - qmlServer->stopServer(); - if (gdbServer) - gdbServer->stopServer(); - doExit(errorCode); -} +#include int main(int argc, char *argv[]) { @@ -916,44 +45,9 @@ int main(int argc, char *argv[]) } QGuiApplication a(qtArgc, &qtArg); - IosTool tool; + Ios::IosTool tool; tool.run(args); int res = a.exec(); exit(res); } -GdbRunner::GdbRunner(IosTool *iosTool, int gdbFd) : - QObject(0), m_iosTool(iosTool), m_gdbFd(gdbFd) -{ -} - -void GdbRunner::run() -{ - { - QMutexLocker l(&m_iosTool->m_xmlMutex); - if (!m_iosTool->splitAppOutput) { - m_iosTool->out.writeStartElement(QLatin1String("app_output")); - m_iosTool->inAppOutput = true; - } - m_iosTool->outFile.flush(); - } - Ios::IosDeviceManager::instance()->processGdbServer(m_gdbFd); - { - QMutexLocker l(&m_iosTool->m_xmlMutex); - if (!m_iosTool->splitAppOutput) { - m_iosTool->inAppOutput = false; - m_iosTool->out.writeEndElement(); - } - m_iosTool->outFile.flush(); - } - close(m_gdbFd); - m_iosTool->doExit(); - emit finished(); -} - -void GdbRunner::stop(int phase) -{ - Ios::IosDeviceManager::instance()->stopGdbServer(m_gdbFd, phase); -} - -#include "main.moc" diff --git a/src/tools/iostool/mobiledevicelib.cpp b/src/tools/iostool/mobiledevicelib.cpp new file mode 100644 index 00000000000..87ce4fd8d34 --- /dev/null +++ b/src/tools/iostool/mobiledevicelib.cpp @@ -0,0 +1,350 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 "mobiledevicelib.h" + +#include + + +#ifdef MOBILE_DEV_DIRECT_LINK +#include "MobileDevice.h" +#endif + +namespace Ios { +MobileDeviceLib::MobileDeviceLib() +{ +} + +bool MobileDeviceLib::load() +{ +#ifdef MOBILE_DEV_DIRECT_LINK + m_AMDSetLogLevel = &AMDSetLogLevel; + m_AMDeviceNotificationSubscribe = &AMDeviceNotificationSubscribe; + //m_AMDeviceNotificationUnsubscribe = &AMDeviceNotificationUnsubscribe; + m_AMDeviceCopyValue = &AMDeviceCopyValue; + m_AMDeviceGetConnectionID = &AMDeviceGetConnectionID; + m_AMDeviceCopyDeviceIdentifier = &AMDeviceCopyDeviceIdentifier; + m_AMDeviceConnect = &AMDeviceConnect; + //m_AMDevicePair = &AMDevicePair; + m_AMDeviceIsPaired = &AMDeviceIsPaired; + m_AMDeviceValidatePairing = &AMDeviceValidatePairing; + m_AMDeviceStartSession = &AMDeviceStartSession; + m_AMDeviceStopSession = &AMDeviceStopSession; + m_AMDeviceDisconnect = &AMDeviceDisconnect; + m_AMDeviceMountImage = &AMDeviceMountImage; + m_AMDeviceStartService = &AMDeviceStartService; + m_AMDeviceTransferApplication = &AMDeviceTransferApplication; + m_AMDeviceInstallApplication = &AMDeviceInstallApplication; + //m_AMDeviceUninstallApplication = &AMDeviceUninstallApplication; + //m_AMDeviceLookupApplications = &AMDeviceLookupApplications; + m_USBMuxConnectByPort = &USBMuxConnectByPort; +#else + QLibrary *libAppleFSCompression = new QLibrary(QLatin1String("/System/Library/PrivateFrameworks/AppleFSCompression.framework/AppleFSCompression")); + if (!libAppleFSCompression->load()) + addError("MobileDevice dependency AppleFSCompression failed to load"); + deps << libAppleFSCompression; + QLibrary *libBom = new QLibrary(QLatin1String("/System/Library/PrivateFrameworks/Bom.framework/Bom")); + if (!libBom->load()) + addError("MobileDevice dependency Bom failed to load"); + deps << libBom; + lib.setFileName(QLatin1String("/System/Library/PrivateFrameworks/MobileDevice.framework/MobileDevice")); + if (!lib.load()) + return false; + m_AMDSetLogLevel = reinterpret_cast(lib.resolve("AMDSetLogLevel")); + if (m_AMDSetLogLevel == 0) + addError("MobileDeviceLib does not define AMDSetLogLevel"); + m_AMDeviceNotificationSubscribe = reinterpret_cast(lib.resolve("AMDeviceNotificationSubscribe")); + if (m_AMDeviceNotificationSubscribe == 0) + addError("MobileDeviceLib does not define AMDeviceNotificationSubscribe"); + m_AMDeviceNotificationUnsubscribe = reinterpret_cast(lib.resolve("AMDeviceNotificationUnsubscribe")); + if (m_AMDeviceNotificationUnsubscribe == 0) + addError("MobileDeviceLib does not define AMDeviceNotificationUnsubscribe"); + m_AMDeviceGetInterfaceType = reinterpret_cast(lib.resolve("AMDeviceGetInterfaceType")); + if (m_AMDeviceGetInterfaceType == 0) + addError("MobileDeviceLib does not define AMDeviceGetInterfaceType"); + m_AMDeviceCopyValue = reinterpret_cast(lib.resolve("AMDeviceCopyValue")); + if (m_AMDSetLogLevel == 0) + addError("MobileDeviceLib does not define AMDSetLogLevel"); + m_AMDeviceGetConnectionID = reinterpret_cast(lib.resolve("AMDeviceGetConnectionID")); + if (m_AMDeviceGetConnectionID == 0) + addError("MobileDeviceLib does not define AMDeviceGetConnectionID"); + m_AMDeviceCopyDeviceIdentifier = reinterpret_cast(lib.resolve("AMDeviceCopyDeviceIdentifier")); + if (m_AMDeviceCopyDeviceIdentifier == 0) + addError("MobileDeviceLib does not define AMDeviceCopyDeviceIdentifier"); + m_AMDeviceConnect = reinterpret_cast(lib.resolve("AMDeviceConnect")); + if (m_AMDeviceConnect == 0) + addError("MobileDeviceLib does not define AMDeviceConnect"); + m_AMDevicePair = reinterpret_cast(lib.resolve("AMDevicePair")); + if (m_AMDevicePair == 0) + addError("MobileDeviceLib does not define AMDevicePair"); + m_AMDeviceIsPaired = reinterpret_cast(lib.resolve("AMDeviceIsPaired")); + if (m_AMDeviceIsPaired == 0) + addError("MobileDeviceLib does not define AMDeviceIsPaired"); + m_AMDeviceValidatePairing = reinterpret_cast(lib.resolve("AMDeviceValidatePairing")); + if (m_AMDeviceValidatePairing == 0) + addError("MobileDeviceLib does not define AMDeviceValidatePairing"); + m_AMDeviceStartSession = reinterpret_cast(lib.resolve("AMDeviceStartSession")); + if (m_AMDeviceStartSession == 0) + addError("MobileDeviceLib does not define AMDeviceStartSession"); + m_AMDeviceStopSession = reinterpret_cast(lib.resolve("AMDeviceStopSession")); + if (m_AMDeviceStopSession == 0) + addError("MobileDeviceLib does not define AMDeviceStopSession"); + m_AMDeviceDisconnect = reinterpret_cast(lib.resolve("AMDeviceDisconnect")); + if (m_AMDeviceDisconnect == 0) + addError("MobileDeviceLib does not define AMDeviceDisconnect"); + m_AMDeviceMountImage = reinterpret_cast(lib.resolve("AMDeviceMountImage")); + if (m_AMDeviceMountImage == 0) + addError("MobileDeviceLib does not define AMDeviceMountImage"); + m_AMDeviceSecureStartService = reinterpret_cast(lib.resolve("AMDeviceSecureStartService")); + if (m_AMDeviceSecureStartService == 0) + addError("MobileDeviceLib does not define AMDeviceSecureStartService"); + m_AMDeviceSecureTransferPath = reinterpret_cast(lib.resolve("AMDeviceSecureTransferPath")); + if (m_AMDeviceSecureTransferPath == 0) + addError("MobileDeviceLib does not define AMDeviceSecureTransferPath"); + m_AMDeviceSecureInstallApplication = reinterpret_cast(lib.resolve("AMDeviceSecureInstallApplication")); + if (m_AMDeviceSecureInstallApplication == 0) + addError("MobileDeviceLib does not define AMDeviceSecureInstallApplication"); + m_AMDServiceConnectionGetSocket = reinterpret_cast(lib.resolve("AMDServiceConnectionGetSocket")); + if (m_AMDServiceConnectionGetSocket == nullptr) + addError("MobileDeviceLib does not define AMDServiceConnectionGetSocket"); + m_AMDeviceUninstallApplication = reinterpret_cast(lib.resolve("AMDeviceUninstallApplication")); + if (m_AMDeviceUninstallApplication == 0) + addError("MobileDeviceLib does not define AMDeviceUninstallApplication"); + m_AMDeviceLookupApplications = reinterpret_cast(lib.resolve("AMDeviceLookupApplications")); + if (m_AMDeviceLookupApplications == 0) + addError("MobileDeviceLib does not define AMDeviceLookupApplications"); + m_AMDErrorString = reinterpret_cast(lib.resolve("AMDErrorString")); + if (m_AMDErrorString == 0) + addError("MobileDeviceLib does not define AMDErrorString"); + m_MISCopyErrorStringForErrorCode = reinterpret_cast(lib.resolve("MISCopyErrorStringForErrorCode")); + if (m_MISCopyErrorStringForErrorCode == 0) + addError("MobileDeviceLib does not define MISCopyErrorStringForErrorCode"); + m_USBMuxConnectByPort = reinterpret_cast(lib.resolve("USBMuxConnectByPort")); + if (m_USBMuxConnectByPort == 0) + addError("MobileDeviceLib does not define USBMuxConnectByPort"); +#endif + return true; +} + +bool MobileDeviceLib::isLoaded() +{ + return lib.isLoaded(); +} + +QStringList MobileDeviceLib::errors() +{ + return m_errors; +} + +void MobileDeviceLib::setLogLevel(int i) +{ + if (m_AMDSetLogLevel) + m_AMDSetLogLevel(i); +} + +am_res_t MobileDeviceLib::deviceNotificationSubscribe(AMDeviceNotificationCallback callback, + unsigned int v1, unsigned int v2, void *callbackArgs, + const AMDeviceNotification **handle) +{ + if (m_AMDeviceNotificationSubscribe) + return m_AMDeviceNotificationSubscribe(callback,v1,v2,callbackArgs,handle); + return -1; +} + +am_res_t MobileDeviceLib::deviceNotificationUnsubscribe(void *handle) +{ + if (m_AMDeviceNotificationUnsubscribe) + return m_AMDeviceNotificationUnsubscribe(handle); + return -1; +} + +int MobileDeviceLib::deviceGetInterfaceType(AMDeviceRef device) +{ + if (m_AMDeviceGetInterfaceType) + return m_AMDeviceGetInterfaceType(device); + return DeviceInterfaceType::UNKNOWN; +} + +CFPropertyListRef MobileDeviceLib::deviceCopyValue(AMDeviceRef device,CFStringRef group,CFStringRef key) +{ + if (m_AMDeviceCopyValue) + return m_AMDeviceCopyValue(device, group, key); + return 0; +} + +unsigned int MobileDeviceLib::deviceGetConnectionID(AMDeviceRef device) +{ + if (m_AMDeviceGetConnectionID) + return m_AMDeviceGetConnectionID(device); + return -1; +} + +CFStringRef MobileDeviceLib::deviceCopyDeviceIdentifier(AMDeviceRef device) +{ + if (m_AMDeviceCopyDeviceIdentifier) + return m_AMDeviceCopyDeviceIdentifier(device); + return 0; +} + +am_res_t MobileDeviceLib::deviceConnect(AMDeviceRef device) +{ + if (m_AMDeviceConnect) + return m_AMDeviceConnect(device); + return -1; +} + +am_res_t MobileDeviceLib::devicePair(AMDeviceRef device) +{ + if (m_AMDevicePair) + return m_AMDevicePair(device); + return -1; +} + +am_res_t MobileDeviceLib::deviceIsPaired(AMDeviceRef device) +{ + if (m_AMDeviceIsPaired) + return m_AMDeviceIsPaired(device); + return -1; +} + +am_res_t MobileDeviceLib::deviceValidatePairing(AMDeviceRef device) +{ + if (m_AMDeviceValidatePairing) + return m_AMDeviceValidatePairing(device); + return -1; +} + +am_res_t MobileDeviceLib::deviceStartSession(AMDeviceRef device) +{ + if (m_AMDeviceStartSession) + return m_AMDeviceStartSession(device); + return -1; +} + +am_res_t MobileDeviceLib::deviceStopSession(AMDeviceRef device) +{ + if (m_AMDeviceStopSession) + return m_AMDeviceStopSession(device); + return -1; +} + +am_res_t MobileDeviceLib::deviceDisconnect(AMDeviceRef device) +{ + if (m_AMDeviceDisconnect) + return m_AMDeviceDisconnect(device); + return -1; +} + +am_res_t MobileDeviceLib::deviceMountImage(AMDeviceRef device, CFStringRef imagePath, + CFDictionaryRef options, + AMDeviceMountImageCallback callback, + void *callbackExtraArgs) +{ + if (m_AMDeviceMountImage) + return m_AMDeviceMountImage(device, imagePath, options, callback, callbackExtraArgs); + return -1; +} + +am_res_t MobileDeviceLib::deviceUninstallApplication(int serviceFd, CFStringRef bundleId, + CFDictionaryRef options, + AMDeviceInstallApplicationCallback callback, + void *callbackExtraArgs) +{ + if (m_AMDeviceUninstallApplication) + return m_AMDeviceUninstallApplication(serviceFd, bundleId, options, callback, callbackExtraArgs); + return -1; +} + +am_res_t MobileDeviceLib::deviceLookupApplications(AMDeviceRef device, CFDictionaryRef options, + CFDictionaryRef *res) +{ + if (m_AMDeviceLookupApplications) + return m_AMDeviceLookupApplications(device, options, res); + return -1; +} + +char *MobileDeviceLib::errorString(am_res_t error) +{ + if (m_AMDErrorString) + return m_AMDErrorString(error); + return 0; +} + +CFStringRef MobileDeviceLib::misErrorStringForErrorCode(am_res_t error) +{ + if (m_MISCopyErrorStringForErrorCode) + return m_MISCopyErrorStringForErrorCode(error); + return NULL; +} + +am_res_t MobileDeviceLib::connectByPort(unsigned int connectionId, int port, ServiceSocket *resFd) +{ + if (m_USBMuxConnectByPort) + return m_USBMuxConnectByPort(connectionId, port, resFd); + return -1; +} + +void MobileDeviceLib::addError(const QString &msg) +{ + qDebug() << "MobileDeviceLib ERROR:" << msg; + m_errors << QLatin1String("MobileDeviceLib ERROR:") << msg; +} + +void MobileDeviceLib::addError(const char *msg) +{ + addError(QLatin1String(msg)); +} + +am_res_t MobileDeviceLib::deviceSecureStartService(AMDeviceRef device, CFStringRef serviceName, ServiceConnRef *fdRef) +{ + if (m_AMDeviceSecureStartService) + return m_AMDeviceSecureStartService(device, serviceName, nullptr, fdRef); + return 0; +} + +int MobileDeviceLib::deviceSecureTransferApplicationPath(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef dict, AMDeviceSecureInstallApplicationCallback callback, int args) +{ + int returnCode = -1; + if (m_AMDeviceSecureTransferPath) + returnCode = m_AMDeviceSecureTransferPath(zero, device, url, dict, callback, args); + return returnCode; +} + +int MobileDeviceLib::deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, AMDeviceSecureInstallApplicationCallback callback, int arg) +{ + int returnCode = -1; + if (m_AMDeviceSecureInstallApplication) { + returnCode = m_AMDeviceSecureInstallApplication(zero, device, url, options, callback, arg); + } + return returnCode; +} + +int MobileDeviceLib::deviceConnectionGetSocket(ServiceConnRef ref) { + int fd = 0; + if (m_AMDServiceConnectionGetSocket) + fd = m_AMDServiceConnectionGetSocket(ref); + return fd; +} +} // IOS diff --git a/src/tools/iostool/mobiledevicelib.h b/src/tools/iostool/mobiledevicelib.h new file mode 100644 index 00000000000..7fdac229038 --- /dev/null +++ b/src/tools/iostool/mobiledevicelib.h @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 "iostooltypes.h" + +#include +#include + + +/* // annoying to import, do without +#include +*/ +/* standard calling convention under Win32 is __stdcall */ +/* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */ +/* _WIN32 symbol is defined by the compiler even though it's NOT compiling code for Windows32 */ +#if defined(_WIN32) && !defined(EFI32) && !defined(EFI64) +#define MDEV_API __stdcall +#else +#define MDEV_API +#endif + +namespace Ios { +extern "C" { + +#ifndef MOBILE_DEV_DIRECT_LINK +class AMDeviceNotification; +typedef const AMDeviceNotification *AMDeviceNotificationRef; +class AMDevice; +struct AMDeviceNotificationCallbackInfo { + AMDevice *_device; + unsigned int _message; + AMDeviceNotification *_subscription; +}; + +enum DeviceInterfaceType { + UNKNOWN = 0, + WIRED, + WIFI +}; + +typedef unsigned int am_res_t; // mach_error_t + +typedef void (MDEV_API *AMDeviceNotificationCallback)(AMDeviceNotificationCallbackInfo *, void *); +typedef am_res_t (MDEV_API *AMDeviceInstallApplicationCallback)(CFDictionaryRef, void *); +typedef mach_error_t (MDEV_API *AMDeviceSecureInstallApplicationCallback)(CFDictionaryRef, int); + + +typedef AMDevice *AMDeviceRef; +#endif +typedef void (MDEV_API *AMDeviceMountImageCallback)(CFDictionaryRef, int); + +typedef void (MDEV_API *AMDSetLogLevelPtr)(int); +typedef am_res_t (MDEV_API *AMDeviceNotificationSubscribePtr)(AMDeviceNotificationCallback, + unsigned int, unsigned int, void *, + const AMDeviceNotification **); +typedef am_res_t (MDEV_API *AMDeviceNotificationUnsubscribePtr)(void *); +typedef int (MDEV_API* AMDeviceGetInterfaceTypePtr)(AMDeviceRef device); +typedef CFPropertyListRef (MDEV_API *AMDeviceCopyValuePtr)(AMDeviceRef,CFStringRef,CFStringRef); +typedef unsigned int (MDEV_API *AMDeviceGetConnectionIDPtr)(AMDeviceRef); +typedef CFStringRef (MDEV_API *AMDeviceCopyDeviceIdentifierPtr)(AMDeviceRef); +typedef am_res_t (MDEV_API *AMDeviceConnectPtr)(AMDeviceRef); +typedef am_res_t (MDEV_API *AMDevicePairPtr)(AMDeviceRef); +typedef am_res_t (MDEV_API *AMDeviceIsPairedPtr)(AMDeviceRef); +typedef am_res_t (MDEV_API *AMDeviceValidatePairingPtr)(AMDeviceRef); +typedef am_res_t (MDEV_API *AMDeviceStartSessionPtr)(AMDeviceRef); +typedef am_res_t (MDEV_API *AMDeviceStopSessionPtr)(AMDeviceRef); +typedef am_res_t (MDEV_API *AMDeviceDisconnectPtr)(AMDeviceRef); +typedef am_res_t (MDEV_API *AMDeviceMountImagePtr)(AMDeviceRef, CFStringRef, CFDictionaryRef, + AMDeviceMountImageCallback, void *); +typedef am_res_t (MDEV_API *AMDeviceUninstallApplicationPtr)(ServiceSocket, CFStringRef, CFDictionaryRef, + AMDeviceInstallApplicationCallback, + void*); +typedef am_res_t (MDEV_API *AMDeviceLookupApplicationsPtr)(AMDeviceRef, CFDictionaryRef, CFDictionaryRef *); +typedef char * (MDEV_API *AMDErrorStringPtr)(am_res_t); +typedef CFStringRef (MDEV_API *MISCopyErrorStringForErrorCodePtr)(am_res_t); +typedef am_res_t (MDEV_API *USBMuxConnectByPortPtr)(unsigned int, int, ServiceSocket*); +// secure Api's +typedef am_res_t (MDEV_API *AMDeviceSecureStartServicePtr)(AMDeviceRef, CFStringRef, unsigned int *, ServiceConnRef *); +typedef int (MDEV_API *AMDeviceSecureTransferPathPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int); +typedef int (MDEV_API *AMDeviceSecureInstallApplicationPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int); +typedef int (MDEV_API *AMDServiceConnectionGetSocketPtr)(ServiceConnRef); +} + +class MobileDeviceLib { +public : + MobileDeviceLib(); + + bool load(); + bool isLoaded(); + QStringList errors(); +// + + void setLogLevel(int i) ; + am_res_t deviceNotificationSubscribe(AMDeviceNotificationCallback callback, + unsigned int v1, unsigned int v2, void *v3, + const AMDeviceNotification **handle); + am_res_t deviceNotificationUnsubscribe(void *handle); + int deviceGetInterfaceType(AMDeviceRef device); + CFPropertyListRef deviceCopyValue(AMDeviceRef,CFStringRef,CFStringRef); + unsigned int deviceGetConnectionID(AMDeviceRef); + CFStringRef deviceCopyDeviceIdentifier(AMDeviceRef); + am_res_t deviceConnect(AMDeviceRef); + am_res_t devicePair(AMDeviceRef); + am_res_t deviceIsPaired(AMDeviceRef); + am_res_t deviceValidatePairing(AMDeviceRef); + am_res_t deviceStartSession(AMDeviceRef); + am_res_t deviceStopSession(AMDeviceRef); + am_res_t deviceDisconnect(AMDeviceRef); + am_res_t deviceMountImage(AMDeviceRef, CFStringRef, CFDictionaryRef, + AMDeviceMountImageCallback, void *); + am_res_t deviceUninstallApplication(int, CFStringRef, CFDictionaryRef, + AMDeviceInstallApplicationCallback, + void*); + am_res_t deviceLookupApplications(AMDeviceRef, CFDictionaryRef, CFDictionaryRef *); + char *errorString(am_res_t error); + CFStringRef misErrorStringForErrorCode(am_res_t error); + am_res_t connectByPort(unsigned int connectionId, int port, ServiceSocket *resFd); + + void addError(const QString &msg); + void addError(const char *msg); + + // Secure API's + am_res_t deviceSecureStartService(AMDeviceRef, CFStringRef, ServiceConnRef *); + int deviceConnectionGetSocket(ServiceConnRef); + int deviceSecureTransferApplicationPath(int, AMDeviceRef, CFURLRef, + CFDictionaryRef, AMDeviceSecureInstallApplicationCallback callback, int); + int deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, + CFDictionaryRef options, AMDeviceSecureInstallApplicationCallback callback, int arg); + + QStringList m_errors; + +private: + QLibrary lib; + QList deps; + AMDSetLogLevelPtr m_AMDSetLogLevel; + AMDeviceNotificationSubscribePtr m_AMDeviceNotificationSubscribe; + AMDeviceNotificationUnsubscribePtr m_AMDeviceNotificationUnsubscribe; + AMDeviceGetInterfaceTypePtr m_AMDeviceGetInterfaceType; + AMDeviceCopyValuePtr m_AMDeviceCopyValue; + AMDeviceGetConnectionIDPtr m_AMDeviceGetConnectionID; + AMDeviceCopyDeviceIdentifierPtr m_AMDeviceCopyDeviceIdentifier; + AMDeviceConnectPtr m_AMDeviceConnect; + AMDevicePairPtr m_AMDevicePair; + AMDeviceIsPairedPtr m_AMDeviceIsPaired; + AMDeviceValidatePairingPtr m_AMDeviceValidatePairing; + AMDeviceStartSessionPtr m_AMDeviceStartSession; + AMDeviceStopSessionPtr m_AMDeviceStopSession; + AMDeviceDisconnectPtr m_AMDeviceDisconnect; + AMDeviceMountImagePtr m_AMDeviceMountImage; + AMDeviceSecureStartServicePtr m_AMDeviceSecureStartService; + AMDeviceSecureTransferPathPtr m_AMDeviceSecureTransferPath; + AMDeviceSecureInstallApplicationPtr m_AMDeviceSecureInstallApplication; + AMDServiceConnectionGetSocketPtr m_AMDServiceConnectionGetSocket; + AMDeviceUninstallApplicationPtr m_AMDeviceUninstallApplication; + AMDeviceLookupApplicationsPtr m_AMDeviceLookupApplications; + AMDErrorStringPtr m_AMDErrorString; + MISCopyErrorStringForErrorCodePtr m_MISCopyErrorStringForErrorCode; + USBMuxConnectByPortPtr m_USBMuxConnectByPort; +}; +} diff --git a/src/tools/iostool/relayserver.cpp b/src/tools/iostool/relayserver.cpp new file mode 100644 index 00000000000..f952560752a --- /dev/null +++ b/src/tools/iostool/relayserver.cpp @@ -0,0 +1,342 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 "relayserver.h" + +#include "iostool.h" + +#ifdef Q_OS_UNIX +#include +#include +#endif + +// avoid utils dependency +#define QTC_CHECK(cond) if (cond) {} else { qWarning() << "assert failed " << #cond << " " \ + << __FILE__ << ":" << __LINE__; } do {} while (0) + +namespace Ios { +Relayer::Relayer(RelayServer *parent, QTcpSocket *clientSocket) : + QObject(parent), m_serverFileDescriptor(0), m_clientSocket(0), m_serverNotifier(0) +{ + setClientSocket(clientSocket); +} + +Relayer::~Relayer() +{ + if (m_serverFileDescriptor > 0) { + ::close(m_serverFileDescriptor); + m_serverFileDescriptor = -1; + if (m_serverNotifier) + delete m_serverNotifier; + } + if (m_clientSocket->isOpen()) + m_clientSocket->close(); + delete m_clientSocket; +} + +void Relayer::setClientSocket(QTcpSocket *clientSocket) +{ + QTC_CHECK(!m_clientSocket); + m_clientSocket = clientSocket; + if (m_clientSocket) { +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + const auto errorOccurred = QOverload::of(&QAbstractSocket::error); +#else + const auto errorOccurred = &QAbstractSocket::errorOccurred; +#endif + connect(m_clientSocket, errorOccurred, this, &Relayer::handleClientHasError); + connect(m_clientSocket, &QAbstractSocket::disconnected, + this, [this](){server()->removeRelayConnection(this);}); + } +} + +bool Relayer::startRelay(int serverFileDescriptor) +{ + QTC_CHECK(!m_serverFileDescriptor); + m_serverFileDescriptor = serverFileDescriptor; + if (!m_clientSocket || m_serverFileDescriptor <= 0) + return false; + fcntl(serverFileDescriptor,F_SETFL, fcntl(serverFileDescriptor, F_GETFL) | O_NONBLOCK); + connect(m_clientSocket, &QIODevice::readyRead, this, &Relayer::handleClientHasData); + m_serverNotifier = new QSocketNotifier(m_serverFileDescriptor, QSocketNotifier::Read, this); + connect(m_serverNotifier, &QSocketNotifier::activated, this, &Relayer::handleSocketHasData); + // no way to check if an error did happen? + if (m_clientSocket->bytesAvailable() > 0) + handleClientHasData(); + return true; +} + +void Relayer::handleSocketHasData(int socket) +{ + m_serverNotifier->setEnabled(false); + char buf[255]; + while (true) { + qptrdiff rRead = read(socket, &buf, sizeof(buf)-1); + if (rRead == -1) { + if (errno == EINTR) + continue; + if (errno == EAGAIN) { + m_serverNotifier->setEnabled(true); + return; + } + iosTool()->errorMsg(qt_error_string(errno)); + close(socket); + iosTool()->stopRelayServers(-1); + return; + } + if (rRead == 0) { + iosTool()->stopRelayServers(0); + return; + } + if (iosTool()->echoRelays()) { + iosTool()->writeMaybeBin(QString::fromLatin1("%1 serverReplies:") + .arg((quintptr)(void *)this), buf, rRead); + } + qint64 pos = 0; + while (true) { + qint64 writtenNow = m_clientSocket->write(buf + int(pos), rRead); + if (writtenNow == -1) { + iosTool()->writeMsg(m_clientSocket->errorString()); + iosTool()->stopRelayServers(-1); + return; + } + if (writtenNow < rRead) { + pos += writtenNow; + rRead -= qptrdiff(writtenNow); + } else { + break; + } + } + m_clientSocket->flush(); + } +} + +void Relayer::handleClientHasData() +{ + char buf[255]; + while (true) { + qint64 toRead = m_clientSocket->bytesAvailable(); + if (qint64(sizeof(buf)-1) < toRead) + toRead = sizeof(buf)-1; + qint64 rRead = m_clientSocket->read(buf, toRead); + if (rRead == -1) { + iosTool()->errorMsg(m_clientSocket->errorString()); + iosTool()->stopRelayServers(); + return; + } + if (rRead == 0) { + if (!m_clientSocket->isOpen()) + iosTool()->stopRelayServers(); + return; + } + int pos = 0; + int irep = 0; + if (iosTool()->echoRelays()) { + iosTool()->writeMaybeBin(QString::fromLatin1("%1 clientAsks:") + .arg((quintptr)(void *)this), buf, rRead); + } + while (true) { + qptrdiff written = write(m_serverFileDescriptor, buf + pos, rRead); + if (written == -1) { + if (errno == EINTR) + continue; + if (errno == EAGAIN) { + if (++irep > 10) { + sleep(1); + irep = 0; + } + continue; + } + iosTool()->errorMsg(qt_error_string(errno)); + iosTool()->stopRelayServers(); + return; + } + if (written == 0) { + iosTool()->stopRelayServers(); + return; + } + if (written < rRead) { + pos += written; + rRead -= written; + } else { + break; + } + } + } +} + +void Relayer::handleClientHasError(QAbstractSocket::SocketError error) +{ + iosTool()->errorMsg(tr("iOS Debugging connection to creator failed with error %1").arg(error)); + server()->removeRelayConnection(this); +} + +IosTool *Relayer::iosTool() const +{ + return (server() ? server()->iosTool() : 0); +} + +RelayServer *Relayer::server() const +{ + return qobject_cast(parent()); +} + +RemotePortRelayer::RemotePortRelayer(GenericRelayServer *parent, QTcpSocket *clientSocket) : + Relayer(parent, clientSocket) +{ + m_remoteConnectTimer.setSingleShot(true); + m_remoteConnectTimer.setInterval(reconnectMsecDelay); + connect(&m_remoteConnectTimer, &QTimer::timeout, this, &RemotePortRelayer::tryRemoteConnect); +} + +void RemotePortRelayer::tryRemoteConnect() +{ + iosTool()->errorMsg(QLatin1String("tryRemoteConnect")); + if (m_serverFileDescriptor > 0) + return; + ServiceSocket ss; + GenericRelayServer *grServer = qobject_cast(server()); + if (!grServer) + return; + if (grServer->m_deviceSession->connectToPort(grServer->m_remotePort, &ss)) { + if (ss > 0) { + iosTool()->errorMsg(QString::fromLatin1("tryRemoteConnect *succeeded* on remote port %1") + .arg(grServer->m_remotePort)); + startRelay(ss); + emit didConnect(grServer); + return; + } + } + iosTool()->errorMsg(QString::fromLatin1("tryRemoteConnect *failed* on remote port %1") + .arg(grServer->m_remotePort)); + m_remoteConnectTimer.start(); +} + +RelayServer::RelayServer(IosTool *parent): + QObject(parent) +{ } + +RelayServer::~RelayServer() +{ + stopServer(); +} + +bool RelayServer::startServer() +{ + QTC_CHECK(!m_ipv4Server.isListening()); + QTC_CHECK(!m_ipv6Server.isListening()); + + connect(&m_ipv4Server, &QTcpServer::newConnection, + this, &RelayServer::handleNewRelayConnection); + connect(&m_ipv6Server, &QTcpServer::newConnection, + this, &RelayServer::handleNewRelayConnection); + + m_port = 0; + if (m_ipv4Server.listen(QHostAddress(QHostAddress::LocalHost), 0)) + m_port = m_ipv4Server.serverPort(); + if (m_ipv6Server.listen(QHostAddress(QHostAddress::LocalHostIPv6), m_port)) + m_port = m_ipv6Server.serverPort(); + + return m_port > 0; +} + +void RelayServer::stopServer() +{ + foreach (Relayer *connection, m_connections) + delete connection; + if (m_ipv4Server.isListening()) + m_ipv4Server.close(); + if (m_ipv6Server.isListening()) + m_ipv6Server.close(); +} + +quint16 RelayServer::serverPort() const +{ + return m_port; +} + +IosTool *RelayServer::iosTool() const +{ + return qobject_cast(parent()); +} + +void RelayServer::handleNewRelayConnection() +{ + iosTool()->errorMsg(QLatin1String("handleNewRelayConnection")); + newRelayConnection(); +} + +void RelayServer::removeRelayConnection(Relayer *relayer) +{ + m_connections.removeAll(relayer); + relayer->deleteLater(); +} + +SingleRelayServer::SingleRelayServer(IosTool *parent, + int serverFileDescriptor) : + RelayServer(parent) +{ + m_serverFileDescriptor = serverFileDescriptor; + if (m_serverFileDescriptor > 0) + fcntl(m_serverFileDescriptor, F_SETFL, fcntl(m_serverFileDescriptor, F_GETFL, 0) | O_NONBLOCK); +} + +void SingleRelayServer::newRelayConnection() +{ + QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections() + ? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection(); + if (m_connections.size() > 0) { + delete clientSocket; + return; + } + if (clientSocket) { + Relayer *newConnection = new Relayer(this, clientSocket); + m_connections.append(newConnection); + newConnection->startRelay(m_serverFileDescriptor); + } +} + +GenericRelayServer::GenericRelayServer(IosTool *parent, int remotePort, + Ios::DeviceSession *deviceSession) : + RelayServer(parent), + m_remotePort(remotePort), + m_deviceSession(deviceSession) +{ + parent->errorMsg(QLatin1String("created qml server")); +} + + +void GenericRelayServer::newRelayConnection() +{ + QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections() + ? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection(); + if (clientSocket) { + iosTool()->errorMsg(QString::fromLatin1("setting up relayer for new connection")); + RemotePortRelayer *newConnection = new RemotePortRelayer(this, clientSocket); + m_connections.append(newConnection); + newConnection->tryRemoteConnect(); + } +} +} diff --git a/src/tools/iostool/relayserver.h b/src/tools/iostool/relayserver.h new file mode 100644 index 00000000000..d41932f47d2 --- /dev/null +++ b/src/tools/iostool/relayserver.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 "iostooltypes.h" + +#include + +#include +#include +#include +#include + +namespace Ios { +class DeviceSession; +class IosTool; +class RelayServer; +class GenericRelayServer; + +class Relayer: public QObject +{ + Q_OBJECT + +public: + Relayer(RelayServer *parent, QTcpSocket *clientSocket); + ~Relayer(); + void setClientSocket(QTcpSocket *clientSocket); + bool startRelay(int serverFileDescriptor); + + void handleSocketHasData(int socket); + void handleClientHasData(); + void handleClientHasError(QAbstractSocket::SocketError error); + +protected: + IosTool *iosTool() const; + RelayServer *server() const; + ServiceSocket m_serverFileDescriptor; + QTcpSocket *m_clientSocket; + QSocketNotifier *m_serverNotifier; +}; + +class RemotePortRelayer: public Relayer +{ + Q_OBJECT + +public: + static const int reconnectMsecDelay = 500; + static const int maxReconnectAttempts = 2*60*5; // 5 min + RemotePortRelayer(GenericRelayServer *parent, QTcpSocket *clientSocket); + void tryRemoteConnect(); + +signals: + void didConnect(GenericRelayServer *serv); + +private: + QTimer m_remoteConnectTimer; +}; + +class RelayServer: public QObject +{ + Q_OBJECT + +public: + RelayServer(IosTool *parent); + ~RelayServer(); + bool startServer(); + void stopServer(); + quint16 serverPort() const; + IosTool *iosTool() const; + + void handleNewRelayConnection(); + void removeRelayConnection(Relayer *relayer); + +protected: + virtual void newRelayConnection() = 0; + + QTcpServer m_ipv4Server; + QTcpServer m_ipv6Server; + quint16 m_port = 0; + QList m_connections; +}; + +class SingleRelayServer: public RelayServer +{ + Q_OBJECT + +public: + SingleRelayServer(IosTool *parent, int serverFileDescriptor); + +protected: + void newRelayConnection() override; + +private: + int m_serverFileDescriptor; +}; + +class GenericRelayServer: public RelayServer +{ + Q_OBJECT + +public: + GenericRelayServer(IosTool *parent, int remotePort, + Ios::DeviceSession *deviceSession); + +protected: + void newRelayConnection() override; + +private: + int m_remotePort; + DeviceSession *m_deviceSession; + friend class RemotePortRelayer; +}; +} From 4d1e3276fc91fbd62d2a18e80fadc01b47d873b8 Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Sun, 7 Mar 2021 01:07:01 +0100 Subject: [PATCH 16/22] iOS: Fix iOS 14 application launch Use service connection to receive and send gdb commands. Communication via socket can no longer be done. Apple introduced this change to plug the security issue when debug session was done over wifi Task-number: QTCREATORBUG-24672 Change-Id: I7ad08242c3b13a2707b6320ee5bc1e18b5f1173d Reviewed-by: Eike Ziller --- src/tools/iostool/gdbrunner.cpp | 11 +- src/tools/iostool/gdbrunner.h | 6 +- src/tools/iostool/iosdevicemanager.cpp | 147 +++++++++++++++---------- src/tools/iostool/iosdevicemanager.h | 6 +- src/tools/iostool/iostool.cpp | 4 +- src/tools/iostool/iostool.h | 2 +- src/tools/iostool/iostooltypes.h | 8 +- src/tools/iostool/mobiledevicelib.cpp | 44 ++++++++ src/tools/iostool/mobiledevicelib.h | 22 +++- 9 files changed, 177 insertions(+), 73 deletions(-) diff --git a/src/tools/iostool/gdbrunner.cpp b/src/tools/iostool/gdbrunner.cpp index 1234a472c3f..e39d82cac2b 100644 --- a/src/tools/iostool/gdbrunner.cpp +++ b/src/tools/iostool/gdbrunner.cpp @@ -26,6 +26,7 @@ #include "gdbrunner.h" #include "iostool.h" +#include "mobiledevicelib.h" #ifdef Q_OS_UNIX #include @@ -34,10 +35,10 @@ namespace Ios { -GdbRunner::GdbRunner(IosTool *iosTool, int gdbFd) : +GdbRunner::GdbRunner(IosTool *iosTool, ServiceConnRef conn) : QObject(nullptr), m_iosTool(iosTool), - m_gdbFd(gdbFd) + m_conn(conn) { } @@ -51,7 +52,7 @@ void GdbRunner::run() } m_iosTool->outFile.flush(); } - Ios::IosDeviceManager::instance()->processGdbServer(m_gdbFd); + Ios::IosDeviceManager::instance()->processGdbServer(m_conn); { QMutexLocker l(&m_iosTool->m_xmlMutex); if (!m_iosTool->splitAppOutput) { @@ -60,14 +61,14 @@ void GdbRunner::run() } m_iosTool->outFile.flush(); } - close(m_gdbFd); + close(m_conn->sockfd); m_iosTool->doExit(); emit finished(); } void GdbRunner::stop(int phase) { - Ios::IosDeviceManager::instance()->stopGdbServer(m_gdbFd, phase); + Ios::IosDeviceManager::instance()->stopGdbServer(m_conn, phase); } } diff --git a/src/tools/iostool/gdbrunner.h b/src/tools/iostool/gdbrunner.h index 27eea4beaf4..77b7ceae97f 100644 --- a/src/tools/iostool/gdbrunner.h +++ b/src/tools/iostool/gdbrunner.h @@ -27,6 +27,8 @@ #include +#include "iostooltypes.h" + namespace Ios { class IosTool; class GdbRunner: public QObject @@ -34,7 +36,7 @@ class GdbRunner: public QObject Q_OBJECT public: - GdbRunner(IosTool *iosTool, int gdbFd); + GdbRunner(IosTool *iosTool, ServiceConnRef conn); void stop(int phase); void run(); @@ -43,6 +45,6 @@ signals: private: IosTool *m_iosTool; - int m_gdbFd; + ServiceConnRef m_conn = nullptr; }; } diff --git a/src/tools/iostool/iosdevicemanager.cpp b/src/tools/iostool/iosdevicemanager.cpp index 1d9b1874ce1..53914f1d590 100644 --- a/src/tools/iostool/iosdevicemanager.cpp +++ b/src/tools/iostool/iosdevicemanager.cpp @@ -45,6 +45,7 @@ #include #include +#include static const bool debugGdbServer = false; static const bool debugAll = false; @@ -200,6 +201,19 @@ static bool findDeveloperDiskImage(const QString &versionStr, const QString &bui return true; } +bool disable_ssl(ServiceConnRef ref) +{ + typedef void (*SSL_free_t)(void*); + static SSL_free_t SSL_free = nullptr; + if (!SSL_free) + SSL_free = (SSL_free_t)dlsym(RTLD_DEFAULT, "SSL_free"); + if (!SSL_free) + return false; + SSL_free(ref->sslContext); + ref->sslContext = nullptr; + return true; +} + extern "C" { typedef void (*DeviceAvailableCallback)(QString deviceId, AMDeviceRef, void *userData); } @@ -234,11 +248,11 @@ public: void addError(const QString &msg); bool writeAll(ServiceSocket fd, const char *cmd, qptrdiff len = -1); bool mountDeveloperDiskImage(); - bool sendGdbCommand(ServiceSocket fd, const char *cmd, qptrdiff len = -1); - QByteArray readGdbReply(ServiceSocket fd); - bool expectGdbReply(ServiceSocket gdbFd, QByteArray expected); - bool expectGdbOkReply(ServiceSocket gdbFd); - bool startServiceSecure(const QString &serviceName, ServiceSocket &fd); + bool sendGdbCommand(ServiceConnRef conn, const char *cmd, qptrdiff len = -1); + QByteArray readGdbReply(ServiceConnRef conn); + bool expectGdbReply(ServiceConnRef conn, QByteArray expected); + bool expectGdbOkReply(ServiceConnRef conn); + bool startServiceSecure(const QString &serviceName, ServiceConnRef &conn); MobileDeviceLib *lib(); @@ -252,7 +266,7 @@ private: private: bool checkRead(qptrdiff nRead, int &maxRetry); - int handleChar(int sock, QByteArray &res, char c, int status); + int handleChar(ServiceConnRef conn, QByteArray &res, char c, int status); }; // ------- IosManagerPrivate interface -------- @@ -275,12 +289,12 @@ public: void didTransferApp(const QString &bundlePath, const QString &deviceId, Ios::IosDeviceManager::OpStatus status); void didStartApp(const QString &bundlePath, const QString &deviceId, - Ios::IosDeviceManager::OpStatus status, int gdbFd, DeviceSession *deviceSession); + Ios::IosDeviceManager::OpStatus status, ServiceConnRef conn, int gdbFd, DeviceSession *deviceSession); void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress, const QString &info); void deviceWithId(QString deviceId, int timeout, DeviceAvailableCallback callback, void *userData); - int processGdbServer(int fd); - void stopGdbServer(int fd, int phase); + int processGdbServer(ServiceConnRef conn); + void stopGdbServer(ServiceConnRef conn, int phase); private: IosDeviceManager *q; QMutex m_sendMutex; @@ -601,11 +615,11 @@ void IosDeviceManagerPrivate::didTransferApp(const QString &bundlePath, const QS } void IosDeviceManagerPrivate::didStartApp(const QString &bundlePath, const QString &deviceId, - IosDeviceManager::OpStatus status, int gdbFd, - DeviceSession *deviceSession) + IosDeviceManager::OpStatus status, ServiceConnRef conn, + int gdbFd, DeviceSession *deviceSession) { - emit IosDeviceManagerPrivate::instance()->q->didStartApp(bundlePath, deviceId, status, gdbFd, - deviceSession); + emit IosDeviceManagerPrivate::instance()->q->didStartApp(bundlePath, deviceId, status, conn, + gdbFd, deviceSession); } void IosDeviceManagerPrivate::isTransferringApp(const QString &bundlePath, const QString &deviceId, @@ -655,18 +669,18 @@ enum GdbServerStatus { PROTOCOL_UNHANDLED }; -int IosDeviceManagerPrivate::processGdbServer(int fd) +int IosDeviceManagerPrivate::processGdbServer(ServiceConnRef conn) { CommandSession session((QString())); { QMutexLocker l(&m_sendMutex); - session.sendGdbCommand(fd, "vCont;c"); // resume all threads + session.sendGdbCommand(conn, "vCont;c"); // resume all threads } GdbServerStatus state = NORMAL_PROCESS; int maxRetry = 10; int maxSignal = 5; while (state == NORMAL_PROCESS) { - QByteArray repl = session.readGdbReply(fd); + QByteArray repl = session.readGdbReply(conn); int signal = 0; if (repl.size() > 0) { state = PROTOCOL_ERROR; @@ -746,7 +760,7 @@ int IosDeviceManagerPrivate::processGdbServer(int fd) state = NORMAL_PROCESS; // Ctrl-C to kill the process } else { QMutexLocker l(&m_sendMutex); - if (session.sendGdbCommand(fd, "vCont;c")) + if (session.sendGdbCommand(conn, "vCont;c")) state = NORMAL_PROCESS; else break; @@ -764,14 +778,14 @@ int IosDeviceManagerPrivate::processGdbServer(int fd) return state != INFERIOR_EXITED; } -void IosDeviceManagerPrivate::stopGdbServer(int fd, int phase) +void IosDeviceManagerPrivate::stopGdbServer(ServiceConnRef conn, int phase) { CommandSession session((QString())); QMutexLocker l(&m_sendMutex); if (phase == 0) - session.writeAll(fd,"\x03",1); + lib()->serviceConnectionSend(conn, "\x03", 1); else - session.sendGdbCommand(fd, "k", 1); + session.sendGdbCommand(conn, "k", 1); } // ------- ConnectSession implementation -------- @@ -827,21 +841,22 @@ bool CommandSession::disconnectDevice() return true; } -bool CommandSession::startServiceSecure(const QString &serviceName, ServiceSocket &fd) +bool CommandSession::startServiceSecure(const QString &serviceName, ServiceConnRef &conn) { bool success = true; // Connect device. AMDeviceConnect + AMDeviceIsPaired + AMDeviceValidatePairing + AMDeviceStartSession if (connectDevice()) { CFStringRef cfsService = serviceName.toCFString(); - ServiceConnRef ref; - if (am_res_t error = lib()->deviceSecureStartService(device, cfsService, &ref)) { + if (am_res_t error = lib()->deviceSecureStartService(device, cfsService, &conn)) { addError(QString::fromLatin1("Starting(Secure) service \"%1\" on device %2 failed, AMDeviceStartSecureService returned %3 (0x%4)") .arg(serviceName).arg(deviceId).arg(mobileDeviceErrorString(lib(), error)).arg(QString::number(error, 16))); success = false; - fd = 0; } else { - fd = lib()->deviceConnectionGetSocket(ref); + if (!conn) { + addError(QString("Starting(Secure) service \"%1\" on device %2 failed." + "Invalid service connection").arg(serviceName).arg(deviceId)); + } } disconnectDevice(); CFRelease(cfsService); @@ -985,23 +1000,23 @@ bool CommandSession::mountDeveloperDiskImage() { return success; } -bool CommandSession::sendGdbCommand(ServiceSocket fd, const char *cmd, qptrdiff len) +bool CommandSession::sendGdbCommand(ServiceConnRef conn, const char *cmd, qptrdiff len) { if (len == -1) len = strlen(cmd); unsigned char checkSum = 0; for (int i = 0; i < len; ++i) checkSum += static_cast(cmd[i]); - bool failure = !writeAll(fd, "$", 1); + bool failure = lib()->serviceConnectionSend(conn, "$", 1) == 0; if (!failure) - failure = !writeAll(fd, cmd, len); + failure = lib()->serviceConnectionSend(conn, cmd, len) == 0; char buf[3]; buf[0] = '#'; const char *hex = "0123456789abcdef"; buf[1] = hex[(checkSum >> 4) & 0xF]; buf[2] = hex[checkSum & 0xF]; if (!failure) - failure = !writeAll(fd, buf, 3); + failure = lib()->serviceConnectionSend(conn, buf, 3) == 0; return !failure; } @@ -1029,7 +1044,7 @@ bool CommandSession::checkRead(qptrdiff nRead, int &maxRetry) return true; } -int CommandSession::handleChar(int fd, QByteArray &res, char c, int status) +int CommandSession::handleChar(ServiceConnRef conn, QByteArray &res, char c, int status) { switch (status) { case 0: @@ -1065,7 +1080,7 @@ int CommandSession::handleChar(int fd, QByteArray &res, char c, int status) } } if (status == 3 && aknowledge) - writeAll(fd, "+", 1); + lib()->serviceConnectionSend(conn, "+", 1); return status + 1; case 4: addError(QString::fromLatin1("gone past end in readGdbReply")); @@ -1078,7 +1093,7 @@ int CommandSession::handleChar(int fd, QByteArray &res, char c, int status) } } -QByteArray CommandSession::readGdbReply(ServiceSocket fd) +QByteArray CommandSession::readGdbReply(ServiceConnRef conn) { // read with minimal buffering because we might want to give the socket away... QByteArray res; @@ -1087,7 +1102,7 @@ QByteArray CommandSession::readGdbReply(ServiceSocket fd) int status = 0; int toRead = 4; while (status < 4 && toRead > 0) { - qptrdiff nRead = read(fd, buf, toRead); + qptrdiff nRead = lib()->serviceConnectionReceive(conn, buf, toRead); if (!checkRead(nRead, maxRetry)) return QByteArray(); if (debugGdbServer) { @@ -1095,7 +1110,7 @@ QByteArray CommandSession::readGdbReply(ServiceSocket fd) qDebug() << "gdbReply read " << buf; } for (qptrdiff i = 0; i< nRead; ++i) - status = handleChar(fd, res, buf[i], status); + status = handleChar(conn, res, buf[i], status); toRead = 4 - status; } if (status != 4) { @@ -1133,9 +1148,9 @@ QString CommandSession::commandName() return QString::fromLatin1("CommandSession(%1)").arg(deviceId); } -bool CommandSession::expectGdbReply(ServiceSocket gdbFd, QByteArray expected) +bool CommandSession::expectGdbReply(ServiceConnRef conn, QByteArray expected) { - QByteArray repl = readGdbReply(gdbFd); + QByteArray repl = readGdbReply(conn); if (repl != expected) { addError(QString::fromLatin1("Unexpected reply: %1 (%2) vs %3 (%4)") .arg(QString::fromLocal8Bit(repl.constData(), repl.size())) @@ -1147,9 +1162,9 @@ bool CommandSession::expectGdbReply(ServiceSocket gdbFd, QByteArray expected) return true; } -bool CommandSession::expectGdbOkReply(ServiceSocket gdbFd) +bool CommandSession::expectGdbOkReply(ServiceConnRef conn) { - return expectGdbReply(gdbFd, QByteArray("OK")); + return expectGdbReply(conn, QByteArray("OK")); } MobileDeviceLib *CommandSession::lib() @@ -1304,23 +1319,40 @@ bool AppOpSession::runApp() { bool failure = (device == 0); QString exe = appPathOnDevice(); - ServiceSocket gdbFd = -1; if (!mountDeveloperDiskImage()) { addError(QString::fromLatin1("Running app \"%1\" failed. Mount developer disk failed.").arg(bundlePath)); failure = true; } - if (!failure && !startServiceSecure(QLatin1String("com.apple.debugserver"), gdbFd)) - gdbFd = 0; - if (gdbFd > 0) { + CFStringRef keys[] = { CFSTR("MinIPhoneVersion"), CFSTR("MinAppleTVVersion") }; + CFStringRef values[] = { CFSTR("14.0"), CFSTR("14.0")}; + CFDictionaryRef version = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, + 2, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + bool useSecureProxy = lib()->deviceIsAtLeastVersionOnPlatform(device, version); + // The debugserver service cannot be launched directly on iOS 14+ + // A secure proxy service sits between the actual debugserver service. + const QString &serviceName = useSecureProxy ? DebugSecureServiceName : DebugServiceName; + ServiceConnRef conn = nullptr; + if (!failure) + startServiceSecure(serviceName, conn); + + if (conn) { + // For older devices remove the ssl encryption as we can directly connecting with the + // debugserver service, i.e. not the secure proxy service. + if (!useSecureProxy) + disable_ssl(conn); // gdbServer protocol, see http://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html#Remote-Protocol // and the lldb handling of that (with apple specific stuff) // http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBRemote.cpp //failure = !sendGdbCommand(gdbFd, "QStartNoAckMode"); // avoid and send required aknowledgements? //if (!failure) failure = !expectGdbOkReply(gdbFd); - if (!failure) failure = !sendGdbCommand(gdbFd, "QEnvironmentHexEncoded:"); // send the environment with a series of these commands... - if (!failure) failure = !sendGdbCommand(gdbFd, "QSetDisableASLR:1"); // avoid address randomization to debug - if (!failure) failure = !expectGdbOkReply(gdbFd); + + // send the environment with a series of these commands... + if (!failure) failure = !sendGdbCommand(conn, "QEnvironmentHexEncoded:"); + // avoid address randomization to debug + if (!failure) failure = !sendGdbCommand(conn, "QSetDisableASLR:1"); + if (!failure) failure = !expectGdbOkReply(conn); QStringList args = extraArgs; QByteArray runCommand("A"); args.insert(0, exe); @@ -1336,14 +1368,17 @@ bool AppOpSession::runApp() runCommand.append(','); runCommand.append(arg); } - if (!failure) failure = !sendGdbCommand(gdbFd, runCommand.constData(), runCommand.size()); - if (!failure) failure = !expectGdbOkReply(gdbFd); - if (!failure) failure = !sendGdbCommand(gdbFd, "qLaunchSuccess"); - if (!failure) failure = !expectGdbOkReply(gdbFd); + if (!failure) failure = !sendGdbCommand(conn, runCommand.constData(), runCommand.size()); + if (!failure) failure = !expectGdbOkReply(conn); + if (!failure) failure = !sendGdbCommand(conn, "qLaunchSuccess"); + if (!failure) failure = !expectGdbOkReply(conn); + } else { + failure = true; } - IosDeviceManagerPrivate::instance()->didStartApp( - bundlePath, deviceId, - (failure ? IosDeviceManager::Failure : IosDeviceManager::Success), gdbFd, this); + + CFSocketNativeHandle fd = failure ? 0 : lib()->deviceConnectionGetSocket(conn); + auto status = failure ? IosDeviceManager::Failure : IosDeviceManager::Success; + IosDeviceManagerPrivate::instance()->didStartApp(bundlePath, deviceId, status, conn, fd, this); return !failure; } @@ -1544,14 +1579,14 @@ void IosDeviceManager::requestDeviceInfo(const QString &deviceId, int timeout) d->requestDeviceInfo(deviceId, timeout); } -int IosDeviceManager::processGdbServer(int fd) +int IosDeviceManager::processGdbServer(ServiceConnRef conn) { - return d->processGdbServer(fd); + return d->processGdbServer(conn); } -void IosDeviceManager::stopGdbServer(int fd, int phase) +void IosDeviceManager::stopGdbServer(ServiceConnRef conn, int phase) { - return d->stopGdbServer(fd, phase); + return d->stopGdbServer(conn, phase); } QStringList IosDeviceManager::errors() { diff --git a/src/tools/iostool/iosdevicemanager.h b/src/tools/iostool/iosdevicemanager.h index a16403010a9..7c521c789fd 100644 --- a/src/tools/iostool/iosdevicemanager.h +++ b/src/tools/iostool/iosdevicemanager.h @@ -64,8 +64,8 @@ public: void requestAppOp(const QString &bundlePath, const QStringList &extraArgs, AppOp appOp, const QString &deviceId, int timeout = 1000); void requestDeviceInfo(const QString &deviceId, int timeout = 1000); - int processGdbServer(int fd); - void stopGdbServer(int fd, int phase); + int processGdbServer(ServiceConnRef conn); + void stopGdbServer(ServiceConnRef conn, int phase); QStringList errors(); signals: @@ -76,7 +76,7 @@ signals: void didTransferApp(const QString &bundlePath, const QString &deviceId, Ios::IosDeviceManager::OpStatus status); void didStartApp(const QString &bundlePath, const QString &deviceId, - Ios::IosDeviceManager::OpStatus status, int gdbFd, + Ios::IosDeviceManager::OpStatus status, ServiceConnRef conn, int gdbFd, Ios::DeviceSession *deviceSession); void deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &info); void appOutput(const QString &output); diff --git a/src/tools/iostool/iostool.cpp b/src/tools/iostool/iostool.cpp index 9123dcec73a..d0be8ede5e9 100644 --- a/src/tools/iostool/iostool.cpp +++ b/src/tools/iostool/iostool.cpp @@ -227,7 +227,7 @@ void IosTool::didTransferApp(const QString &bundlePath, const QString &deviceId, } void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId, - IosDeviceManager::OpStatus status, int gdbFd, + IosDeviceManager::OpStatus status, ServiceConnRef conn, int gdbFd, DeviceSession *deviceSession) { Q_UNUSED(bundlePath) @@ -281,7 +281,7 @@ void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId, outFile.flush(); } if (!debug) { - gdbRunner = new GdbRunner(this, gdbFd); + gdbRunner = new GdbRunner(this, conn); // we should not stop the event handling of the main thread // all output moves to the new thread (other option would be to signal it back) QThread *gdbProcessThread = new QThread(); diff --git a/src/tools/iostool/iostool.h b/src/tools/iostool/iostool.h index 24e78c66810..3519982c9b9 100644 --- a/src/tools/iostool/iostool.h +++ b/src/tools/iostool/iostool.h @@ -63,7 +63,7 @@ private: void didTransferApp(const QString &bundlePath, const QString &deviceId, Ios::IosDeviceManager::OpStatus status); void didStartApp(const QString &bundlePath, const QString &deviceId, - IosDeviceManager::OpStatus status, int gdbFd, + IosDeviceManager::OpStatus status, ServiceConnRef conn, int gdbFd, DeviceSession *deviceSession); void deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &info); void appOutput(const QString &output); diff --git a/src/tools/iostool/iostooltypes.h b/src/tools/iostool/iostooltypes.h index 766afe143d2..d665ebb44b0 100644 --- a/src/tools/iostool/iostooltypes.h +++ b/src/tools/iostool/iostooltypes.h @@ -31,8 +31,12 @@ #include - extern "C" { +struct service_conn_t { + char unknown[0x10]; + int sockfd; + void *sslContext = nullptr; +}; +typedef service_conn_t *ServiceConnRef; typedef unsigned int ServiceSocket; // match_port_t (i.e. natural_t) or socket (on windows, i.e sock_t) -typedef unsigned int *ServiceConnRef; } // extern C diff --git a/src/tools/iostool/mobiledevicelib.cpp b/src/tools/iostool/mobiledevicelib.cpp index 87ce4fd8d34..7f18f49a33c 100644 --- a/src/tools/iostool/mobiledevicelib.cpp +++ b/src/tools/iostool/mobiledevicelib.cpp @@ -130,6 +130,18 @@ bool MobileDeviceLib::load() if (m_AMDServiceConnectionGetSocket == nullptr) addError("MobileDeviceLib does not define AMDServiceConnectionGetSocket"); m_AMDeviceUninstallApplication = reinterpret_cast(lib.resolve("AMDeviceUninstallApplication")); + m_AMDServiceConnectionSend = reinterpret_cast(lib.resolve("AMDServiceConnectionSend")); + if (m_AMDServiceConnectionSend == nullptr) + addError("MobileDeviceLib does not define AMDServiceConnectionSend"); + m_AMDServiceConnectionReceive = reinterpret_cast(lib.resolve("AMDServiceConnectionReceive")); + if (m_AMDServiceConnectionReceive == nullptr) + addError("MobileDeviceLib does not define AMDServiceConnectionReceive"); + m_AMDServiceConnectionInvalidate = reinterpret_cast(lib.resolve("AMDServiceConnectionInvalidate")); + if (m_AMDServiceConnectionInvalidate == nullptr) + addError("MobileDeviceLib does not define AMDServiceConnectionInvalidate"); + m_AMDeviceIsAtLeastVersionOnPlatform = reinterpret_cast(lib.resolve("AMDeviceIsAtLeastVersionOnPlatform")); + if (m_AMDeviceIsAtLeastVersionOnPlatform == nullptr) + addError("MobileDeviceLib does not define AMDeviceIsAtLeastVersionOnPlatform"); if (m_AMDeviceUninstallApplication == 0) addError("MobileDeviceLib does not define AMDeviceUninstallApplication"); m_AMDeviceLookupApplications = reinterpret_cast(lib.resolve("AMDeviceLookupApplications")); @@ -347,4 +359,36 @@ int MobileDeviceLib::deviceConnectionGetSocket(ServiceConnRef ref) { fd = m_AMDServiceConnectionGetSocket(ref); return fd; } + +int MobileDeviceLib::serviceConnectionSend(ServiceConnRef ref, const void *data, size_t size) +{ + int bytesSent = -1; + if (m_AMDServiceConnectionSend) { + bytesSent = m_AMDServiceConnectionSend(ref, data, size); + } + return bytesSent; +} + +int MobileDeviceLib::serviceConnectionReceive(ServiceConnRef ref, void *data, size_t size) +{ + int bytestRead = 0; + if (m_AMDServiceConnectionReceive) { + bytestRead = m_AMDServiceConnectionReceive(ref, data, size); + } + return bytestRead; +} + +void MobileDeviceLib::serviceConnectionInvalidate(ServiceConnRef serviceConnRef) +{ + if (m_AMDServiceConnectionInvalidate) + m_AMDServiceConnectionInvalidate(serviceConnRef); +} + +bool MobileDeviceLib::deviceIsAtLeastVersionOnPlatform(AMDeviceRef device, CFDictionaryRef versions) +{ + if (m_AMDeviceIsAtLeastVersionOnPlatform) + return m_AMDeviceIsAtLeastVersionOnPlatform(device, versions); + return false; +} + } // IOS diff --git a/src/tools/iostool/mobiledevicelib.h b/src/tools/iostool/mobiledevicelib.h index 7fdac229038..37eae664302 100644 --- a/src/tools/iostool/mobiledevicelib.h +++ b/src/tools/iostool/mobiledevicelib.h @@ -103,6 +103,11 @@ typedef am_res_t (MDEV_API *AMDeviceSecureStartServicePtr)(AMDeviceRef, CFString typedef int (MDEV_API *AMDeviceSecureTransferPathPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int); typedef int (MDEV_API *AMDeviceSecureInstallApplicationPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int); typedef int (MDEV_API *AMDServiceConnectionGetSocketPtr)(ServiceConnRef); + +typedef int (MDEV_API *AMDServiceConnectionSendPtr)(ServiceConnRef, const void *, size_t); +typedef int (MDEV_API *AMDServiceConnectionReceivePtr)(ServiceConnRef, void *, size_t); +typedef void (MDEV_API *AMDServiceConnectionInvalidatePtr)(ServiceConnRef); +typedef bool (MDEV_API *AMDeviceIsAtLeastVersionOnPlatformPtr)(AMDeviceRef, CFDictionaryRef); } class MobileDeviceLib { @@ -147,9 +152,18 @@ public : am_res_t deviceSecureStartService(AMDeviceRef, CFStringRef, ServiceConnRef *); int deviceConnectionGetSocket(ServiceConnRef); int deviceSecureTransferApplicationPath(int, AMDeviceRef, CFURLRef, - CFDictionaryRef, AMDeviceSecureInstallApplicationCallback callback, int); + CFDictionaryRef, + AMDeviceSecureInstallApplicationCallback callback, int); int deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, - CFDictionaryRef options, AMDeviceSecureInstallApplicationCallback callback, int arg); + CFDictionaryRef options, + AMDeviceSecureInstallApplicationCallback callback, int arg); + + // Use MobileDevice API's to communicate with service launched on the device. + // The communication is encrypted if ServiceConnRef::sslContext is valid. + int serviceConnectionSend(ServiceConnRef ref, const void *data, size_t size); + int serviceConnectionReceive(ServiceConnRef ref, void *data, size_t size); + void serviceConnectionInvalidate(ServiceConnRef serviceConnRef); + bool deviceIsAtLeastVersionOnPlatform(AMDeviceRef device, CFDictionaryRef versions); QStringList m_errors; @@ -175,6 +189,10 @@ private: AMDeviceSecureTransferPathPtr m_AMDeviceSecureTransferPath; AMDeviceSecureInstallApplicationPtr m_AMDeviceSecureInstallApplication; AMDServiceConnectionGetSocketPtr m_AMDServiceConnectionGetSocket; + AMDServiceConnectionSendPtr m_AMDServiceConnectionSend; + AMDServiceConnectionReceivePtr m_AMDServiceConnectionReceive; + AMDServiceConnectionInvalidatePtr m_AMDServiceConnectionInvalidate; + AMDeviceIsAtLeastVersionOnPlatformPtr m_AMDeviceIsAtLeastVersionOnPlatform; AMDeviceUninstallApplicationPtr m_AMDeviceUninstallApplication; AMDeviceLookupApplicationsPtr m_AMDeviceLookupApplications; AMDErrorStringPtr m_AMDErrorString; From b152a7287c3655652842a98d97e82da5531818be Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Wed, 10 Mar 2021 13:20:25 +0100 Subject: [PATCH 17/22] iOS: Create single instance of mobile device library wrapper Task-number: QTCREATORBUG-24672 Change-Id: I30f0022735409dbbd03b6bdadf7138ff6294b131 Reviewed-by: Eike Ziller --- src/tools/iostool/gdbrunner.cpp | 3 +- src/tools/iostool/iosdevicemanager.cpp | 126 +++++++++++++------------ src/tools/iostool/mobiledevicelib.cpp | 13 +++ src/tools/iostool/mobiledevicelib.h | 10 +- 4 files changed, 86 insertions(+), 66 deletions(-) diff --git a/src/tools/iostool/gdbrunner.cpp b/src/tools/iostool/gdbrunner.cpp index e39d82cac2b..4f4f110c125 100644 --- a/src/tools/iostool/gdbrunner.cpp +++ b/src/tools/iostool/gdbrunner.cpp @@ -61,7 +61,8 @@ void GdbRunner::run() } m_iosTool->outFile.flush(); } - close(m_conn->sockfd); + MobileDeviceLib::instance().serviceConnectionInvalidate(m_conn); + m_conn = nullptr; m_iosTool->doExit(); emit finished(); } diff --git a/src/tools/iostool/iosdevicemanager.cpp b/src/tools/iostool/iosdevicemanager.cpp index 53914f1d590..cab1d69ed3f 100644 --- a/src/tools/iostool/iosdevicemanager.cpp +++ b/src/tools/iostool/iosdevicemanager.cpp @@ -77,12 +77,13 @@ static const QString DebugServiceName = "com.apple.debugserver"; static const QString DebugSecureServiceName = "com.apple.debugserver.DVTSecureSocketProxy"; -static QString mobileDeviceErrorString(MobileDeviceLib *lib, am_res_t code) +static QString mobileDeviceErrorString(am_res_t code) { QString s = QStringLiteral("Unknown error (0x%08x)").arg(code); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); // AMDErrors, 0x0, 0xe8000001-0xe80000db - if (char *ptr = lib->errorString(code)) { + if (char *ptr = mLib.errorString(code)) { CFStringRef key = QString::fromLatin1(ptr).toCFString(); CFURLRef url = QUrl::fromLocalFile( @@ -98,7 +99,7 @@ static QString mobileDeviceErrorString(MobileDeviceLib *lib, am_res_t code) } CFRelease(key); - } else if (CFStringRef str = lib->misErrorStringForErrorCode(code)) { + } else if (CFStringRef str = mLib.misErrorStringForErrorCode(code)) { // MIS errors, 0xe8008001-0xe800801e s = QString::fromCFString(str); CFRelease(str); @@ -254,8 +255,6 @@ public: bool expectGdbOkReply(ServiceConnRef conn); bool startServiceSecure(const QString &serviceName, ServiceConnRef &conn); - MobileDeviceLib *lib(); - AMDeviceRef device; int progressBase; int unexpectedChars; @@ -301,7 +300,6 @@ private: QHash m_devices; QMultiHash m_pendingLookups; AMDeviceNotificationRef m_notification; - MobileDeviceLib m_lib; }; class DevInfoSession: public CommandSession { @@ -472,14 +470,8 @@ IosDeviceManagerPrivate::IosDeviceManagerPrivate (IosDeviceManager *q) : q(q), m bool IosDeviceManagerPrivate::watchDevices() { - if (!m_lib.load()) - addError(QLatin1String("Error loading MobileDevice.framework")); - if (!m_lib.errors().isEmpty()) { - foreach (const QString &msg, m_lib.errors()) - addError(msg); - } - m_lib.setLogLevel(5); - am_res_t e = m_lib.deviceNotificationSubscribe(&deviceNotificationCallback, 0, 0, + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + am_res_t e = mLib.deviceNotificationSubscribe(&deviceNotificationCallback, 0, 0, 0, &m_notification); if (e != 0) { addError(QLatin1String("AMDeviceNotificationSubscribe failed")); @@ -508,7 +500,8 @@ void IosDeviceManagerPrivate::requestDeviceInfo(const QString &deviceId, int tim QStringList IosDeviceManagerPrivate::errors() { - return m_lib.errors(); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + return mLib.errors(); } void IosDeviceManagerPrivate::addError(QString errorMsg) @@ -520,7 +513,8 @@ void IosDeviceManagerPrivate::addError(QString errorMsg) QString IosDeviceManagerPrivate::deviceId(AMDeviceRef device) { - CFStringRef s = m_lib.deviceCopyDeviceIdentifier(device); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + CFStringRef s = mLib.deviceCopyDeviceIdentifier(device); // remove dashes as a hotfix for QTCREATORBUG-21291 const auto id = QString::fromCFString(s).remove('-'); if (s) CFRelease(s); @@ -532,7 +526,8 @@ void IosDeviceManagerPrivate::addDevice(AMDeviceRef device) const QString devId = deviceId(device); CFRetain(device); - DeviceInterfaceType interfaceType = static_cast(lib()->deviceGetInterfaceType(device)); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + DeviceInterfaceType interfaceType = static_cast(mLib.deviceGetInterfaceType(device)); if (interfaceType == DeviceInterfaceType::UNKNOWN) { if (debugAll) qDebug() << "Skipping device." << devId << "Interface type: Unknown."; @@ -603,11 +598,6 @@ void IosDeviceManagerPrivate::checkPendingLookups() } } -MobileDeviceLib *IosDeviceManagerPrivate::lib() -{ - return &m_lib; -} - void IosDeviceManagerPrivate::didTransferApp(const QString &bundlePath, const QString &deviceId, IosDeviceManager::OpStatus status) { @@ -782,8 +772,9 @@ void IosDeviceManagerPrivate::stopGdbServer(ServiceConnRef conn, int phase) { CommandSession session((QString())); QMutexLocker l(&m_sendMutex); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); if (phase == 0) - lib()->serviceConnectionSend(conn, "\x03", 1); + mLib.serviceConnectionSend(conn, "\x03", 1); else session.sendGdbCommand(conn, "k", 1); } @@ -801,26 +792,27 @@ bool CommandSession::connectDevice() if (!device) return false; - if (am_res_t error1 = lib()->deviceConnect(device)) { + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + if (am_res_t error1 = mLib.deviceConnect(device)) { addError(QString::fromLatin1("connectDevice %1 failed, AMDeviceConnect returned %2 (0x%3)") - .arg(deviceId).arg(mobileDeviceErrorString(lib(), error1)).arg(error1)); + .arg(deviceId).arg(mobileDeviceErrorString(error1)).arg(error1)); return false; } - if (lib()->deviceIsPaired(device) == 0) { // not paired - if (am_res_t error = lib()->devicePair(device)) { + if (mLib.deviceIsPaired(device) == 0) { // not paired + if (am_res_t error = mLib.devicePair(device)) { addError(QString::fromLatin1("connectDevice %1 failed, AMDevicePair returned %2 (0x%3)") - .arg(deviceId).arg(mobileDeviceErrorString(lib(), error)).arg(error)); + .arg(deviceId).arg(mobileDeviceErrorString(error)).arg(error)); return false; } } - if (am_res_t error2 = lib()->deviceValidatePairing(device)) { + if (am_res_t error2 = mLib.deviceValidatePairing(device)) { addError(QString::fromLatin1("connectDevice %1 failed, AMDeviceValidatePairing returned %2 (0x%3)") - .arg(deviceId).arg(mobileDeviceErrorString(lib(), error2)).arg(error2)); + .arg(deviceId).arg(mobileDeviceErrorString(error2)).arg(error2)); return false; } - if (am_res_t error3 = lib()->deviceStartSession(device)) { + if (am_res_t error3 = mLib.deviceStartSession(device)) { addError(QString::fromLatin1("connectDevice %1 failed, AMDeviceStartSession returned %2 (0x%3)") - .arg(deviceId).arg(mobileDeviceErrorString(lib(), error3)).arg(error3)); + .arg(deviceId).arg(mobileDeviceErrorString(error3)).arg(error3)); return false; } return true; @@ -828,14 +820,15 @@ bool CommandSession::connectDevice() bool CommandSession::disconnectDevice() { - if (am_res_t error = lib()->deviceStopSession(device)) { + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + if (am_res_t error = mLib.deviceStopSession(device)) { addError(QString::fromLatin1("stopSession %1 failed, AMDeviceStopSession returned %2 (0x%3)") - .arg(deviceId).arg(mobileDeviceErrorString(lib(), error)).arg(error)); + .arg(deviceId).arg(mobileDeviceErrorString(error)).arg(error)); return false; } - if (am_res_t error = lib()->deviceDisconnect(device)) { + if (am_res_t error = mLib.deviceDisconnect(device)) { addError(QString::fromLatin1("disconnectDevice %1 failed, AMDeviceDisconnect returned %2 (0x%3)") - .arg(deviceId).arg(mobileDeviceErrorString(lib(), error)).arg(error)); + .arg(deviceId).arg(mobileDeviceErrorString(error)).arg(error)); return false; } return true; @@ -848,9 +841,10 @@ bool CommandSession::startServiceSecure(const QString &serviceName, ServiceConnR // Connect device. AMDeviceConnect + AMDeviceIsPaired + AMDeviceValidatePairing + AMDeviceStartSession if (connectDevice()) { CFStringRef cfsService = serviceName.toCFString(); - if (am_res_t error = lib()->deviceSecureStartService(device, cfsService, &conn)) { + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + if (am_res_t error = mLib.deviceSecureStartService(device, cfsService, &conn)) { addError(QString::fromLatin1("Starting(Secure) service \"%1\" on device %2 failed, AMDeviceStartSecureService returned %3 (0x%4)") - .arg(serviceName).arg(deviceId).arg(mobileDeviceErrorString(lib(), error)).arg(QString::number(error, 16))); + .arg(serviceName).arg(deviceId).arg(mobileDeviceErrorString(error)).arg(QString::number(error, 16))); success = false; } else { if (!conn) { @@ -877,7 +871,9 @@ bool CommandSession::connectToPort(quint16 port, ServiceSocket *fd) ServiceSocket fileDescriptor; if (!connectDevice()) return false; - if (am_res_t error = lib()->connectByPort(lib()->deviceGetConnectionID(device), htons(port), &fileDescriptor)) { + + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + if (am_res_t error = mLib.connectByPort(mLib.deviceGetConnectionID(device), htons(port), &fileDescriptor)) { addError(QString::fromLatin1("connectByPort on device %1 port %2 failed, AMDeviceStartService returned %3") .arg(deviceId).arg(port).arg(error)); failure = true; @@ -977,13 +973,14 @@ bool CommandSession::mountDeveloperDiskImage() { if (connectDevice()) { CFStringRef cfImgPath = imagePath.toCFString(); - am_res_t result = lib()->deviceMountImage(device, cfImgPath, options, &mountCallback, 0); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + am_res_t result = mLib.deviceMountImage(device, cfImgPath, options, &mountCallback, 0); if (result == 0 || result == kAMDMobileImageMounterImageMountFailed) { // Mounting succeeded or developer image already installed success = true; } else { addError(QString::fromLatin1("Mount Developer Disk Image \"%1\" failed, AMDeviceMountImage returned %2 (0x%3)") - .arg(imagePath).arg(mobileDeviceErrorString(lib(), result)).arg(QString::number(result, 16))); + .arg(imagePath).arg(mobileDeviceErrorString(result)).arg(QString::number(result, 16))); } CFRelease(cfImgPath); disconnectDevice(); @@ -1007,16 +1004,18 @@ bool CommandSession::sendGdbCommand(ServiceConnRef conn, const char *cmd, qptrdi unsigned char checkSum = 0; for (int i = 0; i < len; ++i) checkSum += static_cast(cmd[i]); - bool failure = lib()->serviceConnectionSend(conn, "$", 1) == 0; + + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + bool failure = mLib.serviceConnectionSend(conn, "$", 1) == 0; if (!failure) - failure = lib()->serviceConnectionSend(conn, cmd, len) == 0; + failure = mLib.serviceConnectionSend(conn, cmd, len) == 0; char buf[3]; buf[0] = '#'; const char *hex = "0123456789abcdef"; buf[1] = hex[(checkSum >> 4) & 0xF]; buf[2] = hex[checkSum & 0xF]; if (!failure) - failure = lib()->serviceConnectionSend(conn, buf, 3) == 0; + failure = mLib.serviceConnectionSend(conn, buf, 3) == 0; return !failure; } @@ -1079,8 +1078,10 @@ int CommandSession::handleChar(ServiceConnRef conn, QByteArray &res, char c, int ++unexpectedChars; } } - if (status == 3 && aknowledge) - lib()->serviceConnectionSend(conn, "+", 1); + if (status == 3 && aknowledge) { + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + mLib.serviceConnectionSend(conn, "+", 1); + } return status + 1; case 4: addError(QString::fromLatin1("gone past end in readGdbReply")); @@ -1101,8 +1102,9 @@ QByteArray CommandSession::readGdbReply(ServiceConnRef conn) int maxRetry = 10; int status = 0; int toRead = 4; + MobileDeviceLib &mLib = MobileDeviceLib::instance(); while (status < 4 && toRead > 0) { - qptrdiff nRead = lib()->serviceConnectionReceive(conn, buf, toRead); + qptrdiff nRead = mLib.serviceConnectionReceive(conn, buf, toRead); if (!checkRead(nRead, maxRetry)) return QByteArray(); if (debugGdbServer) { @@ -1167,22 +1169,18 @@ bool CommandSession::expectGdbOkReply(ServiceConnRef conn) return expectGdbReply(conn, QByteArray("OK")); } -MobileDeviceLib *CommandSession::lib() -{ - return IosDeviceManagerPrivate::instance()->lib(); -} - bool CommandSession::developerDiskImagePath(QString *path, QString *signaturePath) { if (device && path && connectDevice()) { - CFPropertyListRef cfProductVersion = lib()->deviceCopyValue(device, 0, CFSTR("ProductVersion")); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + CFPropertyListRef cfProductVersion = mLib.deviceCopyValue(device, 0, CFSTR("ProductVersion")); QString versionString; if (cfProductVersion && CFGetTypeID(cfProductVersion) == CFStringGetTypeID()) { versionString = QString::fromCFString(reinterpret_cast(cfProductVersion)); } CFRelease(cfProductVersion); - CFPropertyListRef cfBuildVersion = lib()->deviceCopyValue(device, 0, CFSTR("BuildVersion")); + CFPropertyListRef cfBuildVersion = mLib.deviceCopyValue(device, 0, CFSTR("BuildVersion")); QString buildString; if (cfBuildVersion && CFGetTypeID(cfBuildVersion) == CFStringGetTypeID()) { buildString = QString::fromCFString(reinterpret_cast(cfBuildVersion)); @@ -1225,19 +1223,20 @@ bool AppOpSession::installApp() &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); // Transfer bundle with secure API AMDeviceTransferApplication. - if (int error = lib()->deviceSecureTransferApplicationPath(0, device, bundleUrl, options, + if (int error = mLib.deviceSecureTransferApplicationPath(0, device, bundleUrl, options, &appSecureTransferSessionCallback,0)) { addError(QString::fromLatin1("TransferAppSession(%1,%2) failed, AMDeviceTransferApplication returned %3 (0x%4)") - .arg(bundlePath, deviceId).arg(mobileDeviceErrorString(lib(), error)).arg(error)); + .arg(bundlePath, deviceId).arg(mobileDeviceErrorString(error)).arg(error)); success = false; } else { // App is transferred. Try installing. if (connectDevice()) { // Secure install app api requires device to be connected. - if (am_res_t error = lib()->deviceSecureInstallApplication(0, device, bundleUrl, options, + if (am_res_t error = mLib.deviceSecureInstallApplication(0, device, bundleUrl, options, &appSecureTransferSessionCallback,0)) { - const QString errorString = mobileDeviceErrorString(lib(), error); + const QString errorString = mobileDeviceErrorString(error); if (!errorString.isEmpty()) { addError(errorString + QStringLiteral(" (0x") @@ -1329,7 +1328,8 @@ bool AppOpSession::runApp() CFDictionaryRef version = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - bool useSecureProxy = lib()->deviceIsAtLeastVersionOnPlatform(device, version); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + bool useSecureProxy = mLib.deviceIsAtLeastVersionOnPlatform(device, version); // The debugserver service cannot be launched directly on iOS 14+ // A secure proxy service sits between the actual debugserver service. const QString &serviceName = useSecureProxy ? DebugSecureServiceName : DebugServiceName; @@ -1376,7 +1376,7 @@ bool AppOpSession::runApp() failure = true; } - CFSocketNativeHandle fd = failure ? 0 : lib()->deviceConnectionGetSocket(conn); + CFSocketNativeHandle fd = failure ? 0 : mLib.deviceConnectionGetSocket(conn); auto status = failure ? IosDeviceManager::Failure : IosDeviceManager::Success; IosDeviceManagerPrivate::instance()->didStartApp(bundlePath, deviceId, status, conn, fd, this); return !failure; @@ -1413,7 +1413,8 @@ QString AppOpSession::appPathOnDevice() (const void**)(&lookupKeys), 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFRelease(lookupKeys); - if (int err = lib()->deviceLookupApplications(device, options, &apps)) { + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + if (int err = mLib.deviceLookupApplications(device, options, &apps)) { addError(QString::fromLatin1("app lookup failed, AMDeviceLookupApplications returned %1") .arg(err)); } @@ -1475,7 +1476,8 @@ QString DevInfoSession::getStringValue(AMDevice *device, const QString &fallback) { QString value = fallback; - CFPropertyListRef cfValue = lib()->deviceCopyValue(device, domain, key); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + CFPropertyListRef cfValue = mLib.deviceCopyValue(device, domain, key); if (cfValue) { if (CFGetTypeID(cfValue) == CFStringGetTypeID()) value = QString::fromCFString(reinterpret_cast(cfValue)); diff --git a/src/tools/iostool/mobiledevicelib.cpp b/src/tools/iostool/mobiledevicelib.cpp index 7f18f49a33c..79c4054a0d4 100644 --- a/src/tools/iostool/mobiledevicelib.cpp +++ b/src/tools/iostool/mobiledevicelib.cpp @@ -33,8 +33,21 @@ #endif namespace Ios { +MobileDeviceLib &MobileDeviceLib::instance() +{ + static MobileDeviceLib lib; + return lib; +} + MobileDeviceLib::MobileDeviceLib() { + if (!load()) + addError(QLatin1String("Error loading MobileDevice.framework")); + if (!errors().isEmpty()) { + foreach (const QString &msg, errors()) + addError(msg); + } + setLogLevel(5); } bool MobileDeviceLib::load() diff --git a/src/tools/iostool/mobiledevicelib.h b/src/tools/iostool/mobiledevicelib.h index 37eae664302..97735fdcb1a 100644 --- a/src/tools/iostool/mobiledevicelib.h +++ b/src/tools/iostool/mobiledevicelib.h @@ -111,13 +111,17 @@ typedef bool (MDEV_API *AMDeviceIsAtLeastVersionOnPlatformPtr)(AMDeviceRef, CFDi } class MobileDeviceLib { -public : MobileDeviceLib(); - bool load(); + +public: + MobileDeviceLib( const MobileDeviceLib& ) = delete; + MobileDeviceLib &operator=( const MobileDeviceLib& ) = delete; + + static MobileDeviceLib &instance(); + bool isLoaded(); QStringList errors(); -// void setLogLevel(int i) ; am_res_t deviceNotificationSubscribe(AMDeviceNotificationCallback callback, From 35d7bc49f0b8766c541274489a37334d3acb6a92 Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Wed, 10 Mar 2021 14:25:17 +0100 Subject: [PATCH 18/22] iOS: Add relay server to route gdb data via service connection Communication using sockets can no longer be done for gdb server, though a TCP socket opened using USB MUX still operates normally. I.e the QML debug server communication remains as is but GDB server data has to be routed via the secure service connection Task-number: QTCREATORBUG-24672 Change-Id: I64631d66dc845dd2d7a20c771534ae17e183a9b8 Reviewed-by: Eike Ziller --- src/tools/iostool/iostool.cpp | 4 +- src/tools/iostool/iostool.h | 8 +-- src/tools/iostool/relayserver.cpp | 100 +++++++++++++++++++++++------- src/tools/iostool/relayserver.h | 41 ++++++++---- 4 files changed, 115 insertions(+), 38 deletions(-) diff --git a/src/tools/iostool/iostool.cpp b/src/tools/iostool/iostool.cpp index d0be8ede5e9..e65cae852a4 100644 --- a/src/tools/iostool/iostool.cpp +++ b/src/tools/iostool/iostool.cpp @@ -259,12 +259,12 @@ void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId, if (deviceSession) { int qmlPort = deviceSession->qmljsDebugPort(); if (qmlPort) { - qmlServer = new GenericRelayServer(this, qmlPort, deviceSession); + qmlServer = new QmlRelayServer(this, qmlPort, deviceSession); qmlServer->startServer(); } } if (debug) { - gdbServer = new SingleRelayServer(this, gdbFd); + gdbServer = new GdbRelayServer(this, gdbFd, conn); if (!gdbServer->startServer()) { doExit(-4); return; diff --git a/src/tools/iostool/iostool.h b/src/tools/iostool/iostool.h index 3519982c9b9..a2fd1f040e4 100644 --- a/src/tools/iostool/iostool.h +++ b/src/tools/iostool/iostool.h @@ -34,8 +34,8 @@ namespace Ios { class GdbRunner; -class SingleRelayServer; -class GenericRelayServer; +class GdbRelayServer; +class QmlRelayServer; class IosTool: public QObject { @@ -79,8 +79,8 @@ private: QFile outFile; QString m_qmlPort; QXmlStreamWriter out; - SingleRelayServer *gdbServer; - GenericRelayServer *qmlServer; + GdbRelayServer *gdbServer; + QmlRelayServer *qmlServer; GdbRunner *gdbRunner; bool m_echoRelays = false; friend class GdbRunner; diff --git a/src/tools/iostool/relayserver.cpp b/src/tools/iostool/relayserver.cpp index f952560752a..449f86057db 100644 --- a/src/tools/iostool/relayserver.cpp +++ b/src/tools/iostool/relayserver.cpp @@ -26,6 +26,7 @@ #include "relayserver.h" #include "iostool.h" +#include "mobiledevicelib.h" #ifdef Q_OS_UNIX #include @@ -45,15 +46,7 @@ Relayer::Relayer(RelayServer *parent, QTcpSocket *clientSocket) : Relayer::~Relayer() { - if (m_serverFileDescriptor > 0) { - ::close(m_serverFileDescriptor); - m_serverFileDescriptor = -1; - if (m_serverNotifier) - delete m_serverNotifier; - } - if (m_clientSocket->isOpen()) - m_clientSocket->close(); - delete m_clientSocket; + closeConnection(); } void Relayer::setClientSocket(QTcpSocket *clientSocket) @@ -93,7 +86,7 @@ void Relayer::handleSocketHasData(int socket) m_serverNotifier->setEnabled(false); char buf[255]; while (true) { - qptrdiff rRead = read(socket, &buf, sizeof(buf)-1); + qptrdiff rRead = readData(socket, &buf, sizeof(buf)-1); if (rRead == -1) { if (errno == EINTR) continue; @@ -158,7 +151,7 @@ void Relayer::handleClientHasData() .arg((quintptr)(void *)this), buf, rRead); } while (true) { - qptrdiff written = write(m_serverFileDescriptor, buf + pos, rRead); + qptrdiff written = writeData(m_serverFileDescriptor, buf + pos, rRead); if (written == -1) { if (errno == EINTR) continue; @@ -193,6 +186,32 @@ void Relayer::handleClientHasError(QAbstractSocket::SocketError error) server()->removeRelayConnection(this); } +int Relayer::readData(int socketFd, void *buf, size_t size) +{ + return read(socketFd, buf, size); +} + +int Relayer::writeData(int socketFd, const void *data, size_t size) +{ + return write(socketFd, data, size); +} + +void Relayer::closeConnection() +{ + if (m_serverFileDescriptor > 0) { + ::close(m_serverFileDescriptor); + m_serverFileDescriptor = -1; + if (m_serverNotifier) { + delete m_serverNotifier; + m_serverNotifier = nullptr; + } + } + if (m_clientSocket->isOpen()) + m_clientSocket->close(); + delete m_clientSocket; + m_clientSocket = nullptr; +} + IosTool *Relayer::iosTool() const { return (server() ? server()->iosTool() : 0); @@ -203,7 +222,7 @@ RelayServer *Relayer::server() const return qobject_cast(parent()); } -RemotePortRelayer::RemotePortRelayer(GenericRelayServer *parent, QTcpSocket *clientSocket) : +RemotePortRelayer::RemotePortRelayer(QmlRelayServer *parent, QTcpSocket *clientSocket) : Relayer(parent, clientSocket) { m_remoteConnectTimer.setSingleShot(true); @@ -217,7 +236,7 @@ void RemotePortRelayer::tryRemoteConnect() if (m_serverFileDescriptor > 0) return; ServiceSocket ss; - GenericRelayServer *grServer = qobject_cast(server()); + QmlRelayServer *grServer = qobject_cast(server()); if (!grServer) return; if (grServer->m_deviceSession->connectToPort(grServer->m_remotePort, &ss)) { @@ -294,16 +313,17 @@ void RelayServer::removeRelayConnection(Relayer *relayer) relayer->deleteLater(); } -SingleRelayServer::SingleRelayServer(IosTool *parent, - int serverFileDescriptor) : - RelayServer(parent) +GdbRelayServer::GdbRelayServer(IosTool *parent, + int serverFileDescriptor, ServiceConnRef conn) : + RelayServer(parent), + m_serverFileDescriptor(serverFileDescriptor), + m_serviceConn(conn) { - m_serverFileDescriptor = serverFileDescriptor; if (m_serverFileDescriptor > 0) fcntl(m_serverFileDescriptor, F_SETFL, fcntl(m_serverFileDescriptor, F_GETFL, 0) | O_NONBLOCK); } -void SingleRelayServer::newRelayConnection() +void GdbRelayServer::newRelayConnection() { QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections() ? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection(); @@ -312,13 +332,13 @@ void SingleRelayServer::newRelayConnection() return; } if (clientSocket) { - Relayer *newConnection = new Relayer(this, clientSocket); + Relayer *newConnection = new ServiceConnectionRelayer(this, clientSocket, m_serviceConn); m_connections.append(newConnection); newConnection->startRelay(m_serverFileDescriptor); } } -GenericRelayServer::GenericRelayServer(IosTool *parent, int remotePort, +QmlRelayServer::QmlRelayServer(IosTool *parent, int remotePort, Ios::DeviceSession *deviceSession) : RelayServer(parent), m_remotePort(remotePort), @@ -328,7 +348,7 @@ GenericRelayServer::GenericRelayServer(IosTool *parent, int remotePort, } -void GenericRelayServer::newRelayConnection() +void QmlRelayServer::newRelayConnection() { QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections() ? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection(); @@ -339,4 +359,42 @@ void GenericRelayServer::newRelayConnection() newConnection->tryRemoteConnect(); } } + +ServiceConnectionRelayer::ServiceConnectionRelayer(RelayServer *parent, QTcpSocket *clientSocket, + ServiceConnRef conn) + : Relayer(parent, clientSocket), + m_serviceConn(conn) +{ + +} + +int ServiceConnectionRelayer::readData(int socketFd, void *buf, size_t size) +{ + Q_UNUSED(socketFd) + if (!buf || !m_serviceConn) + return 0; + MobileDeviceLib &mlib = MobileDeviceLib::instance(); + return mlib.serviceConnectionReceive(m_serviceConn, buf, size); +} + +int ServiceConnectionRelayer::writeData(int socketFd, const void *data, size_t size) +{ + Q_UNUSED(socketFd) + if (!data || !m_serviceConn) + return 0; + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + return mLib.serviceConnectionSend(m_serviceConn, data, size); +} + +void ServiceConnectionRelayer::closeConnection() +{ + Relayer::closeConnection(); + if (m_serviceConn) { + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + mLib.serviceConnectionInvalidate(m_serviceConn); + m_serviceConn = nullptr; + } + +} + } diff --git a/src/tools/iostool/relayserver.h b/src/tools/iostool/relayserver.h index d41932f47d2..0b01b7271e1 100644 --- a/src/tools/iostool/relayserver.h +++ b/src/tools/iostool/relayserver.h @@ -38,7 +38,7 @@ namespace Ios { class DeviceSession; class IosTool; class RelayServer; -class GenericRelayServer; +class QmlRelayServer; class Relayer: public QObject { @@ -55,11 +55,29 @@ public: void handleClientHasError(QAbstractSocket::SocketError error); protected: + virtual int readData(int socketFd, void* buf, size_t size); + virtual int writeData(int socketFd, const void *data, size_t size); + virtual void closeConnection(); + IosTool *iosTool() const; RelayServer *server() const; ServiceSocket m_serverFileDescriptor; - QTcpSocket *m_clientSocket; - QSocketNotifier *m_serverNotifier; + QTcpSocket *m_clientSocket = nullptr; + QSocketNotifier *m_serverNotifier = nullptr; +}; + +class ServiceConnectionRelayer : public Relayer +{ +public: + ServiceConnectionRelayer(RelayServer *parent, QTcpSocket *clientSocket, ServiceConnRef conn); + +protected: + int readData(int socketFd, void* buf, size_t size) override; + int writeData(int socketFd, const void *data, size_t size) override; + void closeConnection() override; + +private: + ServiceConnRef m_serviceConn; }; class RemotePortRelayer: public Relayer @@ -69,11 +87,11 @@ class RemotePortRelayer: public Relayer public: static const int reconnectMsecDelay = 500; static const int maxReconnectAttempts = 2*60*5; // 5 min - RemotePortRelayer(GenericRelayServer *parent, QTcpSocket *clientSocket); + RemotePortRelayer(QmlRelayServer *parent, QTcpSocket *clientSocket); void tryRemoteConnect(); signals: - void didConnect(GenericRelayServer *serv); + void didConnect(QmlRelayServer *serv); private: QTimer m_remoteConnectTimer; @@ -103,27 +121,28 @@ protected: QList m_connections; }; -class SingleRelayServer: public RelayServer +class GdbRelayServer: public RelayServer { Q_OBJECT public: - SingleRelayServer(IosTool *parent, int serverFileDescriptor); + GdbRelayServer(IosTool *parent, int serverFileDescriptor, ServiceConnRef conn); protected: void newRelayConnection() override; private: - int m_serverFileDescriptor; + int m_serverFileDescriptor = -1; + ServiceConnRef m_serviceConn = nullptr; }; -class GenericRelayServer: public RelayServer +class QmlRelayServer: public RelayServer { Q_OBJECT public: - GenericRelayServer(IosTool *parent, int remotePort, - Ios::DeviceSession *deviceSession); + QmlRelayServer(IosTool *parent, int remotePort, + Ios::DeviceSession *deviceSession); protected: void newRelayConnection() override; From 05701491a1caefcfcc2a1f00ee7c07b76cff2cd9 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 12 Mar 2021 10:10:13 +0100 Subject: [PATCH 19/22] FakeVim: Fix compilation with Qt 6 By using recursive QHash instead of recursive QMap, which has issues compiling under some circumstances with MSVC. Change-Id: I545a5eb9002f247a5015e7ea5e59cf74895b1e21 Reviewed-by: hjk --- src/plugins/fakevim/CMakeLists.txt | 1 - src/plugins/fakevim/fakevimhandler.cpp | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/fakevim/CMakeLists.txt b/src/plugins/fakevim/CMakeLists.txt index b9bd8362ebe..ddb6f3c1f1e 100644 --- a/src/plugins/fakevim/CMakeLists.txt +++ b/src/plugins/fakevim/CMakeLists.txt @@ -1,5 +1,4 @@ add_qtc_plugin(FakeVim - CONDITION Qt5_VERSION VERSION_LESS 6.0.0 PLUGIN_DEPENDS Core TextEditor PLUGIN_TEST_DEPENDS CppEditor CppTools SOURCES ${TEST_SOURCES} diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 9526fb78377..a00d43a6fe8 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1300,6 +1300,11 @@ public: << quoteUnprintable(m_text); } + friend uint qHash(const Input &i) + { + return ::qHash(i.m_key); + } + private: int m_key = 0; int m_xkey = 0; @@ -1645,7 +1650,7 @@ private: }; // Mappings for a specific mode (trie structure) -class ModeMapping : public QMap +class ModeMapping : public QHash { public: const Inputs &value() const { return m_value; } From db6ad528bb4a29c5c89e7e1a0d667ba82870cd9b Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Tue, 2 Mar 2021 13:35:07 +0100 Subject: [PATCH 20/22] QmlDesigner: Implement new control design * Update creator theme files and related enum * Remove unused ActionIndicator functionality * Update all controls (Colors, Positions, Sizes) * Add global hover state and cleanup all other states * Add global hover functionality to ButtonRow * Add missing states * Add new MenuItemWithIcon * Add checkers.png for StateDelegate preview background * Update copyright headers * Replace AnchorButtons spacing * Make ADS title bar buttons and tab bar buttons themeable * Fix replace CSS colors to allow specifing alpha * Fix replace CSS overwritting consecutive variables * Make navigator icons and other elements themeable * Make connection view themeable * Make item library themeable * Fix item library import path * Update all HelperWidgets * Fix GradientDialogPopup Task-number: QDS-3768 Change-Id: I28a5fed178c95d098db052b8c2eabaa083d37b81 Reviewed-by: Alessandro Portale --- .../itemLibraryQmlSources/AddImport.qml | 60 +++- .../itemLibraryQmlSources/ItemDelegate.qml | 5 +- .../itemLibraryQmlSources/ItemsView.qml | 8 +- .../itemLibraryQmlSources/LibraryHeader.qml | 106 ++++-- .../QtQuick/ItemPane.qml | 2 + .../QtQuick/QtObjectPane.qml | 1 + .../QtQuick3D/Object3DPane.qml | 1 + .../AligmentHorizontalButtons.qml | 3 +- .../HelperWidgets/AligmentVerticalButtons.qml | 3 +- .../imports/HelperWidgets/AnchorButtons.qml | 10 +- .../HelperWidgets/BoolButtonRowButton.qml | 3 +- .../imports/HelperWidgets/Button.qml | 2 +- .../imports/HelperWidgets/ButtonRowButton.qml | 10 +- .../imports/HelperWidgets/ColorButton.qml | 323 +++++++++--------- .../HelperWidgets/ColorCheckButton.qml | 19 +- .../imports/HelperWidgets/ColorEditor.qml | 263 +++++++------- .../imports/HelperWidgets/ColorLine.qml | 5 +- .../imports/HelperWidgets/ComboBox.qml | 3 +- .../HelperWidgets/EditableListView.qml | 4 +- .../HelperWidgets/ExpressionTextField.qml | 18 +- .../imports/HelperWidgets/FontSection.qml | 2 - .../HelperWidgets/GradientDialogPopup.qml | 15 +- .../HelperWidgets/GradientPresetList.qml | 2 +- .../GradientPresetTabContent.qml | 11 +- .../HelperWidgets/HorizontalScrollBar.qml | 2 +- .../imports/HelperWidgets/HueSlider.qml | 3 +- .../imports/HelperWidgets/Label.qml | 2 +- .../imports/HelperWidgets/OriginControl.qml | 6 +- .../imports/HelperWidgets/RoundedPanel.qml | 9 +- .../imports/HelperWidgets/Section.qml | 26 +- .../HelperWidgets/StandardTextSection.qml | 20 +- .../imports/HelperWidgets/UrlChooser.qml | 92 +++-- .../HelperWidgets/VerticalScrollBar.qml | 2 +- .../imports/StudioControls/AbstractButton.qml | 78 ++++- .../StudioControls/ActionIndicator.qml | 69 +--- .../imports/StudioControls/Button.qml | 3 +- .../imports/StudioControls/ButtonGroup.qml | 2 +- .../imports/StudioControls/ButtonRow.qml | 31 +- .../imports/StudioControls/CheckBox.qml | 96 ++++-- .../imports/StudioControls/CheckIndicator.qml | 88 +++-- .../imports/StudioControls/ComboBox.qml | 81 +++-- .../imports/StudioControls/ComboBoxInput.qml | 67 ++-- .../imports/StudioControls/ContextMenu.qml | 2 +- .../StudioControls/ExpandingSpacer.qml | 2 +- .../imports/StudioControls/ItemDelegate.qml | 2 +- .../imports/StudioControls/Menu.qml | 5 +- .../imports/StudioControls/MenuItem.qml | 16 +- .../StudioControls/MenuItemWithIcon.qml | 79 +++++ .../imports/StudioControls/MenuSeparator.qml | 2 +- .../StudioControls/RealSliderPopup.qml | 11 +- .../imports/StudioControls/RealSpinBox.qml | 83 +++-- .../StudioControls/RealSpinBoxIndicator.qml | 127 +++++-- .../StudioControls/RealSpinBoxInput.qml | 72 ++-- .../imports/StudioControls/ScrollBar.qml | 2 +- .../imports/StudioControls/ScrollView.qml | 2 +- .../StudioControls/SecondColumnLayout.qml | 4 +- .../imports/StudioControls/Section.qml | 45 ++- .../imports/StudioControls/SectionLabel.qml | 4 +- .../imports/StudioControls/SectionLayout.qml | 9 +- .../imports/StudioControls/Slider.qml | 10 +- .../imports/StudioControls/SliderPopup.qml | 15 +- .../imports/StudioControls/SpinBox.qml | 97 +++--- .../StudioControls/SpinBoxIndicator.qml | 146 ++++++-- .../imports/StudioControls/SpinBoxInput.qml | 76 +++-- .../imports/StudioControls/TabBar.qml | 6 +- .../imports/StudioControls/TabButton.qml | 9 +- .../imports/StudioControls/TextArea.qml | 4 +- .../imports/StudioControls/TextField.qml | 71 ++-- .../StudioControls/TranslationIndicator.qml | 96 ++++-- .../imports/StudioControls/qmldir | 1 + .../imports/StudioTheme/Constants.qml | 2 +- .../imports/StudioTheme/InternalConstants.qml | 189 +++++----- .../imports/StudioTheme/Values.qml | 160 +++++++-- .../imports/StudioTheme/icons.ttf | Bin 16092 -> 16516 bytes .../statesEditorQmlSources/StatesDelegate.qml | 30 +- .../statesEditorQmlSources/StatesList.qml | 8 +- .../images/checkers.png | Bin 0 -> 80 bytes share/qtcreator/themes/dark.creatortheme | 160 +++++++-- share/qtcreator/themes/default.creatortheme | 162 +++++++-- .../themes/design-light.creatortheme | 167 +++++++-- share/qtcreator/themes/design.creatortheme | 158 +++++++-- share/qtcreator/themes/flat-dark.creatortheme | 160 +++++++-- .../qtcreator/themes/flat-light.creatortheme | 164 +++++++-- share/qtcreator/themes/flat.creatortheme | 160 +++++++-- .../dockareatitlebar.cpp | 15 +- .../advanceddockingsystem/dockwidgettab.cpp | 62 +++- .../advanceddockingsystem/dockwidgettab.h | 23 ++ .../advanceddockingsystem/elidinglabel.cpp | 2 +- .../linux/floatingwidgettitlebar.cpp | 4 +- src/libs/utils/theme/theme.h | 123 +++++-- .../components/componentcore/theme.cpp | 15 +- .../connectioneditor/connectionviewwidget.ui | 8 +- .../connectioneditor/stylesheet.css | 125 +++---- .../itemlibrary/itemlibrarywidget.cpp | 7 +- .../navigator/iconcheckboxitemdelegate.cpp | 25 +- .../navigator/iconcheckboxitemdelegate.h | 7 +- .../components/navigator/nameitemdelegate.cpp | 14 +- .../navigator/navigatortreeview.cpp | 42 +-- .../components/navigator/navigatorview.cpp | 105 ++++-- .../components/resources/dockwidgets.css | 142 ++++---- .../components/resources/scrollbar.css | 4 +- .../components/resources/stylesheet.css | 100 +++--- src/plugins/qmldesigner/designmodewidget.cpp | 38 +-- .../qmldesigner/documentwarningwidget.cpp | 9 +- 104 files changed, 3262 insertions(+), 1682 deletions(-) create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItemWithIcon.qml create mode 100644 share/qtcreator/qmldesigner/statesEditorQmlSources/images/checkers.png diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AddImport.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AddImport.qml index 53712827700..71399afa011 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AddImport.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AddImport.qml @@ -26,6 +26,8 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuickDesignerTheme 1.0 +import HelperWidgets 2.0 +import StudioTheme 1.0 as StudioTheme Column { id: root @@ -33,7 +35,7 @@ Column { Text { id: header text: qsTr("Select a Module to Add") - color: "#ffffff" + color: StudioTheme.Values.themeTextColor font.pixelSize: 16 width: parent.width height: 50 @@ -54,17 +56,16 @@ Column { model: addImportModel delegate: Rectangle { + id: itemBackground width: listView.width height: isSeparator ? 4 : 25 - color: isSeparator ? Theme.color(Theme.BackgroundColorNormal) - : mouseArea.containsMouse - ? Qt.lighter(Theme.qmlDesignerButtonColor(), 1.3) - : Theme.qmlDesignerButtonColor() + color: StudioTheme.Values.themeListItemBackground visible: importVisible Text { + id: itemText text: importUrl - color: Theme.color(Theme.PanelTextColorLight) + color: StudioTheme.Values.themeListItemText anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left anchors.right: parent.right @@ -79,6 +80,53 @@ Column { onClicked: rootView.handleAddImport(index) enabled: !isSeparator } + + states: [ + State { + name: "default" + when: !isSeparator && !mouseArea.containsMouse && !mouseArea.pressed + PropertyChanges { + target: itemBackground + color: StudioTheme.Values.themeListItemBackground + } + PropertyChanges { + target: itemText + color: StudioTheme.Values.themeListItemText + } + }, + State { + name: "separator" + when: isSeparator + PropertyChanges { + target: itemBackground + color: StudioTheme.Values.themePanelBackground + } + }, + State { + name: "hover" + when: !isSeparator && mouseArea.containsMouse && !mouseArea.containsPress + PropertyChanges { + target: itemBackground + color: StudioTheme.Values.themeListItemBackgroundHover + } + PropertyChanges { + target: itemText + color: StudioTheme.Values.themeListItemTextHover + } + }, + State { + name: "press" + when: !isSeparator && mouseArea.containsPress + PropertyChanges { + target: itemBackground + color: StudioTheme.Values.themeListItemBackgroundPress + } + PropertyChanges { + target: itemText + color: StudioTheme.Values.themeListItemTextPress + } + } + ] } } } diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml index 045398205db..6e0724d86bb 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml @@ -27,6 +27,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuickDesignerTheme 1.0 import HelperWidgets 2.0 +import StudioTheme 1.0 as StudioTheme Item { id: delegateRoot @@ -37,7 +38,7 @@ Item { anchors.topMargin: 1 anchors.fill: parent - color: Theme.qmlDesignerButtonColor() + color: StudioTheme.Values.themePanelBackground Image { id: itemIcon // to be set by model @@ -68,7 +69,7 @@ Item { verticalAlignment: Qt.AlignVCenter horizontalAlignment: Qt.AlignHCenter text: itemName // to be set by model - color: Theme.color(Theme.PanelTextColorLight) + color: StudioTheme.Values.themeTextColor renderType: Text.NativeRendering } diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml index 2923451de50..9f7c2b13b64 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml @@ -193,8 +193,12 @@ ScrollView { Grid { id: itemGrid - columns: parent.width / styleConstants.cellWidth - property int flexibleWidth: (parent.width - styleConstants.cellWidth * columns) / columns + property real actualWidth: parent.width - itemGrid.leftPadding -itemGrid.rightPadding + property int flexibleWidth: (itemGrid.actualWidth / columns) - styleConstants.cellWidth + + leftPadding: 6 + rightPadding: 6 + columns: itemGrid.actualWidth / styleConstants.cellWidth Repeater { model: itemModel diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml index da2e18ff873..164a1034221 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml @@ -26,6 +26,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuickDesignerTheme 1.0 +import HelperWidgets 2.0 as HelperWidgets import StudioControls 1.0 as StudioControls import StudioTheme 1.0 as StudioTheme @@ -47,7 +48,7 @@ Item { Column { anchors.left: parent.left anchors.right: parent.right - spacing: 10 + spacing: 9 TabBar { id: tabBar @@ -58,7 +59,7 @@ Item { spacing: 40 background: Rectangle { - color: Theme.color(Theme.QmlDesigner_BackgroundColorDarkAlternate) + color: StudioTheme.Values.themePanelBackground } Repeater { @@ -74,8 +75,9 @@ Item { Text { // TabButton text text: modelData.title font.pixelSize: 13 - font.bold: true - color: tabBar.currentIndex === index ? "#0094ce" : "#dadada" + font.bold: false + color: tabBar.currentIndex === index ? StudioTheme.Values.themeInteraction + : StudioTheme.Values.themeTextColor anchors.left: parent.left anchors.top: parent.top anchors.bottom: parent.bottom @@ -93,11 +95,8 @@ Item { anchors.topMargin: 1 width: 24 height: 24 - color: mouseArea.containsMouse ? "#353535" : "#262626" - - ToolTip.delay: 500 - ToolTip.text: modelData.addToolTip - ToolTip.visible: mouseArea.containsMouse + color: mouseArea.containsMouse ? StudioTheme.Values.themeControlBackgroundHover + : StudioTheme.Values.themeControlBackground Label { // + sign text: StudioTheme.Constants.plus @@ -106,15 +105,17 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter anchors.centerIn: parent - color: tabBar.currentIndex === index ? "#0094ce" : "#a8a8a8" + color: tabBar.currentIndex === index ? StudioTheme.Values.themeIconColorSelected + : StudioTheme.Values.themeIconColor } - MouseArea { + HelperWidgets.ToolTipArea { id: mouseArea anchors.fill: parent hoverEnabled: true onClicked: index == 0 ? rootView.handleAddModule() : rootView.handleAddAsset() + tooltip: modelData.addToolTip } } } @@ -124,7 +125,8 @@ Item { anchors.bottom: parent.bottom width: parent.width height: 2 - color: tabBar.currentIndex === index ? "#0094ce" : "#a8a8a8" + color: tabBar.currentIndex === index ? StudioTheme.Values.themeInteraction + : StudioTheme.Values.themeTextColor } } @@ -136,29 +138,50 @@ Item { TextField { // filter id: searchFilterText placeholderText: qsTr("Search") - placeholderTextColor: "#a8a8a8" - color: "#dadada" - selectedTextColor: "#0094ce" + placeholderTextColor: StudioTheme.Values.themePlaceholderTextColor + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor background: Rectangle { - color: "#111111" - border.color: "#666666" + id: textFieldBackground + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border } + + height: StudioTheme.Values.defaultControlHeight + + leftPadding: 32 + rightPadding: 30 + anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 5 anchors.rightMargin: 5 selectByMouse: true + hoverEnabled: true onTextChanged: rootView.handleSearchfilterChanged(text) + Label { + text: StudioTheme.Constants.search + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: 16 + anchors.left: parent.left + anchors.leftMargin: 7 + anchors.verticalCenter: parent.verticalCenter + color: StudioTheme.Values.themeIconColor + } + Rectangle { // x button - width: 15 + width: 16 height: 15 anchors.right: parent.right anchors.rightMargin: 5 anchors.verticalCenter: parent.verticalCenter visible: searchFilterText.text !== "" - color: xMouseArea.containsMouse ? "#353535" : "transparent" + color: xMouseArea.containsMouse ? StudioTheme.Values.themePanelBackground + : "transparent" Label { text: StudioTheme.Constants.closeCross @@ -167,7 +190,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter anchors.centerIn: parent - color: "#dadada" + color: StudioTheme.Values.themeIconColor } MouseArea { @@ -177,6 +200,49 @@ Item { onClicked: searchFilterText.text = "" } } + + states: [ + State { + name: "default" + when: !searchFilterText.hovered && !searchFilterText.activeFocus + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: searchFilterText + placeholderTextColor: StudioTheme.Values.themePlaceholderTextColor + } + }, + State { + name: "hover" + when: searchFilterText.hovered && !searchFilterText.activeFocus + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeControlBackgroundHover + border.color: StudioTheme.Values.themeControlOutline + } + + PropertyChanges { + target: searchFilterText + placeholderTextColor: StudioTheme.Values.themePlaceholderTextColor + } + }, + State { + name: "edit" + when: searchFilterText.activeFocus + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeControlBackgroundInteraction + border.color: StudioTheme.Values.themeControlOutlineInteraction + } + PropertyChanges { + target: searchFilterText + placeholderTextColor: StudioTheme.Values.themePlaceholderTextColorInteraction + } + } + ] } } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml index fd39b0bd2d6..c1a0ed8fa4d 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml @@ -71,6 +71,7 @@ Rectangle { Label { anchors.fill: parent anchors.leftMargin: StudioTheme.Values.inputHorizontalPadding + anchors.topMargin: StudioTheme.Values.typeLabelVerticalShift text: backendValues.className.value } ToolTipArea { @@ -338,6 +339,7 @@ Rectangle { SecondColumnLayout { SpinBox { + width: StudioTheme.Values.squareComponentWidth * 4 sliderIndicatorVisible: true backendValue: backendValues.opacity decimals: 2 diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml index 96d22e5a7b9..faeefce9ee2 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml @@ -68,6 +68,7 @@ Rectangle { Label { anchors.fill: parent anchors.leftMargin: StudioTheme.Values.inputHorizontalPadding + anchors.topMargin: StudioTheme.Values.typeLabelVerticalShift text: backendValues.className.value } ToolTipArea { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Object3DPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Object3DPane.qml index 78d99f4d28f..143e0232e80 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Object3DPane.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Object3DPane.qml @@ -68,6 +68,7 @@ Rectangle { Label { anchors.fill: parent anchors.leftMargin: StudioTheme.Values.inputHorizontalPadding + anchors.topMargin: StudioTheme.Values.typeLabelVerticalShift text: backendValues.className.value } ToolTipArea { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml index eb96c62722b..c57bc44b881 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml @@ -39,7 +39,8 @@ Row { property bool baseStateFlag: isBaseState; - property color __currentColor: blueHighlight ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeTextColor + property color __currentColor: blueHighlight ? StudioTheme.Values.themeIconColorInteraction + : StudioTheme.Values.themeIconColor onValueChanged: { buttonAlignLeft.checked = true diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml index 65d23975e6c..ba95a23d660 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml @@ -39,7 +39,8 @@ Row { property bool baseStateFlag: isBaseState; - property color __currentColor: blueHighlight ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeTextColor + property color __currentColor: blueHighlight ? StudioTheme.Values.themeIconColorInteraction + : StudioTheme.Values.themeIconColor onValueChanged: { buttonAlignTop.checked = true diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AnchorButtons.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AnchorButtons.qml index 483c4947f0c..87900734f1b 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AnchorButtons.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AnchorButtons.qml @@ -124,8 +124,9 @@ StudioControls.ButtonRow { } } - AbstractButton { - enabled: false + Item { + width: 16 + 2 * StudioTheme.Values.border + height: 5 } AbstractButton { @@ -147,8 +148,9 @@ StudioControls.ButtonRow { } } - AbstractButton { - enabled: false + Item { + width: 16 + 2 * StudioTheme.Values.border + height: 5 } AbstractButton { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/BoolButtonRowButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/BoolButtonRowButton.qml index 5a79e7a78fb..725014b4efe 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/BoolButtonRowButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/BoolButtonRowButton.qml @@ -34,7 +34,8 @@ StudioControls.Button { property variant backendValue property bool isHighlighted: false - iconColor: isHighlighted ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeTextColor + iconColor: isHighlighted ? StudioTheme.Values.themeIconColorInteraction + : StudioTheme.Values.themeIconColor actionIndicatorVisible: true checkable: true diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Button.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Button.qml index a20469966af..5326edd615a 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Button.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Button.qml @@ -72,7 +72,7 @@ T.AbstractButton { when: myButton.hovered && !myButton.pressed PropertyChanges { target: buttonBackground - color: StudioTheme.Values.themeHoverHighlight + color: StudioTheme.Values.themeControlBackgroundHover } }, State { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml index a893a12529a..ffac673a3e3 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml @@ -26,6 +26,7 @@ import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQuickDesignerTheme 1.0 +import StudioTheme 1.0 as StudioTheme Item { id: buttonRowButton @@ -41,8 +42,8 @@ Item { property alias tooltip: toolTipArea.tooltip - width: 24 + leftPadding - height: 24 + width: StudioTheme.Values.height + leftPadding + height: StudioTheme.Values.height property int leftPadding: 0 @@ -69,7 +70,7 @@ Item { anchors.fill: parent visible: checked - color: Theme.qmlDesignerBackgroundColorDarker() + color: StudioTheme.Values.themeControlBackgroundInteraction } RoundedPanel { @@ -77,7 +78,7 @@ Item { anchors.fill: parent visible: !checked - color: Theme.qmlDesignerButtonColor() + color: StudioTheme.Values.themeControlBackground } } @@ -102,6 +103,5 @@ Item { buttonRowButton.clicked() } onDoubleClicked: buttonRowButton.doubleClicked() - } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml index afba6def0c7..520e6f30899 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml @@ -24,6 +24,7 @@ ****************************************************************************/ import QtQuick 2.1 +import StudioTheme 1.0 as StudioTheme Item { id: colorButton @@ -229,10 +230,10 @@ Item { } Rectangle { anchors.fill: parent - anchors.margins: -1 + anchors.margins: -StudioTheme.Values.border color: "#00000000" - border.color: "black" - border.width: 1 + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border } } @@ -249,188 +250,194 @@ Item { onClicked: colorButton.updateColor() } - Row { + Column { anchors.left: hueSlider.right anchors.margins: colorButton.sliderMargins - spacing: 10 + spacing: StudioTheme.Values.sectionRowSpacing - Column { - spacing: 10 - Row { - z: 3 - spacing: 1 - Label { - text: "R" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter + Row { + spacing: 20 + + Column { + spacing: StudioTheme.Values.sectionRowSpacing + + Row { + z: 3 + spacing: 1 + Label { + text: "R" + width: 16 + color: StudioTheme.Values.themeTextColor + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: redSlider + width: 68 + + stepSize: 1 + minimumValue: 0 + maximumValue: 255 + decimals: 0 + + onValueModified: { + var tmp = redSlider.value / 255.0 + if (colorButton.color.r !== tmp && !colorButton.block) { + colorButton.color.r = tmp + colorButton.updateColor() + } + } + } } - DoubleSpinBox { - id: redSlider - width: 68 - stepSize: 1 - minimumValue: 0 - maximumValue: 255 - decimals: 0 + Row { + z: 2 + spacing: 1 + Label { + text: "G" + width: 16 + color: StudioTheme.Values.themeTextColor + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: greenSlider + width: 68 - onValueModified: { - var tmp = redSlider.value / 255.0 - if (colorButton.color.r !== tmp && !colorButton.block) { - colorButton.color.r = tmp - colorButton.updateColor() + stepSize: 1 + minimumValue: 0 + maximumValue: 255 + decimals: 0 + + onValueModified: { + var tmp = greenSlider.value / 255.0 + if (colorButton.color.g !== tmp && !colorButton.block) { + colorButton.color.g = tmp + colorButton.updateColor() + } + } + } + } + + Row { + z: 1 + spacing: 1 + Label { + text: "B" + width: 16 + color: StudioTheme.Values.themeTextColor + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: blueSlider + width: 68 + + stepSize: 1 + minimumValue: 0 + maximumValue: 255 + decimals: 0 + + onValueModified: { + var tmp = blueSlider.value / 255.0 + if (colorButton.color.b !== tmp && !colorButton.block) { + colorButton.color.b = tmp + colorButton.updateColor() + } } } } } - Row { - z: 2 - spacing: 1 - Label { - text: "G" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - } - DoubleSpinBox { - id: greenSlider - width: 68 + Column { + spacing: StudioTheme.Values.sectionRowSpacing - stepSize: 1 - minimumValue: 0 - maximumValue: 255 - decimals: 0 - - onValueModified: { - var tmp = greenSlider.value / 255.0 - if (colorButton.color.g !== tmp && !colorButton.block) { - colorButton.color.g = tmp - colorButton.updateColor() + Row { + z: 3 + spacing: 1 + Label { + text: "H" + width: 16 + color: StudioTheme.Values.themeTextColor + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: hueSlider2 + width: 64 + onValueModified: { + if (colorButton.hue !== hueSlider2.value && !colorButton.block) { + colorButton.hue = hueSlider2.value + colorButton.updateColor() + } } } } - } - Row { - z: 1 - spacing: 1 - Label { - text: "B" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - } - DoubleSpinBox { - id: blueSlider - width: 68 - - stepSize: 1 - minimumValue: 0 - maximumValue: 255 - decimals: 0 - - onValueModified: { - var tmp = blueSlider.value / 255.0 - if (colorButton.color.b !== tmp && !colorButton.block) { - colorButton.color.b = tmp - colorButton.updateColor() + Row { + z: 2 + spacing: 1 + Label { + text: "S" + width: 16 + color: StudioTheme.Values.themeTextColor + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: saturationSlider + width: 64 + onValueModified: { + if (colorButton.saturation !== saturationSlider.value && !colorButton.block) { + colorButton.saturation = saturationSlider.value + colorButton.updateColor() + } } } } - } - Row { - z: 0 - spacing: 1 - Label { - text: "A" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - } - DoubleSpinBox { - id: alphaSlider - sliderIndicatorVisible: true - width: 68 - onValueModified: { - if (colorButton.alpha !== alphaSlider.value && !colorButton.block) { - colorButton.alpha = alphaSlider.value - colorButton.updateColor() + Row { + z: 1 + spacing: 1 + Label { + text: "L" + width: 16 + color: StudioTheme.Values.themeTextColor + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: lightnessSlider + width: 64 + onValueModified: { + if (colorButton.lightness !== lightnessSlider.value && !colorButton.block) { + colorButton.lightness = lightnessSlider.value + colorButton.updateColor() + } } } } } } - 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 - onValueModified: { - if (colorButton.hue !== hueSlider2.value && !colorButton.block) { - colorButton.hue = hueSlider2.value - colorButton.updateColor() - } - } - } + Row { + z: 0 + spacing: 1 + Label { + text: "A" + width: 16 + color: StudioTheme.Values.themeTextColor + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter } - - Row { - z: 2 - spacing: 1 - Label { - text: "S" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - } - DoubleSpinBox { - id: saturationSlider - width: 64 - onValueModified: { - if (colorButton.saturation !== saturationSlider.value && !colorButton.block) { - colorButton.saturation = saturationSlider.value - colorButton.updateColor() - } - } - } - } - - Row { - z: 1 - spacing: 1 - Label { - text: "L" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - } - DoubleSpinBox { - id: lightnessSlider - width: 64 - onValueModified: { - if (colorButton.lightness !== lightnessSlider.value && !colorButton.block) { - colorButton.lightness = lightnessSlider.value - colorButton.updateColor() - } + DoubleSpinBox { + id: alphaSlider + sliderIndicatorVisible: true + width: 169 + onValueModified: { + if (colorButton.alpha !== alphaSlider.value && !colorButton.block) { + colorButton.alpha = alphaSlider.value + colorButton.updateColor() } } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml index f45e8661031..a66921a8c4a 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml @@ -24,34 +24,35 @@ ****************************************************************************/ import QtQuick 2.1 +import StudioTheme 1.0 as StudioTheme Item { id: root property bool checked: false property alias buttonColor: checkBox.color - width: 30 - height: 24 + width: StudioTheme.Values.height + height: StudioTheme.Values.height signal rightMouseButtonClicked Rectangle { id: backgroundBox - width: 24 - height: 24 + width: StudioTheme.Values.height + height: StudioTheme.Values.height anchors.right: parent.right color: "white" border.color: "white" - border.width: 1 + border.width: StudioTheme.Values.border Rectangle { id: checkBox - width: 22 - height: 22 + width: StudioTheme.Values.height - 2 * StudioTheme.Values.border + height: StudioTheme.Values.height - 2 * StudioTheme.Values.border anchors.centerIn: parent border.color: "black" - border.width: 1 + border.width: StudioTheme.Values.border } } @@ -62,7 +63,7 @@ Item { source: "image://icons/down-arrow" anchors.verticalCenter: parent.verticalCenter anchors.right: backgroundBox.left - anchors.rightMargin: 2 + anchors.rightMargin: 4 opacity: colorToolTip.containsMouse ? 1 : 0.8 rotation: root.checked ? 0.0 : 270.0 } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml index 3d8291e7e70..d621fcb0cf5 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml @@ -27,6 +27,7 @@ import QtQuick 2.1 import QtQuick.Layouts 1.0 import QtQuickDesignerTheme 1.0 import QtQuick.Dialogs 1.3 +import StudioTheme 1.0 as StudioTheme import StudioControls 1.0 as StudioControls Column { @@ -214,6 +215,10 @@ Column { SecondColumnLayout { + Item { + width: 6 + } + ColorCheckButton { id: checkButton buttonColor: colorEditor.color @@ -260,7 +265,6 @@ Column { } ButtonRow { - id: buttonRow exclusive: true @@ -303,59 +307,48 @@ Column { GradientDialogPopup { id: gradientDialogPopupLinear - dialogHeight: 80 - content: GridLayout { - rowSpacing: 4 - anchors.fill: parent - height: 40 + dialogHeight: 110 + content: Column { + spacing: StudioTheme.Values.sectionRowSpacing - columns: 4 - rows: 2 + RowLayout { + Label { + text: "X1" + width: 18 + tooltip: qsTr("Defines the start point for color interpolation.") + } - anchors.leftMargin: 12 - anchors.rightMargin: 6 + GradientPropertySpinBox { propertyName: "x1" } - anchors.topMargin: 28 - anchors.bottomMargin: 6 + Item { width: StudioTheme.Values.controlLabelGap } - Label { - text: "X1" - width: 18 - tooltip: qsTr("Defines the start point for color interpolation.") + Label { + text: "X2" + width: 18 + tooltip: qsTr("Defines the end point for color interpolation.") + } + + GradientPropertySpinBox { propertyName: "x2" } } - GradientPropertySpinBox { - propertyName: "x1" - } + RowLayout { + Label { + text: "Y1" + width: 18 + tooltip: qsTr("Defines the start point for color interpolation.") + } - Label { - text: "X2" - width: 18 - tooltip: qsTr("Defines the end point for color interpolation.") - } + GradientPropertySpinBox { propertyName: "y1" } - GradientPropertySpinBox { - propertyName: "x2" - } + Item { width: StudioTheme.Values.controlLabelGap } - Label { - text: "y1" - width: 18 - tooltip: qsTr("Defines the start point for color interpolation.") - } + Label { + text: "Y2" + width: 18 + tooltip: qsTr("Defines the end point for color interpolation.") + } - GradientPropertySpinBox { - propertyName: "y1" - } - - Label { - text: "Y2" - width: 18 - tooltip: qsTr("Defines the end point for color interpolation.") - } - - GradientPropertySpinBox { - propertyName: "y2" + GradientPropertySpinBox { propertyName: "y2" } } } } @@ -384,78 +377,67 @@ Column { GradientDialogPopup { id: gradientDialogPopupRadial dialogHeight: 140 - content: GridLayout { - rowSpacing: 4 - anchors.fill: parent - height: 40 + content: Column { + spacing: StudioTheme.Values.sectionRowSpacing - columns: 4 - rows: 3 + RowLayout { + Label { + text: "CenterX" + width: 74 + tooltip: qsTr("Defines the center point.") + } - anchors.leftMargin: 12 - anchors.rightMargin: 6 + GradientPropertySpinBox { propertyName: "centerX" } - anchors.topMargin: 28 - anchors.bottomMargin: 6 + Item { width: StudioTheme.Values.controlLabelGap } - Label { - text: "CenterX" - width: 64 - tooltip: qsTr("Defines the center point.") + Label { + text: "CenterY" + width: 74 + tooltip: qsTr("Defines the center point.") + } + + GradientPropertySpinBox { propertyName: "centerY" } } - GradientPropertySpinBox { - propertyName: "centerX" + RowLayout { + Label { + text: "FocalX" + width: 74 + tooltip: qsTr("Defines the focal point.") + } + + GradientPropertySpinBox { propertyName: "focalX" } + + Item { width: StudioTheme.Values.controlLabelGap } + + Label { + text: "FocalY" + width: 74 + tooltip: qsTr("Defines the focal point.") + } + + GradientPropertySpinBox { propertyName: "focalY" } } - Label { - text: "CenterY" - width: 64 - tooltip: qsTr("Defines the center point.") - } + RowLayout { + Label { + text: "Center Radius" + width: 74 + tooltip: qsTr("Defines the center point.") + } - GradientPropertySpinBox { - propertyName: "centerY" - } + GradientPropertySpinBox { propertyName: "centerRadius" } - Label { - text: "FocalX" - width: 64 - tooltip: qsTr("Defines the focal point.") - } + Item { width: StudioTheme.Values.controlLabelGap } - GradientPropertySpinBox { - propertyName: "focalX" - } + Label { + text: "Focal Radius" + width: 74 + tooltip: qsTr("Defines the focal radius. Set to 0 for simple radial gradients.") + } - Label { - text: "FocalY" - width: 64 - tooltip: qsTr("Defines the focal point.") - } - - GradientPropertySpinBox { - propertyName: "focalY" - } - - Label { - text: "Center Radius" - width: 64 - tooltip: qsTr("Defines the center point.") - } - - GradientPropertySpinBox { - propertyName: "centerRadius" - } - - Label { - text: "Focal Radius" - width: 64 - tooltip: qsTr("Defines the focal radius. Set to 0 for simple radial gradients.") - } - - GradientPropertySpinBox { - propertyName: "focalRadius" + GradientPropertySpinBox { propertyName: "focalRadius" } } } } @@ -484,50 +466,39 @@ Column { GradientDialogPopup { id: gradientDialogPopupConical - dialogHeight: 80 - content: GridLayout { - rowSpacing: 4 - anchors.fill: parent - height: 40 + dialogHeight: 110 + content: Column { + spacing: StudioTheme.Values.sectionRowSpacing - columns: 4 - rows: 2 + RowLayout { + Label { + text: "CenterX" + width: 64 + tooltip: qsTr("Defines the center point.") + } - anchors.leftMargin: 12 - anchors.rightMargin: 6 + GradientPropertySpinBox { propertyName: "centerX" } - anchors.topMargin: 28 - anchors.bottomMargin: 6 + Item { width: StudioTheme.Values.controlLabelGap } - Label { - text: "CenterX" - width: 64 - tooltip: qsTr("Defines the center point.") + Label { + text: "CenterY" + width: 64 + tooltip: qsTr("Defines the center point.") + } + + GradientPropertySpinBox { propertyName: "centerY" } } - GradientPropertySpinBox { - propertyName: "centerX" - } + RowLayout { + Label { + text: "Angle" + width: 64 + tooltip: qsTr("Defines the start angle for the conical gradient. The value is in degrees (0-360).") + } - Label { - text: "CenterY" - width: 64 - tooltip: qsTr("Defines the center point.") - } - - GradientPropertySpinBox { - propertyName: "centerY" - } - - Label { - text: "Angle" - width: 64 - tooltip: qsTr("Defines the start angle for the conical gradient. The value is in degrees (0-360).") - } - - GradientPropertySpinBox { - propertyName: "angle" - } + GradientPropertySpinBox { propertyName: "angle" } + } } } } @@ -546,13 +517,13 @@ Column { Rectangle { id: gradientPickerButton - width: 20 - height: 20 + width: StudioTheme.Values.height + height: StudioTheme.Values.height visible: colorEditor.supportGradient - color: Theme.qmlDesignerButtonColor() - border.color: Theme.qmlDesignerBorderColor() - border.width: 1 + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border ToolTipArea { anchors.fill: parent diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml index 18d9750be09..c12642e70f2 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml @@ -25,6 +25,7 @@ import QtQuick 2.1 import HelperWidgets 2.0 +import StudioTheme 1.0 as StudioTheme Item { width: 300 @@ -42,8 +43,8 @@ Item { Rectangle { height: 16 width: parent.width - border.color: "#555555" - border.width: 1 + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border id: colorLine color: "white" diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml index bb449273184..4f8d5d87b06 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml @@ -32,7 +32,8 @@ StudioControls.ComboBox { property variant backendValue - labelColor: edit && !colorLogic.errorState ? StudioTheme.Values.themeTextColor : colorLogic.textColor + labelColor: edit && !colorLogic.errorState ? StudioTheme.Values.themeTextColor + : colorLogic.textColor property string scope: "Qt" enum ValueType { String, Integer, Enum } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/EditableListView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/EditableListView.qml index a2a73d4edf7..19cbd34da4d 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/EditableListView.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/EditableListView.qml @@ -181,7 +181,9 @@ Rectangle { id: actionIndicator width: actionIndicator.visible ? __actionIndicatorWidth : 0 height: actionIndicator.visible ? __actionIndicatorHeight : 0 - showBackground: true + + border.width: StudioTheme.Values.border + border.color: StudioTheme.Values.themeControlOutline icon.color: extFuncLogic.color icon.text: extFuncLogic.glyph diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml index 53557780d1a..111b369d8ea 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml @@ -66,9 +66,9 @@ StudioControls.TextField { Popup { id: textFieldPopup - x: textField.x - y: textField.height - StudioTheme.Values.border - width: textField.width + x: StudioTheme.Values.border + y: textField.height + width: textField.width - (StudioTheme.Values.border * 2) // 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. @@ -106,11 +106,14 @@ StudioControls.TextField { padding: 0 text: itemDelegateText.text + highlighted: listView.currentIndex === index + contentItem: Text { id: itemDelegateText leftPadding: 8 text: modelData - color: StudioTheme.Values.themeTextColor + color: highlighted ? StudioTheme.Values.themeTextSelectedTextColor + : StudioTheme.Values.themeTextColor font: textField.font elide: Text.ElideRight verticalAlignment: Text.AlignVCenter @@ -144,9 +147,8 @@ StudioControls.TextField { } background: Rectangle { - color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeInteraction - border.width: StudioTheme.Values.border + color: StudioTheme.Values.themePopupBackground + border.width: 0 } enter: Transition { @@ -155,7 +157,7 @@ StudioControls.TextField { } } - verticalAlignment: Text.AlignTop + verticalAlignment: Text.AlignVCenter onPressed: listView.model = null diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml index 7e86c24d2cf..1a44ee198a5 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml @@ -124,7 +124,6 @@ Section { StudioControls.ComboBox { id: sizeType model: ["pixels", "points"] - property color textColor: Theme.color(Theme.PanelTextColorLight) actionIndicatorVisible: false onActivated: { @@ -148,7 +147,6 @@ Section { text: qsTr("Font style") } FontStyleButtons { - bold: fontSection.boldStyle italic: fontSection.italicStyle underline: fontSection.underlineStyle diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientDialogPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientDialogPopup.qml index 2373c32c648..dae40f85343 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientDialogPopup.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientDialogPopup.qml @@ -44,7 +44,7 @@ Loader { property Component content property int dialogHeight: 240 - property int dialogWidth: 440 + property int dialogWidth: 400 sourceComponent: Component { FocusScope { @@ -61,8 +61,7 @@ Loader { Rectangle { anchors.fill: parent - color: Theme.qmlDesignerBackgroundColorDarker() - opacity: 0.6 + color: StudioTheme.Values.themePopupOverlayColor } MouseArea { @@ -84,10 +83,11 @@ Loader { width: parent.width - 8 - xOffset height: gradientDialogLoader.dialogHeight - color: Theme.qmlDesignerBackgroundColorDarkAlternate() - border.color: Theme.qmlDesignerBorderColor() + color: StudioTheme.Values.themePanelBackground + border.color: StudioTheme.Values.themeControlOutline Label { + id: title x: 8 y: 6 font.bold: true @@ -106,7 +106,10 @@ Loader { } Loader { - anchors.fill: parent + anchors.top: title.bottom + anchors.topMargin: 8 + anchors.left: parent.left + anchors.leftMargin: 8 sourceComponent: gradientDialogLoader.content } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml index 4a0665076a6..aa96c2fb77b 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml @@ -68,7 +68,7 @@ Dialog { anchors.fill: parent anchors.margins: -12 anchors.bottomMargin: -70 - color: StudioTheme.Values.themeColumnBackground + color: StudioTheme.Values.themePanelBackground ColumnLayout { anchors.fill: parent diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml index fd0fee4cf77..c987e616fe3 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml @@ -53,11 +53,12 @@ Rectangle { Layout.fillHeight: true anchors.fill: parent anchors.leftMargin: 10 + rightMargin: StudioTheme.Values.scrollBarThickness clip: true delegate: gradientDelegate - property int gridColumns: width / tabBackground.gridCellWidth; - cellWidth: width / gridColumns + property int gridColumns: (width - rightMargin) / tabBackground.gridCellWidth; + cellWidth: (width - rightMargin) / gridColumns cellHeight: 185 property bool bothVisible: horizontal.scrollBarVisible && vertical.scrollBarVisible @@ -133,7 +134,7 @@ Rectangle { PropertyChanges { target: backgroundCard color: StudioTheme.Values.themeControlBackgroundPressed - border.width: 1 + border.width: StudioTheme.Values.border border.color: StudioTheme.Values.themeInteraction } }, @@ -143,7 +144,7 @@ Rectangle { PropertyChanges { target: backgroundCard color:StudioTheme.Values.themeInteraction - border.width: 1 + border.width: StudioTheme.Values.border border.color: StudioTheme.Values.themeControlBackgroundPressed } } @@ -312,7 +313,7 @@ Rectangle { target: nameBackgroundColor color: StudioTheme.Values.themeControlBackgroundPressed border.color: StudioTheme.Values.themeInteraction - border.width: 1 + border.width: StudioTheme.Values.border } PropertyChanges { target: nameText; visible: false } PropertyChanges { target: nameInput; visible: true } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HorizontalScrollBar.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HorizontalScrollBar.qml index 12111f7e1c0..7774493c89a 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HorizontalScrollBar.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HorizontalScrollBar.qml @@ -41,7 +41,7 @@ ScrollBar { padding: 0 background: Rectangle { - color: StudioTheme.Values.themeSectionHeadBackground + color: StudioTheme.Values.themeScrollBarTrack } contentItem: Rectangle { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HueSlider.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HueSlider.qml index cb67d3a5184..66e657e10a3 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HueSlider.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HueSlider.qml @@ -24,6 +24,7 @@ ****************************************************************************/ import QtQuick 2.1 +import StudioTheme 1.0 as StudioTheme Item { id: colorSlider @@ -63,7 +64,7 @@ Item { Rectangle { anchors.fill: track anchors.margins: -1 - color: "darkGray" + color: StudioTheme.Values.themeControlOutline } Rectangle { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml index c642280d1a2..06f75a3425e 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml @@ -38,7 +38,7 @@ Label { width: Math.max(Math.min(240, parent.width - 280), 50) color: ((label.disabledState || label.disabledStateSoft) - ? StudioTheme.Values.themeDisabledTextColor + ? StudioTheme.Values.themeTextColorDisabled : StudioTheme.Values.themeTextColor) elide: Text.ElideRight diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml index e70f28ace44..1e97df3e115 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml @@ -35,12 +35,12 @@ Item { property variant backendValue property color borderColorSelected: colorLogic.textColor - property color borderColor: Theme.qmlDesignerBorderColor() + property color borderColor: StudioTheme.Values.themeControlOutline property bool showTranslateCheckBox: true - readonly property color selectedColor: Theme.qmlDesignerBackgroundColorDarkAlternate() - readonly property color unselectedColor: Theme.qmlDesignerBackgroundColorDarker() + readonly property color selectedColor: StudioTheme.Values.themeControlBackgroundInteraction + readonly property color unselectedColor: StudioTheme.Values.themeControlBackground property bool enabled: true diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml index 16778b34238..f3b34c9e8b0 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml @@ -26,6 +26,7 @@ import QtQuick 2.1 import QtQuick.Layouts 1.0 import QtQuickDesignerTheme 1.0 +import StudioTheme 1.0 as StudioTheme Rectangle { id: panel @@ -43,8 +44,8 @@ Rectangle { */ border.width: roundLeft || roundRight ? 1 : 0 - color: Theme.qmlDesignerButtonColor() - border.color: Theme.qmlDesignerBorderColor() + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline Rectangle { anchors.fill: parent @@ -71,7 +72,7 @@ Rectangle { } Rectangle { - color: Theme.qmlDesignerBorderColor() + color: StudioTheme.Values.themeControlOutline anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right @@ -81,7 +82,7 @@ Rectangle { } Rectangle { - color: Theme.qmlDesignerBorderColor() + color: StudioTheme.Values.themeControlOutline anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml index e3b37cb9186..cdc5780f523 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -62,7 +62,7 @@ Item { Rectangle { id: header - height: 20 + height: StudioTheme.Values.sectionHeadHeight anchors.left: parent.left anchors.right: parent.right color: Qt.lighter(StudioTheme.Values.themeSectionHeadBackground, 1.0 + (0.2 * level)) @@ -82,8 +82,8 @@ Item { anchors.verticalCenter: parent.verticalCenter color: StudioTheme.Values.themeTextColor x: 22 + (level * levelShift) - font.bold: true font.pixelSize: StudioTheme.Values.myFontSize + font.capitalization: Font.AllUppercase } MouseArea { @@ -112,15 +112,20 @@ Item { anchors.rightMargin: 5 + leftPadding anchors.leftMargin: 5 - leftPadding visible: false - color: "#666666" + color: StudioTheme.Values.themeControlOutline } default property alias __content: row.children readonly property alias contentItem: row - implicitHeight: Math.round(row.height + header.height - + section.topPadding + section.bottomPadding) + implicitHeight: Math.round(row.height + header.height + topRow.height + bottomRow.height) + + Row { + id: topRow + height: StudioTheme.Values.sectionHeadSpacerHeight + anchors.top: header.bottom + } Row { id: row @@ -128,8 +133,13 @@ Item { anchors.leftMargin: section.leftPadding anchors.right: parent.right anchors.rightMargin: section.rightPadding - anchors.top: header.bottom - anchors.topMargin: section.topPadding + anchors.top: topRow.bottom + } + + Row { + id: bottomRow + height: StudioTheme.Values.sectionHeadSpacerHeight + anchors.top: row.bottom } states: [ diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml index cbd6fe9d650..a1987dd2ad5 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml @@ -127,20 +127,18 @@ Section { text: qsTr("Alignment") } - AligmentHorizontalButtons { + Row { + AligmentHorizontalButtons {} + Item { + visible: showVerticalAlignment + width: 20 + height: 2 + } + + AligmentVerticalButtons { visible: showVerticalAlignment } } - Label { - visible: showVerticalAlignment - text: ("") - } - - AligmentVerticalButtons { - visible: showVerticalAlignment - } - - Label { visible: showFormatProperty text: qsTr("Format") diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml index a2c0c6bf93d..38b7f4557fe 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml @@ -23,7 +23,7 @@ ** ****************************************************************************/ -import QtQuick 2.1 +import QtQuick 2.15 import HelperWidgets 2.0 import StudioControls 1.0 as StudioControls import StudioTheme 1.0 as StudioTheme @@ -35,7 +35,8 @@ RowLayout { id: urlChooser property variant backendValue - property color textColor: colorLogic.highlight ? colorLogic.textColor : "white" + property color textColor: colorLogic.highlight ? colorLogic.textColor + : StudioTheme.Values.themeTextColor property string filter: "*.png *.gif *.jpg *.bmp *.jpeg *.svg *.pbm *.pgm *.ppm *.xbm *.xpm *.hdr *.webp" FileResourcesModel { @@ -57,50 +58,85 @@ RowLayout { property int hoverIndex: -1 ToolTip { - visible: comboBox.hovered + id: toolTip + visible: comboBox.hovered && toolTip.text !== "" text: urlChooser.backendValue.valueToString - delay: 1000 + delay: StudioTheme.Values.toolTipDelay + height: StudioTheme.Values.toolTipHeight + background: Rectangle { + color: StudioTheme.Values.themeToolTipBackground + border.color: StudioTheme.Values.themeToolTipOutline + border.width: StudioTheme.Values.border + } + contentItem: Label { + color: StudioTheme.Values.themeToolTipText + text: toolTip.text + verticalAlignment: Text.AlignVCenter + } } delegate: ItemDelegate { id: delegateItem width: parent.width - height: 20 - highlighted: comboBox.hoverIndex === index + height: StudioTheme.Values.height - 2 * StudioTheme.Values.border + padding: 0 + highlighted: comboBox.highlightedIndex === index - indicator: Label { // selected item check mark - padding: 5 - y: (parent.height - height) / 2 - text: StudioTheme.Constants.tickIcon - font.pixelSize: 10 - font.family: StudioTheme.Constants.iconFont.family - color: Theme.color(comboBox.hoverIndex === index ? Theme.PanelTextColorLight - : Theme.QmlDesigner_HighlightColor) - visible: comboBox.currentIndex === index + indicator: Item { + id: itemDelegateIconArea + width: delegateItem.height + height: delegateItem.height + + Label { + id: itemDelegateIcon + text: StudioTheme.Constants.tickIcon + color: delegateItem.highlighted ? StudioTheme.Values.themeTextSelectedTextColor + : StudioTheme.Values.themeTextColor + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + visible: comboBox.currentIndex === index ? true : false + anchors.fill: parent + renderType: Text.NativeRendering + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } } - contentItem: Label { - leftPadding: 10 + contentItem: Text { + leftPadding: itemDelegateIconArea.width text: modelData - anchors.top: parent.top - color: Theme.color(Theme.PanelTextColorLight) - font.pixelSize: 13 + color: delegateItem.highlighted ? StudioTheme.Values.themeTextSelectedTextColor + : StudioTheme.Values.themeTextColor + font: comboBox.font + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter } background: Rectangle { - anchors.fill: parent - color: parent.highlighted ? Theme.color(Theme.QmlDesigner_HighlightColor) : "transparent" + id: itemDelegateBackground + x: 0 + y: 0 + width: delegateItem.width + height: delegateItem.height + color: delegateItem.highlighted ? StudioTheme.Values.themeInteraction : "transparent" } ToolTip { + id: itemToolTip visible: delegateItem.hovered && comboBox.highlightedIndex === index text: fileModel.fullPathModel[index] - delay: 1000 - } - - onHoveredChanged: { - if (hovered) - comboBox.hoverIndex = index + delay: StudioTheme.Values.toolTipDelay + height: StudioTheme.Values.toolTipHeight + background: Rectangle { + color: StudioTheme.Values.themeToolTipBackground + border.color: StudioTheme.Values.themeToolTipOutline + border.width: StudioTheme.Values.border + } + contentItem: Label { + color: StudioTheme.Values.themeToolTipText + text: itemToolTip.text + verticalAlignment: Text.AlignVCenter + } } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/VerticalScrollBar.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/VerticalScrollBar.qml index 97234524d44..258d22d5c2e 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/VerticalScrollBar.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/VerticalScrollBar.qml @@ -41,7 +41,7 @@ ScrollBar { padding: 0 background: Rectangle { - color: StudioTheme.Values.themeSectionHeadBackground + color: StudioTheme.Values.themeScrollBarTrack } contentItem: Rectangle { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml index 629d482a206..759a3b01a10 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -30,12 +30,15 @@ import StudioTheme 1.0 as StudioTheme T.AbstractButton { id: myButton + property bool globalHover: false + property alias buttonIcon: buttonIcon.text property alias iconColor: buttonIcon.color property alias iconFont: buttonIcon.font.family property alias iconSize: buttonIcon.font.pixelSize property alias iconItalic: buttonIcon.font.italic property alias iconBold: buttonIcon.font.bold + property alias iconRotation: buttonIcon.rotation property alias backgroundVisible: buttonBackground.visible property alias backgroundRadius: buttonBackground.radius @@ -49,14 +52,14 @@ T.AbstractButton { activeFocusOnTab: false onHoveredChanged: { - if (parent !== undefined && parent.hover !== undefined) - parent.hover = hovered + if (parent !== undefined && parent.hoverCallback !== undefined) + parent.hoverCallback() } background: Rectangle { id: buttonBackground - color: myButton.checked ? StudioTheme.Values.themeControlBackgroundChecked : StudioTheme.Values.themeControlBackground - border.color: myButton.checked ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline border.width: StudioTheme.Values.border } @@ -75,14 +78,49 @@ T.AbstractButton { horizontalAlignment: Text.AlignHCenter anchors.fill: parent renderType: Text.QtRendering + + states: [ + State { + name: "default" + when: myButton.enabled && !myButton.pressed && !myButton.checked + PropertyChanges { + target: buttonIcon + color: StudioTheme.Values.themeIconColor + } + }, + State { + name: "press" + when: myButton.enabled && myButton.pressed + PropertyChanges { + target: buttonIcon + color: StudioTheme.Values.themeIconColorInteraction + } + }, + State { + name: "select" + when: myButton.enabled && !myButton.pressed && myButton.checked + PropertyChanges { + target: buttonIcon + color: StudioTheme.Values.themeIconColorSelected + } + }, + State { + name: "disable" + when: !myButton.enabled + PropertyChanges { + target: buttonIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] } } states: [ State { name: "default" - when: myButton.enabled && !myButton.hovered && !myButton.pressed - && !myButton.checked + when: myButton.enabled && !myButton.globalHover && !myButton.hovered + && !myButton.pressed && !myButton.checked PropertyChanges { target: buttonBackground color: StudioTheme.Values.themeControlBackground @@ -93,38 +131,42 @@ T.AbstractButton { } }, State { - name: "hovered" - when: myButton.hovered && !myButton.pressed + name: "globalHover" + when: myButton.globalHover && !myButton.hovered && !myButton.pressed PropertyChanges { target: buttonBackground - color: StudioTheme.Values.themeHoverHighlight + color: StudioTheme.Values.themeControlBackgroundGlobalHover } }, State { - name: "pressed" + name: "hover" + when: myButton.hovered && !myButton.pressed + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeControlBackgroundHover + } + }, + State { + name: "press" when: myButton.hovered && myButton.pressed PropertyChanges { target: buttonBackground - color: StudioTheme.Values.themeControlBackgroundPressed + color: StudioTheme.Values.themeControlBackgroundInteraction border.color: StudioTheme.Values.themeInteraction } PropertyChanges { target: myButton - z: 10 + z: 100 } }, State { - name: "disabled" + name: "disable" 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 index cde5beedc17..8d68e467b5f 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -32,18 +32,16 @@ Rectangle { property Item myControl - property bool showBackground: StudioTheme.Constants.showActionIndicatorBackground property alias icon: actionIndicatorIcon property bool hover: false property bool pressed: false property bool forceVisible: false - color: actionIndicator.showBackground ? StudioTheme.Values.themeControlBackground : "transparent" - border.color: actionIndicator.showBackground ? StudioTheme.Values.themeControlOutline : "transparent" + color: "transparent" - implicitWidth: StudioTheme.Values.height - implicitHeight: StudioTheme.Values.height + implicitWidth: StudioTheme.Values.actionIndicatorWidth + implicitHeight: StudioTheme.Values.actionIndicatorHeight signal clicked z: 10 @@ -65,7 +63,7 @@ Rectangle { states: [ State { - name: "hovered" + name: "hover" when: actionIndicator.hover && !actionIndicator.pressed && (!myControl || (!myControl.edit && !myControl.drag)) && actionIndicator.enabled @@ -76,7 +74,7 @@ Rectangle { } }, State { - name: "disabled" + name: "disable" when: !actionIndicator.enabled PropertyChanges { target: actionIndicatorIcon @@ -93,59 +91,4 @@ Rectangle { onContainsMouseChanged: actionIndicator.hover = containsMouse onClicked: actionIndicator.clicked() } - - states: [ - State { - name: "default" - when: myControl !== undefined && myControl.enabled && !actionIndicator.hover - && !actionIndicator.pressed && !myControl.hover - && !myControl.edit && !myControl.drag && actionIndicator.showBackground - PropertyChanges { - target: actionIndicator - color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeControlOutline - } - }, - State { - name: "globalHover" - when: myControl !== undefined && myControl.hover !== undefined - && myControl.hover && !actionIndicator.hover && !actionIndicator.pressed - && myControl.edit !== undefined && !myControl.edit && myControl.drag !== undefined - && !myControl.drag && actionIndicator.showBackground - PropertyChanges { - target: actionIndicator - color: StudioTheme.Values.themeHoverHighlight - border.color: StudioTheme.Values.themeControlOutline - } - }, - State { - name: "edit" - when: myControl !== undefined && myControl.edit !== undefined - && myControl.edit && actionIndicator.showBackground - PropertyChanges { - target: actionIndicator - color: StudioTheme.Values.themeFocusEdit - border.color: StudioTheme.Values.themeInteraction - } - }, - State { - name: "drag" - when: myControl !== undefined && myControl.drag !== undefined - && myControl.drag && actionIndicator.showBackground - PropertyChanges { - target: actionIndicator - color: StudioTheme.Values.themeFocusDrag - border.color: StudioTheme.Values.themeInteraction - } - }, - State { - name: "disabled" - when: myControl !== undefined && !myControl.enabled && actionIndicator.showBackground - PropertyChanges { - target: actionIndicator - color: StudioTheme.Values.themeControlBackgroundDisabled - border.color: StudioTheme.Values.themeControlOutlineDisabled - } - } - ] } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml index a9b0a2b81c7..f707288cb56 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -32,6 +32,7 @@ ButtonRow { property alias buttonIcon: myAbstractButton.buttonIcon property alias iconColor: myAbstractButton.iconColor + property alias iconRotation: myAbstractButton.iconRotation property alias checkable: myAbstractButton.checkable property alias checked: myAbstractButton.checked diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml index 1b233c590bc..2b8f2d67ac6 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml index b889173e3c9..edc60655d37 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -31,22 +31,41 @@ import StudioTheme 1.0 as StudioTheme Row { id: myButtonRow - property bool hover: false + property bool hover: actionIndicator.hover || myButtonRow.childHover + property bool childHover: false property alias actionIndicator: actionIndicator property alias actionIndicatorVisible: actionIndicator.visible - property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth - property real __actionIndicatorHeight: StudioTheme.Values.height + property real __actionIndicatorWidth: StudioTheme.Values.actionIndicatorWidth + property real __actionIndicatorHeight: StudioTheme.Values.actionIndicatorHeight ActionIndicator { id: actionIndicator myControl: myButtonRow x: 0 y: 0 - width: actionIndicator.visible ? __actionIndicatorWidth : 0 - height: actionIndicator.visible ? __actionIndicatorHeight : 0 + // + StudioTheme.Values.border on width because of negative spacing on the row + width: actionIndicator.visible ? myButtonRow.__actionIndicatorWidth + StudioTheme.Values.border : 0 + height: actionIndicator.visible ? myButtonRow.__actionIndicatorHeight : 0 } spacing: -StudioTheme.Values.border + + function hoverCallback() { + var hover = false + + for (var i = 0; i < children.length; ++i) { + if (children[i].hovered !== undefined) + hover = hover || children[i].hovered + } + + myButtonRow.childHover = hover + } + + onHoverChanged: { + for (var i = 0; i < children.length; ++i) + if (children[i].globalHover !== undefined) + children[i].globalHover = myButtonRow.hover + } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml index 5e55a4855be..ab834856ad6 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -32,25 +32,24 @@ T.CheckBox { property alias actionIndicator: actionIndicator + // This property is used to indicate the global hover state property bool hover: myCheckBox.hovered property bool edit: false property alias actionIndicatorVisible: actionIndicator.visible - property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth - property real __actionIndicatorHeight: StudioTheme.Values.height + property real __actionIndicatorWidth: StudioTheme.Values.actionIndicatorWidth + property real __actionIndicatorHeight: StudioTheme.Values.actionIndicatorHeight property alias labelVisible: checkBoxLabel.visible property alias labelColor: checkBoxLabel.color font.pixelSize: StudioTheme.Values.myFontSize - implicitWidth: Math.max( - implicitBackgroundWidth + leftInset + rightInset, - implicitContentWidth + leftPadding + rightPadding) - implicitHeight: Math.max( - implicitBackgroundHeight + topInset + bottomInset, - implicitContentHeight + topPadding + bottomPadding, - implicitIndicatorHeight + topPadding + bottomPadding) + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) spacing: StudioTheme.Values.checkBoxSpacing hoverEnabled: true @@ -58,15 +57,14 @@ T.CheckBox { ActionIndicator { id: actionIndicator - myControl: myCheckBox // TODO global hover issue. Can be solved with extra property in ActionIndicator - width: actionIndicator.visible ? __actionIndicatorWidth : 0 - height: actionIndicator.visible ? __actionIndicatorHeight : 0 + myControl: myCheckBox + width: actionIndicator.visible ? myCheckBox.__actionIndicatorWidth : 0 + height: actionIndicator.visible ? myCheckBox.__actionIndicatorHeight : 0 } indicator: Rectangle { id: checkBoxBackground - x: actionIndicator.x + actionIndicator.width - - (actionIndicator.visible ? StudioTheme.Values.border : 0) + x: actionIndicator.width y: 0 z: 5 implicitWidth: StudioTheme.Values.height @@ -112,33 +110,75 @@ T.CheckBox { states: [ State { name: "default" - when: myCheckBox.enabled && !myCheckBox.hovered - && !myCheckBox.pressed + when: myCheckBox.enabled && !myCheckBox.hover + && !myCheckBox.pressed && !actionIndicator.hover PropertyChanges { target: checkBoxBackground color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: checkedIcon + color: StudioTheme.Values.themeIconColor + } + PropertyChanges { + target: partiallyCheckedIcon + color: StudioTheme.Values.themeIconColor } }, State { - name: "hovered" - when: myCheckBox.hovered && !myCheckBox.pressed - && !actionIndicator.hover + name: "globalHover" + when: actionIndicator.hover && myCheckBox.hover && !myCheckBox.pressed PropertyChanges { target: checkBoxBackground - color: StudioTheme.Values.themeHoverHighlight + color: StudioTheme.Values.themeControlBackgroundGlobalHover + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: checkedIcon + color: StudioTheme.Values.themeIconColor + } + PropertyChanges { + target: partiallyCheckedIcon + color: StudioTheme.Values.themeIconColor } }, State { - name: "pressed" - when: myCheckBox.hovered && myCheckBox.pressed + name: "hover" + when: myCheckBox.hover && !actionIndicator.hover && !myCheckBox.pressed PropertyChanges { target: checkBoxBackground - color: StudioTheme.Values.themeFocusEdit - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackgroundHover + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: checkedIcon + color: StudioTheme.Values.themeIconColor // TODO naming + } + PropertyChanges { + target: partiallyCheckedIcon + color: StudioTheme.Values.themeIconColor } }, State { - name: "disabled" + name: "press" + when: myCheckBox.hover && myCheckBox.pressed + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeControlBackgroundInteraction + border.color: StudioTheme.Values.themeControlOutlineInteraction + } + PropertyChanges { + target: checkedIcon + color: StudioTheme.Values.themeIconColorInteraction + } + PropertyChanges { + target: partiallyCheckedIcon + color: StudioTheme.Values.themeIconColorInteraction + } + }, + State { + name: "disable" when: !myCheckBox.enabled PropertyChanges { target: checkBoxBackground @@ -147,11 +187,11 @@ T.CheckBox { } PropertyChanges { target: checkedIcon - color: StudioTheme.Values.themeTextColorDisabled + color: StudioTheme.Values.themeIconColorDisabled } PropertyChanges { target: partiallyCheckedIcon - color: StudioTheme.Values.themeTextColorDisabled + color: StudioTheme.Values.themeIconColorDisabled } PropertyChanges { target: checkBoxLabel diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml index 4c314b9101e..049942acf86 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -33,27 +33,33 @@ Rectangle { property T.Control myControl property T.Popup myPopup - property bool hover: false + property bool hover: checkIndicatorMouseArea.containsMouse + property bool pressed: checkIndicatorMouseArea.containsPress property bool checked: false color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeControlOutline - state: "default" + border.width: 0 Connections { target: myPopup - onClosed: checkIndicator.checked = false - onOpened: checkIndicator.checked = true + function onClosed() { checkIndicator.checked = false } + function 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() + if (myPopup.opened) { + myPopup.close() + } else { + myPopup.open() + myPopup.forceActiveFocus() + } + + if (myControl.activeFocus) + myControl.focus = false } } @@ -71,63 +77,87 @@ Rectangle { states: [ State { name: "default" - when: myControl.enabled && !(checkIndicator.hover - || myControl.hover) - && !checkIndicator.checked && !myControl.edit - && !myControl.drag + when: myControl.enabled && checkIndicator.enabled && !myControl.edit + && !checkIndicator.hover && !myControl.hover && !myControl.drag + && !checkIndicator.checked PropertyChanges { target: checkIndicator color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeControlOutline } }, State { - name: "hovered" - when: (checkIndicator.hover || myControl.hover) - && !checkIndicator.checked && !myControl.edit - && !myControl.drag + name: "globalHover" + when: myControl.enabled && checkIndicator.enabled && !myControl.drag + && !checkIndicator.hover && myControl.hover && !myControl.edit + && !checkIndicator.checked PropertyChanges { target: checkIndicator - color: StudioTheme.Values.themeHoverHighlight - border.color: StudioTheme.Values.themeControlOutline + color: StudioTheme.Values.themeControlBackgroundGlobalHover } }, State { - name: "checked" + name: "hover" + when: myControl.enabled && checkIndicator.enabled && !myControl.drag + && checkIndicator.hover && myControl.hover && !checkIndicator.pressed + && !checkIndicator.checked + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeControlBackgroundHover + } + }, + State { + name: "check" when: checkIndicator.checked + PropertyChanges { + target: checkIndicatorIcon + color: StudioTheme.Values.themeIconColorInteraction + } PropertyChanges { target: checkIndicator color: StudioTheme.Values.themeInteraction - border.color: StudioTheme.Values.themeInteraction } }, State { name: "edit" when: myControl.edit && !checkIndicator.checked && !(checkIndicator.hover && myControl.hover) + PropertyChanges { + target: checkIndicatorIcon + color: StudioTheme.Values.themeTextColor + } PropertyChanges { target: checkIndicator - color: StudioTheme.Values.themeFocusEdit - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackground + } + }, + State { + name: "press" + when: myControl.enabled && checkIndicator.enabled && !myControl.drag + && checkIndicator.pressed + PropertyChanges { + target: checkIndicatorIcon + color: StudioTheme.Values.themeIconColorInteraction + } + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeInteraction } }, State { name: "drag" - when: myControl.drag && !checkIndicator.checked + when: (myControl.drag !== undefined && myControl.drag) && !checkIndicator.checked && !(checkIndicator.hover && myControl.hover) PropertyChanges { target: checkIndicator - color: StudioTheme.Values.themeFocusDrag - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackgroundInteraction } }, State { - name: "disabled" + name: "disable" when: !myControl.enabled PropertyChanges { target: checkIndicator color: StudioTheme.Values.themeControlBackgroundDisabled - border.color: StudioTheme.Values.themeControlOutlineDisabled } PropertyChanges { target: checkIndicatorIcon diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml index 449a40432a1..625c262799b 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml @@ -1,8 +1,6 @@ - - /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -35,14 +33,16 @@ T.ComboBox { property alias actionIndicator: actionIndicator property alias labelColor: comboBoxInput.color - property bool hover: false // This property is used to indicate the global hover state - property bool edit: myComboBox.activeFocus + // This property is used to indicate the global hover state + property bool hover: comboBoxInput.hover || actionIndicator.hover || popupIndicator.hover + property bool edit: myComboBox.activeFocus && myComboBox.editable + property bool open: comboBoxPopup.opened property bool dirty: false // user modification flag property alias actionIndicatorVisible: actionIndicator.visible - property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth - property real __actionIndicatorHeight: StudioTheme.Values.height + property real __actionIndicatorWidth: StudioTheme.Values.actionIndicatorWidth + property real __actionIndicatorHeight: StudioTheme.Values.actionIndicatorHeight property alias textInput: comboBoxInput @@ -50,12 +50,11 @@ T.ComboBox { enum ActivatedReason { EditingFinished, Other } - width: StudioTheme.Values.squareComponentWidth * 5 - height: StudioTheme.Values.height + width: StudioTheme.Values.defaultControlWidth + height: StudioTheme.Values.defaultControlHeight leftPadding: actionIndicator.width - - (myComboBox.actionIndicatorVisible ? StudioTheme.Values.border : 0) - rightPadding: popupIndicator.width - StudioTheme.Values.border + rightPadding: popupIndicator.width + StudioTheme.Values.border font.pixelSize: StudioTheme.Values.myFontSize wheelEnabled: false @@ -94,19 +93,18 @@ T.ComboBox { 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 + x: comboBoxInput.x + comboBoxInput.width + y: StudioTheme.Values.border + width: StudioTheme.Values.checkIndicatorWidth - StudioTheme.Values.border + height: StudioTheme.Values.checkIndicatorHeight - (StudioTheme.Values.border * 2) } background: Rectangle { id: comboBoxBackground - color: StudioTheme.Values.themeControlOutline + color: StudioTheme.Values.themeControlBackground border.color: StudioTheme.Values.themeControlOutline border.width: StudioTheme.Values.border x: actionIndicator.width - - (myComboBox.actionIndicatorVisible ? StudioTheme.Values.border : 0) width: myComboBox.width - actionIndicator.width height: myComboBox.height } @@ -138,7 +136,8 @@ T.ComboBox { contentItem: Text { leftPadding: itemDelegateIconArea.width text: myComboBox.textRole ? (Array.isArray(myComboBox.model) ? modelData[myComboBox.textRole] : model[myComboBox.textRole]) : modelData - color: StudioTheme.Values.themeTextColor + color: myItemDelegate.highlighted ? StudioTheme.Values.themeTextSelectedTextColor + : StudioTheme.Values.themeTextColor font: myComboBox.font elide: Text.ElideRight verticalAlignment: Text.AlignVCenter @@ -152,7 +151,8 @@ T.ComboBox { T.Label { id: itemDelegateIcon text: StudioTheme.Constants.tickIcon - color: myItemDelegate.highlighted ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeInteraction + color: myItemDelegate.highlighted ? StudioTheme.Values.themeTextSelectedTextColor + : StudioTheme.Values.themeTextColor font.family: StudioTheme.Constants.iconFont.family font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti visible: myComboBox.currentIndex === index ? true : false @@ -177,9 +177,9 @@ T.ComboBox { popup: T.Popup { id: comboBoxPopup - x: comboBoxInput.x - y: myComboBox.height - StudioTheme.Values.border - width: comboBoxInput.width + popupIndicator.width - StudioTheme.Values.border + x: actionIndicator.width + StudioTheme.Values.border + y: myComboBox.height + width: myComboBox.width - actionIndicator.width - (StudioTheme.Values.border * 2) // 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. @@ -205,9 +205,8 @@ T.ComboBox { } background: Rectangle { - color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeInteraction - border.width: StudioTheme.Values.border + color: StudioTheme.Values.themePopupBackground + border.width: 0 } enter: Transition { @@ -219,7 +218,8 @@ T.ComboBox { states: [ State { name: "default" - when: !myComboBox.hover && !myComboBox.edit + when: myComboBox.enabled && !myComboBox.hover && !myComboBox.edit && !myComboBox.open + && !myComboBox.activeFocus PropertyChanges { target: myComboBox wheelEnabled: false @@ -230,13 +230,16 @@ T.ComboBox { } PropertyChanges { target: comboBoxBackground - color: StudioTheme.Values.themeControlOutline + color: StudioTheme.Values.themeControlBackground border.color: StudioTheme.Values.themeControlOutline } }, + // This state is intended for ComboBoxes which aren't editable, but have focus e.g. via + // tab focus. It is therefor possible to use the mouse wheel to scroll through the items. State { name: "focus" - when: myComboBox.edit && !myComboBox.editable + when: myComboBox.enabled && myComboBox.activeFocus && !myComboBox.editable + && !myComboBox.open PropertyChanges { target: myComboBox wheelEnabled: true @@ -248,7 +251,7 @@ T.ComboBox { }, State { name: "edit" - when: myComboBox.edit && myComboBox.editable && !comboBoxPopup.opened + when: myComboBox.enabled && myComboBox.edit && myComboBox.editable && !myComboBox.open PropertyChanges { target: myComboBox wheelEnabled: true @@ -260,8 +263,8 @@ T.ComboBox { } PropertyChanges { target: comboBoxBackground - color: StudioTheme.Values.themeInteraction - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackgroundInteraction + border.color: StudioTheme.Values.themeControlOutline } StateChangeScript { script: comboBoxPopup.close() @@ -269,7 +272,7 @@ T.ComboBox { }, State { name: "popup" - when: myComboBox.edit && comboBoxPopup.opened + when: myComboBox.enabled && myComboBox.open PropertyChanges { target: myComboBox wheelEnabled: true @@ -279,6 +282,20 @@ T.ComboBox { selectByMouse: false readOnly: true } + PropertyChanges { + target: comboBoxBackground + color: StudioTheme.Values.themeControlBackgroundInteraction + border.color: StudioTheme.Values.themeControlOutlineInteraction + } + }, + State { + name: "disable" + when: !myComboBox.enabled + PropertyChanges { + target: comboBoxBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } } ] diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml index 3485316c3e7..5945837ebf7 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -33,7 +33,7 @@ TextInput { property T.Control myControl property bool edit: textInput.activeFocus - property bool drag: false + property bool hover: mouseArea.containsMouse z: 2 font: myControl.font @@ -54,15 +54,14 @@ TextInput { clip: true Rectangle { - id: textInputArea - x: 0 - y: 0 + id: textInputBackground + x: StudioTheme.Values.border + y: StudioTheme.Values.border z: -1 width: textInput.width - height: StudioTheme.Values.height + height: StudioTheme.Values.height - (StudioTheme.Values.border * 2) color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeControlOutline - border.width: StudioTheme.Values.border + border.width: 0 } TapHandler { @@ -73,6 +72,7 @@ TextInput { if (textInput.readOnly) { if (myControl.popup.opened) { myControl.popup.close() + myControl.focus = false } else { myControl.forceActiveFocus() myControl.popup.open() @@ -91,20 +91,17 @@ TextInput { 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.edit - && !mouseArea.containsMouse && !myControl.drag + when: myControl.enabled && !textInput.edit && !textInput.hover && !myControl.hover + && !myControl.open PropertyChanges { - target: textInputArea + target: textInputBackground color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeControlOutline } PropertyChanges { target: tapHandler @@ -116,27 +113,38 @@ TextInput { } }, State { - name: "hovered" - when: myControl.hover && !textInput.edit && !myControl.drag + name: "globalHover" + when: myControl.hover && !textInput.hover && !textInput.edit && !myControl.open PropertyChanges { - target: textInputArea - color: StudioTheme.Values.themeHoverHighlight - border.color: StudioTheme.Values.themeControlOutline + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundGlobalHover } }, + State { + name: "hover" + when: textInput.hover && myControl.hover && !textInput.edit + PropertyChanges { + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundHover + } + }, + // This state is intended for ComboBoxes which aren't editable, but have focus e.g. via + // tab focus. It is therefor possible to use the mouse wheel to scroll through the items. State { name: "focus" when: textInput.edit && !myControl.editable PropertyChanges { - target: textInputArea - color: StudioTheme.Values.themeFocusEdit - border.color: StudioTheme.Values.themeInteraction + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundInteraction } }, State { name: "edit" when: textInput.edit && myControl.editable - extend: "focus" + PropertyChanges { + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundInteraction + } PropertyChanges { target: tapHandler enabled: false @@ -147,12 +155,19 @@ TextInput { } }, State { - name: "disabled" + name: "popup" + when: myControl.open + PropertyChanges { + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundHover + } + }, + State { + name: "disable" when: !myControl.enabled PropertyChanges { - target: textInputArea + target: textInputBackground color: StudioTheme.Values.themeControlBackgroundDisabled - border.color: StudioTheme.Values.themeControlOutlineDisabled } PropertyChanges { target: textInput diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml index 9d7685534a9..3b122e78b67 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml index 9e48128c493..fdfd86ce277 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml index c2190c5d838..1a08091c315 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml index 773282958f5..327eafcf08f 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml @@ -1,8 +1,6 @@ - - /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -24,6 +22,7 @@ ** 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 diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml index 023f9b0f5dc..0b3f0685b29 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -35,10 +35,9 @@ T.MenuItem { implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, implicitContentWidth + leftPadding + rightPadding) - implicitHeight: Math.max( - implicitBackgroundHeight + topInset + bottomInset, - implicitContentHeight + topPadding + bottomPadding, - implicitIndicatorHeight + topPadding + bottomPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) padding: 0 spacing: 0 @@ -50,7 +49,8 @@ T.MenuItem { id: textLabel text: control.text font: control.font - color: control.enabled ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeTextColorDisabled + color: control.enabled ? StudioTheme.Values.themeTextColor + : StudioTheme.Values.themeTextColorDisabled anchors.verticalCenter: parent.verticalCenter } @@ -78,6 +78,8 @@ T.MenuItem { y: StudioTheme.Values.border width: control.menu.width - (StudioTheme.Values.border * 2) height: control.height - (StudioTheme.Values.border * 2) - color: control.down ? control.palette.midlight : control.highlighted ? StudioTheme.Values.themeInteraction : "transparent" + color: control.down ? control.palette.midlight + : control.highlighted ? StudioTheme.Values.themeInteraction + : "transparent" } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItemWithIcon.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItemWithIcon.qml new file mode 100644 index 00000000000..d8493d2c022 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItemWithIcon.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 +import QtQuick.Controls 2.12 + +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 + action: Action {} + + contentItem: Item { + Text { + id: iconLabel + text: control.checked ? StudioTheme.Constants.tickIcon : "" + visible: true + color: control.enabled ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeTextColorDisabled + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.myIconFontSize + anchors.verticalCenter: parent.verticalCenter + } + + Text { + id: textLabel + x: StudioTheme.Values.height + text: control.text + font: control.font + color: control.enabled ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeTextColorDisabled + anchors.verticalCenter: parent.verticalCenter + } + } + + background: Rectangle { + implicitWidth: iconLabel.implicitWidth + textLabel.implicitWidth + control.labelSpacing + + control.leftPadding + control.rightPadding + implicitHeight: StudioTheme.Values.height + x: StudioTheme.Values.border + y: StudioTheme.Values.border + width: control.menu.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 index a2f2f57e946..634d2e6e737 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSliderPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSliderPopup.qml index dd6be8cbc13..96027373ee1 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSliderPopup.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSliderPopup.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -32,14 +32,16 @@ T.Popup { property T.Control myControl + property bool drag: slider.pressed + dim: false closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnEscape | T.Popup.CloseOnReleaseOutside | T.Popup.CloseOnReleaseOutsideParent background: Rectangle { - color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themePopupBackground + border.width: 0 } contentItem: T.Slider { @@ -63,7 +65,8 @@ T.Popup { width: StudioTheme.Values.sliderHandleWidth height: StudioTheme.Values.sliderHandleHeight radius: 0 - color: slider.pressed ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline + color: slider.pressed ? StudioTheme.Values.themeSliderHandleInteraction + : StudioTheme.Values.themeSliderHandle } background: Rectangle { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml index 0da5776d406..a1f10d318d1 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -50,8 +50,10 @@ T.SpinBox { } property bool edit: spinBoxInput.activeFocus - property bool hover: false // This property is used to indicate the global hover state + // This property is used to indicate the global hover state + property bool hover: mySpinBox.hovered || actionIndicator.hover property bool drag: false + property bool sliderDrag: sliderPopup.drag property bool dirty: false // user modification flag @@ -59,18 +61,16 @@ T.SpinBox { property real realDragRange: mySpinBox.realTo - mySpinBox.realFrom property alias actionIndicatorVisible: actionIndicator.visible - property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth - property real __actionIndicatorHeight: StudioTheme.Values.height + property real __actionIndicatorWidth: StudioTheme.Values.actionIndicatorWidth + property real __actionIndicatorHeight: StudioTheme.Values.actionIndicatorHeight 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 real __spinBoxIndicatorWidth: StudioTheme.Values.spinBoxIndicatorWidth + property real __spinBoxIndicatorHeight: StudioTheme.Values.spinBoxIndicatorHeight property alias sliderIndicatorVisible: sliderIndicator.visible - property real __sliderIndicatorWidth: StudioTheme.Values.squareComponentWidth - property real __sliderIndicatorHeight: StudioTheme.Values.height + property real __sliderIndicatorWidth: StudioTheme.Values.sliderIndicatorWidth + property real __sliderIndicatorHeight: StudioTheme.Values.sliderIndicatorHeight property alias compressedValueTimer: myTimer @@ -83,13 +83,13 @@ T.SpinBox { // Use custom wheel handling due to bugs property bool __wheelEnabled: false wheelEnabled: false + hoverEnabled: true - width: StudioTheme.Values.squareComponentWidth * 5 - height: StudioTheme.Values.height + width: StudioTheme.Values.defaultControlWidth + height: StudioTheme.Values.defaultControlHeight leftPadding: spinBoxIndicatorDown.x + spinBoxIndicatorDown.width - - (spinBoxIndicatorVisible ? 0 : StudioTheme.Values.border) - rightPadding: sliderIndicator.width - (sliderIndicatorVisible ? StudioTheme.Values.border : 0) + rightPadding: sliderIndicator.width + StudioTheme.Values.border font.pixelSize: StudioTheme.Values.myFontSize editable: true @@ -113,8 +113,8 @@ T.SpinBox { myControl: mySpinBox x: 0 y: 0 - width: actionIndicator.visible ? __actionIndicatorWidth : 0 - height: actionIndicator.visible ? __actionIndicatorHeight : 0 + width: actionIndicator.visible ? mySpinBox.__actionIndicatorWidth : 0 + height: actionIndicator.visible ? mySpinBox.__actionIndicatorHeight : 0 } up.indicator: RealSpinBoxIndicator { @@ -124,12 +124,13 @@ T.SpinBox { visible: mySpinBox.spinBoxIndicatorVisible onRealReleased: mySpinBox.realIncrease() onRealPressAndHold: mySpinBox.realIncrease() - x: actionIndicator.width + (mySpinBox.actionIndicatorVisible ? 0 : StudioTheme.Values.border) + x: actionIndicator.width + StudioTheme.Values.border y: StudioTheme.Values.border width: mySpinBox.spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorWidth : 0 height: mySpinBox.spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorHeight : 0 - realEnabled: (mySpinBox.realFrom < mySpinBox.realTo) ? (mySpinBox.realValue < mySpinBox.realTo) : (mySpinBox.realValue > mySpinBox.realTo) + realEnabled: (mySpinBox.realFrom < mySpinBox.realTo) ? (mySpinBox.realValue < mySpinBox.realTo) + : (mySpinBox.realValue > mySpinBox.realTo) } down.indicator: RealSpinBoxIndicator { @@ -138,12 +139,13 @@ T.SpinBox { visible: mySpinBox.spinBoxIndicatorVisible onRealReleased: mySpinBox.realDecrease() onRealPressAndHold: mySpinBox.realDecrease() - x: actionIndicator.width + (mySpinBox.actionIndicatorVisible ? 0 : StudioTheme.Values.border) + x: actionIndicator.width + StudioTheme.Values.border y: spinBoxIndicatorUp.y + spinBoxIndicatorUp.height width: mySpinBox.spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorWidth : 0 height: mySpinBox.spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorHeight : 0 - realEnabled: (mySpinBox.realFrom < mySpinBox.realTo) ? (mySpinBox.realValue > mySpinBox.realFrom) : (mySpinBox.realValue < mySpinBox.realFrom) + realEnabled: (mySpinBox.realFrom < mySpinBox.realTo) ? (mySpinBox.realValue > mySpinBox.realFrom) + : (mySpinBox.realValue < mySpinBox.realFrom) } contentItem: RealSpinBoxInput { @@ -173,7 +175,7 @@ T.SpinBox { color: StudioTheme.Values.themeControlOutline border.color: StudioTheme.Values.themeControlOutline border.width: StudioTheme.Values.border - x: actionIndicator.width - (mySpinBox.actionIndicatorVisible ? StudioTheme.Values.border : 0) + x: actionIndicator.width width: mySpinBox.width - actionIndicator.width height: mySpinBox.height } @@ -182,18 +184,19 @@ T.SpinBox { id: sliderIndicator myControl: mySpinBox myPopup: sliderPopup - x: spinBoxInput.x + spinBoxInput.width - StudioTheme.Values.border - width: sliderIndicator.visible ? mySpinBox.__sliderIndicatorWidth : 0 - height: sliderIndicator.visible ? mySpinBox.__sliderIndicatorHeight : 0 + x: spinBoxInput.x + spinBoxInput.width + y: StudioTheme.Values.border + width: sliderIndicator.visible ? mySpinBox.__sliderIndicatorWidth - StudioTheme.Values.border : 0 + height: sliderIndicator.visible ? mySpinBox.__sliderIndicatorHeight - (StudioTheme.Values.border * 2) : 0 visible: false // reasonable default } RealSliderPopup { id: sliderPopup myControl: mySpinBox - x: spinBoxInput.x - y: StudioTheme.Values.height - StudioTheme.Values.border - width: spinBoxInput.width + sliderIndicator.width - StudioTheme.Values.border + x: actionIndicator.width + StudioTheme.Values.border + y: StudioTheme.Values.height + width: mySpinBox.width - actionIndicator.width - (StudioTheme.Values.border * 2) height: StudioTheme.Values.sliderHeight enter: Transition { @@ -203,6 +206,7 @@ T.SpinBox { } textFromValue: function (value, locale) { + locale.numberOptions = Locale.OmitGroupSeparator return Number(mySpinBox.realValue).toLocaleString(locale, 'f', mySpinBox.decimals) } @@ -214,8 +218,8 @@ T.SpinBox { states: [ State { name: "default" - when: mySpinBox.enabled && !mySpinBox.hover - && !mySpinBox.edit && !mySpinBox.drag + when: mySpinBox.enabled && !mySpinBox.hover && !mySpinBox.hovered + && !mySpinBox.edit && !mySpinBox.drag && !mySpinBox.sliderDrag PropertyChanges { target: mySpinBox __wheelEnabled: false @@ -226,7 +230,7 @@ T.SpinBox { } PropertyChanges { target: spinBoxBackground - color: StudioTheme.Values.themeControlOutline + color: StudioTheme.Values.themeControlBackground border.color: StudioTheme.Values.themeControlOutline } }, @@ -243,21 +247,21 @@ T.SpinBox { } PropertyChanges { target: spinBoxBackground - color: StudioTheme.Values.themeInteraction - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackgroundInteraction + border.color: StudioTheme.Values.themeControlOutline } }, State { name: "drag" - when: mySpinBox.drag + when: mySpinBox.drag || mySpinBox.sliderDrag PropertyChanges { target: spinBoxBackground - color: StudioTheme.Values.themeInteraction - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackgroundInteraction + border.color: StudioTheme.Values.themeControlOutlineInteraction } }, State { - name: "disabled" + name: "disable" when: !mySpinBox.enabled PropertyChanges { target: spinBoxBackground @@ -296,12 +300,8 @@ T.SpinBox { } onDisplayTextChanged: spinBoxInput.text = mySpinBox.displayText onActiveFocusChanged: { - if (mySpinBox.activeFocus) - // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason) + if (mySpinBox.activeFocus) // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason) spinBoxInput.selectAll() - - if (sliderPopup.opened && !mySpinBox.activeFocus) - sliderPopup.close() } Keys.onPressed: { @@ -336,7 +336,6 @@ T.SpinBox { } function setValueFromInput() { - if (!mySpinBox.dirty) return diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxIndicator.qml index 0216bb20d9e..30233272967 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxIndicator.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxIndicator.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -32,8 +32,8 @@ Rectangle { property T.Control myControl - property bool hover: false - property bool pressed: false + property bool hover: spinBoxIndicatorMouseArea.containsMouse + property bool pressed: spinBoxIndicatorMouseArea.containsPress property bool released: false property bool realEnabled: true @@ -77,15 +77,12 @@ Rectangle { property bool pressedAndHeld: false anchors.fill: parent - // Shift the MouseArea down by 1 pixel due to potentially overlapping areas - anchors.topMargin: iconFlip < 0 ? 0 : 1 - anchors.bottomMargin: iconFlip < 0 ? 1 : 0 hoverEnabled: true pressAndHoldInterval: 500 - onContainsMouseChanged: spinBoxIndicator.hover = containsMouse - onContainsPressChanged: spinBoxIndicator.pressed = containsPress onPressed: { - myControl.forceActiveFocus() + if (myControl.activeFocus) + spinBoxIndicator.forceActiveFocus() + spinBoxIndicator.realPressed() mouse.accepted = true } @@ -130,15 +127,42 @@ Rectangle { states: [ State { - name: "default" - when: myControl.enabled && spinBoxIndicator.enabled + name: "globalHover" + when: myControl.enabled && spinBoxIndicator.enabled && !myControl.drag + && !spinBoxIndicator.hover && myControl.hover && !myControl.edit PropertyChanges { target: spinBoxIndicatorIcon color: StudioTheme.Values.themeTextColor } }, State { - name: "disabled" + name: "hover" + when: myControl.enabled && spinBoxIndicator.enabled && !myControl.drag + && spinBoxIndicator.hover && myControl.hover && !spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeIconColorHover + } + }, + State { + name: "press" + when: myControl.enabled && spinBoxIndicator.enabled && !myControl.drag + && spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicatorIcon + color: "#323232" // TODO + } + }, + State { + name: "edit" + when: myControl.edit + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeTextColor + } + }, + State { + name: "disable" when: !myControl.enabled || !spinBoxIndicator.enabled PropertyChanges { target: spinBoxIndicatorIcon @@ -151,55 +175,102 @@ Rectangle { states: [ State { name: "default" - when: myControl.enabled && !(spinBoxIndicator.hover - || myControl.hover) - && !spinBoxIndicator.pressed && !myControl.edit - && !myControl.drag + when: myControl.enabled && !myControl.edit + && !spinBoxIndicator.hover && !myControl.hover && !myControl.drag + PropertyChanges { + target: spinBoxIndicatorIcon + visible: false + } PropertyChanges { target: spinBoxIndicator color: StudioTheme.Values.themeControlBackground } }, State { - name: "hovered" - when: (spinBoxIndicator.hover || myControl.hover) - && !spinBoxIndicator.pressed && !myControl.edit - && !myControl.drag + name: "globalHover" + when: myControl.enabled && spinBoxIndicator.enabled && !myControl.drag + && !spinBoxIndicator.hover && myControl.hover && !myControl.edit + PropertyChanges { + target: spinBoxIndicatorIcon + visible: true + } PropertyChanges { target: spinBoxIndicator - color: StudioTheme.Values.themeHoverHighlight + color: StudioTheme.Values.themeControlBackgroundGlobalHover } }, State { - name: "pressed" - when: spinBoxIndicator.pressed + name: "hover" + when: myControl.enabled && !myControl.drag + && spinBoxIndicator.hover && myControl.hover && !spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicatorIcon + visible: true + } PropertyChanges { target: spinBoxIndicator - color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackgroundHover + } + }, + State { + name: "press" + when: myControl.enabled && spinBoxIndicator.enabled && !myControl.drag + && spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicatorIcon + visible: true + } + PropertyChanges { + target: spinBoxIndicator + color: "#2aafd3" // TODO } }, State { name: "edit" when: myControl.edit + PropertyChanges { + target: spinBoxIndicatorIcon + visible: true + } PropertyChanges { target: spinBoxIndicator - color: StudioTheme.Values.themeFocusEdit + color: StudioTheme.Values.themeControlBackground } }, State { name: "drag" when: myControl.drag + PropertyChanges { + target: spinBoxIndicatorIcon + visible: false + } PropertyChanges { target: spinBoxIndicator - color: StudioTheme.Values.themeFocusDrag + color: StudioTheme.Values.themeControlBackgroundInteraction } }, State { - name: "disabled" + name: "disable" when: !myControl.enabled + PropertyChanges { + target: spinBoxIndicatorIcon + visible: false + } PropertyChanges { target: spinBoxIndicator - color: StudioTheme.Values.themeControlBackgroundDisabled + color: StudioTheme.Values.themeControlBackground + } + }, + State { + name: "limit" + when: !spinBoxIndicator.enabled && !spinBoxIndicator.realEnabled && myControl.hover + PropertyChanges { + target: spinBoxIndicatorIcon + visible: true + } + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackground } } ] diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml index 45dce181fe0..aa2603273c5 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -34,6 +34,7 @@ TextInput { property bool edit: textInput.activeFocus property bool drag: false + property bool hover: mouseArea.containsMouse z: 2 font: myControl.font @@ -59,15 +60,14 @@ TextInput { onActiveFocusChanged: textInput.focus = activeFocus Rectangle { - id: textInputArea - color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeControlOutline - border.width: StudioTheme.Values.border + id: textInputBackground x: 0 - y: 0 + y: StudioTheme.Values.border z: -1 width: textInput.width - height: StudioTheme.Values.height + height: StudioTheme.Values.height - (StudioTheme.Values.border * 2) + color: StudioTheme.Values.themeControlBackground + border.width: 0 } Item { @@ -118,8 +118,6 @@ TextInput { propagateComposedEvents: true acceptedButtons: Qt.LeftButton cursorShape: Qt.PointingHandCursor - // Sets the global hover - onContainsMouseChanged: myControl.hover = containsMouse onPositionChanged: { if (!mouseArea.dragging @@ -238,12 +236,11 @@ TextInput { states: [ State { name: "default" - when: myControl.enabled && !textInput.edit - && !mouseArea.containsMouse && !myControl.drag + when: myControl.enabled && !textInput.edit && !textInput.hover && !myControl.hover + && !myControl.drag && !myControl.sliderDrag PropertyChanges { - target: textInputArea + target: textInputBackground color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeControlOutline } PropertyChanges { target: mouseArea @@ -251,21 +248,28 @@ TextInput { } }, State { - name: "hovered" - when: myControl.hover && !textInput.edit && !myControl.drag + name: "globalHover" + when: myControl.hover && !textInput.hover + && !textInput.edit && !myControl.drag PropertyChanges { - target: textInputArea - color: StudioTheme.Values.themeHoverHighlight - border.color: StudioTheme.Values.themeControlOutline + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundGlobalHover + } + }, + State { + name: "hover" + when: textInput.hover && myControl.hover && !textInput.edit && !myControl.drag + PropertyChanges { + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundHover } }, State { name: "edit" when: textInput.edit && !myControl.drag PropertyChanges { - target: textInputArea - color: StudioTheme.Values.themeFocusEdit - border.color: StudioTheme.Values.themeInteraction + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundInteraction } PropertyChanges { target: mouseArea @@ -276,18 +280,32 @@ TextInput { name: "drag" when: myControl.drag PropertyChanges { - target: textInputArea - color: StudioTheme.Values.themeFocusDrag - border.color: StudioTheme.Values.themeInteraction + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundInteraction + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeInteraction } }, State { - name: "disabled" + name: "sliderDrag" + when: myControl.sliderDrag + PropertyChanges { + target: textInputBackground + color: StudioTheme.Values.themeControlBackground + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disable" when: !myControl.enabled PropertyChanges { - target: textInputArea + target: textInputBackground color: StudioTheme.Values.themeControlBackgroundDisabled - border.color: StudioTheme.Values.themeControlOutlineDisabled } PropertyChanges { target: textInput diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml index 886e92206b4..094a54e7283 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml index 3f21c4dbbfa..3cb222a50eb 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml index d5c917f5ce3..0214ae46ddf 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -28,5 +28,5 @@ import QtQuick.Layouts 1.12 RowLayout { Layout.fillWidth: true - spacing: 4 + spacing: 0 } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml index 98a163a3228..e115b13eded 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -34,7 +34,7 @@ Item { property int topPadding: 4 property int rightPadding: 0 - property int animationDuration: 0 + property int animationDuration: 120 property bool expanded: true @@ -42,28 +42,27 @@ Item { Rectangle { id: header - height: StudioTheme.Values.height + height: StudioTheme.Values.sectionHeadHeight anchors.left: parent.left anchors.right: parent.right - color: StudioTheme.Values.themeControlBackground + color: StudioTheme.Values.themeSectionHeadBackground SectionLabel { id: label anchors.verticalCenter: parent.verticalCenter color: StudioTheme.Values.themeTextColor x: 22 - //font.bold: true font.pixelSize: StudioTheme.Values.myFontSize - // TODO font size? + font.capitalization: Font.AllUppercase } SectionLabel { id: arrow width: StudioTheme.Values.spinControlIconSizeMulti height: StudioTheme.Values.spinControlIconSizeMulti - text: StudioTheme.Constants.upDownSquare2 + text: StudioTheme.Constants.startNode color: StudioTheme.Values.themeTextColor renderType: Text.NativeRendering anchors.left: parent.left @@ -74,7 +73,7 @@ Item { Behavior on rotation { NumberAnimation { easing.type: Easing.OutCubic - duration: animationDuration + duration: section.animationDuration } } } @@ -82,7 +81,6 @@ Item { MouseArea { anchors.fill: parent onClicked: { - section.animationDuration = 120 section.expanded = !section.expanded if (!section.expanded) // TODO section.forceActiveFocus() @@ -94,7 +92,13 @@ Item { readonly property alias contentItem: row - implicitHeight: Math.round(row.height + header.height) + implicitHeight: Math.round(row.height + header.height + topRow.height + bottomRow.height) + + Row { + id: topRow + height: StudioTheme.Values.sectionHeadSpacerHeight + anchors.top: header.bottom + } Row { id: row @@ -102,18 +106,31 @@ Item { anchors.leftMargin: leftPadding anchors.right: parent.right anchors.rightMargin: rightPadding - anchors.top: header.bottom - anchors.topMargin: topPadding + anchors.top: topRow.bottom + } + + Row { + id: bottomRow + height: StudioTheme.Values.sectionHeadSpacerHeight + anchors.top: row.bottom } Behavior on implicitHeight { NumberAnimation { easing.type: Easing.OutCubic - duration: animationDuration + duration: section.animationDuration } } states: [ + State { + name: "Expanded" + when: section.expanded + PropertyChanges { + target: arrow + rotation: 90 + } + }, State { name: "Collapsed" when: !section.expanded @@ -123,7 +140,7 @@ Item { } PropertyChanges { target: arrow - rotation: -90 + rotation: 0 } } ] diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml index 73fec21ce05..a05f3b673ab 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -35,7 +35,7 @@ T.Label { // workaround because PictureSpecifics.qml still use this //property alias toolTip: toolTipArea.tooltip - width: Math.max(Math.min(240, parent.width - 220), 80) + width: Math.max(Math.min(240, parent.width - 220), 90) color: StudioTheme.Values.themeTextColor font.pixelSize: StudioTheme.Values.myFontSize // TODO elide: Text.ElideRight diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml index 22054feebb4..cf1561862d2 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,10 +25,11 @@ import QtQuick 2.12 import QtQuick.Layouts 1.12 +import StudioTheme 1.0 as StudioTheme GridLayout { columns: 2 - columnSpacing: 12 - rowSpacing: 4 - width: parent.width - 16 + columnSpacing: StudioTheme.Values.sectionColumnSpacing + rowSpacing: StudioTheme.Values.sectionRowSpacing + width: parent.width - 16 // TODO parameterize } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml index e8cfe2a13a9..0a260618be7 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -50,8 +50,8 @@ T.Slider { property bool edit: slider.activeFocus property alias actionIndicatorVisible: actionIndicator.visible - property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth - property real __actionIndicatorHeight: StudioTheme.Values.height + property real __actionIndicatorWidth: StudioTheme.Values.actionIndicatorWidth + property real __actionIndicatorHeight: StudioTheme.Values.actionIndicatorHeight implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, implicitHandleWidth + leftPadding + rightPadding) @@ -231,7 +231,7 @@ T.Slider { } }, State { - name: "hovered" + name: "hover" when: slider.enabled && slider.hover && !slider.edit PropertyChanges { target: slider @@ -258,7 +258,7 @@ T.Slider { } }, State { - name: "disabled" + name: "disable" when: !slider.enabled PropertyChanges { target: tickmarkFromLabel diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml index a80ff78c40a..7077de4eaad 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -32,12 +32,16 @@ T.Popup { property T.Control myControl + property bool drag: slider.pressed + dim: false - closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent + closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent + | T.Popup.CloseOnEscape | T.Popup.CloseOnReleaseOutside + | T.Popup.CloseOnReleaseOutsideParent background: Rectangle { - color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themePopupBackground + border.width: 0 } contentItem: T.Slider { @@ -61,7 +65,8 @@ T.Popup { width: StudioTheme.Values.sliderHandleWidth height: StudioTheme.Values.sliderHandleHeight radius: 0 - color: slider.pressed ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline + color: slider.pressed ? StudioTheme.Values.themeSliderHandleInteraction + : StudioTheme.Values.themeSliderHandle } background: Rectangle { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml index 60d35ac51f5..673515fdedd 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -40,35 +40,35 @@ T.SpinBox { property real maxStepSize: 10 property bool edit: spinBoxInput.activeFocus - property bool hover: false // This property is used to indicate the global hover state + // This property is used to indicate the global hover state + property bool hover: mySpinBox.hovered || actionIndicator.hover property bool drag: false + property bool sliderDrag: sliderPopup.drag property alias actionIndicatorVisible: actionIndicator.visible - property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth - property real __actionIndicatorHeight: StudioTheme.Values.height + property real __actionIndicatorWidth: StudioTheme.Values.actionIndicatorWidth + property real __actionIndicatorHeight: StudioTheme.Values.actionIndicatorHeight 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 real __spinBoxIndicatorWidth: StudioTheme.Values.spinBoxIndicatorWidth + property real __spinBoxIndicatorHeight: StudioTheme.Values.spinBoxIndicatorHeight property alias sliderIndicatorVisible: sliderIndicator.visible - property real __sliderIndicatorWidth: StudioTheme.Values.squareComponentWidth - property real __sliderIndicatorHeight: StudioTheme.Values.height + property real __sliderIndicatorWidth: StudioTheme.Values.sliderIndicatorWidth + property real __sliderIndicatorHeight: StudioTheme.Values.sliderIndicatorHeight signal compressedValueModified // Use custom wheel handling due to bugs property bool __wheelEnabled: false wheelEnabled: false + hoverEnabled: true // TODO - width: StudioTheme.Values.squareComponentWidth * 5 - height: StudioTheme.Values.height + width: StudioTheme.Values.defaultControlWidth + height: StudioTheme.Values.defaultControlHeight leftPadding: spinBoxIndicatorDown.x + spinBoxIndicatorDown.width - - (spinBoxIndicatorVisible ? 0 : StudioTheme.Values.border) - rightPadding: sliderIndicator.width - (sliderIndicatorVisible ? StudioTheme.Values.border : 0) + rightPadding: sliderIndicator.width + StudioTheme.Values.border font.pixelSize: StudioTheme.Values.myFontSize editable: true @@ -93,44 +93,41 @@ T.SpinBox { ActionIndicator { id: actionIndicator myControl: mySpinBox - x: 0 y: 0 - width: actionIndicator.visible ? __actionIndicatorWidth : 0 - height: actionIndicator.visible ? __actionIndicatorHeight : 0 + width: actionIndicator.visible ? mySpinBox.__actionIndicatorWidth : 0 + height: actionIndicator.visible ? mySpinBox.__actionIndicatorHeight : 0 } up.indicator: SpinBoxIndicator { id: spinBoxIndicatorUp myControl: mySpinBox - - visible: spinBoxIndicatorVisible + iconFlip: -1 + visible: mySpinBox.spinBoxIndicatorVisible //hover: mySpinBox.up.hovered // TODO QTBUG-74688 pressed: mySpinBox.up.pressed - iconFlip: -1 - - x: actionIndicator.width + (actionIndicatorVisible ? 0 : StudioTheme.Values.border) + x: actionIndicator.width + StudioTheme.Values.border y: StudioTheme.Values.border - width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0 - height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0 + width: spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorWidth : 0 + height: spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorHeight : 0 - enabled: (mySpinBox.from < mySpinBox.to) ? mySpinBox.value < mySpinBox.to : mySpinBox.value > mySpinBox.to + enabled: (mySpinBox.from < mySpinBox.to) ? mySpinBox.value < mySpinBox.to + : mySpinBox.value > mySpinBox.to } down.indicator: SpinBoxIndicator { id: spinBoxIndicatorDown myControl: mySpinBox - - visible: spinBoxIndicatorVisible + visible: mySpinBox.spinBoxIndicatorVisible //hover: mySpinBox.down.hovered // TODO QTBUG-74688 pressed: mySpinBox.down.pressed - - x: actionIndicator.width + (actionIndicatorVisible ? 0 : StudioTheme.Values.border) + x: actionIndicator.width + StudioTheme.Values.border y: spinBoxIndicatorUp.y + spinBoxIndicatorUp.height - width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0 - height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0 + width: spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorWidth : 0 + height: spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorHeight : 0 - enabled: (mySpinBox.from < mySpinBox.to) ? mySpinBox.value > mySpinBox.from : mySpinBox.value < mySpinBox.from + enabled: (mySpinBox.from < mySpinBox.to) ? mySpinBox.value > mySpinBox.from + : mySpinBox.value < mySpinBox.from } contentItem: SpinBoxInput { @@ -143,7 +140,7 @@ T.SpinBox { color: StudioTheme.Values.themeControlOutline border.color: StudioTheme.Values.themeControlOutline border.width: StudioTheme.Values.border - x: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + x: actionIndicator.width width: mySpinBox.width - actionIndicator.width height: mySpinBox.height } @@ -152,20 +149,19 @@ T.SpinBox { id: sliderIndicator myControl: mySpinBox myPopup: sliderPopup - - x: spinBoxInput.x + spinBoxInput.width - StudioTheme.Values.border - width: sliderIndicator.visible ? __sliderIndicatorWidth : 0 - height: sliderIndicator.visible ? __sliderIndicatorHeight : 0 + x: spinBoxInput.x + spinBoxInput.width + y: StudioTheme.Values.border + width: sliderIndicator.visible ? mySpinBox.__sliderIndicatorWidth - StudioTheme.Values.border : 0 + height: sliderIndicator.visible ? mySpinBox.__sliderIndicatorHeight - (StudioTheme.Values.border * 2) : 0 visible: false // reasonable default } SliderPopup { id: sliderPopup myControl: mySpinBox - - x: spinBoxInput.x - y: StudioTheme.Values.height - StudioTheme.Values.border - width: spinBoxInput.width + sliderIndicator.width - StudioTheme.Values.border + x: actionIndicator.width + StudioTheme.Values.border + y: StudioTheme.Values.height + width: mySpinBox.width - actionIndicator.width - (StudioTheme.Values.border * 2) height: StudioTheme.Values.sliderHeight enter: Transition { @@ -175,6 +171,7 @@ T.SpinBox { } textFromValue: function (value, locale) { + locale.numberOptions = Locale.OmitGroupSeparator return Number(value / mySpinBox.factor).toLocaleString(locale, 'f', mySpinBox.decimals) } @@ -186,8 +183,8 @@ T.SpinBox { states: [ State { name: "default" - when: mySpinBox.enabled && !mySpinBox.hover - && !mySpinBox.edit && !mySpinBox.drag + when: mySpinBox.enabled && !mySpinBox.hover && !mySpinBox.hovered + && !mySpinBox.edit && !mySpinBox.drag && !mySpinBox.sliderDrag PropertyChanges { target: mySpinBox __wheelEnabled: false @@ -198,7 +195,7 @@ T.SpinBox { } PropertyChanges { target: spinBoxBackground - color: StudioTheme.Values.themeControlOutline + color: StudioTheme.Values.themeControlBackground border.color: StudioTheme.Values.themeControlOutline } }, @@ -215,21 +212,21 @@ T.SpinBox { } PropertyChanges { target: spinBoxBackground - color: StudioTheme.Values.themeInteraction - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackgroundInteraction + border.color: StudioTheme.Values.themeControlOutline } }, State { name: "drag" - when: mySpinBox.drag + when: mySpinBox.drag || mySpinBox.sliderDrag PropertyChanges { target: spinBoxBackground - color: StudioTheme.Values.themeInteraction - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackgroundInteraction + border.color: StudioTheme.Values.themeControlOutlineInteraction } }, State { - name: "disabled" + name: "disable" when: !mySpinBox.enabled PropertyChanges { target: spinBoxBackground diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml index 3f272860e9c..e65fe117a68 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -32,8 +32,8 @@ Rectangle { property T.Control myControl - property bool hover: false - property bool pressed: false + property bool hover: spinBoxIndicatorMouseArea.containsMouse + property bool pressed: spinBoxIndicatorMouseArea.containsPress property alias iconFlip: spinBoxIndicatorIconScale.yScale @@ -46,9 +46,10 @@ Rectangle { id: spinBoxIndicatorMouseArea anchors.fill: parent hoverEnabled: true - onContainsMouseChanged: spinBoxIndicator.hover = containsMouse onPressed: { - myControl.forceActiveFocus() + if (myControl.activeFocus) + spinBoxIndicator.forceActiveFocus() + mouse.accepted = false } } @@ -69,64 +70,153 @@ Rectangle { origin.y: spinBoxIndicatorIcon.height / 2 yScale: 1 } + + states: [ + State { + name: "globalHover" + when: myControl.enabled && spinBoxIndicator.enabled && !myControl.drag + && !spinBoxIndicator.hover && myControl.hover && !myControl.edit + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeTextColor + } + }, + State { + name: "hover" + when: myControl.enabled && spinBoxIndicator.enabled && !myControl.drag + && spinBoxIndicator.hover && myControl.hover && !spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeIconColorHover + } + }, + State { + name: "press" + when: myControl.enabled && spinBoxIndicator.enabled && !myControl.drag + && spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicatorIcon + color: "#323232" // TODO + } + }, + State { + name: "edit" + when: myControl.edit + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeTextColor + } + }, + State { + name: "disable" + when: !myControl.enabled || !spinBoxIndicator.enabled + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] } states: [ State { name: "default" - when: myControl.enabled && !(spinBoxIndicator.hover - || myControl.hover) - && !spinBoxIndicator.pressed && !myControl.edit - && !myControl.drag && spinBoxIndicator.enabled + when: myControl.enabled && !myControl.edit + && !spinBoxIndicator.hover && !myControl.hover && !myControl.drag + PropertyChanges { + target: spinBoxIndicatorIcon + visible: false + } PropertyChanges { target: spinBoxIndicator color: StudioTheme.Values.themeControlBackground } }, State { - name: "hovered" - when: (spinBoxIndicator.hover || myControl.hover) - && !spinBoxIndicator.pressed && !myControl.edit - && !myControl.drag && spinBoxIndicator.enabled + name: "globalHover" + when: myControl.enabled && spinBoxIndicator.enabled && !myControl.drag + && !spinBoxIndicator.hover && myControl.hover && !myControl.edit + PropertyChanges { + target: spinBoxIndicatorIcon + visible: true + } PropertyChanges { target: spinBoxIndicator - color: StudioTheme.Values.themeHoverHighlight + color: StudioTheme.Values.themeControlBackgroundGlobalHover } }, State { - name: "pressed" - when: spinBoxIndicator.pressed && spinBoxIndicator.enabled + name: "hover" + when: myControl.enabled && !myControl.drag + && spinBoxIndicator.hover && myControl.hover && !spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicatorIcon + visible: true + } PropertyChanges { target: spinBoxIndicator - color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackgroundHover + } + }, + State { + name: "press" + when: myControl.enabled && spinBoxIndicator.enabled && !myControl.drag + && spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicatorIcon + visible: true + } + PropertyChanges { + target: spinBoxIndicator + color: "#2aafd3" // TODO } }, State { name: "edit" - when: myControl.edit && spinBoxIndicator.enabled + when: myControl.edit + PropertyChanges { + target: spinBoxIndicatorIcon + visible: true + } PropertyChanges { target: spinBoxIndicator - color: StudioTheme.Values.themeFocusEdit + color: StudioTheme.Values.themeControlBackground } }, State { name: "drag" - when: myControl.drag && spinBoxIndicator.enabled + when: myControl.drag + PropertyChanges { + target: spinBoxIndicatorIcon + visible: false + } PropertyChanges { target: spinBoxIndicator - color: StudioTheme.Values.themeFocusDrag + color: StudioTheme.Values.themeControlBackgroundInteraction } }, State { - name: "disabled" - when: !myControl.enabled || !spinBoxIndicator.enabled - PropertyChanges { - target: spinBoxIndicator - color: StudioTheme.Values.themeControlBackgroundDisabled - } + name: "disable" + when: !myControl.enabled PropertyChanges { target: spinBoxIndicatorIcon - color: StudioTheme.Values.themeTextColorDisabled + visible: false + } + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackground + } + }, + State { + name: "limit" + when: !spinBoxIndicator.enabled && !spinBoxIndicator.realEnabled && myControl.hover + PropertyChanges { + target: spinBoxIndicatorIcon + visible: true + } + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackground } } ] diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml index 50b4a068aa8..9776f407215 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -34,6 +34,7 @@ TextInput { property bool edit: textInput.activeFocus property bool drag: false + property bool hover: mouseArea.containsMouse z: 2 font: myControl.font @@ -59,17 +60,14 @@ TextInput { onActiveFocusChanged: textInput.focus = activeFocus Rectangle { - id: textInputArea - - color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeControlOutline - border.width: StudioTheme.Values.border - + id: textInputBackground x: 0 - y: 0 + y: StudioTheme.Values.border z: -1 width: textInput.width - height: StudioTheme.Values.height + height: StudioTheme.Values.height - (StudioTheme.Values.border * 2) + color: StudioTheme.Values.themeControlBackground + border.width: 0 } DragHandler { @@ -117,8 +115,6 @@ TextInput { propagateComposedEvents: true acceptedButtons: Qt.LeftButton cursorShape: Qt.PointingHandCursor - // Sets the global hover - onContainsMouseChanged: myControl.hover = containsMouse onPressed: mouse.accepted = false onWheel: { if (!myControl.__wheelEnabled) @@ -139,12 +135,11 @@ TextInput { states: [ State { name: "default" - when: myControl.enabled && !textInput.edit - && !mouseArea.containsMouse && !myControl.drag + when: myControl.enabled && !textInput.edit && !textInput.hover && !myControl.hover + && !myControl.drag && !myControl.sliderDrag PropertyChanges { - target: textInputArea + target: textInputBackground color: StudioTheme.Values.themeControlBackground - border.color: StudioTheme.Values.themeControlOutline } PropertyChanges { target: dragHandler @@ -160,21 +155,28 @@ TextInput { } }, State { - name: "hovered" - when: myControl.hover && !textInput.edit && !myControl.drag + name: "globalHover" + when: myControl.hover && !textInput.hover && !textInput.edit && !myControl.drag PropertyChanges { - target: textInputArea - color: StudioTheme.Values.themeHoverHighlight - border.color: StudioTheme.Values.themeControlOutline + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundGlobalHover + } + }, + State { + name: "hover" + when: textInput.hover && myControl.hover + && !textInput.edit && !myControl.drag + PropertyChanges { + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundHover } }, State { name: "edit" - when: textInput.edit + when: textInput.edit && !myControl.drag PropertyChanges { - target: textInputArea - color: StudioTheme.Values.themeFocusEdit - border.color: StudioTheme.Values.themeInteraction + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundInteraction } PropertyChanges { target: dragHandler @@ -193,18 +195,32 @@ TextInput { name: "drag" when: myControl.drag PropertyChanges { - target: textInputArea - color: StudioTheme.Values.themeFocusDrag - border.color: StudioTheme.Values.themeInteraction + target: textInputBackground + color: StudioTheme.Values.themeControlBackgroundInteraction + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeInteraction } }, State { - name: "disabled" + name: "sliderDrag" + when: myControl.sliderDrag + PropertyChanges { + target: textInputBackground + color: StudioTheme.Values.themeControlBackground + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disable" when: !myControl.enabled PropertyChanges { - target: textInputArea + target: textInputBackground color: StudioTheme.Values.themeControlBackgroundDisabled - border.color: StudioTheme.Values.themeControlOutlineDisabled } PropertyChanges { target: textInput diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TabBar.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TabBar.qml index 1b71f1f4dea..c8a55ca74d4 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TabBar.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TabBar.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -36,7 +36,7 @@ T.TabBar { implicitContentHeight + topPadding + bottomPadding) spacing: 0 - bottomPadding: 4 + bottomPadding: 2 contentItem: ListView { model: myButton.contentModel @@ -50,6 +50,6 @@ T.TabBar { } background: Rectangle { - color: StudioTheme.Values.themeTabLight + color: StudioTheme.Values.themeTabActiveBackground } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TabButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TabButton.qml index 3b8efdfe55a..9e73544cbc7 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TabButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TabButton.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -39,14 +39,15 @@ T.TabButton { background: Rectangle { id: buttonBackground - color: myButton.checked ? StudioTheme.Values.themeTabLight : StudioTheme.Values.themeTabDark - border.color: StudioTheme.Values.themeControlOutline + color: myButton.checked ? StudioTheme.Values.themeTabActiveBackground + : StudioTheme.Values.themeTabInactiveBackground border.width: 0 } contentItem: T.Label { id: buttonIcon - color: myButton.checked ? StudioTheme.Values.themeTabDark : StudioTheme.Values.themeTabLight + color: myButton.checked ? StudioTheme.Values.themeTabActiveText + : StudioTheme.Values.themeTabInactiveText font.weight: Font.Bold //font.family: StudioTheme.Constants.font.family font.pixelSize: StudioTheme.Values.myFontSize diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml index 6aaa71c7e85..ec155136b04 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -43,7 +43,7 @@ TextField { width: myTextField.popupWidth height: scrollView.height background: Rectangle { - color: StudioTheme.Values.themeFocusEdit + color: StudioTheme.Values.themePopupBackground border.color: StudioTheme.Values.themeInteraction border.width: StudioTheme.Values.border } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml index 5faa7cbd128..5351514731b 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -33,16 +33,18 @@ T.TextField { property alias actionIndicator: actionIndicator property alias translationIndicator: translationIndicator + // This property is used to indicate the global hover state + property bool hover: actionIndicator.hover || mouseArea.containsMouse + || translationIndicator.hover property bool edit: myTextField.activeFocus - 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 real __actionIndicatorWidth: StudioTheme.Values.actionIndicatorWidth + property real __actionIndicatorHeight: StudioTheme.Values.actionIndicatorHeight property alias translationIndicatorVisible: translationIndicator.visible - property real __translationIndicatorWidth: StudioTheme.Values.squareComponentWidth - property real __translationIndicatorHeight: StudioTheme.Values.height + property real __translationIndicatorWidth: StudioTheme.Values.translationIndicatorWidth + property real __translationIndicatorHeight: StudioTheme.Values.translationIndicatorHeight horizontalAlignment: Qt.AlignLeft verticalAlignment: Qt.AlignVCenter @@ -58,14 +60,12 @@ T.TextField { persistentSelection: focus // QTBUG-73807 clip: true - width: StudioTheme.Values.height * 5 - height: StudioTheme.Values.height - implicitHeight: StudioTheme.Values.height + width: StudioTheme.Values.defaultControlWidth + height: StudioTheme.Values.defaultControlHeight + implicitHeight: StudioTheme.Values.defaultControlHeight leftPadding: StudioTheme.Values.inputHorizontalPadding + actionIndicator.width - - (actionIndicatorVisible ? StudioTheme.Values.border : 0) rightPadding: StudioTheme.Values.inputHorizontalPadding + translationIndicator.width - - (translationIndicatorVisible ? StudioTheme.Values.border : 0) MouseArea { id: mouseArea @@ -75,7 +75,6 @@ T.TextField { 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) @@ -104,8 +103,8 @@ T.TextField { myControl: myTextField x: 0 y: 0 - width: actionIndicator.visible ? __actionIndicatorWidth : 0 - height: actionIndicator.visible ? __actionIndicatorHeight : 0 + width: actionIndicator.visible ? myTextField.__actionIndicatorWidth : 0 + height: actionIndicator.visible ? myTextField.__actionIndicatorHeight : 0 } background: Rectangle { @@ -113,7 +112,7 @@ T.TextField { color: StudioTheme.Values.themeControlBackground border.color: StudioTheme.Values.themeControlOutline border.width: StudioTheme.Values.border - x: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + x: actionIndicator.width width: myTextField.width - actionIndicator.width height: myTextField.height } @@ -136,27 +135,53 @@ T.TextField { color: StudioTheme.Values.themeControlBackground border.color: StudioTheme.Values.themeControlOutline } + PropertyChanges { + target: myTextField + color: StudioTheme.Values.themeTextColor + } PropertyChanges { target: mouseArea cursorShape: Qt.PointingHandCursor } }, State { - name: "hovered" - when: myTextField.hover && !myTextField.edit + name: "globalHover" + when: (actionIndicator.hover || translationIndicator.hover) && !myTextField.edit PropertyChanges { target: textFieldBackground - color: StudioTheme.Values.themeHoverHighlight + color: StudioTheme.Values.themeControlBackgroundGlobalHover border.color: StudioTheme.Values.themeControlOutline } + PropertyChanges { + target: myTextField + color: StudioTheme.Values.themeTextColor + } + }, + State { + name: "hover" + when: mouseArea.containsMouse && !actionIndicator.hover && !translationIndicator.hover + && !myTextField.edit + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeControlBackgroundHover + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: myTextField + color: StudioTheme.Values.themeTextColor + } }, State { name: "edit" when: myTextField.edit PropertyChanges { target: textFieldBackground - color: StudioTheme.Values.themeFocusEdit - border.color: StudioTheme.Values.themeInteraction + color: StudioTheme.Values.themeControlBackgroundInteraction + border.color: StudioTheme.Values.themeControlOutlineInteraction + } + PropertyChanges { + target: myTextField + color: StudioTheme.Values.themeTextColor } PropertyChanges { target: mouseArea @@ -164,13 +189,17 @@ T.TextField { } }, State { - name: "disabled" + name: "disable" when: !myTextField.enabled PropertyChanges { target: textFieldBackground color: StudioTheme.Values.themeControlBackgroundDisabled border.color: StudioTheme.Values.themeControlOutlineDisabled } + PropertyChanges { + target: myTextField + color: StudioTheme.Values.themeTextColorDisabled + } } ] diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml index 7c4e0c90cec..6c20f933d02 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -32,35 +32,29 @@ Item { property Item myControl - property bool hover: false - property bool pressed: false + property bool hover: translationIndicatorMouseArea.containsMouse + property bool pressed: translationIndicatorMouseArea.pressed property bool checked: false signal clicked - state: "default" - Rectangle { id: translationIndicatorBackground - color: StudioTheme.Values.themeColumnBackground // TODO create extra variable, this one is used - border.color: StudioTheme.Values.themeTranslationIndicatorBorder + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border anchors.centerIn: parent - width: matchParity(translationIndicator.height, - StudioTheme.Values.smallRectWidth) - height: matchParity(translationIndicator.height, - StudioTheme.Values.smallRectWidth) + 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 } @@ -68,7 +62,6 @@ Item { id: translationIndicatorMouseArea anchors.fill: parent hoverEnabled: true - onContainsMouseChanged: translationIndicator.hover = containsMouse onPressed: mouse.accepted = true // TODO onClicked: { translationIndicator.checked = !translationIndicator.checked @@ -87,6 +80,43 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter anchors.fill: parent + + states: [ + State { + name: "default" + when: translationIndicator.enabled && !translationIndicator.pressed + && !translationIndicator.checked + PropertyChanges { + target: translationIndicatorIcon + color: StudioTheme.Values.themeIconColor + } + }, + State { + name: "press" + when: translationIndicator.enabled && translationIndicator.pressed + PropertyChanges { + target: translationIndicatorIcon + color: StudioTheme.Values.themeIconColorInteraction + } + }, + State { + name: "check" + when: translationIndicator.enabled && !translationIndicator.pressed + && translationIndicator.checked + PropertyChanges { + target: translationIndicatorIcon + color: StudioTheme.Values.themeIconColorSelected + } + }, + State { + name: "disable" + when: !myControl.enabled + PropertyChanges { + target: translationIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] } states: [ @@ -94,44 +124,48 @@ Item { name: "default" when: myControl.enabled && !translationIndicator.hover && !translationIndicator.pressed && !myControl.hover - && !myControl.edit && !myControl.drag - && !translationIndicator.checked + && !myControl.edit && !translationIndicator.checked PropertyChanges { target: translationIndicatorBackground - color: StudioTheme.Values.themeColumnBackground - border.color: StudioTheme.Values.themeTranslationIndicatorBorder + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline } }, State { - name: "checked" - when: translationIndicator.checked - + name: "globalHover" + when: myControl.hover && !translationIndicator.hover PropertyChanges { target: translationIndicatorBackground - color: StudioTheme.Values.themeInteraction // TODO + color: StudioTheme.Values.themeControlBackgroundGlobalHover + border.color: StudioTheme.Values.themeControlOutline } }, State { - name: "hovered" + name: "hover" when: translationIndicator.hover && !translationIndicator.pressed - && !myControl.edit && !myControl.drag && !myControl.drag PropertyChanges { target: translationIndicatorBackground - color: StudioTheme.Values.themeFocusDrag // TODO + color: StudioTheme.Values.themeControlBackgroundHover + border.color: StudioTheme.Values.themeControlOutline } }, State { - name: "disabled" + name: "press" + when: translationIndicator.hover && translationIndicator.pressed + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeControlBackgroundInteraction + border.color: StudioTheme.Values.themeControlOutlineInteraction + } + }, + State { + name: "disable" 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 index 75cf4f0cfad..e59dd1f3d79 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir @@ -12,6 +12,7 @@ ExpandingSpacer 1.0 ExpandingSpacer.qml ItemDelegate 1.0 ItemDelegate.qml Menu 1.0 Menu.qml MenuItem 1.0 MenuItem.qml +MenuItemWithIcon 1.0 MenuItemWithIcon.qml MenuSeparator 1.0 MenuSeparator.qml RealSliderPopup 1.0 RealSliderPopup.qml RealSpinBox 1.0 RealSpinBox.qml diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml index 74edf9ccee8..87e33a93a27 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml index 09aedf94008..54bbe343623 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -48,94 +48,101 @@ QtObject { readonly property string adsClose: "\u0029" readonly property string adsDetach: "\u002A" readonly property string adsDropDown: "\u002B" - readonly property string aliasAnimated: "\u002C" - readonly property string aliasProperty: "\u002D" - readonly property string alignBottom: "\u002E" - readonly property string alignCenterHorizontal: "\u002F" - readonly property string alignCenterVertical: "\u0030" - readonly property string alignLeft: "\u0031" - readonly property string alignRight: "\u0032" - readonly property string alignTo: "\u0033" - readonly property string alignTop: "\u0034" - readonly property string anchorBaseline: "\u0035" - readonly property string anchorBottom: "\u0036" - readonly property string anchorFill: "\u0037" - readonly property string anchorLeft: "\u0038" - readonly property string anchorRight: "\u0039" - readonly property string anchorTop: "\u003A" - readonly property string animatedProperty: "\u003B" - readonly property string annotationBubble: "\u003C" - readonly property string annotationDecal: "\u003D" - readonly property string assign: "\u003E" - readonly property string centerHorizontal: "\u003F" - readonly property string centerVertical: "\u0040" - readonly property string closeCross: "\u0041" - readonly property string curveDesigner: "\u0042" - readonly property string curveEditor: "\u0043" - readonly property string decisionNode: "\u0044" - readonly property string deleteColumn: "\u0045" - readonly property string deleteRow: "\u0046" - readonly property string deleteTable: "\u0047" - readonly property string detach: "\u0048" - readonly property string distributeBottom: "\u0049" - readonly property string distributeCenterHorizontal: "\u004A" - readonly property string distributeCenterVertical: "\u004B" - readonly property string distributeLeft: "\u004C" - readonly property string distributeOriginBottomRight: "\u004D" - readonly property string distributeOriginCenter: "\u004E" - readonly property string distributeOriginNone: "\u004F" - readonly property string distributeOriginTopLeft: "\u0050" - readonly property string distributeRight: "\u0051" - readonly property string distributeSpacingHorizontal: "\u0052" - readonly property string distributeSpacingVertical: "\u0053" - readonly property string distributeTop: "\u0054" - readonly property string edit: "\u0055" - readonly property string flowAction: "\u0056" - readonly property string flowTransition: "\u0057" - readonly property string fontStyleBold: "\u0058" - readonly property string fontStyleItalic: "\u0059" - readonly property string fontStyleStrikethrough: "\u005A" - readonly property string fontStyleUnderline: "\u005B" - readonly property string gridView: "\u005C" - readonly property string idAliasOff: "\u005D" - readonly property string idAliasOn: "\u005E" - readonly property string listView: "\u005F" - readonly property string lockOff: "\u0060" - readonly property string lockOn: "\u0061" - readonly property string mergeCells: "\u0062" - readonly property string minus: "\u0063" - readonly property string pin: "\u0064" - readonly property string plus: "\u0065" - readonly property string redo: "\u0066" - readonly property string rotationFill: "\u0067" - readonly property string rotationOutline: "\u0068" - readonly property string search: "\u0069" - readonly property string splitColumns: "\u006A" - readonly property string splitRows: "\u006B" - readonly property string startNode: "\u006C" - readonly property string testIcon: "\u006D" - readonly property string textAlignBottom: "\u006E" - readonly property string textAlignCenter: "\u006F" - readonly property string textAlignLeft: "\u0070" - readonly property string textAlignMiddle: "\u0071" - readonly property string textAlignRight: "\u0072" - readonly property string textAlignTop: "\u0073" - readonly property string textBulletList: "\u0074" - readonly property string textFullJustification: "\u0075" - readonly property string textNumberedList: "\u0076" - readonly property string tickIcon: "\u0077" - readonly property string triState: "\u0078" - readonly property string undo: "\u0079" - readonly property string unpin: "\u007A" - readonly property string upDownIcon: "\u007B" - readonly property string upDownSquare2: "\u007C" - readonly property string visibilityOff: "\u007D" - readonly property string visibilityOn: "\u007E" - readonly property string wildcard: "\u007F" - readonly property string zoomAll: "\u0080" - readonly property string zoomIn: "\u0081" - readonly property string zoomOut: "\u0082" - readonly property string zoomSelection: "\u0083" + readonly property string alias: "\u002C" + readonly property string aliasAnimated: "\u002D" + readonly property string aliasProperty: "\u002E" + readonly property string alignBottom: "\u002F" + readonly property string alignCenterHorizontal: "\u0030" + readonly property string alignCenterVertical: "\u0031" + readonly property string alignLeft: "\u0032" + readonly property string alignRight: "\u0033" + readonly property string alignTo: "\u0034" + readonly property string alignTop: "\u0035" + readonly property string anchorBaseline: "\u0036" + readonly property string anchorBottom: "\u0037" + readonly property string anchorFill: "\u0038" + readonly property string anchorLeft: "\u0039" + readonly property string anchorRight: "\u003A" + readonly property string anchorTop: "\u003B" + readonly property string animatedProperty: "\u003C" + readonly property string annotationBubble: "\u003D" + readonly property string annotationDecal: "\u003E" + readonly property string assign: "\u003F" + readonly property string centerHorizontal: "\u0040" + readonly property string centerVertical: "\u0041" + readonly property string closeCross: "\u0042" + readonly property string curveDesigner: "\u0043" + readonly property string curveEditor: "\u0044" + readonly property string decisionNode: "\u0045" + readonly property string deleteColumn: "\u0046" + readonly property string deleteRow: "\u0047" + readonly property string deleteTable: "\u0048" + readonly property string detach: "\u0049" + readonly property string distributeBottom: "\u004A" + readonly property string distributeCenterHorizontal: "\u004B" + readonly property string distributeCenterVertical: "\u004C" + readonly property string distributeLeft: "\u004D" + readonly property string distributeOriginBottomRight: "\u004E" + readonly property string distributeOriginCenter: "\u004F" + readonly property string distributeOriginNone: "\u0050" + readonly property string distributeOriginTopLeft: "\u0051" + readonly property string distributeRight: "\u0052" + readonly property string distributeSpacingHorizontal: "\u0053" + readonly property string distributeSpacingVertical: "\u0054" + readonly property string distributeTop: "\u0055" + readonly property string edit: "\u0056" + readonly property string flowAction: "\u0057" + readonly property string flowTransition: "\u0058" + readonly property string fontStyleBold: "\u0059" + readonly property string fontStyleItalic: "\u005A" + readonly property string fontStyleStrikethrough: "\u005B" + readonly property string fontStyleUnderline: "\u005C" + readonly property string gridView: "\u005D" + readonly property string idAliasOff: "\u005E" + readonly property string idAliasOn: "\u005F" + readonly property string keyframe: "\u0060" + readonly property string linkTriangle: "\u0061" + readonly property string linked: "\u0062" + readonly property string listView: "\u0063" + readonly property string lockOff: "\u0064" + readonly property string lockOn: "\u0065" + readonly property string mergeCells: "\u0066" + readonly property string minus: "\u0067" + readonly property string mirror: "\u0068" + readonly property string pin: "\u0069" + readonly property string plus: "\u006A" + readonly property string promote: "\u006B" + readonly property string redo: "\u006C" + readonly property string rotationFill: "\u006D" + readonly property string rotationOutline: "\u006E" + readonly property string search: "\u006F" + readonly property string splitColumns: "\u0070" + readonly property string splitRows: "\u0071" + readonly property string startNode: "\u0072" + readonly property string testIcon: "\u0073" + readonly property string textAlignBottom: "\u0074" + readonly property string textAlignCenter: "\u0075" + readonly property string textAlignLeft: "\u0076" + readonly property string textAlignMiddle: "\u0077" + readonly property string textAlignRight: "\u0078" + readonly property string textAlignTop: "\u0079" + readonly property string textBulletList: "\u007A" + readonly property string textFullJustification: "\u007B" + readonly property string textNumberedList: "\u007C" + readonly property string tickIcon: "\u007D" + readonly property string triState: "\u007E" + readonly property string unLinked: "\u007F" + readonly property string undo: "\u0080" + readonly property string unpin: "\u0081" + readonly property string upDownIcon: "\u0082" + readonly property string upDownSquare2: "\u0083" + readonly property string visibilityOff: "\u0084" + readonly property string visibilityOn: "\u0085" + readonly property string wildcard: "\u0086" + readonly property string zoomAll: "\u0087" + readonly property string zoomIn: "\u0088" + readonly property string zoomOut: "\u0089" + readonly property string zoomSelection: "\u008A" readonly property font iconFont: Qt.font({ "family": controlIcons.name, @@ -151,8 +158,4 @@ QtObject { "family": mySystemFont.name, "pointSize": Qt.application.font.pixelSize * 1.6 }) - - readonly property color backgroundColor: "#c2c2c2" - - readonly property bool showActionIndicatorBackground: false } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml index 3d504302a78..0ea1e18746c 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -30,11 +30,11 @@ import QtQuickDesignerTheme 1.0 QtObject { id: values - property real baseHeight: 20 + property real baseHeight: 29 property real baseFont: 12 - property real baseIconFont: 10 + property real baseIconFont: 12 - property real scaleFactor: 1.1 + property real scaleFactor: 1.0 property real height: Math.round(values.baseHeight * values.scaleFactor) property real myFontSize: Math.round(values.baseFont * values.scaleFactor) @@ -54,9 +54,9 @@ QtObject { property real spinControlIconSize: 8 property real spinControlIconSizeMulti: values.spinControlIconSize * values.scaleFactor - property real sliderTrackHeight: values.height / 4 - property real sliderHandleHeight: values.sliderTrackHeight * 2 - property real sliderHandleWidth: values.sliderTrackHeight + property real sliderTrackHeight: values.height / 3 + property real sliderHandleHeight: values.sliderTrackHeight * 1.8 + property real sliderHandleWidth: values.sliderTrackHeight * 0.5 property real sliderFontSize: Math.round(8 * values.scaleFactor) property real sliderPadding: Math.round(6 * values.scaleFactor) property real sliderMargin: Math.round(3 * values.scaleFactor) @@ -77,52 +77,126 @@ QtObject { property real contextMenuLabelSpacing: Math.round(30 * values.scaleFactor) property real contextMenuHorizontalPadding: Math.round(6 * values.scaleFactor) - property real inputHorizontalPadding: Math.round(4 * values.scaleFactor) + property real inputHorizontalPadding: Math.round(6 * values.scaleFactor) + property real typeLabelVerticalShift: Math.round(5 * values.scaleFactor) property real scrollBarThickness: 10 + property real toolTipHeight: 25 + property int toolTipDelay: 1000 + + // Layout sizes + property real sectionColumnSpacing: 30 // distance between label and sliderControlSize + property real sectionRowSpacing: 5 + property real sectionHeadGap: 15 + property real sectionHeadHeight: 21 // tab and section + property real sectionHeadSpacerHeight: 15 + + property real controlLabelWidth: 15 + property real controlLabelGap: 5 + property real controlGap: 5 // TODO different name + + + property real columnGap: 10 + + property real iconAreaWidth: Math.round(21 * values.scaleFactor) + + // Control sizes + + property real defaultControlWidth: values.squareComponentWidth * 5 + property real defaultControlHeight: values.height + + property real actionIndicatorWidth: values.iconAreaWidth //StudioTheme.Values.squareComponentWidth + property real actionIndicatorHeight: values.height + + property real spinBoxIndicatorWidth: values.smallRectWidth - 2 * values.border + property real spinBoxIndicatorHeight: values.height / 2 - values.border + + property real sliderIndicatorWidth: values.squareComponentWidth + property real sliderIndicatorHeight: values.height + + property real translationIndicatorWidth: values.squareComponentWidth + property real translationIndicatorHeight: values.height + + property real checkIndicatorWidth: values.squareComponentWidth + property real checkIndicatorHeight: values.height + // Theme Colors - // COLORS NOW COME FROM THE THEME FILES - property string themeControlBackground: Theme.color(Theme.DScontrolBackground) - property string themeControlOutline: Theme.color(Theme.DScontrolOutline) - property string themeTextColor: Theme.color(Theme.DStextColor) - property string themeDisabledTextColor: Theme.color(Theme.DSdisabledTextColor) property string themePanelBackground: Theme.color(Theme.DSpanelBackground) - property string themeHoverHighlight: Theme.color(Theme.DShoverHighlight) - property string themeColumnBackground: Theme.color(Theme.DScolumnBackground) - property string themeFocusEdit: Theme.color(Theme.DSfocusEdit) - property string themeFocusDrag: Theme.color(Theme.DSfocusDrag) - property string themeControlBackgroundPressed: Theme.color(Theme.DScontrolBackgroundPressed) - property string themeControlBackgroundChecked: Theme.color(Theme.DScontrolBackgroundChecked) - property string themeInteraction: Theme.color(Theme.DSinteraction) - property string themeSliderActiveTrack: Theme.color(Theme.DSsliderActiveTrack) - property string themeSliderInactiveTrack: Theme.color(Theme.DSsliderInactiveTrack) - property string themeSliderHandle: Theme.color(Theme.DSsliderHandle) - property string themeSliderActiveTrackHover: Theme.color(Theme.DSactiveTrackHover) - property string themeSliderInactiveTrackHover: Theme.color(Theme.DSsliderInactiveTrackHover) - property string themeSliderHandleHover: Theme.color(Theme.DSsliderHandleHover) - property string themeSliderActiveTrackFocus: Theme.color(Theme.DSsliderActiveTrackFocus) - property string themeSliderInactiveTrackFocus:Theme.color(Theme.DSsliderInactiveTrackFocus) - property string themeSliderHandleFocus: Theme.color(Theme.DSsliderHandleFocus) - property string themeErrorColor: Theme.color(Theme.DSerrorColor) - // NEW NEW NEW NEW NEW + property string themeInteraction: Theme.color(Theme.DSinteraction) + property string themeError: Theme.color(Theme.DSerrorColor) + property string themeDisabled: Theme.color(Theme.DSdisabledColor) + + // Control colors + property string themeControlBackground: Theme.color(Theme.DScontrolBackground) + property string themeControlBackgroundInteraction: Theme.color(Theme.DScontrolBackgroundInteraction) property string themeControlBackgroundDisabled: Theme.color(Theme.DScontrolBackgroundDisabled) + property string themeControlBackgroundGlobalHover: Theme.color(Theme.DScontrolBackgroundGlobalHover) + property string themeControlBackgroundHover: Theme.color(Theme.DScontrolBackgroundHover) + + property string themeControlOutline: Theme.color(Theme.DScontrolOutline) + property string themeControlOutlineInteraction: Theme.color(Theme.DScontrolOutlineInteraction) property string themeControlOutlineDisabled: Theme.color(Theme.DScontrolOutlineDisabled) + + // Text colors + property string themeTextColor: Theme.color(Theme.DStextColor) property string themeTextColorDisabled: Theme.color(Theme.DStextColorDisabled) property string themeTextSelectionColor: Theme.color(Theme.DStextSelectionColor) - property string themeTextSelectedTextColor:Theme.color(Theme.DStextSelectedTextColor) + property string themeTextSelectedTextColor: Theme.color(Theme.DStextSelectedTextColor) + + property string themePlaceholderTextColor: Theme.color(Theme.DSplaceholderTextColor) + property string themePlaceholderTextColorInteraction: Theme.color(Theme.DSplaceholderTextColorInteraction) + + // Icon colors + property string themeIconColor: Theme.color(Theme.DSiconColor) + property string themeIconColorHover: Theme.color(Theme.DSiconColorHover) + property string themeIconColorInteraction: Theme.color(Theme.DSiconColorInteraction) + property string themeIconColorDisabled: Theme.color(Theme.DSiconColorDisabled) + property string themeIconColorSelected: Theme.color(Theme.DSiconColorSelected) + + property string themeLinkIndicatorColor: Theme.color(Theme.DSlinkIndicatorColor) + property string themeLinkIndicatorColorHover: Theme.color(Theme.DSlinkIndicatorColorHover) + property string themeLinkIndicatorColorInteraction: Theme.color(Theme.DSlinkIndicatorColorInteraction) + property string themeLinkIndicatorColorDisabled: Theme.color(Theme.DSlinkIndicatorColorDisabled) + + // Popup background color (ComboBox, SpinBox, TextArea) + property string themePopupBackground: Theme.color(Theme.DSpopupBackground) + // GradientPopupDialog modal overly color + property string themePopupOverlayColor: Theme.color(Theme.DSpopupOverlayColor) + + // ToolTip (UrlChooser) + property string themeToolTipBackground: Theme.color(Theme.DStoolTipBackground) + property string themeToolTipOutline: Theme.color(Theme.DStoolTipOutline) + property string themeToolTipText: Theme.color(Theme.DStoolTipText) + + // Slider colors + property string themeSliderActiveTrack: Theme.color(Theme.DSsliderActiveTrack) + property string themeSliderActiveTrackHover: Theme.color(Theme.DSactiveTrackHover) + property string themeSliderActiveTrackFocus: Theme.color(Theme.DSsliderActiveTrackFocus) + property string themeSliderInactiveTrack: Theme.color(Theme.DSsliderInactiveTrack) + property string themeSliderInactiveTrackHover: Theme.color(Theme.DSsliderInactiveTrackHover) + property string themeSliderInactiveTrackFocus: Theme.color(Theme.DSsliderInactiveTrackFocus) + property string themeSliderHandle: Theme.color(Theme.DSsliderHandle) + property string themeSliderHandleHover: Theme.color(Theme.DSsliderHandleHover) + property string themeSliderHandleFocus: Theme.color(Theme.DSsliderHandleFocus) + property string themeSliderHandleInteraction: Theme.color(Theme.DSsliderHandleInteraction) + property string themeScrollBarTrack: Theme.color(Theme.DSscrollBarTrack) property string themeScrollBarHandle: Theme.color(Theme.DSscrollBarHandle) - property string themeControlBackgroundInteraction: Theme.color(Theme.DScontrolBackgroundInteraction) // TODO Name. Right now themeFocusEdit is used for all 'edit' states. Is that correct? Different color! - property string themeTranslationIndicatorBorder: Theme.color(Theme.DStranlsationIndicatorBorder) + property string themeSectionHeadBackground: Theme.color(Theme.DSsectionHeadBackground) - property string themeTabDark: Theme.color(Theme.QmlDesigner_TabDark) - property string themeTabLight: Theme.color(Theme.QmlDesigner_TabLight) + property string themeTabActiveBackground: Theme.color(Theme.DStabActiveBackground) + property string themeTabActiveText: Theme.color(Theme.DStabActiveText) + property string themeTabInactiveBackground: Theme.color(Theme.DStabInactiveBackground) + property string themeTabInactiveText: Theme.color(Theme.DStabInactiveText) - property string themeStateDefaultHighlight: "#ffe400" + property string themeStateDefaultHighlight: Theme.color(Theme.DSstateDefaultHighlight) + property string themeStateSeparator: Theme.color(Theme.DSstateSeparatorColor) + property string themeStateBackground: Theme.color(Theme.DSstateBackgroundColor) + property string themeStatePreviewOutline: Theme.color(Theme.DSstatePreviewOutline) // Taken out of Constants.js property string themeChangedStateText: Theme.color(Theme.DSchangedStateText) @@ -131,4 +205,16 @@ QtObject { property string theme3DAxisXColor: Theme.color(Theme.DS3DAxisXColor) property string theme3DAxisYColor: Theme.color(Theme.DS3DAxisYColor) property string theme3DAxisZColor: Theme.color(Theme.DS3DAxisZColor) + + property string themeActionBinding: Theme.color(Theme.DSactionBinding) + property string themeActionAlias: Theme.color(Theme.DSactionAlias) + property string themeActionKeyframe: Theme.color(Theme.DSactionKeyframe) + property string themeActionJIT: Theme.color(Theme.DSactionJIT) + + property string themeListItemBackground: Theme.color(Theme.DSnavigatorItemBackground) + property string themeListItemBackgroundHover: Theme.color(Theme.DSnavigatorItemBackgroundHover) + property string themeListItemBackgroundPress: Theme.color(Theme.DSnavigatorItemBackgroundSelected) + property string themeListItemText: Theme.color(Theme.DSnavigatorText) + property string themeListItemTextHover: Theme.color(Theme.DSnavigatorTextHover) + property string themeListItemTextPress: Theme.color(Theme.DSnavigatorTextSelected) } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf index f5e80745563d26364d520b9d50c90f287f3cd3f5..aef8a37d5697b9ef4d8d4d1255edcd1face7b21c 100644 GIT binary patch delta 2666 zcmcap+tSEb&%nsQz`)DUz`)E9;N}+MJ0;_1A_Id%1_J|wjDN7cQDjG|0s{kM1Oo#@ zLUL|m!Is-?XBiln<}ffYIwhBtC@?58RWdLzKVV>BU`bCbF8KeSfti89A%TH`fg?Sq zGVOuvDINv}mIDk7275A66I0~XuAXLKV7SA;z+jebaC3=E7r7#J8H<>V(P7WCBmFfcGb0cpxjtSDgE&ajAqfzg72fk7cJF*nuJ>8~aO zgJ}%|1Jl!j{NfVflv-m328$F12KHZI&oMGE%raMa8P9L?m4Tc21p~++4^KA;?cnM5 z|IdFj_G)Gokc%0ZK*9_RAdSo_|IHYpm|y(=^CyqJ8YBXhgHSABk=)64jIp9!%nJW4 z7^0X}7*0X-GB7YpOy0mKDay*A$Dqf+3?}tJVe|hlL*C>&jOnTj3@i)`43-Sj7^XAm zF}N@=Fjz1+GNdq=GE8QuW8eqtXqX(wBq_xz{tSQAjcrXAi}^0g$$E>n6w$Y zHt%3kXRJTP$iQgESjD)G@d*!W!e+=Ki-yQcOT!lF`pWT0+!8%-q)Q-$o;g&B<)-O!fc&{WoKN z#jM1@&A`CP#Lmg6&dF%b$;kZbpEl!F<$t>Wbd?#e{?k@wyv%r+=|3u88Kj1Rfti8% zzcup{W?2Ry1~CRH1_o6lF;PK9K}91m5jJH-K}A6mGhsnRK~_aUMW)Z3e1Cp2R&w(3 zasJ!Jw6dP>*FR>)bN><<=ilJt`d7`&#xKP8H-a&Yi;v0m9}D9j{eMXejQ{`qKh6Ax zsR`srRX#>_Ms`LqBXdS|CJqh>j(^VTjQd1A#TfUgvvD)>Fx5!^ZIPE_s+DG7V#xbn z&s@#4nZc7GjDdksRD_+4olRLuT}@q09YRk&z$I93EM{zEZf0&~%V?smrohf7Dk3gs zY%UH_p=N4gZl)kE#%N@&X3MCiti;YH%Enx6BPJp$D=jL>FTxq_Brhc{X{4c%qGH7F z#L39R#=|Zn$uG#w?e6t&Q*fZ4@8){uX!UeAPvflA6vn=Y*nb%+vFt{g?oyI0j85Dx zyNrZbSXo&(1%ymE*u{10>n$w=+4xq@l4BO;X5`}0(~09*;^i3}yk~cyKc_W^u&`e2 zt1HQg(GmZ$G)+>gg*4S;7H`hsnk!n*#K7?1g82or0s}JxI|BnJv!b}UI^!3{FaLP{ z@i4N!fB&9Y0nGgJ{{4Ff1_mYumj7+cPnaGsFfp()Ft93eGAc4MKmMb{`2L?ebMZg7 zD(0v^N16VB$`od}*+LAe44MoKs_N!uCTdFjjOylQ#zx{|q9XO|3`**1rY81`;-F9z zGXgR685zZyRZVi7+x9q@nv_LVRYyid{1g8c84-~U7u{#fSYfo)B*%GoyGyA_X;?&f zZFS^72{4sooZ}W9*XCSmT)M@GvBDVS7&ZpW|I3(HGo52#XW(ZLXHa1?f^6l69O5MdPM``gYZBEn}RFgrKAQ6xYp#KJq5i_tAzOg!!1t_*R;JW>9CCLk4z zXZS=W=S*W|N)F;Tc4T2r_nyr3Pe+<@D&xN#kQVsc17vH2imG&R`Y<)oGlJg3K9zB^Yi0aWkLT?5xJcj+Bx?sSQh7!0yU4BC?ebaRE68DPQ4z`zGeOXic`C}}gz3lGNB!1XQ2 z*OCm=p=>4wc7}scHZy|>qcN1t!XU{w2g+t;5MaCkWwS9zGRZP9GcdAnGB7YWFo23y z5Sx*~h#?s&&cwjSuo22;X2@VT31Ta-a5Atk7%^smI4qnDtPBc_+n{VV1|!ColfRiL z+Z!_IFn}Cd#E{RB&ydZaz~IaPV&^erGUPEZIOi8s7GzJQO+IfHFnO|R0ly`KE`t#m8!#9#7)};5)8nwzHPQuX0V|qk);w9kT#+$% zvXl84KE_nWG{$ts48}~xEXM4~d=?woI1_U+6N@+Rwz$l!lAT(aR+N~Vs#jc=E|8O% zmmN}+nV6TJ0~X){38bb>?zC}K;mXY{D#|Ycsbeq5%mdLJ1v#a~AO?3qQGRZIN$Te7 rHm;1EJf(R)nR(f%DU&7a7AZ3R{|`!IkTAY|Bkc+(itoUiSe|YG87_!- delta 2131 zcmZo^WV};b&%nsQz`)DUz`)E9;N}+MJ9#o!4FiMS0R{#J8UJ8?qsaDDX$A(y2nGg* zgyh`Bf-Se(jxjJW^)N6nIwhBtC@?58RWdLzUtnNhU`bCbF8KeSfti89ZU+Mc14nvJ zW!hy1?qUW8mL&`f`b#oW6I0}Z&t)($Fx+8aU@*(bNUcxg`t^Sj0|TQ70|SFfMs7)k z&}7a^1_nlu0atSJlN0UNm;^8|FkfL{U^thXSW&>RfngB?1EU241A{_dVs2{TrpnI@ z3??273{2Mw@{3ERx*yeLU@%u;U|^pL_8cPv!{VD$XUFr~d}ZKfe!;-Nz;OGn>l6s> z;5z01|NrLf)yyg&7c(${gc%q>8ktr8n=?c)zxep z75-Z=L@}!{oP_9QU|^P-yn#_tn1w-)L63nMOzJVTGKe$CPQJ&O?rF&|jUkFbkHLk( zg29o&lwmSM9RojDl`7aBY7A-&9ANCupw6Jjz|SDhpv|Dbz{tSQAjcrXAi}^0fs^Mj zX)`u&KEb5USpR@gjM0a20^-1vU+3-K56FW|o+z#(8H zkR~ui;E=!tfp>x~f)fPq2pI|030)C35UvrC5U~*n5$O@t5%mzw5`7~UCALPKP25Ag zN&FH6!{h@jQw3QVSpIu4KW0{7P-f6(FlLCJoWiOm#3UkSWM-nK!~msPl_vMFs@J#3 z${uuf63rJ3GL=$dR+r@AW-eeB5;`O-$6UanXDGp$FAyTCVxp>Q@^6x=iHeE|Qy?=t zNTn1vH%mS<8<)sI5g{Jtd`>+>agG8}M;nJj4vH$G1p+?XxE#dGY#IHG&6ye1O_UfJ z*}4C1$^pg}9(3AYP(OTbv=?utN)qjGMllg~P7uMS zq|V96rlhWBV$R8^W@2U}&dF$I#O%(-_U{CvK07W>v9Yr=I{Z7%&L_;y zXvt{7F3eQPF2eTj#J}_G!t88pjQal$v$3%YvoqR*B>C9?9cQ#;2PI-=2J!#Z%nz9+ zPZi(d&&VMA|0nZBCN2gM1_ogzHc=6AMlmCEMl(|rHDx7sPDV9TE?zdqL+m2#jEC6y zxVYH=`Tz50XX4`H;$;6P&(6;Hke!o@kK>;a<2eonhRtiZ=88@>R6J16%rNbLG;=63 zBLfG641*2>1EVs#p`tdUprWvm7`vbdo3f&knyH|PnKhH5xw;;sx*D4-qq3=qnYbLI zIJ2mD+P_^H;!I950wRo}e1F^dL`3+EG8o;`6NN%7ymS3#=Y}?mFzPe@%VE4C%Ky&< zB+qz;PlV}&u_Fs}y0^~c$vM+lnF@m$SQw)I$1;a8{bpbX=QUdf23SIZ(UZHC^aL1} zfD_5TN#G>Iv}y7lB?SQ{F;MzZ`6mR5Xcb1r$@i7iCbK9XRAynY_+Q4nmFX$iR9OZq zET*p4*XBnx)pqh7eGPt8Lw8P&Rq5F5sp`fgq540Z`8?BSP;tb`D9C*NPdKCLKPBcl zo0qF|u}{|3FQ{i@Q1~Cue2(cC)LLBzPlj|%tIh2g#l_h88QGMT)XmJ>2Gq zVa(6S#?A0%Z$GB-0dF@q>qXH-*GV&iAzV^jtw zje1n?tmBgB;b!Fd&dSEi$i!r=1MA;oxs@>UGSQ%LvUD?^#xLs^=n3y?P+5R>Oi3mwrrO7%8 z+Q~99GIH>X3g#MFs7Z;7ZPqu4VXc>BFaa0ipaNf#p$W=nVqj-j17$Nam@z6r*(?l_ zjJ;4cD}w;zNhq6*L6V7&fti7kg_D7S!H9tY%4TFRV(^2qnHcyO=0MrZ3^@#2Kx_pT zP6ieRBgRM&hlP`Yl|g}VIh4)DV8nQ9vX+^$mH~qfg91YmLlHwhLq0<`1A}vZL1j^9 zdPa$YMzW@Yk%5tcjzUsVet!1kiRJ;5@0b+`8!;F#=rR~G7&7QGfY?S129u-B^|*`- zbPWx4K{_T+G`~DK)k1+WZE~B%naK&38#hZ^ooAjbY-hvEUXYomS6r6PQIJzwyt&xU gm2vV>`*}(XjQ{_GQY6IJw{O%3g9;HuUFtdo0G+zLVE_OC diff --git a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml index f4faae6bbe4..5cbefc03d1f 100644 --- a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml +++ b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml @@ -170,7 +170,7 @@ Rectangle { Rectangle { anchors.margins: (isDefaultState || (isBaseState && !modelHasDefaultState)) ? -myRoot.highlightBorderWidth : 0 anchors.fill: column - color: Theme.color(Theme.DSsliderActiveTrackFocus) + color: StudioTheme.Values.themeStateSeparator border.color: StudioTheme.Values.themeStateDefaultHighlight border.width: (isDefaultState || (isBaseState && !modelHasDefaultState)) ? myRoot.highlightBorderWidth : 0 } @@ -188,14 +188,14 @@ Rectangle { width: myRoot.width - 2 * myRoot.stateMargin height: myRoot.topAreaHeight - color: Theme.color(Theme.DShoverHighlight) + color: StudioTheme.Values.themeStateBackground StudioControls.TextField { id: stateNameField property string oldValue - width: StudioTheme.Values.height * 7 + width: StudioTheme.Values.height * 5.5 anchors.top: parent.top anchors.topMargin: myRoot.textFieldMargin @@ -247,7 +247,7 @@ Rectangle { anchors.rightMargin: myRoot.previewMargin anchors.verticalCenter: stateNameField.verticalCenter - color: Theme.color(Theme.DStextColor) + color: StudioTheme.Values.themeTextColor font.italic: true font.pixelSize: StudioTheme.Values.myFontSize font.family: StudioTheme.Constants.font @@ -261,27 +261,29 @@ Rectangle { Rectangle { id: stateImageArea - width: myRoot.width - 2 * myRoot.stateMargin height: myRoot.bottomAreaHeight - - color: Theme.color(Theme.DShoverHighlight) - + color: StudioTheme.Values.themeStateBackground visible: expanded + Image { + anchors.fill: stateImageBackground + source: "images/checkers.png" + fillMode: Image.Tile + } + Rectangle { - border.width: StudioTheme.Values.border - border.color: Theme.color(Theme.DSsliderActiveTrackFocus) - color: Theme.color(Theme.DSsliderInactiveTrack) - + id: stateImageBackground anchors.centerIn: parent - width: Math.round(stateImage.paintedWidth) + 2 * StudioTheme.Values.border height: Math.round(stateImage.paintedHeight) + 2 * StudioTheme.Values.border + color: "transparent" + border.width: StudioTheme.Values.border + border.color: StudioTheme.Values.themeStatePreviewOutline } + Image { id: stateImage - anchors.margins: myRoot.previewMargin anchors.centerIn: parent anchors.fill: parent diff --git a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml index 4abaa896d2f..fee38c2213d 100644 --- a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml +++ b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml @@ -33,7 +33,7 @@ import StudioTheme 1.0 as StudioTheme FocusScope { id: root - property int delegateTopAreaHeight: 30 + property int delegateTopAreaHeight: StudioTheme.Values.height + 8 property int delegateBottomAreaHeight: 200 property int delegateColumnSpacing: 2 property int delegateStateMargin: 16 @@ -72,7 +72,7 @@ FocusScope { Rectangle { id: background anchors.fill: parent - color: Theme.color(Theme.QmlDesigner_BackgroundColorDarkAlternate) + color: StudioTheme.Values.themePanelBackground } MouseArea { @@ -137,7 +137,7 @@ FocusScope { } Rectangle { - color: Theme.color(Theme.DSsliderActiveTrackFocus) + color: StudioTheme.Values.themeStateSeparator x: root.padding y: root.padding width: Math.min((root.delegateWidth * flickable.count) + (2 * (flickable.count - 1)), @@ -168,7 +168,7 @@ FocusScope { height: root.delegateHeight isBaseState: 0 === internalNodeId isCurrentState: root.currentStateInternalId === internalNodeId - baseColor: isCurrentState ? Theme.color(Theme.DSinteraction) : background.color + baseColor: isCurrentState ? StudioTheme.Values.themeInteraction : background.color delegateStateName: stateName delegateStateImageSource: stateImageSource delegateStateImageSize: stateImageSize diff --git a/share/qtcreator/qmldesigner/statesEditorQmlSources/images/checkers.png b/share/qtcreator/qmldesigner/statesEditorQmlSources/images/checkers.png new file mode 100644 index 0000000000000000000000000000000000000000..72cb9f0350646967cbd0bdc5c69981796f43a2dd GIT binary patch literal 80 zcmeAS@N?(olHy`uVBq!ia0y~yVBi5^4h9AWhGIEpYX$}eaZeY=5RT~N3Kq8i2OAob f_*$Ac0?#lqSbc8ylogof3sUOo>gTe~DWM4fJ|+>W literal 0 HcmV?d00001 diff --git a/share/qtcreator/themes/dark.creatortheme b/share/qtcreator/themes/dark.creatortheme index cbc51b2ef69..736d517c6ef 100644 --- a/share/qtcreator/themes/dark.creatortheme +++ b/share/qtcreator/themes/dark.creatortheme @@ -22,44 +22,136 @@ backgroundColorDisabled=ff444444 qmlDesignerButtonColor=ff3c3e40 [Colors] - ;DS controls theme START -DScontrolBackground=ff404040 -DScontrolOutline=ff595959 -DStextColor=ffffffff -DSdisabledTextColor=ff909090 -DSpanelBackground=ff454444 -DShoverHighlight=ff313131 -DScolumnBackground=ff363636 -DSfocusEdit=ff444444 -DSfocusDrag=ff565656 -DScontrolBackgroundPressed=ff7a7a7a -DScontrolBackgroundChecked=ff565656 -DSinteraction=ff3f91c4 -DSsliderActiveTrack=ff7a7a7a -DSsliderInactiveTrack=ff4d4d4d -DSsliderHandle=ff505050 -DSsliderActiveTrackHover=ff7f7f7f -DSsliderInactiveTrackHover=ff505050 -DSsliderHandleHover=ff7a7a7a -DSsliderActiveTrackFocus=ffaaaaaa -DSsliderInactiveTrackFocus=ff7a7a7a -DSsliderHandleFocus=ff3f91c4 +DSpanelBackground=ff323232 + +DSinteraction=ff2aafd3 DSerrorColor=ffdf3a3a -DScontrolBackgroundDisabled=ff363636 -DScontrolOutlineDisabled=ff4d4d4d -DStextColorDisabled=ff7a7a7a -DStextSelectionColor=ff3f91c4 -DStextSelectedTextColor=ffffffff -DSscrollBarTrack=ff4d4d4d +DSdisabledColor=ff707070 + +DScontrolBackground=ff323232 +DScontrolBackgroundInteraction=ff595959 +DScontrolBackgroundDisabled=ff323232 +DScontrolBackgroundGlobalHover=ff474747 +DScontrolBackgroundHover=ff666666 + +DScontrolOutline=ff1f1f1f +DScontrolOutlineInteraction=ff2aafd3 +DScontrolOutlineDisabled=ff707070 + +DStextColor=ffffffff +DStextColorDisabled=ff707070 +DStextSelectionColor=ff2aafd3 +DStextSelectedTextColor=ff000000 + +DSplaceholderTextColor=ffffffff +DSplaceholderTextColorInteraction=ffababab + +DSiconColor=ffffffff +DSiconColorHover=ff262626 +DSiconColorInteraction=ff707070 +DSiconColorDisabled=ff707070 +DSiconColorSelected=ff2aafd3 + +DSlinkIndicatorColor=ff808080 +DSlinkIndicatorColorHover=ffffffff +DSlinkIndicatorColorInteraction=ff2aafd3 +DSlinkIndicatorColorDisabled=ff707070 + +DSpopupBackground=ff474747 +DSpopupOverlayColor=99191919 + +DSsliderActiveTrack=ff7c7b7b +DSsliderActiveTrackHover=ff000000 +DSsliderActiveTrackFocus=ffaaaaaa +DSsliderInactiveTrack=ff595959 +DSsliderInactiveTrackHover=ff505050 +DSsliderInactiveTrackFocus=ff606060 +DSsliderHandle=ff1f1f1f +DSsliderHandleHover=ff606060 +DSsliderHandleFocus=ff0492c9 +DSsliderHandleInteraction=ff2aafd3 + +DSscrollBarTrack=ff404040 DSscrollBarHandle=ff505050 -DScontrolBackgroundInteraction=ff4d4d4d -DStranslationIndicatorBorder=ff7f7f7f -DSsectionHeadBackground=ff424242 + +DSsectionHeadBackground=ff1f1f1f + +DSstateDefaultHighlight=ffffe400 +DSstateSeparatorColor=ff7c7b7b +DSstateBackgroundColor=ff383838 +DSstatePreviewOutline=ffaaaaaa + DSchangedStateText=ff99ccff -DS3DAxisXColor=ffe00000 + +DS3DAxisXColor=ffd00000 DS3DAxisYColor=ff009900 -DS3DAxisZColor=ff6060ff +DS3DAxisZColor=ff5050ff + +DSactionBinding=ff2aafd3 +DSactionAlias=fff93a3a +DSactionKeyframe=ffe0e01b +DSactionJIT=ff2db543 + +DStableHeaderBackground=ffff0000 +DStableHeaderText=ff00ff00 + +DSdockContainerBackground=ff323232 +DSdockContainerSplitter=ff323232 +DSdockAreaBackground=ff262728 + +DSdockWidgetBackground=ff00ff00 +DSdockWidgetSplitter=ff595959 +DSdockWidgetTitleBar=ff1f1f1f + +DStitleBarText=ffdadada +DStitleBarIcon=ffffffff +DStitleBarButtonHover=40ffffff +DStitleBarButtonPress=60ffffff + +DStabContainerBackground=ff0000ff +DStabSplitter=ff595959 + +DStabInactiveBackground=ff1f1f1f +DStabInactiveText=ffdadada +DStabInactiveIcon=ffffffff +DStabInactiveButtonHover=ff1f1f1f +DStabInactiveButtonPress=ff1f1f1f + +DStabActiveBackground=ffdadada +DStabActiveText=ff111111 +DStabActiveIcon=ff000000 +DStabActiveButtonHover=ffdadada +DStabActiveButtonPress=ffdadada + +DStabFocusBackground=ff2aafd3 +DStabFocusText=ff111111 +DStabFocusIcon=ff000000 +DStabFocusButtonHover=ff2aafd3 +DStabFocusButtonPress=ff2aafd3 + +DSnavigatorBranch=ff7c7b7b +DSnavigatorBranchIndicator=ff7c7b7b +DSnavigatorItemBackground=ff262626 +DSnavigatorItemBackgroundHover=ff666666 +DSnavigatorItemBackgroundSelected=ff1f1f1f +DSnavigatorText=ffffffff +DSnavigatorTextHover=ff1f1f1f +DSnavigatorTextSelected=ff2aafd3 +DSnavigatorIcon=ffffffff +DSnavigatorIconHover=ff1f1f1f +DSnavigatorIconSelected=ff7c7b7b +DSnavigatorAliasIconChecked=ffff0000 +DSnavigatorDropIndicatorBackground=ff2aafd3 +DSnavigatorDropIndicatorOutline=ff2aafd3 + +DSheaderViewBackground=ff1f1f1f +DStableViewAlternateBackground=ff00ff00 + +DStoolTipBackground=ff111111 +DStoolTipOutline=ffdadada +DStoolTipText=ffdadada + ;DS controls theme END BackgroundColorAlternate=alternateBackground @@ -263,7 +355,7 @@ QmlDesigner_BackgroundColor=qmlDesignerButtonColor QmlDesigner_HighlightColor=ff46a2da QmlDesigner_FormEditorSelectionColor=ff4ba2ff QmlDesigner_FormEditorForegroundColor=ffffffff -QmlDesigner_BackgroundColorDarkAlternate=qmlDesignerButtonColor +QmlDesigner_BackgroundColorDarkAlternate=ff323232 QmlDesigner_BackgroundColorDarker=ff151515 QmlDesigner_BorderColor=splitterColor QmlDesigner_ButtonColor=ff505050 diff --git a/share/qtcreator/themes/default.creatortheme b/share/qtcreator/themes/default.creatortheme index 2710025524c..dcca311d9e7 100644 --- a/share/qtcreator/themes/default.creatortheme +++ b/share/qtcreator/themes/default.creatortheme @@ -13,44 +13,136 @@ splitterColor=ff151515 qmlDesignerButtonColor=ff4c4e50 [Colors] - ;DS controls theme START -DScontrolBackground=ff404040 -DScontrolOutline=ff595959 -DStextColor=ffffffff -DSdisabledTextColor=ff909090 -DSpanelBackground=ff454444 -DShoverHighlight=ff313131 -DScolumnBackground=ff363636 -DSfocusEdit=ff444444 -DSfocusDrag=ff565656 -DScontrolBackgroundPressed=ff7a7a7a -DScontrolBackgroundChecked=ff565656 -DSinteraction=ff3f91c4 -DSsliderActiveTrack=ff7a7a7a -DSsliderInactiveTrack=ff4d4d4d -DSsliderHandle=ff505050 -DSsliderActiveTrackHover=ff7f7f7f -DSsliderInactiveTrackHover=ff505050 -DSsliderHandleHover=ff7a7a7a -DSsliderActiveTrackFocus=ffaaaaaa -DSsliderInactiveTrackFocus=ff7a7a7a -DSsliderHandleFocus=ff3f91c4 +DSpanelBackground=ffeaeaea + +DSinteraction=ff2aafd3 DSerrorColor=ffdf3a3a -DScontrolBackgroundDisabled=ff363636 -DScontrolOutlineDisabled=ff4d4d4d -DStextColorDisabled=ff7a7a7a -DStextSelectionColor=ff3f91c4 -DStextSelectedTextColor=ffffffff -DSscrollBarTrack=ff4d4d4d -DSscrollBarHandle=ff505050 -DScontrolBackgroundInteraction=ff4d4d4d -DStranslationIndicatorBorder=ff7f7f7f -DSsectionHeadBackground=ff424242 +DSdisabledColor=ff8e8e8e + +DScontrolBackground=ffeaeaea +DScontrolBackgroundInteraction=ffc9c9c9 +DScontrolBackgroundDisabled=ff8e8e8e +DScontrolBackgroundGlobalHover=ffe5e5e5 +DScontrolBackgroundHover=ffd1d1d1 + +DScontrolOutline=ffcecccc +DScontrolOutlineInteraction=ff2aafd3 +DScontrolOutlineDisabled=ff707070 + +DStextColor=ff262626 +DStextColorDisabled=ff707070 +DStextSelectionColor=ff2aafd3 +DStextSelectedTextColor=ff000000 + +DSplaceholderTextColor=ff262626 +DSplaceholderTextColorInteraction=ffababab + +DSiconColor=ff262626 +DSiconColorHover=ff191919 +DSiconColorInteraction=ffffffff +DSiconColorDisabled=ff707070 +DSiconColorSelected=ff2aafd3 + +DSlinkIndicatorColor=ff808080 +DSlinkIndicatorColorHover=ff1f1f1f +DSlinkIndicatorColorInteraction=ff2aafd3 +DSlinkIndicatorColorDisabled=ff707070 + +DSpopupBackground=ffd3d3d3 +DSpopupOverlayColor=99191919 + +DSsliderActiveTrack=ff7c7b7b +DSsliderActiveTrackHover=ff000000 +DSsliderActiveTrackFocus=ffaaaaaa +DSsliderInactiveTrack=ffaaaaaa +DSsliderInactiveTrackHover=ff505050 +DSsliderInactiveTrackFocus=ff606060 +DSsliderHandle=ff1f1f1f +DSsliderHandleHover=ff606060 +DSsliderHandleFocus=ff0492c9 +DSsliderHandleInteraction=ff2aafd3 + +DSscrollBarTrack=ffb5b4b4 +DSscrollBarHandle=ff9b9b9b + +DSsectionHeadBackground=ffd8d8d8 + +DSstateDefaultHighlight=ffffe400 +DSstateSeparatorColor=ffadadad +DSstateBackgroundColor=ffe0e0e0 +DSstatePreviewOutline=ff363636 + DSchangedStateText=ff99ccff -DS3DAxisXColor=ffe00000 + +DS3DAxisXColor=ffd00000 DS3DAxisYColor=ff009900 -DS3DAxisZColor=ff6060ff +DS3DAxisZColor=ff5050ff + +DSactionBinding=ff2aafd3 +DSactionAlias=fff93a3a +DSactionKeyframe=ffe0e01b +DSactionJIT=ff2db543 + +DStableHeaderBackground=ffff0000 +DStableHeaderText=ff00ff00 + +DSdockContainerBackground=ff323232 +DSdockContainerSplitter=ff323232 +DSdockAreaBackground=ff262728 + +DSdockWidgetBackground=ff00ff00 +DSdockWidgetSplitter=ff595959 +DSdockWidgetTitleBar=ffeaeaea + +DStitleBarText=ffdadada +DStitleBarIcon=f4f5052 +DStitleBarButtonHover=40ffffff +DStitleBarButtonPress=60ffffff + +DStabContainerBackground=ff0000ff +DStabSplitter=ff595959 + +DStabInactiveBackground=ff999999 +DStabInactiveText=ff262626 +DStabInactiveIcon=ffffffff +DStabInactiveButtonHover=ff1f1f1f +DStabInactiveButtonPress=ff1f1f1f + +DStabActiveBackground=ffdadada +DStabActiveText=ff111111 +DStabActiveIcon=ff000000 +DStabActiveButtonHover=ffdadada +DStabActiveButtonPress=ffdadada + +DStabFocusBackground=ff2aafd3 +DStabFocusText=ff111111 +DStabFocusIcon=ff000000 +DStabFocusButtonHover=ff2aafd3 +DStabFocusButtonPress=ff2aafd3 + +DSnavigatorBranch=ff7c7b7b +DSnavigatorBranchIndicator=ff7c7b7b +DSnavigatorItemBackground=ffd8d8d8 +DSnavigatorItemBackgroundHover=ffc2c2c2 +DSnavigatorItemBackgroundSelected=ffffffff +DSnavigatorText=ff262626 +DSnavigatorTextHover=ff1f1f1f +DSnavigatorTextSelected=ff2aafd3 +DSnavigatorIcon=ff1f1f1f +DSnavigatorIconHover=ff1f1f1f +DSnavigatorIconSelected=ff7c7b7b +DSnavigatorAliasIconChecked=ffff0000 +DSnavigatorDropIndicatorBackground=ff2aafd3 +DSnavigatorDropIndicatorOutline=ff2aafd3 + +DSheaderViewBackground=ffd8d8d8 +DStableViewAlternateBackground=ff00ff00 + +DStoolTipBackground=ff111111 +DStoolTipOutline=ffdadada +DStoolTipText=ffdadada + ;DS controls theme END BackgroundColorAlternate=ff3d3d3d @@ -232,7 +324,7 @@ QmlDesigner_BackgroundColor=qmlDesignerButtonColor QmlDesigner_HighlightColor=ff46a2da QmlDesigner_FormEditorSelectionColor=ff4ba2ff QmlDesigner_FormEditorForegroundColor=brightText -QmlDesigner_BackgroundColorDarkAlternate=qmlDesignerButtonColor +QmlDesigner_BackgroundColorDarkAlternate=ffeaeaea QmlDesigner_BackgroundColorDarker=ff4e4e4e QmlDesigner_BorderColor=splitterColor QmlDesigner_ButtonColor=ff7a7a7a diff --git a/share/qtcreator/themes/design-light.creatortheme b/share/qtcreator/themes/design-light.creatortheme index ef52ec12cd2..44b4109dd24 100644 --- a/share/qtcreator/themes/design-light.creatortheme +++ b/share/qtcreator/themes/design-light.creatortheme @@ -24,53 +24,146 @@ splitter=ffbdbebf qmlDesignerButtonColor=fff8f8f8 textColorLink=ff007af4 textColorLinkVisited=ffa57aff -backgroundColorDisabled=ff444444 +backgroundColorDisabled=ff8e8e8e [Colors] ;DS controls theme START -DScontrolBackground=ffffffff -DScontrolOutline=ff777777 -DStextColor=ff242424 -DSdisabledTextColor=ff505050 -DSpanelBackground=fff2f2f2 -DShoverHighlight=ffe6e6e6 -DScolumnBackground=ffaaaaaa -DSfocusEdit=ffeaeaea -DSfocusDrag=ffd1d1d1 -DScontrolBackgroundPressed=ff505050 -DScontrolBackgroundChecked=ff5e5e5e -DSinteraction=ff0492c9 -DSsliderActiveTrack=ff363636 -DSsliderInactiveTrack=ffe6e6e6 -DSsliderHandle=ff777777 -DSsliderActiveTrackHover=ff7f7f7f -DSsliderInactiveTrackHover=ff5e5e5e -DSsliderHandleHover=ff505050 -DSsliderActiveTrackFocus=ff363636 -DSsliderInactiveTrackFocus=ff505050 -DSsliderHandleFocus=ff0492c9 +DSpanelBackground=ffeaeaea + +DSinteraction=ff2aafd3 DSerrorColor=ffdf3a3a -DScontrolBackgroundDisabled=ffaaaaaa -DScontrolOutlineDisabled=ff777777 -DStextColorDisabled=ff505050 -DStextSelectionColor=ff0492c9 -DStextSelectedTextColor=ffffffff -DSscrollBarTrack=ff777777 -DSscrollBarHandle=ff505050 -DScontrolBackgroundInteraction=ff777777 -DStranslationIndicatorBorder=ffebebeb -DSsectionHeadBackground=ffebebeb +DSdisabledColor=ff8e8e8e + +DScontrolBackground=ffeaeaea +DScontrolBackgroundInteraction=ffc9c9c9 +DScontrolBackgroundDisabled=ff8e8e8e +DScontrolBackgroundGlobalHover=ffe5e5e5 +DScontrolBackgroundHover=ffd1d1d1 + +DScontrolOutline=ffcecccc +DScontrolOutlineInteraction=ff2aafd3 +DScontrolOutlineDisabled=ff707070 + +DStextColor=ff262626 +DStextColorDisabled=ff707070 +DStextSelectionColor=ff2aafd3 +DStextSelectedTextColor=ff000000 + +DSplaceholderTextColor=ff262626 +DSplaceholderTextColorInteraction=ffababab + +DSiconColor=ff262626 +DSiconColorHover=ff191919 +DSiconColorInteraction=ffffffff +DSiconColorDisabled=ff707070 +DSiconColorSelected=ff2aafd3 + +DSlinkIndicatorColor=ff808080 +DSlinkIndicatorColorHover=ff1f1f1f +DSlinkIndicatorColorInteraction=ff2aafd3 +DSlinkIndicatorColorDisabled=ff707070 + +DSpopupBackground=ffd3d3d3 +DSpopupOverlayColor=99191919 + +DSsliderActiveTrack=ff7c7b7b +DSsliderActiveTrackHover=ff000000 +DSsliderActiveTrackFocus=ffaaaaaa +DSsliderInactiveTrack=ffaaaaaa +DSsliderInactiveTrackHover=ff505050 +DSsliderInactiveTrackFocus=ff606060 +DSsliderHandle=ff1f1f1f +DSsliderHandleHover=ff606060 +DSsliderHandleFocus=ff0492c9 +DSsliderHandleInteraction=ff2aafd3 + +DSscrollBarTrack=ffb5b4b4 +DSscrollBarHandle=ff9b9b9b + +DSsectionHeadBackground=ffd8d8d8 + +DSstateDefaultHighlight=ffffe400 +DSstateSeparatorColor=ffadadad +DSstateBackgroundColor=ffe0e0e0 +DSstatePreviewOutline=ff363636 + DSchangedStateText=ff99ccff -DS3DAxisXColor=ffff0000 -DS3DAxisYColor=ff00A000 -DS3DAxisZColor=ff0000ff + +DS3DAxisXColor=ffd00000 +DS3DAxisYColor=ff009900 +DS3DAxisZColor=ff5050ff + +DSactionBinding=ff2aafd3 +DSactionAlias=fff93a3a +DSactionKeyframe=ffe0e01b +DSactionJIT=ff2db543 + +DStableHeaderBackground=ffff0000 +DStableHeaderText=ff00ff00 + +DSdockContainerBackground=ff323232 +DSdockContainerSplitter=ff323232 +DSdockAreaBackground=ff262728 + +DSdockWidgetBackground=ff00ff00 +DSdockWidgetSplitter=ff595959 +DSdockWidgetTitleBar=ffeaeaea + +DStitleBarText=ffdadada +DStitleBarIcon=f4f5052 +DStitleBarButtonHover=40ffffff +DStitleBarButtonPress=60ffffff + +DStabContainerBackground=ff0000ff +DStabSplitter=ff595959 + +DStabInactiveBackground=ff999999 +DStabInactiveText=ff262626 +DStabInactiveIcon=ffffffff +DStabInactiveButtonHover=ff1f1f1f +DStabInactiveButtonPress=ff1f1f1f + +DStabActiveBackground=ffdadada +DStabActiveText=ff111111 +DStabActiveIcon=ff000000 +DStabActiveButtonHover=ffdadada +DStabActiveButtonPress=ffdadada + +DStabFocusBackground=ff2aafd3 +DStabFocusText=ff111111 +DStabFocusIcon=ff000000 +DStabFocusButtonHover=ff2aafd3 +DStabFocusButtonPress=ff2aafd3 + +DSnavigatorBranch=ff7c7b7b +DSnavigatorBranchIndicator=ff7c7b7b +DSnavigatorItemBackground=ffd8d8d8 +DSnavigatorItemBackgroundHover=ffc2c2c2 +DSnavigatorItemBackgroundSelected=ffffffff +DSnavigatorText=ff262626 +DSnavigatorTextHover=ff1f1f1f +DSnavigatorTextSelected=ff2aafd3 +DSnavigatorIcon=ff1f1f1f +DSnavigatorIconHover=ff1f1f1f +DSnavigatorIconSelected=ff7c7b7b +DSnavigatorAliasIconChecked=ffff0000 +DSnavigatorDropIndicatorBackground=ff2aafd3 +DSnavigatorDropIndicatorOutline=ff2aafd3 + +DSheaderViewBackground=ffd8d8d8 +DStableViewAlternateBackground=ff00ff00 + +DStoolTipBackground=ff111111 +DStoolTipOutline=ffdadada +DStoolTipText=ffdadada + ;DS controls theme END BackgroundColorAlternate=alternateBackground BackgroundColorDark=shadowBackground BackgroundColorHover=hoverBackground BackgroundColorNormal=normalBackground -BackgroundColorDisabled=ff444444 +BackgroundColorDisabled=ff7a7a7a BackgroundColorSelected=selectedBackground BadgeLabelBackgroundColorChecked=ffe0e0e0 BadgeLabelBackgroundColorUnchecked=ff808080 @@ -246,7 +339,7 @@ QmlDesigner_BackgroundColor=qmlDesignerButtonColor QmlDesigner_HighlightColor=ff0492c9 QmlDesigner_FormEditorSelectionColor=ffd3299a QmlDesigner_FormEditorForegroundColor=ffffffff -QmlDesigner_BackgroundColorDarkAlternate=qmlDesignerButtonColor +QmlDesigner_BackgroundColorDarkAlternate=ffeaeaea QmlDesigner_BackgroundColorDarker=fff5f5f5 QmlDesigner_BorderColor=splitter QmlDesigner_ButtonColor=f0f0f0 diff --git a/share/qtcreator/themes/design.creatortheme b/share/qtcreator/themes/design.creatortheme index 67457b28495..f93c74914b9 100644 --- a/share/qtcreator/themes/design.creatortheme +++ b/share/qtcreator/themes/design.creatortheme @@ -4,7 +4,7 @@ PreferredStyles=Fusion DefaultTextEditorColorScheme=creator-dark.xml [Palette] -shadowBackground=ff191919 +shadowBackground=ff1f1f1f text=ffdadada textDisabled=60a4a6a8 selectedBackgroundText=aa1f75cc @@ -23,47 +23,137 @@ textColorLink=ff007af4 textColorLinkVisited=ffa57aff backgroundColorDisabled=ff444444 - - - [Colors] ;DS controls theme START -DScontrolBackground=ff242424 -DScontrolOutline=ff404040 -DStextColor=ffffffff -DSdisabledTextColor=ff909090 -DSpanelBackground=ff2a2a2a -DShoverHighlight=ff313131 -DScolumnBackground=ff363636 -DSfocusEdit=ff444444 -DSfocusDrag=ff565656 -DScontrolBackgroundPressed=ff606060 -DScontrolBackgroundChecked=ff565656 -DSinteraction=ff0492c9 -DSsliderActiveTrack=ff606060 -DSsliderInactiveTrack=ff404040 -DSsliderHandle=ff505050 -DSsliderActiveTrackHover=ff7f7f7f -DSsliderInactiveTrackHover=ff505050 -DSsliderHandleHover=ff606060 -DSsliderActiveTrackFocus=ffaaaaaa -DSsliderInactiveTrackFocus=ff606060 -DSsliderHandleFocus=ff0492c9 +DSpanelBackground=ff323232 + +DSinteraction=ff2aafd3 DSerrorColor=ffdf3a3a -DScontrolBackgroundDisabled=ff363636 -DScontrolOutlineDisabled=ff404040 -DStextColorDisabled=ff606060 -DStextSelectionColor=ff0492c9 -DStextSelectedTextColor=ffffffff +DSdisabledColor=ff707070 + +DScontrolBackground=ff323232 +DScontrolBackgroundInteraction=ff595959 +DScontrolBackgroundDisabled=ff323232 +DScontrolBackgroundGlobalHover=ff474747 +DScontrolBackgroundHover=ff666666 + +DScontrolOutline=ff1f1f1f +DScontrolOutlineInteraction=ff2aafd3 +DScontrolOutlineDisabled=ff707070 + +DStextColor=ffffffff +DStextColorDisabled=ff707070 +DStextSelectionColor=ff2aafd3 +DStextSelectedTextColor=ff000000 + +DSplaceholderTextColor=ffffffff +DSplaceholderTextColorInteraction=ffababab + +DSiconColor=ffffffff +DSiconColorHover=ff262626 +DSiconColorInteraction=ff707070 +DSiconColorDisabled=ff707070 +DSiconColorSelected=ff2aafd3 + +DSlinkIndicatorColor=ff808080 +DSlinkIndicatorColorHover=ffffffff +DSlinkIndicatorColorInteraction=ff2aafd3 +DSlinkIndicatorColorDisabled=ff707070 + +DSpopupBackground=ff474747 +DSpopupOverlayColor=99191919 + +DSsliderActiveTrack=ff7c7b7b +DSsliderActiveTrackHover=ff000000 +DSsliderActiveTrackFocus=ffaaaaaa +DSsliderInactiveTrack=ff595959 +DSsliderInactiveTrackHover=ff505050 +DSsliderInactiveTrackFocus=ff606060 +DSsliderHandle=ff1f1f1f +DSsliderHandleHover=ff606060 +DSsliderHandleFocus=ff0492c9 +DSsliderHandleInteraction=ff2aafd3 + DSscrollBarTrack=ff404040 DSscrollBarHandle=ff505050 -DScontrolBackgroundInteraction=ff404040 -DStranslationIndicatorBorder=ff7f7f7f -DSsectionHeadBackground=ff191919 + +DSsectionHeadBackground=ff1f1f1f + +DSstateDefaultHighlight=ffffe400 +DSstateSeparatorColor=ff7c7b7b +DSstateBackgroundColor=ff383838 +DSstatePreviewOutline=ffaaaaaa + DSchangedStateText=ff99ccff + DS3DAxisXColor=ffd00000 DS3DAxisYColor=ff009900 DS3DAxisZColor=ff5050ff + +DSactionBinding=ff2aafd3 +DSactionAlias=fff93a3a +DSactionKeyframe=ffe0e01b +DSactionJIT=ff2db543 + +DStableHeaderBackground=ffff0000 +DStableHeaderText=ff00ff00 + +DSdockContainerBackground=ff323232 +DSdockContainerSplitter=ff323232 +DSdockAreaBackground=ff262728 + +DSdockWidgetBackground=ff00ff00 +DSdockWidgetSplitter=ff595959 +DSdockWidgetTitleBar=ff1f1f1f + +DStitleBarText=ffdadada +DStitleBarIcon=ffffffff +DStitleBarButtonHover=40ffffff +DStitleBarButtonPress=60ffffff + +DStabContainerBackground=ff0000ff +DStabSplitter=ff595959 + +DStabInactiveBackground=ff1f1f1f +DStabInactiveText=ffdadada +DStabInactiveIcon=ffffffff +DStabInactiveButtonHover=ff1f1f1f +DStabInactiveButtonPress=ff1f1f1f + +DStabActiveBackground=ffdadada +DStabActiveText=ff111111 +DStabActiveIcon=ff000000 +DStabActiveButtonHover=ffdadada +DStabActiveButtonPress=ffdadada + +DStabFocusBackground=ff2aafd3 +DStabFocusText=ff111111 +DStabFocusIcon=ff000000 +DStabFocusButtonHover=ff2aafd3 +DStabFocusButtonPress=ff2aafd3 + +DSnavigatorBranch=ff7c7b7b +DSnavigatorBranchIndicator=ff7c7b7b +DSnavigatorItemBackground=ff262626 +DSnavigatorItemBackgroundHover=ff666666 +DSnavigatorItemBackgroundSelected=ff1f1f1f +DSnavigatorText=ffffffff +DSnavigatorTextHover=ff1f1f1f +DSnavigatorTextSelected=ff2aafd3 +DSnavigatorIcon=ffffffff +DSnavigatorIconHover=ff1f1f1f +DSnavigatorIconSelected=ff7c7b7b +DSnavigatorAliasIconChecked=ffff0000 +DSnavigatorDropIndicatorBackground=ff2aafd3 +DSnavigatorDropIndicatorOutline=ff2aafd3 + +DSheaderViewBackground=ff1f1f1f +DStableViewAlternateBackground=ff00ff00 + +DStoolTipBackground=ff111111 +DStoolTipOutline=ffdadada +DStoolTipText=ffdadada + ;DS controls theme END BackgroundColorAlternate=alternateBackground @@ -270,7 +360,7 @@ QmlDesigner_FormEditorForegroundColor=ffdadada ;background color for main form view, library, navigator, properties, connections ;QmlDesigner_BackgroundColorDarkAlternate=ff4c4e50 -QmlDesigner_BackgroundColorDarkAlternate=ff262626 +QmlDesigner_BackgroundColorDarkAlternate=ff323232 ;filter outlines, override W/H outlines, properties spinbox background, timeline separators. ;QmlDesigner_BackgroundColorDarker=ff262728 diff --git a/share/qtcreator/themes/flat-dark.creatortheme b/share/qtcreator/themes/flat-dark.creatortheme index 0d750afcf0d..aa9c150b1a5 100644 --- a/share/qtcreator/themes/flat-dark.creatortheme +++ b/share/qtcreator/themes/flat-dark.creatortheme @@ -26,44 +26,136 @@ backgroundColorDisabled=ff444444 qmlDesignerButtonColor=ff4c4e50 [Colors] - ;DS controls theme START -DScontrolBackground=ff404040 -DScontrolOutline=ff595959 -DStextColor=ffffffff -DSdisabledTextColor=ff909090 -DSpanelBackground=ff454444 -DShoverHighlight=ff313131 -DScolumnBackground=ff363636 -DSfocusEdit=ff444444 -DSfocusDrag=ff565656 -DScontrolBackgroundPressed=ff7a7a7a -DScontrolBackgroundChecked=ff565656 -DSinteraction=ff1d545c -DSsliderActiveTrack=ff7a7a7a -DSsliderInactiveTrack=ff4d4d4d -DSsliderHandle=ff505050 -DSsliderActiveTrackHover=ff7f7f7f -DSsliderInactiveTrackHover=ff505050 -DSsliderHandleHover=ff7a7a7a -DSsliderActiveTrackFocus=ffaaaaaa -DSsliderInactiveTrackFocus=ff7a7a7a -DSsliderHandleFocus=ff1d545c +DSpanelBackground=ff323232 + +DSinteraction=ff2aafd3 DSerrorColor=ffdf3a3a -DScontrolBackgroundDisabled=ff363636 -DScontrolOutlineDisabled=ff4d4d4d -DStextColorDisabled=ff7a7a7a -DStextSelectionColor=ff1d545c -DStextSelectedTextColor=ffffffff -DSscrollBarTrack=ff4d4d4d +DSdisabledColor=ff707070 + +DScontrolBackground=ff323232 +DScontrolBackgroundInteraction=ff595959 +DScontrolBackgroundDisabled=ff323232 +DScontrolBackgroundGlobalHover=ff474747 +DScontrolBackgroundHover=ff666666 + +DScontrolOutline=ff1f1f1f +DScontrolOutlineInteraction=ff2aafd3 +DScontrolOutlineDisabled=ff707070 + +DStextColor=ffffffff +DStextColorDisabled=ff707070 +DStextSelectionColor=ff2aafd3 +DStextSelectedTextColor=ff000000 + +DSplaceholderTextColor=ffffffff +DSplaceholderTextColorInteraction=ffababab + +DSiconColor=ffffffff +DSiconColorHover=ff262626 +DSiconColorInteraction=ff707070 +DSiconColorDisabled=ff707070 +DSiconColorSelected=ff2aafd3 + +DSlinkIndicatorColor=ff808080 +DSlinkIndicatorColorHover=ffffffff +DSlinkIndicatorColorInteraction=ff2aafd3 +DSlinkIndicatorColorDisabled=ff707070 + +DSpopupBackground=ff474747 +DSpopupOverlayColor=99191919 + +DSsliderActiveTrack=ff7c7b7b +DSsliderActiveTrackHover=ff000000 +DSsliderActiveTrackFocus=ffaaaaaa +DSsliderInactiveTrack=ff595959 +DSsliderInactiveTrackHover=ff505050 +DSsliderInactiveTrackFocus=ff606060 +DSsliderHandle=ff1f1f1f +DSsliderHandleHover=ff606060 +DSsliderHandleFocus=ff0492c9 +DSsliderHandleInteraction=ff2aafd3 + +DSscrollBarTrack=ff404040 DSscrollBarHandle=ff505050 -DScontrolBackgroundInteraction=ff4d4d4d -DStranslationIndicatorBorder=ff7f7f7f -DSsectionHeadBackground=ff424242 + +DSsectionHeadBackground=ff1f1f1f + +DSstateDefaultHighlight=ffffe400 +DSstateSeparatorColor=ff7c7b7b +DSstateBackgroundColor=ff383838 +DSstatePreviewOutline=ffaaaaaa + DSchangedStateText=ff99ccff -DS3DAxisXColor=ffe00000 + +DS3DAxisXColor=ffd00000 DS3DAxisYColor=ff009900 -DS3DAxisZColor=ff6060ff +DS3DAxisZColor=ff5050ff + +DSactionBinding=ff2aafd3 +DSactionAlias=fff93a3a +DSactionKeyframe=ffe0e01b +DSactionJIT=ff2db543 + +DStableHeaderBackground=ffff0000 +DStableHeaderText=ff00ff00 + +DSdockContainerBackground=ff323232 +DSdockContainerSplitter=ff323232 +DSdockAreaBackground=ff262728 + +DSdockWidgetBackground=ff00ff00 +DSdockWidgetSplitter=ff595959 +DSdockWidgetTitleBar=ff1f1f1f + +DStitleBarText=ffdadada +DStitleBarIcon=ffffffff +DStitleBarButtonHover=40ffffff +DStitleBarButtonPress=60ffffff + +DStabContainerBackground=ff0000ff +DStabSplitter=ff595959 + +DStabInactiveBackground=ff1f1f1f +DStabInactiveText=ffdadada +DStabInactiveIcon=ffffffff +DStabInactiveButtonHover=ff1f1f1f +DStabInactiveButtonPress=ff1f1f1f + +DStabActiveBackground=ffdadada +DStabActiveText=ff111111 +DStabActiveIcon=ff000000 +DStabActiveButtonHover=ffdadada +DStabActiveButtonPress=ffdadada + +DStabFocusBackground=ff2aafd3 +DStabFocusText=ff111111 +DStabFocusIcon=ff000000 +DStabFocusButtonHover=ff2aafd3 +DStabFocusButtonPress=ff2aafd3 + +DSnavigatorBranch=ff7c7b7b +DSnavigatorBranchIndicator=ff7c7b7b +DSnavigatorItemBackground=ff262626 +DSnavigatorItemBackgroundHover=ff666666 +DSnavigatorItemBackgroundSelected=ff1f1f1f +DSnavigatorText=ffffffff +DSnavigatorTextHover=ff1f1f1f +DSnavigatorTextSelected=ff2aafd3 +DSnavigatorIcon=ffffffff +DSnavigatorIconHover=ff1f1f1f +DSnavigatorIconSelected=ff7c7b7b +DSnavigatorAliasIconChecked=ffff0000 +DSnavigatorDropIndicatorBackground=ff2aafd3 +DSnavigatorDropIndicatorOutline=ff2aafd3 + +DSheaderViewBackground=ff1f1f1f +DStableViewAlternateBackground=ff00ff00 + +DStoolTipBackground=ff111111 +DStoolTipOutline=ffdadada +DStoolTipText=ffdadada + ;DS controls theme END BackgroundColorAlternate=alternateBackground @@ -245,7 +337,7 @@ QmlDesigner_BackgroundColor=qmlDesignerButtonColor QmlDesigner_HighlightColor=ff1d545c QmlDesigner_FormEditorSelectionColor=ff4ba2ff QmlDesigner_FormEditorForegroundColor=ffffffff -QmlDesigner_BackgroundColorDarkAlternate=qmlDesignerButtonColor +QmlDesigner_BackgroundColorDarkAlternate=ff323232 QmlDesigner_BackgroundColorDarker=ff262728 QmlDesigner_BorderColor=splitter QmlDesigner_ButtonColor=ff595b5c diff --git a/share/qtcreator/themes/flat-light.creatortheme b/share/qtcreator/themes/flat-light.creatortheme index 9c07ef1f6e7..21be06f7eef 100644 --- a/share/qtcreator/themes/flat-light.creatortheme +++ b/share/qtcreator/themes/flat-light.creatortheme @@ -22,44 +22,136 @@ warning=ffecbc1c qmlDesignerButtonColor=fff8f8f8 [Colors] - ;DS controls theme START -DScontrolBackground=ffffffff -DScontrolOutline=ff777777 -DStextColor=ff242424 -DSdisabledTextColor=ff505050 -DSpanelBackground=fff2f2f2 -DShoverHighlight=ffe6e6e6 -DScolumnBackground=ffaaaaaa -DSfocusEdit=ffeaeaea -DSfocusDrag=ffd1d1d1 -DScontrolBackgroundPressed=ff505050 -DScontrolBackgroundChecked=ff5e5e5e -DSinteraction=ff0492c9 -DSsliderActiveTrack=ff363636 -DSsliderInactiveTrack=ffe6e6e6 -DSsliderHandle=ff777777 -DSsliderActiveTrackHover=ff7f7f7f -DSsliderInactiveTrackHover=ff5e5e5e -DSsliderHandleHover=ff505050 -DSsliderActiveTrackFocus=ff363636 -DSsliderInactiveTrackFocus=ff505050 -DSsliderHandleFocus=ff0492c9 +DSpanelBackground=ffeaeaea + +DSinteraction=ff2aafd3 DSerrorColor=ffdf3a3a -DScontrolBackgroundDisabled=ffaaaaaa -DScontrolOutlineDisabled=ff777777 -DStextColorDisabled=ff505050 -DStextSelectionColor=ff0492c9 -DStextSelectedTextColor=ffffffff -DSscrollBarTrack=ff777777 -DSscrollBarHandle=ff505050 -DScontrolBackgroundInteraction=ff777777 -DStranslationIndicatorBorder=ffebebeb -DSsectionHeadBackground=ffebebeb +DSdisabledColor=ff8e8e8e + +DScontrolBackground=ffeaeaea +DScontrolBackgroundInteraction=ffc9c9c9 +DScontrolBackgroundDisabled=ff8e8e8e +DScontrolBackgroundGlobalHover=ffe5e5e5 +DScontrolBackgroundHover=ffd1d1d1 + +DScontrolOutline=ffcecccc +DScontrolOutlineInteraction=ff2aafd3 +DScontrolOutlineDisabled=ff707070 + +DStextColor=ff262626 +DStextColorDisabled=ff707070 +DStextSelectionColor=ff2aafd3 +DStextSelectedTextColor=ff000000 + +DSplaceholderTextColor=ff262626 +DSplaceholderTextColorInteraction=ffababab + +DSiconColor=ff262626 +DSiconColorHover=ff191919 +DSiconColorInteraction=ffffffff +DSiconColorDisabled=ff707070 +DSiconColorSelected=ff2aafd3 + +DSlinkIndicatorColor=ff808080 +DSlinkIndicatorColorHover=ff1f1f1f +DSlinkIndicatorColorInteraction=ff2aafd3 +DSlinkIndicatorColorDisabled=ff707070 + +DSpopupBackground=ffd3d3d3 +DSpopupOverlayColor=99191919 + +DSsliderActiveTrack=ff7c7b7b +DSsliderActiveTrackHover=ff000000 +DSsliderActiveTrackFocus=ffaaaaaa +DSsliderInactiveTrack=ffaaaaaa +DSsliderInactiveTrackHover=ff505050 +DSsliderInactiveTrackFocus=ff606060 +DSsliderHandle=ff1f1f1f +DSsliderHandleHover=ff606060 +DSsliderHandleFocus=ff0492c9 +DSsliderHandleInteraction=ff2aafd3 + +DSscrollBarTrack=ffb5b4b4 +DSscrollBarHandle=ff9b9b9b + +DSsectionHeadBackground=ffd8d8d8 + +DSstateDefaultHighlight=ffffe400 +DSstateSeparatorColor=ffadadad +DSstateBackgroundColor=ffe0e0e0 +DSstatePreviewOutline=ff363636 + DSchangedStateText=ff99ccff -DS3DAxisXColor=ffff0000 -DS3DAxisYColor=ff00A000 -DS3DAxisZColor=ff0000ff + +DS3DAxisXColor=ffd00000 +DS3DAxisYColor=ff009900 +DS3DAxisZColor=ff5050ff + +DSactionBinding=ff2aafd3 +DSactionAlias=fff93a3a +DSactionKeyframe=ffe0e01b +DSactionJIT=ff2db543 + +DStableHeaderBackground=ffff0000 +DStableHeaderText=ff00ff00 + +DSdockContainerBackground=ff323232 +DSdockContainerSplitter=ff323232 +DSdockAreaBackground=ff262728 + +DSdockWidgetBackground=ff00ff00 +DSdockWidgetSplitter=ff595959 +DSdockWidgetTitleBar=ffeaeaea + +DStitleBarText=ffdadada +DStitleBarIcon=f4f5052 +DStitleBarButtonHover=40ffffff +DStitleBarButtonPress=60ffffff + +DStabContainerBackground=ff0000ff +DStabSplitter=ff595959 + +DStabInactiveBackground=ff999999 +DStabInactiveText=ff262626 +DStabInactiveIcon=ffffffff +DStabInactiveButtonHover=ff1f1f1f +DStabInactiveButtonPress=ff1f1f1f + +DStabActiveBackground=ffdadada +DStabActiveText=ff111111 +DStabActiveIcon=ff000000 +DStabActiveButtonHover=ffdadada +DStabActiveButtonPress=ffdadada + +DStabFocusBackground=ff2aafd3 +DStabFocusText=ff111111 +DStabFocusIcon=ff000000 +DStabFocusButtonHover=ff2aafd3 +DStabFocusButtonPress=ff2aafd3 + +DSnavigatorBranch=ff7c7b7b +DSnavigatorBranchIndicator=ff7c7b7b +DSnavigatorItemBackground=ffd8d8d8 +DSnavigatorItemBackgroundHover=ffc2c2c2 +DSnavigatorItemBackgroundSelected=ffffffff +DSnavigatorText=ff262626 +DSnavigatorTextHover=ff1f1f1f +DSnavigatorTextSelected=ff2aafd3 +DSnavigatorIcon=ff1f1f1f +DSnavigatorIconHover=ff1f1f1f +DSnavigatorIconSelected=ff7c7b7b +DSnavigatorAliasIconChecked=ffff0000 +DSnavigatorDropIndicatorBackground=ff2aafd3 +DSnavigatorDropIndicatorOutline=ff2aafd3 + +DSheaderViewBackground=ffd8d8d8 +DStableViewAlternateBackground=ff00ff00 + +DStoolTipBackground=ff111111 +DStoolTipOutline=ffdadada +DStoolTipText=ffdadada + ;DS controls theme END BackgroundColorAlternate=alternateBackground @@ -241,7 +333,7 @@ QmlDesigner_BackgroundColor=qmlDesignerButtonColor QmlDesigner_HighlightColor=ff46a2da QmlDesigner_FormEditorSelectionColor=ff4ba2ff QmlDesigner_FormEditorForegroundColor=ffffffff -QmlDesigner_BackgroundColorDarkAlternate=qmlDesignerButtonColor +QmlDesigner_BackgroundColorDarkAlternate=ffeaeaea QmlDesigner_BackgroundColorDarker=fff5f5f5 QmlDesigner_BorderColor=splitter QmlDesigner_ButtonColor=ffcccccc diff --git a/share/qtcreator/themes/flat.creatortheme b/share/qtcreator/themes/flat.creatortheme index 2565972643e..25a582d17ec 100644 --- a/share/qtcreator/themes/flat.creatortheme +++ b/share/qtcreator/themes/flat.creatortheme @@ -20,44 +20,136 @@ splitter=ff313131 qmlDesignerButtonColor=ff4c4e50 [Colors] - ;DS controls theme START -DScontrolBackground=ff404040 -DScontrolOutline=ff595959 -DStextColor=ffffffff -DSdisabledTextColor=ff909090 -DSpanelBackground=ff454444 -DShoverHighlight=ff313131 -DScolumnBackground=ff363636 -DSfocusEdit=ff444444 -DSfocusDrag=ff565656 -DScontrolBackgroundPressed=ff7a7a7a -DScontrolBackgroundChecked=ff565656 -DSinteraction=ff3f91c4 -DSsliderActiveTrack=ff7a7a7a -DSsliderInactiveTrack=ff4d4d4d -DSsliderHandle=ff505050 -DSsliderActiveTrackHover=ff7f7f7f -DSsliderInactiveTrackHover=ff505050 -DSsliderHandleHover=ff7a7a7a -DSsliderActiveTrackFocus=ffaaaaaa -DSsliderInactiveTrackFocus=ff7a7a7a -DSsliderHandleFocus=ff3f91c4 +DSpanelBackground=ff323232 + +DSinteraction=ff2aafd3 DSerrorColor=ffdf3a3a -DScontrolBackgroundDisabled=ff363636 -DScontrolOutlineDisabled=ff4d4d4d -DStextColorDisabled=ff7a7a7a -DStextSelectionColor=ff3f91c4 -DStextSelectedTextColor=ffffffff -DSscrollBarTrack=ff4d4d4d +DSdisabledColor=ff707070 + +DScontrolBackground=ff323232 +DScontrolBackgroundInteraction=ff595959 +DScontrolBackgroundDisabled=ff323232 +DScontrolBackgroundGlobalHover=ff474747 +DScontrolBackgroundHover=ff666666 + +DScontrolOutline=ff1f1f1f +DScontrolOutlineInteraction=ff2aafd3 +DScontrolOutlineDisabled=ff707070 + +DStextColor=ffffffff +DStextColorDisabled=ff707070 +DStextSelectionColor=ff2aafd3 +DStextSelectedTextColor=ff000000 + +DSplaceholderTextColor=ffffffff +DSplaceholderTextColorInteraction=ffababab + +DSiconColor=ffffffff +DSiconColorHover=ff262626 +DSiconColorInteraction=ff707070 +DSiconColorDisabled=ff707070 +DSiconColorSelected=ff2aafd3 + +DSlinkIndicatorColor=ff808080 +DSlinkIndicatorColorHover=ffffffff +DSlinkIndicatorColorInteraction=ff2aafd3 +DSlinkIndicatorColorDisabled=ff707070 + +DSpopupBackground=ff474747 +DSpopupOverlayColor=99191919 + +DSsliderActiveTrack=ff7c7b7b +DSsliderActiveTrackHover=ff000000 +DSsliderActiveTrackFocus=ffaaaaaa +DSsliderInactiveTrack=ff595959 +DSsliderInactiveTrackHover=ff505050 +DSsliderInactiveTrackFocus=ff606060 +DSsliderHandle=ff1f1f1f +DSsliderHandleHover=ff606060 +DSsliderHandleFocus=ff0492c9 +DSsliderHandleInteraction=ff2aafd3 + +DSscrollBarTrack=ff404040 DSscrollBarHandle=ff505050 -DScontrolBackgroundInteraction=ff4d4d4d -DStranslationIndicatorBorder=ff7f7f7f -DSsectionHeadBackground=ff424242 + +DSsectionHeadBackground=ff1f1f1f + +DSstateDefaultHighlight=ffffe400 +DSstateSeparatorColor=ff7c7b7b +DSstateBackgroundColor=ff383838 +DSstatePreviewOutline=ffaaaaaa + DSchangedStateText=ff99ccff -DS3DAxisXColor=ffe00000 + +DS3DAxisXColor=ffd00000 DS3DAxisYColor=ff009900 -DS3DAxisZColor=ff6060ff +DS3DAxisZColor=ff5050ff + +DSactionBinding=ff2aafd3 +DSactionAlias=fff93a3a +DSactionKeyframe=ffe0e01b +DSactionJIT=ff2db543 + +DStableHeaderBackground=ffff0000 +DStableHeaderText=ff00ff00 + +DSdockContainerBackground=ff323232 +DSdockContainerSplitter=ff323232 +DSdockAreaBackground=ff262728 + +DSdockWidgetBackground=ff00ff00 +DSdockWidgetSplitter=ff595959 +DSdockWidgetTitleBar=ff1f1f1f + +DStitleBarText=ffdadada +DStitleBarIcon=ffffffff +DStitleBarButtonHover=40ffffff +DStitleBarButtonPress=60ffffff + +DStabContainerBackground=ff0000ff +DStabSplitter=ff595959 + +DStabInactiveBackground=ff1f1f1f +DStabInactiveText=ffdadada +DStabInactiveIcon=ffffffff +DStabInactiveButtonHover=ff1f1f1f +DStabInactiveButtonPress=ff1f1f1f + +DStabActiveBackground=ffdadada +DStabActiveText=ff111111 +DStabActiveIcon=ff000000 +DStabActiveButtonHover=ffdadada +DStabActiveButtonPress=ffdadada + +DStabFocusBackground=ff2aafd3 +DStabFocusText=ff111111 +DStabFocusIcon=ff000000 +DStabFocusButtonHover=ff2aafd3 +DStabFocusButtonPress=ff2aafd3 + +DSnavigatorBranch=ff7c7b7b +DSnavigatorBranchIndicator=ff7c7b7b +DSnavigatorItemBackground=ff262626 +DSnavigatorItemBackgroundHover=ff666666 +DSnavigatorItemBackgroundSelected=ff1f1f1f +DSnavigatorText=ffffffff +DSnavigatorTextHover=ff1f1f1f +DSnavigatorTextSelected=ff2aafd3 +DSnavigatorIcon=ffffffff +DSnavigatorIconHover=ff1f1f1f +DSnavigatorIconSelected=ff7c7b7b +DSnavigatorAliasIconChecked=ffff0000 +DSnavigatorDropIndicatorBackground=ff2aafd3 +DSnavigatorDropIndicatorOutline=ff2aafd3 + +DSheaderViewBackground=ff1f1f1f +DStableViewAlternateBackground=ff00ff00 + +DStoolTipBackground=ff111111 +DStoolTipOutline=ffdadada +DStoolTipText=ffdadada + ;DS controls theme END BackgroundColorAlternate=alternateBackground @@ -239,7 +331,7 @@ QmlDesigner_BackgroundColor=qmlDesignerButtonColor QmlDesigner_HighlightColor=ff46a2da QmlDesigner_FormEditorSelectionColor=ff4ba2ff QmlDesigner_FormEditorForegroundColor=ffffffff -QmlDesigner_BackgroundColorDarkAlternate=qmlDesignerButtonColor +QmlDesigner_BackgroundColorDarkAlternate=ff323232 QmlDesigner_BackgroundColorDarker=ff262728 QmlDesigner_BorderColor=splitter QmlDesigner_ButtonColor=ff595b5c diff --git a/src/libs/advanceddockingsystem/dockareatitlebar.cpp b/src/libs/advanceddockingsystem/dockareatitlebar.cpp index ba13cd7a8ab..79fca4487c2 100644 --- a/src/libs/advanceddockingsystem/dockareatitlebar.cpp +++ b/src/libs/advanceddockingsystem/dockareatitlebar.cpp @@ -133,12 +133,14 @@ namespace ADS void DockAreaTitleBarPrivate::createButtons() { - const QSize iconSize(14, 14); + const QSize iconSize(11, 11); + const QSize buttonSize(17, 17); QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + // Tabs menu button m_tabsMenuButton = new TitleBarButton(testConfigFlag(DockManager::DockAreaHasTabsMenuButton)); m_tabsMenuButton->setObjectName("tabsMenuButton"); - m_tabsMenuButton->setAutoRaise(true); + //m_tabsMenuButton->setAutoRaise(true); m_tabsMenuButton->setPopupMode(QToolButton::InstantPopup); internal::setButtonIcon(m_tabsMenuButton, QStyle::SP_TitleBarUnshadeButton, @@ -152,6 +154,7 @@ namespace ADS internal::setToolTip(m_tabsMenuButton, QObject::tr("List All Tabs")); m_tabsMenuButton->setSizePolicy(sizePolicy); m_tabsMenuButton->setIconSize(iconSize); + m_tabsMenuButton->setFixedSize(buttonSize); m_layout->addWidget(m_tabsMenuButton, 0); QObject::connect(m_tabsMenuButton->menu(), &QMenu::triggered, @@ -161,13 +164,14 @@ namespace ADS // Undock button m_undockButton = new TitleBarButton(testConfigFlag(DockManager::DockAreaHasUndockButton)); m_undockButton->setObjectName("detachGroupButton"); - m_undockButton->setAutoRaise(true); + //m_undockButton->setAutoRaise(true); internal::setToolTip(m_undockButton, QObject::tr("Detach Group")); internal::setButtonIcon(m_undockButton, QStyle::SP_TitleBarNormalButton, ADS::DockAreaUndockIcon); m_undockButton->setSizePolicy(sizePolicy); m_undockButton->setIconSize(iconSize); + m_undockButton->setFixedSize(buttonSize); m_layout->addWidget(m_undockButton, 0); QObject::connect(m_undockButton, &QToolButton::clicked, @@ -177,7 +181,7 @@ namespace ADS // Close button m_closeButton = new TitleBarButton(testConfigFlag(DockManager::DockAreaHasCloseButton)); m_closeButton->setObjectName("dockAreaCloseButton"); - m_closeButton->setAutoRaise(true); + //m_closeButton->setAutoRaise(true); internal::setButtonIcon(m_closeButton, QStyle::SP_TitleBarCloseButton, ADS::DockAreaCloseIcon); @@ -188,11 +192,14 @@ namespace ADS m_closeButton->setSizePolicy(sizePolicy); m_closeButton->setIconSize(iconSize); + m_closeButton->setFixedSize(buttonSize); m_layout->addWidget(m_closeButton, 0); QObject::connect(m_closeButton, &QToolButton::clicked, q, &DockAreaTitleBar::onCloseButtonClicked); + + m_layout->addSpacing(1); } void DockAreaTitleBarPrivate::createTabBar() diff --git a/src/libs/advanceddockingsystem/dockwidgettab.cpp b/src/libs/advanceddockingsystem/dockwidgettab.cpp index 7a4784b6e0d..680bc7d873e 100644 --- a/src/libs/advanceddockingsystem/dockwidgettab.cpp +++ b/src/libs/advanceddockingsystem/dockwidgettab.cpp @@ -45,6 +45,8 @@ #include "floatingdragpreview.h" #include "iconprovider.h" +#include + #include #include #include @@ -54,7 +56,10 @@ #include #include #include +#include #include +#include +#include #include @@ -81,7 +86,7 @@ namespace ADS eDragState m_dragState = DraggingInactive; AbstractFloatingWidget *m_floatingWidget = nullptr; QIcon m_icon; - QAbstractButton *m_closeButton = nullptr; + TabButton *m_closeButton = nullptr; QPoint m_tabDragStartPosition; /** @@ -122,8 +127,9 @@ namespace ADS /** * Creates the close button as QPushButton or as QToolButton */ - QAbstractButton *createCloseButton() const + TabButton *createCloseButton() const { + /* if (testConfigFlag(DockManager::TabCloseButtonIsToolButton)) { auto button = new QToolButton(); button->setAutoRaise(true); @@ -131,6 +137,8 @@ namespace ADS } else { return new QPushButton(); } + */ + return new TabButton(); } template @@ -179,7 +187,8 @@ namespace ADS QStyle::SP_TitleBarCloseButton, TabCloseIcon); m_closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - m_closeButton->setIconSize(QSize(14, 14)); + m_closeButton->setIconSize(QSize(11, 11)); + m_closeButton->setFixedSize(QSize(17, 17)); q->onDockWidgetFeaturesChanged(); internal::setToolTip(m_closeButton, QObject::tr("Close Tab")); QObject::connect(m_closeButton, @@ -196,9 +205,9 @@ namespace ADS boxLayout->setSpacing(0); q->setLayout(boxLayout); boxLayout->addWidget(m_titleLabel, 1, Qt::AlignVCenter); - boxLayout->addSpacing(spacing); - boxLayout->addWidget(m_closeButton, 0, Qt::AlignVCenter); boxLayout->addSpacing(qRound(spacing * 4.0 / 3.0)); + boxLayout->addWidget(m_closeButton, 0, Qt::AlignVCenter); + boxLayout->addSpacing(1); boxLayout->setAlignment(Qt::AlignCenter | Qt::AlignVCenter); if (DockManager::testConfigFlag(DockManager::FocusHighlighting)) @@ -263,6 +272,39 @@ namespace ADS return true; } + + TabButton::TabButton(QWidget *parent) + : TabButtonType(parent) + , m_active(false) + , m_focus(false) + {} + + void TabButton::setActive(bool value) { m_active = value; } + void TabButton::setFocus(bool value) { m_focus = value; } + + void TabButton::paintEvent(QPaintEvent *event) + { + Q_UNUSED(event) + + QStylePainter p(this); + QStyleOptionToolButton opt; + initStyleOption(&opt); + opt.icon = QIcon(); // set to null icon otherwise it is drawn twice + p.drawComplexControl(QStyle::CC_ToolButton, opt); + + QIcon::Mode mode = QIcon::Mode::Normal; + if (m_active) + mode = QIcon::Mode::Active; + if (m_focus) + mode = QIcon::Mode::Selected; + + const QPoint iconPosition = rect().center() - QPoint(iconSize().width() * 0.5, + iconSize().height() * 0.5); + + p.drawPixmap(iconPosition, icon().pixmap(iconSize(), mode)); + } + + DockWidgetTab::DockWidgetTab(DockWidget *dockWidget, QWidget *parent) : QFrame(parent) , d(new DockWidgetTabPrivate(this)) @@ -420,6 +462,8 @@ namespace ADS bool tabHasCloseButton = (activeTabHasCloseButton && active) | allTabsHaveCloseButton; d->m_closeButton->setVisible(dockWidgetClosable && tabHasCloseButton); + d->m_closeButton->setActive(active); + // Focus related stuff if (DockManager::testConfigFlag(DockManager::FocusHighlighting) && !d->m_dockWidget->dockManager()->isRestoringState()) { @@ -550,12 +594,8 @@ namespace ADS void DockWidgetTab::updateStyle() { - if (DockManager::testConfigFlag(DockManager::FocusHighlighting)) { - if (property("focused").toBool()) - d->m_closeButton->setChecked(true); - else - d->m_closeButton->setChecked(false); - } + if (DockManager::testConfigFlag(DockManager::FocusHighlighting)) + d->m_closeButton->setFocus(property("focused").toBool()); internal::repolishStyle(this, internal::RepolishDirectChildren); } diff --git a/src/libs/advanceddockingsystem/dockwidgettab.h b/src/libs/advanceddockingsystem/dockwidgettab.h index 15dd13582f1..482454b4b8b 100644 --- a/src/libs/advanceddockingsystem/dockwidgettab.h +++ b/src/libs/advanceddockingsystem/dockwidgettab.h @@ -38,6 +38,7 @@ #include "ads_globals.h" #include +#include namespace ADS { @@ -45,6 +46,28 @@ class DockWidget; class DockAreaWidget; class DockWidgetTabPrivate; +using TabButtonType = QToolButton; + +class TabButton : public TabButtonType +{ + Q_OBJECT + +public: + using Super = TabButtonType; + TabButton(QWidget *parent = nullptr); + + void setActive(bool value); + void setFocus(bool value); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + bool m_active; + bool m_focus; +}; + + /** * A dock widget tab that shows a title and an icon. * The dock widget tab is shown in the dock area title bar to switch between diff --git a/src/libs/advanceddockingsystem/elidinglabel.cpp b/src/libs/advanceddockingsystem/elidinglabel.cpp index 171eeaa18ee..47ada904610 100644 --- a/src/libs/advanceddockingsystem/elidinglabel.cpp +++ b/src/libs/advanceddockingsystem/elidinglabel.cpp @@ -39,7 +39,7 @@ namespace ADS { /** - * Private data of public ClickableLabel + * Private data of public ElidingLabel */ struct ElidingLabelPrivate { diff --git a/src/libs/advanceddockingsystem/linux/floatingwidgettitlebar.cpp b/src/libs/advanceddockingsystem/linux/floatingwidgettitlebar.cpp index 7393ae458fb..e55c0dd7b16 100644 --- a/src/libs/advanceddockingsystem/linux/floatingwidgettitlebar.cpp +++ b/src/libs/advanceddockingsystem/linux/floatingwidgettitlebar.cpp @@ -81,7 +81,8 @@ void FloatingWidgetTitleBarPrivate::createLayout() QStyle::SP_TitleBarCloseButton, ADS::FloatingWidgetCloseIcon); m_closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - m_closeButton->setIconSize(QSize(14, 14)); + m_closeButton->setIconSize(QSize(11, 11)); + m_closeButton->setFixedSize(QSize(17, 17)); m_closeButton->setVisible(true); m_closeButton->setFocusPolicy(Qt::NoFocus); QObject::connect(m_closeButton, @@ -100,6 +101,7 @@ void FloatingWidgetTitleBarPrivate::createLayout() layout->addWidget(m_titleLabel, 1); layout->addSpacing(spacing); layout->addWidget(m_closeButton); + layout->addSpacing(1); layout->setAlignment(Qt::AlignCenter); m_titleLabel->setVisible(true); diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h index a266c62bb5b..dd8735c4029 100644 --- a/src/libs/utils/theme/theme.h +++ b/src/libs/utils/theme/theme.h @@ -303,42 +303,121 @@ public: /* Palette for DS Controls */ - DScontrolBackground, - DScontrolOutline, - DStextColor, - DSdisabledTextColor, DSpanelBackground, - DShoverHighlight, - DScolumnBackground, - DSfocusEdit, - DSfocusDrag, - DScontrolBackgroundPressed, - DScontrolBackgroundChecked, DSinteraction, - DSsliderActiveTrack, - DSsliderInactiveTrack, - DSsliderHandle, - DSsliderActiveTrackHover, - DSsliderInactiveTrackHover, - DSsliderHandleHover, - DSsliderActiveTrackFocus, - DSsliderInactiveTrackFocus, - DSsliderHandleFocus, DSerrorColor, + DSdisabledColor, + DScontrolBackground, + DScontrolBackgroundInteraction, DScontrolBackgroundDisabled, + DScontrolBackgroundGlobalHover, + DScontrolBackgroundHover, + DScontrolOutline, + DScontrolOutlineInteraction, DScontrolOutlineDisabled, + DStextColor, DStextColorDisabled, DStextSelectionColor, DStextSelectedTextColor, + + DSplaceholderTextColor, + DSplaceholderTextColorInteraction, + + DSiconColor, + DSiconColorHover, + DSiconColorInteraction, + DSiconColorDisabled, + DSiconColorSelected, + DSlinkIndicatorColor, + DSlinkIndicatorColorHover, + DSlinkIndicatorColorInteraction, + DSlinkIndicatorColorDisabled, + DSpopupBackground, + DSpopupOverlayColor, + DSsliderActiveTrack, + DSsliderActiveTrackHover, + DSsliderActiveTrackFocus, + DSsliderInactiveTrack, + DSsliderInactiveTrackHover, + DSsliderInactiveTrackFocus, + DSsliderHandle, + DSsliderHandleHover, + DSsliderHandleFocus, + DSsliderHandleInteraction, DSscrollBarTrack, DSscrollBarHandle, - DScontrolBackgroundInteraction, - DStranslationIndicatorBorder, DSsectionHeadBackground, + DSstateDefaultHighlight, + DSstateSeparatorColor, + DSstateBackgroundColor, + DSstatePreviewOutline, DSchangedStateText, DS3DAxisXColor, DS3DAxisYColor, - DS3DAxisZColor + DS3DAxisZColor, + DSactionBinding, + DSactionAlias, + DSactionKeyframe, + DSactionJIT, + + DStableHeaderBackground, + DStableHeaderText, + + DSdockContainerBackground, + DSdockContainerSplitter, + DSdockAreaBackground, + + DSdockWidgetBackground, + DSdockWidgetSplitter, + DSdockWidgetTitleBar, + + DStitleBarText, + DStitleBarIcon, + DStitleBarButtonHover, + DStitleBarButtonPress, + + DStabContainerBackground, + DStabSplitter, + + DStabInactiveBackground, + DStabInactiveText, + DStabInactiveIcon, + DStabInactiveButtonHover, + DStabInactiveButtonPress, + + DStabActiveBackground, + DStabActiveText, + DStabActiveIcon, + DStabActiveButtonHover, + DStabActiveButtonPress, + + DStabFocusBackground, + DStabFocusText, + DStabFocusIcon, + DStabFocusButtonHover, + DStabFocusButtonPress, + + DSnavigatorBranch, + DSnavigatorBranchIndicator, + DSnavigatorItemBackground, + DSnavigatorItemBackgroundHover, + DSnavigatorItemBackgroundSelected, + DSnavigatorText, + DSnavigatorTextHover, + DSnavigatorTextSelected, + DSnavigatorIcon, + DSnavigatorIconHover, + DSnavigatorIconSelected, + DSnavigatorAliasIconChecked, + DSnavigatorDropIndicatorBackground, + DSnavigatorDropIndicatorOutline, + + DSheaderViewBackground, + DStableViewAlternateBackground, + + DStoolTipBackground, + DStoolTipOutline, + DStoolTipText }; enum Gradient { diff --git a/src/plugins/qmldesigner/components/componentcore/theme.cpp b/src/plugins/qmldesigner/components/componentcore/theme.cpp index 7f11f513b71..2c31414db33 100644 --- a/src/plugins/qmldesigner/components/componentcore/theme.cpp +++ b/src/plugins/qmldesigner/components/componentcore/theme.cpp @@ -76,7 +76,7 @@ QColor Theme::evaluateColorAtThemeInstance(const QString &themeColorName) const QMetaEnum e = m.enumerator(m.indexOfEnumerator("Color")); for (int i = 0, total = e.keyCount(); i < total; ++i) { if (QString::fromLatin1(e.key(i)) == themeColorName) - return color(static_cast(i)).name(); + return color(static_cast(i)); } qWarning() << Q_FUNC_INFO << "error while evaluating" << themeColorName; @@ -101,14 +101,21 @@ QString Theme::replaceCssColors(const QString &input) while (it.hasNext()) { const QRegularExpressionMatch match = it.next(); const QString themeColorName = match.captured(1); + const QRegularExpression replaceExp("creatorTheme\\." + themeColorName + "(\\s|;|\\n)"); if (themeColorName == "smallFontPixelSize") { - output.replace("creatorTheme." + themeColorName, QString::number(instance()->smallFontPixelSize()) + "px"); + output.replace(replaceExp, + QString::number(instance()->smallFontPixelSize()) + "px" + "\\1"); } else if (themeColorName == "captionFontPixelSize") { - output.replace("creatorTheme." + themeColorName, QString::number(instance()->captionFontPixelSize()) + "px"); + output.replace(replaceExp, + QString::number(instance()->captionFontPixelSize()) + "px" + "\\1"); } else { const QColor color = instance()->evaluateColorAtThemeInstance(themeColorName); - output.replace("creatorTheme." + themeColorName, color.name()); + // Create rgba(r, g, b, a) + const QString rgbaStr = QString("rgba(%1, %2, %3, %4)") + .arg(color.red()).arg(color.green()).arg(color.blue()) + .arg(color.alpha()); + output.replace(replaceExp, rgbaStr + "\\1"); } pos += match.capturedLength(); } diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.ui b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.ui index e1839f581e5..40939468c5e 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.ui +++ b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.ui @@ -18,7 +18,7 @@ 0 - 0 + 1 0 @@ -43,13 +43,13 @@ 0 - 4 + 2 16777215 - 4 + 2 @@ -244,7 +244,7 @@ - + stackedWidget diff --git a/src/plugins/qmldesigner/components/connectioneditor/stylesheet.css b/src/plugins/qmldesigner/components/connectioneditor/stylesheet.css index 879d089f9fd..0fbd4f191cb 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/stylesheet.css +++ b/src/plugins/qmldesigner/components/connectioneditor/stylesheet.css @@ -1,71 +1,64 @@ -QFrame -{ - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; - color: creatorTheme.PanelTextColorLight; +QFrame { + background-color: creatorTheme.DSpanelBackground; + color: creatorTheme.DStextColor; font-size: creatorTheme.captionFontPixelSize; border-radius: 0px; } QTableView { - color: creatorTheme.PanelTextColorLight; - selection-color: creatorTheme.PanelTextColorLight; - selection-background-color: creatorTheme.QmlDesigner_HighlightColor; - + color: creatorTheme.DStextColor; + selection-color: creatorTheme.DStextSelectedTextColor; + selection-background-color: creatorTheme.DStextSelectionColor; } QTabBar QToolButton { - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; + background-color: creatorTheme.DSpanelBackground; border: 1px solid creatorTheme.QmlDesigner_BackgroundColorDarker; border-radius: 0px; } -QTableView::item -{ +QTableView::item { border: 0px; padding-left: 4px; } -QTableView::item:focus -{ +QTableView::item:focus { border: none; background-color: transparent; } -QTableView::item:selected -{ +QTableView::item:selected { border: none } QHeaderView::section { - background-color: #494949; + background-color: creatorTheme.DSheaderViewBackground; border: 0px; color: creatorTheme.DStextColor; margin-right: 1px } QTableView { - alternate-background-color: #414141; + alternate-background-color: creatorTheme.DStableViewAlternateBackground; } QWidget#widgetSpacer { - background-color: creatorTheme.QmlDesigner_TabLight; + background-color: creatorTheme.DStabActiveBackground; } QStackedWidget { border: 0px; - background-color: creatorTheme.QmlDesigner_TabLight; + background-color: creatorTheme.DStabActiveBackground; } QTabBar::tab:selected { border: none; border-image: none; image: none; - - background-color: creatorTheme.QmlDesigner_TabLight; - color: creatorTheme.QmlDesigner_TabDark; + background-color: creatorTheme.DStabActiveBackground; + color: creatorTheme.DStabActiveText; } - QTabBar::tab { width: 92px; height: 22px; @@ -75,48 +68,62 @@ QTabBar::tab { margin-right: 0px; font: bold; font-size: creatorTheme.captionFontPixelSize; - background-color: creatorTheme.QmlDesigner_TabDark; - color: creatorTheme.QmlDesigner_TabLight; + background-color: creatorTheme.DStabInactiveBackground; + color: creatorTheme.DStabInactiveText; } -QSpinBox -{ +/* +QSpinBox { font-size: creatorTheme.captionFontPixelSize; - color: white; + color: creatorTheme.DStextColor; padding-right: 2px; padding-top: 2px; padding-bottom: 2px; padding-left: 12px; - border: 2px solid #0F0F0F; - border-width: 1; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #2c2c2c, stop: 1 #333333); - - min-height: 22px; -} - - QDoubleSpinBox - { - font-size: creatorTheme.captionFontPixelSize; - color: white; - padding-right: 2px; - padding-top: 2px; - padding-bottom: 2px; - padding-left: 12px; - border: 2px solid #0F0F0F; - border-width: 1; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #2c2c2c, stop: 1 #333333); + border: 1px solid creatorTheme.DScontrolOutline; + background-color: creatorTheme.DScontrolBackground; min-height: 22px; - } - -QLineEdit -{ - color: white; - font-size: creatorTheme.captionFontPixelSize; - border: 2px solid #0F0F0F; - border-width: 1; - min-height: 26px; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #2c2c2c, stop: 1 #333333); +} + +QDoubleSpinBox { + font-size: creatorTheme.captionFontPixelSize; + color: creatorTheme.DStextColor; + padding-right: 2px; + padding-top: 2px; + padding-bottom: 2px; + padding-left: 12px; + border: 1px solid creatorTheme.DScontrolOutline; + background-color: creatorTheme.DScontrolBackground; + min-height: 22px; +} +*/ + +QLineEdit { + color: creatorTheme.DStextColor; + selection-color: creatorTheme.DStextSelectedTextColor; + selection-background-color: creatorTheme.DStextSelectionColor; + font-size: creatorTheme.captionFontPixelSize; + border: 1px solid creatorTheme.DScontrolOutline; + min-height: 26px; + background-color: creatorTheme.DScontrolBackground; +} + +QComboBox { + color: creatorTheme.DStextColor; + selection-color: creatorTheme.DStextSelectedTextColor; + selection-background-color: creatorTheme.DStextSelectionColor; + font-size: creatorTheme.captionFontPixelSize; + border: 1px solid creatorTheme.DScontrolOutline; + min-height: 26px; + background-color: creatorTheme.DScontrolBackground; +} + +QComboBox QAbstractItemView { + show-decoration-selected: 1; /* make the selection span the entire width of the view */ + background-color: creatorTheme.DSpopupBackground; /* sets background of the menu */ + border: 1px solid creatorTheme.DScontrolOutline; + margin: 0px; /* some spacing around the menu */ + color: creatorTheme.DStextColor; + selection-color: creatorTheme.DStextSelectedTextColor; + selection-background-color: creatorTheme.DSinteraction; } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 1fcaadb5634..278bc934e37 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -144,13 +144,14 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache, m_headerWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); Theme::setupTheme(m_headerWidget->engine()); m_headerWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); - m_headerWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate)); + m_headerWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground)); m_headerWidget->rootContext()->setContextProperty("rootView", QVariant::fromValue(this)); // create add imports widget m_addImportWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); - m_addImportWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate)); Theme::setupTheme(m_addImportWidget->engine()); + m_addImportWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); + m_addImportWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground)); m_addImportWidget->rootContext()->setContextProperties({ {"addImportModel", QVariant::fromValue(m_itemLibraryAddImportModel.data())}, {"rootView", QVariant::fromValue(this)}, @@ -172,7 +173,7 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache, m_itemViewQuickWidget->rootContext()->setContextProperty("tooltipBackend", m_previewTooltipBackend.get()); - m_itemViewQuickWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_ButtonColor)); + m_itemViewQuickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground)); m_itemViewQuickWidget->engine()->addImageProvider(QStringLiteral("qmldesigner_itemlibrary"), new Internal::ItemLibraryImageProvider); Theme::setupTheme(m_itemViewQuickWidget->engine()); diff --git a/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.cpp b/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.cpp index 953dfdf1937..d0e1fa69d28 100644 --- a/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.cpp +++ b/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.cpp @@ -45,12 +45,9 @@ namespace QmlDesigner { -IconCheckboxItemDelegate::IconCheckboxItemDelegate(QObject *parent, - const QIcon &checkedIcon, - const QIcon &uncheckedIcon) +IconCheckboxItemDelegate::IconCheckboxItemDelegate(QObject *parent, const QIcon &icon) : QStyledItemDelegate(parent), - m_checkedIcon(checkedIcon), - m_uncheckedIcon(uncheckedIcon) + m_icon(icon) {} QSize IconCheckboxItemDelegate::sizeHint(const QStyleOptionViewItem & /*option*/, @@ -83,12 +80,18 @@ void IconCheckboxItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &styleOption, const QModelIndex &modelIndex) const { - if (styleOption.state & QStyle::State_MouseOver && !isThisOrAncestorLocked(modelIndex)) - painter->fillRect(styleOption.rect.adjusted(0, delegateMargin, 0, -delegateMargin), - Theme::getColor(Theme::Color::DSsliderHandle)); + QIcon::Mode mode = QIcon::Mode::Normal; - if (styleOption.state & QStyle::State_Selected) + if (styleOption.state & QStyle::State_MouseOver && !isThisOrAncestorLocked(modelIndex)) { + painter->fillRect(styleOption.rect.adjusted(0, delegateMargin, 0, -delegateMargin), + Theme::getColor(Theme::Color::DSnavigatorItemBackgroundHover)); + mode = QIcon::Mode::Active; // hover + } + + if (styleOption.state & QStyle::State_Selected) { NavigatorTreeView::drawSelectionBackground(painter, styleOption); + mode = QIcon::Mode::Selected; + } bool isVisibilityIcon = modelIndex.column() != NavigatorTreeModel::ColumnType::Visibility; // We need to invert the check status if visibility icon @@ -106,8 +109,8 @@ void IconCheckboxItemDelegate::paint(QPainter *painter, const QPoint iconPosition(styleOption.rect.left() + (styleOption.rect.width() - iconSize.width()) / 2, styleOption.rect.top() + 2 + delegateMargin); - const QIcon &icon = isChecked(modelIndex) ? m_checkedIcon : m_uncheckedIcon; - const QPixmap iconPixmap = icon.pixmap(window, iconSize); + const QIcon::State state = isChecked(modelIndex) ? QIcon::State::On : QIcon::State::Off; + const QPixmap iconPixmap = m_icon.pixmap(window, iconSize, mode, state); painter->save(); diff --git a/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.h b/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.h index 4f77e42c97a..1101d3c9881 100644 --- a/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.h +++ b/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.h @@ -34,9 +34,7 @@ class NavigatorTreeModel; class IconCheckboxItemDelegate : public QStyledItemDelegate { public: - explicit IconCheckboxItemDelegate(QObject *parent, - const QIcon &checkedIcon, - const QIcon &uncheckedIcon); + explicit IconCheckboxItemDelegate(QObject *parent, const QIcon &icon); QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; @@ -52,7 +50,6 @@ protected: const QModelIndex &index) override; private: - const QIcon m_checkedIcon; - const QIcon m_uncheckedIcon; + const QIcon m_icon; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp b/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp index 3d22e128eac..88c5d9d46cd 100644 --- a/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp +++ b/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp @@ -217,12 +217,18 @@ void NameItemDelegate::paint(QPainter *painter, { painter->save(); - if (styleOption.state & QStyle::State_MouseOver && !isThisOrAncestorLocked(modelIndex)) - painter->fillRect(styleOption.rect.adjusted(0, delegateMargin, 0, -delegateMargin), - Theme::getColor(Theme::Color::DSsliderHandle)); + painter->setPen(Theme::getColor(Theme::Color::DSnavigatorText)); - if (styleOption.state & QStyle::State_Selected) + if (styleOption.state & QStyle::State_MouseOver && !isThisOrAncestorLocked(modelIndex)) { + painter->fillRect(styleOption.rect.adjusted(0, delegateMargin, 0, -delegateMargin), + Theme::getColor(Theme::Color::DSnavigatorItemBackgroundHover)); + painter->setPen(Theme::getColor(Theme::Color::DSnavigatorTextHover)); + } + + if (styleOption.state & QStyle::State_Selected) { NavigatorTreeView::drawSelectionBackground(painter, styleOption); + painter->setPen(Theme::getColor(Theme::Color::DSnavigatorTextSelected)); + } iconOffset = drawIcon(painter, styleOption, modelIndex); diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp index 1d8052c9a11..3327fefcb44 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp @@ -74,7 +74,7 @@ public: mouseOverStateSavedFrameRectangle = option->rect; painter->fillRect(option->rect.adjusted(0, delegateMargin, 0, -delegateMargin), - Theme::getColor(Theme::Color::QmlDesigner_BorderColor)); + Theme::getColor(Theme::Color::DSnavigatorItemBackground)); } else if (element == PE_IndicatorItemViewItemDrop) { // between elements and on elements we have a width if (option->rect.width() > 0) { @@ -101,7 +101,8 @@ public: int bef_v = mid_v; int aft_h = mid_h; int aft_v = mid_v; - QBrush brush(Theme::getColor(Theme::Color::DSsliderHandle), Qt::SolidPattern); + + QBrush brush(Theme::getColor(Theme::Color::DSnavigatorBranch), Qt::SolidPattern); if (option->state & State_Item) { if (option->direction == Qt::RightToLeft) painter->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush); @@ -116,11 +117,11 @@ public: int delta = decoration_size / 2; bef_h -= delta; bef_v -= delta; - aft_h += delta; - aft_v += delta; + //aft_h += delta; + //aft_v += delta; const QRectF rect(bef_h, bef_v, decoration_size + 1, decoration_size + 1); - painter->fillRect(rect, QBrush(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate))); + painter->fillRect(rect, QBrush(Theme::getColor(Theme::Color::DSpanelBackground))); static const QPointF collapsePoints[3] = { QPointF(0.0, 0.0), @@ -134,7 +135,7 @@ public: QPointF(4.0, 4.0) }; - auto color = Theme::getColor(Theme::Color::IconsBaseColor); + auto color = Theme::getColor(Theme::Color::DSnavigatorBranchIndicator); painter->setPen(color); painter->setBrush(color); @@ -167,23 +168,15 @@ public: private: // functions QColor highlightBrushColor() const { - QColor highlightBrushColor = m_currentTextColor; - highlightBrushColor.setAlphaF(0.7); - return highlightBrushColor; + QColor color = Theme::getColor(Theme::Color::DSnavigatorDropIndicatorBackground); + color.setAlphaF(0.7); + return color; } QColor highlightLineColor() const { - return highlightBrushColor().lighter(); - } - QColor backgroundBrushColor() const - { - QColor backgroundBrushColor = highlightBrushColor(); - backgroundBrushColor.setAlphaF(0.2); - return backgroundBrushColor; - } - QColor backgroundLineColor() const - { - return backgroundBrushColor().lighter(); + QColor color = Theme::getColor(Theme::Color::DSnavigatorDropIndicatorOutline); + color.setAlphaF(0.7); + return color; } void drawHighlightFrame(const QRect &frameRectangle, QPainter *painter) const @@ -192,12 +185,7 @@ private: // functions painter->setBrush(highlightBrushColor()); painter->drawRect(frameRectangle); } - void drawBackgroundFrame(const QRect &frameRectangle, QPainter *painter) const - { - painter->setPen(QPen(backgroundLineColor(), 2)); - painter->setBrush(backgroundBrushColor()); - painter->drawRect(frameRectangle); - } + void drawIndicatorLine(const QPoint &leftPoint, const QPoint &rightPoint, QPainter *painter) const { painter->setPen(QPen(highlightLineColor(), 3)); @@ -231,7 +219,7 @@ void NavigatorTreeView::drawSelectionBackground(QPainter *painter, const QStyleO { painter->save(); painter->fillRect(option.rect.adjusted(0, delegateMargin, 0, -delegateMargin), - Theme::getColor(Theme::Color::QmlDesigner_HighlightColor)); + Theme::getColor(Theme::Color::DSnavigatorItemBackgroundSelected)); painter->restore(); } diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp index d095dc8501b..b3440777881 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp @@ -615,44 +615,85 @@ void NavigatorView::setupWidget() #ifndef QMLDESIGNER_TEST const QString fontName = "qtds_propertyIconFont.ttf"; + const QSize size = QSize(28, 28); - const QIcon visibilityOnIcon = - Utils::StyleHelper::getIconFromIconFont(fontName, - Theme::getIconUnicode(Theme::Icon::visibilityOn), - 20, 20, QColor(Qt::white)); - const QIcon visibilityOffIcon = - Utils::StyleHelper::getIconFromIconFont(fontName, - Theme::getIconUnicode(Theme::Icon::visibilityOff), - 20, 20, QColor(Qt::white)); + const QString visibilityOnUnicode = Theme::getIconUnicode(Theme::Icon::visibilityOn); + const QString visibilityOffUnicode = Theme::getIconUnicode(Theme::Icon::visibilityOff); - const QIcon aliasOnIcon = - Utils::StyleHelper::getIconFromIconFont(fontName, - Theme::getIconUnicode(Theme::Icon::idAliasOn), - 20, 20, QColor(Qt::red)); - const QIcon aliasOffIcon = - Utils::StyleHelper::getIconFromIconFont(fontName, - Theme::getIconUnicode(Theme::Icon::idAliasOff), - 20, 20, QColor(Qt::white)); + const QString aliasOnUnicode = Theme::getIconUnicode(Theme::Icon::idAliasOn); + const QString aliasOffUnicode = Theme::getIconUnicode(Theme::Icon::idAliasOff); - const QIcon lockOnIcon = - Utils::StyleHelper::getIconFromIconFont(fontName, - Theme::getIconUnicode(Theme::Icon::lockOn), - 20, 20, QColor(Qt::white)); - const QIcon lockOffIcon = - Utils::StyleHelper::getIconFromIconFont(fontName, - Theme::getIconUnicode(Theme::Icon::lockOff), - 20, 20, QColor(Qt::white)); + const QString lockOnUnicode = Theme::getIconUnicode(Theme::Icon::lockOn); + const QString lockOffUnicode = Theme::getIconUnicode(Theme::Icon::lockOff); + + auto visibilityIconOffNormal = Utils::StyleHelper::IconFontHelper( + visibilityOffUnicode, Theme::getColor(Theme::DSnavigatorIcon), size, QIcon::Normal, QIcon::Off); + auto visibilityIconOffHover = Utils::StyleHelper::IconFontHelper( + visibilityOffUnicode, Theme::getColor(Theme::DSnavigatorIconHover), size, QIcon::Active, QIcon::Off); + auto visibilityIconOffSelected = Utils::StyleHelper::IconFontHelper( + visibilityOffUnicode, Theme::getColor(Theme::DSnavigatorIconSelected), size, QIcon::Selected, QIcon::Off); + auto visibilityIconOnNormal = Utils::StyleHelper::IconFontHelper( + visibilityOnUnicode, Theme::getColor(Theme::DSnavigatorIcon), size, QIcon::Normal, QIcon::On); + auto visibilityIconOnHover = Utils::StyleHelper::IconFontHelper( + visibilityOnUnicode, Theme::getColor(Theme::DSnavigatorIconHover), size, QIcon::Active, QIcon::On); + auto visibilityIconOnSelected = Utils::StyleHelper::IconFontHelper( + visibilityOnUnicode, Theme::getColor(Theme::DSnavigatorIconSelected), size, QIcon::Selected, QIcon::On); + + const QIcon visibilityIcon = Utils::StyleHelper::getIconFromIconFont( + fontName, {visibilityIconOffNormal, + visibilityIconOffHover, + visibilityIconOffSelected, + visibilityIconOnNormal, + visibilityIconOnHover, + visibilityIconOnSelected}); + + auto aliasIconOffNormal = Utils::StyleHelper::IconFontHelper( + aliasOffUnicode, Theme::getColor(Theme::DSnavigatorIcon), size, QIcon::Normal, QIcon::Off); + auto aliasIconOffHover = Utils::StyleHelper::IconFontHelper( + aliasOffUnicode, Theme::getColor(Theme::DSnavigatorIconHover), size, QIcon::Active, QIcon::Off); + auto aliasIconOffSelected = Utils::StyleHelper::IconFontHelper( + aliasOffUnicode, Theme::getColor(Theme::DSnavigatorIconSelected), size, QIcon::Selected, QIcon::Off); + auto aliasIconOnNormal = Utils::StyleHelper::IconFontHelper( + aliasOnUnicode, Theme::getColor(Theme::DSnavigatorAliasIconChecked), size, QIcon::Normal, QIcon::On); + auto aliasIconOnHover = Utils::StyleHelper::IconFontHelper( + aliasOnUnicode, Theme::getColor(Theme::DSnavigatorAliasIconChecked), size, QIcon::Active, QIcon::On); + auto aliasIconOnSelected = Utils::StyleHelper::IconFontHelper( + aliasOnUnicode, Theme::getColor(Theme::DSnavigatorAliasIconChecked), size, QIcon::Selected, QIcon::On); + + const QIcon aliasIcon = Utils::StyleHelper::getIconFromIconFont( + fontName, {aliasIconOffNormal, + aliasIconOffHover, + aliasIconOffSelected, + aliasIconOnNormal, + aliasIconOnHover, + aliasIconOnSelected}); + + auto lockIconOffNormal = Utils::StyleHelper::IconFontHelper( + lockOffUnicode, Theme::getColor(Theme::DSnavigatorIcon), size, QIcon::Normal, QIcon::Off); + auto lockIconOffHover = Utils::StyleHelper::IconFontHelper( + lockOffUnicode, Theme::getColor(Theme::DSnavigatorIconHover), size, QIcon::Active, QIcon::Off); + auto lockIconOffSelected = Utils::StyleHelper::IconFontHelper( + lockOffUnicode, Theme::getColor(Theme::DSnavigatorIconSelected), size, QIcon::Selected, QIcon::Off); + auto lockIconOnNormal = Utils::StyleHelper::IconFontHelper( + lockOnUnicode, Theme::getColor(Theme::DSnavigatorIcon), size, QIcon::Normal, QIcon::On); + auto lockIconOnHover = Utils::StyleHelper::IconFontHelper( + lockOnUnicode, Theme::getColor(Theme::DSnavigatorIconHover), size, QIcon::Active, QIcon::On); + auto lockIconOnSelected = Utils::StyleHelper::IconFontHelper( + lockOnUnicode, Theme::getColor(Theme::DSnavigatorIconSelected), size, QIcon::Selected, QIcon::On); + + const QIcon lockIcon = Utils::StyleHelper::getIconFromIconFont( + fontName, {lockIconOffNormal, + lockIconOffHover, + lockIconOffSelected, + lockIconOnNormal, + lockIconOnHover, + lockIconOnSelected}); auto idDelegate = new NameItemDelegate(this); - IconCheckboxItemDelegate *visibilityDelegate = - new IconCheckboxItemDelegate(this, visibilityOnIcon, visibilityOffIcon); - - IconCheckboxItemDelegate *aliasDelegate = - new IconCheckboxItemDelegate(this, aliasOnIcon, aliasOffIcon); - - IconCheckboxItemDelegate *lockDelegate = - new IconCheckboxItemDelegate(this, lockOnIcon, lockOffIcon); + auto visibilityDelegate = new IconCheckboxItemDelegate(this, visibilityIcon); + auto aliasDelegate = new IconCheckboxItemDelegate(this, aliasIcon); + auto lockDelegate = new IconCheckboxItemDelegate(this, lockIcon); treeWidget()->setItemDelegateForColumn(NavigatorTreeModel::ColumnType::Name, idDelegate); treeWidget()->setItemDelegateForColumn(NavigatorTreeModel::ColumnType::Alias, aliasDelegate); diff --git a/src/plugins/qmldesigner/components/resources/dockwidgets.css b/src/plugins/qmldesigner/components/resources/dockwidgets.css index 7205c051e23..84865f47491 100644 --- a/src/plugins/qmldesigner/components/resources/dockwidgets.css +++ b/src/plugins/qmldesigner/components/resources/dockwidgets.css @@ -1,112 +1,119 @@ -ADS--DockContainerWidget -{ - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; +ADS--DockContainerWidget { + background: creatorTheme.DSdockContainerBackground; } -ADS--DockContainerWidget QSplitter::handle -{ - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; +ADS--DockContainerWidget QSplitter::handle { + background: creatorTheme.DSdockContainerSplitter; } -ADS--DockAreaWidget -{ - background-color: creatorTheme.BackgroundColorNormal; +ADS--DockAreaWidget { + background: creatorTheme.DSdockAreaBackground; } -ADS--DockAreaWidget #tabsMenuButton::menu-indicator -{ +ADS--DockAreaWidget #tabsMenuButton::menu-indicator { image: none; } ADS--DockSplitter::handle:horizontal { width: 1px; - background-color: creatorTheme.SplitterColor; + background: creatorTheme.DSdockWidgetSplitter; } ADS--DockSplitter::handle:vertical { height: 1px; - background-color: creatorTheme.SplitterColor; + background: creatorTheme.DSdockWidgetSplitter; } -ADS--DockWidgetTab -{ - background-color: creatorTheme.BackgroundColorDark; - border-color: creatorTheme.SplitterColor; +ADS--DockWidgetTab { + background-color: creatorTheme.DStabInactiveBackground; + border-color: creatorTheme.DStabSplitter; border-style: solid; border-width: 0 1px 0 0; } -ADS--DockWidgetTab[activeTab="true"] -{ - background-color: creatorTheme.QmlDesigner_TabLight; +ADS--DockWidgetTab QLabel { + color: creatorTheme.DStabInactiveText; } -ADS--DockWidgetTab QLabel -{ - color: creatorTheme.QmlDesigner_TabLight; +ADS--DockWidgetTab[activeTab="true"] { + background: creatorTheme.DStabActiveBackground; } -ADS--DockWidgetTab[activeTab="true"] QLabel -{ - color: creatorTheme.QmlDesigner_TabDark; +ADS--DockWidgetTab[activeTab="true"] QLabel { + color: creatorTheme.DStabActiveText; } -ADS--DockWidget -{ - background-color: palette(light); - border-color: red; - border-style: solid; - border-width: 0; +ADS--DockWidgetTab[activeTab="true"] > #tabCloseButton:hover { + background: creatorTheme.DStabActiveButtonHover; } -ADS--DockAreaTitleBar -{ - background-color: creatorTheme.BackgroundColorDark; +ADS--DockWidgetTab[activeTab="true"] > #tabCloseButton:pressed { + background: creatorTheme.DStabActiveButtonPress; } -QWidget#tabsContainerWidget -{ - background-color: creatorTheme.BackgroundColorDark; +ADS--DockWidget { + background: creatorTheme.DSdockWidgetBackground; + border: none; } -ADS--TitleBarButton -{ - padding: 0px 0px; +QWidget#tabsContainerWidget { + background: creatorTheme.DStabContainerBackground; } -ADS--TitleBarButton:hover -{ - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; +ADS--TitleBarButton { + margin: 1px; + background: none; + border: none; } -QScrollArea#dockWidgetScrollArea -{ - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; +ADS--TitleBarButton:hover { + background-color: creatorTheme.DStitleBarButtonHover; +} + +ADS--TitleBarButton:press { + background-color: creatorTheme.DStitleBarButtonPress; +} + +#floatingTitleLabel { + color: creatorTheme.DStitleBarText; +} + +#floatingTitleCloseButton { + margin: 1px; + background: none; + border: none; +} + +#floatingTitleCloseButton:hover { + background: creatorTheme.DStitleBarButtonHover; +} + +#floatingTitleCloseButton:pressed { + background: creatorTheme.DStitleBarButtonPress; +} + +QScrollArea#dockWidgetScrollArea { + background-color: creatorTheme.DSpanelBackground; padding: 0px; border: none; } -#tabCloseButton -{ - margin-top: 2px; +#tabCloseButton { + margin: 1px; background: none; border: none; - padding: 0px -2px; } -#tabCloseButton:hover -{ - border: 1px solid rgba(0, 0, 0, 32); - background: rgba(0, 0, 0, 16); +#tabCloseButton:hover { + background: creatorTheme.DStabInactiveButtonHover; } -#tabCloseButton:pressed -{ - background: rgba(0, 0, 0, 32); +#tabCloseButton:pressed { + background: creatorTheme.DStabInactiveButtonPress; } QScrollBar { - background-color: creatorTheme.BackgroundColorDark; + background: creatorTheme.DSscrollBarTrack; } QScrollBar:vertical { @@ -118,7 +125,7 @@ QScrollBar:horizontal { } QScrollBar::handle { - background-color: creatorTheme.QmlDesigner_ScrollBarHandleColor; + background: creatorTheme.DSscrollBarHandle; } QScrollBar::handle:vertical { @@ -141,28 +148,27 @@ QScrollBar::sub-page { /* Focus related styling */ ADS--DockWidgetTab[focused="true"] { - background: creatorTheme.DSinteraction; - border-color: creatorTheme.DSinteraction; + background: creatorTheme.DStabFocusBackground; } ADS--DockWidgetTab[focused="true"] > #tabCloseButton:hover { - background: rgba(255, 255, 255, 48); + background: creatorTheme.DStabFocusButtonHover; } ADS--DockWidgetTab[focused="true"] > #tabCloseButton:pressed { - background: rgba(255, 255, 255, 92); + background: creatorTheme.DStabFocusButtonPress; } ADS--DockWidgetTab[focused="true"] QLabel { - color: palette(creatorTheme.DStextColor); + color: creatorTheme.DStabFocusText; } ADS--DockAreaTitleBar { - background: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; - border-bottom: 2px solid creatorTheme.QmlDesigner_TabLight; + background: creatorTheme.DSdockWidgetTitleBar; + border-bottom: 2px solid creatorTheme.DStabActiveBackground; padding-bottom: 0px; } ADS--DockAreaWidget[focused="true"] ADS--DockAreaTitleBar { - border-bottom-color: creatorTheme.DSinteraction; + border-bottom-color: creatorTheme.DStabFocusBackground; } diff --git a/src/plugins/qmldesigner/components/resources/scrollbar.css b/src/plugins/qmldesigner/components/resources/scrollbar.css index e9ab217685c..fee4870e7f7 100644 --- a/src/plugins/qmldesigner/components/resources/scrollbar.css +++ b/src/plugins/qmldesigner/components/resources/scrollbar.css @@ -1,5 +1,5 @@ QScrollBar { - background-color: creatorTheme.BackgroundColorDark; + background-color: creatorTheme.DSscrollBarTrack; } QScrollBar:vertical { @@ -11,7 +11,7 @@ QScrollBar:horizontal { } QScrollBar::handle { - background-color: creatorTheme.QmlDesigner_ScrollBarHandleColor; + background-color: creatorTheme.DSscrollBarHandle; } QScrollBar::handle:vertical { diff --git a/src/plugins/qmldesigner/components/resources/stylesheet.css b/src/plugins/qmldesigner/components/resources/stylesheet.css index 59d883b9a85..dfc80a5b594 100644 --- a/src/plugins/qmldesigner/components/resources/stylesheet.css +++ b/src/plugins/qmldesigner/components/resources/stylesheet.css @@ -1,6 +1,11 @@ -QFrame { - border: 2px; - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; +QFrame, +QScrollArea, +QStackedWidget, +QGraphicsView, +QTabWidget, +QTabWidget::pane { /* The tab widget frame */ + border: 0px; + background-color: creatorTheme.DSpanelBackground; } QLabel { @@ -8,54 +13,52 @@ QLabel { border-image: none; padding: 0; background: none; - color: creatorTheme.PanelTextColorLight; + color: creatorTheme.DStextColor; + selection-color: creatorTheme.DStextSelectedTextColor; + selection-background-color: creatorTheme.DSinteraction; } -QScrollArea { - border: 0px; - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; +QFrame { + border: 2px; } -QStackedWidget { - border: 0px; - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; +QTreeView, +QListView { + color: creatorTheme.DStextColor; + selection-color: creatorTheme.DStextSelectedTextColor; + selection-background-color: creatorTheme.DSinteraction; } -QGraphicsView { - border: 0px; - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; +QPushButton { + color: creatorTheme.DStextColor; + border: 1px solid creatorTheme.DScontrolOutline; + background: creatorTheme.DScontrolBackground; + padding: 4px 2px 4px 2px; + min-width: 70px; } - QTreeView { - color: creatorTheme.PanelTextColorLight; - selection-color: creatorTheme.PanelTextColorLight; - selection-background-color: creatorTheme.QmlDesigner_HighlightColor; - } - - QListView { - color: creatorTheme.PanelTextColorLight; - selection-color: creatorTheme.PanelTextColorLight; - selection-background-color: creatorTheme.QmlDesigner_HighlightColor; - } - - QComboBox QAbstractItemView { - show-decoration-selected: 1; /* make the selection span the entire width of the view */ - background-color: creatorTheme.DSpanelBackground; /* sets background of the menu */ - border: 1px solid black; - margin: 0px; /* some spacing around the menu */ - color: creatorTheme.DStextColor; - selection-background-color: creatorTheme.DSinteraction; - selection-color: creatorTheme.DStextSelectedTextColor; - } - -QTabWidget { - border: 0px; - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; +QPushButton:hover { + background: creatorTheme.DScontrolBackgroundHover; } -QTabWidget::pane { /* The tab widget frame */ - border: 0px; - background-color: creatorTheme.QmlDesigner_BackgroundColorDarkAlternate; +QPushButton:pressed { + border-color: creatorTheme.DScontrolOutlineInteraction; + background: creatorTheme.DScontrolBackgroundInteraction; + color: creatorTheme.DSiconColorInteraction; +} + +QCheckBox { + color: creatorTheme.DStextColor; +} + +QComboBox QAbstractItemView { + show-decoration-selected: 1; /* make the selection span the entire width of the view */ + background-color: creatorTheme.DSpopupBackground; /* sets background of the menu */ + border: 1px solid creatorTheme.DScontrolOutline; + margin: 0px; /* some spacing around the menu */ + color: creatorTheme.DStextColor; + selection-color: creatorTheme.DStextSelectedTextColor; + selection-background-color: creatorTheme.DSinteraction; } QTabBar::tab { @@ -63,8 +66,8 @@ QTabBar::tab { height: 22px; border-image: none; - background-color: creatorTheme.QmlDesigner_TabDark; - color: creatorTheme.QmlDesigner_TabLight; + background-color: creatorTheme.DStabInactiveBackground; + color: creatorTheme.DStabInactiveText; margin: 0px; font: bold; font-size: creatorTheme.captionFontPixelSize; @@ -72,6 +75,13 @@ QTabBar::tab { QTabBar::tab:selected { border: none; /* no border for a flat push button */ - background-color: creatorTheme.QmlDesigner_TabLight; - color: creatorTheme.QmlDesigner_TabDark; + background-color: creatorTheme.DStabActiveBackground; + color: creatorTheme.DStabActiveText; +} + +QLineEdit { + color: creatorTheme.DStextColor; + background-color: creatorTheme.DSdockAreaBackground; + selection-color: creatorTheme.DStextSelectedTextColor; + selection-background-color: creatorTheme.DStextSelectionColor; } diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index ba13a299a7a..4c485c02b3a 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -215,7 +215,7 @@ void DesignModeWidget::disableWidgets() static void addSpacerToToolBar(QToolBar *toolBar) { QWidget* empty = new QWidget(); - empty->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); + empty->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); toolBar->addWidget(empty); } @@ -231,6 +231,7 @@ void DesignModeWidget::setup() ADS::DockManager::setConfigFlags(ADS::DockManager::DefaultNonOpaqueConfig); ADS::DockManager::setConfigFlag(ADS::DockManager::FocusHighlighting, true); + ADS::DockManager::setConfigFlag(ADS::DockManager::AllTabsHaveCloseButton, true); m_dockManager = new ADS::DockManager(this); m_dockManager->setSettings(settings); m_dockManager->setWorkspacePresetsPath(Core::ICore::resourcePath() + QLatin1String("/qmldesigner/workspacePresets/")); @@ -239,32 +240,30 @@ void DesignModeWidget::setup() m_dockManager->setStyleSheet(Theme::replaceCssColors(sheet)); // Setup icons - const QColor iconColor(Theme::getColor(Theme::IconsBaseColor)); - const QColor buttonColor(Theme::getColor(Theme::QmlDesigner_TabLight)); // TODO Use correct color roles - const QColor tabColor(Theme::getColor(Theme::QmlDesigner_TabDark)); + const QColor iconColor(Theme::getColor(Theme::DStitleBarIcon)); const QString closeUnicode = Theme::getIconUnicode(Theme::Icon::adsClose); const QString menuUnicode = Theme::getIconUnicode(Theme::Icon::adsDropDown); const QString undockUnicode = Theme::getIconUnicode(Theme::Icon::adsDetach); const QString fontName = "qtds_propertyIconFont.ttf"; - const QIcon closeIcon = Utils::StyleHelper::getIconFromIconFont(fontName, closeUnicode, 28, 28, buttonColor); - const QIcon menuIcon = Utils::StyleHelper::getIconFromIconFont(fontName, menuUnicode, 28, 28, buttonColor); - const QIcon undockIcon = Utils::StyleHelper::getIconFromIconFont(fontName, undockUnicode, 28, 28, buttonColor); + const QSize size = QSize(28, 28); - auto closeIconNormal = Utils::StyleHelper::IconFontHelper(closeUnicode, - tabColor, - QSize(28, 28), - QIcon::Normal, - QIcon::Off); + const QIcon closeIcon = Utils::StyleHelper::getIconFromIconFont(fontName, closeUnicode, 28, 28, iconColor); + const QIcon menuIcon = Utils::StyleHelper::getIconFromIconFont(fontName, menuUnicode, 28, 28, iconColor); + const QIcon undockIcon = Utils::StyleHelper::getIconFromIconFont(fontName, undockUnicode, 28, 28, iconColor); - auto closeIconFocused = Utils::StyleHelper::IconFontHelper(closeUnicode, - Theme::getColor(Theme::DStextColor), - QSize(28, 28), - QIcon::Normal, - QIcon::On); + auto tabCloseIconNormal = Utils::StyleHelper::IconFontHelper( + closeUnicode, Theme::getColor(Theme::DStabInactiveIcon), size, QIcon::Normal, QIcon::Off); + auto tabCloseIconActive = Utils::StyleHelper::IconFontHelper( + closeUnicode, Theme::getColor(Theme::DStabActiveIcon), size, QIcon::Active, QIcon::Off); + auto tabCloseIconFocus = Utils::StyleHelper::IconFontHelper( + closeUnicode, Theme::getColor(Theme::DStabFocusIcon), size, QIcon::Selected, QIcon::Off); - const QIcon tabsCloseIcon = Utils::StyleHelper::getIconFromIconFont(fontName, {closeIconNormal, closeIconFocused}); + const QIcon tabsCloseIcon = Utils::StyleHelper::getIconFromIconFont( + fontName, {tabCloseIconNormal, + tabCloseIconActive, + tabCloseIconFocus}); ADS::DockManager::iconProvider().registerCustomIcon(ADS::TabCloseIcon, tabsCloseIcon); ADS::DockManager::iconProvider().registerCustomIcon(ADS::DockAreaMenuIcon, menuIcon); @@ -470,7 +469,8 @@ void DesignModeWidget::setup() }); const QIcon gaIcon = Utils::StyleHelper::getIconFromIconFont( - fontName, Theme::getIconUnicode(Theme::Icon::annotationBubble), 36, 36, iconColor); + fontName, Theme::getIconUnicode(Theme::Icon::annotationBubble), + 36, 36, Theme::getColor(Theme::IconsBaseColor)); toolBar->addAction(gaIcon, tr("Edit global annotation for current file."), [&](){ ModelNode node = currentDesignDocument()->rewriterView()->rootModelNode(); diff --git a/src/plugins/qmldesigner/documentwarningwidget.cpp b/src/plugins/qmldesigner/documentwarningwidget.cpp index 08a2a129a9e..e691912fb90 100644 --- a/src/plugins/qmldesigner/documentwarningwidget.cpp +++ b/src/plugins/qmldesigner/documentwarningwidget.cpp @@ -175,12 +175,11 @@ bool DocumentWarningWidget::eventFilter(QObject *object, QEvent *event) void DocumentWarningWidget::showEvent(QShowEvent *event) { - const QColor backgroundColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_BackgroundColor); + const QColor backgroundColor = Utils::creatorTheme()->color(Utils::Theme::DScontrolBackground); + const QColor outlineColor = Utils::creatorTheme()->color(Utils::Theme::DScontrolOutline); QPalette pal = palette(); - QColor color = pal.color(QPalette::ToolTipBase); - const QColor backgroundNoAlpha = Utils::StyleHelper::alphaBlendedColors(color, backgroundColor); - color.setAlpha(255); - pal.setColor(QPalette::ToolTipBase, backgroundNoAlpha); + pal.setColor(QPalette::ToolTipBase, backgroundColor); + pal.setColor(QPalette::ToolTipText, outlineColor); setPalette(pal); m_gotoCodeWasClicked = false; moveToParentCenter(); From 23477f633bf1f83c25e2a7bc55c8462195035598 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 9 Mar 2021 16:00:59 +0100 Subject: [PATCH 21/22] QmlDesigner: Use theme colors for easing curve editor Change-Id: I38969d88caf6ad536c19fbf0998e19230559ceb1 Reviewed-by: Knud Dollereder Reviewed-by: Thomas Hartmann --- .../components/timelineeditor/canvasstyledialog.h | 10 ++++++---- .../components/timelineeditor/splineeditor.cpp | 13 +++++-------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.h b/src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.h index b3b1a86c956..4fd7e77c270 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.h +++ b/src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.h @@ -27,6 +27,8 @@ #include "timelinecontrols.h" +#include + #include #include @@ -41,14 +43,14 @@ struct CanvasStyle qreal thinLineWidth = 0.3; qreal thickLineWidth = 2.5; - QColor thinLineColor = qRgb(0x99, 0x99, 0x99); - QColor thickLineColor = qRgb(0x5f, 0x5f, 0x5f); + QColor thinLineColor = Theme::getColor(Theme::DSscrollBarHandle); + QColor thickLineColor = Theme::getColor(Theme::DSscrollBarHandle); qreal handleSize = 7.0; qreal handleLineWidth = 2.0; - QColor endPointColor = qRgb(0xd6, 0xd3, 0x51); - QColor interPointColor = qRgb(0xce, 0x17, 0x17); + QColor endPointColor = Theme::getColor(Theme::IconsWarningToolBarColor); + QColor interPointColor = Theme::getColor(Theme::DSerrorColor); qreal curveWidth = 3.0; }; diff --git a/src/plugins/qmldesigner/components/timelineeditor/splineeditor.cpp b/src/plugins/qmldesigner/components/timelineeditor/splineeditor.cpp index 3431e5c7a7a..40ca4ec7add 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/splineeditor.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/splineeditor.cpp @@ -91,21 +91,18 @@ void SplineEditor::paintEvent(QPaintEvent *) { QPainter painter(this); - QPen pen(Qt::black); + QPen pen(Theme::getColor(Theme::DScontrolOutline)); pen.setWidth(1); painter.drawRect(0, 0, width() - 1, height() - 1); painter.setRenderHint(QPainter::Antialiasing); - pen = QPen(Qt::darkGray); - pen.setWidth(1); - painter.setPen(pen); - - QColor curveColor = Qt::white; + QColor curveColor = Theme::getColor(Theme::PanelTextColorLight); if (!m_curve.isLegal()) - curveColor = Qt::red; + curveColor = Theme::getColor(Theme::DSerrorColor); + + QBrush background(Theme::getColor(Theme::BackgroundColorDark)); - QBrush background(Theme::instance()->qmlDesignerBackgroundColorDarker()); m_canvas.paintGrid(&painter, background); m_canvas.paintCurve(&painter, m_curve, curveColor); m_canvas.paintControlPoints(&painter, m_curve); From f820164b1ab4edf0421ac2b222b51b1e12e5430c Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Tue, 16 Mar 2021 00:08:36 +0200 Subject: [PATCH 22/22] QmlDesigner: Use a different color for unimported items section Fixes: QDS-3873 Change-Id: Ic713353d8fe5c1bfb4ff11f1224294ecde182fa7 Reviewed-by: Thomas Hartmann --- .../qmldesigner/itemLibraryQmlSources/ItemDelegate.qml | 3 +++ .../qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml | 4 ++++ .../imports/HelperWidgets/Section.qml | 1 + .../propertyEditorQmlSources/imports/StudioTheme/Values.qml | 2 ++ .../qmldesigner/components/itemlibrary/itemlibraryimport.h | 2 ++ 5 files changed, 12 insertions(+) diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml index 6e0724d86bb..3f59deb8061 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml @@ -31,6 +31,9 @@ import StudioTheme 1.0 as StudioTheme Item { id: delegateRoot + + property alias textColor: text.color + signal showContextMenu() Rectangle { diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml index 9f7c2b13b64..f4e69d31ae6 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml @@ -155,6 +155,8 @@ ScrollView { sectionHeight: 30 sectionFontSize: 15 showArrow: categoryModel.rowCount() > 0 + labelColor: importUnimported ? StudioTheme.Values.themeUnimportedModuleColor + : StudioTheme.Values.themeTextColor leftPadding: 0 rightPadding: 0 topPadding: 0 @@ -204,6 +206,8 @@ ScrollView { model: itemModel delegate: ItemDelegate { visible: itemVisible + textColor: importUnimported ? StudioTheme.Values.themeUnimportedModuleColor + : StudioTheme.Values.themeTextColor width: styleConstants.cellWidth + itemGrid.flexibleWidth height: styleConstants.cellHeight onShowContextMenu: { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml index cdc5780f523..57d0d65a771 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml @@ -32,6 +32,7 @@ import StudioTheme 1.0 as StudioTheme Item { id: section property alias caption: label.text + property alias labelColor: label.color property alias sectionHeight: header.height property alias sectionBackgroundColor: header.color property alias sectionFontSize: label.font.pixelSize diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml index 0ea1e18746c..4fd5c23c6c8 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml @@ -198,6 +198,8 @@ QtObject { property string themeStateBackground: Theme.color(Theme.DSstateBackgroundColor) property string themeStatePreviewOutline: Theme.color(Theme.DSstatePreviewOutline) + property string themeUnimportedModuleColor: "#e33c2e" + // Taken out of Constants.js property string themeChangedStateText: Theme.color(Theme.DSchangedStateText) diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h index 982e47df70e..997ca65c714 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h @@ -42,6 +42,7 @@ class ItemLibraryImport : public QObject Q_PROPERTY(bool importUsed READ importUsed NOTIFY importUsedChanged FINAL) Q_PROPERTY(bool importExpanded READ importExpanded WRITE setImportExpanded NOTIFY importExpandChanged FINAL) Q_PROPERTY(bool importRemovable READ importRemovable NOTIFY importRemovableChanged FINAL) + Q_PROPERTY(bool importUnimported READ importUnimported FINAL) Q_PROPERTY(QObject *categoryModel READ categoryModel NOTIFY categoryModelChanged FINAL) public: @@ -90,6 +91,7 @@ signals: private: void updateRemovable(); + bool importUnimported() const { return m_sectionType == SectionType::Unimported; } Import m_import; bool m_importExpanded = true;