forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/6.0'
Change-Id: I9b824b8bb7b0b5d76e9e8f28f909b542adf773f0
This commit is contained in:
38
dist/changes-6.0.0.md
vendored
38
dist/changes-6.0.0.md
vendored
@@ -21,21 +21,30 @@ Editing
|
|||||||
|
|
||||||
* Added support for multiple cursor editing (QTCREATORBUG-16013)
|
* Added support for multiple cursor editing (QTCREATORBUG-16013)
|
||||||
* Added import and export for font settings (QTCREATORBUG-6833)
|
* Added import and export for font settings (QTCREATORBUG-6833)
|
||||||
|
* Fixed missing permissions update when files change (QTCREATORBUG-22447)
|
||||||
|
|
||||||
### C++
|
### C++
|
||||||
|
|
||||||
* Updated to LLVM 13
|
* Updated to LLVM 13
|
||||||
* Added completion and function hint to `clangd` support
|
|
||||||
* Added option for saving open files automatically after refactoring
|
* Added option for saving open files automatically after refactoring
|
||||||
(QTCREATORBUG-25924)
|
(QTCREATORBUG-25924)
|
||||||
|
* Added information about source to tooltip on diagnostics
|
||||||
* Fixed `Insert Definition` for templates with value parameters
|
* Fixed `Insert Definition` for templates with value parameters
|
||||||
(QTCREATORBUG-26113)
|
(QTCREATORBUG-26113)
|
||||||
* Fixed canceling of C++ parsing on configuration change (QTCREATORBUG-24890)
|
* Fixed canceling of C++ parsing on configuration change (QTCREATORBUG-24890)
|
||||||
|
* Fixed crash when checking for refactoring actions (QTCREATORBUG-26316)
|
||||||
|
* Fixed wrong target compiler option (QTCREATORBUG-25615)
|
||||||
|
* Fixed parentheses matching (QTCREATORBUG-26400)
|
||||||
|
* Clangd
|
||||||
|
* Added warning for older `clangd` versions
|
||||||
|
* Added support for completion and function hint
|
||||||
|
* Improved location of generated `compile_commands.json` (QTCREATORBUG-26431)
|
||||||
|
|
||||||
### QML
|
### QML
|
||||||
|
|
||||||
* Improved wizards for Qt 6.2 (QTCREATORBUG-26170)
|
* Improved wizards for Qt 6.2 (QTCREATORBUG-26170)
|
||||||
* Simplified wizards
|
* Simplified wizards
|
||||||
|
* Fixed wrong warning on JavaScript equality checks (QTCREATORBUG-25917)
|
||||||
|
|
||||||
### Language Server Protocol
|
### Language Server Protocol
|
||||||
|
|
||||||
@@ -53,11 +62,16 @@ Projects
|
|||||||
* Fixed redundant output on process crash (QTCREATORBUG-26049)
|
* Fixed redundant output on process crash (QTCREATORBUG-26049)
|
||||||
* Fixed duplicates in file rename dialog (QTCREATORBUG-26268)
|
* Fixed duplicates in file rename dialog (QTCREATORBUG-26268)
|
||||||
* Fixed variable expansion for working directory (QTCREATORBUG-26274)
|
* Fixed variable expansion for working directory (QTCREATORBUG-26274)
|
||||||
|
* Fixed possible warning when opening files from compile output
|
||||||
|
(QTCREATORBUG-26422)
|
||||||
|
* Fixed that re-detecting compilers removed compilers from kits
|
||||||
|
(QTCREATORBUG-25697)
|
||||||
|
|
||||||
### CMake
|
### CMake
|
||||||
|
|
||||||
* Removed separate `<Headers>` node from project tree (QTCREATORBUG-18206,
|
* Removed separate `<Headers>` node from project tree (QTCREATORBUG-18206,
|
||||||
QTCREATORBUG-24609, QTCREATORBUG-25407)
|
QTCREATORBUG-24609, QTCREATORBUG-25407)
|
||||||
|
* Improved performance while loading large projects
|
||||||
* Fixed that CMake warnings and project loading errors were not added to
|
* Fixed that CMake warnings and project loading errors were not added to
|
||||||
`Issues` pane (QTCREATORBUG-26231)
|
`Issues` pane (QTCREATORBUG-26231)
|
||||||
* Fixed header file handling when mentioned in target sources
|
* Fixed header file handling when mentioned in target sources
|
||||||
@@ -70,6 +84,19 @@ Projects
|
|||||||
|
|
||||||
* Fixed crash when canceling parsing (QTCREATORBUG-26333)
|
* Fixed crash when canceling parsing (QTCREATORBUG-26333)
|
||||||
|
|
||||||
|
### Compilation Database
|
||||||
|
|
||||||
|
* Fixed that headers were not shown as part of the project (QTCREATORBUG-26356)
|
||||||
|
|
||||||
|
Debugging
|
||||||
|
---------
|
||||||
|
|
||||||
|
### GDB
|
||||||
|
|
||||||
|
* Fixed issue with non-English locale (QTCREATORBUG-26384)
|
||||||
|
* Fixed variable expansion for `Additional Startup Commands`
|
||||||
|
(QTCREATORBUG-26382)
|
||||||
|
|
||||||
Version Control Systems
|
Version Control Systems
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
@@ -101,6 +128,10 @@ Platforms
|
|||||||
* Added details to device settings (QTCREATORBUG-23991)
|
* Added details to device settings (QTCREATORBUG-23991)
|
||||||
* Added filter field for Android SDK manager
|
* Added filter field for Android SDK manager
|
||||||
|
|
||||||
|
### WebAssembly
|
||||||
|
|
||||||
|
* Fixed running applications (QTCREATORBUG-25905, QTCREATORBUG-26189)
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
* Various improvements
|
* Various improvements
|
||||||
@@ -125,12 +156,14 @@ Eike Ziller
|
|||||||
Fawzi Mohamed
|
Fawzi Mohamed
|
||||||
Henning Gruendl
|
Henning Gruendl
|
||||||
Ihor Dutchak
|
Ihor Dutchak
|
||||||
|
Ivan Komissarov
|
||||||
Jaroslaw Kobus
|
Jaroslaw Kobus
|
||||||
Johanna Vanhatapio
|
Johanna Vanhatapio
|
||||||
Jonas Karlsson
|
Jonas Karlsson
|
||||||
Kai Köhne
|
Kai Köhne
|
||||||
Kama Wójcik
|
Kama Wójcik
|
||||||
Knud Dollereder
|
Knud Dollereder
|
||||||
|
Leena Miettinen
|
||||||
Li Xi
|
Li Xi
|
||||||
Loren Burkholder
|
Loren Burkholder
|
||||||
Mahmoud Badri
|
Mahmoud Badri
|
||||||
@@ -143,10 +176,13 @@ Petar Perisin
|
|||||||
Piotr Mikolajczyk
|
Piotr Mikolajczyk
|
||||||
Samuel Ghinet
|
Samuel Ghinet
|
||||||
Shantanu Tushar
|
Shantanu Tushar
|
||||||
|
Tapani Mattila
|
||||||
Tasuku Suzuki
|
Tasuku Suzuki
|
||||||
Thiago Macieira
|
Thiago Macieira
|
||||||
Thomas Hartmann
|
Thomas Hartmann
|
||||||
Tim Jenssen
|
Tim Jenssen
|
||||||
Tony Leinonen
|
Tony Leinonen
|
||||||
Tor Arne Vestbø
|
Tor Arne Vestbø
|
||||||
|
Tuomo Pelkonen
|
||||||
|
Vikas Pachdha
|
||||||
Vladimir Serdyuk
|
Vladimir Serdyuk
|
||||||
|
44
doc/qtcreator/examples/accelbubble/AndroidManifest.xml
Normal file
44
doc/qtcreator/examples/accelbubble/AndroidManifest.xml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="org.qtproject.example"
|
||||||
|
android:installLocation="auto"
|
||||||
|
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
|
||||||
|
android:versionName="-- %%INSERT_VERSION_NAME%% --">
|
||||||
|
<!-- %%INSERT_PERMISSIONS -->
|
||||||
|
<!-- %%INSERT_FEATURES -->
|
||||||
|
<supports-screens
|
||||||
|
android:anyDensity="true"
|
||||||
|
android:largeScreens="true"
|
||||||
|
android:normalScreens="true"
|
||||||
|
android:smallScreens="true" />
|
||||||
|
<application
|
||||||
|
android:name="org.qtproject.qt.android.bindings.QtApplication"
|
||||||
|
android:extractNativeLibs="true"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:label="-- %%INSERT_APP_NAME%% --"
|
||||||
|
android:requestLegacyExternalStorage="true">
|
||||||
|
<activity
|
||||||
|
android:name="org.qtproject.qt.android.bindings.QtActivity"
|
||||||
|
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
|
||||||
|
android:label="-- %%INSERT_APP_NAME%% --"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:screenOrientation="portrait">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.app.lib_name"
|
||||||
|
android:value="-- %%INSERT_APP_LIB_NAME%% --" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.app.arguments"
|
||||||
|
android:value="-- %%INSERT_APP_ARGUMENTS%% --" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.app.extract_android_style"
|
||||||
|
android:value="minimal" />
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
@@ -1,12 +0,0 @@
|
|||||||
import QtQuick 2.14
|
|
||||||
import QtQuick.Window 2.14
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: bubble
|
|
||||||
source: "Bluebubble.svg"
|
|
||||||
smooth: true
|
|
||||||
property real centerX
|
|
||||||
property real bubbleCenter
|
|
||||||
property real centerY
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
}
|
|
32
doc/qtcreator/examples/accelbubble/CMakeLists.txt
Normal file
32
doc/qtcreator/examples/accelbubble/CMakeLists.txt
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(accelbubble VERSION 0.1 LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
find_package(Qt6 6.2 COMPONENTS Quick Sensors Svg Xml REQUIRED)
|
||||||
|
|
||||||
|
qt_add_executable(accelbubbleexample
|
||||||
|
main.cpp
|
||||||
|
MANUAL_FINALIZATION
|
||||||
|
)
|
||||||
|
set_target_properties(accelbubbleexample PROPERTIES
|
||||||
|
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
|
||||||
|
)
|
||||||
|
set_property(TARGET accelbubbleexample APPEND PROPERTY
|
||||||
|
QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android
|
||||||
|
)
|
||||||
|
qt_add_qml_module(accelbubbleexample
|
||||||
|
URI accelbubble
|
||||||
|
VERSION 1.0
|
||||||
|
QML_FILES main.qml
|
||||||
|
RESOURCES Bluebubble.svg
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(accelbubbleexample
|
||||||
|
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
|
||||||
|
target_link_libraries(accelbubbleexample
|
||||||
|
PRIVATE Qt6::Quick Qt6::Sensors Qt6::Svg Qt6::Xml)
|
||||||
|
|
||||||
|
qt_finalize_executable(accelbubbleexample)
|
34
doc/qtcreator/examples/accelbubble/Info.plist
Normal file
34
doc/qtcreator/examples/accelbubble/Info.plist
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>accelbubble</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>accelbubble</string>
|
||||||
|
<key>CFBundleGetInfoString</key>
|
||||||
|
<string>Created by Qt</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>io.qt.accelbubble</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>accelbubble</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>NOTE</key>
|
||||||
|
<string>This file was generated by Qt.</string>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@@ -1,25 +0,0 @@
|
|||||||
QT += quick sensors svg xml
|
|
||||||
|
|
||||||
CONFIG += c++11
|
|
||||||
|
|
||||||
# You can make your code fail to compile if it uses deprecated APIs.
|
|
||||||
# In order to do so, uncomment the following line.
|
|
||||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
main.cpp
|
|
||||||
|
|
||||||
RESOURCES += qml.qrc
|
|
||||||
|
|
||||||
# Additional import path used to resolve QML modules in Qt Creator's code model
|
|
||||||
QML_IMPORT_PATH =
|
|
||||||
|
|
||||||
# Additional import path used to resolve QML modules just for Qt Quick Designer
|
|
||||||
QML_DESIGNER_IMPORT_PATH =
|
|
||||||
|
|
||||||
# Default rules for deployment.
|
|
||||||
qnx: target.path = /tmp/$${TARGET}/bin
|
|
||||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
|
||||||
!isEmpty(target.path): INSTALLS += target
|
|
||||||
|
|
||||||
ANDROID_ABIS = armeabi-v7a
|
|
@@ -1,14 +1,13 @@
|
|||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
|
||||||
|
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
const QUrl url(QStringLiteral("qrc:/main.qml"));
|
const QUrl url(u"qrc:/accelbubble/main.qml"_qs);
|
||||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
|
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
|
||||||
&app, [url](QObject *obj, const QUrl &objUrl) {
|
&app, [url](QObject *obj, const QUrl &objUrl) {
|
||||||
if (!obj && url == objUrl)
|
if (!obj && url == objUrl)
|
||||||
|
@@ -1,49 +1,22 @@
|
|||||||
import QtQuick 2.14
|
import QtQuick
|
||||||
import QtQuick.Window 2.14
|
import QtSensors
|
||||||
import QtSensors 5.12
|
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
id: window
|
|
||||||
visible: true
|
|
||||||
property alias mainWindow: mainWindow
|
|
||||||
property alias bubble: bubble
|
|
||||||
Rectangle {
|
|
||||||
id: mainWindow
|
id: mainWindow
|
||||||
color: "#ffffff"
|
width: 320
|
||||||
anchors.fill: parent
|
height: 480
|
||||||
|
visible: true
|
||||||
Bubble {
|
title: qsTr("Accelerate Bubble")
|
||||||
id: bubble
|
readonly property double radians_to_degrees: 180 / Math.PI
|
||||||
x: bubble.centerX - bubbleCenter
|
|
||||||
y: bubble.centerY - bubbleCenter
|
|
||||||
bubbleCenter: bubble.width /2
|
|
||||||
centerX: mainWindow.width /2
|
|
||||||
centerY: mainWindow.height /2
|
|
||||||
|
|
||||||
Behavior on y {
|
|
||||||
SmoothedAnimation {
|
|
||||||
easing.type: Easing.Linear
|
|
||||||
duration: 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on x {
|
|
||||||
SmoothedAnimation {
|
|
||||||
easing.type: Easing.Linear
|
|
||||||
duration: 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Accelerometer {
|
Accelerometer {
|
||||||
id: accel
|
id: accel
|
||||||
dataRate: 100
|
dataRate: 100
|
||||||
active: true
|
active:true
|
||||||
readonly property double radians_to_degrees: 180 / Math.PI
|
|
||||||
|
|
||||||
onReadingChanged: {
|
onReadingChanged: {
|
||||||
var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)
|
var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * .1)
|
||||||
var newY = (bubble.y - calcPitch(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)
|
var newY = (bubble.y - calcPitch(accel.reading.x, accel.reading.y, accel.reading.z) * .1)
|
||||||
|
|
||||||
if (isNaN(newX) || isNaN(newY))
|
if (isNaN(newX) || isNaN(newY))
|
||||||
return;
|
return;
|
||||||
@@ -66,9 +39,33 @@ Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function calcPitch(x,y,z) {
|
function calcPitch(x,y,z) {
|
||||||
return -Math.atan2(y, Math.hypot(x, z)) * accel.radians_to_degrees;
|
return -Math.atan2(y, Math.hypot(x, z)) * mainWindow.radians_to_degrees;
|
||||||
}
|
}
|
||||||
function calcRoll(x,y,z) {
|
function calcRoll(x,y,z) {
|
||||||
return -Math.atan2(x, Math.hypot(y, z)) * accel.radians_to_degrees;
|
return -Math.atan2(x, Math.hypot(y, z)) * mainWindow.radians_to_degrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: bubble
|
||||||
|
source: "Bluebubble.svg"
|
||||||
|
smooth: true
|
||||||
|
property real centerX: mainWindow.width / 2
|
||||||
|
property real centerY: mainWindow.height / 2
|
||||||
|
property real bubbleCenter: bubble.width / 2
|
||||||
|
x: centerX - bubbleCenter
|
||||||
|
y: centerY - bubbleCenter
|
||||||
|
|
||||||
|
Behavior on y {
|
||||||
|
SmoothedAnimation {
|
||||||
|
easing.type: Easing.Linear
|
||||||
|
duration: 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Behavior on x {
|
||||||
|
SmoothedAnimation {
|
||||||
|
easing.type: Easing.Linear
|
||||||
|
duration: 100
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/">
|
|
||||||
<file>main.qml</file>
|
|
||||||
<file>Bluebubble.svg</file>
|
|
||||||
<file>Bubble.qml</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
BIN
doc/qtcreator/images/qtquick-mobile-tutorial-manifest.png
Normal file
BIN
doc/qtcreator/images/qtquick-mobile-tutorial-manifest.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
@@ -36,19 +36,21 @@
|
|||||||
|
|
||||||
\title Creating a Mobile Application
|
\title Creating a Mobile Application
|
||||||
|
|
||||||
This tutorial describes developing Qt Quick applications for Android and iOS
|
This tutorial describes how to use \QC to develop Qt Quick applications for
|
||||||
devices using Qt Quick Controls.
|
Android and iOS devices when using Qt 6 as the minimum Qt version and CMake
|
||||||
We use \QC to implement a Qt Quick application
|
as the build system.
|
||||||
that accelerates an SVG (Scalable Vector Graphics) image based on the
|
|
||||||
changing accelerometer values.
|
We implement a Qt Quick application that accelerates an SVG (Scalable Vector
|
||||||
|
Graphics) image based on the changing accelerometer values.
|
||||||
|
|
||||||
|
\note You must have the \l{Qt Sensors} module from Qt 6.2 or later installed
|
||||||
|
to be able to follow this tutorial.
|
||||||
|
|
||||||
\image creator_android_tutorial_ex_app.png
|
\image creator_android_tutorial_ex_app.png
|
||||||
|
|
||||||
For more information about the UI choices you have, see \l{User Interfaces}.
|
|
||||||
|
|
||||||
\section1 Setting up the Development Environment
|
\section1 Setting up the Development Environment
|
||||||
|
|
||||||
To be able to build the application for and run it on a mobile device, you must
|
To build the application for and run it on a mobile device, you must
|
||||||
set up the development environment for the device platform and configure a
|
set up the development environment for the device platform and configure a
|
||||||
connection between \QC and the mobile device.
|
connection between \QC and the mobile device.
|
||||||
|
|
||||||
@@ -63,163 +65,58 @@
|
|||||||
|
|
||||||
\include qtquick-tutorial-create-empty-project.qdocinc qtquick empty application
|
\include qtquick-tutorial-create-empty-project.qdocinc qtquick empty application
|
||||||
|
|
||||||
\section1 Creating the Accelbubble Main View
|
\section1 Adding Images as Resources
|
||||||
|
|
||||||
The main view of the application displays an SVG bubble image that moves
|
The main view of the application displays an SVG bubble image that moves
|
||||||
around the screen when you tilt the device.
|
around the screen when you tilt the device.
|
||||||
|
|
||||||
We use \e {Bluebubble.svg} in this tutorial, but you can use any other
|
We use \e {Bluebubble.svg} in this tutorial, but you can use any other
|
||||||
image or component, instead.
|
image or component instead.
|
||||||
|
|
||||||
To create the UI in \l{Form Editor}:
|
For the image to appear when you run the application, you must specify it
|
||||||
|
as a resource in the \c RESOURCES section of \e CMakeLists.txt file that
|
||||||
|
the wizard created for you:
|
||||||
|
|
||||||
\list 1
|
\quotefromfile accelbubble/CMakeLists.txt
|
||||||
|
\skipto qt_add_qml_module
|
||||||
|
\printuntil )
|
||||||
|
|
||||||
\li Open the \e main.qml in \uicontrol {Form Editor}.
|
\section1 Creating the Accelbubble Main View
|
||||||
|
|
||||||
\li In \l Library > \uicontrol Components >
|
We create the main view in the \e main.qml file by adding an \l Image
|
||||||
\uicontrol {Default Components} > \uicontrol Basic, select
|
component with \e Bluebubble.svg as the source:
|
||||||
\uicontrol Rectangle and drag-and-drop it to \e Window
|
|
||||||
in \l Navigator.
|
|
||||||
|
|
||||||
\li Select the rectangle instance in \uicontrol Navigator to edit its
|
\quotefromfile accelbubble/main.qml
|
||||||
properties in \l Properties:
|
\skipto Image
|
||||||
|
\printuntil smooth
|
||||||
|
|
||||||
\image qtquick-mobile-app-tutorial-main-view.png "Rectangle in different views"
|
Next, we add custom properties to position the image in respect to the width
|
||||||
|
and height of the main window:
|
||||||
|
|
||||||
\list a
|
\printuntil y:
|
||||||
|
|
||||||
\li In the \uicontrol ID field enter \e mainWindow, to be able
|
|
||||||
to reference the rectangle from other places.
|
|
||||||
|
|
||||||
\li Select the \uicontrol Layout tab, and then click
|
|
||||||
the \inlineimage icons/anchor-fill.png
|
|
||||||
(\uicontrol {Fill to Parent}) button to anchor the rectangle
|
|
||||||
to the window.
|
|
||||||
|
|
||||||
\endlist
|
|
||||||
|
|
||||||
\li Select \uicontrol Library > \uicontrol Assets >
|
|
||||||
\inlineimage plus.png
|
|
||||||
to locate Bluebubble.svg (or your own image) and add it to
|
|
||||||
the project folder.
|
|
||||||
\li Drag and drop the image from \uicontrol Assets to
|
|
||||||
\e mainWindow in \uicontrol Navigator. \QC creates an
|
|
||||||
instance of an \l{Images}{Image} component for you
|
|
||||||
with the path to the image file set as the value of
|
|
||||||
the \uicontrol Source field in \uicontrol Properties.
|
|
||||||
|
|
||||||
\li In the \uicontrol Properties view, \uicontrol ID field, enter
|
|
||||||
\e bubble to be able to reference the image from other places.
|
|
||||||
|
|
||||||
\image qtquick-mobile-app-tutorial-image.png "Image file in different views"
|
|
||||||
|
|
||||||
\li Select the \inlineimage icons/alias.png
|
|
||||||
(\uicontrol Export) button in \uicontrol Navigator to export
|
|
||||||
\e mainWindow and \e bubble as properties.
|
|
||||||
|
|
||||||
\endlist
|
|
||||||
|
|
||||||
We want to modify the properties of the bubble in ways that are not
|
|
||||||
supported in \uicontrol {Form Editor}, and therefore we turn it into
|
|
||||||
a custom component:
|
|
||||||
|
|
||||||
\list 1
|
|
||||||
|
|
||||||
\li Right-click the image and select
|
|
||||||
\uicontrol {Move Component into Separate File}.
|
|
||||||
|
|
||||||
\image qtquick-mobile-app-tutorial-bubble-component.png
|
|
||||||
|
|
||||||
\li In the \uicontrol {Component name} field, enter \e Bubble.
|
|
||||||
|
|
||||||
\li Deselect the \uicontrol x and \uicontrol y check boxes,
|
|
||||||
because we want to use the accelerometer to determine
|
|
||||||
the location of the bubble on the screen.
|
|
||||||
|
|
||||||
\li Select \uicontrol OK to create \e Bubble.qml.
|
|
||||||
|
|
||||||
\endlist
|
|
||||||
|
|
||||||
\QC creates an instance of the Bubble component in \e main.qml.
|
|
||||||
|
|
||||||
To check your code, you can compare your \e main.qml and
|
|
||||||
\e {Bubble.qml} with the corresponding example files.
|
|
||||||
|
|
||||||
The UI is now ready and you can add the necessary properties for
|
|
||||||
making the bubble move.
|
|
||||||
|
|
||||||
\section1 Moving the Bubble
|
|
||||||
|
|
||||||
We add custom properties to position the image in respect to the width
|
|
||||||
and height of the main window.
|
|
||||||
|
|
||||||
\list 1
|
|
||||||
\li Open \e Bubble.qml in \uicontrol {Form Editor}.
|
|
||||||
\li In \l {Connection View} > \uicontrol Properties,
|
|
||||||
select the \inlineimage plus.png
|
|
||||||
button to add a custom property for the Bubble component.
|
|
||||||
\image qtquick-mobile-app-tutorial-custom-properties.png "Connection View Properties tab"
|
|
||||||
\li Double-click the value in the \uicontrol Property column, and enter
|
|
||||||
\e centerY as the name of the property.
|
|
||||||
\li Double-click the value in the \uicontrol {Property Type} column,
|
|
||||||
and select \e real as the component of the property. You will specify
|
|
||||||
the property value later in \uicontrol Properties.
|
|
||||||
\li Add two more properties of the same type with the names \e centerY
|
|
||||||
and \e bubbleCenter.
|
|
||||||
\li Open \e main.qml in \uicontrol {Form Editor}.
|
|
||||||
\li Select \e bubble in \uicontrol Navigator to specify values for the
|
|
||||||
custom properties in \uicontrol Properties.
|
|
||||||
\li In the \uicontrol X field, select \inlineimage icons/action-icon.png
|
|
||||||
, and then select \uicontrol {Set Binding} to open
|
|
||||||
\uicontrol {Binding Editor}.
|
|
||||||
\image qtquick-mobile-app-tutorial-binding-editor1.png "Setting binding for X in Binding Editor"
|
|
||||||
\li Enter the following value to center the bubble horizontally in the
|
|
||||||
main window when the application starts:
|
|
||||||
\c{bubble.centerX - bubbleCenter}.
|
|
||||||
\li Select \uicontrol OK to close the binding editor and save the
|
|
||||||
binding.
|
|
||||||
\li In the \uicontrol X field, set the following binding to center the
|
|
||||||
bubble vertically: \c{bubble.centerY - bubbleCenter}.
|
|
||||||
\li In the \uicontrol centerY field, enter the following value to bind
|
|
||||||
the y coordinate of the bubble center to half the height of the main
|
|
||||||
window: \c {mainWindow.height /2}.
|
|
||||||
\image qtquick-mobile-app-tutorial-binding-editor.png "Setting binding for centerX"
|
|
||||||
\li In the \uicontrol centerX field, bind the x coordinate of
|
|
||||||
the bubble center to half the width of the main window:
|
|
||||||
\c {mainWindow.width /2}.
|
|
||||||
\li In the \uicontrol bubbleCenter field, bind the center of
|
|
||||||
the bubble to half of its width: \c {bubble.width /2}.
|
|
||||||
\endlist
|
|
||||||
|
|
||||||
We now want to add code to move the bubble based on Accelerometer sensor
|
We now want to add code to move the bubble based on Accelerometer sensor
|
||||||
values. This is not supported by \l {Form Editor}, so we will do
|
values. First, we add the following import statement:
|
||||||
it in \l {Text Editor}:
|
|
||||||
|
|
||||||
\list 1
|
|
||||||
\li Add the following import statement to \e main.qml:
|
|
||||||
|
|
||||||
\quotefromfile accelbubble/main.qml
|
\quotefromfile accelbubble/main.qml
|
||||||
\skipto QtSensors
|
\skipto QtSensors
|
||||||
\printline QtSensors
|
\printline QtSensors
|
||||||
|
|
||||||
\li Add the \l{Accelerometer} component with the necessary properties:
|
Next, we add the \l{Accelerometer} component with the necessary properties:
|
||||||
|
|
||||||
\skipto Accelerometer
|
\skipto Accelerometer
|
||||||
\printuntil radians_to_degrees
|
\printuntil active
|
||||||
\skipto }
|
|
||||||
\printuntil }
|
|
||||||
|
|
||||||
\li Add the following JavaScript functions that calculate the
|
Then, we add the following JavaScript functions that calculate the
|
||||||
x and y position of the bubble based on the current Accelerometer
|
x and y position of the bubble based on the current Accelerometer
|
||||||
values:
|
values:
|
||||||
|
|
||||||
\quotefromfile accelbubble/main.qml
|
\quotefromfile accelbubble/main.qml
|
||||||
\skipto function
|
\skipto function
|
||||||
\printuntil Math.atan2(x
|
\printuntil }
|
||||||
\printuntil }
|
\printuntil }
|
||||||
|
|
||||||
\li Add the following JavaScript code for \c onReadingChanged signal of
|
We add the following JavaScript code for \c onReadingChanged signal of
|
||||||
Accelerometer component to make the bubble move when the Accelerometer
|
Accelerometer component to make the bubble move when the Accelerometer
|
||||||
values change:
|
values change:
|
||||||
|
|
||||||
@@ -231,7 +128,8 @@
|
|||||||
within the bounds of the screen. If the Accelerometer returns
|
within the bounds of the screen. If the Accelerometer returns
|
||||||
\e {not a number} (NaN), the value is ignored and the bubble
|
\e {not a number} (NaN), the value is ignored and the bubble
|
||||||
position is not updated.
|
position is not updated.
|
||||||
\li Add \l SmoothedAnimation behavior on the \c x and \c y properties of
|
|
||||||
|
We add \l SmoothedAnimation behavior on the \c x and \c y properties of
|
||||||
the bubble to make its movement look smoother.
|
the bubble to make its movement look smoother.
|
||||||
|
|
||||||
\quotefromfile accelbubble/main.qml
|
\quotefromfile accelbubble/main.qml
|
||||||
@@ -239,7 +137,6 @@
|
|||||||
\printuntil x
|
\printuntil x
|
||||||
\printuntil }
|
\printuntil }
|
||||||
\printuntil }
|
\printuntil }
|
||||||
\endlist
|
|
||||||
|
|
||||||
\section1 Locking Device Orientation
|
\section1 Locking Device Orientation
|
||||||
|
|
||||||
@@ -248,35 +145,69 @@
|
|||||||
better for the screen orientation to be fixed.
|
better for the screen orientation to be fixed.
|
||||||
|
|
||||||
To lock the orientation to portrait or landscape on Android, specify it in
|
To lock the orientation to portrait or landscape on Android, specify it in
|
||||||
an AndroidManifest.xml that you can generate in \QC. For more information,
|
an \e AndroidManifest.xml that you can generate in \QC. For more information,
|
||||||
see \l{Editing Manifest Files}.
|
see \l{Editing Manifest Files}.
|
||||||
|
|
||||||
On iOS, you can lock the device orientation in an Info.plist file that you
|
\image qtquick-mobile-tutorial-manifest.png "Accelbubble manifest file"
|
||||||
specify in the .pro file as the value of the QMAKE_INFO_PLIST variable.
|
|
||||||
|
To generate and use a manifest file, you must specify the Android package
|
||||||
|
source directory, \c QT_ANDROID_PACKAGE_SOURCE_DIR in the \e CMakeLists.txt
|
||||||
|
file:
|
||||||
|
|
||||||
|
\quotefromfile accelbubble/CMakeLists.txt
|
||||||
|
\skipto set_property
|
||||||
|
\printuntil )
|
||||||
|
|
||||||
|
Because our CMake version is older than 3.19, we must add a manual
|
||||||
|
finalization step to the \c qt_add_executable function:
|
||||||
|
|
||||||
|
\quotefromfile accelbubble/CMakeLists.txt
|
||||||
|
\skipto qt_add_executable
|
||||||
|
\printuntil )
|
||||||
|
|
||||||
|
We also need to add the \c qt_finalize_executable function:
|
||||||
|
|
||||||
|
\skipto qt_finalize_executable
|
||||||
|
\printuntil )
|
||||||
|
|
||||||
|
On iOS, you can lock the device orientation in an \e Info.plist file
|
||||||
|
that you specify in the \e CMakeLists.txt file as the value of the
|
||||||
|
\c MACOSX_BUNDLE_INFO_PLIST variable:
|
||||||
|
|
||||||
|
\quotefromfile accelbubble/CMakeLists.txt
|
||||||
|
\skipto set_target_properties
|
||||||
|
\printuntil )
|
||||||
|
|
||||||
\section1 Adding Dependencies
|
\section1 Adding Dependencies
|
||||||
|
|
||||||
Update the accelbubble.pro file with the following library dependency
|
You must tell the build system which Qt modules your application needs by
|
||||||
information:
|
specifying dependencies in the project file. Select \uicontrol Projects to
|
||||||
|
update the CMake configuration with the following Qt module information:
|
||||||
|
\c Sensors, \c Svg, \c Xml.
|
||||||
|
|
||||||
\code
|
The \e CMakeLists.txt file should contain the following entries that tell
|
||||||
QT += quick sensors svg xml
|
CMake to look up the Qt installation and import the Qt Sensors, Qt SVG,
|
||||||
\endcode
|
and Qt XML modules needed by the application:
|
||||||
|
|
||||||
On iOS, you must link to the above libraries statically, by adding the
|
\quotefromfile accelbubble/CMakeLists.txt
|
||||||
plugin names explicitly as values of the QTPLUGIN variable. Specify a
|
\skipto find_package
|
||||||
qmake scope for iOS builds (which can also contain the QMAKE_INFO_PLIST
|
\printuntil REQUIRED
|
||||||
variable):
|
|
||||||
|
|
||||||
\code
|
You also need to add the Qt modules to the list of target link libraries.
|
||||||
ios {
|
\c target_link_libraries tells CMake that the accelbubble executable uses
|
||||||
QTPLUGIN += qsvg qsvgicon qtsensors_ios
|
the Qt Sensors, Qt SVG, and Qt XML modules by referencing the targets
|
||||||
QMAKE_INFO_PLIST = Info.plist
|
imported by the \c find_package() call above. This adds the necessary
|
||||||
}
|
arguments to the linker and makes sure that the appropriate include
|
||||||
\endcode
|
directories and compiler definitions are passed to the C++ compiler.
|
||||||
|
|
||||||
After adding the dependencies, select \uicontrol Build > \uicontrol {Run qmake} to apply
|
\skipto target_link_libraries(accelbubble
|
||||||
the changes to the Makefile of the project.
|
\printuntil Qt6
|
||||||
|
|
||||||
|
After adding the dependencies, select \uicontrol Build >
|
||||||
|
\uicontrol {Run CMake} to apply configuration changes.
|
||||||
|
|
||||||
|
For more information about the CMakeLists.txt file, see
|
||||||
|
\l{Get started with CMake}.
|
||||||
|
|
||||||
\section1 Running the Application
|
\section1 Running the Application
|
||||||
|
|
||||||
@@ -292,7 +223,7 @@
|
|||||||
If you are using a device running Android v4.2.2, it should prompt you to
|
If you are using a device running Android v4.2.2, it should prompt you to
|
||||||
verify the connection to allow USB debugging from the PC it is connected
|
verify the connection to allow USB debugging from the PC it is connected
|
||||||
to. To avoid such prompts every time you connect the device, select the
|
to. To avoid such prompts every time you connect the device, select the
|
||||||
\uicontrol {Always allow from the computer} check box, and then select
|
\uicontrol {Always allow from this computer} check box, and then select
|
||||||
\uicontrol OK.
|
\uicontrol OK.
|
||||||
|
|
||||||
\li To run the application on the device, press \key {Ctrl+R}.
|
\li To run the application on the device, press \key {Ctrl+R}.
|
||||||
|
@@ -184,18 +184,14 @@ void Qt5RenderNodeInstanceServer::completeComponent(const CompleteComponentComma
|
|||||||
{
|
{
|
||||||
Qt5NodeInstanceServer::completeComponent(command);
|
Qt5NodeInstanceServer::completeComponent(command);
|
||||||
|
|
||||||
QList<ServerNodeInstance> instanceList;
|
const QVector<qint32> ids = command.instances();
|
||||||
foreach (qint32 instanceId, command.instances()) {
|
for (qint32 instanceId : ids) {
|
||||||
if (hasInstanceForId(instanceId)) {
|
if (hasInstanceForId(instanceId)) {
|
||||||
ServerNodeInstance instance = instanceForId(instanceId);
|
ServerNodeInstance instance = instanceForId(instanceId);
|
||||||
if (instance.isValid()) {
|
if (instance.isValid())
|
||||||
instanceList.append(instance);
|
|
||||||
m_dirtyInstanceSet.insert(instance);
|
m_dirtyInstanceSet.insert(instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand(instanceList));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlDesigner::Qt5RenderNodeInstanceServer::removeSharedMemory(const QmlDesigner::RemoveSharedMemoryCommand &command)
|
void QmlDesigner::Qt5RenderNodeInstanceServer::removeSharedMemory(const QmlDesigner::RemoveSharedMemoryCommand &command)
|
||||||
|
@@ -33,7 +33,9 @@ import StudioTheme 1.0 as StudioTheme
|
|||||||
PropertyEditorPane {
|
PropertyEditorPane {
|
||||||
id: itemPane
|
id: itemPane
|
||||||
|
|
||||||
ComponentSection {}
|
ComponentSection {
|
||||||
|
showState: true
|
||||||
|
}
|
||||||
|
|
||||||
GeometrySection {}
|
GeometrySection {}
|
||||||
|
|
||||||
@@ -82,22 +84,6 @@ PropertyEditorPane {
|
|||||||
|
|
||||||
ExpandingSpacer {}
|
ExpandingSpacer {}
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyLabel { text: qsTr("State") }
|
|
||||||
|
|
||||||
SecondColumnLayout {
|
|
||||||
ComboBox {
|
|
||||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
|
||||||
+ StudioTheme.Values.actionIndicatorWidth
|
|
||||||
width: implicitWidth
|
|
||||||
editable: true
|
|
||||||
backendValue: backendValues.state
|
|
||||||
model: allStateNames
|
|
||||||
valueType: ComboBox.String
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpandingSpacer {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
Controls.Label {
|
Controls.Label {
|
||||||
text: qsTr("Select an Item in the Form Editor, Navigator or Text Edit View to see its properties.")
|
text: qsTr("Select a component in Form Editor, Navigator, or Text Editor to see its properties.")
|
||||||
font.pixelSize: StudioTheme.Values.myFontSize * 1.5
|
font.pixelSize: StudioTheme.Values.myFontSize * 1.5
|
||||||
color: StudioTheme.Values.themeTextColor
|
color: StudioTheme.Values.themeTextColor
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
@@ -32,7 +32,9 @@ import StudioTheme 1.0 as StudioTheme
|
|||||||
PropertyEditorPane {
|
PropertyEditorPane {
|
||||||
id: itemPane
|
id: itemPane
|
||||||
|
|
||||||
ComponentSection {}
|
ComponentSection {
|
||||||
|
showState: majorVersion >= 6
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@@ -787,7 +787,9 @@ SecondColumnLayout {
|
|||||||
|
|
||||||
ControlLabel {
|
ControlLabel {
|
||||||
text: "Hex"
|
text: "Hex"
|
||||||
width: StudioTheme.Values.colorEditorPopupHexLabelWidth
|
width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
|
+ StudioTheme.Values.controlGap
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,11 +32,14 @@ import HelperWidgets 2.0
|
|||||||
import StudioTheme 1.0 as StudioTheme
|
import StudioTheme 1.0 as StudioTheme
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
|
id: root
|
||||||
caption: qsTr("Component")
|
caption: qsTr("Component")
|
||||||
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
property bool showState: false
|
||||||
|
|
||||||
SectionLayout {
|
SectionLayout {
|
||||||
PropertyLabel { text: qsTr("Type") }
|
PropertyLabel { text: qsTr("Type") }
|
||||||
|
|
||||||
@@ -262,5 +265,26 @@ Section {
|
|||||||
onCanceled: hideWidget()
|
onCanceled: hideWidget()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PropertyLabel {
|
||||||
|
visible: root.showState
|
||||||
|
text: qsTr("State")
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
visible: root.showState
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||||
|
+ StudioTheme.Values.actionIndicatorWidth
|
||||||
|
width: implicitWidth
|
||||||
|
editable: true
|
||||||
|
backendValue: backendValues.state
|
||||||
|
model: allStateNames
|
||||||
|
valueType: ComboBox.String
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpandingSpacer {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,13 +33,13 @@ Item {
|
|||||||
property string propertyName
|
property string propertyName
|
||||||
|
|
||||||
property alias decimals: spinBox.decimals
|
property alias decimals: spinBox.decimals
|
||||||
|
|
||||||
property alias value: spinBox.realValue
|
property alias value: spinBox.realValue
|
||||||
|
|
||||||
property alias minimumValue: spinBox.realFrom
|
property alias minimumValue: spinBox.realFrom
|
||||||
property alias maximumValue: spinBox.realTo
|
property alias maximumValue: spinBox.realTo
|
||||||
property alias stepSize: spinBox.realStepSize
|
property alias stepSize: spinBox.realStepSize
|
||||||
|
|
||||||
|
property alias pixelsPerUnit: spinBox.pixelsPerUnit
|
||||||
|
|
||||||
width: 90
|
width: 90
|
||||||
implicitHeight: spinBox.height
|
implicitHeight: spinBox.height
|
||||||
|
|
||||||
@@ -52,6 +52,8 @@ Item {
|
|||||||
StudioControls.RealSpinBox {
|
StudioControls.RealSpinBox {
|
||||||
id: spinBox
|
id: spinBox
|
||||||
|
|
||||||
|
__devicePixelRatio: devicePixelRatio()
|
||||||
|
|
||||||
width: wrapper.width
|
width: wrapper.width
|
||||||
actionIndicatorVisible: false
|
actionIndicatorVisible: false
|
||||||
|
|
||||||
|
@@ -199,8 +199,6 @@ QtObject {
|
|||||||
property real colorEditorPopupCmoboBoxWidth: 110
|
property real colorEditorPopupCmoboBoxWidth: 110
|
||||||
property real colorEditorPopupSpinBoxWidth: 54
|
property real colorEditorPopupSpinBoxWidth: 54
|
||||||
|
|
||||||
property real colorEditorPopupHexLabelWidth: 20
|
|
||||||
|
|
||||||
// Theme Colors
|
// Theme Colors
|
||||||
|
|
||||||
property string themePanelBackground: Theme.color(Theme.DSpanelBackground)
|
property string themePanelBackground: Theme.color(Theme.DSpanelBackground)
|
||||||
|
@@ -133,8 +133,8 @@ ModelManagerInterface::ModelManagerInterface(QObject *parent)
|
|||||||
qRegisterMetaType<QmlJS::PathAndLanguage>("QmlJS::PathAndLanguage");
|
qRegisterMetaType<QmlJS::PathAndLanguage>("QmlJS::PathAndLanguage");
|
||||||
qRegisterMetaType<QmlJS::PathsAndLanguages>("QmlJS::PathsAndLanguages");
|
qRegisterMetaType<QmlJS::PathsAndLanguages>("QmlJS::PathsAndLanguages");
|
||||||
|
|
||||||
m_defaultProjectInfo.qtQmlPath = QFileInfo(
|
m_defaultProjectInfo.qtQmlPath =
|
||||||
QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)).canonicalFilePath();
|
FilePath::fromUserInput(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath));
|
||||||
m_defaultProjectInfo.qtVersionString = QLibraryInfo::version().toString();
|
m_defaultProjectInfo.qtVersionString = QLibraryInfo::version().toString();
|
||||||
|
|
||||||
updateImportPaths();
|
updateImportPaths();
|
||||||
@@ -1217,16 +1217,14 @@ void ModelManagerInterface::updateImportPaths()
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const ProjectInfo &pInfo : qAsConst(m_projects)) {
|
for (const ProjectInfo &pInfo : qAsConst(m_projects)) {
|
||||||
if (!pInfo.qtQmlPath.isEmpty()) {
|
if (!pInfo.qtQmlPath.isEmpty())
|
||||||
allImportPaths.maybeInsert(Utils::FilePath::fromString(pInfo.qtQmlPath),
|
allImportPaths.maybeInsert(pInfo.qtQmlPath, Dialect::QmlQtQuick2);
|
||||||
Dialect::QmlQtQuick2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const QString pathAtt = defaultProjectInfo().qtQmlPath;
|
const FilePath pathAtt = defaultProjectInfo().qtQmlPath;
|
||||||
if (!pathAtt.isEmpty())
|
if (!pathAtt.isEmpty())
|
||||||
allImportPaths.maybeInsert(Utils::FilePath::fromString(pathAtt), Dialect::QmlQtQuick2);
|
allImportPaths.maybeInsert(pathAtt, Dialect::QmlQtQuick2);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &importPath : defaultProjectInfo().importPaths) {
|
for (const auto &importPath : defaultProjectInfo().importPaths) {
|
||||||
@@ -1435,7 +1433,7 @@ LibraryInfo ModelManagerInterface::builtins(const Document::Ptr &doc) const
|
|||||||
{
|
{
|
||||||
const ProjectInfo info = projectInfoForPath(doc->fileName());
|
const ProjectInfo info = projectInfoForPath(doc->fileName());
|
||||||
if (!info.qtQmlPath.isEmpty())
|
if (!info.qtQmlPath.isEmpty())
|
||||||
return m_validSnapshot.libraryInfo(info.qtQmlPath);
|
return m_validSnapshot.libraryInfo(info.qtQmlPath.toString());
|
||||||
return LibraryInfo();
|
return LibraryInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1483,13 +1481,13 @@ ViewerContext ModelManagerInterface::getVContext(const ViewerContext &vCtx,
|
|||||||
switch (res.language.dialect()) {
|
switch (res.language.dialect()) {
|
||||||
case Dialect::AnyLanguage:
|
case Dialect::AnyLanguage:
|
||||||
case Dialect::Qml:
|
case Dialect::Qml:
|
||||||
maybeAddPath(res, info.qtQmlPath);
|
maybeAddPath(res, info.qtQmlPath.toString());
|
||||||
Q_FALLTHROUGH();
|
Q_FALLTHROUGH();
|
||||||
case Dialect::QmlQtQuick2:
|
case Dialect::QmlQtQuick2:
|
||||||
case Dialect::QmlQtQuick2Ui:
|
case Dialect::QmlQtQuick2Ui:
|
||||||
{
|
{
|
||||||
if (res.language == Dialect::QmlQtQuick2 || res.language == Dialect::QmlQtQuick2Ui)
|
if (res.language == Dialect::QmlQtQuick2 || res.language == Dialect::QmlQtQuick2Ui)
|
||||||
maybeAddPath(res, info.qtQmlPath);
|
maybeAddPath(res, info.qtQmlPath.toString());
|
||||||
|
|
||||||
QList<Dialect> languages = res.language.companionLanguages();
|
QList<Dialect> languages = res.language.companionLanguages();
|
||||||
auto addPathsOnLanguageMatch = [&](const PathsAndLanguages &importPaths) {
|
auto addPathsOnLanguageMatch = [&](const PathsAndLanguages &importPaths) {
|
||||||
@@ -1534,7 +1532,7 @@ ViewerContext ModelManagerInterface::getVContext(const ViewerContext &vCtx,
|
|||||||
for (const QString &path : qAsConst(defaultVCtx.paths))
|
for (const QString &path : qAsConst(defaultVCtx.paths))
|
||||||
maybeAddPath(res, path);
|
maybeAddPath(res, path);
|
||||||
if (res.language == Dialect::AnyLanguage || res.language == Dialect::Qml)
|
if (res.language == Dialect::AnyLanguage || res.language == Dialect::Qml)
|
||||||
maybeAddPath(res, info.qtQmlPath);
|
maybeAddPath(res, info.qtQmlPath.toString());
|
||||||
if (res.language == Dialect::AnyLanguage || res.language == Dialect::Qml
|
if (res.language == Dialect::AnyLanguage || res.language == Dialect::Qml
|
||||||
|| res.language == Dialect::QmlQtQuick2 || res.language == Dialect::QmlQtQuick2Ui) {
|
|| res.language == Dialect::QmlQtQuick2 || res.language == Dialect::QmlQtQuick2Ui) {
|
||||||
const auto environemntPaths = environmentImportPaths();
|
const auto environemntPaths = environmentImportPaths();
|
||||||
|
@@ -78,10 +78,10 @@ public:
|
|||||||
// whether trying to run qmldump makes sense
|
// whether trying to run qmldump makes sense
|
||||||
bool tryQmlDump = false;
|
bool tryQmlDump = false;
|
||||||
bool qmlDumpHasRelocatableFlag = true;
|
bool qmlDumpHasRelocatableFlag = true;
|
||||||
QString qmlDumpPath;
|
Utils::FilePath qmlDumpPath;
|
||||||
::Utils::Environment qmlDumpEnvironment;
|
Utils::Environment qmlDumpEnvironment;
|
||||||
|
|
||||||
QString qtQmlPath;
|
Utils::FilePath qtQmlPath;
|
||||||
QString qtVersionString;
|
QString qtVersionString;
|
||||||
QmlJS::QmlLanguageBundles activeBundle;
|
QmlJS::QmlLanguageBundles activeBundle;
|
||||||
QmlJS::QmlLanguageBundles extendedBundle;
|
QmlJS::QmlLanguageBundles extendedBundle;
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include <utils/filesystemwatcher.h>
|
#include <utils/filesystemwatcher.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@@ -41,7 +42,9 @@
|
|||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
using namespace LanguageUtils;
|
using namespace LanguageUtils;
|
||||||
using namespace QmlJS;
|
using namespace Utils;
|
||||||
|
|
||||||
|
namespace QmlJS {
|
||||||
|
|
||||||
PluginDumper::PluginDumper(ModelManagerInterface *modelManager)
|
PluginDumper::PluginDumper(ModelManagerInterface *modelManager)
|
||||||
: QObject(modelManager)
|
: QObject(modelManager)
|
||||||
@@ -86,29 +89,30 @@ void PluginDumper::onLoadBuiltinTypes(const QmlJS::ModelManagerInterface::Projec
|
|||||||
if (info.qmlDumpPath.isEmpty() || info.qtQmlPath.isEmpty())
|
if (info.qmlDumpPath.isEmpty() || info.qtQmlPath.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QString importsPath = QDir::cleanPath(info.qtQmlPath);
|
// FIXME: This doesn't work for non-local paths.
|
||||||
|
const QString importsPath = QDir::cleanPath(info.qtQmlPath.toString());
|
||||||
if (m_runningQmldumps.values().contains(importsPath))
|
if (m_runningQmldumps.values().contains(importsPath))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LibraryInfo builtinInfo;
|
LibraryInfo builtinInfo;
|
||||||
if (!force) {
|
if (!force) {
|
||||||
const Snapshot snapshot = m_modelManager->snapshot();
|
const Snapshot snapshot = m_modelManager->snapshot();
|
||||||
builtinInfo = snapshot.libraryInfo(info.qtQmlPath);
|
builtinInfo = snapshot.libraryInfo(info.qtQmlPath.toString());
|
||||||
if (builtinInfo.isValid())
|
if (builtinInfo.isValid())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
builtinInfo = LibraryInfo(LibraryInfo::Found);
|
builtinInfo = LibraryInfo(LibraryInfo::Found);
|
||||||
m_modelManager->updateLibraryInfo(info.qtQmlPath, builtinInfo);
|
m_modelManager->updateLibraryInfo(info.qtQmlPath.toString(), builtinInfo);
|
||||||
|
|
||||||
// prefer QTDIR/qml/builtins.qmltypes if available
|
// prefer QTDIR/qml/builtins.qmltypes if available
|
||||||
const QString builtinQmltypesPath = info.qtQmlPath + QLatin1String("/builtins.qmltypes");
|
const QString builtinQmltypesPath = info.qtQmlPath.toString() + QLatin1String("/builtins.qmltypes");
|
||||||
if (QFile::exists(builtinQmltypesPath)) {
|
if (QFile::exists(builtinQmltypesPath)) {
|
||||||
loadQmltypesFile(QStringList(builtinQmltypesPath), info.qtQmlPath, builtinInfo);
|
loadQmltypesFile(QStringList(builtinQmltypesPath), info.qtQmlPath.toString(), builtinInfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
runQmlDump(info, QStringList(QLatin1String("--builtins")), info.qtQmlPath);
|
runQmlDump(info, QStringList(QLatin1String("--builtins")), info.qtQmlPath);
|
||||||
m_qtToInfo.insert(info.qtQmlPath, info);
|
m_qtToInfo.insert(info.qtQmlPath.toString(), info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString makeAbsolute(const QString &path, const QString &base)
|
static QString makeAbsolute(const QString &path, const QString &base)
|
||||||
@@ -227,10 +231,10 @@ static void printParseWarnings(const QString &libraryPath, const QString &warnin
|
|||||||
"%2").arg(libraryPath, warning));
|
"%2").arg(libraryPath, warning));
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString qmlPluginDumpErrorMessage(QProcess *process)
|
static QString qmlPluginDumpErrorMessage(QtcProcess *process)
|
||||||
{
|
{
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
const QString binary = QDir::toNativeSeparators(process->program());
|
const QString binary = process->commandLine().executable().toUserOutput();
|
||||||
switch (process->error()) {
|
switch (process->error()) {
|
||||||
case QProcess::FailedToStart:
|
case QProcess::FailedToStart:
|
||||||
errorMessage = PluginDumper::tr("\"%1\" failed to start: %2").arg(binary, process->errorString());
|
errorMessage = PluginDumper::tr("\"%1\" failed to start: %2").arg(binary, process->errorString());
|
||||||
@@ -250,7 +254,7 @@ static QString qmlPluginDumpErrorMessage(QProcess *process)
|
|||||||
errorMessage = PluginDumper::tr("\"%1\" returned exit code %2.").arg(binary).arg(process->exitCode());
|
errorMessage = PluginDumper::tr("\"%1\" returned exit code %2.").arg(binary).arg(process->exitCode());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
errorMessage += QLatin1Char('\n') + PluginDumper::tr("Arguments: %1").arg(process->arguments().join(QLatin1Char(' ')));
|
errorMessage += '\n' + PluginDumper::tr("Arguments: %1").arg(process->commandLine().arguments());
|
||||||
if (process->error() != QProcess::FailedToStart) {
|
if (process->error() != QProcess::FailedToStart) {
|
||||||
const QString stdErr = QString::fromLocal8Bit(process->readAllStandardError());
|
const QString stdErr = QString::fromLocal8Bit(process->readAllStandardError());
|
||||||
if (!stdErr.isEmpty()) {
|
if (!stdErr.isEmpty()) {
|
||||||
@@ -261,11 +265,8 @@ static QString qmlPluginDumpErrorMessage(QProcess *process)
|
|||||||
return errorMessage;
|
return errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
|
void PluginDumper::qmlPluginTypeDumpDone(QtcProcess *process)
|
||||||
{
|
{
|
||||||
QProcess *process = qobject_cast<QProcess *>(sender());
|
|
||||||
if (!process)
|
|
||||||
return;
|
|
||||||
process->deleteLater();
|
process->deleteLater();
|
||||||
|
|
||||||
const QString libraryPath = m_runningQmldumps.take(process);
|
const QString libraryPath = m_runningQmldumps.take(process);
|
||||||
@@ -275,7 +276,7 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
|
|||||||
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
|
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
|
||||||
bool privatePlugin = libraryPath.endsWith(QLatin1String("private"));
|
bool privatePlugin = libraryPath.endsWith(QLatin1String("private"));
|
||||||
|
|
||||||
if (exitCode != 0) {
|
if (process->exitCode() != 0) {
|
||||||
const QString errorMessages = qmlPluginDumpErrorMessage(process);
|
const QString errorMessages = qmlPluginDumpErrorMessage(process);
|
||||||
if (!privatePlugin)
|
if (!privatePlugin)
|
||||||
ModelManagerInterface::writeWarning(qmldumpErrorMessage(libraryPath, errorMessages));
|
ModelManagerInterface::writeWarning(qmldumpErrorMessage(libraryPath, errorMessages));
|
||||||
@@ -333,11 +334,8 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginDumper::qmlPluginTypeDumpError(QProcess::ProcessError)
|
void PluginDumper::qmlPluginTypeDumpError(QtcProcess *process)
|
||||||
{
|
{
|
||||||
QProcess *process = qobject_cast<QProcess *>(sender());
|
|
||||||
if (!process)
|
|
||||||
return;
|
|
||||||
process->deleteLater();
|
process->deleteLater();
|
||||||
|
|
||||||
const QString libraryPath = m_runningQmldumps.take(process);
|
const QString libraryPath = m_runningQmldumps.take(process);
|
||||||
@@ -632,20 +630,17 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginDumper::runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info,
|
void PluginDumper::runQmlDump(const ModelManagerInterface::ProjectInfo &info,
|
||||||
const QStringList &arguments, const QString &importPath)
|
const QStringList &arguments, const FilePath &importPath)
|
||||||
{
|
{
|
||||||
QDir wd = QDir(importPath);
|
auto process = new QtcProcess(this);
|
||||||
wd.cdUp();
|
process->setEnvironment(info.qmlDumpEnvironment);
|
||||||
QProcess *process = new QProcess(this);
|
process->setWorkingDirectory(importPath);
|
||||||
process->setEnvironment(info.qmlDumpEnvironment.toStringList());
|
process->setCommand({info.qmlDumpPath, arguments});
|
||||||
QString workingDir = wd.canonicalPath();
|
connect(process, &QtcProcess::finished, this, [this, process] { qmlPluginTypeDumpDone(process); });
|
||||||
process->setWorkingDirectory(workingDir);
|
connect(process, &QtcProcess::errorOccurred, this, [this, process] { qmlPluginTypeDumpError(process); });
|
||||||
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
process->start();
|
||||||
this, &PluginDumper::qmlPluginTypeDumpDone);
|
m_runningQmldumps.insert(process, importPath.toString());
|
||||||
connect(process, &QProcess::errorOccurred, this, &PluginDumper::qmlPluginTypeDumpError);
|
|
||||||
process->start(info.qmlDumpPath, arguments);
|
|
||||||
m_runningQmldumps.insert(process, importPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginDumper::dump(const Plugin &plugin)
|
void PluginDumper::dump(const Plugin &plugin)
|
||||||
@@ -691,7 +686,7 @@ void PluginDumper::dump(const Plugin &plugin)
|
|||||||
args << plugin.importUri;
|
args << plugin.importUri;
|
||||||
args << plugin.importVersion;
|
args << plugin.importVersion;
|
||||||
args << (plugin.importPath.isEmpty() ? QLatin1String(".") : plugin.importPath);
|
args << (plugin.importPath.isEmpty() ? QLatin1String(".") : plugin.importPath);
|
||||||
runQmlDump(info, args, plugin.qmldirPath);
|
runQmlDump(info, args, FilePath::fromString(plugin.qmldirPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -792,3 +787,5 @@ QString PluginDumper::resolvePlugin(const QDir &qmldirPath, const QString &qmldi
|
|||||||
}
|
}
|
||||||
return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, validSuffixList, prefix);
|
return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, validSuffixList, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // QmlJS
|
||||||
|
@@ -27,9 +27,10 @@
|
|||||||
|
|
||||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||||
|
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QProcess>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QDir;
|
class QDir;
|
||||||
@@ -57,8 +58,8 @@ private:
|
|||||||
Q_INVOKABLE void onLoadPluginTypes(const QString &libraryPath, const QString &importPath,
|
Q_INVOKABLE void onLoadPluginTypes(const QString &libraryPath, const QString &importPath,
|
||||||
const QString &importUri, const QString &importVersion);
|
const QString &importUri, const QString &importVersion);
|
||||||
Q_INVOKABLE void dumpAllPlugins();
|
Q_INVOKABLE void dumpAllPlugins();
|
||||||
void qmlPluginTypeDumpDone(int exitCode);
|
void qmlPluginTypeDumpDone(Utils::QtcProcess *process);
|
||||||
void qmlPluginTypeDumpError(QProcess::ProcessError error);
|
void qmlPluginTypeDumpError(Utils::QtcProcess *process);
|
||||||
void pluginChanged(const QString &pluginLibrary);
|
void pluginChanged(const QString &pluginLibrary);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -87,7 +88,8 @@ private:
|
|||||||
QList<LanguageUtils::FakeMetaObject::ConstPtr> objects;
|
QList<LanguageUtils::FakeMetaObject::ConstPtr> objects;
|
||||||
};
|
};
|
||||||
|
|
||||||
void runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info, const QStringList &arguments, const QString &importPath);
|
void runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info, const QStringList &arguments,
|
||||||
|
const Utils::FilePath &importPath);
|
||||||
void dump(const Plugin &plugin);
|
void dump(const Plugin &plugin);
|
||||||
QFuture<QmlTypeDescription> loadQmlTypeDescription(const QStringList &path) const;
|
QFuture<QmlTypeDescription> loadQmlTypeDescription(const QStringList &path) const;
|
||||||
QString buildQmltypesPath(const QString &name) const;
|
QString buildQmltypesPath(const QString &name) const;
|
||||||
@@ -116,7 +118,7 @@ private:
|
|||||||
|
|
||||||
ModelManagerInterface *m_modelManager;
|
ModelManagerInterface *m_modelManager;
|
||||||
Utils::FileSystemWatcher *m_pluginWatcher;
|
Utils::FileSystemWatcher *m_pluginWatcher;
|
||||||
QHash<QProcess *, QString> m_runningQmldumps;
|
QHash<Utils::QtcProcess *, QString> m_runningQmldumps;
|
||||||
QList<Plugin> m_plugins;
|
QList<Plugin> m_plugins;
|
||||||
QHash<QString, int> m_libraryToPluginIndex;
|
QHash<QString, int> m_libraryToPluginIndex;
|
||||||
QHash<QString, QmlJS::ModelManagerInterface::ProjectInfo> m_qtToInfo;
|
QHash<QString, QmlJS::ModelManagerInterface::ProjectInfo> m_qtToInfo;
|
||||||
|
@@ -475,6 +475,12 @@ static ProcessInterface *newProcessInstance(QObject *parent, QtcProcess::Process
|
|||||||
class QtcProcessPrivate : public QObject
|
class QtcProcessPrivate : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum StartFailure {
|
||||||
|
NoFailure,
|
||||||
|
WrongFileNameFailure,
|
||||||
|
OtherFailure
|
||||||
|
};
|
||||||
|
|
||||||
explicit QtcProcessPrivate(QtcProcess *parent,
|
explicit QtcProcessPrivate(QtcProcess *parent,
|
||||||
QtcProcess::ProcessImpl processImpl,
|
QtcProcess::ProcessImpl processImpl,
|
||||||
ProcessMode processMode)
|
ProcessMode processMode)
|
||||||
@@ -488,13 +494,11 @@ public:
|
|||||||
connect(m_process, &ProcessInterface::finished,
|
connect(m_process, &ProcessInterface::finished,
|
||||||
this, &QtcProcessPrivate::slotFinished);
|
this, &QtcProcessPrivate::slotFinished);
|
||||||
connect(m_process, &ProcessInterface::errorOccurred,
|
connect(m_process, &ProcessInterface::errorOccurred,
|
||||||
this, &QtcProcessPrivate::slotError);
|
this, [this](QProcess::ProcessError error) { handleError(error, OtherFailure); });
|
||||||
connect(m_process, &ProcessInterface::readyReadStandardOutput,
|
connect(m_process, &ProcessInterface::readyReadStandardOutput,
|
||||||
this, &QtcProcessPrivate::handleReadyReadStandardOutput);
|
this, &QtcProcessPrivate::handleReadyReadStandardOutput);
|
||||||
connect(m_process, &ProcessInterface::readyReadStandardError,
|
connect(m_process, &ProcessInterface::readyReadStandardError,
|
||||||
this, &QtcProcessPrivate::handleReadyReadStandardError);
|
this, &QtcProcessPrivate::handleReadyReadStandardError);
|
||||||
connect(&m_timer, &QTimer::timeout, this, &QtcProcessPrivate::slotTimeout);
|
|
||||||
m_timer.setInterval(1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleReadyReadStandardOutput()
|
void handleReadyReadStandardOutput()
|
||||||
@@ -530,7 +534,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
m_process->setErrorString(QLatin1String(
|
m_process->setErrorString(QLatin1String(
|
||||||
"The program \"%1\" does not exist or is not executable.").arg(program));
|
"The program \"%1\" does not exist or is not executable.").arg(program));
|
||||||
slotError(QProcess::FailedToStart);
|
handleError(QProcess::FailedToStart, WrongFileNameFailure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,14 +550,13 @@ public:
|
|||||||
|
|
||||||
void slotTimeout();
|
void slotTimeout();
|
||||||
void slotFinished(int exitCode, QProcess::ExitStatus e);
|
void slotFinished(int exitCode, QProcess::ExitStatus e);
|
||||||
void slotError(QProcess::ProcessError);
|
void handleError(QProcess::ProcessError error, StartFailure startFailure);
|
||||||
void clearForRun();
|
void clearForRun();
|
||||||
|
|
||||||
QtcProcess::Result interpretExitCode(int exitCode);
|
QtcProcess::Result interpretExitCode(int exitCode);
|
||||||
|
|
||||||
QTextCodec *m_codec = QTextCodec::codecForLocale();
|
QTextCodec *m_codec = QTextCodec::codecForLocale();
|
||||||
QTimer m_timer;
|
QEventLoop *m_eventLoop = nullptr;
|
||||||
QEventLoop m_eventLoop;
|
|
||||||
QtcProcess::Result m_result = QtcProcess::StartFailed;
|
QtcProcess::Result m_result = QtcProcess::StartFailed;
|
||||||
QProcess::ExitStatus m_exitStatus = QProcess::NormalExit;
|
QProcess::ExitStatus m_exitStatus = QProcess::NormalExit;
|
||||||
ChannelBuffer m_stdOut;
|
ChannelBuffer m_stdOut;
|
||||||
@@ -562,7 +565,7 @@ public:
|
|||||||
|
|
||||||
int m_hangTimerCount = 0;
|
int m_hangTimerCount = 0;
|
||||||
int m_maxHangTimerCount = defaultMaxHangTimerCount;
|
int m_maxHangTimerCount = defaultMaxHangTimerCount;
|
||||||
bool m_startFailure = false;
|
StartFailure m_startFailure = NoFailure;
|
||||||
bool m_timeOutMessageBoxEnabled = false;
|
bool m_timeOutMessageBoxEnabled = false;
|
||||||
bool m_waitingForUser = false;
|
bool m_waitingForUser = false;
|
||||||
bool m_processUserEvents = false;
|
bool m_processUserEvents = false;
|
||||||
@@ -576,7 +579,7 @@ void QtcProcessPrivate::clearForRun()
|
|||||||
m_stdErr.clearForRun();
|
m_stdErr.clearForRun();
|
||||||
m_stdErr.codec = m_codec;
|
m_stdErr.codec = m_codec;
|
||||||
m_result = QtcProcess::StartFailed;
|
m_result = QtcProcess::StartFailed;
|
||||||
m_startFailure = false;
|
m_startFailure = NoFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
QtcProcess::Result QtcProcessPrivate::interpretExitCode(int exitCode)
|
QtcProcess::Result QtcProcessPrivate::interpretExitCode(int exitCode)
|
||||||
@@ -963,7 +966,7 @@ void QtcProcess::setResult(Result result)
|
|||||||
|
|
||||||
int QtcProcess::exitCode() const
|
int QtcProcess::exitCode() const
|
||||||
{
|
{
|
||||||
if (d->m_startFailure)
|
if (d->m_startFailure == QtcProcessPrivate::WrongFileNameFailure)
|
||||||
return 255; // This code is being returned by QProcess when FailedToStart error occurred
|
return 255; // This code is being returned by QProcess when FailedToStart error occurred
|
||||||
return d->m_process->exitCode();
|
return d->m_process->exitCode();
|
||||||
}
|
}
|
||||||
@@ -1065,7 +1068,7 @@ void QtcProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode)
|
|||||||
|
|
||||||
QProcess::ProcessError QtcProcess::error() const
|
QProcess::ProcessError QtcProcess::error() const
|
||||||
{
|
{
|
||||||
if (d->m_startFailure)
|
if (d->m_startFailure == QtcProcessPrivate::WrongFileNameFailure)
|
||||||
return QProcess::FailedToStart;
|
return QProcess::FailedToStart;
|
||||||
return d->m_process->error();
|
return d->m_process->error();
|
||||||
}
|
}
|
||||||
@@ -1407,17 +1410,24 @@ void QtcProcess::runBlocking()
|
|||||||
// On Windows, start failure is triggered immediately if the
|
// On Windows, start failure is triggered immediately if the
|
||||||
// executable cannot be found in the path. Do not start the
|
// executable cannot be found in the path. Do not start the
|
||||||
// event loop in that case.
|
// event loop in that case.
|
||||||
if (!d->m_startFailure) {
|
if (d->m_startFailure == QtcProcessPrivate::NoFailure) {
|
||||||
d->m_timer.start();
|
QTimer timer(this);
|
||||||
|
connect(&timer, &QTimer::timeout, d, &QtcProcessPrivate::slotTimeout);
|
||||||
|
timer.setInterval(1000);
|
||||||
|
timer.start();
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
if (isGuiThread())
|
if (isGuiThread())
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
#endif
|
#endif
|
||||||
d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
|
QEventLoop eventLoop(this);
|
||||||
|
QTC_ASSERT(!d->m_eventLoop, return);
|
||||||
|
d->m_eventLoop = &eventLoop;
|
||||||
|
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
d->m_eventLoop = nullptr;
|
||||||
d->m_stdOut.append(d->m_process->readAllStandardOutput());
|
d->m_stdOut.append(d->m_process->readAllStandardOutput());
|
||||||
d->m_stdErr.append(d->m_process->readAllStandardError());
|
d->m_stdErr.append(d->m_process->readAllStandardError());
|
||||||
|
|
||||||
d->m_timer.stop();
|
timer.stop();
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
if (isGuiThread())
|
if (isGuiThread())
|
||||||
QApplication::restoreOverrideCursor();
|
QApplication::restoreOverrideCursor();
|
||||||
@@ -1510,7 +1520,8 @@ void QtcProcessPrivate::slotFinished(int exitCode, QProcess::ExitStatus status)
|
|||||||
m_result = QtcProcess::TerminatedAbnormally;
|
m_result = QtcProcess::TerminatedAbnormally;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m_eventLoop.quit();
|
if (m_eventLoop)
|
||||||
|
m_eventLoop->quit();
|
||||||
|
|
||||||
m_stdOut.handleRest();
|
m_stdOut.handleRest();
|
||||||
m_stdErr.handleRest();
|
m_stdErr.handleRest();
|
||||||
@@ -1518,7 +1529,7 @@ void QtcProcessPrivate::slotFinished(int exitCode, QProcess::ExitStatus status)
|
|||||||
emit q->finished();
|
emit q->finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcessPrivate::slotError(QProcess::ProcessError error)
|
void QtcProcessPrivate::handleError(QProcess::ProcessError error, StartFailure startFailure)
|
||||||
{
|
{
|
||||||
m_hangTimerCount = 0;
|
m_hangTimerCount = 0;
|
||||||
if (debug)
|
if (debug)
|
||||||
@@ -1526,8 +1537,9 @@ void QtcProcessPrivate::slotError(QProcess::ProcessError error)
|
|||||||
// Was hang detected before and killed?
|
// Was hang detected before and killed?
|
||||||
if (m_result != QtcProcess::Hang)
|
if (m_result != QtcProcess::Hang)
|
||||||
m_result = QtcProcess::StartFailed;
|
m_result = QtcProcess::StartFailed;
|
||||||
m_startFailure = true;
|
m_startFailure = startFailure;
|
||||||
m_eventLoop.quit();
|
if (m_eventLoop)
|
||||||
|
m_eventLoop->quit();
|
||||||
|
|
||||||
emit q->errorOccurred(error);
|
emit q->errorOccurred(error);
|
||||||
}
|
}
|
||||||
|
@@ -67,6 +67,28 @@ void setThemeApplicationPalette()
|
|||||||
QApplication::setPalette(m_creatorTheme->palette());
|
QApplication::setPalette(m_creatorTheme->palette());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void maybeForceMacOSLight(Theme *theme)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
// Match the native UI theme and palette with the creator
|
||||||
|
// theme by forcing light aqua for light creator themes.
|
||||||
|
if (theme && !theme->flag(Theme::DarkUserInterface))
|
||||||
|
Internal::forceMacOSLightAquaApperance();
|
||||||
|
#else
|
||||||
|
Q_UNUSED(theme)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool macOSSystemIsDark()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
static bool systemIsDark = Internal::currentAppearanceIsDark();
|
||||||
|
return systemIsDark;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void setCreatorTheme(Theme *theme)
|
void setCreatorTheme(Theme *theme)
|
||||||
{
|
{
|
||||||
if (m_creatorTheme == theme)
|
if (m_creatorTheme == theme)
|
||||||
@@ -74,13 +96,7 @@ void setCreatorTheme(Theme *theme)
|
|||||||
delete m_creatorTheme;
|
delete m_creatorTheme;
|
||||||
m_creatorTheme = theme;
|
m_creatorTheme = theme;
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
maybeForceMacOSLight(theme);
|
||||||
// Match the native UI theme and palette with the creator
|
|
||||||
// theme by forcing light aqua for light creator themes.
|
|
||||||
if (theme && !theme->flag(Theme::DarkUserInterface))
|
|
||||||
Internal::forceMacOSLightAquaApperance();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
setThemeApplicationPalette();
|
setThemeApplicationPalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,6 +267,8 @@ bool Theme::systemUsesDarkMode()
|
|||||||
bool ok;
|
bool ok;
|
||||||
const auto setting = QSettings(regkey, QSettings::NativeFormat).value("AppsUseLightTheme").toInt(&ok);
|
const auto setting = QSettings(regkey, QSettings::NativeFormat).value("AppsUseLightTheme").toInt(&ok);
|
||||||
return ok && setting == 0;
|
return ok && setting == 0;
|
||||||
|
} else if (HostOsInfo::isMacHost()) {
|
||||||
|
return macOSSystemIsDark();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -270,6 +288,13 @@ static QPalette copyPalette(const QPalette &p)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Theme::setInitialPalette(Theme *initTheme)
|
||||||
|
{
|
||||||
|
macOSSystemIsDark(); // initialize value for system mode
|
||||||
|
maybeForceMacOSLight(initTheme);
|
||||||
|
initialPalette();
|
||||||
|
}
|
||||||
|
|
||||||
QPalette Theme::initialPalette()
|
QPalette Theme::initialPalette()
|
||||||
{
|
{
|
||||||
static QPalette palette = copyPalette(QApplication::palette());
|
static QPalette palette = copyPalette(QApplication::palette());
|
||||||
|
@@ -485,6 +485,8 @@ public:
|
|||||||
static bool systemUsesDarkMode();
|
static bool systemUsesDarkMode();
|
||||||
static QPalette initialPalette();
|
static QPalette initialPalette();
|
||||||
|
|
||||||
|
static void setInitialPalette(Theme *initTheme);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Theme(Theme *originTheme, QObject *parent = nullptr);
|
Theme(Theme *originTheme, QObject *parent = nullptr);
|
||||||
ThemePrivate *d;
|
ThemePrivate *d;
|
||||||
|
@@ -29,6 +29,7 @@ namespace Utils {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
void forceMacOSLightAquaApperance();
|
void forceMacOSLightAquaApperance();
|
||||||
|
bool currentAppearanceIsDark();
|
||||||
|
|
||||||
} // Internal
|
} // Internal
|
||||||
} // Utils
|
} // Utils
|
||||||
|
@@ -49,5 +49,17 @@ void forceMacOSLightAquaApperance()
|
|||||||
NSApp.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
|
NSApp.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool currentAppearanceIsDark()
|
||||||
|
{
|
||||||
|
#if __has_builtin(__builtin_available)
|
||||||
|
if (__builtin_available(macOS 10.14, *)) {
|
||||||
|
auto appearance = [NSApp.effectiveAppearance
|
||||||
|
bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]];
|
||||||
|
return [appearance isEqualToString:NSAppearanceNameDarkAqua];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // Internal
|
} // Internal
|
||||||
} // Utils
|
} // Utils
|
||||||
|
@@ -423,7 +423,7 @@ void AndroidBuildApkWidget::onOpenSslCheckBoxChanged()
|
|||||||
Utils::FilePath projectPath = m_step->buildConfiguration()->buildSystem()->projectFilePath();
|
Utils::FilePath projectPath = m_step->buildConfiguration()->buildSystem()->projectFilePath();
|
||||||
QFile projectFile(projectPath.toString());
|
QFile projectFile(projectPath.toString());
|
||||||
if (!projectFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
if (!projectFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
||||||
qWarning() << "Cound't open project file to add OpenSSL extra libs: " << projectPath;
|
qWarning() << "Cannot open project file to add OpenSSL extra libs: " << projectPath;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,27 +494,31 @@ AndroidBuildApkStep::AndroidBuildApkStep(BuildStepList *parent, Utils::Id id)
|
|||||||
|
|
||||||
bool AndroidBuildApkStep::init()
|
bool AndroidBuildApkStep::init()
|
||||||
{
|
{
|
||||||
if (!AbstractProcessStep::init())
|
if (!AbstractProcessStep::init()) {
|
||||||
|
reportWarningOrError(tr("\"%1\" step failed initialization.").arg(displayName()),
|
||||||
|
Task::Error);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_signPackage) {
|
if (m_signPackage) {
|
||||||
qCDebug(buildapkstepLog) << "Signing enabled";
|
qCDebug(buildapkstepLog) << "Signing enabled";
|
||||||
// check keystore and certificate passwords
|
// check keystore and certificate passwords
|
||||||
if (!verifyKeystorePassword() || !verifyCertificatePassword()) {
|
if (!verifyKeystorePassword() || !verifyCertificatePassword()) {
|
||||||
qCDebug(buildapkstepLog) << "Init failed. Keystore/Certificate password verification failed.";
|
reportWarningOrError(tr("Keystore/Certificate password verification failed."),
|
||||||
|
Task::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buildType() != BuildConfiguration::Release) {
|
if (buildType() != BuildConfiguration::Release)
|
||||||
const QString error = tr("Warning: Signing a debug or profile package.");
|
reportWarningOrError(tr("Warning: Signing a debug or profile package."), Task::Warning);
|
||||||
emit addOutput(error, OutputFormat::ErrorMessage);
|
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Warning, error));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit());
|
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit());
|
||||||
if (!version)
|
if (!version) {
|
||||||
|
reportWarningOrError(tr("The Qt version for kit %1 is invalid.").arg(kit()->displayName()),
|
||||||
|
Task::Error);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const QVersionNumber sdkToolsVersion = AndroidConfigurations::currentConfig().sdkToolsVersion();
|
const QVersionNumber sdkToolsVersion = AndroidConfigurations::currentConfig().sdkToolsVersion();
|
||||||
if (sdkToolsVersion >= QVersionNumber(25, 3, 0)
|
if (sdkToolsVersion >= QVersionNumber(25, 3, 0)
|
||||||
@@ -526,16 +530,14 @@ bool AndroidBuildApkStep::init()
|
|||||||
"is %2")
|
"is %2")
|
||||||
.arg(sdkToolsVersion.toString())
|
.arg(sdkToolsVersion.toString())
|
||||||
.arg("5.9.0/5.6.3");
|
.arg("5.9.0/5.6.3");
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
reportWarningOrError(error, Task::Error);
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (version->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) {
|
} else if (version->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) {
|
||||||
const QString error = tr("The minimum Qt version required for Gradle build to work is %1. "
|
const QString error = tr("The minimum Qt version required for Gradle build to work is %1. "
|
||||||
"It is recommended to install the latest Qt version.")
|
"It is recommended to install the latest Qt version.")
|
||||||
.arg("5.4.0");
|
.arg("5.4.0");
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
reportWarningOrError(error, Task::Error);
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,8 +547,7 @@ bool AndroidBuildApkStep::init()
|
|||||||
= tr("The API level set for the APK is less than the minimum required by the kit."
|
= tr("The API level set for the APK is less than the minimum required by the kit."
|
||||||
"\nThe minimum API level required by the kit is %1.")
|
"\nThe minimum API level required by the kit is %1.")
|
||||||
.arg(minSDKForKit);
|
.arg(minSDKForKit);
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
reportWarningOrError(error, Task::Error);
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,16 +569,16 @@ bool AndroidBuildApkStep::init()
|
|||||||
|
|
||||||
m_inputFile = AndroidQtVersion::androidDeploymentSettings(target());
|
m_inputFile = AndroidQtVersion::androidDeploymentSettings(target());
|
||||||
if (m_inputFile.isEmpty()) {
|
if (m_inputFile.isEmpty()) {
|
||||||
qCDebug(buildapkstepLog) << "no input file" << target()->activeBuildKey();
|
|
||||||
m_skipBuilding = true;
|
m_skipBuilding = true;
|
||||||
|
reportWarningOrError(tr("No valid input file for \"%1\".").arg(target()->activeBuildKey()),
|
||||||
|
Task::Warning);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
m_skipBuilding = false;
|
m_skipBuilding = false;
|
||||||
|
|
||||||
if (m_buildTargetSdk.isEmpty()) {
|
if (m_buildTargetSdk.isEmpty()) {
|
||||||
const QString error = tr("Android build SDK not defined. Check Android settings.");
|
reportWarningOrError(tr("Android build SDK version is not defined. Check Android settings.")
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
, Task::Error);
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,10 +666,8 @@ void AndroidBuildApkStep::processFinished(int exitCode, QProcess::ExitStatus sta
|
|||||||
bool AndroidBuildApkStep::verifyKeystorePassword()
|
bool AndroidBuildApkStep::verifyKeystorePassword()
|
||||||
{
|
{
|
||||||
if (!m_keystorePath.exists()) {
|
if (!m_keystorePath.exists()) {
|
||||||
const QString error = tr("Cannot sign the package. Invalid keystore path (%1).")
|
reportWarningOrError(tr("Cannot sign the package. Invalid keystore path (%1).")
|
||||||
.arg(m_keystorePath.toString());
|
.arg(m_keystorePath.toString()), Task::Error);
|
||||||
emit addOutput(error, OutputFormat::ErrorMessage);
|
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,10 +686,8 @@ bool AndroidBuildApkStep::verifyCertificatePassword()
|
|||||||
{
|
{
|
||||||
if (!AndroidManager::checkCertificateExists(m_keystorePath.toString(), m_keystorePasswd,
|
if (!AndroidManager::checkCertificateExists(m_keystorePath.toString(), m_keystorePasswd,
|
||||||
m_certificateAlias)) {
|
m_certificateAlias)) {
|
||||||
const QString error = tr("Cannot sign the package. Certificate alias %1 does not exist.")
|
reportWarningOrError(tr("Cannot sign the package. Certificate alias %1 does not exist.")
|
||||||
.arg(m_certificateAlias);
|
.arg(m_certificateAlias), Task::Error);
|
||||||
emit addOutput(error, OutputFormat::ErrorMessage);
|
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,9 +728,8 @@ static bool copyFileIfNewer(const FilePath &sourceFilePath,
|
|||||||
void AndroidBuildApkStep::doRun()
|
void AndroidBuildApkStep::doRun()
|
||||||
{
|
{
|
||||||
if (m_skipBuilding) {
|
if (m_skipBuilding) {
|
||||||
const QString error = tr("Android deploy settings file not found, not building an APK.");
|
reportWarningOrError(tr("Android deploy settings file not found, not building an APK."),
|
||||||
emit addOutput(error, BuildStep::OutputFormat::ErrorMessage);
|
Task::Error);
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Error, error));
|
|
||||||
emit finished(true);
|
emit finished(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -743,8 +739,11 @@ void AndroidBuildApkStep::doRun()
|
|||||||
const QString buildKey = target()->activeBuildKey();
|
const QString buildKey = target()->activeBuildKey();
|
||||||
|
|
||||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit());
|
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit());
|
||||||
if (!version)
|
if (!version) {
|
||||||
|
reportWarningOrError(tr("The Qt version for kit %1 is invalid.")
|
||||||
|
.arg(kit()->displayName()), Task::Error);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const FilePath buildDir = buildDirectory();
|
const FilePath buildDir = buildDirectory();
|
||||||
const FilePath androidBuildDir = AndroidManager::androidBuildDirectory(target());
|
const FilePath androidBuildDir = AndroidManager::androidBuildDirectory(target());
|
||||||
@@ -752,10 +751,9 @@ void AndroidBuildApkStep::doRun()
|
|||||||
FilePath androidLibsDir = androidBuildDir / "libs" / abi;
|
FilePath androidLibsDir = androidBuildDir / "libs" / abi;
|
||||||
if (!androidLibsDir.exists()) {
|
if (!androidLibsDir.exists()) {
|
||||||
if (!androidLibsDir.ensureWritableDir()) {
|
if (!androidLibsDir.ensureWritableDir()) {
|
||||||
const QString error = tr("The Android build folder %1 wasn't found and "
|
reportWarningOrError(tr("The Android build folder %1 was not found and could "
|
||||||
"couldn't be created.").arg(androidLibsDir.toUserOutput());
|
"not be created.").arg(androidLibsDir.toUserOutput()),
|
||||||
emit addOutput(error, BuildStep::OutputFormat::ErrorMessage);
|
Task::Error);
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
} else if (version->qtVersion() >= QtSupport::QtVersionNumber{6, 0, 0}
|
} else if (version->qtVersion() >= QtSupport::QtVersionNumber{6, 0, 0}
|
||||||
&& version->qtVersion() <= QtSupport::QtVersionNumber{6, 1, 1}) {
|
&& version->qtVersion() <= QtSupport::QtVersionNumber{6, 1, 1}) {
|
||||||
@@ -769,11 +767,10 @@ void AndroidBuildApkStep::doRun()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!from.copyFile(to)) {
|
if (!from.copyFile(to)) {
|
||||||
const QString error = tr("Couldn't copy the target's lib file %1 to the "
|
reportWarningOrError(tr("Cannot copy the target's lib file %1 to the "
|
||||||
"Android build folder %2.")
|
"Android build folder %2.")
|
||||||
.arg(fileName, androidLibsDir.toUserOutput());
|
.arg(fileName, androidLibsDir.toUserOutput()),
|
||||||
emit addOutput(error, BuildStep::OutputFormat::ErrorMessage);
|
Task::Error);
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -799,9 +796,14 @@ void AndroidBuildApkStep::doRun()
|
|||||||
applicationBinary = buildSystem()->buildTarget(buildKey).targetFilePath.toString();
|
applicationBinary = buildSystem()->buildTarget(buildKey).targetFilePath.toString();
|
||||||
FilePath androidLibsDir = androidBuildDir / "libs" / androidAbis.first();
|
FilePath androidLibsDir = androidBuildDir / "libs" / androidAbis.first();
|
||||||
for (const FilePath &target : targets) {
|
for (const FilePath &target : targets) {
|
||||||
if (!copyFileIfNewer(target, androidLibsDir.pathAppended(target.fileName())))
|
if (!copyFileIfNewer(target, androidLibsDir.pathAppended(target.fileName()))) {
|
||||||
|
reportWarningOrError(
|
||||||
|
tr("Cannot copy file \"%1\" to Android build libs folder \"%2\".")
|
||||||
|
.arg(target.toUserOutput()).arg(androidLibsDir.toUserOutput()),
|
||||||
|
Task::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
deploySettings["target-architecture"] = androidAbis.first();
|
deploySettings["target-architecture"] = androidAbis.first();
|
||||||
} else {
|
} else {
|
||||||
applicationBinary = buildSystem()->buildTarget(buildKey).targetFilePath.fileName();
|
applicationBinary = buildSystem()->buildTarget(buildKey).targetFilePath.fileName();
|
||||||
@@ -818,8 +820,14 @@ void AndroidBuildApkStep::doRun()
|
|||||||
FilePath androidLibsDir = androidBuildDir / "libs" / abi;
|
FilePath androidLibsDir = androidBuildDir / "libs" / abi;
|
||||||
for (const FilePath &target : targets) {
|
for (const FilePath &target : targets) {
|
||||||
if (target.endsWith(targetSuffix)) {
|
if (target.endsWith(targetSuffix)) {
|
||||||
if (!copyFileIfNewer(target, androidLibsDir.pathAppended(target.fileName())))
|
const FilePath destination = androidLibsDir.pathAppended(target.fileName());
|
||||||
|
if (!copyFileIfNewer(target, destination)) {
|
||||||
|
reportWarningOrError(
|
||||||
|
tr("Cannot copy file \"%1\" to Android build libs folder \"%2\".")
|
||||||
|
.arg(target.toUserOutput()).arg(androidLibsDir.toUserOutput()),
|
||||||
|
Task::Error);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
architectures[abi] = AndroidManager::archTriplet(abi);
|
architectures[abi] = AndroidManager::archTriplet(abi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -846,16 +854,18 @@ void AndroidBuildApkStep::doRun()
|
|||||||
deploySettings["qml-root-path"] = qmlRootPath;
|
deploySettings["qml-root-path"] = qmlRootPath;
|
||||||
|
|
||||||
QFile f{m_inputFile.toString()};
|
QFile f{m_inputFile.toString()};
|
||||||
if (!f.open(QIODevice::WriteOnly))
|
if (!f.open(QIODevice::WriteOnly)) {
|
||||||
|
reportWarningOrError(tr("Cannot open androiddeployqt input file \"%1\" for writing.")
|
||||||
|
.arg(m_inputFile.toUserOutput()), Task::Error);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
f.write(QJsonDocument{deploySettings}.toJson());
|
f.write(QJsonDocument{deploySettings}.toJson());
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!setup()) {
|
if (!setup()) {
|
||||||
const QString error = tr("Cannot set up Android, not building an APK.");
|
reportWarningOrError(tr("Cannot set up \"%1\", not building an APK.").arg(displayName()),
|
||||||
emit addOutput(error, BuildStep::OutputFormat::ErrorMessage);
|
Task::Error);
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Error, error));
|
|
||||||
emit finished(false);
|
emit finished(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -863,6 +873,13 @@ void AndroidBuildApkStep::doRun()
|
|||||||
AbstractProcessStep::doRun();
|
AbstractProcessStep::doRun();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AndroidBuildApkStep::reportWarningOrError(const QString &message, Task::TaskType type)
|
||||||
|
{
|
||||||
|
qCDebug(buildapkstepLog) << message;
|
||||||
|
emit addOutput(message, OutputFormat::ErrorMessage);
|
||||||
|
TaskHub::addTask(BuildSystemTask(type, message));
|
||||||
|
}
|
||||||
|
|
||||||
void AndroidBuildApkStep::processStarted()
|
void AndroidBuildApkStep::processStarted()
|
||||||
{
|
{
|
||||||
emit addOutput(tr("Starting: \"%1\" %2")
|
emit addOutput(tr("Starting: \"%1\" %2")
|
||||||
|
@@ -92,6 +92,8 @@ private:
|
|||||||
|
|
||||||
void doRun() override;
|
void doRun() override;
|
||||||
|
|
||||||
|
void reportWarningOrError(const QString &message, ProjectExplorer::Task::TaskType type);
|
||||||
|
|
||||||
bool m_buildAAB = false;
|
bool m_buildAAB = false;
|
||||||
bool m_signPackage = false;
|
bool m_signPackage = false;
|
||||||
bool m_verbose = false;
|
bool m_verbose = false;
|
||||||
|
@@ -1408,7 +1408,7 @@ Environment AndroidConfigurations::toolsEnvironment(const AndroidConfig &config)
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AndroidConfig &AndroidConfigurations::currentConfig()
|
AndroidConfig &AndroidConfigurations::currentConfig()
|
||||||
{
|
{
|
||||||
return m_instance->m_config; // ensure that m_instance is initialized
|
return m_instance->m_config; // ensure that m_instance is initialized
|
||||||
}
|
}
|
||||||
|
@@ -211,7 +211,7 @@ class ANDROID_EXPORT AndroidConfigurations : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const AndroidConfig ¤tConfig();
|
static AndroidConfig ¤tConfig();
|
||||||
static Internal::AndroidSdkManager *sdkManager();
|
static Internal::AndroidSdkManager *sdkManager();
|
||||||
static void setConfig(const AndroidConfig &config);
|
static void setConfig(const AndroidConfig &config);
|
||||||
static AndroidConfigurations *instance();
|
static AndroidConfigurations *instance();
|
||||||
|
@@ -112,9 +112,8 @@ bool AndroidDeployQtStep::init()
|
|||||||
{
|
{
|
||||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit());
|
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit());
|
||||||
if (!version) {
|
if (!version) {
|
||||||
qCDebug(deployStepLog,
|
reportWarningOrError(tr("The Qt version for kit %1 is invalid.").arg(kit()->displayName()),
|
||||||
"The Qt version for kit %s is not valid.",
|
Task::Error);
|
||||||
qPrintable(kit()->displayName()));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,18 +121,21 @@ bool AndroidDeployQtStep::init()
|
|||||||
|
|
||||||
m_androidABIs = AndroidManager::applicationAbis(target());
|
m_androidABIs = AndroidManager::applicationAbis(target());
|
||||||
if (m_androidABIs.isEmpty()) {
|
if (m_androidABIs.isEmpty()) {
|
||||||
const QString error = tr("No Android arch set by the .pro file.");
|
reportWarningOrError(tr("No Android architecture (ABI) is set by the project."),
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
Task::Error);
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit addOutput(tr("Initializing deployment to Android device/simulator"), OutputFormat::Stdout);
|
emit addOutput(tr("Initializing deployment to Android device/simulator"),
|
||||||
|
OutputFormat::NormalMessage);
|
||||||
|
|
||||||
RunConfiguration *rc = target()->activeRunConfiguration();
|
RunConfiguration *rc = target()->activeRunConfiguration();
|
||||||
QTC_ASSERT(rc, return false);
|
QTC_ASSERT(rc, reportWarningOrError(tr("The kit's run configuration is invalid."), Task::Error);
|
||||||
|
return false);
|
||||||
BuildConfiguration *bc = target()->activeBuildConfiguration();
|
BuildConfiguration *bc = target()->activeBuildConfiguration();
|
||||||
QTC_ASSERT(bc, return false);
|
QTC_ASSERT(bc, reportWarningOrError(tr("The kit's build configuration is invalid."),
|
||||||
|
Task::Error);
|
||||||
|
return false);
|
||||||
|
|
||||||
auto androidBuildApkStep = bc->buildSteps()->firstOfType<AndroidBuildApkStep>();
|
auto androidBuildApkStep = bc->buildSteps()->firstOfType<AndroidBuildApkStep>();
|
||||||
const int minTargetApi = AndroidManager::minimumSDK(target());
|
const int minTargetApi = AndroidManager::minimumSDK(target());
|
||||||
@@ -142,9 +144,12 @@ bool AndroidDeployQtStep::init()
|
|||||||
|
|
||||||
// Try to re-use user-provided information from an earlier step of the same type.
|
// Try to re-use user-provided information from an earlier step of the same type.
|
||||||
BuildStepList *bsl = stepList();
|
BuildStepList *bsl = stepList();
|
||||||
QTC_ASSERT(bsl, return false);
|
QTC_ASSERT(bsl, reportWarningOrError(tr("The kit's build steps list is invalid."), Task::Error);
|
||||||
|
return false);
|
||||||
auto androidDeployQtStep = bsl->firstOfType<AndroidDeployQtStep>();
|
auto androidDeployQtStep = bsl->firstOfType<AndroidDeployQtStep>();
|
||||||
QTC_ASSERT(androidDeployQtStep, return false);
|
QTC_ASSERT(androidDeployQtStep,
|
||||||
|
reportWarningOrError(tr("The kit's deploy configuration is invalid."), Task::Error);
|
||||||
|
return false);
|
||||||
AndroidDeviceInfo info;
|
AndroidDeviceInfo info;
|
||||||
if (androidDeployQtStep != this)
|
if (androidDeployQtStep != this)
|
||||||
info = androidDeployQtStep->m_deviceInfo;
|
info = androidDeployQtStep->m_deviceInfo;
|
||||||
@@ -159,44 +164,44 @@ bool AndroidDeployQtStep::init()
|
|||||||
if (selectedAbis.isEmpty())
|
if (selectedAbis.isEmpty())
|
||||||
selectedAbis.append(bs->extraData(buildKey, Constants::AndroidAbi).toString());
|
selectedAbis.append(bs->extraData(buildKey, Constants::AndroidAbi).toString());
|
||||||
|
|
||||||
|
// TODO: use AndroidDevice directly instead of AndroidDeviceInfo.
|
||||||
if (!info.isValid()) {
|
if (!info.isValid()) {
|
||||||
const IDevice *dev = DeviceKitAspect::device(kit()).data();
|
const IDevice *dev = DeviceKitAspect::device(kit()).data();
|
||||||
|
if (!dev) {
|
||||||
|
reportWarningOrError(tr("The deployment device \"%1\" is invalid."), Task::Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
info = AndroidDevice::androidDeviceInfoFromIDevice(dev);
|
info = AndroidDevice::androidDeviceInfoFromIDevice(dev);
|
||||||
m_deviceInfo = info; // Keep around for later steps
|
m_deviceInfo = info; // Keep around for later steps
|
||||||
|
|
||||||
if (!info.isValid()) {
|
if (!info.isValid()) {
|
||||||
const QString error = tr("The deployment device \"%1\" is invalid.")
|
reportWarningOrError(tr("The deployment device \"%1\" is invalid.")
|
||||||
.arg(dev->displayName());
|
.arg(dev->displayName()), Task::Error);
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AndroidDevice *androidDev = static_cast<const AndroidDevice *>(dev);
|
const AndroidDevice *androidDev = static_cast<const AndroidDevice *>(dev);
|
||||||
if (androidDev && !androidDev->canSupportAbis(selectedAbis)) {
|
if (androidDev && !androidDev->canSupportAbis(selectedAbis)) {
|
||||||
const QString error = tr("The deployment device \"%1\" doesn't support the "
|
const QString error = tr("The deployment device \"%1\" does not support the "
|
||||||
"architectures used by the kit.\n"
|
"architectures used by the kit.\n"
|
||||||
"The kit supports \"%2\", but the device uses \"%3\".")
|
"The kit supports \"%2\", but the device uses \"%3\".")
|
||||||
.arg(dev->displayName()).arg(selectedAbis.join(", "))
|
.arg(dev->displayName()).arg(selectedAbis.join(", "))
|
||||||
.arg(androidDev->supportedAbis().join(", "));
|
.arg(androidDev->supportedAbis().join(", "));
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
reportWarningOrError(error, Task::Error);
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (androidDev && !androidDev->canHandleDeployments()) {
|
if (androidDev && !androidDev->canHandleDeployments()) {
|
||||||
const QString error = tr("The deployment device \"%1\" is disconnected.")
|
reportWarningOrError(tr("The deployment device \"%1\" is disconnected.")
|
||||||
.arg(dev->displayName());
|
.arg(dev->displayName()), Task::Error);
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QtSupport::BaseQtVersion * const qt = QtSupport::QtKitAspect::qtVersion(kit());
|
const QtSupport::BaseQtVersion * const qt = QtSupport::QtKitAspect::qtVersion(kit());
|
||||||
if (qt && qt->supportsMultipleQtAbis() && !selectedAbis.contains(info.cpuAbi.first())) {
|
if (qt && qt->supportsMultipleQtAbis() && !selectedAbis.contains(info.cpuAbi.first())) {
|
||||||
TaskHub::addTask(DeploymentTask(
|
TaskHub::addTask(DeploymentTask(Task::Warning,
|
||||||
Task::Warning,
|
|
||||||
tr("Android: The main ABI of the deployment device (%1) is not selected. The app "
|
tr("Android: The main ABI of the deployment device (%1) is not selected. The app "
|
||||||
"execution or debugging might not work properly. Add it from Projects > Build > "
|
"execution or debugging might not work properly. Add it from Projects > Build > "
|
||||||
"Build Steps > qmake > ABIs.")
|
"Build Steps > qmake > ABIs.")
|
||||||
@@ -213,7 +218,7 @@ bool AndroidDeployQtStep::init()
|
|||||||
AndroidManager::setDeviceApiLevel(target(), info.sdk);
|
AndroidManager::setDeviceApiLevel(target(), info.sdk);
|
||||||
AndroidManager::setDeviceAbis(target(), info.cpuAbi);
|
AndroidManager::setDeviceAbis(target(), info.cpuAbi);
|
||||||
|
|
||||||
emit addOutput(tr("Deploying to %1").arg(m_serialNumber), OutputFormat::Stdout);
|
emit addOutput(tr("Deploying to %1").arg(m_serialNumber), OutputFormat::NormalMessage);
|
||||||
|
|
||||||
m_uninstallPreviousPackageRun = m_uninstallPreviousPackage->value();
|
m_uninstallPreviousPackageRun = m_uninstallPreviousPackage->value();
|
||||||
if (m_uninstallPreviousPackageRun)
|
if (m_uninstallPreviousPackageRun)
|
||||||
@@ -223,8 +228,10 @@ bool AndroidDeployQtStep::init()
|
|||||||
if (m_useAndroiddeployqt) {
|
if (m_useAndroiddeployqt) {
|
||||||
const QString buildKey = target()->activeBuildKey();
|
const QString buildKey = target()->activeBuildKey();
|
||||||
const ProjectNode *node = target()->project()->findNodeForBuildKey(buildKey);
|
const ProjectNode *node = target()->project()->findNodeForBuildKey(buildKey);
|
||||||
if (!node)
|
if (!node) {
|
||||||
|
reportWarningOrError(tr("The deployment step's project node is invalid."), Task::Error);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
m_apkPath = Utils::FilePath::fromString(node->data(Constants::AndroidApk).toString());
|
m_apkPath = Utils::FilePath::fromString(node->data(Constants::AndroidApk).toString());
|
||||||
if (!m_apkPath.isEmpty()) {
|
if (!m_apkPath.isEmpty()) {
|
||||||
m_manifestName = Utils::FilePath::fromString(node->data(Constants::AndroidManifest).toString());
|
m_manifestName = Utils::FilePath::fromString(node->data(Constants::AndroidManifest).toString());
|
||||||
@@ -233,16 +240,13 @@ bool AndroidDeployQtStep::init()
|
|||||||
} else {
|
} else {
|
||||||
QString jsonFile = AndroidQtVersion::androidDeploymentSettings(target()).toString();
|
QString jsonFile = AndroidQtVersion::androidDeploymentSettings(target()).toString();
|
||||||
if (jsonFile.isEmpty()) {
|
if (jsonFile.isEmpty()) {
|
||||||
const QString error = tr("Cannot find the androiddeploy Json file.");
|
reportWarningOrError(tr("Cannot find the androiddeployqt input JSON file."),
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
Task::Error);
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_command = version->hostBinPath();
|
m_command = version->hostBinPath();
|
||||||
if (m_command.isEmpty()) {
|
if (m_command.isEmpty()) {
|
||||||
const QString error = tr("Cannot find the androiddeployqt tool.");
|
reportWarningOrError(tr("Cannot find the androiddeployqt tool."), Task::Error);
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_command = m_command.pathAppended("androiddeployqt").withExecutableSuffix();
|
m_command = m_command.pathAppended("androiddeployqt").withExecutableSuffix();
|
||||||
@@ -302,13 +306,14 @@ AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy()
|
|||||||
if (m_uninstallPreviousPackageRun) {
|
if (m_uninstallPreviousPackageRun) {
|
||||||
packageName = AndroidManager::packageName(m_manifestName);
|
packageName = AndroidManager::packageName(m_manifestName);
|
||||||
if (packageName.isEmpty()) {
|
if (packageName.isEmpty()) {
|
||||||
const QString error = tr("Cannot find the package name.");
|
reportWarningOrError(tr("Cannot find the package name from the Android Manifest "
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
"file \"%1\".").arg(m_manifestName.toUserOutput()),
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
Task::Error);
|
||||||
return Failure;
|
return Failure;
|
||||||
}
|
}
|
||||||
qCDebug(deployStepLog) << "Uninstalling previous package";
|
const QString msg = tr("Uninstalling the previous package \"%1\".").arg(packageName);
|
||||||
emit addOutput(tr("Uninstall previous package %1.").arg(packageName), OutputFormat::NormalMessage);
|
qCDebug(deployStepLog) << msg;
|
||||||
|
emit addOutput(msg, OutputFormat::NormalMessage);
|
||||||
runCommand({m_adbPath,
|
runCommand({m_adbPath,
|
||||||
AndroidDeviceInfo::adbSelector(m_serialNumber)
|
AndroidDeviceInfo::adbSelector(m_serialNumber)
|
||||||
<< "uninstall" << packageName});
|
<< "uninstall" << packageName});
|
||||||
@@ -337,8 +342,7 @@ AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy()
|
|||||||
|
|
||||||
m_process->start();
|
m_process->start();
|
||||||
|
|
||||||
emit addOutput(tr("Starting: \"%1\"").arg(cmd.toUserOutput()),
|
emit addOutput(tr("Starting: \"%1\"").arg(cmd.toUserOutput()), OutputFormat::NormalMessage);
|
||||||
BuildStep::OutputFormat::NormalMessage);
|
|
||||||
|
|
||||||
while (!m_process->waitForFinished(200)) {
|
while (!m_process->waitForFinished(200)) {
|
||||||
if (m_process->state() == QProcess::NotRunning)
|
if (m_process->state() == QProcess::NotRunning)
|
||||||
@@ -369,24 +373,27 @@ AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy()
|
|||||||
|
|
||||||
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
|
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
|
||||||
emit addOutput(tr("The process \"%1\" exited normally.").arg(m_command.toUserOutput()),
|
emit addOutput(tr("The process \"%1\" exited normally.").arg(m_command.toUserOutput()),
|
||||||
BuildStep::OutputFormat::NormalMessage);
|
OutputFormat::NormalMessage);
|
||||||
} else if (exitStatus == QProcess::NormalExit) {
|
} else if (exitStatus == QProcess::NormalExit) {
|
||||||
const QString error = tr("The process \"%1\" exited with code %2.")
|
const QString error = tr("The process \"%1\" exited with code %2.")
|
||||||
.arg(m_command.toUserOutput(), QString::number(exitCode));
|
.arg(m_command.toUserOutput(), QString::number(exitCode));
|
||||||
emit addOutput(error, BuildStep::OutputFormat::ErrorMessage);
|
reportWarningOrError(error, Task::Error);
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
} else {
|
} else {
|
||||||
const QString error = tr("The process \"%1\" crashed.").arg(m_command.toUserOutput());
|
const QString error = tr("The process \"%1\" crashed.").arg(m_command.toUserOutput());
|
||||||
emit addOutput(error, BuildStep::OutputFormat::ErrorMessage);
|
reportWarningOrError(error, Task::Error);
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deployError != NoError) {
|
if (deployError != NoError) {
|
||||||
if (m_uninstallPreviousPackageRun)
|
if (m_uninstallPreviousPackageRun) {
|
||||||
deployError = Failure; // Even re-install failed. Set to Failure.
|
deployError = Failure; // Even re-install failed. Set to Failure.
|
||||||
|
reportWarningOrError(
|
||||||
|
tr("Installing the app failed even after uninstalling the previous one."),
|
||||||
|
Task::Error);
|
||||||
|
}
|
||||||
} else if (exitCode != 0 || exitStatus != QProcess::NormalExit) {
|
} else if (exitCode != 0 || exitStatus != QProcess::NormalExit) {
|
||||||
// Set the deployError to Failure when no deployError code was detected
|
// Set the deployError to Failure when no deployError code was detected
|
||||||
// but the adb tool failed otherwise relay the detected deployError.
|
// but the adb tool failed otherwise relay the detected deployError.
|
||||||
|
reportWarningOrError(tr("Installing the app failed with an unknown error."), Task::Error);
|
||||||
deployError = Failure;
|
deployError = Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +428,8 @@ void AndroidDeployQtStep::slotAskForUninstall(DeployErrorCode errorCode)
|
|||||||
mask <<= 1;
|
mask <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uninstallMsg.append(tr("\nUninstalling the installed package may solve the issue.\nDo you want to uninstall the existing package?"));
|
uninstallMsg.append(tr("\nUninstalling the installed package may solve the issue.\n"
|
||||||
|
"Do you want to uninstall the existing package?"));
|
||||||
int button = QMessageBox::critical(nullptr, tr("Install failed"), uninstallMsg,
|
int button = QMessageBox::critical(nullptr, tr("Install failed"), uninstallMsg,
|
||||||
QMessageBox::Yes, QMessageBox::No);
|
QMessageBox::Yes, QMessageBox::No);
|
||||||
m_askForUninstall = button == QMessageBox::Yes;
|
m_askForUninstall = button == QMessageBox::Yes;
|
||||||
@@ -432,10 +440,13 @@ bool AndroidDeployQtStep::runImpl()
|
|||||||
if (!m_avdName.isEmpty()) {
|
if (!m_avdName.isEmpty()) {
|
||||||
QString serialNumber = AndroidAvdManager().waitForAvd(m_avdName, cancelChecker());
|
QString serialNumber = AndroidAvdManager().waitForAvd(m_avdName, cancelChecker());
|
||||||
qCDebug(deployStepLog) << "Deploying to AVD:" << m_avdName << serialNumber;
|
qCDebug(deployStepLog) << "Deploying to AVD:" << m_avdName << serialNumber;
|
||||||
if (serialNumber.isEmpty())
|
if (serialNumber.isEmpty()) {
|
||||||
|
reportWarningOrError(tr("The deployment AVD \"%1\" cannot be started.")
|
||||||
|
.arg(m_avdName), Task::Error);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
m_serialNumber = serialNumber;
|
m_serialNumber = serialNumber;
|
||||||
qCDebug(deployStepLog) << "Target device serial number change:" << serialNumber;
|
qCDebug(deployStepLog) << "Deployment device serial number changed:" << serialNumber;
|
||||||
AndroidManager::setDeviceSerialNumber(target(), serialNumber);
|
AndroidManager::setDeviceSerialNumber(target(), serialNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +462,8 @@ bool AndroidDeployQtStep::runImpl()
|
|||||||
if (!m_filesToPull.isEmpty())
|
if (!m_filesToPull.isEmpty())
|
||||||
emit addOutput(tr("Pulling files necessary for debugging."), OutputFormat::NormalMessage);
|
emit addOutput(tr("Pulling files necessary for debugging."), OutputFormat::NormalMessage);
|
||||||
|
|
||||||
// Note that values are not necessarily unique, e.g. app_process is looked up in several directories
|
// Note that values are not necessarily unique, e.g. app_process is looked up in several
|
||||||
|
// directories
|
||||||
for (auto itr = m_filesToPull.constBegin(); itr != m_filesToPull.constEnd(); ++itr) {
|
for (auto itr = m_filesToPull.constBegin(); itr != m_filesToPull.constEnd(); ++itr) {
|
||||||
QFile::remove(itr.value());
|
QFile::remove(itr.value());
|
||||||
}
|
}
|
||||||
@@ -464,8 +476,7 @@ bool AndroidDeployQtStep::runImpl()
|
|||||||
const QString error = tr("Package deploy: Failed to pull \"%1\" to \"%2\".")
|
const QString error = tr("Package deploy: Failed to pull \"%1\" to \"%2\".")
|
||||||
.arg(itr.key())
|
.arg(itr.key())
|
||||||
.arg(itr.value());
|
.arg(itr.value());
|
||||||
emit addOutput(error, OutputFormat::ErrorMessage);
|
reportWarningOrError(error, Task::Error);
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,11 +529,8 @@ void AndroidDeployQtStep::runCommand(const CommandLine &command)
|
|||||||
buildProc.setCommand(command);
|
buildProc.setCommand(command);
|
||||||
buildProc.setProcessUserEventWhileRunning();
|
buildProc.setProcessUserEventWhileRunning();
|
||||||
buildProc.runBlocking();
|
buildProc.runBlocking();
|
||||||
if (buildProc.result() != QtcProcess::FinishedWithSuccess) {
|
if (buildProc.result() != QtcProcess::FinishedWithSuccess)
|
||||||
const QString error = buildProc.exitMessage();
|
reportWarningOrError(buildProc.exitMessage(), Task::Error);
|
||||||
emit addOutput(error, OutputFormat::ErrorMessage);
|
|
||||||
TaskHub::addTask(DeploymentTask(Task::Error, error));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *AndroidDeployQtStep::createConfigWidget()
|
QWidget *AndroidDeployQtStep::createConfigWidget()
|
||||||
@@ -590,6 +598,13 @@ AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::parseDeployErrors(
|
|||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AndroidDeployQtStep::reportWarningOrError(const QString &message, Task::TaskType type)
|
||||||
|
{
|
||||||
|
qCDebug(deployStepLog) << message;
|
||||||
|
emit addOutput(message, OutputFormat::ErrorMessage);
|
||||||
|
TaskHub::addTask(DeploymentTask(type, message));
|
||||||
|
}
|
||||||
|
|
||||||
// AndroidDeployQtStepFactory
|
// AndroidDeployQtStepFactory
|
||||||
|
|
||||||
AndroidDeployQtStepFactory::AndroidDeployQtStepFactory()
|
AndroidDeployQtStepFactory::AndroidDeployQtStepFactory()
|
||||||
|
@@ -83,8 +83,15 @@ private:
|
|||||||
void stdError(const QString &line);
|
void stdError(const QString &line);
|
||||||
DeployErrorCode parseDeployErrors(const QString &deployOutputLine) const;
|
DeployErrorCode parseDeployErrors(const QString &deployOutputLine) const;
|
||||||
|
|
||||||
friend void operator|=(DeployErrorCode &e1, const DeployErrorCode &e2) { e1 = static_cast<AndroidDeployQtStep::DeployErrorCode>((int)e1 | (int)e2); }
|
friend void operator|=(DeployErrorCode &e1, const DeployErrorCode &e2) {
|
||||||
friend DeployErrorCode operator|(const DeployErrorCode &e1, const DeployErrorCode &e2) { return static_cast<AndroidDeployQtStep::DeployErrorCode>((int)e1 | (int)e2); }
|
e1 = static_cast<AndroidDeployQtStep::DeployErrorCode>((int)e1 | (int)e2);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend DeployErrorCode operator|(const DeployErrorCode &e1, const DeployErrorCode &e2) {
|
||||||
|
return static_cast<AndroidDeployQtStep::DeployErrorCode>((int)e1 | (int)e2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reportWarningOrError(const QString &message, ProjectExplorer::Task::TaskType type);
|
||||||
|
|
||||||
Utils::FilePath m_manifestName;
|
Utils::FilePath m_manifestName;
|
||||||
QString m_serialNumber;
|
QString m_serialNumber;
|
||||||
|
@@ -627,8 +627,8 @@ AndroidDeviceManager *AndroidDeviceManager::instance()
|
|||||||
|
|
||||||
AndroidDeviceManager::AndroidDeviceManager(QObject *parent)
|
AndroidDeviceManager::AndroidDeviceManager(QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
m_avdManager(m_androidConfig),
|
m_androidConfig(AndroidConfigurations::currentConfig()),
|
||||||
m_androidConfig(AndroidConfigurations::currentConfig())
|
m_avdManager(m_androidConfig)
|
||||||
{
|
{
|
||||||
connect(qApp, &QCoreApplication::aboutToQuit, this, [this]() {
|
connect(qApp, &QCoreApplication::aboutToQuit, this, [this]() {
|
||||||
m_devicesUpdaterTimer.stop();
|
m_devicesUpdaterTimer.stop();
|
||||||
|
@@ -90,7 +90,7 @@ public:
|
|||||||
ProjectExplorer::IDevice::Ptr create() const override;
|
ProjectExplorer::IDevice::Ptr create() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AndroidConfig m_androidConfig;
|
const AndroidConfig &m_androidConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AndroidDeviceManager : public QObject
|
class AndroidDeviceManager : public QObject
|
||||||
@@ -116,8 +116,8 @@ private:
|
|||||||
QFutureWatcher<QVector<AndroidDeviceInfo>> m_devicesFutureWatcher;
|
QFutureWatcher<QVector<AndroidDeviceInfo>> m_devicesFutureWatcher;
|
||||||
QFutureWatcher<QPair<ProjectExplorer::IDevice::ConstPtr, bool>> m_removeAvdFutureWatcher;
|
QFutureWatcher<QPair<ProjectExplorer::IDevice::ConstPtr, bool>> m_removeAvdFutureWatcher;
|
||||||
QTimer m_devicesUpdaterTimer;
|
QTimer m_devicesUpdaterTimer;
|
||||||
|
AndroidConfig &m_androidConfig;
|
||||||
AndroidAvdManager m_avdManager;
|
AndroidAvdManager m_avdManager;
|
||||||
AndroidConfig m_androidConfig;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -72,6 +72,8 @@ private:
|
|||||||
void setupOutputFormatter(OutputFormatter *formatter) final;
|
void setupOutputFormatter(OutputFormatter *formatter) final;
|
||||||
void doRun() final;
|
void doRun() final;
|
||||||
|
|
||||||
|
void reportWarningOrError(const QString &message, ProjectExplorer::Task::TaskType type);
|
||||||
|
|
||||||
QStringList m_androidDirsToClean;
|
QStringList m_androidDirsToClean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,11 +91,16 @@ AndroidPackageInstallationStep::AndroidPackageInstallationStep(BuildStepList *bs
|
|||||||
|
|
||||||
bool AndroidPackageInstallationStep::init()
|
bool AndroidPackageInstallationStep::init()
|
||||||
{
|
{
|
||||||
if (!AbstractProcessStep::init())
|
if (!AbstractProcessStep::init()) {
|
||||||
|
reportWarningOrError(tr("\"%1\" step failed initialization.").arg(displayName()),
|
||||||
|
Task::TaskType::Error);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ToolChain *tc = ToolChainKitAspect::cxxToolChain(kit());
|
ToolChain *tc = ToolChainKitAspect::cxxToolChain(kit());
|
||||||
QTC_ASSERT(tc, return false);
|
QTC_ASSERT(tc, reportWarningOrError(tr("\"%1\" step has an invalid C++ toolchain.")
|
||||||
|
.arg(displayName()), Task::TaskType::Error);
|
||||||
|
return false);
|
||||||
|
|
||||||
QString dirPath = nativeAndroidBuildPath();
|
QString dirPath = nativeAndroidBuildPath();
|
||||||
const QString innerQuoted = ProcessArgs::quoteArg(dirPath);
|
const QString innerQuoted = ProcessArgs::quoteArg(dirPath);
|
||||||
@@ -140,8 +147,9 @@ void AndroidPackageInstallationStep::doRun()
|
|||||||
if (!dir.isEmpty() && androidDir.exists()) {
|
if (!dir.isEmpty() && androidDir.exists()) {
|
||||||
emit addOutput(tr("Removing directory %1").arg(dir), OutputFormat::NormalMessage);
|
emit addOutput(tr("Removing directory %1").arg(dir), OutputFormat::NormalMessage);
|
||||||
if (!androidDir.removeRecursively(&error)) {
|
if (!androidDir.removeRecursively(&error)) {
|
||||||
emit addOutput(error, OutputFormat::Stderr);
|
reportWarningOrError(tr("Failed to clean \"%1\" from the previous build, with "
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Error, error));
|
"error:\n%2").arg(androidDir.toUserOutput()).arg(error),
|
||||||
|
Task::TaskType::Error);
|
||||||
emit finished(false);
|
emit finished(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -167,13 +175,21 @@ void AndroidPackageInstallationStep::doRun()
|
|||||||
qPrintable(file.fileName()));
|
qPrintable(file.fileName()));
|
||||||
} else {
|
} else {
|
||||||
qCDebug(packageInstallationStepLog,
|
qCDebug(packageInstallationStepLog,
|
||||||
"Cound't add %s to the package. The QML debugger might not work properly.",
|
"Cannot add %s to the package. The QML debugger might not work properly.",
|
||||||
qPrintable(file.fileName()));
|
qPrintable(file.fileName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AndroidPackageInstallationStep::reportWarningOrError(const QString &message,
|
||||||
|
Task::TaskType type)
|
||||||
|
{
|
||||||
|
qCDebug(packageInstallationStepLog) << message;
|
||||||
|
emit addOutput(message, OutputFormat::ErrorMessage);
|
||||||
|
TaskHub::addTask(BuildSystemTask(type, message));
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// AndroidPackageInstallationStepFactory
|
// AndroidPackageInstallationStepFactory
|
||||||
//
|
//
|
||||||
|
@@ -78,7 +78,7 @@ private:
|
|||||||
Utils::FilePath createQmlrcFile(const Utils::FilePath &workFolder, const QString &basename);
|
Utils::FilePath createQmlrcFile(const Utils::FilePath &workFolder, const QString &basename);
|
||||||
|
|
||||||
ProjectExplorer::RunControl *m_rc = nullptr;
|
ProjectExplorer::RunControl *m_rc = nullptr;
|
||||||
AndroidConfig m_androidConfig;
|
const AndroidConfig &m_androidConfig;
|
||||||
QString m_serialNumber;
|
QString m_serialNumber;
|
||||||
QStringList m_avdAbis;
|
QStringList m_avdAbis;
|
||||||
int m_viewerPid = -1;
|
int m_viewerPid = -1;
|
||||||
|
@@ -48,8 +48,8 @@ namespace Internal {
|
|||||||
* @brief Download Android SDK tools package from within Qt Creator.
|
* @brief Download Android SDK tools package from within Qt Creator.
|
||||||
*/
|
*/
|
||||||
AndroidSdkDownloader::AndroidSdkDownloader()
|
AndroidSdkDownloader::AndroidSdkDownloader()
|
||||||
|
: m_androidConfig(AndroidConfigurations::currentConfig())
|
||||||
{
|
{
|
||||||
m_androidConfig = AndroidConfigurations::currentConfig();
|
|
||||||
connect(&m_manager, &QNetworkAccessManager::finished, this, &AndroidSdkDownloader::downloadFinished);
|
connect(&m_manager, &QNetworkAccessManager::finished, this, &AndroidSdkDownloader::downloadFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -72,7 +72,7 @@ private:
|
|||||||
QNetworkReply *m_reply = nullptr;
|
QNetworkReply *m_reply = nullptr;
|
||||||
Utils::FilePath m_sdkFilename;
|
Utils::FilePath m_sdkFilename;
|
||||||
QProgressDialog *m_progressDialog = nullptr;
|
QProgressDialog *m_progressDialog = nullptr;
|
||||||
AndroidConfig m_androidConfig;
|
const AndroidConfig &m_androidConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Internal
|
} // Internal
|
||||||
|
@@ -108,7 +108,7 @@ private:
|
|||||||
|
|
||||||
Ui_AndroidSettingsWidget m_ui;
|
Ui_AndroidSettingsWidget m_ui;
|
||||||
AndroidSdkManagerWidget *m_sdkManagerWidget = nullptr;
|
AndroidSdkManagerWidget *m_sdkManagerWidget = nullptr;
|
||||||
AndroidConfig m_androidConfig{AndroidConfigurations::currentConfig()};
|
AndroidConfig &m_androidConfig{AndroidConfigurations::currentConfig()};
|
||||||
|
|
||||||
AndroidSdkManager m_sdkManager{m_androidConfig};
|
AndroidSdkManager m_sdkManager{m_androidConfig};
|
||||||
AndroidSdkDownloader m_sdkDownloader;
|
AndroidSdkDownloader m_sdkDownloader;
|
||||||
|
@@ -116,7 +116,7 @@ bool AndroidToolChain::isValid() const
|
|||||||
|
|
||||||
void AndroidToolChain::addToEnvironment(Environment &env) const
|
void AndroidToolChain::addToEnvironment(Environment &env) const
|
||||||
{
|
{
|
||||||
AndroidConfig config = AndroidConfigurations::currentConfig();
|
const AndroidConfig &config = AndroidConfigurations::currentConfig();
|
||||||
env.set(QLatin1String("ANDROID_NDK_HOST"), config.toolchainHostFromNdk(m_ndkLocation));
|
env.set(QLatin1String("ANDROID_NDK_HOST"), config.toolchainHostFromNdk(m_ndkLocation));
|
||||||
const Utils::FilePath javaHome = config.openJDKLocation();
|
const Utils::FilePath javaHome = config.openJDKLocation();
|
||||||
if (javaHome.exists()) {
|
if (javaHome.exists()) {
|
||||||
@@ -178,7 +178,7 @@ static FilePath clangPlusPlusPath(const FilePath &clangPath)
|
|||||||
|
|
||||||
static QList<FilePath> uniqueNdksForCurrentQtVersions()
|
static QList<FilePath> uniqueNdksForCurrentQtVersions()
|
||||||
{
|
{
|
||||||
AndroidConfig config = AndroidConfigurations::currentConfig();
|
const AndroidConfig &config = AndroidConfigurations::currentConfig();
|
||||||
|
|
||||||
auto androidQtVersions = QtSupport::QtVersionManager::versions(
|
auto androidQtVersions = QtSupport::QtVersionManager::versions(
|
||||||
[](const QtSupport::BaseQtVersion *v) {
|
[](const QtSupport::BaseQtVersion *v) {
|
||||||
|
@@ -51,9 +51,9 @@ static Q_LOGGING_CATEGORY(avdDialogLog, "qtc.android.avdDialog", QtWarningMsg)
|
|||||||
|
|
||||||
AvdDialog::AvdDialog(const AndroidConfig &config, QWidget *parent)
|
AvdDialog::AvdDialog(const AndroidConfig &config, QWidget *parent)
|
||||||
: QDialog(parent),
|
: QDialog(parent),
|
||||||
|
m_androidConfig(config),
|
||||||
m_sdkManager(m_androidConfig),
|
m_sdkManager(m_androidConfig),
|
||||||
m_allowedNameChars(QLatin1String("[a-z|A-Z|0-9|._-]*")),
|
m_allowedNameChars(QLatin1String("[a-z|A-Z|0-9|._-]*"))
|
||||||
m_androidConfig(config)
|
|
||||||
{
|
{
|
||||||
m_avdDialog.setupUi(this);
|
m_avdDialog.setupUi(this);
|
||||||
m_hideTipTimer.setInterval(2000);
|
m_hideTipTimer.setInterval(2000);
|
||||||
|
@@ -71,12 +71,12 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ui::AddNewAVDDialog m_avdDialog;
|
Ui::AddNewAVDDialog m_avdDialog;
|
||||||
AndroidSdkManager m_sdkManager;
|
|
||||||
CreateAvdInfo m_createdAvdInfo;
|
CreateAvdInfo m_createdAvdInfo;
|
||||||
QTimer m_hideTipTimer;
|
QTimer m_hideTipTimer;
|
||||||
QRegularExpression m_allowedNameChars;
|
QRegularExpression m_allowedNameChars;
|
||||||
QList<DeviceDefinitionStruct> m_deviceDefinitionsList;
|
QList<DeviceDefinitionStruct> m_deviceDefinitionsList;
|
||||||
AndroidConfig m_androidConfig;
|
const AndroidConfig &m_androidConfig;
|
||||||
|
AndroidSdkManager m_sdkManager;
|
||||||
QMap<AvdDialog::DeviceType, QString> deviceTypeToStringMap;
|
QMap<AvdDialog::DeviceType, QString> deviceTypeToStringMap;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1272,9 +1272,11 @@ void ClangdTestHighlighting::test()
|
|||||||
};
|
};
|
||||||
const TextEditor::HighlightingResults results = findResults();
|
const TextEditor::HighlightingResults results = findResults();
|
||||||
|
|
||||||
|
if (client()->versionNumber() < QVersionNumber(14)) {
|
||||||
QEXPECT_FAIL("typedef as underlying type in enum declaration",
|
QEXPECT_FAIL("typedef as underlying type in enum declaration",
|
||||||
"https://github.com/clangd/clangd/issues/878",
|
"https://github.com/clangd/clangd/issues/878",
|
||||||
Abort);
|
Abort);
|
||||||
|
}
|
||||||
QEXPECT_FAIL("Q_PROPERTY (property name)", "FIXME: How to do this?", Abort);
|
QEXPECT_FAIL("Q_PROPERTY (property name)", "FIXME: How to do this?", Abort);
|
||||||
QEXPECT_FAIL("Q_PROPERTY (getter)", "FIXME: How to do this?", Abort);
|
QEXPECT_FAIL("Q_PROPERTY (getter)", "FIXME: How to do this?", Abort);
|
||||||
QEXPECT_FAIL("Q_PROPERTY (notifier)", "FIXME: How to do this?", Abort);
|
QEXPECT_FAIL("Q_PROPERTY (notifier)", "FIXME: How to do this?", Abort);
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include <coreplugin/find/itemviewfind.h>
|
#include <coreplugin/find/itemviewfind.h>
|
||||||
#include <projectexplorer/buildsteplist.h>
|
#include <projectexplorer/buildsteplist.h>
|
||||||
#include <projectexplorer/gnumakeparser.h>
|
#include <projectexplorer/gnumakeparser.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
#include <projectexplorer/processparameters.h>
|
#include <projectexplorer/processparameters.h>
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
@@ -376,13 +377,15 @@ void CMakeBuildStep::setBuildTargets(const QStringList &buildTargets)
|
|||||||
|
|
||||||
CommandLine CMakeBuildStep::cmakeCommand() const
|
CommandLine CMakeBuildStep::cmakeCommand() const
|
||||||
{
|
{
|
||||||
CMakeTool *tool = CMakeKitAspect::cmakeTool(kit());
|
CommandLine cmd;
|
||||||
|
if (CMakeTool *tool = CMakeKitAspect::cmakeTool(kit()))
|
||||||
|
cmd.setExecutable(tool->cmakeExecutable());
|
||||||
|
|
||||||
CommandLine cmd(tool ? tool->cmakeExecutable() : FilePath(), {});
|
FilePath buildDirectory = ".";
|
||||||
QString buildDirectory = ".";
|
|
||||||
if (buildConfiguration())
|
if (buildConfiguration())
|
||||||
buildDirectory = buildConfiguration()->buildDirectory().path();
|
buildDirectory = buildConfiguration()->buildDirectory();
|
||||||
cmd.addArgs({"--build", buildDirectory});
|
|
||||||
|
cmd.addArgs({"--build", buildDirectory.onDevice(cmd.executable()).path()});
|
||||||
|
|
||||||
cmd.addArg("--target");
|
cmd.addArg("--target");
|
||||||
cmd.addArgs(Utils::transform(m_buildTargets, [this](const QString &s) {
|
cmd.addArgs(Utils::transform(m_buildTargets, [this](const QString &s) {
|
||||||
|
@@ -72,7 +72,11 @@ void CMakeProcess::run(const BuildDirParameters ¶meters, const QStringList &
|
|||||||
CMakeTool *cmake = parameters.cmakeTool();
|
CMakeTool *cmake = parameters.cmakeTool();
|
||||||
QTC_ASSERT(parameters.isValid() && cmake, return);
|
QTC_ASSERT(parameters.isValid() && cmake, return);
|
||||||
|
|
||||||
const FilePath buildDirectory = parameters.buildDirectory;
|
const FilePath cmakeExecutable = cmake->cmakeExecutable();
|
||||||
|
|
||||||
|
const FilePath sourceDirectory = parameters.sourceDirectory.onDevice(cmakeExecutable);
|
||||||
|
const FilePath buildDirectory = parameters.buildDirectory.onDevice(cmakeExecutable);
|
||||||
|
|
||||||
if (!buildDirectory.exists()) {
|
if (!buildDirectory.exists()) {
|
||||||
QString msg = tr("The build directory \"%1\" does not exist")
|
QString msg = tr("The build directory \"%1\" does not exist")
|
||||||
.arg(buildDirectory.toUserOutput());
|
.arg(buildDirectory.toUserOutput());
|
||||||
@@ -119,12 +123,8 @@ void CMakeProcess::run(const BuildDirParameters ¶meters, const QStringList &
|
|||||||
connect(process.get(), &QtcProcess::finished,
|
connect(process.get(), &QtcProcess::finished,
|
||||||
this, &CMakeProcess::handleProcessFinished);
|
this, &CMakeProcess::handleProcessFinished);
|
||||||
|
|
||||||
const FilePath cmakeExecutable = cmake->cmakeExecutable();
|
|
||||||
const FilePath sourceDirectory = parameters.sourceDirectory.onDevice(cmakeExecutable);
|
|
||||||
|
|
||||||
CommandLine commandLine(cmakeExecutable);
|
CommandLine commandLine(cmakeExecutable);
|
||||||
commandLine.addArgs({"-S", sourceDirectory.mapToDevicePath(),
|
commandLine.addArgs({"-S", sourceDirectory.path(), "-B", buildDirectory.path()});
|
||||||
"-B", buildDirectory.mapToDevicePath()});
|
|
||||||
commandLine.addArgs(arguments);
|
commandLine.addArgs(arguments);
|
||||||
|
|
||||||
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||||
|
@@ -140,11 +140,12 @@ MakeInstallCommand CMakeProject::makeInstallCommand(const Target *target,
|
|||||||
config << "--config" << bc->cmakeBuildType();
|
config << "--config" << bc->cmakeBuildType();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString buildDirectory = ".";
|
FilePath buildDirectory = ".";
|
||||||
if (bc)
|
if (bc)
|
||||||
buildDirectory = bc->buildDirectory().toString();
|
buildDirectory = bc->buildDirectory();
|
||||||
|
|
||||||
cmd.arguments << "--build" << buildDirectory << "--target" << installTarget << config;
|
cmd.arguments << "--build" << buildDirectory.onDevice(cmd.command).mapToDevicePath()
|
||||||
|
<< "--target" << installTarget << config;
|
||||||
|
|
||||||
cmd.environment.set("DESTDIR", QDir::toNativeSeparators(installRoot));
|
cmd.environment.set("DESTDIR", QDir::toNativeSeparators(installRoot));
|
||||||
return cmd;
|
return cmd;
|
||||||
|
@@ -162,10 +162,11 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const CoreArguments args = parseArguments(arguments);
|
const CoreArguments args = parseArguments(arguments);
|
||||||
Theme::initialPalette(); // Initialize palette before setting it
|
|
||||||
Theme *themeFromArg = ThemeEntry::createTheme(args.themeId);
|
Theme *themeFromArg = ThemeEntry::createTheme(args.themeId);
|
||||||
setCreatorTheme(themeFromArg ? themeFromArg
|
Theme *theme = themeFromArg ? themeFromArg
|
||||||
: ThemeEntry::createTheme(ThemeEntry::themeSetting()));
|
: ThemeEntry::createTheme(ThemeEntry::themeSetting());
|
||||||
|
Theme::setInitialPalette(theme); // Initialize palette before setting it
|
||||||
|
setCreatorTheme(theme);
|
||||||
InfoBar::initialize(ICore::settings());
|
InfoBar::initialize(ICore::settings());
|
||||||
new ActionManager(this);
|
new ActionManager(this);
|
||||||
ActionManager::setPresentationModeEnabled(args.presentationMode);
|
ActionManager::setPresentationModeEnabled(args.presentationMode);
|
||||||
|
@@ -455,8 +455,13 @@ void FolderNavigationWidget::insertRootDirectory(
|
|||||||
m_rootSelector->setCurrentIndex(index);
|
m_rootSelector->setCurrentIndex(index);
|
||||||
if (previousIndex < m_rootSelector->count())
|
if (previousIndex < m_rootSelector->count())
|
||||||
m_rootSelector->removeItem(previousIndex);
|
m_rootSelector->removeItem(previousIndex);
|
||||||
|
if (Core::EditorManager::currentEditor()) {
|
||||||
if (m_autoSync) // we might find a better root for current selection now
|
if (m_autoSync) // we might find a better root for current selection now
|
||||||
handleCurrentEditorChanged(Core::EditorManager::currentEditor());
|
handleCurrentEditorChanged(Core::EditorManager::currentEditor());
|
||||||
|
} else if (m_rootAutoSync) {
|
||||||
|
// assume the new root is better (e.g. because a project was opened)
|
||||||
|
m_rootSelector->setCurrentIndex(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderNavigationWidget::removeRootDirectory(const QString &id)
|
void FolderNavigationWidget::removeRootDirectory(const QString &id)
|
||||||
|
@@ -62,6 +62,10 @@
|
|||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <coreplugin/find/searchresultwindow.h>
|
#include <coreplugin/find/searchresultwindow.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/projectnodes.h>
|
||||||
|
#include <projectexplorer/projecttree.h>
|
||||||
|
#include <projectexplorer/session.h>
|
||||||
|
|
||||||
#include <texteditor/basefilefind.h>
|
#include <texteditor/basefilefind.h>
|
||||||
#include <texteditor/behaviorsettings.h>
|
#include <texteditor/behaviorsettings.h>
|
||||||
#include <texteditor/codeassist/assistproposalitem.h>
|
#include <texteditor/codeassist/assistproposalitem.h>
|
||||||
@@ -76,8 +80,6 @@
|
|||||||
#include <texteditor/textdocumentlayout.h>
|
#include <texteditor/textdocumentlayout.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
|
||||||
#include <projectexplorer/projecttree.h>
|
|
||||||
|
|
||||||
#include <cplusplus/ASTPath.h>
|
#include <cplusplus/ASTPath.h>
|
||||||
#include <cplusplus/FastPreprocessor.h>
|
#include <cplusplus/FastPreprocessor.h>
|
||||||
#include <cplusplus/MatchingText.h>
|
#include <cplusplus/MatchingText.h>
|
||||||
@@ -101,6 +103,7 @@ enum { UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL = 200 };
|
|||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
|
using namespace ProjectExplorer;
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
@@ -1045,7 +1048,7 @@ void CppEditorWidget::switchDeclarationDefinition(bool inNextSplit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CppEditorWidget::findLinkAt(const QTextCursor &cursor,
|
void CppEditorWidget::findLinkAt(const QTextCursor &cursor,
|
||||||
Utils::ProcessLinkCallback &&processLinkCallback,
|
ProcessLinkCallback &&processLinkCallback,
|
||||||
bool resolveTarget,
|
bool resolveTarget,
|
||||||
bool inNextSplit)
|
bool inNextSplit)
|
||||||
{
|
{
|
||||||
@@ -1054,9 +1057,36 @@ void CppEditorWidget::findLinkAt(const QTextCursor &cursor,
|
|||||||
|
|
||||||
const Utils::FilePath &filePath = textDocument()->filePath();
|
const Utils::FilePath &filePath = textDocument()->filePath();
|
||||||
|
|
||||||
|
// Let following a "leaf" C++ symbol take us to the designer, if we are in a generated
|
||||||
|
// UI header.
|
||||||
|
QTextCursor c(cursor);
|
||||||
|
c.select(QTextCursor::WordUnderCursor);
|
||||||
|
ProcessLinkCallback callbackWrapper = [start = c.selectionStart(), end = c.selectionEnd(),
|
||||||
|
doc = QPointer(cursor.document()), callback = std::move(processLinkCallback),
|
||||||
|
filePath](const Link &link) {
|
||||||
|
const int linkPos = doc ? Text::positionInText(doc, link.targetLine, link.targetColumn + 1)
|
||||||
|
: -1;
|
||||||
|
if (link.targetFilePath == filePath && linkPos >= start && linkPos < end) {
|
||||||
|
const QString fileName = filePath.fileName();
|
||||||
|
if (fileName.startsWith("ui_") && fileName.endsWith(".h")) {
|
||||||
|
const QString uiFileName = fileName.mid(3, fileName.length() - 4) + "ui";
|
||||||
|
for (const Project * const project : SessionManager::projects()) {
|
||||||
|
const auto nodeMatcher = [uiFileName](Node *n) {
|
||||||
|
return n->filePath().fileName() == uiFileName;
|
||||||
|
};
|
||||||
|
if (const Node * const uiNode = project->rootProjectNode()
|
||||||
|
->findNode(nodeMatcher)) {
|
||||||
|
EditorManager::openEditor(uiNode->filePath());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(link);
|
||||||
|
};
|
||||||
followSymbolInterface().findLink(
|
followSymbolInterface().findLink(
|
||||||
CursorInEditor{cursor, filePath, this, textDocument()},
|
CursorInEditor{cursor, filePath, this, textDocument()},
|
||||||
std::move(processLinkCallback),
|
std::move(callbackWrapper),
|
||||||
resolveTarget,
|
resolveTarget,
|
||||||
d->m_modelManager->snapshot(),
|
d->m_modelManager->snapshot(),
|
||||||
d->m_lastSemanticInfo.doc,
|
d->m_lastSemanticInfo.doc,
|
||||||
|
@@ -3116,8 +3116,10 @@ public:
|
|||||||
defaultImplTargetComboBox->insertItems(0, implTargetStrings);
|
defaultImplTargetComboBox->insertItems(0, implTargetStrings);
|
||||||
connect(defaultImplTargetComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
connect(defaultImplTargetComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
[this](int index) {
|
[this](int index) {
|
||||||
for (QComboBox * const cb : qAsConst(m_implTargetBoxes))
|
for (int i = 0; i < m_implTargetBoxes.size(); ++i) {
|
||||||
cb->setCurrentIndex(index);
|
if (!m_candidates.at(i)->type()->asFunctionType()->isPureVirtual())
|
||||||
|
static_cast<QComboBox *>(m_implTargetBoxes.at(i))->setCurrentIndex(index);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const auto defaultImplTargetLayout = new QHBoxLayout;
|
const auto defaultImplTargetLayout = new QHBoxLayout;
|
||||||
defaultImplTargetLayout->addWidget(new QLabel(tr("Default implementation location:")));
|
defaultImplTargetLayout->addWidget(new QLabel(tr("Default implementation location:")));
|
||||||
@@ -3128,10 +3130,13 @@ public:
|
|||||||
oo.showFunctionSignatures = true;
|
oo.showFunctionSignatures = true;
|
||||||
oo.showReturnTypes = true;
|
oo.showReturnTypes = true;
|
||||||
for (int i = 0; i < m_candidates.size(); ++i) {
|
for (int i = 0; i < m_candidates.size(); ++i) {
|
||||||
|
const Function * const func = m_candidates.at(i)->type()->asFunctionType();
|
||||||
|
QTC_ASSERT(func, continue);
|
||||||
const auto implTargetComboBox = new QComboBox;
|
const auto implTargetComboBox = new QComboBox;
|
||||||
m_implTargetBoxes.append(implTargetComboBox);
|
m_implTargetBoxes.append(implTargetComboBox);
|
||||||
implTargetComboBox->insertItems(0, implTargetStrings);
|
implTargetComboBox->insertItems(0, implTargetStrings);
|
||||||
const Symbol * const func = m_candidates.at(i);
|
if (func->isPureVirtual())
|
||||||
|
implTargetComboBox->setCurrentIndex(0);
|
||||||
candidatesLayout->addWidget(new QLabel(oo.prettyType(func->type(), func->name())),
|
candidatesLayout->addWidget(new QLabel(oo.prettyType(func->type(), func->name())),
|
||||||
i, 0);
|
i, 0);
|
||||||
candidatesLayout->addWidget(implTargetComboBox, i, 1);
|
candidatesLayout->addWidget(implTargetComboBox, i, 1);
|
||||||
|
@@ -1079,7 +1079,7 @@ void CdbEngine::activateFrame(int index)
|
|||||||
|
|
||||||
if (debug || debugLocals)
|
if (debug || debugLocals)
|
||||||
qDebug("activateFrame idx=%d '%s' %d", index,
|
qDebug("activateFrame idx=%d '%s' %d", index,
|
||||||
qPrintable(frame.file), frame.line);
|
qPrintable(frame.file.toUserOutput()), frame.line);
|
||||||
stackHandler()->setCurrentIndex(index);
|
stackHandler()->setCurrentIndex(index);
|
||||||
gotoLocation(frame);
|
gotoLocation(frame);
|
||||||
if (m_pythonVersion > 0x030000)
|
if (m_pythonVersion > 0x030000)
|
||||||
@@ -2615,7 +2615,7 @@ static StackFrames parseFrames(const GdbMi &gdbmi, bool *incomplete = nullptr)
|
|||||||
frame.level = QString::number(i);
|
frame.level = QString::number(i);
|
||||||
const GdbMi fullName = frameMi["fullname"];
|
const GdbMi fullName = frameMi["fullname"];
|
||||||
if (fullName.isValid()) {
|
if (fullName.isValid()) {
|
||||||
frame.file = Utils::FileUtils::normalizedPathName(fullName.data());
|
frame.file = Utils::FilePath::fromString(fullName.data()).normalizedPathName();
|
||||||
frame.line = frameMi["line"].data().toInt();
|
frame.line = frameMi["line"].data().toInt();
|
||||||
frame.usable = false; // To be decided after source path mapping.
|
frame.usable = false; // To be decided after source path mapping.
|
||||||
const GdbMi languageMi = frameMi["language"];
|
const GdbMi languageMi = frameMi["language"];
|
||||||
@@ -2661,12 +2661,12 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
|
|||||||
return ParseStackStepOut;
|
return ParseStackStepOut;
|
||||||
}
|
}
|
||||||
if (hasFile) {
|
if (hasFile) {
|
||||||
const NormalizedSourceFileName fileName = sourceMapNormalizeFileNameFromDebugger(frames.at(i).file);
|
const NormalizedSourceFileName fileName = sourceMapNormalizeFileNameFromDebugger(frames.at(i).file.toString());
|
||||||
if (!fileName.exists && i == 0 && sourceStepInto) {
|
if (!fileName.exists && i == 0 && sourceStepInto) {
|
||||||
showMessage("Step into: Hit frame with no source, step out...", LogMisc);
|
showMessage("Step into: Hit frame with no source, step out...", LogMisc);
|
||||||
return ParseStackStepOut;
|
return ParseStackStepOut;
|
||||||
}
|
}
|
||||||
frames[i].file = fileName.fileName;
|
frames[i].file = FilePath::fromString(fileName.fileName);
|
||||||
frames[i].usable = fileName.exists;
|
frames[i].usable = fileName.exists;
|
||||||
if (current == -1 && frames[i].usable)
|
if (current == -1 && frames[i].usable)
|
||||||
current = i;
|
current = i;
|
||||||
|
@@ -161,7 +161,7 @@ static bool debuggerActionsEnabledHelper(DebuggerState state)
|
|||||||
|
|
||||||
Location::Location(const StackFrame &frame, bool marker)
|
Location::Location(const StackFrame &frame, bool marker)
|
||||||
{
|
{
|
||||||
m_fileName = Utils::FilePath::fromString(frame.file);
|
m_fileName = frame.file;
|
||||||
m_lineNumber = frame.line;
|
m_lineNumber = frame.line;
|
||||||
m_needsMarker = marker;
|
m_needsMarker = marker;
|
||||||
m_functionName = frame.function;
|
m_functionName = frame.function;
|
||||||
|
@@ -912,9 +912,14 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_runParameters.inferior = runnable();
|
Runnable inferior = runnable();
|
||||||
|
const FilePath &debuggerExecutable = m_runParameters.debugger.command.executable();
|
||||||
|
inferior.command.setExecutable(inferior.command.executable().onDevice(debuggerExecutable));
|
||||||
|
inferior.workingDirectory = inferior.workingDirectory.onDevice(debuggerExecutable);
|
||||||
// Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...)
|
// Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...)
|
||||||
m_runParameters.inferior.workingDirectory = m_runParameters.inferior.workingDirectory.normalizedPathName();
|
inferior.workingDirectory = inferior.workingDirectory.normalizedPathName();
|
||||||
|
m_runParameters.inferior = inferior;
|
||||||
|
|
||||||
setUseTerminal(allowTerminal == DoAllowTerminal && m_runParameters.useTerminal);
|
setUseTerminal(allowTerminal == DoAllowTerminal && m_runParameters.useTerminal);
|
||||||
|
|
||||||
const QByteArray envBinary = qgetenv("QTC_DEBUGGER_PATH");
|
const QByteArray envBinary = qgetenv("QTC_DEBUGGER_PATH");
|
||||||
|
@@ -718,10 +718,9 @@ DebuggerToolTipContext::DebuggerToolTipContext()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool filesMatch(const QString &file1, const QString &file2)
|
static bool filesMatch(const FilePath &file1, const FilePath &file2)
|
||||||
{
|
{
|
||||||
return FilePath::fromString(QFileInfo(file1).canonicalFilePath())
|
return file1.canonicalPath() == file2.canonicalPath();
|
||||||
== FilePath::fromString(QFileInfo(file2).canonicalFilePath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebuggerToolTipContext::matchesFrame(const StackFrame &frame) const
|
bool DebuggerToolTipContext::matchesFrame(const StackFrame &frame) const
|
||||||
@@ -945,7 +944,7 @@ void DebuggerToolTipHolder::saveSessionData(QXmlStreamWriter &w) const
|
|||||||
w.writeStartElement(toolTipElementC);
|
w.writeStartElement(toolTipElementC);
|
||||||
QXmlStreamAttributes attributes;
|
QXmlStreamAttributes attributes;
|
||||||
// attributes.append(toolTipClassAttributeC, QString::fromLatin1(metaObject()->className()));
|
// attributes.append(toolTipClassAttributeC, QString::fromLatin1(metaObject()->className()));
|
||||||
attributes.append(fileNameAttributeC, context.fileName);
|
attributes.append(fileNameAttributeC, context.fileName.toString());
|
||||||
if (!context.function.isEmpty())
|
if (!context.function.isEmpty())
|
||||||
attributes.append(functionAttributeC, context.function);
|
attributes.append(functionAttributeC, context.function);
|
||||||
attributes.append(textPositionAttributeC, QString::number(context.position));
|
attributes.append(textPositionAttributeC, QString::number(context.position));
|
||||||
@@ -1019,15 +1018,15 @@ void DebuggerToolTipManagerPrivate::updateVisibleToolTips()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString fileName = toolTipEditor->textDocument()->filePath().toString();
|
const FilePath filePath = toolTipEditor->textDocument()->filePath();
|
||||||
if (fileName.isEmpty()) {
|
if (filePath.isEmpty()) {
|
||||||
hideAllToolTips();
|
hideAllToolTips();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reposition and show all tooltips of that file.
|
// Reposition and show all tooltips of that file.
|
||||||
for (DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips)) {
|
for (DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips)) {
|
||||||
if (tooltip->context.fileName == fileName)
|
if (tooltip->context.fileName == filePath)
|
||||||
tooltip->positionShow(toolTipEditor->editorWidget());
|
tooltip->positionShow(toolTipEditor->editorWidget());
|
||||||
else
|
else
|
||||||
tooltip->widget->hide();
|
tooltip->widget->hide();
|
||||||
@@ -1085,7 +1084,8 @@ void DebuggerToolTipManagerPrivate::loadSessionData()
|
|||||||
if (readStartElement(r, toolTipElementC)) {
|
if (readStartElement(r, toolTipElementC)) {
|
||||||
const QXmlStreamAttributes attributes = r.attributes();
|
const QXmlStreamAttributes attributes = r.attributes();
|
||||||
DebuggerToolTipContext context;
|
DebuggerToolTipContext context;
|
||||||
context.fileName = attributes.value(fileNameAttributeC).toString();
|
context.fileName = FilePath::fromString(
|
||||||
|
attributes.value(fileNameAttributeC).toString());
|
||||||
context.position = attributes.value(textPositionAttributeC).toString().toInt();
|
context.position = attributes.value(textPositionAttributeC).toString().toInt();
|
||||||
context.line = attributes.value(textLineAttributeC).toString().toInt();
|
context.line = attributes.value(textLineAttributeC).toString().toInt();
|
||||||
context.column = attributes.value(textColumnAttributeC).toString().toInt();
|
context.column = attributes.value(textColumnAttributeC).toString().toInt();
|
||||||
@@ -1197,7 +1197,7 @@ void DebuggerToolTipManagerPrivate::slotTooltipOverrideRequested
|
|||||||
|
|
||||||
DebuggerToolTipContext context;
|
DebuggerToolTipContext context;
|
||||||
context.engineType = m_engine->objectName();
|
context.engineType = m_engine->objectName();
|
||||||
context.fileName = document->filePath().toString();
|
context.fileName = document->filePath();
|
||||||
context.position = pos;
|
context.position = pos;
|
||||||
editorWidget->convertPosition(pos, &context.line, &context.column);
|
editorWidget->convertPosition(pos, &context.line, &context.column);
|
||||||
QString raw = cppExpressionAt(editorWidget, context.position, &context.line, &context.column,
|
QString raw = cppExpressionAt(editorWidget, context.position, &context.line, &context.column,
|
||||||
|
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include "debuggerconstants.h"
|
#include "debuggerconstants.h"
|
||||||
|
|
||||||
|
#include <utils/filepath.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDate>
|
#include <QDate>
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
@@ -46,7 +48,7 @@ public:
|
|||||||
bool isSame(const DebuggerToolTipContext &other) const;
|
bool isSame(const DebuggerToolTipContext &other) const;
|
||||||
QString toolTip() const;
|
QString toolTip() const;
|
||||||
|
|
||||||
QString fileName;
|
Utils::FilePath fileName;
|
||||||
int position;
|
int position;
|
||||||
int line;
|
int line;
|
||||||
int column;
|
int column;
|
||||||
|
@@ -346,11 +346,11 @@ void PdbEngine::refreshState(const GdbMi &reportedState)
|
|||||||
void PdbEngine::refreshLocation(const GdbMi &reportedLocation)
|
void PdbEngine::refreshLocation(const GdbMi &reportedLocation)
|
||||||
{
|
{
|
||||||
StackFrame frame;
|
StackFrame frame;
|
||||||
frame.file = reportedLocation["file"].data();
|
frame.file = Utils::FilePath::fromString(reportedLocation["file"].data());
|
||||||
frame.line = reportedLocation["line"].toInt();
|
frame.line = reportedLocation["line"].toInt();
|
||||||
frame.usable = QFileInfo(frame.file).isReadable();
|
frame.usable = frame.file.isReadableFile();
|
||||||
if (state() == InferiorRunOk) {
|
if (state() == InferiorRunOk) {
|
||||||
showMessage(QString("STOPPED AT: %1:%2").arg(frame.file).arg(frame.line));
|
showMessage(QString("STOPPED AT: %1:%2").arg(frame.file.toUserOutput()).arg(frame.line));
|
||||||
gotoLocation(frame);
|
gotoLocation(frame);
|
||||||
notifyInferiorSpontaneousStop();
|
notifyInferiorSpontaneousStop();
|
||||||
updateAll();
|
updateAll();
|
||||||
@@ -535,7 +535,7 @@ void PdbEngine::refreshStack(const GdbMi &stack)
|
|||||||
for (const GdbMi &item : stack["frames"]) {
|
for (const GdbMi &item : stack["frames"]) {
|
||||||
StackFrame frame;
|
StackFrame frame;
|
||||||
frame.level = item["level"].data();
|
frame.level = item["level"].data();
|
||||||
frame.file = item["file"].data();
|
frame.file = Utils::FilePath::fromString(item["file"].data());
|
||||||
frame.function = item["function"].data();
|
frame.function = item["function"].data();
|
||||||
frame.module = item["function"].data();
|
frame.module = item["function"].data();
|
||||||
frame.line = item["line"].toInt();
|
frame.line = item["line"].toInt();
|
||||||
@@ -544,7 +544,7 @@ void PdbEngine::refreshStack(const GdbMi &stack)
|
|||||||
if (usable.isValid())
|
if (usable.isValid())
|
||||||
frame.usable = usable.data().toInt();
|
frame.usable = usable.data().toInt();
|
||||||
else
|
else
|
||||||
frame.usable = QFileInfo(frame.file).isReadable();
|
frame.usable = frame.file.isReadableFile();
|
||||||
frames.append(frame);
|
frames.append(frame);
|
||||||
}
|
}
|
||||||
bool canExpand = stack["hasmore"].toInt();
|
bool canExpand = stack["hasmore"].toInt();
|
||||||
|
@@ -2036,8 +2036,9 @@ StackFrame QmlEnginePrivate::extractStackFrame(const QVariant &bodyVal)
|
|||||||
stackFrame.function = extractString(body.value("func"));
|
stackFrame.function = extractString(body.value("func"));
|
||||||
if (stackFrame.function.isEmpty())
|
if (stackFrame.function.isEmpty())
|
||||||
stackFrame.function = QCoreApplication::translate("QmlEngine", "Anonymous Function");
|
stackFrame.function = QCoreApplication::translate("QmlEngine", "Anonymous Function");
|
||||||
stackFrame.file = engine->toFileInProject(extractString(body.value("script")));
|
stackFrame.file = FilePath::fromString(
|
||||||
stackFrame.usable = QFileInfo(stackFrame.file).isReadable();
|
engine->toFileInProject(extractString(body.value("script"))));
|
||||||
|
stackFrame.usable = stackFrame.file.isReadableFile();
|
||||||
stackFrame.receiver = extractString(body.value("receiver"));
|
stackFrame.receiver = extractString(body.value("receiver"));
|
||||||
stackFrame.line = body.value("line").toInt() + 1;
|
stackFrame.line = body.value("line").toInt() + 1;
|
||||||
|
|
||||||
|
@@ -134,7 +134,7 @@ void SourceAgent::updateLocationMarker()
|
|||||||
d->editor->textDocument()->removeMark(d->locationMark);
|
d->editor->textDocument()->removeMark(d->locationMark);
|
||||||
delete d->locationMark;
|
delete d->locationMark;
|
||||||
d->locationMark = nullptr;
|
d->locationMark = nullptr;
|
||||||
if (d->engine->stackHandler()->currentFrame().file == d->path) {
|
if (d->engine->stackHandler()->currentFrame().file == Utils::FilePath::fromString(d->path)) {
|
||||||
int lineNumber = d->engine->stackHandler()->currentFrame().line;
|
int lineNumber = d->engine->stackHandler()->currentFrame().line;
|
||||||
|
|
||||||
d->locationMark = new TextMark(Utils::FilePath(), lineNumber,
|
d->locationMark = new TextMark(Utils::FilePath(), lineNumber,
|
||||||
|
@@ -190,7 +190,7 @@ static void blockRecursion(const Overview &overview,
|
|||||||
|
|
||||||
QStringList getUninitializedVariables(const Snapshot &snapshot,
|
QStringList getUninitializedVariables(const Snapshot &snapshot,
|
||||||
const QString &functionName,
|
const QString &functionName,
|
||||||
const QString &file,
|
const FilePath &file,
|
||||||
int line)
|
int line)
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
@@ -33,6 +33,7 @@ class TextDocument;
|
|||||||
class TextEditorWidget;
|
class TextEditorWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Utils { class FilePath; }
|
||||||
namespace CPlusPlus { class Snapshot; }
|
namespace CPlusPlus { class Snapshot; }
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
@@ -52,7 +53,7 @@ QString cppFunctionAt(const QString &fileName, int line, int column = 0);
|
|||||||
// of a function from the code model. Shadowed variables will
|
// of a function from the code model. Shadowed variables will
|
||||||
// be reported using the debugger naming conventions '<shadowed n>'
|
// be reported using the debugger naming conventions '<shadowed n>'
|
||||||
QStringList getUninitializedVariables(const CPlusPlus::Snapshot &snapshot,
|
QStringList getUninitializedVariables(const CPlusPlus::Snapshot &snapshot,
|
||||||
const QString &function, const QString &file, int line);
|
const QString &function, const Utils::FilePath &file, int line);
|
||||||
|
|
||||||
ContextData getLocationContext(TextEditor::TextDocument *document, int lineNumber);
|
ContextData getLocationContext(TextEditor::TextDocument *document, int lineNumber);
|
||||||
|
|
||||||
|
@@ -35,6 +35,8 @@
|
|||||||
|
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -93,7 +95,8 @@ StackFrame StackFrame::parseFrame(const GdbMi &frameMi, const DebuggerRunParamet
|
|||||||
frame.level = frameMi["level"].data();
|
frame.level = frameMi["level"].data();
|
||||||
frame.function = frameMi["function"].data();
|
frame.function = frameMi["function"].data();
|
||||||
frame.module = frameMi["module"].data();
|
frame.module = frameMi["module"].data();
|
||||||
frame.file = frameMi["file"].data();
|
const FilePath debugger = rp.debugger.command.executable();
|
||||||
|
frame.file = FilePath::fromString(frameMi["file"].data()).onDevice(debugger);
|
||||||
frame.line = frameMi["line"].toInt();
|
frame.line = frameMi["line"].toInt();
|
||||||
frame.address = frameMi["address"].toAddress();
|
frame.address = frameMi["address"].toAddress();
|
||||||
frame.context = frameMi["context"].data();
|
frame.context = frameMi["context"].data();
|
||||||
@@ -107,13 +110,13 @@ StackFrame StackFrame::parseFrame(const GdbMi &frameMi, const DebuggerRunParamet
|
|||||||
if (usable.isValid())
|
if (usable.isValid())
|
||||||
frame.usable = usable.data().toInt();
|
frame.usable = usable.data().toInt();
|
||||||
else
|
else
|
||||||
frame.usable = QFileInfo(frame.file).isReadable();
|
frame.usable = frame.file.isReadableFile();
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString StackFrame::toToolTip() const
|
QString StackFrame::toToolTip() const
|
||||||
{
|
{
|
||||||
const QString filePath = QDir::toNativeSeparators(file);
|
const QString filePath = file.toUserOutput();
|
||||||
QString res;
|
QString res;
|
||||||
QTextStream str(&res);
|
QTextStream str(&res);
|
||||||
str << "<html><body><table>";
|
str << "<html><body><table>";
|
||||||
@@ -150,7 +153,7 @@ QString StackFrame::toToolTip() const
|
|||||||
"frame. However, matching sources have not been found.");
|
"frame. However, matching sources have not been found.");
|
||||||
showDistributionNote = true;
|
showDistributionNote = true;
|
||||||
}
|
}
|
||||||
if (!Utils::HostOsInfo::isWindowsHost() && showDistributionNote) {
|
if (file.osType() != OsTypeWindows && showDistributionNote) {
|
||||||
str << ' ' << tr("Note that most distributions ship debug information "
|
str << ' ' << tr("Note that most distributions ship debug information "
|
||||||
"in separate packages.");
|
"in separate packages.");
|
||||||
}
|
}
|
||||||
@@ -159,19 +162,14 @@ QString StackFrame::toToolTip() const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString findFile(const QString &baseDir, const QString &relativeFile)
|
static FilePath findFile(const FilePath &baseDir, const FilePath &relativeFile)
|
||||||
{
|
{
|
||||||
QDir dir(baseDir);
|
for (FilePath dir(baseDir); !dir.isEmpty(); dir = dir.parentDir()) {
|
||||||
while (true) {
|
const FilePath absolutePath = dir.resolvePath(relativeFile);
|
||||||
const QString path = dir.absoluteFilePath(relativeFile);
|
if (absolutePath.isFile())
|
||||||
const QFileInfo fi(path);
|
return absolutePath;
|
||||||
if (fi.isFile())
|
|
||||||
return path;
|
|
||||||
if (dir.isRoot())
|
|
||||||
break;
|
|
||||||
dir.cdUp();
|
|
||||||
}
|
}
|
||||||
return QString();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to resolve files coming from resource files.
|
// Try to resolve files coming from resource files.
|
||||||
@@ -179,21 +177,23 @@ void StackFrame::fixQrcFrame(const DebuggerRunParameters &rp)
|
|||||||
{
|
{
|
||||||
if (language != QmlLanguage)
|
if (language != QmlLanguage)
|
||||||
return;
|
return;
|
||||||
QFileInfo aFi(file);
|
if (file.isAbsolutePath()) {
|
||||||
if (aFi.isAbsolute()) {
|
usable = file.isFile();
|
||||||
usable = aFi.isFile();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!file.startsWith("qrc:/"))
|
if (!file.startsWith("qrc:/"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QString relativeFile = file.right(file.size() - 5);
|
FilePath relativeFile = file;
|
||||||
while (relativeFile.startsWith('/'))
|
QString relativePath = file.path();
|
||||||
relativeFile = relativeFile.mid(1);
|
relativePath = relativePath.right(relativePath.size() - 5);
|
||||||
|
while (relativePath.startsWith('/'))
|
||||||
|
relativePath = relativePath.mid(1);
|
||||||
|
relativeFile.setPath(relativePath);
|
||||||
|
|
||||||
QString absFile = findFile(rp.projectSourceDirectory.toString(), relativeFile);
|
FilePath absFile = findFile(rp.projectSourceDirectory, relativeFile);
|
||||||
if (absFile.isEmpty())
|
if (absFile.isEmpty())
|
||||||
absFile = findFile(QDir::currentPath(), relativeFile);
|
absFile = findFile(FilePath::fromString(QDir::currentPath()), relativeFile);
|
||||||
|
|
||||||
if (absFile.isEmpty())
|
if (absFile.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include "debuggerconstants.h"
|
#include "debuggerconstants.h"
|
||||||
|
|
||||||
|
#include <utils/filepath.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ public:
|
|||||||
DebuggerLanguage language = CppLanguage;
|
DebuggerLanguage language = CppLanguage;
|
||||||
QString level;
|
QString level;
|
||||||
QString function;
|
QString function;
|
||||||
QString file; // We try to put an absolute file name in there.
|
Utils::FilePath file;// We try to put an absolute file name in there.
|
||||||
QString module; // Sometimes something like "/usr/lib/libstdc++.so.6"
|
QString module; // Sometimes something like "/usr/lib/libstdc++.so.6"
|
||||||
QString receiver; // Used in ScriptEngine only.
|
QString receiver; // Used in ScriptEngine only.
|
||||||
qint32 line = -1;
|
qint32 line = -1;
|
||||||
|
@@ -101,7 +101,7 @@ QVariant StackFrameItem::data(int column, int role) const
|
|||||||
case StackFunctionNameColumn:
|
case StackFunctionNameColumn:
|
||||||
return simplifyType(frame.function);
|
return simplifyType(frame.function);
|
||||||
case StackFileNameColumn:
|
case StackFileNameColumn:
|
||||||
return frame.file.isEmpty() ? frame.module : FilePath::fromString(frame.file).fileName();
|
return frame.file.isEmpty() ? frame.module : frame.file.fileName();
|
||||||
case StackLineNumberColumn:
|
case StackLineNumberColumn:
|
||||||
return frame.line > 0 ? QVariant(frame.line) : QVariant();
|
return frame.line > 0 ? QVariant(frame.line) : QVariant();
|
||||||
case StackAddressColumn:
|
case StackAddressColumn:
|
||||||
|
@@ -4,12 +4,7 @@ add_qtc_plugin(Docker
|
|||||||
docker_global.h
|
docker_global.h
|
||||||
dockerbuildstep.cpp dockerbuildstep.h
|
dockerbuildstep.cpp dockerbuildstep.h
|
||||||
dockerconstants.h
|
dockerconstants.h
|
||||||
dockerdevice.cpp
|
dockerdevice.cpp dockerdevice.h
|
||||||
dockerdevice.h
|
dockerplugin.cpp dockerplugin.h
|
||||||
dockerplugin.cpp
|
dockersettings.cpp dockersettings.h
|
||||||
dockerplugin.h
|
|
||||||
dockerrunconfiguration.cpp
|
|
||||||
dockerrunconfiguration.h
|
|
||||||
dockersettings.cpp
|
|
||||||
dockersettings.h
|
|
||||||
)
|
)
|
||||||
|
@@ -6,7 +6,6 @@ SOURCES += \
|
|||||||
dockerbuildstep.cpp \
|
dockerbuildstep.cpp \
|
||||||
dockerdevice.cpp \
|
dockerdevice.cpp \
|
||||||
dockerplugin.cpp \
|
dockerplugin.cpp \
|
||||||
dockerrunconfiguration.cpp \
|
|
||||||
dockersettings.cpp
|
dockersettings.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
@@ -15,5 +14,4 @@ HEADERS += \
|
|||||||
dockerconstants.h \
|
dockerconstants.h \
|
||||||
dockerdevice.h \
|
dockerdevice.h \
|
||||||
dockerplugin.h \
|
dockerplugin.h \
|
||||||
dockerrunconfiguration.h \
|
|
||||||
dockersettings.h
|
dockersettings.h
|
||||||
|
@@ -19,8 +19,6 @@ QtcPlugin {
|
|||||||
"dockerdevice.cpp",
|
"dockerdevice.cpp",
|
||||||
"dockerplugin.h",
|
"dockerplugin.h",
|
||||||
"dockerplugin.cpp",
|
"dockerplugin.cpp",
|
||||||
"dockerrunconfiguration.h",
|
|
||||||
"dockerrunconfiguration.cpp",
|
|
||||||
"dockersettings.h",
|
"dockersettings.h",
|
||||||
"dockersettings.cpp"
|
"dockersettings.cpp"
|
||||||
]
|
]
|
||||||
|
@@ -29,11 +29,9 @@
|
|||||||
|
|
||||||
#include "dockerbuildstep.h"
|
#include "dockerbuildstep.h"
|
||||||
#include "dockerdevice.h"
|
#include "dockerdevice.h"
|
||||||
#include "dockerrunconfiguration.h"
|
|
||||||
#include "dockersettings.h"
|
#include "dockersettings.h"
|
||||||
|
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/runcontrol.h>
|
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
@@ -49,13 +47,6 @@ public:
|
|||||||
// DockerOptionsPage optionsPage{&settings};
|
// DockerOptionsPage optionsPage{&settings};
|
||||||
|
|
||||||
DockerDeviceFactory deviceFactory;
|
DockerDeviceFactory deviceFactory;
|
||||||
// DockerContainerRunConfigurationFactory containerRunConfigFactory;
|
|
||||||
|
|
||||||
// RunWorkerFactory containerRunWorkerFactory{
|
|
||||||
// RunWorkerFactory::make<SimpleTargetRunner>(),
|
|
||||||
// {ProjectExplorer::Constants::NORMAL_RUN_MODE},
|
|
||||||
// {containerRunConfigFactory.runConfigurationId()}
|
|
||||||
// };
|
|
||||||
|
|
||||||
// DockerBuildStepFactory buildStepFactory;
|
// DockerBuildStepFactory buildStepFactory;
|
||||||
Utils::optional<bool> daemonRunning;
|
Utils::optional<bool> daemonRunning;
|
||||||
|
@@ -1,126 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "dockerrunconfiguration.h"
|
|
||||||
|
|
||||||
#include "dockerconstants.h"
|
|
||||||
#include "dockerdevice.h"
|
|
||||||
|
|
||||||
#include <projectexplorer/kitinformation.h>
|
|
||||||
#include <projectexplorer/project.h>
|
|
||||||
#include <projectexplorer/runconfigurationaspects.h>
|
|
||||||
#include <projectexplorer/runcontrol.h>
|
|
||||||
#include <projectexplorer/target.h>
|
|
||||||
|
|
||||||
#include <utils/stringutils.h>
|
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
using namespace Utils;
|
|
||||||
|
|
||||||
namespace Docker {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class DockerContainerRunConfiguration : public RunConfiguration
|
|
||||||
{
|
|
||||||
Q_DECLARE_TR_FUNCTIONS(Docker::Internal::DockerRunConfiguration)
|
|
||||||
|
|
||||||
public:
|
|
||||||
DockerContainerRunConfiguration(Target *target, Id id)
|
|
||||||
: RunConfiguration(target, id)
|
|
||||||
{
|
|
||||||
auto rmOption = addAspect<BoolAspect>();
|
|
||||||
rmOption->setSettingsKey("Docker.RunConfiguration.RmOption");
|
|
||||||
rmOption->setDefaultValue(true);
|
|
||||||
rmOption->setLabelText(tr("Automatically remove the container when it exits"));
|
|
||||||
|
|
||||||
auto ttyOption = addAspect<BoolAspect>();
|
|
||||||
ttyOption->setSettingsKey("Docker.RunConfiguration.TtyOption");
|
|
||||||
ttyOption->setLabelText(tr("Allocate a pseudo-TTY"));
|
|
||||||
ttyOption->setVisible(false); // Not yet.
|
|
||||||
|
|
||||||
auto interactiveOption = addAspect<BoolAspect>();
|
|
||||||
interactiveOption->setSettingsKey("Docker.RunConfiguration.InteractiveOption");
|
|
||||||
interactiveOption->setLabelText(tr("Keep STDIN open even if not attached"));
|
|
||||||
interactiveOption->setVisible(false); // Not yet.
|
|
||||||
|
|
||||||
auto effectiveCommand = addAspect<StringAspect>();
|
|
||||||
effectiveCommand->setLabelText(tr("Effective command call:"));
|
|
||||||
effectiveCommand->setDisplayStyle(StringAspect::TextEditDisplay);
|
|
||||||
effectiveCommand->setReadOnly(true);
|
|
||||||
|
|
||||||
setUpdater([this, effectiveCommand] {
|
|
||||||
IDevice::ConstPtr device = DeviceKitAspect::device(kit());
|
|
||||||
QTC_ASSERT(device, return);
|
|
||||||
DockerDevice::ConstPtr dockerDevice = qSharedPointerCast<const DockerDevice>(device);
|
|
||||||
QTC_ASSERT(dockerDevice, return);
|
|
||||||
const DockerDeviceData &data = dockerDevice->data();
|
|
||||||
|
|
||||||
const Runnable r = runnable();
|
|
||||||
const QStringList dockerRunFlags = r.extraData[Constants::DOCKER_RUN_FLAGS].toStringList();
|
|
||||||
|
|
||||||
CommandLine cmd("docker");
|
|
||||||
cmd.addArg("run");
|
|
||||||
cmd.addArgs(dockerRunFlags);
|
|
||||||
cmd.addArg(data.imageId);
|
|
||||||
|
|
||||||
// FIXME: the global one above is apparently not sufficient.
|
|
||||||
effectiveCommand->setReadOnly(true);
|
|
||||||
effectiveCommand->setValue(cmd.toUserOutput());
|
|
||||||
});
|
|
||||||
|
|
||||||
setRunnableModifier([rmOption, interactiveOption, ttyOption](Runnable &runnable) {
|
|
||||||
QStringList runArgs;
|
|
||||||
if (!rmOption->value())
|
|
||||||
runArgs.append("--rm=false");
|
|
||||||
if (interactiveOption->value())
|
|
||||||
runArgs.append("--interactive");
|
|
||||||
if (ttyOption->value())
|
|
||||||
runArgs.append("--tty");
|
|
||||||
runnable.extraData[Constants::DOCKER_RUN_FLAGS].toStringList();
|
|
||||||
});
|
|
||||||
|
|
||||||
setCommandLineGetter([] {
|
|
||||||
return CommandLine();
|
|
||||||
});
|
|
||||||
|
|
||||||
update();
|
|
||||||
connect(rmOption, &BaseAspect::changed, this, &RunConfiguration::update);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool isEnabled() const override { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
DockerContainerRunConfigurationFactory::DockerContainerRunConfigurationFactory() :
|
|
||||||
FixedRunConfigurationFactory(DockerContainerRunConfiguration::tr("Docker Container"))
|
|
||||||
{
|
|
||||||
registerRunConfiguration<DockerContainerRunConfiguration>
|
|
||||||
("Docker.DockerContainerRunConfiguration");
|
|
||||||
addSupportedTargetDeviceType(Constants::DOCKER_DEVICE_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Internal
|
|
||||||
} // Docker
|
|
@@ -479,12 +479,18 @@ void IosConfigurations::loadProvisioningData(bool notify)
|
|||||||
QList<QVariantMap> teams;
|
QList<QVariantMap> teams;
|
||||||
for (auto accountiterator = teamMap.cbegin(), end = teamMap.cend();
|
for (auto accountiterator = teamMap.cbegin(), end = teamMap.cend();
|
||||||
accountiterator != end; ++accountiterator) {
|
accountiterator != end; ++accountiterator) {
|
||||||
QVariantMap teamInfo = accountiterator.value().toMap();
|
// difference between Qt 5 (map) and Qt 6 (list of maps)
|
||||||
|
const bool isList = accountiterator->userType() == QMetaType::QVariantList;
|
||||||
|
const QVariantList teamsList = isList ? accountiterator.value().toList()
|
||||||
|
: QVariantList({accountiterator.value()});
|
||||||
|
for (const QVariant &teamInfoIt : teamsList) {
|
||||||
|
QVariantMap teamInfo = teamInfoIt.toMap();
|
||||||
int provisioningTeamIsFree = teamInfo.value(freeTeamTag).toBool() ? 1 : 0;
|
int provisioningTeamIsFree = teamInfo.value(freeTeamTag).toBool() ? 1 : 0;
|
||||||
teamInfo[freeTeamTag] = provisioningTeamIsFree;
|
teamInfo[freeTeamTag] = provisioningTeamIsFree;
|
||||||
teamInfo[emailTag] = accountiterator.key();
|
teamInfo[emailTag] = accountiterator.key();
|
||||||
teams.append(teamInfo);
|
teams.append(teamInfo);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Sort team id's to move the free provisioning teams at last of the list.
|
// Sort team id's to move the free provisioning teams at last of the list.
|
||||||
Utils::sort(teams, [](const QVariantMap &teamInfo1, const QVariantMap &teamInfo2) {
|
Utils::sort(teams, [](const QVariantMap &teamInfo1, const QVariantMap &teamInfo2) {
|
||||||
|
@@ -12,4 +12,5 @@ add_qtc_plugin(McuSupport
|
|||||||
mcusupportsdk.cpp mcusupportsdk.h
|
mcusupportsdk.cpp mcusupportsdk.h
|
||||||
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
|
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
|
||||||
mcusupportversiondetection.cpp mcusupportversiondetection.h
|
mcusupportversiondetection.cpp mcusupportversiondetection.h
|
||||||
|
mcusupportcmakemapper.cpp mcusupportcmakemapper.h
|
||||||
)
|
)
|
||||||
|
@@ -13,7 +13,8 @@ HEADERS += \
|
|||||||
mcusupportplugin.h \
|
mcusupportplugin.h \
|
||||||
mcusupportsdk.h \
|
mcusupportsdk.h \
|
||||||
mcusupportrunconfiguration.h \
|
mcusupportrunconfiguration.h \
|
||||||
mcusupportversiondetection.h
|
mcusupportversiondetection.h \
|
||||||
|
mcusupportcmakemapper.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
mcusupportdevice.cpp \
|
mcusupportdevice.cpp \
|
||||||
@@ -22,7 +23,8 @@ SOURCES += \
|
|||||||
mcusupportplugin.cpp \
|
mcusupportplugin.cpp \
|
||||||
mcusupportsdk.cpp \
|
mcusupportsdk.cpp \
|
||||||
mcusupportrunconfiguration.cpp \
|
mcusupportrunconfiguration.cpp \
|
||||||
mcusupportversiondetection.cpp
|
mcusupportversiondetection.cpp \
|
||||||
|
mcusupportcmakemapper.cpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
mcusupport.qrc
|
mcusupport.qrc
|
||||||
|
@@ -32,5 +32,7 @@ QtcPlugin {
|
|||||||
"mcusupportrunconfiguration.h",
|
"mcusupportrunconfiguration.h",
|
||||||
"mcusupportversiondetection.cpp",
|
"mcusupportversiondetection.cpp",
|
||||||
"mcusupportversiondetection.h",
|
"mcusupportversiondetection.h",
|
||||||
|
"mcusupportcmakemapper.h",
|
||||||
|
"mcusupportcmakemapper.cpp"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
76
src/plugins/mcusupport/mcusupportcmakemapper.cpp
Normal file
76
src/plugins/mcusupport/mcusupportcmakemapper.cpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "mcusupportcmakemapper.h"
|
||||||
|
#include "utils/namevalueitem.h"
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const QHash<QString, QString> &envVarToCMakeVarMapping()
|
||||||
|
{
|
||||||
|
static const QHash<QString, QString> mapping = {
|
||||||
|
{"EVK_MIMXRT1060_SDK_PATH","QUL_BOARD_SDK_DIR"},
|
||||||
|
{"EVK_MIMXRT1064_SDK_PATH","QUL_BOARD_SDK_DIR"},
|
||||||
|
{"EVK_MIMXRT595_SDK_PATH","QUL_BOARD_SDK_DIR"},
|
||||||
|
{"EVK_MIMXRT1170_SDK_PATH","QUL_BOARD_SDK_DIR"},
|
||||||
|
{"EVKB_IMXRT1050_SDK_PATH","QUL_BOARD_SDK_DIR"},
|
||||||
|
{"STM32Cube_FW_F7_SDK_PATH","QUL_BOARD_SDK_DIR"},
|
||||||
|
{"STM32Cube_FW_F4_SDK_PATH","QUL_BOARD_SDK_DIR"},
|
||||||
|
{"STM32Cube_FW_L4_SDK_PATH","QUL_BOARD_SDK_DIR"},
|
||||||
|
{"STM32Cube_FW_H7_SDK_PATH","QUL_BOARD_SDK_DIR"},
|
||||||
|
{"ARMGCC_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
|
||||||
|
{"IAR_ARM_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
|
||||||
|
{"GHS_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
|
||||||
|
{"GHS_ARM_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
|
||||||
|
{"EVK_MIMXRT1170_FREERTOS_PATH","FREERTOS_DIR"},
|
||||||
|
{"EVK_MIMXRT1170_FREERTOS_PATH","FREERTOS_DIR"},
|
||||||
|
{"IMXRT1064_FREERTOS_DIR","FREERTOS_DIR"},
|
||||||
|
{"IMXRT595_FREERTOS_DIR","FREERTOS_DIR"},
|
||||||
|
{"STM32F7_FREERTOS_DIR", "FREERTOS_DIR"},
|
||||||
|
{"eFlashLoad_PATH","eFlashLoad_PATH"},
|
||||||
|
{"RenesasFlashProgrammer_PATH", "RenesasFlashProgrammer_PATH"},
|
||||||
|
{"MCUXpressoIDE_PATH", "MCUXpressoIDE_PATH"},
|
||||||
|
{"JLINK_PATH", "JLINK_PATH"},
|
||||||
|
{"TVII_GRAPHICS_DRIVER_DIR", "TVII_GRAPHICS_DRIVER_DIR"},
|
||||||
|
{"CYPRESS_AUTO_FLASH_UTILITY_DIR", "CYPRESS_AUTO_FLASH_UTILITY_DIR"},
|
||||||
|
{"EK_RA6M3G_E2_PROJECT_PATH", "EK_RA6M3G_E2_PROJECT_PATH"},
|
||||||
|
{"EK_RA6M3G_FSP_PATH", "EK_RA6M3G_FSP_PATH"},
|
||||||
|
};
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
QList<CMakeProjectManager::CMakeConfigItem> McuSupport::Internal::mapEnvVarsToQul2xCmakeVars(
|
||||||
|
const Utils::EnvironmentItems &envVars)
|
||||||
|
{
|
||||||
|
const auto &mapping = envVarToCMakeVarMapping();
|
||||||
|
auto cmakeVars = Utils::transform(envVars, [mapping](const Utils::EnvironmentItem &envVar) {
|
||||||
|
return CMakeProjectManager::CMakeConfigItem(mapping.value(envVar.name, "").toUtf8(), envVar.value.toUtf8());
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
return Utils::filtered(cmakeVars, [](const CMakeProjectManager::CMakeConfigItem &item) {
|
||||||
|
return !item.key.isEmpty();
|
||||||
|
});
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of Qt Creator.
|
** This file is part of Qt Creator.
|
||||||
@@ -22,20 +22,14 @@
|
|||||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <projectexplorer/runconfiguration.h>
|
#include "cmakeprojectmanager/cmakeconfigitem.h"
|
||||||
|
#include "utils/environmentfwd.h"
|
||||||
|
|
||||||
namespace Docker {
|
namespace McuSupport {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
QList<CMakeProjectManager::CMakeConfigItem> mapEnvVarsToQul2xCmakeVars(
|
||||||
class DockerContainerRunConfigurationFactory
|
const Utils::EnvironmentItems &envVars);
|
||||||
: public ProjectExplorer::FixedRunConfigurationFactory
|
}
|
||||||
{
|
} // namespace McuSupport
|
||||||
public:
|
|
||||||
DockerContainerRunConfigurationFactory();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // Internal
|
|
||||||
} // Docker
|
|
@@ -27,6 +27,7 @@
|
|||||||
#include "mcusupportoptions.h"
|
#include "mcusupportoptions.h"
|
||||||
#include "mcusupportsdk.h"
|
#include "mcusupportsdk.h"
|
||||||
#include "mcusupportplugin.h"
|
#include "mcusupportplugin.h"
|
||||||
|
#include "mcusupportcmakemapper.h"
|
||||||
|
|
||||||
#include <baremetal/baremetalconstants.h>
|
#include <baremetal/baremetalconstants.h>
|
||||||
#include <cmakeprojectmanager/cmaketoolmanager.h>
|
#include <cmakeprojectmanager/cmaketoolmanager.h>
|
||||||
@@ -70,7 +71,7 @@ using namespace Utils;
|
|||||||
namespace McuSupport {
|
namespace McuSupport {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
static const int KIT_VERSION = 8; // Bumps up whenever details in Kit creation change
|
static const int KIT_VERSION = 9; // Bumps up whenever details in Kit creation change
|
||||||
|
|
||||||
static FilePath packagePathFromSettings(const QString &settingsKey,
|
static FilePath packagePathFromSettings(const QString &settingsKey,
|
||||||
QSettings::Scope scope = QSettings::UserScope,
|
QSettings::Scope scope = QSettings::UserScope,
|
||||||
@@ -99,6 +100,22 @@ static bool kitNeedsQtVersion()
|
|||||||
return !HostOsInfo::isWindowsHost();
|
return !HostOsInfo::isWindowsHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems)
|
||||||
|
{
|
||||||
|
using namespace CMakeProjectManager;
|
||||||
|
const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems);
|
||||||
|
const auto cmakeVarNames = Utils::transform(cmakeVars, &CMakeConfigItem::key);
|
||||||
|
|
||||||
|
// First filter out all Qul2.x CMake vars
|
||||||
|
auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit),
|
||||||
|
[&](const auto &configItem) {
|
||||||
|
return !cmakeVarNames.contains(configItem.key);
|
||||||
|
});
|
||||||
|
// Then append them with new values
|
||||||
|
config.append(cmakeVars);
|
||||||
|
CMakeConfigurationKitAspect::setConfiguration(kit, config);
|
||||||
|
}
|
||||||
|
|
||||||
McuPackage::McuPackage(const QString &label, const FilePath &defaultPath,
|
McuPackage::McuPackage(const QString &label, const FilePath &defaultPath,
|
||||||
const QString &detectionPath, const QString &settingsKey,
|
const QString &detectionPath, const QString &settingsKey,
|
||||||
const McuPackageVersionDetector *versionDetector)
|
const McuPackageVersionDetector *versionDetector)
|
||||||
@@ -231,7 +248,7 @@ bool McuPackage::writeToSettings() const
|
|||||||
const FilePath savedPath = packagePathFromSettings(m_settingsKey, QSettings::UserScope, m_defaultPath);
|
const FilePath savedPath = packagePathFromSettings(m_settingsKey, QSettings::UserScope, m_defaultPath);
|
||||||
const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' +
|
const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' +
|
||||||
QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey;
|
QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey;
|
||||||
Core::ICore::settings()->setValueWithDefault(key, m_path, m_defaultPath);
|
Core::ICore::settings()->setValueWithDefault(key, m_path.toString(), m_defaultPath.toString());
|
||||||
|
|
||||||
return savedPath != m_path;
|
return savedPath != m_path;
|
||||||
}
|
}
|
||||||
@@ -573,6 +590,14 @@ void McuTarget::setColorDepth(int colorDepth)
|
|||||||
m_colorDepth = colorDepth;
|
m_colorDepth = colorDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void McuSdkRepository::deletePackagesAndTargets()
|
||||||
|
{
|
||||||
|
qDeleteAll(packages);
|
||||||
|
packages.clear();
|
||||||
|
qDeleteAll(mcuTargets);
|
||||||
|
mcuTargets.clear();
|
||||||
|
}
|
||||||
|
|
||||||
McuSupportOptions::McuSupportOptions(QObject *parent)
|
McuSupportOptions::McuSupportOptions(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, qtForMCUsSdkPackage(Sdk::createQtForMCUsPackage())
|
, qtForMCUsSdkPackage(Sdk::createQtForMCUsPackage())
|
||||||
@@ -635,14 +660,6 @@ void McuSupportOptions::registerExamples()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void McuSupportOptions::deletePackagesAndTargets()
|
|
||||||
{
|
|
||||||
qDeleteAll(packages);
|
|
||||||
packages.clear();
|
|
||||||
qDeleteAll(mcuTargets);
|
|
||||||
mcuTargets.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
const QVersionNumber &McuSupportOptions::minimalQulVersion()
|
const QVersionNumber &McuSupportOptions::minimalQulVersion()
|
||||||
{
|
{
|
||||||
static const QVersionNumber v({1, 3});
|
static const QVersionNumber v({1, 3});
|
||||||
@@ -654,8 +671,8 @@ void McuSupportOptions::setQulDir(const FilePath &dir)
|
|||||||
deletePackagesAndTargets();
|
deletePackagesAndTargets();
|
||||||
qtForMCUsSdkPackage->updateStatus();
|
qtForMCUsSdkPackage->updateStatus();
|
||||||
if (qtForMCUsSdkPackage->validStatus())
|
if (qtForMCUsSdkPackage->validStatus())
|
||||||
Sdk::targetsAndPackages(dir, &packages, &mcuTargets);
|
Sdk::targetsAndPackages(dir, &sdkRepository);
|
||||||
for (auto package : qAsConst(packages))
|
for (const auto &package : qAsConst(sdkRepository.packages))
|
||||||
connect(package, &McuPackage::changed, this, &McuSupportOptions::changed);
|
connect(package, &McuPackage::changed, this, &McuSupportOptions::changed);
|
||||||
|
|
||||||
emit changed();
|
emit changed();
|
||||||
@@ -736,6 +753,11 @@ static void setKitDevice(Kit *k, const McuTarget* mcuTarget)
|
|||||||
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
|
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool expectsCmakeVars(const McuTarget *mcuTarget)
|
||||||
|
{
|
||||||
|
return mcuTarget->qulVersion() >= QVersionNumber{2,0};
|
||||||
|
}
|
||||||
|
|
||||||
static void setKitEnvironment(Kit *k, const McuTarget *mcuTarget,
|
static void setKitEnvironment(Kit *k, const McuTarget *mcuTarget,
|
||||||
const McuPackage *qtForMCUsSdkPackage)
|
const McuPackage *qtForMCUsSdkPackage)
|
||||||
{
|
{
|
||||||
@@ -770,6 +792,11 @@ static void setKitEnvironment(Kit *k, const McuTarget *mcuTarget,
|
|||||||
if (kitNeedsQtVersion())
|
if (kitNeedsQtVersion())
|
||||||
changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"});
|
changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"});
|
||||||
|
|
||||||
|
// Hack, this problem should be solved in lower layer
|
||||||
|
if (expectsCmakeVars(mcuTarget)) {
|
||||||
|
remapQul2xCmakeVars(k, changes);
|
||||||
|
}
|
||||||
|
|
||||||
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
|
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -812,6 +839,11 @@ static void updateKitEnvironment(Kit *k, const McuTarget *mcuTarget)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hack, this problem should be solved in lower layer
|
||||||
|
if (expectsCmakeVars(mcuTarget)) {
|
||||||
|
remapQul2xCmakeVars(k, changes);
|
||||||
|
}
|
||||||
|
|
||||||
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
|
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1015,6 +1047,11 @@ bool McuSupportOptions::kitUpToDate(const Kit *kit, const McuTarget *mcuTarget,
|
|||||||
kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()) == qtForMCUsSdkPackage->path();
|
kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()) == qtForMCUsSdkPackage->path();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void McuSupportOptions::deletePackagesAndTargets()
|
||||||
|
{
|
||||||
|
sdkRepository.deletePackagesAndTargets();
|
||||||
|
}
|
||||||
|
|
||||||
McuSupportOptions::UpgradeOption McuSupportOptions::askForKitUpgrades()
|
McuSupportOptions::UpgradeOption McuSupportOptions::askForKitUpgrades()
|
||||||
{
|
{
|
||||||
QMessageBox upgradePopup(Core::ICore::dialogParent());
|
QMessageBox upgradePopup(Core::ICore::dialogParent());
|
||||||
@@ -1076,12 +1113,11 @@ void McuSupportOptions::createAutomaticKits()
|
|||||||
}
|
}
|
||||||
|
|
||||||
FilePath dir = qtForMCUsPackage->path();
|
FilePath dir = qtForMCUsPackage->path();
|
||||||
QVector<McuPackage*> packages;
|
McuSdkRepository repo;
|
||||||
QVector<McuTarget*> mcuTargets;
|
Sdk::targetsAndPackages(dir, &repo);
|
||||||
Sdk::targetsAndPackages(dir, &packages, &mcuTargets);
|
|
||||||
|
|
||||||
bool needsUpgrade = false;
|
bool needsUpgrade = false;
|
||||||
for (auto target: qAsConst(mcuTargets)) {
|
for (const auto &target: qAsConst(repo.mcuTargets)) {
|
||||||
// if kit already exists, skip
|
// if kit already exists, skip
|
||||||
if (!matchingKits(target, qtForMCUsPackage).empty())
|
if (!matchingKits(target, qtForMCUsPackage).empty())
|
||||||
continue;
|
continue;
|
||||||
@@ -1096,8 +1132,7 @@ void McuSupportOptions::createAutomaticKits()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qDeleteAll(packages);
|
repo.deletePackagesAndTargets();
|
||||||
qDeleteAll(mcuTargets);
|
|
||||||
|
|
||||||
if (needsUpgrade)
|
if (needsUpgrade)
|
||||||
McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade();
|
McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade();
|
||||||
@@ -1110,10 +1145,10 @@ void McuSupportOptions::createAutomaticKits()
|
|||||||
|
|
||||||
void McuSupportOptions::checkUpgradeableKits()
|
void McuSupportOptions::checkUpgradeableKits()
|
||||||
{
|
{
|
||||||
if (!qtForMCUsSdkPackage->validStatus() || mcuTargets.length() == 0)
|
if (!qtForMCUsSdkPackage->validStatus() || sdkRepository.mcuTargets.length() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Utils::anyOf(mcuTargets, [this](const McuTarget *target) {
|
if (Utils::anyOf(sdkRepository.mcuTargets, [this](const McuTarget *target) {
|
||||||
return !upgradeableKits(target, this->qtForMCUsSdkPackage).empty() &&
|
return !upgradeableKits(target, this->qtForMCUsSdkPackage).empty() &&
|
||||||
matchingKits(target, this->qtForMCUsSdkPackage).empty();
|
matchingKits(target, this->qtForMCUsSdkPackage).empty();
|
||||||
}))
|
}))
|
||||||
@@ -1128,11 +1163,10 @@ void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption)
|
|||||||
auto qtForMCUsPackage = Sdk::createQtForMCUsPackage();
|
auto qtForMCUsPackage = Sdk::createQtForMCUsPackage();
|
||||||
|
|
||||||
auto dir = qtForMCUsPackage->path();
|
auto dir = qtForMCUsPackage->path();
|
||||||
QVector<McuPackage*> packages;
|
McuSdkRepository repo;
|
||||||
QVector<McuTarget*> mcuTargets;
|
Sdk::targetsAndPackages(dir, &repo);
|
||||||
Sdk::targetsAndPackages(dir, &packages, &mcuTargets);
|
|
||||||
|
|
||||||
for (auto target: qAsConst(mcuTargets)) {
|
for (const auto &target: qAsConst(repo.mcuTargets)) {
|
||||||
if (!matchingKits(target, qtForMCUsPackage).empty())
|
if (!matchingKits(target, qtForMCUsPackage).empty())
|
||||||
// already up-to-date
|
// already up-to-date
|
||||||
continue;
|
continue;
|
||||||
@@ -1149,8 +1183,7 @@ void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qDeleteAll(packages);
|
repo.deletePackagesAndTargets();
|
||||||
qDeleteAll(mcuTargets);
|
|
||||||
delete qtForMCUsPackage;
|
delete qtForMCUsPackage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1166,10 +1199,9 @@ void McuSupportOptions::fixKitsDependencies()
|
|||||||
auto qtForMCUsPackage = Sdk::createQtForMCUsPackage();
|
auto qtForMCUsPackage = Sdk::createQtForMCUsPackage();
|
||||||
|
|
||||||
FilePath dir = qtForMCUsPackage->path();
|
FilePath dir = qtForMCUsPackage->path();
|
||||||
QVector<McuPackage*> packages;
|
McuSdkRepository repo;
|
||||||
QVector<McuTarget*> mcuTargets;
|
Sdk::targetsAndPackages(dir, &repo);
|
||||||
Sdk::targetsAndPackages(dir, &packages, &mcuTargets);
|
for (const auto &target: qAsConst(repo.mcuTargets)) {
|
||||||
for (auto target: qAsConst(mcuTargets)) {
|
|
||||||
if (target->isValid()) {
|
if (target->isValid()) {
|
||||||
for (auto kit : kitsWithMismatchedDependencies(target)) {
|
for (auto kit : kitsWithMismatchedDependencies(target)) {
|
||||||
updateKitEnvironment(kit, target);
|
updateKitEnvironment(kit, target);
|
||||||
@@ -1177,8 +1209,7 @@ void McuSupportOptions::fixKitsDependencies()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qDeleteAll(packages);
|
repo.deletePackagesAndTargets();
|
||||||
qDeleteAll(mcuTargets);
|
|
||||||
delete qtForMCUsPackage;
|
delete qtForMCUsPackage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1242,18 +1273,16 @@ void McuSupportOptions::fixExistingKits()
|
|||||||
qtForMCUsPackage->updateStatus();
|
qtForMCUsPackage->updateStatus();
|
||||||
if (qtForMCUsPackage->validStatus()) {
|
if (qtForMCUsPackage->validStatus()) {
|
||||||
FilePath dir = qtForMCUsPackage->path();
|
FilePath dir = qtForMCUsPackage->path();
|
||||||
QVector<McuPackage*> packages;
|
McuSdkRepository repo;
|
||||||
QVector<McuTarget*> mcuTargets;
|
Sdk::targetsAndPackages(dir, &repo);
|
||||||
Sdk::targetsAndPackages(dir, &packages, &mcuTargets);
|
for (const auto &target: qAsConst(repo.mcuTargets))
|
||||||
for (auto target: qAsConst(mcuTargets))
|
|
||||||
for (auto kit: existingKits(target)) {
|
for (auto kit: existingKits(target)) {
|
||||||
if (McuDependenciesKitAspect::dependencies(kit).isEmpty()) {
|
if (McuDependenciesKitAspect::dependencies(kit).isEmpty()) {
|
||||||
setKitDependencies(kit, target, qtForMCUsPackage);
|
setKitDependencies(kit, target, qtForMCUsPackage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qDeleteAll(packages);
|
repo.deletePackagesAndTargets();
|
||||||
qDeleteAll(mcuTargets);
|
|
||||||
}
|
}
|
||||||
delete qtForMCUsPackage;
|
delete qtForMCUsPackage;
|
||||||
}
|
}
|
||||||
|
@@ -200,6 +200,15 @@ private:
|
|||||||
int m_colorDepth = -1;
|
int m_colorDepth = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class McuSdkRepository
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QVector<McuPackage*> packages;
|
||||||
|
QVector<McuTarget*> mcuTargets;
|
||||||
|
|
||||||
|
void deletePackagesAndTargets();
|
||||||
|
};
|
||||||
|
|
||||||
class McuSupportOptions : public QObject
|
class McuSupportOptions : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -214,9 +223,8 @@ public:
|
|||||||
McuSupportOptions(QObject *parent = nullptr);
|
McuSupportOptions(QObject *parent = nullptr);
|
||||||
~McuSupportOptions() override;
|
~McuSupportOptions() override;
|
||||||
|
|
||||||
QVector<McuPackage*> packages;
|
|
||||||
QVector<McuTarget*> mcuTargets;
|
|
||||||
McuPackage *qtForMCUsSdkPackage = nullptr;
|
McuPackage *qtForMCUsSdkPackage = nullptr;
|
||||||
|
McuSdkRepository sdkRepository;
|
||||||
|
|
||||||
void setQulDir(const Utils::FilePath &dir);
|
void setQulDir(const Utils::FilePath &dir);
|
||||||
static Utils::FilePath qulDirFromSettings();
|
static Utils::FilePath qulDirFromSettings();
|
||||||
|
@@ -190,7 +190,7 @@ void McuSupportOptionsWidget::updateStatus()
|
|||||||
m_mcuTargetsGroupBox->setVisible(ready);
|
m_mcuTargetsGroupBox->setVisible(ready);
|
||||||
m_packagesGroupBox->setVisible(ready && !mcuTarget->packages().isEmpty());
|
m_packagesGroupBox->setVisible(ready && !mcuTarget->packages().isEmpty());
|
||||||
m_kitCreationGroupBox->setVisible(ready);
|
m_kitCreationGroupBox->setVisible(ready);
|
||||||
m_mcuTargetsInfoLabel->setVisible(valid && m_options.mcuTargets.isEmpty());
|
m_mcuTargetsInfoLabel->setVisible(valid && m_options.sdkRepository.mcuTargets.isEmpty());
|
||||||
if (m_mcuTargetsInfoLabel->isVisible()) {
|
if (m_mcuTargetsInfoLabel->isVisible()) {
|
||||||
m_mcuTargetsInfoLabel->setType(Utils::InfoLabel::NotOk);
|
m_mcuTargetsInfoLabel->setType(Utils::InfoLabel::NotOk);
|
||||||
const Utils::FilePath sdkPath = m_options.qtForMCUsSdkPackage->basePath();
|
const Utils::FilePath sdkPath = m_options.qtForMCUsSdkPackage->basePath();
|
||||||
@@ -261,7 +261,7 @@ void McuSupportOptionsWidget::showMcuTargetPackages()
|
|||||||
row.fieldItem->widget()->hide();
|
row.fieldItem->widget()->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto package : qAsConst(m_options.packages)) {
|
for (auto package : qAsConst(m_options.sdkRepository.packages)) {
|
||||||
QWidget *packageWidget = package->widget();
|
QWidget *packageWidget = package->widget();
|
||||||
if (!mcuTarget->packages().contains(package))
|
if (!mcuTarget->packages().contains(package))
|
||||||
continue;
|
continue;
|
||||||
@@ -275,9 +275,9 @@ void McuSupportOptionsWidget::showMcuTargetPackages()
|
|||||||
McuTarget *McuSupportOptionsWidget::currentMcuTarget() const
|
McuTarget *McuSupportOptionsWidget::currentMcuTarget() const
|
||||||
{
|
{
|
||||||
const int mcuTargetIndex = m_mcuTargetsComboBox->currentIndex();
|
const int mcuTargetIndex = m_mcuTargetsComboBox->currentIndex();
|
||||||
return (mcuTargetIndex == -1 || m_options.mcuTargets.isEmpty())
|
return (mcuTargetIndex == -1 || m_options.sdkRepository.mcuTargets.isEmpty())
|
||||||
? nullptr
|
? nullptr
|
||||||
: m_options.mcuTargets.at(mcuTargetIndex);
|
: m_options.sdkRepository.mcuTargets.at(mcuTargetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void McuSupportOptionsWidget::showEvent(QShowEvent *event)
|
void McuSupportOptionsWidget::showEvent(QShowEvent *event)
|
||||||
@@ -292,7 +292,7 @@ void McuSupportOptionsWidget::apply()
|
|||||||
|
|
||||||
m_options.qtForMCUsSdkPackage->writeGeneralSettings();
|
m_options.qtForMCUsSdkPackage->writeGeneralSettings();
|
||||||
pathsChanged |= m_options.qtForMCUsSdkPackage->writeToSettings();
|
pathsChanged |= m_options.qtForMCUsSdkPackage->writeToSettings();
|
||||||
for (auto package : qAsConst(m_options.packages))
|
for (auto package : qAsConst(m_options.sdkRepository.packages))
|
||||||
pathsChanged |= package->writeToSettings();
|
pathsChanged |= package->writeToSettings();
|
||||||
|
|
||||||
if (pathsChanged) {
|
if (pathsChanged) {
|
||||||
@@ -306,7 +306,7 @@ void McuSupportOptionsWidget::populateMcuTargetsComboBox()
|
|||||||
m_options.populatePackagesAndTargets();
|
m_options.populatePackagesAndTargets();
|
||||||
m_mcuTargetsComboBox->clear();
|
m_mcuTargetsComboBox->clear();
|
||||||
m_mcuTargetsComboBox->addItems(
|
m_mcuTargetsComboBox->addItems(
|
||||||
Utils::transform<QStringList>(m_options.mcuTargets, [](McuTarget *t) {
|
Utils::transform<QStringList>(m_options.sdkRepository.mcuTargets, [](McuTarget *t) {
|
||||||
return McuSupportOptions::kitName(t);
|
return McuSupportOptions::kitName(t);
|
||||||
}));
|
}));
|
||||||
updateStatus();
|
updateStatus();
|
||||||
|
@@ -331,19 +331,28 @@ struct McuTargetDescription
|
|||||||
};
|
};
|
||||||
|
|
||||||
QString qulVersion;
|
QString qulVersion;
|
||||||
QString platform;
|
QString compatVersion;
|
||||||
QString platformName;
|
struct {
|
||||||
QString platformVendor;
|
QString id;
|
||||||
|
QString name;
|
||||||
|
QString vendor;
|
||||||
QVector<int> colorDepths;
|
QVector<int> colorDepths;
|
||||||
QString toolchainId;
|
|
||||||
QVector<QString> toolchainVersions;
|
|
||||||
QString boardSdkEnvVar;
|
|
||||||
QString boardSdkName;
|
|
||||||
QString boardSdkDefaultPath;
|
|
||||||
QVector<QString> boardSdkVersions;
|
|
||||||
QString freeRTOSEnvVar;
|
|
||||||
QString freeRTOSBoardSdkSubDir;
|
|
||||||
TargetType type;
|
TargetType type;
|
||||||
|
} platform;
|
||||||
|
struct {
|
||||||
|
QString id;
|
||||||
|
QVector<QString> versions;
|
||||||
|
} toolchain;
|
||||||
|
struct {
|
||||||
|
QString name;
|
||||||
|
QString defaultPath;
|
||||||
|
QString envVar;
|
||||||
|
QVector<QString> versions;
|
||||||
|
} boardSdk;
|
||||||
|
struct {
|
||||||
|
QString envVar;
|
||||||
|
QString boardSdkSubDir;
|
||||||
|
} freeRTOS;
|
||||||
};
|
};
|
||||||
|
|
||||||
static McuPackageVersionDetector* generatePackageVersionDetector(QString envVar)
|
static McuPackageVersionDetector* generatePackageVersionDetector(QString envVar)
|
||||||
@@ -373,29 +382,29 @@ static McuPackage *createBoardSdkPackage(const McuTargetDescription& desc)
|
|||||||
auto sdkName = postfixPos > 0 ? envVar.left(postfixPos) : envVar;
|
auto sdkName = postfixPos > 0 ? envVar.left(postfixPos) : envVar;
|
||||||
return QString::fromLatin1("MCU SDK (%1)").arg(sdkName);
|
return QString::fromLatin1("MCU SDK (%1)").arg(sdkName);
|
||||||
};
|
};
|
||||||
const QString sdkName = desc.boardSdkName.isEmpty() ? generateSdkName(desc.boardSdkEnvVar) : desc.boardSdkName;
|
const QString sdkName = desc.boardSdk.name.isEmpty() ? generateSdkName(desc.boardSdk.envVar) : desc.boardSdk.name;
|
||||||
|
|
||||||
const FilePath defaultPath = [&] {
|
const FilePath defaultPath = [&] {
|
||||||
const auto envVar = desc.boardSdkEnvVar.toLatin1();
|
const auto envVar = desc.boardSdk.envVar.toLatin1();
|
||||||
if (qEnvironmentVariableIsSet(envVar))
|
if (qEnvironmentVariableIsSet(envVar))
|
||||||
return FilePath::fromUserInput(qEnvironmentVariable(envVar));
|
return FilePath::fromUserInput(qEnvironmentVariable(envVar));
|
||||||
if (!desc.boardSdkDefaultPath.isEmpty()) {
|
if (!desc.boardSdk.defaultPath.isEmpty()) {
|
||||||
FilePath defaultPath = FilePath::fromUserInput(QDir::rootPath() + desc.boardSdkDefaultPath);
|
FilePath defaultPath = FilePath::fromUserInput(QDir::rootPath() + desc.boardSdk.defaultPath);
|
||||||
if (defaultPath.exists())
|
if (defaultPath.exists())
|
||||||
return defaultPath;
|
return defaultPath;
|
||||||
}
|
}
|
||||||
return FileUtils::homePath();
|
return FileUtils::homePath();
|
||||||
}();
|
}();
|
||||||
|
|
||||||
const auto versionDetector = generatePackageVersionDetector(desc.boardSdkEnvVar);
|
const auto versionDetector = generatePackageVersionDetector(desc.boardSdk.envVar);
|
||||||
|
|
||||||
auto result = new McuPackage(
|
auto result = new McuPackage(
|
||||||
sdkName,
|
sdkName,
|
||||||
defaultPath,
|
defaultPath,
|
||||||
{},
|
{},
|
||||||
desc.boardSdkEnvVar,
|
desc.boardSdk.envVar,
|
||||||
versionDetector);
|
versionDetector);
|
||||||
result->setEnvironmentVariableName(desc.boardSdkEnvVar);
|
result->setEnvironmentVariableName(desc.boardSdk.envVar);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +443,7 @@ struct McuTargetFactory
|
|||||||
{
|
{
|
||||||
auto qulVersion = QVersionNumber::fromString(description.qulVersion);
|
auto qulVersion = QVersionNumber::fromString(description.qulVersion);
|
||||||
if (qulVersion <= QVersionNumber({1,3})) {
|
if (qulVersion <= QVersionNumber({1,3})) {
|
||||||
if (description.type == McuTargetDescription::TargetType::Desktop)
|
if (description.platform.type == McuTargetDescription::TargetType::Desktop)
|
||||||
return createDesktopTargetsLegacy(description);
|
return createDesktopTargetsLegacy(description);
|
||||||
|
|
||||||
// There was a platform backends related refactoring in Qul 1.4
|
// There was a platform backends related refactoring in Qul 1.4
|
||||||
@@ -459,44 +468,44 @@ protected:
|
|||||||
QVector<McuTarget *> createMcuTargetsLegacy(const McuTargetDescription &desc)
|
QVector<McuTarget *> createMcuTargetsLegacy(const McuTargetDescription &desc)
|
||||||
{
|
{
|
||||||
QVector<McuTarget *> mcuTargets;
|
QVector<McuTarget *> mcuTargets;
|
||||||
McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchainId);
|
McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id);
|
||||||
if (!tcPkg)
|
if (!tcPkg)
|
||||||
tcPkg = createUnsupportedToolChainPackage();
|
tcPkg = createUnsupportedToolChainPackage();
|
||||||
for (auto os : {McuTarget::OS::BareMetal, McuTarget::OS::FreeRTOS}) {
|
for (auto os : {McuTarget::OS::BareMetal, McuTarget::OS::FreeRTOS}) {
|
||||||
for (int colorDepth : desc.colorDepths) {
|
for (int colorDepth : desc.platform.colorDepths) {
|
||||||
QVector<McuPackage*> required3rdPartyPkgs = { tcPkg };
|
QVector<McuPackage*> required3rdPartyPkgs = { tcPkg };
|
||||||
if (vendorPkgs.contains(desc.platformVendor))
|
if (vendorPkgs.contains(desc.platform.vendor))
|
||||||
required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platformVendor));
|
required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor));
|
||||||
|
|
||||||
FilePath boardSdkDefaultPath;
|
FilePath boardSdkDefaultPath;
|
||||||
if (!desc.boardSdkEnvVar.isEmpty()) {
|
if (!desc.boardSdk.envVar.isEmpty()) {
|
||||||
if (!boardSdkPkgs.contains(desc.boardSdkEnvVar)) {
|
if (!boardSdkPkgs.contains(desc.boardSdk.envVar)) {
|
||||||
auto boardSdkPkg = desc.boardSdkEnvVar != "RGL_DIR"
|
auto boardSdkPkg = desc.boardSdk.envVar != "RGL_DIR"
|
||||||
? createBoardSdkPackage(desc)
|
? createBoardSdkPackage(desc)
|
||||||
: createRGLPackage();
|
: createRGLPackage();
|
||||||
boardSdkPkgs.insert(desc.boardSdkEnvVar, boardSdkPkg);
|
boardSdkPkgs.insert(desc.boardSdk.envVar, boardSdkPkg);
|
||||||
}
|
}
|
||||||
auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdkEnvVar);
|
auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdk.envVar);
|
||||||
boardSdkDefaultPath = boardSdkPkg->defaultPath();
|
boardSdkDefaultPath = boardSdkPkg->defaultPath();
|
||||||
required3rdPartyPkgs.append(boardSdkPkg);
|
required3rdPartyPkgs.append(boardSdkPkg);
|
||||||
}
|
}
|
||||||
if (os == McuTarget::OS::FreeRTOS) {
|
if (os == McuTarget::OS::FreeRTOS) {
|
||||||
if (desc.freeRTOSEnvVar.isEmpty()) {
|
if (desc.freeRTOS.envVar.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
if (!freeRTOSPkgs.contains(desc.freeRTOSEnvVar)) {
|
if (!freeRTOSPkgs.contains(desc.freeRTOS.envVar)) {
|
||||||
freeRTOSPkgs.insert(desc.freeRTOSEnvVar, createFreeRTOSSourcesPackage(
|
freeRTOSPkgs.insert(desc.freeRTOS.envVar, createFreeRTOSSourcesPackage(
|
||||||
desc.freeRTOSEnvVar, boardSdkDefaultPath,
|
desc.freeRTOS.envVar, boardSdkDefaultPath,
|
||||||
desc.freeRTOSBoardSdkSubDir));
|
desc.freeRTOS.boardSdkSubDir));
|
||||||
}
|
}
|
||||||
required3rdPartyPkgs.append(freeRTOSPkgs.value(desc.freeRTOSEnvVar));
|
required3rdPartyPkgs.append(freeRTOSPkgs.value(desc.freeRTOS.envVar));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto platform = McuTarget::Platform{ desc.platform, desc.platformName, desc.platformVendor };
|
const auto platform = McuTarget::Platform{ desc.platform.id, desc.platform.name, desc.platform.vendor };
|
||||||
auto mcuTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
|
auto mcuTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
|
||||||
platform, os, required3rdPartyPkgs, tcPkg);
|
platform, os, required3rdPartyPkgs, tcPkg);
|
||||||
if (desc.colorDepths.count() > 1)
|
if (desc.platform.colorDepths.count() > 1)
|
||||||
mcuTarget->setColorDepth(colorDepth);
|
mcuTarget->setColorDepth(colorDepth);
|
||||||
mcuTargets.append(mcuTarget);
|
mcuTargets.append(mcuTarget);
|
||||||
}
|
}
|
||||||
@@ -506,10 +515,10 @@ protected:
|
|||||||
|
|
||||||
QVector<McuTarget *> createDesktopTargetsLegacy(const McuTargetDescription& desc)
|
QVector<McuTarget *> createDesktopTargetsLegacy(const McuTargetDescription& desc)
|
||||||
{
|
{
|
||||||
McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchainId);
|
McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id);
|
||||||
if (!tcPkg)
|
if (!tcPkg)
|
||||||
tcPkg = createUnsupportedToolChainPackage();
|
tcPkg = createUnsupportedToolChainPackage();
|
||||||
const auto platform = McuTarget::Platform{ desc.platform, desc.platformName, desc.platformVendor };
|
const auto platform = McuTarget::Platform{ desc.platform.id, desc.platform.name, desc.platform.vendor };
|
||||||
auto desktopTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
|
auto desktopTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
|
||||||
platform, McuTarget::OS::Desktop, {}, tcPkg);
|
platform, McuTarget::OS::Desktop, {}, tcPkg);
|
||||||
return { desktopTarget };
|
return { desktopTarget };
|
||||||
@@ -519,21 +528,21 @@ protected:
|
|||||||
{
|
{
|
||||||
// OS deduction
|
// OS deduction
|
||||||
const auto os = [&] {
|
const auto os = [&] {
|
||||||
if (desc.type == McuTargetDescription::TargetType::Desktop)
|
if (desc.platform.type == McuTargetDescription::TargetType::Desktop)
|
||||||
return McuTarget::OS::Desktop;
|
return McuTarget::OS::Desktop;
|
||||||
else if (!desc.freeRTOSEnvVar.isEmpty())
|
else if (!desc.freeRTOS.envVar.isEmpty())
|
||||||
return McuTarget::OS::FreeRTOS;
|
return McuTarget::OS::FreeRTOS;
|
||||||
return McuTarget::OS::BareMetal;
|
return McuTarget::OS::BareMetal;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
QVector<McuTarget *> mcuTargets;
|
QVector<McuTarget *> mcuTargets;
|
||||||
McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchainId);
|
McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id);
|
||||||
if (tcPkg) {
|
if (tcPkg) {
|
||||||
if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1,8}))
|
if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1,8}))
|
||||||
tcPkg->setVersions(desc.toolchainVersions);
|
tcPkg->setVersions(desc.toolchain.versions);
|
||||||
} else
|
} else
|
||||||
tcPkg = createUnsupportedToolChainPackage();
|
tcPkg = createUnsupportedToolChainPackage();
|
||||||
for (int colorDepth : desc.colorDepths) {
|
for (int colorDepth : desc.platform.colorDepths) {
|
||||||
QVector<McuPackage*> required3rdPartyPkgs;
|
QVector<McuPackage*> required3rdPartyPkgs;
|
||||||
// Desktop toolchains don't need any additional settings
|
// Desktop toolchains don't need any additional settings
|
||||||
if (tcPkg
|
if (tcPkg
|
||||||
@@ -542,34 +551,34 @@ protected:
|
|||||||
required3rdPartyPkgs.append(tcPkg);
|
required3rdPartyPkgs.append(tcPkg);
|
||||||
|
|
||||||
// Add setting specific to platform IDE
|
// Add setting specific to platform IDE
|
||||||
if (vendorPkgs.contains(desc.platformVendor))
|
if (vendorPkgs.contains(desc.platform.vendor))
|
||||||
required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platformVendor));
|
required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor));
|
||||||
|
|
||||||
// Board SDK specific settings
|
// Board SDK specific settings
|
||||||
FilePath boardSdkDefaultPath;
|
FilePath boardSdkDefaultPath;
|
||||||
if (!desc.boardSdkEnvVar.isEmpty()) {
|
if (!desc.boardSdk.envVar.isEmpty()) {
|
||||||
if (!boardSdkPkgs.contains(desc.boardSdkEnvVar)) {
|
if (!boardSdkPkgs.contains(desc.boardSdk.envVar)) {
|
||||||
auto boardSdkPkg = createBoardSdkPackage(desc);
|
auto boardSdkPkg = createBoardSdkPackage(desc);
|
||||||
boardSdkPkgs.insert(desc.boardSdkEnvVar, boardSdkPkg);
|
boardSdkPkgs.insert(desc.boardSdk.envVar, boardSdkPkg);
|
||||||
}
|
}
|
||||||
auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdkEnvVar);
|
auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdk.envVar);
|
||||||
if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1,8}))
|
if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1,8}))
|
||||||
boardSdkPkg->setVersions(desc.boardSdkVersions);
|
boardSdkPkg->setVersions(desc.boardSdk.versions);
|
||||||
boardSdkDefaultPath = boardSdkPkg->defaultPath();
|
boardSdkDefaultPath = boardSdkPkg->defaultPath();
|
||||||
required3rdPartyPkgs.append(boardSdkPkg);
|
required3rdPartyPkgs.append(boardSdkPkg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free RTOS specific settings
|
// Free RTOS specific settings
|
||||||
if (!desc.freeRTOSEnvVar.isEmpty()) {
|
if (!desc.freeRTOS.envVar.isEmpty()) {
|
||||||
if (!freeRTOSPkgs.contains(desc.freeRTOSEnvVar)) {
|
if (!freeRTOSPkgs.contains(desc.freeRTOS.envVar)) {
|
||||||
freeRTOSPkgs.insert(desc.freeRTOSEnvVar, createFreeRTOSSourcesPackage(
|
freeRTOSPkgs.insert(desc.freeRTOS.envVar, createFreeRTOSSourcesPackage(
|
||||||
desc.freeRTOSEnvVar, boardSdkDefaultPath,
|
desc.freeRTOS.envVar, boardSdkDefaultPath,
|
||||||
desc.freeRTOSBoardSdkSubDir));
|
desc.freeRTOS.boardSdkSubDir));
|
||||||
}
|
}
|
||||||
required3rdPartyPkgs.append(freeRTOSPkgs.value(desc.freeRTOSEnvVar));
|
required3rdPartyPkgs.append(freeRTOSPkgs.value(desc.freeRTOS.envVar));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto platform = McuTarget::Platform{ desc.platform, desc.platformName, desc.platformVendor };
|
const auto platform = McuTarget::Platform{ desc.platform.id, desc.platform.name, desc.platform.vendor };
|
||||||
auto mcuTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
|
auto mcuTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
|
||||||
platform, os, required3rdPartyPkgs, tcPkg);
|
platform, os, required3rdPartyPkgs, tcPkg);
|
||||||
mcuTarget->setColorDepth(colorDepth);
|
mcuTarget->setColorDepth(colorDepth);
|
||||||
@@ -634,17 +643,20 @@ static QFileInfoList targetDescriptionFiles(const Utils::FilePath &dir)
|
|||||||
return kitsDir.entryInfoList();
|
return kitsDir.entryInfoList();
|
||||||
}
|
}
|
||||||
|
|
||||||
static McuTargetDescription parseDescriptionJson(const QByteArray &data)
|
static QString extractQulVersion(const QByteArray &data)
|
||||||
{
|
{
|
||||||
const QJsonDocument document = QJsonDocument::fromJson(data);
|
const QJsonDocument document = QJsonDocument::fromJson(data);
|
||||||
const QJsonObject target = document.object();
|
const QJsonObject target = document.object();
|
||||||
|
return target.value("qulVersion").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion, const QJsonObject &target)
|
||||||
|
{
|
||||||
|
const QString compatVersion = target.value("compatVersion").toString();
|
||||||
const QJsonObject toolchain = target.value("toolchain").toObject();
|
const QJsonObject toolchain = target.value("toolchain").toObject();
|
||||||
const QJsonObject boardSdk = target.value("boardSdk").toObject();
|
const QJsonObject boardSdk = target.value("boardSdk").toObject();
|
||||||
const QJsonObject freeRTOS = target.value("freeRTOS").toObject();
|
const QJsonObject freeRTOS = target.value("freeRTOS").toObject();
|
||||||
|
|
||||||
const QVariantList colorDepths = target.value("colorDepths").toArray().toVariantList();
|
|
||||||
const auto colorDepthsVector = Utils::transform<QVector<int> >(
|
|
||||||
colorDepths, [&](const QVariant &colorDepth) { return colorDepth.toInt(); });
|
|
||||||
const QVariantList toolchainVersions = toolchain.value("versions").toArray().toVariantList();
|
const QVariantList toolchainVersions = toolchain.value("versions").toArray().toVariantList();
|
||||||
const auto toolchainVersionsVector = Utils::transform<QVector<QString> >(
|
const auto toolchainVersionsVector = Utils::transform<QVector<QString> >(
|
||||||
toolchainVersions, [&](const QVariant &version) { return version.toString(); });
|
toolchainVersions, [&](const QVariant &version) { return version.toString(); });
|
||||||
@@ -653,21 +665,76 @@ static McuTargetDescription parseDescriptionJson(const QByteArray &data)
|
|||||||
boardSdkVersions, [&](const QVariant &version) { return version.toString(); });
|
boardSdkVersions, [&](const QVariant &version) { return version.toString(); });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
target.value("qulVersion").toString(),
|
qulVersion,
|
||||||
|
compatVersion,
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
toolchain.value("id").toString(),
|
||||||
|
toolchainVersionsVector,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
boardSdk.value("name").toString(),
|
||||||
|
boardSdk.value("defaultPath").toString(),
|
||||||
|
boardSdk.value("envVar").toString(),
|
||||||
|
boardSdkVersionsVector,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
freeRTOS.value("envVar").toString(),
|
||||||
|
freeRTOS.value("boardSdkSubDir").toString(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static McuTargetDescription parseDescriptionJsonV1x(const QString &qulVersion, const QJsonObject &target)
|
||||||
|
{
|
||||||
|
auto description = parseDescriptionJsonCommon(qulVersion, target);
|
||||||
|
|
||||||
|
const QVariantList colorDepths = target.value("colorDepths").toArray().toVariantList();
|
||||||
|
const auto colorDepthsVector = Utils::transform<QVector<int> >(
|
||||||
|
colorDepths, [&](const QVariant &colorDepth) { return colorDepth.toInt(); });
|
||||||
|
|
||||||
|
description.platform = {
|
||||||
target.value("platform").toString(),
|
target.value("platform").toString(),
|
||||||
target.value("platformName").toString(),
|
target.value("platformName").toString(),
|
||||||
target.value("platformVendor").toString(),
|
target.value("platformVendor").toString(),
|
||||||
colorDepthsVector,
|
colorDepthsVector,
|
||||||
toolchain.value("id").toString(),
|
description.boardSdk.envVar.isEmpty() ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU
|
||||||
toolchainVersionsVector,
|
|
||||||
boardSdk.value("envVar").toString(),
|
|
||||||
boardSdk.value("name").toString(),
|
|
||||||
boardSdk.value("defaultPath").toString(),
|
|
||||||
boardSdkVersionsVector,
|
|
||||||
freeRTOS.value("envVar").toString(),
|
|
||||||
freeRTOS.value("boardSdkSubDir").toString(),
|
|
||||||
boardSdk.empty() ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU
|
|
||||||
};
|
};
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
static McuTargetDescription parseDescriptionJsonV2x(const QString &qulVersion, const QJsonObject &target)
|
||||||
|
{
|
||||||
|
const QJsonObject platform = target.value("platform").toObject();
|
||||||
|
|
||||||
|
const QVariantList colorDepths = platform.value("colorDepths").toArray().toVariantList();
|
||||||
|
const auto colorDepthsVector = Utils::transform<QVector<int> >(
|
||||||
|
colorDepths, [&](const QVariant &colorDepth) { return colorDepth.toInt(); });
|
||||||
|
const QString platformName = platform.value("platformName").toString();
|
||||||
|
McuTargetDescription description = parseDescriptionJsonCommon(qulVersion, target);
|
||||||
|
description.platform = {
|
||||||
|
platform.value("id").toString(),
|
||||||
|
platformName,
|
||||||
|
platform.value("vendor").toString(),
|
||||||
|
colorDepthsVector,
|
||||||
|
platformName == "Desktop" ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU,
|
||||||
|
};
|
||||||
|
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
static McuTargetDescription parseDescriptionJson(const QByteArray &data)
|
||||||
|
{
|
||||||
|
const QJsonDocument document = QJsonDocument::fromJson(data);
|
||||||
|
const QJsonObject target = document.object();
|
||||||
|
|
||||||
|
const QString qulVersion = target.value("qulVersion").toString();
|
||||||
|
|
||||||
|
switch (QVersionNumber::fromString(qulVersion).majorVersion()) {
|
||||||
|
case 1: return parseDescriptionJsonV1x(qulVersion, target);
|
||||||
|
case 2: return parseDescriptionJsonV2x(qulVersion, target);
|
||||||
|
default: return { qulVersion };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://doc.qt.io/qtcreator/creator-developing-mcu.html#supported-qt-for-mcus-sdks
|
// https://doc.qt.io/qtcreator/creator-developing-mcu.html#supported-qt-for-mcus-sdks
|
||||||
@@ -695,8 +762,7 @@ bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void targetsAndPackages(const Utils::FilePath &dir, QVector<McuPackage *> *packages,
|
void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo)
|
||||||
QVector<McuTarget *> *mcuTargets)
|
|
||||||
{
|
{
|
||||||
QList<McuTargetDescription> descriptions;
|
QList<McuTargetDescription> descriptions;
|
||||||
|
|
||||||
@@ -706,8 +772,17 @@ void targetsAndPackages(const Utils::FilePath &dir, QVector<McuPackage *> *packa
|
|||||||
if (!file.open(QFile::ReadOnly))
|
if (!file.open(QFile::ReadOnly))
|
||||||
continue;
|
continue;
|
||||||
const McuTargetDescription desc = parseDescriptionJson(file.readAll());
|
const McuTargetDescription desc = parseDescriptionJson(file.readAll());
|
||||||
if (QVersionNumber::fromString(desc.qulVersion) < McuSupportOptions::minimalQulVersion()) {
|
|
||||||
const auto pth = Utils::FilePath::fromString(fileInfo.filePath());
|
const auto pth = Utils::FilePath::fromString(fileInfo.filePath());
|
||||||
|
bool ok = false;
|
||||||
|
const int compatVersion = desc.compatVersion.toInt(&ok);
|
||||||
|
if (!desc.compatVersion.isEmpty() && ok && compatVersion > MAX_COMPATIBILITY_VERSION) {
|
||||||
|
printMessage(McuTarget::tr("Skipped %1. Unsupported version \"%2\".").arg(
|
||||||
|
QDir::toNativeSeparators(pth.fileNameWithPathComponents(1)),
|
||||||
|
desc.qulVersion),
|
||||||
|
false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (QVersionNumber::fromString(desc.qulVersion) < McuSupportOptions::minimalQulVersion()) {
|
||||||
const QString qtcSupportText = oldSdkQtcRequiredVersion.contains(desc.qulVersion) ?
|
const QString qtcSupportText = oldSdkQtcRequiredVersion.contains(desc.qulVersion) ?
|
||||||
McuTarget::tr("Detected version \"%1\", only supported by Qt Creator %2.")
|
McuTarget::tr("Detected version \"%1\", only supported by Qt Creator %2.")
|
||||||
.arg(desc.qulVersion, oldSdkQtcRequiredVersion.value(desc.qulVersion))
|
.arg(desc.qulVersion, oldSdkQtcRequiredVersion.value(desc.qulVersion))
|
||||||
@@ -744,7 +819,7 @@ void targetsAndPackages(const Utils::FilePath &dir, QVector<McuPackage *> *packa
|
|||||||
// This whole section could be removed when minimalQulVersion will reach 1.5 or above
|
// This whole section could be removed when minimalQulVersion will reach 1.5 or above
|
||||||
{
|
{
|
||||||
const bool hasDesktopDescription = Utils::contains(descriptions, [](const McuTargetDescription &desc) {
|
const bool hasDesktopDescription = Utils::contains(descriptions, [](const McuTargetDescription &desc) {
|
||||||
return desc.type == McuTargetDescription::TargetType::Desktop;
|
return desc.platform.type == McuTargetDescription::TargetType::Desktop;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!hasDesktopDescription) {
|
if (!hasDesktopDescription) {
|
||||||
@@ -764,12 +839,12 @@ void targetsAndPackages(const Utils::FilePath &dir, QVector<McuPackage *> *packa
|
|||||||
desktopDescription.qulVersion = descriptions.empty() ?
|
desktopDescription.qulVersion = descriptions.empty() ?
|
||||||
McuSupportOptions::minimalQulVersion().toString()
|
McuSupportOptions::minimalQulVersion().toString()
|
||||||
: descriptions.first().qulVersion;
|
: descriptions.first().qulVersion;
|
||||||
desktopDescription.platform = "Qt";
|
desktopDescription.platform.id = "Qt";
|
||||||
desktopDescription.platformName = "Desktop";
|
desktopDescription.platform.name = "Desktop";
|
||||||
desktopDescription.platformVendor = "Qt";
|
desktopDescription.platform.vendor = "Qt";
|
||||||
desktopDescription.colorDepths = {32};
|
desktopDescription.platform.colorDepths = {32};
|
||||||
desktopDescription.toolchainId = Utils::HostOsInfo::isWindowsHost() ? QString("msvc") : QString("gcc");
|
desktopDescription.toolchain.id = Utils::HostOsInfo::isWindowsHost() ? QString("msvc") : QString("gcc");
|
||||||
desktopDescription.type = McuTargetDescription::TargetType::Desktop;
|
desktopDescription.platform.type = McuTargetDescription::TargetType::Desktop;
|
||||||
descriptions.prepend(desktopDescription);
|
descriptions.prepend(desktopDescription);
|
||||||
} else {
|
} else {
|
||||||
if (dir.exists())
|
if (dir.exists())
|
||||||
@@ -782,10 +857,10 @@ void targetsAndPackages(const Utils::FilePath &dir, QVector<McuPackage *> *packa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mcuTargets->append(targetsFromDescriptions(descriptions, packages));
|
repo->mcuTargets.append(targetsFromDescriptions(descriptions, &(repo->packages)));
|
||||||
|
|
||||||
// Keep targets sorted lexicographically
|
// Keep targets sorted lexicographically
|
||||||
std::sort(mcuTargets->begin(), mcuTargets->end(), [] (const McuTarget* lhs, const McuTarget* rhs) {
|
std::sort(repo->mcuTargets.begin(), repo->mcuTargets.end(), [] (const McuTarget* lhs, const McuTarget* rhs) {
|
||||||
return McuSupportOptions::kitName(lhs) < McuSupportOptions::kitName(rhs);
|
return McuSupportOptions::kitName(lhs) < McuSupportOptions::kitName(rhs);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -33,17 +33,18 @@ class FilePath;
|
|||||||
|
|
||||||
namespace McuSupport {
|
namespace McuSupport {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
#define MAX_COMPATIBILITY_VERSION 1
|
||||||
|
|
||||||
|
class McuSdkRepository;
|
||||||
class McuPackage;
|
class McuPackage;
|
||||||
class McuToolChainPackage;
|
|
||||||
class McuTarget;
|
|
||||||
namespace Sdk {
|
namespace Sdk {
|
||||||
|
|
||||||
McuPackage *createQtForMCUsPackage();
|
McuPackage *createQtForMCUsPackage();
|
||||||
|
|
||||||
bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message);
|
bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message);
|
||||||
|
|
||||||
void targetsAndPackages(const Utils::FilePath &qulDir,
|
void targetsAndPackages(const Utils::FilePath &qulDir, McuSdkRepository *repo);
|
||||||
QVector<McuPackage*> *packages, QVector<McuTarget*> *mcuTargets);
|
|
||||||
|
|
||||||
Utils::FilePath kitsPath(const Utils::FilePath &dir);
|
Utils::FilePath kitsPath(const Utils::FilePath &dir);
|
||||||
|
|
||||||
|
@@ -14,6 +14,10 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
qul_target_qml_sources(%{ProjectName} %{MainQmlFile})
|
qul_target_qml_sources(%{ProjectName} %{MainQmlFile})
|
||||||
|
|
||||||
app_target_setup_os(%{ProjectName})
|
app_target_setup_os(%{ProjectName})
|
||||||
app_target_default_main(%{ProjectName} %{RootItemName})
|
|
||||||
|
if(Qul_VERSION VERSION_GREATER_EQUAL "2.0")
|
||||||
|
app_target_default_entrypoint(%{ProjectName} %{RootItemName})
|
||||||
|
else()
|
||||||
|
app_target_default_main(%{ProjectName} %{RootItemName})
|
||||||
|
endif()
|
||||||
|
@@ -1219,17 +1219,14 @@ void SimpleTargetRunner::doStart(const Runnable &runnable, const IDevice::ConstP
|
|||||||
|
|
||||||
connect(&m_launcher, &ApplicationLauncher::processExited,
|
connect(&m_launcher, &ApplicationLauncher::processExited,
|
||||||
this, [this, runnable](int exitCode, QProcess::ExitStatus status) {
|
this, [this, runnable](int exitCode, QProcess::ExitStatus status) {
|
||||||
QString msg;
|
if (m_stopReported)
|
||||||
if (status == QProcess::CrashExit)
|
return;
|
||||||
msg = tr("%1 crashed.");
|
const QString msg = (status == QProcess::CrashExit)
|
||||||
else
|
? tr("%1 crashed.") : tr("%2 exited with code %1").arg(exitCode);
|
||||||
msg = tr("%2 exited with code %1").arg(exitCode);
|
|
||||||
const QString displayName = runnable.command.executable().toUserOutput();
|
const QString displayName = runnable.command.executable().toUserOutput();
|
||||||
appendMessage(msg.arg(displayName), Utils::NormalMessageFormat);
|
appendMessage(msg.arg(displayName), Utils::NormalMessageFormat);
|
||||||
if (!m_stopReported) {
|
|
||||||
m_stopReported = true;
|
m_stopReported = true;
|
||||||
reportStopped();
|
reportStopped();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(&m_launcher, &ApplicationLauncher::error,
|
connect(&m_launcher, &ApplicationLauncher::error,
|
||||||
|
@@ -38,6 +38,7 @@ add_qtc_plugin(QmlDesigner
|
|||||||
designermcumanager.cpp designermcumanager.h
|
designermcumanager.cpp designermcumanager.h
|
||||||
richtexteditordialog.cpp richtexteditordialog.h
|
richtexteditordialog.cpp richtexteditordialog.h
|
||||||
editorproxy.cpp editorproxy.h
|
editorproxy.cpp editorproxy.h
|
||||||
|
boilerplate.qrc
|
||||||
EXPLICIT_MOC
|
EXPLICIT_MOC
|
||||||
components/propertyeditor/propertyeditorvalue.h
|
components/propertyeditor/propertyeditorvalue.h
|
||||||
components/connectioneditor/connectionviewwidget.h
|
components/connectioneditor/connectionviewwidget.h
|
||||||
|
5
src/plugins/qmldesigner/boilerplate.qrc
Normal file
5
src/plugins/qmldesigner/boilerplate.qrc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/boilerplatetemplates">
|
||||||
|
<file>qmlprojectmaincpp.tpl</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
@@ -599,12 +599,20 @@ void FormEditorWidget::dropEvent(QDropEvent *dropEvent)
|
|||||||
->viewManager().designerActionManager();
|
->viewManager().designerActionManager();
|
||||||
QHash<QString, QStringList> addedAssets = actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
|
QHash<QString, QStringList> addedAssets = actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
|
||||||
|
|
||||||
// add image assets to Form Editor
|
// Create Image components for added image assets
|
||||||
const QStringList addedImages = addedAssets.value(ComponentCoreConstants::addImagesDisplayString);
|
const QStringList addedImages = addedAssets.value(ComponentCoreConstants::addImagesDisplayString);
|
||||||
for (const QString &imgPath : addedImages) {
|
for (const QString &imgPath : addedImages) {
|
||||||
QmlItemNode::createQmlItemNodeFromImage(m_formEditorView, imgPath, {},
|
QmlItemNode::createQmlItemNodeFromImage(m_formEditorView, imgPath, {},
|
||||||
m_formEditorView->scene()->rootFormEditorItem()->qmlItemNode());
|
m_formEditorView->scene()->rootFormEditorItem()->qmlItemNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create Text components for added font assets
|
||||||
|
const QStringList addedFonts = addedAssets.value(ComponentCoreConstants::addFontsDisplayString);
|
||||||
|
for (const QString &fontPath : addedFonts) {
|
||||||
|
QString fontFamily = QFileInfo(fontPath).baseName();
|
||||||
|
QmlItemNode::createQmlItemNodeFromFont(m_formEditorView, fontFamily, rootItemRect().center(),
|
||||||
|
m_formEditorView->scene()->rootFormEditorItem()->qmlItemNode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -46,8 +46,7 @@ ComponentView::ComponentView(QObject *parent)
|
|||||||
|
|
||||||
void ComponentView::nodeAboutToBeRemoved(const ModelNode &removedNode)
|
void ComponentView::nodeAboutToBeRemoved(const ModelNode &removedNode)
|
||||||
{
|
{
|
||||||
removeSingleNodeFromList(removedNode);
|
removeFromListRecursive(removedNode);
|
||||||
searchForComponentAndRemoveFromList(removedNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStandardItemModel *ComponentView::standardItemModel() const
|
QStandardItemModel *ComponentView::standardItemModel() const
|
||||||
@@ -75,7 +74,7 @@ void ComponentView::setComponentToMaster()
|
|||||||
m_componentAction->setCurrentIndex(indexOfMaster());
|
m_componentAction->setCurrentIndex(indexOfMaster());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComponentView::removeSingleNodeFromList(const ModelNode &node)
|
void ComponentView::removeNodeFromList(const ModelNode &node)
|
||||||
{
|
{
|
||||||
for (int row = 0; row < m_standardItemModel->rowCount(); row++) {
|
for (int row = 0; row < m_standardItemModel->rowCount(); row++) {
|
||||||
if (m_standardItemModel->item(row)->data(ModelNodeRole).toInt() == node.internalId())
|
if (m_standardItemModel->item(row)->data(ModelNodeRole).toInt() == node.internalId())
|
||||||
@@ -83,6 +82,18 @@ void ComponentView::removeSingleNodeFromList(const ModelNode &node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ComponentView::addNodeToList(const ModelNode &node)
|
||||||
|
{
|
||||||
|
if (hasEntryForNode(node))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString description = descriptionForNode(node);
|
||||||
|
auto item = new QStandardItem(description);
|
||||||
|
item->setData(QVariant::fromValue(node.internalId()), ModelNodeRole);
|
||||||
|
item->setEditable(false);
|
||||||
|
m_standardItemModel->appendRow(item);
|
||||||
|
}
|
||||||
|
|
||||||
int ComponentView::indexForNode(const ModelNode &node) const
|
int ComponentView::indexForNode(const ModelNode &node) const
|
||||||
{
|
{
|
||||||
for (int row = 0; row < m_standardItemModel->rowCount(); row++) {
|
for (int row = 0; row < m_standardItemModel->rowCount(); row++) {
|
||||||
@@ -112,7 +123,7 @@ bool ComponentView::hasEntryForNode(const ModelNode &node) const
|
|||||||
return indexForNode(node) >= 0;
|
return indexForNode(node) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComponentView::addMasterDocument()
|
void ComponentView::ensureMasterDocument()
|
||||||
{
|
{
|
||||||
if (!hasMasterEntry()) {
|
if (!hasMasterEntry()) {
|
||||||
QStandardItem *item = new QStandardItem(QLatin1String("master"));
|
QStandardItem *item = new QStandardItem(QLatin1String("master"));
|
||||||
@@ -122,9 +133,11 @@ void ComponentView::addMasterDocument()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComponentView::removeMasterDocument()
|
void ComponentView::maybeRemoveMasterDocument()
|
||||||
{
|
{
|
||||||
m_standardItemModel->removeRow(indexOfMaster());
|
int idx = indexOfMaster();
|
||||||
|
if (idx >= 0 && m_standardItemModel->rowCount() == 1)
|
||||||
|
m_standardItemModel->removeRow(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ComponentView::descriptionForNode(const ModelNode &node) const
|
QString ComponentView::descriptionForNode(const ModelNode &node) const
|
||||||
@@ -155,6 +168,15 @@ void ComponentView::updateDescription(const ModelNode &node)
|
|||||||
m_standardItemModel->item(nodeIndex)->setText(descriptionForNode(node));
|
m_standardItemModel->item(nodeIndex)->setText(descriptionForNode(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ComponentView::isSubComponentNode(const ModelNode &node) const
|
||||||
|
{
|
||||||
|
return node.nodeSourceType() == ModelNode::NodeWithComponentSource
|
||||||
|
|| (node.hasParentProperty()
|
||||||
|
&& !node.parentProperty().isDefaultProperty()
|
||||||
|
&& node.metaInfo().isValid()
|
||||||
|
&& node.metaInfo().isGraphicalItem());
|
||||||
|
}
|
||||||
|
|
||||||
void ComponentView::modelAttached(Model *model)
|
void ComponentView::modelAttached(Model *model)
|
||||||
{
|
{
|
||||||
if (AbstractView::model() == model)
|
if (AbstractView::model() == model)
|
||||||
@@ -187,46 +209,25 @@ void ComponentView::nodeCreated(const ModelNode &createdNode)
|
|||||||
|
|
||||||
void ComponentView::searchForComponentAndAddToList(const ModelNode &node)
|
void ComponentView::searchForComponentAndAddToList(const ModelNode &node)
|
||||||
{
|
{
|
||||||
bool masterNotAdded = true;
|
const auto nodeList = node.allSubModelNodesAndThisNode();
|
||||||
|
bool hasMaster = false;
|
||||||
foreach (const ModelNode &node, node.allSubModelNodesAndThisNode()) {
|
for (const ModelNode &childNode : nodeList) {
|
||||||
if (node.nodeSourceType() == ModelNode::NodeWithComponentSource
|
if (isSubComponentNode(childNode)) {
|
||||||
|| (node.hasParentProperty()
|
if (!hasMaster) {
|
||||||
&& !node.parentProperty().isDefaultProperty()
|
hasMaster = true;
|
||||||
&& node.metaInfo().isValid()
|
ensureMasterDocument();
|
||||||
&& node.metaInfo().isGraphicalItem())) {
|
|
||||||
if (masterNotAdded) {
|
|
||||||
masterNotAdded = true;
|
|
||||||
addMasterDocument();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasEntryForNode(node)) {
|
|
||||||
QString description = descriptionForNode(node);
|
|
||||||
|
|
||||||
auto item = new QStandardItem(description);
|
|
||||||
item->setData(QVariant::fromValue(node.internalId()), ModelNodeRole);
|
|
||||||
item->setEditable(false);
|
|
||||||
removeSingleNodeFromList(node); //remove node if already present
|
|
||||||
m_standardItemModel->appendRow(item);
|
|
||||||
}
|
}
|
||||||
|
addNodeToList(childNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComponentView::searchForComponentAndRemoveFromList(const ModelNode &node)
|
void ComponentView::removeFromListRecursive(const ModelNode &node)
|
||||||
{
|
{
|
||||||
QList<ModelNode> nodeList;
|
const auto nodeList = node.allSubModelNodesAndThisNode();
|
||||||
nodeList.append(node);
|
for (const ModelNode &childNode : std::as_const(nodeList))
|
||||||
nodeList.append(node.allSubModelNodes());
|
removeNodeFromList(childNode);
|
||||||
|
maybeRemoveMasterDocument();
|
||||||
|
|
||||||
foreach (const ModelNode &childNode, nodeList) {
|
|
||||||
if (childNode.nodeSourceType() == ModelNode::NodeWithComponentSource)
|
|
||||||
removeSingleNodeFromList(childNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_standardItemModel->rowCount() == 1)
|
|
||||||
removeMasterDocument();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComponentView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
|
void ComponentView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
|
||||||
@@ -240,4 +241,17 @@ void ComponentView::nodeIdChanged(const ModelNode& node, const QString& /*newId*
|
|||||||
{
|
{
|
||||||
updateDescription(node);
|
updateDescription(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ComponentView::nodeSourceChanged(const ModelNode &node, const QString &/*newNodeSource*/)
|
||||||
|
{
|
||||||
|
if (isSubComponentNode(node)) {
|
||||||
|
if (!hasEntryForNode(node)) {
|
||||||
|
ensureMasterDocument();
|
||||||
|
addNodeToList(node);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
removeNodeFromList(node);
|
||||||
|
maybeRemoveMasterDocument();
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -62,6 +62,7 @@ public:
|
|||||||
const NodeAbstractProperty &oldPropertyParent,
|
const NodeAbstractProperty &oldPropertyParent,
|
||||||
AbstractView::PropertyChangeFlags propertyChange) override;
|
AbstractView::PropertyChangeFlags propertyChange) override;
|
||||||
void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId) override;
|
void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId) override;
|
||||||
|
void nodeSourceChanged(const ModelNode &node, const QString &newNodeSource) override;
|
||||||
|
|
||||||
QStandardItemModel *standardItemModel() const;
|
QStandardItemModel *standardItemModel() const;
|
||||||
|
|
||||||
@@ -76,16 +77,18 @@ signals:
|
|||||||
private: //functions
|
private: //functions
|
||||||
void updateModel();
|
void updateModel();
|
||||||
void searchForComponentAndAddToList(const ModelNode &node);
|
void searchForComponentAndAddToList(const ModelNode &node);
|
||||||
void searchForComponentAndRemoveFromList(const ModelNode &node);
|
void removeFromListRecursive(const ModelNode &node);
|
||||||
void removeSingleNodeFromList(const ModelNode &node);
|
void removeNodeFromList(const ModelNode &node);
|
||||||
|
void addNodeToList(const ModelNode &node);
|
||||||
int indexForNode(const ModelNode &node) const;
|
int indexForNode(const ModelNode &node) const;
|
||||||
int indexOfMaster() const;
|
int indexOfMaster() const;
|
||||||
bool hasMasterEntry() const;
|
bool hasMasterEntry() const;
|
||||||
bool hasEntryForNode(const ModelNode &node) const;
|
bool hasEntryForNode(const ModelNode &node) const;
|
||||||
void addMasterDocument();
|
void ensureMasterDocument();
|
||||||
void removeMasterDocument();
|
void maybeRemoveMasterDocument();
|
||||||
QString descriptionForNode(const ModelNode &node) const;
|
QString descriptionForNode(const ModelNode &node) const;
|
||||||
void updateDescription(const ModelNode &node);
|
void updateDescription(const ModelNode &node);
|
||||||
|
bool isSubComponentNode(const ModelNode &node) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStandardItemModel *m_standardItemModel;
|
QStandardItemModel *m_standardItemModel;
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include <QMultiHash>
|
#include <QMultiHash>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
@@ -69,6 +70,7 @@ private: // functions
|
|||||||
void parseQuick3DAssetsDir(const QString &quick3DAssetsPath);
|
void parseQuick3DAssetsDir(const QString &quick3DAssetsPath);
|
||||||
void parseQuick3DAssetsItem(const QString &importUrl, const QString &quick3DAssetsPath = {});
|
void parseQuick3DAssetsItem(const QString &importUrl, const QString &quick3DAssetsPath = {});
|
||||||
QStringList quick3DAssetPaths() const;
|
QStringList quick3DAssetPaths() const;
|
||||||
|
TypeName resolveDirQualifier(const QString &dirPath) const;
|
||||||
|
|
||||||
private: // variables
|
private: // variables
|
||||||
QFileSystemWatcher m_watcher;
|
QFileSystemWatcher m_watcher;
|
||||||
@@ -76,6 +78,7 @@ private: // variables
|
|||||||
// key: canonical directory path
|
// key: canonical directory path
|
||||||
QMultiHash<QString,QString> m_dirToQualifier;
|
QMultiHash<QString,QString> m_dirToQualifier;
|
||||||
QUrl m_filePath;
|
QUrl m_filePath;
|
||||||
|
QDir m_filePathDir;
|
||||||
QPointer<Model> m_model;
|
QPointer<Model> m_model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -134,8 +134,11 @@ void SubComponentManager::parseDirectories()
|
|||||||
if (dirInfo.exists() && dirInfo.isDir())
|
if (dirInfo.exists() && dirInfo.isDir())
|
||||||
parseDirectory(canonicalPath);
|
parseDirectory(canonicalPath);
|
||||||
|
|
||||||
foreach (const QString &subDir, QDir(QFileInfo(file).path()).entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot)) {
|
const QStringList subDirs = QDir(QFileInfo(file).path()).entryList(QDir::Dirs | QDir::NoDot
|
||||||
parseDirectory(canonicalPath + QLatin1Char('/') + subDir, true, subDir.toUtf8());
|
| QDir::NoDotDot);
|
||||||
|
for (const QString &subDir : subDirs) {
|
||||||
|
const QString canSubPath = canonicalPath + QLatin1Char('/') + subDir;
|
||||||
|
parseDirectory(canSubPath, true, resolveDirQualifier(canSubPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +149,10 @@ void SubComponentManager::parseDirectories()
|
|||||||
foreach (const Import &import, m_imports) {
|
foreach (const Import &import, m_imports) {
|
||||||
if (import.isFileImport()) {
|
if (import.isFileImport()) {
|
||||||
QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.file()).toLocalFile());
|
QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.file()).toLocalFile());
|
||||||
if (dirInfo.exists() && dirInfo.isDir())
|
if (dirInfo.exists() && dirInfo.isDir()) {
|
||||||
parseDirectory(dirInfo.canonicalFilePath(), true, dirInfo.baseName().toUtf8());
|
const QString canPath = dirInfo.canonicalFilePath();
|
||||||
|
parseDirectory(canPath, true, resolveDirQualifier(canPath));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
QString url = import.url();
|
QString url = import.url();
|
||||||
url.replace(QLatin1Char('.'), QLatin1Char('/'));
|
url.replace(QLatin1Char('.'), QLatin1Char('/'));
|
||||||
@@ -445,6 +450,11 @@ QStringList SubComponentManager::quick3DAssetPaths() const
|
|||||||
return retPaths;
|
return retPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeName SubComponentManager::resolveDirQualifier(const QString &dirPath) const
|
||||||
|
{
|
||||||
|
return m_filePathDir.relativeFilePath(dirPath).toUtf8();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class SubComponentManager
|
\class SubComponentManager
|
||||||
|
|
||||||
@@ -472,10 +482,12 @@ void SubComponentManager::update(const QUrl &filePath, const QList<Import> &impo
|
|||||||
if (!m_filePath.isEmpty()) {
|
if (!m_filePath.isEmpty()) {
|
||||||
const QString file = m_filePath.toLocalFile();
|
const QString file = m_filePath.toLocalFile();
|
||||||
oldDir = QFileInfo(QFileInfo(file).path());
|
oldDir = QFileInfo(QFileInfo(file).path());
|
||||||
|
m_filePathDir = QDir();
|
||||||
}
|
}
|
||||||
if (!filePath.isEmpty()) {
|
if (!filePath.isEmpty()) {
|
||||||
const QString file = filePath.toLocalFile();
|
const QString file = filePath.toLocalFile();
|
||||||
newDir = QFileInfo(QFileInfo(file).path());
|
newDir = QFileInfo(QFileInfo(file).path());
|
||||||
|
m_filePathDir = {newDir.absoluteFilePath()};
|
||||||
}
|
}
|
||||||
|
|
||||||
m_filePath = filePath;
|
m_filePath = filePath;
|
||||||
@@ -538,8 +550,10 @@ void SubComponentManager::updateImport(const Import &import)
|
|||||||
|
|
||||||
if (import.isFileImport()) {
|
if (import.isFileImport()) {
|
||||||
QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.file()).toLocalFile());
|
QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.file()).toLocalFile());
|
||||||
if (dirInfo.exists() && dirInfo.isDir())
|
if (dirInfo.exists() && dirInfo.isDir()) {
|
||||||
parseDirectory(dirInfo.canonicalFilePath(), true, dirInfo.baseName().toUtf8());
|
const QString canPath = dirInfo.canonicalFilePath();
|
||||||
|
parseDirectory(canPath, true, resolveDirQualifier(canPath));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
QString url = import.url();
|
QString url = import.url();
|
||||||
|
|
||||||
|
@@ -914,16 +914,30 @@ static QList<QmlDesigner::Import> generatePossibleFileImports(const QString &pat
|
|||||||
usedImportsSet.insert(i.info.path());
|
usedImportsSet.insert(i.info.path());
|
||||||
|
|
||||||
QList<QmlDesigner::Import> possibleImports;
|
QList<QmlDesigner::Import> possibleImports;
|
||||||
|
const QStringList qmlList("*.qml");
|
||||||
|
const QStringList qmldirList("qmldir");
|
||||||
|
|
||||||
foreach (const QString &subDir, QDir(path).entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot)) {
|
QStringList fileImportPaths;
|
||||||
QDir dir(path + "/" + subDir);
|
const QChar delimeter('/');
|
||||||
if (!dir.entryInfoList(QStringList("*.qml"), QDir::Files).isEmpty()
|
|
||||||
&& dir.entryInfoList(QStringList("qmldir"), QDir::Files).isEmpty()
|
std::function<void(const QString &)> checkDir;
|
||||||
&& !usedImportsSet.contains(dir.path())) {
|
checkDir = [&](const QString &checkPath) {
|
||||||
QmlDesigner::Import import = QmlDesigner::Import::createFileImport(subDir);
|
const QStringList entries = QDir(checkPath).entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot);
|
||||||
|
const QString checkPathDelim = checkPath + delimeter;
|
||||||
|
for (const QString &entry : entries) {
|
||||||
|
QDir dir(checkPathDelim + entry);
|
||||||
|
const QString dirPath = dir.path();
|
||||||
|
if (!dir.entryInfoList(qmlList, QDir::Files).isEmpty()
|
||||||
|
&& dir.entryInfoList(qmldirList, QDir::Files).isEmpty()
|
||||||
|
&& !usedImportsSet.contains(dirPath)) {
|
||||||
|
const QString importName = dir.path().mid(path.size() + 1);
|
||||||
|
QmlDesigner::Import import = QmlDesigner::Import::createFileImport(importName);
|
||||||
possibleImports.append(import);
|
possibleImports.append(import);
|
||||||
}
|
}
|
||||||
|
checkDir(dirPath);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
checkDir(path);
|
||||||
|
|
||||||
return possibleImports;
|
return possibleImports;
|
||||||
}
|
}
|
||||||
@@ -931,17 +945,44 @@ static QList<QmlDesigner::Import> generatePossibleFileImports(const QString &pat
|
|||||||
static QList<QmlDesigner::Import> generatePossibleLibraryImports(const QHash<QString, ImportKey> &filteredPossibleImportKeys)
|
static QList<QmlDesigner::Import> generatePossibleLibraryImports(const QHash<QString, ImportKey> &filteredPossibleImportKeys)
|
||||||
{
|
{
|
||||||
QList<QmlDesigner::Import> possibleImports;
|
QList<QmlDesigner::Import> possibleImports;
|
||||||
|
QSet<QString> controlsImplVersions;
|
||||||
|
bool hasVersionedControls = false;
|
||||||
|
bool hasVersionlessControls = false;
|
||||||
|
const QString controlsName = "QtQuick.Controls";
|
||||||
|
const QString controlsImplName = "QtQuick.Controls.impl";
|
||||||
|
|
||||||
foreach (const ImportKey &importKey, filteredPossibleImportKeys) {
|
for (const ImportKey &importKey : filteredPossibleImportKeys) {
|
||||||
QString libraryName = importKey.splitPath.join(QLatin1Char('.'));
|
QString libraryName = importKey.splitPath.join(QLatin1Char('.'));
|
||||||
int majorVersion = importKey.majorVersion;
|
int majorVersion = importKey.majorVersion;
|
||||||
if (majorVersion >= 0) {
|
if (majorVersion >= 0) {
|
||||||
int minorVersion = (importKey.minorVersion == LanguageUtils::ComponentVersion::NoVersion) ? 0 : importKey.minorVersion;
|
int minorVersion = (importKey.minorVersion == LanguageUtils::ComponentVersion::NoVersion) ? 0 : importKey.minorVersion;
|
||||||
QString version = QStringLiteral("%1.%2").arg(majorVersion).arg(minorVersion);
|
QString version = QStringLiteral("%1.%2").arg(majorVersion).arg(minorVersion);
|
||||||
possibleImports.append(QmlDesigner::Import::createLibraryImport(libraryName, version));
|
possibleImports.append(QmlDesigner::Import::createLibraryImport(libraryName, version));
|
||||||
|
|
||||||
|
// In Qt6, QtQuick.Controls itself doesn't have any version as it has no types,
|
||||||
|
// so it never gets added normally to possible imports.
|
||||||
|
// We work around this by injecting corresponding QtQuick.Controls version for each
|
||||||
|
// found impl version, if no valid QtQuick.Controls versions are found.
|
||||||
|
if (!hasVersionedControls) {
|
||||||
|
if (libraryName == controlsImplName)
|
||||||
|
controlsImplVersions.insert(version);
|
||||||
|
else if (libraryName == controlsName)
|
||||||
|
hasVersionedControls = true;
|
||||||
|
}
|
||||||
|
} else if (!hasVersionlessControls && libraryName == controlsName) {
|
||||||
|
// If QtQuick.Controls module is not included even in non-versioned, it means
|
||||||
|
// QtQuick.Controls is either in use or not available at all,
|
||||||
|
// so we shouldn't inject it.
|
||||||
|
hasVersionlessControls = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasVersionlessControls && !hasVersionedControls && !controlsImplVersions.isEmpty()) {
|
||||||
|
for (const auto &version : std::as_const(controlsImplVersions))
|
||||||
|
possibleImports.append(QmlDesigner::Import::createLibraryImport(controlsName, version));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return possibleImports;
|
return possibleImports;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2111,7 +2152,7 @@ void TextToModelMerger::collectLinkErrors(QList<DocumentMessage> *errors, const
|
|||||||
void TextToModelMerger::collectImportErrors(QList<DocumentMessage> *errors)
|
void TextToModelMerger::collectImportErrors(QList<DocumentMessage> *errors)
|
||||||
{
|
{
|
||||||
if (m_rewriterView->model()->imports().isEmpty()) {
|
if (m_rewriterView->model()->imports().isEmpty()) {
|
||||||
const QmlJS::DiagnosticMessage diagnosticMessage(QmlJS::Severity::Error, SourceLocation(0, 0, 0, 0), QCoreApplication::translate("QmlDesigner::TextToModelMerger", "No import statements found"));
|
const QmlJS::DiagnosticMessage diagnosticMessage(QmlJS::Severity::Error, SourceLocation(0, 0, 0, 0), QCoreApplication::translate("QmlDesigner::TextToModelMerger", "No import statements found."));
|
||||||
errors->append(DocumentMessage(diagnosticMessage, QUrl::fromLocalFile(m_document->fileName())));
|
errors->append(DocumentMessage(diagnosticMessage, QUrl::fromLocalFile(m_document->fileName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2137,7 +2178,7 @@ void TextToModelMerger::collectImportErrors(QList<DocumentMessage> *errors)
|
|||||||
SourceLocation(0, 0, 0, 0),
|
SourceLocation(0, 0, 0, 0),
|
||||||
QCoreApplication::translate(
|
QCoreApplication::translate(
|
||||||
"QmlDesigner::TextToModelMerger",
|
"QmlDesigner::TextToModelMerger",
|
||||||
"QtQuick 6 is not supported with a Qt 5 kit."));
|
"Qt Quick 6 is not supported with a Qt 5 kit."));
|
||||||
errors->prepend(
|
errors->prepend(
|
||||||
DocumentMessage(diagnosticMessage,
|
DocumentMessage(diagnosticMessage,
|
||||||
QUrl::fromLocalFile(m_document->fileName())));
|
QUrl::fromLocalFile(m_document->fileName())));
|
||||||
@@ -2161,7 +2202,7 @@ void TextToModelMerger::collectImportErrors(QList<DocumentMessage> *errors)
|
|||||||
diagnosticMessage(QmlJS::Severity::Error,
|
diagnosticMessage(QmlJS::Severity::Error,
|
||||||
SourceLocation(0, 0, 0, 0),
|
SourceLocation(0, 0, 0, 0),
|
||||||
QCoreApplication::translate("QmlDesigner::TextToModelMerger",
|
QCoreApplication::translate("QmlDesigner::TextToModelMerger",
|
||||||
"Unsupported QtQuick version"));
|
"Unsupported Qt Quick version."));
|
||||||
errors->append(DocumentMessage(diagnosticMessage,
|
errors->append(DocumentMessage(diagnosticMessage,
|
||||||
QUrl::fromLocalFile(m_document->fileName())));
|
QUrl::fromLocalFile(m_document->fileName())));
|
||||||
}
|
}
|
||||||
|
@@ -30,9 +30,11 @@
|
|||||||
|
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/runcontrol.h>
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
|
|
||||||
#include <qmlprojectmanager/qmlprojectmanagerconstants.h>
|
#include <qmlprojectmanager/qmlprojectmanagerconstants.h>
|
||||||
|
#include <qmlprojectmanager/qmlmainfileaspect.h>
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
@@ -44,21 +46,15 @@
|
|||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
namespace GenerateCmakeLists {
|
|
||||||
|
|
||||||
const QDir::Filters FILES_ONLY = QDir::Files;
|
namespace GenerateCmake {
|
||||||
const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
|
|
||||||
|
|
||||||
const char CMAKEFILENAME[] = "CMakeLists.txt";
|
|
||||||
const char QMLDIRFILENAME[] = "qmldir";
|
|
||||||
|
|
||||||
void generateMenuEntry()
|
void generateMenuEntry()
|
||||||
{
|
{
|
||||||
Core::ActionContainer *buildMenu =
|
Core::ActionContainer *buildMenu =
|
||||||
Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT);
|
Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT);
|
||||||
const Core::Context projectCntext(QmlProjectManager::Constants::QML_PROJECT_ID);
|
|
||||||
auto action = new QAction("Generate CMakeLists.txt files");
|
auto action = new QAction("Generate CMakeLists.txt files");
|
||||||
QObject::connect(action, &QAction::triggered, GenerateCmakeLists::onGenerateCmakeLists);
|
QObject::connect(action, &QAction::triggered, GenerateCmake::onGenerateCmakeLists);
|
||||||
Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.CreateCMakeLists");
|
Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.CreateCMakeLists");
|
||||||
buildMenu->addAction(cmd, ProjectExplorer::Constants::G_BUILD_RUN);
|
buildMenu->addAction(cmd, ProjectExplorer::Constants::G_BUILD_RUN);
|
||||||
|
|
||||||
@@ -71,9 +67,33 @@ void generateMenuEntry()
|
|||||||
|
|
||||||
void onGenerateCmakeLists()
|
void onGenerateCmakeLists()
|
||||||
{
|
{
|
||||||
generateMainCmake(ProjectExplorer::SessionManager::startupProject()->projectDirectory());
|
FilePath rootDir = ProjectExplorer::SessionManager::startupProject()->projectDirectory();
|
||||||
|
GenerateCmakeLists::generateMainCmake(rootDir);
|
||||||
|
GenerateEntryPoints::generateMainCpp(rootDir);
|
||||||
|
GenerateEntryPoints::generateMainQml(rootDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool writeFile(const FilePath &filePath, const QString &fileContent)
|
||||||
|
{
|
||||||
|
QFile file(filePath.toString());
|
||||||
|
file.open(QIODevice::WriteOnly);
|
||||||
|
QTextStream stream(&file);
|
||||||
|
stream << fileContent;
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GenerateCmakeLists {
|
||||||
|
|
||||||
|
const QDir::Filters FILES_ONLY = QDir::Files;
|
||||||
|
const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
|
||||||
|
|
||||||
|
const char CMAKEFILENAME[] = "CMakeLists.txt";
|
||||||
|
const char QMLDIRFILENAME[] = "qmldir";
|
||||||
|
|
||||||
QStringList processDirectory(const FilePath &dir)
|
QStringList processDirectory(const FilePath &dir)
|
||||||
{
|
{
|
||||||
QStringList moduleNames;
|
QStringList moduleNames;
|
||||||
@@ -149,9 +169,7 @@ const char MODULEFILE_CREATE_MODULE[] = "qt6_add_qml_module(%1\n\tURI \"%1\"\n\t
|
|||||||
QString generateModuleCmake(const FilePath &dir)
|
QString generateModuleCmake(const FilePath &dir)
|
||||||
{
|
{
|
||||||
QString fileContent;
|
QString fileContent;
|
||||||
const QStringList qmlFilesOnly("*.qml");
|
|
||||||
const QStringList qmldirFilesOnly(QMLDIRFILENAME);
|
const QStringList qmldirFilesOnly(QMLDIRFILENAME);
|
||||||
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
|
|
||||||
|
|
||||||
FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY);
|
FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY);
|
||||||
if (!qmldirFileList.isEmpty()) {
|
if (!qmldirFileList.isEmpty()) {
|
||||||
@@ -161,18 +179,15 @@ QString generateModuleCmake(const FilePath &dir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePaths qmlFileList = dir.dirEntries(qmlFilesOnly, FILES_ONLY);
|
QStringList qmlFileList = getDirectoryTreeQmls(dir);
|
||||||
QString qmlFiles;
|
QString qmlFiles;
|
||||||
for (FilePath &qmlFile : qmlFileList) {
|
for (QString &qmlFile : qmlFileList)
|
||||||
if (project->isKnownFile(qmlFile))
|
qmlFiles.append(QString("\t\t%1\n").arg(qmlFile));
|
||||||
qmlFiles.append(QString("\t\t%1\n").arg(qmlFile.fileName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList resourceFileList = getDirectoryTreeResources(dir);
|
QStringList resourceFileList = getDirectoryTreeResources(dir);
|
||||||
QString resourceFiles;
|
QString resourceFiles;
|
||||||
for (QString &resourceFile : resourceFileList) {
|
for (QString &resourceFile : resourceFileList)
|
||||||
resourceFiles.append(QString("\t\t%1\n").arg(resourceFile));
|
resourceFiles.append(QString("\t\t%1\n").arg(resourceFile));
|
||||||
}
|
|
||||||
|
|
||||||
QString moduleContent;
|
QString moduleContent;
|
||||||
if (!qmlFiles.isEmpty()) {
|
if (!qmlFiles.isEmpty()) {
|
||||||
@@ -226,6 +241,31 @@ QStringList getSingletonsFromQmldirFile(const FilePath &filePath)
|
|||||||
return singletons;
|
return singletons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList getDirectoryTreeQmls(const FilePath &dir)
|
||||||
|
{
|
||||||
|
const QStringList qmlFilesOnly("*.qml");
|
||||||
|
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
|
||||||
|
QStringList qmlFileList;
|
||||||
|
|
||||||
|
FilePaths thisDirFiles = dir.dirEntries(qmlFilesOnly, FILES_ONLY);
|
||||||
|
for (FilePath &file : thisDirFiles) {
|
||||||
|
if (!isFileBlacklisted(file.fileName()) &&
|
||||||
|
project->isKnownFile(file)) {
|
||||||
|
qmlFileList.append(file.fileName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
|
||||||
|
for (FilePath &subDir : subDirsList) {
|
||||||
|
QStringList subDirQmlFiles = getDirectoryTreeQmls(subDir);
|
||||||
|
for (QString &qmlFile : subDirQmlFiles) {
|
||||||
|
qmlFileList.append(subDir.fileName().append('/').append(qmlFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qmlFileList;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList getDirectoryTreeResources(const FilePath &dir)
|
QStringList getDirectoryTreeResources(const FilePath &dir)
|
||||||
{
|
{
|
||||||
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
|
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
|
||||||
@@ -255,11 +295,7 @@ QStringList getDirectoryTreeResources(const FilePath &dir)
|
|||||||
void createCmakeFile(const FilePath &dir, const QString &content)
|
void createCmakeFile(const FilePath &dir, const QString &content)
|
||||||
{
|
{
|
||||||
FilePath filePath = dir.pathAppended(CMAKEFILENAME);
|
FilePath filePath = dir.pathAppended(CMAKEFILENAME);
|
||||||
QFile cmakeFile(filePath.toString());
|
GenerateCmake::writeFile(filePath, content);
|
||||||
cmakeFile.open(QIODevice::WriteOnly);
|
|
||||||
QTextStream stream(&cmakeFile);
|
|
||||||
stream << content;
|
|
||||||
cmakeFile.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFileBlacklisted(const QString &fileName)
|
bool isFileBlacklisted(const QString &fileName)
|
||||||
@@ -269,4 +305,48 @@ bool isFileBlacklisted(const QString &fileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace GenerateEntryPoints {
|
||||||
|
bool generateEntryPointFiles(const FilePath &dir)
|
||||||
|
{
|
||||||
|
bool cppOk = generateMainCpp(dir);
|
||||||
|
bool qmlOk = generateMainQml(dir);
|
||||||
|
|
||||||
|
return cppOk && qmlOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char MAIN_CPPFILE_CONTENT[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
|
||||||
|
const char MAIN_CPPFILE_NAME[] = "main.cpp";
|
||||||
|
|
||||||
|
bool generateMainCpp(const FilePath &dir)
|
||||||
|
{
|
||||||
|
QFile templatefile(MAIN_CPPFILE_CONTENT);
|
||||||
|
templatefile.open(QIODevice::ReadOnly);
|
||||||
|
QTextStream stream(&templatefile);
|
||||||
|
QString content = stream.readAll();
|
||||||
|
templatefile.close();
|
||||||
|
|
||||||
|
FilePath filePath = dir.pathAppended(MAIN_CPPFILE_NAME);
|
||||||
|
return GenerateCmake::writeFile(filePath, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char MAIN_QMLFILE_CONTENT[] = "import %1Qml\n\n%2 {\n}\n";
|
||||||
|
const char MAIN_QMLFILE_NAME[] = "main.qml";
|
||||||
|
|
||||||
|
bool generateMainQml(const FilePath &dir)
|
||||||
|
{
|
||||||
|
FilePath filePath = dir.pathAppended(MAIN_QMLFILE_NAME);
|
||||||
|
QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName();
|
||||||
|
ProjectExplorer::RunConfiguration *runConfiguration = ProjectExplorer::SessionManager::startupRunConfiguration();
|
||||||
|
QString mainClass;
|
||||||
|
|
||||||
|
if (const auto aspect = runConfiguration->aspect<QmlProjectManager::QmlMainFileAspect>())
|
||||||
|
mainClass = FilePath::fromString(aspect->mainScript()).baseName();
|
||||||
|
|
||||||
|
return GenerateCmake::writeFile(filePath, QString(MAIN_QMLFILE_CONTENT).arg(projectName).arg(mainClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -30,16 +30,25 @@
|
|||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
namespace GenerateCmakeLists {
|
namespace GenerateCmake {
|
||||||
void generateMenuEntry();
|
void generateMenuEntry();
|
||||||
void onGenerateCmakeLists();
|
void onGenerateCmakeLists();
|
||||||
|
bool writeFile(const Utils::FilePath &filePath, const QString &fileContent);
|
||||||
|
}
|
||||||
|
namespace GenerateCmakeLists {
|
||||||
void generateMainCmake(const Utils::FilePath &rootDir);
|
void generateMainCmake(const Utils::FilePath &rootDir);
|
||||||
void generateSubdirCmake(const Utils::FilePath &dir);
|
void generateSubdirCmake(const Utils::FilePath &dir);
|
||||||
QString generateModuleCmake(const Utils::FilePath &dir);
|
QString generateModuleCmake(const Utils::FilePath &dir);
|
||||||
QStringList processDirectory(const Utils::FilePath &dir);
|
QStringList processDirectory(const Utils::FilePath &dir);
|
||||||
QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
|
QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
|
||||||
|
QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
|
||||||
QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
|
QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
|
||||||
void createCmakeFile(const Utils::FilePath &filePath, const QString &content);
|
void createCmakeFile(const Utils::FilePath &filePath, const QString &content);
|
||||||
bool isFileBlacklisted(const QString &fileName);
|
bool isFileBlacklisted(const QString &fileName);
|
||||||
}
|
}
|
||||||
|
namespace GenerateEntryPoints {
|
||||||
|
bool generateEntryPointFiles(const Utils::FilePath &dir);
|
||||||
|
bool generateMainCpp(const Utils::FilePath &dir);
|
||||||
|
bool generateMainQml(const Utils::FilePath &dir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -223,7 +223,7 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
|
|||||||
if (DesignerSettings::getValue(DesignerSettingsKey::STANDALONE_MODE).toBool())
|
if (DesignerSettings::getValue(DesignerSettingsKey::STANDALONE_MODE).toBool())
|
||||||
GenerateResource::generateMenuEntry();
|
GenerateResource::generateMenuEntry();
|
||||||
|
|
||||||
GenerateCmakeLists::generateMenuEntry();
|
GenerateCmake::generateMenuEntry();
|
||||||
|
|
||||||
const QString fontPath
|
const QString fontPath
|
||||||
= Core::ICore::resourcePath(
|
= Core::ICore::resourcePath(
|
||||||
|
58
src/plugins/qmldesigner/qmlprojectmaincpp.tpl
Normal file
58
src/plugins/qmldesigner/qmlprojectmaincpp.tpl
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Quick Studio Components.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 or (at your option) any later version
|
||||||
|
** approved by the KDE Free Qt Foundation. The licenses are as published by
|
||||||
|
** the Free Software Foundation and appearing in the file LICENSE.GPL3
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
qputenv("QT_LOGGING_RULES", "qt.qml.connections=false");
|
||||||
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
|
QQmlApplicationEngine engine;
|
||||||
|
const QUrl url(u"qrc:Main/main.qml"_qs);
|
||||||
|
QObject::connect(
|
||||||
|
&engine, &QQmlApplicationEngine::objectCreated, &app,
|
||||||
|
[url](QObject *obj, const QUrl &objUrl) {
|
||||||
|
if (!obj && url == objUrl)
|
||||||
|
QCoreApplication::exit(-1);
|
||||||
|
},
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
|
engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml");
|
||||||
|
engine.addImportPath(":/");
|
||||||
|
|
||||||
|
engine.load(url);
|
||||||
|
|
||||||
|
if (engine.rootObjects().isEmpty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
@@ -83,7 +83,7 @@ static void setupProjectInfoQmlBundles(ModelManagerInterface::ProjectInfo &proje
|
|||||||
if (projectInfo.project)
|
if (projectInfo.project)
|
||||||
activeTarget = projectInfo.project->activeTarget();
|
activeTarget = projectInfo.project->activeTarget();
|
||||||
Kit *activeKit = activeTarget ? activeTarget->kit() : KitManager::defaultKit();
|
Kit *activeKit = activeTarget ? activeTarget->kit() : KitManager::defaultKit();
|
||||||
const QHash<QString, QString> replacements = {{QLatin1String("$(QT_INSTALL_QML)"), projectInfo.qtQmlPath}};
|
const QHash<QString, QString> replacements = {{QLatin1String("$(QT_INSTALL_QML)"), projectInfo.qtQmlPath.toString()}};
|
||||||
|
|
||||||
for (IBundleProvider *bp : IBundleProvider::allBundleProviders())
|
for (IBundleProvider *bp : IBundleProvider::allBundleProviders())
|
||||||
bp->mergeBundlesForKit(activeKit, projectInfo.activeBundle, replacements);
|
bp->mergeBundlesForKit(activeKit, projectInfo.activeBundle, replacements);
|
||||||
@@ -146,17 +146,17 @@ ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfoForProject(
|
|||||||
}
|
}
|
||||||
if (qtVersion && qtVersion->isValid()) {
|
if (qtVersion && qtVersion->isValid()) {
|
||||||
projectInfo.tryQmlDump = project && qtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT);
|
projectInfo.tryQmlDump = project && qtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT);
|
||||||
projectInfo.qtQmlPath = qtVersion->qmlPath().toFileInfo().canonicalFilePath();
|
projectInfo.qtQmlPath = qtVersion->qmlPath();
|
||||||
projectInfo.qtVersionString = qtVersion->qtVersionString();
|
projectInfo.qtVersionString = qtVersion->qtVersionString();
|
||||||
} else if (!activeKit || !activeKit->value(QtSupport::SuppliesQtQuickImportPath::id(), false).toBool()) {
|
} else if (!activeKit || !activeKit->value(QtSupport::SuppliesQtQuickImportPath::id(), false).toBool()) {
|
||||||
projectInfo.qtQmlPath = QFileInfo(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)).canonicalFilePath();
|
projectInfo.qtQmlPath = FilePath::fromUserInput(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath));
|
||||||
projectInfo.qtVersionString = QLatin1String(qVersion());
|
projectInfo.qtVersionString = QLatin1String(qVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
projectInfo.qmlDumpPath.clear();
|
projectInfo.qmlDumpPath.clear();
|
||||||
const QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(activeKit);
|
const QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(activeKit);
|
||||||
if (version && projectInfo.tryQmlDump) {
|
if (version && projectInfo.tryQmlDump) {
|
||||||
projectInfo.qmlDumpPath = version->qmlplugindumpFilePath().toString();
|
projectInfo.qmlDumpPath = version->qmlplugindumpFilePath();
|
||||||
projectInfo.qmlDumpHasRelocatableFlag = version->hasQmlDumpWithRelocatableFlag();
|
projectInfo.qmlDumpHasRelocatableFlag = version->hasQmlDumpWithRelocatableFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -502,6 +502,7 @@ public:
|
|||||||
void duplicateSelection(bool comment);
|
void duplicateSelection(bool comment);
|
||||||
void updateCannotDecodeInfo();
|
void updateCannotDecodeInfo();
|
||||||
void collectToCircularClipboard();
|
void collectToCircularClipboard();
|
||||||
|
void setClipboardSelection();
|
||||||
|
|
||||||
void ctor(const QSharedPointer<TextDocument> &doc);
|
void ctor(const QSharedPointer<TextDocument> &doc);
|
||||||
void handleHomeKey(bool anchor, bool block);
|
void handleHomeKey(bool anchor, bool block);
|
||||||
@@ -5217,7 +5218,8 @@ void TextEditorWidget::mousePressEvent(QMouseEvent *e)
|
|||||||
|
|
||||||
void TextEditorWidget::mouseReleaseEvent(QMouseEvent *e)
|
void TextEditorWidget::mouseReleaseEvent(QMouseEvent *e)
|
||||||
{
|
{
|
||||||
if (d->m_linkPressed && d->isMouseNavigationEvent(e) && e->button() == Qt::LeftButton) {
|
const Qt::MouseButton button = e->button();
|
||||||
|
if (d->m_linkPressed && d->isMouseNavigationEvent(e) && button == Qt::LeftButton) {
|
||||||
EditorManager::addCurrentPositionToNavigationHistory();
|
EditorManager::addCurrentPositionToNavigationHistory();
|
||||||
bool inNextSplit = ((e->modifiers() & Qt::AltModifier) && !alwaysOpenLinksInNextSplit())
|
bool inNextSplit = ((e->modifiers() & Qt::AltModifier) && !alwaysOpenLinksInNextSplit())
|
||||||
|| (alwaysOpenLinksInNextSplit() && !(e->modifiers() & Qt::AltModifier));
|
|| (alwaysOpenLinksInNextSplit() && !(e->modifiers() & Qt::AltModifier));
|
||||||
@@ -5227,12 +5229,22 @@ void TextEditorWidget::mouseReleaseEvent(QMouseEvent *e)
|
|||||||
if (self && self->openLink(symbolLink, inNextSplit))
|
if (self && self->openLink(symbolLink, inNextSplit))
|
||||||
self->d->clearLink();
|
self->d->clearLink();
|
||||||
}, true, inNextSplit);
|
}, true, inNextSplit);
|
||||||
|
} else if (button == Qt::MiddleButton
|
||||||
|
&& !isReadOnly()
|
||||||
|
&& QGuiApplication::clipboard()->supportsSelection()) {
|
||||||
|
if (!(e->modifiers() & Qt::AltModifier))
|
||||||
|
doSetTextCursor(cursorForPosition(e->pos()));
|
||||||
|
if (const QMimeData *md = QGuiApplication::clipboard()->mimeData(QClipboard::Selection))
|
||||||
|
insertFromMimeData(md);
|
||||||
|
e->accept();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HostOsInfo::isLinuxHost() && handleForwardBackwardMouseButtons(e))
|
if (!HostOsInfo::isLinuxHost() && handleForwardBackwardMouseButtons(e))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QPlainTextEdit::mouseReleaseEvent(e);
|
QPlainTextEdit::mouseReleaseEvent(e);
|
||||||
|
d->setClipboardSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorWidget::mouseDoubleClickEvent(QMouseEvent *e)
|
void TextEditorWidget::mouseDoubleClickEvent(QMouseEvent *e)
|
||||||
@@ -5247,6 +5259,14 @@ void TextEditorWidget::mouseDoubleClickEvent(QMouseEvent *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPlainTextEdit::mouseDoubleClickEvent(e);
|
QPlainTextEdit::mouseDoubleClickEvent(e);
|
||||||
|
d->setClipboardSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextEditorWidgetPrivate::setClipboardSelection()
|
||||||
|
{
|
||||||
|
QClipboard *clipboard = QGuiApplication::clipboard();
|
||||||
|
if (m_cursors.hasSelection() && clipboard->supportsSelection())
|
||||||
|
clipboard->setMimeData(q->createMimeDataFromSelection(), QClipboard::Selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorWidget::leaveEvent(QEvent *e)
|
void TextEditorWidget::leaveEvent(QEvent *e)
|
||||||
|
@@ -267,7 +267,7 @@ void tst_ImportCheck::importTypes()
|
|||||||
|
|
||||||
// the default qtQmlPath is based on the Qt version in use otherwise
|
// the default qtQmlPath is based on the Qt version in use otherwise
|
||||||
ModelManagerInterface::ProjectInfo defaultProject;
|
ModelManagerInterface::ProjectInfo defaultProject;
|
||||||
defaultProject.qtQmlPath = importPath;
|
defaultProject.qtQmlPath = Utils::FilePath::fromString(importPath);
|
||||||
modelManager->setDefaultProject(defaultProject, nullptr);
|
modelManager->setDefaultProject(defaultProject, nullptr);
|
||||||
modelManager->activateScan();
|
modelManager->activateScan();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user