diff options
47 files changed, 723 insertions, 271 deletions
diff --git a/dist/changes-7.0.0.md b/dist/changes-7.0.0.md index a9c98815a54..991e52926a6 100644 --- a/dist/changes-7.0.0.md +++ b/dist/changes-7.0.0.md @@ -22,6 +22,8 @@ General * Added `Tools > Debug Qt Creator > Show Logs` for viewing Qt Creator debug logs * Moved C++ code model and language client inspectors to `Tools > Debug Qt Creator` +* Fixed persistence of `Show Folders on Top` in `File System` + (QTCREATORBUG-27131) Editing ------- @@ -30,23 +32,33 @@ Editing * Added support for choosing external editor as default editor (QTCREATORBUG-13880) * Fixed copy action in text editing macros (QTCREATORBUG-26363) +* Fixed cursor position after backspace and going up or down + (QTCREATORBUG-27035) ### C++ +* Switched to LLVM 14 in binary packages * Switched to Clangd by default (QTCREATORBUG-22917) * Fixed that compilation errors appeared below code model errors in `Issues` pane (QTCREATORBUG-23655) * Fixed that duplication files did not adapt header guard (QTCREATORBUG-26654) * Fixed highlighting and indentation of raw string literals (QTCREATORBUG-26211) * Fixed performance issue in global indexer (QTCREATORBUG-26841) +* Fixed tiny refactoring icon on HiDPI screens (QTCREATORBUG-26905) +* Fixed dot to arrow conversion with extra characters (QTCREATORBUG-27034) * clang-format * Moved settings to `Code Style` editor * Added synchronization between `clang-format` settings and custom code style * Clangd + * Added support for parse contexts (QTCREATORBUG-27009) * Added memory usage inspector to language client inspector * Added highlighting of `Q_PROPERTY` declarations * Improved display of diagnostic messages * Fixed access type categorization for functions + * Fixed highlighting issues (QTCREATORBUG-27059, QTCREATORBUG-27111) + * Fixed generating `Q_PROPERTY` members (QTCREATORBUG-27063) + * Fixed display of outdated diagnostics (QTCREATORBUG-26585) + * Fixed that `Unknown argument` diagnostics were shown (QTCREATORBUG-27113) ### QML @@ -64,6 +76,7 @@ Editing (QTCREATORBUG-26624) * Fixed that outdated diagnostic could be shown (QTCREATORBUG-26585) * Fixed issue with re-highlighting (QTCREATORBUG-26624) +* Fixed crash when rapidly closing documents (QTCREATORBUG-26534) ### FakeVim @@ -76,7 +89,11 @@ Projects * Added multiple selection to `Issues` pane (QTCREATORBUG-25547, QTCREATORBUG-26720) * Improved automatic (re-)detection of toolchains (QTCREATORBUG-26460) +* Changed default C++ standard for project wizards to C++17 (QTCREATORBUG-27045) * Fixed unnecessary toolchain calls at startup +* Fixed warning that file is not part of any project (QTCREATORBUG-26987) +* Fixed that leading spaces could break custom output parsers + (QTCREATORBUG-26892) ### CMake @@ -92,6 +109,12 @@ Projects * Added context menu actions for resolving mismatches between kit, initial and current configuration * Added `Help` to context menu for variable names +* Fixed that CMake was unnecessarily run after Kit update +* Fixed crash when Kit has no toolchain (QTCREATORBUG-26777) + +### Qbs + +* Fixed that `cpp.cFlags` and `cpp.cxxFlags` were not considered for code model ### Generic @@ -101,6 +124,10 @@ Projects * Fixed parsing of `SUBDIRS` +### Mercurial + +* Fixed saving of settings (QTCREATORBUG-27091) + Debugging --------- @@ -143,11 +170,23 @@ Test Integration Platforms --------- +### Windows + +* Fixed auto-detection of MinGW compiler (QTCREATORBUG-27057) +* Fixed missing compile `Issues` for MSVC (QTCREATORBUG-27056) +* Fixed wrong path separator when using `-client` (QTCREATORBUG-27075) + +### Linux + +* Added Wayland backend (QTCREATORBUG-26867) + ### macOS * Fixed that macOS dark mode was not used for dark themes (QTCREATORBUG-22477) * Fixed that user applications inherited access permissions from Qt Creator (QTCREATORBUG-26743) +* Fixed key repeat (QTCREATORBUG-26925) +* Fixed environment when opening `Terminal` with `zsh` ### Android @@ -159,10 +198,14 @@ Platforms (QTCREATORBUG-26709) * Fixed detection of available NDK platforms for recent NDKs (QTCREATORBUG-26772) +* Fixed naming of devices that are connected via USB and WiFi at the same time +* Fixed deployment if Kit fails to determine ABI (QTCREATORBUG-27103) ### Remote Linux * Fixed UI state after stopping remote applications (QTCREATORBUG-26848) +* Fixed missing error message in `Application Output` when remote application + crashes (QTCREATORBUG-27007) ### WebAssembly @@ -181,20 +224,26 @@ Platforms Credits for these changes go to: -------------------------------- Aaron Barany +Aleksei German Alessandro Portale Alexander Drozdov Allan Sandfeld Jensen +Andre Hartmann André Pönitz Anton Alimoff +Antti Määttä Artem Sokolovskii Assam Boudjelthia +Björn Schäpers Christiaan Janssen Christian Kandeler Christian Stenger +Christian Strømme Cristian Adam Cristián Maureira-Fredes David Schulz Eike Ziller +Erik Verbruggen Fawzi Mohamed Henning Gruendl Huixiong Cao @@ -209,20 +258,28 @@ Knud Dollereder Leena Miettinen Mahmoud Badri Marco Bubke +Mats Honkamaa Maximilian Goldstein Miikka Heikkinen Morten Johan Sørvig Orgad Shaneh +Oswald Buddenhagen Petar Perisin Piotr Mikolajczyk +Piotr Mućko +Rafael Roquetto Robert Löhning Samuel Ghinet +Tapani Mattila Tasuku Suzuki +Thiago Macieira Thomas Hartmann Tim Jenssen Tony Leinonen Topi Reinio Tor Arne Vestbø +Tuomo Pelkonen Ulf Hermann Ville Nummela +Xiaofeng Wang XutaxKamay diff --git a/doc/qtdesignstudio/images/studio-project-wizards.png b/doc/qtdesignstudio/images/studio-project-wizards.png Binary files differindex a6cd93f15e2..3a329bd16e4 100644 --- a/doc/qtdesignstudio/images/studio-project-wizards.png +++ b/doc/qtdesignstudio/images/studio-project-wizards.png diff --git a/doc/qtdesignstudio/src/components/qtquick-mcu-support.qdocinc b/doc/qtdesignstudio/src/components/qtquick-mcu-support.qdocinc index 87ed1b95662..4b9608fcf36 100644 --- a/doc/qtdesignstudio/src/components/qtquick-mcu-support.qdocinc +++ b/doc/qtdesignstudio/src/components/qtquick-mcu-support.qdocinc @@ -34,7 +34,7 @@ development. In this manual, we indicate which components are supported at the time of writing. - To develop for MCUs, \l{Using Project Wizards}{create an MCU project}. Only + To develop for MCUs, \l{Creating a Project}{create an MCU project}. Only the components available on MCUs are displayed in \l Components. Only a subset of properties is supported for the supported components. The properties that are not available on MCUs are marked in the \l Properties diff --git a/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc index 96a392322ed..2de6f69cde2 100644 --- a/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc +++ b/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc @@ -37,35 +37,27 @@ Creating a project enables you to: \list - \li Group files together + \li Group files together. \li Include \l{UI Files}{UI files} (.ui.qml), component files (.qml), - and assets files - \li Specify settings for previewing UIs + and assets files. + \li Specify settings for previewing UIs. \endlist - Setting up a new project in \QDS is aided by a wizard that guides you - step-by-step through the project creation process. The wizard templates - prompt you to enter the settings needed for a particular type of project - and create the necessary files for you. + Setting up a new project in \QDS is aided by a wizard with a set of + presets that you can choose from. You can adjust project settings and save + custom presets. When you create a project, all necessary files are created. - To test how well your designs work, you can preview the - UIs on the desktop, embedded Linux devices, or Android devices. For more - information, see \l{Validating with Target Hardware}. - - \image studio-project-wizards.png "A list of project wizards" - - You can export designs from other design tools and import them to projects - or create them from scratch using the following wizard presets: + The following presets are available: \table \header \li Category - \li Wizard Preset + \li Preset \li Purpose \row \li Recents \li - \li Lists the most recent presets that you have used. + \li Lists your most recently used presets. \row \li {1,2} General \li Empty @@ -100,15 +92,30 @@ \li Launcher \li Creates a project that uses default components such as rectangles, images, and text, and defines a launcher application. + \row + \li Custom + \li + \li Lists your saved custom presets. + \note This tab is not visible if there are no saved custom presets. \endtable - \section1 Using Project Wizards + \image studio-project-wizards.png "The Create Project wizard" - To create a new project: + To test how well your designs work, you can preview the + UIs on the desktop, embedded Linux devices, or Android devices. For more + information, see \l{Validating with Target Hardware}. + + You can export designs from other design tools and import them to projects. + For more information, see \l{Exporting from Design Tools} and + \l{Importing Designs From Other Design Tools}. + + \section1 Creating a Project + + To create a project: \list 1 \li Select \uicontrol File > \uicontrol {New Project}. - \li In the \uicontrol Presets tab, select a wizard preset. + \li In the \uicontrol Presets tab, select a preset. \li In the \uicontrol Details tab: \list \li Enter a name for the project. Keep in mind that projects @@ -167,9 +174,24 @@ \uicontrol Assets > \inlineimage icons/plus.png . + \section1 Using Custom Presets + + You can save project settings as custom presets. All saved custom presets + are available on the \uicontrol Custom tab in the + \uicontrol {Create Project} wizard. You cannot modify custom presets once + you have created them. + + To create a custom preset: + \list 1 + \li In the \uicontrol {Create Project} wizard, set the details and style + that you want to use. + \li Select \uicontrol {Save Custom Preset} and give a name for the custom + preset. + \endlist + \section1 Adding Files to Projects - You can use wizard templates also to add individual files to projects. + You can use wizard templates to add individual files to projects. The wizard templates in the \uicontrol {Qt Quick Controls} category create stylable versions of the components in the \uicontrol {Qt Quick Controls} diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-particles.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-particles.qdoc index e3561b33346..7f81f8f2de4 100644 --- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-particles.qdoc +++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-particles.qdoc @@ -130,7 +130,7 @@ \li \l {Textures}{Texture} (four instances) \endlist - We start by creating a \l{Using Project Wizards}{Qt Quick 3D Application} + We start by creating a \l{Creating a Project}{Qt Quick 3D Application} project and adding the assets to it. We then follow the instructions above to add the \uicontrol {Particle System} component instance, which provides us with our first \uicontrol Emitter, \uicontrol {Sprite Particle}, and diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNodeView.qml index d6574f660ca..19b3c4c35d7 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNodeView.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNodeView.qml @@ -37,7 +37,7 @@ View3D { function fitToViewPort() { // The magic number is the distance from camera default pos to origin - _generalHelper.calculateNodeBoundsAndFocusCamera(theCamera, importScene, root, + _generalHelper.calculateNodeBoundsAndFocusCamera(theCamera, sourceModel, root, 1040); } @@ -65,7 +65,7 @@ View3D { Model { id: model - source: sourceModel.source + source: _generalHelper.resolveAbsoluteSourceUrl(sourceModel) geometry: sourceModel.geometry materials: [ diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp index 66cd2d80b8e..1b1788e4acf 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -42,6 +42,7 @@ #include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h> #include <QtQuick3DUtils/private/qssgbounds3_p.h> #include <QtQuick3DUtils/private/qssgutils_p.h> +#include <QtQml/qqml.h> #include <QtQuick/qquickwindow.h> #include <QtQuick/qquickitem.h> #include <QtCore/qmath.h> @@ -93,6 +94,26 @@ QString GeneralHelper::generateUniqueName(const QString &nameRoot) return QStringLiteral("%1_%2").arg(nameRoot).arg(count); } +// Resolves absolute model source path +QUrl GeneralHelper::resolveAbsoluteSourceUrl(const QQuick3DModel *sourceModel) +{ + if (!sourceModel) + return {}; + + const QUrl source = sourceModel->source(); + if (source.hasFragment()) { + // Fragment is part of the url separated by '#', check if it is an index or primitive + bool isNumber = false; + source.fragment().toInt(&isNumber); + // If it wasn't an index, then it was a primitive and we can return it as-is + if (!isNumber) + return source; + } + + QQmlContext *context = qmlContext(sourceModel); + return context ? context->resolvedUrl(source) : source; +} + void GeneralHelper::orbitCamera(QQuick3DCamera *camera, const QVector3D &startRotation, const QVector3D &lookAtPoint, const QVector3D &pressPos, const QVector3D ¤tPos) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h index ac67172ab32..562848c7720 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h @@ -33,6 +33,7 @@ #include <QPointer> #include <QQuaternion> #include <QTimer> +#include <QUrl> #include <QVariant> #include <QVector3D> #include <QtQuick3D/private/qquick3dpickresult_p.h> @@ -58,6 +59,7 @@ public: Q_INVOKABLE void requestOverlayUpdate(); Q_INVOKABLE QString generateUniqueName(const QString &nameRoot); + Q_INVOKABLE QUrl resolveAbsoluteSourceUrl(const QQuick3DModel *sourceModel); Q_INVOKABLE void orbitCamera(QQuick3DCamera *camera, const QVector3D &startRotation, const QVector3D &lookAtPoint, const QVector3D &pressPos, diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 9656e0e5e89..0d6c069faec 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -1091,9 +1091,15 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView() m_modelNode3DImageViewData.window->resize(renderSize); m_modelNode3DImageViewData.rootItem->setSize(renderSize); - QMetaObject::invokeMethod( - m_modelNode3DImageViewData.rootItem, "createViewForObject", - Q_ARG(QVariant, objectToVariant(instanceObj))); + if (createdFromComponent) { + QMetaObject::invokeMethod( + m_modelNode3DImageViewData.rootItem, "createViewForNode", + Q_ARG(QVariant, objectToVariant(instanceObj))); + } else { + QMetaObject::invokeMethod( + m_modelNode3DImageViewData.rootItem, "createViewForObject", + Q_ARG(QVariant, objectToVariant(instanceObj))); + } // Need to render twice, first render updates spatial nodes for (int i = 0; i < 2; ++i) { diff --git a/share/qtcreator/qmldesigner/newprojectdialog/NewProjectDialog.qml b/share/qtcreator/qmldesigner/newprojectdialog/NewProjectDialog.qml index 4cc82bc79cc..f895cdd8c40 100644 --- a/share/qtcreator/qmldesigner/newprojectdialog/NewProjectDialog.qml +++ b/share/qtcreator/qmldesigner/newprojectdialog/NewProjectDialog.qml @@ -204,11 +204,22 @@ Item { font.weight: Font.DemiBold font.pixelSize: DialogValues.viewHeaderPixelSize verticalAlignment: Text.AlignVCenter - color: tabBarRow.currIndex === index ? DialogValues.textColorInteraction - : DialogValues.textColor + + color: { + var color = tabBarRow.currIndex === index + ? DialogValues.textColorInteraction + : DialogValues.textColor + + return tabItemMouseArea.containsMouse + ? Qt.darker(color, 1.5) + : color + } + Behavior on color { ColorAnimation { duration: tabBar.animDur } } MouseArea { + id: tabItemMouseArea + hoverEnabled: true anchors.fill: parent onClicked: { tabBar.selectTab(index) diff --git a/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml b/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml index b348a6da350..1f154810b00 100644 --- a/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml +++ b/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml @@ -286,12 +286,8 @@ Item { realStepSize: 10 font.pixelSize: DialogValues.defaultPixelSize - onRealValueChanged: { - if (widthField.realValue >= heightField.realValue) - orientationButton.setHorizontal() - else - orientationButton.setVertical() - } + onRealValueChanged: orientationButton.isHorizontal = + widthField.realValue >= heightField.realValue } // Width Text Field Binding { @@ -311,12 +307,8 @@ Item { realStepSize: 10 font.pixelSize: DialogValues.defaultPixelSize - onRealValueChanged: { - if (widthField.realValue >= heightField.realValue) - orientationButton.setHorizontal() - else - orientationButton.setVertical() - } + onRealValueChanged: orientationButton.isHorizontal = + widthField.realValue >= heightField.realValue } // Height Text Field Binding { @@ -327,69 +319,69 @@ Item { Item { Layout.fillWidth: true } - Button { + Item { id: orientationButton implicitWidth: 100 implicitHeight: 50 - checked: false - hoverEnabled: false - background: Rectangle { - width: parent.width - height: parent.height - color: "transparent" - - Row { - Item { - width: orientationButton.width / 2 - height: orientationButton.height - Rectangle { - id: horizontalBar - color: "white" - width: parent.width - height: orientationButton.height / 2 - anchors.verticalCenter: parent.verticalCenter - radius: 3 - } + property bool isHorizontal: false + + Row { + spacing: orientationButton.width / 4 + + function computeColor(barId) { + var color = DialogValues.textColor + + if (barId === horizontalBar) { + color = orientationButton.isHorizontal + ? DialogValues.textColorInteraction + : DialogValues.textColor + } else { + color = orientationButton.isHorizontal + ? DialogValues.textColor + : DialogValues.textColorInteraction } - Item { - width: orientationButton.width / 4 - height: orientationButton.height - } + if (orientationButtonMouseArea.containsMouse) + color = Qt.darker(color, 1.5) - Rectangle { - id: verticalBar - width: orientationButton.width / 4 - height: orientationButton.height - color: "white" - radius: 3 - } + return color } - } - onClicked: { - if (widthField.realValue && heightField.realValue) { - [widthField.realValue, heightField.realValue] = [heightField.realValue, widthField.realValue] - orientationButton.checked = !orientationButton.checked + Rectangle { + id: horizontalBar + color: parent.computeColor(horizontalBar) + width: orientationButton.width / 2 + height: orientationButton.height / 2 + anchors.verticalCenter: parent.verticalCenter + radius: 3 + } - if (widthField.realValue === heightField.realValue) - orientationButton.checked ? setVertical() : setHorizontal() + Rectangle { + id: verticalBar + color: parent.computeColor(verticalBar) + width: orientationButton.width / 4 + height: orientationButton.height + radius: 3 } } - function setHorizontal() { - orientationButton.checked = false - horizontalBar.color = DialogValues.textColorInteraction - verticalBar.color = "white" - } + MouseArea { + id: orientationButtonMouseArea + anchors.fill: parent + hoverEnabled: true + + onClicked: { + if (widthField.realValue && heightField.realValue) { + [widthField.realValue, heightField.realValue] = [heightField.realValue, widthField.realValue] - function setVertical() { - orientationButton.checked = true - horizontalBar.color = "white" - verticalBar.color = DialogValues.textColorInteraction + if (widthField.realValue === heightField.realValue) + orientationButton.isHorizontal = !orientationButton.isHorizontal + else + orientationButton.isHorizontal = widthField.realValue > heightField.realValue + } + } } } // Orientation button - } // GridLayout: orientation + width + height Rectangle { @@ -507,6 +499,8 @@ Item { presetNameTextField.text = text.trim() presetNameTextField.text = text.replace(/\s+/g, " ") } + + onAccepted: savePresetDialog.accept() } Binding { diff --git a/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Styles.qml b/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Styles.qml index 72be983e33a..2f8da50c6c3 100644 --- a/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Styles.qml +++ b/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Styles.qml @@ -160,8 +160,17 @@ Item { + 2 * DialogValues.styleImageBorderWidth height: DialogValues.styleImageHeight + 2 * DialogValues.styleImageBorderWidth - border.color: index === stylesList.currentIndex ? DialogValues.textColorInteraction : "transparent" - border.width: index === stylesList.currentIndex ? DialogValues.styleImageBorderWidth : 0 + + border.color: itemRectMouseArea.containsMouse + ? DialogValues.textColor + : (index === stylesList.currentIndex + ? DialogValues.textColorInteraction + : "transparent") + + border.width: index === stylesList.currentIndex || itemRectMouseArea.containsMouse + ? DialogValues.styleImageBorderWidth + : 0 + color: "transparent" Image { @@ -173,6 +182,12 @@ Item { asynchronous: false source: "image://newprojectdialog_library/" + BackendApi.styleModel.iconId(model.index) } + + MouseArea { + id: itemRectMouseArea + anchors.fill: parent + hoverEnabled: true + } } // Rectangle Text { diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl index 6221e10ea61..f105c83c553 100644 --- a/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl +++ b/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl @@ -1,12 +1,12 @@ cmake_minimum_required(VERSION 3.18) -project(%{ProjectName} LANGUAGES CXX) +project(%{ProjectName}App LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) find_package(Qt6 COMPONENTS Gui Qml Quick) -add_executable(%{ProjectExecutableName} src/main.cpp) +qt_add_executable(%{ProjectExecutableName} src/main.cpp) qt_add_resources(%{ProjectExecutableName} "configuration" PREFIX "/" diff --git a/share/qtcreator/templates/wizards/classes/itemmodel/itemmodel.cpp b/share/qtcreator/templates/wizards/classes/itemmodel/itemmodel.cpp index 4a438f48e49..71f9074a69b 100644 --- a/share/qtcreator/templates/wizards/classes/itemmodel/itemmodel.cpp +++ b/share/qtcreator/templates/wizards/classes/itemmodel/itemmodel.cpp @@ -84,7 +84,7 @@ bool %{CN}::setData(const QModelIndex &index, const QVariant &value, int role) { if (data(index, role) != value) { // FIXME: Implement me! - emit dataChanged(index, index, QVector<int>() << role); + emit dataChanged(index, index, {role}); return true; } return false; @@ -95,7 +95,7 @@ Qt::ItemFlags %{CN}::flags(const QModelIndex &index) const if (!index.isValid()) return Qt::NoItemFlags; - return Qt::ItemIsEditable; // FIXME: Implement me! + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; // FIXME: Implement me! } @endif @if %{AddData} @@ -105,6 +105,7 @@ bool %{CN}::insertRows(int row, int count, const QModelIndex &parent) beginInsertRows(parent, row, row + count - 1); // FIXME: Implement me! endInsertRows(); + return true; } bool %{CN}::insertColumns(int column, int count, const QModelIndex &parent) @@ -112,6 +113,7 @@ bool %{CN}::insertColumns(int column, int count, const QModelIndex &parent) beginInsertColumns(parent, column, column + count - 1); // FIXME: Implement me! endInsertColumns(); + return true; } @endif @if %{RemoveData} @@ -121,6 +123,7 @@ bool %{CN}::removeRows(int row, int count, const QModelIndex &parent) beginRemoveRows(parent, row, row + count - 1); // FIXME: Implement me! endRemoveRows(); + return true; } bool %{CN}::removeColumns(int column, int count, const QModelIndex &parent) @@ -128,6 +131,7 @@ bool %{CN}::removeColumns(int column, int count, const QModelIndex &parent) beginRemoveColumns(parent, column, column + count - 1); // FIXME: Implement me! endRemoveColumns(); + return true; } @endif %{JS: Cpp.closeNamespaces('%{Class}')}\ diff --git a/share/qtcreator/templates/wizards/classes/itemmodel/listmodel.cpp b/share/qtcreator/templates/wizards/classes/itemmodel/listmodel.cpp index 921267d015d..9b08462ef4e 100644 --- a/share/qtcreator/templates/wizards/classes/itemmodel/listmodel.cpp +++ b/share/qtcreator/templates/wizards/classes/itemmodel/listmodel.cpp @@ -68,7 +68,7 @@ bool %{CN}::setData(const QModelIndex &index, const QVariant &value, int role) { if (data(index, role) != value) { // FIXME: Implement me! - emit dataChanged(index, index, QVector<int>() << role); + emit dataChanged(index, index, {role}); return true; } return false; @@ -79,7 +79,7 @@ Qt::ItemFlags %{CN}::flags(const QModelIndex &index) const if (!index.isValid()) return Qt::NoItemFlags; - return Qt::ItemIsEditable; // FIXME: Implement me! + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; // FIXME: Implement me! } @endif @if %{AddData} @@ -89,6 +89,7 @@ bool %{CN}::insertRows(int row, int count, const QModelIndex &parent) beginInsertRows(parent, row, row + count - 1); // FIXME: Implement me! endInsertRows(); + return true; } @endif @if %{RemoveData} @@ -98,6 +99,7 @@ bool %{CN}::removeRows(int row, int count, const QModelIndex &parent) beginRemoveRows(parent, row, row + count - 1); // FIXME: Implement me! endRemoveRows(); + return true; } @endif %{JS: Cpp.closeNamespaces('%{Class}')}\ diff --git a/share/qtcreator/templates/wizards/classes/itemmodel/tablemodel.cpp b/share/qtcreator/templates/wizards/classes/itemmodel/tablemodel.cpp index e8c71f18bb9..794510501fa 100644 --- a/share/qtcreator/templates/wizards/classes/itemmodel/tablemodel.cpp +++ b/share/qtcreator/templates/wizards/classes/itemmodel/tablemodel.cpp @@ -75,7 +75,7 @@ bool %{CN}::setData(const QModelIndex &index, const QVariant &value, int role) { if (data(index, role) != value) { // FIXME: Implement me! - emit dataChanged(index, index, QVector<int>() << role); + emit dataChanged(index, index, {role}); return true; } return false; @@ -86,7 +86,7 @@ Qt::ItemFlags %{CN}::flags(const QModelIndex &index) const if (!index.isValid()) return Qt::NoItemFlags; - return Qt::ItemIsEditable; // FIXME: Implement me! + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; // FIXME: Implement me! } @endif @if %{AddData} @@ -96,6 +96,7 @@ bool %{CN}::insertRows(int row, int count, const QModelIndex &parent) beginInsertRows(parent, row, row + count - 1); // FIXME: Implement me! endInsertRows(); + return true; } bool %{CN}::insertColumns(int column, int count, const QModelIndex &parent) @@ -103,6 +104,7 @@ bool %{CN}::insertColumns(int column, int count, const QModelIndex &parent) beginInsertColumns(parent, column, column + count - 1); // FIXME: Implement me! endInsertColumns(); + return true; } @endif @if %{RemoveData} @@ -112,6 +114,7 @@ bool %{CN}::removeRows(int row, int count, const QModelIndex &parent) beginRemoveRows(parent, row, row + count - 1); // FIXME: Implement me! endRemoveRows(); + return true; } bool %{CN}::removeColumns(int column, int count, const QModelIndex &parent) @@ -119,6 +122,7 @@ bool %{CN}::removeColumns(int column, int count, const QModelIndex &parent) beginRemoveColumns(parent, column, column + count - 1); // FIXME: Implement me! endRemoveColumns(); + return true; } @endif %{JS: Cpp.closeNamespaces('%{Class}')}\ diff --git a/src/libs/languageserverprotocol/servercapabilities.cpp b/src/libs/languageserverprotocol/servercapabilities.cpp index 8e2dc530539..dd2b7628eb1 100644 --- a/src/libs/languageserverprotocol/servercapabilities.cpp +++ b/src/libs/languageserverprotocol/servercapabilities.cpp @@ -281,11 +281,11 @@ Utils::optional<Utils::variant<QString, bool> > ServerCapabilities::WorkspaceServerCapabilities::WorkspaceFoldersCapabilities::changeNotifications() const { using RetType = Utils::variant<QString, bool>; - const QJsonValue &provider = value(implementationProviderKey); - if (provider.isUndefined()) + const QJsonValue &change = value(changeNotificationsKey); + if (change.isUndefined()) return Utils::nullopt; - return Utils::make_optional(provider.isBool() ? RetType(provider.toBool()) - : RetType(provider.toString())); + return Utils::make_optional(change.isBool() ? RetType(change.toBool()) + : RetType(change.toString())); } void ServerCapabilities::WorkspaceServerCapabilities::WorkspaceFoldersCapabilities::setChangeNotifications( diff --git a/src/libs/ssh/ssh.qbs b/src/libs/ssh/ssh.qbs index 0b940452c3d..295117c0714 100644 --- a/src/libs/ssh/ssh.qbs +++ b/src/libs/ssh/ssh.qbs @@ -4,7 +4,13 @@ Project { name: "QtcSsh" QtcLibrary { - cpp.defines: base.concat("QTCSSH_LIBRARY") + cpp.defines: { + var defines = base; + defines.push("QTCSSH_LIBRARY"); + if (project.withAutotests && !defines.contains("WITH_TESTS")) + defines.push("WITH_TESTS"); + return defines; + } cpp.enableExceptions: true Depends { name: "Qt"; submodules: ["widgets", "network" ] } diff --git a/src/libs/ssh/sshconnection.cpp b/src/libs/ssh/sshconnection.cpp index 4e695cbbfc5..2e07e12bbad 100644 --- a/src/libs/ssh/sshconnection.cpp +++ b/src/libs/ssh/sshconnection.cpp @@ -404,4 +404,95 @@ SftpTransferPtr SshConnection::setupTransfer( d->connectionArgs(SshSettings::sftpFilePath()))); } +#ifdef WITH_TESTS +namespace SshTest { +const QString getHostFromEnvironment() +{ + const QString host = QString::fromLocal8Bit(qgetenv("QTC_SSH_TEST_HOST")); + if (host.isEmpty() && qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS")) + return QString("127.0.0.1"); + return host; +} + +quint16 getPortFromEnvironment() +{ + const int port = qEnvironmentVariableIntValue("QTC_SSH_TEST_PORT"); + return port != 0 ? quint16(port) : 22; +} + +const QString getUserFromEnvironment() +{ + return QString::fromLocal8Bit(qgetenv("QTC_SSH_TEST_USER")); +} + +const QString getKeyFileFromEnvironment() +{ + const FilePath defaultKeyFile = FileUtils::homePath() / ".ssh/id_rsa"; + const QString keyFile = QString::fromLocal8Bit(qgetenv("QTC_SSH_TEST_KEYFILE")); + if (keyFile.isEmpty()) { + if (qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS")) + return defaultKeyFile.toString(); + } + return keyFile; +} + +const QString userAtHost() +{ + QString userMidFix = getUserFromEnvironment(); + if (!userMidFix.isEmpty()) + userMidFix.append('@'); + return userMidFix + getHostFromEnvironment(); +} + +SshConnectionParameters getParameters() +{ + SshConnectionParameters params; + if (!qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS")) { + params.setUserName(getUserFromEnvironment()); + params.privateKeyFile = Utils::FilePath::fromUserInput(getKeyFileFromEnvironment()); + } + params.setHost(getHostFromEnvironment()); + params.setPort(getPortFromEnvironment()); + params.timeout = 10; + params.authenticationType = !params.privateKeyFile.isEmpty() + ? QSsh::SshConnectionParameters::AuthenticationTypeSpecificKey + : QSsh::SshConnectionParameters::AuthenticationTypeAll; + return params; +} + +bool checkParameters(const QSsh::SshConnectionParameters ¶ms) +{ + if (qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS")) + return true; + if (params.host().isEmpty()) { + qWarning("No hostname provided. Set QTC_SSH_TEST_HOST."); + return false; + } + if (params.userName().isEmpty()) + qWarning("No user name provided - test may fail with empty default. Set QTC_SSH_TEST_USER."); + if (params.privateKeyFile.isEmpty()) { + qWarning("No key file provided. Set QTC_SSH_TEST_KEYFILE."); + return false; + } + return true; +} + +void printSetupHelp() +{ + qInfo() << "In order to run this test properly it requires some setup (example for fedora):\n" + "1. Run a server on the host to connect to:\n" + " systemctl start sshd\n" + "2. Create your own ssh key (needed only once). For fedora it needs ecdsa type:\n" + " ssh-keygen -t ecdsa\n" + "3. Make your public key known to the server (needed only once):\n" + " ssh-copy-id -i [full path to your public key] [user@host]\n" + "4. Set the env variables before executing test:\n" + " QTC_SSH_TEST_HOST=127.0.0.1\n" + " QTC_SSH_TEST_KEYFILE=[full path to your private key]\n" + " QTC_SSH_TEST_USER=[your user name]\n"; +} + +} // namespace SshTest +#endif + } // namespace QSsh diff --git a/src/libs/ssh/sshconnection.h b/src/libs/ssh/sshconnection.h index 74aa9bdf525..d63b5b321f1 100644 --- a/src/libs/ssh/sshconnection.h +++ b/src/libs/ssh/sshconnection.h @@ -139,6 +139,19 @@ private: SshConnectionPrivate * const d; }; +#ifdef WITH_TESTS +namespace SshTest { +const QString QSSH_EXPORT getHostFromEnvironment(); +quint16 QSSH_EXPORT getPortFromEnvironment(); +const QString QSSH_EXPORT getUserFromEnvironment(); +const QString QSSH_EXPORT getKeyFileFromEnvironment(); +const QSSH_EXPORT QString userAtHost(); +SshConnectionParameters QSSH_EXPORT getParameters(); +bool QSSH_EXPORT checkParameters(const SshConnectionParameters ¶ms); +void QSSH_EXPORT printSetupHelp(); +} // namespace SshTest +#endif + } // namespace QSsh Q_DECLARE_METATYPE(QSsh::SshConnectionParameters::AuthenticationType) diff --git a/src/libs/utils/tooltip/tips.cpp b/src/libs/utils/tooltip/tips.cpp index 2a1f4f8093f..e8c3cae6df6 100644 --- a/src/libs/utils/tooltip/tips.cpp +++ b/src/libs/utils/tooltip/tips.cpp @@ -88,7 +88,7 @@ const QMetaObject *TipLabel::metaObject() const struct qt_meta_stringdata_Utils_t { const uint offsetsAndSize[2]; char stringdata0[24]; - } qt_meta_stringdata = { 8, sizeof("QTipLabel"), "QTipLabel" }; + } qt_meta_stringdata = { {8, sizeof("QTipLabel")}, "QTipLabel" }; static const QMetaObject tipMetaObject { &QLabel::staticMetaObject, // SuperData superdata diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index 3c2d4fd5d1a..8609fc7a89f 100644 --- a/src/plugins/android/androiddevice.cpp +++ b/src/plugins/android/androiddevice.cpp @@ -624,7 +624,7 @@ void AndroidDeviceManager::HandleAvdsListChange() } QVector<Id> connectedDevs; - for (auto item : m_avdsFutureWatcher.result()) { + for (const AndroidDeviceInfo &item : m_avdsFutureWatcher.result()) { const Utils::Id deviceId = AndroidDevice::idFromDeviceInfo(item); const QString displayName = AndroidDevice::displayNameFromInfo(item); IDevice::ConstPtr dev = devMgr->find(deviceId); diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index cfa4f54f65d..8b01467e27a 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -51,6 +51,7 @@ #include <utils/environment.h> #include <utils/fileutils.h> #include <utils/hostosinfo.h> +#include <utils/infolabel.h> #include <utils/layoutbuilder.h> #include <utils/overridecursor.h> #include <utils/pathlisteditor.h> @@ -324,13 +325,26 @@ public: data.useLocalUidGid = on; }); + m_pathsListLabel = new InfoLabel(tr("Paths to mount:")); + // FIXME: 8.0: use + //m_pathsListLabel->setToolTip(tr("Source directory list should not be empty")); + m_pathsListEdit = new PathListEditor; + // FIXME: 8.0: use + //m_pathsListEdit->setPlaceholderText(tr("Host directories to mount into the container")); m_pathsListEdit->setToolTip(tr("Maps paths in this list one-to-one to the " "docker container.")); m_pathsListEdit->setPathList(data.mounts); - connect(m_pathsListEdit, &PathListEditor::changed, this, [dockerDevice, this]() { + auto markupMounts = [this] { + const bool isEmpty = m_pathsListEdit->pathList().isEmpty(); + m_pathsListLabel->setType(isEmpty ? InfoLabel::Warning : InfoLabel::None); + }; + markupMounts(); + + connect(m_pathsListEdit, &PathListEditor::changed, this, [dockerDevice, markupMounts, this] { dockerDevice->setMounts(m_pathsListEdit->pathList()); + markupMounts(); }); auto logView = new QTextBrowser; @@ -346,6 +360,8 @@ public: searchDirsComboBox->addItem(tr("Search in Selected Directories")); auto searchDirsLineEdit = new FancyLineEdit; + // FIXME: 8.0: use + //searchDirsLineEdit->setPlaceholderText(tr("Semicolon-separated list of directories")); searchDirsLineEdit->setToolTip( tr("Select the paths in the docker image that should be scanned for kit entries.")); searchDirsLineEdit->setHistoryCompleter("DockerMounts", true); @@ -397,7 +413,7 @@ public: daemonStateLabel, m_daemonReset, m_daemonState, Break(), m_runAsOutsideUser, Break(), Column { - new QLabel(tr("Paths to mount:")), + m_pathsListLabel, m_pathsListEdit, }, Break(), Column { @@ -437,7 +453,8 @@ private: QToolButton *m_daemonReset; QLabel *m_daemonState; QCheckBox *m_runAsOutsideUser; - Utils::PathListEditor *m_pathsListEdit; + InfoLabel *m_pathsListLabel; + PathListEditor *m_pathsListEdit; KitDetector m_kitItemDetector; }; @@ -1545,12 +1562,19 @@ public: m_log = new QTextBrowser; m_log->setVisible(false); + const QString fail = QString{"Docker: "} + + QCoreApplication::translate("Debugger::Internal::GdbEngine", + "Process failed to start."); + auto errorLabel = new Utils::InfoLabel(fail, Utils::InfoLabel::Error, this); + errorLabel->setVisible(false); + m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); using namespace Layouting; Column { m_view, m_log, + errorLabel, m_buttons, }.attachTo(this); @@ -1588,6 +1612,13 @@ public: m_log->append(DockerDevice::tr("Error: %1").arg(out)); }); + connect(m_process, &Utils::QtcProcess::finished, + this, [this, errorLabel]() { + if (m_process->exitCode() != 0) { + errorLabel->setVisible(true); + } + }); + connect(m_view->selectionModel(), &QItemSelectionModel::selectionChanged, [this] { const QModelIndexList selectedRows = m_view->selectionModel()->selectedRows(); QTC_ASSERT(selectedRows.size() == 1, return); diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp index 2d1ef6f554d..d679e6017d4 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp @@ -281,4 +281,20 @@ bool NavigatorTreeView::viewportEvent(QEvent *event) return QTreeView::viewportEvent(event); } +void NavigatorTreeView::mousePressEvent(QMouseEvent *event) +{ + // Block drag from starting if press was on an item that is not draggable. + // This is necessary as it is the selected items that are dragged and the pressed item may not + // be a selected item, e.g. when pressing on locked item, leading to unexpected drags. + m_dragAllowed = model()->flags(indexAt(event->pos())) & Qt::ItemIsDragEnabled; + + QTreeView::mousePressEvent(event); +} + +void NavigatorTreeView::startDrag(Qt::DropActions supportedActions) +{ + if (m_dragAllowed) + QTreeView::startDrag(supportedActions); +} + } diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreeview.h b/src/plugins/qmldesigner/components/navigator/navigatortreeview.h index 227746e207d..6f2211f82bd 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreeview.h +++ b/src/plugins/qmldesigner/components/navigator/navigatortreeview.h @@ -40,8 +40,13 @@ public: static void drawSelectionBackground(QPainter *painter, const QStyleOption &option); bool viewportEvent(QEvent *event) override; +protected: + void mousePressEvent(QMouseEvent *event) override; + void startDrag(Qt::DropActions supportedActions) override; + private: PreviewToolTip *m_previewToolTip = nullptr; qint32 m_previewToolTipNodeId = -1; + bool m_dragAllowed = true; }; } diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp index 14f1982b72d..c49a8c5035b 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp @@ -32,9 +32,9 @@ #include <coreplugin/messagebox.h> #include "pluginmanager/widgetpluginmanager.h" - #include <QDebug> #include <QMessageBox> +#include <QMutex> enum { debug = false @@ -107,6 +107,7 @@ void MetaInfoPrivate::parseItemLibraryDescriptions() using QmlDesigner::Internal::MetaInfoPrivate; MetaInfo MetaInfo::s_global; +QMutex s_lock; QStringList MetaInfo::s_pluginDirs; @@ -157,6 +158,8 @@ ItemLibraryInfo *MetaInfo::itemLibraryInfo() const */ MetaInfo MetaInfo::global() { + QMutexLocker locker(&s_lock); + if (!s_global.m_p->m_isInitialized) { s_global.m_p = QSharedPointer<MetaInfoPrivate>(new MetaInfoPrivate(&s_global)); s_global.m_p->initialize(); diff --git a/src/plugins/qmldesigner/dynamiclicensecheck.h b/src/plugins/qmldesigner/dynamiclicensecheck.h index 8cc7982895c..fb1e3661b85 100644 --- a/src/plugins/qmldesigner/dynamiclicensecheck.h +++ b/src/plugins/qmldesigner/dynamiclicensecheck.h @@ -42,27 +42,48 @@ enum FoundLicense { enterprise }; -FoundLicense checkLicense() { +namespace Internal { +ExtensionSystem::IPlugin *licenseCheckerPlugin() +{ const ExtensionSystem::PluginSpec *pluginSpec = Utils::findOrDefault( ExtensionSystem::PluginManager::plugins(), Utils::equal(&ExtensionSystem::PluginSpec::name, QString("LicenseChecker"))); - if (!pluginSpec) - return community; - - ExtensionSystem::IPlugin *plugin = pluginSpec->plugin(); + if (pluginSpec) + return pluginSpec->plugin(); + return nullptr; +} +} // namespace Internal - if (!plugin) - return community; - bool retVal = false; - bool success = QMetaObject::invokeMethod(plugin, - "qdsEnterpriseLicense", - Qt::DirectConnection, - Q_RETURN_ARG(bool, retVal)); - if (success && retVal) - return enterprise; +FoundLicense checkLicense() +{ + if (auto plugin = Internal::licenseCheckerPlugin()) { + bool retVal = false; + bool success = QMetaObject::invokeMethod(plugin, + "qdsEnterpriseLicense", + Qt::DirectConnection, + Q_RETURN_ARG(bool, retVal)); + if (success && retVal) + return enterprise; + else + return professional; + } + return community; +} - return professional; +QString licensee() +{ + if (auto plugin = Internal::licenseCheckerPlugin()) { + QString retVal; + bool success = QMetaObject::invokeMethod(plugin, + "licensee", + Qt::DirectConnection, + Q_RETURN_ARG(QString, retVal)); + if (success) + return retVal; + } + return {}; } + } // namespace Utils diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index b9ea5c5107b..d23575a8395 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -35,6 +35,7 @@ #include "qmldesignerconstants.h" #include "qmldesignerprojectmanager.h" #include "settingspage.h" +#include "dynamiclicensecheck.h" #include <metainfo.h> #include <connectionview.h> @@ -312,14 +313,24 @@ bool QmlDesignerPlugin::delayedInitialize() d->viewManager.registerFormEditorTool(std::make_unique<QmlDesigner::TransitionTool>()); if (QmlProjectManager::QmlProject::isQtDesignStudio()) { + d->mainWidget.initialize(); + emitUsageStatistics("StandaloneMode"); if (QmlProjectManager::QmlProject::isQtDesignStudioStartedFromQtC()) emitUsageStatistics("QDSlaunchedFromQtC"); - emitUsageStatistics("QDSstartupCount"); + emitUsageStatistics("QDSstartupCount"); + + FoundLicense license = checkLicense(); + if (license == FoundLicense::enterprise) + Core::ICore::appendAboutInformation(tr("License: Enterprise")); + else if (license == FoundLicense::professional) + Core::ICore::appendAboutInformation(tr("License: Professional")); + + if (!licensee().isEmpty()) + Core::ICore::appendAboutInformation(tr("Licensee: %1").arg(licensee())); } - if (QmlProjectManager::QmlProject::isQtDesignStudio()) - d->mainWidget.initialize(); + MetaInfo::global(); return true; } diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp index 17cce6402f8..bc7b6f3bde9 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp @@ -210,7 +210,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage) QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); - if (!editor) + if (!editor || !modelManager) return; if (d->lastMessageBox) diff --git a/src/plugins/remotelinux/filesystemaccess_test.cpp b/src/plugins/remotelinux/filesystemaccess_test.cpp index 2c95a5ca81b..1cf68a056c7 100644 --- a/src/plugins/remotelinux/filesystemaccess_test.cpp +++ b/src/plugins/remotelinux/filesystemaccess_test.cpp @@ -41,10 +41,12 @@ using namespace Utils; namespace RemoteLinux { namespace Internal { -static const char TEST_IP[] = "127.0.0.1"; static const char TEST_DIR[] = "/tmp/testdir"; -static const FilePath baseFilePath = FilePath::fromString("ssh://" + QString(TEST_IP) - + QString(TEST_DIR)); + +static const FilePath baseFilePath() +{ + return FilePath::fromString("ssh://" + QSsh::SshTest::userAtHost() + QString(TEST_DIR)); +} TestLinuxDeviceFactory::TestLinuxDeviceFactory() : IDeviceFactory("test") @@ -54,11 +56,9 @@ TestLinuxDeviceFactory::TestLinuxDeviceFactory() setConstructionFunction(&LinuxDevice::create); setCreator([] { LinuxDevice::Ptr newDev = LinuxDevice::create(); - qDebug() << "device : " << newDev->type(); newDev->setType("test"); - QSsh::SshConnectionParameters sshParams = newDev->sshParameters(); - sshParams.setHost(TEST_IP); - sshParams.setPort(22); + qDebug() << "device : " << newDev->type(); + QSsh::SshConnectionParameters sshParams = QSsh::SshTest::getParameters(); newDev->setSshParameters(sshParams); return newDev; }); @@ -66,15 +66,28 @@ TestLinuxDeviceFactory::TestLinuxDeviceFactory() FilePath createFile(const QString &name) { - FilePath testFilePath = baseFilePath / name; - FilePath dummyFilePath = FilePath::fromString("ssh://" + QString(TEST_IP) + "/dev/null"); + FilePath testFilePath = baseFilePath() / name; + FilePath dummyFilePath = FilePath::fromString("ssh://" + QSsh::SshTest::userAtHost() + "/dev/null"); dummyFilePath.copyFile(testFilePath); return testFilePath; } void FileSystemAccessTest::initTestCase() { - FilePath filePath = baseFilePath; + const QSsh::SshConnectionParameters params = QSsh::SshTest::getParameters(); + qDebug() << "Using following SSH parameter:" + << "\nHost:" << params.host() + << "\nPort:" << params.port() + << "\nUser:" << params.userName() + << "\nSSHKey:" << params.privateKeyFile; + if (!QSsh::SshTest::checkParameters(params)) { + m_skippedAtWhole = true; + QSsh::SshTest::printSetupHelp(); + QSKIP("Ensure you have added your default ssh public key to your own authorized keys and " + "environment QTC_REMOTELINUX_SSH_DEFAULTS set or follow setup help above."); + return; + } + FilePath filePath = baseFilePath(); if (DeviceManager::deviceForPath(filePath) == nullptr) { DeviceManager *const devMgr = DeviceManager::instance(); @@ -87,13 +100,15 @@ void FileSystemAccessTest::initTestCase() void FileSystemAccessTest::cleanupTestCase() { - QVERIFY(baseFilePath.exists()); - QVERIFY(baseFilePath.removeRecursively()); + if (m_skippedAtWhole) // no need to clean up either + return; + QVERIFY(baseFilePath().exists()); + QVERIFY(baseFilePath().removeRecursively()); } void FileSystemAccessTest::testDirStatuses() { - FilePath filePath = baseFilePath; + FilePath filePath = baseFilePath(); QVERIFY(filePath.exists()); QVERIFY(filePath.isDir()); QVERIFY(filePath.isWritableDir()); @@ -120,7 +135,7 @@ void FileSystemAccessTest::testDirStatuses() void FileSystemAccessTest::testBytesAvailable() { - FilePath testFilePath = FilePath::fromString("ssh://" + QString(TEST_IP) + "/tmp"); + FilePath testFilePath = FilePath::fromString("ssh://" + QSsh::SshTest::userAtHost() + "/tmp"); QVERIFY(testFilePath.exists()); QVERIFY(testFilePath.bytesAvailable() > 0); } @@ -143,9 +158,9 @@ void FileSystemAccessTest::testFileActions() // ToDo: remove ".contains", make fileContents exact equal content QVERIFY(testFilePath.fileContents().contains(content)); - QVERIFY(testFilePath.renameFile(baseFilePath / "test1")); + QVERIFY(testFilePath.renameFile(baseFilePath() / "test1")); // It is Ok that FilePath doesn't change itself after rename. - FilePath newTestFilePath = baseFilePath / "test1"; + FilePath newTestFilePath = baseFilePath() / "test1"; QVERIFY(newTestFilePath.exists()); QVERIFY(!testFilePath.removeFile()); QVERIFY(newTestFilePath.exists()); diff --git a/src/plugins/remotelinux/filesystemaccess_test.h b/src/plugins/remotelinux/filesystemaccess_test.h index 4b43e202d44..7dacd1ae936 100644 --- a/src/plugins/remotelinux/filesystemaccess_test.h +++ b/src/plugins/remotelinux/filesystemaccess_test.h @@ -53,6 +53,7 @@ private slots: private: TestLinuxDeviceFactory m_testLinuxDeviceFactory; + bool m_skippedAtWhole = false; }; } // Internal diff --git a/src/plugins/texteditor/snippets/snippeteditor.cpp b/src/plugins/texteditor/snippets/snippeteditor.cpp index 63ca32273a9..01e3757182d 100644 --- a/src/plugins/texteditor/snippets/snippeteditor.cpp +++ b/src/plugins/texteditor/snippets/snippeteditor.cpp @@ -61,4 +61,9 @@ void SnippetEditorWidget::focusOutEvent(QFocusEvent *event) TextEditorWidget::focusOutEvent(event); } +void SnippetEditorWidget::contextMenuEvent(QContextMenuEvent *e) +{ + QPlainTextEdit::contextMenuEvent(e); +} + } // namespace diff --git a/src/plugins/texteditor/snippets/snippeteditor.h b/src/plugins/texteditor/snippets/snippeteditor.h index 8bb972cf685..f422c09bb5f 100644 --- a/src/plugins/texteditor/snippets/snippeteditor.h +++ b/src/plugins/texteditor/snippets/snippeteditor.h @@ -42,6 +42,7 @@ signals: protected: void focusOutEvent(QFocusEvent *event) override; + void contextMenuEvent(QContextMenuEvent *e) override; int extraAreaWidth(int * /* markWidthPtr */ = nullptr) const override { return 0; } }; diff --git a/tests/auto/ssh/CMakeLists.txt b/tests/auto/ssh/CMakeLists.txt index 2156e6d59aa..8dd1915805f 100644 --- a/tests/auto/ssh/CMakeLists.txt +++ b/tests/auto/ssh/CMakeLists.txt @@ -3,6 +3,7 @@ file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_L add_qtc_test(tst_ssh DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\"" + WITH_TESTS DEPENDS Utils QtcSsh SOURCES tst_ssh.cpp ) diff --git a/tests/auto/ssh/ssh.qbs b/tests/auto/ssh/ssh.qbs index 3f513cca778..c4f4fe38c09 100644 --- a/tests/auto/ssh/ssh.qbs +++ b/tests/auto/ssh/ssh.qbs @@ -11,6 +11,7 @@ QtcAutotest { qtc.ide_libexec_path); var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath); defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"'); + defines.push("WITH_TESTS"); return defines; } } diff --git a/tests/auto/ssh/tst_ssh.cpp b/tests/auto/ssh/tst_ssh.cpp index 26fb09caa0b..cce90e79ba5 100644 --- a/tests/auto/ssh/tst_ssh.cpp +++ b/tests/auto/ssh/tst_ssh.cpp @@ -47,73 +47,8 @@ #include <cstdlib> -/* -In order to run this test properly it requires some setup (example for fedora): -1. Run a server: - systemctl start sshd -2. Create your own ssh key (needed only once). For fedora it needs ecdsa type: - ssh-keygen -t ecdsa -3. Make your public key known to the server (needed only once): - ssh-copy-id -i [full path to your public key] -4. Set the env variables before executing test: - QTC_SSH_TEST_HOST=127.0.0.1 - QTC_SSH_TEST_KEYFILE=[full path to your private key] - QTC_SSH_TEST_USER=[your user name] -*/ using namespace QSsh; -static QString getHostFromEnvironment() -{ - return QString::fromLocal8Bit(qgetenv("QTC_SSH_TEST_HOST")); -} - -static const char *portVar() { return "QTC_SSH_TEST_PORT"; } -static const char *userVar() { return "QTC_SSH_TEST_USER"; } -static const char *keyFileVar() { return "QTC_SSH_TEST_KEYFILE"; } - -static quint16 getPortFromEnvironment() -{ - const int port = qEnvironmentVariableIntValue(portVar()); - return port != 0 ? quint16(port) : 22; -} - -static QString getUserFromEnvironment() -{ - return QString::fromLocal8Bit(qgetenv(userVar())); -} - -static QString getKeyFileFromEnvironment() -{ - return QString::fromLocal8Bit(qgetenv(keyFileVar())); -} - -static SshConnectionParameters getParameters() -{ - SshConnectionParameters params; - params.setHost(getHostFromEnvironment()); - params.setPort(getPortFromEnvironment()); - params.setUserName(getUserFromEnvironment()); - params.timeout = 10; - params.privateKeyFile = Utils::FilePath::fromUserInput(getKeyFileFromEnvironment()); - params.authenticationType = !params.privateKeyFile.isEmpty() - ? SshConnectionParameters::AuthenticationTypeSpecificKey - : SshConnectionParameters::AuthenticationTypeAll; - return params; -} - -#define CHECK_PARAMS(params) \ - do { \ - if (params.host().isEmpty()) { \ - QSKIP("No hostname provided. Set QTC_SSH_TEST_HOST."); \ - } \ - if (params.userName().isEmpty()) \ - QSKIP(qPrintable(QString::fromLatin1("No user name provided. Set %1.") \ - .arg(QString::fromUtf8(userVar())))); \ - if (params.privateKeyFile.isEmpty()) \ - QSKIP(qPrintable(QString::fromLatin1("No key file provided. Set %1.") \ - .arg(QString::fromUtf8(keyFileVar())))); \ - } while (false) - class tst_Ssh : public QObject { Q_OBJECT @@ -137,6 +72,10 @@ private: void tst_Ssh::initTestCase() { + const SshConnectionParameters params = SshTest::getParameters(); + if (!SshTest::checkParameters(params)) + SshTest::printSetupHelp(); + Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/' + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH)); Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() @@ -154,10 +93,10 @@ void tst_Ssh::errorHandling_data() QTest::newRow("no host") << QString("hgdfxgfhgxfhxgfchxgcf") << quint16(12345) << SshConnectionParameters::AuthenticationTypeAll << QString("egal") << QString(); - const QString theHost = getHostFromEnvironment(); + const QString theHost = SshTest::getHostFromEnvironment(); if (theHost.isEmpty()) return; - const quint16 thePort = getPortFromEnvironment(); + const quint16 thePort = SshTest::getPortFromEnvironment(); QTest::newRow("non-existing key file") << theHost << thePort << SshConnectionParameters::AuthenticationTypeSpecificKey << QString("root") << QString("somefilenamethatwedontexpecttocontainavalidkey"); @@ -228,8 +167,9 @@ void tst_Ssh::remoteProcess_data() void tst_Ssh::remoteProcess() { - const SshConnectionParameters params = getParameters(); - CHECK_PARAMS(params); + const SshConnectionParameters params = SshTest::getParameters(); + if (!SshTest::checkParameters(params)) + QSKIP("Insufficient setup - set QTC_SSH_TEST_* variables."); QFETCH(QByteArray, commandLine); QFETCH(bool, isBlocking); @@ -287,8 +227,9 @@ void tst_Ssh::remoteProcess() void tst_Ssh::remoteProcessChannels() { - const SshConnectionParameters params = getParameters(); - CHECK_PARAMS(params); + const SshConnectionParameters params = SshTest::getParameters(); + if (!SshTest::checkParameters(params)) + QSKIP("Insufficient setup - set QTC_SSH_TEST_* variables."); SshConnection connection(params); QVERIFY(waitForConnection(connection)); @@ -325,8 +266,9 @@ void tst_Ssh::remoteProcessChannels() void tst_Ssh::remoteProcessInput() { - const SshConnectionParameters params = getParameters(); - CHECK_PARAMS(params); + const SshConnectionParameters params = SshTest::getParameters(); + if (!SshTest::checkParameters(params)) + QSKIP("Insufficient setup - set QTC_SSH_TEST_* variables."); SshConnection connection(params); QVERIFY(waitForConnection(connection)); @@ -369,8 +311,9 @@ void tst_Ssh::remoteProcessInput() void tst_Ssh::sftp() { // Connect to server - const SshConnectionParameters params = getParameters(); - CHECK_PARAMS(params); + const SshConnectionParameters params = SshTest::getParameters(); + if (!SshTest::checkParameters(params)) + QSKIP("Insufficient setup - set QTC_SSH_TEST_* variables."); SshConnection connection(params); QVERIFY(waitForConnection(connection)); diff --git a/tests/manual/docker/boot2qt/build.sh b/tests/manual/docker/boot2qt/build.sh index 9d8c87a8240..7365a4477f3 100755 --- a/tests/manual/docker/boot2qt/build.sh +++ b/tests/manual/docker/boot2qt/build.sh @@ -28,9 +28,15 @@ uid=$(id -u) gid=$(id -g) +repo=b2qt-qemuarm64 +tag=6.0.0 +tcdir=/opt/toolchain +envfile=environment-setup-skylake-64-poky-linux +qtcconf=configure-qtcreator.sh + if [ ! -e toolchain.sh ]; then host=http://ci-files02-hki.intra.qt.io - dir=/packages/jenkins/enterprise/b2qt/yocto/6.2/ + dir=/packages/jenkins/enterprise/b2qt/yocto/dev/intel-skylake-64 file=b2qt-x86_64-meta-toolchain-b2qt-embedded-qt6-sdk-intel-skylake-64.sh curl $host/$dir/$file -o $file || exit 1 ln -s $file toolchain.sh @@ -38,4 +44,118 @@ fi sed -e "s/<UID>/${uid}/" -e "s/<GID>/${gid}/" Dockerfile.in > Dockerfile -docker build -f Dockerfile . -t b2qt-qemuarm64:6.0.0 +docker build -f Dockerfile . -t $repo:$tag + + +ABI="x86-linux-poky-elf-64bit" + +OECORE_NATIVE_SYSROOT=/opt/toolchain/sysroots/x86_64-pokysdk-linux +PREFIX="docker://$repo:$tag/opt/toolchain/sysroots/x86_64-pokysdk-linux" + +CC="${PREFIX}/usr/bin/x86_64-poky-linux/x86_64-poky-linux-gcc" +CXX="${PREFIX}/usr/bin/x86_64-poky-linux/x86_64-poky-linux-g++" +GDB="${PREFIX}/usr/bin/x86_64-poky-linux/x86_64-poky-linux-gdb" +QMAKE="${PREFIX}/usr/bin/qmake" +CMAKE="${PREFIX}/usr/bin/cmake" + +SDKTOOL="../../../../libexec/qtcreator/sdktool" + +MACHINE="intel-skylake-64" + +if [ ! -x ${SDKTOOL} ]; then + echo "Cannot find 'sdktool' from QtCreator" + exit 1 +fi + + +#MKSPEC=$(qmake -query QMAKE_XSPEC) +MKSPEC=linux-oe-g++ + +#RELEASE=$(qmake -query QT_VERSION) +RELEASE=$tag + +NAME=${NAME:-"Custom Qt ${RELEASE} ${MACHINE}"} +BASEID="byos.${RELEASE}.${MACHINE}" + +${SDKTOOL} rmKit --id ${BASEID}.kit 2>/dev/null || true +${SDKTOOL} rmQt --id ${BASEID}.qt || true +${SDKTOOL} rmTC --id ProjectExplorer.ToolChain.Gcc:${BASEID}.gcc || true +${SDKTOOL} rmTC --id ProjectExplorer.ToolChain.Gcc:${BASEID}.g++ || true +${SDKTOOL} rmDebugger --id ${BASEID}.gdb 2>/dev/null || true +${SDKTOOL} rmCMake --id ${BASEID}.cmake 2>/dev/null || true +${SDKTOOL} rmDev --id "$repo:$tag" 2>/dev/null || true + +if [ -n "${REMOVEONLY}" ]; then + echo "Kit removed: ${NAME}" + exit 0 +fi + +${SDKTOOL} addAbiFlavor \ + --flavor poky \ + --oses linux 2>/dev/null || true + +${SDKTOOL} addDev \ + --id "$repo:$tag" \ + --type 1 \ + --name "Docker $repo:$tag" \ + --dockerRepo $repo \ + --dockerTag $tag \ + --dockerMappedPaths '/data' \ + --osType DockerDeviceType + +${SDKTOOL} addTC \ + --id "ProjectExplorer.ToolChain.Gcc:${BASEID}.gcc" \ + --name "GCC ${NAME}" \ + --path "${CC}" \ + --abi "${ABI}" \ + --language C + +${SDKTOOL} addTC \ + --id "ProjectExplorer.ToolChain.Gcc:${BASEID}.g++" \ + --name "G++ ${NAME}" \ + --path "${CXX}" \ + --abi "${ABI}" \ + --language Cxx + +${SDKTOOL} addDebugger \ + --id "${BASEID}.gdb" \ + --name "GDB ${NAME}" \ + --engine 1 \ + --binary "${GDB}" \ + --abis "${ABI}" + +${SDKTOOL} addQt \ + --id "${BASEID}.qt" \ + --name "${NAME}" \ + --type "Qdb.EmbeddedLinuxQt" \ + --qmake ${QMAKE} \ + --abis "${ABI}" + +${SDKTOOL} addCMake \ + --id "${BASEID}.cmake" \ + --name "CMake ${NAME}" \ + --path ${CMAKE} + +${SDKTOOL} addKit \ + --id "${BASEID}.kit" \ + --name "${NAME}" \ + --qt "${BASEID}.qt" \ + --debuggerid "${BASEID}.gdb" \ + --sysroot "docker://$repo:$tag/opt/toolchain/sysroots/skylake-64-poky-linux" \ + --devicetype "DockerDeviceType" \ + --device "$repo:$tag" \ + --builddevice "$repo:$tag" \ + --Ctoolchain "ProjectExplorer.ToolChain.Gcc:${BASEID}.gcc" \ + --Cxxtoolchain "ProjectExplorer.ToolChain.Gcc:${BASEID}.g++" \ + --icon ":/boot2qt/images/B2Qt_QtC_icon.png" \ + --mkspec "" \ + --cmake "${BASEID}.cmake" \ + --cmake-config "CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}" \ + --cmake-config "CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}" \ + --cmake-config "CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX}" \ + --cmake-config "QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable}" \ + --cmake-config "CMAKE_TOOLCHAIN_FILE:FILEPATH=${OECORE_NATIVE_SYSROOT}/usr/lib/cmake/Qt6/qt.toolchain.cmake" \ + --cmake-config "CMAKE_MAKE_PROGRAM:FILEPATH=ninja" \ + --cmake-generator "Ninja" + +echo "Configured Qt Creator with new kit: ${NAME}" diff --git a/tests/system/objects.map b/tests/system/objects.map index a222860aadc..074fc19ae7e 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -22,7 +22,6 @@ :Add Bookmark_BookmarkDialog {name='BookmarkDialog' type='BookmarkDialog' visible='1' windowTitle='Add Bookmark'} :Add to Version Control.No_QPushButton {text='No' type='QPushButton' unnamed='1' visible='1' window=':Add to Version Control_QMessageBox'} :Add to Version Control_QMessageBox {text~='Add the file.*to version control (.*)?' type='QMessageBox' unnamed='1' visible='1'} -:Additional arguments:_QWidget {buddy=':Qt Creator.Additional arguments:_QLabel' type='QWidget' unnamed='1' visible='1'} :Analyzer Toolbar.AnalyzerManagerToolBox_QComboBox {container=':DebugModeWidget.Toolbar_QDockWidget' name='PerspectiveChooser' type='QComboBox' visible='1'} :Analyzer Toolbar.Clear_QToolButton {container=':DebugModeWidget.Toolbar_QDockWidget' toolTip='Discard data' type='QToolButton' unnamed='1' visible='1'} :Analyzer Toolbar.Elapsed:_QLabel {container=':DebugModeWidget.Toolbar_QDockWidget' text~='Elapsed: \\\\d+.\\\\d s' type='QLabel' unnamed='1' visible='1'} @@ -118,15 +117,12 @@ :QML Debugging.No_QPushButton {text='No' type='QPushButton' unnamed='1' visible='1' window=':QML Debugging_QMessageBox'} :QML Debugging_QMessageBox {text='The option will only take effect if the project is recompiled. Do you want to recompile now?' type='QMessageBox' unnamed='1' visible='1'} :Qt Creator.Add Bookmark_QToolButton {text='Add Bookmark' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} -:Qt Creator.Additional arguments:_QLabel {text='Additional arguments:' type='QLabel' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.CloseDoc_QToolButton {toolTip?='Close Document *' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.CloseFind_QToolButton {name='close' type='QToolButton' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.Compile Output_Core::OutputWindow {type='Core::OutputWindow' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow' windowTitle='Compile Output'} :Qt Creator.Configure Project_QPushButton {text='Configure Project' type='QPushButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.DebugModeWidget_QSplitter {name='DebugModeWidget' type='QSplitter' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.DragDoc_QToolButton {toolTip='Drag to drag documents between splits' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} -:Qt Creator.Effective qmake call:_QLabel {text='Effective qmake call:' type='QLabel' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} -:Qt Creator.Effective qmake call:_QTextEdit {aboveWidget=':Additional arguments:_QWidget' leftWidget=':Qt Creator.Effective qmake call:_QLabel' type='QTextEdit' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.Events_QDockWidget {name='QmlProfiler.Statistics.DockDockWidget' type='QDockWidget' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.Events_QTabBar {aboveWidget=':Qt Creator.Events_QDockWidget' type='QTabBar' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.Issues_QListView {type='QListView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow' windowTitle='Issues'} diff --git a/tests/system/shared/build_utils.py b/tests/system/shared/build_utils.py index f74bea0df10..a58a1fa93d7 100644 --- a/tests/system/shared/build_utils.py +++ b/tests/system/shared/build_utils.py @@ -163,13 +163,17 @@ def selectBuildConfig(wantedKit, configName, afterSwitchTo=ViewConstants.EDIT): test.warning("Don't know where you trying to switch to (%s)" % afterSwitchTo) # This will not trigger a rebuild. If needed, caller has to do this. -def verifyBuildConfig(currentTarget, configName, shouldBeDebug=False, enableShadowBuild=False, enableQmlDebug=False): +def verifyBuildConfig(currentTarget, configName, shouldBeDebug=False, enableShadowBuild=False, + enableQmlDebug=False, buildSystem=None): selectBuildConfig(currentTarget, configName, None) ensureChecked(waitForObject(":scrollArea.Details_Utils::DetailsButton")) - ensureChecked("{leftWidget={text='Shadow build:' type='QLabel' unnamed='1' visible='1' " - "window=':Qt Creator_Core::Internal::MainWindow'} " - "type='QCheckBox' unnamed='1' visible='1' " - "window=':Qt Creator_Core::Internal::MainWindow'}", enableShadowBuild) + + if buildSystem == "qmake": + ensureChecked("{leftWidget={text='Shadow build:' type='QLabel' unnamed='1' visible='1' " + "window=':Qt Creator_Core::Internal::MainWindow'} " + "type='QCheckBox' unnamed='1' visible='1' " + "window=':Qt Creator_Core::Internal::MainWindow'}", enableShadowBuild) + buildCfCombo = waitForObject("{leftWidget=':scrollArea.Edit build configuration:_QLabel' " "type='QComboBox' unnamed='1' visible='1'}") if shouldBeDebug: @@ -184,11 +188,15 @@ def verifyBuildConfig(currentTarget, configName, shouldBeDebug=False, enableShad pass # Since waitForObject waits for the object to be enabled, # it will wait here until compilation of the debug libraries has finished. + runCMakeButton = ("{type='QPushButton' text='Run CMake' unnamed='1' " + "window=':Qt Creator_Core::Internal::MainWindow'}") if currentTarget not in (Targets.DESKTOP_4_8_7_DEFAULT, Targets.EMBEDDED_LINUX): qmlDebuggingCombo = findObject(':Qt Creator.QML debugging and profiling:_QComboBox') if selectFromCombo(qmlDebuggingCombo, 'Enable'): - # Don't rebuild now - clickButton(waitForObject(":QML Debugging.No_QPushButton", 5000)) + if buildSystem is None or buildSystem == "CMake": # re-run cmake to apply + clickButton(waitForObject(runCMakeButton)) + elif buildSystem == "qmake": # Don't rebuild now + clickButton(waitForObject(":QML Debugging.No_QPushButton", 5000)) try: problemFound = waitForObject("{window=':Qt Creator_Core::Internal::MainWindow' " "type='QLabel' name='problemLabel' visible='1'}", 1000) @@ -201,8 +209,10 @@ def verifyBuildConfig(currentTarget, configName, shouldBeDebug=False, enableShad qmlDebuggingCombo = findObject(':Qt Creator.QML debugging and profiling:_QComboBox') if selectFromCombo(qmlDebuggingCombo, "Disable"): test.log("Qml debugging libraries are available - unchecked qml debugging.") - # Don't rebuild now - clickButton(waitForObject(":QML Debugging.No_QPushButton", 5000)) + if buildSystem is None or buildSystem == "CMake": # re-run cmake to apply + clickButton(waitForObject(runCMakeButton)) + elif buildSystem == "qmake": # Don't rebuild now + clickButton(waitForObject(":QML Debugging.No_QPushButton", 5000)) clickButton(waitForObject(":scrollArea.Details_Utils::DetailsButton")) switchViewTo(ViewConstants.EDIT) diff --git a/tests/system/shared/debugger.py b/tests/system/shared/debugger.py index daf67db6aaf..39b184146e4 100644 --- a/tests/system/shared/debugger.py +++ b/tests/system/shared/debugger.py @@ -84,7 +84,7 @@ def setBreakpointsForCurrentProject(filesAndLines): editor = getEditorForFileSuffix(curFile, True) if not placeCursorToLine(editor, curLine, True): return None - invokeMenuItem("Debug", "Toggle Breakpoint") + invokeMenuItem("Debug", "Enable or Disable Breakpoint") filePath = str(waitForObjectExists(":Qt Creator_FilenameQComboBox").toolTip) breakPointList.append({filePath:lineNumberWithCursor(editor)}) test.log('Set breakpoint in %s' % curFile, curLine) @@ -175,8 +175,24 @@ def doSimpleDebugging(currentKit, currentConfigName, expectedBPOrder=[], enableQ def isMsvcConfig(currentKit): switchViewTo(ViewConstants.PROJECTS) switchToBuildOrRunSettingsFor(currentKit, ProjectSettings.BUILD) - clickButton(waitForObject(":scrollArea.Details_Utils::DetailsButton")) - isMsvc = " -spec win32-msvc" in str(waitForObject(":Qt Creator.Effective qmake call:_QTextEdit").plainText) + + waitForObject(":Projects.ProjectNavigationTreeView") + bAndRIndex = getQModelIndexStr("text='Build & Run'", ":Projects.ProjectNavigationTreeView") + wantedKitName = Targets.getStringForTarget(currentKit) + wantedKitIndexString = getQModelIndexStr("text='%s'" % wantedKitName, bAndRIndex) + if not test.verify(__kitIsActivated__(findObject(wantedKitIndexString)), + "Verifying target '%s' is enabled." % wantedKitName): + raise Exception("Kit '%s' is not activated in the project." % wantedKitName) + index = waitForObject(wantedKitIndexString) + toolTip = str(index.data(Qt.ToolTipRole).toString()) + compilerPattern = re.compile("<tr><td><b>Compiler:</b></td><td>(?P<compiler>.+)</td></tr>") + match = compilerPattern.search(toolTip) + if match is None: + test.warning("UI seems to have changed - failed to check for compiler.") + return False + + compiler = str(match.group("compiler")) + isMsvc = compiler.startswith("MSVC") or compiler.startswith("Microsoft Visual C") switchViewTo(ViewConstants.EDIT) return isMsvc diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py index e5f4c4bc6b6..16570424b03 100644 --- a/tests/system/shared/project.py +++ b/tests/system/shared/project.py @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (C) 2016 The Qt Company Ltd. +# Copyright (C) 2022 The Qt Company Ltd. # Contact: https://www.qt.io/licensing/ # # This file is part of Qt Creator. @@ -69,10 +69,8 @@ def openCmakeProject(projectPath, buildDir): invokeMenuItem("File", "Open File or Project...") selectFromFileDialog(projectPath) __chooseTargets__([]) # uncheck all - targetToChoose = Targets.DESKTOP_4_8_7_DEFAULT # FIXME make the intended target a parameter - if not qt4Available: - targetToChoose = Targets.DESKTOP_5_14_1_DEFAULT - __chooseTargets__([targetToChoose], additionalFunc=additionalFunction) + # FIXME make the intended target a parameter + __chooseTargets__([Targets.DESKTOP_5_14_1_DEFAULT], additionalFunc=additionalFunction) clickButton(waitForObject(":Qt Creator.Configure Project_QPushButton")) return True @@ -224,22 +222,31 @@ def __modifyAvailableTargets__(available, requiredQt, asStrings=False): if Qt5Path.toVersionTuple(found.group(1)) < Qt5Path.toVersionTuple(requiredQt): available.discard(currentItem) +def __getProjectFileName__(projectName, buildSystem): + if buildSystem is None or buildSystem == "CMake": + return "CMakeLists.txt" + else: + return projectName + (".pro" if buildSystem == "qmake" else ".qbs") + # Creates a Qt GUI project # param path specifies where to create the project # param projectName is the name for the new project # param checks turns tests in the function on if set to True -def createProject_Qt_GUI(path, projectName, checks = True, addToVersionControl = "<None>"): +# param addToVersionControl selects the specified VCS from Creator's wizard +# param buildSystem selects the specified build system from Creator's wizard +def createProject_Qt_GUI(path, projectName, checks=True, addToVersionControl="<None>", + buildSystem=None): template = "Qt Widgets Application" available = __createProjectOrFileSelectType__(" Application (Qt)", template) __createProjectSetNameAndPath__(path, projectName, checks) - buildSystem = __handleBuildSystem__(None) + buildSystem = __handleBuildSystem__(buildSystem) if checks: exp_filename = "mainwindow" h_file = exp_filename + ".h" cpp_file = exp_filename + ".cpp" ui_file = exp_filename + ".ui" - pro_file = projectName + ".pro" + projectFile = __getProjectFileName__(projectName, buildSystem) waitFor("object.exists(':headerFileLineEdit_Utils::FileNameValidatingLineEdit')", 20000) waitFor("object.exists(':sourceFileLineEdit_Utils::FileNameValidatingLineEdit')", 20000) @@ -259,7 +266,7 @@ def createProject_Qt_GUI(path, projectName, checks = True, addToVersionControl = path = os.path.abspath(path) path = os.path.join(path, projectName) expectedFiles = [path] - expectedFiles.extend(__sortFilenamesOSDependent__(["main.cpp", cpp_file, h_file, ui_file, pro_file])) + expectedFiles.extend(__sortFilenamesOSDependent__(["main.cpp", cpp_file, h_file, ui_file, projectFile])) __createProjectHandleLastPage__(expectedFiles, addToVersionControl) waitForProjectParsing() @@ -283,9 +290,9 @@ def createProject_Qt_Console(path, projectName, checks = True, buildSystem = Non path = os.path.abspath(path) path = os.path.join(path, projectName) cpp_file = "main.cpp" - pro_file = projectName + ".pro" + projectFile = __getProjectFileName__(projectName, buildSystem) expectedFiles = [path] - expectedFiles.extend(__sortFilenamesOSDependent__([cpp_file, pro_file])) + expectedFiles.extend(__sortFilenamesOSDependent__([cpp_file, projectFile])) __createProjectHandleLastPage__(expectedFiles) waitForProjectParsing() @@ -375,7 +382,8 @@ def createNewNonQtProject(workingDir, projectName, target, plainC=False, buildSy __createProjectHandleLastPage__() return projectName -def createNewCPPLib(projectDir, projectName, className, target, isStatic): + +def createNewCPPLib(projectDir, projectName, className, target, isStatic, buildSystem=None): available = __createProjectOrFileSelectType__(" Library", "C++ Library", False, True) if isStatic: libType = LibType.STATIC @@ -384,7 +392,7 @@ def createNewCPPLib(projectDir, projectName, className, target, isStatic): if projectDir == None: projectDir = tempDir() projectName = __createProjectSetNameAndPath__(projectDir, projectName, False) - __handleBuildSystem__(None) + __handleBuildSystem__(buildSystem) selectFromCombo(waitForObject("{name='Type' type='QComboBox' visible='1' " "window=':New_ProjectExplorer::JsonWizard'}"), LibType.getStringForLib(libType)) @@ -396,10 +404,12 @@ def createNewCPPLib(projectDir, projectName, className, target, isStatic): __createProjectHandleLastPage__() return projectName, className -def createNewQtPlugin(projectDir, projectName, className, target, baseClass="QGenericPlugin"): + +def createNewQtPlugin(projectDir, projectName, className, target, baseClass="QGenericPlugin", + buildSystem=None): available = __createProjectOrFileSelectType__(" Library", "C++ Library", False, True) projectName = __createProjectSetNameAndPath__(projectDir, projectName, False) - __handleBuildSystem__(None) + __handleBuildSystem__(buildSystem) selectFromCombo(waitForObject("{name='Type' type='QComboBox' visible='1' " "window=':New_ProjectExplorer::JsonWizard'}"), LibType.getStringForLib(LibType.QT_PLUGIN)) diff --git a/tests/system/suite_APTW/tst_APTW01/test.py b/tests/system/suite_APTW/tst_APTW01/test.py index ac833cffc93..cb03f38e1b8 100644 --- a/tests/system/suite_APTW/tst_APTW01/test.py +++ b/tests/system/suite_APTW/tst_APTW01/test.py @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (C) 2016 The Qt Company Ltd. +# Copyright (C) 2022 The Qt Company Ltd. # Contact: https://www.qt.io/licensing/ # # This file is part of Qt Creator. @@ -31,7 +31,7 @@ def main(): # warnings from the clang code model in "issues" view if not startCreatorVerifyingClang(False): return - createProject_Qt_GUI(tempDir(), "SampleApp") + createProject_Qt_GUI(tempDir(), "SampleApp", buildSystem="qmake") # run project for debug and release and verify results runVerify() #close Qt Creator diff --git a/tests/system/suite_APTW/tst_APTW02/test.py b/tests/system/suite_APTW/tst_APTW02/test.py index bff30f84e4e..e4f9a6d6ea1 100644 --- a/tests/system/suite_APTW/tst_APTW02/test.py +++ b/tests/system/suite_APTW/tst_APTW02/test.py @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (C) 2016 The Qt Company Ltd. +# Copyright (C) 2022 The Qt Company Ltd. # Contact: https://www.qt.io/licensing/ # # This file is part of Qt Creator. @@ -30,7 +30,7 @@ def main(): startQC() if not startedWithoutPluginError(): return - createNewQtQuickApplication(tempDir(), "SampleApp") + createNewQtQuickApplication(tempDir(), "SampleApp", buildSystem="qmake") # run project for debug and release and verify results runVerify() #close Qt Creator diff --git a/tests/system/suite_APTW/tst_APTW03/test.py b/tests/system/suite_APTW/tst_APTW03/test.py index 2a7c78bdde1..e18b67ea978 100644 --- a/tests/system/suite_APTW/tst_APTW03/test.py +++ b/tests/system/suite_APTW/tst_APTW03/test.py @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (C) 2016 The Qt Company Ltd. +# Copyright (C) 2022 The Qt Company Ltd. # Contact: https://www.qt.io/licensing/ # # This file is part of Qt Creator. @@ -65,9 +65,9 @@ def handleInsertVirtualFunctions(expected, toAdd): def checkSimpleCppLib(projectName, static): projectName, className = createNewCPPLib(tempDir(), projectName, "MyClass", Targets.desktopTargetClasses(), - static) + static, buildSystem="qmake") for kit, config in iterateBuildConfigs("Release"): - verifyBuildConfig(kit, config, False, True) + verifyBuildConfig(kit, config, False, True, buildSystem="qmake") invokeMenuItem('Build', 'Build Project "%s"' % projectName) waitForCompile(10000) checkCompile() @@ -87,10 +87,11 @@ def main(): checkSimpleCppLib("SampleApp2", True) pluginTargets = (Targets.DESKTOP_5_10_1_DEFAULT, Targets.DESKTOP_5_14_1_DEFAULT) - projectName, className = createNewQtPlugin(tempDir(), "SampleApp3", "MyPlugin", pluginTargets) + projectName, className = createNewQtPlugin(tempDir(), "SampleApp3", "MyPlugin", pluginTargets, + buildSystem="qmake") virtualFunctionsAdded = False for kit, config in iterateBuildConfigs("Debug"): - verifyBuildConfig(kit, config, True, True) + verifyBuildConfig(kit, config, True, True, buildSystem="qmake") invokeMenuItem('Build', 'Build Project "%s"' % projectName) waitForCompile(10000) if not virtualFunctionsAdded: diff --git a/tests/system/suite_debugger/tst_debug_empty_main/test.py b/tests/system/suite_debugger/tst_debug_empty_main/test.py index 3e0e456e921..4a2bd938288 100644 --- a/tests/system/suite_debugger/tst_debug_empty_main/test.py +++ b/tests/system/suite_debugger/tst_debug_empty_main/test.py @@ -98,7 +98,7 @@ def __handleAppOutputWaitForDebuggerFinish__(): def performDebugging(projectName): for kit, config in iterateBuildConfigs("Debug"): test.log("Selecting '%s' as build config" % config) - verifyBuildConfig(kit, config, True, True) + verifyBuildConfig(kit, config, True, True, buildSystem="qmake") waitForObject(":*Qt Creator.Build Project_Core::Internal::FancyToolButton") selectFromLocator("t rebuild", "Rebuild (Rebuild All Projects)") waitForCompile() @@ -111,7 +111,7 @@ def performDebugging(projectName): editor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") placeCursorToLine(editor, "int main.*", True) type(editor, "<Down>") - invokeMenuItem("Debug", "Toggle Breakpoint") + invokeMenuItem("Debug", "Enable or Disable Breakpoint") clickButton(waitForObject(":*Qt Creator.Start Debugging_Core::Internal::FancyToolButton")) handleDebuggerWarnings(config, isMsvc) clickButton(waitForObject(":*Qt Creator.Continue_Core::Internal::FancyToolButton")) diff --git a/tests/system/suite_debugger/tst_simple_debug/test.py b/tests/system/suite_debugger/tst_simple_debug/test.py index 7237e00aae0..8c9c71a8fc2 100644 --- a/tests/system/suite_debugger/tst_simple_debug/test.py +++ b/tests/system/suite_debugger/tst_simple_debug/test.py @@ -44,8 +44,8 @@ def main(): 'onTriggered: console.log("Break here")']) invokeMenuItem("File", "Save All") filesAndLines = [ - { "%s.Sources.main\\.cpp" % projectName : "QQmlApplicationEngine engine;" }, - { "%s.Resources.qml\.qrc./.main\\.qml" % projectName : 'onTriggered.*' } + { "%s.%s.Source Files.main\\.cpp" % (projectName, projectName) : "QQmlApplicationEngine engine;" }, + { "%s.%s.qml\.qrc./.main\\.qml" % (projectName, projectName) : 'onTriggered.*' } ] test.log("Setting breakpoints") expectedBreakpointsOrder = setBreakpointsForCurrentProject(filesAndLines) diff --git a/tests/system/suite_general/tst_build_speedcrunch/test.py b/tests/system/suite_general/tst_build_speedcrunch/test.py index e98a9b0e9a5..3ebed1b67e8 100644 --- a/tests/system/suite_general/tst_build_speedcrunch/test.py +++ b/tests/system/suite_general/tst_build_speedcrunch/test.py @@ -41,10 +41,7 @@ def main(): startQC() if not startedWithoutPluginError(): return - targetToChoose = Targets.DESKTOP_4_8_7_DEFAULT - if not qt4Available: - targetToChoose = Targets.DESKTOP_5_14_1_DEFAULT - openQmakeProject(SpeedCrunchPath, [targetToChoose]) + openQmakeProject(SpeedCrunchPath, [Targets.DESKTOP_5_14_1_DEFAULT]) waitForProjectParsing() fancyToolButton = waitForObject(":*Qt Creator_Core::Internal::FancyToolButton") |