Merge remote-tracking branch 'origin/4.15'

Change-Id: I65e889663dac29a2efd85eba35bdb39a6611c801
This commit is contained in:
Eike Ziller
2021-02-24 13:57:54 +01:00
41 changed files with 1252 additions and 179 deletions

View File

@@ -1,24 +0,0 @@
# This needs a special conan repository to work!
# Please run:
# conan remote add qtcreator https://api.bintray.com/conan/qtcreator/qtcreator
# conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan
# to make this repository available!
#
# Then do the following to build Qt Creator:
# 1. Create a build directory and change into it
# 2. Run "conan install /path/to/qtcreator/sources --build missing"
# 3. Run "cmake -DCMAKE_TOOLCHAIN_FILE=conan_paths.cmake /path/to/qtcreator/sources -GNinja"
[requires]
qt/5.15.1@bincrafters/stable
llvm/8.0.0@qtcreator/stable
[generators]
cmake_paths
[options]
qt:qtdeclarative=True
qt:qtscript=True
qt:qtserialport=True
qt:qtsvg=True
qt:qttools=True

View File

@@ -72,6 +72,7 @@ Debugging
### LLDB
* Fixed that application output could be printed delayed (QTCREATORBUG-24667)
* Fixed performance issue (QTCREATORBUG-25185, QTCREATORBUG-25217)
### CDB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@@ -163,8 +163,10 @@
To globally change the system environment from the one in which
\QC is started, select \uicontrol Tools > \uicontrol Options >
\uicontrol Environment > \uicontrol System, and then select
\uicontrol Change in the \uicontrol Environment field. For more
information, see \l{Specifying Environment Settings}.
\uicontrol Change in the \uicontrol Environment field.
\if defined(qtcreator)
For more information, see \l{Specifying Environment Settings}.
\endif
\li Select the \uicontrol {Modifies current document} check box to make sure
that if the current document is modified by the tool, it is saved

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -411,6 +411,14 @@
For more information about the \uicontrol {QML Debugger Console} view, see
\l{Executing JavaScript Expressions}.
If the text in the output panes is not displayed correctly, \QC might
be using a different codec from the one used by the tools that generate
the output. To specify the codec to use, select \uicontrol Tools >
\uicontrol Options > \uicontrol Environment > \uicontrol Interface, and
then select the codec in the \uicontrol {Text codec for tools} field.
\image qtcreator-options-environment-interface.png "Interface tab in the Environment options"
\section1 Finding and Filtering Output
To search from output, press \key {Ctrl+F} when the pane is active. Enter

View File

@@ -230,17 +230,18 @@
\li Uses a \uicontrol Grid component to lay out the selected
components.
\li \l{Using Layouts}
\if defined(qtdesignstudio)
\row
\li \inlineimage icons/edit.png
\li \uicontrol {Show Event List} (\key {Alt+E}): opens a dialog for
viewing and creating an {event list} for an
application flow.
viewing and creating an event list for an application flow.
\li \l{Simulating Events}
\row
\li \inlineimage icons/assign.png
\li \uicontrol {Assign Events to Actions} (\key {Alt+A}): assigns
events to actions in an application flow.
\li \l{Simulating Events}
\endif
\row
\li Styling
\li Displays the UI style used for UI controls.

View File

@@ -89,9 +89,10 @@
\image qmldesigner-states.png "States and Properties views"
\note If you have \l{Locking Items}{locked an item} in \uicontrol Navigator,
and you attempt to remove states where you change the values of its
properties, you are prompted to confirm the removal.
\note If you have \l{Locking Components}{locked a component} in
\uicontrol Navigator, and you attempt to remove states where you
change the values of its properties, you are prompted to confirm
the removal.
For more information, watch the following video:

View File

