QmlDesigner: Allow adding of resources

* Allows adding of multiple files
 * Files are copied
 * Files are added to the project
 * Supported file types can be extended

Change-Id: I41d1d18c4a3fc9c6c50e0629070d9a2cbf082976
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Thomas Hartmann
2018-01-25 16:41:24 +01:00
committed by Tim Jenssen
parent 4ebe9458c7
commit e7bc21e912
8 changed files with 150 additions and 4 deletions

View File

@@ -164,6 +164,8 @@ const int priorityGoIntoComponent = 40;
const int priorityGenericToolBar = 50; const int priorityGenericToolBar = 50;
const int priorityLast = 60; const int priorityLast = 60;
const char addImagesDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Image Files");
} //ComponentCoreConstants } //ComponentCoreConstants
} //QmlDesigner } //QmlDesigner

View File

@@ -178,6 +178,16 @@ void DesignerActionManager::setupContext()
m_designerActionManagerView->setupContext(); m_designerActionManagerView->setupContext();
} }
QList<AddResourceHandler> DesignerActionManager::addResourceHandler() const
{
return m_addResourceHandler;
}
void DesignerActionManager::registerAddResourceHandler(const AddResourceHandler &handler)
{
m_addResourceHandler.append(handler);
}
class VisiblityModelNodeAction : public ModelNodeContextMenuAction class VisiblityModelNodeAction : public ModelNodeContextMenuAction
{ {
public: public:
@@ -983,6 +993,22 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ChangeStyleAction()); 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) void DesignerActionManager::addDesignerAction(ActionInterface *newAction)
{ {
m_designerActions.append(QSharedPointer<ActionInterface>(newAction)); m_designerActions.append(QSharedPointer<ActionInterface>(newAction));

View File

@@ -42,6 +42,25 @@ namespace QmlDesigner {
class DesignerActionManagerView; class DesignerActionManagerView;
typedef std::function<bool (const QString &filename, const QString &targetDirectory)> 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 class DesignerActionToolBar : public Utils::StyledBar
{ {
public: public:
@@ -64,6 +83,7 @@ public:
QList<ActionInterface* > designerActions() const; QList<ActionInterface* > designerActions() const;
void createDefaultDesignerActions(); void createDefaultDesignerActions();
void createDefaultAddResourceHandler();
DesignerActionManagerView *view(); DesignerActionManagerView *view();
DesignerActionToolBar *createToolBar(QWidget *parent = 0) const; DesignerActionToolBar *createToolBar(QWidget *parent = 0) const;
@@ -76,9 +96,13 @@ public:
DesignerActionManager(const DesignerActionManager&) = delete; DesignerActionManager(const DesignerActionManager&) = delete;
DesignerActionManager & operator=(const DesignerActionManager&) = delete; DesignerActionManager & operator=(const DesignerActionManager&) = delete;
QList<AddResourceHandler> addResourceHandler() const;
void registerAddResourceHandler(const AddResourceHandler &handler);
private: private:
QList<QSharedPointer<ActionInterface> > m_designerActions; QList<QSharedPointer<ActionInterface> > m_designerActions;
DesignerActionManagerView *m_designerActionManagerView; DesignerActionManagerView *m_designerActionManagerView;
QList<AddResourceHandler> m_addResourceHandler;
}; };
} //QmlDesigner } //QmlDesigner

View File

@@ -56,6 +56,10 @@
#include <qmljseditor/qmljsfindreferences.h> #include <qmljseditor/qmljsfindreferences.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/projecttree.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -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 } // namespace Mode
} //QmlDesigner } //QmlDesigner

View File

@@ -72,7 +72,7 @@ void addItemToStackedContainer(const SelectionContext &selectionContext);
void increaseIndexOfStackedContainer(const SelectionContext &selectionContext); void increaseIndexOfStackedContainer(const SelectionContext &selectionContext);
void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext); void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext);
void addTabBarToStackedContainer(const SelectionContext &selectionContext); void addTabBarToStackedContainer(const SelectionContext &selectionContext);
bool addImageToProject(const QString &fileName, const QString &directory);
} // namespace ModelNodeOperationso } // namespace ModelNodeOperationso
} //QmlDesigner } //QmlDesigner

View File

