diff options
| author | Tannin <devnull@localhost> | 2013-04-04 21:49:44 +0200 |
|---|---|---|
| committer | Tannin <devnull@localhost> | 2013-04-04 21:49:44 +0200 |
| commit | de27ab391f5c56db9532e7cbc32145d21e5df97c (patch) | |
| tree | 349ad259558322936381297a77b207c65ed87de3 /src | |
| parent | d9a6dbb916236531a96b9b84b06e7be666c05d56 (diff) | |
- creating mods from overwrite
- moving files from overwrite to mods
- offline mode
- several fixes to the grouping system
- fix to "duplicate translation" errors
Diffstat (limited to 'src')
| -rw-r--r-- | src/mainwindow.cpp | 121 | ||||
| -rw-r--r-- | src/mainwindow.h | 7 | ||||
| -rw-r--r-- | src/mainwindow.ui | 12 | ||||
| -rw-r--r-- | src/modlist.cpp | 108 | ||||
| -rw-r--r-- | src/modlist.h | 12 | ||||
| -rw-r--r-- | src/modlistsortproxy.cpp | 20 | ||||
| -rw-r--r-- | src/modlistsortproxy.h | 2 | ||||
| -rw-r--r-- | src/organizer.pro | 6 | ||||
| -rw-r--r-- | src/organizer_de.ts | 6 | ||||
| -rw-r--r-- | src/organizer_es.ts | 6 | ||||
| -rw-r--r-- | src/organizer_fr.ts | 6 | ||||
| -rw-r--r-- | src/overwriteinfodialog.cpp | 4 | ||||
| -rw-r--r-- | src/overwriteinfodialog.ui | 11 | ||||
| -rw-r--r-- | src/pluginlist.cpp | 8 | ||||
| -rw-r--r-- | src/qtgroupingproxy.cpp | 187 | ||||
| -rw-r--r-- | src/qtgroupingproxy.h | 17 | ||||
| -rw-r--r-- | src/resources.qrc | 3 | ||||
| -rw-r--r-- | src/resources/emblem-favorite.png | bin | 839 -> 836 bytes | |||
| -rw-r--r-- | src/settings.cpp | 8 | ||||
| -rw-r--r-- | src/settings.h | 5 | ||||
| -rw-r--r-- | src/settingsdialog.ui | 13 |
21 files changed, 441 insertions, 121 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 592c933d..2f0ca1db 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -92,10 +92,30 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <TlHelp32.h> +#include <QNetworkInterface> + + using namespace MOBase; using namespace MOShared; +static bool isOnline() +{ + QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces(); + + bool connected = false; + for (auto iter = interfaces.begin(); iter != interfaces.end(); ++iter) { + if ( (iter->flags() & QNetworkInterface::IsUp) && + (iter->flags() & QNetworkInterface::IsRunning) && + !(iter->flags() & QNetworkInterface::IsLoopBack)) { + connected = true; + } + } + + return connected; +} + + MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), m_Tutorial(this, "MainWindow"), m_ExeName(exeName), m_OldProfileIndex(-1), @@ -134,12 +154,11 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget m_ModListSortProxy = new ModListSortProxy(m_CurrentProfile, this); m_ModListSortProxy->setSourceModel(&m_ModList); - QAbstractProxyModel *proxyModel = new QIdentityProxyModel(this); - proxyModel->setSourceModel(m_ModListSortProxy); - ui->modList->setModel(proxyModel); + ui->modList->setModel(m_ModListSortProxy); ui->modList->sortByColumn(ModList::COL_PRIORITY, Qt::AscendingOrder); ui->modList->setItemDelegateForColumn(ModList::COL_FLAGS, new IconDelegate(ui->modList)); + //ui->modList->setAcceptDrops(true); ui->modList->header()->installEventFilter(&m_ModList); ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray()); ui->modList->installEventFilter(&m_ModList); @@ -161,6 +180,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget // set up plugin list m_PluginListSortProxy = new PluginListSortProxy(this); m_PluginListSortProxy->setSourceModel(&m_PluginList); + ui->espList->setModel(m_PluginListSortProxy); ui->espList->sortByColumn(PluginList::COL_PRIORITY, Qt::AscendingOrder); ui->espList->header()->restoreState(initSettings.value("plugin_list_state").toByteArray()); @@ -202,10 +222,13 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget this, SLOT(saveSelectionChanged(QListWidgetItem*))); connect(&m_PluginList, SIGNAL(saveTimer()), this, SLOT(savePluginList())); + connect(&m_ModList, SIGNAL(modorder_changed()), this, SLOT(modorder_changed())); connect(&m_ModList, SIGNAL(removeOrigin(QString)), this, SLOT(removeOrigin(QString))); connect(&m_ModList, SIGNAL(showMessage(QString)), this, SLOT(showMessage(QString))); connect(&m_ModList, SIGNAL(modRenamed(QString,QString)), this, SLOT(modRenamed(QString,QString))); + connect(ui->modList, SIGNAL(dropModeUpdate(bool)), &m_ModList, SLOT(dropModeUpdate(bool))); + connect(m_ModListSortProxy, SIGNAL(filterActive(bool)), this, SLOT(modFilterActive(bool))); connect(ui->modFilterEdit, SIGNAL(textChanged(QString)), m_ModListSortProxy, SLOT(updateFilter(QString))); connect(ui->espFilterEdit, SIGNAL(textChanged(QString)), m_PluginListSortProxy, SLOT(updateFilter(QString))); @@ -242,7 +265,13 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget FileDialogMemory::restore(initSettings); fixCategories(); - m_Updater.testForUpdate(); + + if (isOnline() && !m_Settings.offlineMode()) { + m_Updater.testForUpdate(); + } else { + qDebug("user doesn't seem to be connected to the internet"); + } + m_StartTime = QTime::currentTime(); m_Tutorial.expose("modList", &m_ModList); @@ -670,6 +699,10 @@ void MainWindow::showEvent(QShowEvent *event) m_Settings.directInterface().setValue("first_start", false); } + + // this has no visible impact when called before the ui is visible + int grouping = m_Settings.directInterface().value("group_state").toInt(); + ui->groupCombo->setCurrentIndex(grouping); } @@ -978,12 +1011,14 @@ IModInterface *MainWindow::getMod(const QString &name) IModInterface *MainWindow::createMod(const QString &name) { - unsigned int index = ModInfo::getIndex(name); + QString fixedName = name; + fixDirectoryName(fixedName); + unsigned int index = ModInfo::getIndex(fixedName); if (index != UINT_MAX) { - throw MyException(tr("The mod \"%1\" already exists!").arg(name)); + throw MyException(tr("The mod \"%1\" already exists!").arg(fixedName)); } - QString targetDirectory = QDir::fromNativeSeparators(m_Settings.getModDirectory()).append("/").append(name.trimmed()); + QString targetDirectory = QDir::fromNativeSeparators(m_Settings.getModDirectory()).append("/").append(fixedName.trimmed()); QSettings settingsFile(targetDirectory.mid(0).append("/meta.ini"), QSettings::IniFormat); @@ -1648,9 +1683,6 @@ void MainWindow::readSettings() languageChange(m_Settings.language()); int selectedExecutable = settings.value("selected_executable").toInt(); setExecutableIndex(selectedExecutable); - - int grouping = settings.value("group_state").toInt(); - ui->groupCombo->setCurrentIndex(grouping); } @@ -2490,8 +2522,14 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, { std::vector<ModInfo::EFlag> flags = modInfo->getFlags(); if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) { - OverwriteInfoDialog dialog(modInfo, this); - dialog.exec(); + QDialog *dialog = this->findChild<QDialog*>("__overwriteDialog"); + if (dialog == NULL) { + dialog = new OverwriteInfoDialog(modInfo, this); + dialog->setObjectName("__overwriteDialog"); + } + dialog->show(); + dialog->raise(); + dialog->activateWindow(); } else { ModInfoDialog dialog(modInfo, m_DirectoryStructure, this); connect(&dialog, SIGNAL(nexusLinkActivated(QString)), this, SLOT(nexusLinkActivated(QString))); @@ -2634,6 +2672,17 @@ void MainWindow::testExtractBSA(int modIndex) } +void MainWindow::ignoreMissingData_clicked() +{ + ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); + QDir(info->absolutePath()).mkdir("textures"); + info->testValid(); + connect(this, SIGNAL(modListDataChanged(QModelIndex,QModelIndex)), &m_ModList, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + + emit modListDataChanged(m_ModList.index(m_ContextRow, 0), m_ModList.index(m_ContextRow, m_ModList.columnCount() - 1)); +} + + void MainWindow::visitOnNexus_clicked() { int modID = m_ModList.data(m_ModList.index(m_ContextRow, 0), Qt::UserRole).toInt(); @@ -2674,6 +2723,28 @@ void MainWindow::syncOverwrite() } +void MainWindow::createModFromOverwrite() +{ + QString name = QInputDialog::getText(this, tr("Create Mod..."), + tr("This will move all files from overwrite into a new, regular mod." + "Please enter a name: ")); + QString fixedName = fixDirectoryName(name); + if (fixedName.isEmpty()) { + reportError(tr("Invalid name")); + return; + } else if (getMod(fixedName) != NULL) { + reportError(tr("A mod with this name already exists")); + return; + } + + IModInterface *newMod = createMod(name); + + ModInfo::Ptr overwriteInfo = ModInfo::getByIndex(m_ContextRow); + + shellMove(QStringList(overwriteInfo->absolutePath() + "\\*"), QStringList(newMod->absolutePath()), this); +} + + void MainWindow::cancelModListEditor() { ui->modList->setEnabled(false); @@ -2959,7 +3030,10 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos) ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); std::vector<ModInfo::EFlag> flags = info->getFlags(); if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) { - menu.addAction(tr("Sync to Mods..."), this, SLOT(syncOverwrite())); + if (QDir(info->absolutePath()).count() > 2) { + menu.addAction(tr("Sync to Mods..."), this, SLOT(syncOverwrite())); + menu.addAction(tr("Create Mod..."), this, SLOT(createModFromOverwrite())); + } } else if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end()) { menu.addAction(tr("Restore Backup"), this, SLOT(restoreBackup_clicked())); menu.addAction(tr("Remove Backup..."), this, SLOT(removeMod_clicked())); @@ -2992,6 +3066,10 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos) menu.addAction(action); } break; } + std::vector<ModInfo::EFlag> flags = info->getFlags(); + if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_INVALID) != flags.end()) { + menu.addAction(tr("Ignore missing data"), this, SLOT(ignoreMissingData_clicked())); + } menu.addAction(tr("Visit on Nexus"), this, SLOT(visitOnNexus_clicked())); menu.addAction(tr("Open in explorer"), this, SLOT(openExplorer_clicked())); @@ -4062,25 +4140,30 @@ void MainWindow::on_groupCombo_currentIndexChanged(int index) QAbstractProxyModel *newModel = NULL; switch (index) { case 1: { - newModel = new QtGroupingProxy(m_ModListSortProxy, QModelIndex(), ModList::COL_CATEGORY, Qt::UserRole); + newModel = new QtGroupingProxy(&m_ModList, QModelIndex(), ModList::COL_CATEGORY, Qt::UserRole, + 0, Qt::UserRole + 2); } break; case 2: { - newModel = new QtGroupingProxy(m_ModListSortProxy, QModelIndex(), ModList::COL_MODID); + newModel = new QtGroupingProxy(&m_ModList, QModelIndex(), ModList::COL_MODID, Qt::DisplayRole, + QtGroupingProxy::FLAG_NOGROUPNAME | QtGroupingProxy::FLAG_NOSINGLE, + Qt::UserRole + 2); } break; default: { newModel = NULL; } break; } - if (newModel != NULL) { - newModel->setSourceModel(m_ModListSortProxy); +// newModel->setSourceModel(m_ModListSortProxy); + m_ModListSortProxy->setSourceModel(newModel); connect(ui->modList, SIGNAL(expanded(QModelIndex)),newModel, SLOT(expanded(QModelIndex))); connect(ui->modList, SIGNAL(collapsed(QModelIndex)), newModel, SLOT(collapsed(QModelIndex))); connect(newModel, SIGNAL(expandItem(QModelIndex)), ui->modList, SLOT(expand(QModelIndex))); - ui->modList->setModel(newModel); +// ui->modList->setModel(newModel); } else { - ui->modList->setModel(m_ModListSortProxy); + m_ModListSortProxy->setSourceModel(&m_ModList); +// ui->modList->setModel(m_ModListSortProxy); } +// ui->modList->setModel(m_ModListSortProxy); // ui->modList->setSelectionMode(QAbstractItemView::ExtendedSelection); } diff --git a/src/mainwindow.h b/src/mainwindow.h index 91c2b17d..5880fcb8 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -137,6 +137,10 @@ signals: */ void styleChanged(const QString &styleFile); + + + void modListDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + protected: virtual void showEvent(QShowEvent *event); @@ -310,6 +314,7 @@ private slots: void endorse_clicked(); void dontendorse_clicked(); void unendorse_clicked(); + void ignoreMissingData_clicked(); void visitOnNexus_clicked(); void openExplorer_clicked(); void information_clicked(); @@ -338,6 +343,8 @@ private slots: void syncOverwrite(); + void createModFromOverwrite(); + void removeOrigin(const QString &name); void procError(QProcess::ProcessError error); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index b7d0057e..39a12ec0 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -161,7 +161,7 @@ p, li { white-space: pre-wrap; } </layout>
</item>
<item>
- <widget class="QTreeView" name="modList">
+ <widget class="ModListView" name="modList">
<property name="minimumSize">
<size>
<width>330</width>
@@ -280,11 +280,8 @@ p, li { white-space: pre-wrap; } <property name="dragEnabled">
<bool>true</bool>
</property>
- <property name="dragDropOverwriteMode">
- <bool>false</bool>
- </property>
<property name="dragDropMode">
- <enum>QAbstractItemView::InternalMove</enum>
+ <enum>QAbstractItemView::DragDrop</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
@@ -1201,6 +1198,11 @@ Right now this has very limited functionality</string> <extends>QLineEdit</extends>
<header>lineeditclear.h</header>
</customwidget>
+ <customwidget>
+ <class>ModListView</class>
+ <extends>QTreeView</extends>
+ <header>modlistview.h</header>
+ </customwidget>
</customwidgets>
<resources>
<include location="resources.qrc"/>
diff --git a/src/modlist.cpp b/src/modlist.cpp index 2d681a0d..fc425f85 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -23,6 +23,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "utility.h" #include "messagedialog.h" #include "installationtester.h" +#include "qtgroupingproxy.h" #include <gameinfo.h> #include <QFileInfo> @@ -49,7 +50,7 @@ using namespace MOBase; ModList::ModList(QObject *parent) : QAbstractItemModel(parent), m_Profile(NULL), m_Modified(false), - m_FontMetrics(QFont()) + m_FontMetrics(QFont()), m_DropOnItems(false) { } @@ -143,15 +144,7 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const if (priority != INT_MIN) { return QVariant(); // hide priority for mods where it's fixed } else { - if ((m_Profile->getModPriority(modIndex) == 0) && (role == Qt::DisplayRole)) { - return tr("min"); - } else if ((m_Profile->getModPriority(modIndex) == static_cast<int>(m_Profile->numRegularMods()) - 1) && - (role == Qt::DisplayRole)) { - return tr("max"); - } else { - //return QString::number(m_Profile->getModPriority(modIndex)); - return m_Profile->getModPriority(modIndex); - } + return m_Profile->getModPriority(modIndex); } } else if (column == COL_MODID) { int modID = modInfo->getNexusID(); @@ -208,11 +201,21 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const } else { return QVariant(); } + } else if (column == COL_PRIORITY) { + return m_Profile->getModPriority(modIndex); } else { return modInfo->getNexusID(); } } else if (role == Qt::UserRole + 1) { return modIndex; + } else if (role == Qt::UserRole + 2) { + switch (column) { + case COL_MODID: return QtGroupingProxy::AGGR_FIRST; + case COL_VERSION: return QtGroupingProxy::AGGR_MAX; + case COL_CATEGORY: return QtGroupingProxy::AGGR_FIRST; + case COL_PRIORITY: return QtGroupingProxy::AGGR_MIN; + default: return QtGroupingProxy::AGGR_NONE; + } } else if (role == Qt::FontRole) { QFont result; if (column == COL_NAME) { @@ -323,10 +326,12 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role) return false; } + int modID = index.row(); + if (role == Qt::CheckStateRole) { bool enabled = value.toInt() == Qt::Checked; - if (m_Profile->modEnabled(index.row()) != enabled) { - m_Profile->setModEnabled(index.row(), enabled); + if (m_Profile->modEnabled(modID) != enabled) { + m_Profile->setModEnabled(modID, enabled); m_Modified = true; emit modlist_changed(index, role); @@ -335,13 +340,13 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role) } else if (role == Qt::EditRole) { switch (index.column()) { case COL_NAME: { - return renameMod(index.row(), value.toString()); + return renameMod(modID, value.toString()); } break; case COL_PRIORITY: { bool ok = false; int newPriority = value.toInt(&ok); if (ok) { - m_Profile->setModPriority(index.row(), newPriority); + m_Profile->setModPriority(modID, newPriority); emit modlist_changed(index, role); return true; @@ -350,7 +355,7 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role) } } break; case COL_MODID: { - ModInfo::Ptr info = ModInfo::getByIndex(index.row()); + ModInfo::Ptr info = ModInfo::getByIndex(modID); bool ok = false; int newID = value.toInt(&ok); if (ok) { @@ -362,7 +367,7 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role) } } break; case COL_VERSION: { - ModInfo::Ptr info = ModInfo::getByIndex(index.row()); + ModInfo::Ptr info = ModInfo::getByIndex(modID); VersionInfo version(value.toString()); if (version.isValid()) { info->setVersion(version); @@ -435,12 +440,23 @@ Qt::ItemFlags ModList::flags(const QModelIndex &modelIndex) const result |= Qt::ItemIsEditable; } } + std::vector<ModInfo::EFlag> flags = modInfo->getFlags(); + if ((m_DropOnItems) && (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) == flags.end())) { + result |= Qt::ItemIsDropEnabled; + } } else { - result |= Qt::ItemIsDropEnabled; + if (!m_DropOnItems) result |= Qt::ItemIsDropEnabled; } return result; } +QStringList ModList::mimeTypes() const +{ + QStringList result = QAbstractItemModel::mimeTypes(); + result.append("text/uri-list"); + return result; +} + void ModList::changeModPriority(std::vector<int> sourceIndices, int newPriority) { @@ -488,13 +504,39 @@ void ModList::changeModPriority(int sourceIndex, int newPriority) } -bool ModList::dropMimeData(const QMimeData *mimeData, Qt::DropAction action, int row, int, const QModelIndex &parent) +bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &parent) { - if (action == Qt::IgnoreAction) { - return true; + QStringList source; + QStringList target; + + if (row == -1) { + row = parent.row(); } - if (m_Profile == NULL) return false; + ModInfo::Ptr modInfo = ModInfo::getByIndex(row); + QDir modDirectory(modInfo->absolutePath()); + QDir gameDirectory(QDir::fromNativeSeparators(ToQString(MOShared::GameInfo::instance().getOverwriteDir()))); + + foreach (const QUrl &url, mimeData->urls()) { + QString relativePath = gameDirectory.relativeFilePath(url.toLocalFile()); + if (relativePath.startsWith("..")) { + qDebug("%s drop ignored", qPrintable(url.toLocalFile())); + continue; + } + source.append(url.toLocalFile()); + target.append(modDirectory.absoluteFilePath(relativePath)); + } + + if (source.count() != 0) { + shellCopy(source, target, NULL); + } + + return true; +} + + +bool ModList::dropMod(const QMimeData *mimeData, int row, const QModelIndex &parent) +{ try { QByteArray encoded = mimeData->data("application/x-qabstractitemmodeldatalist"); @@ -538,6 +580,22 @@ bool ModList::dropMimeData(const QMimeData *mimeData, Qt::DropAction action, int } +bool ModList::dropMimeData(const QMimeData *mimeData, Qt::DropAction action, int row, int, const QModelIndex &parent) +{ + if (action == Qt::IgnoreAction) { + return true; + } + + if (m_Profile == NULL) return false; + if (mimeData->hasUrls()) { + return dropURLs(mimeData, row, parent); + } else { + return dropMod(mimeData, row, parent); + } + +} + + void ModList::removeRowForce(int row) { if (static_cast<unsigned int>(row) >= ModInfo::getNumMods()) { @@ -610,6 +668,14 @@ QMap<int, QVariant> ModList::itemData(const QModelIndex &index) const } +void ModList::dropModeUpdate(bool dropOnItems) +{ + if (m_DropOnItems != dropOnItems) { + m_DropOnItems = dropOnItems; + } +} + + QString ModList::getColumnName(int column) { switch (column) { diff --git a/src/modlist.h b/src/modlist.h index ea850d54..a0b6e841 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -105,11 +105,11 @@ public: // implementation of virtual functions of QAbstractItemModel virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; virtual Qt::ItemFlags flags(const QModelIndex &modelIndex) const; - virtual Qt::DropActions supportedDropActions() const { return Qt::MoveAction; } + virtual Qt::DropActions supportedDropActions() const { return Qt::MoveAction | Qt::CopyAction; } + virtual QStringList mimeTypes() const; virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); virtual void removeRow(int row, const QModelIndex &parent); - virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; virtual QModelIndex parent(const QModelIndex &child) const; @@ -118,6 +118,8 @@ public: // implementation of virtual functions of QAbstractItemModel public slots: + void dropModeUpdate(bool dropOnItems); + signals: /** @@ -202,6 +204,10 @@ private: bool renameMod(int index, const QString &newName); + bool dropURLs(const QMimeData *mimeData, int row, const QModelIndex &parent); + + bool dropMod(const QMimeData *mimeData, int row, const QModelIndex &parent); + private slots: private: @@ -227,6 +233,8 @@ private: QFontMetrics m_FontMetrics; + bool m_DropOnItems; + }; #endif // MODLIST_H diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 071e0384..11b3f69a 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -57,21 +57,20 @@ void ModListSortProxy::setCategoryFilter(int category) this->invalidate(); } - Qt::ItemFlags ModListSortProxy::flags(const QModelIndex &modelIndex) const { Qt::ItemFlags flags = sourceModel()->flags(mapToSource(modelIndex)); if (sortColumn() != ModList::COL_PRIORITY) { flags &= ~Qt::ItemIsDragEnabled; } + return flags; } - void ModListSortProxy::displayColumnSelection(const QPoint &pos) { - QMenu menu; + QMenu menu; for (int i = 0; i <= ModList::COL_LASTCOLUMN; ++i) { QCheckBox *checkBox = new QCheckBox(&menu); @@ -105,7 +104,7 @@ void ModListSortProxy::enableAllVisible() if (m_Profile == NULL) return; for (int i = 0; i < this->rowCount(); ++i) { - int modID = mapToSource(index(i, 0)).row(); + int modID = mapToSource(index(i, 0)).data(Qt::UserRole + 1).toInt(); m_Profile->setModEnabled(modID, true); } invalidate(); @@ -115,18 +114,25 @@ void ModListSortProxy::enableAllVisible() void ModListSortProxy::disableAllVisible() { if (m_Profile == NULL) return; + for (int i = 0; i < this->rowCount(); ++i) { - int modID = mapToSource(index(i, 0)).row(); + int modID = mapToSource(index(i, 0)).data(Qt::UserRole + 1).toInt(); m_Profile->setModEnabled(modID, false); } + invalidate(); } bool ModListSortProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const { - int leftIndex = left.row(); - int rightIndex = right.row(); + bool lOk, rOk; + int leftIndex = left.data(Qt::UserRole + 1).toInt(&lOk); + int rightIndex = right.data(Qt::UserRole + 1).toInt(&rOk); + if (!lOk || !rOk) { + return false; + } + ModInfo::Ptr leftMod = ModInfo::getByIndex(leftIndex); ModInfo::Ptr rightMod = ModInfo::getByIndex(rightIndex); diff --git a/src/modlistsortproxy.h b/src/modlistsortproxy.h index 8b86b222..d1e3e238 100644 --- a/src/modlistsortproxy.h +++ b/src/modlistsortproxy.h @@ -54,8 +54,6 @@ public: bool filterMatches(ModInfo::Ptr info, bool enabled) const; -//virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const; - public slots: void displayColumnSelection(const QPoint &pos); diff --git a/src/organizer.pro b/src/organizer.pro index 560394a4..582ba633 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -77,7 +77,8 @@ SOURCES += \ gameinfoimpl.cpp \
csvbuilder.cpp \
savetextasdialog.cpp \
- qtgroupingproxy.cpp
+ qtgroupingproxy.cpp \
+ modlistview.cpp
HEADERS += \
transfersavesdialog.h \
@@ -142,7 +143,8 @@ HEADERS += \ gameinfoimpl.h \
csvbuilder.h \
savetextasdialog.h \
- qtgroupingproxy.h
+ qtgroupingproxy.h \
+ modlistview.h
FORMS += \
transfersavesdialog.ui \
diff --git a/src/organizer_de.ts b/src/organizer_de.ts index 52e53e8b..6f7dcf1c 100644 --- a/src/organizer_de.ts +++ b/src/organizer_de.ts @@ -1180,12 +1180,6 @@ p, li { white-space: pre-wrap; } <translation>Installation fehlgeschlagen (Fehlercode %1)</translation> </message> <message> - <location filename="installationmanager.cpp" line="774"/> - <source>Installation as fomod failed: %1</source> - <oldsource>failed to open archive "%1": %2</oldsource> - <translation type="unfinished">konnte das Archiv "%1" nicht öffnen: %2</translation> - </message> - <message> <location filename="installationmanager.cpp" line="79"/> <source>archive.dll not loaded: "%1"</source> <translation type="unfinished"></translation> diff --git a/src/organizer_es.ts b/src/organizer_es.ts index c3cfc0fe..a3e77c64 100644 --- a/src/organizer_es.ts +++ b/src/organizer_es.ts @@ -1147,12 +1147,6 @@ p, li { white-space: pre-wrap; } <translation type="unfinished"></translation> </message> <message> - <location filename="installationmanager.cpp" line="774"/> - <source>Installation as fomod failed: %1</source> - <oldsource>failed to open archive "%1": %2</oldsource> - <translation type="unfinished">error al abrir el archivo "%1": %2</translation> - </message> - <message> <location filename="installationmanager.cpp" line="79"/> <source>archive.dll not loaded: "%1"</source> <translation type="unfinished"></translation> diff --git a/src/organizer_fr.ts b/src/organizer_fr.ts index 029451eb..70cd5ab7 100644 --- a/src/organizer_fr.ts +++ b/src/organizer_fr.ts @@ -1140,12 +1140,6 @@ p, li { white-space: pre-wrap; } <translation type="unfinished"></translation> </message> <message> - <location filename="installationmanager.cpp" line="774"/> - <source>Installation as fomod failed: %1</source> - <oldsource>failed to open archive "%1": %2</oldsource> - <translation type="unfinished">impossible d'ouvrir l'archive "%1": %2</translation> - </message> - <message> <location filename="installationmanager.cpp" line="79"/> <source>archive.dll not loaded: "%1"</source> <translation type="unfinished"></translation> diff --git a/src/overwriteinfodialog.cpp b/src/overwriteinfodialog.cpp index 99699b52..11e7b552 100644 --- a/src/overwriteinfodialog.cpp +++ b/src/overwriteinfodialog.cpp @@ -77,6 +77,8 @@ OverwriteInfoDialog::OverwriteInfoDialog(ModInfo::Ptr modInfo, QWidget *parent) { ui->setupUi(this); + this->setWindowModality(Qt::NonModal); + QString path = modInfo->absolutePath(); m_FileSystemModel = new MyFileSystemModel(this); m_FileSystemModel->setReadOnly(false); @@ -84,7 +86,6 @@ OverwriteInfoDialog::OverwriteInfoDialog(ModInfo::Ptr modInfo, QWidget *parent) ui->filesView->setModel(m_FileSystemModel); ui->filesView->setRootIndex(m_FileSystemModel->index(path)); ui->filesView->setColumnWidth(0, 250); -// ui->filesView->header()->hideSection(3); m_DeleteAction = new QAction(tr("&Delete"), ui->filesView); m_RenameAction = new QAction(tr("&Rename"), ui->filesView); @@ -225,7 +226,6 @@ void OverwriteInfoDialog::on_filesView_customContextMenuRequested(const QPoint & QItemSelectionModel *selectionModel = ui->filesView->selectionModel(); m_FileSelection = selectionModel->selectedRows(0); -// m_FileSelection = m_FileTree->indexAt(pos); QMenu menu(ui->filesView); menu.addAction(m_NewFolderAction); diff --git a/src/overwriteinfodialog.ui b/src/overwriteinfodialog.ui index 2aa1bcd8..c6119ca6 100644 --- a/src/overwriteinfodialog.ui +++ b/src/overwriteinfodialog.ui @@ -19,6 +19,15 @@ <property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
+ <property name="dragEnabled">
+ <bool>true</bool>
+ </property>
+ <property name="dragDropMode">
+ <enum>QAbstractItemView::DragOnly</enum>
+ </property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::ExtendedSelection</enum>
+ </property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
@@ -30,7 +39,7 @@ <enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ <set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index dfac8ccb..b5bb483b 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -599,13 +599,7 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const return m_ESPs[index].m_Name; } break; case COL_PRIORITY: { - if (m_ESPs[index].m_Priority == 0) { - return tr("min"); - } else if (m_ESPs[index].m_Priority == static_cast<int>(m_ESPs.size()) - 1) { - return tr("max"); - } else { - return QString::number(m_ESPs[index].m_Priority); - } + return m_ESPs[index].m_Priority; } break; case COL_MODINDEX: { if (m_ESPs[index].m_LoadOrder == -1) { diff --git a/src/qtgroupingproxy.cpp b/src/qtgroupingproxy.cpp index 95a4aad0..4e066f65 100644 --- a/src/qtgroupingproxy.cpp +++ b/src/qtgroupingproxy.cpp @@ -14,7 +14,7 @@ * this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
-// Modifications 2013-03-27 to 2013-03-28 by Sebastian Herbord
+// Modifications 2013-03-27 to 2013-03-29 by Sebastian Herbord
#include "QtGroupingProxy.h"
@@ -31,11 +31,12 @@ \ingroup model-view
*/
-QtGroupingProxy::QtGroupingProxy(QAbstractItemModel *model, QModelIndex rootNode, int groupedColumn, Qt::ItemDataRole groupedRole, unsigned int flags )
+QtGroupingProxy::QtGroupingProxy(QAbstractItemModel *model, QModelIndex rootNode, int groupedColumn, int groupedRole, unsigned int flags , int aggregateRole)
: QAbstractProxyModel()
, m_rootNode( rootNode )
, m_groupedColumn( 0 )
, m_groupedRole( groupedRole )
+ , m_aggregateRole( aggregateRole )
, m_flags( flags )
{
setSourceModel( model );
@@ -104,7 +105,7 @@ QtGroupingProxy::belongsTo( const QModelIndex &idx ) i.next();
int role = i.key();
QVariant variant = i.value();
- qDebug() << "role " << role << " : (" << variant.typeName() << ") : "<< variant;
+ // qDebug() << "role " << role << " : (" << variant.typeName() << ") : "<< variant;
if ( variant.type() == QVariant::List )
{
//a list of variants get's expanded to multiple rows
@@ -171,7 +172,32 @@ QtGroupingProxy::buildTree() //dumpGroups();
if (m_flags & FLAG_NOSINGLE) {
+ // awkward: flatten single-item groups as a post-processing steps.
+ int currentKey = 0;
+ quint32 quint32max = std::numeric_limits<quint32>::max();
+ std::vector<int> rmgroups;
+
+ QHash<quint32, QList<int> > temp;
+
+ for (auto iter = m_groupHash.begin(); iter != m_groupHash.end(); ++iter) {
+ if ((iter.key() == quint32max) ||
+ (iter->count() == 1)) {
+ temp[quint32max].append(iter.value());
+ if (iter.key() != quint32max) {
+ rmgroups.push_back(iter.key());
+ }
+ } else {
+ temp[currentKey++] = *iter;
+ }
+ }
+ m_groupHash = temp;
+
+ // second loop is necessary because qt containers can't be iterated from end to
+ // removing by index from begin to end is ugly
+ for (auto iter = rmgroups.rbegin(); iter != rmgroups.rend(); ++iter) {
+ m_groupMaps.removeAt(*iter);
+ }
}
endResetModel();
@@ -191,6 +217,7 @@ QtGroupingProxy::addSourceRow( const QModelIndex &idx ) QList<int> updatedGroups;
QList<RowData> groupData = belongsTo( idx );
+
//an empty list here means it's supposed to go in root.
if( groupData.isEmpty() )
{
@@ -346,7 +373,6 @@ QtGroupingProxy::rowCount( const QModelIndex &index ) const if( !index.isValid() )
{
//the number of top level groups + the number of non-grouped items
- qDebug("groups: %d - ungrouped: %d", m_groupMaps.count(), m_groupHash.value(std::numeric_limits<quint32>::max()).count());
int rows = m_groupMaps.count() + m_groupHash.value( std::numeric_limits<quint32>::max() ).count();
//qDebug() << rows << " in root group";
return rows;
@@ -359,12 +385,12 @@ QtGroupingProxy::rowCount( const QModelIndex &index ) const int rows = m_groupHash.value( groupIndex ).count();
//qDebug() << rows << " in group " << m_groupMaps[groupIndex];
return rows;
+ } else {
+ QModelIndex originalIndex = mapToSource( index );
+ int rowCount = sourceModel()->rowCount( originalIndex );
+ //qDebug() << "original item: rowCount == " << rowCount;
+ return rowCount;
}
-
- QModelIndex originalIndex = mapToSource( index );
- int rowCount = sourceModel()->rowCount( originalIndex );
- //qDebug() << "original item: rowCount == " << rowCount;
- return rowCount;
}
int
@@ -379,6 +405,44 @@ QtGroupingProxy::columnCount( const QModelIndex &index ) const return sourceModel()->columnCount( mapToSource( index ) );
}
+
+static bool variantLess(const QVariant &LHS, const QVariant &RHS)
+{
+ if ((LHS.type() == RHS.type()) &&
+ ((LHS.type() == QVariant::Int) || (LHS.type() == QVariant::UInt))) {
+ return LHS.toInt() < RHS.toInt();
+ }
+
+ // this should always work (comparing empty strings in the worst case) but
+ // the results may be wrong
+ return LHS.toString() < RHS.toString();
+}
+
+
+static QVariant variantMax(const QVariantList &variants)
+{
+ QVariant result = variants.first();
+ foreach (const QVariant &iter, variants) {
+ if (variantLess(result, iter)) {
+ result = iter;
+ }
+ }
+ return result;
+}
+
+
+static QVariant variantMin(const QVariantList &variants)
+{
+ QVariant result = variants.first();
+ foreach (const QVariant &iter, variants) {
+ if (variantLess(iter, result)) {
+ result = iter;
+ }
+ }
+ return result;
+}
+
+
QVariant
QtGroupingProxy::data( const QModelIndex &index, int role ) const
{
@@ -389,18 +453,8 @@ QtGroupingProxy::data( const QModelIndex &index, int role ) const int column = index.column();
if( isGroup( index ) )
{
- if (column != 0) return QVariant();
-
- //qDebug() << __FUNCTION__ << "is a group";
- //use cached or precalculated data
- if( m_groupMaps[row][column].contains( Qt::DisplayRole ) )
- {
- //qDebug() << "Using cached data";
+ if ((role != Qt::DisplayRole) && (role != Qt::EditRole)) {
switch (role) {
- case Qt::DisplayRole: {
- QString value = m_groupMaps[row][column].value( role ).toString();
- return QString("----- %1 -----").arg(value.isEmpty() ? tr("<unset>") : value);
- } break;
case Qt::ForegroundRole: {
return QBrush(Qt::gray);
} break;
@@ -415,13 +469,47 @@ QtGroupingProxy::data( const QModelIndex &index, int role ) const case Qt::UserRole: {
return m_groupMaps[row][column].value( Qt::DisplayRole ).toString();
} break;
+ case Qt::CheckStateRole: {
+ if (column != 0) return QVariant();
+ int childCount = m_groupHash.value( row ).count();
+ int checked = 0;
+ QModelIndex parentIndex = this->index( row, 0, index.parent() );
+ for( int childRow = 0; childRow < childCount; ++childRow )
+ {
+ QModelIndex childIndex = this->index( childRow, 0, parentIndex );
+ QVariant data = mapToSource( childIndex ).data( Qt::CheckStateRole );
+ if (data.toInt() == 2) ++checked;
+ }
+ if (checked == childCount) return Qt::Checked;
+ else if (checked == 0) return Qt::Unchecked;
+ else return Qt::PartiallyChecked;
+ } break;
default: {
- return QVariant();
+ QModelIndex parentIndex = this->index( row, 0, index.parent() );
+ if (m_groupHash.value( row ).count() > 0) {
+ return this->index(0, 0, parentIndex).data(role);
+ } else {
+ return QVariant();
+ }
// return m_groupMaps[row][column].value( role );
} break;
}
}
+ //qDebug() << __FUNCTION__ << "is a group";
+ //use cached or precalculated data
+ if( m_groupMaps[row][column].contains( Qt::DisplayRole ) )
+ {
+ // qDebug() << "Using cached data for " << row << "x" << column << ": " << m_groupMaps[row][column].value(Qt::DisplayRole).toString();
+ if ((m_flags & FLAG_NOGROUPNAME) != 0) {
+ QModelIndex parentIndex = this->index( row, 0, index.parent() );
+ QModelIndex childIndex = this->index( 0, column, parentIndex );
+ return childIndex.data(role).toString();
+ } else {
+ return m_groupMaps[row][column].value( role ).toString();
+ }
+ }
+
//for column 0 we gather data from the grouped column instead
if( column == 0 )
column = m_groupedColumn;
@@ -432,6 +520,13 @@ QtGroupingProxy::data( const QModelIndex &index, int role ) const if( childCount == 0 )
return QVariant();
+ int function = AGGR_NONE;
+ if (m_aggregateRole >= Qt::UserRole) {
+ QModelIndex parentIndex = this->index( row, 0, index.parent() );
+ QModelIndex childIndex = this->index( 0, column, parentIndex );
+ function = mapToSource(childIndex).data(m_aggregateRole).toInt();
+ }
+
//qDebug() << __FUNCTION__ << "childCount: " << childCount;
//Need a parentIndex with column == 0 because only those have children.
QModelIndex parentIndex = this->index( row, 0, index.parent() );
@@ -448,19 +543,29 @@ QtGroupingProxy::data( const QModelIndex &index, int role ) const ItemData roleMap = m_groupMaps[row].value( column );
foreach( const QVariant &variant, variantsOfChildren )
{
- if( roleMap[ role ] != variant )
+ if( roleMap[ role ] != variant ) {
roleMap.insert( role, variantsOfChildren );
+ }
}
//qDebug() << QString("roleMap[%1]:").arg(role) << roleMap[role];
- //only one unique variant? No need to return a list
- if( variantsOfChildren.count() == 1 )
- return variantsOfChildren.first();
if( variantsOfChildren.count() == 0 )
return QVariant();
- return variantsOfChildren;
+ //only one unique variant? No need to return a list
+ switch (function) {
+ case AGGR_EMPTY: return QVariant();
+ case AGGR_FIRST: return variantsOfChildren.first();
+ case AGGR_MAX: return variantMax(variantsOfChildren);
+ case AGGR_MIN: return variantMin(variantsOfChildren);
+ default: {
+ if( variantsOfChildren.count() == 1 )
+ return variantsOfChildren.first();
+
+ return variantsOfChildren;
+ } break;
+ }
}
return mapToSource( index ).data( role );
@@ -612,7 +717,7 @@ QtGroupingProxy::mapFromSource( const QModelIndex &idx ) const //qDebug() << "proxyParent: " << proxyParent;
//qDebug() << "proxyRow: " << proxyRow;
- return this->index( proxyRow, 0, proxyParent );
+ return this->index( proxyRow, idx.column(), proxyParent );
}
Qt::ItemFlags
@@ -632,10 +737,28 @@ QtGroupingProxy::flags( const QModelIndex &idx ) const if( isGroup( idx ) )
{
// dumpGroups();
- // Qt::ItemFlags defaultFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
- Qt::ItemFlags defaultFlags(Qt::NoItemFlags);
+ Qt::ItemFlags defaultFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
+ //Qt::ItemFlags defaultFlags(Qt::ItemIsEnabled);
bool groupIsEditable = true;
+ if (idx.column() == 0) {
+ bool checkable = true;
+ foreach ( int originalRow, m_groupHash.value( idx.row() ) )
+ {
+ QModelIndex originalIdx = sourceModel()->index( originalRow, 0,
+ m_rootNode.parent() );
+ if ( (originalIdx.flags() & Qt::ItemIsUserCheckable) == 0 )
+ {
+ qDebug("row %d is not checkable", originalRow);
+ checkable = false;
+ }
+ }
+
+ if ( checkable ) {
+ defaultFlags |= Qt::ItemIsUserCheckable;
+ }
+ }
+
//it's possible to have empty groups
if( m_groupHash.value( idx.row() ).count() == 0 )
{
@@ -658,7 +781,6 @@ QtGroupingProxy::flags( const QModelIndex &idx ) const break;
}
}
-
if( groupIsEditable )
return ( defaultFlags | Qt::ItemIsEditable | Qt::ItemIsDropEnabled );
return defaultFlags;
@@ -671,9 +793,9 @@ QtGroupingProxy::flags( const QModelIndex &idx ) const QModelIndex groupedColumnIndex =
sourceModel()->index( originalIdx.row(), m_groupedColumn, originalIdx.parent() );
bool groupIsEditable = sourceModel()->flags( groupedColumnIndex ).testFlag( Qt::ItemIsEditable );
+
if( groupIsEditable )
return originalItemFlags | Qt::ItemIsDragEnabled;
-
return originalItemFlags;
}
@@ -736,8 +858,9 @@ QtGroupingProxy::hasChildren( const QModelIndex &parent ) const if( !parent.isValid() )
return true;
- if( isGroup( parent ) )
+ if( isGroup( parent ) ) {
return !m_groupHash.value( parent.row() ).isEmpty();
+ }
return sourceModel()->hasChildren( mapToSource( parent ) );
}
diff --git a/src/qtgroupingproxy.h b/src/qtgroupingproxy.h index a7f151ce..e09ae7b4 100644 --- a/src/qtgroupingproxy.h +++ b/src/qtgroupingproxy.h @@ -36,12 +36,21 @@ class QtGroupingProxy : public QAbstractProxyModel public:
static const unsigned int FLAG_NOSINGLE = 1;
- static const unsigned int FLAG_NAMETOPITEM = 2;
+ static const unsigned int FLAG_NOGROUPNAME = 2;
+
+ enum EAggregateFunction {
+ AGGR_NONE, // no aggregation, return child elements as list
+ AGGR_EMPTY, // display nothing
+ AGGR_FIRST, // return value of the topmost item
+ AGGR_MAX, // return maximum value
+ AGGR_MIN // return minimum value
+ };
public:
explicit QtGroupingProxy( QAbstractItemModel *model, QModelIndex rootNode = QModelIndex(),
- int groupedColumn = -1, Qt::ItemDataRole groupedRole = Qt::DisplayRole,
- unsigned int flags = 0);
+ int groupedColumn = -1, int groupedRole = Qt::DisplayRole,
+ unsigned int flags = 0,
+ int aggregateRole = Qt::DisplayRole);
~QtGroupingProxy();
void setGroupedColumn( int groupedColumn );
@@ -150,6 +159,8 @@ private: QSet<QString> m_expandedItems;
unsigned int m_flags;
int m_groupedRole;
+
+ int m_aggregateRole;
};
#endif //GROUPINGPROXY_H
diff --git a/src/resources.qrc b/src/resources.qrc index 855a23fc..a743ba39 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -50,5 +50,8 @@ <file alias="emblem_conflict_overwritten">resources/conflict-overwritten.png</file> <file alias="emblem_conflict_redundant">resources/conflict-redundant.png</file> <file alias="emblem_notes">resources/accessories-text-editor.png</file> + <file alias="network_idle">resources/network-idle.png</file> + <file alias="network_offline">resources/network-offline.png</file> + <file alias="network_error">resources/network-error.png</file> </qresource> </RCC> diff --git a/src/resources/emblem-favorite.png b/src/resources/emblem-favorite.png Binary files differindex b43e09c7..6f003c55 100644 --- a/src/resources/emblem-favorite.png +++ b/src/resources/emblem-favorite.png diff --git a/src/settings.cpp b/src/settings.cpp index 3ee916c0..57fba055 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -165,6 +165,11 @@ bool Settings::getNexusLogin(QString &username, QString &password) const } } +bool Settings::offlineMode() const +{ + return m_Settings.value("Settings/offline_mode", false).toBool(); +} + int Settings::logLevel() const { return m_Settings.value("Settings/log_level", 0).toInt(); @@ -367,6 +372,7 @@ void Settings::query(QWidget *parent) QCheckBox *preferIntegratedCheckBox = dialog.findChild<QCheckBox*>("preferIntegratedBox"); QCheckBox *preferExternalBox = dialog.findChild<QCheckBox*>("preferExternalBox"); QCheckBox *quickInstallerBox = dialog.findChild<QCheckBox*>("quickInstallerBox"); + QCheckBox *offlineBox = dialog.findChild<QCheckBox*>("offlineBox"); QLineEdit *nmmVersionEdit = dialog.findChild<QLineEdit*>("nmmVersionEdit"); QListWidget *pluginsList = dialog.findChild<QListWidget*>("pluginsList"); @@ -447,6 +453,7 @@ void Settings::query(QWidget *parent) preferIntegratedCheckBox->setChecked(m_Settings.value("Settings/prefer_integrated_installer", false).toBool()); preferExternalBox->setChecked(m_Settings.value("Settings/prefer_external_browser", false).toBool()); quickInstallerBox->setChecked(m_Settings.value("Settings/enable_quick_installer", true).toBool()); + offlineBox->setChecked(m_Settings.value("Settings/offline_mode", false).toBool()); nmmVersionEdit->setText(m_Settings.value("Settings/nmm_version", "0.33.1").toString()); logLevelBox->setCurrentIndex(logLevel()); @@ -516,6 +523,7 @@ void Settings::query(QWidget *parent) } m_Settings.setValue("Settings/prefer_integrated_installer", preferIntegratedCheckBox->isChecked()); m_Settings.setValue("Settings/prefer_external_browser", preferExternalBox->isChecked()); + m_Settings.setValue("Settings/offline_mode", offlineBox->isChecked()); m_Settings.setValue("Settings/enable_quick_installer", quickInstallerBox->isChecked()); m_Settings.setValue("Settings/nmm_version", nmmVersionEdit->text()); diff --git a/src/settings.h b/src/settings.h index 34d61a24..38f22b71 100644 --- a/src/settings.h +++ b/src/settings.h @@ -125,6 +125,11 @@ public: bool getNexusLogin(QString &username, QString &password) const; /** + * @return true if the user disabled internet features + */ + bool offlineMode() const; + + /** * @return the configured log level */ int logLevel() const; diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui index 6c54bc62..f248ae29 100644 --- a/src/settingsdialog.ui +++ b/src/settingsdialog.ui @@ -392,6 +392,19 @@ On some systems this will require administrative rights.</string> </widget>
</item>
<item>
+ <widget class="QCheckBox" name="offlineBox">
+ <property name="statusTip">
+ <string>Disable automatic internet features</string>
+ </property>
+ <property name="whatsThis">
+ <string>Disable automatic internet features. This does not affect features that are explicitly invoked by the user (like checking mods for updates, endorsing, opening the web browser)</string>
+ </property>
+ <property name="text">
+ <string>Offline Mode</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
|
