/* Copyright (C) 2012 Sebastian Herbord. All rights reserved. This file is part of Mod Organizer. Mod Organizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Mod Organizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Mod Organizer. If not, see . */ #include "modinfodialog.h" #include "ui_modinfodialog.h" #include "plugincontainer.h" #include "organizercore.h" #include "modinfodialogtextfiles.h" #include "modinfodialogimages.h" #include "modinfodialogesps.h" #include "modinfodialogconflicts.h" #include "modinfodialogcategories.h" #include "modinfodialognexus.h" #include "modinfodialogfiletree.h" using namespace MOBase; using namespace MOShared; const int max_scan_for_context_menu = 50; class ModFileListWidget : public QListWidgetItem { friend bool operator<(const ModFileListWidget &LHS, const ModFileListWidget &RHS); public: ModFileListWidget(const QString &text, int sortValue, QListWidget *parent = 0) : QListWidgetItem(text, parent, QListWidgetItem::UserType + 1), m_SortValue(sortValue) {} private: int m_SortValue; }; static bool operator<(const ModFileListWidget &LHS, const ModFileListWidget &RHS) { return LHS.m_SortValue < RHS.m_SortValue; } bool canPreviewFile( PluginContainer& pluginContainer, bool isArchive, const QString& filename) { if (isArchive) { return false; } const auto ext = QFileInfo(filename).suffix(); return pluginContainer.previewGenerator().previewSupported(ext); } bool canOpenFile(bool isArchive, const QString&) { // can open anything as long as it's not in an archive return !isArchive; } bool canHideFile(bool isArchive, const QString& filename) { if (isArchive) { // can't hide files from archives return false; } if (filename.endsWith(ModInfo::s_HiddenExt)) { // already hidden return false; } return true; } bool canUnhideFile(bool isArchive, const QString& filename) { if (isArchive) { // can't unhide files from archives return false; } if (!filename.endsWith(ModInfo::s_HiddenExt)) { // already visible return false; } return true; } FileRenamer::RenameResults hideFile(FileRenamer& renamer, const QString &oldName) { const QString newName = oldName + ModInfo::s_HiddenExt; return renamer.rename(oldName, newName); } FileRenamer::RenameResults unhideFile(FileRenamer& renamer, const QString &oldName) { QString newName = oldName.left(oldName.length() - ModInfo::s_HiddenExt.length()); return renamer.rename(oldName, newName); } ModInfoDialog::ModInfoDialog( ModInfo::Ptr modInfo, bool unmanaged, OrganizerCore *organizerCore, PluginContainer *pluginContainer, QWidget *parent) : TutorableDialog("ModInfoDialog", parent), ui(new Ui::ModInfoDialog), m_ModInfo(modInfo), m_RootPath(modInfo->absolutePath()), m_OrganizerCore(organizerCore), m_PluginContainer(pluginContainer), m_Origin(nullptr) { ui->setupUi(this); auto* ds = m_OrganizerCore->directoryStructure(); if (ds->originExists(ToWString(m_ModInfo->name()))) { m_Origin = &ds->getOriginByName(ToWString(m_ModInfo->name())); if (m_Origin->isDisabled()) { m_Origin = nullptr; } } this->setWindowTitle(m_ModInfo->name()); this->setWindowModality(Qt::WindowModal); auto* sc = new QShortcut(QKeySequence::Delete, this); connect(sc, &QShortcut::activated, [&]{ onDeleteShortcut(); }); m_tabs = createTabs(); bool tabSelected = false; for (std::size_t i=0; i(i)); }); bool enabled = true; if (unmanaged) { enabled = m_tabs[i]->canHandleUnmanaged(); } else if (m_ModInfo->hasFlag(ModInfo::FLAG_SEPARATOR)) { enabled = m_tabs[i]->canHandleSeparators(); } ui->tabWidget->setTabEnabled(static_cast(i), enabled); if (!tabSelected && enabled) { ui->tabWidget->setCurrentIndex(static_cast(i)); tabSelected = true; } } for (auto& tab : m_tabs) { tab->setMod(m_ModInfo, m_Origin); } } ModInfoDialog::~ModInfoDialog() { delete ui; } std::vector> ModInfoDialog::createTabs() { std::vector> v; v.push_back(createTab(TAB_TEXTFILES)); v.push_back(createTab(TAB_INIFILES)); v.push_back(createTab(TAB_IMAGES)); v.push_back(createTab(TAB_ESPS)); v.push_back(createTab(TAB_CONFLICTS)); v.push_back(createTab(TAB_CATEGORIES)); v.push_back(createTab(TAB_NEXUS)); v.push_back(createTab(TAB_NOTES)); v.push_back(createTab(TAB_FILETREE)); return v; } int ModInfoDialog::exec() { refreshLists(); return TutorableDialog::exec(); } void ModInfoDialog::saveState(Settings& s) const { s.directInterface().setValue("mod_info_tabs", saveTabState()); for (const auto& tab : m_tabs) { tab->saveState(s); } } void ModInfoDialog::restoreState(const Settings& s) { restoreTabState(s.directInterface().value("mod_info_tabs").toByteArray()); for (const auto& tab : m_tabs) { tab->restoreState(s); } } void ModInfoDialog::restoreTabState(const QByteArray &state) { QDataStream stream(state); int count = 0; stream >> count; QStringList tabIds; // first, only determine the new mapping for (int newPos = 0; newPos < count; ++newPos) { QString tabId; stream >> tabId; tabIds.append(tabId); int oldPos = tabIndex(tabId); if (oldPos != -1) { m_RealTabPos[newPos] = oldPos; } else { m_RealTabPos[newPos] = newPos; } } // then actually move the tabs QTabBar *tabBar = ui->tabWidget->tabBar(); ui->tabWidget->blockSignals(true); for (int newPos = 0; newPos < count; ++newPos) { QString tabId = tabIds.at(newPos); int oldPos = tabIndex(tabId); tabBar->moveTab(oldPos, newPos); } ui->tabWidget->blockSignals(false); } QByteArray ModInfoDialog::saveTabState() const { QByteArray result; QDataStream stream(&result, QIODevice::WriteOnly); stream << ui->tabWidget->count(); for (int i = 0; i < ui->tabWidget->count(); ++i) { stream << ui->tabWidget->widget(i)->objectName(); } return result; } int ModInfoDialog::tabIndex(const QString& tabId) { for (int i = 0; i < ui->tabWidget->count(); ++i) { if (ui->tabWidget->widget(i)->objectName() == tabId) { return i; } } return -1; } void ModInfoDialog::onDeleteShortcut() { for (auto& t : m_tabs) { if (t->deleteRequested()) { break; } } } void ModInfoDialog::refreshLists() { for (auto& tab : m_tabs) { tab->update(); } if (m_RootPath.length() > 0) { QDirIterator dirIterator(m_RootPath, QDir::Files, QDirIterator::Subdirectories); while (dirIterator.hasNext()) { QString fileName = dirIterator.next(); for (auto& tab : m_tabs) { if (tab->feedFile(m_RootPath, fileName)) { break; } } } } } void ModInfoDialog::on_closeButton_clicked() { for (auto& tab : m_tabs) { if (!tab->canClose()) { return; } } close(); } void ModInfoDialog::openTab(int tab) { if (ui->tabWidget->isTabEnabled(tab)) { ui->tabWidget->setCurrentIndex(tab); } } void ModInfoDialog::on_tabWidget_currentChanged(int index) { } void ModInfoDialog::on_nextButton_clicked() { int currentTab = ui->tabWidget->currentIndex(); int tab = m_RealTabPos[currentTab]; emit modOpenNext(tab); this->accept(); } void ModInfoDialog::on_prevButton_clicked() { int currentTab = ui->tabWidget->currentIndex(); int tab = m_RealTabPos[currentTab]; emit modOpenPrev(tab); this->accept(); }