Merge "Merge remote-tracking branch 'origin/4.13' into master"

This commit is contained in:
The Qt Project
2020-08-10 13:59:18 +00:00
205 changed files with 6161 additions and 10173 deletions

View File

@@ -258,7 +258,7 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
1. Clone LLVM/Clang and checkout a suitable branch
git clone -b release_80-based --recursive https://code.qt.io/clang/llvm-project.git
git clone -b release_100-based --recursive https://code.qt.io/clang/llvm-project.git
2. Build and install LLVM/Clang
@@ -278,7 +278,7 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
For Windows:
cmake ^
-G "NMake Makefiles JOM" ^
-G Ninja ^
-D CMAKE_BUILD_TYPE=Release ^
-D LLVM_ENABLE_RTTI=ON ^
-D LLVM_ENABLE_PROJECTS="clang;clang-tools-extra" ^
@@ -290,7 +290,7 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
The ClangFormat plugin depends on the additional patch
https://code.qt.io/cgit/clang/clang.git/commit/?h=release_80-based&id=fa1b9053729ec6a4425a44ec5502dd388928274a
https://code.qt.io/cgit/clang/llvm-project.git/commit/?h=release_100-based&id=9b992a0f7f160dd6c75f20a4dcfcf7c60a4894df
While the plugin builds without it, it will be disabled on start with an error message.

View File

@@ -15,7 +15,7 @@ if (yaml-cpp_FOUND)
unset(yaml_cpp_include_dir CACHE)
find_path(yaml_cpp_include_dir yaml-cpp/yaml.h)
endif()
target_include_directories(yaml-cpp INTERFACE ${yaml_cpp_include_dir})
set_target_properties(yaml-cpp PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${yaml_cpp_include_dir}")
else()
set(yaml-cpp_FOUND 1)
set_package_properties(yaml-cpp PROPERTIES DESCRIPTION "using internal src/libs/3rdparty/yaml-cpp")

View File

@@ -37,6 +37,7 @@ Editing
* Added editor tool button for `Analyze File` (QTCREATORBUG-23348)
* Added `Add forward declaration` refactoring action (QTCREATORBUG-23444)
* Extended `Add Include` refactoring action to non-Qt classes (QTCREATORBUG-21)
* Fixed MSVC detection with some locale settings (QTCREATORBUG-24311)
* Fixed indentation with C++11 list initialization (QTCREATORBUG-16977, QTCREATORBUG-24035)
* Fixed indentation with trailing return types (QTCREATORBUG-23502)
* Fixed issue with `std::chrono::time_point` (QTCREATORBUG-24067)
@@ -69,6 +70,7 @@ Editing
### Python
* Added tool button for opening interactive Python, optionally importing current file
* Fixed highlighting of parentheses
### Diff Viewer
@@ -121,6 +123,7 @@ Debugging
---------
* Added option to reset all formats for watches to default
* Added option to override sysroot setting when starting or attaching to external application
Analyzer
--------
@@ -130,6 +133,7 @@ Analyzer
* Re-added editor text marks for diagnostics (QTCREATORBUG-23349)
* Changed to use separate `clazy-standalone` executable
* Fixed issue with `clang-tidy` and `WarningsAsErrors` (QTCREATORBUG-23423)
* Fixed output parsing of `clazy`
Version Control Systems
-----------------------
@@ -142,7 +146,7 @@ Version Control Systems
Test Integration
----------------
* Added support for Catch test framework (QTCREATORBUG-19740)
* Added support for Catch2 test framework (QTCREATORBUG-19740)
### Google Test
@@ -163,6 +167,7 @@ Platforms
* Removed Ministro deployment option (QTCREATORBUG-23761)
* Added service editor to manifest editor (QTCREATORBUG-23937)
* Added splash screen editor to manifest editor (QTCREATORBUG-24011, QTCREATORBUG-24013)
* Fixed QML debugging and profiling (QTCREATORBUG-24155)
* Fixed debugging on x86 and armv7 architectures (QTCREATORBUG-24191)
* Fixed issue with long kit names (QTBUG-83875)

View File

@@ -102,7 +102,7 @@
The packages are deployed on the connected Android devices. To switch the
device used as a default device for the selected kit, select
\uicontrol Projects > \uicontrol Run > \uicontrol {Deploy to Android device}
\uicontrol Projects > \uicontrol Run > \uicontrol {Deploy to Android Device}
> \uicontrol {Reset Default Devices}. The setting applies until you restart \QC.
For more information, see \l{Selecting Android Devices}.

View File

@@ -75,6 +75,10 @@
\endlist
If \QC cannot detect the encoding of the files to compare, an info bar
appears that displays the option to reload the document using some other
encoding. For more information, see \l {File Encoding}.
\section1 Viewing the Changes
\image creator-diff-editor.png "Diff editor output in the Edit mode"

View File

@@ -406,6 +406,9 @@
Select \uicontrol {Add Files} to locate and add individual
files.
To list the folders and files in ascending alphabetic order in the source
tree, select \uicontrol {Sort Alphabetically} in the context menu.
By default, resources are accessible in the application under the same file
name as they have in the source tree, with a \c{:/} prefix, or by a URL with
a \c qrc scheme. To specify a path prefix for all files in the \c .qrc file,

View File

@@ -253,25 +253,29 @@ def deploy_libclang(install_dir, llvm_install_dir, chrpath_bin):
clangbindirtarget))
resourcetarget = os.path.join(clanglibdirtarget, 'clang')
else:
# libclang -> Qt Creator libraries
libsources = glob(os.path.join(llvm_install_dir, 'lib', 'libclang.so*'))
for libsource in libsources:
deployinfo.append((libsource, os.path.join(install_dir, 'lib', 'qtcreator')))
clangbinary = os.path.join(llvm_install_dir, 'bin', 'clang')
clangdbinary = os.path.join(llvm_install_dir, 'bin', 'clangd')
clangtidybinary = os.path.join(llvm_install_dir, 'bin', 'clang-tidy')
clazybinary = os.path.join(llvm_install_dir, 'bin', 'clazy-standalone')
# clang binaries -> clang libexec
clangbinary_targetdir = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'bin')
if not os.path.exists(clangbinary_targetdir):
os.makedirs(clangbinary_targetdir)
deployinfo.append((clangbinary, clangbinary_targetdir))
deployinfo.append((clangdbinary, clangbinary_targetdir))
deployinfo.append((clangtidybinary, clangbinary_targetdir))
deployinfo.append((clazybinary, clangbinary_targetdir))
# copy link target if clang is actually a symlink
if os.path.islink(clangbinary):
linktarget = os.readlink(clangbinary)
deployinfo.append((os.path.join(os.path.dirname(clangbinary), linktarget),
os.path.join(clangbinary_targetdir, linktarget)))
for binary in ['clang', 'clangd', 'clang-tidy', 'clazy-standalone']:
binary_filepath = os.path.join(llvm_install_dir, 'bin', binary)
deployinfo.append((binary_filepath, clangbinary_targetdir))
# add link target if binary is actually a symlink (to a binary in the same directory)
if os.path.islink(binary_filepath):
linktarget = os.readlink(binary_filepath)
deployinfo.append((os.path.join(os.path.dirname(binary_filepath), linktarget),
os.path.join(clangbinary_targetdir, linktarget)))
clanglibs_targetdir = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'lib')
# support libraries (for clazy) -> clang libexec
if not os.path.exists(clanglibs_targetdir):
os.makedirs(clanglibs_targetdir)
for lib_pattern in ['ClazyPlugin.so', 'libclang-cpp.so*']:
for lib in glob(os.path.join(llvm_install_dir, 'lib', lib_pattern)):
deployinfo.append((lib, clanglibs_targetdir))
resourcetarget = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'lib', 'clang')
print("copying libclang...")
@@ -281,10 +285,15 @@ def deploy_libclang(install_dir, llvm_install_dir, chrpath_bin):
if common.is_linux_platform():
# libclang was statically compiled, so there is no need for the RPATHs
# and they are confusing when fixing RPATHs later in the process
print("removing libclang RPATHs...")
# and they are confusing when fixing RPATHs later in the process.
# Also fix clazy-standalone RPATH.
print("fixing Clang RPATHs...")
for source, target in deployinfo:
if not os.path.islink(target):
filename = os.path.basename(source)
targetfilepath = target if not os.path.isdir(target) else os.path.join(target, filename)
if filename == 'clazy-standalone':
subprocess.check_call([chrpath_bin, '-r', '$ORIGIN/../lib', targetfilepath])
elif not os.path.islink(target):
targetfilepath = target if not os.path.isdir(target) else os.path.join(target, os.path.basename(source))
subprocess.check_call([chrpath_bin, '-d', targetfilepath])

View File

@@ -133,6 +133,8 @@ if [ $LLVM_INSTALL_DIR ]; then
mkdir -p "$libexec_path/clang/lib"
cp -Rf "$LLVM_INSTALL_DIR"/lib/libclang.*dylib "$app_path/Contents/Frameworks/" || exit 1
cp -Rf "$LLVM_INSTALL_DIR"/lib/clang "$libexec_path/clang/lib/" || exit 1
cp -Rf "$LLVM_INSTALL_DIR"/lib/libclang-cpp.dylib "$libexec_path/clang/lib/" || exit 1
cp -Rf "$LLVM_INSTALL_DIR"/lib/ClazyPlugin.dylib "$libexec_path/clang/lib/" || exit 1
clangsource="$LLVM_INSTALL_DIR"/bin/clang
clanglinktarget="$(readlink "$clangsource")"
cp -Rf "$clangsource" "$libexec_path/clang/bin/" || exit 1
@@ -145,6 +147,7 @@ if [ $LLVM_INSTALL_DIR ]; then
cp -Rf "$clangtidysource" "$libexec_path/clang/bin/" || exit 1
clazysource="$LLVM_INSTALL_DIR"/bin/clazy-standalone
cp -Rf "$clazysource" "$libexec_path/clang/bin/" || exit 1
install_name_tool -add_rpath "@executable_path/../lib" "$libexec_path/clang/bin/clazy-standalone" || exit 1
fi
clangbackendArgument="-executable=$libexec_path/clangbackend"
clangpchmanagerArgument="-executable=$libexec_path/clangpchmanagerbackend"

View File

@@ -110,7 +110,10 @@ class Dumper(DumperBase):
# There is no cdb api for the size of bitfields.
# Workaround this issue by parsing the native debugger text for integral types.
if val.type.code == TypeCode.Integral:
integerString = nativeValue.nativeDebuggerValue()
try:
integerString = nativeValue.nativeDebuggerValue()
except UnicodeDecodeError:
integerString = '' # cannot decode - read raw
if integerString == 'true':
val.ldata = int(1).to_bytes(1, byteorder='little')
elif integerString == 'false':

View File

@@ -2903,11 +2903,11 @@ class DumperBase():
return dd(intval, self.laddress, form)
def display(self):
if self.ldisplay is not None:
return self.ldisplay
simple = self.value()
if simple is not None:
return str(simple)
if self.ldisplay is not None:
return self.ldisplay
#if self.ldata is not None:
# if sys.version_info[0] == 2 and isinstance(self.ldata, buffer):
# return bytes(self.ldata).encode('hex')

View File

