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 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 2. Build and install LLVM/Clang
@@ -278,7 +278,7 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
For Windows: For Windows:
cmake ^ cmake ^
-G "NMake Makefiles JOM" ^ -G Ninja ^
-D CMAKE_BUILD_TYPE=Release ^ -D CMAKE_BUILD_TYPE=Release ^
-D LLVM_ENABLE_RTTI=ON ^ -D LLVM_ENABLE_RTTI=ON ^
-D LLVM_ENABLE_PROJECTS="clang;clang-tools-extra" ^ -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 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. 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) unset(yaml_cpp_include_dir CACHE)
find_path(yaml_cpp_include_dir yaml-cpp/yaml.h) find_path(yaml_cpp_include_dir yaml-cpp/yaml.h)
endif() 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() else()
set(yaml-cpp_FOUND 1) set(yaml-cpp_FOUND 1)
set_package_properties(yaml-cpp PROPERTIES DESCRIPTION "using internal src/libs/3rdparty/yaml-cpp") 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 editor tool button for `Analyze File` (QTCREATORBUG-23348)
* Added `Add forward declaration` refactoring action (QTCREATORBUG-23444) * Added `Add forward declaration` refactoring action (QTCREATORBUG-23444)
* Extended `Add Include` refactoring action to non-Qt classes (QTCREATORBUG-21) * 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 C++11 list initialization (QTCREATORBUG-16977, QTCREATORBUG-24035)
* Fixed indentation with trailing return types (QTCREATORBUG-23502) * Fixed indentation with trailing return types (QTCREATORBUG-23502)
* Fixed issue with `std::chrono::time_point` (QTCREATORBUG-24067) * Fixed issue with `std::chrono::time_point` (QTCREATORBUG-24067)
@@ -69,6 +70,7 @@ Editing
### Python ### Python
* Added tool button for opening interactive Python, optionally importing current file * Added tool button for opening interactive Python, optionally importing current file
* Fixed highlighting of parentheses
### Diff Viewer ### Diff Viewer
@@ -121,6 +123,7 @@ Debugging
--------- ---------
* Added option to reset all formats for watches to default * Added option to reset all formats for watches to default
* Added option to override sysroot setting when starting or attaching to external application
Analyzer Analyzer
-------- --------
@@ -130,6 +133,7 @@ Analyzer
* Re-added editor text marks for diagnostics (QTCREATORBUG-23349) * Re-added editor text marks for diagnostics (QTCREATORBUG-23349)
* Changed to use separate `clazy-standalone` executable * Changed to use separate `clazy-standalone` executable
* Fixed issue with `clang-tidy` and `WarningsAsErrors` (QTCREATORBUG-23423) * Fixed issue with `clang-tidy` and `WarningsAsErrors` (QTCREATORBUG-23423)
* Fixed output parsing of `clazy`
Version Control Systems Version Control Systems
----------------------- -----------------------
@@ -142,7 +146,7 @@ Version Control Systems
Test Integration Test Integration
---------------- ----------------
* Added support for Catch test framework (QTCREATORBUG-19740) * Added support for Catch2 test framework (QTCREATORBUG-19740)
### Google Test ### Google Test
@@ -163,6 +167,7 @@ Platforms
* Removed Ministro deployment option (QTCREATORBUG-23761) * Removed Ministro deployment option (QTCREATORBUG-23761)
* Added service editor to manifest editor (QTCREATORBUG-23937) * Added service editor to manifest editor (QTCREATORBUG-23937)
* Added splash screen editor to manifest editor (QTCREATORBUG-24011, QTCREATORBUG-24013) * 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 debugging on x86 and armv7 architectures (QTCREATORBUG-24191)
* Fixed issue with long kit names (QTBUG-83875) * 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 The packages are deployed on the connected Android devices. To switch the
device used as a default device for the selected kit, select 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. > \uicontrol {Reset Default Devices}. The setting applies until you restart \QC.
For more information, see \l{Selecting Android Devices}. For more information, see \l{Selecting Android Devices}.

View File

@@ -75,6 +75,10 @@
\endlist \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 \section1 Viewing the Changes
\image creator-diff-editor.png "Diff editor output in the Edit mode" \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 Select \uicontrol {Add Files} to locate and add individual
files. 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 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 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, 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)) clangbindirtarget))
resourcetarget = os.path.join(clanglibdirtarget, 'clang') resourcetarget = os.path.join(clanglibdirtarget, 'clang')
else: else:
# libclang -> Qt Creator libraries
libsources = glob(os.path.join(llvm_install_dir, 'lib', 'libclang.so*')) libsources = glob(os.path.join(llvm_install_dir, 'lib', 'libclang.so*'))
for libsource in libsources: for libsource in libsources:
deployinfo.append((libsource, os.path.join(install_dir, 'lib', 'qtcreator'))) deployinfo.append((libsource, os.path.join(install_dir, 'lib', 'qtcreator')))
clangbinary = os.path.join(llvm_install_dir, 'bin', 'clang') # clang binaries -> clang libexec
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')
clangbinary_targetdir = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'bin') clangbinary_targetdir = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'bin')
if not os.path.exists(clangbinary_targetdir): if not os.path.exists(clangbinary_targetdir):
os.makedirs(clangbinary_targetdir) os.makedirs(clangbinary_targetdir)
deployinfo.append((clangbinary, clangbinary_targetdir)) for binary in ['clang', 'clangd', 'clang-tidy', 'clazy-standalone']:
deployinfo.append((clangdbinary, clangbinary_targetdir)) binary_filepath = os.path.join(llvm_install_dir, 'bin', binary)
deployinfo.append((clangtidybinary, clangbinary_targetdir)) deployinfo.append((binary_filepath, clangbinary_targetdir))
deployinfo.append((clazybinary, clangbinary_targetdir)) # add link target if binary is actually a symlink (to a binary in the same directory)
# copy link target if clang is actually a symlink if os.path.islink(binary_filepath):
if os.path.islink(clangbinary): linktarget = os.readlink(binary_filepath)
linktarget = os.readlink(clangbinary) deployinfo.append((os.path.join(os.path.dirname(binary_filepath), linktarget),
deployinfo.append((os.path.join(os.path.dirname(clangbinary), linktarget), os.path.join(clangbinary_targetdir, 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') resourcetarget = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'lib', 'clang')
print("copying libclang...") print("copying libclang...")
@@ -281,10 +285,15 @@ def deploy_libclang(install_dir, llvm_install_dir, chrpath_bin):
if common.is_linux_platform(): if common.is_linux_platform():
# libclang was statically compiled, so there is no need for the RPATHs # libclang was statically compiled, so there is no need for the RPATHs
# and they are confusing when fixing RPATHs later in the process # and they are confusing when fixing RPATHs later in the process.
print("removing libclang RPATHs...") # Also fix clazy-standalone RPATH.
print("fixing Clang RPATHs...")
for source, target in deployinfo: 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)) targetfilepath = target if not os.path.isdir(target) else os.path.join(target, os.path.basename(source))
subprocess.check_call([chrpath_bin, '-d', targetfilepath]) subprocess.check_call([chrpath_bin, '-d', targetfilepath])

View File

@@ -133,6 +133,8 @@ if [ $LLVM_INSTALL_DIR ]; then
mkdir -p "$libexec_path/clang/lib" 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/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/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 clangsource="$LLVM_INSTALL_DIR"/bin/clang
clanglinktarget="$(readlink "$clangsource")" clanglinktarget="$(readlink "$clangsource")"
cp -Rf "$clangsource" "$libexec_path/clang/bin/" || exit 1 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 cp -Rf "$clangtidysource" "$libexec_path/clang/bin/" || exit 1
clazysource="$LLVM_INSTALL_DIR"/bin/clazy-standalone clazysource="$LLVM_INSTALL_DIR"/bin/clazy-standalone
cp -Rf "$clazysource" "$libexec_path/clang/bin/" || exit 1 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 fi
clangbackendArgument="-executable=$libexec_path/clangbackend" clangbackendArgument="-executable=$libexec_path/clangbackend"
clangpchmanagerArgument="-executable=$libexec_path/clangpchmanagerbackend" clangpchmanagerArgument="-executable=$libexec_path/clangpchmanagerbackend"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -170,7 +170,7 @@ Node {
scale: Qt.vector3d(0.024, 0.024, 0.024) scale: Qt.vector3d(0.024, 0.024, 0.024)
materials: DefaultMaterial { materials: DefaultMaterial {
id: material id: material
emissiveColor: highlightOnHover diffuseColor: highlightOnHover
&& (centerMouseArea.hovering || centerMouseArea.dragging) && (centerMouseArea.hovering || centerMouseArea.dragging)
? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1)) ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1))
: 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) scale: Qt.vector3d(0.020, 0.020, 0.020)
materials: DefaultMaterial { materials: DefaultMaterial {
id: material id: material
emissiveColor: scaleRod.color diffuseColor: scaleRod.color
lighting: DefaultMaterial.NoLighting lighting: DefaultMaterial.NoLighting
} }
} }

