summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2019-06-23 04:04:54 -0400
committerisanae <14251494+isanae@users.noreply.github.com>2019-07-02 10:10:18 -0400
commit895883571b2b71c891dbaad4662adc7b39256286 (patch)
tree6a5dcfe0eff064bdaed00ff0b3ba1034f6b9f70c
parentcbdc4cc3284f13477bfbf292d15c4a5742627091 (diff)
splitting filetree tab
moved mod info dialog classes to a sub filter
-rw-r--r--src/CMakeLists.txt19
-rw-r--r--src/modinfodialog.cpp409
-rw-r--r--src/modinfodialog.h28
-rw-r--r--src/modinfodialog.ui8
-rw-r--r--src/modinfodialogconflicts.cpp14
-rw-r--r--src/modinfodialogconflicts.h16
-rw-r--r--src/modinfodialogfiletree.cpp420
-rw-r--r--src/modinfodialogfiletree.h39
8 files changed, 502 insertions, 451 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7dc39fd9..1d27f444 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -57,6 +57,7 @@ SET(organizer_SRCS
modinfodialogcategories.cpp
modinfodialogconflicts.cpp
modinfodialogesps.cpp
+ modinfodialogfiletree.cpp
modinfodialogimages.cpp
modinfodialognexus.cpp
modinfodialogtab.cpp
@@ -164,6 +165,7 @@ SET(organizer_HDRS
modinfodialogcategories.h
modinfodialogconflicts.h
modinfodialogesps.h
+ modinfodialogfiletree.h
modinfodialogimages.h
modinfodialognexus.h
modinfodialogtab.h
@@ -364,21 +366,24 @@ set(locking
set(modinfo
modinfo
modinfobackup
+ modinfoforeign
+ modinfooverwrite
+ modinforegular
+ modinfoseparator
+ modinfowithconflictinfo
+)
+
+set(modinfo\\dialog
modinfodialog
modinfodialogcategories
modinfodialogconflicts
modinfodialogesps
+ modinfodialogfiletree
modinfodialogimages
modinfodialognexus
modinfodialogtab
modinfodialogtextfiles
- modinfoforeign
- modinfooverwrite
- modinforegular
- modinfoseparator
- modinfowithconflictinfo
)
-
set(modlist
modlist
modlistsortproxy
@@ -443,7 +448,7 @@ set(widgets
)
set(src_filters
- application core browser dialogs downloads executables locking modinfo
+ application core browser dialogs downloads executables locking modinfo modinfo\\dialog
modlist plugins previews profiles settings utilities widgets
)
diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp
index b78f4515..6463a5a6 100644
--- a/src/modinfodialog.cpp
+++ b/src/modinfodialog.cpp
@@ -43,6 +43,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "modinfodialogconflicts.h"
#include "modinfodialogcategories.h"
#include "modinfodialognexus.h"
+#include "modinfodialogfiletree.h"
#include <QDir>
#include <QDirIterator>
@@ -193,7 +194,7 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
ui->tabWidget->setTabEnabled(TAB_CONFLICTS, false);
ui->tabWidget->setTabEnabled(TAB_CATEGORIES, true);
ui->tabWidget->setTabEnabled(TAB_NEXUS, false);
- //ui->tabWidget->setTabEnabled(TAB_NOTES, false);
+ ui->tabWidget->setTabEnabled(TAB_NOTES, true);
ui->tabWidget->setTabEnabled(TAB_FILETREE, false);
}
else if (unmanaged)
@@ -205,8 +206,8 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
ui->tabWidget->setTabEnabled(TAB_CONFLICTS, true);
ui->tabWidget->setTabEnabled(TAB_CATEGORIES, false);
ui->tabWidget->setTabEnabled(TAB_NEXUS, false);
- ui->tabWidget->setTabEnabled(TAB_FILETREE, false);
ui->tabWidget->setTabEnabled(TAB_NOTES, false);
+ ui->tabWidget->setTabEnabled(TAB_FILETREE, false);
} else {
ui->tabWidget->setTabEnabled(TAB_TEXTFILES, true);
ui->tabWidget->setTabEnabled(TAB_INIFILES, true);
@@ -215,8 +216,8 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
ui->tabWidget->setTabEnabled(TAB_CONFLICTS, true);
ui->tabWidget->setTabEnabled(TAB_CATEGORIES, true);
ui->tabWidget->setTabEnabled(TAB_NEXUS, true);
-
- initFiletree(modInfo);
+ ui->tabWidget->setTabEnabled(TAB_NOTES, true);
+ ui->tabWidget->setTabEnabled(TAB_FILETREE, true);
}
// activate first enabled tab
@@ -252,7 +253,7 @@ std::vector<std::unique_ptr<ModInfoDialogTab>> ModInfoDialog::createTabs()
{
return createTabsImpl<
TextFilesTab, IniFilesTab, ImagesTab, ESPsTab,
- ConflictsTab, CategoriesTab, NexusTab, NotesTab>(
+ ConflictsTab, CategoriesTab, NexusTab, NotesTab, FileTreeTab>(
*m_OrganizerCore, *m_PluginContainer, this, ui);
}
@@ -262,35 +263,6 @@ int ModInfoDialog::exec()
return TutorableDialog::exec();
}
-void ModInfoDialog::initFiletree(ModInfo::Ptr modInfo)
-{
- ui->fileTree = findChild<QTreeView*>("fileTree");
-
- m_FileSystemModel = new QFileSystemModel(this);
- m_FileSystemModel->setReadOnly(false);
- m_FileSystemModel->setRootPath(m_RootPath);
- ui->fileTree->setModel(m_FileSystemModel);
- ui->fileTree->setRootIndex(m_FileSystemModel->index(m_RootPath));
- ui->fileTree->setColumnWidth(0, 300);
-
- m_NewFolderAction = new QAction(tr("&New Folder"), ui->fileTree);
- m_OpenAction = new QAction(tr("&Open"), ui->fileTree);
- m_PreviewAction = new QAction(tr("&Preview"), ui->fileTree);
- m_RenameAction = new QAction(tr("&Rename"), ui->fileTree);
- m_DeleteAction = new QAction(tr("&Delete"), ui->fileTree);
- m_HideAction = new QAction(tr("&Hide"), ui->fileTree);
- m_UnhideAction = new QAction(tr("&Unhide"), ui->fileTree);
-
- connect(m_NewFolderAction, SIGNAL(triggered()), this, SLOT(createDirectoryTriggered()));
- connect(m_OpenAction, SIGNAL(triggered()), this, SLOT(openTriggered()));
- connect(m_PreviewAction, SIGNAL(triggered()), this, SLOT(previewTriggered()));
- connect(m_RenameAction, SIGNAL(triggered()), this, SLOT(renameTriggered()));
- connect(m_DeleteAction, SIGNAL(triggered()), this, SLOT(deleteTriggered()));
- connect(m_HideAction, SIGNAL(triggered()), this, SLOT(hideTriggered()));
- connect(m_UnhideAction, SIGNAL(triggered()), this, SLOT(unhideTriggered()));
-}
-
-
int ModInfoDialog::tabIndex(const QString &tabId)
{
for (int i = 0; i < ui->tabWidget->count(); ++i) {
@@ -301,7 +273,6 @@ int ModInfoDialog::tabIndex(const QString &tabId)
return -1;
}
-
void ModInfoDialog::saveState(Settings& s) const
{
s.directInterface().setValue("mod_info_tabs", saveTabState());
@@ -340,6 +311,7 @@ void ModInfoDialog::restoreTabState(const QByteArray &state)
m_RealTabPos[newPos] = newPos;
}
}
+
// then actually move the tabs
QTabBar *tabBar = ui->tabWidget->findChild<QTabBar*>("qt_tabwidget_tabbar"); // magic name = bad
ui->tabWidget->blockSignals(true);
@@ -407,377 +379,10 @@ void ModInfoDialog::openTab(int tab)
}
}
-QString ModInfoDialog::getFileCategory(int categoryID)
-{
- switch (categoryID) {
- case 1: return tr("Main");
- case 2: return tr("Update");
- case 3: return tr("Optional");
- case 4: return tr("Old");
- case 5: return tr("Miscellaneous");
- case 6: return tr("Deleted");
- default: return tr("Unknown");
- }
-}
-
void ModInfoDialog::on_tabWidget_currentChanged(int index)
{
}
-bool ModInfoDialog::recursiveDelete(const QModelIndex &index)
-{
- for (int childRow = 0; childRow < m_FileSystemModel->rowCount(index); ++childRow) {
- QModelIndex childIndex = m_FileSystemModel->index(childRow, 0, index);
- if (m_FileSystemModel->isDir(childIndex)) {
- if (!recursiveDelete(childIndex)) {
- qCritical("failed to delete %s", m_FileSystemModel->fileName(childIndex).toUtf8().constData());
- return false;
- }
- } else {
- if (!m_FileSystemModel->remove(childIndex)) {
- qCritical("failed to delete %s", m_FileSystemModel->fileName(childIndex).toUtf8().constData());
- return false;
- }
- }
- }
- if (!m_FileSystemModel->remove(index)) {
- qCritical("failed to delete %s", m_FileSystemModel->fileName(index).toUtf8().constData());
- return false;
- }
- return true;
-}
-
-
-void ModInfoDialog::on_openInExplorerButton_clicked()
-{
- shell::ExploreFile(m_ModInfo->absolutePath());
-}
-
-void ModInfoDialog::deleteFile(const QModelIndex &index)
-{
- bool res = m_FileSystemModel->isDir(index) ? recursiveDelete(index)
- : m_FileSystemModel->remove(index);
- if (!res) {
- QString fileName = m_FileSystemModel->fileName(index);
- reportError(tr("Failed to delete %1").arg(fileName));
- }
-}
-
-void ModInfoDialog::delete_activated()
-{
- if (ui->fileTree->hasFocus()) {
- QItemSelectionModel *selection = ui->fileTree->selectionModel();
-
- if (selection->hasSelection() && selection->selectedRows().count() >= 1) {
-
- if (selection->selectedRows().count() == 0) {
- return;
- }
- else if (selection->selectedRows().count() == 1) {
- QString fileName = m_FileSystemModel->fileName(selection->selectedRows().at(0));
- if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to delete \"%1\"?").arg(fileName),
- QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
- return;
- }
- }
- else {
- if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to delete the selected files?"),
- QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
- return;
- }
- }
-
- foreach(QModelIndex index, selection->selectedRows()) {
- deleteFile(index);
- }
- }
- }
-}
-
-void ModInfoDialog::deleteTriggered()
-{
- if (m_FileSelection.count() == 0) {
- return;
- } else if (m_FileSelection.count() == 1) {
- QString fileName = m_FileSystemModel->fileName(m_FileSelection.at(0));
- if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to delete \"%1\"?").arg(fileName),
- QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
- return;
- }
- } else {
- if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to delete the selected files?"),
- QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
- return;
- }
- }
-
- foreach(QModelIndex index, m_FileSelection) {
- deleteFile(index);
- }
-}
-
-
-void ModInfoDialog::renameTriggered()
-{
- QModelIndex selection = m_FileSelection.at(0);
- QModelIndex index = selection.sibling(selection.row(), 0);
- if (!index.isValid() || m_FileSystemModel->isReadOnly()) {
- return;
- }
-
- ui->fileTree->edit(index);
-}
-
-
-void ModInfoDialog::hideTriggered()
-{
- changeFiletreeVisibility(false);
-}
-
-
-void ModInfoDialog::unhideTriggered()
-{
- changeFiletreeVisibility(true);
-}
-
-void ModInfoDialog::changeFiletreeVisibility(bool visible)
-{
- bool changed = false;
- bool stop = false;
-
- qDebug().nospace()
- << (visible ? "unhiding" : "hiding") << " "
- << m_FileSelection.size() << " filetree files";
-
- QFlags<FileRenamer::RenameFlags> flags =
- (visible ? FileRenamer::UNHIDE : FileRenamer::HIDE);
-
- if (m_FileSelection.size() > 1) {
- flags |= FileRenamer::MULTIPLE;
- }
-
- FileRenamer renamer(this, flags);
-
- for (const auto& index : m_FileSelection) {
- if (stop) {
- break;
- }
-
- const QString path = m_FileSystemModel->filePath(index);
- auto result = FileRenamer::RESULT_CANCEL;
-
- if (visible) {
- if (!canUnhideFile(false, path)) {
- qDebug().nospace() << "cannot unhide " << path << ", skipping";
- continue;
- }
- result = unhideFile(renamer, path);
- } else {
- if (!canHideFile(false, path)) {
- qDebug().nospace() << "cannot hide " << path << ", skipping";
- continue;
- }
- result = hideFile(renamer, path);
- }
-
- switch (result) {
- case FileRenamer::RESULT_OK: {
- // will trigger a refresh at the end
- changed = true;
- break;
- }
-
- case FileRenamer::RESULT_SKIP: {
- // nop
- break;
- }
-
- case FileRenamer::RESULT_CANCEL: {
- // stop right now, but make sure to refresh if needed
- stop = true;
- break;
- }
- }
- }
-
- qDebug().nospace() << (visible ? "unhiding" : "hiding") << " filetree files done";
-
- if (changed) {
- qDebug().nospace() << "triggering refresh";
- if (m_Origin) {
- emit originModified(m_Origin->getID());
- }
- refreshLists();
- }
-}
-
-
-void ModInfoDialog::openTriggered()
-{
- if (m_FileSelection.size() == 1) {
- const auto index = m_FileSelection.at(0);
- if (!index.isValid()) {
- return;
- }
-
- QString fileName = m_FileSystemModel->filePath(index);
- shell::OpenFile(fileName);
- }
-}
-
-void ModInfoDialog::previewTriggered()
-{
- if (m_FileSelection.size() == 1) {
- const auto index = m_FileSelection.at(0);
- if (!index.isValid()) {
- return;
- }
-
- QString fileName = m_FileSystemModel->filePath(index);
- m_OrganizerCore->previewFile(this, m_ModInfo->name(), fileName);
- }
-}
-
-void ModInfoDialog::createDirectoryTriggered()
-{
- QModelIndex selection = m_FileSelection.at(0);
-
- QModelIndex index = m_FileSystemModel->isDir(selection) ? selection
- : selection.parent();
- index = index.sibling(index.row(), 0);
-
- QString name = tr("New Folder");
- QString path = m_FileSystemModel->filePath(index).append("/");
-
- QModelIndex existingIndex = m_FileSystemModel->index(path + name);
- int suffix = 1;
- while (existingIndex.isValid()) {
- name = tr("New Folder") + QString::number(suffix++);
- existingIndex = m_FileSystemModel->index(path + name);
- }
-
- QModelIndex newIndex = m_FileSystemModel->mkdir(index, name);
- if (!newIndex.isValid()) {
- reportError(tr("Failed to create \"%1\"").arg(name));
- return;
- }
-
- ui->fileTree->setCurrentIndex(newIndex);
- ui->fileTree->edit(newIndex);
-}
-
-
-void ModInfoDialog::on_fileTree_customContextMenuRequested(const QPoint &pos)
-{
- QItemSelectionModel *selectionModel = ui->fileTree->selectionModel();
- m_FileSelection = selectionModel->selectedRows(0);
-
- QMenu menu(ui->fileTree);
-
- menu.addAction(m_NewFolderAction);
-
- if (selectionModel->hasSelection()) {
- bool enableOpen = true;
- bool enablePreview = true;
- bool enableRename = true;
- bool enableDelete = true;
- bool enableHide = true;
- bool enableUnhide = true;
-
- if (m_FileSelection.size() == 1) {
- // single selection
-
- // only enable open action if a file is selected
- bool hasFiles = false;
-
- foreach(QModelIndex idx, m_FileSelection) {
- if (m_FileSystemModel->fileInfo(idx).isFile()) {
- hasFiles = true;
- break;
- }
- }
-
- if (!hasFiles) {
- enableOpen = false;
- enablePreview = false;
- }
-
- const QString fileName = m_FileSystemModel->fileName(m_FileSelection.at(0));
-
- if (!canPreviewFile(*m_PluginContainer, false, fileName)) {
- enablePreview = false;
- }
-
- if (!canHideFile(false, fileName)) {
- enableHide = false;
- }
-
- if (!canUnhideFile(false, fileName)) {
- enableUnhide = false;
- }
- } else {
- // this is a multiple selection, don't show open action so users don't open
- // a thousand files
- enableOpen = false;
- enablePreview = false;
- enableRename = false;
-
- if (m_FileSelection.size() < max_scan_for_context_menu) {
- // if the number of selected items is low, checking them to accurately
- // show the menu items is worth it
- enableHide = false;
- enableUnhide = false;
-
- for (const auto& index : m_FileSelection) {
- const QString fileName = m_FileSystemModel->fileName(index);
-
- if (canHideFile(false, fileName)) {
- enableHide = true;
- }
-
- if (canUnhideFile(false, fileName)) {
- enableUnhide = true;
- }
-
- if (enableHide && enableUnhide) {
- // found both, no need to check more
- break;
- }
- }
- }
- }
-
- if (enableOpen) {
- menu.addAction(m_OpenAction);
- }
-
- if (enablePreview) {
- menu.addAction(m_PreviewAction);
- }
-
- if (enableRename) {
- menu.addAction(m_RenameAction);
- }
-
- if (enableDelete) {
- menu.addAction(m_DeleteAction);
- }
-
- if (enableHide) {
- menu.addAction(m_HideAction);
- }
-
- if (enableUnhide) {
- menu.addAction(m_UnhideAction);
- }
- } else {
- m_FileSelection.clear();
- m_FileSelection.append(m_FileSystemModel->index(m_FileSystemModel->rootPath(), 0));
- }
-
- menu.exec(ui->fileTree->viewport()->mapToGlobal(pos));
-}
-
void ModInfoDialog::on_nextButton_clicked()
{
int currentTab = ui->tabWidget->currentIndex();
diff --git a/src/modinfodialog.h b/src/modinfodialog.h
index 7b96d21a..b367f647 100644
--- a/src/modinfodialog.h
+++ b/src/modinfodialog.h
@@ -54,19 +54,6 @@ class TextEditor;
class ModInfoDialogTab;
-class ElideLeftDelegate : public QStyledItemDelegate
-{
-public:
- using QStyledItemDelegate::QStyledItemDelegate;
-
-protected:
- void initStyleOption(QStyleOptionViewItem* o, const QModelIndex& i) const
- {
- QStyledItemDelegate::initStyleOption(o, i);
- o->textElideMode = Qt::ElideLeft;
- }
-};
-
bool canPreviewFile(PluginContainer& pluginContainer, bool isArchive, const QString& filename);
bool canOpenFile(bool isArchive, const QString& filename);
@@ -145,12 +132,6 @@ signals:
void originModified(int originID);
private:
-
- void initFiletree(ModInfo::Ptr modInfo);
-
- void refreshLists();
-
- QString getFileCategory(int categoryID);
bool recursiveDelete(const QModelIndex &index);
void deleteFile(const QModelIndex &index);
@@ -189,17 +170,9 @@ private:
OrganizerCore *m_OrganizerCore;
PluginContainer *m_PluginContainer;
- QFileSystemModel *m_FileSystemModel;
QTreeView *m_FileTree;
QModelIndexList m_FileSelection;
- QAction *m_NewFolderAction;
- QAction *m_OpenAction;
- QAction *m_PreviewAction;
- QAction *m_RenameAction;
- QAction *m_DeleteAction;
- QAction *m_HideAction;
- QAction *m_UnhideAction;
const MOShared::DirectoryEntry *m_Directory;
MOShared::FilesOrigin *m_Origin;
@@ -209,6 +182,7 @@ private:
std::vector<std::unique_ptr<ModInfoDialogTab>> createTabs();
+ void refreshLists();
void refreshFiles();
void restoreTabState(const QByteArray &state);
diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui
index 360ecc79..04282e81 100644
--- a/src/modinfodialog.ui
+++ b/src/modinfodialog.ui
@@ -20,7 +20,7 @@
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
- <number>7</number>
+ <number>8</number>
</property>
<property name="movable">
<bool>true</bool>
@@ -1088,7 +1088,7 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</widget>
- <widget class="QWidget" name="tabFiles">
+ <widget class="QWidget" name="tabFiles1">
<attribute name="title">
<string>Filetree</string>
</attribute>
@@ -1096,7 +1096,7 @@ p, li { white-space: pre-wrap; }
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
- <widget class="QPushButton" name="openInExplorerButton">
+ <widget class="QPushButton" name="openInExplorerButton1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -1124,7 +1124,7 @@ p, li { white-space: pre-wrap; }
</layout>
</item>
<item>
- <widget class="QTreeView" name="fileTree">
+ <widget class="QTreeView" name="fileTree1">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
diff --git a/src/modinfodialogconflicts.cpp b/src/modinfodialogconflicts.cpp
index 4176ac3e..e7f189c2 100644
--- a/src/modinfodialogconflicts.cpp
+++ b/src/modinfodialogconflicts.cpp
@@ -24,6 +24,20 @@ int naturalCompare(const QString& a, const QString& b)
}
+class ElideLeftDelegate : public QStyledItemDelegate
+{
+public:
+ using QStyledItemDelegate::QStyledItemDelegate;
+
+protected:
+ void initStyleOption(QStyleOptionViewItem* o, const QModelIndex& i) const
+ {
+ QStyledItemDelegate::initStyleOption(o, i);
+ o->textElideMode = Qt::ElideLeft;
+ }
+};
+
+
class ConflictItem : public QTreeWidgetItem
{
public:
diff --git a/src/modinfodialogconflicts.h b/src/modinfodialogconflicts.h
index 20362575..9c011163 100644
--- a/src/modinfodialogconflicts.h
+++ b/src/modinfodialogconflicts.h
@@ -115,18 +115,12 @@ public:
private:
struct Actions
{
- QAction* hide;
- QAction* unhide;
- QAction* open;
- QAction* preview;
- QMenu* gotoMenu;
+ QAction* hide = nullptr;
+ QAction* unhide = nullptr;
+ QAction* open = nullptr;
+ QAction* preview = nullptr;
+ QMenu* gotoMenu = nullptr;
std::vector<QAction*> gotoActions;
-
- Actions() :
- hide(nullptr), unhide(nullptr), open(nullptr), preview(nullptr),
- gotoMenu(nullptr)
- {
- }
};
GeneralConflictsTab m_general;
diff --git a/src/modinfodialogfiletree.cpp b/src/modinfodialogfiletree.cpp
new file mode 100644
index 00000000..e277b04b
--- /dev/null
+++ b/src/modinfodialogfiletree.cpp
@@ -0,0 +1,420 @@
+#include "modinfodialogfiletree.h"
+#include "ui_modinfodialog.h"
+#include "organizercore.h"
+#include <utility.h>
+#include <report.h>
+
+using MOBase::reportError;
+namespace shell = MOBase::shell;
+
+FileTreeTab::FileTreeTab(
+ OrganizerCore& oc, PluginContainer& plugin,
+ QWidget* parent, Ui::ModInfoDialog* ui)
+ : ModInfoDialogTab(oc, plugin, parent, ui), m_fs(nullptr)
+{
+ m_fs = new QFileSystemModel(this);
+ m_fs->setReadOnly(false);
+ ui->fileTree1->setModel(m_fs);
+ ui->fileTree1->setColumnWidth(0, 300);
+
+ m_actions.newFolder = new QAction(tr("&New Folder"), ui->fileTree1);
+ m_actions.open = new QAction(tr("&Open"), ui->fileTree1);
+ m_actions.preview = new QAction(tr("&Preview"), ui->fileTree1);
+ m_actions.rename = new QAction(tr("&Rename"), ui->fileTree1);
+ m_actions.del = new QAction(tr("&Delete"), ui->fileTree1);
+ m_actions.hide = new QAction(tr("&Hide"), ui->fileTree1);
+ m_actions.unhide = new QAction(tr("&Unhide"), ui->fileTree1);
+
+ connect(m_actions.newFolder, &QAction::triggered, [&]{ onCreateDirectory(); });
+ connect(m_actions.open, &QAction::triggered, [&]{ onOpen(); });
+ connect(m_actions.preview, &QAction::triggered, [&]{ onPreview(); });
+ connect(m_actions.rename, &QAction::triggered, [&]{ onRename(); });
+ connect(m_actions.del, &QAction::triggered, [&]{ onDelete(); });
+ connect(m_actions.hide, &QAction::triggered, [&]{ onHide(); });
+ connect(m_actions.unhide, &QAction::triggered, [&]{ onUnhide(); });
+}
+
+void FileTreeTab::clear()
+{
+ m_fs->setRootPath({});
+ //ui->fileTree1->
+}
+
+void FileTreeTab::update()
+{
+ const auto rootPath = mod()->absolutePath();
+
+ m_fs->setRootPath(rootPath);
+ ui->fileTree1->setRootIndex(m_fs->index(rootPath));
+}
+
+QModelIndex FileTreeTab::singleSelection() const
+{
+ const auto rows = ui->fileTree1->selectionModel()->selectedRows();
+ if (rows.size() != 1) {
+ return {};
+ }
+
+ return rows[0];
+}
+
+void FileTreeTab::onCreateDirectory()
+{
+ auto selection = singleSelection();
+ if (!selection.isValid()) {
+ return;
+ }
+
+ QModelIndex index = m_fs->isDir(selection) ? selection : selection.parent();
+ index = index.sibling(index.row(), 0);
+
+ QString name = tr("New Folder");
+ QString path = m_fs->filePath(index).append("/");
+
+ QModelIndex existingIndex = m_fs->index(path + name);
+ int suffix = 1;
+ while (existingIndex.isValid()) {
+ name = tr("New Folder") + QString::number(suffix++);
+ existingIndex = m_fs->index(path + name);
+ }
+
+ QModelIndex newIndex = m_fs->mkdir(index, name);
+ if (!newIndex.isValid()) {
+ reportError(tr("Failed to create \"%1\"").arg(name));
+ return;
+ }
+
+ ui->fileTree1->setCurrentIndex(newIndex);
+ ui->fileTree1->edit(newIndex);
+}
+
+void FileTreeTab::onOpen()
+{
+ auto selection = singleSelection();
+ if (!selection.isValid()) {
+ return;
+ }
+
+ shell::OpenFile(m_fs->filePath(selection));
+}
+
+void FileTreeTab::onPreview()
+{
+ auto selection = singleSelection();
+ if (!selection.isValid()) {
+ return;
+ }
+
+ core().previewFile(parentWidget(), mod()->name(), m_fs->filePath(selection));
+}
+
+void FileTreeTab::onRename()
+{
+ auto selection = singleSelection();
+ if (!selection.isValid()) {
+ return;
+ }
+
+ QModelIndex index = selection.sibling(selection.row(), 0);
+ if (!index.isValid() || m_fs->isReadOnly()) {
+ return;
+ }
+
+ ui->fileTree1->edit(index);
+}
+
+void FileTreeTab::onDelete()
+{
+ const auto rows = ui->fileTree1->selectionModel()->selectedRows();
+ if (rows.count() == 0) {
+ return;
+ }
+
+ QString message;
+
+ if (rows.count() == 1) {
+ QString fileName = m_fs->fileName(rows[0]);
+ message = tr("Are sure you want to delete \"%1\"?").arg(fileName);
+ } else {
+ message = tr("Are sure you want to delete the selected files?");
+ }
+
+ if (QMessageBox::question(parentWidget(), tr("Confirm"), message) != QMessageBox::Yes) {
+ return;
+ }
+
+ foreach(QModelIndex index, m_FileSelection) {
+ deleteFile(index);
+ }
+}
+
+
+bool FileTreeTab::recursiveDelete(const QModelIndex &index)
+{
+ for (int childRow = 0; childRow < m_FileSystemModel->rowCount(index); ++childRow) {
+ QModelIndex childIndex = m_FileSystemModel->index(childRow, 0, index);
+ if (m_FileSystemModel->isDir(childIndex)) {
+ if (!recursiveDelete(childIndex)) {
+ qCritical("failed to delete %s", m_FileSystemModel->fileName(childIndex).toUtf8().constData());
+ return false;
+ }
+ } else {
+ if (!m_FileSystemModel->remove(childIndex)) {
+ qCritical("failed to delete %s", m_FileSystemModel->fileName(childIndex).toUtf8().constData());
+ return false;
+ }
+ }
+ }
+ if (!m_FileSystemModel->remove(index)) {
+ qCritical("failed to delete %s", m_FileSystemModel->fileName(index).toUtf8().constData());
+ return false;
+ }
+ return true;
+}
+
+
+void ModInfoDialog::on_openInExplorerButton_clicked()
+{
+ shell::ExploreFile(m_ModInfo->absolutePath());
+}
+
+void ModInfoDialog::deleteFile(const QModelIndex &index)
+{
+ bool res = m_FileSystemModel->isDir(index) ? recursiveDelete(index)
+ : m_FileSystemModel->remove(index);
+ if (!res) {
+ QString fileName = m_FileSystemModel->fileName(index);
+ reportError(tr("Failed to delete %1").arg(fileName));
+ }
+}
+
+void ModInfoDialog::delete_activated()
+{
+ if (ui->fileTree->hasFocus()) {
+ QItemSelectionModel *selection = ui->fileTree->selectionModel();
+
+ if (selection->hasSelection() && selection->selectedRows().count() >= 1) {
+
+ if (selection->selectedRows().count() == 0) {
+ return;
+ }
+ else if (selection->selectedRows().count() == 1) {
+ QString fileName = m_FileSystemModel->fileName(selection->selectedRows().at(0));
+ if (QMessageBox::question(this, tr("Confirm"), tr("Are sure you want to delete \"%1\"?").arg(fileName),
+ QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
+ return;
+ }
+ }
+ else {
+ if (QMessageBox::question(this, tr("Confirm"), tr("Are sure you want to delete the selected files?"),
+ QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
+ return;
+ }
+ }
+
+ foreach(QModelIndex index, selection->selectedRows()) {
+ deleteFile(index);
+ }
+ }
+ }
+}
+
+
+
+
+
+void ModInfoDialog::hideTriggered()
+{
+ changeFiletreeVisibility(false);
+}
+
+
+void ModInfoDialog::unhideTriggered()
+{
+ changeFiletreeVisibility(true);
+}
+
+void ModInfoDialog::changeFiletreeVisibility(bool visible)
+{
+ bool changed = false;
+ bool stop = false;
+
+ qDebug().nospace()
+ << (visible ? "unhiding" : "hiding") << " "
+ << m_FileSelection.size() << " filetree files";
+
+ QFlags<FileRenamer::RenameFlags> flags =
+ (visible ? FileRenamer::UNHIDE : FileRenamer::HIDE);
+
+ if (m_FileSelection.size() > 1) {
+ flags |= FileRenamer::MULTIPLE;
+ }
+
+ FileRenamer renamer(this, flags);
+
+ for (const auto& index : m_FileSelection) {
+ if (stop) {
+ break;
+ }
+
+ const QString path = m_FileSystemModel->filePath(index);
+ auto result = FileRenamer::RESULT_CANCEL;
+
+ if (visible) {
+ if (!canUnhideFile(false, path)) {
+ qDebug().nospace() << "cannot unhide " << path << ", skipping";
+ continue;
+ }
+ result = unhideFile(renamer, path);
+ } else {
+ if (!canHideFile(false, path)) {
+ qDebug().nospace() << "cannot hide " << path << ", skipping";
+ continue;
+ }
+ result = hideFile(renamer, path);
+ }
+
+ switch (result) {
+ case FileRenamer::RESULT_OK: {
+ // will trigger a refresh at the end
+ changed = true;
+ break;
+ }
+
+ case FileRenamer::RESULT_SKIP: {
+ // nop
+ break;
+ }
+
+ case FileRenamer::RESULT_CANCEL: {
+ // stop right now, but make sure to refresh if needed
+ stop = true;
+ break;
+ }
+ }
+ }
+
+ qDebug().nospace() << (visible ? "unhiding" : "hiding") << " filetree files done";
+
+ if (changed) {
+ qDebug().nospace() << "triggering refresh";
+ if (m_Origin) {
+ emit originModified(m_Origin->getID());
+ }
+ refreshLists();
+ }
+}
+
+
+
+
+void ModInfoDialog::on_fileTree_customContextMenuRequested(const QPoint &pos)
+{
+ QItemSelectionModel *selectionModel = ui->fileTree->selectionModel();
+ m_FileSelection = selectionModel->selectedRows(0);
+
+ QMenu menu(ui->fileTree);
+
+ menu.addAction(m_NewFolderAction);
+
+ if (selectionModel->hasSelection()) {
+ bool enableOpen = true;
+ bool enablePreview = true;
+ bool enableRename = true;
+ bool enableDelete = true;
+ bool enableHide = true;
+ bool enableUnhide = true;
+
+ if (m_FileSelection.size() == 1) {
+ // single selection
+
+ // only enable open action if a file is selected
+ bool hasFiles = false;
+
+ foreach(QModelIndex idx, m_FileSelection) {
+ if (m_FileSystemModel->fileInfo(idx).isFile()) {
+ hasFiles = true;
+ break;
+ }
+ }
+
+ if (!hasFiles) {
+ enableOpen = false;
+ enablePreview = false;
+ }
+
+ const QString fileName = m_FileSystemModel->fileName(m_FileSelection.at(0));
+
+ if (!canPreviewFile(*m_PluginContainer, false, fileName)) {
+ enablePreview = false;
+ }
+
+ if (!canHideFile(false, fileName)) {
+ enableHide = false;
+ }
+
+ if (!canUnhideFile(false, fileName)) {
+ enableUnhide = false;
+ }
+ } else {
+ // this is a multiple selection, don't show open action so users don't open
+ // a thousand files
+ enableOpen = false;
+ enablePreview = false;
+ enableRename = false;
+
+ if (m_FileSelection.size() < max_scan_for_context_menu) {
+ // if the number of selected items is low, checking them to accurately
+ // show the menu items is worth it
+ enableHide = false;
+ enableUnhide = false;
+
+ for (const auto& index : m_FileSelection) {
+ const QString fileName = m_FileSystemModel->fileName(index);
+
+ if (canHideFile(false, fileName)) {
+ enableHide = true;
+ }
+
+ if (canUnhideFile(false, fileName)) {
+ enableUnhide = true;
+ }
+
+ if (enableHide && enableUnhide) {
+ // found both, no need to check more
+ break;
+ }
+ }
+ }
+ }
+
+ if (enableOpen) {
+ menu.addAction(m_OpenAction);
+ }
+
+ if (enablePreview) {
+ menu.addAction(m_PreviewAction);
+ }
+
+ if (enableRename) {
+ menu.addAction(m_RenameAction);
+ }
+
+ if (enableDelete) {
+ menu.addAction(m_DeleteAction);
+ }
+
+ if (enableHide) {
+ menu.addAction(m_HideAction);
+ }
+
+ if (enableUnhide) {
+ menu.addAction(m_UnhideAction);
+ }
+ } else {
+ m_FileSelection.clear();
+ m_FileSelection.append(m_FileSystemModel->index(m_FileSystemModel->rootPath(), 0));
+ }
+
+ menu.exec(ui->fileTree->viewport()->mapToGlobal(pos));
+}
diff --git a/src/modinfodialogfiletree.h b/src/modinfodialogfiletree.h
new file mode 100644
index 00000000..e7708ab8
--- /dev/null
+++ b/src/modinfodialogfiletree.h
@@ -0,0 +1,39 @@
+#ifndef MODINFODIALOGFILETREE_H
+#define MODINFODIALOGFILETREE_H
+
+#include "modinfodialogtab.h"
+
+class FileTreeTab : public ModInfoDialogTab
+{
+public:
+ FileTreeTab(
+ OrganizerCore& oc, PluginContainer& plugin,
+ QWidget* parent, Ui::ModInfoDialog* ui);
+
+ void clear() override;
+ void update() override;
+
+private:
+ struct Actions
+ {
+ QAction *newFolder = nullptr;
+ QAction *open = nullptr;
+ QAction *preview = nullptr;
+ QAction *rename = nullptr;
+ QAction *del = nullptr;
+ QAction *hide = nullptr;
+ QAction *unhide = nullptr;
+ };
+
+ QFileSystemModel* m_fs;
+ Actions m_actions;
+
+ QModelIndex singleSelection() const;
+ void onCreateDirectory();
+ void onOpen();
+ void onPreview();
+ void onRename();
+ void onDelete();
+};
+
+#endif // MODINFODIALOGFILETREE_H