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, 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..3f59deb8061 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml @@ -27,9 +27,13 @@ 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 + + property alias textColor: text.color + signal showContextMenu() Rectangle { @@ -37,7 +41,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 +72,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..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 @@ -193,13 +195,19 @@ 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 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/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..57d0d65a771 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. @@ -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 @@ -62,7 +63,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 +83,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 +113,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 +134,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..4fd5c23c6c8 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,128 @@ 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) + + property string themeUnimportedModuleColor: "#e33c2e" // Taken out of Constants.js property string themeChangedStateText: Theme.color(Theme.DSchangedStateText) @@ -131,4 +207,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 f5e80745563..aef8a37d569 100644 Binary files a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf and b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf differ 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 00000000000..72cb9f03506 Binary files /dev/null and b/share/qtcreator/qmldesigner/statesEditorQmlSources/images/checkers.png differ 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() 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/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 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/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/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/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); } } 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); } 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; }; 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/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 29fc47dc9a0..d9cea02c1b8 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -919,6 +919,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 3ddd523e014..7c0b3a551b7 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -739,7 +739,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(); @@ -783,7 +784,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 3531e0d7fff..d1b1a29b6f3 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 diff --git a/src/plugins/fakevim/CMakeLists.txt b/src/plugins/fakevim/CMakeLists.txt index 96678f3e3b8..a7c1cf736c4 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 417dcd5728b..0ced6f42f22 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1285,6 +1285,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; @@ -1630,7 +1635,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; } diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp index 1a6789f91ee..2f2e80fbf0e 100644 --- a/src/plugins/mcusupport/mcusupportsdk.cpp +++ b/src/plugins/mcusupport/mcusupportsdk.cpp @@ -687,13 +687,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() @@ -707,8 +712,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); } } 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/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/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; 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..997ca65c714 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h @@ -42,12 +42,14 @@ 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: enum class SectionType { Default, User, + Quick3DAssets, Unimported }; @@ -75,6 +77,7 @@ public: void expandCategories(bool expand = true); static QString userComponentsTitle(); + static QString quick3DAssetsTitle(); static QString unimportedComponentsTitle(); SectionType sectionType() const; @@ -88,6 +91,7 @@ signals: private: void updateRemovable(); + bool importUnimported() const { return m_sectionType == SectionType::Unimported; } Import m_import; bool m_importExpanded = true; 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; 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/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); 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, 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(); 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)); 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..4f4f110c125 --- /dev/null +++ b/src/tools/iostool/gdbrunner.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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" +#include "mobiledevicelib.h" + +#ifdef Q_OS_UNIX +#include +#include +#endif + +namespace Ios { + +GdbRunner::GdbRunner(IosTool *iosTool, ServiceConnRef conn) : + QObject(nullptr), + m_iosTool(iosTool), + m_conn(conn) +{ +} + +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_conn); + { + QMutexLocker l(&m_iosTool->m_xmlMutex); + if (!m_iosTool->splitAppOutput) { + m_iosTool->inAppOutput = false; + m_iosTool->out.writeEndElement(); + } + m_iosTool->outFile.flush(); + } + MobileDeviceLib::instance().serviceConnectionInvalidate(m_conn); + m_conn = nullptr; + m_iosTool->doExit(); + emit finished(); +} + +void GdbRunner::stop(int phase) +{ + Ios::IosDeviceManager::instance()->stopGdbServer(m_conn, phase); +} + +} diff --git a/src/tools/iostool/gdbrunner.h b/src/tools/iostool/gdbrunner.h new file mode 100644 index 00000000000..77b7ceae97f --- /dev/null +++ b/src/tools/iostool/gdbrunner.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** 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 "iostooltypes.h" + +namespace Ios { +class IosTool; +class GdbRunner: public QObject +{ + Q_OBJECT + +public: + GdbRunner(IosTool *iosTool, ServiceConnRef conn); + void stop(int phase); + void run(); + +signals: + void finished(); + +private: + IosTool *m_iosTool; + ServiceConnRef m_conn = nullptr; +}; +} diff --git a/src/tools/iostool/iosdevicemanager.cpp b/src/tools/iostool/iosdevicemanager.cpp index 7003710d9d1..cab1d69ed3f 100644 --- a/src/tools/iostool/iosdevicemanager.cpp +++ b/src/tools/iostool/iosdevicemanager.cpp @@ -24,45 +24,28 @@ ****************************************************************************/ #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 +#include static const bool debugGdbServer = false; static const bool debugAll = false; @@ -82,72 +65,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,89 +73,17 @@ 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) +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( @@ -253,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); @@ -262,7 +108,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+)\\)"); @@ -356,6 +202,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); } @@ -390,13 +249,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); - - MobileDeviceLib *lib(); + 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); AMDeviceRef device; int progressBase; @@ -408,7 +265,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 -------- @@ -431,19 +288,18 @@ 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; QHash m_devices; QMultiHash m_pendingLookups; AMDeviceNotificationRef m_notification; - MobileDeviceLib m_lib; }; class DevInfoSession: public CommandSession { @@ -498,7 +354,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 +382,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 +394,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 +440,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(); @@ -614,13 +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")); @@ -649,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) @@ -661,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); @@ -673,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."; @@ -744,11 +598,6 @@ void IosDeviceManagerPrivate::checkPendingLookups() } } -MobileDeviceLib *IosDeviceManagerPrivate::lib() -{ - return &m_lib; -} - void IosDeviceManagerPrivate::didTransferApp(const QString &bundlePath, const QString &deviceId, IosDeviceManager::OpStatus status) { @@ -756,11 +605,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, @@ -810,18 +659,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; @@ -901,7 +750,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; @@ -919,14 +768,15 @@ 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); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); if (phase == 0) - session.writeAll(fd,"\x03",1); + mLib.serviceConnectionSend(conn, "\x03", 1); else - session.sendGdbCommand(fd, "k", 1); + session.sendGdbCommand(conn, "k", 1); } // ------- ConnectSession implementation -------- @@ -942,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; @@ -969,34 +820,37 @@ 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; } -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)) { + 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; - 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); @@ -1017,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; @@ -1117,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(); @@ -1140,23 +997,25 @@ 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); + + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + bool failure = mLib.serviceConnectionSend(conn, "$", 1) == 0; if (!failure) - failure = !writeAll(fd, cmd, len); + 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 = !writeAll(fd, buf, 3); + failure = mLib.serviceConnectionSend(conn, buf, 3) == 0; return !failure; } @@ -1184,7 +1043,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: @@ -1219,8 +1078,10 @@ int CommandSession::handleChar(int fd, QByteArray &res, char c, int status) ++unexpectedChars; } } - if (status == 3 && aknowledge) - writeAll(fd, "+", 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")); @@ -1233,7 +1094,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; @@ -1241,8 +1102,9 @@ QByteArray CommandSession::readGdbReply(ServiceSocket fd) int maxRetry = 10; int status = 0; int toRead = 4; + MobileDeviceLib &mLib = MobileDeviceLib::instance(); while (status < 4 && toRead > 0) { - qptrdiff nRead = read(fd, buf, toRead); + qptrdiff nRead = mLib.serviceConnectionReceive(conn, buf, toRead); if (!checkRead(nRead, maxRetry)) return QByteArray(); if (debugGdbServer) { @@ -1250,7 +1112,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) { @@ -1288,9 +1150,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())) @@ -1302,27 +1164,23 @@ bool CommandSession::expectGdbReply(ServiceSocket gdbFd, QByteArray expected) return true; } -bool CommandSession::expectGdbOkReply(ServiceSocket gdbFd) +bool CommandSession::expectGdbOkReply(ServiceConnRef conn) { - return expectGdbReply(gdbFd, QByteArray("OK")); -} - -MobileDeviceLib *CommandSession::lib() -{ - return IosDeviceManagerPrivate::instance()->lib(); + return expectGdbReply(conn, QByteArray("OK")); } 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)); @@ -1365,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") @@ -1459,23 +1318,41 @@ 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); + 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; + 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); @@ -1491,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 : mLib.deviceConnectionGetSocket(conn); + auto status = failure ? IosDeviceManager::Failure : IosDeviceManager::Success; + IosDeviceManagerPrivate::instance()->didStartApp(bundlePath, deviceId, status, conn, fd, this); return !failure; } @@ -1533,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)); } @@ -1595,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)); @@ -1655,318 +1537,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) { @@ -2010,14 +1581,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 5d6c489b7d6..7c521c789fd 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 { @@ -69,9 +64,10 @@ 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: void deviceAdded(const QString &deviceId); void deviceRemoved(const QString &deviceId); @@ -80,11 +76,12 @@ 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); 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..e65cae852a4 --- /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, ServiceConnRef conn, 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 QmlRelayServer(this, qmlPort, deviceSession); + qmlServer->startServer(); + } + } + if (debug) { + gdbServer = new GdbRelayServer(this, gdbFd, conn); + 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, 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(); + 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..a2fd1f040e4 --- /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 GdbRelayServer; +class QmlRelayServer; + +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, ServiceConnRef conn, 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; + GdbRelayServer *gdbServer; + QmlRelayServer *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..d665ebb44b0 --- /dev/null +++ b/src/tools/iostool/iostooltypes.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** 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" { +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) +} // 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..79c4054a0d4 --- /dev/null +++ b/src/tools/iostool/mobiledevicelib.cpp @@ -0,0 +1,407 @@ +/**************************************************************************** +** +** 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::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() +{ +#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")); + 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")); + 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; +} + +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 new file mode 100644 index 00000000000..97735fdcb1a --- /dev/null +++ b/src/tools/iostool/mobiledevicelib.h @@ -0,0 +1,206 @@ +/**************************************************************************** +** +** 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); + +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 { + 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, + 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); + + // 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; + +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; + AMDServiceConnectionSendPtr m_AMDServiceConnectionSend; + AMDServiceConnectionReceivePtr m_AMDServiceConnectionReceive; + AMDServiceConnectionInvalidatePtr m_AMDServiceConnectionInvalidate; + AMDeviceIsAtLeastVersionOnPlatformPtr m_AMDeviceIsAtLeastVersionOnPlatform; + 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..449f86057db --- /dev/null +++ b/src/tools/iostool/relayserver.cpp @@ -0,0 +1,400 @@ +/**************************************************************************** +** +** 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" +#include "mobiledevicelib.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() +{ + closeConnection(); +} + +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 = readData(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 = writeData(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); +} + +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); +} + +RelayServer *Relayer::server() const +{ + return qobject_cast(parent()); +} + +RemotePortRelayer::RemotePortRelayer(QmlRelayServer *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; + QmlRelayServer *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(); +} + +GdbRelayServer::GdbRelayServer(IosTool *parent, + int serverFileDescriptor, ServiceConnRef conn) : + RelayServer(parent), + m_serverFileDescriptor(serverFileDescriptor), + m_serviceConn(conn) +{ + if (m_serverFileDescriptor > 0) + fcntl(m_serverFileDescriptor, F_SETFL, fcntl(m_serverFileDescriptor, F_GETFL, 0) | O_NONBLOCK); +} + +void GdbRelayServer::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 ServiceConnectionRelayer(this, clientSocket, m_serviceConn); + m_connections.append(newConnection); + newConnection->startRelay(m_serverFileDescriptor); + } +} + +QmlRelayServer::QmlRelayServer(IosTool *parent, int remotePort, + Ios::DeviceSession *deviceSession) : + RelayServer(parent), + m_remotePort(remotePort), + m_deviceSession(deviceSession) +{ + parent->errorMsg(QLatin1String("created qml server")); +} + + +void QmlRelayServer::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(); + } +} + +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 new file mode 100644 index 00000000000..0b01b7271e1 --- /dev/null +++ b/src/tools/iostool/relayserver.h @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** 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 QmlRelayServer; + +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: + 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 = 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 +{ + Q_OBJECT + +public: + static const int reconnectMsecDelay = 500; + static const int maxReconnectAttempts = 2*60*5; // 5 min + RemotePortRelayer(QmlRelayServer *parent, QTcpSocket *clientSocket); + void tryRemoteConnect(); + +signals: + void didConnect(QmlRelayServer *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 GdbRelayServer: public RelayServer +{ + Q_OBJECT + +public: + GdbRelayServer(IosTool *parent, int serverFileDescriptor, ServiceConnRef conn); + +protected: + void newRelayConnection() override; + +private: + int m_serverFileDescriptor = -1; + ServiceConnRef m_serviceConn = nullptr; +}; + +class QmlRelayServer: public RelayServer +{ + Q_OBJECT + +public: + QmlRelayServer(IosTool *parent, int remotePort, + Ios::DeviceSession *deviceSession); + +protected: + void newRelayConnection() override; + +private: + int m_remotePort; + DeviceSession *m_deviceSession; + friend class RemotePortRelayer; +}; +} 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(): 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.")