View File

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

View File

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

View File

@@ -23,15 +23,11 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.1 import QtQuick 2.15
import QtQuick.Controls 1.1 import QtQuick.Layouts 1.15
import QtQuick.Controls.Styles 1.0
import "../common"
import QtQuick.Layouts 1.0
import HelperWidgets 2.0
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioTheme 1.0 as StudioTheme
/* The view displaying the item grid. /* The view displaying the item grid.
@@ -65,9 +61,6 @@ ScrollView {
Item { Item {
id: styleConstants id: styleConstants
readonly property color backgroundColor: Theme.qmlDesignerBackgroundColorDarkAlternate()
readonly property color lighterBackgroundColor: Theme.color(Theme.FancyToolBarSeparatorColor)
property int textWidth: 58 property int textWidth: 58
property int textHeight: Theme.smallFontPixelSize() * 2 property int textHeight: Theme.smallFontPixelSize() * 2
@@ -81,48 +74,37 @@ ScrollView {
2 * cellVerticalMargin + cellVerticalSpacing 2 * cellVerticalMargin + cellVerticalSpacing
} }
Rectangle { Column {
id: background id: column
anchors.fill: parent Repeater {
color: styleConstants.backgroundColor 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
} Repeater {
model: sectionEntries
Flickable { delegate: ItemDelegate {
contentHeight: column.height visible: itemVisible
Column { width: styleConstants.cellWidth + itemGrid.flexibleWidth
id: column height: styleConstants.cellHeight
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
}
} }
} }
} }
} }
} }
} }
} }

View File

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

View File

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

View File

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

View File

@@ -23,10 +23,11 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.0 import QtQuick 2.15
import HelperWidgets 2.0 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
@@ -35,14 +36,15 @@ Rectangle {
width: 320 width: 320
height: 400 height: 400
color: Theme.qmlDesignerBackgroundColorDarkAlternate() color: Theme.qmlDesignerBackgroundColorDarkAlternate()
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: forceActiveFocus() onClicked: forceActiveFocus()
} }
ScrollView { ScrollView {
clip: true
anchors.fill: parent anchors.fill: parent
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
Column { Column {
y: -1 y: -1
@@ -57,7 +59,6 @@ Rectangle {
SectionLayout { SectionLayout {
Label { Label {
text: qsTr("Type") text: qsTr("Type")
} }
SecondColumnLayout { SecondColumnLayout {
@@ -65,15 +66,12 @@ Rectangle {
RoundedPanel { RoundedPanel {
Layout.fillWidth: true Layout.fillWidth: true
height: 24 height: StudioTheme.Values.height
Label { Label {
x: 6
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 16 anchors.leftMargin: StudioTheme.Values.inputHorizontalPadding
text: backendValues.className.value text: backendValues.className.value
verticalAlignment: Text.AlignVCenter
} }
ToolTipArea { ToolTipArea {
anchors.fill: parent anchors.fill: parent
@@ -87,10 +85,10 @@ Rectangle {
} }
ExpressionTextField { ExpressionTextField {
z: 2
id: typeLineEdit id: typeLineEdit
z: 2
completeOnlyTypes: true completeOnlyTypes: true
replaceCurrentTextByCompletion: true
anchors.fill: parent anchors.fill: parent
visible: false visible: false
@@ -98,10 +96,26 @@ Rectangle {
showButtons: false showButtons: false
fixedSize: true fixedSize: true
property bool blockEditingFinished: false
onEditingFinished: { onEditingFinished: {
if (visible) if (typeLineEdit.blockEditingFinished)
return
typeLineEdit.blockEditingFinished = true
if (typeLineEdit.visible)
changeTypeName(typeLineEdit.text.trim()) 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 { SecondColumnLayout {
spacing: 2
LineEdit { LineEdit {
id: lineEdit id: lineEdit
@@ -129,29 +144,55 @@ Rectangle {
showExtendedFunctionButton: false showExtendedFunctionButton: false
enabled: !modelNodeBackend.multiSelection enabled: !modelNodeBackend.multiSelection
} }
// workaround: without this item the lineedit does not shrink to the
// right size after resizing to a wider width
Image { Rectangle {
visible: !modelNodeBackend.multiSelection id: aliasIndicator
Layout.preferredWidth: 20 color: "transparent"
Layout.preferredHeight: 20 border.color: "transparent"
horizontalAlignment: Image.AlignHCenter implicitWidth: StudioTheme.Values.height
verticalAlignment: Image.AlignVCenter implicitHeight: StudioTheme.Values.height
source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked" 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 { ToolTipArea {
id: toolTipArea
enabled: !modelNodeBackend.multiSelection enabled: !modelNodeBackend.multiSelection
anchors.fill: parent anchors.fill: parent
onClicked: toogleExportAlias() onClicked: toogleExportAlias()
tooltip: qsTr("Exports this item as an alias property of the root item.") 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 { Label {
@@ -280,7 +321,6 @@ Rectangle {
Item { Item {
width: 10 width: 10
height: 10 height: 10
} }
CheckBox { CheckBox {
@@ -319,88 +359,92 @@ Rectangle {
width: 4 width: 4
} }
TabView { StudioControls.TabBar {
id: tabBar
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right 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 height: currentHeight + extraHeight
property int currentHeight: getTab(currentIndex).item.implicitHeight Column {
property int extraHeight: 40 anchors.left: parent.left
anchors.right: parent.right
Tab { Loader {
title: backendValues.className.value 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.left: parent.left
anchors.right: parent.right anchors.right: parent.right
Loader { id: specificsOne;
anchors.left: parent.left source: specificsUrl;
anchors.right: parent.right
visible: theSource !== ""
id: specificsTwo; property int loaderHeight: specificsOne.item.height + tabView.extraHeight
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
}
} }
} }
Tab { Column {
title: qsTr("Layout") anchors.left: parent.left
component: Column { anchors.right: parent.right
anchors.left: parent.left
anchors.right: parent.right
LayoutSection { LayoutSection {
} }
MarginSection { MarginSection {
visible: anchorBackend.isInLayout visible: anchorBackend.isInLayout
backendValueTopMargin: backendValues.Layout_topMargin backendValueTopMargin: backendValues.Layout_topMargin
backendValueBottomMargin: backendValues.Layout_bottomMargin backendValueBottomMargin: backendValues.Layout_bottomMargin
backendValueLeftMargin: backendValues.Layout_leftMargin backendValueLeftMargin: backendValues.Layout_leftMargin
backendValueRightMargin: backendValues.Layout_rightMargin backendValueRightMargin: backendValues.Layout_rightMargin
backendValueMargins: backendValues.Layout_margins backendValueMargins: backendValues.Layout_margins
} }
AlignDistributeSection { AlignDistributeSection {
visible: !anchorBackend.isInLayout visible: !anchorBackend.isInLayout
}
} }
} }
Tab { Column {
anchors.fill: parent anchors.left: parent.left
title: qsTr("Advanced") anchors.right: parent.right
component: Column {
anchors.left: parent.left
anchors.right: parent.right
AdvancedSection { AdvancedSection {
} }
LayerSection { LayerSection {
}
} }
} }
} }

View File

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

View File

@@ -23,10 +23,11 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.0 import QtQuick 2.15
import HelperWidgets 2.0
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioTheme 1.0 as StudioTheme
Rectangle { Rectangle {
id: itemPane id: itemPane
@@ -43,6 +44,7 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
Column { Column {
id: rootColumn
y: -1 y: -1
width: itemPane.width width: itemPane.width
Section { Section {
@@ -54,7 +56,6 @@ Rectangle {
SectionLayout { SectionLayout {
Label { Label {
text: qsTr("Type") text: qsTr("Type")
} }
SecondColumnLayout { SecondColumnLayout {
@@ -62,15 +63,12 @@ Rectangle {
RoundedPanel { RoundedPanel {
Layout.fillWidth: true Layout.fillWidth: true
height: 24 height: StudioTheme.Values.height
Label { Label {
x: 6
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 16 anchors.leftMargin: StudioTheme.Values.inputHorizontalPadding
text: backendValues.className.value text: backendValues.className.value
verticalAlignment: Text.AlignVCenter
} }
ToolTipArea { ToolTipArea {
anchors.fill: parent anchors.fill: parent
@@ -87,7 +85,7 @@ Rectangle {
z: 2 z: 2
id: typeLineEdit id: typeLineEdit
completeOnlyTypes: true completeOnlyTypes: true
replaceCurrentTextByCompletion: true
anchors.fill: parent anchors.fill: parent
visible: false visible: false
@@ -95,17 +93,33 @@ Rectangle {
showButtons: false showButtons: false
fixedSize: true fixedSize: true
property bool blockEditingFinished: false
onEditingFinished: { onEditingFinished: {
if (visible) if (typeLineEdit.blockEditingFinished)
return
typeLineEdit.blockEditingFinished = true
if (typeLineEdit.visible)
changeTypeName(typeLineEdit.text.trim()) 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 { Item {
Layout.preferredWidth: 16 Layout.preferredWidth: 20
Layout.preferredHeight: 16 Layout.preferredHeight: 20
} }
} }
@@ -114,6 +128,7 @@ Rectangle {
} }
SecondColumnLayout { SecondColumnLayout {
spacing: 2
LineEdit { LineEdit {
id: lineEdit id: lineEdit
@@ -127,12 +142,48 @@ Rectangle {
enabled: !modelNodeBackend.multiSelection enabled: !modelNodeBackend.multiSelection
} }
Image { Rectangle {
visible: !modelNodeBackend.multiSelection id: aliasIndicator
Layout.preferredWidth: 16 color: "transparent"
Layout.preferredHeight: 16 border.color: "transparent"
source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked" 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 { ToolTipArea {
id: toolTipArea
enabled: !modelNodeBackend.multiSelection enabled: !modelNodeBackend.multiSelection
anchors.fill: parent anchors.fill: parent
onClicked: toogleExportAlias() onClicked: toogleExportAlias()
@@ -148,69 +199,30 @@ Rectangle {
width: 4 width: 4
} }
TabView { Column {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
frameVisible: false Loader {
id: specificsTwo
anchors.left: parent.left
anchors.right: parent.right
visible: theSource !== ""
sourceComponent: specificQmlComponent
id: tabView property string theSource: specificQmlData
height: Math.max(layoutSectionHeight, specficsHeight)
property int layoutSectionHeight: 400 onTheSourceChanged: {
property int specficsOneHeight: 0 active = false
property int specficsTwoHeight: 0 active = true
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
}
}
} }
} }
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 buttonIcon: StudioTheme.Constants.centerVertical
tooltip: qsTr("Anchor item vertically.") tooltip: qsTr("Anchor item vertically.")
property bool verticalCentered: anchorBackend.verticalCentered; property bool verticalCentered: anchorBackend.verticalCentered
onVerticalCenteredChanged: { onVerticalCenteredChanged: {
checked = verticalCentered checked = verticalCentered
} }
@@ -179,7 +179,7 @@ StudioControls.ButtonRow {
buttonIcon: StudioTheme.Constants.centerHorizontal buttonIcon: StudioTheme.Constants.centerHorizontal
tooltip: qsTr("Anchor item horizontally.") tooltip: qsTr("Anchor item horizontally.")
property bool horizontalCentered: anchorBackend.horizontalCentered; property bool horizontalCentered: anchorBackend.horizontalCentered
onHorizontalCenteredChanged: { onHorizontalCenteredChanged: {
checked = horizontalCentered 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/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -23,48 +23,79 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.1 import QtQuick 2.15
import QtQuick.Controls 1.1 as Controls import QtQuick.Templates 2.15 as T
import QtQuick.Controls.Styles 1.1 import StudioTheme 1.0 as StudioTheme
import "Constants.js" as Constants
Controls.Button { T.AbstractButton {
property color borderColor: "#222" id: myButton
property color highlightColor: "orange"
property color textColor: "#eee" implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
style: ButtonStyle { implicitContentWidth + leftPadding + rightPadding)
label: Text { implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
color: Constants.colorsDefaultText implicitContentHeight + topPadding + bottomPadding)
anchors.fill: parent
renderType: Text.NativeRendering background: Rectangle {
verticalAlignment: Text.AlignVCenter id: buttonBackground
horizontalAlignment: Text.AlignHCenter implicitWidth: 100
text: control.text implicitHeight: 23
opacity: enabled ? 1 : 0.7 radius: 3
} color: StudioTheme.Values.themeControlBackground
background: Rectangle { border.color: StudioTheme.Values.themeControlOutline
implicitWidth: 100 border.width: StudioTheme.Values.border
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
}
}
} }
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 2.15
import QtQuick.Controls 1.0 as Controls import QtQuick.Layouts 1.15
import QtQuick.Layouts 1.0
import QtQuick.Controls.Private 1.0
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
Item { Item {

View File

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

View File

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

View File

@@ -23,13 +23,14 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.1 import QtQuick 2.15
import "Constants.js" as Constants import QtQuick.Window 2.15
import StudioControls 1.0 as StudioControls import QtQuick.Controls 2.15
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
StudioControls.TextField { StudioControls.TextField {
id: textField id: textField
signal rejected signal rejected
@@ -38,103 +39,199 @@ StudioControls.TextField {
actionIndicator.visible: false actionIndicator.visible: false
property bool completeOnlyTypes: false property bool completeOnlyTypes: false
property bool completionActive: listView.model !== null
property bool completionActive: listView.count > 0
property bool dotCompletion: false property bool dotCompletion: false
property int dotCursorPos: 0 property int dotCursorPos: 0
property string prefix property string prefix
property alias showButtons: buttonrow.visible property alias showButtons: buttonrow.visible
property bool fixedSize: false property bool fixedSize: false
property bool replaceCurrentTextByCompletion: false
property alias completionList: listView
function commitCompletion() { function commitCompletion() {
var cursorPos = textField.cursorPosition if (replaceCurrentTextByCompletion) {
textField.text = listView.currentItem.text
var string = textField.text } else {
var before = string.slice(0, cursorPos - textField.prefix.length) var cursorPos = textField.cursorPosition
var after = string.slice(cursorPos) var string = textField.text
var before = string.slice(0, cursorPos - textField.prefix.length)
textField.text = before + listView.currentItem.text + after var after = string.slice(cursorPos)
textField.cursorPosition = cursorPos + listView.currentItem.text.length - prefix.length
textField.text = before + listView.currentItem.text + after
textField.cursorPosition = cursorPos + listView.currentItem.text.length - prefix.length
}
listView.model = null listView.model = null
} }
ListView { Popup {
id: listView 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 visible: textField.completionActive
delegate: Text {
text: modelData onClosed: listView.model = null
color: Theme.color(Theme.PanelTextColorLight)
Rectangle { contentItem: ListView {
visible: index === listView.currentIndex id: listView
z: -1 clip: true
anchors.fill: parent implicitHeight: contentHeight
color: Theme.qmlDesignerBackgroundColorDarkAlternate() 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 background: Rectangle {
anchors.topMargin: 26 color: StudioTheme.Values.themeControlBackground
anchors.bottomMargin: textField.fixedSize ? -180 : 12 border.color: StudioTheme.Values.themeInteraction
anchors.bottom: parent.bottom border.width: StudioTheme.Values.border
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
}
] enter: Transition {
}
exit: Transition {
}
} }
verticalAlignment: Text.AlignTop verticalAlignment: Text.AlignTop
onPressed: listView.model = null
Keys.priority: Keys.BeforeItem Keys.priority: Keys.BeforeItem
Keys.onPressed: { 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 textField.dotCursorPos = textField.cursorPosition + 1
var list = autoComplete(textField.text+".", textField.dotCursorPos, false, textField.completeOnlyTypes) text = textField.text + "."
textField.prefix = list.pop() pos = textField.dotCursorPos
listView.model = list; explicitComplete = false
textField.dotCompletion = true textField.dotCompletion = true
} else { break
if (textField.completionActive) {
var list2 = autoComplete(textField.text + event.text, case Qt.Key_Right:
textField.cursorPosition + event.text.length, if (!textField.completionActive)
true, textField.completeOnlyTypes) return
textField.prefix = list2.pop()
listView.model = list2; 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: { Keys.onSpacePressed: {
if (event.modifiers & Qt.ControlModifier) { if (event.modifiers & Qt.ControlModifier) {
var list = autoComplete(textField.text, textField.cursorPosition, true, textField.completeOnlyTypes) var list = autoComplete(textField.text, textField.cursorPosition, true, textField.completeOnlyTypes)
textField.prefix = list.pop() textField.prefix = textField.text.substring(0, textField.cursorPosition)
listView.model = list; if (list.length && list[list.length - 1] === textField.prefix)
list.pop()
listView.model = list
textField.dotCompletion = false textField.dotCompletion = false
event.accepted = true; event.accepted = true;
if (list.length == 1)
textField.commitCompletion()
} else { } else {
event.accepted = false event.accepted = false
} }

View File

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

View File

@@ -23,12 +23,11 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.11 import QtQuick 2.15
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.15
import QtQuick.Dialogs 1.3 import QtQuick.Dialogs 1.3
import HelperWidgets 2.0
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
@@ -76,49 +75,52 @@ Dialog {
anchors.margins: 13 anchors.margins: 13
anchors.bottomMargin: 71 anchors.bottomMargin: 71
TabView { StudioControls.TabBar {
id: presetTabView id: presetTabBar
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
Layout.fillHeight: true
Layout.fillWidth: true
Tab { anchors.left: parent.left
title: qsTr("System Presets") anchors.right: parent.right
anchors.fill: parent
GradientPresetTabContent { StudioControls.TabButton {
id: defaultTabContent text: qsTr("System Presets")
viewModel: defaultPresetListModel }
editableName: false 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 { GradientPresetTabContent {
title: qsTr("User Presets") id: customTabContent
anchors.fill: parent viewModel: customPresetListModel
editableName: true
onPresetNameChanged: customPresetListModel.changePresetName(id, name)
GradientPresetTabContent { property int deleteId
id: customTabContent
viewModel: customPresetListModel
editableName: true
onPresetNameChanged: customPresetListModel.changePresetName(id, name)
property int deleteId onDeleteButtonClicked: {
deleteId = id
deleteDialog.open()
}
onDeleteButtonClicked: { MessageDialog {
deleteId = id id: deleteDialog
deleteDialog.open() visible: false
} modality: Qt.WindowModal
standardButtons: Dialog.No | Dialog.Yes
MessageDialog { title: qsTr("Delete preset?")
id: deleteDialog text: qsTr("Are you sure you want to delete this preset?")
visible: false onAccepted: customPresetListModel.deletePreset(customTabContent.deleteId)
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 2.15
import QtQuick.Layouts 1.12 import QtQuick.Controls 2.15
import QtQuick.Dialogs 1.3 import QtQuick.Layouts 1.15
import HelperWidgets 2.0
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
@@ -48,271 +47,277 @@ Rectangle {
property real delegateHeight: 178 property real delegateHeight: 178
property real gridCellWidth: 160 property real gridCellWidth: 160
ScrollView { GridView {
id: gradientTable
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 10
clip: true
delegate: gradientDelegate
GridView { property int gridColumns: width / tabBackground.gridCellWidth;
id: gradientTable cellWidth: width / gridColumns
Layout.fillWidth: true cellHeight: 185
Layout.fillHeight: true
anchors.fill: parent
anchors.leftMargin: 10
clip: true
delegate: gradientDelegate
property int gridColumns: width / tabBackground.gridCellWidth; property bool bothVisible: horizontal.scrollBarVisible && vertical.scrollBarVisible
cellWidth: width / gridColumns
cellHeight: 185
Component { ScrollBar.horizontal: HorizontalScrollBar {
id: gradientDelegate id: horizontal
parent: gradientTable
}
Rectangle { ScrollBar.vertical: VerticalScrollBar {
id: backgroundCard id: vertical
color: StudioTheme.Values.themeControlOutline parent: gradientTable
clip: true }
property real flexibleWidth: (gradientTable.width - gradientTable.cellWidth * gradientTable.gridColumns) / gradientTable.gridColumns Component {
property bool isSelected: false id: gradientDelegate
width: gradientTable.cellWidth + flexibleWidth - 8 Rectangle {
height: tabBackground.delegateHeight id: backgroundCard
radius: 16 color: StudioTheme.Values.themeControlOutline
clip: true
function selectPreset(index) { property real flexibleWidth: (gradientTable.width - gradientTable.cellWidth * gradientTable.gridColumns) / gradientTable.gridColumns
gradientTable.currentIndex = index property bool isSelected: false
gradientData.stops = stopsPosList
gradientData.colors = stopsColorList
gradientData.stopsCount = stopListSize
gradientData.presetID = presetID
gradientData.presetType = presetTabView.currentIndex
if (gradientData.selectedItem != null) width: gradientTable.cellWidth + flexibleWidth - 8
gradientData.selectedItem.isSelected = false height: tabBackground.delegateHeight
radius: 16
backgroundCard.isSelected = true function selectPreset(index) {
gradientData.selectedItem = backgroundCard 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 { states: [
id: rectMouseArea State {
anchors.fill: parent name: "default"
hoverEnabled: true when: !(rectMouseArea.containsMouse || removeButton.hovered ||
onClicked: { (nameMouseArea.containsMouse && !tabBackground.editableName)) &&
presetNameBox.edit = false !backgroundCard.isSelected
nameInput.focus = false PropertyChanges {
backgroundCard.selectPreset(index) 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: [ Item {
State { id: presetNameBox
name: "default" Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
when: !(rectMouseArea.containsMouse || removeButton.hovered || Layout.preferredWidth: backgroundCard.width - 2
(nameMouseArea.containsMouse && !tabBackground.editableName)) && Layout.preferredHeight: backgroundCard.height - gradientRect.height - 4
!backgroundCard.isSelected Layout.bottomMargin: 4
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 { property bool edit: false
spacing: 2
anchors.fill: parent
Rectangle { Rectangle {
id: gradientRect id: nameBackgroundColor
width: 150 enabled: tabBackground.editableName
height: 150 color: "transparent"
radius: 16 radius: 16
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter visible: true
Layout.topMargin: 2 anchors.fill: parent
}
gradient: Gradient { ToolTipArea {
id: showGr id: nameMouseArea
} anchors.fill: parent
tooltip: nameText.text
propagateComposedEvents: true
Component { onClicked: {
id: stopComponent if (!tabBackground.editableName) {
GradientStop {} backgroundCard.selectPreset(index)
} return
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 { presetNameBox.edit = true
id: removeButton nameInput.forceActiveFocus()
visible: editableName && (rectMouseArea.containsMouse || removeButton.hovered) // have to select text like this, otherwise there is an issue with long names
backgroundRadius: StudioTheme.Values.smallRectWidth nameInput.cursorPosition = 0
anchors.right: parent.right nameInput.cursorPosition = nameInput.length
anchors.rightMargin: 5 nameInput.selectAll()
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)
} }
} }
Item { Text {
id: presetNameBox id: nameText
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter text: presetName
Layout.preferredWidth: backgroundCard.width - 2 anchors.fill: parent
Layout.preferredHeight: backgroundCard.height - gradientRect.height - 4 horizontalAlignment: Text.AlignHCenter
Layout.bottomMargin: 4 verticalAlignment: Text.AlignVCenter
color: StudioTheme.Values.themeTextColor
property bool edit: false elide: Text.ElideMiddle
maximumLineCount: 1
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 }
}
]
} }
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/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -23,25 +23,29 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.2 import QtQuick 2.15
import QtQuick.Controls 1.1 import QtQuick.Controls 2.15
import QtQuick.Controls.Styles 1.1 import StudioTheme 1.0 as StudioTheme
import QtQuickDesignerTheme 1.0
TextFieldStyle { ScrollBar {
selectionColor: Theme.color(Theme.PanelTextColorLight) id: scrollBar
selectedTextColor: Theme.color(Theme.PanelTextColorDark)
textColor: Theme.color(Theme.PanelTextColorLight)
placeholderTextColor: Theme.color(Theme.PanelTextColorMid)
padding.top: 4 property bool scrollBarVisible: parent.childrenRect.width > parent.width
padding.bottom: 4
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 { background: Rectangle {
implicitWidth: 100 color: StudioTheme.Values.themeSectionHeadBackground
implicitHeight: font.pixelSize + padding.top + padding.bottom }
color: Theme.color(Theme.FancyToolButtonSelectedColor)
border.color: Theme.qmlDesignerBackgroundColorDarker() 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 2.15
import QtQuick.Controls 2.0 as Controls import HelperWidgets 2.0
import QtQuick.Layouts 1.0 import StudioTheme 1.0 as StudioTheme
Item { Label {
id: label id: myLabel
width: parent.width < 300 ? 80 : Math.min(140, parent.width - 220)
height: 16
property alias source: image.source
Item { property alias icon: myLabel.text
width: 16
height: 16
Image {
id: image
anchors.fill: parent
}
} text: StudioTheme.Constants.actionIcon
font.family: StudioTheme.Constants.iconFont.family
Layout.preferredWidth: width font.pixelSize: StudioTheme.Values.myIconFontSize
Layout.minimumWidth: width
Layout.maximumWidth: width
// Component.onCompleted: {
// label.Layout.preferredWidth = width
// }
} }

View File

@@ -23,13 +23,37 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.1 import QtQuick 2.15
import QtQuick.Controls 1.0 as Controls import QtQuick.Controls 2.15
import "../../../common/" import StudioTheme 1.0 as StudioTheme
Controls.ScrollView { Flickable {
style: DesignerScrollViewStyle { 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/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -23,9 +23,29 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.1 import QtQuick 2.15
import QtQuick.Controls 1.0 as Controls 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 DoubleSpinBox 2.0 DoubleSpinBox.qml
SpinBox 2.0 SpinBox.qml SpinBox 2.0 SpinBox.qml
StandardTextSection 2.0 StandardTextSection.qml StandardTextSection 2.0 StandardTextSection.qml
Tab 2.0 Tab.qml
TabView 2.0 TabView.qml
ToolTipArea 2.0 ToolTipArea.qml ToolTipArea 2.0 ToolTipArea.qml
UrlChooser 2.0 UrlChooser.qml UrlChooser 2.0 UrlChooser.qml
PaddingSection 2.0 PaddingSection.qml PaddingSection 2.0 PaddingSection.qml
RoundedPanel 2.0 RoundedPanel.qml RoundedPanel 2.0 RoundedPanel.qml
ExpressionTextField 2.0 ExpressionTextField.qml ExpressionTextField 2.0 ExpressionTextField.qml
MarginSection 2.0 MarginSection.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 color: StudioTheme.Values.themeHoverHighlight
border.color: StudioTheme.Values.themeControlOutline border.color: StudioTheme.Values.themeControlOutline
} }
}, },
State { State {
name: "edit" name: "edit"

View File

@@ -46,8 +46,7 @@ T.CheckBox {
implicitWidth: Math.max( implicitWidth: Math.max(
implicitBackgroundWidth + leftInset + rightInset, implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding implicitContentWidth + leftPadding + rightPadding)
+ implicitIndicatorWidth + spacing + actionIndicator.width)
implicitHeight: Math.max( implicitHeight: Math.max(
implicitBackgroundHeight + topInset + bottomInset, implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding, 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/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -23,38 +23,33 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.2 import QtQuick 2.15
import QtQuick.Controls 1.1 import QtQuick.Templates 2.15 as T
import QtQuick.Controls.Styles 1.1 import StudioTheme 1.0 as StudioTheme
import QtQuickDesignerTheme 1.0
ScrollViewStyle { T.TabBar {
readonly property color scrollbarColor: Theme.color(Theme.BackgroundColorDark) id: myButton
readonly property color scrollBarHandleColor: Theme.color(Theme.QmlDesigner_ScrollBarHandleColor)
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 { spacing: 0
height: 10 bottomPadding: 4
width: 10
color: scrollbarColor contentItem: ListView {
} model: myButton.contentModel
handle: Item { currentIndex: myButton.currentIndex
implicitWidth: 10
implicitHeight: 10 spacing: myButton.spacing
Rectangle { orientation: ListView.Horizontal
anchors.fill: parent boundsBehavior: Flickable.StopAtBounds
color: scrollBarHandleColor flickableDirection: Flickable.AutoFlickIfNeeded
} snapMode: ListView.SnapToItem
} }
decrementControl: Item {} background: Rectangle {
incrementControl: Item {} color: StudioTheme.Values.themeTabLight
corner: Item {}
//Even if the platform style reports touch support a scrollview should not be flickable.
Component.onCompleted: {
control.flickableItem.interactive = false
} }
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/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -23,40 +23,38 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.1 import QtQuick 2.15
import QtQuick.Controls 1.0 as Controls import QtQuick.Templates 2.15 as T
import QtQuick.Controls.Styles 1.1
import QtQuickDesignerTheme 1.0
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
Controls.TabView { T.TabButton {
id: root id: myButton
frameVisible: false implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
style: TabViewStyle { implicitContentWidth + leftPadding + rightPadding)
frameOverlap: 0 implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
frame: Item { } implicitContentHeight + topPadding + bottomPadding)
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()
}
Rectangle { padding: 1
color:Theme.qmlDesignerTabLight()
width: parent.width background: Rectangle {
height: 4 id: buttonBackground
anchors.bottom: parent.bottom 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 SpinBox 1.0 SpinBox.qml
SpinBoxIndicator 1.0 SpinBoxIndicator.qml SpinBoxIndicator 1.0 SpinBoxIndicator.qml
SpinBoxInput 1.0 SpinBoxInput.qml SpinBoxInput 1.0 SpinBoxInput.qml
TabBar 1.0 TabBar.qml
TabButton 1.0 TabButton.qml
TextArea 1.0 TextArea.qml TextArea 1.0 TextArea.qml
TextField 1.0 TextField.qml TextField 1.0 TextField.qml
TranslationIndicator 1.0 TranslationIndicator.qml TranslationIndicator 1.0 TranslationIndicator.qml

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1320,6 +1320,40 @@ UiObjectMember: T_DEFAULT UiObjectMemberPropertyNoInitialiser;
} break; } 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; UiObjectMember: T_DEFAULT UiObjectMemberListPropertyNoInitialiser;
/. /.
case $rule_number: { 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_XOR_EQ = 84,
T_YIELD = 100, T_YIELD = 100,
ACCEPT_STATE = 1098, ACCEPT_STATE = 1102,
RULE_COUNT = 616, RULE_COUNT = 619,
STATE_COUNT = 1099, STATE_COUNT = 1103,
TERMINAL_COUNT = 134, TERMINAL_COUNT = 134,
NON_TERMINAL_COUNT = 238, NON_TERMINAL_COUNT = 238,
GOTO_INDEX_OFFSET = 1099, GOTO_INDEX_OFFSET = 1103,
GOTO_INFO_OFFSET = 6942, GOTO_INFO_OFFSET = 6857,
GOTO_CHECK_OFFSET = 6942 GOTO_CHECK_OFFSET = 6857
}; };
static const char *const spell[]; 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. ** Copyright (C) 2016 The Qt Company Ltd.
@@ -22,7 +24,6 @@
** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** 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 QT_QML_END_NAMESPACE

View File

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

View File

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

View File

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

View File

@@ -55,6 +55,7 @@ public:
PyValue childFromName(const std::string &name); PyValue childFromName(const std::string &name);
PyValue childFromField(const PyField &field); PyValue childFromField(const PyField &field);
PyValue childFromIndex(int index); PyValue childFromIndex(int index);
ULONG currentNumberOfDescendants();
static PyValue createValue(ULONG64 address, const PyType &type); static PyValue createValue(ULONG64 address, const PyType &type);
static int tag(const std::string &typeName); 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. // the start assuming this is invoked for crashed applications.
std::ostringstream callStr; std::ostringstream callStr;
const QtInfo &qtInfo = QtInfo::get(SymbolGroupValueContext(exc.dataSpaces(), exc.symbols())); 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 << ')'; << jsExecutionEngine << std::dec << std::noshowbase << ')';
std::wstring wOutput; std::wstring wOutput;
if (!ExtensionContext::instance().call(callStr.str(), ExtensionContext::CallWithExceptionsHandled, &wOutput, &errorMessage)) if (!ExtensionContext::instance().call(callStr.str(), ExtensionContext::CallWithExceptionsHandled, &wOutput, &errorMessage))

View File

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

View File

@@ -30,10 +30,12 @@
#include "hostosinfo.h" #include "hostosinfo.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QXmlStreamWriter> // Mac. #include <QDir>
#include <QFileInfo>
#include <QMetaType> #include <QMetaType>
#include <QStringList> #include <QStringList>
#include <QUrl> #include <QUrl>
#include <QXmlStreamWriter> // Mac.
#include <functional> #include <functional>
#include <memory> #include <memory>
@@ -179,9 +181,14 @@ public:
#endif // QT_GUI_LIB #endif // QT_GUI_LIB
static bool removeRecursively(const FilePath &filePath, QString *error = nullptr); static bool removeRecursively(const FilePath &filePath, QString *error = nullptr);
static bool copyRecursively( static bool copyRecursively(const FilePath &srcFilePath,
const FilePath &srcFilePath, const FilePath &tgtFilePath, QString *error = nullptr, const FilePath &tgtFilePath,
const std::function<bool (QFileInfo, QFileInfo, QString *)> &copyHelper = nullptr); 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 FilePath resolveSymlinks(const FilePath &path);
static QString fileSystemFriendlyName(const QString &name); static QString fileSystemFriendlyName(const QString &name);
static int indexOfQmakeUnfriendly(const QString &name, int startpos = 0); static int indexOfQmakeUnfriendly(const QString &name, int startpos = 0);
@@ -195,6 +202,42 @@ public:
static QByteArray fileId(const FilePath &fileName); 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 // for actually finding out if e.g. directories are writable on Windows
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View File

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

View File

@@ -140,12 +140,15 @@ FilePath OutputLineParser::absoluteFilePath(const FilePath &filePath)
return filePath; return filePath;
FilePaths candidates; FilePaths candidates;
for (const FilePath &dir : searchDirectories()) { for (const FilePath &dir : searchDirectories()) {
const FilePath candidate = dir.pathAppended(filePath.toString()); FilePath candidate = dir.pathAppended(filePath.toString());
if (candidate.exists() || d->skipFileExistsCheck) if (candidate.exists() || d->skipFileExistsCheck) {
candidates << candidate; candidate = FilePath::fromString(QDir::cleanPath(candidate.toString()));
if (!candidates.contains(candidate))
candidates << candidate;
}
} }
if (candidates.count() == 1) if (candidates.count() == 1)
return FilePath::fromString(QDir::cleanPath(candidates.first().toString())); return candidates.first();
QString fp = filePath.toString(); QString fp = filePath.toString();
while (fp.startsWith("../")) while (fp.startsWith("../"))
@@ -282,12 +285,24 @@ void OutputFormatter::overridePostPrintAction(const PostPrintAction &postPrintAc
void OutputFormatter::doAppendMessage(const QString &text, OutputFormat format) void OutputFormatter::doAppendMessage(const QString &text, OutputFormat format)
{ {
const QTextCharFormat charFmt = charFormat(format); QTextCharFormat charFmt = charFormat(format);
const QList<FormattedText> formattedText = parseAnsi(text, charFmt); QList<FormattedText> formattedText = parseAnsi(text, charFmt);
const QString cleanLine = std::accumulate(formattedText.begin(), formattedText.end(), QString(), const QString cleanLine = std::accumulate(formattedText.begin(), formattedText.end(), QString(),
[](const FormattedText &t1, const FormattedText &t2) { return t1.text + t2.text; }); [](const FormattedText &t1, const FormattedText &t2) { return t1.text + t2.text; });
QList<OutputLineParser *> involvedParsers; QList<OutputLineParser *> involvedParsers;
const OutputLineParser::Result res = handleMessage(cleanLine, format, 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) { if (res.newContent) {
append(res.newContent.value(), charFmt); append(res.newContent.value(), charFmt);
return; return;

View File

@@ -546,6 +546,41 @@ QLinearGradient StyleHelper::statusBarGradient(const QRect &statusBarRect)
return grad; 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) QIcon StyleHelper::getIconFromIconFont(const QString &fontName, const QString &iconSymbol, int fontSize, int iconSize, QColor color)
{ {
QFontDatabase a; QFontDatabase a;

View File

@@ -93,6 +93,36 @@ public:
static void tintImage(QImage &img, const QColor &tintColor); static void tintImage(QImage &img, const QColor &tintColor);
static QLinearGradient statusBarGradient(const QRect &statusBarRect); 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, QColor color);
static QIcon getIconFromIconFont(const QString &fontName, const QString &iconSymbol, int fontSize, int iconSize); static QIcon getIconFromIconFont(const QString &fontName, const QString &iconSymbol, int fontSize, int iconSize);

View File

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

View File

@@ -50,6 +50,7 @@
#include <QComboBox> #include <QComboBox>
#include <QGroupBox> #include <QGroupBox>
#include <QFileDialog> #include <QFileDialog>
#include <QFormLayout>
#include <QLabel> #include <QLabel>
#include <QListView> #include <QListView>
#include <QPushButton> #include <QPushButton>
@@ -74,7 +75,6 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
vbox->addWidget(createSignPackageGroup()); vbox->addWidget(createSignPackageGroup());
vbox->addWidget(createApplicationGroup()); vbox->addWidget(createApplicationGroup());
vbox->addWidget(createAdvancedGroup()); vbox->addWidget(createAdvancedGroup());
vbox->addWidget(createCreateTemplatesGroup());
vbox->addWidget(createAdditionalLibrariesGroup()); vbox->addWidget(createAdditionalLibrariesGroup());
connect(m_step->buildConfiguration(), &BuildConfiguration::buildTypeChanged, connect(m_step->buildConfiguration(), &BuildConfiguration::buildTypeChanged,
@@ -96,7 +96,7 @@ QWidget *AndroidBuildApkWidget::createApplicationGroup()
auto group = new QGroupBox(tr("Application"), this); auto group = new QGroupBox(tr("Application"), this);
auto targetSDKComboBox = new QComboBox(group); auto targetSDKComboBox = new QComboBox();
targetSDKComboBox->addItems(targets); targetSDKComboBox->addItems(targets);
targetSDKComboBox->setCurrentIndex(targets.indexOf(m_step->buildTargetSdk())); targetSDKComboBox->setCurrentIndex(targets.indexOf(m_step->buildTargetSdk()));
@@ -107,9 +107,18 @@ QWidget *AndroidBuildApkWidget::createApplicationGroup()
AndroidManager::updateGradleProperties(step()->target(), QString()); // FIXME: Use real key. AndroidManager::updateGradleProperties(step()->target(), QString()); // FIXME: Use real key.
}); });
auto hbox = new QHBoxLayout(group); auto formLayout = new QFormLayout(group);
hbox->addWidget(new QLabel(tr("Android build SDK:"), group)); formLayout->addRow(tr("Android build SDK:"), targetSDKComboBox);
hbox->addWidget(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; return group;
} }
@@ -120,7 +129,7 @@ QWidget *AndroidBuildApkWidget::createSignPackageGroup()
sizePolicy.setHorizontalStretch(0); sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(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); auto keystoreLocationLabel = new QLabel(tr("Keystore:"), group);
keystoreLocationLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); keystoreLocationLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
@@ -242,24 +251,6 @@ QWidget *AndroidBuildApkWidget::createAdvancedGroup()
return group; 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() QWidget *AndroidBuildApkWidget::createAdditionalLibrariesGroup()
{ {
auto group = new QGroupBox(tr("Additional Libraries")); auto group = new QGroupBox(tr("Additional Libraries"));

View File

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

View File

@@ -39,6 +39,7 @@
#include <projectexplorer/kitinformation.h> #include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h> #include <projectexplorer/kitmanager.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h> #include <projectexplorer/session.h>
#include <projectexplorer/toolchainmanager.h> #include <projectexplorer/toolchainmanager.h>
@@ -1284,7 +1285,12 @@ void AndroidConfigurations::removeUnusedDebuggers()
static bool containsAllAbis(const QStringList &abis) 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) for (const QString &abi : abis)
if (supportedAbis.contains(abi)) if (supportedAbis.contains(abi))
supportedAbis.removeOne(abi); supportedAbis.removeOne(abi);
@@ -1524,6 +1530,21 @@ AndroidConfigurations::AndroidConfigurations()
AndroidConfigurations::~AndroidConfigurations() = default; 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 AndroidConfig::getJdkPath()
{ {
FilePath jdkHome; FilePath jdkHome;
@@ -1563,6 +1584,16 @@ FilePath AndroidConfig::getJdkPath()
break; 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 { } else {
QStringList args; QStringList args;
if (HostOsInfo::isMacHost()) if (HostOsInfo::isMacHost())
@@ -1581,7 +1612,8 @@ FilePath AndroidConfig::getJdkPath()
jdkHome = FilePath::fromUtf8(jdkPath); jdkHome = FilePath::fromUtf8(jdkPath);
} else { } else {
jdkPath.replace("bin/java", ""); // For OpenJDK 11 jdkPath.replace("bin/java", ""); // For OpenJDK 11
jdkPath.replace("jre/bin/java", ""); jdkPath.replace("jre", "");
jdkPath.replace("//", "/");
jdkHome = FilePath::fromUtf8(jdkPath); 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_ARCHITECTURE[] = "Android.Architecture";
const char ANDROID_PACKAGE_SOURCE_DIR[] = "AndroidPackageSourceDir"; const char ANDROID_PACKAGE_SOURCE_DIR[] = "AndroidPackageSourceDir";
const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs"; const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs";
const char ANDROID_ABIS[] = "ANDROID_ABIS";
const char ANDROID_PACKAGENAME[] = "Android.PackageName"; const char ANDROID_PACKAGENAME[] = "Android.PackageName";
const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[] const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[]

View File

@@ -38,6 +38,7 @@
#include <coreplugin/messagemanager.h> #include <coreplugin/messagemanager.h>
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/buildsteplist.h> #include <projectexplorer/buildsteplist.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/project.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); m_uninstallPreviousPackage = qt && qt->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0);
//: AndroidDeployQtStep default display name //: AndroidDeployQtStep default display name
setDefaultDisplayName(tr("Deploy to Android device")); setDefaultDisplayName(tr("Deploy to Android Device"));
connect(this, &AndroidDeployQtStep::askForUninstall, connect(this, &AndroidDeployQtStep::askForUninstall,
this, &AndroidDeployQtStep::slotAskForUninstall, this, &AndroidDeployQtStep::slotAskForUninstall,
@@ -207,6 +208,18 @@ bool AndroidDeployQtStep::init()
if (!info.isValid()) // aborted if (!info.isValid()) // aborted
return false; 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_avdName = info.avdname;
m_serialNumber = info.serialNumber; m_serialNumber = info.serialNumber;
qCDebug(deployStepLog) << "Selected device info:" << info; qCDebug(deployStepLog) << "Selected device info:" << info;
@@ -484,7 +497,8 @@ void AndroidDeployQtStep::gatherFilesToPull()
QString linkerName("linker"); QString linkerName("linker");
QString libDirName("lib"); QString libDirName("lib");
auto preferreABI = AndroidManager::apkDevicePreferredAbi(target()); 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"; m_filesToPull["/system/bin/app_process64"] = buildDir + "app_process";
libDirName = "lib64"; libDirName = "lib64";
linkerName = "linker64"; linkerName = "linker64";

View File

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

View File

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

View File

@@ -64,7 +64,6 @@
#include <QFileDialog> #include <QFileDialog>
#include <QFileInfo> #include <QFileInfo>
#include <QFormLayout> #include <QFormLayout>
#include <QGroupBox>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QImage> #include <QImage>
#include <QLabel> #include <QLabel>
@@ -134,338 +133,351 @@ AndroidManifestEditorWidget::AndroidManifestEditorWidget()
this, &AndroidManifestEditorWidget::updateAfterFileLoad); 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() 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); topLayout->addWidget(createPackageFormLayout(mainWidget), 0, 0);
topLayout->addWidget(createApplicationGroupBox(mainWidget), 0, 1);
auto packageGroupBox = new QGroupBox(mainWidget); topLayout->addWidget(createPermissionsGroupBox(mainWidget), 1, 0, 1, 2);
topLayout->addWidget(packageGroupBox); topLayout->addWidget(createAdvancedGroupBox(mainWidget), 2, 0, 1, 2);
topLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::MinimumExpanding), 3, 0);
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));
auto mainWidgetScrollArea = new QScrollArea; auto mainWidgetScrollArea = new QScrollArea;
mainWidgetScrollArea->setWidgetResizable(true); mainWidgetScrollArea->setWidgetResizable(true);
@@ -575,6 +587,7 @@ bool AndroidManifestEditorWidget::setActivePage(EditorPage page)
if (!servicesValid(m_services->services())) { if (!servicesValid(m_services->services())) {
QMessageBox::critical(nullptr, tr("Service Definition Invalid"), QMessageBox::critical(nullptr, tr("Service Definition Invalid"),
tr("Cannot switch to source when there are invalid services.")); tr("Cannot switch to source when there are invalid services."));
m_advanvedTabWidget->setCurrentIndex(1);
return false; return false;
} }
syncToEditor(); syncToEditor();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,57 +2,278 @@
<ui version="4.0"> <ui version="4.0">
<class>AndroidSettingsWidget</class> <class>AndroidSettingsWidget</class>
<widget class="QWidget" name="AndroidSettingsWidget"> <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"> <property name="windowTitle">
<string>Android Configuration</string> <string>Android Configuration</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <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> <item>
<widget class="QScrollArea" name="scrollArea"> <widget class="QGroupBox" name="javaSettingsGroupBox">
<property name="frameShape"> <property name="minimumSize">
<enum>QFrame::NoFrame</enum> <size>
<width>0</width>
<height>0</height>
</size>
</property> </property>
<property name="frameShadow"> <property name="title">
<enum>QFrame::Plain</enum> <string>Java Settings</string>
</property> </property>
<property name="lineWidth"> <layout class="QGridLayout" name="gridLayout">
<number>0</number> <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>
<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> <bool>true</bool>
</property> </property>
<widget class="QWidget" name="scrollAreaWidgetContents_2"> </widget>
<property name="geometry"> </item>
<rect> <item>
<x>0</x> <widget class="QTabWidget" name="managerTabWidget">
<y>0</y> <property name="currentIndex">
<width>1123</width> <number>0</number>
<height>818</height> </property>
</rect> <widget class="QWidget" name="avdManagerTab">
</property> <attribute name="title">
<property name="autoFillBackground"> <string>AVD Manager</string>
<bool>false</bool> </attribute>
</property> <layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@@ -66,435 +287,148 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QGroupBox" name="javaSettingsGroupBox"> <widget class="QTableView" name="AVDTableView">
<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">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="selectionMode">
<string>Automatically create kits for Android tool chains</string> <enum>QAbstractItemView::SingleSelection</enum>
</property> </property>
<property name="checked"> <property name="selectionBehavior">
<bool>true</bool> <enum>QAbstractItemView::SelectRows</enum>
</property> </property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QTabWidget" name="managerTabWidget"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="currentIndex"> <item>
<number>0</number> <widget class="QLabel" name="DataPartitionSizeLable">
</property> <property name="text">
<widget class="QWidget" name="avdManagerTab"> <string>System/data partition size:</string>
<attribute name="title">
<string>AVD Manager</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property> </property>
<property name="topMargin"> </widget>
<number>0</number> </item>
<item>
<widget class="QSpinBox" name="DataPartitionSizeSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="rightMargin"> <property name="suffix">
<number>0</number> <string> Mb</string>
</property> </property>
<property name="bottomMargin"> <property name="maximum">
<number>0</number> <number>99999</number>
</property> </property>
<item> <property name="value">
<widget class="QTableView" name="AVDTableView"> <number>1024</number>
<property name="sizePolicy"> </property>
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> </widget>
<horstretch>0</horstretch> </item>
<verstretch>0</verstretch> <item>
</sizepolicy> <widget class="QPushButton" name="AVDStartPushButton">
</property> <property name="enabled">
<property name="selectionMode"> <bool>false</bool>
<enum>QAbstractItemView::SingleSelection</enum> </property>
</property> <property name="sizePolicy">
<property name="selectionBehavior"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<enum>QAbstractItemView::SelectRows</enum> <horstretch>0</horstretch>
</property> <verstretch>0</verstretch>
<property name="textElideMode"> </sizepolicy>
<enum>Qt::ElideMiddle</enum> </property>
</property> <property name="text">
<attribute name="horizontalHeaderHighlightSections"> <string>Start...</string>
<bool>false</bool> </property>
</attribute> </widget>
<attribute name="verticalHeaderVisible"> </item>
<bool>false</bool> <item>
</attribute> <widget class="QPushButton" name="AVDRefreshPushButton">
</widget> <property name="text">
</item> <string>Refresh List</string>
<item> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> </widget>
<item> </item>
<widget class="QLabel" name="DataPartitionSizeLable"> <item>
<property name="text"> <spacer name="verticalSpacer_2">
<string>System/data partition size:</string> <property name="orientation">
</property> <enum>Qt::Vertical</enum>
</widget> </property>
</item> <property name="sizeType">
<item> <enum>QSizePolicy::Fixed</enum>
<widget class="QSpinBox" name="DataPartitionSizeSpinBox"> </property>
<property name="sizePolicy"> <property name="sizeHint" stdset="0">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <size>
<horstretch>0</horstretch> <width>0</width>
<verstretch>0</verstretch> <height>8</height>
</sizepolicy> </size>
</property> </property>
<property name="suffix"> </spacer>
<string> Mb</string> </item>
</property> <item>
<property name="maximum"> <widget class="QPushButton" name="AVDAddPushButton">
<number>99999</number> <property name="sizePolicy">
</property> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<property name="value"> <horstretch>0</horstretch>
<number>1024</number> <verstretch>0</verstretch>
</property> </sizepolicy>
</widget> </property>
</item> <property name="text">
<item> <string>Add...</string>
<widget class="QPushButton" name="AVDStartPushButton"> </property>
<property name="enabled"> </widget>
<bool>false</bool> </item>
</property> <item>
<property name="sizePolicy"> <widget class="QPushButton" name="AVDRemovePushButton">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <property name="enabled">
<horstretch>0</horstretch> <bool>false</bool>
<verstretch>0</verstretch> </property>
</sizepolicy> <property name="sizePolicy">
</property> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<property name="text"> <horstretch>0</horstretch>
<string>Start...</string> <verstretch>0</verstretch>
</property> </sizepolicy>
</widget> </property>
</item> <property name="text">
<item> <string>Remove</string>
<widget class="QPushButton" name="AVDRefreshPushButton"> </property>
<property name="text"> </widget>
<string>Refresh List</string> </item>
</property> <item>
</widget> <spacer name="verticalSpacer">
</item> <property name="orientation">
<item> <enum>Qt::Vertical</enum>
<spacer name="verticalSpacer_2"> </property>
<property name="orientation"> <property name="sizeHint" stdset="0">
<enum>Qt::Vertical</enum> <size>
</property> <width>20</width>
<property name="sizeType"> <height>40</height>
<enum>QSizePolicy::Fixed</enum> </size>
</property> </property>
<property name="sizeHint" stdset="0"> </spacer>
<size> </item>
<width>0</width> </layout>
<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> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="sdkManagerTab">
<attribute name="title">
<string>SDK Manager</string>
</attribute>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

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

View File

@@ -182,7 +182,7 @@ ChooseDirectoryPage::ChooseDirectoryPage(CreateAndroidManifestWizard *wizard)
if (wizard->copyGradle()) { if (wizard->copyGradle()) {
auto checkBox = new QCheckBox(this); auto checkBox = new QCheckBox(this);
checkBox->setChecked(true); checkBox->setChecked(false);
connect(checkBox, &QCheckBox::toggled, wizard, &CreateAndroidManifestWizard::setCopyGradle); connect(checkBox, &QCheckBox::toggled, wizard, &CreateAndroidManifestWizard::setCopyGradle);
checkBox->setText(tr("Copy the Gradle files to Android directory")); 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.")); 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::CreateAndroidManifestWizard(BuildSystem *buildSystem) CreateAndroidManifestWizard::CreateAndroidManifestWizard(BuildSystem *buildSystem)
: m_buildSystem(buildSystem), m_copyState(Ask) : m_buildSystem(buildSystem)
{ {
setWindowTitle(tr("Create Android Template Files Wizard")); setWindowTitle(tr("Create Android Template Files Wizard"));
@@ -290,70 +290,12 @@ void CreateAndroidManifestWizard::setCopyGradle(bool copy)
m_copyGradle = 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() void CreateAndroidManifestWizard::createAndroidTemplateFiles()
{ {
if (m_directory.isEmpty()) if (m_directory.isEmpty())
return; return;
QStringList addedFiles; FileUtils::CopyAskingForOverwrite copy(this);
Target *target = m_buildSystem->target(); Target *target = m_buildSystem->target();
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target->kit()); QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target->kit());
if (!version) if (!version)
@@ -361,21 +303,23 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles()
if (version->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) { if (version->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) {
const QString src = version->prefix().toString() + "/src/android/java/AndroidManifest.xml"; const QString src = version->prefix().toString() + "/src/android/java/AndroidManifest.xml";
FileUtils::copyRecursively(FilePath::fromString(src), FileUtils::copyRecursively(FilePath::fromString(src),
FilePath::fromString(m_directory + QLatin1String("/AndroidManifest.xml")), FilePath::fromString(m_directory
nullptr, [this, &addedFiles](QFileInfo src, QFileInfo dst, QString *){return copy(src, dst, &addedFiles);}); + QLatin1String("/AndroidManifest.xml")),
nullptr,
copy);
} else { } else {
const QString src = version->prefix().toString() + "/src/android/templates"; const QString src = version->prefix().toString() + "/src/android/templates";
FileUtils::copyRecursively(FilePath::fromString(src), FileUtils::copyRecursively(FilePath::fromString(src),
FilePath::fromString(m_directory), FilePath::fromString(m_directory),
nullptr, [this, &addedFiles](QFileInfo src, QFileInfo dst, QString *){return copy(src, dst, &addedFiles);}); nullptr,
copy);
if (m_copyGradle) { if (m_copyGradle) {
FilePath gradlePath = version->prefix().pathAppended("src/3rdparty/gradle"); FilePath gradlePath = version->prefix().pathAppended("src/3rdparty/gradle");
if (!gradlePath.exists()) if (!gradlePath.exists())
gradlePath = AndroidConfigurations::currentConfig().sdkLocation().pathAppended("/tools/templates/gradle/wrapper"); gradlePath = AndroidConfigurations::currentConfig().sdkLocation().pathAppended("/tools/templates/gradle/wrapper");
FileUtils::copyRecursively(gradlePath, FilePath::fromString(m_directory), FileUtils::copyRecursively(gradlePath, FilePath::fromString(m_directory), nullptr, copy);
nullptr, [this, &addedFiles](QFileInfo src, QFileInfo dst, QString *){return copy(src, dst, &addedFiles);});
} }
AndroidManager::updateGradleProperties(target, m_buildKey); AndroidManager::updateGradleProperties(target, m_buildKey);
@@ -385,7 +329,7 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles()
QString androidPackageDir; QString androidPackageDir;
ProjectNode *node = target->project()->findNodeForBuildKey(m_buildKey); ProjectNode *node = target->project()->findNodeForBuildKey(m_buildKey);
if (node) { if (node) {
node->addFiles(addedFiles); node->addFiles(copy.files());
androidPackageDir = node->data(Android::Constants::AndroidPackageSourceDir).toString(); androidPackageDir = node->data(Android::Constants::AndroidPackageSourceDir).toString();
if (androidPackageDir.isEmpty()) { if (androidPackageDir.isEmpty()) {

View File

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

View File

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

View File

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

View File

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

View File

@@ -27,6 +27,7 @@
#include "catchconfiguration.h" #include "catchconfiguration.h"
#include "catchframework.h" #include "catchframework.h"
#include <projectexplorer/project.h>
#include <projectexplorer/session.h> #include <projectexplorer/session.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -38,14 +39,26 @@ QString CatchTreeItem::testCasesString() const
return m_state & CatchTreeItem::Parameterized ? QString(name() + " -*") : name(); 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 QVariant CatchTreeItem::data(int column, int role) const
{ {
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
if (type() == Root) if (type() == Root)
break; break;
return QString(name() + stateSuffix()); return QString(nonRootDisplayName(this) + stateSuffix());
case Qt::CheckStateRole: case Qt::CheckStateRole:
switch (type()) { switch (type()) {
case Root: 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 if (buildTargets.size() > 1 ) // there are multiple executables with the same build target
return; // let the user decide which one to run 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 // 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 // there would be no BuildTargetInfo that could match

View File

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

View File

@@ -35,6 +35,7 @@ namespace Internal {
static const char SK_ACTIVE_FRAMEWORKS[] = "AutoTest.ActiveFrameworks"; static const char SK_ACTIVE_FRAMEWORKS[] = "AutoTest.ActiveFrameworks";
static const char SK_RUN_AFTER_BUILD[] = "AutoTest.RunAfterBuild"; 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) 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); const QVariant runAfterBuild = m_project->namedSettings(SK_RUN_AFTER_BUILD);
m_runAfterBuild = runAfterBuild.isValid() ? RunAfterBuildMode(runAfterBuild.toInt()) m_runAfterBuild = runAfterBuild.isValid() ? RunAfterBuildMode(runAfterBuild.toInt())
: RunAfterBuildMode::None; : RunAfterBuildMode::None;
m_checkStateCache.fromSettings(m_project->namedSettings(SK_CHECK_STATES).toHash());
} }
void TestProjectSettings::save() void TestProjectSettings::save()
@@ -104,6 +106,8 @@ void TestProjectSettings::save()
activeFrameworks.insert(it.key()->id().toString(), it.value()); activeFrameworks.insert(it.key()->id().toString(), it.value());
m_project->setNamedSettings(SK_ACTIVE_FRAMEWORKS, activeFrameworks); m_project->setNamedSettings(SK_ACTIVE_FRAMEWORKS, activeFrameworks);
m_project->setNamedSettings(SK_RUN_AFTER_BUILD, int(m_runAfterBuild)); 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 } // namespace Internal

View File

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

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