@@ -107,29 +107,10 @@ def get_arguments():
args.with_debug_info = args.build_type == 'RelWithDebInfo'
return args
def build_qtcreator(args, paths):
if not os.path.exists(paths.build):
os.makedirs(paths.build)
prefix_paths = [os.path.abspath(fp) for fp in args.prefix_paths] + [paths.qt]
if paths.llvm:
prefix_paths += [paths.llvm]
if paths.elfutils:
prefix_paths += [paths.elfutils]
prefix_paths = [common.to_posix_path(fp) for fp in prefix_paths]
with_docs_str = 'OFF' if args.no_docs else 'ON'
build_date_option = 'OFF' if args.no_build_date else 'ON'
test_option = 'ON' if args.with_tests else 'OFF'
def common_cmake_arguments(args):
separate_debug_info_option = 'ON' if args.with_debug_info else 'OFF'
cmake_args = ['cmake',
'-DCMAKE_PREFIX_PATH=' + ';'.join(prefix_paths),
'-DCMAKE_BUILD_TYPE=' + args.build_type,
cmake_args = ['-DCMAKE_BUILD_TYPE=' + args.build_type,
'-DQTC_SEPARATE_DEBUG_INFO=' + separate_debug_info_option,
'-DSHOW_BUILD_DATE=' + build_date_option,
'-DWITH_DOCS=' + with_docs_str,
'-DBUILD_DEVELOPER_DOCS=' + with_docs_str,
'-DBUILD_EXECUTABLE_SDKTOOL=OFF',
'-DCMAKE_INSTALL_PREFIX=' + common.to_posix_path(paths.install),
'-DWITH_TESTS=' + test_option,
'-G', 'Ninja']
if args.python3:
@@ -147,14 +128,39 @@ def build_qtcreator(args, paths):
if not os.environ.get('CC') and not os.environ.get('CXX'):
cmake_args += ['-DCMAKE_C_COMPILER=cl',
'-DCMAKE_CXX_COMPILER=cl']
cmake_args += ['-DBUILD_EXECUTABLE_WIN32INTERRUPT=OFF',
'-DBUILD_EXECUTABLE_WIN64INTERRUPT=OFF',
'-DBUILD_LIBRARY_QTCREATORCDBEXT=OFF']
if args.python_path:
python_library = glob.glob(os.path.join(args.python_path, 'libs', 'python??.lib'))
if python_library:
cmake_args += ['-DPYTHON_LIBRARY=' + python_library[0],
'-DPYTHON_INCLUDE_DIR=' + os.path.join(args.python_path, 'include')]
return cmake_args
def build_qtcreator(args, paths):
if not os.path.exists(paths.build):
os.makedirs(paths.build)
prefix_paths = [os.path.abspath(fp) for fp in args.prefix_paths] + [paths.qt]
if paths.llvm:
prefix_paths += [paths.llvm]
if paths.elfutils:
prefix_paths += [paths.elfutils]
prefix_paths = [common.to_posix_path(fp) for fp in prefix_paths]
with_docs_str = 'OFF' if args.no_docs else 'ON'
build_date_option = 'OFF' if args.no_build_date else 'ON'
test_option = 'ON' if args.with_tests else 'OFF'
cmake_args = ['cmake',
'-DCMAKE_PREFIX_PATH=' + ';'.join(prefix_paths),
'-DSHOW_BUILD_DATE=' + build_date_option,
'-DWITH_DOCS=' + with_docs_str,
'-DBUILD_DEVELOPER_DOCS=' + with_docs_str,
'-DBUILD_EXECUTABLE_SDKTOOL=OFF',
'-DCMAKE_INSTALL_PREFIX=' + common.to_posix_path(paths.install),
'-DWITH_TESTS=' + test_option]
cmake_args += common_cmake_arguments(args)
if common.is_windows_platform():
cmake_args += ['-DBUILD_EXECUTABLE_WIN32INTERRUPT=OFF',
'-DBUILD_EXECUTABLE_WIN64INTERRUPT=OFF',
'-DBUILD_LIBRARY_QTCREATORCDBEXT=OFF']
# TODO this works around a CMake bug https://gitlab.kitware.com/cmake/cmake/issues/20119
cmake_args += ['-DBUILD_WITH_PCH=OFF']
@@ -198,28 +204,34 @@ def build_qtcreator(args, paths):
def build_wininterrupt(args, paths):
if not common.is_windows_platform():
return
# assumes existing Qt Creator build
cmake_args = ['-DBUILD_EXECUTABLE_WIN32INTERRUPT=ON',
'-DBUILD_EXECUTABLE_WIN64INTERRUPT=ON',
'-DBUILD_LIBRARY_QTCREATORCDBEXT=OFF']
common.check_print_call(['cmake'] + cmake_args + [paths.src], paths.build)
common.check_print_call(['cmake', '--build', '.'], paths.build)
if not os.path.exists(paths.wininterrupt_build):
os.makedirs(paths.wininterrupt_build)
prefix_paths = [common.to_posix_path(os.path.abspath(fp)) for fp in args.prefix_paths]
cmake_args = ['-DCMAKE_PREFIX_PATH=' + ';'.join(prefix_paths),
'-DCMAKE_INSTALL_PREFIX=' + common.to_posix_path(paths.wininterrupt_install)]
cmake_args += common_cmake_arguments(args)
common.check_print_call(['cmake'] + cmake_args + [os.path.join(paths.src, 'src', 'tools', 'wininterrupt')],
paths.wininterrupt_build)
common.check_print_call(['cmake', '--build', '.'], paths.wininterrupt_build)
common.check_print_call(['cmake', '--install', '.', '--prefix', paths.wininterrupt_install,
'--component', 'wininterrupt'],
paths.build)
paths.wininterrupt_build)
def build_qtcreatorcdbext(args, paths):
if args.no_cdb:
return
# assumes existing Qt Creator build
cmake_args = ['-DBUILD_EXECUTABLE_WIN32INTERRUPT=OFF',
'-DBUILD_EXECUTABLE_WIN64INTERRUPT=OFF',
'-DBUILD_LIBRARY_QTCREATORCDBEXT=ON']
common.check_print_call(['cmake'] + cmake_args + [paths.src], paths.build)
common.check_print_call(['cmake', '--build', '.'], paths.build)
if not os.path.exists(paths.qtcreatorcdbext_build):
os.makedirs(paths.qtcreatorcdbext_build)
prefix_paths = [common.to_posix_path(os.path.abspath(fp)) for fp in args.prefix_paths]
cmake_args = ['-DCMAKE_PREFIX_PATH=' + ';'.join(prefix_paths),
'-DCMAKE_INSTALL_PREFIX=' + common.to_posix_path(paths.qtcreatorcdbext_install)]
cmake_args += common_cmake_arguments(args)
common.check_print_call(['cmake'] + cmake_args + [os.path.join(paths.src, 'src', 'libs', 'qtcreatorcdbext')],
paths.qtcreatorcdbext_build)
common.check_print_call(['cmake', '--build', '.'], paths.qtcreatorcdbext_build)
common.check_print_call(['cmake', '--install', '.', '--prefix', paths.qtcreatorcdbext_install,
'--component', 'qtcreatorcdbext'],
paths.build)
paths.qtcreatorcdbext_build)
def package_qtcreator(args, paths):
if not args.no_zip:
@@ -261,7 +273,7 @@ def package_qtcreator(args, paths):
def get_paths(args):
Paths = collections.namedtuple('Paths',
['qt', 'src', 'build',
['qt', 'src', 'build', 'wininterrupt_build', 'qtcreatorcdbext_build',
'install', 'dev_install', 'debug_install',
'wininterrupt_install', 'qtcreatorcdbext_install', 'result',
'elfutils', 'llvm'])
@@ -270,6 +282,8 @@ def get_paths(args):
return Paths(qt=os.path.abspath(args.qt_path),
src=os.path.abspath(args.src),
build=os.path.join(build_path, 'build'),
wininterrupt_build=os.path.join(build_path, 'build-wininterrupt'),
qtcreatorcdbext_build=os.path.join(build_path, 'build-qtcreatorcdbext'),
install=os.path.join(install_path, 'qt-creator'),
dev_install=os.path.join(install_path, 'qt-creator-dev'),
debug_install=os.path.join(install_path, 'qt-creator-debug'),

View File

@@ -75,7 +75,7 @@ Item {
anchors.fill: parent
onPressed: {
rootView.startDragAndDrop(mouseRegion, itemLibraryEntry)
rootView.startDragAndDrop(itemLibraryEntry)
}
}
}

View File

@@ -307,7 +307,7 @@ QmlDesigner_ScrollBarHandleColor=ff595b5c
;palette colors
;outline colors on the combo box, zoom slider, flowtag button, dialog outlines, on loading project the whole screen flashes this color
;outline colors on the combo box, zoom slider, dialog outlines, on loading project the whole screen flashes this color
;PaletteWindow=normalBackground
PaletteWindow=ff262626
@@ -347,7 +347,7 @@ PaletteText=text
;text for flowtags, import dropdown, ticks for tick boxes.
; text for ticks for tick boxes.
PaletteButtonText=text
;PaletteButtonText=ffd3299a

View File

@@ -242,7 +242,7 @@ bool DocumentOnTypeFormattingParams::isValid(ErrorHierarchy *error) const
}
DocumentOnTypeFormattingRequest::DocumentOnTypeFormattingRequest(
const DocumentFormattingParams &params)
const DocumentOnTypeFormattingParams &params)
: Request(methodName, params)
{ }

View File

@@ -786,10 +786,10 @@ public:
};
class LANGUAGESERVERPROTOCOL_EXPORT DocumentOnTypeFormattingRequest : public Request<
QList<TextEdit>, std::nullptr_t, DocumentFormattingParams>
LanguageClientArray<TextEdit>, std::nullptr_t, DocumentOnTypeFormattingParams>
{
public:
explicit DocumentOnTypeFormattingRequest(const DocumentFormattingParams &params);
explicit DocumentOnTypeFormattingRequest(const DocumentOnTypeFormattingParams &params);
using Request::Request;
constexpr static const char methodName[] = "textDocument/onTypeFormatting";
};

