diff options
| author | Tannin <devnull@localhost> | 2013-03-22 18:57:45 +0100 |
|---|---|---|
| committer | Tannin <devnull@localhost> | 2013-03-22 18:57:45 +0100 |
| commit | ec0ea9df8dabe686d3256665c7ed638660309915 (patch) | |
| tree | 39ff86ad325494c3531c159990ee695e84bee469 /src | |
| parent | 24cc3861912cc33235af587d4f4feb538c1054dc (diff) | |
| parent | 74c75e60d67b66a63225239c1f6b1403662857aa (diff) | |
Merge with default
Diffstat (limited to 'src')
| -rw-r--r-- | src/categoriesdialog.cpp | 3 | ||||
| -rw-r--r-- | src/editexecutablesdialog.cpp | 40 | ||||
| -rw-r--r-- | src/loadmechanism.cpp | 3 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 75 | ||||
| -rw-r--r-- | src/mainwindow.h | 6 | ||||
| -rw-r--r-- | src/mainwindow.ui | 21 | ||||
| -rw-r--r-- | src/modinfo.cpp | 3 | ||||
| -rw-r--r-- | src/modlist.cpp | 2 | ||||
| -rw-r--r-- | src/nexusdialog.cpp | 5 | ||||
| -rw-r--r-- | src/organizer.pro | 7 | ||||
| -rw-r--r-- | src/pluginlist.cpp | 2 | ||||
| -rw-r--r-- | src/pluginlistsortproxy.cpp | 262 | ||||
| -rw-r--r-- | src/pluginlistsortproxy.h | 101 | ||||
| -rw-r--r-- | src/profile.cpp | 21 | ||||
| -rw-r--r-- | src/profile.h | 2 | ||||
| -rw-r--r-- | src/shared/inject.cpp | 1 | ||||
| -rw-r--r-- | src/shared/oblivioninfo.cpp | 1 | ||||
| -rw-r--r-- | src/shared/skyriminfo.cpp | 8 | ||||
| -rw-r--r-- | src/shared/skyriminfo.h | 4 | ||||
| -rw-r--r-- | src/shared/util.cpp | 7 | ||||
| -rw-r--r-- | src/shared/util.h | 3 | ||||
| -rw-r--r-- | src/spawn.cpp | 23 | ||||
| -rw-r--r-- | src/version.rc | 4 |
23 files changed, 377 insertions, 227 deletions
diff --git a/src/categoriesdialog.cpp b/src/categoriesdialog.cpp index 21e1a5aa..c7f03740 100644 --- a/src/categoriesdialog.cpp +++ b/src/categoriesdialog.cpp @@ -86,7 +86,8 @@ public: { QLineEdit *edit = qobject_cast<QLineEdit*>(editor); int pos = 0; - if (m_Validator->validate(edit->text(), pos) == QValidator::Acceptable) { + QString editText = edit->text(); + if (m_Validator->validate(editText, pos) == QValidator::Acceptable) { QItemDelegate::setModelData(editor, model, index); } } diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 42f29d83..e0d1994d 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -21,6 +21,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "ui_editexecutablesdialog.h" #include "filedialogmemory.h" #include <QMessageBox> +#include <Shellapi.h> +#include <utility.h> using namespace MOBase; @@ -87,6 +89,7 @@ void EditExecutablesDialog::resetInput() { ui->binaryEdit->setText(""); ui->titleEdit->setText(""); + ui->workingDirEdit->clear(); ui->argumentsEdit->setText(""); ui->closeCheckBox->setChecked(false); } @@ -113,11 +116,42 @@ void EditExecutablesDialog::on_addButton_clicked() void EditExecutablesDialog::on_browseButton_clicked() { QString binaryName = FileDialogMemory::getOpenFileName("editExecutableBinary", this, - tr("Select a binary"), QString(), tr("Executable (%1)").arg("*.exe *.bat")); + tr("Select a binary"), QString(), tr("Executable (%1)").arg("*.exe *.bat *.jar")); - QLineEdit *binaryEdit = findChild<QLineEdit*>("binaryEdit"); + if (binaryName.endsWith(".jar", Qt::CaseInsensitive)) { + QString binaryPath; + { // try to find java automatically + std::wstring binaryNameW = ToWString(binaryName); + WCHAR buffer[MAX_PATH]; + if (::FindExecutableW(binaryNameW.c_str(), NULL, buffer) > (HINSTANCE)32) { + DWORD binaryType = 0UL; + if (!::GetBinaryTypeW(binaryNameW.c_str(), &binaryType)) { + qDebug("failed to determine binary type: %lu", ::GetLastError()); + } else if (binaryType == SCS_32BIT_BINARY) { + binaryPath = ToQString(buffer); + } + } + } + if (binaryPath.isEmpty()) { + QSettings javaReg("HKEY_LOCAL_MACHINE\\Software\\JavaSoft\\Java Runtime Environment", QSettings::NativeFormat); + if (javaReg.contains("CurrentVersion")) { + QString currentVersion = javaReg.value("CurrentVersion").toString(); + binaryPath = javaReg.value(QString("%1/JavaHome").arg(currentVersion)).toString().append("\\bin\\javaw.exe"); + } + } + if (binaryPath.isEmpty()) { + QMessageBox::information(this, tr("Java (32-bit) required"), + tr("MO requires 32-bit java to run this application. If you already have it installed, select javaw.exe " + "from that installation as the binary.")); + } else { + ui->binaryEdit->setText(binaryPath); + } - binaryEdit->setText(QDir::toNativeSeparators(binaryName)); + ui->workingDirEdit->setText(QDir::toNativeSeparators(QFileInfo(binaryName).absolutePath())); + ui->argumentsEdit->setText("-jar \"" + QDir::toNativeSeparators(binaryName) + "\""); + } else { + ui->binaryEdit->setText(QDir::toNativeSeparators(binaryName)); + } } void EditExecutablesDialog::on_browseDirButton_clicked() diff --git a/src/loadmechanism.cpp b/src/loadmechanism.cpp index 8eed460f..426b3763 100644 --- a/src/loadmechanism.cpp +++ b/src/loadmechanism.cpp @@ -169,7 +169,8 @@ void LoadMechanism::deactivateProxyDLL() } } - removeHintFile(QDir(gameDirectory)); + QDir dir(gameDirectory); + removeHintFile(dir); } catch (const std::exception &e) { QMessageBox::critical(NULL, QObject::tr("Failed to deactivate proxy-dll loading"), e.what()); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6c8871ce..67a0de49 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -209,6 +209,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget connect(&m_ModList, SIGNAL(showMessage(QString)), this, SLOT(showMessage(QString))); connect(&m_ModList, SIGNAL(modRenamed(QString,QString)), this, SLOT(modRenamed(QString,QString))); connect(ui->modFilterEdit, SIGNAL(textChanged(QString)), m_ModListSortProxy, SLOT(updateFilter(QString))); + connect(ui->espFilterEdit, SIGNAL(textChanged(QString)), m_PluginListSortProxy, SLOT(updateFilter(QString))); connect(&m_ModList, SIGNAL(modlist_changed(int)), m_ModListSortProxy, SLOT(invalidate())); connect(&m_ModList, SIGNAL(removeSelectedMods()), this, SLOT(removeMod_clicked())); @@ -228,6 +229,9 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget connect(&TutorialManager::instance(), SIGNAL(windowTutorialFinished(QString)), this, SLOT(windowTutorialFinished(QString))); + m_CheckBSATimer.setSingleShot(true); + connect(&m_CheckBSATimer, SIGNAL(timeout()), this, SLOT(checkBSAList())); + m_DirectoryRefresher.moveToThread(&m_RefresherThread); m_RefresherThread.start(); @@ -448,10 +452,12 @@ void MainWindow::createHelpWidget() typedef std::vector<std::pair<int, QAction*> > ActionList; ActionList tutorials; - QDirIterator dirIter("tutorials", QStringList("*.js"), QDir::Files); + + QDirIterator dirIter(QApplication::applicationDirPath() + "/tutorials", QStringList("*.js"), QDir::Files); while (dirIter.hasNext()) { dirIter.next(); QString fileName = dirIter.fileName(); + QFile file(dirIter.filePath()); if (!file.open(QIODevice::ReadOnly)) { qCritical() << "Failed to open " << fileName; @@ -483,6 +489,27 @@ void MainWindow::createHelpWidget() } +void MainWindow::saveArchiveList() +{ + if (m_ArchivesInit) { + QFile archiveFile(m_CurrentProfile->getArchivesFileName()); + if (archiveFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) { + QTreeWidgetItem *item = ui->bsaList->topLevelItem(i); + if ((item != NULL) && (item->checkState(0) == Qt::Checked)) { + archiveFile.write(item->text(0).toUtf8().append("\r\n")); + } + } + } else { + reportError(tr("failed to save archives order, do you have write access " + "to \"%1\"?").arg(m_CurrentProfile->getArchivesFileName())); + } + archiveFile.close(); + } else { + qWarning("archive list not initialised"); + } +} + bool MainWindow::saveCurrentLists() { if (m_DirectoryUpdate) { @@ -508,23 +535,11 @@ bool MainWindow::saveCurrentLists() reportError(tr("failed to save load order: %1").arg(e.what())); } - if (m_ArchivesInit) { - QFile archiveFile(m_CurrentProfile->getArchivesFileName()); - if (archiveFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) { - QTreeWidgetItem *item = ui->bsaList->topLevelItem(i); - if ((item != NULL) && (item->checkState(0) == Qt::Checked)) { - archiveFile.write(item->text(0).toUtf8().append("\r\n")); - } - } - } else { - reportError(tr("failed to save archives order, do you have write access " - "to \"%1\"?").arg(m_CurrentProfile->getArchivesFileName())); - } - archiveFile.close(); - } else { - qWarning("archive list not initialised"); + // ensure the archive list exists + if (!QFile::exists(m_CurrentProfile->getArchivesFileName())) { + saveArchiveList(); } + return true; } @@ -554,7 +569,7 @@ bool MainWindow::addProfile() void MainWindow::hookUpWindowTutorials() { - QDirIterator dirIter("tutorials", QStringList("*.js"), QDir::Files); + QDirIterator dirIter(QApplication::applicationDirPath() + "/tutorials", QStringList("*.js"), QDir::Files); while (dirIter.hasNext()) { dirIter.next(); QString fileName = dirIter.fileName(); @@ -1064,6 +1079,9 @@ void MainWindow::startExeAction() void MainWindow::refreshModList() { + // don't lose changes! + m_CurrentProfile->writeModlistNow(true); + ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure); m_CurrentProfile->refreshModStatus(); @@ -1107,7 +1125,7 @@ void MainWindow::setExecutableIndex(int index) void MainWindow::activateSelectedProfile() { QString profileName = ui->profileBox->currentText(); - qDebug() << "activate profile " << profileName; + qDebug("activate profile \"%s\"", qPrintable(profileName)); QString profileDir = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())) .append("/").append(profileName); delete m_CurrentProfile; @@ -1655,12 +1673,6 @@ void MainWindow::on_tabWidget_currentChanged(int index) } -static QString guessModName(const QString &fileName) -{ - return QFileInfo(fileName).baseName(); -} - - void MainWindow::installMod(const QString &fileName) { bool hasIniTweaks = false; @@ -2680,9 +2692,9 @@ void MainWindow::savePrimaryCategory() void MainWindow::checkModsForUpdates() { + statusBar()->show(); if (NexusInterface::instance()->getAccessManager()->loggedIn()) { m_ModsToUpdate = ModInfo::checkAllForUpdate(this); - statusBar()->show(); m_RefreshProgress->setRange(0, m_ModsToUpdate); } else { QString username, password; @@ -3310,7 +3322,7 @@ int MainWindow::getBinaryExecuteInfo(const QFileInfo &targetInfo, { // try to find java automatically WCHAR buffer[MAX_PATH]; - if (FindExecutableW(targetPathW.c_str(), NULL, buffer) > (HINSTANCE)32) { + if (::FindExecutableW(targetPathW.c_str(), NULL, buffer) > (HINSTANCE)32) { DWORD binaryType = 0UL; if (!::GetBinaryTypeW(targetPathW.c_str(), &binaryType)) { qDebug("failed to determine binary type: %lu", ::GetLastError()); @@ -3694,8 +3706,12 @@ void MainWindow::loginFailed(const QString &message) foreach (QString url, m_PendingDownloads) { downloadRequestedNXM(url); } + m_PendingDownloads.clear(); + } else { + MessageDialog::showMessage(tr("login failed: %1").arg(message), this); + m_PostLoginTasks.clear(); + statusBar()->hide(); } - m_PendingDownloads.clear(); } @@ -3837,7 +3853,8 @@ void MainWindow::on_bsaList_customContextMenuRequested(const QPoint &pos) void MainWindow::on_bsaList_itemChanged(QTreeWidgetItem*, int) { - checkBSAList(); + saveArchiveList(); + m_CheckBSATimer.start(500); } void MainWindow::on_actionProblems_triggered() diff --git a/src/mainwindow.h b/src/mainwindow.h index 1484a1bf..25071127 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -46,6 +46,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "installationmanager.h" #include "selfupdater.h" #include "savegamegamebyro.h" +#include "modlistsortproxy.h" #include "pluginlistsortproxy.h" #include "tutorialcontrol.h" #include "savegameinfowidgetgamebryo.h" @@ -104,6 +105,7 @@ public: void addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, ModInfo::Ptr info); + void saveArchiveList(); public slots: void displayColumnSelection(const QPoint &pos); @@ -171,6 +173,7 @@ private: void installMod(const QString &fileName); void installMod(); bool modifyExecutablesDialog(); + void modOpenNext(); void displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab); void displayModInformation(int row, int tab = 0); void testExtractBSA(int modIndex); @@ -280,6 +283,7 @@ private: QStringList m_ActiveArchives; bool m_DirectoryUpdate; bool m_ArchivesInit; + QTimer m_CheckBSATimer; QTime m_StartTime; SaveGameInfoWidget *m_CurrentSaveView; @@ -397,6 +401,8 @@ private slots: void startExeAction(); + void checkBSAList(); + private slots: // ui slots // actions void on_actionAdd_Profile_triggered(); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 370265da..bcb0f156 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -621,9 +621,18 @@ p, li { white-space: pre-wrap; } <string notr="true">ESPs</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
- <property name="margin">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="topMargin">
<number>6</number>
</property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
@@ -748,6 +757,16 @@ p, li { white-space: pre-wrap; } </attribute>
</widget>
</item>
+ <item>
+ <widget class="MOBase::LineEditClear" name="espFilterEdit">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="placeholderText">
+ <string>Namefilter</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="bsaTab">
diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 28bdf789..31f0278c 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -726,6 +726,9 @@ ModInfoRegular::EConflictType ModInfoRegular::isConflicted() const overwritten = true; break; } + } else if (alternatives.size() == 1) { + // only alternative is data -> no conflict + regular = true; } } } diff --git a/src/modlist.cpp b/src/modlist.cpp index dad77d68..bc838a98 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -146,7 +146,7 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const } else { if ((m_Profile->getModPriority(modIndex) == 0) && (role == Qt::DisplayRole)) { return tr("min"); - } else if ((m_Profile->getModPriority(modIndex) == m_Profile->numRegularMods() - 1) && + } else if ((m_Profile->getModPriority(modIndex) == static_cast<int>(m_Profile->numRegularMods()) - 1) && (role == Qt::DisplayRole)) { return tr("max"); } else { diff --git a/src/nexusdialog.cpp b/src/nexusdialog.cpp index 91c0caf8..6d8e850b 100644 --- a/src/nexusdialog.cpp +++ b/src/nexusdialog.cpp @@ -142,8 +142,8 @@ void NexusDialog::login(const QString &username, const QString &password) { m_AccessManager->login(username, password); - connect(m_AccessManager, SIGNAL(loginSuccessful(bool)), this, SLOT(loginFinished(bool))); - connect(m_AccessManager, SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString))); + connect(m_AccessManager, SIGNAL(loginSuccessful(bool)), this, SLOT(loginFinished(bool)), Qt::UniqueConnection); + connect(m_AccessManager, SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)), Qt::UniqueConnection); } @@ -160,6 +160,7 @@ void NexusDialog::loginFinished(bool necessary) if (necessary && this->isVisible()) { MessageDialog::showMessage(tr("login successful"), this); } + loadNexus(); emit loginSuccessful(necessary); } diff --git a/src/organizer.pro b/src/organizer.pro index 633b2a21..0dbd2427 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -195,6 +195,11 @@ CONFIG(debug, debug|release) { QMAKE_LFLAGS += /DEBUG
}
+QMAKE_CXXFLAGS_WARN_ON -= -W3
+QMAKE_CXXFLAGS_WARN_ON += -W4
+QMAKE_CXXFLAGS += -wd4127 -wd4512 -wd4189
+
+
CONFIG += embed_manifest_exe
# QMAKE_CXXFLAGS += /analyze
@@ -227,7 +232,7 @@ TRANSLATIONS = organizer_de.ts \ PRE_TARGETDEPS += compiler_TSQM_make_all
} else:message(No translation files in project)
-LIBS += -lmo_shared -luibase -lshell32 -lole32 -luser32 -ladvapi32 -lgdi32 -lPsapi -lVersion -lbsatk
+LIBS += -lmo_shared -luibase -lshell32 -lole32 -luser32 -ladvapi32 -lgdi32 -lPsapi -lVersion -lbsatk -lshlwapi
DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS NOMINMAX
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index da31d11c..aa7bf4a3 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -606,7 +606,7 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const case COL_PRIORITY: { if (m_ESPs[index].m_Priority == 0) { return tr("min"); - } else if (m_ESPs[index].m_Priority == m_ESPs.size() - 1) { + } 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); diff --git a/src/pluginlistsortproxy.cpp b/src/pluginlistsortproxy.cpp index 788073ab..5bff24f5 100644 --- a/src/pluginlistsortproxy.cpp +++ b/src/pluginlistsortproxy.cpp @@ -17,127 +17,141 @@ You should have received a copy of the GNU General Public License along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */ -#include "pluginlistsortproxy.h"
-#include "pluginlist.h"
-#include <QMenu>
-#include <QCheckBox>
-#include <QWidgetAction>
-
-
-PluginListSortProxy::PluginListSortProxy(QObject *parent)
- : QSortFilterProxyModel(parent),
- m_SortIndex(0), m_SortOrder(Qt::AscendingOrder)
-{
- m_EnabledColumns.set(PluginList::COL_NAME);
- m_EnabledColumns.set(PluginList::COL_PRIORITY);
- m_EnabledColumns.set(PluginList::COL_MODINDEX);
- this->setDynamicSortFilter(true);
-}
-
-
-unsigned int PluginListSortProxy::getEnabledColumns() const
-{
- unsigned int result = 0;
- for (int i = 0; i <= PluginList::COL_LASTCOLUMN; ++i) {
- if (m_EnabledColumns.test(i)) {
- result |= 1 << i;
- }
- }
- return result;
-}
-
-
-void PluginListSortProxy::setEnabledColumns(unsigned int columns)
-{
- emit layoutAboutToBeChanged();
- for (int i = 0; i <= PluginList::COL_LASTCOLUMN; ++i) {
- m_EnabledColumns.set(i, (columns & (1 << i)) != 0);
- }
- emit layoutChanged();
-}
-
-
-Qt::ItemFlags PluginListSortProxy::flags(const QModelIndex &modelIndex) const
-{
- Qt::ItemFlags flags = sourceModel()->flags(mapToSource(modelIndex));
- if (sortColumn() == PluginList::COL_NAME) {
- flags &= ~Qt::ItemIsDragEnabled;
- }
- return flags;
-}
-
-
-void PluginListSortProxy::displayColumnSelection(const QPoint &pos)
-{
- QMenu menu;
-
- for (int i = 0; i <= PluginList::COL_LASTCOLUMN; ++i) {
- QCheckBox *checkBox = new QCheckBox(&menu);
- checkBox->setText(PluginList::getColumnName(i));
- checkBox->setChecked(m_EnabledColumns.test(i) ? Qt::Checked : Qt::Unchecked);
- QWidgetAction *checkableAction = new QWidgetAction(&menu);
- checkableAction->setDefaultWidget(checkBox);
- menu.addAction(checkableAction);
- }
- menu.exec(pos);
- int i = 0;
-
- emit layoutAboutToBeChanged();
- m_EnabledColumns.reset();
- foreach (const QAction *action, menu.actions()) {
- const QWidgetAction *widgetAction = qobject_cast<const QWidgetAction*>(action);
- if (widgetAction != NULL) {
- const QCheckBox *checkBox = qobject_cast<const QCheckBox*>(widgetAction->defaultWidget());
- if (checkBox != NULL) {
- m_EnabledColumns.set(i, checkBox->checkState() == Qt::Checked);
- }
- }
- ++i;
- }
- emit layoutChanged();
-}
-
-
-bool PluginListSortProxy::lessThan(const QModelIndex &left,
- const QModelIndex &right) const
-{
- PluginList *plugins = qobject_cast<PluginList*>(sourceModel());
- switch (left.column()) {
- case PluginList::COL_NAME: {
- return QString::compare(plugins->getName(left.row()), plugins->getName(right.row()), Qt::CaseInsensitive) < 0;
- } break;
- case PluginList::COL_PRIORITY:
- case PluginList::COL_MODINDEX: {
- return plugins->getPriority(left.row()) < plugins->getPriority(right.row());
- } break;
- default: {
- static bool first = true;
- if (first) {
- qCritical("invalid sort column %d", left.column());
- first = false;
- }
- return plugins->getPriority(left.row()) < plugins->getPriority(right.row());
- } break;
- }
-}
-
-
-bool PluginListSortProxy::dropMimeData(const QMimeData *data, Qt::DropAction action,
- int row, int column, const QModelIndex &parent)
-{
- if ((row == -1) && (column == -1)) {
- return this->sourceModel()->dropMimeData(data, action, -1, -1, mapToSource(parent));
- }
- // in the regular model, when dropping between rows, the row-value passed to
- // the sourceModel is inconsistent between ascending and descending ordering.
- // This should fix that
- if (sortOrder() == Qt::DescendingOrder) {
- --row;
- }
-
- QModelIndex proxyIndex = index(row, column, parent);
- QModelIndex sourceIndex = mapToSource(proxyIndex);
- return this->sourceModel()->dropMimeData(data, action, sourceIndex.row(), sourceIndex.column(),
- sourceIndex.parent());
-}
-
+#include "pluginlistsortproxy.h" +#include "pluginlist.h" +#include <QMenu> +#include <QCheckBox> +#include <QWidgetAction> + + +PluginListSortProxy::PluginListSortProxy(QObject *parent) + : QSortFilterProxyModel(parent), + m_SortIndex(0), m_SortOrder(Qt::AscendingOrder) +{ + m_EnabledColumns.set(PluginList::COL_NAME); + m_EnabledColumns.set(PluginList::COL_PRIORITY); + m_EnabledColumns.set(PluginList::COL_MODINDEX); + this->setDynamicSortFilter(true); +} + + +unsigned int PluginListSortProxy::getEnabledColumns() const +{ + unsigned int result = 0; + for (int i = 0; i <= PluginList::COL_LASTCOLUMN; ++i) { + if (m_EnabledColumns.test(i)) { + result |= 1 << i; + } + } + return result; +} + + +void PluginListSortProxy::setEnabledColumns(unsigned int columns) +{ + emit layoutAboutToBeChanged(); + for (int i = 0; i <= PluginList::COL_LASTCOLUMN; ++i) { + m_EnabledColumns.set(i, (columns & (1 << i)) != 0); + } + emit layoutChanged(); +} + + +Qt::ItemFlags PluginListSortProxy::flags(const QModelIndex &modelIndex) const +{ + Qt::ItemFlags flags = sourceModel()->flags(mapToSource(modelIndex)); + if (sortColumn() == PluginList::COL_NAME) { + flags &= ~Qt::ItemIsDragEnabled; + } + return flags; +} + + +void PluginListSortProxy::displayColumnSelection(const QPoint &pos) +{ + QMenu menu; + + for (int i = 0; i <= PluginList::COL_LASTCOLUMN; ++i) { + QCheckBox *checkBox = new QCheckBox(&menu); + checkBox->setText(PluginList::getColumnName(i)); + checkBox->setChecked(m_EnabledColumns.test(i) ? Qt::Checked : Qt::Unchecked); + QWidgetAction *checkableAction = new QWidgetAction(&menu); + checkableAction->setDefaultWidget(checkBox); + menu.addAction(checkableAction); + } + menu.exec(pos); + int i = 0; + + emit layoutAboutToBeChanged(); + m_EnabledColumns.reset(); + foreach (const QAction *action, menu.actions()) { + const QWidgetAction *widgetAction = qobject_cast<const QWidgetAction*>(action); + if (widgetAction != NULL) { + const QCheckBox *checkBox = qobject_cast<const QCheckBox*>(widgetAction->defaultWidget()); + if (checkBox != NULL) { + m_EnabledColumns.set(i, checkBox->checkState() == Qt::Checked); + } + } + ++i; + } + emit layoutChanged(); +} + + +void PluginListSortProxy::updateFilter(const QString &filter) +{ + m_CurrentFilter = filter; + invalidateFilter(); +} + + +bool PluginListSortProxy::filterAcceptsRow(int row, const QModelIndex&) const +{ + return m_CurrentFilter.isEmpty() || + sourceModel()->data(sourceModel()->index(row, 0)).toString().contains(m_CurrentFilter, Qt::CaseInsensitive); +} + + +bool PluginListSortProxy::lessThan(const QModelIndex &left, + const QModelIndex &right) const +{ + PluginList *plugins = qobject_cast<PluginList*>(sourceModel()); + switch (left.column()) { + case PluginList::COL_NAME: { + return QString::compare(plugins->getName(left.row()), plugins->getName(right.row()), Qt::CaseInsensitive) < 0; + } break; + case PluginList::COL_PRIORITY: + case PluginList::COL_MODINDEX: { + return plugins->getPriority(left.row()) < plugins->getPriority(right.row()); + } break; + default: { + static bool first = true; + if (first) { + qCritical("invalid sort column %d", left.column()); + first = false; + } + return plugins->getPriority(left.row()) < plugins->getPriority(right.row()); + } break; + } +} + + +bool PluginListSortProxy::dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent) +{ + if ((row == -1) && (column == -1)) { + return this->sourceModel()->dropMimeData(data, action, -1, -1, mapToSource(parent)); + } + // in the regular model, when dropping between rows, the row-value passed to + // the sourceModel is inconsistent between ascending and descending ordering. + // This should fix that + if (sortOrder() == Qt::DescendingOrder) { + --row; + } + + QModelIndex proxyIndex = index(row, column, parent); + QModelIndex sourceIndex = mapToSource(proxyIndex); + return this->sourceModel()->dropMimeData(data, action, sourceIndex.row(), sourceIndex.column(), + sourceIndex.parent()); +} + diff --git a/src/pluginlistsortproxy.h b/src/pluginlistsortproxy.h index 7397ff7c..d5c71858 100644 --- a/src/pluginlistsortproxy.h +++ b/src/pluginlistsortproxy.h @@ -17,52 +17,55 @@ You should have received a copy of the GNU General Public License along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef PLUGINLISTSORTPROXY_H
-#define PLUGINLISTSORTPROXY_H
-
-
-#include <bitset>
-#include <QSortFilterProxyModel>
-#include "pluginlist.h"
-
-
-class PluginListSortProxy : public QSortFilterProxyModel
-{
- Q_OBJECT
-public:
-
- enum ESorting {
- SORT_ASCENDING,
- SORT_DESCENDING
- };
-
-public:
-
- explicit PluginListSortProxy(QObject *parent = 0);
-
- unsigned int getEnabledColumns() const;
-
- void setEnabledColumns(unsigned int columns);
-
- virtual Qt::ItemFlags flags(const QModelIndex &modelIndex) const;
-
- virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
-
-public slots:
-
- void displayColumnSelection(const QPoint &pos);
-
-protected:
-
- virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
-
-private:
-
- int m_SortIndex;
- Qt::SortOrder m_SortOrder;
-
- std::bitset<PluginList::COL_LASTCOLUMN + 1> m_EnabledColumns;
-
-};
-
-#endif // PLUGINLISTSORTPROXY_H
+#ifndef PLUGINLISTSORTPROXY_H +#define PLUGINLISTSORTPROXY_H + + +#include <bitset> +#include <QSortFilterProxyModel> +#include "pluginlist.h" + + +class PluginListSortProxy : public QSortFilterProxyModel +{ + Q_OBJECT +public: + + enum ESorting { + SORT_ASCENDING, + SORT_DESCENDING + }; + +public: + + explicit PluginListSortProxy(QObject *parent = 0); + + unsigned int getEnabledColumns() const; + + void setEnabledColumns(unsigned int columns); + + virtual Qt::ItemFlags flags(const QModelIndex &modelIndex) const; + + virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + +public slots: + + void displayColumnSelection(const QPoint &pos); + void updateFilter(const QString &filter); + +protected: + + virtual bool filterAcceptsRow(int row, const QModelIndex &parent) const; + virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + +private: + + int m_SortIndex; + Qt::SortOrder m_SortOrder; + + std::bitset<PluginList::COL_LASTCOLUMN + 1> m_EnabledColumns; + QString m_CurrentFilter; + +}; + +#endif // PLUGINLISTSORTPROXY_H diff --git a/src/profile.cpp b/src/profile.cpp index 62ac943e..97bd06b9 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -136,8 +136,10 @@ void Profile::cancelWriteModlist() const } -void Profile::writeModlistNow() const +void Profile::writeModlistNow(bool onlyOnTimer) const { + if (onlyOnTimer && !m_SaveTimer->isActive()) return; + m_SaveTimer->stop(); if (!m_Directory.exists()) return; #pragma message("right now, this is doing unnecessary saves. Need a flag that says that mod priority, enabled-state or name of a mod has changed") @@ -225,11 +227,6 @@ void Profile::createTweakedIniFile() void Profile::refreshModStatus() { - // don't lose changes! - if (m_SaveTimer->isActive()) { - writeModlistNow(); - } - QFile file(getModlistFileName()); if (!file.exists()) { throw MyException(QObject::tr("failed to find \"%1\"").arg(getModlistFileName())); @@ -600,11 +597,15 @@ void Profile::deactivateInvalidation() const } } + // just to be safe... + ::SetFileAttributesW(iniFileName.c_str(), FILE_ATTRIBUTE_NORMAL); + if (!::WritePrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), ToWString(archives.join(", ").toUtf8()).c_str(), iniFileName.c_str()) || !::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFileName.c_str()) || !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFileName.c_str())) { - throw windows_error("failed to modify ini file"); + QString errorMessage = tr("failed to modify \"%1\"").arg(ToQString(iniFileName)); + throw windows_error(errorMessage.toUtf8().constData()); } } } @@ -627,11 +628,15 @@ void Profile::activateInvalidation(const QString& dataDirectory) const archives.insert(0, invalidationBSA); } + // just to be safe... + ::SetFileAttributesW(iniFileName.c_str(), FILE_ATTRIBUTE_NORMAL); + if (!::WritePrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), ToWString(archives.join(", ").toUtf8()).c_str(), iniFileName.c_str()) || !::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFileName.c_str()) || !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFileName.c_str())) { - throw windows_error("failed to modify ini file"); + QString errorMessage = tr("failed to modify \"%1\"").arg(ToQString(iniFileName)); + throw windows_error(errorMessage.toUtf8().constData()); } QString bsaFile = dataDirectory + "/" + invalidationBSA; diff --git a/src/profile.h b/src/profile.h index 52b6a5eb..9c678a23 100644 --- a/src/profile.h +++ b/src/profile.h @@ -275,7 +275,7 @@ signals: public slots: - void writeModlistNow() const; + void writeModlistNow(bool onlyOnTimer = false) const; private: diff --git a/src/shared/inject.cpp b/src/shared/inject.cpp index 9fea7fc8..5a111c4a 100644 --- a/src/shared/inject.cpp +++ b/src/shared/inject.cpp @@ -136,6 +136,7 @@ void injectDLL(HANDLE processHandle, HANDLE threadHandle, const std::string &dll (written != sizeof(stubLocal))) {
throw windows_error("failed to write stub to target process");
}
+
// finally, make the stub the new next thing for the thread to execute
threadContext.Eip = (ULONG)stubRemote;
if (::SetThreadContext(threadHandle, &threadContext) == 0) {
diff --git a/src/shared/oblivioninfo.cpp b/src/shared/oblivioninfo.cpp index 1c714072..73e841a7 100644 --- a/src/shared/oblivioninfo.cpp +++ b/src/shared/oblivioninfo.cpp @@ -134,7 +134,6 @@ void OblivionInfo::createProfile(const std::wstring &directory, bool useDefaults if (!FileExists(target.str())) {
std::wostringstream source;
- source << getMyGamesDirectory() << L"\\Oblivion\\oblivion.ini";
if (useDefaults) {
source << getGameDirectory() << L"\\oblivion_default.ini";
} else {
diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp index 6302cef3..1c13effb 100644 --- a/src/shared/skyriminfo.cpp +++ b/src/shared/skyriminfo.cpp @@ -27,6 +27,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "error_report.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
+#include <Shlwapi.h>
#include <boost/assign.hpp>
namespace MOShared {
@@ -36,6 +37,11 @@ SkyrimInfo::SkyrimInfo(const std::wstring &omoDirectory, const std::wstring &gam : GameInfo(omoDirectory, gameDirectory)
{
identifyMyGamesDirectory(L"skyrim");
+
+ wchar_t appDataPath[MAX_PATH];
+ if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appDataPath))) {
+ m_AppData = appDataPath;
+ }
}
bool SkyrimInfo::identifyGame(const std::wstring &searchPath)
@@ -259,7 +265,7 @@ bool SkyrimInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPa }
if ((_wcsicmp(fileName, L"plugins.txt") == 0) &&
- (wcsstr(fullPath, L"AppData") != NULL)){
+ (m_AppData.empty() || (StrStrIW(fullPath, m_AppData.c_str()) != NULL))) {
return true;
}
diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h index b12a5d58..024d0395 100644 --- a/src/shared/skyriminfo.h +++ b/src/shared/skyriminfo.h @@ -97,6 +97,10 @@ private: static bool identifyGame(const std::wstring &searchPath);
+private:
+
+ std::wstring m_AppData;
+
};
} // namespace MOShared
diff --git a/src/shared/util.cpp b/src/shared/util.cpp index a6378a74..e61ae8a6 100644 --- a/src/shared/util.cpp +++ b/src/shared/util.cpp @@ -79,6 +79,13 @@ std::string &ToLower(std::string &text) return text;
}
+std::string ToLower(const std::string &text)
+{
+ std::string temp = text;
+
+ std::transform(temp.begin(), temp.end(), temp.begin(), tolower);
+ return temp;
+}
std::wstring &ToLower(std::wstring &text)
{
diff --git a/src/shared/util.h b/src/shared/util.h index 9c59f6db..80983cb0 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -39,8 +39,9 @@ std::string ToString(const std::wstring &source, bool utf8); std::wstring ToWString(const std::string &source, bool utf8);
std::string &ToLower(std::string &text);
-std::wstring &ToLower(std::wstring &text);
+std::string ToLower(const std::string &text);
+std::wstring &ToLower(std::wstring &text);
std::wstring ToLower(const std::wstring &text);
VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName);
diff --git a/src/spawn.cpp b/src/spawn.cpp index 39bd2af9..e83c8e21 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -20,6 +20,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "spawn.h" #include "report.h" #include "utility.h" +#include <boost/scoped_array.hpp> #include <gameinfo.h> #include <inject.h> #include <appconfig.h> @@ -31,6 +32,8 @@ using namespace MOBase; using namespace MOShared; +static const int BUFSIZE = 4096; + bool spawn(LPCWSTR binary, LPCWSTR arguments, LPCWSTR currentDirectory, bool suspended, HANDLE& processHandle, HANDLE& threadHandle) { STARTUPINFO si; @@ -44,7 +47,25 @@ bool spawn(LPCWSTR binary, LPCWSTR arguments, LPCWSTR currentDirectory, bool sus } else { commandLine = new wchar_t[length]; _snwprintf(commandLine, length, L"\"%ls\"", binary); + } + QString moPath = QCoreApplication::applicationDirPath(); + + boost::scoped_array<TCHAR> oldPath(new TCHAR[BUFSIZE]); + DWORD offset = ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), BUFSIZE); + if (offset > BUFSIZE) { + oldPath.reset(new TCHAR[offset]); + ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), offset); + } + + { + boost::scoped_array<TCHAR> newPath(new TCHAR[offset + moPath.length() + 2]); + _tcsncpy(newPath.get(), oldPath.get(), offset - 1); + newPath.get()[offset - 1] = L'\0'; + _tcsncat(newPath.get(), TEXT(";"), 1); + _tcsncat(newPath.get(), ToWString(QDir::toNativeSeparators(moPath)).c_str(), moPath.length()); + + ::SetEnvironmentVariable(TEXT("PATH"), newPath.get()); } PROCESS_INFORMATION pi; @@ -58,6 +79,8 @@ bool spawn(LPCWSTR binary, LPCWSTR arguments, LPCWSTR currentDirectory, bool sus &si, &pi // startup and process information ); + ::SetEnvironmentVariable(TEXT("PATH"), oldPath.get()); + delete [] commandLine; if (!success) { diff --git a/src/version.rc b/src/version.rc index 23f7b6e3..9f083ed4 100644 --- a/src/version.rc +++ b/src/version.rc @@ -1,7 +1,7 @@ #include "Winver.h"
-#define VER_FILEVERSION 0,12,8,0
-#define VER_FILEVERSION_STR 0,12,8,0
+#define VER_FILEVERSION 0,12,9,0
+#define VER_FILEVERSION_STR 0,12,9,0
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
|