@@ -45,9 +45,11 @@
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
#include <QApplication> #include <QApplication>
#include <QDrag> #include <QDrag>
#include <QFileDialog>
#include <QFileInfo> #include <QFileInfo>
#include <QFileSystemModel> #include <QFileSystemModel>
#include <QGridLayout> #include <QGridLayout>
@@ -76,6 +78,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
m_itemViewQuickWidget(new QQuickWidget), m_itemViewQuickWidget(new QQuickWidget),
m_resourcesView(new ItemLibraryResourceView(this)), m_resourcesView(new ItemLibraryResourceView(this)),
m_importTagsWidget(new QWidget(this)), m_importTagsWidget(new QWidget(this)),
m_addResourcesWidget(new QWidget(this)),
m_filterFlag(QtBasic) m_filterFlag(QtBasic)
{ {
m_compressionTimer.setInterval(200); m_compressionTimer.setInterval(200);
@@ -148,7 +151,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
layout->addWidget(spacer, 1, 0); layout->addWidget(spacer, 1, 0);
layout->addWidget(lineEditFrame, 2, 0, 1, 1); layout->addWidget(lineEditFrame, 2, 0, 1, 1);
layout->addWidget(m_importTagsWidget.data(), 3, 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()); setSearchFilter(QString());
@@ -164,6 +168,20 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
auto *flowLayout = new Utils::FlowLayout(m_importTagsWidget.data()); auto *flowLayout = new Utils::FlowLayout(m_importTagsWidget.data());
flowLayout->setMargin(4); 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 // init the first load of the QML UI elements
reloadQmlSource(); reloadQmlSource();
} }
@@ -232,12 +250,15 @@ void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index)
if (index == 2) { if (index == 2) {
m_filterLineEdit->setVisible(false); m_filterLineEdit->setVisible(false);
m_importTagsWidget->setVisible(true); m_importTagsWidget->setVisible(true);
m_addResourcesWidget->setVisible(false);
} if (index == 1) { } if (index == 1) {
m_filterLineEdit->setVisible(true); m_filterLineEdit->setVisible(true);
m_importTagsWidget->setVisible(false); m_importTagsWidget->setVisible(false);
m_addResourcesWidget->setVisible(true);
} else { } else {
m_filterLineEdit->setVisible(true); m_filterLineEdit->setVisible(true);
m_importTagsWidget->setVisible(true); m_importTagsWidget->setVisible(true);
m_addResourcesWidget->setVisible(false);
} }
m_stackedWidget->setCurrentIndex(index); m_stackedWidget->setCurrentIndex(index);
@@ -279,6 +300,7 @@ void ItemLibraryWidget::setupImportTagWidget()
button->setIcon(Utils::Icons::PLUS.icon()); button->setIcon(Utils::Icons::PLUS.icon());
button->setText(import); button->setText(import);
button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
button->setToolTip(tr("Add import %1").arg(import));
connect(button, &QToolButton::clicked, this, [this, import]() { connect(button, &QToolButton::clicked, this, [this, import]() {
addPossibleImport(import); addPossibleImport(import);
}); });
@@ -366,4 +388,47 @@ void ItemLibraryWidget::addPossibleImport(const QString &name)
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
} }
void ItemLibraryWidget::addResources()
{
auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
QTC_ASSERT(document, return);
QList<AddResourceHandler> handlers = QmlDesignerPlugin::instance()->viewManager().designerActionManager().addResourceHandler();
QMultiMap<QString, QString> 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));
}
}
}
}
} }

View File

@@ -96,6 +96,7 @@ private:
void removeImport(const QString &name); void removeImport(const QString &name);
void addImport(const QString &name, const QString &version); void addImport(const QString &name, const QString &version);
void addPossibleImport(const QString &name); void addPossibleImport(const QString &name);
void addResources();
QTimer m_compressionTimer; QTimer m_compressionTimer;
QSize m_itemIconSize; QSize m_itemIconSize;
@@ -111,6 +112,7 @@ private:
QScopedPointer<QQuickWidget> m_itemViewQuickWidget; QScopedPointer<QQuickWidget> m_itemViewQuickWidget;
QScopedPointer<ItemLibraryResourceView> m_resourcesView; QScopedPointer<ItemLibraryResourceView> m_resourcesView;
QScopedPointer<QWidget> m_importTagsWidget; QScopedPointer<QWidget> m_importTagsWidget;
QScopedPointer<QWidget> m_addResourcesWidget;
QShortcut *m_qmlSourceUpdateShortcut; QShortcut *m_qmlSourceUpdateShortcut;

View File

@@ -229,8 +229,10 @@ static void hideToolButtons(QList<QToolButton*> &buttons)
void DesignModeWidget::setup() void DesignModeWidget::setup()
{ {
viewManager().designerActionManager().createDefaultDesignerActions(); auto &actionManager = viewManager().designerActionManager();
viewManager().designerActionManager().polishActions(); actionManager.createDefaultDesignerActions();
actionManager.createDefaultAddResourceHandler();
actionManager.polishActions();
QList<Core::INavigationWidgetFactory *> factories = QList<Core::INavigationWidgetFactory *> factories =
ExtensionSystem::PluginManager::getObjects<Core::INavigationWidgetFactory>(); ExtensionSystem::PluginManager::getObjects<Core::INavigationWidgetFactory>();