Merge remote-tracking branch 'origin/4.15'
Change-Id: Ifae18bacb0c4bdb1e0516c9f92c0fd16150e35e6
@@ -219,10 +219,11 @@ function(add_qtc_library name)
|
||||
endif()
|
||||
|
||||
qtc_output_binary_dir(_output_binary_dir)
|
||||
string(REGEX MATCH "^[0-9]*" IDE_VERSION_MAJOR ${IDE_VERSION})
|
||||
set_target_properties(${name} PROPERTIES
|
||||
SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
VERSION "${IDE_VERSION}"
|
||||
SOVERSION "${PROJECT_VERSION_MAJOR}"
|
||||
SOVERSION "${IDE_VERSION_MAJOR}"
|
||||
MACHO_CURRENT_VERSION ${IDE_VERSION}
|
||||
MACHO_COMPATIBILITY_VERSION ${IDE_VERSION_COMPAT}
|
||||
CXX_EXTENSIONS OFF
|
||||
@@ -240,7 +241,7 @@ function(add_qtc_library name)
|
||||
if (WIN32 AND library_type STREQUAL "SHARED" AND NOT _arg_UNVERSIONED)
|
||||
# Match qmake naming scheme e.g. Library4.dll
|
||||
set_target_properties(${name} PROPERTIES
|
||||
SUFFIX "${PROJECT_VERSION_MAJOR}${CMAKE_SHARED_LIBRARY_SUFFIX}"
|
||||
SUFFIX "${IDE_VERSION_MAJOR}${CMAKE_SHARED_LIBRARY_SUFFIX}"
|
||||
PREFIX ""
|
||||
)
|
||||
endif()
|
||||
@@ -491,8 +492,9 @@ function(add_qtc_plugin target_name)
|
||||
|
||||
if (WIN32)
|
||||
# Match qmake naming scheme e.g. Plugin4.dll
|
||||
string(REGEX MATCH "^[0-9]*" IDE_VERSION_MAJOR ${IDE_VERSION})
|
||||
set_target_properties(${target_name} PROPERTIES
|
||||
SUFFIX "${PROJECT_VERSION_MAJOR}${CMAKE_SHARED_LIBRARY_SUFFIX}"
|
||||
SUFFIX "${IDE_VERSION_MAJOR}${CMAKE_SHARED_LIBRARY_SUFFIX}"
|
||||
PREFIX ""
|
||||
)
|
||||
endif()
|
||||
|
BIN
doc/qtcreator/images/qtcreator-type-hierarchy-view.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
@@ -327,8 +327,19 @@
|
||||
|
||||
\section1 Viewing Type Hierarchy
|
||||
|
||||
To view the base classes of a class, right-click the class and select
|
||||
\uicontrol {Open Type Hierarchy} or press \key {Ctrl+Shift+T}.
|
||||
To view the base classes and derived classes of a class, right-click the
|
||||
class in the code editor and select \uicontrol {Open Type Hierarchy} or
|
||||
press \key {Ctrl+Shift+T}.
|
||||
|
||||
\image qtcreator-type-hierarchy-view.png "Type Hierarchy view"
|
||||
|
||||
To navigate in the type hierarchy, double-click a class or select it,
|
||||
and then select \uicontrol {Open Type Hierarchy} in the context menu.
|
||||
The previous class is highlighted in the view.
|
||||
|
||||
The definition of the selected class is opened in the code editor. You
|
||||
can also select \uicontrol {Open in Editor} in the context menu to open
|
||||
it.
|
||||
|
||||
\section1 Viewing Include Hierarchy
|
||||
|
||||
|
@@ -6,6 +6,6 @@ if (NOT APPLE AND NOT WIN32)
|
||||
applications
|
||||
metainfo
|
||||
DESTINATION
|
||||
share
|
||||
${CMAKE_INSTALL_DATAROOTDIR}
|
||||
)
|
||||
endif()
|
||||
|
@@ -229,7 +229,8 @@ public:
|
||||
}
|
||||
if (const auto declarator = (*it)->asDeclarator()) {
|
||||
if (containsToken(declarator->core_declarator)) {
|
||||
if (declarator->initializer && (!declarator->postfix_declarator_list
|
||||
if (declarator->initializer && declarator->equal_token
|
||||
&& (!declarator->postfix_declarator_list
|
||||
|| !declarator->postfix_declarator_list->value
|
||||
|| !declarator->postfix_declarator_list->value->asFunctionDeclarator())) {
|
||||
return Usage::Type::Initialization;
|
||||
|
@@ -268,6 +268,13 @@ public:
|
||||
return second == first;
|
||||
}
|
||||
|
||||
friend bool operator!=(const Utf8String &first, const char *second)
|
||||
{
|
||||
return first.byteArray != second;
|
||||
}
|
||||
|
||||
friend bool operator!=(const char *first, const Utf8String &second) { return second != first; }
|
||||
|
||||
friend bool operator==(const Utf8String &first, const QString &second)
|
||||
{
|
||||
return first.byteArray == second.toUtf8();
|
||||
|
@@ -68,8 +68,10 @@
|
||||
#include <utils/stringutils.h>
|
||||
#include <utils/variablechooser.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QBoxLayout>
|
||||
#include <QCheckBox>
|
||||
#include <QClipboard>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDir>
|
||||
@@ -707,6 +709,23 @@ bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event)
|
||||
if ((action = createForceAction(ConfigModel::DataItem::STRING, idx)))
|
||||
menu->addAction(action);
|
||||
|
||||
auto copy = new QAction(tr("Copy"), this);
|
||||
menu->addAction(copy);
|
||||
connect(copy, &QAction::triggered, this, [this] {
|
||||
const QModelIndexList selectedIndexes = m_configView->selectionModel()->selectedIndexes();
|
||||
|
||||
const QModelIndexList validIndexes = Utils::filtered(selectedIndexes, [](const QModelIndex &index) {
|
||||
return index.isValid() && index.flags().testFlag(Qt::ItemIsSelectable);
|
||||
});
|
||||
|
||||
const QStringList variableList = Utils::transform(validIndexes, [this](const QModelIndex &index) {
|
||||
return ConfigModel::dataItemFromIndex(index)
|
||||
.toCMakeConfigItem().toArgument(m_buildConfiguration->macroExpander());
|
||||
});
|
||||
|
||||
QApplication::clipboard()->setText(variableList.join('\n'), QClipboard::Clipboard);
|
||||
});
|
||||
|
||||
menu->move(e->globalPos());
|
||||
menu->show();
|
||||
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <android/androidconstants.h>
|
||||
#include <coreplugin/fileiconprovider.h>
|
||||
#include <ios/iosconstants.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -71,7 +72,9 @@ CMakeProjectNode::CMakeProjectNode(const Utils::FilePath &directory) :
|
||||
ProjectExplorer::ProjectNode(directory)
|
||||
{
|
||||
setPriority(Node::DefaultProjectPriority + 1000);
|
||||
setIcon(QIcon(":/projectexplorer/images/projectexplorer.png")); // TODO: Use proper icon!
|
||||
static const QIcon productIcon = Core::FileIconProvider::directoryIcon(
|
||||
ProjectExplorer::Constants::FILEOVERLAY_PRODUCT);
|
||||
setIcon(productIcon);
|
||||
setListInProject(false);
|
||||
}
|
||||
|
||||
|
@@ -83,6 +83,35 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
CMakeConfigItem toCMakeConfigItem() const {
|
||||
CMakeConfigItem cmi;
|
||||
cmi.key = key.toUtf8();
|
||||
cmi.value = value.toUtf8();
|
||||
switch (type) {
|
||||
case DataItem::BOOLEAN:
|
||||
cmi.type = CMakeConfigItem::BOOL;
|
||||
break;
|
||||
case DataItem::FILE:
|
||||
cmi.type = CMakeConfigItem::FILEPATH;
|
||||
break;
|
||||
case DataItem::DIRECTORY:
|
||||
cmi.type = CMakeConfigItem::PATH;
|
||||
break;
|
||||
case DataItem::STRING:
|
||||
cmi.type = CMakeConfigItem::STRING;
|
||||
break;
|
||||
case DataItem::UNKNOWN:
|
||||
cmi.type = CMakeConfigItem::INTERNAL;
|
||||
break;
|
||||
}
|
||||
cmi.isUnset = isUnset;
|
||||
cmi.isAdvanced = isAdvanced;
|
||||
cmi.values = values;
|
||||
cmi.documentation = description.toUtf8();
|
||||
|
||||
return cmi;
|
||||
}
|
||||
|
||||
enum Type { BOOLEAN, FILE, DIRECTORY, STRING, UNKNOWN};
|
||||
|
||||
QString key;
|
||||
|
@@ -814,7 +814,7 @@ void SearchResult::setAdditionalReplaceWidget(QWidget *widget)
|
||||
*/
|
||||
void SearchResult::addResult(const SearchResultItem &item)
|
||||
{
|
||||
m_widget->addResults({item}, AddSorted);
|
||||
m_widget->addResults({item}, AddOrdered);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@@ -796,6 +796,14 @@ void MainWindow::registerDefaultActions()
|
||||
// mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
|
||||
// tmpaction->setEnabled(true);
|
||||
// connect(tmpaction, &QAction::triggered, qApp, &QApplication::aboutQt);
|
||||
|
||||
// Contact
|
||||
tmpaction = new QAction(tr("Contact..."), this);
|
||||
cmd = ActionManager::registerAction(tmpaction, "QtCreator.Contact");
|
||||
mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
|
||||
tmpaction->setEnabled(true);
|
||||
connect(tmpaction, &QAction::triggered, this, &MainWindow::contact);
|
||||
|
||||
// About sep
|
||||
if (!HostOsInfo::isMacHost()) { // doesn't have the "About" actions in the Help menu
|
||||
tmpaction = new QAction(this);
|
||||
@@ -1237,6 +1245,33 @@ void MainWindow::aboutPlugins()
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void MainWindow::contact()
|
||||
{
|
||||
QMessageBox dlg(QMessageBox::Information, tr("Contact"),
|
||||
tr("<p>Qt Creator developers can be reached at the Qt Creator mailing list:</p>"
|
||||
"%1"
|
||||
"<p>or the #qt-creator channel on FreeNode IRC:</p>"
|
||||
"%2"
|
||||
"<p>Our bug tracker is located at %3.</p>"
|
||||
"<p>Please use %4 for bigger chunks of text.</p>")
|
||||
.arg("<p> "
|
||||
"<a href=\"https://lists.qt-project.org/listinfo/qt-creator\">"
|
||||
"mailto:qt-creator@qt-project.org"
|
||||
"</a></p>")
|
||||
.arg("<p> "
|
||||
"<a href=\"https://irc.freenode.org\">"
|
||||
"irc://freenode.org/qt-creator"
|
||||
"</a></p>")
|
||||
.arg("<a href=\"https://bugreports.qt.io/projects/QTCREATORBUG\">"
|
||||
"https://bugreports.qt.io"
|
||||
"</a>")
|
||||
.arg("<a href=\"https://pastebin.com\">"
|
||||
"https://pastebin.com"
|
||||
"</a>"),
|
||||
QMessageBox::Ok, this);
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
QPrinter *MainWindow::printer() const
|
||||
{
|
||||
if (!m_printer)
|
||||
|
@@ -129,6 +129,7 @@ private:
|
||||
static void setFocusToEditor();
|
||||
void aboutQtCreator();
|
||||
void aboutPlugins();
|
||||
void contact();
|
||||
void updateFocusWidget(QWidget *old, QWidget *now);
|
||||
NavigationWidget *navigationWidget(Side side) const;
|
||||
void setSidebarVisible(bool visible, Side side);
|
||||
|
@@ -155,6 +155,8 @@ OutputWindow::OutputWindow(Context context, const QString &settingsKey, QWidget
|
||||
|
||||
connect(verticalScrollBar(), &QAbstractSlider::sliderMoved,
|
||||
this, &OutputWindow::updateAutoScroll);
|
||||
connect(verticalScrollBar(), &QAbstractSlider::sliderReleased,
|
||||
this, &OutputWindow::updateAutoScroll);
|
||||
|
||||
undoAction->setEnabled(false);
|
||||
redoAction->setEnabled(false);
|
||||
@@ -449,7 +451,7 @@ void OutputWindow::handleOutputChunk(const QString &output, OutputFormat format)
|
||||
|
||||
void OutputWindow::updateAutoScroll()
|
||||
{
|
||||
d->scrollToBottom = isScrollbarAtBottom();
|
||||
d->scrollToBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum() - 1;
|
||||
}
|
||||
|
||||
void OutputWindow::setMaxCharCount(int count)
|
||||
@@ -473,11 +475,6 @@ void OutputWindow::appendMessage(const QString &output, OutputFormat format)
|
||||
d->queueTimer.start();
|
||||
}
|
||||
|
||||
bool OutputWindow::isScrollbarAtBottom() const
|
||||
{
|
||||
return verticalScrollBar()->value() == verticalScrollBar()->maximum();
|
||||
}
|
||||
|
||||
QMimeData *OutputWindow::createMimeDataFromSelection() const
|
||||
{
|
||||
const auto mimeData = new QMimeData;
|
||||
|
@@ -91,7 +91,6 @@ public slots:
|
||||
void setWordWrapEnabled(bool wrap);
|
||||
|
||||
protected:
|
||||
bool isScrollbarAtBottom() const;
|
||||
virtual void handleLink(const QPoint &pos);
|
||||
|
||||
private:
|
||||
|
@@ -51,14 +51,14 @@
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
static const char crashReportingEnabledKey[] = "CrashReportingEnabled";
|
||||
static const char showCrashButtonKey[] = "ShowCrashButton";
|
||||
|
||||
namespace Core {
|
||||
namespace Internal {
|
||||
|
||||
// TODO: move to somewhere in Utils
|
||||
#ifdef ENABLE_CRASHPAD
|
||||
const char crashReportingEnabledKey[] = "CrashReportingEnabled";
|
||||
const char showCrashButtonKey[] = "ShowCrashButton";
|
||||
|
||||
// TODO: move to somewhere in Utils
|
||||
static QString formatSize(qint64 size)
|
||||
{
|
||||
QStringList units {QObject::tr("Bytes"), QObject::tr("KB"), QObject::tr("MB"),
|
||||
|
@@ -853,7 +853,7 @@ void DebuggerEnginePrivate::setupViews()
|
||||
|
||||
m_perspective->addWindow(m_stackWindow, Perspective::SplitVertical, nullptr);
|
||||
m_perspective->addWindow(m_breakWindow, Perspective::SplitHorizontal, m_stackWindow);
|
||||
m_perspective->addWindow(m_threadsWindow, Perspective::AddToTab, m_breakWindow,false);
|
||||
m_perspective->addWindow(m_threadsWindow, Perspective::AddToTab, m_breakWindow);
|
||||
m_perspective->addWindow(m_modulesWindow, Perspective::AddToTab, m_threadsWindow, false);
|
||||
m_perspective->addWindow(m_sourceFilesWindow, Perspective::AddToTab, m_modulesWindow, false);
|
||||
m_perspective->addWindow(m_localsAndInspectorWindow, Perspective::AddToTab, nullptr, true, Qt::RightDockWidgetArea);
|
||||
|
@@ -1558,7 +1558,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
|
||||
return;
|
||||
|
||||
// Duplicated editors are not signalled by the EditorManager. Track them nevertheless.
|
||||
connect(editor, &IEditor::editorDuplicated, this, [this, editor](IEditor *duplicate) {
|
||||
connect(editor, &IEditor::editorDuplicated, this, [this](IEditor *duplicate) {
|
||||
editorOpened(duplicate);
|
||||
connect(duplicate, &QObject::destroyed, this, [this, duplicate] {
|
||||
m_editorToHandler.remove(duplicate);
|
||||
|
@@ -931,7 +931,10 @@ void HelpWidget::updateCloseButton()
|
||||
{
|
||||
if (supportsPages()) {
|
||||
const bool closeOnReturn = LocalHelpManager::returnOnClose() && m_style == ModeWidget;
|
||||
m_closeAction->setEnabled(closeOnReturn || m_viewerStack->count() > 1);
|
||||
const bool hasMultiplePages = m_viewerStack->count() > 1;
|
||||
m_closeAction->setEnabled(closeOnReturn || hasMultiplePages);
|
||||
m_gotoPrevious->setEnabled(hasMultiplePages);
|
||||
m_gotoNext->setEnabled(hasMultiplePages);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -81,7 +81,9 @@ void OpenPagesSwitcher::gotoPreviousPage()
|
||||
void OpenPagesSwitcher::selectAndHide()
|
||||
{
|
||||
setVisible(false);
|
||||
emit setCurrentPage(m_openPagesWidget->currentIndex());
|
||||
QModelIndex index = m_openPagesWidget->currentIndex();
|
||||
if (index.isValid())
|
||||
emit setCurrentPage(index);
|
||||
}
|
||||
|
||||
void OpenPagesSwitcher::selectCurrentPage(int index)
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 257 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 510 B |
Before Width: | Height: | Size: 782 B |
@@ -8,7 +8,6 @@
|
||||
<file>images/mode_project@2x.png</file>
|
||||
<file>images/mode_project_mask.png</file>
|
||||
<file>images/mode_project_mask@2x.png</file>
|
||||
<file>images/projectexplorer.png</file>
|
||||
<file>images/buildhammerhandle.png</file>
|
||||
<file>images/buildhammerhandle@2x.png</file>
|
||||
<file>images/buildhammerhead.png</file>
|
||||
|
@@ -70,7 +70,11 @@ AnnotationCommentTab::AnnotationCommentTab(QWidget *parent)
|
||||
"project type",
|
||||
"project version",
|
||||
"Screen Description",
|
||||
"Section"}});
|
||||
"Section",
|
||||
"normalcolor",
|
||||
"focuscolor",
|
||||
"selectedcolor",
|
||||
"pressedcolor"}});
|
||||
|
||||
connect(ui->titleEdit, &QComboBox::currentTextChanged,
|
||||
this, &AnnotationCommentTab::commentTitleChanged);
|
||||
|
@@ -90,6 +90,7 @@ const char fitSelectionToScreenCommandId[] = "FitSelectionToScreen";
|
||||
const char editAnnotationCommandId[] = "EditAnnotation";
|
||||
|
||||
const char openSignalDialogCommandId[] = "OpenSignalDialog";
|
||||
const char update3DAssetCommandId[] = "Update3DAsset";
|
||||
|
||||
const char selectionCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Selection");
|
||||
const char flowConnectionCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Connect");
|
||||
@@ -131,6 +132,7 @@ const char moveToComponentDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextM
|
||||
const char editAnnotationDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Edit Annotation");
|
||||
|
||||
const char openSignalDialogDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Open Signal Dialog");
|
||||
const char update3DAssetDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Update 3D Asset");
|
||||
|
||||
const char setIdDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Set Id");
|
||||
|
||||
|
@@ -1412,6 +1412,17 @@ void DesignerActionManager::createDefaultDesignerActions()
|
||||
66,
|
||||
&openSignalDialog,
|
||||
&singleSelectionAndHasSlotTrigger));
|
||||
|
||||
addDesignerAction(new ModelNodeContextMenuAction(
|
||||
update3DAssetCommandId,
|
||||
update3DAssetDisplayName,
|
||||
{},
|
||||
rootCategory,
|
||||
QKeySequence(),
|
||||
priorityGenericToolBar,
|
||||
&updateImported3DAsset,
|
||||
&selectionIsImported3DAsset,
|
||||
&selectionIsImported3DAsset));
|
||||
}
|
||||
|
||||
void DesignerActionManager::createDefaultAddResourceHandler()
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <bindingproperty.h>
|
||||
#include <nodeproperty.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
#include <qmldesignerconstants.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -99,6 +100,21 @@ bool selectionIsComponent(const SelectionContext &selectionState)
|
||||
&& selectionState.currentSingleSelectedNode().isComponent();
|
||||
}
|
||||
|
||||
bool selectionIsImported3DAsset(const SelectionContext &selectionState)
|
||||
{
|
||||
ModelNode node = selectionState.currentSingleSelectedNode();
|
||||
if (selectionState.view() && node.isValid() && node.hasMetaInfo()) {
|
||||
QString fileName = node.metaInfo().componentFileName(); // absolute path
|
||||
if (fileName.isEmpty()) {
|
||||
// Node is not a file component, so we have to check if the current doc itself is
|
||||
fileName = node.model()->fileUrl().toLocalFile();
|
||||
}
|
||||
if (fileName.contains(Constants::QUICK_3D_ASSETS_FOLDER))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} //SelectionStateFunctors
|
||||
|
||||
} //QmlDesigner
|
||||
|
@@ -109,6 +109,7 @@ bool selectionHasSameParent(const SelectionContext &selectionState);
|
||||
bool selectionIsComponent(const SelectionContext &selectionState);
|
||||
bool singleSelectionItemIsAnchored(const SelectionContext &selectionState);
|
||||
bool singleSelectionItemIsNotAnchored(const SelectionContext &selectionState);
|
||||
bool selectionIsImported3DAsset(const SelectionContext &selectionState);
|
||||
|
||||
} // namespace SelectionStateFunctors
|
||||
|
||||
|
@@ -1581,6 +1581,15 @@ void openSignalDialog(const SelectionContext &selectionContext)
|
||||
SignalList::showWidget(selectionContext.currentSingleSelectedNode());
|
||||
}
|
||||
|
||||
void updateImported3DAsset(const SelectionContext &selectionContext)
|
||||
{
|
||||
if (selectionContext.view()) {
|
||||
selectionContext.view()->emitCustomNotification(
|
||||
"UpdateImported3DAsset", {selectionContext.currentSingleSelectedNode()});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ModelNodeOperations
|
||||
|
||||
} //QmlDesigner
|
||||
|
@@ -89,6 +89,7 @@ void removeGroup(const SelectionContext &selectionContext);
|
||||
void editAnnotation(const SelectionContext &selectionContext);
|
||||
|
||||
void openSignalDialog(const SelectionContext &selectionContext);
|
||||
void updateImported3DAsset(const SelectionContext &selectionContext);
|
||||
|
||||
// ModelNodePreviewImageOperations
|
||||
QVariant previewImageDataForGenericNode(const ModelNode &modelNode);
|
||||
|
@@ -28,26 +28,33 @@
|
||||
#include "qmldesignerplugin.h"
|
||||
#include "qmldesignerconstants.h"
|
||||
#include "model.h"
|
||||
#include "nodemetainfo.h"
|
||||
#include "variantproperty.h"
|
||||
|
||||
#include "utils/outputformatter.h"
|
||||
#include "theme.h"
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QtCore/qfileinfo.h>
|
||||
#include <QtCore/qdir.h>
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
#include <QtCore/qtimer.h>
|
||||
#include <QtCore/qjsonarray.h>
|
||||
#include <QtWidgets/qpushbutton.h>
|
||||
#include <QtWidgets/qgridlayout.h>
|
||||
#include <QtWidgets/qlabel.h>
|
||||
#include <QtWidgets/qcheckbox.h>
|
||||
#include <QtWidgets/qspinbox.h>
|
||||
#include <QtWidgets/qscrollbar.h>
|
||||
#include <QtWidgets/qtabbar.h>
|
||||
#include <QtWidgets/qscrollarea.h>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QLoggingCategory>
|
||||
#include <QTimer>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
#include <QPushButton>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QCheckBox>
|
||||
#include <QSpinBox>
|
||||
#include <QScrollBar>
|
||||
#include <QTabBar>
|
||||
#include <QScrollArea>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -70,14 +77,15 @@ static const int rowHeight = 26;
|
||||
|
||||
}
|
||||
|
||||
ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &importFiles,
|
||||
const QString &defaulTargetDirectory,
|
||||
const QVariantMap &supportedExts,
|
||||
const QVariantMap &supportedOpts,
|
||||
QWidget *parent) :
|
||||
QDialog(parent)
|
||||
ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(
|
||||
const QStringList &importFiles, const QString &defaulTargetDirectory,
|
||||
const QVariantMap &supportedExts, const QVariantMap &supportedOpts,
|
||||
const QJsonObject &defaultOpts, const QSet<QString> &preselectedFilesForOverwrite,
|
||||
QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::ItemLibraryAssetImportDialog)
|
||||
, m_importer(this)
|
||||
, m_preselectedFilesForOverwrite(preselectedFilesForOverwrite)
|
||||
{
|
||||
setModal(true);
|
||||
ui->setupUi(this);
|
||||
@@ -172,6 +180,16 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
|
||||
while (optIt != supportedOpts.constEnd()) {
|
||||
QJsonObject options = QJsonObject::fromVariantMap(qvariant_cast<QVariantMap>(optIt.value()));
|
||||
m_importOptions << options.value("options").toObject();
|
||||
auto it = defaultOpts.constBegin();
|
||||
while (it != defaultOpts.constEnd()) {
|
||||
if (m_importOptions.last().contains(it.key())) {
|
||||
QJsonObject optObj = m_importOptions.last()[it.key()].toObject();
|
||||
QJsonValue value(it.value().toObject()["value"]);
|
||||
optObj.insert("value", value);
|
||||
m_importOptions.last().insert(it.key(), optObj);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
groups << options.value("groups").toObject();
|
||||
const auto &exts = optIt.key().split(':');
|
||||
for (const auto &ext : exts)
|
||||
@@ -252,6 +270,125 @@ ItemLibraryAssetImportDialog::~ItemLibraryAssetImportDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ItemLibraryAssetImportDialog::updateImport(const ModelNode &updateNode,
|
||||
const QVariantMap &supportedExts,
|
||||
const QVariantMap &supportedOpts)
|
||||
{
|
||||
QString errorMsg;
|
||||
const ModelNode &node = updateNode;
|
||||
if (node.isValid() && node.hasMetaInfo()) {
|
||||
QString compFileName = node.metaInfo().componentFileName(); // absolute path
|
||||
bool preselectNodeSource = false;
|
||||
if (compFileName.isEmpty()) {
|
||||
// Node is not a file component, so we have to check if the current doc itself is
|
||||
compFileName = node.model()->fileUrl().toLocalFile();
|
||||
preselectNodeSource = true;
|
||||
}
|
||||
QFileInfo compFileInfo{compFileName};
|
||||
|
||||
// Find to top asset folder
|
||||
const QString assetFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER).mid(1);
|
||||
const QStringList parts = compFileName.split('/');
|
||||
int i = parts.size() - 1;
|
||||
int previousSize = 0;
|
||||
for (; i >= 0; --i) {
|
||||
if (parts[i] == assetFolder)
|
||||
break;
|
||||
previousSize = parts[i].size();
|
||||
}
|
||||
if (i >= 0) {
|
||||
const QString assetPath = compFileName.left(compFileName.lastIndexOf(assetFolder)
|
||||
+ assetFolder.size() + previousSize + 1);
|
||||
const QDir assetDir(assetPath);
|
||||
|
||||
// Find import options and the original source scene
|
||||
const QString jsonFileName = assetDir.absoluteFilePath(
|
||||
Constants::QUICK_3D_ASSET_IMPORT_DATA_NAME);
|
||||
QFile jsonFile{jsonFileName};
|
||||
if (jsonFile.open(QIODevice::ReadOnly)) {
|
||||
QJsonParseError jsonError;
|
||||
const QByteArray fileData = jsonFile.readAll();
|
||||
auto jsonDocument = QJsonDocument::fromJson(fileData, &jsonError);
|
||||
jsonFile.close();
|
||||
if (jsonError.error == QJsonParseError::NoError) {
|
||||
QJsonObject jsonObj = jsonDocument.object();
|
||||
const QJsonObject options = jsonObj.value(
|
||||
Constants::QUICK_3D_ASSET_IMPORT_DATA_OPTIONS_KEY).toObject();
|
||||
QString sourcePath = jsonObj.value(
|
||||
Constants::QUICK_3D_ASSET_IMPORT_DATA_SOURCE_KEY).toString();
|
||||
if (options.isEmpty() || sourcePath.isEmpty()) {
|
||||
errorMsg = QCoreApplication::translate(
|
||||
"ModelNodeOperations",
|
||||
"Asset import data file '%1' is invalid.").arg(jsonFileName);
|
||||
} else {
|
||||
QFileInfo sourceInfo{sourcePath};
|
||||
if (!sourceInfo.exists()) {
|
||||
// Unable to find original scene source, launch file dialog to locate it
|
||||
QString initialPath;
|
||||
ProjectExplorer::Project *currentProject
|
||||
= ProjectExplorer::SessionManager::projectForFile(
|
||||
Utils::FilePath::fromString(compFileName));
|
||||
if (currentProject)
|
||||
initialPath = currentProject->projectDirectory().toString();
|
||||
else
|
||||
initialPath = compFileInfo.absolutePath();
|
||||
QStringList selectedFiles = QFileDialog::getOpenFileNames(
|
||||
Core::ICore::dialogParent(),
|
||||
tr("Locate 3D Asset '%1'").arg(sourceInfo.fileName()),
|
||||
initialPath, sourceInfo.fileName());
|
||||
if (!selectedFiles.isEmpty()
|
||||
&& QFileInfo{selectedFiles[0]}.fileName() == sourceInfo.fileName()) {
|
||||
sourcePath = selectedFiles[0];
|
||||
sourceInfo.setFile(sourcePath);
|
||||
}
|
||||
}
|
||||
if (sourceInfo.exists()) {
|
||||
// In case of a selected node inside an imported component, preselect
|
||||
// any file pointed to by a "source" property of the node.
|
||||
QSet<QString> preselectedFiles;
|
||||
if (preselectNodeSource && updateNode.hasProperty("source")) {
|
||||
QString source = updateNode.variantProperty("source").value().toString();
|
||||
if (QFileInfo{source}.isRelative())
|
||||
source = QDir{compFileInfo.absolutePath()}.absoluteFilePath(source);
|
||||
preselectedFiles.insert(source);
|
||||
}
|
||||
auto importDlg = new ItemLibraryAssetImportDialog(
|
||||
{sourceInfo.absoluteFilePath()},
|
||||
node.model()->fileUrl().toLocalFile(),
|
||||
supportedExts, supportedOpts, options,
|
||||
preselectedFiles, Core::ICore::mainWindow());
|
||||
importDlg->show();
|
||||
|
||||
} else {
|
||||
errorMsg = QCoreApplication::translate(
|
||||
"ModelNodeOperations", "Unable to locate source scene '%1'.")
|
||||
.arg(sourceInfo.fileName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errorMsg = jsonError.errorString();
|
||||
}
|
||||
} else {
|
||||
errorMsg = QCoreApplication::translate("ModelNodeOperations",
|
||||
"Opening asset import data file '%1' failed.")
|
||||
.arg(jsonFileName);
|
||||
}
|
||||
} else {
|
||||
errorMsg = QCoreApplication::translate("ModelNodeOperations",
|
||||
"Unable to resolve asset import path.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!errorMsg.isEmpty()) {
|
||||
QMessageBox::warning(
|
||||
qobject_cast<QWidget *>(Core::ICore::dialogParent()),
|
||||
QCoreApplication::translate("ModelNodeOperations", "Import Update Failed"),
|
||||
QCoreApplication::translate("ModelNodeOperations",
|
||||
"Failed to update import.\nError:\n%1").arg(errorMsg),
|
||||
QMessageBox::Close);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemLibraryAssetImportDialog::createTab(const QString &tabLabel, int optionsIndex,
|
||||
const QJsonObject &groups)
|
||||
{
|
||||
@@ -610,7 +747,8 @@ void ItemLibraryAssetImportDialog::onImport()
|
||||
|
||||
if (!m_quick3DFiles.isEmpty()) {
|
||||
m_importer.importQuick3D(m_quick3DFiles, m_quick3DImportPath,
|
||||
m_importOptions, m_extToImportOptionsMap);
|
||||
m_importOptions, m_extToImportOptionsMap,
|
||||
m_preselectedFilesForOverwrite);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -25,9 +25,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "itemlibraryassetimporter.h"
|
||||
#include "modelnode.h"
|
||||
|
||||
#include <QtWidgets/qdialog.h>
|
||||
#include <QtCore/qjsonobject.h>
|
||||
#include <QDialog>
|
||||
#include <QJsonObject>
|
||||
#include <QSet>
|
||||
|
||||
namespace Utils {
|
||||
class OutputFormatter;
|
||||
@@ -49,9 +51,15 @@ public:
|
||||
const QString &defaulTargetDirectory,
|
||||
const QVariantMap &supportedExts,
|
||||
const QVariantMap &supportedOpts,
|
||||
const QJsonObject &defaultOpts,
|
||||
const QSet<QString> &preselectedFilesForOverwrite,
|
||||
QWidget *parent = nullptr);
|
||||
~ItemLibraryAssetImportDialog();
|
||||
|
||||
static void updateImport(const ModelNode &updateNode,
|
||||
const QVariantMap &supportedExts,
|
||||
const QVariantMap &supportedOpts);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
@@ -82,5 +90,6 @@ private:
|
||||
QHash<QString, int> m_extToImportOptionsMap;
|
||||
int m_optionsHeight = 0;
|
||||
int m_optionsRows = 0;
|
||||
QSet<QString> m_preselectedFilesForOverwrite;
|
||||
};
|
||||
}
|
||||
|
@@ -33,16 +33,19 @@
|
||||
#include "rewritertransaction.h"
|
||||
#include "rewritingexception.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QSaveFile>
|
||||
#include <QFile>
|
||||
#include <QLoggingCategory>
|
||||
#include <QTemporaryDir>
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QSaveFile>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -64,7 +67,8 @@ ItemLibraryAssetImporter::~ItemLibraryAssetImporter() {
|
||||
void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles,
|
||||
const QString &importPath,
|
||||
const QVector<QJsonObject> &options,
|
||||
const QHash<QString, int> &extToImportOptionsMap)
|
||||
const QHash<QString, int> &extToImportOptionsMap,
|
||||
const QSet<QString> &preselectedFilesForOverwrite)
|
||||
{
|
||||
if (m_isImporting)
|
||||
cancelImport();
|
||||
@@ -79,7 +83,7 @@ void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles,
|
||||
|
||||
m_importPath = importPath;
|
||||
|
||||
parseFiles(inputFiles, options, extToImportOptionsMap);
|
||||
parseFiles(inputFiles, options, extToImportOptionsMap, preselectedFilesForOverwrite);
|
||||
|
||||
if (!isCancelled()) {
|
||||
const auto parseData = m_parseData;
|
||||
@@ -203,7 +207,8 @@ void ItemLibraryAssetImporter::reset()
|
||||
|
||||
void ItemLibraryAssetImporter::parseFiles(const QStringList &filePaths,
|
||||
const QVector<QJsonObject> &options,
|
||||
const QHash<QString, int> &extToImportOptionsMap)
|
||||
const QHash<QString, int> &extToImportOptionsMap,
|
||||
const QSet<QString> &preselectedFilesForOverwrite)
|
||||
{
|
||||
if (isCancelled())
|
||||
return;
|
||||
@@ -219,7 +224,7 @@ void ItemLibraryAssetImporter::parseFiles(const QStringList &filePaths,
|
||||
int index = extToImportOptionsMap.value(QFileInfo(file).suffix());
|
||||
ParseData pd;
|
||||
pd.options = options[index];
|
||||
if (preParseQuick3DAsset(file, pd)) {
|
||||
if (preParseQuick3DAsset(file, pd, preselectedFilesForOverwrite)) {
|
||||
pd.importId = ++m_importIdCounter;
|
||||
m_parseData.insert(pd.importId, pd);
|
||||
}
|
||||
@@ -227,7 +232,8 @@ void ItemLibraryAssetImporter::parseFiles(const QStringList &filePaths,
|
||||
}
|
||||
}
|
||||
|
||||
bool ItemLibraryAssetImporter::preParseQuick3DAsset(const QString &file, ParseData &pd)
|
||||
bool ItemLibraryAssetImporter::preParseQuick3DAsset(const QString &file, ParseData &pd,
|
||||
const QSet<QString> &preselectedFilesForOverwrite)
|
||||
{
|
||||
pd.targetDir = QDir(m_importPath);
|
||||
pd.outDir = QDir(m_tempDir->path());
|
||||
@@ -264,7 +270,9 @@ bool ItemLibraryAssetImporter::preParseQuick3DAsset(const QString &file, ParseDa
|
||||
pd.assetName = assetDirs[0];
|
||||
pd.targetDirPath = pd.targetDir.filePath(pd.assetName);
|
||||
}
|
||||
OverwriteResult result = confirmAssetOverwrite(pd.assetName);
|
||||
OverwriteResult result = preselectedFilesForOverwrite.isEmpty()
|
||||
? confirmAssetOverwrite(pd.assetName)
|
||||
: OverwriteResult::Update;
|
||||
if (result == OverwriteResult::Skip) {
|
||||
addWarning(tr("Skipped import of existing asset: \"%1\"").arg(pd.assetName));
|
||||
return false;
|
||||
@@ -282,8 +290,11 @@ bool ItemLibraryAssetImporter::preParseQuick3DAsset(const QString &file, ParseDa
|
||||
alwaysOverwrite.insert(iconIt.fileInfo().absoluteFilePath());
|
||||
}
|
||||
alwaysOverwrite.insert(sourceSceneTargetFilePath(pd));
|
||||
alwaysOverwrite.insert(pd.targetDirPath + '/' + Constants::QUICK_3D_ASSET_IMPORT_DATA_NAME);
|
||||
|
||||
Internal::AssetImportUpdateDialog dlg {pd.targetDirPath, {}, alwaysOverwrite,
|
||||
Internal::AssetImportUpdateDialog dlg {pd.targetDirPath,
|
||||
preselectedFilesForOverwrite,
|
||||
alwaysOverwrite,
|
||||
qobject_cast<QWidget *>(parent())};
|
||||
int exitVal = dlg.exec();
|
||||
|
||||
@@ -291,7 +302,7 @@ bool ItemLibraryAssetImporter::preParseQuick3DAsset(const QString &file, ParseDa
|
||||
if (exitVal == QDialog::Accepted)
|
||||
overwriteFiles = dlg.selectedFiles();
|
||||
if (!overwriteFiles.isEmpty()) {
|
||||
overwriteFiles.append(QStringList::fromSet(alwaysOverwrite));
|
||||
overwriteFiles.append(Utils::toList(alwaysOverwrite));
|
||||
m_overwrittenImports.insert(pd.targetDirPath, overwriteFiles);
|
||||
} else {
|
||||
addWarning(tr("No files selected for overwrite, skipping import: \"%1\"").arg(pd.assetName));
|
||||
@@ -421,6 +432,18 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(const ParseData &pd)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate import metadata file
|
||||
const QString sourcePath = pd.sourceInfo.absoluteFilePath();
|
||||
QString importDataFileName = outDir.absoluteFilePath(Constants::QUICK_3D_ASSET_IMPORT_DATA_NAME);
|
||||
QSaveFile importDataFile(importDataFileName);
|
||||
if (importDataFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
QJsonObject optObj;
|
||||
optObj.insert(Constants::QUICK_3D_ASSET_IMPORT_DATA_OPTIONS_KEY, pd.options);
|
||||
optObj.insert(Constants::QUICK_3D_ASSET_IMPORT_DATA_SOURCE_KEY, sourcePath);
|
||||
importDataFile.write(QJsonDocument{optObj}.toJson());
|
||||
importDataFile.commit();
|
||||
}
|
||||
|
||||
// Gather all generated files
|
||||
QDirIterator dirIt(outDir.path(), QDir::Files, QDirIterator::Subdirectories);
|
||||
while (dirIt.hasNext()) {
|
||||
@@ -429,7 +452,7 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(const ParseData &pd)
|
||||
}
|
||||
|
||||
// Copy the original asset into a subdirectory
|
||||
assetFiles.insert(pd.sourceInfo.absoluteFilePath(), sourceSceneTargetFilePath(pd));
|
||||
assetFiles.insert(sourcePath, sourceSceneTargetFilePath(pd));
|
||||
m_importFiles.insert(assetFiles);
|
||||
}
|
||||
|
||||
|
@@ -54,7 +54,8 @@ public:
|
||||
|
||||
void importQuick3D(const QStringList &inputFiles, const QString &importPath,
|
||||
const QVector<QJsonObject> &options,
|
||||
const QHash<QString, int> &extToImportOptionsMap);
|
||||
const QHash<QString, int> &extToImportOptionsMap,
|
||||
const QSet<QString> &preselectedFilesForOverwrite);
|
||||
|
||||
bool isImporting() const;
|
||||
void cancelImport();
|
||||
@@ -91,8 +92,10 @@ private:
|
||||
void notifyFinished();
|
||||
void reset();
|
||||
void parseFiles(const QStringList &filePaths, const QVector<QJsonObject> &options,
|
||||
const QHash<QString, int> &extToImportOptionsMap);
|
||||
bool preParseQuick3DAsset(const QString &file, ParseData &pd);
|
||||
const QHash<QString, int> &extToImportOptionsMap,
|
||||
const QSet<QString> &preselectedFilesForOverwrite);
|
||||
bool preParseQuick3DAsset(const QString &file, ParseData &pd,
|
||||
const QSet<QString> &preselectedFilesForOverwrite);
|
||||
void postParseQuick3DAsset(const ParseData &pd);
|
||||
void copyImportedFiles();
|
||||
|
||||
|
@@ -48,6 +48,7 @@
|
||||
#include <utils/algorithm.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
#include <qmlitemnode.h>
|
||||
#include <qmldesignerconstants.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -240,7 +241,7 @@ void ItemLibraryView::updateImport3DSupport(const QVariantMap &supportMap)
|
||||
auto handle3DModel = [this](const QStringList &fileNames, const QString &defaultDir) -> bool {
|
||||
auto importDlg = new ItemLibraryAssetImportDialog(fileNames, defaultDir,
|
||||
m_importableExtensions3DMap,
|
||||
m_importOptions3DMap,
|
||||
m_importOptions3DMap, {}, {},
|
||||
Core::ICore::mainWindow());
|
||||
importDlg->show();
|
||||
return true;
|
||||
@@ -263,4 +264,15 @@ void ItemLibraryView::updateImport3DSupport(const QVariantMap &supportMap)
|
||||
m_importOptions3DMap = qvariant_cast<QVariantMap>(supportMap.value("options"));
|
||||
}
|
||||
|
||||
void ItemLibraryView::customNotification(const AbstractView *view, const QString &identifier,
|
||||
const QList<ModelNode> &nodeList, const QList<QVariant> &data)
|
||||
{
|
||||
if (identifier == "UpdateImported3DAsset" && nodeList.size() > 0) {
|
||||
ItemLibraryAssetImportDialog::updateImport(nodeList[0], m_importableExtensions3DMap,
|
||||
m_importOptions3DMap);
|
||||
} else {
|
||||
AbstractView::customNotification(view, identifier, nodeList, data);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -55,6 +55,8 @@ public:
|
||||
void usedImportsChanged(const QList<Import> &usedImports) override;
|
||||
void documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings) override;
|
||||
void updateImport3DSupport(const QVariantMap &supportMap) override;
|
||||
void customNotification(const AbstractView *view, const QString &identifier,
|
||||
const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
|
||||
|
||||
void setResourcePath(const QString &resourcePath);
|
||||
|
||||
|
@@ -144,6 +144,7 @@ void PropertyEditorValue::setValueWithEmit(const QVariant &value)
|
||||
|
||||
setValue(newValue);
|
||||
m_isBound = false;
|
||||
m_expression.clear();
|
||||
emit valueChanged(nameAsQString(), value);
|
||||
emit valueChangedQml();
|
||||
emit isBoundChanged();
|
||||
@@ -182,6 +183,7 @@ void PropertyEditorValue::setExpressionWithEmit(const QString &expression)
|
||||
{
|
||||
if ( m_expression != expression) {
|
||||
setExpression(expression);
|
||||
m_value.clear();
|
||||
emit expressionChanged(nameAsQString());
|
||||
}
|
||||
}
|
||||
|
@@ -69,6 +69,9 @@ const char QML_DESIGNER_SUBFOLDER[] = "/designer/";
|
||||
const char QUICK_3D_ASSETS_FOLDER[] = "/Quick3DAssets";
|
||||
const char QUICK_3D_ASSET_LIBRARY_ICON_SUFFIX[] = "_libicon";
|
||||
const char QUICK_3D_ASSET_ICON_DIR[] = "_icons";
|
||||
const char QUICK_3D_ASSET_IMPORT_DATA_NAME[] = "_importdata.json";
|
||||
const char QUICK_3D_ASSET_IMPORT_DATA_OPTIONS_KEY[] = "import_options";
|
||||
const char QUICK_3D_ASSET_IMPORT_DATA_SOURCE_KEY[] = "source_scene";
|
||||
const char DEFAULT_ASSET_IMPORT_FOLDER[] = "/asset_imports";
|
||||
|
||||
// Menus
|
||||
|
@@ -41,6 +41,8 @@
|
||||
#include <QPair>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace Core;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
@@ -107,6 +109,8 @@ TranslationWizardPage::TranslationWizardPage(const QString &enabledExpr)
|
||||
});
|
||||
sort(localeStrings, [](const LocalePair &l1, const LocalePair &l2) {
|
||||
return l1.first < l2.first; });
|
||||
localeStrings.erase(std::unique(localeStrings.begin(), localeStrings.end()),
|
||||
localeStrings.end());
|
||||
for (const LocalePair &lp : qAsConst(localeStrings))
|
||||
m_languageComboBox.addItem(lp.first, lp.second);
|
||||
formLayout->addRow(tr("Language:"), &m_languageComboBox);
|
||||
|
@@ -334,8 +334,6 @@ void IconLister::addProjectExplorerIcons()
|
||||
|
||||
{QIcon(":/projectexplorer/images/category_buildrun.png"), "category_buildrun.png", prefix,
|
||||
""},
|
||||
{QIcon(":/projectexplorer/images/projectexplorer.png"), "projectexplorer.png", prefix,
|
||||
""},
|
||||
{QIcon(":/projectexplorer/images/session.png"), "session.png", prefix,
|
||||
""},
|
||||
{QIcon(":/projectexplorer/images/BuildSettings.png"), "BuildSettings.png", prefix,
|
||||
|
@@ -9333,6 +9333,28 @@
|
||||
style="fill:none;stroke:#1986a0;stroke-opacity:1"
|
||||
id="path5210-3" />
|
||||
</g>
|
||||
<g
|
||||
id="src/plugins/projectexplorer/images/fileoverlay_product"
|
||||
transform="translate(160)">
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#transparentBackgroundRect"
|
||||
id="use2479-2"
|
||||
width="100%"
|
||||
transform="translate(80,68)"
|
||||
height="100%" />
|
||||
<path
|
||||
id="path2592"
|
||||
style="fill:#6300aa;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-opacity:0.75;paint-order:stroke fill"
|
||||
d="m 73.99414,527.11523 -1.03125,0.42579 0.22852,1.06445 -0.58399,0.58789 -1.0664,-0.22852 -0.42579,1.0293 0.91407,0.5918 v 0.82812 l -0.91407,0.5918 0.42579,1.03125 1.06445,-0.22852 0.58789,0.58399 -0.22852,1.0664 1.0293,0.42579 0.5918,-0.91407 h 0.82812 l 0.5918,0.91407 1.03125,-0.42579 -0.22852,-1.06445 0.58399,-0.58789 1.0664,0.22852 0.42579,-1.0293 -0.91407,-0.5918 v -0.82812 l 0.91407,-0.5918 -0.42579,-1.03125 -1.06445,0.22852 -0.58789,-0.58399 0.22852,-1.0664 -1.0293,-0.42579 -0.5918,0.91407 h -0.82812 z" />
|
||||
<circle
|
||||
style="fill:none;stroke:#ffffff"
|
||||
id="path2669"
|
||||
cx="75"
|
||||
cy="531"
|
||||
r="1.5" />
|
||||
</g>
|
||||
<g
|
||||
id="src/libs/utils/images/filesave">
|
||||
<rect
|
||||
|
Before Width: | Height: | Size: 380 KiB After Width: | Height: | Size: 381 KiB |
@@ -2021,7 +2021,7 @@ void tst_FindUsages::writableRefs()
|
||||
struct S {
|
||||
S() : value2(value) {}
|
||||
static int value;
|
||||
int value2;
|
||||
int value2 : 2;
|
||||
static void *p;
|
||||
static const void *p2;
|
||||
struct Nested {
|
||||
|
@@ -66,10 +66,12 @@ def startQC(additionalParameters=None, withPreparedSettingsPath=True, closeLinkT
|
||||
appWithOptions.extend(('-platform', 'windows:dialogs=none'))
|
||||
test.log("Starting now: %s" % ' '.join(appWithOptions))
|
||||
appContext = startApplication(' '.join(appWithOptions))
|
||||
if closeLinkToQt:
|
||||
clickButton(waitForObject(":*Qt Creator.Do Not Show Again_QToolButton"))
|
||||
if cancelTour:
|
||||
clickButton(waitForObject(":*Qt Creator.Do Not Show Again_QToolButton"))
|
||||
if closeLinkToQt or cancelTour:
|
||||
progressBarWait(3000) # wait for the "Updating documentation" progress bar
|
||||
if closeLinkToQt:
|
||||
clickButton(waitForObject(":*Qt Creator.Do Not Show Again_QToolButton"))
|
||||
if cancelTour:
|
||||
clickButton(waitForObject(":*Qt Creator.Do Not Show Again_QToolButton"))
|
||||
return appContext;
|
||||
|
||||
def startedWithoutPluginError():
|
||||
|