Compare commits

...
Author SHA1 Message Date
Tannin c57b172204 - removed some obsolete code
- MO will no longer start an application while the directory structure is being refreshed because MO may need to access profile files afterwards
- bugfix: the overwrite info-dialog was not destroyed and could thus keep a lock on files thus preventing those files from being moved/deleted
2013-09-22 13:10:21 +02:00
Tannin dfca8be71b - esp reader now handles invalid files more gracefully
- files moved will now also be treated as "deleted" in the old location so a newly created file with that same name is not created in overwrite
- introduced a mechanism by which MO can recognize if it crashed before when attempting to load a plugin. That plugin can be blacklisted so it doesn't get loaded again
- plugins can now programaticaly change their settings
- plugins can now store data persistently without exposing that data as settings
- requesting an unset-setting from a plugin is no longer treated as a bug
- clarified warning message for when files are in overwrite directory
- the proxyPython plugin will now discover if python initialization crashed MO on a previous session and give the user a chance to fix it or disable the plugin
- bugfix: GetModuleFileName modified the buffer past the zero termination. While this doesn't violate the API documentation it is different from the regular windows implementation
- bugfix: proxy plugins couldn't access the parent widget
- bugfix: when moving a file from overwrite to a mod the in-memory file structure wasn't updated
- bugfix: name input dialog for profiles allowed names that weren't valid directory names
- bugfix: profile dialog wasn't able to delete profiles if the name started or ended in whitespaces
- bugfix: The name-cells for plugin settings could be changed (without effect)
- removed a few obsolete files from the repository
2013-09-21 19:25:33 +02:00
Tannin 08037bf876 Added tag release v1.0.1 for changeset b90a2e9174c0 2013-09-21 18:59:47 +02:00
Tannin 500ab7f706 - bugfix: testing for missing masters at the wrong time seems to have caused crashes
- bugfix: mod list is now written to a temporary file first. Only on success is the original file overwritten
- bugfix: moving a mod priority to just above the overwrite could cause a crash or error message
- bugfix: versions with a release candidate number weren't sorted correctly (woops)
- bugfix: staging script didn't include archive.dll and dlls.manifest
- installation time on overwrite no longer updates constantly
2013-09-16 22:32:42 +02:00
Tannin 08309b71ba Added tag release v1.0.0rc1 for changeset 438584941a82 2013-09-15 16:11:16 +02:00
32 changed files with 544 additions and 495 deletions
-5
View File
@@ -65,11 +65,6 @@ ActivateModsDialog::~ActivateModsDialog()
}
void ActivateModsDialog::on_buttonBox_accepted()
{
}
std::set<QString> ActivateModsDialog::getModsToActivate()
{
std::set<QString> result;
-1
View File
@@ -62,7 +62,6 @@ public:
std::set<QString> getESPsToActivate();
private slots:
void on_buttonBox_accepted();
private:
Ui::ActivateModsDialog *ui;
-98
View File
@@ -1,98 +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 "archivetree.h"
#include <QDragMoveEvent>
ArchiveTree::ArchiveTree(QWidget *parent) :
QTreeWidget(parent)
{
}
bool ArchiveTree::testMovePossible(QTreeWidgetItem *source, QTreeWidgetItem *target)
{
if ((target == NULL) ||
(source == NULL)) {
return false;
}
if ((source == target) ||
(source->parent() == target)) {
return false;
}
return true;
}
void ArchiveTree::dragEnterEvent(QDragEnterEvent *event)
{
QTreeWidgetItem *source = this->currentItem();
if ((source == NULL) || (source->parent() == NULL)) {
// can't change top level
event->ignore();
return;
} else {
QTreeWidget::dragEnterEvent(event);
}
}
void ArchiveTree::dragMoveEvent(QDragMoveEvent *event)
{
if (!testMovePossible(this->currentItem(), itemAt(event->pos()))) {
event->ignore();
} else {
QTreeWidget::dragMoveEvent(event);
}
}
void ArchiveTree::dropEvent(QDropEvent *event)
{
event->ignore();
QTreeWidgetItem *target = itemAt(event->pos());
QList<QTreeWidgetItem*> sourceItems = this->selectedItems();
for (QList<QTreeWidgetItem*>::iterator iter = sourceItems.begin();
iter != sourceItems.end(); ++iter) {
QTreeWidgetItem *source = *iter;
if ((source->parent() != NULL) &&
testMovePossible(source, target)) {
source->parent()->removeChild(source);
if (target->data(0, Qt::UserRole).toInt() != 0) {
// target is a file
if (target->parent() == NULL) {
// this should really not happen, how should a
// file get to the top level?
return;
}
int index = target->parent()->indexOfChild(target);
target->parent()->insertChild(index, source);
emit changed();
} else {
// target is a directory
target->insertChild(target->childCount(), source);
emit changed();
}
}
}
}
-55
View File
@@ -1,55 +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 ARCHIVETREE_H
#define ARCHIVETREE_H
#include <QTreeWidget>
/**
* @brief QT tree widget used to display the content of an archive in the manual installation dialog
**/
class ArchiveTree : public QTreeWidget
{
Q_OBJECT
public:
explicit ArchiveTree(QWidget *parent = 0);
signals:
void changed();
public slots:
protected:
virtual void dragEnterEvent(QDragEnterEvent *event);
virtual void dragMoveEvent(QDragMoveEvent *event);
virtual void dropEvent(QDropEvent *event);
private:
bool testMovePossible(QTreeWidgetItem *source, QTreeWidgetItem *target);
};
#endif // ARCHIVETREE_H
-10
View File
@@ -172,16 +172,6 @@ void ExecutablesList::addExecutable(const QString &title, const QString &executa
}
}
/*void ExecutablesList::remove(const QString &executableName)
{
for (std::vector<Executable>::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) {
if (iter->m_Custom && (iter->m_BinaryInfo.absoluteFilePath() == executableName)) {
m_Executables.erase(iter);
break;
}
}
}*/
void ExecutablesList::remove(const QString &title)
{
-48
View File
@@ -1,48 +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 "finddialog.h"
#include "ui_finddialog.h"
FindDialog::FindDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::FindDialog)
{
ui->setupUi(this);
}
FindDialog::~FindDialog()
{
delete ui;
}
void FindDialog::on_nextBtn_clicked()
{
emit findNext();
}
void FindDialog::on_patternEdit_textChanged(const QString &pattern)
{
emit patternChanged(pattern);
}
void FindDialog::on_closeBtn_clicked()
{
this->close();
}
-73
View File
@@ -1,73 +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 FINDDIALOG_H
#define FINDDIALOG_H
#include <QDialog>
namespace Ui {
class FindDialog;
}
/**
* @brief Find dialog used in the TextView dialog
**/
class FindDialog : public QDialog
{
Q_OBJECT
public:
/**
* @brief constructor
*
* @param parent parent widget
**/
explicit FindDialog(QWidget *parent = 0);
~FindDialog();
signals:
/**
* @brief emitted when the user wants to jump to the next location matching the pattern
**/
void findNext();
/**
* @brief emitted when the user changes the pattern to search for
*
* @param pattern the new search pattern
**/
void patternChanged(const QString &pattern);
private slots:
void on_nextBtn_clicked();
void on_patternEdit_textChanged(const QString &arg1);
void on_closeBtn_clicked();
private:
Ui::FindDialog *ui;
};
#endif // FINDDIALOG_H
+1 -1
View File
@@ -343,7 +343,7 @@ int main(int argc, char *argv[])
bool done = false;
while (!done) {
if (!GameInfo::init(moPath, ToWString(gamePath))) {
if (!GameInfo::init(moPath, ToWString(QDir::toNativeSeparators(gamePath)))) {
if (!gamePath.isEmpty()) {
reportError(QObject::tr("No game identified in \"%1\". The directory is required to contain "
"the game binary and its launcher.").arg(gamePath));
+102 -11
View File
@@ -98,6 +98,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QNetworkInterface>
#include <QNetworkProxy>
#include <QtConcurrentRun>
#include <QCoreApplication>
#ifdef TEST_MODELS
@@ -233,6 +234,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), this, SLOT(modlistChanged(QModelIndex, int)));
connect(&m_ModList, SIGNAL(removeSelectedMods()), this, SLOT(removeMod_clicked()));
connect(&m_ModList, SIGNAL(requestColumnSelect(QPoint)), this, SLOT(displayColumnSelection(QPoint)));
connect(&m_ModList, SIGNAL(fileMoved(QString, QString, QString)), this, SLOT(fileMoved(QString, 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)));
@@ -997,6 +999,7 @@ bool MainWindow::registerPlugin(QObject *plugin)
{ // proxy plugins
IPluginProxy *proxy = qobject_cast<IPluginProxy*>(plugin);
if (verifyPlugin(proxy)) {
proxy->setParentWidget(this);
QStringList pluginNames = proxy->pluginList(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()));
foreach (const QString &pluginName, pluginNames) {
try {
@@ -1040,11 +1043,38 @@ void MainWindow::loadPlugins()
registerPlugin(plugin);
}
QFile loadCheck(QCoreApplication::applicationDirPath() + "/plugin_loadcheck.tmp");
if (loadCheck.exists() && loadCheck.open(QIODevice::ReadOnly)) {
// oh, there was a failed plugin load last time. Find out which plugin was loaded last
QString fileName;
while (!loadCheck.atEnd()) {
fileName = QString::fromUtf8(loadCheck.readLine().constData()).trimmed();
}
if (QMessageBox::question(this, tr("Plugin error"),
tr("It appears the plugin \"%1\" failed to load last startup and caused MO to crash. Do you want to disable it?\n"
"(Please note: If this is the first time you see this message for this plugin you may want to give it another try. "
"The plugin may be able to recover from the problem)").arg(fileName),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
m_Settings.addBlacklistPlugin(fileName);
}
loadCheck.close();
}
loadCheck.open(QIODevice::WriteOnly);
QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
qDebug("looking for plugins in %s", QDir::toNativeSeparators(pluginPath).toUtf8().constData());
QDirIterator iter(pluginPath, QDir::Files | QDir::NoDotAndDotDot);
while (iter.hasNext()) {
iter.next();
if (m_Settings.pluginBlacklisted(iter.fileName())) {
qDebug("plugin \"%s\" blacklisted", qPrintable(iter.fileName()));
continue;
}
loadCheck.write(iter.fileName().toUtf8());
loadCheck.write("\n");
loadCheck.flush();
QString pluginName = iter.filePath();
if (QLibrary::isLibrary(pluginName)) {
QPluginLoader pluginLoader(pluginName);
@@ -1063,6 +1093,9 @@ void MainWindow::loadPlugins()
}
}
// remove the load check file on success
loadCheck.remove();
m_DownloadManager.setSupportedExtensions(m_InstallationManager.getSupportedExtensions());
m_DiagnosisPlugins.push_back(this);
@@ -1172,6 +1205,21 @@ QVariant MainWindow::pluginSetting(const QString &pluginName, const QString &key
return m_Settings.pluginSetting(pluginName, key);
}
void MainWindow::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value)
{
m_Settings.setPluginSetting(pluginName, key, value);
}
QVariant MainWindow::persistent(const QString &pluginName, const QString &key, const QVariant &def) const
{
return m_Settings.pluginPersistent(pluginName, key, def);
}
void MainWindow::setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync)
{
m_Settings.setPluginPersistent(pluginName, key, value, sync);
}
QString MainWindow::pluginDataPath() const
{
QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
@@ -1224,6 +1272,11 @@ HANDLE MainWindow::spawnBinaryDirect(const QFileInfo &binary, const QString &arg
}
}
while (m_RefreshProgress->isVisible()) {
::Sleep(1000);
QCoreApplication::processEvents();
}
return startBinary(binary, arguments, profileName, m_Settings.logLevel(), currentDirectory, true);
}
@@ -1273,11 +1326,9 @@ void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments,
this->setEnabled(true);
refreshDirectoryStructure();
refreshDataTree();
if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) {
QFile::remove(m_CurrentProfile->getLoadOrderFileName());
}
refreshLists();
dialog->hide();
}
}
@@ -1622,11 +1673,15 @@ void MainWindow::refreshESPList()
m_CurrentProfile->writeModlist();
// clear list
m_PluginList.refresh(m_CurrentProfile->getName(),
*m_DirectoryStructure,
m_CurrentProfile->getPluginsFileName(),
m_CurrentProfile->getLoadOrderFileName(),
m_CurrentProfile->getLockedOrderFileName());
try {
m_PluginList.refresh(m_CurrentProfile->getName(),
*m_DirectoryStructure,
m_CurrentProfile->getPluginsFileName(),
m_CurrentProfile->getLoadOrderFileName(),
m_CurrentProfile->getLockedOrderFileName());
} catch (const std::exception &e) {
reportError(tr("Failed to refresh list of esps: %s").arg(e.what()));
}
}
@@ -1926,7 +1981,6 @@ void MainWindow::on_btnRefreshData_clicked()
{
if (!m_DirectoryUpdate) {
refreshDirectoryStructure();
refreshDataTree();
} else {
qDebug("directory update");
}
@@ -2331,8 +2385,12 @@ void MainWindow::directory_refreshed()
{
DirectoryEntry *newStructure = m_DirectoryRefresher.getDirectoryStructure();
if (newStructure != NULL) {
delete m_DirectoryStructure;
DirectoryEntry *oldStructure = m_DirectoryStructure;
m_DirectoryStructure = newStructure;
delete oldStructure;
refreshDataTree();
refreshLists();
} else {
// TODO: don't know why this happens, this slot seems to get called twice with only one emit
return;
@@ -2541,6 +2599,29 @@ void MainWindow::modlistChanged(int)
}
void MainWindow::fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName)
{
const FileEntry::Ptr filePtr = m_DirectoryStructure->findFile(ToWString(filePath));
if (filePtr.get() != NULL) {
try {
FilesOrigin &oldOrigin = m_DirectoryStructure->getOriginByName(ToWString(oldOriginName));
FilesOrigin &newOrigin = m_DirectoryStructure->getOriginByName(ToWString(newOriginName));
QString fullNewPath = ToQString(newOrigin.getPath()) + "\\" + filePath;
WIN32_FIND_DATAW findData;
::FindFirstFileW(ToWString(fullNewPath).c_str(), &findData);
filePtr->addOrigin(newOrigin.getID(), findData.ftCreationTime, L"");
filePtr->removeOrigin(oldOrigin.getID());
} catch (const std::exception &e) {
reportError(tr("Failed to move \"%1\" from mod \"%2\" to \"%3\": %4").arg(filePath).arg(oldOriginName).arg(newOriginName).arg(e.what()));
}
} else {
// this is probably not an error, the specified path is likely a directory
}
}
QTreeWidgetItem *MainWindow::addFilterItem(QTreeWidgetItem *root, const QString &name, int categoryID)
{
QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(name));
@@ -2795,6 +2876,15 @@ void MainWindow::unendorse_clicked()
}
void MainWindow::overwriteClosed(int)
{
QDialog *dialog = this->findChild<QDialog*>("__overwriteDialog");
if (dialog != NULL) {
dialog->deleteLater();
}
}
void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab)
{
std::vector<ModInfo::EFlag> flags = modInfo->getFlags();
@@ -2807,6 +2897,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index,
dialog->show();
dialog->raise();
dialog->activateWindow();
connect(dialog, SIGNAL(finished(int)), this, SLOT(overwriteClosed(int)));
} else {
ModInfoDialog dialog(modInfo, m_DirectoryStructure, this);
connect(&dialog, SIGNAL(nexusLinkActivated(QString)), this, SLOT(nexusLinkActivated(QString)));
@@ -3024,8 +3115,8 @@ void MainWindow::createModFromOverwrite()
}
ModInfo::Ptr overwriteInfo = ModInfo::getByIndex(m_ContextRow);
shellMove(QStringList(overwriteInfo->absolutePath() + "\\*"), QStringList(newMod->absolutePath()), this);
shellMove(QStringList(QDir::toNativeSeparators(overwriteInfo->absolutePath()) + "\\*"),
QStringList(QDir::toNativeSeparators(newMod->absolutePath())), this);
refreshModList();
}
+7
View File
@@ -105,6 +105,9 @@ public:
virtual bool removeMod(MOBase::IModInterface *mod);
virtual void modDataChanged(MOBase::IModInterface *mod);
virtual QVariant pluginSetting(const QString &pluginName, const QString &key) const;
virtual void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value);
virtual QVariant persistent(const QString &pluginName, const QString &key, const QVariant &def = QVariant()) const;
virtual void setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync = true);
virtual QString pluginDataPath() const;
virtual void installMod(const QString &fileName);
virtual QString resolvePath(const QString &fileName) const;
@@ -315,6 +318,8 @@ private:
std::vector<MOBase::IPluginDiagnose*> m_DiagnosisPlugins;
std::vector<QString> m_UnloadedPlugins;
QFile m_PluginsCheck;
private slots:
void showMessage(const QString &message);
@@ -435,6 +440,7 @@ private slots:
void updateStyle(const QString &style);
void modlistChanged(const QModelIndex &index, int role);
void fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName);
void savePluginList();
@@ -458,6 +464,7 @@ private slots:
void toolBar_customContextMenuRequested(const QPoint &point);
void removeFromToolbar();
void overwriteClosed(int);
private slots: // ui slots
// actions
+1 -1
View File
@@ -786,7 +786,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye
<item>
<widget class="QLabel" name="bsaWarning">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Marked Archives (&lt;img src=&quot;:/MO/gui/resources/dialog-warning_16.png&quot;/&gt;) are still loaded on Skyrim but the &lt;a href=&quot;http://forums.bethsoft.com/topic/1354395-update-bsas-and-you/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;regular file override&lt;/span&gt;&lt;/a&gt; mechanism will apply: Loose files override BSAs, no matter the mod/plugin priority.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Marked Archives (&lt;img src=&quot;:/MO/gui/warning_16&quot;/&gt;) are still loaded on Skyrim but the &lt;a href=&quot;http://forums.bethsoft.com/topic/1354395-update-bsas-and-you/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;regular file override&lt;/span&gt;&lt;/a&gt; mechanism will apply: Loose files override BSAs, no matter the mod/plugin priority.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
+1 -1
View File
@@ -792,9 +792,9 @@ ModInfoBackup::ModInfoBackup(const QDir &path, DirectoryEntry **directoryStructu
ModInfoOverwrite::ModInfoOverwrite()
: m_StartupTime(QDateTime::currentDateTime())
{
testValid();
}
+5 -1
View File
@@ -811,7 +811,7 @@ public:
virtual void endorse(bool) {}
virtual QString name() const { return "Overwrite"; }
virtual QString notes() const { return ""; }
virtual QDateTime creationTime() const { return QDateTime::currentDateTime(); }
virtual QDateTime creationTime() const { return m_StartupTime; }
virtual QString absolutePath() const;
virtual MOBase::VersionInfo getNewestVersion() const { return ""; }
virtual QString getInstallationFile() const { return ""; }
@@ -828,6 +828,10 @@ private:
ModInfoOverwrite();
private:
QDateTime m_StartupTime;
};
#endif // MODINFO_H
+8
View File
@@ -477,6 +477,7 @@ Qt::ItemFlags ModList::flags(const QModelIndex &modelIndex) const
return result;
}
QStringList ModList::mimeTypes() const
{
QStringList result = QAbstractItemModel::mimeTypes();
@@ -544,6 +545,12 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa
QDir modDirectory(modInfo->absolutePath());
QDir gameDirectory(QDir::fromNativeSeparators(ToQString(MOShared::GameInfo::instance().getOverwriteDir())));
unsigned int overwriteIndex = ModInfo::findMod([](ModInfo::Ptr mod) -> bool {
std::vector<ModInfo::EFlag> flags = mod->getFlags();
return std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end(); });
QString overwriteName = ModInfo::getByIndex(overwriteIndex)->name();
foreach (const QUrl &url, mimeData->urls()) {
QString relativePath = gameDirectory.relativeFilePath(url.toLocalFile());
if (relativePath.startsWith("..")) {
@@ -552,6 +559,7 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa
}
source.append(url.toLocalFile());
target.append(modDirectory.absoluteFilePath(relativePath));
emit fileMoved(relativePath, overwriteName, modInfo->name());
}
if (source.count() != 0) {
+8
View File
@@ -182,6 +182,14 @@ signals:
*/
void removeSelectedMods();
/**
* @brief fileMoved emitted when a file is moved from one mod to another
* @param relativePath relative path of the file moved
* @param oldOriginName name of the origin that previously contained the file
* @param newOriginName name of the origin that now contains the file
*/
void fileMoved(const QString &relativePath, const QString &oldOriginName, const QString &newOriginName);
protected:
// event filter, handles event from the header and the tree view itself
+10
View File
@@ -0,0 +1,10 @@
#include "noeditdelegate.h"
NoEditDelegate::NoEditDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
QWidget *NoEditDelegate::createEditor(QWidget*, const QStyleOptionViewItem&, const QModelIndex&) const {
return NULL;
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef NOEDITDELEGATE_H
#define NOEDITDELEGATE_H
#include <QStyledItemDelegate>
class NoEditDelegate: public QStyledItemDelegate {
public:
NoEditDelegate(QObject *parent = NULL);
virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
#endif // NOEDITDELEGATE_H
+7 -8
View File
@@ -51,7 +51,6 @@ SOURCES += \
json.cpp \
installationmanager.cpp \
helper.cpp \
finddialog.cpp \
filedialogmemory.cpp \
executableslist.cpp \
editexecutablesdialog.cpp \
@@ -66,7 +65,6 @@ SOURCES += \
categoriesdialog.cpp \
categories.cpp \
bbcode.cpp \
archivetree.cpp \
activatemodsdialog.cpp \
moapplication.cpp \
profileinputdialog.cpp \
@@ -80,7 +78,8 @@ SOURCES += \
serverinfo.cpp \
../esptk/record.cpp \
../esptk/espfile.cpp \
../esptk/subrecord.cpp
../esptk/subrecord.cpp \
noeditdelegate.cpp
HEADERS += \
transfersavesdialog.h \
@@ -119,7 +118,6 @@ HEADERS += \
json.h \
installationmanager.h \
helper.h \
finddialog.h \
filedialogmemory.h \
executableslist.h \
editexecutablesdialog.h \
@@ -134,7 +132,6 @@ HEADERS += \
categoriesdialog.h \
categories.h \
bbcode.h \
archivetree.h \
activatemodsdialog.h \
moapplication.h \
profileinputdialog.h \
@@ -148,7 +145,9 @@ HEADERS += \
serverinfo.h \
../esptk/record.h \
../esptk/espfile.h \
../esptk/subrecord.h
../esptk/subrecord.h \
../esptk/espexceptions.h \
noeditdelegate.h
FORMS += \
transfersavesdialog.ui \
@@ -218,8 +217,8 @@ TRANSLATIONS = organizer_de.ts \
organizer_zh_CN.ts \
organizer_cs.ts \
organizer_tr.ts \
organizer_ru.ts \
organizer.en.ts
# organizer.en.ts \
organizer_ru.ts
!isEmpty(TRANSLATIONS) {
isEmpty(QMAKE_LRELEASE) {
-1
View File
@@ -37,7 +37,6 @@ public:
virtual int columnCount(const QModelIndex &parent) const {
m_RegularColumnCount = QFileSystemModel::columnCount(parent);
// return m_RegularColumnCount + 1;
return m_RegularColumnCount;
}
+15 -8
View File
@@ -140,8 +140,12 @@ void PluginList::refresh(const QString &profileName, const DirectoryEntry &baseD
std::find(primaryPlugins.begin(), primaryPlugins.end(), ToWString(filename.toLower())) != primaryPlugins.end();
bool archive = false;
FilesOrigin &origin = baseDirectory.getOriginByID(current->getOrigin(archive));
m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), ToQString(origin.getName()), ToQString(current->getFullPath())));
try {
FilesOrigin &origin = baseDirectory.getOriginByID(current->getOrigin(archive));
m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), ToQString(origin.getName()), ToQString(current->getFullPath())));
} catch (const std::exception &e) {
reportError(tr("failed to update esp info for file %1 (source id: %2), error: %3").arg(filename).arg(current->getOrigin(archive)).arg(e.what()));
}
}
}
@@ -594,6 +598,8 @@ int PluginList::columnCount(const QModelIndex &) const
void PluginList::testMasters()
{
// emit layoutAboutToBeChanged();
std::set<QString> enabledMasters;
for (auto iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
if (iter->m_Enabled) {
@@ -613,7 +619,8 @@ void PluginList::testMasters()
}
}
emit layoutChanged();
#pragma message("emitting this seems to cause a crash!")
// emit layoutChanged();
}
@@ -738,18 +745,18 @@ void PluginList::setPluginPriority(int row, int &newPriority)
if (!m_ESPs[row].m_IsMaster) {
// don't allow esps to be moved above esms
while ((newPriorityTemp < static_cast<int>(m_ESPsByPriority.size() - 1)) &&
m_ESPs[m_ESPsByPriority[newPriorityTemp]].m_IsMaster) {
m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).m_IsMaster) {
++newPriorityTemp;
}
} else {
// don't allow esms to be moved below esps
while ((newPriorityTemp > 0) &&
!m_ESPs[m_ESPsByPriority[newPriorityTemp]].m_IsMaster) {
!m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).m_IsMaster) {
--newPriorityTemp;
}
// also don't allow "regular" esms to be moved above primary plugins
while ((newPriorityTemp < static_cast<int>(m_ESPsByPriority.size() - 1)) &&
(m_ESPs[m_ESPsByPriority[newPriorityTemp]].m_ForceEnabled)) {
(m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).m_ForceEnabled)) {
++newPriorityTemp;
}
}
@@ -806,9 +813,9 @@ void PluginList::changePluginPriority(std::vector<int> rows, int newPriority)
}
refreshLoadOrder();
startSaveTime();
emit layoutChanged();
startSaveTime();
}

Some files were not shown because too many files have changed in this diff Show More