diff --git a/src/plugins/resourceeditor/qrceditor/qrceditor.cpp b/src/plugins/resourceeditor/qrceditor/qrceditor.cpp index 2fa4aa6ec0541f0daeca2710153ab4671bc0b59a..5101b711034b8b8c4be860ef05a4511aa2971017 100644 --- a/src/plugins/resourceeditor/qrceditor/qrceditor.cpp +++ b/src/plugins/resourceeditor/qrceditor/qrceditor.cpp @@ -54,6 +54,8 @@ QrcEditor::QrcEditor(QWidget *parent) layout->addWidget(m_treeview); connect(m_ui.removeButton, SIGNAL(clicked()), this, SLOT(onRemove())); + connect(m_ui.removeNonExistingButton, &QPushButton::clicked, + this, &QrcEditor::onRemoveNonExisting); // 'Add' button with menu QMenu *addMenu = new QMenu(this); @@ -402,6 +404,16 @@ void QrcEditor::onRemove() updateHistoryControls(); } +// Slot for 'Remove missing files' button +void QrcEditor::onRemoveNonExisting() +{ + QList toRemove = m_treeview->nonExistingFiles(); + + QUndoCommand * const removeCommand = new RemoveMultipleEntryCommand(m_treeview, toRemove); + m_history.push(removeCommand); + updateHistoryControls(); +} + // Slot for 'Add File' button void QrcEditor::onAddFiles() { diff --git a/src/plugins/resourceeditor/qrceditor/qrceditor.h b/src/plugins/resourceeditor/qrceditor/qrceditor.h index 3e51a8003bdc93cad17cacd9f7ecc0a18641b867..0bdf999f41538c479a857373e4e4a0fb347cf940 100644 --- a/src/plugins/resourceeditor/qrceditor/qrceditor.h +++ b/src/plugins/resourceeditor/qrceditor/qrceditor.h @@ -86,6 +86,7 @@ private slots: void onPrefixChanged(const QString &prefix); void onLanguageChanged(const QString &language); void onRemove(); + void onRemoveNonExisting(); void onAddFiles(); void onAddPrefix(); diff --git a/src/plugins/resourceeditor/qrceditor/qrceditor.ui b/src/plugins/resourceeditor/qrceditor/qrceditor.ui index f9245dcaf52ce700d30a2bec3198484eeb4f1454..5bac2230ce303e787ad4bb4c21c3489617af0597 100644 --- a/src/plugins/resourceeditor/qrceditor/qrceditor.ui +++ b/src/plugins/resourceeditor/qrceditor/qrceditor.ui @@ -14,7 +14,16 @@ 0 - + + 0 + + + 0 + + + 0 + + 0 @@ -80,6 +89,13 @@ + + + + Remove Missing Files + + + diff --git a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp index ce6bd87a5dc31cb69ece028c47e700db6d6f8267..449e064ca3166c20a822145b9f1b0cf8b4f4af9b 100644 --- a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp +++ b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp @@ -653,6 +653,25 @@ QString ResourceModel::errorMessage() const return m_resource_file.errorMessage(); } +QList ResourceModel::nonExistingFiles() const +{ + QList files; + QFileInfo fi; + int prefixCount = rowCount(QModelIndex()); + for (int i = 0; i < prefixCount; ++i) { + QModelIndex prefix = index(i, 0, QModelIndex()); + int fileCount = rowCount(prefix); + for (int j = 0; j < fileCount; ++j) { + QModelIndex fileIndex = index(j, 0, prefix); + QString fileName = file(fileIndex); + fi.setFile(fileName); + if (!fi.exists()) + files << fileIndex; + } + } + return files; +} + Qt::ItemFlags ResourceModel::flags(const QModelIndex &index) const { Qt::ItemFlags f = QAbstractItemModel::flags(index); diff --git a/src/plugins/resourceeditor/qrceditor/resourcefile_p.h b/src/plugins/resourceeditor/qrceditor/resourcefile_p.h index 75806f1eb3e639ad598757968afe1ffc3a6cd35e..1e560bacf824655da11367a0fc47e9281b8f0d5b 100644 --- a/src/plugins/resourceeditor/qrceditor/resourcefile_p.h +++ b/src/plugins/resourceeditor/qrceditor/resourcefile_p.h @@ -217,6 +217,8 @@ public: QString errorMessage() const; + QList nonExistingFiles() const; + protected: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; bool setData(const QModelIndex &index, const QVariant &value, int role); diff --git a/src/plugins/resourceeditor/qrceditor/resourceview.cpp b/src/plugins/resourceeditor/qrceditor/resourceview.cpp index 086a8653b0a39ac303936091f0e3af015616a2f4..10644cc9b9d610cdb57afe2d7d8ab02101161004 100644 --- a/src/plugins/resourceeditor/qrceditor/resourceview.cpp +++ b/src/plugins/resourceeditor/qrceditor/resourceview.cpp @@ -348,6 +348,11 @@ QModelIndex ResourceView::addPrefix() return idx; } +QList ResourceView::nonExistingFiles() +{ + return m_qrcModel->nonExistingFiles(); +} + void ResourceView::refresh() { m_qrcModel->refresh(); diff --git a/src/plugins/resourceeditor/qrceditor/resourceview.h b/src/plugins/resourceeditor/qrceditor/resourceview.h index 9468550e80d8f4edd4e1f1e15131dccb3fcebaa9..ee38c6cd178eade8b363ce23202254d48a6971c5 100644 --- a/src/plugins/resourceeditor/qrceditor/resourceview.h +++ b/src/plugins/resourceeditor/qrceditor/resourceview.h @@ -111,6 +111,7 @@ public: void removeFiles(int prefixIndex, int firstFileIndex, int lastFileIndex); QStringList fileNamesToAdd(); QModelIndex addPrefix(); + QList nonExistingFiles(); void refresh(); diff --git a/src/plugins/resourceeditor/qrceditor/undocommands.cpp b/src/plugins/resourceeditor/qrceditor/undocommands.cpp index ac6cf8dc71892942971999ff27f135ae0788324d..db8025574c010a3b35098d9495462695fa350f73 100644 --- a/src/plugins/resourceeditor/qrceditor/undocommands.cpp +++ b/src/plugins/resourceeditor/qrceditor/undocommands.cpp @@ -153,6 +153,36 @@ void RemoveEntryCommand::freeEntry() m_entry = 0; } +RemoveMultipleEntryCommand::RemoveMultipleEntryCommand(ResourceView *view, const QList &list) +{ + m_subCommands.reserve(list.size()); + for (const QModelIndex &index : list) + m_subCommands.push_back(new RemoveEntryCommand(view, index)); +} + +RemoveMultipleEntryCommand::~RemoveMultipleEntryCommand() +{ + qDeleteAll(m_subCommands); +} + +void RemoveMultipleEntryCommand::redo() +{ + auto it = m_subCommands.rbegin(); + auto end = m_subCommands.rend(); + + for (; it != end; ++it) + (*it)->redo(); +} + +void RemoveMultipleEntryCommand::undo() +{ + auto it = m_subCommands.begin(); + auto end = m_subCommands.end(); + + for (; it != end; ++it) + (*it)->undo(); +} + AddFilesCommand::AddFilesCommand(ResourceView *view, int prefixIndex, int cursorFileIndex, const QStringList &fileNames) : ViewCommand(view), m_prefixIndex(prefixIndex), m_cursorFileIndex(cursorFileIndex), diff --git a/src/plugins/resourceeditor/qrceditor/undocommands_p.h b/src/plugins/resourceeditor/qrceditor/undocommands_p.h index 6bc698bbd0b390cec652fbcc9184c9ed1549c29f..d1efdd50e83a31a296c90409e2ab3b6288d8143e 100644 --- a/src/plugins/resourceeditor/qrceditor/undocommands_p.h +++ b/src/plugins/resourceeditor/qrceditor/undocommands_p.h @@ -119,6 +119,24 @@ private: void freeEntry(); }; +/*! + \class RemoveMultipleEntryCommand + + Removes multiple \l QModelIndex including all children from a \l ResourceView. +*/ +class RemoveMultipleEntryCommand : public QUndoCommand +{ + std::vector m_subCommands; +public: + // list must be in view order + RemoveMultipleEntryCommand(ResourceView *view, const QList &list); + ~RemoveMultipleEntryCommand(); +private: + void redo() override; + void undo() override; +}; + + /*! \class AddFilesCommand diff --git a/src/plugins/resourceeditor/resourceeditorconstants.h b/src/plugins/resourceeditor/resourceeditorconstants.h index 30209855d6cbdf4e57c941d8bbacee766cf724b3..9a59f3e2feaada6a9136d1e20c65cae7de928d23 100644 --- a/src/plugins/resourceeditor/resourceeditorconstants.h +++ b/src/plugins/resourceeditor/resourceeditorconstants.h @@ -45,6 +45,7 @@ const char C_RESOURCE_MIMETYPE[] = "application/vnd.qt.xml.resource"; const char C_ADD_PREFIX[] = "ResourceEditor.AddPrefix"; const char C_REMOVE_PREFIX[] = "ResourceEditor.RemovePrefix"; const char C_RENAME_PREFIX[] = "ResourceEditor.RenamePrefix"; +const char C_REMOVE_NON_EXISTING[] = "RessourceEditor.RemoveNonExistign"; const char C_REMOVE_FILE[] = "ResourceEditor.RemoveFile"; const char C_RENAME_FILE[] = "ResourceEditor.RenameFile"; diff --git a/src/plugins/resourceeditor/resourceeditorplugin.cpp b/src/plugins/resourceeditor/resourceeditorplugin.cpp index bf2d9f3d403def94de96522b0860c79682866b5a..68937543f1575593b521680b35e5fedebe264512 100644 --- a/src/plugins/resourceeditor/resourceeditorplugin.cpp +++ b/src/plugins/resourceeditor/resourceeditorplugin.cpp @@ -166,6 +166,11 @@ bool ResourceEditorPlugin::initialize(const QStringList &arguments, QString *err folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES); connect(m_removePrefix, SIGNAL(triggered()), this, SLOT(removePrefixContextMenu())); + m_removeNonExisting = new QAction(tr("Remove Missing Files"), this); + command = Core::ActionManager::registerAction(m_removeNonExisting, Constants::C_REMOVE_NON_EXISTING, projectTreeContext); + folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES); + connect(m_removeNonExisting, &QAction::triggered, this, &ResourceEditorPlugin::removeNonExisting); + m_renameResourceFile = new QAction(tr("Rename..."), this); command = Core::ActionManager::registerAction(m_renameResourceFile, Constants::C_RENAME_FILE, projectTreeContext); folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES); @@ -203,6 +208,7 @@ bool ResourceEditorPlugin::initialize(const QStringList &arguments, QString *err m_addPrefix->setEnabled(false); m_removePrefix->setEnabled(false); m_renamePrefix->setEnabled(false); + m_removeNonExisting->setEnabled(false); m_renameResourceFile->setEnabled(false); m_removeResourceFile->setEnabled(false); @@ -255,6 +261,12 @@ void ResourceEditorPlugin::removePrefixContextMenu() } } +void ResourceEditorPlugin::removeNonExisting() +{ + ResourceTopLevelNode *topLevel = static_cast(ProjectTree::currentNode()); + topLevel->removeNonExistingFiles(); +} + void ResourceEditorPlugin::renameFileContextMenu() { ProjectExplorerPlugin::initiateInlineRenaming(); @@ -332,6 +344,9 @@ void ResourceEditorPlugin::updateContextActions(Node *node, Project *) m_renamePrefix->setEnabled(isResourceFolder); m_renamePrefix->setVisible(isResourceFolder); + m_removeNonExisting->setEnabled(isResourceNode); + m_removeNonExisting->setVisible(isResourceNode); + if (isResourceNode) Core::DocumentManager::populateOpenWithMenu(m_openWithMenu, node->path().toString()); else diff --git a/src/plugins/resourceeditor/resourceeditorplugin.h b/src/plugins/resourceeditor/resourceeditorplugin.h index 44c5a84717abe4da56197600516810470d455333..231807edcabe6236abc083102e856bd090d34cdd 100644 --- a/src/plugins/resourceeditor/resourceeditorplugin.h +++ b/src/plugins/resourceeditor/resourceeditorplugin.h @@ -74,6 +74,7 @@ private slots: void removePrefixContextMenu(); void renameFileContextMenu(); void removeFileContextMenu(); + void removeNonExisting(); void openEditorContextMenu(); @@ -97,6 +98,7 @@ private: QAction *m_addPrefix; QAction *m_removePrefix; QAction *m_renamePrefix; + QAction *m_removeNonExisting; QAction *m_renameResourceFile; QAction *m_removeResourceFile; diff --git a/src/plugins/resourceeditor/resourcenode.cpp b/src/plugins/resourceeditor/resourcenode.cpp index 541b8f5dc44365ea86e030a305d2a7dc3d111642..c918515a3d5f3ccdee29d07e67d74310f3058e10 100644 --- a/src/plugins/resourceeditor/resourcenode.cpp +++ b/src/plugins/resourceeditor/resourcenode.cpp @@ -256,6 +256,29 @@ bool ResourceTopLevelNode::removePrefix(const QString &prefix, const QString &la return false; } +bool ResourceTopLevelNode::removeNonExistingFiles() +{ + ResourceFile file(path().toString()); + if (!file.load()) + return false; + + QFileInfo fi; + + for (int i = 0; i < file.prefixCount(); ++i) { + int fileCount = file.fileCount(i); + for (int j = fileCount -1; j >= 0; --j) { + fi.setFile(file.file(i, j)); + if (!fi.exists()) + file.removeFile(i, j); + } + } + + Core::DocumentManager::expectFileChange(path().toString()); + file.save(); + Core::DocumentManager::unexpectFileChange(path().toString()); + return true; +} + ProjectExplorer::FolderNode::AddNewInformation ResourceTopLevelNode::addNewInformation(const QStringList &files, Node *context) const { QString name = QCoreApplication::translate("ResourceTopLevelNode", "%1 Prefix: %2") diff --git a/src/plugins/resourceeditor/resourcenode.h b/src/plugins/resourceeditor/resourcenode.h index 139029978bc36dea38294fa796b6861d4647e810..02299af258b98caa1984055d23a352af906f6ca1 100644 --- a/src/plugins/resourceeditor/resourcenode.h +++ b/src/plugins/resourceeditor/resourcenode.h @@ -58,6 +58,7 @@ public: AddNewInformation addNewInformation(const QStringList &files, Node *context) const; bool showInSimpleTree() const; + bool removeNonExistingFiles(); private: Internal::ResourceFileWatcher *m_document;