Merge remote-tracking branch 'origin/4.11'

Change-Id: I48e406d43f185e893523cc5e0dcf288afdc3e36c
This commit is contained in:
Eike Ziller
2019-10-17 07:32:01 +02:00
133 changed files with 2326 additions and 1070 deletions

View File

@@ -34,10 +34,6 @@ if (WITH_TESTS)
set(IMPLICIT_DEPENDS Qt5::Test)
endif()
if (BUILD_WITH_PCH)
list(APPEND IMPLICIT_DEPENDS Qt5::Core)
endif()
find_package(Qt5
COMPONENTS Concurrent Core Gui LinguistTools Network PrintSupport Qml Quick
QuickWidgets Sql Widgets Xml ${QT_TEST_COMPONENT}

View File

@@ -288,6 +288,14 @@ endfunction()
function(enable_pch target)
if (BUILD_WITH_PCH)
# Skip PCH for targets that do not use the expected visibility settings:
get_target_property(visibility_property "${target}" CXX_VISIBILITY_PRESET)
get_target_property(inlines_property "${target}" VISIBILITY_INLINES_HIDDEN)
if (NOT visibility_property STREQUAL "hidden" OR NOT inlines_property)
return()
endif()
get_target_property(target_type ${target} TYPE)
if (NOT ${target_type} STREQUAL "OBJECT_LIBRARY")
function(_recursively_collect_dependencies input_target)
@@ -309,19 +317,25 @@ function(enable_pch target)
function(_add_pch_target pch_target pch_file pch_dependency)
if (EXISTS ${pch_file})
add_library(${pch_target} STATIC
${CMAKE_BINARY_DIR}/empty_pch.cpp)
${CMAKE_CURRENT_BINARY_DIR}/empty_pch.cpp
${CMAKE_CURRENT_BINARY_DIR}/empty_pch.c)
target_compile_definitions(${pch_target} PRIVATE ${DEFAULT_DEFINES})
set_target_properties(${pch_target} PROPERTIES
PRECOMPILE_HEADERS ${pch_file})
PRECOMPILE_HEADERS ${pch_file}
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON)
target_link_libraries(${pch_target} PRIVATE ${pch_dependency})
endif()
endfunction()
if (NOT TARGET QtCreatorPchGui AND NOT TARGET QtCreatorPchConsole)
file(WRITE ${CMAKE_BINARY_DIR}/empty_pch.cpp.in "/*empty file*/")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/empty_pch.c_cpp.in "/*empty file*/")
configure_file(
${CMAKE_BINARY_DIR}/empty_pch.cpp.in
${CMAKE_BINARY_DIR}/empty_pch.cpp)
${CMAKE_CURRENT_BINARY_DIR}/empty_pch.c_cpp.in
${CMAKE_CURRENT_BINARY_DIR}/empty_pch.cpp)
configure_file(
${CMAKE_CURRENT_BINARY_DIR}/empty_pch.c_cpp.in
${CMAKE_CURRENT_BINARY_DIR}/empty_pch.c)
_add_pch_target(QtCreatorPchGui
"${PROJECT_SOURCE_DIR}/src/shared/qtcreator_gui_pch.h" Qt5::Widgets)
@@ -329,12 +343,14 @@ function(enable_pch target)
"${PROJECT_SOURCE_DIR}/src/shared/qtcreator_pch.h" Qt5::Core)
endif()
set(PCH_TARGET QtCreatorPchConsole)
unset(PCH_TARGET)
if ("Qt5::Widgets" IN_LIST dependencies)
set(PCH_TARGET QtCreatorPchGui)
elseif ("Qt5::Core" IN_LIST dependencies)
set(PCH_TARGET QtCreatorPchConsole)
endif()
if (TARGET ${PCH_TARGET})
if (TARGET "${PCH_TARGET}")
set_target_properties(${target} PROPERTIES
PRECOMPILE_HEADERS_REUSE_FROM ${PCH_TARGET})
endif()
@@ -364,7 +380,7 @@ endfunction()
#
function(add_qtc_library name)
cmake_parse_arguments(_arg "STATIC;OBJECT;SKIP_TRANSLATION" ""
cmake_parse_arguments(_arg "STATIC;OBJECT;SKIP_TRANSLATION;BUILD_BY_DEFAULT" "DESTINATION"
"DEFINES;DEPENDS;EXTRA_TRANSLATIONS;INCLUDES;PUBLIC_DEFINES;PUBLIC_DEPENDS;PUBLIC_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;PROPERTIES" ${ARGN}
)
@@ -384,8 +400,13 @@ function(add_qtc_library name)
set(library_type OBJECT)
endif()
set(_exclude_from_all EXCLUDE_FROM_ALL)
if (_arg_BUILD_BY_DEFAULT)
unset(_exclude_from_all)
endif()
# Do not just build libraries...
add_library(${name} ${library_type} EXCLUDE_FROM_ALL ${_arg_SOURCES})
add_library(${name} ${library_type} ${_exclude_from_all} ${_arg_SOURCES})
add_library(${IDE_CASED_ID}::${name} ALIAS ${name})
set_public_headers(${name} "${_arg_SOURCES}")
@@ -432,6 +453,11 @@ function(add_qtc_library name)
set(skip_translation ON)
endif()
set(_DESTINATION "${IDE_BIN_PATH}")
if (_arg_DESTINATION)
set(_DESTINATION "${_arg_DESTINATION}")
endif()
qtc_output_binary_dir(_output_binary_dir)
set_target_properties(${name} PROPERTIES
SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
@@ -440,7 +466,7 @@ function(add_qtc_library name)
VISIBILITY_INLINES_HIDDEN ON
BUILD_RPATH "${_LIB_RPATH}"
INSTALL_RPATH "${_LIB_RPATH}"
RUNTIME_OUTPUT_DIRECTORY "${_output_binary_dir}/${IDE_BIN_PATH}"
RUNTIME_OUTPUT_DIRECTORY "${_output_binary_dir}/${_DESTINATION}"
LIBRARY_OUTPUT_DIRECTORY "${_output_binary_dir}/${IDE_LIBRARY_PATH}"
ARCHIVE_OUTPUT_DIRECTORY "${_output_binary_dir}/${IDE_LIBRARY_PATH}"
${_arg_PROPERTIES}
@@ -454,7 +480,7 @@ function(add_qtc_library name)
install(TARGETS ${name}
EXPORT ${IDE_CASED_ID}
RUNTIME DESTINATION "${IDE_BIN_PATH}"
RUNTIME DESTINATION "${_DESTINATION}"
LIBRARY
DESTINATION "${IDE_LIBRARY_PATH}"
${NAMELINK_OPTION}

View File

@@ -23,6 +23,7 @@ you can check out from the public Git repository. For example:
* Added option to change line ending style via editor tool bar
* Fixed that explicit colors or styles in KSyntaxHighlighting specifications were ignored
(QTCREATORBUG-13545, QTCREATORBUG-22229, QTCREATORBUG-22646)
* Fixed behavior of backtab with multi-line selection (QTCREATORBUG-16970)
### Language Client
@@ -37,10 +38,12 @@ you can check out from the public Git repository. For example:
* Fixed that build environment was not used for asking compilers about built-in headers
(QTCREATORBUG-17985)
* Fixed handling of `-mllvm` command line option
* Fixed handling of `noexcept` when refactoring (QTCREATORBUG-11849, QTCREATORBUG-19699)
### QML
* Fixed pragma reformatting
* Updated to parser from Qt 5.15
* Fixed pragma reformatting (QTCREATORBUG-22326)
### Python
@@ -55,6 +58,7 @@ you can check out from the public Git repository. For example:
## Projects
* Added experimental support for Qt for WebAssembly (QTCREATORBUG-21068)
* Added experimental support for Qt for MCUs
* Added `Build` > `Build for Run Configuration` (QTCREATORBUG-22403)
* Added more space for custom command line arguments (QTCREATORBUG-17890)
* Added option to continue building after a single project failed with `Build` > `Build All`
@@ -63,13 +67,14 @@ you can check out from the public Git repository. For example:
* Added option for translation file to wizards (QTCREATORBUG-7453)
* Added option to rename files with same base name when renaming files via project tree
(QTCREATORBUG-21738)
* Changed build process to run with low priority (QTCREATORBUG-5155)
* Added option for running build process with low priority (QTCREATORBUG-5155)
* Made it possible to schedule running the project while building it (QTCREATORBUG-14297)
* Improved unconfigured project page (QTCREATORBUG-20018)
* Fixed parsing of `lld` output (QTCREATORBUG-22623)
* Fixed issues with expanding macros in environment variables
* Fixed that generated files were appearing in Locator and project wide searches
(QTCREATORBUG-20176)
* Fixed disabled project context menu item (QTCREATORBUG-22850)
### QMake
@@ -110,7 +115,14 @@ you can check out from the public Git repository. For example:
* Added support for loading results from `clang-tidy` and `clazy` that were
exported with `-export-fixes`
* Added option for overriding configuration per project
* Added option to analyze only open or edited documents
* Changed to use separate `clang-tidy` executable
* Separated diagnostic configuration settings for code model
(`C++` > `Code Model`) and analyzer (`Analyzer` > `Clang Tools`)
## Qt Widget Designer
* Fixed lookup of resources (QTCREATORBUG-22909, QTCREATORBUG-22962)
## Qt Quick Designer
@@ -118,7 +130,10 @@ you can check out from the public Git repository. For example:
* Added support for importing 3D assets into Quick3D components
(QDS-1051, QDS-1053)
* Added option for keyframe time in `Edit` dialog (QDS-1072)
* Added snapping of timeline playhead to keyframes when shift-dragging
(QDS-1068)
* Fixed issues with dragging timeline items (QDS-1074)
* Fixed various timeline editor issues (QDS-1073)
## Version Control Systems
@@ -146,7 +161,7 @@ you can check out from the public Git repository. For example:
### Android
* Added warning if `sdkmanager` could not be run, including hint to correct Java SDK
* Added warning if `sdkmanager` could not be run, including hint to appropriate Java SDK
(QTCREATORBUG-22626)
* Added knowledge of Android 10 and API level 29
* Fixed issue with multiple Java versions in `PATH` (QTCREATORBUG-22504)
@@ -155,15 +170,18 @@ you can check out from the public Git repository. For example:
* Moved support for [Qt for Device Creation](https://doc.qt.io/QtForDeviceCreation/qtdc-index.html)
(Boot2Qt) to open source
* Fixed issues with SFTP on Windows (QTCREATORBUG-22471)
### QNX
* Fixed registration of toolchain as C compiler
* Fixed issue with license checking of QCC
* Fixed deployment of public key (QTCREATORBUG-22591)
### Bare Metal
* Added support for STM8 and MSP430 architectures
* Fixed that it was not possible to add custom deployment steps (QTCREATORBUG-22977)
## Credits for these changes go to:
Aleksei German
@@ -180,7 +198,9 @@ David Schulz
Denis Shienkov
Eike Ziller
Frederik Schwarzer
Henning Gruendl
Joel Smith
Laurent Montel
Leander Schulten
Leena Miettinen
Mahmoud Badri
@@ -199,6 +219,7 @@ Thomas Hartmann
Tim Henning
Tim Jenssen
Tobias Hunger
Tommi Pekkala
Uladzislau Paulovich
Ulf Hermann
Ville Nummela

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -64,7 +64,7 @@
\row
\li Find free Qt-based applications
\li \l{http://qt-apps.org/}{Qt Apps}
\li \l{https://github.com/topics/qt}{Qt Apps on GitHub}
\row
\li Develop with a commercial Qt license and support -

View File

@@ -143,7 +143,7 @@ class PlainDumper:
d.putValue(d.hexencode(val), 'utf8:1:0')
elif sys.version_info[0] <= 2 and isinstance(val, unicode):
d.putValue(val)
else: # Assuming LazyString
elif val is not None: # Assuming LazyString
d.putCharArrayValue(val.address, val.length,
val.type.target().sizeof)

View File

@@ -0,0 +1,101 @@
/****************************************************************************
**
** Copyright (C) 2019 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.
**
****************************************************************************/
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick3D 1.0
import QtQuick.Controls 2.0
Window {
width: 1024
height: 768
visible: true
title: "3D"
flags: Qt.WindowStaysOnTopHint | Qt.Window | Qt.WindowTitleHint | Qt.WindowCloseButtonHint
Rectangle {
color: "black"
anchors.fill: parent
}
Column {
y: 32
Slider {
id: slider
value: -600
from: -1200
to: 600
}
Slider {
id: slider2
value: 0
from: -360
to: 360
}
CheckBox {
id: checkBox
text: "Light"
Rectangle {
anchors.fill: parent
z: -1
}
}
}
Binding {
target: view.scene
property: "rotation.y"
value: slider2.value
}
property alias scene: view.scene
property alias showLight: checkBox.checked
id: viewWindow
View3D {
id: view
anchors.fill: parent
enableWireframeMode: true
camera: camera01
Light {
id: directionalLight
visible: checkBox.checked
}
Camera {
id: camera01
z: slider.value
}
Component.onCompleted: {
directionalLight.setParentItem(view.scene)
camera01.setParentItem(view.scene)
}
}
}

View File

@@ -28,7 +28,5 @@ be met: https://www.gnu.org/licenses/gpl-3.0.html.</string>
<string>qml2puppet</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.qtcreator.qml2puppet</string>
<key>LSUIElement</key>
<string>1</string>
</dict>
</plist>

View File

@@ -958,7 +958,6 @@ void NodeInstanceServer::setInstancePropertyVariant(const PropertyValueContainer
void NodeInstanceServer::setInstanceAuxiliaryData(const PropertyValueContainer &auxiliaryContainer)
{
//instanceId() == 0: the item is root
if (auxiliaryContainer.instanceId() == 0 && (auxiliaryContainer.name() == "width" ||
auxiliaryContainer.name() == "height")) {
@@ -978,6 +977,16 @@ void NodeInstanceServer::setInstanceAuxiliaryData(const PropertyValueContainer &
} else {
rootNodeInstance().resetProperty(propertyName);
}
} else if (auxiliaryContainer.name() == "invisible") {
if (hasInstanceForId(auxiliaryContainer.instanceId())) {
ServerNodeInstance instance = instanceForId(auxiliaryContainer.instanceId());
if (instance.isSubclassOf("QQuick3DNode")) {
if (!auxiliaryContainer.value().isNull())
instance.setPropertyVariant("visible", !auxiliaryContainer.value().toBool());
else
instance.resetProperty("visible");
}
}
}
}

View File

@@ -633,7 +633,7 @@ QObject *ObjectNodeInstance::createPrimitive(const QString &typeName, int majorN
if (mockHash.contains(typeName))
object = QmlPrivateGate::createComponent(mockHash.value(typeName), context);
else
else if (majorNumber != -1 && minorNumber != -1)
object = QmlPrivateGate::createPrimitive(polishTypeName, majorNumber, minorNumber, context);
/* Let's try to create the primitive from source, since with incomplete meta info this might be a pure

View File

@@ -60,8 +60,33 @@
#include <designersupportdelegate.h>
#include <QQmlProperty>
#include <QOpenGLContext>
#include <QQuickView>
namespace QmlDesigner {
static QVariant objectToVariant(QObject *object)
{
return QVariant::fromValue(object);
}
static QObject *createEditView3D(QQmlEngine *engine)
{
QQmlComponent component(engine, QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"));
QWindow *window = qobject_cast<QWindow *>(component.create());
//For macOS we have to use the 4.1 core profile
QSurfaceFormat surfaceFormat = window->requestedFormat();
surfaceFormat.setVersion(4, 1);
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
window->setFormat(surfaceFormat);
return window;
}
Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
Qt5NodeInstanceServer(nodeInstanceClient)
{
@@ -122,6 +147,49 @@ bool Qt5InformationNodeInstanceServer::isDirtyRecursiveForParentInstances(QQuick
return false;
}
QObject *Qt5InformationNodeInstanceServer::findRootNodeOf3DViewport(
const QList<ServerNodeInstance> &instanceList) const
{
for (const ServerNodeInstance &instance : instanceList) {
if (instance.isSubclassOf("QQuick3DViewport")) {
for (const ServerNodeInstance &child : instanceList) { /* Look for scene node */
/* The QQuick3DViewport always creates a root node.
* This root node contains the complete scene. */
if (child.isSubclassOf("QQuick3DNode") && child.parent() == instance)
return child.internalObject()->property("parent").value<QObject *>();
}
}
}
return nullptr;
}
void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeInstance> &instanceList)
{
ServerNodeInstance root = rootNodeInstance();
QObject *node = nullptr;
bool showCustomLight = false;
if (root.isSubclassOf("QQuick3DNode")) {
node = root.internalObject();
showCustomLight = true; // Pure node scene we should add a custom light
} else {
node = findRootNodeOf3DViewport(instanceList);
}
if (node) { // If we found a scene we create the edit view
QObject *view = createEditView3D(engine());
QQmlProperty sceneProperty(view, "scene", context());
node->setParent(view);
sceneProperty.write(objectToVariant(node));
QQmlProperty parentProperty(node, "parent", context());
parentProperty.write(objectToVariant(view));
QQmlProperty completeSceneProperty(view, "showLight", context());
completeSceneProperty.write(showCustomLight);
}
}
void Qt5InformationNodeInstanceServer::collectItemChangesAndSendChangeCommands()
{
static bool inFunction = false;
@@ -232,6 +300,8 @@ void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &com
sendChildrenChangedCommand(instanceList);
nodeInstanceClient()->componentCompleted(createComponentCompletedCommand(instanceList));
if (qEnvironmentVariableIsSet("QMLDESIGNER_QUICK3D_MODE"))
setup3DEditView(instanceList);
}
void Qt5InformationNodeInstanceServer::sendChildrenChangedCommand(const QList<ServerNodeInstance> &childList)

View File

@@ -51,6 +51,9 @@ protected:
bool isDirtyRecursiveForParentInstances(QQuickItem *item) const;
private:
void setup3DEditView(const QList<ServerNodeInstance> &instanceList);
QObject *findRootNodeOf3DViewport(const QList<ServerNodeInstance> &instanceList) const;
QSet<ServerNodeInstance> m_parentChangedSet;
QList<ServerNodeInstance> m_completedComponentList;
QList<TokenCommand> m_tokenList;

View File

@@ -54,7 +54,6 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) :
NodeInstanceClientProxy(parent)
{
prioritizeDown();
DesignerSupport::activateDesignerWindowManager();
if (QCoreApplication::arguments().at(1) == QLatin1String("--readcapturedstream")) {
qputenv("DESIGNER_DONT_USE_SHARED_MEMORY", "1");
setNodeInstanceServer(new Qt5TestNodeInstanceServer(this));
@@ -62,12 +61,20 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) :
readDataStream();
QCoreApplication::exit();
} else if (QCoreApplication::arguments().at(2) == QLatin1String("previewmode")) {
DesignerSupport::activateDesignerWindowManager();
setNodeInstanceServer(new Qt5PreviewNodeInstanceServer(this));
initializeSocket();
} else if (QCoreApplication::arguments().at(2) == QLatin1String("editormode")) {
/* The editormode does not use the DesignerWindowManager,
* because we want to be able to show the 3D Edit View
* as a normal QQuickView.
* The DesignerWindowManager prevents any window from actually being shown. */
if (!qEnvironmentVariableIsSet("QMLDESIGNER_QUICK3D_MODE"))
DesignerSupport::activateDesignerWindowManager();
setNodeInstanceServer(new Qt5InformationNodeInstanceServer(this));
initializeSocket();
} else if (QCoreApplication::arguments().at(2) == QLatin1String("rendermode")) {
DesignerSupport::activateDesignerWindowManager();
setNodeInstanceServer(new Qt5RenderNodeInstanceServer(this));
initializeSocket();
}

View File

@@ -37,6 +37,9 @@
#include <createscenecommand.h>
#include <reparentinstancescommand.h>
#include <QDebug>
#include <QOpenGLContext>
namespace QmlDesigner {
Qt5NodeInstanceServer::Qt5NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient)
@@ -68,6 +71,17 @@ void Qt5NodeInstanceServer::initializeView()
DesignerSupport::createOpenGLContext(m_quickView.data());
if (qEnvironmentVariableIsSet("QMLDESIGNER_QUICK3D_MODE")
&& QCoreApplication::arguments().at(2) == "editormode") {
/* In '3d editormode' we do not use the DesignerWindowManager
* and since we do not show the QQuickView we have to manually create the OpenGL context */
auto context = new QOpenGLContext(m_quickView);
context->setFormat(surfaceFormat);
context->create();
if (!context->makeCurrent(m_quickView))
qWarning("QOpenGLContext: makeCurrent() failed...");
}
if (qEnvironmentVariableIsSet("QML_FILE_SELECTORS")) {
QQmlFileSelector *fileSelector = new QQmlFileSelector(engine(), engine());
QStringList customSelectors = QString::fromUtf8(qgetenv("QML_FILE_SELECTORS")).split(",");

View File

@@ -67,6 +67,7 @@ class ServerNodeInstance
friend class NodeInstanceServer;
friend class Qt4NodeInstanceServer;
friend class Qt4PreviewNodeInstanceServer;
friend class Qt5InformationNodeInstanceServer;
friend class Qt5NodeInstanceServer;
friend class Qt5PreviewNodeInstanceServer;
friend class Qt5TestNodeInstanceServer;
@@ -162,6 +163,8 @@ public:
QList<ServerNodeInstance> stateInstances() const;
static bool isSubclassOf(QObject *object, const QByteArray &superTypeName);
private: // functions
ServerNodeInstance(const QSharedPointer<Internal::ObjectNodeInstance> &abstractInstance);
@@ -192,8 +195,6 @@ private: // functions
void paintUpdate();
static bool isSubclassOf(QObject *object, const QByteArray &superTypeName);
void setNodeSource(const QString &source);
bool holdsGraphical() const;

View File

@@ -132,8 +132,20 @@ int main(int argc, char *argv[])
// Since we always render text into an FBO, we need to globally disable
// subpixel antialiasing and instead use gray.
qputenv("QSG_DISTANCEFIELD_ANTIALIASING", "gray");
#ifdef Q_OS_OSX //This keeps qml2puppet from stealing focus
#ifdef Q_OS_MACOS
if (!qEnvironmentVariableIsSet("QMLDESIGNER_QUICK3D_MODE")) {
qputenv("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM", "true");
} else {
// We have to parse the arguments before Q[Gui]Application creation
// Since the Qt arguments are not filtered out, yet we do not know the position of the argument
for (int i = 0; i < argc; ++i) {
const char *arg = argv[i];
//In previewmode and rendermode we hide the process
if (!qstrcmp(arg, "previewmode") || !qstrcmp(arg, "rendermode"))
qputenv("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM", "true");
// This keeps qml2puppet from stealing focus
}
}
#endif
//If a style different from Desktop is set we have to use QGuiApplication

View File

@@ -7,5 +7,6 @@
<file>mockfiles/SwipeView.qml</file>
<file>mockfiles/GenericBackend.qml</file>
<file>mockfiles/Dialog.qml</file>
<file>mockfiles/EditView3D.qml</file>
</qresource>
</RCC>

View File

@@ -203,7 +203,7 @@ Item {
id: mapMouseArea
anchors.fill: parent
onPositionChanged: {
if (pressed && mouse.button === Qt.LeftButton) {
if (pressed && mouse.buttons === Qt.LeftButton) {
var xx = Math.max(0, Math.min(mouse.x, parent.width))
var yy = Math.max(0, Math.min(mouse.y, parent.height))

View File

@@ -152,11 +152,15 @@ Item {
var y = extendedFunctionButton.mapToGlobal(0,0).y - 40
bindingEditor.showWidget(x, y)
bindingEditor.text = backendValue.expression
bindingEditor.prepareBindings()
}
BindingEditor {
id: bindingEditor
backendValueProperty: backendValue
modelNodeBackendProperty: modelNodeBackend
onRejected: {
hideWidget()
expressionDialogLoader.visible = false

View File

@@ -1,6 +1,6 @@
{
"version": 1,
"supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ],
"supportedProjectTypes": [ "PythonProject" ],
"id": "U.QtForPythonApplicationWindow",
"category": "F.Application",
"trDescription": "Creates a Qt for Python application that contains an empty window.",

View File

@@ -16,6 +16,4 @@ add_subdirectory(sqlite)
add_subdirectory(clangsupport)
add_subdirectory(tracing)
if (WIN32)
add_subdirectory(qtcreatorcdbext)
endif()
add_subdirectory(qtcreatorcdbext)

View File

@@ -863,8 +863,13 @@ UiImport: UiImportHead UiVersionSpecifier Semicolon;
UiImport: UiImportHead UiVersionSpecifier T_AS QmlIdentifier Semicolon;
/.
case $rule_number: {
sym(1).UiImport->versionToken = loc(2);
sym(1).UiImport->version = sym(2).UiVersionSpecifier;
auto versionToken = loc(2);
auto version = sym(2).UiVersionSpecifier;
sym(1).UiImport->version = version;
if (version->minorToken.isValid()) {
versionToken.length += version->minorToken.length + (version->minorToken.offset - versionToken.offset - versionToken.length);
}
sym(1).UiImport->versionToken = versionToken;
sym(1).UiImport->asToken = loc(3);
sym(1).UiImport->importIdToken = loc(4);
sym(1).UiImport->importId = stringRef(4);

View File

@@ -398,8 +398,13 @@ bool Parser::parse(int startToken)
#line 866 "qmljs.g"
case 22: {
sym(1).UiImport->versionToken = loc(2);
sym(1).UiImport->version = sym(2).UiVersionSpecifier;
auto versionToken = loc(2);
auto version = sym(2).UiVersionSpecifier;
sym(1).UiImport->version = version;
if (version->minorToken.isValid()) {
versionToken.length += version->minorToken.length + (version->minorToken.offset - versionToken.offset - versionToken.length);
}
sym(1).UiImport->versionToken = versionToken;
sym(1).UiImport->asToken = loc(3);
sym(1).UiImport->importIdToken = loc(4);
sym(1).UiImport->importId = stringRef(4);

View File

@@ -265,6 +265,11 @@ public:
addLocation(line, column);
}
void pragmaLibrary() override
{
isLibrary = true;
}
virtual QList<SourceLocation> locations() { return _locations; }
const QString documentPath;

View File

@@ -24,8 +24,9 @@
****************************************************************************/
#include "qmljsreformatter.h"
#include "qmljscodeformatter.h"
#include "qmljsbind.h"
#include "parser/qmljsast_p.h"
#include "parser/qmljsastvisitor_p.h"
#include "parser/qmljsengine_p.h"
@@ -122,6 +123,10 @@ public:
// emit directives
if (_doc->bind()->isJsLibrary()) {
out(QLatin1String(".pragma library"));
newLine();
}
const QList<SourceLocation> &directives = _doc->jsDirectives();
for (const auto &d: directives) {
quint32 line = 1;

View File

@@ -1,29 +1,41 @@
#todo
# - handle if there is no debug python lib python35_d
# - needs to be tested
if (MINGW)
message(STATUS "MinGW detected. Removing qtcreatorcdbext from build.")
if (NOT WIN32 OR NOT MSVC)
return()
endif()
include(CheckIncludeFile)
check_include_file(wdbgexts.h HAVE_WDBGEXTS_H)
if (NOT HAVE_WDBGEXTS_H)
find_path(WDbgExtsPath wdbgexts.h
HINTS
"$ENV{CDB_PATH}"
"$ENV{ProgramFiles}/Debugging Tools For Windows/sdk"
"$ENV{ProgramFiles}/Debugging Tools For Windows (x86)/sdk"
"$ENV{ProgramFiles}/Debugging Tools For Windows (x64)/sdk"
"$ENV{ProgramFiles}/Debugging Tools For Windows 64-bit/sdk"
"$ENV{ProgramW6432}/Debugging Tools For Windows (x86)/sdk"
"$ENV{ProgramW6432}/Debugging Tools For Windows (x64)/sdk"
"$ENV{ProgramW6432}/Debugging Tools For Windows 64-bit/sdk"
"$ENV{ProgramFiles}/Windows Kits/8.0/Debuggers"
"$ENV{ProgramFiles}/Windows Kits/8.1/Debuggers"
"$ENV{ProgramFiles}/Windows Kits/10/Debuggers"
"$ENV{ProgramFiles\(x86\)}/Windows Kits/8.0/Debuggers/inc"
"$ENV{ProgramFiles\(x86\)}/Windows Kits/8.1/Debuggers/inc"
"$ENV{ProgramFiles\(x86\)}/Windows Kits/10/Debuggers/inc"
)
if (NOT WDbgExtsPath)
message(WARNING "wdbgexts.h not found. Removing qtcreatorcdbext from build.")
return()
endif()
find_package(PythonLibs 3.5)
if (NOT ${PYTHONLIBS_FOUND})
message(WARNING "PythonLibs 3.5 not found. Removing qtcreatorcdbext from build.")
return()
find_library(DbgEngLib dbgeng HINTS ${WDbgExtsPath})
set(ArchSuffix 32)
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ArchSuffix 64)
endif()
add_qtc_library(qtcreatorcdbext
DEPENDS ${PYTHON_LIBRARIES}
INCLUDES ${PYTHON_INCLUDE_DIR}
DEFINES WITH_PYTHON=1
BUILD_BY_DEFAULT
DEPENDS ${DbgEngLib}
DESTINATION lib/qtcreatorcdbext${ArchSuffix}/
SOURCES
common.cpp common.h
containers.cpp containers.h
@@ -33,14 +45,53 @@ add_qtc_library(qtcreatorcdbext
iinterfacepointer.h
knowntype.h
outputcallback.cpp outputcallback.h
pycdbextmodule.cpp pycdbextmodule.h
pyfield.cpp pyfield.h
pystdoutredirect.cpp pystdoutredirect.h
pytype.cpp pytype.h
pyvalue.cpp pyvalue.h
qtcreatorcdbext.def
qtcreatorcdbextension.cpp
stringutils.cpp stringutils.h
symbolgroup.cpp symbolgroup.h
symbolgroupnode.cpp symbolgroupnode.h
symbolgroupvalue.cpp symbolgroupvalue.h
)
find_package(PythonLibs 3.5)
if (NOT ${PYTHONLIBS_FOUND})
message(WARNING "PythonLibs (at least version 3.5) not found. qtcreatorcdbext will be built without Python support.")
return()
endif()
set(PythonRegex "^(.*)/(.*)/(python[0-9]+)${CMAKE_IMPORT_LIBRARY_SUFFIX}$")
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(PythonRegex "^(.*)/(.*)/(python[0-9]+_d)${CMAKE_IMPORT_LIBRARY_SUFFIX}$")
endif()
foreach(lib IN LISTS PYTHON_LIBRARIES)
if (lib MATCHES ${PythonRegex})
set(PythonDll "${CMAKE_MATCH_1}/${CMAKE_MATCH_3}${CMAKE_SHARED_LIBRARY_SUFFIX}")
break()
endif()
endforeach()
if (NOT PythonDll)
message(WARNING "PythonDll not found. qtcreatorcdbext will be built without Python support.")
return()
endif()
extend_qtc_target(qtcreatorcdbext
DEPENDS "${PYTHON_LIBRARIES}"
INCLUDES "${PYTHON_INCLUDE_DIR}"
DEFINES WITH_PYTHON=1
SOURCES
pycdbextmodule.cpp pycdbextmodule.h
pyfield.cpp pyfield.h
pystdoutredirect.cpp pystdoutredirect.h
pytype.cpp pytype.h
pyvalue.cpp pyvalue.h
)
install(FILES "${PythonDll}" DESTINATION lib/qtcreatorcdbext${ArchSuffix}/)
add_custom_target(copy_python_dll ALL VERBATIM)
add_custom_command(TARGET copy_python_dll POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy "${PythonDll}" "${PROJECT_BINARY_DIR}/lib/qtcreatorcdbext${ArchSuffix}/"
VERBATIM
)

View File

@@ -151,7 +151,7 @@ QString ShellCommand::displayName() const
result = tr("UNKNOWN");
if (!job.command.arguments().isEmpty())
result += ' ' + job.command.arguments().at(0);
result += ' ' + job.command.splitArguments().at(0);
return result;
}

View File

@@ -39,6 +39,9 @@
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerruncontrol.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/project.h>
@@ -48,6 +51,7 @@
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
#include <utils/outputformat.h>
#include <utils/qtcprocess.h>
@@ -59,21 +63,19 @@
#include <QFuture>
#include <QFutureInterface>
#include <QLabel>
#include <QLoggingCategory>
#include <QProcess>
#include <QPushButton>
#include <QTimer>
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerruncontrol.h>
#include <utils/algorithm.h>
using namespace ProjectExplorer;
using namespace Utils;
namespace Autotest {
namespace Internal {
static Q_LOGGING_CATEGORY(runnerLog, "qtc.autotest.testrunner", QtWarningMsg)
static TestRunner *s_instance = nullptr;
TestRunner *TestRunner::instance()
@@ -231,6 +233,11 @@ void TestRunner::scheduleNext()
const int timeout = AutotestPlugin::settings()->timeout;
QTimer::singleShot(timeout, m_currentProcess, [this]() { cancelCurrent(Timeout); });
qCInfo(runnerLog) << "Command:" << m_currentProcess->program();
qCInfo(runnerLog) << "Arguments:" << m_currentProcess->arguments();
qCInfo(runnerLog) << "Working directory:" << m_currentProcess->workingDirectory();
qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment();
m_currentProcess->start();
if (!m_currentProcess->waitForStarted()) {
reportResult(ResultType::MessageFatal,

View File

@@ -181,7 +181,8 @@ QList<TestTreeItem *> TestTreeModel::testItemsByName(TestTreeItem *root, const Q
}
TestTreeItem *testCase = node->findFirstLevelChild([&testName](TestTreeItem *it) {
QTC_ASSERT(it, return false);
return it->type() == TestTreeItem::TestFunction && it->name() == testName;
return (it->type() == TestTreeItem::TestCase
|| it->type() == TestTreeItem::TestFunction) && it->name() == testName;
}); // collect only actual tests, not special functions like init, cleanup etc.
if (testCase)
result << testCase;

View File

@@ -40,7 +40,7 @@ BareMetalGdbCommandsDeployStepWidget::BareMetalGdbCommandsDeployStepWidget(BareM
: BuildStepConfigWidget(&step), m_step(step)
{
const auto fl = new QFormLayout(this);
fl->setMargin(0);
fl->setContentsMargins(0, 0, 0, 0);
fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
setLayout(fl);
m_commands = new QPlainTextEdit(this);

View File

@@ -45,11 +45,26 @@
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <projectexplorer/deployconfiguration.h>
using namespace ProjectExplorer;
namespace BareMetal {
namespace Internal {
class BareMetalDeployConfigurationFactory : public DeployConfigurationFactory
{
public:
BareMetalDeployConfigurationFactory()
{
setConfigBaseId("BareMetal.DeployConfiguration");
setDefaultDisplayName(QCoreApplication::translate("BareMetalDeployConfiguration",
"Deploy to BareMetal Device"));
addSupportedTargetDeviceType(Constants::BareMetalOsType);
}
};
// BareMetalPluginPrivate
class BareMetalPluginPrivate
@@ -63,6 +78,7 @@ public:
BareMetalCustomRunConfigurationFactory customRunConfigurationFactory;
GdbServerProvidersSettingsPage gdbServerProviderSettinsPage;
GdbServerProviderManager gdbServerProviderManager;
BareMetalDeployConfigurationFactory deployConfigurationFactory;
RunWorkerFactory runWorkerFactory{
RunWorkerFactory::make<BareMetalDebugSupport>(),

View File

@@ -86,20 +86,14 @@ void KeilParser::amendDescription(const QString &desc)
++m_lines;
}
void KeilParser::stdError(const QString &line)
// ARM compiler specific parsers.
bool KeilParser::parseArmWarningOrErrorDetailsMessage(const QString &lne)
{
IOutputParser::stdError(line);
const QString lne = rightTrimmed(line);
QRegularExpression re;
QRegularExpressionMatch match;
// ARM compiler specific patterns.
re.setPattern("^\"(.+)\", line (\\d+).*:\\s+(Warning|Error):(\\s+|.+)([#|L].+)$");
match = re.match(lne);
if (match.hasMatch()) {
const QRegularExpression re("^\"(.+)\", line (\\d+).*:\\s+(Warning|Error):(\\s+|.+)([#|L].+)$");
const QRegularExpressionMatch match = re.match(lne);
if (!match.hasMatch())
return false;
enum CaptureIndex { FilePathIndex = 1, LineNumberIndex,
MessageTypeIndex, MessageNoteIndex, DescriptionIndex };
const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
@@ -109,19 +103,106 @@ void KeilParser::stdError(const QString &line)
const QString descr = match.captured(DescriptionIndex);
const Task task(type, descr, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
newTask(task);
return;
}
return true;
}
re.setPattern("^(Error|Fatal error):\\s(.+)$");
match = re.match(lne);
if (match.hasMatch()) {
bool KeilParser::parseArmErrorOrFatalErorrMessage(const QString &lne)
{
const QRegularExpression re("^(Error|Fatal error):\\s(.+)$");
const QRegularExpressionMatch match = re.match(lne);
if (!match.hasMatch())
return false;
enum CaptureIndex { MessageTypeIndex = 1, DescriptionIndex };
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
const QString descr = match.captured(DescriptionIndex);
const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
newTask(task);
return true;
}
// MCS51 compiler specific parsers.
bool KeilParser::parseMcs51WarningOrErrorDetailsMessage1(const QString &lne)
{
const QRegularExpression re("^\\*{3} (WARNING|ERROR) (\\w+) IN LINE (\\d+) OF (.+\\.\\S+): (.+)$");
const QRegularExpressionMatch match = re.match(lne);
if (!match.hasMatch())
return false;
enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex, LineNumberIndex,
FilePathIndex, MessageTextIndex };
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
const int lineno = match.captured(LineNumberIndex).toInt();
const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
match.captured(FilePathIndex));
const QString descr = QString("%1: %2").arg(match.captured(MessageCodeIndex),
match.captured(MessageTextIndex));
const Task task(type, descr, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
newTask(task);
return true;
}
bool KeilParser::parseMcs51WarningOrErrorDetailsMessage2(const QString &lne)
{
const QRegularExpression re("^\\*{3} (WARNING|ERROR) (#\\w+) IN (\\d+) \\((.+), LINE \\d+\\): (.+)$");
const QRegularExpressionMatch match = re.match(lne);
if (!match.hasMatch())
return false;
enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex, LineNumberIndex,
FilePathIndex, MessageTextIndex };
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
const int lineno = match.captured(LineNumberIndex).toInt();
const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
match.captured(FilePathIndex));
const QString descr = QString("%1: %2").arg(match.captured(MessageCodeIndex),
match.captured(MessageTextIndex));
const Task task(type, descr, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
newTask(task);
return true;
}
bool KeilParser::parseMcs51WarningOrFatalErrorMessage(const QString &lne)
{
const QRegularExpression re("^\\*{3} (WARNING|FATAL ERROR) (.+)$");
const QRegularExpressionMatch match = re.match(lne);
if (!match.hasMatch())
return false;
enum CaptureIndex { MessageTypeIndex = 1, MessageDescriptionIndex };
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
const QString descr = match.captured(MessageDescriptionIndex);
const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
newTask(task);
return true;
}
bool KeilParser::parseMcs51FatalErrorMessage2(const QString &lne)
{
const QRegularExpression re("^(A|C)51 FATAL[ |-]ERROR");
const QRegularExpressionMatch match = re.match(lne);
if (!match.hasMatch())
return false;
const QString key = match.captured(1);
QString descr;
if (key == QLatin1Char('A'))
descr = "Assembler fatal error";
else if (key == QLatin1Char('C'))
descr = "Compiler fatal error";
const Task task(Task::TaskType::Error, descr, {}, -1,
Constants::TASK_CATEGORY_COMPILE);
newTask(task);
return true;
}
void KeilParser::stdError(const QString &line)
{
IOutputParser::stdError(line);
const QString lne = rightTrimmed(line);
// Check for ARM compiler specific patterns.
if (parseArmWarningOrErrorDetailsMessage(lne))
return;
if (parseArmErrorOrFatalErorrMessage(lne))
return;
}
if (lne.startsWith(QLatin1Char(' '))) {
amendDescription(lne);
@@ -137,64 +218,13 @@ void KeilParser::stdOutput(const QString &line)
const QString lne = rightTrimmed(line);
QRegularExpression re;
QRegularExpressionMatch match;
// MSC51 compiler specific patterns.
re.setPattern("^\\*{3} (WARNING|ERROR) (\\w+) IN LINE (\\d+) OF (.+\\.\\S+): (.+)$");
match = re.match(lne);
if (match.hasMatch()) {
enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex, LineNumberIndex,
FilePathIndex, MessageTextIndex };
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
const int lineno = match.captured(LineNumberIndex).toInt();
const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
match.captured(FilePathIndex));
const QString descr = QString("%1: %2").arg(match.captured(MessageCodeIndex),
match.captured(MessageTextIndex));
const Task task(type, descr, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
newTask(task);
}
re.setPattern("^\\*{3} (WARNING|ERROR) (#\\w+) IN (\\d+) \\((.+), LINE \\d+\\): (.+)$");
match = re.match(lne);
if (match.hasMatch()) {
enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex, LineNumberIndex,
FilePathIndex, MessageTextIndex };
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
const int lineno = match.captured(LineNumberIndex).toInt();
const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
match.captured(FilePathIndex));
const QString descr = QString("%1: %2").arg(match.captured(MessageCodeIndex),
match.captured(MessageTextIndex));
const Task task(type, descr, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
newTask(task);
}
re.setPattern("^\\*{3} (FATAL ERROR) (.+)$");
match = re.match(lne);
if (match.hasMatch()) {
enum CaptureIndex { MessageTypeIndex = 1, MessageDescriptionIndex };
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
const QString descr = match.captured(MessageDescriptionIndex);
const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
newTask(task);
// Check for MSC51 compiler specific patterns.
const bool parsed = parseMcs51WarningOrErrorDetailsMessage1(lne)
|| parseMcs51WarningOrErrorDetailsMessage2(lne);
if (!parsed) {
if (parseMcs51WarningOrFatalErrorMessage(lne))
return;
}
re.setPattern("^(A|C)51 FATAL[ |-]ERROR");
match = re.match(lne);
if (match.hasMatch()) {
const QString key = match.captured(1);
QString descr;
if (key == QLatin1Char('A'))
descr = "Assembler fatal error";
else if (key == QLatin1Char('C'))
descr = "Compiler fatal error";
const Task task(Task::TaskType::Error, descr, {}, -1,
Constants::TASK_CATEGORY_COMPILE);
newTask(task);
if (parseMcs51FatalErrorMessage2(lne))
return;
}
@@ -463,6 +493,21 @@ void BareMetalPlugin::testKeilOutputParsers_data()
<< QString();
// Linker messages.
QTest::newRow("MCS51: Linker warning")
<< QString::fromLatin1("*** WARNING L16: Some warning\n"
" Some detail 1")
<< OutputParserTester::STDOUT
<< QString::fromLatin1("*** WARNING L16: Some warning\n"
" Some detail 1\n")
<< QString()
<< (Tasks() << Task(Task::Warning,
QLatin1String("L16: Some warning\n"
" Some detail 1"),
Utils::FilePath(),
-1,
categoryCompile))
<< QString();
QTest::newRow("MCS51: Linker simple fatal error")
<< QString::fromLatin1("*** FATAL ERROR L456: Some error")
<< OutputParserTester::STDOUT

View File

@@ -45,6 +45,16 @@ private:
void newTask(const ProjectExplorer::Task &task);
void amendDescription(const QString &desc);
// ARM compiler specific parsers.
bool parseArmWarningOrErrorDetailsMessage(const QString &lne);
bool parseArmErrorOrFatalErorrMessage(const QString &lne);
// MCS51 compiler specific parsers.
bool parseMcs51WarningOrErrorDetailsMessage1(const QString &lne);
bool parseMcs51WarningOrErrorDetailsMessage2(const QString &lne);
bool parseMcs51WarningOrFatalErrorMessage(const QString &lne);
bool parseMcs51FatalErrorMessage2(const QString &lne);
void stdError(const QString &line) final;
void stdOutput(const QString &line) final;
void doFlush() final;

View File

@@ -110,7 +110,7 @@ void SdccParser::stdError(const QString &line)
return;
}
re.setPattern("^(.+\\.\\S+):(\\d+): (syntax error): (.+)$");
re.setPattern("^(.+\\.\\S+):(\\d+): (Error|error|syntax error): (.+)$");
match = re.match(lne);
if (match.hasMatch()) {
enum CaptureIndex { FilePathIndex = 1, LineNumberIndex,
@@ -125,7 +125,7 @@ void SdccParser::stdError(const QString &line)
return;
}
re.setPattern("^at (\\d+): (error) \\d+: (.+)$");
re.setPattern("^at (\\d+): (warning|error) \\d+: (.+)$");
match = re.match(lne);
if (match.hasMatch()) {
enum CaptureIndex { MessageCodeIndex = 1, MessageTypeIndex, MessageTextIndex };
@@ -208,6 +208,18 @@ void BareMetalPlugin::testSdccOutputParsers_data()
// Compiler messages.
QTest::newRow("Assembler error")
<< QString::fromLatin1("c:\\foo\\main.c:63: Error: Some error")
<< OutputParserTester::STDERR
<< QString()
<< QString::fromLatin1("c:\\foo\\main.c:63: Error: Some error\n")
<< (Tasks() << Task(Task::Error,
QLatin1String("Some error"),
Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
63,
categoryCompile))
<< QString();
QTest::newRow("Compiler single line warning")
<< QString::fromLatin1("c:\\foo\\main.c:63: warning 123: Some warning")
<< OutputParserTester::STDERR
@@ -238,6 +250,18 @@ void BareMetalPlugin::testSdccOutputParsers_data()
categoryCompile))
<< QString();
QTest::newRow("Compiler simple single line error")
<< QString::fromLatin1("c:\\foo\\main.c:63: error: Some error")
<< OutputParserTester::STDERR
<< QString()
<< QString::fromLatin1("c:\\foo\\main.c:63: error: Some error\n")
<< (Tasks() << Task(Task::Error,
QLatin1String("Some error"),
Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
63,
categoryCompile))
<< QString();
QTest::newRow("Compiler single line error")
<< QString::fromLatin1("c:\\foo\\main.c:63: error 123: Some error")
<< OutputParserTester::STDERR
@@ -292,6 +316,18 @@ void BareMetalPlugin::testSdccOutputParsers_data()
categoryCompile))
<< QString();
QTest::newRow("Compiler bad option warning")
<< QString::fromLatin1("at 1: warning 123: Some warning")
<< OutputParserTester::STDERR
<< QString()
<< QString::fromLatin1("at 1: warning 123: Some warning\n")
<< (Tasks() << Task(Task::Warning,
QLatin1String("Some warning"),
Utils::FilePath(),
-1,
categoryCompile))
<< QString();
QTest::newRow("Linker warning")
<< QString::fromLatin1("?ASlink-Warning-Couldn't find library 'foo.lib'")
<< OutputParserTester::STDERR

View File

@@ -328,7 +328,7 @@ DeploymentData CMakeBuildConfiguration::deploymentData() const
for (const CMakeBuildTarget &ct : m_buildTargets) {
if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType) {
if (!ct.executable.isEmpty()
&& !result.deployableForLocalFile(ct.executable).isValid()) {
&& result.deployableForLocalFile(ct.executable).localFilePath() != ct.executable) {
result.addFile(ct.executable.toString(),
deploymentPrefix + buildDir.relativeFilePath(ct.executable.toFileInfo().dir().path()),
DeployableFile::TypeExecutable);
@@ -652,10 +652,9 @@ QList<BuildInfo> CMakeBuildConfigurationFactory::availableBuilds(const Kit *k,
for (int type = BuildTypeDebug; type != BuildTypeLast; ++type) {
BuildInfo info = createBuildInfo(k, path.toString(), BuildType(type));
if (forSetup) {
info.displayName = info.typeName;
info.buildDirectory = CMakeBuildConfiguration::shadowBuildDirectory(projectPath,
k,
info.displayName,
info.typeName,
info.buildType);
}
result << info;
@@ -676,26 +675,28 @@ BuildInfo CMakeBuildConfigurationFactory::createBuildInfo(const Kit *k,
CMakeConfigItem buildTypeItem;
switch (buildType) {
case BuildTypeNone:
info.typeName = tr("Build");
info.typeName = "Build";
info.displayName = tr("Build");
info.buildType = BuildConfiguration::Unknown;
break;
case BuildTypeDebug:
buildTypeItem = {CMakeConfigItem("CMAKE_BUILD_TYPE", "Debug")};
info.typeName = tr("Debug");
info.typeName = "Debug";
info.displayName = tr("Debug");
info.buildType = BuildConfiguration::Debug;
break;
case BuildTypeRelease:
buildTypeItem = {CMakeConfigItem("CMAKE_BUILD_TYPE", "Release")};
info.typeName = tr("Release");
info.typeName = "Release";
info.displayName = tr("Release");
info.buildType = BuildConfiguration::Release;
break;
case BuildTypeMinSizeRel:
buildTypeItem = {CMakeConfigItem("CMAKE_BUILD_TYPE", "MinSizeRel")};
info.typeName = tr("Minimum Size Release");
info.typeName = "MinSizeRel";
info.displayName = tr("Minimum Size Release");
info.buildType = BuildConfiguration::Release;
break;
case BuildTypeRelWithDebInfo:
buildTypeItem = {CMakeConfigItem("CMAKE_BUILD_TYPE", "RelWithDebInfo")};
info.typeName = tr("Release with Debug Information");
info.typeName = "RelWithDebInfo";
info.displayName = tr("Release with Debug Information");
info.buildType = BuildConfiguration::Profile;
break;
default:
@@ -703,6 +704,8 @@ BuildInfo CMakeBuildConfigurationFactory::createBuildInfo(const Kit *k,
break;
}
buildTypeItem = {CMakeConfigItem("CMAKE_BUILD_TYPE", info.typeName.toUtf8())};
if (!buildTypeItem.isNull())
extra.configuration.append(buildTypeItem);

View File

@@ -319,6 +319,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
});
QModelIndex idx = m_configModel->indexForItem(item);
idx = m_configTextFilterModel->mapFromSource(m_configFilterModel->mapFromSource(idx));
m_configView->setFocus();
m_configView->scrollTo(idx);
m_configView->setCurrentIndex(idx);
m_configView->edit(idx);

View File

@@ -87,7 +87,7 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl) :
if (m_buildTarget.isEmpty())
setBuildTarget(defaultBuildTarget());
setLowPriorityIfConfigured();
setLowPriority();
connect(target(), &Target::kitChanged, this, &CMakeBuildStep::cmakeCommandChanged);
connect(project(), &Project::parsingFinished,

View File

@@ -167,8 +167,7 @@ void CMakeTool::setFilePath(const Utils::FilePath &executable)
if (m_executable == executable)
return;
m_introspection->m_didRun = false;
m_introspection->m_didAttemptToRun = false;
m_introspection = std::make_unique<Internal::IntrospectionData>();
m_executable = executable;
CMakeToolManager::notifyAboutUpdate(this);

View File

@@ -176,7 +176,7 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
: QIcon::Disabled;
QRect iconRect(0, 0, Constants::MODEBAR_ICON_SIZE, Constants::MODEBAR_ICON_SIZE);
const bool isTitledAction = defaultAction()->property("titledAction").toBool();
const bool isTitledAction = defaultAction() && defaultAction()->property("titledAction").toBool();
// draw popup texts
if (isTitledAction && !m_iconsOnly) {
QFont normalFont(painter.font());
@@ -286,7 +286,7 @@ QSize FancyToolButton::sizeHint() const
}
QSizeF buttonSize = iconSize().expandedTo(QSize(64, 38));
if (defaultAction()->property("titledAction").toBool()) {
if (defaultAction() && defaultAction()->property("titledAction").toBool()) {
QFont boldFont(font());
boldFont.setPointSizeF(StyleHelper::sidebarFontSize());
boldFont.setBold(true);

View File

@@ -80,12 +80,6 @@ void registerDocumentation(const QStringList &files)
m_instance->registerDocumentation(files);
}
void unregisterDocumentation(const QStringList &nameSpaces)
{
if (checkInstance())
m_instance->unregisterDocumentation(nameSpaces);
}
QMap<QString, QUrl> linksForIdentifier(const QString &id)
{
return checkInstance() ? m_instance->linksForIdentifier(id) : QMap<QString, QUrl>();

View File

@@ -61,7 +61,6 @@ enum HelpViewerLocation {
CORE_EXPORT QString documentationPath();
CORE_EXPORT void registerDocumentation(const QStringList &fileNames);
CORE_EXPORT void unregisterDocumentation(const QStringList &nameSpaces);
CORE_EXPORT QMap<QString, QUrl> linksForIdentifier(const QString &id);
CORE_EXPORT QMap<QString, QUrl> linksForKeyword(const QString &id);

View File

@@ -39,7 +39,6 @@ protected:
public:
virtual void registerDocumentation(const QStringList &fileNames) = 0;
virtual void unregisterDocumentation(const QStringList &nameSpaces) = 0;
virtual QMap<QString, QUrl> linksForIdentifier(const QString &id) = 0;
virtual QMap<QString, QUrl> linksForKeyword(const QString &keyword) = 0;
virtual QByteArray fileData(const QUrl &url) = 0;

View File

@@ -238,6 +238,9 @@ void ModeManager::removeMode(IMode *mode)
{
const int index = d->m_modes.indexOf(mode);
d->m_modes.remove(index);
if (d->m_startingUp)
return;
d->m_modeCommands.remove(index);
d->m_modeStack->removeTab(index);

View File

@@ -115,6 +115,7 @@ IOutputPane::~IOutputPane()
const int i = Utils::indexOf(g_outputPanes, Utils::equal(&OutputPaneData::pane, this));
QTC_ASSERT(i >= 0, return);
delete g_outputPanes.at(i).button;
g_outputPanes.removeAt(i);
delete m_zoomInButton;
delete m_zoomOutButton;

View File

@@ -1813,6 +1813,7 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &
{QString::fromLatin1("ToolChain Type"), part->toolchainType.toString()},
{QString::fromLatin1("ToolChain Target Triple"), part->toolChainTargetTriple},
{QString::fromLatin1("ToolChain Word Width"), CMI::Utils::toString(part->toolChainWordWidth)},
{QString::fromLatin1("ToolChain Install Dir"), part->toolChainInstallDir.toString()},
{QString::fromLatin1("Language Version"), CMI::Utils::toString(part->languageVersion)},
{QString::fromLatin1("Language Extensions"), CMI::Utils::toString(part->languageExtensions)},
{QString::fromLatin1("Qt Version"), CMI::Utils::toString(part->qtVersion)}

View File

@@ -381,7 +381,7 @@ CppIncludeHierarchyWidget::CppIncludeHierarchyWidget()
m_delegate.setAnnotationRole(AnnotationRole);
m_inspectedFile = new TextEditorLinkLabel(this);
m_inspectedFile->setMargin(5);
m_inspectedFile->setContentsMargins(5, 5, 5, 5);
m_treeView = new CppIncludeHierarchyTreeView;
m_treeView->setModel(&m_model);

View File

@@ -91,7 +91,7 @@ namespace Internal {
CppTypeHierarchyWidget::CppTypeHierarchyWidget()
{
m_inspectedClass = new TextEditor::TextEditorLinkLabel(this);
m_inspectedClass->setMargin(5);
m_inspectedClass->setContentsMargins(5, 5, 5, 5);
m_model = new CppTypeHierarchyModel(this);
m_treeView = new NavigationTreeView(this);
m_treeView->setActivationMode(SingleClickActivation);

View File

@@ -529,6 +529,7 @@ void Dumper::dumpProjectInfos( const QList<ProjectInfo> &projectInfos)
m_out << i3 << "ToolChain Type : " << part->toolchainType.toString() << "\n";
m_out << i3 << "ToolChain Target Triple: " << part->toolChainTargetTriple << "\n";
m_out << i3 << "ToolChain Word Width : " << part->toolChainWordWidth << "\n";
m_out << i3 << "ToolChain Install Dir : " << part->toolChainInstallDir << "\n";
m_out << i3 << "Compiler Flags : " << part->compilerFlags.join(", ") << "\n";
m_out << i3 << "Selected For Building : " << part->selectedForBuilding << "\n";
m_out << i3 << "Build System Target : " << part->buildSystemTarget << "\n";

View File

@@ -167,6 +167,7 @@ ProjectPart::Ptr ProjectInfoGenerator::createProjectPart(
part->isMsvc2015Toolchain = tcInfo.isMsvc2015ToolChain;
part->toolChainWordWidth = tcInfo.wordWidth == 64 ? ProjectPart::WordWidth64Bit
: ProjectPart::WordWidth32Bit;
part->toolChainInstallDir = tcInfo.installDir;
part->toolChainTargetTriple = tcInfo.targetTriple;
part->extraCodeModelFlags = tcInfo.extraCodeModelFlags;
part->compilerFlags = flags.commandLineFlags;

View File

@@ -30,9 +30,12 @@
#endif
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <QRegularExpression>
#include <utils/algorithm.h>
namespace CppTools {
using ProjectExplorer::HeaderPath;
@@ -57,6 +60,31 @@ bool HeaderPathFilter::isProjectHeaderPath(const QString &path) const
return path.startsWith(projectDirectory) || path.startsWith(buildDirectory);
}
void HeaderPathFilter::removeGccInternalIncludePaths()
{
if (projectPart.toolchainType != ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID
&& projectPart.toolchainType != ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID) {
return;
}
if (projectPart.toolChainInstallDir.isEmpty())
return;
const Utils::FilePath gccInstallDir = projectPart.toolChainInstallDir;
auto isGccInternalInclude = [gccInstallDir](const HeaderPath &headerPath){
const auto includePath = Utils::FilePath::fromString(headerPath.path);
if (includePath.isChildOf(gccInstallDir)) {
const QString remainingPath = headerPath.path.mid(gccInstallDir.toString().size());
// MinGW ships the standard library headers in "<installdir>/include/c++".
// Ensure that we do not remove include paths pointing there.
return !remainingPath.startsWith("/include/c++");
}
return false;
};
Utils::erase(builtInHeaderPaths, isGccInternalInclude);
}
void HeaderPathFilter::filterHeaderPath(const ProjectExplorer::HeaderPath &headerPath)
{
if (headerPath.path.isEmpty())
@@ -92,24 +120,19 @@ QString clangIncludeDirectory(const QString &clangVersion, const QString &clangR
#endif
}
HeaderPaths::iterator resourceIterator(HeaderPaths &headerPaths, bool isMacOs)
HeaderPaths::iterator resourceIterator(HeaderPaths &headerPaths)
{
// include/c++, include/g++, libc++\include and libc++abi\include
static const QString cppIncludes = R"((.*\/include\/.*(g\+\+|c\+\+).*))"
R"(|(.*libc\+\+\/include))"
R"(|(.*libc\+\+abi\/include))";
static const QString cppIncludes = R"((.*/include/.*(g\+\+|c\+\+).*))"
R"(|(.*libc\+\+/include))"
R"(|(.*libc\+\+abi/include))"
R"(|(/usr/local/include))";
static const QRegularExpression includeRegExp("\\A(" + cppIncludes + ")\\z");
// The same as includeRegExp but also matches /usr/local/include
static const QRegularExpression includeRegExpMac("\\A(" + cppIncludes
+ R"(|(\/usr\/local\/include))" + ")\\z");
const QRegularExpression &includePathRegEx = isMacOs ? includeRegExpMac : includeRegExp;
return std::stable_partition(headerPaths.begin(),
headerPaths.end(),
[&](const HeaderPath &headerPath) {
return includePathRegEx.match(headerPath.path).hasMatch();
return includeRegExp.match(headerPath.path).hasMatch();
});
}
@@ -120,7 +143,7 @@ bool isClangSystemHeaderPath(const HeaderPath &headerPath)
// For example GCC on macOS uses system clang include path which makes clang code model
// include incorrect system headers.
static const QRegularExpression clangIncludeDir(
R"(\A.*\/lib\d*\/clang\/\d+\.\d+(\.\d+)?\/include\z)");
R"(\A.*/lib\d*/clang/\d+\.\d+(\.\d+)?/include\z)");
return clangIncludeDir.match(headerPath.path).hasMatch();
}
@@ -135,9 +158,9 @@ void removeClangSystemHeaderPaths(HeaderPaths &headerPaths)
void HeaderPathFilter::tweakHeaderPaths()
{
removeClangSystemHeaderPaths(builtInHeaderPaths);
removeGccInternalIncludePaths();
auto split = resourceIterator(builtInHeaderPaths,
projectPart.toolChainTargetTriple.contains("darwin"));
auto split = resourceIterator(builtInHeaderPaths);
if (!clangVersion.isEmpty()) {
const QString clangIncludePath = clangIncludeDirectory(clangVersion, clangResourceDirectory);

View File

@@ -57,6 +57,8 @@ private:
bool isProjectHeaderPath(const QString &path) const;
void removeGccInternalIncludePaths();
static QString ensurePathWithSlashEnding(const QString &path);
public:

View File

@@ -42,6 +42,7 @@
#include <cplusplus/Token.h>
#include <utils/cpplanguage_details.h>
#include <utils/fileutils.h>
#include <QString>
#include <QSharedPointer>
@@ -108,6 +109,7 @@ public:
bool isMsvc2015Toolchain = false;
QString toolChainTargetTriple;
ToolChainWordWidth toolChainWordWidth = WordWidth32Bit;
Utils::FilePath toolChainInstallDir;
ProjectExplorer::WarningFlags warningFlags = ProjectExplorer::WarningFlags::Default;
// Misc

View File

@@ -345,6 +345,7 @@ private:
Utils::PathChooser *m_pathChooserFileName;
QLabel *m_labelLineNumber;
QLineEdit *m_lineEditLineNumber;
QCheckBox *m_checkBoxPropagate;
QLabel *m_labelEnabled;
QCheckBox *m_checkBoxEnabled;
QLabel *m_labelAddress;
@@ -501,6 +502,11 @@ BreakpointDialog::BreakpointDialog(unsigned int enabledParts, QWidget *parent)
m_labelThreadSpec = new QLabel(tr("&Thread specification:"), groupBoxAdvanced);
m_labelThreadSpec->setBuddy(m_lineEditThreadSpec);
m_checkBoxPropagate = new QCheckBox(tr("Propagate Change to Preset Breakpoint"), this);
m_checkBoxPropagate->setCheckable(true);
m_checkBoxPropagate->setChecked(true);
m_checkBoxPropagate->setVisible(false); // FIXME: Make it work.
m_buttonBox = new QDialogButtonBox(this);
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
@@ -538,6 +544,8 @@ BreakpointDialog::BreakpointDialog(unsigned int enabledParts, QWidget *parent)
verticalLayout->addSpacing(10);
verticalLayout->addWidget(groupBoxAdvanced);
verticalLayout->addSpacing(10);
verticalLayout->addWidget(m_checkBoxPropagate);
verticalLayout->addSpacing(10);
verticalLayout->addWidget(m_buttonBox);
verticalLayout->setStretchFactor(groupBoxAdvanced, 10);

View File

@@ -832,7 +832,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
QTC_ASSERT(vbox, return);
auto label = new QLabel(widget);
label->setText(text);
label->setMargin(6);
label->setContentsMargins(6, 6, 6, 6);
vbox->insertWidget(0, label);
};

View File

@@ -567,6 +567,7 @@ void LogWindow::doOutput()
if (m_queuedOutput.isEmpty())
return;
if (theGlobalLog)
theGlobalLog->doOutput(m_queuedOutput);
QTextCursor cursor = m_combinedText->textCursor();
@@ -706,6 +707,7 @@ GlobalLogWindow::GlobalLogWindow()
GlobalLogWindow::~GlobalLogWindow()
{
theGlobalLog = nullptr;
}
void GlobalLogWindow::doOutput(const QString &output)

View File

@@ -27,7 +27,6 @@
#include "helpconstants.h"
#include "helpmanager.h"
#include <coreplugin/helpmanager.h>
#include <utils/algorithm.h>
#include <QFileDialog>
@@ -244,7 +243,7 @@ void DocSettingsPage::addDocumentation()
void DocSettingsPage::apply()
{
Core::HelpManager::unregisterDocumentation(m_filesToUnregister.keys());
HelpManager::unregisterNamespaces(m_filesToUnregister.keys());
QStringList files;
auto it = m_filesToRegisterUserManaged.constBegin();
while (it != m_filesToRegisterUserManaged.constEnd()) {

View File

@@ -172,7 +172,7 @@ void HelpManager::registerDocumentationNow(QFutureInterface<bool> &futureInterfa
futureInterface.reportResult(docsChanged);
}
void HelpManager::unregisterDocumentation(const QStringList &nameSpaces)
void HelpManager::unregisterNamespaces(const QStringList &nameSpaces)
{
if (d->m_needsSetup) {
for (const QString &name : nameSpaces)
@@ -372,7 +372,7 @@ void HelpManager::setupHelpManager()
d->cleanUpDocumentation();
if (!d->m_nameSpacesToUnregister.isEmpty()) {
m_instance->unregisterDocumentation(Utils::toList(d->m_nameSpacesToUnregister));
m_instance->unregisterNamespaces(Utils::toList(d->m_nameSpacesToUnregister));
d->m_nameSpacesToUnregister.clear();
}

View File

@@ -49,7 +49,8 @@ public:
static QString collectionFilePath();
void registerDocumentation(const QStringList &fileNames) override;
void unregisterDocumentation(const QStringList &nameSpaces) override;
static void unregisterNamespaces(const QStringList &nameSpaces);
static void registerUserDocumentation(const QStringList &filePaths);
static QSet<QString> userDocumentationPaths();

View File

@@ -311,79 +311,113 @@ signals:
void changed();
};
McuSupportOptions::McuSupportOptions(QObject *parent)
: QObject(parent)
static PackageOptions* createQulPackage()
{
auto qulPackage = new PackageOptions(
auto result = new PackageOptions(
McuSupportOptionsPage::tr("Qt MCU SDK"),
QDir::homePath(),
Utils::HostOsInfo::withExecutableSuffix("bin/qmltocpp"),
"qulSdk");
qulPackage->setEnvironmentVariableName("Qul_DIR");
result->setEnvironmentVariableName("Qul_DIR");
return result;
}
const QString armGccDefaultPath =
static PackageOptions* createArmGccPackage()
{
const QString defaultPath =
Utils::HostOsInfo::isWindowsHost() ?
QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles(x86)"))
+ "/GNU Tools ARM Embedded/"
: QString("%{Env:ARMGCC_DIR}");
auto armGcc = new PackageOptions(
auto result = new PackageOptions(
McuSupportOptionsPage::tr("GNU Arm Embedded Toolchain"),
armGccDefaultPath,
defaultPath,
Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"),
Constants::SETTINGS_KEY_PACKAGE_ARMGCC);
armGcc->setDownloadUrl(
result->setDownloadUrl(
QUrl::fromUserInput("https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads"));
armGcc->setEnvironmentVariableName("ARMGCC_DIR");
toolchainPackage = armGcc;
result->setEnvironmentVariableName("ARMGCC_DIR");
return result;
}
auto stm32CubeFwF7Sdk = new PackageOptions(
static PackageOptions* createStm32CubeFwF7SdkPackage()
{
auto result = new PackageOptions(
McuSupportOptionsPage::tr("STM32Cube SDK"),
"%{Env:STM32Cube_FW_F7_SDK_PATH}",
"Drivers/STM32F7xx_HAL_Driver",
"stm32CubeFwF7Sdk");
stm32CubeFwF7Sdk->setDownloadUrl(
result->setDownloadUrl(
QUrl::fromUserInput("https://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-mcu-packages/stm32cubef7.html"));
stm32CubeFwF7Sdk->setEnvironmentVariableName("STM32Cube_FW_F7_SDK_PATH");
result->setEnvironmentVariableName("STM32Cube_FW_F7_SDK_PATH");
return result;
}
const QString stm32CubeProgrammerDefaultPath =
static PackageOptions* createStm32CubeProgrammerPackage()
{
const QString defaultPath =
Utils::HostOsInfo::isWindowsHost() ?
QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles"))
+ "/STMicroelectronics/STM32Cube/STM32CubeProgrammer/"
: QDir::homePath();
auto stm32CubeProgrammer = new PackageOptions(
auto result = new PackageOptions(
McuSupportOptionsPage::tr("STM32CubeProgrammer"),
stm32CubeProgrammerDefaultPath,
defaultPath,
"bin",
"stm32CubeProgrammer");
stm32CubeProgrammer->setDownloadUrl(
result->setDownloadUrl(
QUrl::fromUserInput("https://www.st.com/en/development-tools/stm32cubeprog.html"));
stm32CubeProgrammer->setAddToPath(true);
result->setAddToPath(true);
return result;
}
auto evkbImxrt1050Sdk = new PackageOptions(
static PackageOptions* createEvkbImxrt1050SdkPackage()
{
auto result = new PackageOptions(
McuSupportOptionsPage::tr("NXP EVKB-IMXRT1050 SDK"),
"%{Env:EVKB_IMXRT1050_SDK_PATH}",
"EVKB-IMXRT1050_manifest_v3_5.xml",
"evkbImxrt1050Sdk");
evkbImxrt1050Sdk->setDownloadUrl(
result->setDownloadUrl(
QUrl::fromUserInput("https://mcuxpresso.nxp.com/en/welcome"));
return result;
}
const QString seggerJLinkDefaultPath =
static PackageOptions* createSeggerJLinkPackage()
{
const QString defaultPath =
Utils::HostOsInfo::isWindowsHost() ?
QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles")) + "/SEGGER/JLink"
: QString("%{Env:SEGGER_JLINK_SOFTWARE_AND_DOCUMENTATION_PATH}");
auto seggerJLink = new PackageOptions(
auto result = new PackageOptions(
McuSupportOptionsPage::tr("SEGGER JLink"),
seggerJLinkDefaultPath,
defaultPath,
Utils::HostOsInfo::withExecutableSuffix("JLink"),
"seggerJLink");
seggerJLink->setDownloadUrl(
result->setDownloadUrl(
QUrl::fromUserInput("https://www.segger.com/downloads/jlink"));
return result;
}
auto stmPackages = {armGcc, stm32CubeFwF7Sdk, stm32CubeProgrammer, qulPackage};
auto nxpPackages = {armGcc, evkbImxrt1050Sdk, seggerJLink, qulPackage};
packages = {armGcc, stm32CubeFwF7Sdk, stm32CubeProgrammer,
evkbImxrt1050Sdk, seggerJLink,
McuSupportOptions::McuSupportOptions(QObject *parent)
: QObject(parent)
{
PackageOptions* qulPackage = createQulPackage();
PackageOptions* armGccPackage = createArmGccPackage();
PackageOptions* stm32CubeFwF7SdkPackage = createStm32CubeFwF7SdkPackage();
PackageOptions* stm32CubeProgrammerPackage = createStm32CubeProgrammerPackage();
PackageOptions* evkbImxrt1050SdkPackage = createEvkbImxrt1050SdkPackage();
PackageOptions* seggerJLinkPackage = createSeggerJLinkPackage();
toolchainPackage = armGccPackage;
auto stmPackages = {armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage,
qulPackage};
auto nxpPackages = {armGccPackage, evkbImxrt1050SdkPackage, seggerJLinkPackage,
qulPackage};
packages = {armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage,
evkbImxrt1050SdkPackage, seggerJLinkPackage, qulPackage};
boards.append(new BoardOptions(
"stm32f7508", "CMake/stm32f7508-discovery.cmake", stmPackages));

View File

@@ -33,6 +33,8 @@
#include <projectexplorer/project.h>
#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <cmakeprojectmanager/cmakekitinformation.h>
#include <cmakeprojectmanager/cmaketool.h>
using namespace ProjectExplorer;
using namespace Utils;
@@ -42,9 +44,17 @@ namespace Internal {
static CommandLine flashAndRunCommand(Target *target)
{
BuildConfiguration *bc = target->activeBuildConfiguration();
const QString projectName = target->project()->displayName();
return CommandLine(bc->environment().searchInPath("cmake"), {});
const CMakeProjectManager::CMakeTool *tool =
CMakeProjectManager::CMakeKitAspect::cmakeTool(target->kit());
return CommandLine(tool->filePath(), {
"--build",
".",
"--target",
QString("flash_%1_and_bootloader").arg(projectName)
});
}
class FlashAndRunConfiguration : public ProjectExplorer::RunConfiguration
@@ -57,6 +67,17 @@ public:
effectiveFlashAndRunCall->setLabelText(tr("Effective flash and run call:"));
effectiveFlashAndRunCall->setDisplayStyle(BaseStringAspect::TextEditDisplay);
effectiveFlashAndRunCall->setReadOnly(true);
auto updateConfiguration = [target, effectiveFlashAndRunCall] {
effectiveFlashAndRunCall->setValue(flashAndRunCommand(target).toUserOutput());
};
updateConfiguration();
connect(target->activeBuildConfiguration(), &BuildConfiguration::buildDirectoryChanged,
this, updateConfiguration);
connect(target->project(), &Project::displayNameChanged,
this, updateConfiguration);
}
};
@@ -67,8 +88,11 @@ public:
: SimpleTargetRunner(runControl)
{
setStarter([this, runControl] {
CommandLine cmd = flashAndRunCommand(runControl->target());
ProjectExplorer::Target *target = runControl->target();
const CommandLine cmd = flashAndRunCommand(target);
Runnable r;
r.workingDirectory =
target->activeBuildConfiguration()->buildDirectory().toUserOutput();
r.setCommandLine(cmd);
SimpleTargetRunner::doStart(r, {});
});

View File

@@ -5,6 +5,6 @@ project(%{ProjectName} VERSION 0.0.1 LANGUAGES CXX)
find_package(Qul)
add_executable(%{ProjectName})
QUL_ADD_QML(%{ProjectName} %{MainQmlFile})
qul_target_qml_sources(%{ProjectName} %{MainQmlFile})
target_link_libraries(%{ProjectName} Qul::QuickUltralite)

View File

@@ -1,5 +1,5 @@
pragma main;
import QtQuick
import QtQuick 2.0
Rectangle {
width: 480
@@ -9,5 +9,6 @@ Rectangle {
anchors.centerIn: parent
color: "salmon"
text: "Hello World!"
font.pixelSize: 14
}
}

View File

@@ -188,7 +188,10 @@ void AbiWidget::setAbis(const Abis &abiList, const Abi &currentAbi)
setCustomAbiComboBoxes(defaultAbi);
}
emitAbiChanged(defaultAbi);
// Update disabled state according to new automatically selected item in main ABI combobox.
// This will call emitAbiChanged with the actual selected ABI.
mainComboBoxChanged();
}
Abis AbiWidget::supportedAbis() const

View File

@@ -230,7 +230,7 @@ void AbstractProcessStep::doRun()
d->m_process->setWorkingDirectory(wd.absolutePath());
d->m_process->setEnvironment(d->m_param.environment());
d->m_process->setCommand(effectiveCommand);
if (d->m_lowPriority)
if (d->m_lowPriority && ProjectExplorerPlugin::projectExplorerSettings().lowBuildPriority)
d->m_process->setLowPriority();
connect(d->m_process.get(), &QProcess::readyReadStandardOutput,
@@ -251,9 +251,8 @@ void AbstractProcessStep::doRun()
processStarted();
}
void AbstractProcessStep::setLowPriorityIfConfigured()
void AbstractProcessStep::setLowPriority()
{
if (ProjectExplorerPlugin::projectExplorerSettings().lowBuildPriority)
d->m_lowPriority = true;
}

View File

@@ -57,7 +57,7 @@ protected:
~AbstractProcessStep() override;
bool init() override;
void doRun() override;
void setLowPriorityIfConfigured();
void setLowPriority();
virtual void finish(bool success);
virtual void processStarted();

View File

@@ -57,8 +57,15 @@ void DeploymentData::addFile(const QString &localFilePath, const QString &remote
DeployableFile DeploymentData::deployableForLocalFile(const Utils::FilePath &localFilePath) const
{
return Utils::findOrDefault(m_files,
Utils::equal(&DeployableFile::localFilePath, localFilePath));
const DeployableFile f = Utils::findOrDefault(m_files,
Utils::equal(&DeployableFile::localFilePath,
localFilePath));
if (f.isValid())
return f;
const QString localFileName = localFilePath.fileName();
return Utils::findOrDefault(m_files, [&localFileName](const DeployableFile &d) {
return d.localFilePath().fileName() == localFileName;
});
}
bool DeploymentData::operator==(const DeploymentData &other) const

View File

@@ -232,6 +232,23 @@ static QString gccVersion(const FilePath &path, const QStringList &env)
return QString::fromLocal8Bit(runGcc(path, arguments, env)).trimmed();
}
static Utils::FilePath gccInstallDir(const FilePath &path, const QStringList &env)
{
const QStringList arguments("-print-search-dirs");
QString output = QString::fromLocal8Bit(runGcc(path, arguments, env)).trimmed();
// Expected output looks like this:
// install: /usr/lib/gcc/x86_64-linux-gnu/7/
// ...
// Note that clang also supports "-print-search-dirs". However, the
// install dir is not part of the output (tested with clang-8/clang-9).
const QString prefix = "install: ";
const QString line = QTextStream(&output).readLine();
if (!line.startsWith(prefix))
return {};
return Utils::FilePath::fromString(QDir::cleanPath(line.mid(prefix.size())));
}
// --------------------------------------------------------------------------
// GccToolChain
// --------------------------------------------------------------------------
@@ -269,6 +286,15 @@ void GccToolChain::setOriginalTargetTriple(const QString &targetTriple)
toolChainUpdated();
}
void GccToolChain::setInstallDir(const Utils::FilePath &installDir)
{
if (m_installDir == installDir)
return;
m_installDir = installDir;
toolChainUpdated();
}
QString GccToolChain::defaultDisplayName() const
{
QString type = typeDisplayName();
@@ -310,6 +336,13 @@ QString GccToolChain::version() const
return m_version;
}
FilePath GccToolChain::installDir() const
{
if (m_installDir.isEmpty())
m_installDir = detectInstallDir();
return m_installDir;
}
void GccToolChain::setTargetAbi(const Abi &abi)
{
if (abi == m_targetAbi)
@@ -715,6 +748,7 @@ void GccToolChain::resetToolChain(const FilePath &path)
const DetectedAbisResult detectedAbis = detectSupportedAbis();
m_supportedAbis = detectedAbis.supportedAbis;
m_originalTargetTriple = detectedAbis.originalTargetTriple;
m_installDir = installDir();
m_targetAbi = Abi();
if (!m_supportedAbis.isEmpty()) {
@@ -856,6 +890,13 @@ QString GccToolChain::detectVersion() const
return gccVersion(findLocalCompiler(m_compilerCommand, env), env.toStringList());
}
Utils::FilePath GccToolChain::detectInstallDir() const
{
Environment env = Environment::systemEnvironment();
addToEnvironment(env);
return gccInstallDir(findLocalCompiler(m_compilerCommand, env), env.toStringList());
}
// --------------------------------------------------------------------------
// GccToolChainFactory
// --------------------------------------------------------------------------
@@ -1119,6 +1160,9 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const ToolChainDescr
const GccToolChain::DetectedAbisResult detectedAbis = guessGccAbi(localCompilerPath,
systemEnvironment.toStringList(),
macros);
const Utils::FilePath installDir = gccInstallDir(localCompilerPath,
systemEnvironment.toStringList());
for (const Abi &abi : detectedAbis.supportedAbis) {
std::unique_ptr<GccToolChain> tc(dynamic_cast<GccToolChain *>(create()));
if (!tc)
@@ -1134,6 +1178,7 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const ToolChainDescr
tc->setSupportedAbis(detectedAbis.supportedAbis);
tc->setTargetAbi(abi);
tc->setOriginalTargetTriple(detectedAbis.originalTargetTriple);
tc->setInstallDir(installDir);
tc->setDisplayName(tc->defaultDisplayName()); // reset displayname
if (!checker || checker(tc.get()))
result.append(tc.release());
@@ -1192,6 +1237,7 @@ void GccToolChainConfigWidget::applyImpl()
tc->setSupportedAbis(m_abiWidget->supportedAbis());
tc->setTargetAbi(m_abiWidget->currentAbi());
}
tc->setInstallDir(tc->detectInstallDir());
tc->setOriginalTargetTriple(tc->detectSupportedAbis().originalTargetTriple);
tc->setDisplayName(displayName); // reset display name
tc->setPlatformCodeGenFlags(splitString(m_platformCodeGenFlagsLineEdit->text()));

View File

@@ -71,6 +71,7 @@ public:
Abi targetAbi() const override;
QString originalTargetTriple() const override;
Utils::FilePath installDir() const override;
QString version() const;
Abis supportedAbis() const override;
void setTargetAbi(const Abi &);
@@ -129,6 +130,7 @@ protected:
void setCompilerCommand(const Utils::FilePath &path);
void setSupportedAbis(const Abis &abis);
void setOriginalTargetTriple(const QString &targetTriple);
void setInstallDir(const Utils::FilePath &installDir);
void setMacroCache(const QStringList &allCxxflags, const Macros &macroCache) const;
Macros macroCache(const QStringList &allCxxflags) const;
@@ -137,6 +139,7 @@ protected:
virtual DetectedAbisResult detectSupportedAbis() const;
virtual QString detectVersion() const;
virtual Utils::FilePath detectInstallDir() const;
// Reinterpret options for compiler drivers inheriting from GccToolChain (e.g qcc) to apply -Wp option
// that passes the initial options directly down to the gcc compiler
@@ -196,6 +199,7 @@ private:
mutable QString m_originalTargetTriple;
mutable HeaderPaths m_headerPaths;
mutable QString m_version;
mutable Utils::FilePath m_installDir;
friend class Internal::GccToolChainConfigWidget;
friend class Internal::GccToolChainFactory;

View File

@@ -65,7 +65,7 @@ MakeStep::MakeStep(BuildStepList *parent, Core::Id id)
m_userJobCount(defaultJobCount())
{
setDefaultDisplayName(defaultDisplayName());
setLowPriorityIfConfigured();
setLowPriority();
}
void MakeStep::setBuildTarget(const QString &buildTarget)

View File

@@ -725,7 +725,7 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi
m_kitAreaWidget = new KitAreaWidget(this);
m_summaryLabel = new QLabel(this);
m_summaryLabel->setMargin(3);
m_summaryLabel->setContentsMargins(3, 3, 3, 3);
m_summaryLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
m_summaryLabel->setStyleSheet(QString::fromLatin1("background: %1;")
.arg(creatorTheme()->color(Theme::MiniProjectTargetSelectorSummaryBackgroundColor).name()));

View File

@@ -776,6 +776,8 @@ void MsvcToolChain::updateEnvironmentModifications(Utils::EnvironmentItems modif
void MsvcToolChain::detectInstalledAbis()
{
if (!m_supportedAbis.isEmpty()) // Build Tools 2015
return;
static QMap<QString, Abis> abiCache;
const QString vcVarsBase
= QDir::fromNativeSeparators(m_vcvarsBat).left(m_vcvarsBat.lastIndexOf('/'));
@@ -1251,6 +1253,13 @@ void MsvcToolChain::resetVarsBat()
m_varsBatArg.clear();
}
void MsvcToolChain::setSupportedAbi(const Abi &abi)
{
// Hack for Build Tools 2015 only.
QTC_CHECK(m_supportedAbis.isEmpty());
m_supportedAbis = { abi };
}
// --------------------------------------------------------------------------
// MsvcBasedToolChainConfigWidget: Creates a simple GUI without error label
// to display name and varsBat. Derived classes should add the error label and
@@ -1855,6 +1864,7 @@ static void detectCppBuildTools2015(QList<ToolChain *> *list)
tc->setDisplayName(name + QLatin1String(e.postFix));
tc->setDetection(ToolChain::AutoDetection);
tc->setLanguage(language);
tc->setSupportedAbi(abi);
list->append(tc);
}
}

View File

@@ -95,6 +95,8 @@ public:
void setupVarsBat(const Abi &abi, const QString &varsBat, const QString &varsBatArg);
void resetVarsBat();
void setSupportedAbi(const Abi &abi);
bool operator==(const ToolChain &) const override;
bool isJobCountSupported() const override { return false; }

View File

@@ -2772,6 +2772,8 @@ QPair<bool, QString> ProjectExplorerPluginPrivate::buildSettingsEnabledForSessio
bool ProjectExplorerPlugin::coreAboutToClose()
{
if (!m_instance)
return true;
if (BuildManager::isBuilding()) {
QMessageBox box;
QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Close"), QMessageBox::AcceptRole);

View File

@@ -184,6 +184,7 @@ ToolChainInfo::ToolChainInfo(const ToolChain *toolChain,
wordWidth = toolChain->targetAbi().wordWidth();
targetTriple = toolChain->originalTargetTriple();
extraCodeModelFlags = toolChain->extraCodeModelFlags();
installDir = toolChain->installDir();
// ...and save the potentially expensive operations for later so that
// they can be run from a worker thread.

View File

@@ -36,6 +36,7 @@
#include <utils/cpplanguage_details.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <QPointer>
@@ -152,6 +153,7 @@ public:
bool isMsvc2015ToolChain = false;
unsigned wordWidth = 0;
QString targetTriple;
Utils::FilePath installDir;
QStringList extraCodeModelFlags;
QString sysRootPath; // For headerPathsRunner.

View File

@@ -99,15 +99,15 @@ RunSettingsWidget::RunSettingsWidget(Target *target) :
m_gridLayout->setContentsMargins(0, 20, 0, 0);
m_gridLayout->setHorizontalSpacing(6);
m_gridLayout->setVerticalSpacing(8);
m_gridLayout->addWidget(deployTitle, 0, 0, 1, 6);
m_gridLayout->addWidget(deployTitle, 0, 0, 1, -1);
m_gridLayout->addWidget(deployLabel, 1, 0, 1, 1);
m_gridLayout->addWidget(m_deployConfigurationCombo, 1, 1, 1, 1);
m_gridLayout->addWidget(m_addDeployToolButton, 1, 2, 1, 1);
m_gridLayout->addWidget(m_removeDeployToolButton, 1, 3, 1, 1);
m_gridLayout->addWidget(m_renameDeployButton, 1, 4, 1, 1);
m_gridLayout->addWidget(deployWidget, 2, 0, 1, 6);
m_gridLayout->addWidget(deployWidget, 2, 0, 1, -1);
m_gridLayout->addWidget(runTitle, 3, 0, 1, 6);
m_gridLayout->addWidget(runTitle, 3, 0, 1, -1);
m_gridLayout->addWidget(runLabel, 4, 0, 1, 1);
m_gridLayout->addWidget(m_runConfigurationCombo, 4, 1, 1, 1);
m_gridLayout->addWidget(m_addRunToolButton, 4, 2, 1, 1);
@@ -115,7 +115,7 @@ RunSettingsWidget::RunSettingsWidget(Target *target) :
m_gridLayout->addWidget(m_renameRunButton, 4, 4, 1, 1);
m_gridLayout->addWidget(m_cloneRunButton, 4, 5, 1, 1);
m_gridLayout->addItem(spacer1, 4, 6, 1, 1);
m_gridLayout->addWidget(runWidget, 5, 0, 1, 6);
m_gridLayout->addWidget(runWidget, 5, 0, 1, -1);
m_gridLayout->addItem(spacer2, 6, 0, 1, 1);
// deploy part

View File

@@ -156,6 +156,8 @@ SessionManager::SessionManager(QObject *parent) : QObject(parent)
SessionManager::~SessionManager()
{
EditorManager::setWindowTitleAdditionHandler({});
EditorManager::setSessionTitleHandler({});
emit m_instance->aboutToUnloadSession(d->m_sessionName);
delete d->m_writer;
delete d;

View File

@@ -359,6 +359,7 @@ void Target::setDeploymentData(const DeploymentData &deploymentData)
if (d->m_deploymentData != deploymentData) {
d->m_deploymentData = deploymentData;
emit deploymentDataChanged();
emit applicationTargetsChanged();
}
}

View File

@@ -117,18 +117,11 @@ private:
Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
}
void kitUpdated(ProjectExplorer::Kit *k)
{
if (k == KitManager::defaultKit())
updateNoteText();
}
void completeChanged()
{
m_configureButton->setEnabled(m_targetSetupPage && m_targetSetupPage->isComplete());
}
void updateNoteText();
void addTargetSetupPage();
Project * const m_project;
@@ -161,41 +154,6 @@ TargetSetupPageWrapper::TargetSetupPageWrapper(Project *project)
this, &TargetSetupPageWrapper::done);
}
void TargetSetupPageWrapper::updateNoteText()
{
if (!m_targetSetupPage)
return;
Kit *k = KitManager::defaultKit();
QString text;
bool showHint = false;
if (!k) {
text = tr("The project <b>%1</b> is not yet configured.<br/>"
"%2 cannot parse the project, because no kit "
"has been set up.")
.arg(m_project->displayName(), Core::Constants::IDE_DISPLAY_NAME);
showHint = true;
} else if (k->isValid()) {
text = tr("The project <b>%1</b> is not yet configured.<br/>"
"%2 uses the kit <b>%3</b> to parse the project.")
.arg(m_project->displayName())
.arg(Core::Constants::IDE_DISPLAY_NAME)
.arg(k->displayName());
showHint = false;
} else {
text = tr("The project <b>%1</b> is not yet configured.<br/>"
"%2 uses the <b>invalid</b> kit <b>%3</b> to parse the project.")
.arg(m_project->displayName())
.arg(Core::Constants::IDE_DISPLAY_NAME)
.arg(k->displayName());
showHint = true;
}
m_targetSetupPage->setNoteText(text);
m_targetSetupPage->showOptionsHint(showHint);
}
void TargetSetupPageWrapper::addTargetSetupPage()
{
m_targetSetupPage = new TargetSetupPage(this);
@@ -207,16 +165,11 @@ void TargetSetupPageWrapper::addTargetSetupPage()
m_targetSetupPage->initializePage();
m_targetSetupPage->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
m_setupPageContainer->addWidget(m_targetSetupPage);
updateNoteText();
completeChanged();
connect(m_targetSetupPage, &QWizardPage::completeChanged,
this, &TargetSetupPageWrapper::completeChanged);
connect(KitManager::instance(), &KitManager::defaultkitChanged,
this, &TargetSetupPageWrapper::updateNoteText);
connect(KitManager::instance(), &KitManager::kitUpdated,
this, &TargetSetupPageWrapper::kitUpdated);
}
//
@@ -264,7 +217,7 @@ void TargetGroupItemPrivate::ensureWidget()
f.setPointSizeF(f.pointSizeF() * 1.4);
f.setBold(true);
label->setFont(f);
label->setMargin(10);
label->setContentsMargins(10, 10, 10, 10);
label->setAlignment(Qt::AlignTop);
auto layout = new QVBoxLayout(m_noKitLabel);
@@ -795,10 +748,8 @@ TargetItem *TargetGroupItem::currentTargetItem() const
TargetItem *TargetGroupItem::targetItem(Target *target) const
{
if (target) {
Id needle = target->id(); // Unconfigured project have no active target.
return findFirstLevelChild([needle](TargetItem *item) { return item->m_kitId == needle; });
}
if (target)
return findFirstLevelChild([target](TargetItem *item) { return item->target() == target; });
return nullptr;
}

View File

@@ -86,18 +86,13 @@ public:
QWidget *scrollAreaWidget;
QScrollArea *scrollArea;
QLabel *headerLabel;
QLabel *descriptionLabel;
QLabel *noValidKitLabel;
QLabel *optionHintLabel;
QCheckBox *allKitsCheckBox;
FancyLineEdit *kitFilterLineEdit;
void setupUi(TargetSetupPage *q)
{
auto setupTargetPage = new QWidget(q);
descriptionLabel = new QLabel(setupTargetPage);
descriptionLabel->setWordWrap(true);
descriptionLabel->setVisible(false);
headerLabel = new QLabel(setupTargetPage);
headerLabel->setWordWrap(true);
@@ -105,16 +100,11 @@ public:
noValidKitLabel = new QLabel(setupTargetPage);
noValidKitLabel->setWordWrap(true);
noValidKitLabel->setText(TargetSetupPage::tr("<span style=\" font-weight:600;\">No valid kits found.</span>"));
optionHintLabel = new QLabel(setupTargetPage);
optionHintLabel->setWordWrap(true);
optionHintLabel->setText(TargetSetupPage::tr(
noValidKitLabel->setText(TargetSetupPage::tr("<span style=\" font-weight:600;\">No suitable kits found.</span><br/>"
"Please add a kit in the <a href=\"buildandrun\">options</a> "
"or via the maintenance tool of the SDK."));
optionHintLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
optionHintLabel->setVisible(false);
noValidKitLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
noValidKitLabel->setVisible(false);
allKitsCheckBox = new QCheckBox(setupTargetPage);
allKitsCheckBox->setTristate(true);
@@ -146,10 +136,8 @@ public:
auto verticalLayout_2 = new QVBoxLayout(setupTargetPage);
verticalLayout_2->addWidget(headerLabel);
verticalLayout_2->addWidget(descriptionLabel);
verticalLayout_2->addWidget(kitFilterLineEdit);
verticalLayout_2->addWidget(noValidKitLabel);
verticalLayout_2->addWidget(optionHintLabel);
verticalLayout_2->addWidget(allKitsCheckBox);
verticalLayout_2->addWidget(centralWidget);
verticalLayout_2->addWidget(scrollAreaWidget);
@@ -158,7 +146,7 @@ public:
verticalLayout_3->setContentsMargins(0, 0, 0, -1);
verticalLayout_3->addWidget(setupTargetPage);
QObject::connect(optionHintLabel, &QLabel::linkActivated,
QObject::connect(noValidKitLabel, &QLabel::linkActivated,
q, &TargetSetupPage::openOptions);
QObject::connect(allKitsCheckBox, &QAbstractButton::clicked,
@@ -213,6 +201,8 @@ TargetSetupPage::TargetSetupPage(QWidget *parent) :
connect(km, &KitManager::kitUpdated, this, &TargetSetupPage::handleKitUpdate);
connect(m_importWidget, &ImportWidget::importFrom,
this, [this](const FilePath &dir) { import(dir); });
connect(KitManager::instance(), &KitManager::kitsChanged,
this, &TargetSetupPage::updateVisibility);
setProperty(SHORT_TITLE_PROPERTY, tr("Kits"));
}
@@ -224,6 +214,7 @@ void TargetSetupPage::initializePage()
setupWidgets();
setupImports();
selectAtLeastOneKit();
updateVisibility();
}
void TargetSetupPage::setRequiredKitPredicate(const Kit::Predicate &predicate)
@@ -348,18 +339,6 @@ bool TargetSetupPage::importLineEditHasFocus() const
return m_importWidget->ownsReturnKey();
}
void TargetSetupPage::setNoteText(const QString &text)
{
m_ui->descriptionLabel->setText(text);
m_ui->descriptionLabel->setVisible(!text.isEmpty());
}
void TargetSetupPage::showOptionsHint(bool show)
{
m_forceOptionHint = show;
updateVisibility();
}
void TargetSetupPage::setupImports()
{
if (!m_importer || m_projectPath.isEmpty())
@@ -446,10 +425,9 @@ void TargetSetupPage::updateVisibility()
m_ui->scrollAreaWidget->setVisible(m_baseLayout == m_ui->scrollArea->widget()->layout());
m_ui->centralWidget->setVisible(m_baseLayout == m_ui->centralWidget->layout());
bool hasKits = m_widgets.size() > 0;
m_ui->noValidKitLabel->setVisible(!hasKits);
m_ui->optionHintLabel->setVisible(m_forceOptionHint || !hasKits);
m_ui->allKitsCheckBox->setVisible(hasKits);
const bool hasUsableKits = KitManager::kit([this](const Kit *k) { return isUsable(k); });
m_ui->noValidKitLabel->setVisible(!hasUsableKits);
m_ui->allKitsCheckBox->setVisible(hasUsableKits);
emit completeChanged();
}

View File

@@ -81,10 +81,6 @@ public:
bool setupProject(Project *project);
QList<Core::Id> selectedKits() const;
/// Overrides the summary text of the targetsetuppage
void setNoteText(const QString &text);
void showOptionsHint(bool show);
void openOptions();
void changeAllKitsSelections();
@@ -139,7 +135,6 @@ private:
QSpacerItem *m_spacer;
QList<QWidget *> m_potentialWidgets;
bool m_forceOptionHint = false;
bool m_widgetsWereSetUp = false;
};

View File

@@ -38,6 +38,7 @@
#include <utils/cpplanguage_details.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <QObject>
#include <QSet>
@@ -114,6 +115,7 @@ public:
virtual ProjectExplorer::Abis supportedAbis() const;
virtual QString originalTargetTriple() const { return QString(); }
virtual QStringList extraCodeModelFlags() const { return QStringList(); }
virtual Utils::FilePath installDir() const { return Utils::FilePath(); }
virtual bool isValid() const = 0;

View File

@@ -27,6 +27,7 @@
#include "qbsbuildconfiguration.h"
#include "qbsbuildstep.h"
#include "qbsinstallstep.h"
#include "qbslogsink.h"
#include "qbspmlogging.h"
#include "qbsprojectimporter.h"
@@ -52,6 +53,7 @@
#include <projectexplorer/buildinfo.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/deployconfiguration.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/headerpath.h>
#include <projectexplorer/kit.h>
@@ -464,6 +466,16 @@ FilePath QbsProject::installRoot()
{
if (!activeTarget())
return FilePath();
const auto dc = activeTarget()->activeDeployConfiguration();
if (dc) {
const QList<BuildStep *> steps = dc->stepList()->steps();
for (const BuildStep * const step : steps) {
if (!step->enabled())
continue;
if (const auto qbsInstallStep = qobject_cast<const QbsInstallStep *>(step))
return FilePath::fromString(qbsInstallStep->installRoot());
}
}
const auto * const bc
= qobject_cast<QbsBuildConfiguration *>(activeTarget()->activeBuildConfiguration());
if (!bc)

View File

@@ -76,7 +76,7 @@ QMakeStep::QMakeStep(BuildStepList *bsl) : AbstractProcessStep(bsl, Constants::Q
{
//: QMakeStep default display name
setDefaultDisplayName(tr("qmake"));
setLowPriorityIfConfigured();
setLowPriority();
}
QmakeBuildConfiguration *QMakeStep::qmakeBuildConfiguration() const

View File

@@ -231,6 +231,7 @@ extend_qtc_plugin(QmlDesigner
snapper.cpp snapper.h
snappinglinecreator.cpp snappinglinecreator.h
toolbox.cpp toolbox.h
option3daction.cpp option3daction.h
)
extend_qtc_plugin(QmlDesigner

View File

@@ -53,10 +53,21 @@
#include <texteditor/syntaxhighlighter.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <metainfo.h>
#include <qmlmodelnodeproxy.h>
#include <variantproperty.h>
#include <bindingproperty.h>
#include <nodeabstractproperty.h>
#include <nodelistproperty.h>
#include <propertyeditorvalue.h>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QDebug>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QPlainTextEdit>
namespace QmlDesigner {
@@ -69,7 +80,7 @@ BindingEditorWidget::BindingEditorWidget()
{
Core::ICore::addContextObject(m_context);
Core::Context context(BINDINGEDITOR_CONTEXT_ID);
const Core::Context context(BINDINGEDITOR_CONTEXT_ID);
/*
* We have to register our own active auto completion shortcut, because the original short cut will
@@ -77,8 +88,12 @@ BindingEditorWidget::BindingEditorWidget()
*/
m_completionAction = new QAction(tr("Trigger Completion"), this);
Core::Command *command = Core::ActionManager::registerAction(m_completionAction, TextEditor::Constants::COMPLETE_THIS, context);
command->setDefaultKeySequence(QKeySequence(Core::useMacShortcuts ? tr("Meta+Space") : tr("Ctrl+Space")));
Core::Command *command = Core::ActionManager::registerAction(
m_completionAction, TextEditor::Constants::COMPLETE_THIS, context);
command->setDefaultKeySequence(QKeySequence(
Core::useMacShortcuts
? tr("Meta+Space")
: tr("Ctrl+Space")));
connect(m_completionAction, &QAction::triggered, [this]() {
invokeAssist(TextEditor::Completion);
@@ -95,18 +110,34 @@ BindingEditorWidget::~BindingEditorWidget()
void BindingEditorWidget::unregisterAutoCompletion()
{
if (m_completionAction)
{
if (m_completionAction) {
Core::ActionManager::unregisterAction(m_completionAction, TextEditor::Constants::COMPLETE_THIS);
delete m_completionAction;
m_completionAction = nullptr;
}
}
TextEditor::AssistInterface *BindingEditorWidget::createAssistInterface(TextEditor::AssistKind assistKind, TextEditor::AssistReason assistReason) const
bool BindingEditorWidget::event(QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
emit returnKeyClicked();
return true;
} else {
return QmlJSEditor::QmlJSEditorWidget::event(event);
}
}
return QmlJSEditor::QmlJSEditorWidget::event(event);
}
TextEditor::AssistInterface *BindingEditorWidget::createAssistInterface(
TextEditor::AssistKind assistKind, TextEditor::AssistReason assistReason) const
{
Q_UNUSED(assistKind);
return new QmlJSEditor::QmlJSCompletionAssistInterface(document(), position(), QString(), assistReason, qmljsdocument->semanticInfo());
return new QmlJSEditor::QmlJSCompletionAssistInterface(
document(), position(), QString(),
assistReason, qmljsdocument->semanticInfo());
}
class BindingDocument : public QmlJSEditor::QmlJSEditorDocument
@@ -122,18 +153,16 @@ protected:
{
TextDocument::applyFontSettings();
m_semanticHighlighter->updateFontSettings(fontSettings());
if (!isSemanticInfoOutdated()) {
if (!isSemanticInfoOutdated())
m_semanticHighlighter->rerun(semanticInfo());
}
}
void triggerPendingUpdates()
{
TextDocument::triggerPendingUpdates(); // calls applyFontSettings if necessary
if (!isSemanticInfoOutdated()) {
if (!isSemanticInfoOutdated())
m_semanticHighlighter->rerun(semanticInfo());
}
}
private:
QmlJSEditor::SemanticHighlighter *m_semanticHighlighter = nullptr;
@@ -142,7 +171,8 @@ private:
class BindingEditorFactory : public TextEditor::TextEditorFactory
{
public:
BindingEditorFactory() {
BindingEditorFactory()
{
setId(BINDINGEDITOR_CONTEXT_ID);
setDisplayName(QCoreApplication::translate("OpenWith::Editors", BINDINGEDITOR_CONTEXT_ID));
@@ -162,17 +192,14 @@ public:
static void decorateEditor(TextEditor::TextEditorWidget *editor)
{
editor->textDocument()->setSyntaxHighlighter(new QmlJSEditor::QmlJSHighlighter);
editor->textDocument()->setIndenter(new QmlJSEditor::Internal::Indenter(editor->textDocument()->document()));
editor->textDocument()->setIndenter(new QmlJSEditor::Internal::Indenter(
editor->textDocument()->document()));
editor->setAutoCompleter(new QmlJSEditor::AutoCompleter);
}
};
BindingEditorDialog::BindingEditorDialog(QWidget *parent)
: QDialog(parent)
, m_editor(nullptr)
, m_editorWidget(nullptr)
, m_verticalLayout(nullptr)
, m_buttonBox(nullptr)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setWindowTitle(tr("Binding Editor"));
@@ -185,12 +212,24 @@ BindingEditorDialog::BindingEditorDialog(QWidget *parent)
this, &BindingEditorDialog::accepted);
QObject::connect(m_buttonBox, &QDialogButtonBox::rejected,
this, &BindingEditorDialog::rejected);
QObject::connect(m_editorWidget, &BindingEditorWidget::returnKeyClicked,
this, &BindingEditorDialog::accepted);
QObject::connect(m_comboBoxItem, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &BindingEditorDialog::itemIDChanged);
QObject::connect(m_comboBoxProperty, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &BindingEditorDialog::propertyIDChanged);
QObject::connect(m_editorWidget, &QPlainTextEdit::textChanged,
this, &BindingEditorDialog::textChanged);
}
BindingEditorDialog::~BindingEditorDialog()
{
delete m_editor; //m_editorWidget is handled by basetexteditor destructor
delete m_buttonBox;
delete m_comboBoxItem;
delete m_comboBoxProperty;
delete m_comboBoxLayout;
delete m_verticalLayout;
}
@@ -216,6 +255,55 @@ void BindingEditorDialog::setEditorValue(const QString &text)
m_editorWidget->document()->setPlainText(text);
}
void BindingEditorDialog::setAllBindings(QList<BindingEditorDialog::BindingOption> bindings)
{
m_lock = true;
m_bindings = bindings;
setupComboBoxes();
adjustProperties();
m_lock = false;
}
void BindingEditorDialog::adjustProperties()
{
const QString expression = editorValue();
QString item;
QString property;
QStringList expressionElements = expression.split(".");
if (!expressionElements.isEmpty()) {
const int itemIndex = m_bindings.indexOf(expressionElements.at(0));
if (itemIndex != -1) {
item = expressionElements.at(0);
expressionElements.removeFirst();
if (!expressionElements.isEmpty()) {
const QString sum = expressionElements.join(".");
if (m_bindings.at(itemIndex).properties.contains(sum))
property = sum;
}
}
}
if (item.isEmpty()) {
item = undefinedString;
if (m_comboBoxItem->findText(item) == -1)
m_comboBoxItem->addItem(item);
}
m_comboBoxItem->setCurrentText(item);
if (property.isEmpty()) {
property = undefinedString;
if (m_comboBoxProperty->findText(property) == -1)
m_comboBoxProperty->addItem(property);
}
m_comboBoxProperty->setCurrentText(property);
}
void BindingEditorDialog::unregisterAutoCompletion()
{
if (m_editorWidget)
@@ -237,7 +325,6 @@ void BindingEditorDialog::setupJSEditor()
m_editorWidget->qmljsdocument = qobject_cast<QmlJSEditor::QmlJSEditorWidget *>(
qmlDesignerEditor->widget())->qmlJsEditorDocument();
m_editorWidget->setParent(this);
m_editorWidget->setLineNumbersVisible(false);
m_editorWidget->setMarksVisible(false);
@@ -245,24 +332,87 @@ void BindingEditorDialog::setupJSEditor()
m_editorWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
m_editorWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
m_editorWidget->setTabChangesFocus(true);
m_editorWidget->show();
}
void BindingEditorDialog::setupUIComponents()
{
m_verticalLayout = new QVBoxLayout(this);
m_comboBoxLayout = new QHBoxLayout;
m_comboBoxItem = new QComboBox(this);
m_comboBoxProperty = new QComboBox(this);
m_editorWidget->setParent(this);
m_editorWidget->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
m_editorWidget->show();
m_buttonBox = new QDialogButtonBox(this);
m_buttonBox->setOrientation(Qt::Horizontal);
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
m_editorWidget->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
m_buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
m_comboBoxLayout->addWidget(m_comboBoxItem);
m_comboBoxLayout->addWidget(m_comboBoxProperty);
m_verticalLayout->addLayout(m_comboBoxLayout);
m_verticalLayout->addWidget(m_editorWidget);
m_verticalLayout->addWidget(m_buttonBox);
this->resize(600,200);
this->resize(660, 240);
}
void BindingEditorDialog::setupComboBoxes()
{
m_comboBoxItem->clear();
m_comboBoxProperty->clear();
for (auto bind : m_bindings)
m_comboBoxItem->addItem(bind.item);
}
void BindingEditorDialog::itemIDChanged(int itemID)
{
const QString previousProperty = m_comboBoxProperty->currentText();
m_comboBoxProperty->clear();
if (m_bindings.size() > itemID && itemID != -1) {
m_comboBoxProperty->addItems(m_bindings.at(itemID).properties);
if (!m_lock)
if (m_comboBoxProperty->findText(previousProperty) != -1)
m_comboBoxProperty->setCurrentText(previousProperty);
const int undefinedItem = m_comboBoxItem->findText(undefinedString);
if ((undefinedItem != -1) && (m_comboBoxItem->itemText(itemID) != undefinedString))
m_comboBoxItem->removeItem(undefinedItem);
}
}
void BindingEditorDialog::propertyIDChanged(int propertyID)
{
const int itemID = m_comboBoxItem->currentIndex();
if (!m_lock)
if (!m_comboBoxProperty->currentText().isEmpty() && (m_comboBoxProperty->currentText() != undefinedString))
setEditorValue(m_comboBoxItem->itemText(itemID) + "." + m_comboBoxProperty->itemText(propertyID));
const int undefinedProperty = m_comboBoxProperty->findText(undefinedString);
if ((undefinedProperty != -1) && (m_comboBoxProperty->itemText(propertyID) != undefinedString))
m_comboBoxProperty->removeItem(undefinedProperty);
}
void BindingEditorDialog::textChanged()
{
if (m_lock)
return;
m_lock = true;
adjustProperties();
m_lock = false;
}
BindingEditor::BindingEditor(QObject *)
{
}
@@ -320,5 +470,74 @@ void BindingEditor::setBindingValue(const QString &text)
m_dialog->setEditorValue(text);
}
void BindingEditor::setBackendValue(const QVariant &backendValue)
{
if (!backendValue.isNull() && backendValue.isValid()) {
m_backendValue = backendValue;
const QObject *backendValueObj = backendValue.value<QObject*>();
const PropertyEditorValue *propertyEditorValue = qobject_cast<const PropertyEditorValue *>(backendValueObj);
m_backendValueTypeName = propertyEditorValue->modelNode().metaInfo().propertyTypeName(
propertyEditorValue->name());
emit backendValueChanged();
}
}
void BindingEditor::setModelNodeBackend(const QVariant &modelNodeBackend)
{
if (!modelNodeBackend.isNull() && modelNodeBackend.isValid()) {
m_modelNodeBackend = modelNodeBackend;
emit modelNodeBackendChanged();
}
}
void BindingEditor::prepareBindings()
{
if (m_backendValue.isNull() || m_modelNodeBackend.isNull())
return;
if (!(m_backendValue.isValid() && m_modelNodeBackend.isValid()))
return;
const auto modelNodeBackendObject = m_modelNodeBackend.value<QObject*>();
const auto backendObjectCasted =
qobject_cast<const QmlDesigner::QmlModelNodeProxy *>(modelNodeBackendObject);
if (backendObjectCasted) {
const QmlDesigner::ModelNode a = backendObjectCasted->qmlObjectNode().modelNode();
const QList<QmlDesigner::ModelNode> allNodes = a.view()->allModelNodes();
QList<BindingEditorDialog::BindingOption> bindings;
for (auto objnode : allNodes) {
BindingEditorDialog::BindingOption binding;
for (auto propertyName : objnode.metaInfo().propertyNames())
if (m_backendValueTypeName == objnode.metaInfo().propertyTypeName(propertyName))
binding.properties.append(QString::fromUtf8(propertyName));
if (!binding.properties.isEmpty() && objnode.hasId()) {
binding.item = objnode.displayName();
bindings.append(binding);
}
}
if (!bindings.isEmpty() && !m_dialog.isNull())
m_dialog->setAllBindings(bindings);
}
}
QVariant BindingEditor::backendValue() const
{
return m_backendValue;
}
QVariant BindingEditor::modelNodeBackend() const
{
return m_modelNodeBackend;
}
}

View File

@@ -42,6 +42,8 @@ QT_BEGIN_NAMESPACE
class QTextEdit;
class QDialogButtonBox;
class QVBoxLayout;
class QHBoxLayout;
class QComboBox;
QT_END_NAMESPACE
namespace QmlDesigner {
@@ -49,6 +51,7 @@ namespace QmlDesigner {
class BindingEditorContext : public Core::IContext
{
Q_OBJECT
public:
BindingEditorContext(QWidget *parent) : Core::IContext(parent)
{
@@ -59,14 +62,22 @@ public:
class BindingEditorWidget : public QmlJSEditor::QmlJSEditorWidget
{
Q_OBJECT
public:
BindingEditorWidget();
~BindingEditorWidget();
~BindingEditorWidget() override;
void unregisterAutoCompletion();
TextEditor::AssistInterface *createAssistInterface(TextEditor::AssistKind assistKind, TextEditor::AssistReason assistReason) const;
bool event(QEvent *event) override;
TextEditor::AssistInterface *createAssistInterface(TextEditor::AssistKind assistKind,
TextEditor::AssistReason assistReason) const override;
signals:
void returnKeyClicked();
public:
QmlJSEditor::QmlJSEditorDocument *qmljsdocument = nullptr;
BindingEditorContext *m_context = nullptr;
QAction *m_completionAction = nullptr;
@@ -76,6 +87,19 @@ class BindingEditorDialog : public QDialog
{
Q_OBJECT
public:
struct BindingOption
{
BindingOption() {}
BindingOption(const QString &value) { item = value; }
bool operator==(const QString &value) const { return value == item; }
bool operator==(const BindingOption &value) const { return value.item == item; }
QString item;
QStringList properties;
};
public:
BindingEditorDialog(QWidget *parent = nullptr);
~BindingEditorDialog() override;
@@ -85,17 +109,32 @@ public:
QString editorValue() const;
void setEditorValue(const QString &text);
void setAllBindings(QList<BindingEditorDialog::BindingOption> bindings);
void adjustProperties();
void unregisterAutoCompletion();
private:
void setupJSEditor();
void setupUIComponents();
void setupComboBoxes();
public slots:
void itemIDChanged(int);
void propertyIDChanged(int);
void textChanged();
private:
TextEditor::BaseTextEditor *m_editor = nullptr;
BindingEditorWidget *m_editorWidget = nullptr;
QVBoxLayout *m_verticalLayout = nullptr;
QDialogButtonBox *m_buttonBox = nullptr;
QHBoxLayout *m_comboBoxLayout = nullptr;
QComboBox *m_comboBoxItem = nullptr;
QComboBox *m_comboBoxProperty = nullptr;
QList<BindingEditorDialog::BindingOption> m_bindings;
bool m_lock = false;
const QString undefinedString = {"[Undefined]"};
};
class BindingEditor : public QObject
@@ -103,6 +142,8 @@ class BindingEditor : public QObject
Q_OBJECT
Q_PROPERTY(QString text READ bindingValue WRITE setBindingValue)
Q_PROPERTY(QVariant backendValueProperty READ backendValue WRITE setBackendValue NOTIFY backendValueChanged)
Q_PROPERTY(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend NOTIFY modelNodeBackendChanged)
public:
BindingEditor(QObject *parent = nullptr);
@@ -116,13 +157,26 @@ public:
QString bindingValue() const;
void setBindingValue(const QString &text);
void setBackendValue(const QVariant &backendValue);
void setModelNodeBackend(const QVariant &modelNodeBackend);
Q_INVOKABLE void prepareBindings();
signals:
void accepted();
void rejected();
void backendValueChanged();
void modelNodeBackendChanged();
private:
QVariant backendValue() const;
QVariant modelNodeBackend() const;
private:
QPointer<BindingEditorDialog> m_dialog;
QVariant m_backendValue;
QVariant m_modelNodeBackend;
TypeName m_backendValueTypeName;
};
}

View File

@@ -36,7 +36,8 @@ SOURCES += formeditoritem.cpp \
bindingindicatorgraphicsitem.cpp \
contentnoteditableindicator.cpp \
backgroundaction.cpp \
formeditortoolbutton.cpp
formeditortoolbutton.cpp \
option3daction.cpp
HEADERS += formeditorscene.h \
formeditorwidget.h \
@@ -75,6 +76,7 @@ HEADERS += formeditorscene.h \
bindingindicatorgraphicsitem.h \
contentnoteditableindicator.h \
backgroundaction.h \
formeditortoolbutton.h
formeditortoolbutton.h \
option3daction.h
RESOURCES += formeditor.qrc

View File

@@ -26,6 +26,7 @@
#include "formeditorview.h"
#include "selectiontool.h"
#include "movetool.h"
#include "option3daction.h"
#include "resizetool.h"
#include "dragtool.h"
#include "formeditorwidget.h"
@@ -45,6 +46,7 @@
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QDebug>
#include <QPair>
@@ -83,6 +85,7 @@ void FormEditorView::modelAttached(Model *model)
setupFormEditorItemTree(rootModelNode());
m_formEditorWidget->updateActions();
setupOption3DAction();
if (!rewriterView()->errors().isEmpty())
formEditorWidget()->showErrorMessageBox(rewriterView()->errors());
@@ -178,6 +181,22 @@ void FormEditorView::temporaryBlockView()
});
}
void FormEditorView::setupOption3DAction()
{
auto import = Import::createLibraryImport("QtQuick3D", "1.0");
auto action = m_formEditorWidget->option3DAction();
if (model() && model()->hasImport(import, true, true)) {
bool enabled = true;
if (rootModelNode().hasAuxiliaryData("3d-view"))
enabled = rootModelNode().auxiliaryData("3d-view").toBool();
action->set3DEnabled(enabled);
action->setEnabled(true);
} else {
action->set3DEnabled(false);
action->setEnabled(false);
}
}
void FormEditorView::nodeCreated(const ModelNode &node)
{
//If the node has source for components/custom parsers we ignore it.
@@ -567,6 +586,16 @@ void FormEditorView::exportAsImage()
m_formEditorWidget->exportAsImage(m_scene->rootFormEditorItem()->boundingRect());
}
void FormEditorView::toggle3DViewEnabled(bool enabled)
{
QTC_ASSERT(model(), return);
QTC_ASSERT(rootModelNode().isValid(), return);
if (enabled)
rootModelNode().removeAuxiliaryData("3d-view");
else
rootModelNode().setAuxiliaryData("3d-view", false);
}
QmlItemNode findRecursiveQmlItemNode(const QmlObjectNode &firstQmlObjectNode)
{
QmlObjectNode qmlObjectNode = firstQmlObjectNode;
@@ -629,6 +658,8 @@ void FormEditorView::delayedReset()
m_scene->clearFormEditorItems();
if (isAttached() && QmlItemNode::isValidQmlItemNode(rootModelNode()))
setupFormEditorItemTree(rootModelNode());
setupOption3DAction();
}
}

View File

@@ -118,6 +118,8 @@ public:
void exportAsImage();
void toggle3DViewEnabled(bool enabled);
protected:
void reset();
void delayedReset();
@@ -129,6 +131,7 @@ private: //functions
void hideNodeFromScene(const QmlItemNode &qmlItemNode);
void createFormEditorWidget();
void temporaryBlockView();
void setupOption3DAction();
private: //variables
QPointer<FormEditorWidget> m_formEditorWidget;

View File

@@ -34,24 +34,25 @@
#include <model.h>
#include <theme.h>
#include <QWheelEvent>
#include <QVBoxLayout>
#include <QActionGroup>
#include <toolbox.h>
#include <zoomaction.h>
#include <backgroundaction.h>
#include <formeditorgraphicsview.h>
#include <formeditorscene.h>
#include <formeditorview.h>
#include <lineeditaction.h>
#include <backgroundaction.h>
#include <option3daction.h>
#include <zoomaction.h>
#include <toolbox.h>
#include <coreplugin/icore.h>
#include <utils/fileutils.h>
#include <utils/utilsicons.h>
#include <QActionGroup>
#include <QFileDialog>
#include <QPainter>
#include <QVBoxLayout>
#include <QWheelEvent>
namespace QmlDesigner {
@@ -143,6 +144,15 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view) :
upperActions.append(m_backgroundAction.data());
m_toolBox->addRightSideAction(m_backgroundAction.data());
m_option3DAction = new Option3DAction(m_toolActionGroup.data());
addAction(m_option3DAction.data());
upperActions.append(m_option3DAction.data());
m_toolBox->addRightSideAction(m_option3DAction.data());
connect(m_option3DAction.data(), &Option3DAction::enabledChanged,
m_formEditorView.data(), &FormEditorView::toggle3DViewEnabled);
connect(m_option3DAction.data(), &Option3DAction::activated,
this, &FormEditorWidget::resetNodeInstanceView);
m_zoomAction = new ZoomAction(m_toolActionGroup.data());
connect(m_zoomAction.data(), &ZoomAction::zoomLevelChanged,
this, &FormEditorWidget::setZoomLevel);
@@ -285,6 +295,11 @@ ZoomAction *FormEditorWidget::zoomAction() const
return m_zoomAction.data();
}
Option3DAction *FormEditorWidget::option3DAction() const
{
return m_option3DAction.data();
}
QAction *FormEditorWidget::showBoundingRectAction() const
{
return m_showBoundingRectAction.data();

View File

@@ -40,6 +40,7 @@ namespace QmlDesigner {
class ZoomAction;
class LineEditAction;
class BackgroundAction;
class Option3DAction;
class FormEditorView;
class FormEditorScene;
class FormEditorGraphicsView;
@@ -54,6 +55,7 @@ public:
FormEditorWidget(FormEditorView *view);
ZoomAction *zoomAction() const;
Option3DAction *option3DAction() const;
QAction *showBoundingRectAction() const;
QAction *snappingAction() const;
QAction *snappingAndAnchoringAction() const;
@@ -112,6 +114,7 @@ private:
QPointer<LineEditAction> m_rootWidthAction;
QPointer<LineEditAction> m_rootHeightAction;
QPointer<BackgroundAction> m_backgroundAction;
QPointer<Option3DAction> m_option3DAction;
QPointer<QAction> m_resetAction;
QPointer<DocumentWarningWidget> m_documentErrorWidget;
};

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "option3daction.h"
#include <QComboBox>
#include <QPainter>
namespace QmlDesigner {
Option3DAction::Option3DAction(QObject *parent) :
QWidgetAction(parent)
{
}
void Option3DAction::set3DEnabled(bool enabled)
{
m_comboBox->setCurrentIndex(enabled ? 1 : 0);
}
QWidget *Option3DAction::createWidget(QWidget *parent)
{
m_comboBox = new QComboBox(parent);
m_comboBox->setFixedWidth(82);
m_comboBox->addItem(tr("2D"));
m_comboBox->addItem(tr("2D/3D"));
m_comboBox->setCurrentIndex(0);
connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this](){
emit enabledChanged(m_comboBox->currentIndex() != 0);
});
connect(m_comboBox, QOverload<int>::of(&QComboBox::activated),
this, [this](){
emit activated();
});
m_comboBox->setProperty("hideborder", true);
m_comboBox->setToolTip(tr("Enable/Disable 3D edit mode."));
return m_comboBox;
}
} // namespace QmlDesigner

View File

@@ -0,0 +1,52 @@
/****************************************************************************
**
** Copyright (C) 2019 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 <QWidgetAction>
QT_FORWARD_DECLARE_CLASS(QComboBox)
namespace QmlDesigner {
class Option3DAction : public QWidgetAction
{
Q_OBJECT
public:
explicit Option3DAction(QObject *parent);
void set3DEnabled(bool enabled);
signals:
void enabledChanged(bool enabled);
void activated();
protected:
QWidget *createWidget(QWidget *parent) override;
private:
QComboBox *m_comboBox = nullptr;
};
} // namespace QmlDesigner

View File

@@ -44,6 +44,7 @@
#include <QtWidgets/qspinbox.h>
#include <QtWidgets/qscrollbar.h>
#include <QtWidgets/qtabbar.h>
#include <QtWidgets/qscrollarea.h>
namespace QmlDesigner {
@@ -62,6 +63,8 @@ static void addFormattedMessage(Utils::OutputFormatter *formatter, const QString
formatter->plainTextEdit()->verticalScrollBar()->maximum());
}
static const int rowHeight = 26;
}
ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &importFiles,
@@ -140,36 +143,135 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
}
m_quick3DImportPath = candidatePath;
// Create UI controls for options
if (!importFiles.isEmpty()) {
QJsonObject supportedOptions = QJsonObject::fromVariantMap(
m_importer.supportedOptions(importFiles[0]));
m_importOptions = supportedOptions.value("options").toObject();
const QJsonObject groups = supportedOptions.value("groups").toObject();
if (!m_quick3DFiles.isEmpty()) {
const QHash<QString, QVariantMap> allOptions = m_importer.allOptions();
const QHash<QString, QStringList> supportedExtensions = m_importer.supportedExtensions();
QVector<QJsonObject> groups;
const int labelWidth = 210;
const int valueWidth = 75;
const int groupIndent = 10;
const int columnSpacing = 10;
const int rowHeight = 26;
auto optIt = allOptions.constBegin();
int optIndex = 0;
while (optIt != allOptions.constEnd()) {
QJsonObject options = QJsonObject::fromVariantMap(optIt.value());
m_importOptions << options.value("options").toObject();
groups << options.value("groups").toObject();
const auto &exts = optIt.key().split(':');
for (const auto &ext : exts)
m_extToImportOptionsMap.insert(ext, optIndex);
++optIt;
++optIndex;
}
// Create tab for each supported extension group that also has files included in the import
QMap<QString, int> tabMap; // QMap used for alphabetical order
for (const auto &file : qAsConst(m_quick3DFiles)) {
auto extIt = supportedExtensions.constBegin();
QString ext = QFileInfo(file).suffix();
while (extIt != supportedExtensions.constEnd()) {
if (!tabMap.contains(extIt.key()) && extIt.value().contains(ext)) {
tabMap.insert(extIt.key(), m_extToImportOptionsMap.value(ext));
break;
}
++extIt;
}
}
ui->tabWidget->clear();
auto tabIt = tabMap.constBegin();
while (tabIt != tabMap.constEnd()) {
createTab(tabIt.key(), tabIt.value(), groups[tabIt.value()]);
++tabIt;
}
// Pad all tabs to same height
for (int i = 0; i < ui->tabWidget->count(); ++i) {
auto optionsArea = qobject_cast<QScrollArea *>(ui->tabWidget->widget(i));
if (optionsArea && optionsArea->widget()) {
auto grid = qobject_cast<QGridLayout *>(optionsArea->widget()->layout());
if (grid) {
int rows = grid->rowCount();
for (int j = rows; j < m_optionsRows; ++j) {
grid->addWidget(new QWidget(optionsArea->widget()), j, 0);
grid->setRowMinimumHeight(j, rowHeight);
}
}
}
}
ui->tabWidget->setCurrentIndex(0);
}
connect(ui->buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked,
this, &ItemLibraryAssetImportDialog::onClose);
connect(ui->tabWidget, &QTabWidget::currentChanged,
this, &ItemLibraryAssetImportDialog::updateUi);
connect(&m_importer, &ItemLibraryAssetImporter::errorReported,
this, &ItemLibraryAssetImportDialog::addError);
connect(&m_importer, &ItemLibraryAssetImporter::warningReported,
this, &ItemLibraryAssetImportDialog::addWarning);
connect(&m_importer, &ItemLibraryAssetImporter::infoReported,
this, &ItemLibraryAssetImportDialog::addInfo);
connect(&m_importer, &ItemLibraryAssetImporter::importNearlyFinished,
this, &ItemLibraryAssetImportDialog::onImportNearlyFinished);
connect(&m_importer, &ItemLibraryAssetImporter::importFinished,
this, &ItemLibraryAssetImportDialog::onImportFinished);
connect(&m_importer, &ItemLibraryAssetImporter::progressChanged,
this, &ItemLibraryAssetImportDialog::setImportProgress);
addInfo(tr("Select import options and press \"Import\" to import the following files:"));
for (const auto &file : m_quick3DFiles)
addInfo(file);
QTimer::singleShot(0, [this]() {
ui->tabWidget->setMaximumHeight(m_optionsHeight + ui->tabWidget->tabBar()->height() + 10);
updateUi();
});
}
ItemLibraryAssetImportDialog::~ItemLibraryAssetImportDialog()
{
delete ui;
}
void ItemLibraryAssetImportDialog::createTab(const QString &tabLabel, int optionsIndex,
const QJsonObject &groups)
{
const int checkBoxColWidth = 18;
const int labelMinWidth = 130;
const int controlMinWidth = 65;
const int columnSpacing = 16;
int rowIndex[2] = {0, 0};
QJsonObject &options = m_importOptions[optionsIndex];
// First index has ungrouped widgets, rest are groups
// First item in each real group is group label
QVector<QVector<QPair<QWidget *, QWidget *>>> widgets;
QHash<QString, int> groupIndexMap;
QHash<QString, QPair<QWidget *, QWidget *>> optionToWidgetsMap;
QHash<QString, QJsonArray> conditionMap;
QHash<QWidget *, QWidget *> conditionalWidgetMap;
QHash<QString, QString> optionToGroupMap;
auto layout = new QGridLayout(ui->optionsAreaContents);
layout->setColumnMinimumWidth(0, groupIndent);
layout->setColumnMinimumWidth(1, labelWidth);
layout->setColumnMinimumWidth(2, valueWidth);
auto optionsArea = new QScrollArea(ui->tabWidget);
optionsArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
auto optionsAreaContents = new QWidget(optionsArea);
auto layout = new QGridLayout(optionsAreaContents);
layout->setColumnMinimumWidth(0, checkBoxColWidth);
layout->setColumnMinimumWidth(1, labelMinWidth);
layout->setColumnMinimumWidth(2, controlMinWidth);
layout->setColumnMinimumWidth(3, columnSpacing);
layout->setColumnMinimumWidth(4, groupIndent);
layout->setColumnMinimumWidth(5, labelWidth);
layout->setColumnMinimumWidth(6, valueWidth);
layout->setColumnMinimumWidth(4, checkBoxColWidth);
layout->setColumnMinimumWidth(5, labelMinWidth);
layout->setColumnMinimumWidth(6, controlMinWidth);
layout->setColumnStretch(0, 0);
layout->setColumnStretch(1, 4);
layout->setColumnStretch(2, 2);
layout->setColumnStretch(3, 0);
layout->setColumnStretch(4, 0);
layout->setColumnStretch(5, 4);
layout->setColumnStretch(6, 2);
widgets.append(QVector<QPair<QWidget *, QWidget *>>());
@@ -178,7 +280,7 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
const QJsonArray items = group.toObject().value("items").toArray();
for (const auto item : items)
optionToGroupMap.insert(item.toString(), name);
auto groupLabel = new QLabel(name, ui->optionsAreaContents);
auto groupLabel = new QLabel(name, optionsAreaContents);
QFont labelFont = groupLabel->font();
labelFont.setBold(true);
groupLabel->setFont(labelFont);
@@ -186,9 +288,9 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
groupIndexMap.insert(name, widgets.size() - 1);
}
const auto optKeys = m_importOptions.keys();
const auto optKeys = options.keys();
for (const auto &optKey : optKeys) {
QJsonObject optObj = m_importOptions.value(optKey).toObject();
QJsonObject optObj = options.value(optKey).toObject();
const QString optName = optObj.value("name").toString();
const QString optDesc = optObj.value("description").toString();
const QString optType = optObj.value("type").toString();
@@ -198,17 +300,18 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
QWidget *optControl = nullptr;
if (optType == "Boolean") {
auto *optCheck = new QCheckBox(ui->optionsAreaContents);
auto *optCheck = new QCheckBox(optionsAreaContents);
optCheck->setChecked(optValue.toBool());
optControl = optCheck;
QObject::connect(optCheck, &QCheckBox::toggled, [this, optCheck, optKey]() {
QJsonObject optObj = m_importOptions.value(optKey).toObject();
QObject::connect(optCheck, &QCheckBox::toggled,
[this, optCheck, optKey, optionsIndex]() {
QJsonObject optObj = m_importOptions[optionsIndex].value(optKey).toObject();
QJsonValue value(optCheck->isChecked());
optObj.insert("value", value);
m_importOptions.insert(optKey, optObj);
m_importOptions[optionsIndex].insert(optKey, optObj);
});
} else if (optType == "Real") {
auto *optSpin = new QDoubleSpinBox(ui->optionsAreaContents);
auto *optSpin = new QDoubleSpinBox(optionsAreaContents);
double min = -999999999.;
double max = 999999999.;
double step = 1.;
@@ -230,13 +333,14 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
optSpin->setDecimals(decimals);
optSpin->setValue(optValue.toDouble());
optSpin->setSingleStep(step);
optSpin->setMinimumWidth(controlMinWidth);
optControl = optSpin;
QObject::connect(optSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
[this, optSpin, optKey]() {
QJsonObject optObj = m_importOptions.value(optKey).toObject();
[this, optSpin, optKey, optionsIndex]() {
QJsonObject optObj = m_importOptions[optionsIndex].value(optKey).toObject();
QJsonValue value(optSpin->value());
optObj.insert("value", value);
m_importOptions.insert(optKey, optObj);
m_importOptions[optionsIndex].insert(optKey, optObj);
});
} else {
qWarning() << __FUNCTION__ << "Unsupported option type:" << optType;
@@ -246,7 +350,7 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
if (!conditions.isEmpty())
conditionMap.insert(optKey, conditions);
auto *optLabel = new QLabel(ui->optionsAreaContents);
auto *optLabel = new QLabel(optionsAreaContents);
optLabel->setText(optName);
optLabel->setToolTip(optDesc);
optControl->setToolTip(optDesc);
@@ -259,37 +363,9 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
optionToWidgetsMap.insert(optKey, {optLabel, optControl});
}
// Add option widgets to layout. Grouped options are added to the tops of the columns
for (int i = 1; i < widgets.size(); ++i) {
int col = rowIndex[1] < rowIndex[0] ? 1 : 0;
const auto &groupWidgets = widgets[i];
if (!groupWidgets.isEmpty()) {
// First widget in each group is the group label
layout->addWidget(groupWidgets[0].first, rowIndex[col], col * 4, 1, 3);
layout->setRowMinimumHeight(rowIndex[col],rowHeight);
++rowIndex[col];
for (int j = 1; j < groupWidgets.size(); ++j) {
layout->addWidget(groupWidgets[j].first, rowIndex[col], col * 4 + 1);
layout->addWidget(groupWidgets[j].second, rowIndex[col], col * 4 + 2);
layout->setRowMinimumHeight(rowIndex[col],rowHeight);
++rowIndex[col];
}
}
}
// Ungrouped options are spread evenly under the groups
int totalRowCount = (rowIndex[0] + rowIndex[1] + widgets[0].size() + 1) / 2;
for (const auto &rowWidgets : qAsConst(widgets[0])) {
int col = rowIndex[0] < totalRowCount ? 0 : 1;
layout->addWidget(rowWidgets.first, rowIndex[col], col * 4, 1, 2);
layout->addWidget(rowWidgets.second, rowIndex[col], col * 4 + 2);
layout->setRowMinimumHeight(rowIndex[col],rowHeight);
++rowIndex[col];
}
// Handle conditions
QHash<QString, QJsonArray>::const_iterator it = conditionMap.begin();
while (it != conditionMap.end()) {
auto it = conditionMap.constBegin();
while (it != conditionMap.constEnd()) {
const QString &option = it.key();
const QJsonArray &conditions = it.value();
const auto &conWidgets = optionToWidgetsMap.value(option);
@@ -327,6 +403,10 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
w2->setEnabled(enable);
};
enableConditionally(optCb, conLabel, conControl, mode);
if (conditionalWidgetMap.contains(optCb))
conditionalWidgetMap.insert(optCb, nullptr);
else
conditionalWidgetMap.insert(optCb, conControl);
QObject::connect(
optCb, &QCheckBox::toggled,
[optCb, conLabel, conControl, mode, enableConditionally]() {
@@ -361,50 +441,125 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
++it;
}
ui->optionsAreaContents->setLayout(layout);
ui->optionsAreaContents->resize(
groupIndent * 2 + labelWidth * 2 + valueWidth * 2 + columnSpacing,
rowHeight * qMax(rowIndex[0], rowIndex[1]));
// Combine options where a non-boolean option depends on a boolean option that no other
// option depends on
auto condIt = conditionalWidgetMap.constBegin();
while (condIt != conditionalWidgetMap.constEnd()) {
if (condIt.value()) {
// Find and fix widget pairs
for (int i = 0; i < widgets.size(); ++i) {
auto &groupWidgets = widgets[i];
auto widgetIt = groupWidgets.begin();
while (widgetIt != groupWidgets.end()) {
if (widgetIt->second == condIt.value()
&& !qobject_cast<QCheckBox *>(condIt.value())) {
if (widgetIt->first)
widgetIt->first->hide();
groupWidgets.erase(widgetIt);
} else {
++widgetIt;
}
}
// If group was left with less than two actual members, disband the group
// and move the remaining member to ungrouped options
// Note: <= 2 instead of < 2 because each group has group label member
if (i != 0 && groupWidgets.size() <= 2) {
widgets[0].prepend(groupWidgets[1]);
groupWidgets[0].first->hide(); // hide group label
groupWidgets.clear();
}
}
}
++condIt;
}
ui->optionsArea->setStyleSheet("QScrollArea {background-color: transparent}");
ui->optionsAreaContents->setStyleSheet(
auto incrementColIndex = [&](int col) {
layout->setRowMinimumHeight(rowIndex[col], rowHeight);
++rowIndex[col];
};
auto insertOptionToLayout = [&](int col, const QPair<QWidget *, QWidget *> &optionWidgets) {
layout->addWidget(optionWidgets.first, rowIndex[col], col * 4 + 1, 1, 2);
int adj = qobject_cast<QCheckBox *>(optionWidgets.second) ? 0 : 2;
layout->addWidget(optionWidgets.second, rowIndex[col], col * 4 + adj);
if (!adj) {
// Check box option may have additional conditional value field
QWidget *condWidget = conditionalWidgetMap.value(optionWidgets.second);
if (condWidget)
layout->addWidget(condWidget, rowIndex[col], col * 4 + 2);
}
incrementColIndex(col);
};
if (widgets.size() == 1 && widgets[0].isEmpty()) {
layout->addWidget(new QLabel(tr("No options available for this type."),
optionsAreaContents), 0, 0, 2, 7, Qt::AlignCenter);
incrementColIndex(0);
incrementColIndex(0);
}
// Add option widgets to layout. Grouped options are added to the tops of the columns
for (int i = 1; i < widgets.size(); ++i) {
int col = rowIndex[1] < rowIndex[0] ? 1 : 0;
const auto &groupWidgets = widgets[i];
if (!groupWidgets.isEmpty()) {
// First widget in each group is the group label
layout->addWidget(groupWidgets[0].first, rowIndex[col], col * 4, 1, 3);
incrementColIndex(col);
for (int j = 1; j < groupWidgets.size(); ++j)
insertOptionToLayout(col, groupWidgets[j]);
// Add a separator line after each group
auto *separator = new QFrame(optionsAreaContents);
separator->setMaximumHeight(1);
separator->setFrameShape(QFrame::HLine);
separator->setFrameShadow(QFrame::Sunken);
separator->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
layout->addWidget(separator, rowIndex[col], col * 4, 1, 3);
incrementColIndex(col);
}
}
// Ungrouped options are spread evenly under the groups
int totalRowCount = (rowIndex[0] + rowIndex[1] + widgets[0].size() + 1) / 2;
for (const auto &rowWidgets : qAsConst(widgets[0])) {
int col = rowIndex[0] < totalRowCount ? 0 : 1;
insertOptionToLayout(col, rowWidgets);
}
int optionRows = qMax(rowIndex[0], rowIndex[1]);
m_optionsRows = qMax(m_optionsRows, optionRows);
m_optionsHeight = qMax(rowHeight * optionRows + 16, m_optionsHeight);
layout->setContentsMargins(8, 8, 8, 8);
optionsAreaContents->setContentsMargins(0, 0, 0, 0);
optionsAreaContents->setLayout(layout);
optionsAreaContents->setMinimumWidth(
(checkBoxColWidth + labelMinWidth + controlMinWidth) * 2 + columnSpacing);
optionsAreaContents->setObjectName("optionsAreaContents"); // For stylesheet
optionsArea->setWidget(optionsAreaContents);
optionsArea->setStyleSheet("QScrollArea {background-color: transparent}");
optionsAreaContents->setStyleSheet(
"QWidget#optionsAreaContents {background-color: transparent}");
connect(ui->buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked,
this, &ItemLibraryAssetImportDialog::onClose);
connect(&m_importer, &ItemLibraryAssetImporter::errorReported,
this, &ItemLibraryAssetImportDialog::addError);
connect(&m_importer, &ItemLibraryAssetImporter::warningReported,
this, &ItemLibraryAssetImportDialog::addWarning);
connect(&m_importer, &ItemLibraryAssetImporter::infoReported,
this, &ItemLibraryAssetImportDialog::addInfo);
connect(&m_importer, &ItemLibraryAssetImporter::importNearlyFinished,
this, &ItemLibraryAssetImportDialog::onImportNearlyFinished);
connect(&m_importer, &ItemLibraryAssetImporter::importFinished,
this, &ItemLibraryAssetImportDialog::onImportFinished);
connect(&m_importer, &ItemLibraryAssetImporter::progressChanged,
this, &ItemLibraryAssetImportDialog::setImportProgress);
addInfo(tr("Select import options and press \"Import\" to import the following files:"));
for (const auto &file : m_quick3DFiles)
addInfo(file);
ui->tabWidget->addTab(optionsArea, tr("%1 options").arg(tabLabel));
}
ItemLibraryAssetImportDialog::~ItemLibraryAssetImportDialog()
void ItemLibraryAssetImportDialog::updateUi()
{
delete ui;
auto optionsArea = qobject_cast<QScrollArea *>(ui->tabWidget->currentWidget());
if (optionsArea) {
auto optionsAreaContents = optionsArea->widget();
int scrollBarWidth = optionsArea->verticalScrollBar()->isVisible()
? optionsArea->verticalScrollBar()->width() : 0;
optionsAreaContents->resize(optionsArea->contentsRect().width()
- scrollBarWidth - 8, m_optionsHeight);
}
}
void ItemLibraryAssetImportDialog::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event)
int scrollBarHeight = ui->optionsArea->horizontalScrollBar()->isVisible()
? ui->optionsArea->horizontalScrollBar()->height() : 0;
ui->tabWidget->setMaximumHeight(ui->optionsAreaContents->height() + scrollBarHeight
+ ui->tabWidget->tabBar()->height() + 8);
ui->optionsArea->resize(ui->tabWidget->currentWidget()->size());
updateUi();
}
void ItemLibraryAssetImportDialog::setCloseButtonState(bool importing)
@@ -436,7 +591,7 @@ void ItemLibraryAssetImportDialog::onImport()
if (!m_quick3DFiles.isEmpty()) {
m_importer.importQuick3D(m_quick3DFiles, m_quick3DImportPath,
m_importOptions.toVariantMap());
m_importOptions, m_extToImportOptionsMap);
}
}
@@ -481,4 +636,5 @@ void ItemLibraryAssetImportDialog::onClose()
deleteLater();
}
}
}

View File

@@ -66,12 +66,18 @@ private:
void onImportFinished();
void onClose();
void createTab(const QString &tabLabel, int optionsIndex, const QJsonObject &groups);
void updateUi();
Ui::ItemLibraryAssetImportDialog *ui = nullptr;
Utils::OutputFormatter *m_outputFormatter = nullptr;
QStringList m_quick3DFiles;
QString m_quick3DImportPath;
ItemLibraryAssetImporter m_importer;
QJsonObject m_importOptions;
QVector<QJsonObject> m_importOptions;
QHash<QString, int> m_extToImportOptionsMap;
int m_optionsHeight = 0;
int m_optionsRows = 0;
};
}

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>631</width>
<height>711</height>
<height>750</height>
</rect>
</property>
<property name="windowTitle">
@@ -32,47 +32,6 @@
<attribute name="title">
<string>Import Options</string>
</attribute>
<widget class="QScrollArea" name="optionsArea">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>611</width>
<height>351</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>2</verstretch>
</sizepolicy>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="widgetResizable">
<bool>false</bool>
</property>
<widget class="QWidget" name="optionsAreaContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>0</width>
<height>0</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
</widget>
</widget>
</widget>
</widget>
</item>

View File

@@ -32,6 +32,7 @@
#include <QtCore/qdir.h>
#include <QtCore/qdiriterator.h>
#include <QtCore/qsavefile.h>
#include <QtCore/qfile.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qtemporarydir.h>
#include <QtWidgets/qapplication.h>
@@ -63,7 +64,8 @@ ItemLibraryAssetImporter::~ItemLibraryAssetImporter() {
void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles,
const QString &importPath,
const QVariantMap &options)
const QVector<QJsonObject> &options,
const QHash<QString, int> &extToImportOptionsMap)
{
if (m_isImporting)
cancelImport();
@@ -79,7 +81,7 @@ void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles,
m_importPath = importPath;
parseFiles(inputFiles, options);
parseFiles(inputFiles, options, extToImportOptionsMap);
if (!isCancelled()) {
// Don't allow cancel anymore as existing asset overwrites are not trivially recoverable.
@@ -162,15 +164,17 @@ void ItemLibraryAssetImporter::addInfo(const QString &infoMsg, const QString &sr
bool ItemLibraryAssetImporter::isQuick3DAsset(const QString &fileName) const
{
#ifdef IMPORT_QUICK3D_ASSETS
static QStringList quick3DExt;
if (quick3DExt.isEmpty()) {
quick3DExt << QString(Constants::FbxExtension)
<< QString(Constants::ColladaExtension)
<< QString(Constants::ObjExtension)
<< QString(Constants::BlenderExtension)
<< QString(Constants::GltfExtension);
const auto exts = m_quick3DAssetImporter->getSupportedExtensions();
for (const auto &ext : exts)
quick3DExt << ext;
}
return quick3DExt.contains(QFileInfo(fileName).suffix());
#else
return false;
#endif
}
QVariantMap ItemLibraryAssetImporter::supportedOptions(const QString &modelFile) const
@@ -182,6 +186,24 @@ QVariantMap ItemLibraryAssetImporter::supportedOptions(const QString &modelFile)
#endif
}
QHash<QString, QVariantMap> ItemLibraryAssetImporter::allOptions() const
{
#ifdef IMPORT_QUICK3D_ASSETS
return m_quick3DAssetImporter->getAllOptions();
#else
return {};
#endif
}
QHash<QString, QStringList> ItemLibraryAssetImporter::supportedExtensions() const
{
#ifdef IMPORT_QUICK3D_ASSETS
return m_quick3DAssetImporter->getSupportedExtensions();
#else
return {};
#endif
}
void ItemLibraryAssetImporter::notifyFinished()
{
m_isImporting = false;
@@ -201,7 +223,9 @@ void ItemLibraryAssetImporter::reset()
#endif
}
void ItemLibraryAssetImporter::parseFiles(const QStringList &filePaths, const QVariantMap &options)
void ItemLibraryAssetImporter::parseFiles(const QStringList &filePaths,
const QVector<QJsonObject> &options,
const QHash<QString, int> &extToImportOptionsMap)
{
if (isCancelled())
return;
@@ -216,8 +240,11 @@ void ItemLibraryAssetImporter::parseFiles(const QStringList &filePaths, const QV
for (const QString &file : filePaths) {
if (isCancelled())
return;
if (isQuick3DAsset(file))
parseQuick3DAsset(file, options);
if (isQuick3DAsset(file)) {
QVariantMap varOpts;
int index = extToImportOptionsMap.value(QFileInfo(file).suffix());
parseQuick3DAsset(file, options[index].toVariantMap());
}
notifyProgress(qRound(++count * quota), progressTitle);
}
notifyProgress(100, progressTitle);
@@ -276,31 +303,70 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar
return;
}
// Generate qmldir file
outDir.setNameFilters({QStringLiteral("*.qml")});
const QFileInfoList qmlFiles = outDir.entryInfoList(QDir::Files);
if (!qmlFiles.isEmpty()) {
// Generate qmldir file if importer doesn't already make one
QString qmldirFileName = outDir.absoluteFilePath(QStringLiteral("qmldir"));
if (!QFileInfo(qmldirFileName).exists()) {
QSaveFile qmldirFile(qmldirFileName);
QString version = QStringLiteral("1.0");
// Note: Currently Quick3D importers only generate externally usable qml files on the top
// level of the import directory, so we don't search subdirectories. The qml files in
// subdirs assume they are used within the context of the toplevel qml files.
QDirIterator qmlIt(outDir.path(), {QStringLiteral("*.qml")}, QDir::Files);
if (qmlIt.hasNext()) {
outDir.mkdir(Constants::QUICK_3D_ASSET_ICON_DIR);
if (qmldirFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
for (const auto &fi : qmlFiles) {
QString qmlInfo;
qmlInfo.append("module ");
qmlInfo.append(m_importPath.split('/').last());
qmlInfo.append(".");
qmlInfo.append(assetName);
qmlInfo.append('\n');
while (qmlIt.hasNext()) {
qmlIt.next();
QFileInfo fi = QFileInfo(qmlIt.filePath());
qmlInfo.append(fi.baseName());
qmlInfo.append(QLatin1Char(' '));
qmlInfo.append(' ');
qmlInfo.append(version);
qmlInfo.append(QLatin1Char(' '));
qmlInfo.append(fi.fileName());
qmldirFile.write(qmlInfo.toUtf8());
qmlInfo.append(' ');
qmlInfo.append(outDir.relativeFilePath(qmlIt.filePath()));
qmlInfo.append('\n');
// Generate item library icon for qml file based on root component
QFile qmlFile(qmlIt.filePath());
if (qmlFile.open(QIODevice::ReadOnly)) {
QString iconFileName = outDir.path() + '/'
+ Constants::QUICK_3D_ASSET_ICON_DIR + '/' + fi.baseName()
+ Constants::QUICK_3D_ASSET_LIBRARY_ICON_SUFFIX;
QString iconFileName2x = iconFileName + "@2x";
QByteArray content = qmlFile.readAll();
int braceIdx = content.indexOf('{');
if (braceIdx != -1) {
int nlIdx = content.lastIndexOf('\n', braceIdx);
QByteArray rootItem = content.mid(nlIdx, braceIdx - nlIdx).trimmed();
if (rootItem == "Node") {
QFile::copy(":/ItemLibrary/images/item-3D_model-icon.png",
iconFileName);
QFile::copy(":/ItemLibrary/images/item-3D_model-icon@2x.png",
iconFileName2x);
} else {
QFile::copy(":/ItemLibrary/images/item-default-icon.png",
iconFileName);
QFile::copy(":/ItemLibrary/images/item-default-icon@2x.png",
iconFileName2x);
}
}
}
}
qmldirFile.write(qmlInfo.toUtf8());
qmldirFile.commit();
} else {
addError(tr("Failed to create qmldir file for asset: \"%1\"").arg(assetName));
}
}
}
// Gather generated files
// Gather all generated files
const int outDirPathSize = outDir.path().size();
QDirIterator dirIt(outDir.path(), QDir::Files, QDirIterator::Subdirectories);
QHash<QString, QString> assetFiles;
@@ -314,7 +380,7 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar
// Copy the original asset into a subdirectory
assetFiles.insert(sourceInfo.absoluteFilePath(),
targetDirPath + QStringLiteral("/source model/") + sourceInfo.fileName());
targetDirPath + QStringLiteral("/source scene/") + sourceInfo.fileName());
m_importFiles.insert(assetFiles);
#else

View File

@@ -27,6 +27,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qhash.h>
#include <QtCore/qjsonobject.h>
#include "import.h"
@@ -46,7 +47,8 @@ public:
~ItemLibraryAssetImporter();
void importQuick3D(const QStringList &inputFiles, const QString &importPath,
const QVariantMap &options);
const QVector<QJsonObject> &options,
const QHash<QString, int> &extToImportOptionsMap);
bool isImporting() const;
void cancelImport();
@@ -58,6 +60,8 @@ public:
bool isQuick3DAsset(const QString &fileName) const;
QVariantMap supportedOptions(const QString &modelFile) const;
QHash<QString, QVariantMap> allOptions() const;
QHash<QString, QStringList> supportedExtensions() const;
signals:
void errorReported(const QString &, const QString &) const;
@@ -70,7 +74,8 @@ signals:
private:
void notifyFinished();
void reset();
void parseFiles(const QStringList &filePaths, const QVariantMap &options);
void parseFiles(const QStringList &filePaths, const QVector<QJsonObject> &options,
const QHash<QString, int> &extToImportOptionsMap);
void parseQuick3DAsset(const QString &file, const QVariantMap &options);
void copyImportedFiles();

View File

@@ -51,6 +51,10 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
#ifdef IMPORT_QUICK3D_ASSETS
#include <QtQuick3DAssetImport/private/qssgassetimportmanager_p.h>
#endif
#include <QApplication>
#include <QDrag>
#include <QFileDialog>
@@ -196,15 +200,20 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
return true;
};
const QString category = tr("3D Models");
auto add3DHandler = [&actionManager, &handle3DModel, &category](const char *ext) {
const QString filter = QStringLiteral("*.%1").arg(QString::fromLatin1(ext));
auto add3DHandler = [&](const QString &category, const QString &ext) {
const QString filter = QStringLiteral("*.%1").arg(ext);
actionManager->registerAddResourceHandler(
AddResourceHandler(category, filter, handle3DModel, 10));
};
// Skip if 3D model handlers have already been added
QSSGAssetImportManager importManager;
QHash<QString, QStringList> supportedExtensions = importManager.getSupportedExtensions();
// All things importable by QSSGAssetImportManager are considered to be in the same category
// so we don't get multiple separate import dialogs when different file types are imported.
const QString category = tr("3D Assets");
// Skip if 3D asset handlers have already been added
const QList<AddResourceHandler> handlers = actionManager->addResourceHandler();
bool categoryAlreadyAdded = false;
for (const auto &handler : handlers) {
@@ -215,11 +224,12 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
}
if (!categoryAlreadyAdded) {
add3DHandler(Constants::FbxExtension);
add3DHandler(Constants::ColladaExtension);
add3DHandler(Constants::ObjExtension);
add3DHandler(Constants::BlenderExtension);
add3DHandler(Constants::GltfExtension);
const auto groups = supportedExtensions.keys();
for (const auto &group : groups) {
const auto extensions = supportedExtensions[group];
for (const auto &ext : extensions)
add3DHandler(category, ext);
}
}
#endif

View File

@@ -607,10 +607,7 @@ bool NavigatorTreeModel::setData(const QModelIndex &index, const QVariant &value
QTC_ASSERT(m_view, return false);
m_view->handleChangedExport(modelNode, value.toInt() != 0);
} else if (index.column() == 2 && role == Qt::CheckStateRole) {
if (value.toInt() == 0)
modelNode.setAuxiliaryData("invisible", true);
else
modelNode.removeAuxiliaryData("invisible");
QmlVisualNode(modelNode).setVisibilityOverride(value.toInt() == 0);
}
return true;

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