diff --git a/dist/changes-4.12.0.md b/dist/changes-4.12.0.md index 731fea31cfe..c240ddc3d0f 100644 --- a/dist/changes-4.12.0.md +++ b/dist/changes-4.12.0.md @@ -57,6 +57,8 @@ Editing * Updated to Qt 5.15 parser (QTCREATORBUG-23591) * Improved support for multiple imports into same namespace (QTCREATORBUG-15684) * Added scanning of `app.qmltypes` and `lib.qmltypes` for type information +* Fixed highlighting for new keywords in Qt 5.15 +* Fixed reading of `qmltypes` from Qt 5.15 (QTCREATORBUG-23855) ### Python @@ -92,15 +94,18 @@ Projects * Improved renaming of files (QTCREATORBUG-19257) * Fixed handling of `object_parallel_to_source` (QTCREATORBUG-18136) * Fixed crash with circular includes (QTCREATORBUG-23567) +* Fixed issue with renaming files (QTCREATORBUG-23720) ### CMake * Improved handling of `source_group` (QTCREATORBUG-23372) * Added support for `Add build library search path to LD_LIBRARY_PATH` (QTCREATORBUG-23464) * Added automatic registration of CMake documentation, if available (QTCREATORBUG-21338) +* Fixed that `.cmake` directory was created in project source directory (QTCREATORBUG-23816) * Fixed issues with `snap` on Ubuntu Linux (QTCREATORBUG-23376) * Fixed handling of `Enable QML` in debugger settings (QTCREATORBUG-23541) * Fixed unneeded reparsing of files +* Fixed code model issues with precompiled headers (QTCREATORBUG-22888) ### Qbs @@ -111,6 +116,7 @@ Projects ### Python * Added option to disable buffered output (QTCREATORBUG-23539) +* Added support for PySide 5.15 to wizards (QTCREATORBUG-23824) ### Generic @@ -164,6 +170,7 @@ Qt Quick Designer * Added support for annotations (QDS-39) * Fixed dragging of keyframes in curve editor (QDS-1405) * Fixed crash when selecting icon (QTCREATORBUG-23773) +* Fixed missing import options (QDS-1592) Version Control Systems ----------------------- @@ -212,7 +219,10 @@ Platforms * Added support for Android 11 with API level 30 * Improved examples browser to only show items tagged with `android` (QTBUG-80716) * Improved manifest editor (QTCREATORBUG-23283) +* Fixed issues with latest SDK r29 (QTCREATORBUG-23726) * Fixed several issues with AVD manager (QTCREATORBUG-23284, QTCREATORBUG-23448) +* Fixed that some essential packages were not installed (QTCREATORBUG-23829) +* Fixed that ABI selection in build configuration did not persist (QTCREATORBUG-23756) ### iOS @@ -231,7 +241,10 @@ Platforms ### MCU -* Added auto-registration of documentation (UL-1685) +* Added auto-registration of documentation and examples (UL-1685, UL-1218) +* Switched to MCUXpresso IDE instead of SEGGER JLink for NXP kits (QTCREATORBUG-23821) +* Fixed issues with desktop kit (QTCREATORBUG-23820) +* Fixed issues with RH850 (QTCREATORBUG-23822) Credits for these changes go to: -------------------------------- diff --git a/doc/qtcreator/config/qtcreator-project.qdocconf b/doc/qtcreator/config/qtcreator-project.qdocconf index a9a0ef579d1..414ac30c9a0 100644 --- a/doc/qtcreator/config/qtcreator-project.qdocconf +++ b/doc/qtcreator/config/qtcreator-project.qdocconf @@ -35,7 +35,8 @@ examples.fileextensions += *.qml *.svg HTML.extraimages = ../../config/images/commercial.png qhp.QtCreator.extraFiles = ../../config/images/commercial.png -depends += qtwidgets \ +depends += qtandroidextras\ + qtwidgets \ qtcmake \ qtcore \ qtqml \ diff --git a/doc/qtcreator/images/qmldesigner-run-custom-exe.png b/doc/qtcreator/images/qmldesigner-run-custom-exe.png index ec143b5478e..c30f6d21857 100644 Binary files a/doc/qtcreator/images/qmldesigner-run-custom-exe.png and b/doc/qtcreator/images/qmldesigner-run-custom-exe.png differ diff --git a/doc/qtcreator/images/qmldesigner-run-settings.png b/doc/qtcreator/images/qmldesigner-run-settings.png index c52fd45e507..457a1a9286a 100644 Binary files a/doc/qtcreator/images/qmldesigner-run-settings.png and b/doc/qtcreator/images/qmldesigner-run-settings.png differ diff --git a/doc/qtcreator/images/qtcreator-analyzer-settings.png b/doc/qtcreator/images/qtcreator-analyzer-settings.png index 2097cb24691..b2c1cdc4127 100644 Binary files a/doc/qtcreator/images/qtcreator-analyzer-settings.png and b/doc/qtcreator/images/qtcreator-analyzer-settings.png differ diff --git a/doc/qtcreator/images/qtcreator-embedded-linux-deployment-overview.png b/doc/qtcreator/images/qtcreator-embedded-linux-deployment-overview.png index e6e9b26a25f..25cdf5c7bf5 100644 Binary files a/doc/qtcreator/images/qtcreator-embedded-linux-deployment-overview.png and b/doc/qtcreator/images/qtcreator-embedded-linux-deployment-overview.png differ diff --git a/doc/qtcreator/images/qtcreator-pprunsettings.png b/doc/qtcreator/images/qtcreator-pprunsettings.png index f1cd9f6e58e..4b53a44d9ab 100644 Binary files a/doc/qtcreator/images/qtcreator-pprunsettings.png and b/doc/qtcreator/images/qtcreator-pprunsettings.png differ diff --git a/doc/qtcreator/images/qtcreator-python-run-settings-custom-executable.png b/doc/qtcreator/images/qtcreator-python-run-settings-custom-executable.png index 3db0379f573..3ac5fa7bf9f 100644 Binary files a/doc/qtcreator/images/qtcreator-python-run-settings-custom-executable.png and b/doc/qtcreator/images/qtcreator-python-run-settings-custom-executable.png differ diff --git a/doc/qtcreator/images/qtcreator-python-run-settings.png b/doc/qtcreator/images/qtcreator-python-run-settings.png index d00e8157a2f..5d3875f4e35 100644 Binary files a/doc/qtcreator/images/qtcreator-python-run-settings.png and b/doc/qtcreator/images/qtcreator-python-run-settings.png differ diff --git a/doc/qtcreator/images/qtcreator-run-environment.png b/doc/qtcreator/images/qtcreator-run-environment.png index 5673ae1b107..515ec87053d 100644 Binary files a/doc/qtcreator/images/qtcreator-run-environment.png and b/doc/qtcreator/images/qtcreator-run-environment.png differ diff --git a/doc/qtcreator/images/qtcreator-run-settings-linux.png b/doc/qtcreator/images/qtcreator-run-settings-linux.png index 00928cb7b33..14e4d5f9695 100644 Binary files a/doc/qtcreator/images/qtcreator-run-settings-linux.png and b/doc/qtcreator/images/qtcreator-run-settings-linux.png differ diff --git a/doc/qtcreator/images/qtcreator-settings-run.png b/doc/qtcreator/images/qtcreator-settings-run.png new file mode 100644 index 00000000000..5d0680fbdf6 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-settings-run.png differ diff --git a/doc/qtcreator/src/android/deploying-android.qdoc b/doc/qtcreator/src/android/deploying-android.qdoc index 966b1d629e4..c4ece062167 100644 --- a/doc/qtcreator/src/android/deploying-android.qdoc +++ b/doc/qtcreator/src/android/deploying-android.qdoc @@ -319,8 +319,8 @@ \li In the \uicontrol Permissions field, you can specify the permissions that your application needs. Starting from Android 6.0 (API 23), permissions have to be - requested at runtime (See \l{QtAndroidExtras}{requestPermissionsSync} or - \l{QtAndroidExtras}{requestPermissions}). For lower Android API levels, + requested at runtime (see \l{QtAndroid::requestPermissionsSync()} or + \l{QtAndroid::requestPermissions()}). For lower Android API levels, users are asked to grant the permissions when they install the application. Android OS then grants the application access to the appropriate data and features. diff --git a/doc/qtcreator/src/linux-mobile/creator-deployment-embedded-linux.qdoc b/doc/qtcreator/src/linux-mobile/creator-deployment-embedded-linux.qdoc index 625666a191f..6d2ad9c2e13 100644 --- a/doc/qtcreator/src/linux-mobile/creator-deployment-embedded-linux.qdoc +++ b/doc/qtcreator/src/linux-mobile/creator-deployment-embedded-linux.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -43,7 +43,7 @@ You can specify settings for deploying applications to generic Linux devices in the project .pro file. You can view the settings in the - \uicontrol {Run Settings}. + \uicontrol Projects mode, in \uicontrol {Run Settings}. \image qtcreator-embedded-linux-deployment-overview.png "Deploy to device" diff --git a/doc/qtcreator/src/linux-mobile/creator-projects-settings-run-linux.qdocinc b/doc/qtcreator/src/linux-mobile/creator-projects-settings-run-linux.qdocinc index 5ae14681fbe..1d64706acf0 100644 --- a/doc/qtcreator/src/linux-mobile/creator-projects-settings-run-linux.qdocinc +++ b/doc/qtcreator/src/linux-mobile/creator-projects-settings-run-linux.qdocinc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -45,8 +45,8 @@ \image qtcreator-run-settings-linux.png "Run settings for Linux-based devices" - You can specify command line arguments to pass to your application in the - \uicontrol Arguments field. + You can specify arguments to pass to your application in the + \uicontrol {Command line arguments} field. //! [run settings linux] */ diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run.qdoc index a67b2052fda..e0d4182379a 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -44,17 +44,25 @@ To view and modify them, select \uicontrol Projects > \uicontrol {Build & Run} > \uicontrol Run. - The available run configurations are listed in the - \uicontrol {Run configuration} field. - To add run configurations for a project, select \uicontrol Add. - To remove the current run configuration, select \uicontrol Remove. - To rename the current run configuration, select \uicontrol Rename. + \image qtcreator-settings-run.png "Run Settings" To prevent \QC from automatically creating run configurations, select \uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run}, and then deselect the \uicontrol {Create suitable run configurations automatically} check box. + \section1 Managing Run Configurations + + The available run configurations are listed in the + \uicontrol {Run configuration} field. + To add run configurations for a project, select \uicontrol Add. To + add a run configuration that is based on the current one, select + \uicontrol Clone. + + To rename the current run configuration, select \uicontrol Rename. + + To remove the current run configuration, select \uicontrol Remove. + The run configurations for qmake projects derive their executable from the parsed .pro files. For more information on how the commands are constructed, see \l{Starting External Processes}. diff --git a/doc/qtcreator/src/python/creator-python-run.qdocinc b/doc/qtcreator/src/python/creator-python-run.qdocinc index 3062f904eb5..af6bd241c8b 100644 --- a/doc/qtcreator/src/python/creator-python-run.qdocinc +++ b/doc/qtcreator/src/python/creator-python-run.qdocinc @@ -59,7 +59,7 @@ command line arguments to be passed to the executable. \endlist - If you want to run some other Python file than \c main.py, create a custom + If you want to run some other Python file than \c main.py, create a custom executable run configuration: \image qtcreator-python-run-settings-custom-executable.png diff --git a/doc/qtcreator/src/qtquick/creator-projects-settings-run-qtquick.qdocinc b/doc/qtcreator/src/qtquick/creator-projects-settings-run-qtquick.qdocinc index 4d1561b47c7..3bce00e2bff 100644 --- a/doc/qtcreator/src/qtquick/creator-projects-settings-run-qtquick.qdocinc +++ b/doc/qtcreator/src/qtquick/creator-projects-settings-run-qtquick.qdocinc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -33,7 +33,9 @@ \list - \li In the \uicontrol Arguments field, you can specify command line arguments + \li In the \uicontrol {QML Viewer} field, specify the \QQV to use. + + \li In the \uicontrol {Command line arguments} field, specify arguments to be passed to the executable. \li In the \uicontrol {Main QML file}, select the file that \QQV will be diff --git a/doc/qtcreatordev/images/actionmanager.png b/doc/qtcreatordev/images/actionmanager.png new file mode 100644 index 00000000000..0c2a954eed6 Binary files /dev/null and b/doc/qtcreatordev/images/actionmanager.png differ diff --git a/doc/qtcreatordev/images/actionmanager.qmodel b/doc/qtcreatordev/images/actionmanager.qmodel new file mode 100644 index 00000000000..f8c56fe1b3a --- /dev/null +++ b/doc/qtcreatordev/images/actionmanager.qmodel @@ -0,0 +1,854 @@ + + + + {f7c67e69-57c5-4eb1-9303-f12bb2ae0a23} + + + + + + + + {9a360a3d-a5ff-4fa0-9a86-540d2cbdfa28} + + + actionmanager + + + + + + + {6f6e0572-b8cc-4d97-95c5-edae83d0a3d2} + + + + + + + + + + {6f6e0572-b8cc-4d97-95c5-edae83d0a3d2} + + + actionmanager + + + + + + + + + + + + {0a2e2d40-ad38-4b91-b9c1-6af2e3d2cf95} + + + {0fa7cf39-5531-4f41-9e2f-d890ef2a248d} + ActionManager + x:300;y:90 + x:-50;y:-15;w:100;h:30 + 0 + 1 + + + false + + + + + + + + + + + {d918082a-dd32-48b8-bdcb-21ade3c1d067} + + + {a3950ef4-9fd9-466f-a575-dc75790749c3} + QAction + x:125;y:340 + x:-30;y:-15;w:60;h:30 + 0 + + + false + + + + + + + + + {d197d1e0-23ef-4041-845f-27c65fe11b70} + + + Context + x:125;y:335 + x:-50;y:-40;w:100;h:80 + + + + + + + + + {613641ea-8fec-4b44-890b-8c6ea42eb9eb} + + + Plugin + x:125;y:330 + x:-65;y:-70;w:130;h:140 + + + + + + + + + + + {c9758c28-e527-4f1b-b911-9c4f7571571c} + + + {ac06f227-7618-422e-a87e-5913950c91d7} + QAction + x:275;y:340 + x:-30;y:-15;w:60;h:30 + 0 + + + false + + + + + + + + + + + {d87082a8-6b2b-404f-abd3-9082585166f4} + + + {0cc14318-53df-4193-8aeb-0d29d4cd1561} + QAction + x:405;y:340 + x:-30;y:-15;w:60;h:30 + 0 + + + false + + + + + + + + + {168c5e3d-54bc-412c-9cb1-9b5481100f2b} + + + Context + x:275;y:335 + x:-50;y:-40;w:100;h:80 + + + + + + + + + {3447fe60-8ac5-4fe9-b518-80daba7e960a} + + + Context + x:405;y:335 + x:-50;y:-40;w:100;h:80 + + + + + + + + + {fcf93e87-8ce6-43ea-ab5e-7ca651d1f429} + + + Plugin + x:340;y:335 + x:-135;y:-70;w:270;h:140 + + + + + + + + + + + {8df1e5cf-5e76-453a-ba69-0fcf31f46d4e} + + + {68e762c3-f1cc-479b-9700-bdb01f208340} + Command + x:195;y:180 + x:-40;y:-35;w:80;h:70 + 0 + + + true + + + + + + + + + + + {a4401c84-57c3-4f34-a88d-f35e28239944} + + + {42259fbc-5917-4caf-836e-0828a032d908} + {0a2e2d40-ad38-4b91-b9c1-6af2e3d2cf95} + {8df1e5cf-5e76-453a-ba69-0fcf31f46d4e} + + + + + + + + + + + + + {7ff85acd-0d85-4fe2-8cc9-d0511f96443c} + + + {39911558-001e-4d0b-9827-d1d372049e86} + Command + x:405;y:180 + x:-40;y:-35;w:80;h:70 + 0 + + + true + + + + + + + + + + + {815d855b-8814-4ac7-8b75-17c3adb45344} + + + {fa3943f6-6bf7-4040-acae-d04c880fb329} + {0a2e2d40-ad38-4b91-b9c1-6af2e3d2cf95} + {7ff85acd-0d85-4fe2-8cc9-d0511f96443c} + + + + + + + + + + + + + {f4567b84-e58c-4212-8d0b-c7040c00639a} + + + {8d18c30e-51c8-4fa2-ad22-ad6962273120} + {8df1e5cf-5e76-453a-ba69-0fcf31f46d4e} + {d918082a-dd32-48b8-bdcb-21ade3c1d067} + + + + + + + + + + + + + {df1469a1-91d8-4c05-8b19-fddffbfc05d6} + + + {8d11e47d-b745-4bf4-b7d2-eb042c307ddf} + {8df1e5cf-5e76-453a-ba69-0fcf31f46d4e} + {c9758c28-e527-4f1b-b911-9c4f7571571c} + + + + + + + + + + + + + {b6288087-3aca-4e28-988c-c11ca3def425} + + + {9f1e7858-c06c-4c7c-97d6-209d3c96360f} + {7ff85acd-0d85-4fe2-8cc9-d0511f96443c} + {d87082a8-6b2b-404f-abd3-9082585166f4} + + + + + + + + + + + + + {ee71f328-354b-4993-8a63-8f4605285440} + + + {158de17f-753a-4b00-8ddf-2f4432871d07} + Menu + x:100;y:190 + x:-25;y:-15;w:50;h:30 + 0 + 1 + + + false + + + + + + + + + {5b8fc43d-fb36-4523-ac54-4262dc0affce} + + + x:270;y:190 + x:-205;y:-20;w:410;h:40 + + + + + + 1586427331500 + General + + + + + + + + + + {0fa7cf39-5531-4f41-9e2f-d890ef2a248d} + + + + + + + + {0fa7cf39-5531-4f41-9e2f-d890ef2a248d} + + + ActionManager + + + + + + + {d5111c81-0745-4724-8d01-8ac36994e31c} + + + + + + + + {d5111c81-0745-4724-8d01-8ac36994e31c} + + + {0fa7cf39-5531-4f41-9e2f-d890ef2a248d} + {c2d3f5b7-87c5-4f67-9911-96a4a251ddd5} + + + + + + + + + + {6308a511-1fd1-472d-bdc2-0bf173c6850c} + + + + + + + + {6308a511-1fd1-472d-bdc2-0bf173c6850c} + + + {0fa7cf39-5531-4f41-9e2f-d890ef2a248d} + {d6694b35-bb04-4830-9713-99470b22b7d7} + + + + + + + + + + {42259fbc-5917-4caf-836e-0828a032d908} + + + + + + + + {42259fbc-5917-4caf-836e-0828a032d908} + + + {0fa7cf39-5531-4f41-9e2f-d890ef2a248d} + {68e762c3-f1cc-479b-9700-bdb01f208340} + + + + + + + + + + {fa3943f6-6bf7-4040-acae-d04c880fb329} + + + + + + + + {fa3943f6-6bf7-4040-acae-d04c880fb329} + + + {0fa7cf39-5531-4f41-9e2f-d890ef2a248d} + {39911558-001e-4d0b-9827-d1d372049e86} + + + + + + + + + + + + + + + + + + + + + {c2d3f5b7-87c5-4f67-9911-96a4a251ddd5} + + + + + + + + {c2d3f5b7-87c5-4f67-9911-96a4a251ddd5} + + + Command + + + + + + + {e5b7a324-70ab-46b9-8d36-9f2ad6c0db57} + + + + + + + + {e5b7a324-70ab-46b9-8d36-9f2ad6c0db57} + + + {c2d3f5b7-87c5-4f67-9911-96a4a251ddd5} + {a3950ef4-9fd9-466f-a575-dc75790749c3} + + + + + + + + + + {703dd2bc-f99c-41b7-8f90-a7292645feb8} + + + + + + + + {703dd2bc-f99c-41b7-8f90-a7292645feb8} + + + {c2d3f5b7-87c5-4f67-9911-96a4a251ddd5} + {ac06f227-7618-422e-a87e-5913950c91d7} + + + + + + + + + + + + + + + + + + + + + {d6694b35-bb04-4830-9713-99470b22b7d7} + + + + + + + + {d6694b35-bb04-4830-9713-99470b22b7d7} + + + Command + + + + + + + {4dc1c5bd-a124-4961-ad65-476e66cb6efe} + + + + + + + + {4dc1c5bd-a124-4961-ad65-476e66cb6efe} + + + {d6694b35-bb04-4830-9713-99470b22b7d7} + {0cc14318-53df-4193-8aeb-0d29d4cd1561} + + + + + + + + + + + + + + + + + + + + + {a3950ef4-9fd9-466f-a575-dc75790749c3} + + + + + + + + {a3950ef4-9fd9-466f-a575-dc75790749c3} + + + QAction + + + + + + + + + + {ac06f227-7618-422e-a87e-5913950c91d7} + + + + + + + + {ac06f227-7618-422e-a87e-5913950c91d7} + + + QAction + + + + + + + + + + {0cc14318-53df-4193-8aeb-0d29d4cd1561} + + + + + + + + {0cc14318-53df-4193-8aeb-0d29d4cd1561} + + + QAction + + + + + + + + + + {68e762c3-f1cc-479b-9700-bdb01f208340} + + + + + + + + {68e762c3-f1cc-479b-9700-bdb01f208340} + + + Command + + + + + + + {8d18c30e-51c8-4fa2-ad22-ad6962273120} + + + + + + + + {8d18c30e-51c8-4fa2-ad22-ad6962273120} + + + {68e762c3-f1cc-479b-9700-bdb01f208340} + {a3950ef4-9fd9-466f-a575-dc75790749c3} + + + + + + + + + + {8d11e47d-b745-4bf4-b7d2-eb042c307ddf} + + + + + + + + {8d11e47d-b745-4bf4-b7d2-eb042c307ddf} + + + {68e762c3-f1cc-479b-9700-bdb01f208340} + {ac06f227-7618-422e-a87e-5913950c91d7} + + + + + + + + + + + + + + + + + + {5d8da03d-d556-4eed-ae0d-6d306453496e} + 1 + QAction + + + + + + + + + + + + {39911558-001e-4d0b-9827-d1d372049e86} + + + + + + + + {39911558-001e-4d0b-9827-d1d372049e86} + + + Command + + + + + + + {9f1e7858-c06c-4c7c-97d6-209d3c96360f} + + + + + + + + {9f1e7858-c06c-4c7c-97d6-209d3c96360f} + + + {39911558-001e-4d0b-9827-d1d372049e86} + {0cc14318-53df-4193-8aeb-0d29d4cd1561} + + + + + + + + + + + + + + + + + + {2d428a77-4751-4fa7-bbb7-7f58995da129} + 1 + QAction + + + + + + + + + + + + {158de17f-753a-4b00-8ddf-2f4432871d07} + + + + + + + + {158de17f-753a-4b00-8ddf-2f4432871d07} + + + Menu + + + + + + + + + + + + + + + + + + diff --git a/doc/qtcreatordev/src/actionmanager.qdoc b/doc/qtcreatordev/src/actionmanager.qdoc new file mode 100644 index 00000000000..194d0eefdff --- /dev/null +++ b/doc/qtcreatordev/src/actionmanager.qdoc @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Creator documentation. +** +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** +****************************************************************************/ + +/*! + \page actionmanager.html + \title The Action Manager and Commands + + \QC provides a central options page for managing shortcuts for actions in + \uicontrol Tools > \uicontrol Options > \uicontrol Environment > + \uicontrol Keyboard. Plugins must tell \QC about the actions they provide, + so they can appear in the options. Also some actions, like \uicontrol Edit > + \uicontrol Undo, need to be dispatched to different plugins depending on the + context which the user is currently in, for example a text editor, or + a UI design component. The Core::ActionManager and Core::Command classes + are used to manage this. + + The action manager contains a list of Core::Command instances. Each command + represents an entry in the keyboard shortcut settings. + + A command also manages which actual QAction is currently represented by the + command, depending on context. For this, a command has its own QAction which + is accessible via Core::Command::action(), and should be used when adding + the command to the UI like the menu and tool buttons. This QAction delegates + its \c triggered() and \c toggled() signals to the currently active QAction. + + \image actionmanager.png + + \section1 Command + + The class Core::Command represents an action with a shortcut that can be + set by the user in the settings, and can be delegated to an actual + QAction in a plugin, depending on context. + + A command is referred to by its unique ID. Plugins use the ID when + registering an action for the command in a specified context with + Core::ActionManager::registerAction(). That method returns a Core::Command + instance that is then used to further configure the action. + If multiple QActions are registered for the same command (the same ID), + they must be registered for different contexts. + The ID is also used for grouping in the options page: everything up to the + first dot in the ID is used as the category, under which to show the + command. + + By default, the options page shows the text of the currently active QAction + in addition to the ID. If that does not fit the purpose well, you can set a + different display text with Core::Command::setDescription(). + + Use the command's Core::Command::setDefaultKeySequence() method to set the + default key sequence that is used if the user doesn't customize it. + The shortcut on the QAction that you register with + Core::ActionManager::registerAction() is never used, so do not set that. + + Core::Command::action() returns the action that should be used for UI and + user interaction. Add this to menus and tool buttons. You should never + set properties like the enabled or visibility state on this QAction + directly. It is managed by the action manager and reflects the state of the + currently active QAction in some plugin. + + The QAction that you registered in the action manager is for your internal + purposes. Use that to connect your logic to the QAction::triggered() + signal, and to set the enabled and visibility state. + Core::Command::action() will reflect these changes, if your QAction is + active, determined by the active context. For performance reasons the + action text, tool tip and icon are not updated by default. They are only + copied from the first QAction registered for the command. Set the + corresponding Core::Command::CommandAttribute if you need dynamic updates + of these properties. + + \section1 Contexts + + When plugins register a QAction for a command, they need to provide a + Core::Context. Which of the registered QActions for a command is currently + active is decided via an ordered list of current contexts. + + Contexts are collected from multiple sources: + + \list + \li Global context. This is a context that is always active, with lowest + priority order. + \li Application focus. Instances of QWidget can be associated to a + context via Core::IContext. All contexts from the current focus + widget up the widget hierarchy are added to the current context. + \li Manually managed contexts. Contexts can be added and removed + manually via ICore::updateAdditionalContexts(). + \endlist + + \section2 Using IContext + + Core::IContext is a separate object that associates the QWidget from + Core::IContext::widget() with the context Core::IContext::context(). + + To associate a widget with a context, create a Core::IContext instance, + set the widget and context on it, and register it with + Core::ICore::addContextObject(). Whenever your widget is in the parent + chain of the application focus widget, the context that you specified + will be active as well. + + \code + auto contextObj = new Core::IContext(this); + contextObj->setWidget(myWidget); + contextObj->setContext(myContext); + Core::ICore::addContextObject(contextObj); + \endcode + + You also have to unregister the IContext object with + Core::ICore::removeContextObject() when you do not need it anymore. + + Some constructs in \QC automatically have an associated context, like + Core::IEditor and Core::IMode. + + \section2 Manually Managing Contexts + + If you want a context to be active or inactive independently of the + application focus, you can add and remove contexts manually with + Core::ICore::updateAdditionalContexts(), Core::ICore::addAdditionalContext() + and Core::ICore::removeAdditionalContext(). + Prefer Core::ICore::updateAdditionalContexts() if you need to remove and add + contexts, to avoid overhead introduced by removing and adding contexts + in separate calls. + + \section1 Registering Actions + + Prefer registering actions in your plugin's + ExtensionSystem::IPlugin::initialize() method. This way any plugin depending + on your plugin has access to these actions. + + \code + namespace Constants { + const char ACTION_ID[] = "Example.Action"; + } // Constants + + bool ExamplePlugin::initialize(const QStringList &arguments, QString *errorString) + { + // some other setup ... + + QAction *action = new QAction(tr("Example Action"), this); + Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID, + Core::Context(Core::Constants::C_GLOBAL)); + cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A"))); + connect(action, &QAction::triggered, this, [this] { + // do something + }); + + // more setup ... + + return true; + } + \endcode + + This snippet sets up a sample action with the ID \c ACTION_ID that is always + active (specified by the context \c {Core::Constants::C_GLOBAL}), and gives + it the keyboard shortcut \c {Ctrl+Alt+Meta+A}. The \c {QAction *action} + that is registered for the global context for the action is owned by the + plugin. Connect to this QAction's triggered signal, and manage the action's + state by calling the corresponding methods on this QAction instance. + + \section1 Summary + + \list + \li Use Core::ActionManager::registerAction() to register your own + QAction for a command with the specified ID. + \li If multiple QActions are registered for the same command, they need + to be registered for different contexts. + \li Use Core::Command::setDefaultKeySequence(), do \e not use + QAction::setShortcut(). + \li Use Core::Command::action() for user-facing purposes, such as + menus and tool buttons. + \li Use your own QAction to set properties like text and icon, and to + connect your application logic. + \endlist +*/ diff --git a/doc/qtcreatordev/src/creating-plugins.qdoc b/doc/qtcreatordev/src/creating-plugins.qdoc index 9b736b0c517..5a8bf7905dc 100644 --- a/doc/qtcreatordev/src/creating-plugins.qdoc +++ b/doc/qtcreatordev/src/creating-plugins.qdoc @@ -63,6 +63,7 @@ \list \li \l{The Plugin Manager, the Object Pool, and Registered Objects} + \li \l{The Action Manager and Commands} \omit \li \l{Aggregations} \li \l{Extending and Providing Interfaces} diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp index 02800c494a5..03dec15d860 100644 --- a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp +++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp @@ -310,10 +310,11 @@ RawProjectParts generateRawProjectParts(const PreprocessedData &input, const FilePath &sourceDirectory) { RawProjectParts rpps; - const QDir sourceDir(sourceDirectory.toString()); int counter = 0; for (const TargetDetails &t : input.targetDetails) { + QDir sourceDir(sourceDirectory.toString()); + bool needPostfix = t.compileGroups.size() > 1; int count = 1; for (const CompileInfo &ci : t.compileGroups) { @@ -356,15 +357,14 @@ RawProjectParts generateRawProjectParts(const PreprocessedData &input, cxxProjectFlags.commandLineFlags = cProjectFlags.commandLineFlags; rpp.setFlagsForCxx(cxxProjectFlags); - FilePath precompiled_header = FilePath::fromString( - findOrDefault(t.sources, [&ending](const SourceInfo &si) { - return si.path.endsWith(ending); - }).path); + FilePath precompiled_header + = FilePath::fromString(findOrDefault(t.sources, [&ending](const SourceInfo &si) { + return si.path.endsWith(ending); + }).path); rpp.setFiles(transform(ci.sources, [&t, &sourceDir](const int si) { return sourceDir.absoluteFilePath(t.sources[static_cast(si)].path); })); - if (!precompiled_header.isEmpty()) { if (precompiled_header.toFileInfo().isRelative()) { const FilePath parentDir = FilePath::fromString(sourceDir.absolutePath()); @@ -379,22 +379,6 @@ RawProjectParts generateRawProjectParts(const PreprocessedData &input, rpps.append(rpp); ++count; } - - // Check sources for more files and associate them with the current target - const QStringList extraSources = Utils::transform( - Utils::filtered(t.sources, [](const SourceInfo &si) { return si.compileGroup == -1; }), - [&sourceDir](const SourceInfo &si) { return sourceDir.absoluteFilePath(si.path); }); - if (!extraSources.isEmpty()) { - RawProjectPart rpp; - rpp.setProjectFileLocation(t.sourceDir.pathAppended("CMakeLists.txt").toString()); - rpp.setBuildSystemTarget(t.name); - rpp.setDisplayName(t.id + "_extra"); - - rpp.setFiles(extraSources); - - // This is all the information we have :-/ - rpps.append(rpp); - } } return rpps; diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index 2faaa4e0cbf..7d1a418249e 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -72,6 +72,7 @@ using namespace Utils; namespace { const char QMAKE_ARGUMENTS_KEY[] = "QtProjectManager.QMakeBuildStep.QMakeArguments"; const char QMAKE_FORCED_KEY[] = "QtProjectManager.QMakeBuildStep.QMakeForced"; +const char QMAKE_SELECTED_ABIS_KEY[] = "QtProjectManager.QMakeBuildStep.SelectedAbis"; } QMakeStep::QMakeStep(BuildStepList *bsl, Core::Id id) @@ -351,6 +352,16 @@ void QMakeStep::runNextCommand() } } +QStringList QMakeStep::selectedAbis() const +{ + return m_selectedAbis; +} + +void QMakeStep::setSelectedAbis(const QStringList &selectedAbis) +{ + m_selectedAbis = selectedAbis; +} + void QMakeStep::setUserArguments(const QString &arguments) { if (m_userArgs == arguments) @@ -464,6 +475,7 @@ QVariantMap QMakeStep::toMap() const QVariantMap map(AbstractProcessStep::toMap()); map.insert(QMAKE_ARGUMENTS_KEY, m_userArgs); map.insert(QMAKE_FORCED_KEY, m_forced); + map.insert(QMAKE_SELECTED_ABIS_KEY, m_selectedAbis); return map; } @@ -471,6 +483,7 @@ bool QMakeStep::fromMap(const QVariantMap &map) { m_userArgs = map.value(QMAKE_ARGUMENTS_KEY).toString(); m_forced = map.value(QMAKE_FORCED_KEY, false).toBool(); + m_selectedAbis = map.value(QMAKE_SELECTED_ABIS_KEY).toStringList(); // Backwards compatibility with < Creator 4.12. const QVariant separateDebugInfo @@ -629,29 +642,26 @@ void QMakeStepConfigWidget::separateDebugInfoChanged() void QMakeStepConfigWidget::abisChanged() { - if (m_abisParam.isEmpty()) - return; - - QStringList args = m_step->extraArguments(); - for (auto it = args.begin(); it != args.end(); ++it) { - if (it->startsWith(m_abisParam)) { - args.erase(it); - break; - } - } - QStringList abis; for (int i = 0; i < abisListWidget->count(); ++i) { auto item = abisListWidget->item(i); if (item->checkState() == Qt::CheckState::Checked) abis << item->text(); } - if (abis.isEmpty()) { - abisListWidget->item(m_preferredAbiIndex)->setCheckState(Qt::CheckState::Checked); - return; + m_step->setSelectedAbis(abis); + + if (isAndroidKit()) { + const QString prefix = "ANDROID_ABIS="; + QStringList args = m_step->extraArguments(); + for (auto it = args.begin(); it != args.end(); ++it) { + if (it->startsWith(prefix)) { + args.erase(it); + break; + } + } + args << prefix + '"' + abis.join(' ') + '"'; + m_step->setExtraArguments(args); } - args << QStringLiteral("%1\"%2\"").arg(m_abisParam, abis.join(' ')); - m_step->setExtraArguments(args); updateSummaryLabel(); updateEffectiveQMakeCall(); @@ -697,6 +707,18 @@ void QMakeStepConfigWidget::askForRebuild(const QString &title) question->show(); } +bool QMakeStepConfigWidget::isAndroidKit() const +{ + BaseQtVersion *qtVersion = QtKitAspect::qtVersion(m_step->target()->kit()); + if (!qtVersion) + return false; + + const Abis abis = qtVersion->qtAbis(); + return Utils::anyOf(abis, [](const Abi &abi) { + return abi.osFlavor() == Abi::OSFlavor::AndroidLinuxFlavor; + }); +} + void QMakeStepConfigWidget::updateSummaryLabel() { BaseQtVersion *qtVersion = QtKitAspect::qtVersion(m_step->target()->kit()); @@ -704,29 +726,35 @@ void QMakeStepConfigWidget::updateSummaryLabel() setSummaryText(tr("qmake: No Qt version set. Cannot run qmake.")); return; } - bool enableAbisSelect = qtVersion->qtAbis().size() > 1; + const Abis abis = qtVersion->qtAbis(); + const bool enableAbisSelect = abis.size() > 1; abisLabel->setVisible(enableAbisSelect); abisListWidget->setVisible(enableAbisSelect); - if (enableAbisSelect && abisListWidget->count() != qtVersion->qtAbis().size()) { + + if (enableAbisSelect && abisListWidget->count() != abis.size()) { abisListWidget->clear(); - bool isAndroid = true; - m_preferredAbiIndex = -1; - for (const auto &abi : qtVersion->qtAbis()) { - auto item = new QListWidgetItem{abi.param(), abisListWidget}; - item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - item->setCheckState(Qt::Unchecked); - isAndroid = isAndroid && abi.osFlavor() == Abi::OSFlavor::AndroidLinuxFlavor; - if (isAndroid && (item->text() == "armeabi-v7a" || - (m_preferredAbiIndex == -1 && item->text() == "arm64-v8a"))) { - m_preferredAbiIndex = abisListWidget->count() - 1; + QStringList selectedAbis = m_step->selectedAbis(); + + if (selectedAbis.isEmpty() && isAndroidKit()) { + // Prefer ARM for Android, prefer 32bit. + for (const Abi &abi : abis) { + if (abi.param() == "armeabi-v7a") + selectedAbis.append(abi.param()); + } + if (selectedAbis.isEmpty()) { + for (const Abi &abi : abis) { + if (abi.param() == "arm64-v8a") + selectedAbis.append(abi.param()); + } } } - if (isAndroid) - m_abisParam = "ANDROID_ABIS="; - if (m_preferredAbiIndex == -1) - m_preferredAbiIndex = 0; - abisListWidget->item(m_preferredAbiIndex)->setCheckState(Qt::Checked); + for (const Abi &abi : abis) { + const QString param = abi.param(); + auto item = new QListWidgetItem{param, abisListWidget}; + item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + item->setCheckState(selectedAbis.contains(param) ? Qt::Checked : Qt::Unchecked); + } abisChanged(); } diff --git a/src/plugins/qmakeprojectmanager/qmakestep.h b/src/plugins/qmakeprojectmanager/qmakestep.h index 1dfce91aa10..6475757e167 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.h +++ b/src/plugins/qmakeprojectmanager/qmakestep.h @@ -155,6 +155,9 @@ public: QVariantMap toMap() const override; + QStringList selectedAbis() const; + void setSelectedAbis(const QStringList &selectedAbis); + signals: void userArgumentsChanged(); void extraArgumentsChanged(); @@ -188,6 +191,7 @@ private: bool m_runMakeQmake = false; bool m_scriptTemplate = false; + QStringList m_selectedAbis; }; @@ -217,11 +221,10 @@ private: void updateSummaryLabel(); void updateEffectiveQMakeCall(); + bool isAndroidKit() const; QMakeStep *m_step = nullptr; bool m_ignoreChange = false; - int m_preferredAbiIndex = -1; - QString m_abisParam; QLabel *abisLabel = nullptr; QComboBox *buildConfigurationComboBox = nullptr; diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 85e0c67ec9e..42feb7c13f7 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -5,7 +5,7 @@ add_qtc_plugin(QmlDesigner DEFINES DESIGNER_CORE_LIBRARY IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\" - INCLUDES + PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/designercore/include PLUGIN_DEPENDS Core ProjectExplorer QmlJSEditor QmakeProjectManager QmlProjectManager @@ -41,7 +41,6 @@ add_qtc_plugin(componentsplugin CONDITION TARGET QmlDesigner DEPENDS Core QmlDesigner Utils Qt5::Qml DEFINES COMPONENTS_LIBRARY - INCLUDES ${CMAKE_CURRENT_LIST_DIR}/designercore/include SOURCES componentsplugin/addtabdesigneraction.cpp componentsplugin/addtabdesigneraction.h componentsplugin/addtabtotabviewdialog.cpp componentsplugin/addtabtotabviewdialog.h @@ -57,7 +56,6 @@ add_qtc_plugin(componentsplugin add_qtc_plugin(qmlpreviewplugin CONDITION TARGET QmlDesigner DEPENDS Core ProjectExplorer QmlDesigner Utils Qt5::Qml - INCLUDES ${CMAKE_CURRENT_LIST_DIR}/designercore/include SOURCES qmlpreviewplugin/qmlpreviewactions.cpp qmlpreviewplugin/qmlpreviewactions.h qmlpreviewplugin/qmlpreviewplugin.cpp qmlpreviewplugin/qmlpreviewplugin.h @@ -70,7 +68,6 @@ add_qtc_plugin(qtquickplugin CONDITION TARGET QmlDesigner DEPENDS Core QmlDesigner Utils Qt5::Qml DEFINES QTQUICK_LIBRARY - INCLUDES ${CMAKE_CURRENT_LIST_DIR}/designercore/include SOURCES qtquickplugin/qtquickplugin.cpp qtquickplugin/qtquickplugin.h qtquickplugin/qtquickplugin.qrc diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationtool.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationtool.cpp index 7cb0bdfa19f..9db5d0d81c3 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationtool.cpp +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationtool.cpp @@ -201,7 +201,7 @@ void AnnotationTool::formEditorItemsChanged(const QList & /*ite int AnnotationTool::wantHandleItem(const ModelNode & /*modelNode*/) const { - return 10; + return 5; } QString AnnotationTool::name() const diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp index 84c8fc1523d..9a643edef8e 100644 --- a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp @@ -101,10 +101,14 @@ void DragTool::createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, const bool rootIsFlow = QmlItemNode(view()->rootModelNode()).isFlowView(); - if (rootIsFlow) - itemPos = QPointF(); + QmlItemNode adjustedParentNode = parentNode; - m_dragNode = QmlItemNode::createQmlItemNode(view(), itemLibraryEntry, itemPos, parentNode); + if (rootIsFlow) { + itemPos = QPointF(); + adjustedParentNode = view()->rootModelNode(); + } + + m_dragNode = QmlItemNode::createQmlItemNode(view(), itemLibraryEntry, itemPos, adjustedParentNode); if (rootIsFlow) m_dragNode.setFlowItemPosition(positonInItemSpace); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp index be6cdcdf567..96a4cc5adf6 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp @@ -585,6 +585,9 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi QColor flowColor = "#e71919"; + if (qmlItemNode().rootModelNode().hasAuxiliaryData("areaColor")) + flowColor = qmlItemNode().rootModelNode().auxiliaryData("areaColor").value(); + if (qmlItemNode().modelNode().hasAuxiliaryData("color")) flowColor = qmlItemNode().modelNode().auxiliaryData("color").value(); @@ -600,7 +603,6 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi if (qmlItemNode().modelNode().hasAuxiliaryData("dash")) dash = qmlItemNode().modelNode().auxiliaryData("dash").toBool(); - pen.setColor(flowColor); if (dash) pen.setStyle(Qt::DashLine); @@ -611,11 +613,16 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi pen.setCosmetic(true); painter->setPen(pen); - if (qmlItemNode().modelNode().hasAuxiliaryData("fillColor")) { + QColor fillColor = QColor(Qt::transparent); - const QColor fillColor = qmlItemNode().modelNode().auxiliaryData("fillColor").value(); - painter->fillRect(boundingRect(), fillColor); - } + if (qmlItemNode().rootModelNode().hasAuxiliaryData("areaFillColor")) + fillColor = qmlItemNode().rootModelNode().auxiliaryData("areaFillColor").value(); + + if (qmlItemNode().modelNode().hasAuxiliaryData("fillColor")) + fillColor = qmlItemNode().modelNode().auxiliaryData("fillColor").value(); + + if (fillColor.alpha() > 0) + painter->fillRect(boundingRect(), fillColor); painter->drawRect(boundingRect()); @@ -1046,6 +1053,9 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi bool dash = false; + if (qmlItemNode().rootModelNode().hasAuxiliaryData("transitionColor")) + color = qmlItemNode().rootModelNode().auxiliaryData("transitionColor").value(); + if (qmlItemNode().modelNode().hasAuxiliaryData("color")) color = qmlItemNode().modelNode().auxiliaryData("color").value(); @@ -1137,6 +1147,9 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap QColor flowColor = "#e71919"; + if (qmlItemNode().rootModelNode().hasAuxiliaryData("blockColor")) + flowColor = qmlItemNode().rootModelNode().auxiliaryData("blockColor").value(); + if (qmlItemNode().modelNode().hasAuxiliaryData("color")) flowColor = qmlItemNode().modelNode().auxiliaryData("color").value(); @@ -1161,11 +1174,13 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap pen.setCosmetic(true); painter->setPen(pen); - if (qmlItemNode().modelNode().hasAuxiliaryData("fillColor")) { + QColor fillColor = QColor(Qt::transparent); - const QColor fillColor = qmlItemNode().modelNode().auxiliaryData("fillColor").value(); - painter->fillRect(boundingRect(), fillColor); - } + if (qmlItemNode().modelNode().hasAuxiliaryData("fillColor")) + fillColor = qmlItemNode().modelNode().auxiliaryData("fillColor").value(); + + if (fillColor.alpha() > 0) + painter->fillRect(boundingRect(), fillColor); painter->drawLine(boundingRect().left(), boundingRect().center().y(), boundingRect().center().x(), boundingRect().top()); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index 6149b248ce9..650892339a0 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -169,25 +169,35 @@ static void deleteWithoutChildren(const QList &items) } } +static bool isFlowNonItem(const QmlItemNode &itemNode) +{ + return itemNode.isFlowTransition() + || itemNode.isFlowWildcard() + || itemNode.isFlowWildcard(); +} + void FormEditorView::removeNodeFromScene(const QmlItemNode &qmlItemNode) { + QList removedItemList; + if (qmlItemNode.isValid()) { QList nodeList; nodeList.append(qmlItemNode.allSubModelNodes()); nodeList.append(qmlItemNode); - QList removedItemList; - removedItemList.append(scene()->itemsForQmlItemNodes(nodeList)); - m_currentTool->itemsAboutToRemoved(removedItemList); //The destructor of QGraphicsItem does delete all its children. //We have to keep the children if they are not children in the model anymore. //Otherwise we delete the children explicitly anyway. deleteWithoutChildren(removedItemList); - } else if (qmlItemNode.isFlowTransition()) { - deleteWithoutChildren(scene()->itemsForQmlItemNodes({qmlItemNode})); + } else if (isFlowNonItem(qmlItemNode)) { + removedItemList.append(scene()->itemsForQmlItemNodes({qmlItemNode})); + deleteWithoutChildren(removedItemList); } + + if (!removedItemList.isEmpty()) + m_currentTool->itemsAboutToRemoved(removedItemList); } void FormEditorView::hideNodeFromScene(const QmlItemNode &qmlItemNode) @@ -308,6 +318,11 @@ void FormEditorView::propertiesAboutToBeRemoved(const QList& p removedItems.append(item); delete item; } + } else if (isFlowNonItem(qmlItemNode)) { + if (FormEditorItem *item = m_scene->itemForQmlItemNode(qmlItemNode)) { + removedItems.append(item); + delete item; + } } } } @@ -377,7 +392,7 @@ void FormEditorView::bindingPropertiesChanged(const QList &prop QmlVisualNode node(property.parentModelNode()); if (node.isFlowTransition()) { FormEditorItem *item = m_scene->itemForQmlItemNode(node.toQmlItemNode()); - if (item) { + if (item && node.hasNodeParent()) { m_scene->reparentItem(node.toQmlItemNode(), node.toQmlItemNode().modelParentItem()); m_scene->synchronizeTransformation(item); item->update(); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp index 7f2558220f0..f708ba0c617 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp @@ -189,9 +189,12 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model) bool forceVisiblity = valid && NodeHints::fromItemLibraryEntry(entry).visibleInLibrary(); - if (m_flowMode) { - forceVisiblity = false; - isItem = metaInfo.isSubclassOf("FlowView.FlowItem"); + if (m_flowMode && metaInfo.isValid()) { + + isItem = metaInfo.isSubclassOf("FlowView.FlowItem") + || metaInfo.isSubclassOf("FlowView.FlowWildcard") + || metaInfo.isSubclassOf("FlowView.FlowDecision"); + forceVisiblity = isItem; } @@ -271,9 +274,6 @@ void ItemLibraryModel::updateVisibility(bool *changed) bool sectionVisibility = itemLibrarySection->updateSectionVisibility(sectionSearchText, §ionChanged); - if (m_flowMode && itemLibrarySection->sectionName() != "My QML Components") - sectionVisibility= false; - *changed |= sectionChanged; *changed |= itemLibrarySection->setVisible(sectionVisibility); } diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index 2bb6b5aded8..c91ff78626f 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -25,6 +25,7 @@ #include "navigatortreemodel.h" #include "navigatorview.h" +#include "qmldesignerplugin.h" #include #include @@ -49,6 +50,7 @@ #include #include #include +#include #include @@ -555,7 +557,8 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i ModelNode targetNode(modelNodeForIndex(rowModelIndex)); const QString imageSource = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")); // absolute path - const QString imageFileName = imageSource.mid(imageSource.lastIndexOf('/') + 1); + const QString imagePath = QmlDesignerPlugin::instance()->documentManager().currentFilePath().toFileInfo().dir().relativeFilePath(imageSource); // relative to .ui.qml file + ModelNode newModelNode; if (targetNode.isSubclassOf("QtQuick3D.DefaultMaterial")) { @@ -569,7 +572,7 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i // set texture source PropertyName prop = "source"; QString type = "QUrl"; - QVariant val = imageFileName; + QVariant val = imagePath; itemLibraryEntry.addProperty(prop, type, val); // create a texture @@ -581,8 +584,9 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i }); } else if (targetNode.isSubclassOf("QtQuick3D.Texture")) { // if dropping an image on a texture, set the texture source - targetNode.variantProperty("source").setValue(imageFileName); + targetNode.variantProperty("source").setValue(imagePath); } else { + // create an image newModelNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imageSource , QPointF(), targetProperty); } diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index 55ad0fb3535..56202a2596b 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -144,10 +144,17 @@ QVariant properDefaultAuxiliaryProperties(const QmlObjectNode &qmlObjectNode, if (node.hasAuxiliaryData(auxName)) return node.auxiliaryData(auxName); - - if (propertyName == "color") + if (propertyName == "transitionColor") return QColor(Qt::red); - if (propertyName == "fillColor") + if (propertyName == "areaColor") + return QColor(Qt::red); + if (propertyName == "blockColor") + return QColor(Qt::red); + if (propertyName == "areaFillColor") + return QColor(Qt::transparent); + else if (propertyName == "color") + return QColor(Qt::red); + else if (propertyName == "fillColor") return QColor(Qt::transparent); else if (propertyName == "width") return 4; @@ -233,6 +240,12 @@ void PropertyEditorQmlBackend::setupAuxiliaryProperties(const QmlObjectNode &qml propertyNames.append({"color", "width", "inOffset", "outOffset", "joinConnection"}); } else if (itemNode.isFlowActionArea()) { propertyNames.append({"color", "width", "fillColor", "outOffset", "dash"}); + } else if (itemNode.isFlowDecision()) { + propertyNames.append({"color", "width", "fillColor", "dash"}); + } else if (itemNode.isFlowWildcard()) { + propertyNames.append({"color", "width", "fillColor", "dash"}); + } else if (itemNode.isFlowView()) { + propertyNames.append({"transitionColor", "areaColor", "areaFillColor", "blockColor" }); } for (const PropertyName &propertyName : propertyNames) { diff --git a/src/plugins/qmldesigner/designercore/include/bindingproperty.h b/src/plugins/qmldesigner/designercore/include/bindingproperty.h index a530cb203f7..b8f60efbd87 100644 --- a/src/plugins/qmldesigner/designercore/include/bindingproperty.h +++ b/src/plugins/qmldesigner/designercore/include/bindingproperty.h @@ -49,6 +49,7 @@ public: AbstractProperty resolveToProperty() const; bool isList() const; QList resolveToModelNodeList() const; + void addModelNodeToArray(const ModelNode &modelNode); bool isAliasExport() const; diff --git a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp index ebd3c7c709a..1f1c1df58fa 100644 --- a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp +++ b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp @@ -199,6 +199,38 @@ QList BindingProperty::resolveToModelNodeList() const return returnList; } +void BindingProperty::addModelNodeToArray(const ModelNode &modelNode) +{ + if (!isValid()) + throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__); + + if (isBindingProperty()) { + QStringList simplifiedList; + if (isList()) { + QString string = expression(); + string.chop(1); + string.remove(0, 1); + QStringList simplifiedList = commaSeparatedSimplifiedStringList(string); + ModelNode node = modelNode; + simplifiedList.append(node.validId()); + setExpression('[' + simplifiedList.join(',') + ']'); + } else { + ModelNode currentNode = resolveToModelNode(); + if (currentNode.isValid()) + simplifiedList.append(currentNode.validId()); + } + ModelNode node = modelNode; + simplifiedList.append(node.validId()); + setExpression('[' + simplifiedList.join(',') + ']'); + } else if (exists()) { + throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, name()); + } else { + ModelNode node = modelNode; + setExpression('[' + node.validId() + ']'); + } + +} + bool BindingProperty::isAliasExport() const { if (!isValid()) diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp index 8eaa777dde2..4ba478f93cf 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp @@ -497,17 +497,20 @@ bool QmlItemNode::isInStackedContainer() const bool QmlItemNode::isFlowView() const { - return modelNode().metaInfo().isSubclassOf("FlowView.FlowView"); + return modelNode().isValid() + && modelNode().metaInfo().isSubclassOf("FlowView.FlowView"); } bool QmlItemNode::isFlowItem() const { - return modelNode().metaInfo().isSubclassOf("FlowView.FlowItem"); + return modelNode().isValid() + && modelNode().metaInfo().isSubclassOf("FlowView.FlowItem"); } bool QmlItemNode::isFlowActionArea() const { - return modelNode().metaInfo().isSubclassOf("FlowView.FlowActionArea"); + return modelNode().isValid() + && modelNode().metaInfo().isSubclassOf("FlowView.FlowActionArea"); } ModelNode QmlItemNode::rootModelNode() const diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp index 9fa5ef8e42d..3fa41cb1ad4 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp @@ -209,7 +209,18 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, NodeAbstractProperty parentProperty = parentQmlItemNode.defaultNodeAbstractProperty(); - return QmlItemNode::createQmlObjectNode(view, itemLibraryEntry, position, parentProperty); + + NodeHints hints = NodeHints::fromItemLibraryEntry(itemLibraryEntry); + const PropertyName forceNonDefaultProperty = hints.forceNonDefaultProperty().toUtf8(); + + QmlObjectNode newNode = QmlItemNode::createQmlObjectNode(view, itemLibraryEntry, position, parentProperty); + + if (!forceNonDefaultProperty.isEmpty()) { + if (parentQmlItemNode.modelNode().metaInfo().hasProperty(forceNonDefaultProperty)) + parentQmlItemNode.nodeListProperty(forceNonDefaultProperty).reparentHere(newNode); + } + + return newNode; } diff --git a/tests/system/suite_CSUP/tst_CSUP01/test.py b/tests/system/suite_CSUP/tst_CSUP01/test.py index d7d556721ce..8cac9bbfb0f 100644 --- a/tests/system/suite_CSUP/tst_CSUP01/test.py +++ b/tests/system/suite_CSUP/tst_CSUP01/test.py @@ -77,7 +77,7 @@ def main(): "possible to select one of the suggestions.") # Step 4: Insert text "voi" to new line and press Tab. resetLine(editorWidget) - type(editorWidget, "unsi") + type(editorWidget, "unsig") try: proposalListView = waitForObject(":popupFrame_Proposal_QListView") waitForObjectItem(proposalListView, "unsigned")