View File

@@ -1,3 +1,19 @@
cmake_minimum_required(VERSION 3.10)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake")
project(qtcreatorcdbext)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (NOT QT_CREATOR_API_DEFINED)
# standalone build
include(QtCreatorIDEBranding)
include(QtCreatorAPI)
endif()
if (NOT WIN32 OR NOT MSVC)
return()
endif()
@@ -111,8 +127,10 @@ if (_library_enabled)
COMPONENT qtcreatorcdbext)
add_custom_target(copy_python_dll ALL VERBATIM)
qtc_output_binary_dir(output_binary_dir)
add_custom_command(TARGET copy_python_dll POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${deployPythonFiles} "${PROJECT_BINARY_DIR}/lib/qtcreatorcdbext${ArchSuffix}/"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${deployPythonFiles} "${output_binary_dir}/lib/qtcreatorcdbext${ArchSuffix}/"
VERBATIM
)
endif()

View File

@@ -300,6 +300,12 @@ extend_qtc_plugin(QmlDesigner
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components/itemlibrary
SOURCES
assetimportupdatedialog.cpp assetimportupdatedialog.h
assetimportupdatedialog.ui
assetimportupdatetreeitem.cpp assetimportupdatetreeitem.h
assetimportupdatetreeitemdelegate.cpp assetimportupdatetreeitemdelegate.h
assetimportupdatetreemodel.cpp assetimportupdatetreemodel.h
assetimportupdatetreeview.cpp assetimportupdatetreeview.h
customfilesystemmodel.cpp customfilesystemmodel.h
itemlibrary.qrc
itemlibraryimageprovider.cpp itemlibraryimageprovider.h

View File

@@ -0,0 +1,94 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "assetimportupdatedialog.h"
#include "ui_assetimportupdatedialog.h"
#include "assetimportupdatetreeview.h"
#include "assetimportupdatetreemodel.h"
#include <QDirIterator>
#include <QPushButton>
#include <QTreeView>
#include <QFileInfo>
#include <QModelIndex>
namespace QmlDesigner {
namespace Internal {
AssetImportUpdateDialog::AssetImportUpdateDialog(
const QString &importPath, const QSet<QString> &preSelectedFiles,
const QSet<QString> &hiddenEntries, QWidget *parent)
: QDialog(parent)
, ui(new Ui::AssetImportUpdateDialog)
{
setModal(true);
ui->setupUi(this);
connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked,
this, &AssetImportUpdateDialog::accept);
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked,
this, &AssetImportUpdateDialog::reject);
connect(ui->expandButton, &QPushButton::clicked,
this, &AssetImportUpdateDialog::expandAll);
connect(ui->collapseButton, &QPushButton::clicked,
this, &AssetImportUpdateDialog::collapseAll);
ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
QList<QFileInfo> infos;
infos.append(QFileInfo{importPath});
QDirIterator it(importPath, {"*"}, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot,
QDirIterator::Subdirectories);
while (it.hasNext()) {
it.next();
const QString absFile = it.fileInfo().absoluteFilePath();
if (!hiddenEntries.contains(absFile))
infos.append(it.fileInfo());
}
ui->treeView->model()->createItems(infos, preSelectedFiles);
ui->treeView->expandAll();
}
AssetImportUpdateDialog::~AssetImportUpdateDialog()
{
delete ui;
}
QStringList AssetImportUpdateDialog::selectedFiles() const
{
return ui->treeView->model()->checkedFiles();
}
void AssetImportUpdateDialog::collapseAll()
{
ui->treeView->collapseAll();
}
void AssetImportUpdateDialog::expandAll()
{
ui->treeView->expandAll();
}
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2021 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 <QDialog>
#include <QStringList>
#include <QSet>
namespace QmlDesigner {
namespace Internal {
namespace Ui {
class AssetImportUpdateDialog;
}
class AssetImportUpdateDialog : public QDialog
{
Q_OBJECT
public:
explicit AssetImportUpdateDialog(const QString &importPath,
const QSet<QString> &preSelectedFiles,
const QSet<QString> &hiddenEntries,
QWidget *parent = nullptr);
~AssetImportUpdateDialog();
QStringList selectedFiles() const;
private:
void collapseAll();
void expandAll();
Ui::AssetImportUpdateDialog *ui = nullptr;
};
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmlDesigner::Internal::AssetImportUpdateDialog</class>
<widget class="QDialog" name="QmlDesigner::Internal::AssetImportUpdateDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>472</width>
<height>360</height>
</rect>
</property>
<property name="windowTitle">
<string>Select Files to Update</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="AssetImportUpdateTreeView" name="treeView">
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0">
<item>
<widget class="QPushButton" name="expandButton">
<property name="text">
<string>Expand All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="collapseButton">
<property name="text">
<string>Collapse All</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>77</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>AssetImportUpdateTreeView</class>
<extends>QTreeView</extends>
<header>assetimportupdatetreeview.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "assetimportupdatetreeitem.h"
namespace QmlDesigner {
namespace Internal {
AssetImportUpdateTreeItem::AssetImportUpdateTreeItem(const QFileInfo &info,
AssetImportUpdateTreeItem *parent)
: m_parent(parent)
, m_fileInfo(info)
{
if (parent)
parent->appendChild(this);
}
AssetImportUpdateTreeItem::~AssetImportUpdateTreeItem()
{
if (m_parent)
m_parent->removeChild(this);
clear();
}
void AssetImportUpdateTreeItem::clear()
{
qDeleteAll(m_children);
m_children.clear();
m_fileInfo = {};
m_parent = nullptr;
}
int AssetImportUpdateTreeItem::childCount() const
{
return m_children.count();
}
int AssetImportUpdateTreeItem::rowOfItem() const
{
return m_parent ? m_parent->m_children.indexOf(const_cast<AssetImportUpdateTreeItem *>(this))
: 0;
}
AssetImportUpdateTreeItem *AssetImportUpdateTreeItem::childAt(int index) const
{
return m_children.at(index);
}
AssetImportUpdateTreeItem *AssetImportUpdateTreeItem::parent() const
{
return m_parent;
}
void AssetImportUpdateTreeItem::removeChild(AssetImportUpdateTreeItem *item)
{
m_children.removeOne(item);
}
void AssetImportUpdateTreeItem::appendChild(AssetImportUpdateTreeItem *item)
{
m_children.append(item);
}
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2021 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 <QString>
#include <QList>
#include <QFileInfo>
namespace QmlDesigner {
namespace Internal {
class AssetImportUpdateTreeItem
{
public:
explicit AssetImportUpdateTreeItem(const QFileInfo &info,
AssetImportUpdateTreeItem *parent = nullptr);
virtual ~AssetImportUpdateTreeItem();
AssetImportUpdateTreeItem *parent() const;
AssetImportUpdateTreeItem *childAt(int index) const;
int childCount() const;
int rowOfItem() const;
void clear();
Qt::CheckState checkState() const { return m_checkState; }
void setCheckState(Qt::CheckState checkState) { m_checkState = checkState; }
const QFileInfo &fileInfo() const { return m_fileInfo; }
void setFileInfo(const QFileInfo &info) { m_fileInfo = info; }
void removeChild(AssetImportUpdateTreeItem *item);
const QList<AssetImportUpdateTreeItem *> &children() const { return m_children; }
private:
void appendChild(AssetImportUpdateTreeItem *item);
AssetImportUpdateTreeItem *m_parent;
QList<AssetImportUpdateTreeItem *> m_children;
Qt::CheckState m_checkState = Qt::Unchecked;
QFileInfo m_fileInfo;
};
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -0,0 +1,101 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "assetimportupdatetreeitemdelegate.h"
#include "assetimportupdatetreemodel.h"
#include <QPainter>
#include <QModelIndex>
namespace QmlDesigner {
namespace Internal {
AssetImportUpdateTreeItemDelegate::AssetImportUpdateTreeItemDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
AssetImportUpdateTreeItemDelegate::LayoutInfo AssetImportUpdateTreeItemDelegate::getLayoutInfo(
const QStyleOptionViewItem &option, const QModelIndex &index) const
{
LayoutInfo info;
info.option = setOptions(index, option);
const bool checkable = (index.model()->flags(index) & Qt::ItemIsUserCheckable);
info.checkState = Qt::Unchecked;
if (checkable) {
QVariant checkStateData = index.data(Qt::CheckStateRole);
info.checkState = static_cast<Qt::CheckState>(checkStateData.toInt());
info.checkRect = doCheck(info.option, info.option.rect, checkStateData);
}
info.textRect = info.option.rect.adjusted(0, 0, info.checkRect.width(), 0);
doLayout(info.option, &info.checkRect, &info.iconRect, &info.textRect, false);
return info;
}
void AssetImportUpdateTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
painter->save();
const LayoutInfo info = getLayoutInfo(option, index);
painter->setFont(info.option.font);
drawBackground(painter, info.option, index);
drawText(painter, info.option, info.textRect, index);
drawCheck(painter, info.option, info.checkRect, info.checkState);
painter->restore();
}
QSize AssetImportUpdateTreeItemDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
const LayoutInfo info = getLayoutInfo(option, index);
const int height = index.data(Qt::SizeHintRole).value<QSize>().height();
// get text width, see QItemDelegatePrivate::displayRect
const QString text = index.data(Qt::DisplayRole).toString();
const QRect textMaxRect(0, 0, INT_MAX / 256, height);
const QRect textLayoutRect = textRectangle(nullptr, textMaxRect, info.option.font, text);
const QRect textRect(info.textRect.x(), info.textRect.y(), textLayoutRect.width(), height);
const QRect layoutRect = info.checkRect | textRect;
return QSize(layoutRect.x(), layoutRect.y()) + layoutRect.size();
}
void AssetImportUpdateTreeItemDelegate::drawText(QPainter *painter,
const QStyleOptionViewItem &option,
const QRect &rect,
const QModelIndex &index) const
{
const QString text = index.data(Qt::DisplayRole).toString();
drawDisplay(painter, option, rect, text);
}
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -0,0 +1,57 @@
/****************************************************************************
**
** Copyright (C) 2021 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 <QItemDelegate>
#include <QStyleOptionViewItem>
namespace QmlDesigner {
namespace Internal {
class AssetImportUpdateTreeItemDelegate : public QItemDelegate
{
public:
AssetImportUpdateTreeItemDelegate(QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
private:
struct LayoutInfo
{
QRect checkRect;
QRect textRect;
QRect iconRect;
Qt::CheckState checkState;
QStyleOptionViewItem option;
};
LayoutInfo getLayoutInfo(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawText(QPainter *painter, const QStyleOptionViewItem &option,
const QRect &rect, const QModelIndex &index) const;
};
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -0,0 +1,262 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "assetimportupdatetreemodel.h"
#include "assetimportupdatetreeitem.h"
#include <QSize>
namespace QmlDesigner {
namespace Internal {
AssetImportUpdateTreeModel::AssetImportUpdateTreeModel(QObject *parent)
: QAbstractItemModel(parent)
{
m_rootItem = new AssetImportUpdateTreeItem {{}};
}
AssetImportUpdateTreeModel::~AssetImportUpdateTreeModel()
{
delete m_rootItem;
}
Qt::ItemFlags AssetImportUpdateTreeModel::flags(const QModelIndex &idx) const
{
Qt::ItemFlags flags = QAbstractItemModel::flags(idx);
if (idx.isValid())
flags |= Qt::ItemIsUserCheckable;
return flags;
}
QModelIndex AssetImportUpdateTreeModel::index(int row, int column,
const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
const AssetImportUpdateTreeItem *parentItem;
parentItem = parent.isValid() ? treeItemAtIndex(parent) : m_rootItem;
const AssetImportUpdateTreeItem *childItem = parentItem->childAt(row);
if (childItem)
return createIndex(row, column, const_cast<AssetImportUpdateTreeItem *>(childItem));
else
return QModelIndex();
}
QModelIndex AssetImportUpdateTreeModel::index(AssetImportUpdateTreeItem *item) const
{
return createIndex(item->rowOfItem(), 0, item);
}
QVariant AssetImportUpdateTreeModel::data(const AssetImportUpdateTreeItem *row, int role) const
{
if (role == Qt::DisplayRole)
return row->fileInfo().fileName();
if (role == Qt::CheckStateRole)
return row->checkState();
if (role == Qt::ToolTipRole)
return row->fileInfo().absoluteFilePath();
return {};
}
QModelIndex AssetImportUpdateTreeModel::parent(const QModelIndex &idx) const
{
if (!idx.isValid())
return QModelIndex();
const AssetImportUpdateTreeItem *childItem = treeItemAtIndex(idx);
const AssetImportUpdateTreeItem *parentItem = childItem->parent();
if (parentItem == m_rootItem)
return QModelIndex();
return createIndex(parentItem->rowOfItem(), 0, const_cast<AssetImportUpdateTreeItem *>(parentItem));
}
int AssetImportUpdateTreeModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0)
return 0;
return parent.isValid() ? treeItemAtIndex(parent)->childCount()
: m_rootItem->childCount();
}
int AssetImportUpdateTreeModel::columnCount(const QModelIndex &) const
{
return 1;
}
AssetImportUpdateTreeItem *AssetImportUpdateTreeModel::treeItemAtIndex(const QModelIndex &idx)
{
return static_cast<AssetImportUpdateTreeItem*>(idx.internalPointer());
}
QVariant AssetImportUpdateTreeModel::data(const QModelIndex &idx, int role) const
{
if (!idx.isValid())
return {};
if (role == Qt::SizeHintRole)
return QSize(0, 20);
return data(treeItemAtIndex(idx), role);
}
bool AssetImportUpdateTreeModel::setData(const QModelIndex &idx, const QVariant &value, int role)
{
if (role == Qt::CheckStateRole) {
auto checkState = static_cast<Qt::CheckState>(value.toInt());
return setCheckState(idx, checkState);
}
return QAbstractItemModel::setData(idx, value, role);
}
bool AssetImportUpdateTreeModel::setCheckState(const QModelIndex &idx, Qt::CheckState checkState,
bool firstCall)
{
AssetImportUpdateTreeItem *item = treeItemAtIndex(idx);
if (item->checkState() == checkState)
return false;
item->setCheckState(checkState);
if (firstCall) {
emit dataChanged(idx, idx);
// check parents
AssetImportUpdateTreeItem *parent = item->parent();
QModelIndex parentIdx = idx.parent();
while (parent) {
bool hasChecked = false;
bool hasUnchecked = false;
for (const auto child : parent->children()) {
if (child->checkState() == Qt::Checked) {
hasChecked = true;
} else if (child->checkState() == Qt::Unchecked) {
hasUnchecked = true;
} else if (child->checkState() == Qt::PartiallyChecked) {
hasChecked = true;
hasUnchecked = true;
}
}
if (hasChecked && hasUnchecked)
parent->setCheckState(Qt::PartiallyChecked);
else if (hasChecked)
parent->setCheckState(Qt::Checked);
else
parent->setCheckState(Qt::Unchecked);
emit dataChanged(parentIdx, parentIdx);
parent = parent->parent();
parentIdx = parentIdx.parent();
}
}
// check children
if (int children = item->childCount()) {
for (int i = 0; i < children; ++i)
setCheckState(index(i, 0, idx), checkState, false);
emit dataChanged(index(0, 0, idx), index(children - 1, 0, idx));
}
return true;
}
void AssetImportUpdateTreeModel::createItems(const QList<QFileInfo> &infos,
const QSet<QString> &preselectedFiles)
{
beginResetModel();
if (!infos.isEmpty()) {
QHash<QString, AssetImportUpdateTreeItem *> dirItems;
for (const auto &info : infos) {
auto parent = dirItems.value(info.absolutePath());
if (!parent)
parent = m_rootItem;
auto item = new AssetImportUpdateTreeItem(info, parent);
if (info.isDir()) {
dirItems.insert(info.absoluteFilePath(), item);
} else {
m_fileItems.append(item);
if (preselectedFiles.contains(info.absoluteFilePath()))
item->setCheckState(Qt::Checked);
}
}
// Remove dir items that have no children from the model
for (auto dirItem : qAsConst(dirItems)) {
if (dirItem->childCount() == 0)
delete dirItem;
}
std::function<Qt::CheckState (AssetImportUpdateTreeItem *)> updateDirCheckStatesRecursive;
updateDirCheckStatesRecursive = [&](AssetImportUpdateTreeItem *item) -> Qt::CheckState {
bool hasChecked = false;
bool hasUnchecked = false;
for (const auto child : item->children()) {
Qt::CheckState childState = child->childCount() > 0
? updateDirCheckStatesRecursive(child)
: child->checkState();
if (childState == Qt::Checked) {
hasChecked = true;
} else if (childState == Qt::Unchecked) {
hasUnchecked = true;
} else {
hasChecked = true;
hasUnchecked = true;
break;
}
}
Qt::CheckState retval = Qt::Unchecked;
if (hasChecked && hasUnchecked)
retval = Qt::PartiallyChecked;
else if (hasChecked)
retval = Qt::Checked;
item->setCheckState(retval);
return retval;
};
m_rootItem->setCheckState(updateDirCheckStatesRecursive(m_rootItem));
}
endResetModel();
}
QStringList AssetImportUpdateTreeModel::checkedFiles() const
{
QStringList retList;
for (const auto item : qAsConst(m_fileItems)) {
if (item->checkState() == Qt::Checked)
retList.append(item->fileInfo().absoluteFilePath());
}
return retList;
}
void AssetImportUpdateTreeModel::clear()
{
beginResetModel();
m_fileItems.clear();
m_rootItem->clear(); // Deletes all children
endResetModel();
}
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2021 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 <QAbstractItemModel>
#include <QFileInfo>
#include <QList>
#include <QSet>
#include <QStringList>
namespace QmlDesigner {
namespace Internal {
class AssetImportUpdateTreeItem;
class AssetImportUpdateTreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
AssetImportUpdateTreeModel(QObject *parent = nullptr);
~AssetImportUpdateTreeModel() override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
void createItems(const QList<QFileInfo> &infos, const QSet<QString> &preselectedFiles);
QStringList checkedFiles() const;
static AssetImportUpdateTreeItem *treeItemAtIndex(const QModelIndex &idx);
public slots:
void clear();
private:
QModelIndex index(AssetImportUpdateTreeItem *item) const;
QVariant data(const AssetImportUpdateTreeItem *row, int role) const;
bool setCheckState(const QModelIndex &idx, Qt::CheckState checkState, bool firstCall = true);
AssetImportUpdateTreeItem *m_rootItem;
QList<AssetImportUpdateTreeItem *> m_fileItems;
};
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -0,0 +1,57 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "assetimportupdatetreeview.h"
#include "assetimportupdatetreemodel.h"
#include "assetimportupdatetreeitemdelegate.h"
#include <QHeaderView>
namespace QmlDesigner {
namespace Internal {
AssetImportUpdateTreeView::AssetImportUpdateTreeView(QWidget *parent)
: Utils::TreeView(parent)
, m_model(new AssetImportUpdateTreeModel(this))
{
setModel(m_model);
setItemDelegate(new AssetImportUpdateTreeItemDelegate(this));
setUniformRowHeights(true);
setExpandsOnDoubleClick(true);
header()->hide();
}
void AssetImportUpdateTreeView::clear()
{
m_model->clear();
}
AssetImportUpdateTreeModel *AssetImportUpdateTreeView::model() const
{
return m_model;
}
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -0,0 +1,54 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "assetimportupdatetreeitem.h"
#include <utils/itemviews.h>
namespace QmlDesigner {
namespace Internal {
class AssetImportUpdateTreeModel;
class AssetImportUpdateTreeView : public Utils::TreeView
{
Q_OBJECT
public:
explicit AssetImportUpdateTreeView(QWidget *parent = nullptr);
AssetImportUpdateTreeModel *model() const;
public slots:
void clear();
protected:
AssetImportUpdateTreeModel *m_model;
};
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -15,7 +15,12 @@ HEADERS += itemlibraryview.h \
itemlibraryaddimportmodel.h \
itemlibraryassetimportdialog.h \
itemlibraryassetimporter.h \
customfilesystemmodel.h
customfilesystemmodel.h \
assetimportupdatedialog.h \
assetimportupdatetreeitem.h \
assetimportupdatetreeitemdelegate.h \
assetimportupdatetreemodel.h \
assetimportupdatetreeview.h
SOURCES += itemlibraryview.cpp \
$$PWD/itemlibraryiconimageprovider.cpp \
@@ -31,7 +36,13 @@ SOURCES += itemlibraryview.cpp \
itemlibraryaddimportmodel.cpp \
itemlibraryassetimportdialog.cpp \
itemlibraryassetimporter.cpp \
customfilesystemmodel.cpp
customfilesystemmodel.cpp \
assetimportupdatedialog.cpp \
assetimportupdatetreeitem.cpp \
assetimportupdatetreeitemdelegate.cpp \
assetimportupdatetreemodel.cpp \
assetimportupdatetreeview.cpp
RESOURCES += itemlibrary.qrc
FORMS += itemlibraryassetimportdialog.ui
FORMS += itemlibraryassetimportdialog.ui \
assetimportupdatedialog.ui

View File

@@ -23,6 +23,7 @@
**
****************************************************************************/
#include "itemlibraryassetimporter.h"
#include "assetimportupdatedialog.h"
#include "qmldesignerplugin.h"
#include "qmldesignerconstants.h"
@@ -41,6 +42,7 @@
#include <QApplication>
#include <QMessageBox>
#include <QJsonDocument>
#include <QPushButton>
namespace
{
@@ -262,11 +264,43 @@ bool ItemLibraryAssetImporter::preParseQuick3DAsset(const QString &file, ParseDa
pd.assetName = assetDirs[0];
pd.targetDirPath = pd.targetDir.filePath(pd.assetName);
}
if (!confirmAssetOverwrite(pd.assetName)) {
OverwriteResult result = confirmAssetOverwrite(pd.assetName);
if (result == OverwriteResult::Skip) {
addWarning(tr("Skipped import of existing asset: \"%1\"").arg(pd.assetName));
return false;
} else if (result == OverwriteResult::Update) {
// Add generated icons and existing source asset file, as those will always need
// to be overwritten
QSet<QString> alwaysOverwrite;
QString iconPath = pd.targetDirPath + '/' + Constants::QUICK_3D_ASSET_ICON_DIR;
// Note: Despite the name, QUICK_3D_ASSET_LIBRARY_ICON_SUFFIX is not a traditional file
// suffix. It's guaranteed to be in the generated icon filename, though.
QStringList filters {QStringLiteral("*%1*").arg(Constants::QUICK_3D_ASSET_LIBRARY_ICON_SUFFIX)};
QDirIterator iconIt(iconPath, filters, QDir::Files);
while (iconIt.hasNext()) {
iconIt.next();
alwaysOverwrite.insert(iconIt.fileInfo().absoluteFilePath());
}
alwaysOverwrite.insert(sourceSceneTargetFilePath(pd));
Internal::AssetImportUpdateDialog dlg {pd.targetDirPath, {}, alwaysOverwrite,
qobject_cast<QWidget *>(parent())};
int exitVal = dlg.exec();
QStringList overwriteFiles;
if (exitVal == QDialog::Accepted)
overwriteFiles = dlg.selectedFiles();
if (!overwriteFiles.isEmpty()) {
overwriteFiles.append(QStringList::fromSet(alwaysOverwrite));
m_overwrittenImports.insert(pd.targetDirPath, overwriteFiles);
} else {
addWarning(tr("No files selected for overwrite, skipping import: \"%1\"").arg(pd.assetName));
return false;
}
} else {
m_overwrittenImports.insert(pd.targetDirPath, {});
}
m_overwrittenImports << pd.targetDirPath;
}
pd.outDir.mkpath(pd.assetName);
@@ -395,8 +429,7 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(const ParseData &pd)
}
// Copy the original asset into a subdirectory
assetFiles.insert(pd.sourceInfo.absoluteFilePath(),
pd.targetDirPath + QStringLiteral("/source scene/") + pd.sourceInfo.fileName());
assetFiles.insert(pd.sourceInfo.absoluteFilePath(), sourceSceneTargetFilePath(pd));
m_importFiles.insert(assetFiles);
}
@@ -408,11 +441,22 @@ void ItemLibraryAssetImporter::copyImportedFiles()
notifyProgress(0, progressTitle);
int counter = 0;
for (const QString &dirPath : qAsConst(m_overwrittenImports)) {
QDir dir(dirPath);
if (dir.exists())
auto it = m_overwrittenImports.constBegin();
while (it != m_overwrittenImports.constEnd()) {
QDir dir(it.key());
if (dir.exists()) {
const auto &overwrittenFiles = it.value();
if (overwrittenFiles.isEmpty()) {
// Overwrite entire import
dir.removeRecursively();
} else {
// Overwrite just selected files
for (const auto &fileName : overwrittenFiles)
QFile::remove(fileName);
}
}
notifyProgress((100 * ++counter) / m_overwrittenImports.size(), progressTitle);
++it;
}
}
@@ -430,7 +474,7 @@ void ItemLibraryAssetImporter::copyImportedFiles()
// by filesystem watchers.
QHash<QString, QString>::const_iterator it = assetFiles.begin();
while (it != assetFiles.end()) {
if (QFileInfo::exists(it.key())) {
if (QFileInfo::exists(it.key()) && !QFileInfo::exists(it.value())) {
QDir targetDir = QFileInfo(it.value()).dir();
if (!targetDir.exists())
targetDir.mkpath(".");
@@ -461,13 +505,26 @@ void ItemLibraryAssetImporter::keepUiAlive() const
QApplication::processEvents();
}
bool ItemLibraryAssetImporter::confirmAssetOverwrite(const QString &assetName)
ItemLibraryAssetImporter::OverwriteResult ItemLibraryAssetImporter::confirmAssetOverwrite(const QString &assetName)
{
const QString title = tr("Overwrite Existing Asset?");
const QString question = tr("Asset already exists. Overwrite?\n\"%1\"").arg(assetName);
return QMessageBox::question(qobject_cast<QWidget *>(parent()),
title, question,
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes;
const QString question = tr("Asset already exists. Overwrite existing or skip?\n\"%1\"").arg(assetName);
QMessageBox msgBox {QMessageBox::Question, title, question, QMessageBox::NoButton,
qobject_cast<QWidget *>(parent())};
QPushButton *updateButton = msgBox.addButton(tr("Overwrite Selected Files"), QMessageBox::NoRole);
QPushButton *overwriteButton = msgBox.addButton(tr("Overwrite All Files"), QMessageBox::NoRole);
QPushButton *skipButton = msgBox.addButton(tr("Skip"), QMessageBox::NoRole);
msgBox.setDefaultButton(overwriteButton);
msgBox.setEscapeButton(skipButton);
msgBox.exec();
if (msgBox.clickedButton() == updateButton)
return OverwriteResult::Update;
else if (msgBox.clickedButton() == overwriteButton)
return OverwriteResult::Overwrite;
return OverwriteResult::Skip;
}
bool ItemLibraryAssetImporter::startImportProcess(const ParseData &pd)
@@ -623,6 +680,11 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
}
}
QString ItemLibraryAssetImporter::sourceSceneTargetFilePath(const ParseData &pd)
{
return pd.targetDirPath + QStringLiteral("/source scene/") + pd.sourceInfo.fileName();
}
bool ItemLibraryAssetImporter::isCancelled() const
{
keepUiAlive();

View File

@@ -99,14 +99,22 @@ private:
void notifyProgress(int value, const QString &text);
void notifyProgress(int value);
void keepUiAlive() const;
bool confirmAssetOverwrite(const QString &assetName);
enum class OverwriteResult {
Skip,
Overwrite,
Update
};
OverwriteResult confirmAssetOverwrite(const QString &assetName);
bool startImportProcess(const ParseData &pd);
bool startIconProcess(int size, const QString &iconFile, const QString &iconSource);
void postImport();
void finalizeQuick3DImport();
QString sourceSceneTargetFilePath(const ParseData &pd);
QSet<QHash<QString, QString>> m_importFiles;
QSet<QString> m_overwrittenImports;
QHash<QString, QStringList> m_overwrittenImports;
bool m_isImporting = false;
bool m_cancelled = false;
QString m_importPath;

View File

@@ -64,6 +64,9 @@ QString ItemLibraryImport::sortingName() const
if (m_isUserSection) // user components always come first
return "_";
if (!hasCategories()) // imports with no categories are at the bottom of the list
return "zzzzz" + importName();
return importName();
}

View File

@@ -30,12 +30,13 @@
#include "itemlibraryitem.h"
#include "itemlibraryinfo.h"
#include <designermcumanager.h>
#include <model.h>
#include <nodehints.h>
#include <nodemetainfo.h>
#include <designermcumanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include "qmldesignerplugin.h"
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
@@ -184,9 +185,13 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
beginResetModel();
clearSections();
Utils::FilePath qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName();
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(qmlFileName);
QString projectName = project ? project->displayName() : "";
// create import sections
for (const Import &import : model->imports()) {
if (import.isLibraryImport()) {
if (import.isLibraryImport() && import.url() != projectName) {
ItemLibraryImport *itemLibImport = new ItemLibraryImport(import, this);
m_importList.append(itemLibImport);
itemLibImport->setImportExpanded(loadExpandedState(import.url()));

View File

@@ -84,6 +84,17 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event)
if (event->type() == QEvent::FocusOut) {
if (obj == m_itemViewQuickWidget.data())
QMetaObject::invokeMethod(m_itemViewQuickWidget->rootObject(), "closeContextMenu");
} else if (event->type() == QMouseEvent::MouseMove) {
if (m_itemToDrag.isValid()) {
ItemLibraryEntry entry = m_itemToDrag.value<ItemLibraryEntry>();
auto drag = new QDrag(this);
drag->setPixmap(Utils::StyleHelper::dpiSpecificImageFile(entry.libraryEntryIconPath()));
drag->setMimeData(m_itemLibraryModel->getMimeData(entry));
drag->exec();
drag->deleteLater();
m_itemToDrag = {};
}
}
return QObject::eventFilter(obj, event);
@@ -218,15 +229,11 @@ void ItemLibraryWidget::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo)
if (m_itemLibraryInfo) {
disconnect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
this, &ItemLibraryWidget::delayedUpdateModel);
disconnect(m_itemLibraryInfo.data(), &ItemLibraryInfo::importTagsChanged,
this, &ItemLibraryWidget::delayedUpdateModel);
}
m_itemLibraryInfo = itemLibraryInfo;
if (itemLibraryInfo) {
connect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
this, &ItemLibraryWidget::delayedUpdateModel);
connect(m_itemLibraryInfo.data(), &ItemLibraryInfo::importTagsChanged,
this, &ItemLibraryWidget::delayedUpdateModel);
}
delayedUpdateModel();
}
@@ -367,25 +374,12 @@ void ItemLibraryWidget::setResourcePath(const QString &resourcePath)
updateSearch();
}
void ItemLibraryWidget::startDragAndDrop(QQuickItem *mouseArea, QVariant itemLibraryId)
void ItemLibraryWidget::startDragAndDrop(const QVariant &itemLibEntry)
{
m_currentitemLibraryEntry = itemLibraryId.value<ItemLibraryEntry>();
QMimeData *mimeData = m_itemLibraryModel->getMimeData(m_currentitemLibraryEntry);
auto drag = new QDrag(this);
drag->setPixmap(Utils::StyleHelper::dpiSpecificImageFile(
m_currentitemLibraryEntry.libraryEntryIconPath()));
drag->setMimeData(mimeData);
/* Workaround for bug in Qt. The release event is not delivered for Qt < 5.9 if a drag is started */
QMouseEvent event (QEvent::MouseButtonRelease, QPoint(-1, -1), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QApplication::sendEvent(mouseArea, &event);
QTimer::singleShot(0, [drag]() {
drag->exec();
drag->deleteLater();
});
// Actual drag is created after mouse has moved to avoid a QDrag bug that causes drag to stay
// active (and blocks mouse release) if mouse is released at the same spot of the drag start.
// This doesn't completely eliminate the bug but makes it significantly harder to produce.
m_itemToDrag = itemLibEntry;
}
void ItemLibraryWidget::setFlowMode(bool b)

View File

@@ -87,7 +87,7 @@ public:
void setModel(Model *model);
void setFlowMode(bool b);
Q_INVOKABLE void startDragAndDrop(QQuickItem *mouseArea, QVariant itemLibId);
Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry);
Q_INVOKABLE void removeImport(const QString &importUrl);
signals:
@@ -123,7 +123,7 @@ private:
QShortcut *m_qmlSourceUpdateShortcut;
AsynchronousImageCache &m_imageCache;
QPointer<Model> m_model;
ItemLibraryEntry m_currentitemLibraryEntry;
QVariant m_itemToDrag;
bool m_updateRetry = false;
QString m_filterText;

View File

@@ -108,14 +108,11 @@ public:
void clearEntries();
QStringList blacklistImports() const;
QStringList showTagsForImports() const;
void addBlacklistImports(const QStringList &list);
void addShowTagsForImports(const QStringList &list);
signals:
void entriesChanged();
void importTagsChanged();
private: // functions
ItemLibraryInfo(QObject *parent = nullptr);
@@ -126,7 +123,6 @@ private: // variables
QPointer<ItemLibraryInfo> m_baseInfo;
QStringList m_blacklistImports;
QStringList m_showTagsForImports;
};
} // namespace QmlDesigner

View File

@@ -344,29 +344,11 @@ QStringList ItemLibraryInfo::blacklistImports() const
return list;
}
// TODO: remove this and its dependencies, as flow tags are removed
QStringList ItemLibraryInfo::showTagsForImports() const
{
auto list = m_showTagsForImports;
if (m_baseInfo)
list.append(m_baseInfo->m_showTagsForImports);
list.removeDuplicates();
return list;
}
void ItemLibraryInfo::addBlacklistImports(const QStringList &list)
{
m_blacklistImports.append(list);
}
void ItemLibraryInfo::addShowTagsForImports(const QStringList &list)
{
if (!list.isEmpty()) {
m_showTagsForImports.append(list);
emit importTagsChanged();
}
}
void ItemLibraryInfo::setBaseInfo(ItemLibraryInfo *baseInfo)
{
m_baseInfo = baseInfo;

View File

@@ -231,7 +231,7 @@ void MetaInfoReader::readImportsProperty(const QString &name, const QVariant &va
if (name == "blacklistImports" && !values.isEmpty()) {
m_metaInfo.itemLibraryInfo()->addBlacklistImports(values);
} else if (name == "showTagsForImports" && !values.isEmpty()) {
m_metaInfo.itemLibraryInfo()->addShowTagsForImports(values);
// Flow tags removed, but keeping this for now to avoid errors parsing old metadata files
} else {
addError(tr("Unknown property for Imports %1").arg(name), currentSourceLocation());
setParserState(Error);

View File

@@ -369,23 +369,6 @@ void SubComponentManager::parseQuick3DAssetDir(const QString &assetPath)
for (QString &asset : assets)
asset.prepend(assetImportRoot + QLatin1Char('.'));
QStringList newFlowTags;
const QStringList flowTags = model()->metaInfo().itemLibraryInfo()->showTagsForImports();
const QString quick3Dlib = QLatin1String(Constants::QT_QUICK_3D_MODULE_NAME);
const QList<Import> possibleImports = model()->possibleImports();
auto isPossibleImport = [&possibleImports](const QString &asset) {
for (const Import &import : possibleImports) {
if (import.url() == asset)
return true;
}
return false;
};
// If there are 3D assets in import path, add a flow tag for QtQuick3D
if (!assets.isEmpty() && !flowTags.contains(quick3Dlib) && isPossibleImport(quick3Dlib))
newFlowTags << quick3Dlib;
// Create item library entries for Quick3D assets that are imported by document
const QString iconPath = QStringLiteral(":/ItemLibrary/images/item-3D_model-icon.png");
for (auto &import : qAsConst(m_imports)) {
@@ -427,17 +410,6 @@ void SubComponentManager::parseQuick3DAssetDir(const QString &assetPath)
}
}
}
// Create flow tags for the rest, if they are possible imports
if (!assets.isEmpty()) {
for (const QString &asset : qAsConst(assets)) {
if (!flowTags.contains(asset) && isPossibleImport(asset))
newFlowTags << asset;
}
}
if (!newFlowTags.isEmpty())
model()->metaInfo().itemLibraryInfo()->addShowTagsForImports(newFlowTags);
}
QStringList SubComponentManager::quick3DAssetPaths() const

View File

@@ -70,7 +70,6 @@ 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 DEFAULT_ASSET_IMPORT_FOLDER[] = "/asset_imports";
const char QT_QUICK_3D_MODULE_NAME[] = "QtQuick3D";
// Menus
const char M_VIEW_WORKSPACES[] = "QmlDesigner.Menu.View.Workspaces";
@@ -86,7 +85,6 @@ const char EVENT_ANNOTATION_ADDED[] = "Annotation Added";
const char EVENT_RESOURCE_IMPORTED[] = "Resource Imported ";
const char EVENT_ACTION_EXECUTED[] = "Action Executed ";
const char EVENT_IMPORT_ADDED[] = "Import Added ";
const char EVENT_IMPORT_ADDED_FLOWTAG[] = "Import Added FlowTag ";
const char EVENT_BINDINGEDITOR_OPENED[] = "Binding Editor Opened";
const char EVENT_RICHTEXT_OPENED[] = "Richtext Editor Opened";
const char EVENT_FORMEDITOR_TIME[] = "Form Editor";

View File

@@ -603,6 +603,17 @@ Project {
"integration/stackedutilitypanelcontroller.h",
"integration/utilitypanelcontroller.cpp",
"integration/utilitypanelcontroller.h",
"itemlibrary/assetimportupdatedialog.cpp",
"itemlibrary/assetimportupdatedialog.h",
"itemlibrary/assetimportupdatedialog.ui",
"itemlibrary/assetimportupdatetreeitem.cpp",
"itemlibrary/assetimportupdatetreeitem.h",
"itemlibrary/assetimportupdatetreeitemdelegate.cpp",
"itemlibrary/assetimportupdatetreeitemdelegate.h",
"itemlibrary/assetimportupdatetreemodel.cpp",
"itemlibrary/assetimportupdatetreemodel.h",
"itemlibrary/assetimportupdatetreeview.cpp",
"itemlibrary/assetimportupdatetreeview.h",
"itemlibrary/itemlibrary.qrc",
"itemlibrary/itemlibraryaddimportmodel.cpp",
"itemlibrary/itemlibraryaddimportmodel.h",

View File

@@ -7,7 +7,8 @@ STATIC_OUTPUT_BASE = $$IDE_DATA_PATH
STATIC_INSTALL_BASE = $$INSTALL_DATA_PATH
DATA_DIRS = \
fonts
fonts \
package-manager
for(data_dir, DATA_DIRS) {
STATIC_FILES += $$files($$PWD/$$data_dir/*, true)

View File

@@ -37,6 +37,7 @@ if (ENABLE_BUILD_QBS)
set(INSTALL_PUBLIC_HEADERS OFF CACHE BOOL "")
set(WITH_TESTS OFF)
set(WITH_PROJECT_FILE_UPDATES ON)
set(QBS_INSTALL_QCH_DOCS ${WITH_DOCS} CACHE BOOL "")
add_subdirectory(qbs)
endif()

View File

@@ -1,3 +1,19 @@
cmake_minimum_required(VERSION 3.10)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake")
project(wininterrupt)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (NOT QT_CREATOR_API_DEFINED)
# standalone build
include(QtCreatorIDEBranding)
include(QtCreatorAPI)
endif()
if (NOT WIN32)
return()
endif()