Commit d7fbe79c authored by Daniel Teske's avatar Daniel Teske

ResourceEditor/Node: Add 'Remove missing files' feature

Change-Id: I081ec83b8cdb4f7c29e754b95370b58865ca2993
Task-number: QTCREATORBUG-13941
Reviewed-by: default avatarLeena Miettinen <riitta-leena.miettinen@theqtcompany.com>
Reviewed-by: default avatarEike Ziller <eike.ziller@theqtcompany.com>
parent 47660a8f
...@@ -54,6 +54,8 @@ QrcEditor::QrcEditor(QWidget *parent) ...@@ -54,6 +54,8 @@ QrcEditor::QrcEditor(QWidget *parent)
layout->addWidget(m_treeview); layout->addWidget(m_treeview);
connect(m_ui.removeButton, SIGNAL(clicked()), this, SLOT(onRemove())); connect(m_ui.removeButton, SIGNAL(clicked()), this, SLOT(onRemove()));
connect(m_ui.removeNonExistingButton, &QPushButton::clicked,
this, &QrcEditor::onRemoveNonExisting);
// 'Add' button with menu // 'Add' button with menu
QMenu *addMenu = new QMenu(this); QMenu *addMenu = new QMenu(this);
...@@ -402,6 +404,16 @@ void QrcEditor::onRemove() ...@@ -402,6 +404,16 @@ void QrcEditor::onRemove()
updateHistoryControls(); updateHistoryControls();
} }
// Slot for 'Remove missing files' button
void QrcEditor::onRemoveNonExisting()
{
QList<QModelIndex> toRemove = m_treeview->nonExistingFiles();
QUndoCommand * const removeCommand = new RemoveMultipleEntryCommand(m_treeview, toRemove);
m_history.push(removeCommand);
updateHistoryControls();
}
// Slot for 'Add File' button // Slot for 'Add File' button
void QrcEditor::onAddFiles() void QrcEditor::onAddFiles()
{ {
......
...@@ -86,6 +86,7 @@ private slots: ...@@ -86,6 +86,7 @@ private slots:
void onPrefixChanged(const QString &prefix); void onPrefixChanged(const QString &prefix);
void onLanguageChanged(const QString &language); void onLanguageChanged(const QString &language);
void onRemove(); void onRemove();
void onRemoveNonExisting();
void onAddFiles(); void onAddFiles();
void onAddPrefix(); void onAddPrefix();
......
...@@ -14,7 +14,16 @@ ...@@ -14,7 +14,16 @@
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
<property name="margin"> <property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
...@@ -80,6 +89,13 @@ ...@@ -80,6 +89,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="removeNonExistingButton">
<property name="text">
<string>Remove Missing Files</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
......
...@@ -653,6 +653,25 @@ QString ResourceModel::errorMessage() const ...@@ -653,6 +653,25 @@ QString ResourceModel::errorMessage() const
return m_resource_file.errorMessage(); return m_resource_file.errorMessage();
} }
QList<QModelIndex> ResourceModel::nonExistingFiles() const
{
QList<QModelIndex> 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 ResourceModel::flags(const QModelIndex &index) const
{ {
Qt::ItemFlags f = QAbstractItemModel::flags(index); Qt::ItemFlags f = QAbstractItemModel::flags(index);
......
...@@ -217,6 +217,8 @@ public: ...@@ -217,6 +217,8 @@ public:
QString errorMessage() const; QString errorMessage() const;
QList<QModelIndex> nonExistingFiles() const;
protected: protected:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value, int role); bool setData(const QModelIndex &index, const QVariant &value, int role);
......
...@@ -348,6 +348,11 @@ QModelIndex ResourceView::addPrefix() ...@@ -348,6 +348,11 @@ QModelIndex ResourceView::addPrefix()
return idx; return idx;
} }
QList<QModelIndex> ResourceView::nonExistingFiles()
{
return m_qrcModel->nonExistingFiles();
}
void ResourceView::refresh() void ResourceView::refresh()
{ {
m_qrcModel->refresh(); m_qrcModel->refresh();
......
...@@ -111,6 +111,7 @@ public: ...@@ -111,6 +111,7 @@ public:
void removeFiles(int prefixIndex, int firstFileIndex, int lastFileIndex); void removeFiles(int prefixIndex, int firstFileIndex, int lastFileIndex);
QStringList fileNamesToAdd(); QStringList fileNamesToAdd();
QModelIndex addPrefix(); QModelIndex addPrefix();
QList<QModelIndex> nonExistingFiles();
void refresh(); void refresh();
......
...@@ -153,6 +153,36 @@ void RemoveEntryCommand::freeEntry() ...@@ -153,6 +153,36 @@ void RemoveEntryCommand::freeEntry()
m_entry = 0; m_entry = 0;
} }
RemoveMultipleEntryCommand::RemoveMultipleEntryCommand(ResourceView *view, const QList<QModelIndex> &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, AddFilesCommand::AddFilesCommand(ResourceView *view, int prefixIndex, int cursorFileIndex,
const QStringList &fileNames) const QStringList &fileNames)
: ViewCommand(view), m_prefixIndex(prefixIndex), m_cursorFileIndex(cursorFileIndex), : ViewCommand(view), m_prefixIndex(prefixIndex), m_cursorFileIndex(cursorFileIndex),
......
...@@ -119,6 +119,24 @@ private: ...@@ -119,6 +119,24 @@ private:
void freeEntry(); void freeEntry();
}; };
/*!
\class RemoveMultipleEntryCommand
Removes multiple \l QModelIndex including all children from a \l ResourceView.
*/
class RemoveMultipleEntryCommand : public QUndoCommand
{
std::vector<QUndoCommand *> m_subCommands;
public:
// list must be in view order
RemoveMultipleEntryCommand(ResourceView *view, const QList<QModelIndex> &list);
~RemoveMultipleEntryCommand();
private:
void redo() override;
void undo() override;
};
/*! /*!
\class AddFilesCommand \class AddFilesCommand
......
...@@ -45,6 +45,7 @@ const char C_RESOURCE_MIMETYPE[] = "application/vnd.qt.xml.resource"; ...@@ -45,6 +45,7 @@ const char C_RESOURCE_MIMETYPE[] = "application/vnd.qt.xml.resource";
const char C_ADD_PREFIX[] = "ResourceEditor.AddPrefix"; const char C_ADD_PREFIX[] = "ResourceEditor.AddPrefix";
const char C_REMOVE_PREFIX[] = "ResourceEditor.RemovePrefix"; const char C_REMOVE_PREFIX[] = "ResourceEditor.RemovePrefix";
const char C_RENAME_PREFIX[] = "ResourceEditor.RenamePrefix"; 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_REMOVE_FILE[] = "ResourceEditor.RemoveFile";
const char C_RENAME_FILE[] = "ResourceEditor.RenameFile"; const char C_RENAME_FILE[] = "ResourceEditor.RenameFile";
......
...@@ -166,6 +166,11 @@ bool ResourceEditorPlugin::initialize(const QStringList &arguments, QString *err ...@@ -166,6 +166,11 @@ bool ResourceEditorPlugin::initialize(const QStringList &arguments, QString *err
folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES); folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES);
connect(m_removePrefix, SIGNAL(triggered()), this, SLOT(removePrefixContextMenu())); 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); m_renameResourceFile = new QAction(tr("Rename..."), this);
command = Core::ActionManager::registerAction(m_renameResourceFile, Constants::C_RENAME_FILE, projectTreeContext); command = Core::ActionManager::registerAction(m_renameResourceFile, Constants::C_RENAME_FILE, projectTreeContext);
folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES); folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES);
...@@ -203,6 +208,7 @@ bool ResourceEditorPlugin::initialize(const QStringList &arguments, QString *err ...@@ -203,6 +208,7 @@ bool ResourceEditorPlugin::initialize(const QStringList &arguments, QString *err
m_addPrefix->setEnabled(false); m_addPrefix->setEnabled(false);
m_removePrefix->setEnabled(false); m_removePrefix->setEnabled(false);
m_renamePrefix->setEnabled(false); m_renamePrefix->setEnabled(false);
m_removeNonExisting->setEnabled(false);
m_renameResourceFile->setEnabled(false); m_renameResourceFile->setEnabled(false);
m_removeResourceFile->setEnabled(false); m_removeResourceFile->setEnabled(false);
...@@ -255,6 +261,12 @@ void ResourceEditorPlugin::removePrefixContextMenu() ...@@ -255,6 +261,12 @@ void ResourceEditorPlugin::removePrefixContextMenu()
} }
} }
void ResourceEditorPlugin::removeNonExisting()
{
ResourceTopLevelNode *topLevel = static_cast<ResourceTopLevelNode *>(ProjectTree::currentNode());
topLevel->removeNonExistingFiles();
}
void ResourceEditorPlugin::renameFileContextMenu() void ResourceEditorPlugin::renameFileContextMenu()
{ {
ProjectExplorerPlugin::initiateInlineRenaming(); ProjectExplorerPlugin::initiateInlineRenaming();
...@@ -332,6 +344,9 @@ void ResourceEditorPlugin::updateContextActions(Node *node, Project *) ...@@ -332,6 +344,9 @@ void ResourceEditorPlugin::updateContextActions(Node *node, Project *)
m_renamePrefix->setEnabled(isResourceFolder); m_renamePrefix->setEnabled(isResourceFolder);
m_renamePrefix->setVisible(isResourceFolder); m_renamePrefix->setVisible(isResourceFolder);
m_removeNonExisting->setEnabled(isResourceNode);
m_removeNonExisting->setVisible(isResourceNode);
if (isResourceNode) if (isResourceNode)
Core::DocumentManager::populateOpenWithMenu(m_openWithMenu, node->path().toString()); Core::DocumentManager::populateOpenWithMenu(m_openWithMenu, node->path().toString());
else else
......
...@@ -74,6 +74,7 @@ private slots: ...@@ -74,6 +74,7 @@ private slots:
void removePrefixContextMenu(); void removePrefixContextMenu();
void renameFileContextMenu(); void renameFileContextMenu();
void removeFileContextMenu(); void removeFileContextMenu();
void removeNonExisting();
void openEditorContextMenu(); void openEditorContextMenu();
...@@ -97,6 +98,7 @@ private: ...@@ -97,6 +98,7 @@ private:
QAction *m_addPrefix; QAction *m_addPrefix;
QAction *m_removePrefix; QAction *m_removePrefix;
QAction *m_renamePrefix; QAction *m_renamePrefix;
QAction *m_removeNonExisting;
QAction *m_renameResourceFile; QAction *m_renameResourceFile;
QAction *m_removeResourceFile; QAction *m_removeResourceFile;
......
...@@ -256,6 +256,29 @@ bool ResourceTopLevelNode::removePrefix(const QString &prefix, const QString &la ...@@ -256,6 +256,29 @@ bool ResourceTopLevelNode::removePrefix(const QString &prefix, const QString &la
return false; 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 ProjectExplorer::FolderNode::AddNewInformation ResourceTopLevelNode::addNewInformation(const QStringList &files, Node *context) const
{ {
QString name = QCoreApplication::translate("ResourceTopLevelNode", "%1 Prefix: %2") QString name = QCoreApplication::translate("ResourceTopLevelNode", "%1 Prefix: %2")
......
...@@ -58,6 +58,7 @@ public: ...@@ -58,6 +58,7 @@ public:
AddNewInformation addNewInformation(const QStringList &files, Node *context) const; AddNewInformation addNewInformation(const QStringList &files, Node *context) const;
bool showInSimpleTree() const; bool showInSimpleTree() const;
bool removeNonExistingFiles();
private: private:
Internal::ResourceFileWatcher *m_document; Internal::ResourceFileWatcher *m_document;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment