diff options
Diffstat (limited to 'src')
33 files changed, 298 insertions, 251 deletions
diff --git a/src/categories.cpp b/src/categories.cpp index 1d5fdefe..0b201dcf 100644 --- a/src/categories.cpp +++ b/src/categories.cpp @@ -19,7 +19,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "categories.h"
#include <utility.h>
-#include "report.h"
+#include <report.h>
#include <gameinfo.h>
#include <QObject>
#include <QFile>
diff --git a/src/downloadlistsortproxy.cpp b/src/downloadlistsortproxy.cpp index 59d7bce6..deddc0cf 100644 --- a/src/downloadlistsortproxy.cpp +++ b/src/downloadlistsortproxy.cpp @@ -60,7 +60,7 @@ bool DownloadListSortProxy::filterAcceptsRow(int source_row, const QModelIndex&) if (m_CurrentFilter.length() == 0) {
return true;
} else if (source_row < m_Manager->numTotalDownloads()) {
- return m_Manager->getFileName(source_row).contains(m_CurrentFilter, Qt::CaseInsensitive);
+ return sourceModel()->index(source_row, 0).data().toString().contains(m_CurrentFilter, Qt::CaseInsensitive);
} else {
return false;
}
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index b5bc8148..81732f4d 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -18,7 +18,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */
#include "downloadmanager.h"
-#include "report.h"
#include "nxmurl.h"
#include "nexusinterface.h"
#include "nxmaccessmanager.h"
@@ -30,6 +29,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "selectiondialog.h"
#include "bbcode.h"
#include <utility.h>
+#include <report.h>
#include <QTimer>
#include <QFileInfo>
#include <QRegExp>
diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index da207f93..e84e1112 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -241,6 +241,9 @@ void EditExecutablesDialog::on_closeButton_clicked() return; } else if (res == QMessageBox::Yes) { saveExecutable(); + // the executable list returned to callers is generated from the user data in the widgets, + // NOT the list we just saved + refreshExecutablesWidget(); } } this->accept(); @@ -284,8 +287,8 @@ void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex &cur ui->closeCheckBox->setToolTip(tr("If checked, MO will be closed once the specified executable is run.")); } ui->removeButton->setEnabled(selectedExecutable.m_Custom); - ui->overwriteAppIDBox->setChecked(selectedExecutable.m_SteamAppID != 0); - if (selectedExecutable.m_SteamAppID != 0) { + ui->overwriteAppIDBox->setChecked(!selectedExecutable.m_SteamAppID.isEmpty()); + if (!selectedExecutable.m_SteamAppID.isEmpty()) { ui->appIDOverwriteEdit->setText(selectedExecutable.m_SteamAppID); } else { ui->appIDOverwriteEdit->clear(); diff --git a/src/executableslist.cpp b/src/executableslist.cpp index c4766fa8..1852b0ad 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -21,6 +21,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <gameinfo.h>
#include <QFileInfo>
#include <QDir>
+#include <QDebug>
#include "utility.h"
#include <algorithm>
@@ -181,18 +182,17 @@ void ExecutablesList::addExecutable(const QString &title, const QString &executa auto existingExe = findExe(title);
if (existingExe != m_Executables.end()) {
- //A note: If this isn't customised, we want to leave
- //the directory and so on WELL alone
+ existingExe->m_Title = title;
+ existingExe->m_Custom = custom;
+ existingExe->m_CloseMO = closeMO;
+ existingExe->m_Toolbar = toolbar;
if (custom) {
+ // for pre-configured executables don't overwrite settings we didn't store
existingExe->m_BinaryInfo = file;
existingExe->m_Arguments = arguments;
existingExe->m_WorkingDirectory = workingDirectory;
existingExe->m_SteamAppID = steamAppID;
}
- existingExe->m_Title = title;
- existingExe->m_CloseMO = closeMO;
- existingExe->m_Custom = custom;
- existingExe->m_Toolbar = toolbar;
if (pos >= 0) {
Executable temp = *existingExe;
m_Executables.erase(existingExe);
diff --git a/src/helper.cpp b/src/helper.cpp index 1f072bd9..41784fe5 100644 --- a/src/helper.cpp +++ b/src/helper.cpp @@ -18,8 +18,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */
#include "helper.h"
-#include "report.h"
#include "utility.h"
+#include <report.h>
#include <LMCons.h>
#define WIN32_LEAN_AND_MEAN
@@ -27,6 +27,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QDir>
+using MOBase::reportError;
+
namespace Helper {
diff --git a/src/icondelegate.cpp b/src/icondelegate.cpp index 794ac7f3..e502dc69 100644 --- a/src/icondelegate.cpp +++ b/src/icondelegate.cpp @@ -45,10 +45,17 @@ void IconDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, painter->translate(option.rect.topLeft());
for (const QString &iconId : icons) {
+ if (iconId.isEmpty()) {
+ x += iconWidth + 4;
+ continue;
+ }
QPixmap icon;
QString fullIconId = QString("%1_%2").arg(iconId).arg(iconWidth);
if (!QPixmapCache::find(fullIconId, &icon)) {
icon = QIcon(iconId).pixmap(iconWidth, iconWidth);
+ if (icon.isNull()) {
+ qWarning("failed to load icon %s", qPrintable(iconId));
+ }
QPixmapCache::insert(fullIconId, icon);
}
painter->drawPixmap(x, 2, iconWidth, iconWidth, icon);
diff --git a/src/logbuffer.cpp b/src/logbuffer.cpp index fdfce6c5..b58ef1de 100644 --- a/src/logbuffer.cpp +++ b/src/logbuffer.cpp @@ -18,13 +18,16 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */
#include "logbuffer.h"
-#include "report.h"
+#include <report.h>
#include <QMutexLocker>
#include <QFile>
#include <QIcon>
#include <QDateTime>
#include <Windows.h>
+
+using MOBase::reportError;
+
QScopedPointer<LogBuffer> LogBuffer::s_Instance;
QMutex LogBuffer::s_Mutex;
diff --git a/src/main.cpp b/src/main.cpp index 0253ad4a..cbf561ed 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,7 +45,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <scopeguard.h>
#include <stdexcept>
#include "mainwindow.h"
-#include "report.h"
+#include <report.h>
#include "modlist.h"
#include "profile.h"
#include "gameinfo.h"
@@ -301,7 +301,7 @@ static bool HaveWriteAccess(const std::wstring &path) }
-QString determineProfile(QStringList arguments, const QSettings &settings)
+QString determineProfile(QStringList &arguments, const QSettings &settings)
{
QString selectedProfileName = QString::fromUtf8(settings.value("selected_profile", "").toByteArray());
{ // see if there is a profile on the command line
@@ -347,11 +347,6 @@ int main(int argc, char *argv[]) );
application.setProperty("dataPath", dataPath);
-#if QT_VERSION >= 0x050000
- qDebug("ssl support: %d", QSslSocket::supportsSsl());
-#endif
-
- qDebug("data path: %s", qPrintable(dataPath));
if (!QDir(dataPath).exists()) {
if (!QDir().mkpath(dataPath)) {
qCritical("failed to create %s", qPrintable(dataPath));
@@ -378,6 +373,10 @@ int main(int argc, char *argv[]) LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
+#if QT_VERSION >= 0x050000
+ qDebug("ssl support: %d", QSslSocket::supportsSsl());
+#endif
+
qDebug("Working directory: %s", qPrintable(QDir::toNativeSeparators(QDir::currentPath())));
qDebug("MO at: %s", qPrintable(QDir::toNativeSeparators(application.applicationDirPath())));
QPixmap pixmap(":/MO/gui/splash");
@@ -399,12 +398,12 @@ int main(int argc, char *argv[]) ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), offset);
}
- std::tstring newPath(oldPath.get());
- newPath += TEXT(";");
+ std::wstring newPath(oldPath.get());
+ newPath += L";";
newPath += ToWString(QDir::toNativeSeparators(QCoreApplication::applicationDirPath())).c_str();
- newPath += TEXT("\\dlls");
+ newPath += L"\\dlls";
- ::SetEnvironmentVariable(TEXT("PATH"), newPath.c_str());
+ ::SetEnvironmentVariableW(L"PATH", newPath.c_str());
}
registerMetaTypes();
@@ -462,8 +461,10 @@ int main(int argc, char *argv[]) } else {
gamePath = QDir::cleanPath(selection.getChoiceData().toString());
if (gamePath.isEmpty()) {
- gamePath = QFileDialog::getExistingDirectory(nullptr, QObject::tr("Please select the game to manage"), QString(),
- QFileDialog::ShowDirsOnly);
+ gamePath = QFileDialog::getExistingDirectory(
+ nullptr, QObject::tr("Please select the game to manage"), QString(),
+ QFileDialog::ShowDirsOnly);
+ qDebug() << "manually selected path " << gamePath;
}
}
} else {
@@ -481,7 +482,7 @@ int main(int argc, char *argv[]) settings.setValue("gamePath", gamePath.toUtf8().constData());
}
- organizer.setManagedGame(ToQString(GameInfo::instance().getGameName()));
+ organizer.setManagedGame(ToQString(GameInfo::instance().getGameName()), gamePath);
organizer.createDefaultProfile();
@@ -510,7 +511,6 @@ int main(int argc, char *argv[]) organizer.updateExecutablesList(settings);
-
QString selectedProfileName = determineProfile(arguments, settings);
organizer.setCurrentProfile(selectedProfileName);
@@ -532,7 +532,8 @@ int main(int argc, char *argv[]) }
qDebug("initializing tutorials");
- TutorialManager::init(qApp->applicationDirPath() + "/" + QString::fromStdWString(AppConfig::tutorialsPath()) + "/");
+ TutorialManager::init(qApp->applicationDirPath() + "/" + QString::fromStdWString(AppConfig::tutorialsPath()) + "/",
+ &organizer);
if (!application.setStyleFile(settings.value("Settings/style", "").toString())) {
// disable invalid stylesheet
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 578d4419..7dba6c72 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1230,11 +1230,8 @@ void MainWindow::refreshSavesIfOpen() }
}
-
-void MainWindow::refreshSaveList()
+QDir MainWindow::currentSavesDir() const
{
- ui->savegameList->clear();
-
QDir savesDir;
if (m_OrganizerCore.currentProfile()->localSavesEnabled()) {
savesDir.setPath(m_OrganizerCore.currentProfile()->absolutePath() + "/saves");
@@ -1246,13 +1243,35 @@ void MainWindow::refreshSaveList() savesDir.setPath(m_OrganizerCore.managedGame()->documentsDirectory().absoluteFilePath(QString::fromWCharArray(path)));
}
+ return savesDir;
+}
+
+void MainWindow::startMonitorSaves()
+{
+ stopMonitorSaves();
+
+ QDir savesDir = currentSavesDir();
+
+ m_SavesWatcher.addPath(savesDir.absolutePath());
+}
+
+void MainWindow::stopMonitorSaves()
+{
if (m_SavesWatcher.directories().length() > 0) {
m_SavesWatcher.removePaths(m_SavesWatcher.directories());
}
- m_SavesWatcher.addPath(savesDir.absolutePath());
+}
+
+void MainWindow::refreshSaveList()
+{
+ ui->savegameList->clear();
+
+ startMonitorSaves(); // re-starts monitoring
QStringList filters;
filters << QString("*.") + m_OrganizerCore.managedGame()->savegameExtension();
+
+ QDir savesDir = currentSavesDir();
savesDir.setNameFilters(filters);
QFileInfoList files = savesDir.entryInfoList(QDir::Files, QDir::Time);
@@ -1677,7 +1696,7 @@ bool MainWindow::modifyExecutablesDialog() try {
EditExecutablesDialog dialog(*m_OrganizerCore.executablesList());
if (dialog.exec() == QDialog::Accepted) {
- m_OrganizerCore.setExecutablesDialog(dialog.getExecutablesList());
+ m_OrganizerCore.setExecutablesList(dialog.getExecutablesList());
result = true;
}
refreshExecutablesList();
@@ -1746,7 +1765,11 @@ void MainWindow::on_actionAdd_Profile_triggered() bool repeat = true;
while (repeat) {
ProfilesDialog profilesDialog(m_GamePath, this);
+ // workaround: need to disable monitoring of the saves directory, otherwise the active
+ // profile directory is locked
+ stopMonitorSaves();
profilesDialog.exec();
+ refreshSaveList(); // since the save list may now be outdated we have to refresh it completely
if (refreshProfiles() && !profilesDialog.failed()) {
repeat = false;
}
@@ -2015,7 +2038,6 @@ void MainWindow::addCategoryFilters(QTreeWidgetItem *root, const std::set<int> & }
}
-
void MainWindow::refreshFilters()
{
QItemSelection currentSelection = ui->modList->selectionModel()->selection();
@@ -2039,11 +2061,10 @@ void MainWindow::refreshFilters() addFilterItem(nullptr, tr("<Not Endorsed>"), CategoryFactory::CATEGORY_SPECIAL_NOTENDORSED, ModListSortProxy::TYPE_SPECIAL);
addContentFilters();
-
std::set<int> categoriesUsed;
for (unsigned int modIdx = 0; modIdx < ModInfo::getNumMods(); ++modIdx) {
ModInfo::Ptr modInfo = ModInfo::getByIndex(modIdx);
- BOOST_FOREACH (int categoryID, modInfo->getCategories()) {
+ for (int categoryID : modInfo->getCategories()) {
int currentID = categoryID;
// also add parents so they show up in the tree
while (currentID != 0) {
@@ -2062,7 +2083,11 @@ void MainWindow::refreshFilters() }
}
ui->modList->selectionModel()->select(currentSelection, QItemSelectionModel::Select);
- QModelIndexList matchList = ui->modList->model()->match(ui->modList->model()->index(0, 0), Qt::DisplayRole, currentIndexName);
+ QModelIndexList matchList;
+ if (currentIndexName.isValid()) {
+ matchList = ui->modList->model()->match(ui->modList->model()->index(0, 0), Qt::DisplayRole, currentIndexName);
+ }
+
if (matchList.size() > 0) {
ui->modList->setCurrentIndex(matchList.at(0));
}
@@ -4408,9 +4433,14 @@ void MainWindow::on_bossButton_clicked() // if the game specifies load order by file time, our own load order file needs to be removed because it's outdated.
// refreshESPList will then use the file time as the load order.
if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) {
+ qDebug("removing loadorder.txt");
QFile::remove(m_OrganizerCore.currentProfile()->getLoadOrderFileName());
}
m_OrganizerCore.refreshESPList();
+ if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) {
+ // the load order should have been retrieved from file time, now save it to our own format
+ m_OrganizerCore.savePluginList();
+ }
}
}
diff --git a/src/mainwindow.h b/src/mainwindow.h index ddea1010..7e59a7b0 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -249,6 +249,11 @@ private: void scheduleUpdateButton();
+ QDir currentSavesDir() const;
+
+ void startMonitorSaves();
+ void stopMonitorSaves();
+
private:
static const char *PATTERN_BACKUP_GLOB;
diff --git a/src/moapplication.cpp b/src/moapplication.cpp index 806c3142..07e6ac39 100644 --- a/src/moapplication.cpp +++ b/src/moapplication.cpp @@ -18,7 +18,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */
#include "moapplication.h"
-#include "report.h"
+#include <report.h>
#include <utility.h>
#include <appconfig.h>
#include <QFile>
@@ -36,6 +36,9 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QDebug>
+using MOBase::reportError;
+
+
class ProxyStyle : public QProxyStyle {
public:
ProxyStyle(QStyle *baseStyle = 0)
diff --git a/src/modflagicondelegate.cpp b/src/modflagicondelegate.cpp index e4c11bc5..d66c3ac5 100644 --- a/src/modflagicondelegate.cpp +++ b/src/modflagicondelegate.cpp @@ -41,8 +41,8 @@ QString ModFlagIconDelegate::getFlagIcon(ModInfo::EFlag flag) const {
switch (flag) {
case ModInfo::FLAG_BACKUP: return ":/MO/gui/emblem_backup";
- case ModInfo::FLAG_INVALID: return ":/MO/gui/emblem_problem";
- case ModInfo::FLAG_NOTENDORSED: return "MO/gui/emblem_notendorsed";
+ case ModInfo::FLAG_INVALID: return ":/MO/gui/problem";
+ case ModInfo::FLAG_NOTENDORSED: return ":/MO/gui/emblem_notendorsed";
case ModInfo::FLAG_NOTES: return ":/MO/gui/emblem_notes";
case ModInfo::FLAG_CONFLICT_OVERWRITE: return ":/MO/gui/emblem_conflict_overwrite";
case ModInfo::FLAG_CONFLICT_OVERWRITTEN: return ":/MO/gui/emblem_conflict_overwritten";
diff --git a/src/modlist.cpp b/src/modlist.cpp index 863e85fc..4475e021 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -19,7 +19,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "modlist.h"
-#include "report.h"
#include "messagedialog.h"
#include "installationtester.h"
#include "qtgroupingproxy.h"
@@ -27,6 +26,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <gameinfo.h>
#include <appconfig.h>
#include <utility.h>
+#include <report.h>
#include <QFileInfo>
#include <QDir>
#include <QDirIterator>
@@ -434,7 +434,6 @@ bool ModList::renameMod(int index, const QString &newName) return true;
}
-
bool ModList::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (m_Profile == nullptr) return false;
@@ -523,9 +522,6 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role) }
-
-
-
QVariant ModList::headerData(int section, Qt::Orientation orientation,
int role) const
{
@@ -846,7 +842,6 @@ bool ModList::dropMimeData(const QMimeData *mimeData, Qt::DropAction action, int } else {
return dropMod(mimeData, row, parent);
}
-
}
void ModList::removeRowForce(int row, const QModelIndex &parent)
diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index d649996f..b40b4144 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -338,7 +338,7 @@ bool ModListSortProxy::filterAcceptsRow(int row, const QModelIndex &parent) cons qDebug("invalid index");
return false;
}
- if (idx.isValid() && sourceModel()->hasChildren(idx)) {
+ if (sourceModel()->hasChildren(idx)) {
for (int i = 0; i < sourceModel()->rowCount(idx); ++i) {
if (filterAcceptsRow(i, idx)) {
return true;
diff --git a/src/organizer.pro b/src/organizer.pro index e7177af3..8424ac3f 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -31,7 +31,6 @@ SOURCES += \ savegameinfowidget.cpp \
savegamegamebryo.cpp \
savegame.cpp \
- report.cpp \
queryoverwritedialog.cpp \
profilesdialog.cpp \
profile.cpp \
@@ -111,7 +110,6 @@ HEADERS += \ savegameinfowidget.h \
savegamegamebyro.h \
savegame.h \
- report.h \
queryoverwritedialog.h \
profilesdialog.h \
profile.h \
@@ -366,4 +364,5 @@ OTHER_FILES += \ DISTFILES += \
tutorials/tutorial_primer_main.js \
tutorials/Tooltip.qml \
- tutorials/TooltipArea.qml
+ tutorials/TooltipArea.qml \
+ SConscript
diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 30d38be3..38b01563 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -7,7 +7,6 @@ #include "filedialogmemory.h"
#include "lockeddialog.h"
#include "modinfodialog.h"
-#include "report.h"
#include "spawn.h"
#include "safewritefile.h"
#include "syncoverwritedialog.h"
@@ -18,6 +17,7 @@ #include <scopeguard.h>
#include <utility.h>
#include <appconfig.h>
+#include <report.h>
#include <questionboxmemory.h>
#include <QNetworkInterface>
#include <QMessageBox>
@@ -188,63 +188,81 @@ OrganizerCore::~OrganizerCore() delete m_DirectoryStructure;
}
-void OrganizerCore::storeSettings()
+QString OrganizerCore::commitSettings(const QString &iniFile)
{
- QString iniFile = qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::iniFileName());
- shellCopy(iniFile, iniFile + ".new", true, qApp->activeWindow());
-
- QSettings::Status result = QSettings::NoError;
- {
- QSettings settings(iniFile + ".new", QSettings::IniFormat);
- if (m_UserInterface != nullptr) {
- m_UserInterface->storeSettings(settings);
- }
- if (m_CurrentProfile != nullptr) {
- settings.setValue("selected_profile", m_CurrentProfile->name().toUtf8().constData());
+ if (!shellRename(iniFile + ".new", iniFile, true, qApp->activeWindow())) {
+ DWORD err = ::GetLastError();
+ // make a second attempt using qt functions but if that fails print the error from the first attempt
+ if (!renameFile(iniFile + ".new", iniFile)) {
+ return windowsErrorString(err);
}
- settings.setValue("ask_for_nexuspw", m_AskForNexusPW);
+ }
+ return QString();
+}
- settings.remove("customExecutables");
- settings.beginWriteArray("customExecutables");
- std::vector<Executable>::const_iterator current, end;
- m_ExecutablesList.getExecutables(current, end);
- int count = 0;
- for (; current != end; ++current) {
- const Executable &item = *current;
- settings.setArrayIndex(count++);
- settings.setValue("title", item.m_Title);
- settings.setValue("custom", item.m_Custom);
- settings.setValue("toolbar", item.m_Toolbar);
- if (item.m_Custom) {
- settings.setValue("binary", item.m_BinaryInfo.absoluteFilePath());
- settings.setValue("arguments", item.m_Arguments);
- settings.setValue("workingDirectory", item.m_WorkingDirectory);
- settings.setValue("closeOnStart", item.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE);
- settings.setValue("steamAppID", item.m_SteamAppID);
- }
+QSettings::Status OrganizerCore::storeSettings(const QString &fileName)
+{
+ QSettings settings(fileName, QSettings::IniFormat);
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->storeSettings(settings);
+ }
+ if (m_CurrentProfile != nullptr) {
+ settings.setValue("selected_profile", m_CurrentProfile->name().toUtf8().constData());
+ }
+ settings.setValue("ask_for_nexuspw", m_AskForNexusPW);
+
+ settings.remove("customExecutables");
+ settings.beginWriteArray("customExecutables");
+ std::vector<Executable>::const_iterator current, end;
+ m_ExecutablesList.getExecutables(current, end);
+ int count = 0;
+ for (; current != end; ++current) {
+ const Executable &item = *current;
+ settings.setArrayIndex(count++);
+ settings.setValue("title", item.m_Title);
+ settings.setValue("custom", item.m_Custom);
+ settings.setValue("toolbar", item.m_Toolbar);
+ if (item.m_Custom) {
+ settings.setValue("binary", item.m_BinaryInfo.absoluteFilePath());
+ settings.setValue("arguments", item.m_Arguments);
+ settings.setValue("workingDirectory", item.m_WorkingDirectory);
+ settings.setValue("closeOnStart", item.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE);
+ settings.setValue("steamAppID", item.m_SteamAppID);
}
- settings.endArray();
+ }
+ settings.endArray();
- FileDialogMemory::save(settings);
+ FileDialogMemory::save(settings);
- settings.sync();
- result = settings.status();
+ settings.sync();
+ return settings.status();
+}
+
+void OrganizerCore::storeSettings()
+{
+ QString iniFile = qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::iniFileName());
+ if (!shellCopy(iniFile, iniFile + ".new", true, qApp->activeWindow())) {
+ QMessageBox::critical(qApp->activeWindow(), tr("Failed to write settings"),
+ tr("An error occured trying to update MO settings to %1: %2").arg(
+ iniFile, windowsErrorString(::GetLastError())));
+ return;
}
+
+ QSettings::Status result = storeSettings(iniFile + ".new");
+
if (result == QSettings::NoError) {
- if (!shellRename(iniFile + ".new", iniFile, true, qApp->activeWindow())) {
- DWORD err = ::GetLastError();
- // make a second attempt using qt functions but if that fails print the error from the first attempt
- if (!renameFile(iniFile + ".new", iniFile)) {
- QMessageBox::critical(qApp->activeWindow(), tr("Failed to write settings"),
- tr("An error occured trying to write back MO settings: %1").arg(windowsErrorString(err)));
- }
+ QString errMsg = commitSettings(iniFile);
+ if (!errMsg.isEmpty()) {
+ qWarning("settings file not writable, may be locked by another application, trying direct write");
+ result = storeSettings(iniFile);
}
- } else {
+ }
+ if (result != QSettings::NoError) {
QString reason = result == QSettings::AccessError ? tr("File is write protected")
: result == QSettings::FormatError ? tr("Invalid file format (probably a bug)")
: tr("Unknown error %1").arg(result);
QMessageBox::critical(qApp->activeWindow(), tr("Failed to write settings"),
- tr("An error occured trying to write back MO settings: %1").arg(reason));
+ tr("An error occured trying to write back MO settings to %1: %2").arg(iniFile + ".new", reason));
}
}
@@ -333,7 +351,6 @@ void OrganizerCore::setUserInterface(IUserInterface *userInterface, QWidget *wid m_UserInterface = userInterface;
if (widget != nullptr) {
-// connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), widget, SLOT(modorder_changed()));
connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), widget, SLOT(modlistChanged(QModelIndex, int)));
connect(&m_ModList, SIGNAL(showMessage(QString)), widget, SLOT(showMessage(QString)));
connect(&m_ModList, SIGNAL(modRenamed(QString,QString)), widget, SLOT(modRenamed(QString,QString)));
@@ -379,11 +396,12 @@ void OrganizerCore::disconnectPlugins() m_PluginContainer = nullptr;
}
-void OrganizerCore::setManagedGame(const QString &gameName)
+void OrganizerCore::setManagedGame(const QString &gameName, const QString &gamePath)
{
m_GameName = gameName;
if (m_PluginContainer != nullptr) {
m_GamePlugin = m_PluginContainer->managedGame(m_GameName);
+ m_GamePlugin->setGamePath(gamePath);
qApp->setProperty("managed_game", QVariant::fromValue(m_GamePlugin));
emit managedGameChanged(m_GamePlugin);
}
@@ -885,8 +903,13 @@ void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &argument // need to remove our stored load order because it may be outdated if a foreign tool changed the
// file time. After removing that file, refreshESPList will use the file time as the order
if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) {
+ qDebug("removing loadorder.txt");
QFile::remove(m_CurrentProfile->getLoadOrderFileName());
- refreshESPList();
+ }
+ refreshESPList();
+ if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) {
+ // the load order should have been retrieved from file time, now save it to our own format
+ savePluginList();
}
m_FinishedRun(binary.absoluteFilePath(), processExitCode);
@@ -1304,6 +1327,9 @@ void OrganizerCore::directory_refreshed() ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
modInfo->clearCaches();
}
+ for (auto task : m_PostRefreshTasks) {
+ task();
+ }
}
void OrganizerCore::profileRefresh()
@@ -1472,6 +1498,11 @@ bool OrganizerCore::saveCurrentLists() void OrganizerCore::savePluginList()
{
+ if (m_DirectoryUpdate) {
+ // delay save till after directory update
+ m_PostRefreshTasks.append([&] () { this->savePluginList(); });
+ return;
+ }
m_PluginList.saveTo(m_CurrentProfile->getPluginsFileName(),
m_CurrentProfile->getLoadOrderFileName(),
m_CurrentProfile->getLockedOrderFileName(),
diff --git a/src/organizercore.h b/src/organizercore.h index e4072b38..e9914ea7 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -73,7 +73,7 @@ public: void connectPlugins(PluginContainer *container);
void disconnectPlugins();
- void setManagedGame(const QString &gameName);
+ void setManagedGame(const QString &gameName, const QString &gamePath);
void updateExecutablesList(QSettings &settings);
@@ -85,13 +85,13 @@ public: MOShared::DirectoryEntry *directoryStructure() { return m_DirectoryStructure; }
DirectoryRefresher *directoryRefresher() { return &m_DirectoryRefresher; }
ExecutablesList *executablesList() { return &m_ExecutablesList; }
- void setExecutablesDialog(const ExecutablesList &executablesList) { m_ExecutablesList = executablesList; }
+ void setExecutablesList(const ExecutablesList &executablesList) {
+ m_ExecutablesList = executablesList;
+ }
Profile *currentProfile() { return m_CurrentProfile; }
void setCurrentProfile(const QString &profileName);
- void setExecutablesList(const ExecutablesList &executablesList);
-
std::set<QString> enabledArchives();
MOBase::VersionInfo getVersion() const { return m_Updater.getVersion(); }
@@ -198,6 +198,10 @@ private: void storeSettings();
+ QSettings::Status storeSettings(const QString &fileName);
+
+ QString commitSettings(const QString &iniFile);
+
bool queryLogin(QString &username, QString &password);
void updateModActiveState(int index, bool active);
@@ -240,6 +244,7 @@ private: PluginList m_PluginList;
QList<std::function<void()>> m_PostLoginTasks;
+ QList<std::function<void()>> m_PostRefreshTasks;
ExecutablesList m_ExecutablesList;
QStringList m_PendingDownloads;
diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp index e1d9d9f0..f741e0dc 100644 --- a/src/plugincontainer.cpp +++ b/src/plugincontainer.cpp @@ -140,12 +140,12 @@ bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName) bf::at_key<IPluginProxy>(m_Plugins).push_back(proxy);
QStringList pluginNames = proxy->pluginList(
QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()));
- foreach (const QString &pluginName, pluginNames) {
+ for (const QString &pluginName : pluginNames) {
try {
QObject *proxiedPlugin = proxy->instantiate(pluginName);
if (proxiedPlugin != nullptr) {
if (registerPlugin(proxiedPlugin, pluginName)) {
- qDebug("loaded plugin \"%s\"", qPrintable(pluginName));
+ qDebug("loaded plugin \"%s\"", qPrintable(QFileInfo(pluginName).fileName()));
} else {
qWarning("plugin \"%s\" failed to load. If this plugin is for an older version of MO "
"you have to update it or delete it if no update exists.",
@@ -273,7 +273,7 @@ void PluginContainer::loadPlugins() qPrintable(pluginName), qPrintable(pluginLoader->errorString()));
} else {
if (registerPlugin(pluginLoader->instance(), pluginName)) {
- qDebug("loaded plugin \"%s\"", qPrintable(pluginName));
+ qDebug("loaded plugin \"%s\"", qPrintable(QFileInfo(pluginName).fileName()));
m_PluginLoaders.push_back(pluginLoader.release());
} else {
m_FailedPlugins.push_back(pluginName);
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index cccb7d12..d3ffcdcb 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -18,7 +18,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */
#include "pluginlist.h"
-#include "report.h"
#include "inject.h"
#include "settings.h"
#include "safewritefile.h"
@@ -28,6 +27,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <gameinfo.h>
#include <iplugingame.h>
#include <espfile.h>
+#include <report.h>
#include <windows_error.h>
#include <QtDebug>
@@ -89,9 +89,9 @@ PluginList::~PluginList() {
m_Refreshed.disconnect_all_slots();
m_PluginMoved.disconnect_all_slots();
+ m_PluginStateChanged.disconnect_all_slots();
}
-
QString PluginList::getColumnName(int column)
{
switch (column) {
@@ -297,13 +297,11 @@ void PluginList::addInformation(const QString &name, const QString &message) }
}
-
bool PluginList::isEnabled(int index)
{
return m_ESPs.at(index).m_Enabled;
}
-
bool PluginList::readLoadOrder(const QString &fileName)
{
std::set<QString> availableESPs;
@@ -326,6 +324,10 @@ bool PluginList::readLoadOrder(const QString &fileName) if (!file.open(QIODevice::ReadOnly)) {
return false;
}
+ if (file.size() == 0) {
+ // MO stores at least a header in the file. if it's completely empty the file is broken
+ return false;
+ }
while (!file.atEnd()) {
QByteArray line = file.readLine().trimmed();
QString modName;
@@ -446,8 +448,12 @@ void PluginList::writePlugins(const QString &fileName, bool writeUnchecked) cons "Please see mo_interface.log for a list of affected plugins and rename them."));
}
- if (file.commitIfDifferent(m_LastSaveHash[fileName])) {
- qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData());
+ if (writtenCount == 0) {
+ qWarning("plugin list would be empty, this is almost certainly wrong. Not saving.");
+ } else {
+ if (file.commitIfDifferent(m_LastSaveHash[fileName])) {
+ qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData());
+ }
}
}
@@ -503,14 +509,16 @@ bool PluginList::saveLoadOrder(DirectoryEntry &directoryStructure) return true;
}
- for (std::vector<ESPInfo>::iterator iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
- std::wstring espName = ToWString(iter->m_Name);
+ qDebug("setting file times on esps");
+
+ for (ESPInfo &esp : m_ESPs) {
+ std::wstring espName = ToWString(esp.m_Name);
const FileEntry::Ptr fileEntry = directoryStructure.findFile(espName);
if (fileEntry.get() != nullptr) {
QString fileName;
bool archive = false;
int originid = fileEntry->getOrigin(archive);
- fileName = QString("%1\\%2").arg(QDir::toNativeSeparators(ToQString(directoryStructure.getOriginByID(originid).getPath()))).arg(iter->m_Name);
+ fileName = QString("%1\\%2").arg(QDir::toNativeSeparators(ToQString(directoryStructure.getOriginByID(originid).getPath()))).arg(esp.m_Name);
HANDLE file = ::CreateFile(ToWString(fileName).c_str(), GENERIC_READ | GENERIC_WRITE,
0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
@@ -524,13 +532,13 @@ bool PluginList::saveLoadOrder(DirectoryEntry &directoryStructure) }
ULONGLONG temp = 0;
- temp = (145731ULL + iter->m_Priority) * 24 * 60 * 60 * 10000000ULL;
+ temp = (145731ULL + esp.m_Priority) * 24 * 60 * 60 * 10000000ULL;
FILETIME newWriteTime;
newWriteTime.dwLowDateTime = (DWORD)(temp & 0xFFFFFFFF);
newWriteTime.dwHighDateTime = (DWORD)(temp >> 32);
- iter->m_Time = newWriteTime;
+ esp.m_Time = newWriteTime;
fileEntry->setFileTime(newWriteTime);
if (!::SetFileTime(file, nullptr, nullptr, &newWriteTime)) {
throw windows_error(QObject::tr("failed to set file time %1").arg(fileName).toUtf8().constData());
@@ -558,7 +566,6 @@ bool PluginList::isESPLocked(int index) const return m_LockedOrder.find(m_ESPs.at(index).m_Name.toLower()) != m_LockedOrder.end();
}
-
void PluginList::lockESPIndex(int index, bool lock)
{
if (lock) {
@@ -573,7 +580,6 @@ qDebug(__FUNCTION__); emit writePluginsList();
}
-
void PluginList::syncLoadOrder()
{
int loadOrder = 0;
@@ -595,9 +601,11 @@ void PluginList::refreshLoadOrder() // set priorities according to locked load order
std::map<int, QString> lockedLoadOrder;
std::for_each(m_LockedOrder.begin(), m_LockedOrder.end(),
- [&lockedLoadOrder] (const std::pair<QString, int> &ele) { lockedLoadOrder[ele.second] = ele.first; });
+ [&lockedLoadOrder] (const std::pair<QString, int> &ele) {
+ lockedLoadOrder[ele.second] = ele.first; });
int targetPrio = 0;
+ bool savePluginsList = false;
// this is guaranteed to iterate from lowest key (load order) to highest
for (auto iter = lockedLoadOrder.begin(); iter != lockedLoadOrder.end(); ++iter) {
auto nameIter = m_ESPsByName.find(iter->second);
@@ -620,16 +628,22 @@ void PluginList::refreshLoadOrder() setPluginPriority(index, temp);
m_ESPs[index].m_LoadOrder = iter->first;
syncLoadOrder();
- emit writePluginsList();
+ savePluginsList = true;
}
}
}
+ if (savePluginsList) {
+ emit writePluginsList();
+ }
}
+void PluginList::disconnectSlots() {
+ m_PluginMoved.disconnect_all_slots();
+ m_Refreshed.disconnect_all_slots();
+ m_PluginStateChanged.disconnect_all_slots();
+}
-
-
-IPluginList::PluginState PluginList::state(const QString &name) const
+IPluginList::PluginStates PluginList::state(const QString &name) const
{
auto iter = m_ESPsByName.find(name.toLower());
if (iter == m_ESPsByName.end()) {
@@ -693,6 +707,12 @@ QString PluginList::origin(const QString &name) const }
}
+bool PluginList::onPluginStateChanged(const std::function<void (const QString &, PluginStates)> &func)
+{
+ auto conn = m_PluginStateChanged.connect(func);
+ return conn.connected();
+}
+
bool PluginList::onRefreshed(const std::function<void ()> &callback)
{
auto conn = m_Refreshed.connect(callback);
@@ -761,15 +781,13 @@ void PluginList::testMasters() // emit layoutChanged();
}
-
QVariant PluginList::data(const QModelIndex &modelIndex, int role) const
{
int index = modelIndex.row();
-
if ((role == Qt::DisplayRole)
|| (role == Qt::EditRole)) {
switch (modelIndex.column()) {
- case COL_NAME: {
+ case COL_NAME: {
return m_ESPs[index].m_Name;
} break;
case COL_PRIORITY: {
@@ -880,7 +898,11 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const bool PluginList::setData(const QModelIndex &modIndex, const QVariant &value, int role)
{
+ QString modName = modIndex.data().toString();
+ IPluginList::PluginStates oldState = state(modName);
+
bool result = false;
+
if (role == Qt::CheckStateRole) {
m_ESPs[modIndex.row()].m_Enabled = value.toInt() == Qt::Checked;
emit dataChanged(modIndex, modIndex);
@@ -900,6 +922,20 @@ bool PluginList::setData(const QModelIndex &modIndex, const QVariant &value, int refreshLoadOrder();
}
}
+
+ IPluginList::PluginStates newState = state(modName);
+ if (oldState != newState) {
+ try {
+ m_PluginStateChanged(modName, newState);
+ testMasters();
+ emit dataChanged(this->index(0, 0), this->index(m_ESPs.size(), columnCount()));
+ } catch (const std::exception &e) {
+ qCritical("failed to invoke state changed notification: %s", e.what());
+ } catch (...) {
+ qCritical("failed to invoke state changed notification: unknown exception");
+ }
+ }
+
return result;
}
@@ -1024,6 +1060,7 @@ void PluginList::changePluginPriority(std::vector<int> rows, int newPriority) layoutChange.finish();
refreshLoadOrder();
+ emit writePluginsList();
}
bool PluginList::dropMimeData(const QMimeData *mimeData, Qt::DropAction action, int row, int, const QModelIndex &parent)
@@ -1124,9 +1161,13 @@ bool PluginList::eventFilter(QObject *obj, QEvent *event) } else if (keyEvent->key() == Qt::Key_Space) {
QItemSelectionModel *selectionModel = itemView->selectionModel();
const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel*>(selectionModel->model());
+ QList<QPersistentModelIndex> indices;
+ for (QModelIndex idx : selectionModel->selectedRows()) {
+ indices.append(idx);
+ }
QModelIndex minRow, maxRow;
- foreach (QModelIndex idx, selectionModel->selectedRows()) {
+ for (QModelIndex idx : indices) {
if (proxyModel != nullptr) {
idx = proxyModel->mapToSource(idx);
}
diff --git a/src/pluginlist.h b/src/pluginlist.h index 7be2df28..79066165 100644 --- a/src/pluginlist.h +++ b/src/pluginlist.h @@ -89,6 +89,7 @@ public: typedef boost::signals2::signal<void ()> SignalRefreshed;
typedef boost::signals2::signal<void (const QString &, int, int)> SignalPluginMoved;
+ typedef boost::signals2::signal<void (const QString &, PluginStates)> SignalPluginStateChanged;
public:
@@ -214,14 +215,11 @@ public: void refreshLoadOrder();
- void disconnectSlots() {
- m_PluginMoved.disconnect_all_slots();
- m_Refreshed.disconnect_all_slots();
- }
+ void disconnectSlots();
public:
- virtual PluginState state(const QString &name) const;
+ virtual PluginStates state(const QString &name) const;
virtual int priority(const QString &name) const;
virtual int loadOrder(const QString &name) const;
virtual bool isMaster(const QString &name) const;
@@ -229,6 +227,7 @@ public: virtual QString origin(const QString &name) const;
virtual bool onRefreshed(const std::function<void()> &callback);
virtual bool onPluginMoved(const std::function<void (const QString &, int, int)> &func);
+ virtual bool onPluginStateChanged(const std::function<void (const QString &, PluginStates)> &func) override;
public: // implementation of the QAbstractTableModel interface
@@ -335,6 +334,7 @@ private: SignalRefreshed m_Refreshed;
SignalPluginMoved m_PluginMoved;
+ SignalPluginStateChanged m_PluginStateChanged;
QTemporaryFile m_TempFile;
diff --git a/src/profile.cpp b/src/profile.cpp index c1e6e5fc..e0adbbc6 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -18,7 +18,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */ #include "profile.h" -#include "report.h" #include "gameinfo.h" #include "windows_error.h" #include "modinfo.h" @@ -28,6 +27,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <error_report.h> #include <appconfig.h> #include <iplugingame.h> +#include <report.h> #include <bsainvalidation.h> #include <dataarchives.h> #include <QMessageBox> @@ -543,7 +543,7 @@ void Profile::mergeTweak(const QString &tweakName, const QString &tweakedIni) co for (std::vector<std::wstring>::iterator keyIter = keys.begin(); keyIter != keys.end(); ++keyIter) { - //TODO this treats everything as strings but how could I differentiate the type? + //TODO this treats everything as strings but how could I differentiate the type? ::GetPrivateProfileStringW(iter->c_str(), keyIter->c_str(), nullptr, buffer.data(), bufferSize, ToWString(tweakName).c_str()); ::WritePrivateProfileStringW(iter->c_str(), keyIter->c_str(), diff --git a/src/report.cpp b/src/report.cpp deleted file mode 100644 index cca511a9..00000000 --- a/src/report.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/*
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#include "report.h"
-#include "utility.h"
-#include <QMessageBox>
-#include <QApplication>
-#include <Windows.h>
-
-
-using namespace MOBase;
-
-
-void reportError(QString message)
-{
- if (QApplication::topLevelWidgets().count() != 0) {
- QMessageBox messageBox(QMessageBox::Warning, QObject::tr("Error"), message, QMessageBox::Ok);
- messageBox.exec();
- } else {
- ::MessageBoxW(nullptr, ToWString(message).c_str(), ToWString(QObject::tr("Error")).c_str(), MB_ICONERROR | MB_OK);
- }
-}
-
-
-std::tstring toTString(const QString& source)
-{
-#ifdef UNICODE
- wchar_t* temp = new wchar_t[source.size() + 1];
- source.toWCharArray(temp);
- temp[source.size()] = '\0';
- std::tstring result(temp);
- delete[] temp;
- return result;
-#else // UNICODE
- return source.toAscii();
-#endif // UNICODE
-}
diff --git a/src/report.h b/src/report.h deleted file mode 100644 index b319f9a0..00000000 --- a/src/report.h +++ /dev/null @@ -1,38 +0,0 @@ -/*
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef REPORT_H
-#define REPORT_H
-
-#include <QString>
-#include <wchar.h>
-
-namespace std {
-#ifdef UNICODE
-typedef wstring tstring;
-#else
-typedef string tstring;
-#endif
-}
-
-void reportError(QString message);
-
-std::tstring toTString(const QString& source);
-
-#endif // REPORT_H
diff --git a/src/safewritefile.cpp b/src/safewritefile.cpp index 3bc1d1c4..007b3da9 100644 --- a/src/safewritefile.cpp +++ b/src/safewritefile.cpp @@ -50,7 +50,8 @@ void SafeWriteFile::commit() { bool SafeWriteFile::commitIfDifferent(QByteArray &inHash) {
QByteArray newHash = hash();
- if (newHash != inHash) {
+ if (newHash != inHash
+ || !QFile::exists(m_FileName)) {
commit();
inHash = newHash;
return true;
diff --git a/src/savetextasdialog.cpp b/src/savetextasdialog.cpp index 1a940094..8f0095d8 100644 --- a/src/savetextasdialog.cpp +++ b/src/savetextasdialog.cpp @@ -1,9 +1,13 @@ #include "savetextasdialog.h"
#include "ui_savetextasdialog.h"
-#include "report.h"
+#include <report.h>
#include <QClipboard>
#include <QFileDialog>
+
+using MOBase::reportError;
+
+
SaveTextAsDialog::SaveTextAsDialog(QWidget *parent)
: QDialog(parent), ui(new Ui::SaveTextAsDialog)
{
diff --git a/src/selfupdater.cpp b/src/selfupdater.cpp index 659233f1..071ee51c 100644 --- a/src/selfupdater.cpp +++ b/src/selfupdater.cpp @@ -20,7 +20,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "selfupdater.h"
#include "utility.h"
#include "installationmanager.h"
-#include "report.h"
#include "messagedialog.h"
#include "downloadmanager.h"
#include "nexusinterface.h"
@@ -28,6 +27,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <versioninfo.h>
#include <gameinfo.h>
#include <skyriminfo.h>
+#include <report.h>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
diff --git a/src/settings.cpp b/src/settings.cpp index c40450b1..c5fa954c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -140,7 +140,6 @@ void Settings::registerPlugin(IPlugin *plugin) } } - QString Settings::obfuscate(const QString &password) const { QByteArray temp = password.toUtf8(); @@ -152,7 +151,6 @@ QString Settings::obfuscate(const QString &password) const return buffer.toBase64(); } - QString Settings::deObfuscate(const QString &password) const { QByteArray temp(QByteArray::fromBase64(password.toUtf8())); @@ -164,7 +162,6 @@ QString Settings::deObfuscate(const QString &password) const return QString::fromUtf8(buffer.constData()); } - bool Settings::hideUncheckedPlugins() const { return m_Settings.value("Settings/hide_unchecked_plugins", false).toBool(); @@ -190,7 +187,6 @@ QString Settings::getDownloadDirectory() const return getConfigurablePath("download_directory", ToQString(AppConfig::downloadPath())); } - void Settings::setDownloadSpeed(const QString &serverName, int bytesPerSecond) { m_Settings.beginGroup("Servers"); @@ -725,9 +721,24 @@ void Settings::query(QWidget *parent) QDir().mkpath(modDirEdit->text()); } - m_Settings.setValue("Settings/download_directory", QDir::toNativeSeparators(downloadDirEdit->text())); - m_Settings.setValue("Settings/cache_directory", QDir::toNativeSeparators(cacheDirEdit->text())); - m_Settings.setValue("Settings/mod_directory", QDir::toNativeSeparators(modDirEdit->text())); + if (QFileInfo(downloadDirEdit->text()) != + QFileInfo(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::downloadPath()))) { + m_Settings.setValue("Settings/download_directory", QDir::toNativeSeparators(downloadDirEdit->text())); + } else { + m_Settings.remove("Settings/download_directory"); + } + if (QFileInfo(cacheDirEdit->text()) != + QFileInfo(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::cachePath()))) { + m_Settings.setValue("Settings/cache_directory", QDir::toNativeSeparators(cacheDirEdit->text())); + } else { + m_Settings.remove("Settings/cache_directory"); + } + if (QFileInfo(modDirEdit->text()) != + QFileInfo(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::modsPath()))) { + m_Settings.setValue("Settings/mod_directory", QDir::toNativeSeparators(modDirEdit->text())); + } else { + m_Settings.remove("Settings/mod_directory"); + } } diff --git a/src/singleinstance.cpp b/src/singleinstance.cpp index dcb0fc78..89332f9b 100644 --- a/src/singleinstance.cpp +++ b/src/singleinstance.cpp @@ -18,13 +18,14 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */
#include "singleinstance.h"
-#include "report.h"
#include "utility.h"
+#include <report.h>
#include <QLocalSocket>
static const char s_Key[] = "mo-43d1a3ad-eeb0-4818-97c9-eda5216c29b5";
static const int s_Timeout = 5000;
+using MOBase::reportError;
SingleInstance::SingleInstance(bool forcePrimary, QObject *parent) :
QObject(parent), m_PrimaryInstance(false)
diff --git a/src/spawn.cpp b/src/spawn.cpp index b1127df3..c79714bb 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -22,6 +22,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "utility.h"
#include <boost/scoped_array.hpp>
#include <gameinfo.h>
+#include <report.h>
#include <inject.h>
#include <Shellapi.h>
#include <appconfig.h>
diff --git a/src/transfersavesdialog.cpp b/src/transfersavesdialog.cpp index c37f0cd0..73267f75 100644 --- a/src/transfersavesdialog.cpp +++ b/src/transfersavesdialog.cpp @@ -54,16 +54,12 @@ TransferSavesDialog::~TransferSavesDialog() void TransferSavesDialog::refreshGlobalSaves()
{
m_GlobalSaves.clear();
-
QDir savesDir(m_GamePlugin->savesDirectory());
-
- QStringList filters;
- filters << m_GamePlugin->savegameExtension();
- savesDir.setNameFilters(filters);
+ savesDir.setNameFilters(QStringList() << QString("*.%1").arg(m_GamePlugin->savegameExtension()));
QStringList files = savesDir.entryList(QDir::Files, QDir::Time);
- foreach (const QString &filename, files) {
+ for (const QString &filename : files) {
SaveGameGamebryo *save = new SaveGameGamebryo(this, savesDir.absoluteFilePath(filename));
save->setParent(this);
m_GlobalSaves.push_back(save);
@@ -77,9 +73,7 @@ void TransferSavesDialog::refreshLocalSaves() QDir savesDir(m_Profile.absolutePath() + "/saves");
- QStringList filters;
- filters << m_GamePlugin->savegameExtension();
- savesDir.setNameFilters(filters);
+ savesDir.setNameFilters(QStringList() << QString("*.%1").arg(m_GamePlugin->savegameExtension()));
QStringList files = savesDir.entryList(QDir::Files, QDir::Time);
diff --git a/src/tutorials/tutorial_firststeps_main.js b/src/tutorials/tutorial_firststeps_main.js index 5ee4e790..2bc270d7 100644 --- a/src/tutorials/tutorial_firststeps_main.js +++ b/src/tutorials/tutorial_firststeps_main.js @@ -61,6 +61,7 @@ function getTutorialSteps() },
function() {
+ unhighlight()
tutorial.text = qsTr("Now it's time to install a few mods!"
+ "Please go along with this because we need a few mods installed to demonstrate other features")
waitForClick()
@@ -86,13 +87,13 @@ function getTutorialSteps() function() {
tutorial.text = qsTr("Downloads will appear on the \"Downloads\"-tab here. You have to download and install at least one mod to proceed.")
- applicationWindow.modInstalled.connect(nextStep)
+ organizer.modInstalled.connect(nextStep)
highlightItem("tabWidget", true)
},
function() {
unhighlight()
- applicationWindow.modInstalled.disconnect(nextStep)
+ organizer.modInstalled.disconnect(nextStep)
tutorial.text = qsTr("Great, you just installed your first mod. Please note that the installation procedure may differ based on how a mod was packaged.")
waitForClick()
},
diff --git a/src/version.rc b/src/version.rc index 272bdb1c..3f7eaadf 100644 --- a/src/version.rc +++ b/src/version.rc @@ -1,7 +1,7 @@ #include "Winver.h"
-#define VER_FILEVERSION 1,3,3,0
-#define VER_FILEVERSION_STR "1,3,3,0\0"
+#define VER_FILEVERSION 1,3,4,0
+#define VER_FILEVERSION_STR "1,3,4,0\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
|
