forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.11'
Change-Id: I48e406d43f185e893523cc5e0dcf288afdc3e36c
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
27
dist/changes-4.11.0.md
vendored
27
dist/changes-4.11.0.md
vendored
@@ -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
|
||||
|
||||
@@ -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 -
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
101
share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
Normal file
101
share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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(",");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -16,6 +16,4 @@ add_subdirectory(sqlite)
|
||||
add_subdirectory(clangsupport)
|
||||
add_subdirectory(tracing)
|
||||
|
||||
if (WIN32)
|
||||
add_subdirectory(qtcreatorcdbext)
|
||||
endif()
|
||||
add_subdirectory(qtcreatorcdbext)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -265,6 +265,11 @@ public:
|
||||
addLocation(line, column);
|
||||
}
|
||||
|
||||
void pragmaLibrary() override
|
||||
{
|
||||
isLibrary = true;
|
||||
}
|
||||
|
||||
virtual QList<SourceLocation> locations() { return _locations; }
|
||||
|
||||
const QString documentPath;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>(),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -57,6 +57,8 @@ private:
|
||||
|
||||
bool isProjectHeaderPath(const QString &path) const;
|
||||
|
||||
void removeGccInternalIncludePaths();
|
||||
|
||||
static QString ensurePathWithSlashEnding(const QString &path);
|
||||
|
||||
public:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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, {});
|
||||
});
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +188,10 @@ void AbiWidget::setAbis(const Abis &abiList, const Abi ¤tAbi)
|
||||
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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 ¯oCache) 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;
|
||||
|
||||
@@ -65,7 +65,7 @@ MakeStep::MakeStep(BuildStepList *parent, Core::Id id)
|
||||
m_userJobCount(defaultJobCount())
|
||||
{
|
||||
setDefaultDisplayName(defaultDisplayName());
|
||||
setLowPriorityIfConfigured();
|
||||
setLowPriority();
|
||||
}
|
||||
|
||||
void MakeStep::setBuildTarget(const QString &buildTarget)
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -359,6 +359,7 @@ void Target::setDeploymentData(const DeploymentData &deploymentData)
|
||||
if (d->m_deploymentData != deploymentData) {
|
||||
d->m_deploymentData = deploymentData;
|
||||
emit deploymentDataChanged();
|
||||
emit applicationTargetsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user