@@ -45,7 +45,7 @@ Node {
source: "meshes/axishelper.mesh"
materials: DefaultMaterial {
id: posMat
emissiveColor: posModel.hovering ? armRoot.hoverColor : armRoot.color
diffuseColor: posModel.hovering ? armRoot.hoverColor : armRoot.color
lighting: DefaultMaterial.NoLighting
}
pickable: true
@@ -62,7 +62,7 @@ Node {
scale: Qt.vector3d(0.025, 0.025, 0.025)
materials: DefaultMaterial {
id: negMat
emissiveColor: negModel.hovering ? armRoot.hoverColor : armRoot.color
diffuseColor: negModel.hovering ? armRoot.hoverColor : armRoot.color
lighting: DefaultMaterial.NoLighting
}
pickable: true

View File

@@ -48,7 +48,7 @@ Model {
materials: [
DefaultMaterial {
id: defaultMaterial
emissiveColor: cameraFrustum.selected ? "#FF0000" : "#555555"
diffuseColor: cameraFrustum.selected ? "#FF0000" : "#555555"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}

View File

@@ -31,7 +31,7 @@ Model {
id: rootModel
property View3D view3D
property alias color: material.emissiveColor
property alias color: material.diffuseColor
property Node targetNode: null
property bool dragging: mouseAreaYZ.dragging || mouseAreaXZ.dragging
property bool active: false
@@ -52,7 +52,7 @@ Model {
DefaultMaterial {
id: material
emissiveColor: "white"
diffuseColor: "white"
lighting: DefaultMaterial.NoLighting
}

View File

@@ -202,7 +202,7 @@ Item {
if ("transformMode" in toolStates)
transformMode = toolStates.transformMode;
else if (resetToDefault)
selectionMode = EditView3D.TransformMode.Move;
transformMode = EditView3D.TransformMode.Move;
if ("editCamState" in toolStates)
cameraControl.restoreCameraState(toolStates.editCamState);
@@ -266,8 +266,10 @@ Item {
{
var theObject = object;
if (selectionMode === EditView3D.SelectionMode.Group) {
while (theObject && theObject !== activeScene && theObject.parent !== activeScene)
while (theObject && theObject !== activeScene
&& (activeScene instanceof Model || theObject.parent !== activeScene)) {
theObject = theObject.parent;
}
}
// Object selection logic:
// Regular click: Clear any multiselection, single-selects the clicked object
@@ -487,6 +489,12 @@ Item {
position: moveGizmo.scenePosition
}
AutoScaleHelper {
id: pivotAutoScale
view3D: overlayView
position: pivotLine.startPos
}
Line3D {
id: pivotLine
visible: viewRoot.selectedNode
@@ -513,14 +521,14 @@ Item {
Model {
id: pivotCap
source: "#Sphere"
scale: autoScale.getScale(Qt.vector3d(0.03, 0.03, 0.03))
scale: pivotAutoScale.getScale(Qt.vector3d(0.03, 0.03, 0.03))
position: pivotLine.startPos
materials: [
DefaultMaterial {
id: lineMat
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
emissiveColor: pivotLine.color
diffuseColor: pivotLine.color
}
]
}

View File

@@ -47,7 +47,7 @@ Node {
materials: [
DefaultMaterial {
id: mainGridMaterial
emissiveColor: "#aaaaaa"
diffuseColor: "#aaaaaa"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
@@ -65,7 +65,7 @@ Node {
materials: [
DefaultMaterial {
id: subGridMaterial
emissiveColor: mainGridMaterial.emissiveColor
diffuseColor: mainGridMaterial.diffuseColor
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
@@ -82,7 +82,7 @@ Node {
materials: [
DefaultMaterial {
id: vCenterLineMaterial
emissiveColor: "#00a1d2"
diffuseColor: "#00a1d2"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
@@ -99,7 +99,7 @@ Node {
materials: [
DefaultMaterial {
id: hCenterLineMaterial
emissiveColor: "#cb211a"
diffuseColor: "#cb211a"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}

View File

@@ -336,7 +336,7 @@ Node {
DefaultMaterial {
id: lightMaterial
emissiveColor: lightGizmo.color
diffuseColor: lightGizmo.color
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}

View File

@@ -33,7 +33,7 @@ Node {
property alias startPos: lineGeometry.startPos
property alias endPos: lineGeometry.endPos
property alias name: lineGeometry.name // Name must be unique for each line
property alias color: lineMat.emissiveColor
property alias color: lineMat.diffuseColor
Model {
geometry: LineGeometry {

View File

@@ -31,7 +31,7 @@ Model {
id: rootModel
property View3D view3D
property alias color: gizmoMaterial.emissiveColor
property alias color: gizmoMaterial.diffuseColor
property alias priority: mouseArea.priority
property Node targetNode: null
property bool dragging: mouseArea.dragging
@@ -53,7 +53,7 @@ Model {
DefaultMaterial {
id: gizmoMaterial
emissiveColor: "white"
diffuseColor: "white"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}

View File

@@ -175,7 +175,7 @@ Node {
source: "#Sphere"
materials: DefaultMaterial {
id: material
emissiveColor: "black"
diffuseColor: "black"
opacity: mouseAreaFree.hovering ? 0.15 : 0
lighting: DefaultMaterial.NoLighting
}

View File

@@ -31,7 +31,7 @@ Model {
id: rotateRing
property View3D view3D
property alias color: material.emissiveColor
property alias color: material.diffuseColor
property Node targetNode: null
property bool dragging: mouseAreaMain.dragging
property bool active: false
@@ -60,7 +60,7 @@ Model {
materials: DefaultMaterial {
id: material
emissiveColor: "white"
diffuseColor: "white"
lighting: DefaultMaterial.NoLighting
}

View File

@@ -170,7 +170,7 @@ Node {
scale: Qt.vector3d(0.024, 0.024, 0.024)
materials: DefaultMaterial {
id: material
emissiveColor: highlightOnHover
diffuseColor: highlightOnHover
&& (centerMouseArea.hovering || centerMouseArea.dragging)
? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1))
: Qt.rgba(0.5, 0.5, 0.5, 1)

View File

@@ -44,7 +44,7 @@ DirectionalDraggable {
scale: Qt.vector3d(0.020, 0.020, 0.020)
materials: DefaultMaterial {
id: material
emissiveColor: scaleRod.color
diffuseColor: scaleRod.color
lighting: DefaultMaterial.NoLighting
}
}

View File

@@ -56,7 +56,7 @@ Node {
materials: [
DefaultMaterial {
emissiveColor: "#fff600"
diffuseColor: "#fff600"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}

View File

@@ -23,9 +23,8 @@
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.0
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
@@ -76,8 +75,6 @@ Item {
id: mouseRegion
anchors.fill: parent
tooltip: itemName
onPressed: {
rootView.startDragAndDrop(mouseRegion, itemLibraryEntry)
}

View File

@@ -23,15 +23,11 @@
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.0
import "../common"
import QtQuick.Layouts 1.0
import HelperWidgets 2.0
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioTheme 1.0 as StudioTheme
/* The view displaying the item grid.
@@ -65,9 +61,6 @@ ScrollView {
Item {
id: styleConstants
readonly property color backgroundColor: Theme.qmlDesignerBackgroundColorDarkAlternate()
readonly property color lighterBackgroundColor: Theme.color(Theme.FancyToolBarSeparatorColor)
property int textWidth: 58
property int textHeight: Theme.smallFontPixelSize() * 2
@@ -81,48 +74,37 @@ ScrollView {
2 * cellVerticalMargin + cellVerticalSpacing
}
Rectangle {
id: background
anchors.fill: parent
color: styleConstants.backgroundColor
}
Column {
id: column
Repeater {
model: itemLibraryModel // to be set in Qml context
delegate: Section {
width: itemsView.width -
(itemsView.verticalScrollBarVisible ? StudioTheme.Values.scrollBarThickness : 0)
caption: sectionName // to be set by model
visible: sectionVisible
topPadding: 2
leftPadding: 2
rightPadding: 1
expanded: sectionExpanded
onExpandedChanged: itemLibraryModel.setExpanded(expanded, sectionName);
Grid {
id: itemGrid
style: DesignerScrollViewStyle {
columns: parent.width / styleConstants.cellWidth
property int flexibleWidth: (parent.width - styleConstants.cellWidth * columns) / columns
}
Flickable {
contentHeight: column.height
Column {
id: column
Repeater {
model: itemLibraryModel // to be set in Qml context
delegate: Section {
width: itemsView.viewport.width
caption: sectionName // to be set by model
visible: sectionVisible
topPadding: 2
leftPadding: 2
rightPadding: 1
expanded: sectionExpanded
onExpandedChanged: itemLibraryModel.setExpanded(expanded, sectionName);
Grid {
id: itemGrid
columns: parent.width / styleConstants.cellWidth
property int flexibleWidth: (parent.width - styleConstants.cellWidth * columns) / columns
Repeater {
model: sectionEntries
delegate: ItemDelegate {
visible: itemVisible
width: styleConstants.cellWidth + itemGrid.flexibleWidth
height: styleConstants.cellHeight
}
Repeater {
model: sectionEntries
delegate: ItemDelegate {
visible: itemVisible
width: styleConstants.cellWidth + itemGrid.flexibleWidth
height: styleConstants.cellHeight
}
}
}
}
}
}
}

View File

@@ -33,7 +33,7 @@ Section {
caption: qsTr("Advanced")
SectionLayout {
rows: 4
columns: 2
Label {
text: qsTr("Origin")
@@ -171,7 +171,6 @@ Section {
backendValue: backendValues.focus
text: backendValues.focus.valueToString
enabled: backendValues.focus.isAvailable
implicitWidth: 180
}
ExpandingSpacer {
}
@@ -187,7 +186,6 @@ Section {
backendValue: backendValues.activeFocusOnTab
text: backendValues.activeFocusOnTab.valueToString
enabled: backendValues.activeFocusOnTab.isAvailable
implicitWidth: 180
}
ExpandingSpacer {
}

View File

@@ -32,10 +32,10 @@ import StudioTheme 1.0 as StudioTheme
Section {
anchors.left: parent.left
anchors.right: parent.right
caption: qsTr("Align")
ColumnLayout {
width: parent.width
SectionLayout {
enabled: alignDistribute.multiSelection &&
!alignDistribute.selectionHasAnchors &&
alignDistribute.selectionExclusivlyItems &&
@@ -49,8 +49,11 @@ Section {
Label {
text: qsTr("Align objects")
width: 120
Layout.columnSpan: 2
}
RowLayout {
Layout.columnSpan: 2
Row {
spacing: -StudioTheme.Values.border
AbstractButton {
@@ -105,8 +108,11 @@ Section {
Label {
text: qsTr("Distribute objects")
width: 120
Layout.columnSpan: 2
}
RowLayout {
Layout.columnSpan: 2
Row {
spacing: -StudioTheme.Values.border
AbstractButton {
@@ -161,8 +167,11 @@ Section {
Label {
text: qsTr("Distribute spacing")
width: 120
Layout.columnSpan: 2
}
RowLayout {
Layout.columnSpan: 2
Row {
spacing: -StudioTheme.Values.border
AbstractButton {
@@ -242,18 +251,16 @@ Section {
}
}
SectionLayout {
columns: 2
ItemFilterModel {
id: itemFilterModel
modelNodeBackendProperty: modelNodeBackend
selectionOnly: true
}
ItemFilterModel {
id: itemFilterModel
modelNodeBackendProperty: modelNodeBackend
selectionOnly: true
}
Label {
text: qsTr("Align to")
}
Label {
text: qsTr("Align to")
}
SecondColumnLayout {
ComboBox {
id: alignToComboBox
Layout.fillWidth: true
@@ -267,9 +274,14 @@ Section {
}
}
Label {
text: qsTr("Key object")
ExpandingSpacer {
}
}
Label {
text: qsTr("Key object")
}
SecondColumnLayout {
ComboBox {
id: keyObjectComboBox
enabled: alignToComboBox.currentIndex === 2
@@ -285,11 +297,15 @@ Section {
lastSelectedItem = "" // TODO
}
}
ExpandingSpacer {
}
}
SectionLayout {
columns: 1
Layout.topMargin: 30
Layout.columnSpan: 2
visible: alignDistribute.multiSelection &&
(alignDistribute.selectionHasAnchors ||
!alignDistribute.selectionExclusivlyItems ||

View File

@@ -23,9 +23,9 @@
**
****************************************************************************/
import QtQuick 2.0
import QtQuick 2.15
import HelperWidgets 2.0
import QtQuick.Layouts 1.0
import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0
import StudioControls 1.0 as StudioControls
@@ -34,11 +34,9 @@ import StudioTheme 1.0 as StudioTheme
RowLayout {
id: anchorRow
anchors.left: parent.left
anchors.right: parent.right
opacity: enabled ? 1 : 0.5
property alias iconSource: icon.source
property alias iconSource: iconLabel.icon
property variant anchorMargin
@@ -64,8 +62,10 @@ RowLayout {
readonly property color __defaultTextColor: StudioTheme.Values.themeTextColor
IconLabel {
id: icon
id: iconLabel
Layout.alignment: Qt.AlignTop
Layout.topMargin: 4
Layout.leftMargin: 4
}
GridLayout {

View File

@@ -23,10 +23,11 @@
**
****************************************************************************/
import QtQuick 2.0
import HelperWidgets 2.0
import QtQuick.Layouts 1.0
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
@@ -35,14 +36,15 @@ Rectangle {
width: 320
height: 400
color: Theme.qmlDesignerBackgroundColorDarkAlternate()
MouseArea {
anchors.fill: parent
onClicked: forceActiveFocus()
}
ScrollView {
clip: true
anchors.fill: parent
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
Column {
y: -1
@@ -57,7 +59,6 @@ Rectangle {
SectionLayout {
Label {
text: qsTr("Type")
}
SecondColumnLayout {
@@ -65,15 +66,12 @@ Rectangle {
RoundedPanel {
Layout.fillWidth: true
height: 24
height: StudioTheme.Values.height
Label {
x: 6
anchors.fill: parent
anchors.leftMargin: 16
anchors.leftMargin: StudioTheme.Values.inputHorizontalPadding
text: backendValues.className.value
verticalAlignment: Text.AlignVCenter
}
ToolTipArea {
anchors.fill: parent
@@ -87,10 +85,10 @@ Rectangle {
}
ExpressionTextField {
z: 2
id: typeLineEdit
z: 2
completeOnlyTypes: true
replaceCurrentTextByCompletion: true
anchors.fill: parent
visible: false
@@ -98,10 +96,26 @@ Rectangle {
showButtons: false
fixedSize: true
property bool blockEditingFinished: false
onEditingFinished: {
if (visible)
if (typeLineEdit.blockEditingFinished)
return
typeLineEdit.blockEditingFinished = true
if (typeLineEdit.visible)
changeTypeName(typeLineEdit.text.trim())
visible = false
typeLineEdit.visible = false
typeLineEdit.blockEditingFinished = false
typeLineEdit.completionList.model = null
}
onRejected: {
typeLineEdit.visible = false
typeLineEdit.completionList.model = null
}
}
@@ -117,6 +131,7 @@ Rectangle {
}
SecondColumnLayout {
spacing: 2
LineEdit {
id: lineEdit
@@ -129,29 +144,55 @@ Rectangle {
showExtendedFunctionButton: false
enabled: !modelNodeBackend.multiSelection
}
// workaround: without this item the lineedit does not shrink to the
// right size after resizing to a wider width
Image {
visible: !modelNodeBackend.multiSelection
Layout.preferredWidth: 20
Layout.preferredHeight: 20
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked"
Rectangle {
id: aliasIndicator
color: "transparent"
border.color: "transparent"
implicitWidth: StudioTheme.Values.height
implicitHeight: StudioTheme.Values.height
z: 10
Label {
id: aliasIndicatorIcon
enabled: !modelNodeBackend.multiSelection
anchors.fill: parent
text: {
if (!aliasIndicatorIcon.enabled)
return StudioTheme.Constants.idAliasOff
return hasAliasExport ? StudioTheme.Constants.idAliasOn : StudioTheme.Constants.idAliasOff
}
color: {
if (!aliasIndicatorIcon.enabled)
return StudioTheme.Values.themeTextColorDisabled
return hasAliasExport ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeTextColor
}
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: Math.round(16 * StudioTheme.Values.scaleFactor)
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
states: [
State {
name: "hovered"
when: toolTipArea.containsMouse && aliasIndicatorIcon.enabled
PropertyChanges {
target: aliasIndicatorIcon
scale: 1.2
}
}
]
}
ToolTipArea {
id: toolTipArea
enabled: !modelNodeBackend.multiSelection
anchors.fill: parent
onClicked: toogleExportAlias()
tooltip: qsTr("Exports this item as an alias property of the root item.")
}
}
Item { //dummy object to preserve layout in case of multiselection
Layout.preferredWidth: 20
Layout.preferredHeight: 20
enabled: modelNodeBackend.multiSelection
visible: enabled
}
}
Label {
@@ -280,7 +321,6 @@ Rectangle {
Item {
width: 10
height: 10
}
CheckBox {
@@ -319,88 +359,92 @@ Rectangle {
width: 4
}
TabView {
StudioControls.TabBar {
id: tabBar
anchors.left: parent.left
anchors.right: parent.right
frameVisible: false
id: tabView
StudioControls.TabButton {
text: backendValues.className.value
}
StudioControls.TabButton {
text: qsTr("Layout")
}
StudioControls.TabButton {
text: qsTr("Advanced")
}
}
StackLayout {
anchors.left: parent.left
anchors.right: parent.right
currentIndex: tabBar.currentIndex
property int currentHeight: children[currentIndex].implicitHeight
property int extraHeight: 40
height: currentHeight + extraHeight
property int currentHeight: getTab(currentIndex).item.implicitHeight
property int extraHeight: 40
Column {
anchors.left: parent.left
anchors.right: parent.right
Tab {
title: backendValues.className.value
Loader {
anchors.left: parent.left
anchors.right: parent.right
visible: theSource !== ""
component: Column {
id: specificsTwo;
sourceComponent: specificQmlComponent
property string theSource: specificQmlData
onTheSourceChanged: {
active = false
active = true
}
}
Loader {
anchors.left: parent.left
anchors.right: parent.right
Loader {
anchors.left: parent.left
anchors.right: parent.right
visible: theSource !== ""
id: specificsOne;
source: specificsUrl;
id: specificsTwo;
sourceComponent: specificQmlComponent
property string theSource: specificQmlData
onTheSourceChanged: {
active = false
active = true
}
}
Loader {
anchors.left: parent.left
anchors.right: parent.right
id: specificsOne;
source: specificsUrl;
property int loaderHeight: specificsOne.item.height + tabView.extraHeight
}
property int loaderHeight: specificsOne.item.height + tabView.extraHeight
}
}
Tab {
title: qsTr("Layout")
component: Column {
anchors.left: parent.left
anchors.right: parent.right
Column {
anchors.left: parent.left
anchors.right: parent.right
LayoutSection {
}
LayoutSection {
}
MarginSection {
visible: anchorBackend.isInLayout
backendValueTopMargin: backendValues.Layout_topMargin
backendValueBottomMargin: backendValues.Layout_bottomMargin
backendValueLeftMargin: backendValues.Layout_leftMargin
backendValueRightMargin: backendValues.Layout_rightMargin
backendValueMargins: backendValues.Layout_margins
}
MarginSection {
visible: anchorBackend.isInLayout
backendValueTopMargin: backendValues.Layout_topMargin
backendValueBottomMargin: backendValues.Layout_bottomMargin
backendValueLeftMargin: backendValues.Layout_leftMargin
backendValueRightMargin: backendValues.Layout_rightMargin
backendValueMargins: backendValues.Layout_margins
}
AlignDistributeSection {
visible: !anchorBackend.isInLayout
}
AlignDistributeSection {
visible: !anchorBackend.isInLayout
}
}
Tab {
anchors.fill: parent
title: qsTr("Advanced")
component: Column {
anchors.left: parent.left
anchors.right: parent.right
Column {
anchors.left: parent.left
anchors.right: parent.right
AdvancedSection {
}
LayerSection {
}
AdvancedSection {
}
LayerSection {
}
}
}

View File

@@ -50,8 +50,8 @@ Section {
}
AnchorRow {
visible: anchorBackend.topAnchored;
iconSource: "image://icons/anchor-top"
visible: anchorBackend.topAnchored
iconSource: StudioTheme.Constants.anchorTop
anchorMargin: backendValues.anchors_topMargin
targetName: anchorBackend.topTarget
onTargetChanged: {
@@ -73,8 +73,8 @@ Section {
}
AnchorRow {
visible: anchorBackend.bottomAnchored;
iconSource: "image://icons/anchor-bottom"
visible: anchorBackend.bottomAnchored
iconSource: StudioTheme.Constants.anchorBottom
anchorMargin: backendValues.anchors_bottomMargin
targetName: anchorBackend.bottomTarget
onTargetChanged: {
@@ -97,8 +97,8 @@ Section {
}
AnchorRow {
visible: anchorBackend.leftAnchored;
iconSource: "image://icons/anchor-left"
visible: anchorBackend.leftAnchored
iconSource: StudioTheme.Constants.anchorLeft
anchorMargin: backendValues.anchors_leftMargin
targetName: anchorBackend.leftTarget
onTargetChanged: {
@@ -120,8 +120,8 @@ Section {
}
AnchorRow {
visible: anchorBackend.rightAnchored;
iconSource: "image://icons/anchor-right"
visible: anchorBackend.rightAnchored
iconSource: StudioTheme.Constants.anchorRight
anchorMargin: backendValues.anchors_rightMargin
targetName: anchorBackend.rightTarget
onTargetChanged: {
@@ -145,8 +145,8 @@ Section {
AnchorRow {
showAlternativeTargets: false
visible: anchorBackend.horizontalCentered;
iconSource: "image://icons/anchor-horizontal"
visible: anchorBackend.horizontalCentered
iconSource: StudioTheme.Constants.centerHorizontal
anchorMargin: backendValues.anchors_horizontalCenterOffset
targetName: anchorBackend.horizontalTarget
onTargetChanged: {
@@ -158,8 +158,8 @@ Section {
AnchorRow {
showAlternativeTargets: false
visible: anchorBackend.verticalCentered;
iconSource: "image://icons/anchor-vertical"
visible: anchorBackend.verticalCentered
iconSource: StudioTheme.Constants.centerVertical
anchorMargin: backendValues.anchors_verticalCenterOffset
targetName: anchorBackend.verticalTarget
onTargetChanged: {

View File

@@ -23,10 +23,11 @@
**
****************************************************************************/
import QtQuick 2.0
import HelperWidgets 2.0
import QtQuick 2.15
import QtQuick.Layouts 1.0
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioTheme 1.0 as StudioTheme
Rectangle {
id: itemPane
@@ -43,6 +44,7 @@ Rectangle {
anchors.fill: parent
Column {
id: rootColumn
y: -1
width: itemPane.width
Section {
@@ -54,7 +56,6 @@ Rectangle {
SectionLayout {
Label {
text: qsTr("Type")
}
SecondColumnLayout {
@@ -62,15 +63,12 @@ Rectangle {
RoundedPanel {
Layout.fillWidth: true
height: 24
height: StudioTheme.Values.height
Label {
x: 6
anchors.fill: parent
anchors.leftMargin: 16
anchors.leftMargin: StudioTheme.Values.inputHorizontalPadding
text: backendValues.className.value
verticalAlignment: Text.AlignVCenter
}
ToolTipArea {
anchors.fill: parent
@@ -87,7 +85,7 @@ Rectangle {
z: 2
id: typeLineEdit
completeOnlyTypes: true
replaceCurrentTextByCompletion: true
anchors.fill: parent
visible: false
@@ -95,17 +93,33 @@ Rectangle {
showButtons: false
fixedSize: true
property bool blockEditingFinished: false
onEditingFinished: {
if (visible)
if (typeLineEdit.blockEditingFinished)
return
typeLineEdit.blockEditingFinished = true
if (typeLineEdit.visible)
changeTypeName(typeLineEdit.text.trim())
visible = false
typeLineEdit.visible = false
typeLineEdit.blockEditingFinished = false
typeLineEdit.completionList.model = null
}
onRejected: {
typeLineEdit.visible = false
typeLineEdit.completionList.model = null
}
}
}
Item {
Layout.preferredWidth: 16
Layout.preferredHeight: 16
Layout.preferredWidth: 20
Layout.preferredHeight: 20
}
}
@@ -114,6 +128,7 @@ Rectangle {
}
SecondColumnLayout {
spacing: 2
LineEdit {
id: lineEdit
@@ -127,12 +142,48 @@ Rectangle {
enabled: !modelNodeBackend.multiSelection
}
Image {
visible: !modelNodeBackend.multiSelection
Layout.preferredWidth: 16
Layout.preferredHeight: 16
source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked"
Rectangle {
id: aliasIndicator
color: "transparent"
border.color: "transparent"
implicitWidth: StudioTheme.Values.height
implicitHeight: StudioTheme.Values.height
z: 10
Label {
id: aliasIndicatorIcon
enabled: !modelNodeBackend.multiSelection
anchors.fill: parent
text: {
if (!aliasIndicatorIcon.enabled)
return StudioTheme.Constants.idAliasOff
return hasAliasExport ? StudioTheme.Constants.idAliasOn : StudioTheme.Constants.idAliasOff
}
color: {
if (!aliasIndicatorIcon.enabled)
return StudioTheme.Values.themeTextColorDisabled
return hasAliasExport ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeTextColor
}
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: Math.round(16 * StudioTheme.Values.scaleFactor)
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
states: [
State {
name: "hovered"
when: toolTipArea.containsMouse && aliasIndicatorIcon.enabled
PropertyChanges {
target: aliasIndicatorIcon
scale: 1.2
}
}
]
}
ToolTipArea {
id: toolTipArea
enabled: !modelNodeBackend.multiSelection
anchors.fill: parent
onClicked: toogleExportAlias()
@@ -148,69 +199,30 @@ Rectangle {
width: 4
}
TabView {
Column {
anchors.left: parent.left
anchors.right: parent.right
frameVisible: false
Loader {
id: specificsTwo
anchors.left: parent.left
anchors.right: parent.right
visible: theSource !== ""
sourceComponent: specificQmlComponent
id: tabView
height: Math.max(layoutSectionHeight, specficsHeight)
property string theSource: specificQmlData
property int layoutSectionHeight: 400
property int specficsOneHeight: 0
property int specficsTwoHeight: 0
property int specficsHeight: Math.max(specficsOneHeight, specficsTwoHeight)
property int extraHeight: 40
Tab {
id: tab
title: backendValues.className.value
component: Column {
anchors.left: parent.left
anchors.right: parent.right
Loader {
anchors.left: parent.left
anchors.right: parent.right
visible: theSource !== ""
id: specificsTwo;
sourceComponent: specificQmlComponent
property string theSource: specificQmlData
onTheSourceChanged: {
active = false
active = true
}
property int loaderHeight: specificsTwo.item.height + tabView.extraHeight
onLoaderHeightChanged: tabView.specficsTwoHeight = loaderHeight
onLoaded: {
tabView.specficsTwoHeight = loaderHeight
}
}
Loader {
anchors.left: parent.left
anchors.right: parent.right
id: specificsOne;
source: specificsUrl;
property int loaderHeight: specificsOne.item.height + tabView.extraHeight
onLoaderHeightChanged: tabView.specficsHeight = loaderHeight
onLoaded: {
tabView.specficsOneHeight = loaderHeight
}
}
onTheSourceChanged: {
active = false
active = true
}
}
Loader {
id: specificsOne
anchors.left: parent.left
anchors.right: parent.right
source: specificsUrl
}
}
}
}

View File

@@ -156,7 +156,7 @@ StudioControls.ButtonRow {
buttonIcon: StudioTheme.Constants.centerVertical
tooltip: qsTr("Anchor item vertically.")
property bool verticalCentered: anchorBackend.verticalCentered;
property bool verticalCentered: anchorBackend.verticalCentered
onVerticalCenteredChanged: {
checked = verticalCentered
}
@@ -179,7 +179,7 @@ StudioControls.ButtonRow {
buttonIcon: StudioTheme.Constants.centerHorizontal
tooltip: qsTr("Anchor item horizontally.")
property bool horizontalCentered: anchorBackend.horizontalCentered;
property bool horizontalCentered: anchorBackend.horizontalCentered
onHorizontalCenteredChanged: {
checked = horizontalCentered
}

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,48 +23,79 @@
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.1 as Controls
import QtQuick.Controls.Styles 1.1
import "Constants.js" as Constants
import QtQuick 2.15
import QtQuick.Templates 2.15 as T
import StudioTheme 1.0 as StudioTheme
Controls.Button {
property color borderColor: "#222"
property color highlightColor: "orange"
property color textColor: "#eee"
style: ButtonStyle {
label: Text {
color: Constants.colorsDefaultText
anchors.fill: parent
renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: control.text
opacity: enabled ? 1 : 0.7
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 23
radius: 3
gradient: control.pressed ? pressedGradient : gradient
Gradient{
id: pressedGradient
GradientStop{color: "#333" ; position: 0}
}
Gradient {
id: gradient
GradientStop {color: "#606060" ; position: 0}
GradientStop {color: "#404040" ; position: 0.07}
GradientStop {color: "#303030" ; position: 1}
}
Rectangle {
anchors.fill: parent
anchors.margins: -1
color: "transparent"
radius: 4
opacity: 0.3
visible: control.activeFocus
}
}
T.AbstractButton {
id: myButton
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
background: Rectangle {
id: buttonBackground
implicitWidth: 100
implicitHeight: 23
radius: 3
color: StudioTheme.Values.themeControlBackground
border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border
}
contentItem: Text {
id: buttonText
color: StudioTheme.Values.themeTextColor
font.family: StudioTheme.Constants.font.family
font.pixelSize: StudioTheme.Values.myFontSize
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
anchors.fill: parent
renderType: Text.QtRendering
text: myButton.text
}
states: [
State {
name: "default"
when: myButton.enabled && !myButton.hovered && !myButton.pressed
&& !myButton.checked
PropertyChanges {
target: buttonBackground
color: StudioTheme.Values.themeControlBackground
}
},
State {
name: "hovered"
when: myButton.hovered && !myButton.pressed
PropertyChanges {
target: buttonBackground
color: StudioTheme.Values.themeHoverHighlight
}
},
State {
name: "pressed"
when: myButton.hovered && myButton.pressed
PropertyChanges {
target: buttonBackground
color: StudioTheme.Values.themeControlBackgroundPressed
border.color: StudioTheme.Values.themeInteraction
}
},
State {
name: "disabled"
when: !myButton.enabled
PropertyChanges {
target: buttonBackground
color: StudioTheme.Values.themeControlBackgroundDisabled
border.color: StudioTheme.Values.themeControlOutlineDisabled
}
PropertyChanges {
target: buttonText
color: StudioTheme.Values.themeTextColorDisabled
}
}
]
}

View File

@@ -23,10 +23,8 @@
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.0 as Controls
import QtQuick.Layouts 1.0
import QtQuick.Controls.Private 1.0
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0
Item {

View File

@@ -38,7 +38,7 @@ Column {
property bool supportGradient: false
property string caption: "Color"
property string caption: qsTr("Color")
property variant backendValue
@@ -47,7 +47,6 @@ Column {
return Qt.rgba(backendValue.value.x, backendValue.value.y, backendValue.value.z, 1);
else
return backendValue.value;
}
property alias gradientPropertyName: gradientLine.gradientPropertyName

View File

@@ -104,6 +104,7 @@ Rectangle {
color: "transparent"
border.width: StudioTheme.Values.border
border.color: StudioTheme.Values.themeInteraction
visible: myColumn.currentItem ? myColumn.currentItem.focus : false
x: myColumn.currentItem ? myColumn.currentItem.x : 0
y: myColumn.currentItem ? myColumn.currentItem.y : 0
z: 10

View File

@@ -23,13 +23,14 @@
**
****************************************************************************/
import QtQuick 2.1
import "Constants.js" as Constants
import StudioControls 1.0 as StudioControls
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuickDesignerTheme 1.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
StudioControls.TextField {
id: textField
signal rejected
@@ -38,103 +39,199 @@ StudioControls.TextField {
actionIndicator.visible: false
property bool completeOnlyTypes: false
property bool completionActive: listView.count > 0
property bool completionActive: listView.model !== null
property bool dotCompletion: false
property int dotCursorPos: 0
property string prefix
property alias showButtons: buttonrow.visible
property bool fixedSize: false
property bool replaceCurrentTextByCompletion: false
property alias completionList: listView
function commitCompletion() {
var cursorPos = textField.cursorPosition
var string = textField.text
var before = string.slice(0, cursorPos - textField.prefix.length)
var after = string.slice(cursorPos)
textField.text = before + listView.currentItem.text + after
textField.cursorPosition = cursorPos + listView.currentItem.text.length - prefix.length
if (replaceCurrentTextByCompletion) {
textField.text = listView.currentItem.text
} else {
var cursorPos = textField.cursorPosition
var string = textField.text
var before = string.slice(0, cursorPos - textField.prefix.length)
var after = string.slice(cursorPos)
textField.text = before + listView.currentItem.text + after
textField.cursorPosition = cursorPos + listView.currentItem.text.length - prefix.length
}
listView.model = null
}
ListView {
id: listView
Popup {
id: textFieldPopup
x: textField.x
y: textField.height - StudioTheme.Values.border
width: textField.width
// TODO Setting the height on the popup solved the problem with the popup of height 0,
// but it has the problem that it sometimes extend over the border of the actual window
// and is then cut off.
height: Math.min(contentItem.implicitHeight + textFieldPopup.topPadding + textFieldPopup.bottomPadding,
textField.Window.height - topMargin - bottomMargin,
StudioTheme.Values.maxComboBoxPopupHeight)
padding: StudioTheme.Values.border
margins: 0 // If not defined margin will be -1
closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnPressOutsideParent
| Popup.CloseOnEscape | Popup.CloseOnReleaseOutside
| Popup.CloseOnReleaseOutsideParent
clip: true
cacheBuffer: 0
snapMode: ListView.SnapToItem
boundsBehavior: Flickable.StopAtBounds
visible: textField.completionActive
delegate: Text {
text: modelData
color: Theme.color(Theme.PanelTextColorLight)
Rectangle {
visible: index === listView.currentIndex
z: -1
anchors.fill: parent
color: Theme.qmlDesignerBackgroundColorDarkAlternate()
onClosed: listView.model = null
contentItem: ListView {
id: listView
clip: true
implicitHeight: contentHeight
boundsBehavior: Flickable.StopAtBounds
ScrollBar.vertical: StudioControls.ScrollBar {
id: popupScrollBar
}
model: null
delegate: ItemDelegate {
id: myItemDelegate
width: textFieldPopup.width - textFieldPopup.leftPadding - textFieldPopup.rightPadding
- (popupScrollBar.visible ? popupScrollBar.contentItem.implicitWidth
+ 2 : 0) // TODO Magic number
height: StudioTheme.Values.height - 2 * StudioTheme.Values.border
padding: 0
text: itemDelegateText.text
contentItem: Text {
id: itemDelegateText
leftPadding: 8
text: modelData
color: StudioTheme.Values.themeTextColor
font: textField.font
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
color: "transparent"
}
hoverEnabled: true
onHoveredChanged: {
if (hovered)
listView.currentIndex = index
}
onClicked: {
listView.currentIndex = index
if (textField.completionActive)
textField.commitCompletion()
}
}
highlight: Rectangle {
id: listViewHighlight
width: textFieldPopup.width - textFieldPopup.leftPadding - textFieldPopup.rightPadding
- (popupScrollBar.visible ? popupScrollBar.contentItem.implicitWidth
+ 2 : 0)
height: StudioTheme.Values.height - 2 * StudioTheme.Values.border
color: StudioTheme.Values.themeInteraction
y: listView.currentItem.y
}
highlightFollowsCurrentItem: false
}
anchors.top: parent.top
anchors.topMargin: 26
anchors.bottomMargin: textField.fixedSize ? -180 : 12
anchors.bottom: parent.bottom
anchors.left: parent.left
width: 200
spacing: 2
children: [
Rectangle {
visible: textField.fixedSize
anchors.fill: parent
color: Theme.qmlDesignerBackgroundColorDarker()
border.color: Theme.qmlDesignerBorderColor()
anchors.rightMargin: 12
z: -1
}
background: Rectangle {
color: StudioTheme.Values.themeControlBackground
border.color: StudioTheme.Values.themeInteraction
border.width: StudioTheme.Values.border
}
]
enter: Transition {
}
exit: Transition {
}
}
verticalAlignment: Text.AlignTop
onPressed: listView.model = null
Keys.priority: Keys.BeforeItem
Keys.onPressed: {
var text = textField.text
var pos = textField.cursorPosition
var explicitComplete = true
if (event.key === Qt.Key_Period) {
switch (event.key) {
case Qt.Key_Period:
textField.dotCursorPos = textField.cursorPosition + 1
var list = autoComplete(textField.text+".", textField.dotCursorPos, false, textField.completeOnlyTypes)
textField.prefix = list.pop()
listView.model = list;
text = textField.text + "."
pos = textField.dotCursorPos
explicitComplete = false
textField.dotCompletion = true
} else {
if (textField.completionActive) {
var list2 = autoComplete(textField.text + event.text,
textField.cursorPosition + event.text.length,
true, textField.completeOnlyTypes)
textField.prefix = list2.pop()
listView.model = list2;
}
break
case Qt.Key_Right:
if (!textField.completionActive)
return
pos = Math.min(textField.cursorPosition + 1, textField.text.length)
break
case Qt.Key_Left:
if (!textField.completionActive)
return
pos = Math.max(0, textField.cursorPosition - 1)
break
case Qt.Key_Backspace:
if (!textField.completionActive)
return
pos = textField.cursorPosition - 1
if (pos < 0)
return
text = textField.text.substring(0, pos) + textField.text.substring(textField.cursorPosition)
break
case Qt.Key_Delete:
return
default:
if (!textField.completionActive)
return
var tmp = textField.text
text = tmp.substring(0, textField.cursorPosition) + event.text + tmp.substring(textField.cursorPosition)
pos = textField.cursorPosition + event.text.length
}
var list = autoComplete(text.trim(), pos, explicitComplete, textField.completeOnlyTypes)
textField.prefix = text.substring(0, pos)
if (list.length && list[list.length - 1] === textField.prefix)
list.pop()
listView.model = list
}
Keys.onSpacePressed: {
if (event.modifiers & Qt.ControlModifier) {
var list = autoComplete(textField.text, textField.cursorPosition, true, textField.completeOnlyTypes)
textField.prefix = list.pop()
listView.model = list;
textField.prefix = textField.text.substring(0, textField.cursorPosition)
if (list.length && list[list.length - 1] === textField.prefix)
list.pop()
listView.model = list
textField.dotCompletion = false
event.accepted = true;
if (list.length == 1)
textField.commitCompletion()
} else {
event.accepted = false
}

View File

@@ -73,7 +73,6 @@ Section {
Layout.fillWidth: true
width: 160
property string familyName: backendValue.value
onFamilyNameChanged: print(styleNamesForFamily(familyName))
}
Label {

View File

@@ -23,12 +23,11 @@
**
****************************************************************************/
import QtQuick 2.11
import QtQuick.Layouts 1.12
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Dialogs 1.3
import HelperWidgets 2.0
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
@@ -76,49 +75,52 @@ Dialog {
anchors.margins: 13
anchors.bottomMargin: 71
TabView {
id: presetTabView
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
Layout.fillHeight: true
Layout.fillWidth: true
StudioControls.TabBar {
id: presetTabBar
Tab {
title: qsTr("System Presets")
anchors.fill: parent
anchors.left: parent.left
anchors.right: parent.right
GradientPresetTabContent {
id: defaultTabContent
viewModel: defaultPresetListModel
editableName: false
}
StudioControls.TabButton {
text: qsTr("System Presets")
}
StudioControls.TabButton {
text: qsTr("User Presets")
}
}
StackLayout {
anchors.left: parent.left
anchors.right: parent.right
currentIndex: presetTabBar.currentIndex
GradientPresetTabContent {
id: defaultTabContent
viewModel: defaultPresetListModel
editableName: false
}
Tab {
title: qsTr("User Presets")
anchors.fill: parent
GradientPresetTabContent {
id: customTabContent
viewModel: customPresetListModel
editableName: true
onPresetNameChanged: customPresetListModel.changePresetName(id, name)
GradientPresetTabContent {
id: customTabContent
viewModel: customPresetListModel
editableName: true
onPresetNameChanged: customPresetListModel.changePresetName(id, name)
property int deleteId
property int deleteId
onDeleteButtonClicked: {
deleteId = id
deleteDialog.open()
}
onDeleteButtonClicked: {
deleteId = id
deleteDialog.open()
}
MessageDialog {
id: deleteDialog
visible: false
modality: Qt.WindowModal
standardButtons: Dialog.No | Dialog.Yes
title: qsTr("Delete preset?")
text: qsTr("Are you sure you want to delete this preset?")
onAccepted: customPresetListModel.deletePreset(customTabContent.deleteId)
}
MessageDialog {
id: deleteDialog
visible: false
modality: Qt.WindowModal
standardButtons: Dialog.No | Dialog.Yes
title: qsTr("Delete preset?")
text: qsTr("Are you sure you want to delete this preset?")
onAccepted: customPresetListModel.deletePreset(customTabContent.deleteId)
}
}
}

View File

@@ -23,12 +23,11 @@
**
****************************************************************************/
import QtQuick 2.11
import QtQuick.Layouts 1.12
import QtQuick.Dialogs 1.3
import HelperWidgets 2.0
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
@@ -48,271 +47,277 @@ Rectangle {
property real delegateHeight: 178
property real gridCellWidth: 160
ScrollView {
GridView {
id: gradientTable
Layout.fillWidth: true
Layout.fillHeight: true
anchors.fill: parent
anchors.leftMargin: 10
clip: true
delegate: gradientDelegate
GridView {
id: gradientTable
Layout.fillWidth: true
Layout.fillHeight: true
anchors.fill: parent
anchors.leftMargin: 10
clip: true
delegate: gradientDelegate
property int gridColumns: width / tabBackground.gridCellWidth;
cellWidth: width / gridColumns
cellHeight: 185
property int gridColumns: width / tabBackground.gridCellWidth;
cellWidth: width / gridColumns
cellHeight: 185
property bool bothVisible: horizontal.scrollBarVisible && vertical.scrollBarVisible
Component {
id: gradientDelegate
ScrollBar.horizontal: HorizontalScrollBar {
id: horizontal
parent: gradientTable
}
Rectangle {
id: backgroundCard
color: StudioTheme.Values.themeControlOutline
clip: true
ScrollBar.vertical: VerticalScrollBar {
id: vertical
parent: gradientTable
}
property real flexibleWidth: (gradientTable.width - gradientTable.cellWidth * gradientTable.gridColumns) / gradientTable.gridColumns
property bool isSelected: false
Component {
id: gradientDelegate
width: gradientTable.cellWidth + flexibleWidth - 8
height: tabBackground.delegateHeight
radius: 16
Rectangle {
id: backgroundCard
color: StudioTheme.Values.themeControlOutline
clip: true
function selectPreset(index) {
gradientTable.currentIndex = index
gradientData.stops = stopsPosList
gradientData.colors = stopsColorList
gradientData.stopsCount = stopListSize
gradientData.presetID = presetID
gradientData.presetType = presetTabView.currentIndex
property real flexibleWidth: (gradientTable.width - gradientTable.cellWidth * gradientTable.gridColumns) / gradientTable.gridColumns
property bool isSelected: false
if (gradientData.selectedItem != null)
gradientData.selectedItem.isSelected = false
width: gradientTable.cellWidth + flexibleWidth - 8
height: tabBackground.delegateHeight
radius: 16
backgroundCard.isSelected = true
gradientData.selectedItem = backgroundCard
function selectPreset(index) {
gradientTable.currentIndex = index
gradientData.stops = stopsPosList
gradientData.colors = stopsColorList
gradientData.stopsCount = stopListSize
gradientData.presetID = presetID
gradientData.presetType = presetTabBar.currentIndex
if (gradientData.selectedItem != null)
gradientData.selectedItem.isSelected = false
backgroundCard.isSelected = true
gradientData.selectedItem = backgroundCard
}
MouseArea {
id: rectMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
presetNameBox.edit = false
nameInput.focus = false
backgroundCard.selectPreset(index)
}
}
MouseArea {
id: rectMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
presetNameBox.edit = false
nameInput.focus = false
backgroundCard.selectPreset(index)
states: [
State {
name: "default"
when: !(rectMouseArea.containsMouse || removeButton.hovered ||
(nameMouseArea.containsMouse && !tabBackground.editableName)) &&
!backgroundCard.isSelected
PropertyChanges {
target: backgroundCard
color: StudioTheme.Values.themeControlOutline
border.width: 0
}
},
State {
name: "hovered"
when: (rectMouseArea.containsMouse || removeButton.hovered ||
(nameMouseArea.containsMouse && !tabBackground.editableName)) &&
!backgroundCard.isSelected
PropertyChanges {
target: backgroundCard
color: StudioTheme.Values.themeControlBackgroundPressed
border.width: 1
border.color: StudioTheme.Values.themeInteraction
}
},
State {
name: "selected"
when: backgroundCard.isSelected
PropertyChanges {
target: backgroundCard
color:StudioTheme.Values.themeInteraction
border.width: 1
border.color: StudioTheme.Values.themeControlBackgroundPressed
}
}
]
ColumnLayout {
spacing: 2
anchors.fill: parent
Rectangle {
id: gradientRect
width: 150
height: 150
radius: 16
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.topMargin: 2
gradient: Gradient {
id: showGr
}
Component {
id: stopComponent
GradientStop {}
}
Component.onCompleted: {
var stopsAmount = stopListSize;
var newStops = [];
for (var i = 0; i < stopsAmount; i++) {
newStops.push( stopComponent.createObject(showGr, { "position": stopsPosList[i], "color": stopsColorList[i] }) );
}
showGr.stops = newStops;
}
AbstractButton {
id: removeButton
visible: editableName && (rectMouseArea.containsMouse || removeButton.hovered)
backgroundRadius: StudioTheme.Values.smallRectWidth
anchors.right: parent.right
anchors.rightMargin: 5
anchors.top: parent.top
anchors.topMargin: 5
width: Math.round(StudioTheme.Values.smallRectWidth)
height: Math.round(StudioTheme.Values.smallRectWidth)
buttonIcon: StudioTheme.Constants.closeCross
onClicked: tabBackground.deleteButtonClicked(index)
}
}
states: [
State {
name: "default"
when: !(rectMouseArea.containsMouse || removeButton.hovered ||
(nameMouseArea.containsMouse && !tabBackground.editableName)) &&
!backgroundCard.isSelected
PropertyChanges {
target: backgroundCard
color: StudioTheme.Values.themeControlOutline
border.width: 0
}
},
State {
name: "hovered"
when: (rectMouseArea.containsMouse || removeButton.hovered ||
(nameMouseArea.containsMouse && !tabBackground.editableName)) &&
!backgroundCard.isSelected
PropertyChanges {
target: backgroundCard
color: StudioTheme.Values.themeControlBackgroundPressed
border.width: 1
border.color: StudioTheme.Values.themeInteraction
}
},
State {
name: "selected"
when: backgroundCard.isSelected
PropertyChanges {
target: backgroundCard
color:StudioTheme.Values.themeInteraction
border.width: 1
border.color: StudioTheme.Values.themeControlBackgroundPressed
}
}
]
Item {
id: presetNameBox
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.preferredWidth: backgroundCard.width - 2
Layout.preferredHeight: backgroundCard.height - gradientRect.height - 4
Layout.bottomMargin: 4
ColumnLayout {
spacing: 2
anchors.fill: parent
property bool edit: false
Rectangle {
id: gradientRect
width: 150
height: 150
id: nameBackgroundColor
enabled: tabBackground.editableName
color: "transparent"
radius: 16
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.topMargin: 2
visible: true
anchors.fill: parent
}
gradient: Gradient {
id: showGr
}
ToolTipArea {
id: nameMouseArea
anchors.fill: parent
tooltip: nameText.text
propagateComposedEvents: true
Component {
id: stopComponent
GradientStop {}
}
Component.onCompleted: {
var stopsAmount = stopListSize;
var newStops = [];
for (var i = 0; i < stopsAmount; i++) {
newStops.push( stopComponent.createObject(showGr, { "position": stopsPosList[i], "color": stopsColorList[i] }) );
onClicked: {
if (!tabBackground.editableName) {
backgroundCard.selectPreset(index)
return
}
showGr.stops = newStops;
}
AbstractButton {
id: removeButton
visible: editableName && (rectMouseArea.containsMouse || removeButton.hovered)
backgroundRadius: StudioTheme.Values.smallRectWidth
anchors.right: parent.right
anchors.rightMargin: 5
anchors.top: parent.top
anchors.topMargin: 5
width: Math.round(StudioTheme.Values.smallRectWidth)
height: Math.round(StudioTheme.Values.smallRectWidth)
buttonIcon: StudioTheme.Constants.closeCross
onClicked: tabBackground.deleteButtonClicked(index)
presetNameBox.edit = true
nameInput.forceActiveFocus()
// have to select text like this, otherwise there is an issue with long names
nameInput.cursorPosition = 0
nameInput.cursorPosition = nameInput.length
nameInput.selectAll()
}
}
Item {
id: presetNameBox
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.preferredWidth: backgroundCard.width - 2
Layout.preferredHeight: backgroundCard.height - gradientRect.height - 4
Layout.bottomMargin: 4
property bool edit: false
Rectangle {
id: nameBackgroundColor
enabled: tabBackground.editableName
color: "transparent"
radius: 16
visible: true
anchors.fill: parent
}
ToolTipArea {
id: nameMouseArea
anchors.fill: parent
tooltip: nameText.text
propagateComposedEvents: true
onClicked: {
if (!tabBackground.editableName) {
backgroundCard.selectPreset(index)
return
}
presetNameBox.edit = true
nameInput.forceActiveFocus()
// have to select text like this, otherwise there is an issue with long names
nameInput.cursorPosition = 0
nameInput.cursorPosition = nameInput.length
nameInput.selectAll()
}
}
Text {
id: nameText
text: presetName
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: StudioTheme.Values.themeTextColor
elide: Text.ElideMiddle
maximumLineCount: 1
}
TextInput {
id: nameInput
enabled: tabBackground.editableName
visible: false
text: presetName
anchors.fill: parent
anchors.leftMargin: 5
anchors.rightMargin: 5
horizontalAlignment: TextInput.AlignHCenter
verticalAlignment: TextInput.AlignVCenter
color: StudioTheme.Values.themeTextColor
selectionColor: StudioTheme.Values.themeInteraction
selectByMouse: true
activeFocusOnPress: true
wrapMode: TextInput.NoWrap
clip: true
onEditingFinished: {
nameText.text = text
tabBackground.presetNameChanged(index, text)
presetNameBox.edit = false
}
Keys.onPressed: {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
event.accepted = true
nameInput.editingFinished()
nameInput.focus = false
}
if (event.key === Qt.Key_Escape) {
event.accepted = true
nameInput.text = nameText.text
nameInput.focus = false
}
}
}
states: [
State {
name: "default"
when: tabBackground.editableName && !nameMouseArea.containsMouse && !presetNameBox.edit
PropertyChanges {
target: nameBackgroundColor
color: "transparent"
border.width: 0
}
PropertyChanges { target: nameText; visible: true }
PropertyChanges { target: nameInput; visible: false }
},
State {
name: "hovered"
when: tabBackground.editableName && nameMouseArea.containsMouse && !presetNameBox.edit
PropertyChanges {
target: nameBackgroundColor
color: StudioTheme.Values.themeControlBackgroundPressed
border.width: 0
}
PropertyChanges { target: nameText; visible: true }
PropertyChanges { target: nameInput; visible: false }
},
State {
name: "edit"
when: tabBackground.editableName && presetNameBox.edit
PropertyChanges {
target: nameBackgroundColor
color: StudioTheme.Values.themeControlBackgroundPressed
border.color: StudioTheme.Values.themeInteraction
border.width: 1
}
PropertyChanges { target: nameText; visible: false }
PropertyChanges { target: nameInput; visible: true }
}
]
Text {
id: nameText
text: presetName
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: StudioTheme.Values.themeTextColor
elide: Text.ElideMiddle
maximumLineCount: 1
}
TextInput {
id: nameInput
enabled: tabBackground.editableName
visible: false
text: presetName
anchors.fill: parent
anchors.leftMargin: 5
anchors.rightMargin: 5
horizontalAlignment: TextInput.AlignHCenter
verticalAlignment: TextInput.AlignVCenter
color: StudioTheme.Values.themeTextColor
selectionColor: StudioTheme.Values.themeInteraction
selectByMouse: true
activeFocusOnPress: true
wrapMode: TextInput.NoWrap
clip: true
onEditingFinished: {
nameText.text = text
tabBackground.presetNameChanged(index, text)
presetNameBox.edit = false
}
Keys.onPressed: {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
event.accepted = true
nameInput.editingFinished()
nameInput.focus = false
}
if (event.key === Qt.Key_Escape) {
event.accepted = true
nameInput.text = nameText.text
nameInput.focus = false
}
}
}
states: [
State {
name: "default"
when: tabBackground.editableName && !nameMouseArea.containsMouse && !presetNameBox.edit
PropertyChanges {
target: nameBackgroundColor
color: "transparent"
border.width: 0
}
PropertyChanges { target: nameText; visible: true }
PropertyChanges { target: nameInput; visible: false }
},
State {
name: "hovered"
when: tabBackground.editableName && nameMouseArea.containsMouse && !presetNameBox.edit
PropertyChanges {
target: nameBackgroundColor
color: StudioTheme.Values.themeControlBackgroundPressed
border.width: 0
}
PropertyChanges { target: nameText; visible: true }
PropertyChanges { target: nameInput; visible: false }
},
State {
name: "edit"
when: tabBackground.editableName && presetNameBox.edit
PropertyChanges {
target: nameBackgroundColor
color: StudioTheme.Values.themeControlBackgroundPressed
border.color: StudioTheme.Values.themeInteraction
border.width: 1
}
PropertyChanges { target: nameText; visible: false }
PropertyChanges { target: nameInput; visible: true }
}
]
}
}
}

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,25 +23,29 @@
**
****************************************************************************/
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuickDesignerTheme 1.0
import QtQuick 2.15
import QtQuick.Controls 2.15
import StudioTheme 1.0 as StudioTheme
TextFieldStyle {
selectionColor: Theme.color(Theme.PanelTextColorLight)
selectedTextColor: Theme.color(Theme.PanelTextColorDark)
textColor: Theme.color(Theme.PanelTextColorLight)
placeholderTextColor: Theme.color(Theme.PanelTextColorMid)
ScrollBar {
id: scrollBar
padding.top: 4
padding.bottom: 4
property bool scrollBarVisible: parent.childrenRect.width > parent.width
orientation: Qt.Horizontal
policy: scrollBar.scrollBarVisible ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
x: 0
y: parent.height - height
width: parent.availableWidth
- (parent.bothVisible ? parent.verticalThickness : 0)
padding: 0
background: Rectangle {
implicitWidth: 100
implicitHeight: font.pixelSize + padding.top + padding.bottom
color: Theme.color(Theme.FancyToolButtonSelectedColor)
border.color: Theme.qmlDesignerBackgroundColorDarker()
color: StudioTheme.Values.themeSectionHeadBackground
}
contentItem: Rectangle {
implicitHeight: StudioTheme.Values.scrollBarThickness
color: StudioTheme.Values.themeScrollBarHandle
}
renderType: Text.NativeRendering
}

View File

@@ -23,31 +23,16 @@
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 2.0 as Controls
import QtQuick.Layouts 1.0
import QtQuick 2.15
import HelperWidgets 2.0
import StudioTheme 1.0 as StudioTheme
Item {
id: label
width: parent.width < 300 ? 80 : Math.min(140, parent.width - 220)
height: 16
property alias source: image.source
Label {
id: myLabel
Item {
width: 16
height: 16
Image {
id: image
anchors.fill: parent
}
property alias icon: myLabel.text
}
Layout.preferredWidth: width
Layout.minimumWidth: width
Layout.maximumWidth: width
// Component.onCompleted: {
// label.Layout.preferredWidth = width
// }
text: StudioTheme.Constants.actionIcon
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: StudioTheme.Values.myIconFontSize
}

View File

@@ -23,13 +23,37 @@
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.0 as Controls
import "../../../common/"
import QtQuick 2.15
import QtQuick.Controls 2.15
import StudioTheme 1.0 as StudioTheme
Controls.ScrollView {
style: DesignerScrollViewStyle {
Flickable {
id: flickable
property alias horizontalThickness: horizontalScrollBar.height
property alias verticalThickness: verticalScrollBar.width
property bool bothVisible: verticalScrollBar.scrollBarVisible
&& horizontalScrollBar.scrollBarVisible
contentWidth: areaItem.childrenRect.width
contentHeight: areaItem.childrenRect.height
boundsBehavior: Flickable.StopAtBounds
default property alias content: areaItem.children
Item {
id: areaItem
}
ScrollBar.horizontal: HorizontalScrollBar {
id: horizontalScrollBar
parent: flickable
scrollBarVisible: areaItem.childrenRect.width > flickable.width
}
ScrollBar.vertical: VerticalScrollBar {
id: verticalScrollBar
parent: flickable
scrollBarVisible: areaItem.childrenRect.height > flickable.height
}
frameVisible: false
}

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,9 +23,29 @@
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.0 as Controls
import QtQuick 2.15
import QtQuick.Controls 2.15
import StudioTheme 1.0 as StudioTheme
Controls.Tab {
ScrollBar {
id: scrollBar
property bool scrollBarVisible: parent.childrenRect.height > parent.height
orientation: Qt.Vertical
policy: scrollBar.scrollBarVisible ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
x: parent.width - width
y: 0
height: parent.availableHeight
- (parent.bothVisible ? parent.horizontalThickness : 0)
padding: 0
background: Rectangle {
color: StudioTheme.Values.themeSectionHeadBackground
}
contentItem: Rectangle {
implicitWidth: StudioTheme.Values.scrollBarThickness
color: StudioTheme.Values.themeScrollBarHandle
}
}

View File

@@ -39,11 +39,11 @@ SimpleColorPalette 2.0 SimpleColorPalette.qml
DoubleSpinBox 2.0 DoubleSpinBox.qml
SpinBox 2.0 SpinBox.qml
StandardTextSection 2.0 StandardTextSection.qml
Tab 2.0 Tab.qml
TabView 2.0 TabView.qml
ToolTipArea 2.0 ToolTipArea.qml
UrlChooser 2.0 UrlChooser.qml
PaddingSection 2.0 PaddingSection.qml
RoundedPanel 2.0 RoundedPanel.qml
ExpressionTextField 2.0 ExpressionTextField.qml
MarginSection 2.0 MarginSection.qml
HorizontalScrollBar 2.0 HorizontalScrollBar.qml
VerticalScrollBar 2.0 VerticalScrollBar.qml

View File

@@ -116,7 +116,6 @@ Rectangle {
color: StudioTheme.Values.themeHoverHighlight
border.color: StudioTheme.Values.themeControlOutline
}
},
State {
name: "edit"

View File

@@ -46,8 +46,7 @@ T.CheckBox {
implicitWidth: Math.max(
implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding
+ implicitIndicatorWidth + spacing + actionIndicator.width)
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(
implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding,

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,38 +23,33 @@
**
****************************************************************************/
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuickDesignerTheme 1.0
import QtQuick 2.15
import QtQuick.Templates 2.15 as T
import StudioTheme 1.0 as StudioTheme
ScrollViewStyle {
readonly property color scrollbarColor: Theme.color(Theme.BackgroundColorDark)
readonly property color scrollBarHandleColor: Theme.color(Theme.QmlDesigner_ScrollBarHandleColor)
T.TabBar {
id: myButton
padding {left: 0; top: 0; right: 0; bottom: 0}
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
scrollBarBackground: Rectangle {
height: 10
width: 10
color: scrollbarColor
}
handle: Item {
implicitWidth: 10
implicitHeight: 10
Rectangle {
anchors.fill: parent
color: scrollBarHandleColor
}
spacing: 0
bottomPadding: 4
contentItem: ListView {
model: myButton.contentModel
currentIndex: myButton.currentIndex
spacing: myButton.spacing
orientation: ListView.Horizontal
boundsBehavior: Flickable.StopAtBounds
flickableDirection: Flickable.AutoFlickIfNeeded
snapMode: ListView.SnapToItem
}
decrementControl: Item {}
incrementControl: Item {}
corner: Item {}
//Even if the platform style reports touch support a scrollview should not be flickable.
Component.onCompleted: {
control.flickableItem.interactive = false
background: Rectangle {
color: StudioTheme.Values.themeTabLight
}
transientScrollBars: false
}

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,40 +23,38 @@
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.0 as Controls
import QtQuick.Controls.Styles 1.1
import QtQuickDesignerTheme 1.0
import QtQuick 2.15
import QtQuick.Templates 2.15 as T
import StudioTheme 1.0 as StudioTheme
Controls.TabView {
id: root
T.TabButton {
id: myButton
frameVisible: false
style: TabViewStyle {
frameOverlap: 0
frame: Item { }
tab: Rectangle {
color: styleData.selected ? Theme.qmlDesignerTabLight() : Theme.qmlDesignerTabDark()
implicitWidth: root.width/root.count + 2
implicitHeight: 28
Text {
id: text
font.bold: true
font.pixelSize: StudioTheme.Values.myFontSize
anchors.centerIn: parent
anchors.verticalCenterOffset: -1
text: styleData.title
renderType: Text.NativeRendering
color: styleData.selected ? Theme.qmlDesignerTabDark() : Theme.qmlDesignerTabLight()
}
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
Rectangle {
color:Theme.qmlDesignerTabLight()
width: parent.width
height: 4
anchors.bottom: parent.bottom
}
}
padding: 1
background: Rectangle {
id: buttonBackground
color: myButton.checked ? StudioTheme.Values.themeTabLight : StudioTheme.Values.themeTabDark
border.color: StudioTheme.Values.themeControlOutline
border.width: 0
}
contentItem: T.Label {
id: buttonIcon
color: myButton.checked ? StudioTheme.Values.themeTabDark : StudioTheme.Values.themeTabLight
font.weight: Font.Bold
//font.family: StudioTheme.Constants.font.family
font.pixelSize: StudioTheme.Values.myFontSize
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
anchors.fill: parent
renderType: Text.QtRendering
text: myButton.text
}
}

View File

@@ -28,6 +28,8 @@ SliderPopup 1.0 SliderPopup.qml
SpinBox 1.0 SpinBox.qml
SpinBoxIndicator 1.0 SpinBoxIndicator.qml
SpinBoxInput 1.0 SpinBoxInput.qml
TabBar 1.0 TabBar.qml
TabButton 1.0 TabButton.qml
TextArea 1.0 TextArea.qml
TextField 1.0 TextField.qml
TranslationIndicator 1.0 TranslationIndicator.qml

View File

@@ -94,27 +94,33 @@ QtObject {
readonly property string fontStyleItalic: "\u0057"
readonly property string fontStyleStrikethrough: "\u0058"
readonly property string fontStyleUnderline: "\u0059"
readonly property string mergeCells: "\u005A"
readonly property string redo: "\u005B"
readonly property string splitColumns: "\u005C"
readonly property string splitRows: "\u005D"
readonly property string startNode: "\u005E"
readonly property string testIcon: "\u005F"
readonly property string textAlignBottom: "\u0060"
readonly property string textAlignCenter: "\u0061"
readonly property string textAlignLeft: "\u0062"
readonly property string textAlignMiddle: "\u0063"
readonly property string textAlignRight: "\u0064"
readonly property string textAlignTop: "\u0065"
readonly property string textBulletList: "\u0066"
readonly property string textFullJustification: "\u0067"
readonly property string textNumberedList: "\u0068"
readonly property string tickIcon: "\u0069"
readonly property string triState: "\u006A"
readonly property string undo: "\u006B"
readonly property string upDownIcon: "\u006C"
readonly property string upDownSquare2: "\u006D"
readonly property string wildcard: "\u006E"
readonly property string idAliasOff: "\u005A"
readonly property string idAliasOn: "\u005B"
readonly property string mergeCells: "\u005C"
readonly property string redo: "\u005D"
readonly property string splitColumns: "\u005E"
readonly property string splitRows: "\u005F"
readonly property string startNode: "\u0060"
readonly property string testIcon: "\u0061"
readonly property string textAlignBottom: "\u0062"
readonly property string textAlignCenter: "\u0063"
readonly property string textAlignLeft: "\u0064"
readonly property string textAlignMiddle: "\u0065"
readonly property string textAlignRight: "\u0066"
readonly property string textAlignTop: "\u0067"
readonly property string textBulletList: "\u0068"
readonly property string textFullJustification: "\u0069"
readonly property string textNumberedList: "\u006A"
readonly property string tickIcon: "\u006B"
readonly property string triState: "\u006C"
readonly property string undo: "\u006D"
readonly property string upDownIcon: "\u006E"
readonly property string upDownSquare2: "\u006F"
readonly property string wildcard: "\u0070"
readonly property string zoomAll: "\u0071"
readonly property string zoomIn: "\u0072"
readonly property string zoomOut: "\u0073"
readonly property string zoomSelection: "\u0074"
readonly property font iconFont: Qt.font({
"family": controlIcons.name,

View File

@@ -79,6 +79,8 @@ QtObject {
property real inputHorizontalPadding: Math.round(4 * values.scaleFactor)
property real scrollBarThickness: 10
// Theme Colors
// COLORS NOW COME FROM THE THEME FILES
@@ -117,6 +119,9 @@ QtObject {
property string themeTranslationIndicatorBorder: Theme.color(Theme.DStranlsationIndicatorBorder)
property string themeSectionHeadBackground: Theme.color(Theme.DSsectionHeadBackground)
property string themeTabDark: Theme.color(Theme.QmlDesigner_TabDark)
property string themeTabLight: Theme.color(Theme.QmlDesigner_TabLight)
// Taken out of Constants.js
property string themeChangedStateText: Theme.color(Theme.DSchangedStateText)
}

View File

@@ -23,13 +23,15 @@
**
****************************************************************************/
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import HelperWidgets 2.0
import QtQuick 2.15
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
Rectangle {
id: myRoot
border.width: 1
property bool isBaseState
property bool isCurrentState
@@ -41,6 +43,8 @@ Rectangle {
property string delegateWhenConditionString
readonly property bool isDefaultState: isDefault
signal delegateInteraction
color: baseColor
border.color: Theme.qmlDesignerBorderColor()
@@ -50,38 +54,28 @@ Rectangle {
}
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked: {
focus = true
root.currentStateInternalId = internalNodeId
contextMenu.dismiss() // close potentially open context menu
myRoot.delegateInteraction()
}
}
ToolButton {
StudioControls.AbstractButton {
id: removeStateButton
style: ButtonStyle {
background: Rectangle {
color: control.hovered ? Qt.lighter(baseColor, 1.2) : "transparent"
Image {
source: "image://icons/close"
height: 16
width: 16
}
}
}
buttonIcon: StudioTheme.Constants.closeCross
anchors.right: parent.right
anchors.rightMargin: 2
anchors.rightMargin: 4
anchors.verticalCenter: stateNameField.verticalCenter
height: 16
width: 16
visible: !isBaseState
onClicked: {
myRoot.delegateInteraction()
if (isDefaultState)
statesEditorModel.resetDefaultState()
@@ -89,86 +83,77 @@ Rectangle {
}
}
Image {
id: whenButton
visible: !isBaseState || (isBaseState && modelHasDefaultState)
width: 14
height: 14
x: 4
y: 6
source: {
if (whenMouseArea.containsMouse)
return "image://icons/submenu"
return delegateHasWhenCondition ? "image://icons/expression" : "image://icons/placeholder"
StudioControls.Menu {
id: contextMenu
StudioControls.MenuItem {
enabled: !isBaseState
text: qsTr("Set when Condition")
onTriggered: {
bindingEditor.showWidget()
bindingEditor.text = delegateWhenConditionString
bindingEditor.prepareBindings()
}
}
MouseArea {
id: whenMouseArea
hoverEnabled: true
anchors.fill: parent
onClicked: contextMenu.popup()
StudioControls.MenuItem {
enabled: !isBaseState && delegateHasWhenCondition
text: qsTr("Reset when Condition")
onTriggered: {
statesEditorModel.resetWhenCondition(internalNodeId)
}
}
Menu {
id: contextMenu
MenuItem {
visible: !isBaseState
text: qsTr("Set when Condition")
onTriggered: {
bindingEditor.showWidget()
bindingEditor.text = delegateWhenConditionString
bindingEditor.prepareBindings()
}
StudioControls.MenuItem {
enabled: !isBaseState && !isDefaultState
text: qsTr("Set as Default")
onTriggered: {
statesEditorModel.setStateAsDefault(internalNodeId)
}
}
MenuItem {
visible: !isBaseState && delegateHasWhenCondition
text: qsTr("Reset when Condition")
onTriggered: {
statesEditorModel.resetWhenCondition(internalNodeId)
}
StudioControls.MenuItem {
enabled: (!isBaseState && isDefaultState) || (isBaseState && modelHasDefaultState)
text: qsTr("Reset Default")
onTriggered: {
statesEditorModel.resetDefaultState()
}
}
MenuItem {
visible: !isBaseState && !isDefaultState
text: qsTr("Set as Default")
onTriggered: {
statesEditorModel.setStateAsDefault(internalNodeId)
}
}
onClosed: {
stateNameField.actionIndicator.forceVisible = false
}
MenuItem {
visible: (!isBaseState && isDefaultState) || (isBaseState && modelHasDefaultState)
text: qsTr("Reset Default")
onTriggered: {
statesEditorModel.resetDefaultState()
}
}
onOpened: {
myRoot.delegateInteraction()
}
}
TextField {
StudioControls.TextField {
id: stateNameField
actionIndicator.onClicked: {
stateNameField.actionIndicator.forceVisible = true
contextMenu.popup()
}
onEditChanged: {
if (contextMenu.open && stateNameField.edit)
contextMenu.dismiss()
}
actionIndicator.icon.text: delegateHasWhenCondition
? StudioTheme.Constants.actionIconBinding : StudioTheme.Constants.actionIcon
translationIndicatorVisible: false
y: 4
font.pixelSize: Theme.smallFontPixelSize()
anchors.left: whenButton.right
anchors.left: parent.left
// use the spacing which the image to the delegate rectangle has
anchors.leftMargin: 4
anchors.right: removeStateButton.left
anchors.rightMargin: 4
style: DesignerTextFieldStyle {
background: Rectangle {
implicitWidth: 100
implicitHeight: font.pixelSize + padding.top + padding.bottom
color: ((isBaseState && modelHasDefaultState) ? "transparent"
: Theme.color(Theme.FancyToolButtonSelectedColor))
border.color: ((isBaseState && !modelHasDefaultState) || isDefaultState) ? "#ffd700"
: (isBaseState && modelHasDefaultState) ? "transparent"
: Theme.qmlDesignerBackgroundColorDarker()
}
}
anchors.rightMargin: 2
readOnly: isBaseState
onActiveFocusChanged: {
@@ -188,7 +173,7 @@ Rectangle {
stateNameField.oldValue = stateNameField.text
if (stateNameField.text != delegateStateName)
if (stateNameField.text !== delegateStateName)
statesEditorModel.renameState(internalNodeId, stateNameField.text)
}
}
@@ -220,8 +205,8 @@ Rectangle {
Text {
id: stateDefaultIndicator
anchors.left: whenButton.left
anchors.leftMargin: 0
anchors.left: parent.left
anchors.leftMargin: StudioTheme.Values.height
anchors.right: removeStateButton.left
anchors.rightMargin: 4
anchors.bottom: parent.bottom

View File

@@ -23,32 +23,33 @@
**
****************************************************************************/
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import "../common"
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
FocusScope {
id: root
height: expanded ? 192 : 40
height: (root.expanded ? 192 : 40) + StudioTheme.Values.scrollBarThickness
signal createNewState
signal deleteState(int internalNodeId)
signal duplicateCurrentState
property int stateImageSize: 180
property int delegateWidth: stateImageSize + 44
property int padding: 2
property int delegateHeight: root.height - padding * 2 + 1
property int delegateWidth: root.stateImageSize + 44
property int delegateHeight: root.height - StudioTheme.Values.scrollBarThickness - root.padding * 2 + 1
property int innerSpacing: 0
property int currentStateInternalId : 0
property int currentStateInternalId: 0
property bool expanded: true
Connections {
target: statesEditorModel
onChangedToState: root.currentStateInternalId = n
function onChangedToState(n) { root.currentStateInternalId = n }
}
SystemPalette {
@@ -66,35 +67,41 @@ FocusScope {
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button === Qt.LeftButton)
if (mouse.button === Qt.LeftButton) {
contextMenu.dismiss()
focus = true
else if (mouse.button === Qt.RightButton)
} else if (mouse.button === Qt.RightButton) {
contextMenu.popup()
}
}
Menu {
StudioControls.Menu {
id: contextMenu
MenuItem {
StudioControls.MenuItem {
text: root.expanded ? qsTr("Collapse") : qsTr("Expand")
onTriggered: {
root.expanded = !root.expanded
}
}
}
}
function closeContextMenu() {
if (contextMenu.open)
contextMenu.dismiss()
}
Item {
id: addStateItem
property int buttonLeftSpacing: 8 * (expanded ? 1 : 2)
property int buttonLeftSpacing: 8 * (root.expanded ? 1 : 2)
anchors.right: parent.right
width: delegateHeight / 2 + buttonLeftSpacing
height: delegateHeight
width: root.delegateHeight / 2 + buttonLeftSpacing
height: root.delegateHeight
Button {
AbstractButton {
id: addStateButton
visible: canAddNewStates
@@ -106,56 +113,69 @@ FocusScope {
width: Math.max(parent.height / 2 - 8, 18)
height: width
onClicked: root.createNewState()
onClicked: {
root.closeContextMenu()
root.createNewState()
}
style: ButtonStyle {
background: Rectangle {
property color buttonBaseColor: Qt.darker(Theme.qmlDesignerBackgroundColorDarkAlternate(), 1.1)
color: control.hovered ? Qt.lighter(buttonBaseColor, 1.2) : buttonBaseColor
border.color: Theme.qmlDesignerBorderColor()
border.width: 1
Image {
source: "image://icons/plus"
width: 16
height: 16
anchors.centerIn: parent
smooth: false
}
background: Rectangle {
property color buttonBaseColor: Qt.darker(Theme.qmlDesignerBackgroundColorDarkAlternate(), 1.1)
color: addStateButton.hovered ? Qt.lighter(buttonBaseColor, 1.2) : buttonBaseColor
border.color: Theme.qmlDesignerBorderColor()
border.width: 1
Image {
source: "image://icons/plus"
width: 16
height: 16
anchors.centerIn: parent
smooth: false
}
}
}
}
ScrollView {
ListView {
id: flickable
boundsBehavior: Flickable.StopAtBounds
clip: true
anchors.left: parent.left
anchors.right: addStateItem.left
height: delegateHeight
y: padding
anchors.leftMargin: padding
anchors.rightMargin: padding
height: root.delegateHeight + StudioTheme.Values.scrollBarThickness
y: root.padding
anchors.leftMargin: root.padding
anchors.rightMargin: root.padding
style: DesignerScrollViewStyle {
model: statesEditorModel
orientation: ListView.Horizontal
spacing: root.innerSpacing
delegate: StatesDelegate {
id: statesDelegate
width: root.delegateWidth
height: root.delegateHeight
isBaseState: 0 == internalNodeId
isCurrentState: root.currentStateInternalId == internalNodeId
baseColor: isCurrentState ? Theme.color(Theme.QmlDesigner_HighlightColor) : background.color
delegateStateName: stateName
delegateStateImageSource: stateImageSource
delegateStateImageSize: stateImageSize
delegateHasWhenCondition: hasWhenCondition
delegateWhenConditionString: whenConditionString
onDelegateInteraction: root.closeContextMenu()
}
ListView {
anchors.fill: parent
model: statesEditorModel
orientation: ListView.Horizontal
spacing: innerSpacing
property bool bothVisible: horizontal.scrollBarVisible && vertical.scrollBarVisible
delegate: StatesDelegate {
id: statesDelegate
width: delegateWidth
height: delegateHeight
isBaseState: 0 == internalNodeId
isCurrentState: root.currentStateInternalId == internalNodeId
baseColor: isCurrentState ? Theme.color(Theme.QmlDesigner_HighlightColor) : background.color
delegateStateName: stateName
delegateStateImageSource: stateImageSource
delegateStateImageSize: stateImageSize
delegateHasWhenCondition: hasWhenCondition
delegateWhenConditionString: whenConditionString
}
ScrollBar.horizontal: HorizontalScrollBar {
id: horizontal
parent: flickable
}
ScrollBar.vertical: VerticalScrollBar {
id: vertical
parent: flickable
}
}
}

View File

@@ -201,6 +201,9 @@ namespace ADS
boxLayout->addSpacing(qRound(spacing * 4.0 / 3.0));
boxLayout->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
if (DockManager::testConfigFlag(DockManager::FocusHighlighting))
m_closeButton->setCheckable(true);
m_titleLabel->setVisible(true);
}
@@ -425,7 +428,6 @@ namespace ADS
setFocus(Qt::OtherFocusReason);
updateFocusStyle = true;
}
if (d->m_isActiveTab == active) {
if (updateFocusStyle)
updateStyle();
@@ -527,6 +529,7 @@ namespace ADS
d->m_titleLabel->setToolTip(text);
}
#endif
return Super::event(event);
}
@@ -547,6 +550,13 @@ namespace ADS
void DockWidgetTab::updateStyle()
{
if (DockManager::testConfigFlag(DockManager::FocusHighlighting)) {
if (property("focused").toBool())
d->m_closeButton->setChecked(true);
else
d->m_closeButton->setChecked(false);
}
internal::repolishStyle(this, internal::RepolishDirectChildren);
}

View File

@@ -1557,7 +1557,8 @@ bool Preprocessor::collectActualArguments(PPToken *tk, QVector<QVector<PPToken>
}
if (!tk->is(T_RPAREN)) {
//###TODO: else error message
return false;
//###TODO: error message
}
return true;
}

View File

@@ -1320,6 +1320,40 @@ UiObjectMember: T_DEFAULT UiObjectMemberPropertyNoInitialiser;
} break;
./
UiObjectMember: T_REQUIRED UiObjectMemberListPropertyNoInitialiser;
/.
case $rule_number: {
AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isRequired = true;
node->requiredToken = loc(1);
sym(1).Node = node;
} break;
./
UiObjectMember: T_DEFAULT T_REQUIRED UiObjectMemberListPropertyNoInitialiser;
/.
case $rule_number: {
AST::UiPublicMember *node = sym(3).UiPublicMember;
node->isRequired = true;
node->requiredToken = loc(2);
node->isDefaultMember = true;
node->defaultToken = loc(1);
sym(1).Node = node;
} break;
./
UiObjectMember: T_REQUIRED T_DEFAULT UiObjectMemberListPropertyNoInitialiser;
/.
case $rule_number: {
AST::UiPublicMember *node = sym(3).UiPublicMember;
node->isRequired = true;
node->requiredToken = loc(1);
node->isDefaultMember = true;
node->defaultToken = loc(2);
sym(1).Node = node;
} break;
./
UiObjectMember: T_DEFAULT UiObjectMemberListPropertyNoInitialiser;
/.
case $rule_number: {

File diff suppressed because it is too large Load Diff

View File

@@ -166,15 +166,15 @@ public:
T_XOR_EQ = 84,
T_YIELD = 100,
ACCEPT_STATE = 1098,
RULE_COUNT = 616,
STATE_COUNT = 1099,
ACCEPT_STATE = 1102,
RULE_COUNT = 619,
STATE_COUNT = 1103,
TERMINAL_COUNT = 134,
NON_TERMINAL_COUNT = 238,
GOTO_INDEX_OFFSET = 1099,
GOTO_INFO_OFFSET = 6942,
GOTO_CHECK_OFFSET = 6942
GOTO_INDEX_OFFSET = 1103,
GOTO_INFO_OFFSET = 6857,
GOTO_CHECK_OFFSET = 6857
};
static const char *const spell[];

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,5 @@
#line 185 "qmljs.g"
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
@@ -22,7 +24,6 @@
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#line 223 "qmljs.g"
//
@@ -291,27 +292,27 @@ protected:
#line 1828 "qmljs.g"
#line 1862 "qmljs.g"
#define J_SCRIPT_REGEXPLITERAL_RULE1 161
#define J_SCRIPT_REGEXPLITERAL_RULE1 164
#line 1840 "qmljs.g"
#line 1874 "qmljs.g"
#define J_SCRIPT_REGEXPLITERAL_RULE2 162
#define J_SCRIPT_REGEXPLITERAL_RULE2 165
#line 3389 "qmljs.g"
#line 3423 "qmljs.g"
#define J_SCRIPT_EXPRESSIONSTATEMENTLOOKAHEAD_RULE 460
#define J_SCRIPT_EXPRESSIONSTATEMENTLOOKAHEAD_RULE 463
#line 4041 "qmljs.g"
#line 4075 "qmljs.g"
#define J_SCRIPT_CONCISEBODYLOOKAHEAD_RULE 530
#define J_SCRIPT_CONCISEBODYLOOKAHEAD_RULE 533
#line 4583 "qmljs.g"
#line 4617 "qmljs.g"
#define J_SCRIPT_EXPORTDECLARATIONLOOKAHEAD_RULE 599
#define J_SCRIPT_EXPORTDECLARATIONLOOKAHEAD_RULE 602
#line 4867 "qmljs.g"
#line 4901 "qmljs.g"
QT_QML_END_NAMESPACE

View File

@@ -502,13 +502,13 @@ protected:
return false;
}
bool visit(Block *) override
bool openBlock()
{
++_block;
return true;
}
void endVisit(Block *) override
void closeBlock()
{
auto it = _declaredBlockVariables.begin();
auto end = _declaredBlockVariables.end();
@@ -521,6 +521,26 @@ protected:
--_block;
}
bool visit(Block *) override
{
return openBlock();
}
void endVisit(Block *) override
{
closeBlock();
}
bool visit(Catch *) override
{
return openBlock();
}
void endVisit(Catch *) override
{
closeBlock();
}
void throwRecursionDepthError() override
{
addMessage(ErrHitMaximumRecursion, SourceLocation());

View File

@@ -220,17 +220,13 @@ static PyObject *cdbext_listOfLocals(PyObject *, PyObject *args) // -> [ Value ]
++currentPartialIname; // skip "local" part
ULONG symbolGroupIndex = 0;
ULONG childEndIndex = 0;
for (;symbolGroupIndex < scopeEnd; ++symbolGroupIndex) {
PyValue value(symbolGroupIndex, symbolGroup);
if (childEndIndex <= symbolGroupIndex) { // do not return a child value
if (value.name() == *currentPartialIname) {
PyList_Append(locals, createPythonObject(value));
return locals;
}
++childEndIndex;
if (value.name() == *currentPartialIname) {
PyList_Append(locals, createPythonObject(value));
return locals;
}
childEndIndex += ULONG(value.childCount());
symbolGroupIndex += value.currentNumberOfDescendants();
}
}

View File

@@ -278,13 +278,18 @@ PyValue PyValue::childFromIndex(int index)
int offset = index + 1;
for (ULONG childIndex = m_index + 1; childIndex < m_index + offset; ) {
const ULONG childDescendantCount = currentNumberOfDescendants(childIndex, m_symbolGroup);
const ULONG childDescendantCount = ::currentNumberOfDescendants(childIndex, m_symbolGroup);
childIndex += childDescendantCount + 1;
offset += childDescendantCount;
}
return PyValue(m_index + offset, m_symbolGroup);
}
ULONG PyValue::currentNumberOfDescendants()
{
return ::currentNumberOfDescendants(m_index, m_symbolGroup);
}
PyValue PyValue::createValue(ULONG64 address, const PyType &type)
{
if (debuggingValueEnabled()) {

View File

@@ -55,6 +55,7 @@ public:
PyValue childFromName(const std::string &name);
PyValue childFromField(const PyField &field);
PyValue childFromIndex(int index);
ULONG currentNumberOfDescendants();
static PyValue createValue(ULONG64 address, const PyType &type);
static int tag(const std::string &typeName);

View File

@@ -1250,7 +1250,7 @@ extern "C" HRESULT CALLBACK qmlstack(CIDebugClient *client, PCSTR argsIn)
// the start assuming this is invoked for crashed applications.
std::ostringstream callStr;
const QtInfo &qtInfo = QtInfo::get(SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()));
callStr << qtInfo.prependQtModule("qt_v4StackTrace(", QtInfo::Qml) << std::showbase << std::hex
callStr << qtInfo.prependQtModule("qt_v4StackTraceForEngine(", QtInfo::Qml) << std::showbase << std::hex
<< jsExecutionEngine << std::dec << std::noshowbase << ')';
std::wstring wOutput;
if (!ExtensionContext::instance().call(callStr.str(), ExtensionContext::CallWithExceptionsHandled, &wOutput, &errorMessage))

View File

@@ -33,7 +33,6 @@
#include <QDataStream>
#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QOperatingSystemVersion>
#include <QRegularExpression>
#include <QTimer>
@@ -202,46 +201,22 @@ bool FileUtils::removeRecursively(const FilePath &filePath, QString *error)
Returns whether the operation succeeded.
*/
bool FileUtils::copyRecursively(const FilePath &srcFilePath, const FilePath &tgtFilePath,
QString *error, const std::function<bool (QFileInfo, QFileInfo, QString *)> &copyHelper)
bool FileUtils::copyRecursively(const FilePath &srcFilePath, const FilePath &tgtFilePath, QString *error)
{
QFileInfo srcFileInfo = srcFilePath.toFileInfo();
if (srcFileInfo.isDir()) {
if (!tgtFilePath.exists()) {
QDir targetDir(tgtFilePath.toString());
targetDir.cdUp();
if (!targetDir.mkdir(tgtFilePath.fileName())) {
return copyRecursively(
srcFilePath, tgtFilePath, error, [](const QFileInfo &src, const QFileInfo &dest, QString *error) {
if (!QFile::copy(src.filePath(), dest.filePath())) {
if (error) {
*error = QCoreApplication::translate("Utils::FileUtils", "Failed to create directory \"%1\".")
.arg(tgtFilePath.toUserOutput());
*error = QCoreApplication::translate("Utils::FileUtils",
"Could not copy file \"%1\" to \"%2\".")
.arg(FilePath::fromFileInfo(src).toUserOutput(),
FilePath::fromFileInfo(dest).toUserOutput());
}
return false;
}
}
QDir sourceDir(srcFilePath.toString());
const QStringList fileNames = sourceDir.entryList(
QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
for (const QString &fileName : fileNames) {
const FilePath newSrcFilePath = srcFilePath / fileName;
const FilePath newTgtFilePath = tgtFilePath / fileName;
if (!copyRecursively(newSrcFilePath, newTgtFilePath, error, copyHelper))
return false;
}
} else {
if (copyHelper) {
if (!copyHelper(srcFileInfo, tgtFilePath.toFileInfo(), error))
return false;
} else {
if (!QFile::copy(srcFilePath.toString(), tgtFilePath.toString())) {
if (error) {
*error = QCoreApplication::translate("Utils::FileUtils", "Could not copy file \"%1\" to \"%2\".")
.arg(srcFilePath.toUserOutput(), tgtFilePath.toUserOutput());
}
return false;
}
}
}
return true;
return true;
});
}
/*!

View File

@@ -30,10 +30,12 @@
#include "hostosinfo.h"
#include <QCoreApplication>
#include <QXmlStreamWriter> // Mac.
#include <QDir>
#include <QFileInfo>
#include <QMetaType>
#include <QStringList>
#include <QUrl>
#include <QXmlStreamWriter> // Mac.
#include <functional>
#include <memory>
@@ -179,9 +181,14 @@ public:
#endif // QT_GUI_LIB
static bool removeRecursively(const FilePath &filePath, QString *error = nullptr);
static bool copyRecursively(
const FilePath &srcFilePath, const FilePath &tgtFilePath, QString *error = nullptr,
const std::function<bool (QFileInfo, QFileInfo, QString *)> &copyHelper = nullptr);
static bool copyRecursively(const FilePath &srcFilePath,
const FilePath &tgtFilePath,
QString *error = nullptr);
template<typename T>
static bool copyRecursively(const FilePath &srcFilePath,
const FilePath &tgtFilePath,
QString *error,
T &&copyHelper);
static FilePath resolveSymlinks(const FilePath &path);
static QString fileSystemFriendlyName(const QString &name);
static int indexOfQmakeUnfriendly(const QString &name, int startpos = 0);
@@ -195,6 +202,42 @@ public:
static QByteArray fileId(const FilePath &fileName);
};
template<typename T>
bool FileUtils::copyRecursively(const FilePath &srcFilePath,
const FilePath &tgtFilePath,
QString *error,
T &&copyHelper)
{
const QFileInfo srcFileInfo = srcFilePath.toFileInfo();
if (srcFileInfo.isDir()) {
if (!tgtFilePath.exists()) {
QDir targetDir(tgtFilePath.toString());
targetDir.cdUp();
if (!targetDir.mkdir(tgtFilePath.fileName())) {
if (error) {
*error = QCoreApplication::translate("Utils::FileUtils",
"Failed to create directory \"%1\".")
.arg(tgtFilePath.toUserOutput());
}
return false;
}
}
const QDir sourceDir(srcFilePath.toString());
const QStringList fileNames = sourceDir.entryList(
QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
for (const QString &fileName : fileNames) {
const FilePath newSrcFilePath = srcFilePath / fileName;
const FilePath newTgtFilePath = tgtFilePath / fileName;
if (!copyRecursively(newSrcFilePath, newTgtFilePath, error, copyHelper))
return false;
}
} else {
if (!copyHelper(srcFileInfo, tgtFilePath.toFileInfo(), error))
return false;
}
return true;
}
// for actually finding out if e.g. directories are writable on Windows
#ifdef Q_OS_WIN

View File

@@ -154,7 +154,7 @@ NameValueItems NameValueDictionary::diff(const NameValueDictionary &other, bool
const QString &newValue = otherIt.value().first;
const bool oldEnabled = thisIt.value().second;
const bool newEnabled = otherIt.value().second;
if (oldValue != newValue) {
if (oldValue != newValue || oldEnabled != newEnabled) {
if (checkAppendPrepend && newValue.startsWith(oldValue)
&& oldEnabled == newEnabled) {
QString appended = newValue.right(newValue.size() - oldValue.size());

View File

@@ -140,12 +140,15 @@ FilePath OutputLineParser::absoluteFilePath(const FilePath &filePath)
return filePath;
FilePaths candidates;
for (const FilePath &dir : searchDirectories()) {
const FilePath candidate = dir.pathAppended(filePath.toString());
if (candidate.exists() || d->skipFileExistsCheck)
candidates << candidate;
FilePath candidate = dir.pathAppended(filePath.toString());
if (candidate.exists() || d->skipFileExistsCheck) {
candidate = FilePath::fromString(QDir::cleanPath(candidate.toString()));
if (!candidates.contains(candidate))
candidates << candidate;
}
}
if (candidates.count() == 1)
return FilePath::fromString(QDir::cleanPath(candidates.first().toString()));
return candidates.first();
QString fp = filePath.toString();
while (fp.startsWith("../"))
@@ -282,12 +285,24 @@ void OutputFormatter::overridePostPrintAction(const PostPrintAction &postPrintAc
void OutputFormatter::doAppendMessage(const QString &text, OutputFormat format)
{
const QTextCharFormat charFmt = charFormat(format);
const QList<FormattedText> formattedText = parseAnsi(text, charFmt);
QTextCharFormat charFmt = charFormat(format);
QList<FormattedText> formattedText = parseAnsi(text, charFmt);
const QString cleanLine = std::accumulate(formattedText.begin(), formattedText.end(), QString(),
[](const FormattedText &t1, const FormattedText &t2) { return t1.text + t2.text; });
QList<OutputLineParser *> involvedParsers;
const OutputLineParser::Result res = handleMessage(cleanLine, format, involvedParsers);
// If the line was recognized by a parser and a redirection was detected for that parser,
// then our formatting should reflect that redirection as well, i.e. print in red
// even if the nominal format is stdout.
if (!involvedParsers.isEmpty()) {
const OutputFormat formatForParser = outputTypeForParser(involvedParsers.last(), format);
if (formatForParser != format && cleanLine == text && formattedText.length() == 1) {
charFmt = charFormat(formatForParser);
formattedText.first().format = charFmt;
}
}
if (res.newContent) {
append(res.newContent.value(), charFmt);
return;

View File

@@ -546,6 +546,41 @@ QLinearGradient StyleHelper::statusBarGradient(const QRect &statusBarRect)
return grad;
}
QIcon StyleHelper::getIconFromIconFont(const QString &fontName, const QList<IconFontHelper> &parameters)
{
QFontDatabase a;
QTC_ASSERT(a.hasFamily(fontName), {});
if (!a.hasFamily(fontName))
return {};
QIcon icon;
for (const IconFontHelper &p : parameters) {
const int maxDpr = qRound(qApp->devicePixelRatio());
for (int dpr = 1; dpr <= maxDpr; dpr++) {
QPixmap pixmap(p.size() * dpr);
pixmap.setDevicePixelRatio(dpr);
pixmap.fill(Qt::transparent);
QFont font(fontName);
font.setPixelSize(p.size().height());
QPainter painter(&pixmap);
painter.save();
painter.setPen(p.color());
painter.setFont(font);
painter.drawText(QRectF(QPoint(0, 0), p.size()), p.iconSymbol());
painter.restore();
icon.addPixmap(pixmap, p.mode(), p.state());
}
}
return icon;
}
QIcon StyleHelper::getIconFromIconFont(const QString &fontName, const QString &iconSymbol, int fontSize, int iconSize, QColor color)
{
QFontDatabase a;

View File

@@ -93,6 +93,36 @@ public:
static void tintImage(QImage &img, const QColor &tintColor);
static QLinearGradient statusBarGradient(const QRect &statusBarRect);
class IconFontHelper
{
public:
IconFontHelper(const QString &iconSymbol,
const QColor &color,
const QSize &size,
QIcon::Mode mode = QIcon::Normal,
QIcon::State state = QIcon::Off)
: m_iconSymbol(iconSymbol)
, m_color(color)
, m_size(size)
, m_mode(mode)
, m_state(state)
{}
QString iconSymbol() const { return m_iconSymbol; }
QColor color() const { return m_color; }
QSize size() const { return m_size; }
QIcon::Mode mode() const { return m_mode; }
QIcon::State state() const { return m_state; }
private:
QString m_iconSymbol;
QColor m_color;
QSize m_size;
QIcon::Mode m_mode;
QIcon::State m_state;
};
static QIcon getIconFromIconFont(const QString &fontName, const QList<IconFontHelper> &parameters);
static QIcon getIconFromIconFont(const QString &fontName, const QString &iconSymbol, int fontSize, int iconSize, QColor color);
static QIcon getIconFromIconFont(const QString &fontName, const QString &iconSymbol, int fontSize, int iconSize);

View File

@@ -25,6 +25,7 @@
#include "androidavdmanager.h"
#include <coreplugin/icore.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
@@ -424,8 +425,8 @@ AndroidDeviceInfoList AvdManagerOutputParser::parseAvdList(const QString &output
}
} else if (parseAvd(avdInfo, &avd)) {
// armeabi-v7a devices can also run armeabi code
if (avd.cpuAbi.contains("armeabi-v7a"))
avd.cpuAbi << "armeabi";
if (avd.cpuAbi.contains(ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A))
avd.cpuAbi << ProjectExplorer::Constants::ANDROID_ABI_ARMEABI;
avd.state = AndroidDeviceInfo::OkState;
avd.type = AndroidDeviceInfo::Emulator;
avdList << avd;

View File

@@ -50,6 +50,7 @@
#include <QComboBox>
#include <QGroupBox>
#include <QFileDialog>
#include <QFormLayout>
#include <QLabel>
#include <QListView>
#include <QPushButton>
@@ -74,7 +75,6 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
vbox->addWidget(createSignPackageGroup());
vbox->addWidget(createApplicationGroup());
vbox->addWidget(createAdvancedGroup());
vbox->addWidget(createCreateTemplatesGroup());
vbox->addWidget(createAdditionalLibrariesGroup());
connect(m_step->buildConfiguration(), &BuildConfiguration::buildTypeChanged,
@@ -96,7 +96,7 @@ QWidget *AndroidBuildApkWidget::createApplicationGroup()
auto group = new QGroupBox(tr("Application"), this);
auto targetSDKComboBox = new QComboBox(group);
auto targetSDKComboBox = new QComboBox();
targetSDKComboBox->addItems(targets);
targetSDKComboBox->setCurrentIndex(targets.indexOf(m_step->buildTargetSdk()));
@@ -107,9 +107,18 @@ QWidget *AndroidBuildApkWidget::createApplicationGroup()
AndroidManager::updateGradleProperties(step()->target(), QString()); // FIXME: Use real key.
});
auto hbox = new QHBoxLayout(group);
hbox->addWidget(new QLabel(tr("Android build SDK:"), group));
hbox->addWidget(targetSDKComboBox);
auto formLayout = new QFormLayout(group);
formLayout->addRow(tr("Android build SDK:"), targetSDKComboBox);
auto createAndroidTemplatesButton = new QPushButton(tr("Create Templates"));
createAndroidTemplatesButton->setToolTip(
tr("Create an Android package for Custom Java code, assets, and Gradle configurations."));
connect(createAndroidTemplatesButton, &QAbstractButton::clicked, this, [this] {
CreateAndroidManifestWizard wizard(m_step->buildSystem());
wizard.exec();
});
formLayout->addRow(tr("Android customization:"), createAndroidTemplatesButton);
return group;
}
@@ -120,7 +129,7 @@ QWidget *AndroidBuildApkWidget::createSignPackageGroup()
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
auto group = new QGroupBox(tr("Sign package"), this);
auto group = new QGroupBox(tr("Application Signature"), this);
auto keystoreLocationLabel = new QLabel(tr("Keystore:"), group);
keystoreLocationLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
@@ -242,24 +251,6 @@ QWidget *AndroidBuildApkWidget::createAdvancedGroup()
return group;
}
QWidget *AndroidBuildApkWidget::createCreateTemplatesGroup()
{
auto createTemplatesGroupBox = new QGroupBox(tr("Android"));
createTemplatesGroupBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
auto createAndroidTemplatesButton = new QPushButton(tr("Create Templates"));
connect(createAndroidTemplatesButton, &QAbstractButton::clicked, this, [this] {
CreateAndroidManifestWizard wizard(m_step->buildSystem());
wizard.exec();
});
auto horizontalLayout = new QHBoxLayout(createTemplatesGroupBox);
horizontalLayout->addWidget(createAndroidTemplatesButton);
horizontalLayout->addStretch(1);
return createTemplatesGroupBox;
}
QWidget *AndroidBuildApkWidget::createAdditionalLibrariesGroup()
{
auto group = new QGroupBox(tr("Additional Libraries"));

View File

@@ -63,7 +63,6 @@ private:
QWidget *createApplicationGroup();
QWidget *createSignPackageGroup();
QWidget *createAdvancedGroup();
QWidget *createCreateTemplatesGroup();
QWidget *createAdditionalLibrariesGroup();
private:

View File

@@ -39,6 +39,7 @@
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/toolchainmanager.h>
@@ -1284,7 +1285,12 @@ void AndroidConfigurations::removeUnusedDebuggers()
static bool containsAllAbis(const QStringList &abis)
{
QStringList supportedAbis{"armeabi-v7a", "arm64-v8a", "x86", "x86_64"};
QStringList supportedAbis{
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A,
ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A,
ProjectExplorer::Constants::ANDROID_ABI_X86,
ProjectExplorer::Constants::ANDROID_ABI_X86_64,
};
for (const QString &abi : abis)
if (supportedAbis.contains(abi))
supportedAbis.removeOne(abi);
@@ -1524,6 +1530,21 @@ AndroidConfigurations::AndroidConfigurations()
AndroidConfigurations::~AndroidConfigurations() = default;
static Utils::FilePath androidStudioPath()
{
if (Utils::HostOsInfo::isWindowsHost()) {
const QLatin1String registryKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio");
const QLatin1String valueName("Path");
#if defined(Q_OS_WIN)
const QSettings settings64(registryKey, QSettings::Registry64Format);
const QSettings settings32(registryKey, QSettings::Registry32Format);
return Utils::FilePath::fromUserInput(
settings64.value(valueName, settings32.value(valueName).toString()).toString());
#endif
}
return {}; // TODO non-Windows
}
FilePath AndroidConfig::getJdkPath()
{
FilePath jdkHome;
@@ -1563,6 +1584,16 @@ FilePath AndroidConfig::getJdkPath()
break;
}
}
// Nothing found yet? Let's try finding Android Studio's jdk
if (jdkHome.isEmpty()) {
const Utils::FilePath androidStudioSdkPath = androidStudioPath();
if (!androidStudioSdkPath.isEmpty()) {
const Utils::FilePath androidStudioSdkJrePath = androidStudioSdkPath / "jre";
if (androidStudioSdkJrePath.exists())
jdkHome = androidStudioSdkJrePath;
}
}
} else {
QStringList args;
if (HostOsInfo::isMacHost())
@@ -1581,7 +1612,8 @@ FilePath AndroidConfig::getJdkPath()
jdkHome = FilePath::fromUtf8(jdkPath);
} else {
jdkPath.replace("bin/java", ""); // For OpenJDK 11
jdkPath.replace("jre/bin/java", "");
jdkPath.replace("jre", "");
jdkPath.replace("//", "/");
jdkHome = FilePath::fromUtf8(jdkPath);
}
}

View File

@@ -64,6 +64,7 @@ const char JAVA_MIMETYPE[] = "text/x-java";
const char ANDROID_ARCHITECTURE[] = "Android.Architecture";
const char ANDROID_PACKAGE_SOURCE_DIR[] = "AndroidPackageSourceDir";
const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs";
const char ANDROID_ABIS[] = "ANDROID_ABIS";
const char ANDROID_PACKAGENAME[] = "Android.PackageName";
const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[]

View File

@@ -38,6 +38,7 @@
#include <coreplugin/messagemanager.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/project.h>
@@ -145,7 +146,7 @@ AndroidDeployQtStep::AndroidDeployQtStep(BuildStepList *parent, Utils::Id id)
m_uninstallPreviousPackage = qt && qt->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0);
//: AndroidDeployQtStep default display name
setDefaultDisplayName(tr("Deploy to Android device"));
setDefaultDisplayName(tr("Deploy to Android Device"));
connect(this, &AndroidDeployQtStep::askForUninstall,
this, &AndroidDeployQtStep::slotAskForUninstall,
@@ -207,6 +208,18 @@ bool AndroidDeployQtStep::init()
if (!info.isValid()) // aborted
return false;
const QString buildKey = target()->activeBuildKey();
auto selectedAbis = buildSystem()->extraData(buildKey, Constants::ANDROID_ABIS).toStringList();
if (!selectedAbis.contains(info.cpuAbi.first())) {
Core::MessageManager::write(
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 > "
"Build Steps > qmake > ABIs.")
.arg(info.cpuAbi.first()),
Core::MessageManager::WithFocus);
}
m_avdName = info.avdname;
m_serialNumber = info.serialNumber;
qCDebug(deployStepLog) << "Selected device info:" << info;
@@ -484,7 +497,8 @@ void AndroidDeployQtStep::gatherFilesToPull()
QString linkerName("linker");
QString libDirName("lib");
auto preferreABI = AndroidManager::apkDevicePreferredAbi(target());
if (preferreABI == "arm64-v8a" || preferreABI == "x86_64") {
if (preferreABI == ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A
|| preferreABI == ProjectExplorer::Constants::ANDROID_ABI_X86_64) {
m_filesToPull["/system/bin/app_process64"] = buildDir + "app_process";
libDirName = "lib64";
linkerName = "linker64";

View File

@@ -44,6 +44,7 @@
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
@@ -262,11 +263,11 @@ QStringList AndroidManager::applicationAbis(const Target *target)
QString AndroidManager::archTriplet(const QString &abi)
{
if (abi == "x86") {
if (abi == ProjectExplorer::Constants::ANDROID_ABI_X86) {
return {"i686-linux-android"};
} else if (abi == "x86_64") {
} else if (abi == ProjectExplorer::Constants::ANDROID_ABI_X86_64) {
return {"x86_64-linux-android"};
} else if (abi == "arm64-v8a") {
} else if (abi == ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A) {
return {"aarch64-linux-android"};
}
return {"arm-linux-androideabi"};
@@ -361,25 +362,25 @@ QString AndroidManager::devicePreferredAbi(const QStringList &deviceAbis, const
Abi AndroidManager::androidAbi2Abi(const QString &androidAbi)
{
if (androidAbi == "arm64-v8a") {
if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A) {
return Abi{Abi::Architecture::ArmArchitecture,
Abi::OS::LinuxOS,
Abi::OSFlavor::AndroidLinuxFlavor,
Abi::BinaryFormat::ElfFormat,
64, androidAbi};
} else if (androidAbi == "armeabi-v7a") {
} else if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A) {
return Abi{Abi::Architecture::ArmArchitecture,
Abi::OS::LinuxOS,
Abi::OSFlavor::AndroidLinuxFlavor,
Abi::BinaryFormat::ElfFormat,
32, androidAbi};
} else if (androidAbi == "x86_64") {
} else if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_X86_64) {
return Abi{Abi::Architecture::X86Architecture,
Abi::OS::LinuxOS,
Abi::OSFlavor::AndroidLinuxFlavor,
Abi::BinaryFormat::ElfFormat,
64, androidAbi};
} else if (androidAbi == "x86") {
} else if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_X86) {
return Abi{Abi::Architecture::X86Architecture,
Abi::OS::LinuxOS,
Abi::OSFlavor::AndroidLinuxFlavor,

View File

@@ -29,6 +29,8 @@
#include <QVector>
#include <QWidget>
#include <QCoreApplication>
namespace TextEditor {
class TextEditorWidget;
}
@@ -40,6 +42,8 @@ class AndroidManifestEditorIconWidget;
class AndroidManifestEditorIconContainerWidget : public QWidget
{
Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidManifestEditorIconContainerWidget)
public:
explicit AndroidManifestEditorIconContainerWidget(QWidget *parent,
TextEditor::TextEditorWidget *textEditorWidget);

View File

@@ -64,7 +64,6 @@
#include <QFileDialog>
#include <QFileInfo>
#include <QFormLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QImage>
#include <QLabel>
@@ -134,338 +133,351 @@ AndroidManifestEditorWidget::AndroidManifestEditorWidget()
this, &AndroidManifestEditorWidget::updateAfterFileLoad);
}
QGroupBox *AndroidManifestEditorWidget::createPermissionsGroupBox(QWidget *parent)
{
auto permissionsGroupBox = new QGroupBox(parent);
permissionsGroupBox->setTitle(tr("Permissions"));
auto layout = new QGridLayout(permissionsGroupBox);
m_defaultPermissonsCheckBox = new QCheckBox(this);
m_defaultPermissonsCheckBox->setText(tr("Include default permissions for Qt modules."));
layout->addWidget(m_defaultPermissonsCheckBox, 0, 0);
m_defaultFeaturesCheckBox = new QCheckBox(this);
m_defaultFeaturesCheckBox->setText(tr("Include default features for Qt modules."));
layout->addWidget(m_defaultFeaturesCheckBox, 1, 0);
m_permissionsComboBox = new QComboBox(permissionsGroupBox);
m_permissionsComboBox->insertItems(0, QStringList()
<< QLatin1String("android.permission.ACCESS_CHECKIN_PROPERTIES")
<< QLatin1String("android.permission.ACCESS_COARSE_LOCATION")
<< QLatin1String("android.permission.ACCESS_FINE_LOCATION")
<< QLatin1String("android.permission.ACCESS_LOCATION_EXTRA_COMMANDS")
<< QLatin1String("android.permission.ACCESS_MOCK_LOCATION")
<< QLatin1String("android.permission.ACCESS_NETWORK_STATE")
<< QLatin1String("android.permission.ACCESS_SURFACE_FLINGER")
<< QLatin1String("android.permission.ACCESS_WIFI_STATE")
<< QLatin1String("android.permission.ACCOUNT_MANAGER")
<< QLatin1String("com.android.voicemail.permission.ADD_VOICEMAIL")
<< QLatin1String("android.permission.AUTHENTICATE_ACCOUNTS")
<< QLatin1String("android.permission.BATTERY_STATS")
<< QLatin1String("android.permission.BIND_ACCESSIBILITY_SERVICE")
<< QLatin1String("android.permission.BIND_APPWIDGET")
<< QLatin1String("android.permission.BIND_DEVICE_ADMIN")
<< QLatin1String("android.permission.BIND_INPUT_METHOD")
<< QLatin1String("android.permission.BIND_REMOTEVIEWS")
<< QLatin1String("android.permission.BIND_TEXT_SERVICE")
<< QLatin1String("android.permission.BIND_VPN_SERVICE")
<< QLatin1String("android.permission.BIND_WALLPAPER")
<< QLatin1String("android.permission.BLUETOOTH")
<< QLatin1String("android.permission.BLUETOOTH_ADMIN")
<< QLatin1String("android.permission.BRICK")
<< QLatin1String("android.permission.BROADCAST_PACKAGE_REMOVED")
<< QLatin1String("android.permission.BROADCAST_SMS")
<< QLatin1String("android.permission.BROADCAST_STICKY")
<< QLatin1String("android.permission.BROADCAST_WAP_PUSH")
<< QLatin1String("android.permission.CALL_PHONE")
<< QLatin1String("android.permission.CALL_PRIVILEGED")
<< QLatin1String("android.permission.CAMERA")
<< QLatin1String("android.permission.CHANGE_COMPONENT_ENABLED_STATE")
<< QLatin1String("android.permission.CHANGE_CONFIGURATION")
<< QLatin1String("android.permission.CHANGE_NETWORK_STATE")
<< QLatin1String("android.permission.CHANGE_WIFI_MULTICAST_STATE")
<< QLatin1String("android.permission.CHANGE_WIFI_STATE")
<< QLatin1String("android.permission.CLEAR_APP_CACHE")
<< QLatin1String("android.permission.CLEAR_APP_USER_DATA")
<< QLatin1String("android.permission.CONTROL_LOCATION_UPDATES")
<< QLatin1String("android.permission.DELETE_CACHE_FILES")
<< QLatin1String("android.permission.DELETE_PACKAGES")
<< QLatin1String("android.permission.DEVICE_POWER")
<< QLatin1String("android.permission.DIAGNOSTIC")
<< QLatin1String("android.permission.DISABLE_KEYGUARD")
<< QLatin1String("android.permission.DUMP")
<< QLatin1String("android.permission.EXPAND_STATUS_BAR")
<< QLatin1String("android.permission.FACTORY_TEST")
<< QLatin1String("android.permission.FLASHLIGHT")
<< QLatin1String("android.permission.FORCE_BACK")
<< QLatin1String("android.permission.GET_ACCOUNTS")
<< QLatin1String("android.permission.GET_PACKAGE_SIZE")
<< QLatin1String("android.permission.GET_TASKS")
<< QLatin1String("android.permission.GLOBAL_SEARCH")
<< QLatin1String("android.permission.HARDWARE_TEST")
<< QLatin1String("android.permission.INJECT_EVENTS")
<< QLatin1String("android.permission.INSTALL_LOCATION_PROVIDER")
<< QLatin1String("android.permission.INSTALL_PACKAGES")
<< QLatin1String("android.permission.INTERNAL_SYSTEM_WINDOW")
<< QLatin1String("android.permission.INTERNET")
<< QLatin1String("android.permission.KILL_BACKGROUND_PROCESSES")
<< QLatin1String("android.permission.MANAGE_ACCOUNTS")
<< QLatin1String("android.permission.MANAGE_APP_TOKENS")
<< QLatin1String("android.permission.MASTER_CLEAR")
<< QLatin1String("android.permission.MODIFY_AUDIO_SETTINGS")
<< QLatin1String("android.permission.MODIFY_PHONE_STATE")
<< QLatin1String("android.permission.MOUNT_FORMAT_FILESYSTEMS")
<< QLatin1String("android.permission.MOUNT_UNMOUNT_FILESYSTEMS")
<< QLatin1String("android.permission.NFC")
<< QLatin1String("android.permission.PERSISTENT_ACTIVITY")
<< QLatin1String("android.permission.PROCESS_OUTGOING_CALLS")
<< QLatin1String("android.permission.READ_CALENDAR")
<< QLatin1String("android.permission.READ_CALL_LOG")
<< QLatin1String("android.permission.READ_CONTACTS")
<< QLatin1String("android.permission.READ_EXTERNAL_STORAGE")
<< QLatin1String("android.permission.READ_FRAME_BUFFER")
<< QLatin1String("com.android.browser.permission.READ_HISTORY_BOOKMARKS")
<< QLatin1String("android.permission.READ_INPUT_STATE")
<< QLatin1String("android.permission.READ_LOGS")
<< QLatin1String("android.permission.READ_PHONE_STATE")
<< QLatin1String("android.permission.READ_PROFILE")
<< QLatin1String("android.permission.READ_SMS")
<< QLatin1String("android.permission.READ_SOCIAL_STREAM")
<< QLatin1String("android.permission.READ_SYNC_SETTINGS")
<< QLatin1String("android.permission.READ_SYNC_STATS")
<< QLatin1String("android.permission.READ_USER_DICTIONARY")
<< QLatin1String("android.permission.REBOOT")
<< QLatin1String("android.permission.RECEIVE_BOOT_COMPLETED")
<< QLatin1String("android.permission.RECEIVE_MMS")
<< QLatin1String("android.permission.RECEIVE_SMS")
<< QLatin1String("android.permission.RECEIVE_WAP_PUSH")
<< QLatin1String("android.permission.RECORD_AUDIO")
<< QLatin1String("android.permission.REORDER_TASKS")
<< QLatin1String("android.permission.RESTART_PACKAGES")
<< QLatin1String("android.permission.SEND_SMS")
<< QLatin1String("android.permission.SET_ACTIVITY_WATCHER")
<< QLatin1String("com.android.alarm.permission.SET_ALARM")
<< QLatin1String("android.permission.SET_ALWAYS_FINISH")
<< QLatin1String("android.permission.SET_ANIMATION_SCALE")
<< QLatin1String("android.permission.SET_DEBUG_APP")
<< QLatin1String("android.permission.SET_ORIENTATION")
<< QLatin1String("android.permission.SET_POINTER_SPEED")
<< QLatin1String("android.permission.SET_PREFERRED_APPLICATIONS")
<< QLatin1String("android.permission.SET_PROCESS_LIMIT")
<< QLatin1String("android.permission.SET_TIME")
<< QLatin1String("android.permission.SET_TIME_ZONE")
<< QLatin1String("android.permission.SET_WALLPAPER")
<< QLatin1String("android.permission.SET_WALLPAPER_HINTS")
<< QLatin1String("android.permission.SIGNAL_PERSISTENT_PROCESSES")
<< QLatin1String("android.permission.STATUS_BAR")
<< QLatin1String("android.permission.SUBSCRIBED_FEEDS_READ")
<< QLatin1String("android.permission.SUBSCRIBED_FEEDS_WRITE")
<< QLatin1String("android.permission.SYSTEM_ALERT_WINDOW")
<< QLatin1String("android.permission.UPDATE_DEVICE_STATS")
<< QLatin1String("android.permission.USE_CREDENTIALS")
<< QLatin1String("android.permission.USE_SIP")
<< QLatin1String("android.permission.VIBRATE")
<< QLatin1String("android.permission.WAKE_LOCK")
<< QLatin1String("android.permission.WRITE_APN_SETTINGS")
<< QLatin1String("android.permission.WRITE_CALENDAR")
<< QLatin1String("android.permission.WRITE_CALL_LOG")
<< QLatin1String("android.permission.WRITE_CONTACTS")
<< QLatin1String("android.permission.WRITE_EXTERNAL_STORAGE")
<< QLatin1String("android.permission.WRITE_GSERVICES")
<< QLatin1String("com.android.browser.permission.WRITE_HISTORY_BOOKMARKS")
<< QLatin1String("android.permission.WRITE_PROFILE")
<< QLatin1String("android.permission.WRITE_SECURE_SETTINGS")
<< QLatin1String("android.permission.WRITE_SETTINGS")
<< QLatin1String("android.permission.WRITE_SMS")
<< QLatin1String("android.permission.WRITE_SOCIAL_STREAM")
<< QLatin1String("android.permission.WRITE_SYNC_SETTINGS")
<< QLatin1String("android.permission.WRITE_USER_DICTIONARY")
);
m_permissionsComboBox->setEditable(true);
layout->addWidget(m_permissionsComboBox, 2, 0);
m_addPermissionButton = new QPushButton(permissionsGroupBox);
m_addPermissionButton->setText(tr("Add"));
layout->addWidget(m_addPermissionButton, 2, 1);
m_permissionsModel = new PermissionsModel(this);
m_permissionsListView = new QListView(permissionsGroupBox);
m_permissionsListView->setModel(m_permissionsModel);
layout->addWidget(m_permissionsListView, 3, 0, 3, 1);
m_removePermissionButton = new QPushButton(permissionsGroupBox);
m_removePermissionButton->setText(tr("Remove"));
layout->addWidget(m_removePermissionButton, 3, 1);
permissionsGroupBox->setLayout(layout);
connect(m_defaultPermissonsCheckBox, &QCheckBox::stateChanged,
this, &AndroidManifestEditorWidget::defaultPermissionOrFeatureCheckBoxClicked);
connect(m_defaultFeaturesCheckBox, &QCheckBox::stateChanged,
this, &AndroidManifestEditorWidget::defaultPermissionOrFeatureCheckBoxClicked);
connect(m_addPermissionButton, &QAbstractButton::clicked,
this, &AndroidManifestEditorWidget::addPermission);
connect(m_removePermissionButton, &QAbstractButton::clicked,
this, &AndroidManifestEditorWidget::removePermission);
connect(m_permissionsComboBox, &QComboBox::currentTextChanged,
this, &AndroidManifestEditorWidget::updateAddRemovePermissionButtons);
return permissionsGroupBox;
}
QGroupBox *AndroidManifestEditorWidget::createPackageFormLayout(QWidget *parent)
{
auto packageGroupBox = new QGroupBox(parent);
packageGroupBox->setTitle(tr("Package"));
auto formLayout = new QFormLayout();
m_packageNameLineEdit = new QLineEdit(packageGroupBox);
m_packageNameLineEdit->setToolTip(tr(
"<p align=\"justify\">Please choose a valid package name for your application (for "
"example, \"org.example.myapplication\").</p><p align=\"justify\">Packages are usually "
"defined using a hierarchical naming pattern, with levels in the hierarchy separated "
"by periods (.) (pronounced \"dot\").</p><p align=\"justify\">In general, a package "
"name begins with the top level domain name of the organization and then the "
"organization's domain and then any subdomains listed in reverse order. The "
"organization can then choose a specific name for their package. Package names should "
"be all lowercase characters whenever possible.</p><p align=\"justify\">Complete "
"conventions for disambiguating package names and rules for naming packages when the "
"Internet domain name cannot be directly used as a package name are described in "
"section 7.7 of the Java Language Specification.</p>"));
formLayout->addRow(tr("Package name:"), m_packageNameLineEdit);
m_packageNameWarning = new QLabel;
m_packageNameWarning->setText(tr("The package name is not valid."));
m_packageNameWarning->setVisible(false);
m_packageNameWarningIcon = new QLabel;
m_packageNameWarningIcon->setPixmap(Utils::Icons::WARNING.pixmap());
m_packageNameWarningIcon->setVisible(false);
m_packageNameWarningIcon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
auto warningRow = new QHBoxLayout;
warningRow->setContentsMargins(0, 0, 0, 0);
warningRow->addWidget(m_packageNameWarningIcon);
warningRow->addWidget(m_packageNameWarning);
formLayout->addRow(QString(), warningRow);
m_versionCodeLineEdit = new QLineEdit(packageGroupBox);
formLayout->addRow(tr("Version code:"), m_versionCodeLineEdit);
m_versionNameLinedit = new QLineEdit(packageGroupBox);
formLayout->addRow(tr("Version name:"), m_versionNameLinedit);
m_androidMinSdkVersion = new QComboBox(packageGroupBox);
m_androidMinSdkVersion->setToolTip(
tr("Sets the minimum required version on which this application can be run."));
m_androidMinSdkVersion->addItem(tr("Not set"), 0);
formLayout->addRow(tr("Minimum required SDK:"), m_androidMinSdkVersion);
m_androidTargetSdkVersion = new QComboBox(packageGroupBox);
m_androidTargetSdkVersion->setToolTip(
tr("Sets the target SDK. Set this to the highest tested version. "
"This disables compatibility behavior of the system for your application."));
m_androidTargetSdkVersion->addItem(tr("Not set"), 0);
formLayout->addRow(tr("Target SDK:"), m_androidTargetSdkVersion);
packageGroupBox->setLayout(formLayout);
updateSdkVersions();
connect(m_packageNameLineEdit, &QLineEdit::textEdited,
this, &AndroidManifestEditorWidget::setPackageName);
connect(m_versionCodeLineEdit, &QLineEdit::textEdited,
this, [this]() { setDirty(); });
connect(m_versionNameLinedit, &QLineEdit::textEdited,
this, [this]() { setDirty(); });
connect(m_androidMinSdkVersion,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this]() { setDirty(); });
connect(m_androidTargetSdkVersion,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this]() { setDirty(); });
return packageGroupBox;
}
QGroupBox *Android::Internal::AndroidManifestEditorWidget::createApplicationGroupBox(QWidget *parent)
{
auto applicationGroupBox = new QGroupBox(parent);
applicationGroupBox->setTitle(tr("Application"));
auto formLayout = new QFormLayout();
m_appNameLineEdit = new QLineEdit(applicationGroupBox);
formLayout->addRow(tr("Application name:"), m_appNameLineEdit);
m_activityNameLineEdit = new QLineEdit(applicationGroupBox);
formLayout->addRow(tr("Activity name:"), m_activityNameLineEdit);
m_targetLineEdit = new QComboBox(applicationGroupBox);
m_targetLineEdit->setEditable(true);
m_targetLineEdit->setDuplicatesEnabled(true);
m_targetLineEdit->installEventFilter(this);
formLayout->addRow(tr("Run:"), m_targetLineEdit);
m_styleExtractMethod = new QComboBox(applicationGroupBox);
formLayout->addRow(tr("Style extraction:"), m_styleExtractMethod);
const QList<QStringList> styleMethodsMap = {
{"default",
"In most cases this will be the same as \"full\", but it can also be something else "
"if needed, e.g. for compatibility reasons."},
{"full", "Useful for Qt Widgets & Qt Quick Controls 1 apps."},
{"minimal", "Useful for Qt Quick Controls 2 apps, it is much faster than \"full\"."},
{"none", "Useful for apps that don't use Qt Widgets, Qt Quick Controls 1 or Qt Quick Controls 2."}};
for (int i = 0; i <styleMethodsMap.size(); ++i) {
m_styleExtractMethod->addItem(styleMethodsMap.at(i).first());
m_styleExtractMethod->setItemData(i, styleMethodsMap.at(i).at(1), Qt::ToolTipRole);
}
applicationGroupBox->setLayout(formLayout);
connect(m_appNameLineEdit, &QLineEdit::textEdited,
this, [this]() { setDirty(); });
connect(m_activityNameLineEdit, &QLineEdit::textEdited,
this, [this]() { setDirty(); });
connect(m_targetLineEdit, &QComboBox::currentTextChanged,
this, [this]() { setDirty(); });
connect(m_styleExtractMethod,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this]() { setDirty(); });
return applicationGroupBox;
}
QGroupBox *AndroidManifestEditorWidget::createAdvancedGroupBox(QWidget *parent)
{
auto otherGroupBox = new QGroupBox(parent);
otherGroupBox->setTitle(tr("Advanced"));
m_advanvedTabWidget = new QTabWidget(otherGroupBox);
auto formLayout = new QFormLayout();
m_iconButtons = new AndroidManifestEditorIconContainerWidget(otherGroupBox, m_textEditorWidget);
m_advanvedTabWidget->addTab(m_iconButtons, tr("Application icon"));
m_services = new AndroidServiceWidget(otherGroupBox);
m_advanvedTabWidget->addTab(m_services, tr("Android services"));
m_splashButtons = new SplashIconContainerWidget(otherGroupBox, m_textEditorWidget);
m_advanvedTabWidget->addTab(m_splashButtons, tr("Splash screen"));
connect(m_services, &AndroidServiceWidget::servicesModified, this, [this]() { setDirty(); });
connect(m_services, &AndroidServiceWidget::servicesModified,
this, &AndroidManifestEditorWidget::clearInvalidServiceInfo);
connect(m_services, &AndroidServiceWidget::servicesInvalid,
this, &AndroidManifestEditorWidget::setInvalidServiceInfo);
connect(m_splashButtons, &SplashIconContainerWidget::splashScreensModified,
this, [this]() { setDirty(); });
formLayout->addRow(m_advanvedTabWidget);
otherGroupBox->setLayout(formLayout);
return otherGroupBox;
}
void AndroidManifestEditorWidget::initializePage()
{
QWidget *mainWidget = new QWidget; // different name
QWidget *mainWidget = new QWidget(); // different name
auto topLayout = new QGridLayout(mainWidget);
auto topLayout = new QVBoxLayout(mainWidget);
auto packageGroupBox = new QGroupBox(mainWidget);
topLayout->addWidget(packageGroupBox);
auto setDirtyFunc = [this] { setDirty(); };
packageGroupBox->setTitle(tr("Package"));
{
auto formLayout = new QFormLayout();
m_packageNameLineEdit = new QLineEdit(packageGroupBox);
m_packageNameLineEdit->setToolTip(tr(
"<p align=\"justify\">Please choose a valid package name "
"for your application (for example, \"org.example.myapplication\").</p>"
"<p align=\"justify\">Packages are usually defined using a hierarchical naming pattern, "
"with levels in the hierarchy separated by periods (.) (pronounced \"dot\").</p>"
"<p align=\"justify\">In general, a package name begins with the top level domain name"
" of the organization and then the organization's domain and then any subdomains listed"
" in reverse order. The organization can then choose a specific name for their package."
" Package names should be all lowercase characters whenever possible.</p>"
"<p align=\"justify\">Complete conventions for disambiguating package names and rules for"
" naming packages when the Internet domain name cannot be directly used as a package name"
" are described in section 7.7 of the Java Language Specification.</p>"));
formLayout->addRow(tr("Package name:"), m_packageNameLineEdit);
m_packageNameWarning = new QLabel;
m_packageNameWarning->setText(tr("The package name is not valid."));
m_packageNameWarning->setVisible(false);
m_packageNameWarningIcon = new QLabel;
m_packageNameWarningIcon->setPixmap(Utils::Icons::WARNING.pixmap());
m_packageNameWarningIcon->setVisible(false);
m_packageNameWarningIcon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
auto warningRow = new QHBoxLayout;
warningRow->setContentsMargins(0, 0, 0, 0);
warningRow->addWidget(m_packageNameWarningIcon);
warningRow->addWidget(m_packageNameWarning);
formLayout->addRow(QString(), warningRow);
m_versionCodeLineEdit = new QLineEdit(packageGroupBox);
formLayout->addRow(tr("Version code:"), m_versionCodeLineEdit);
m_versionNameLinedit = new QLineEdit(packageGroupBox);
formLayout->addRow(tr("Version name:"), m_versionNameLinedit);
m_androidMinSdkVersion = new QComboBox(packageGroupBox);
m_androidMinSdkVersion->setToolTip(
tr("Sets the minimum required version on which this application can be run."));
m_androidMinSdkVersion->addItem(tr("Not set"), 0);
formLayout->addRow(tr("Minimum required SDK:"), m_androidMinSdkVersion);
m_androidTargetSdkVersion = new QComboBox(packageGroupBox);
m_androidTargetSdkVersion->setToolTip(
tr("Sets the target SDK. Set this to the highest tested version. "
"This disables compatibility behavior of the system for your application."));
m_androidTargetSdkVersion->addItem(tr("Not set"), 0);
formLayout->addRow(tr("Target SDK:"), m_androidTargetSdkVersion);
packageGroupBox->setLayout(formLayout);
updateSdkVersions();
connect(m_packageNameLineEdit, &QLineEdit::textEdited,
this, &AndroidManifestEditorWidget::setPackageName);
connect(m_versionCodeLineEdit, &QLineEdit::textEdited,
this, setDirtyFunc);
connect(m_versionNameLinedit, &QLineEdit::textEdited,
this, setDirtyFunc);
connect(m_androidMinSdkVersion,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, setDirtyFunc);
connect(m_androidTargetSdkVersion,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, setDirtyFunc);
}
// Application
auto applicationGroupBox = new QGroupBox(mainWidget);
topLayout->addWidget(applicationGroupBox);
applicationGroupBox->setTitle(tr("Application"));
{
auto formLayout = new QFormLayout();
m_appNameLineEdit = new QLineEdit(applicationGroupBox);
formLayout->addRow(tr("Application name:"), m_appNameLineEdit);
m_activityNameLineEdit = new QLineEdit(applicationGroupBox);
formLayout->addRow(tr("Activity name:"), m_activityNameLineEdit);
m_targetLineEdit = new QComboBox(applicationGroupBox);
m_targetLineEdit->setEditable(true);
m_targetLineEdit->setDuplicatesEnabled(true);
m_targetLineEdit->installEventFilter(this);
formLayout->addRow(tr("Run:"), m_targetLineEdit);
m_styleExtractMethod = new QComboBox(applicationGroupBox);
formLayout->addRow(tr("Style extraction:"), m_styleExtractMethod);
const QList<QStringList> styleMethodsMap = {
{"default", "In most cases this will be the same as \"full\", but it can also be something else if needed, e.g. for compatibility reasons."},
{"full", "Useful for Qt Widgets & Qt Quick Controls 1 apps."},
{"minimal", "Useful for Qt Quick Controls 2 apps, it is much faster than \"full\"."},
{"none", "Useful for apps that don't use Qt Widgets, Qt Quick Controls 1 or Qt Quick Controls 2."}};
for (int i = 0; i <styleMethodsMap.size(); ++i) {
m_styleExtractMethod->addItem(styleMethodsMap.at(i).first());
m_styleExtractMethod->setItemData(i, styleMethodsMap.at(i).at(1), Qt::ToolTipRole);
}
m_iconButtons = new AndroidManifestEditorIconContainerWidget(applicationGroupBox, m_textEditorWidget);
formLayout->addRow(tr("Application icon:"), new QLabel());
formLayout->addRow(QString(), m_iconButtons);
m_splashButtons = new SplashIconContainerWidget(applicationGroupBox, m_textEditorWidget);
formLayout->addRow(tr("Splash screen:"), new QLabel());
formLayout->addRow(QString(), m_splashButtons);
m_services = new AndroidServiceWidget(this);
formLayout->addRow(tr("Android services:"), m_services);
applicationGroupBox->setLayout(formLayout);
connect(m_appNameLineEdit, &QLineEdit::textEdited,
this, setDirtyFunc);
connect(m_activityNameLineEdit, &QLineEdit::textEdited,
this, setDirtyFunc);
connect(m_targetLineEdit, &QComboBox::currentTextChanged,
this, setDirtyFunc);
connect(m_styleExtractMethod,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, setDirtyFunc);
connect(m_services, &AndroidServiceWidget::servicesModified,
this, setDirtyFunc);
connect(m_splashButtons, &SplashIconContainerWidget::splashScreensModified,
this, setDirtyFunc);
connect(m_services, &AndroidServiceWidget::servicesModified,
this, &AndroidManifestEditorWidget::clearInvalidServiceInfo);
connect(m_services, &AndroidServiceWidget::servicesInvalid,
this, &AndroidManifestEditorWidget::setInvalidServiceInfo);
}
// Permissions
auto permissionsGroupBox = new QGroupBox(mainWidget);
topLayout->addWidget(permissionsGroupBox);
permissionsGroupBox->setTitle(tr("Permissions"));
{
auto layout = new QGridLayout(permissionsGroupBox);
m_defaultPermissonsCheckBox = new QCheckBox(this);
m_defaultPermissonsCheckBox->setText(tr("Include default permissions for Qt modules."));
layout->addWidget(m_defaultPermissonsCheckBox, 0, 0);
m_defaultFeaturesCheckBox = new QCheckBox(this);
m_defaultFeaturesCheckBox->setText(tr("Include default features for Qt modules."));
layout->addWidget(m_defaultFeaturesCheckBox, 1, 0);
m_permissionsComboBox = new QComboBox(permissionsGroupBox);
m_permissionsComboBox->insertItems(0, QStringList()
<< QLatin1String("android.permission.ACCESS_CHECKIN_PROPERTIES")
<< QLatin1String("android.permission.ACCESS_COARSE_LOCATION")
<< QLatin1String("android.permission.ACCESS_FINE_LOCATION")
<< QLatin1String("android.permission.ACCESS_LOCATION_EXTRA_COMMANDS")
<< QLatin1String("android.permission.ACCESS_MOCK_LOCATION")
<< QLatin1String("android.permission.ACCESS_NETWORK_STATE")
<< QLatin1String("android.permission.ACCESS_SURFACE_FLINGER")
<< QLatin1String("android.permission.ACCESS_WIFI_STATE")
<< QLatin1String("android.permission.ACCOUNT_MANAGER")
<< QLatin1String("com.android.voicemail.permission.ADD_VOICEMAIL")
<< QLatin1String("android.permission.AUTHENTICATE_ACCOUNTS")
<< QLatin1String("android.permission.BATTERY_STATS")
<< QLatin1String("android.permission.BIND_ACCESSIBILITY_SERVICE")
<< QLatin1String("android.permission.BIND_APPWIDGET")
<< QLatin1String("android.permission.BIND_DEVICE_ADMIN")
<< QLatin1String("android.permission.BIND_INPUT_METHOD")
<< QLatin1String("android.permission.BIND_REMOTEVIEWS")
<< QLatin1String("android.permission.BIND_TEXT_SERVICE")
<< QLatin1String("android.permission.BIND_VPN_SERVICE")
<< QLatin1String("android.permission.BIND_WALLPAPER")
<< QLatin1String("android.permission.BLUETOOTH")
<< QLatin1String("android.permission.BLUETOOTH_ADMIN")
<< QLatin1String("android.permission.BRICK")
<< QLatin1String("android.permission.BROADCAST_PACKAGE_REMOVED")
<< QLatin1String("android.permission.BROADCAST_SMS")
<< QLatin1String("android.permission.BROADCAST_STICKY")
<< QLatin1String("android.permission.BROADCAST_WAP_PUSH")
<< QLatin1String("android.permission.CALL_PHONE")
<< QLatin1String("android.permission.CALL_PRIVILEGED")
<< QLatin1String("android.permission.CAMERA")
<< QLatin1String("android.permission.CHANGE_COMPONENT_ENABLED_STATE")
<< QLatin1String("android.permission.CHANGE_CONFIGURATION")
<< QLatin1String("android.permission.CHANGE_NETWORK_STATE")
<< QLatin1String("android.permission.CHANGE_WIFI_MULTICAST_STATE")
<< QLatin1String("android.permission.CHANGE_WIFI_STATE")
<< QLatin1String("android.permission.CLEAR_APP_CACHE")
<< QLatin1String("android.permission.CLEAR_APP_USER_DATA")
<< QLatin1String("android.permission.CONTROL_LOCATION_UPDATES")
<< QLatin1String("android.permission.DELETE_CACHE_FILES")
<< QLatin1String("android.permission.DELETE_PACKAGES")
<< QLatin1String("android.permission.DEVICE_POWER")
<< QLatin1String("android.permission.DIAGNOSTIC")
<< QLatin1String("android.permission.DISABLE_KEYGUARD")
<< QLatin1String("android.permission.DUMP")
<< QLatin1String("android.permission.EXPAND_STATUS_BAR")
<< QLatin1String("android.permission.FACTORY_TEST")
<< QLatin1String("android.permission.FLASHLIGHT")
<< QLatin1String("android.permission.FORCE_BACK")
<< QLatin1String("android.permission.GET_ACCOUNTS")
<< QLatin1String("android.permission.GET_PACKAGE_SIZE")
<< QLatin1String("android.permission.GET_TASKS")
<< QLatin1String("android.permission.GLOBAL_SEARCH")
<< QLatin1String("android.permission.HARDWARE_TEST")
<< QLatin1String("android.permission.INJECT_EVENTS")
<< QLatin1String("android.permission.INSTALL_LOCATION_PROVIDER")
<< QLatin1String("android.permission.INSTALL_PACKAGES")
<< QLatin1String("android.permission.INTERNAL_SYSTEM_WINDOW")
<< QLatin1String("android.permission.INTERNET")
<< QLatin1String("android.permission.KILL_BACKGROUND_PROCESSES")
<< QLatin1String("android.permission.MANAGE_ACCOUNTS")
<< QLatin1String("android.permission.MANAGE_APP_TOKENS")
<< QLatin1String("android.permission.MASTER_CLEAR")
<< QLatin1String("android.permission.MODIFY_AUDIO_SETTINGS")
<< QLatin1String("android.permission.MODIFY_PHONE_STATE")
<< QLatin1String("android.permission.MOUNT_FORMAT_FILESYSTEMS")
<< QLatin1String("android.permission.MOUNT_UNMOUNT_FILESYSTEMS")
<< QLatin1String("android.permission.NFC")
<< QLatin1String("android.permission.PERSISTENT_ACTIVITY")
<< QLatin1String("android.permission.PROCESS_OUTGOING_CALLS")
<< QLatin1String("android.permission.READ_CALENDAR")
<< QLatin1String("android.permission.READ_CALL_LOG")
<< QLatin1String("android.permission.READ_CONTACTS")
<< QLatin1String("android.permission.READ_EXTERNAL_STORAGE")
<< QLatin1String("android.permission.READ_FRAME_BUFFER")
<< QLatin1String("com.android.browser.permission.READ_HISTORY_BOOKMARKS")
<< QLatin1String("android.permission.READ_INPUT_STATE")
<< QLatin1String("android.permission.READ_LOGS")
<< QLatin1String("android.permission.READ_PHONE_STATE")
<< QLatin1String("android.permission.READ_PROFILE")
<< QLatin1String("android.permission.READ_SMS")
<< QLatin1String("android.permission.READ_SOCIAL_STREAM")
<< QLatin1String("android.permission.READ_SYNC_SETTINGS")
<< QLatin1String("android.permission.READ_SYNC_STATS")
<< QLatin1String("android.permission.READ_USER_DICTIONARY")
<< QLatin1String("android.permission.REBOOT")
<< QLatin1String("android.permission.RECEIVE_BOOT_COMPLETED")
<< QLatin1String("android.permission.RECEIVE_MMS")
<< QLatin1String("android.permission.RECEIVE_SMS")
<< QLatin1String("android.permission.RECEIVE_WAP_PUSH")
<< QLatin1String("android.permission.RECORD_AUDIO")
<< QLatin1String("android.permission.REORDER_TASKS")
<< QLatin1String("android.permission.RESTART_PACKAGES")
<< QLatin1String("android.permission.SEND_SMS")
<< QLatin1String("android.permission.SET_ACTIVITY_WATCHER")
<< QLatin1String("com.android.alarm.permission.SET_ALARM")
<< QLatin1String("android.permission.SET_ALWAYS_FINISH")
<< QLatin1String("android.permission.SET_ANIMATION_SCALE")
<< QLatin1String("android.permission.SET_DEBUG_APP")
<< QLatin1String("android.permission.SET_ORIENTATION")
<< QLatin1String("android.permission.SET_POINTER_SPEED")
<< QLatin1String("android.permission.SET_PREFERRED_APPLICATIONS")
<< QLatin1String("android.permission.SET_PROCESS_LIMIT")
<< QLatin1String("android.permission.SET_TIME")
<< QLatin1String("android.permission.SET_TIME_ZONE")
<< QLatin1String("android.permission.SET_WALLPAPER")
<< QLatin1String("android.permission.SET_WALLPAPER_HINTS")
<< QLatin1String("android.permission.SIGNAL_PERSISTENT_PROCESSES")
<< QLatin1String("android.permission.STATUS_BAR")
<< QLatin1String("android.permission.SUBSCRIBED_FEEDS_READ")
<< QLatin1String("android.permission.SUBSCRIBED_FEEDS_WRITE")
<< QLatin1String("android.permission.SYSTEM_ALERT_WINDOW")
<< QLatin1String("android.permission.UPDATE_DEVICE_STATS")
<< QLatin1String("android.permission.USE_CREDENTIALS")
<< QLatin1String("android.permission.USE_SIP")
<< QLatin1String("android.permission.VIBRATE")
<< QLatin1String("android.permission.WAKE_LOCK")
<< QLatin1String("android.permission.WRITE_APN_SETTINGS")
<< QLatin1String("android.permission.WRITE_CALENDAR")
<< QLatin1String("android.permission.WRITE_CALL_LOG")
<< QLatin1String("android.permission.WRITE_CONTACTS")
<< QLatin1String("android.permission.WRITE_EXTERNAL_STORAGE")
<< QLatin1String("android.permission.WRITE_GSERVICES")
<< QLatin1String("com.android.browser.permission.WRITE_HISTORY_BOOKMARKS")
<< QLatin1String("android.permission.WRITE_PROFILE")
<< QLatin1String("android.permission.WRITE_SECURE_SETTINGS")
<< QLatin1String("android.permission.WRITE_SETTINGS")
<< QLatin1String("android.permission.WRITE_SMS")
<< QLatin1String("android.permission.WRITE_SOCIAL_STREAM")
<< QLatin1String("android.permission.WRITE_SYNC_SETTINGS")
<< QLatin1String("android.permission.WRITE_USER_DICTIONARY")
);
m_permissionsComboBox->setEditable(true);
layout->addWidget(m_permissionsComboBox, 2, 0);
m_addPermissionButton = new QPushButton(permissionsGroupBox);
m_addPermissionButton->setText(tr("Add"));
layout->addWidget(m_addPermissionButton, 2, 1);
m_permissionsModel = new PermissionsModel(this);
m_permissionsListView = new QListView(permissionsGroupBox);
m_permissionsListView->setModel(m_permissionsModel);
layout->addWidget(m_permissionsListView, 3, 0, 3, 1);
m_removePermissionButton = new QPushButton(permissionsGroupBox);
m_removePermissionButton->setText(tr("Remove"));
layout->addWidget(m_removePermissionButton, 3, 1);
permissionsGroupBox->setLayout(layout);
connect(m_defaultPermissonsCheckBox, &QCheckBox::stateChanged,
this, &AndroidManifestEditorWidget::defaultPermissionOrFeatureCheckBoxClicked);
connect(m_defaultFeaturesCheckBox, &QCheckBox::stateChanged,
this, &AndroidManifestEditorWidget::defaultPermissionOrFeatureCheckBoxClicked);
connect(m_addPermissionButton, &QAbstractButton::clicked,
this, &AndroidManifestEditorWidget::addPermission);
connect(m_removePermissionButton, &QAbstractButton::clicked,
this, &AndroidManifestEditorWidget::removePermission);
connect(m_permissionsComboBox, &QComboBox::currentTextChanged,
this, &AndroidManifestEditorWidget::updateAddRemovePermissionButtons);
}
topLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
topLayout->addWidget(createPackageFormLayout(mainWidget), 0, 0);
topLayout->addWidget(createApplicationGroupBox(mainWidget), 0, 1);
topLayout->addWidget(createPermissionsGroupBox(mainWidget), 1, 0, 1, 2);
topLayout->addWidget(createAdvancedGroupBox(mainWidget), 2, 0, 1, 2);
topLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::MinimumExpanding), 3, 0);
auto mainWidgetScrollArea = new QScrollArea;
mainWidgetScrollArea->setWidgetResizable(true);
@@ -575,6 +587,7 @@ bool AndroidManifestEditorWidget::setActivePage(EditorPage page)
if (!servicesValid(m_services->services())) {
QMessageBox::critical(nullptr, tr("Service Definition Invalid"),
tr("Cannot switch to source when there are invalid services."));
m_advanvedTabWidget->setCurrentIndex(1);
return false;
}
syncToEditor();

View File

@@ -28,6 +28,9 @@
#include <texteditor/texteditor.h>
#include <QAbstractListModel>
#include <QGroupBox>
#include <QGridLayout>
#include <QTabWidget>
#include <QStackedWidget>
#include <QTimer>
@@ -156,6 +159,11 @@ private:
QString parseComment(QXmlStreamReader &reader, QXmlStreamWriter &writer);
void parseUnknownElement(QXmlStreamReader &reader, QXmlStreamWriter &writer, bool ignore=false);
QGroupBox *createPermissionsGroupBox(QWidget *parent);
QGroupBox *createPackageFormLayout(QWidget *parent);
QGroupBox *createApplicationGroupBox(QWidget *parent);
QGroupBox *createAdvancedGroupBox(QWidget *parent);
bool m_dirty; // indicates that we need to call syncToEditor()
bool m_stayClean;
int m_errorLine;
@@ -192,6 +200,7 @@ private:
TextEditor::TextEditorWidget *m_textEditorWidget;
AndroidManifestEditor *m_editor;
QString m_androidNdkPlatform;
QTabWidget *m_advanvedTabWidget = nullptr;
};
} // namespace Internal
} // namespace Android

View File

@@ -77,7 +77,7 @@ public:
setConfigBaseId("Qt4ProjectManager.AndroidDeployConfiguration2");
addSupportedTargetDeviceType(Constants::ANDROID_DEVICE_TYPE);
setDefaultDisplayName(QCoreApplication::translate("Android::Internal",
"Deploy to Android device"));
"Deploy to Android Device"));
addInitialStep(AndroidDeployQtStep::stepId());
}
};

View File

@@ -35,6 +35,7 @@
#include <qtsupport/qtsupportconstants.h>
#include <qtsupport/qtversionmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/project.h>
@@ -86,25 +87,25 @@ QString AndroidQtVersion::invalidReason() const
Abis AndroidQtVersion::detectQtAbis() const
{
auto androidAbi2Abi = [](const QString &androidAbi) {
if (androidAbi == "arm64-v8a") {
if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A) {
return Abi{Abi::Architecture::ArmArchitecture,
Abi::OS::LinuxOS,
Abi::OSFlavor::AndroidLinuxFlavor,
Abi::BinaryFormat::ElfFormat,
64, androidAbi};
} else if (androidAbi == "armeabi-v7a") {
} else if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A) {
return Abi{Abi::Architecture::ArmArchitecture,
Abi::OS::LinuxOS,
Abi::OSFlavor::AndroidLinuxFlavor,
Abi::BinaryFormat::ElfFormat,
32, androidAbi};
} else if (androidAbi == "x86_64") {
} else if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_X86_64) {
return Abi{Abi::Architecture::X86Architecture,
Abi::OS::LinuxOS,
Abi::OSFlavor::AndroidLinuxFlavor,
Abi::BinaryFormat::ElfFormat,
64, androidAbi};
} else if (androidAbi == "x86") {
} else if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_X86) {
return Abi{Abi::Architecture::X86Architecture,
Abi::OS::LinuxOS,
Abi::OSFlavor::AndroidLinuxFlavor,

View File

@@ -33,6 +33,7 @@
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerrunconfigurationaspect.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/runcontrol.h>
@@ -127,21 +128,23 @@ static void findProcessPID(QFutureInterface<qint64> &fi, QStringList selector,
if (packageName.isEmpty())
return;
QStringList args = {selector};
FilePath adbPath = AndroidConfigurations::currentConfig().adbToolPath();
args.append("shell");
args.append(preNougat ? pidScriptPreNougat : pidScript.arg(packageName));
qint64 processPID = -1;
chrono::high_resolution_clock::time_point start = chrono::high_resolution_clock::now();
do {
QThread::msleep(200);
FilePath adbPath = AndroidConfigurations::currentConfig().adbToolPath();
selector.append("shell");
selector.append(preNougat ? pidScriptPreNougat : pidScript.arg(packageName));
const auto out = SynchronousProcess().runBlocking({adbPath, selector}).allRawOutput();
const auto out = SynchronousProcess().runBlocking({adbPath, args}).allRawOutput();
if (preNougat) {
processPID = extractPID(out, packageName);
} else {
if (!out.isEmpty())
processPID = out.trimmed().toLongLong();
}
} while (processPID == -1 && !isTimedOut(start) && !fi.isCanceled());
} while ((processPID == -1 || processPID == 0) && !isTimedOut(start) && !fi.isCanceled());
qCDebug(androidRunWorkerLog) << "PID found:" << processPID << ", PreNougat:" << preNougat;
if (!fi.isCanceled())
@@ -162,32 +165,32 @@ static void deleter(QProcess *p)
static QString gdbServerArch(const QString &androidAbi)
{
if (androidAbi == "arm64-v8a")
if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A)
return QString("arm64");
if (androidAbi == "armeabi-v7a")
if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A)
return QString("arm");
// That's correct for "x86_64" and "x86", and best guess at anything that will evolve:
// That's correct for x86_64 and x86, and best guess at anything that will evolve:
return androidAbi;
}
static QString lldbServerArch(const QString &androidAbi)
{
if (androidAbi == "armeabi-v7a")
return QString("armeabi");
// Correct for arm64-v8a "x86_64" and "x86", and best guess at anything that will evolve:
if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A)
return {ProjectExplorer::Constants::ANDROID_ABI_ARMEABI};
// Correct for arm64-v8a, x86 and x86_64, and best guess at anything that will evolve:
return androidAbi; // arm64-v8a, x86, x86_64
}
static QString lldbServerArch2(const QString &androidAbi)
{
if (androidAbi == "armeabi-v7a")
if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A)
return {"arm"};
if (androidAbi == "x86")
if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_X86)
return {"i386"};
if (androidAbi == "arm64-v8a")
if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A)
return {"aarch64"};
// Correct for "x86_64" a and best guess at anything that will evolve:
return androidAbi; // arm64-v8a
// Correct for x86_64 and best guess at anything that will evolve:
return androidAbi; // x86_64
}
static FilePath debugServer(bool useLldb, const Target *target)

View File

@@ -56,6 +56,7 @@
#include <QLoggingCategory>
#include <QMessageBox>
#include <QModelIndex>
#include <QScrollArea>
#include <QSettings>
#include <QStandardPaths>
#include <QString>
@@ -368,7 +369,14 @@ AndroidSettingsWidget::AndroidSettingsWidget()
m_ui.managerTabWidget->tabBar()->setEnabled(true);
});
connect(m_sdkManagerWidget, &AndroidSdkManagerWidget::licenseWorkflowStarted, [this] {
m_ui.scrollArea->ensureWidgetVisible(m_ui.managerTabWidget);
QObject *parentWidget = parent();
while (parentWidget) {
if (auto scrollArea = qobject_cast<QScrollArea *>(parentWidget)) {
scrollArea->ensureWidgetVisible(m_ui.managerTabWidget);
break;
}
parentWidget = parentWidget->parent();
};
});
QMap<int, QString> javaValidationPoints;
@@ -405,42 +413,49 @@ AndroidSettingsWidget::AndroidSettingsWidget()
connect(m_ui.OpenJDKLocationPathChooser, &PathChooser::rawPathChanged,
this, &AndroidSettingsWidget::validateJdk);
FilePath currentJdkPath = m_androidConfig.openJDKLocation();
if (currentJdkPath.isEmpty())
currentJdkPath = AndroidConfig::getJdkPath();
m_ui.OpenJDKLocationPathChooser->setFilePath(currentJdkPath);
if (m_androidConfig.openJDKLocation().isEmpty())
m_androidConfig.setOpenJDKLocation(AndroidConfig::getJdkPath());
m_ui.OpenJDKLocationPathChooser->setFilePath(m_androidConfig.openJDKLocation());
m_ui.OpenJDKLocationPathChooser->setPromptDialogTitle(tr("Select JDK Path"));
FilePath currentSDKPath = m_androidConfig.sdkLocation();
if (currentSDKPath.isEmpty())
currentSDKPath = AndroidConfig::defaultSdkPath();
m_ui.SDKLocationPathChooser->setFilePath(currentSDKPath);
if (m_androidConfig.sdkLocation().isEmpty())
m_androidConfig.setSdkLocation(AndroidConfig::defaultSdkPath());
m_ui.SDKLocationPathChooser->setFilePath(m_androidConfig.sdkLocation());
m_ui.SDKLocationPathChooser->setPromptDialogTitle(tr("Select Android SDK Folder"));
m_ui.openSslPathChooser->setPromptDialogTitle(tr("Select OpenSSL Include Project File"));
FilePath currentOpenSslPath = m_androidConfig.openSslLocation();
if (currentOpenSslPath.isEmpty())
currentOpenSslPath = currentSDKPath.pathAppended("android_openssl");
m_ui.openSslPathChooser->setFilePath(currentOpenSslPath);
if (m_androidConfig.openSslLocation().isEmpty())
m_androidConfig.setOpenSslLocation(m_androidConfig.sdkLocation() / ("android_openssl"));
m_ui.openSslPathChooser->setFilePath(m_androidConfig.openSslLocation());
m_ui.DataPartitionSizeSpinBox->setValue(m_androidConfig.partitionSize());
m_ui.CreateKitCheckBox->setChecked(m_androidConfig.automaticKitCreation());
m_ui.AVDTableView->setModel(&m_AVDModel);
m_ui.AVDTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
m_ui.AVDTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
for (int column : {1, 2, 5})
m_ui.AVDTableView->horizontalHeader()->setSectionResizeMode(
column, QHeaderView::ResizeToContents);
const QIcon downloadIcon = Icons::ONLINE.icon();
m_ui.downloadSDKToolButton->setIcon(downloadIcon);
m_ui.downloadNDKToolButton->setIcon(downloadIcon);
m_ui.downloadOpenJDKToolButton->setIcon(downloadIcon);
m_ui.sdkToolsAutoDownloadButton->setToolTip(tr(
"Automatically download Android SDK Tools to selected location.\n\n"
"If the selected path contains no valid SDK Tools, the SDK Tools package "
"is downloaded from %1, and extracted to the selected path.\n"
"After the SDK Tools are properly set up, you are prompted to install "
"any essential packages required for Qt to build for Android.")
.arg(m_androidConfig.sdkToolsUrl().toString()));
m_ui.sdkToolsAutoDownloadButton->setToolTip(
tr("Automatically download Android SDK Tools to selected location.\n\n"
"If the selected path contains no valid SDK Tools, the SDK Tools package is downloaded\n"
"from %1,\n"
"and extracted to the selected path.\n"
"After the SDK Tools are properly set up, you are prompted to install any essential\n"
"packages required for Qt to build for Android.")
.arg(m_androidConfig.sdkToolsUrl().toString()));
m_ui.downloadOpenSSLPrebuiltLibs->setToolTip(
tr("Automatically download OpenSSL prebuilt libraries.\n\n"
"These libraries can be shipped with your application if any SSL operations\n"
"are performed. Find the checkbox under \"Projects > Build > Build Steps >\n"
"Build Android APK > Additional Libraries\".\n"
"If the automatic download fails, Qt Creator proposes to open the download URL\n"
"in the system's browser for manual download."));
connect(m_ui.SDKLocationPathChooser, &PathChooser::rawPathChanged,
this, &AndroidSettingsWidget::onSdkPathChanged);
@@ -700,7 +715,7 @@ void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent)
QMessageBox msgBox;
msgBox.setText(tr("OpenSSL prebuilt libraries cloning failed. ") + msgSuffix
+ tr("Opening OpenSSL URL for manual download."));
msgBox.addButton(tr("OK"), QMessageBox::YesRole);
msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole);
QAbstractButton *openButton = msgBox.addButton(tr("Open Download URL"), QMessageBox::ActionRole);
msgBox.exec();
@@ -849,13 +864,7 @@ AndroidSettingsPage::AndroidSettingsPage()
setId(Constants::ANDROID_SETTINGS_ID);
setDisplayName(AndroidSettingsWidget::tr("Android"));
setCategory(ProjectExplorer::Constants::DEVICE_SETTINGS_CATEGORY);
setWidgetCreator([] {
auto widget = new AndroidSettingsWidget;
QPalette pal = widget->palette();
pal.setColor(QPalette::Window, Utils::creatorTheme()->color(Theme::BackgroundColorNormal));
widget->setPalette(pal);
return widget;
});
setWidgetCreator([] { return new AndroidSettingsWidget; });
}
} // namespace Internal

View File

@@ -2,57 +2,278 @@
<ui version="4.0">
<class>AndroidSettingsWidget</class>
<widget class="QWidget" name="AndroidSettingsWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1131</width>
<height>826</height>
</rect>
</property>
<property name="windowTitle">
<string>Android Configuration</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<widget class="QGroupBox" name="javaSettingsGroupBox">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
<property name="title">
<string>Java Settings</string>
</property>
<property name="lineWidth">
<number>0</number>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="Utils::PathChooser" name="OpenJDKLocationPathChooser" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="downloadOpenJDKToolButton">
<property name="toolTip">
<string>Open JDK download URL in the system's browser.</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="OpenJDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>JDK location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="Utils::DetailsWidget" name="javaDetailsWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="androidSettingsGroupBox">
<property name="title">
<string>Android Settings</string>
</property>
<property name="widgetResizable">
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="1" rowspan="3">
<widget class="QListWidget" name="ndkListWidget">
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="modelColumn">
<number>0</number>
</property>
<property name="sortingEnabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="2" rowspan="3" colspan="4">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="addCustomNdkButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Add the selected custom NDK. The toolchains and debuggers will be created automatically.</string>
</property>
<property name="text">
<string>Add...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeCustomNdkButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Remove the selected NDK if it has been added manually.</string>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="5" column="0" colspan="7">
<widget class="Utils::DetailsWidget" name="androidDetailsWidget" native="true"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="ndkComboBoxLabel">
<property name="text">
<string>Android NDK list:</string>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QToolButton" name="downloadSDKToolButton">
<property name="toolTip">
<string>Open Android SDK download URL in the system's browser.</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="SDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Android SDK location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QToolButton" name="downloadNDKToolButton">
<property name="toolTip">
<string>Open Android NDK download URL in the system's browser.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Utils::PathChooser" name="SDKLocationPathChooser" native="true"/>
</item>
<item row="0" column="2" colspan="4">
<widget class="QPushButton" name="sdkToolsAutoDownloadButton">
<property name="text">
<string>Set Up SDK</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="androidOpenSSLSettingsGroupBox">
<property name="title">
<string>Android OpenSSL settings (Optional)</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>OpenSSL binaries location:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="Utils::DetailsWidget" name="openSslDetailsWidget" native="true"/>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="downloadOpenSSLPrebuiltLibs">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Download OpenSSL</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="Utils::PathChooser" name="openSslPathChooser" native="true">
<property name="toolTip">
<string>Select the path of the prebuilt OpenSSL binaries.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="CreateKitCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Automatically create kits for Android tool chains</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1123</width>
<height>818</height>
</rect>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
</widget>
</item>
<item>
<widget class="QTabWidget" name="managerTabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="avdManagerTab">
<attribute name="title">
<string>AVD Manager</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
@@ -66,435 +287,148 @@
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="javaSettingsGroupBox">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Java Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="Utils::PathChooser" name="OpenJDKLocationPathChooser" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="downloadOpenJDKToolButton">
<property name="toolTip">
<string>Open JDK download URL in the system's browser.</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="OpenJDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>JDK location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="Utils::DetailsWidget" name="javaDetailsWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="androidSettingsGroupBox">
<property name="title">
<string>Android Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="1" rowspan="3">
<widget class="QListWidget" name="ndkListWidget">
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="modelColumn">
<number>0</number>
</property>
<property name="sortingEnabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="2" rowspan="3" colspan="4">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="addCustomNdkButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Add the selected custom NDK. The toolchains and debuggers will be created automatically.</string>
</property>
<property name="text">
<string>Add...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeCustomNdkButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Remove the selected NDK if it has been added manually.</string>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="5" column="0" colspan="7">
<widget class="Utils::DetailsWidget" name="androidDetailsWidget" native="true"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="ndkComboBoxLabel">
<property name="text">
<string>Android NDK list:</string>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QToolButton" name="downloadSDKToolButton">
<property name="toolTip">
<string>Open Android SDK download URL in the system's browser.</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="SDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Android SDK location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QToolButton" name="downloadNDKToolButton">
<property name="toolTip">
<string>Open Android NDK download URL in the system's browser.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Utils::PathChooser" name="SDKLocationPathChooser" native="true"/>
</item>
<item row="0" column="2" colspan="4">
<widget class="QPushButton" name="sdkToolsAutoDownloadButton">
<property name="text">
<string>Set Up SDK</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="androidOpenSSLSettingsGroupBox">
<property name="title">
<string>Android OpenSSL settings (Optional)</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>OpenSSL binaries location:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="Utils::DetailsWidget" name="openSslDetailsWidget" native="true"/>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="downloadOpenSSLPrebuiltLibs">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Automatically download OpenSSL prebuilt libraries. If the automatic download fails, Qt Creator proposes to open the download URL in the system's browser for manual download.</string>
</property>
<property name="text">
<string>Download OpenSSL</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="Utils::PathChooser" name="openSslPathChooser" native="true">
<property name="toolTip">
<string>Select the path of the prebuilt OpenSSL binaries.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="CreateKitCheckBox">
<widget class="QTableView" name="AVDTableView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Automatically create kits for Android tool chains</string>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="checked">
<bool>true</bool>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<widget class="QTabWidget" name="managerTabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="avdManagerTab">
<attribute name="title">
<string>AVD Manager</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="DataPartitionSizeLable">
<property name="text">
<string>System/data partition size:</string>
</property>
<property name="topMargin">
<number>0</number>
</widget>
</item>
<item>
<widget class="QSpinBox" name="DataPartitionSizeSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="rightMargin">
<number>0</number>
<property name="suffix">
<string> Mb</string>
</property>
<property name="bottomMargin">
<number>0</number>
<property name="maximum">
<number>99999</number>
</property>
<item>
<widget class="QTableView" name="AVDTableView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="DataPartitionSizeLable">
<property name="text">
<string>System/data partition size:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="DataPartitionSizeSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string> Mb</string>
</property>
<property name="maximum">
<number>99999</number>
</property>
<property name="value">
<number>1024</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="AVDStartPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Start...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="AVDRefreshPushButton">
<property name="text">
<string>Refresh List</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>8</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="AVDAddPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="AVDRemovePushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="sdkManagerTab">
<attribute name="title">
<string>SDK Manager</string>
</attribute>
</widget>
</widget>
<property name="value">
<number>1024</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="AVDStartPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Start...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="AVDRefreshPushButton">
<property name="text">
<string>Refresh List</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>8</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="AVDAddPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="AVDRemovePushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="sdkManagerTab">
<attribute name="title">
<string>SDK Manager</string>
</attribute>
</widget>
</widget>
</item>
</layout>

View File

@@ -27,6 +27,7 @@
#include "androidsdkmanager.h"
#include "androidavdmanager.h"
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h>
#include <utils/tooltip/tooltip.h>
#include <utils/utilsicons.h>
@@ -58,8 +59,12 @@ AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStri
m_hideTipTimer.setSingleShot(true);
if (abis.isEmpty()) {
m_avdDialog.abiComboBox->addItems(QStringList({"x86", "x86_64", "armeabi-v7a",
"armeabi", "arm64-v8a"}));
m_avdDialog.abiComboBox->addItems(QStringList({
ProjectExplorer::Constants::ANDROID_ABI_X86,
ProjectExplorer::Constants::ANDROID_ABI_X86_64,
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A,
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI,
ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A}));
} else {
m_avdDialog.abiComboBox->addItems(abis);
}

View File

@@ -182,7 +182,7 @@ ChooseDirectoryPage::ChooseDirectoryPage(CreateAndroidManifestWizard *wizard)
if (wizard->copyGradle()) {
auto checkBox = new QCheckBox(this);
checkBox->setChecked(true);
checkBox->setChecked(false);
connect(checkBox, &QCheckBox::toggled, wizard, &CreateAndroidManifestWizard::setCopyGradle);
checkBox->setText(tr("Copy the Gradle files to Android directory"));
checkBox->setToolTip(tr("It is highly recommended if you are planning to extend the Java part of your Qt application."));
@@ -245,7 +245,7 @@ void ChooseDirectoryPage::initializePage()
// CreateAndroidManifestWizard
//
CreateAndroidManifestWizard::CreateAndroidManifestWizard(BuildSystem *buildSystem)
: m_buildSystem(buildSystem), m_copyState(Ask)
: m_buildSystem(buildSystem)
{
setWindowTitle(tr("Create Android Template Files Wizard"));
@@ -290,70 +290,12 @@ void CreateAndroidManifestWizard::setCopyGradle(bool copy)
m_copyGradle = copy;
}
bool CreateAndroidManifestWizard::copy(const QFileInfo &src, const QFileInfo &dst, QStringList * addedFiles)
{
bool copyFile = true;
if (dst.exists()) {
switch (m_copyState) {
case Ask:
{
int res = QMessageBox::question(this,
tr("Overwrite %1 file").arg(dst.fileName()),
tr("Overwrite existing \"%1\"?")
.arg(QDir(m_directory).relativeFilePath(dst.absoluteFilePath())),
QMessageBox::Yes | QMessageBox::YesToAll |
QMessageBox::No | QMessageBox::NoToAll |
QMessageBox::Cancel);
switch (res) {
case QMessageBox::YesToAll:
m_copyState = OverwriteAll;
break;
case QMessageBox::Yes:
break;
case QMessageBox::NoToAll:
m_copyState = SkipAll;
copyFile = false;
break;
case QMessageBox::No:
copyFile = false;
break;
default:
return false;
}
}
break;
case SkipAll:
copyFile = false;
break;
default:
break;
}
if (copyFile)
QFile::remove(dst.filePath());
}
if (!dst.absoluteDir().exists())
dst.absoluteDir().mkpath(dst.absolutePath());
if (copyFile && !QFile::copy(src.filePath(), dst.filePath())) {
QMessageBox::warning(this, tr("File Creation Error"),
tr("Could not copy file \"%1\" to \"%2\".")
.arg(src.filePath()).arg(dst.filePath()));
return false;
}
addedFiles->append(dst.absoluteFilePath());
return true;
}
void CreateAndroidManifestWizard::createAndroidTemplateFiles()
{
if (m_directory.isEmpty())
return;
QStringList addedFiles;
FileUtils::CopyAskingForOverwrite copy(this);
Target *target = m_buildSystem->target();
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target->kit());
if (!version)
@@ -361,21 +303,23 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles()
if (version->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) {
const QString src = version->prefix().toString() + "/src/android/java/AndroidManifest.xml";
FileUtils::copyRecursively(FilePath::fromString(src),
FilePath::fromString(m_directory + QLatin1String("/AndroidManifest.xml")),
nullptr, [this, &addedFiles](QFileInfo src, QFileInfo dst, QString *){return copy(src, dst, &addedFiles);});
FilePath::fromString(m_directory
+ QLatin1String("/AndroidManifest.xml")),
nullptr,
copy);
} else {
const QString src = version->prefix().toString() + "/src/android/templates";
FileUtils::copyRecursively(FilePath::fromString(src),
FilePath::fromString(m_directory),
nullptr, [this, &addedFiles](QFileInfo src, QFileInfo dst, QString *){return copy(src, dst, &addedFiles);});
nullptr,
copy);
if (m_copyGradle) {
FilePath gradlePath = version->prefix().pathAppended("src/3rdparty/gradle");
if (!gradlePath.exists())
gradlePath = AndroidConfigurations::currentConfig().sdkLocation().pathAppended("/tools/templates/gradle/wrapper");
FileUtils::copyRecursively(gradlePath, FilePath::fromString(m_directory),
nullptr, [this, &addedFiles](QFileInfo src, QFileInfo dst, QString *){return copy(src, dst, &addedFiles);});
FileUtils::copyRecursively(gradlePath, FilePath::fromString(m_directory), nullptr, copy);
}
AndroidManager::updateGradleProperties(target, m_buildKey);
@@ -385,7 +329,7 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles()
QString androidPackageDir;
ProjectNode *node = target->project()->findNodeForBuildKey(m_buildKey);
if (node) {
node->addFiles(addedFiles);
node->addFiles(copy.files());
androidPackageDir = node->data(Android::Constants::AndroidPackageSourceDir).toString();
if (androidPackageDir.isEmpty()) {

View File

@@ -54,19 +54,11 @@ public:
ProjectExplorer::BuildSystem *buildSystem() const;
private:
enum CopyState {
Ask,
OverwriteAll,
SkipAll
};
bool copy(const QFileInfo &src, const QFileInfo &dst, QStringList *addedFiles);
void createAndroidManifestFile();
void createAndroidTemplateFiles();
ProjectExplorer::BuildSystem *m_buildSystem;
QString m_buildKey;
QString m_directory;
CopyState m_copyState;
bool m_copyGradle;
};

View File

@@ -40,6 +40,7 @@ add_qtc_plugin(AutoTest
gtest/gtesttreeitem.cpp gtest/gtesttreeitem.h
gtest/gtestvisitors.cpp gtest/gtestvisitors.h
iframeworksettings.h
itemdatacache.h
itestframework.cpp itestframework.h
itestparser.cpp itestparser.h
projectsettingswidget.cpp projectsettingswidget.h

View File

@@ -79,6 +79,7 @@ HEADERS += \
autotesticons.h \
autotestplugin.h \
iframeworksettings.h \
itemdatacache.h \
itestframework.h \
itestparser.h \
projectsettingswidget.h \

View File

@@ -37,6 +37,7 @@ QtcPlugin {
"autotestconstants.h",
"autotestplugin.cpp",
"autotestplugin.h",
"itemdatacache.h",
"projectsettingswidget.cpp",
"projectsettingswidget.h",
"testcodeparser.cpp",

View File

@@ -27,6 +27,7 @@
#include "catchconfiguration.h"
#include "catchframework.h"
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <utils/qtcassert.h>
@@ -38,14 +39,26 @@ QString CatchTreeItem::testCasesString() const
return m_state & CatchTreeItem::Parameterized ? QString(name() + " -*") : name();
}
static QString nonRootDisplayName(const CatchTreeItem *it)
{
if (it->type() != TestTreeItem::TestSuite)
return it->name();
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project)
return it->name();
TestTreeItem *parent = it->parentItem();
int baseDirSize = (parent->type() == TestTreeItem::GroupNode)
? parent->filePath().size() : project->projectDirectory().toString().size();
return it->name().mid(baseDirSize + 1);
}
QVariant CatchTreeItem::data(int column, int role) const
{
switch (role) {
case Qt::DisplayRole:
if (type() == Root)
break;
return QString(name() + stateSuffix());
return QString(nonRootDisplayName(this) + stateSuffix());
case Qt::CheckStateRole:
switch (type()) {
case Root:

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "testtreeitem.h"
#include <utils/optional.h>
#include <QVariantHash>
namespace Autotest {
namespace Internal {
template<class T>
class ItemDataCache
{
public:
void insert(TestTreeItem *item, const T &value) { m_cache[item->cacheName()] = {0, value}; }
void evolve()
{
auto it = m_cache.begin(), end = m_cache.end();
while (it != end)
it = it->generation++ >= maxGen ? m_cache.erase(it) : ++it;
}
Utils::optional<T> get(TestTreeItem *item)
{
auto entry = m_cache.find(item->cacheName());
if (entry == m_cache.end())
return Utils::nullopt;
entry->generation = 0;
return Utils::make_optional(entry->value);
};
void clear() { m_cache.clear(); }
bool isEmpty() const { return m_cache.isEmpty(); }
QVariantHash toSettings() const
{
QVariantHash result;
for (auto it = m_cache.cbegin(), end = m_cache.cend(); it != end; ++it)
result.insert(it.key(), QVariant::fromValue(it.value().value));
return result;
}
void fromSettings(const QVariantHash &stored)
{
m_cache.clear();
for (auto it = stored.cbegin(), end = stored.cend(); it != end; ++it)
m_cache[it.key()] = {0, qvariant_cast<T>(it.value())};
}
private:
static constexpr int maxGen = 10;
struct Entry
{
int generation = 0;
T value;
};
QHash<QString, Entry> m_cache;
};
} // namespace Internal
} // namespace Autotest

View File

@@ -151,7 +151,8 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
if (buildTargets.size() > 1 ) // there are multiple executables with the same build target
return; // let the user decide which one to run
const BuildTargetInfo targetInfo = buildTargets.first();
const BuildTargetInfo targetInfo = buildTargets.size() ? buildTargets.first()
: BuildTargetInfo();
// we might end up with an empty targetFilePath - e.g. when having a library we just link to
// there would be no BuildTargetInfo that could match

View File

@@ -25,10 +25,9 @@
#pragma once
#include "itemdatacache.h"
#include "testrunner.h"
#include "testtreemodel.h"
#include <coreplugin/inavigationwidgetfactory.h>
#include <utils/navigationtreeview.h>
@@ -49,8 +48,12 @@ class ProgressIndicator;
}
namespace Autotest {
class TestTreeModel;
namespace Internal {
class TestTreeSortFilterModel;
class TestTreeView;
class TestNavigationWidget : public QWidget

View File

@@ -35,6 +35,7 @@ namespace Internal {
static const char SK_ACTIVE_FRAMEWORKS[] = "AutoTest.ActiveFrameworks";
static const char SK_RUN_AFTER_BUILD[] = "AutoTest.RunAfterBuild";
static const char SK_CHECK_STATES[] = "AutoTest.CheckStates";
static Q_LOGGING_CATEGORY(LOG, "qtc.autotest.frameworkmanager", QtWarningMsg)
@@ -93,6 +94,7 @@ void TestProjectSettings::load()
const QVariant runAfterBuild = m_project->namedSettings(SK_RUN_AFTER_BUILD);
m_runAfterBuild = runAfterBuild.isValid() ? RunAfterBuildMode(runAfterBuild.toInt())
: RunAfterBuildMode::None;
m_checkStateCache.fromSettings(m_project->namedSettings(SK_CHECK_STATES).toHash());
}
void TestProjectSettings::save()
@@ -104,6 +106,8 @@ void TestProjectSettings::save()
activeFrameworks.insert(it.key()->id().toString(), it.value());
m_project->setNamedSettings(SK_ACTIVE_FRAMEWORKS, activeFrameworks);
m_project->setNamedSettings(SK_RUN_AFTER_BUILD, int(m_runAfterBuild));
if (!m_checkStateCache.isEmpty())
m_project->setNamedSettings(SK_CHECK_STATES, m_checkStateCache.toSettings());
}
} // namespace Internal

View File

@@ -26,6 +26,7 @@
#pragma once
#include "testsettings.h"
#include "testtreemodel.h"
#include <projectexplorer/project.h>
@@ -50,6 +51,7 @@ public:
{ m_activeTestFrameworks = enabledFrameworks; }
QMap<ITestFramework *, bool> activeFrameworks() const { return m_activeTestFrameworks; }
void activateFramework(const Utils::Id &id, bool activate);
Internal::ItemDataCache<Qt::CheckState> *checkStateCache() { return &m_checkStateCache; }
private:
void load();
void save();
@@ -58,6 +60,7 @@ private:
bool m_useGlobalSettings = true;
RunAfterBuildMode m_runAfterBuild = RunAfterBuildMode::None;
QMap<ITestFramework *, bool> m_activeTestFrameworks;
Internal::ItemDataCache<Qt::CheckState> m_checkStateCache;
};
} // namespace Internal

Some files were not shown because too many files have changed in this diff Show More