diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h index 0035b90fad3..028d3a21b4b 100644 --- a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h +++ b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h @@ -164,6 +164,8 @@ const int priorityGoIntoComponent = 40; const int priorityGenericToolBar = 50; const int priorityLast = 60; +const char addImagesDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Image Files"); + } //ComponentCoreConstants } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index 629f290026e..b658f9fe407 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -178,6 +178,16 @@ void DesignerActionManager::setupContext() m_designerActionManagerView->setupContext(); } +QList DesignerActionManager::addResourceHandler() const +{ + return m_addResourceHandler; +} + +void DesignerActionManager::registerAddResourceHandler(const AddResourceHandler &handler) +{ + m_addResourceHandler.append(handler); +} + class VisiblityModelNodeAction : public ModelNodeContextMenuAction { public: @@ -983,6 +993,22 @@ void DesignerActionManager::createDefaultDesignerActions() addDesignerAction(new ChangeStyleAction()); } +void DesignerActionManager::createDefaultAddResourceHandler() +{ + registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString, + "*.png", + ModelNodeOperations::addImageToProject)); + registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString, + "*.jpg", + ModelNodeOperations::addImageToProject)); + registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString, + "*.bmp", + ModelNodeOperations::addImageToProject)); + registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString, + "*.svg", + ModelNodeOperations::addImageToProject)); +} + void DesignerActionManager::addDesignerAction(ActionInterface *newAction) { m_designerActions.append(QSharedPointer(newAction)); diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h index 6cd7d7f2e2e..b4531db8959 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h @@ -42,6 +42,25 @@ namespace QmlDesigner { class DesignerActionManagerView; +typedef std::function AddResourceOperation; + +struct AddResourceHandler +{ +public: + AddResourceHandler( const QString &_category, + const QString &_filter, + AddResourceOperation _operation) + : category(_category) + ,filter(_filter) + ,operation(_operation) + { + } + + QString category; + QString filter; + AddResourceOperation operation; +}; + class DesignerActionToolBar : public Utils::StyledBar { public: @@ -64,6 +83,7 @@ public: QList designerActions() const; void createDefaultDesignerActions(); + void createDefaultAddResourceHandler(); DesignerActionManagerView *view(); DesignerActionToolBar *createToolBar(QWidget *parent = 0) const; @@ -76,9 +96,13 @@ public: DesignerActionManager(const DesignerActionManager&) = delete; DesignerActionManager & operator=(const DesignerActionManager&) = delete; + QList addResourceHandler() const; + void registerAddResourceHandler(const AddResourceHandler &handler); + private: QList > m_designerActions; DesignerActionManagerView *m_designerActionManagerView; + QList m_addResourceHandler; }; } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index 85e67747502..0861597828f 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -56,6 +56,10 @@ #include +#include +#include +#include + #include #include @@ -1020,6 +1024,27 @@ void addTabBarToStackedContainer(const SelectionContext &selectionContext) } } +bool addImageToProject(const QString &fileName, const QString &directory) +{ + const QString targetFile = directory + "/" + QFileInfo(fileName).fileName(); + const bool success = QFile::copy(fileName, targetFile); + + auto document = QmlDesignerPlugin::instance()->currentDesignDocument(); + + QTC_ASSERT(document, return false); + + if (success) { + ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(document->fileName()); + if (node) { + ProjectExplorer::FolderNode *containingFolder = node->parentFolderNode(); + if (containingFolder) + containingFolder->addFiles(QStringList(targetFile)); + } + } + + return success; +} + } // namespace Mode } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h index 39dfef4975a..0aec320316e 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h @@ -72,7 +72,7 @@ void addItemToStackedContainer(const SelectionContext &selectionContext); void increaseIndexOfStackedContainer(const SelectionContext &selectionContext); void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext); void addTabBarToStackedContainer(const SelectionContext &selectionContext); - +bool addImageToProject(const QString &fileName, const QString &directory); } // namespace ModelNodeOperationso } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 81313c43022..2016fd909c1 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -45,9 +45,11 @@ #include #include +#include #include #include +#include #include #include #include @@ -76,6 +78,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : m_itemViewQuickWidget(new QQuickWidget), m_resourcesView(new ItemLibraryResourceView(this)), m_importTagsWidget(new QWidget(this)), + m_addResourcesWidget(new QWidget(this)), m_filterFlag(QtBasic) { m_compressionTimer.setInterval(200); @@ -148,7 +151,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : layout->addWidget(spacer, 1, 0); layout->addWidget(lineEditFrame, 2, 0, 1, 1); layout->addWidget(m_importTagsWidget.data(), 3, 0, 1, 1); - layout->addWidget(m_stackedWidget.data(), 4, 0, 1, 1); + layout->addWidget(m_addResourcesWidget.data(), 4, 0, 1, 1); + layout->addWidget(m_stackedWidget.data(), 5, 0, 1, 1); setSearchFilter(QString()); @@ -164,6 +168,20 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : auto *flowLayout = new Utils::FlowLayout(m_importTagsWidget.data()); flowLayout->setMargin(4); + m_addResourcesWidget->setVisible(false); + flowLayout = new Utils::FlowLayout(m_addResourcesWidget.data()); + flowLayout->setMargin(4); + auto button = new QToolButton(m_addResourcesWidget.data()); + auto font = button->font(); + font.setPixelSize(9); + button->setFont(font); + button->setIcon(Utils::Icons::PLUS.icon()); + button->setText(tr("Add New Resources...")); + button->setToolTip(tr("Add new resources to project.")); + button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + flowLayout->addWidget(button); + connect(button, &QToolButton::clicked, this, &ItemLibraryWidget::addResources); + // init the first load of the QML UI elements reloadQmlSource(); } @@ -232,12 +250,15 @@ void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index) if (index == 2) { m_filterLineEdit->setVisible(false); m_importTagsWidget->setVisible(true); + m_addResourcesWidget->setVisible(false); } if (index == 1) { m_filterLineEdit->setVisible(true); m_importTagsWidget->setVisible(false); + m_addResourcesWidget->setVisible(true); } else { m_filterLineEdit->setVisible(true); m_importTagsWidget->setVisible(true); + m_addResourcesWidget->setVisible(false); } m_stackedWidget->setCurrentIndex(index); @@ -279,6 +300,7 @@ void ItemLibraryWidget::setupImportTagWidget() button->setIcon(Utils::Icons::PLUS.icon()); button->setText(import); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + button->setToolTip(tr("Add import %1").arg(import)); connect(button, &QToolButton::clicked, this, [this, import]() { addPossibleImport(import); }); @@ -366,4 +388,47 @@ void ItemLibraryWidget::addPossibleImport(const QString &name) QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); } +void ItemLibraryWidget::addResources() +{ + auto document = QmlDesignerPlugin::instance()->currentDesignDocument(); + + QTC_ASSERT(document, return); + + QList handlers = QmlDesignerPlugin::instance()->viewManager().designerActionManager().addResourceHandler(); + QMultiMap map; + for (const AddResourceHandler &handler : handlers) { + map.insert(handler.category, handler.filter); + } + + QStringList filters; + + for (const QString &key : map.uniqueKeys()) { + QString str = key + " ("; + str.append(map.values(key).join(" ")); + str.append(")"); + filters.append(str); + } + + const auto fileNames = QFileDialog::getOpenFileNames(this, + tr("Add Resources"), + document->fileName().parentDir().toString(), + filters.join(";;")); + + if (!fileNames.isEmpty()) { + const auto directory = QFileDialog::getExistingDirectory(this, + tr("Target Direcotry"), + document->fileName().parentDir().toString()); + + for (const QString &fileName : fileNames) { + for (const AddResourceHandler &handler : handlers) { + QString postfix = handler.filter; + postfix.remove(0, 1); + if (fileName.endsWith(postfix)) + if (!handler.operation(fileName, directory)) + Core::AsynchronousMessageBox::warning(tr("Failed to add File"), tr("Could not add %1 to project.").arg(fileName)); + } + } + } +} + } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h index 8ca7467bfee..5e07f508755 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h @@ -96,6 +96,7 @@ private: void removeImport(const QString &name); void addImport(const QString &name, const QString &version); void addPossibleImport(const QString &name); + void addResources(); QTimer m_compressionTimer; QSize m_itemIconSize; @@ -111,6 +112,7 @@ private: QScopedPointer m_itemViewQuickWidget; QScopedPointer m_resourcesView; QScopedPointer m_importTagsWidget; + QScopedPointer m_addResourcesWidget; QShortcut *m_qmlSourceUpdateShortcut; diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 3809e0366bd..cdad6b7bd7f 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -229,8 +229,10 @@ static void hideToolButtons(QList &buttons) void DesignModeWidget::setup() { - viewManager().designerActionManager().createDefaultDesignerActions(); - viewManager().designerActionManager().polishActions(); + auto &actionManager = viewManager().designerActionManager(); + actionManager.createDefaultDesignerActions(); + actionManager.createDefaultAddResourceHandler(); + actionManager.polishActions(); QList factories = ExtensionSystem::PluginManager::getObjects();