Compare commits

...
Author SHA1 Message Date
Tannin bf0db9c218 - position of splitter in main window is now saved and restored
- confirmation dialog before enabling/disabling all plugins
- bugfix: GetPrivateProfileString-hook potentially accessed buffer that is allowed to be NULL
- bugfix: attempt to extract an archive crashed MO in 0.99.2
- bugfix: archive list wasn't saved correctly in 0.99.2
- bugfix: plugins.txt was incorrectly interpreted as utf-8
2013-08-25 13:15:23 +02:00
Tannin 8fcf21e771 - column sizing is now changeable by the user yet still automatically resizes fit content on first start 2013-08-24 23:11:20 +02:00
Tannin b46b2fe6f2 Merge 2013-08-24 22:50:22 +02:00
Tannin e91eebefbe - download size is now displayed
- multiple esps/mods can now be enabled/disabled at once using space
- bugfix: fomod installer didn't compile because of changes to condition checking
- bugfix: broken inverse virtual name resolution in case of non-default mod directory
2013-08-24 22:50:00 +02:00
Tannin 2e605b275b Added tag release v0.99.2 for changeset 95e629510d01 2013-08-24 14:14:00 +02:00
Tannin 87f4e2df26 Merge 2013-08-17 08:54:53 +02:00
Tannin 9272013103 - bugfix: download manager will now properly pause all downloads on exiting the application
- bugfix: resumed downloads now get their automatic-retry-count reset
- fiddled with condition tests in fomod (not sure if it works right now)
2013-08-17 08:54:09 +02:00
17 changed files with 381 additions and 170 deletions
+2
View File
@@ -44,6 +44,7 @@ DownloadListWidgetDelegate::DownloadListWidgetDelegate(DownloadManager *manager,
: QItemDelegate(parent), m_Manager(manager), m_ItemWidget(new DownloadListWidget), m_ContextRow(0), m_View(view)
{
m_NameLabel = m_ItemWidget->findChild<QLabel*>("nameLabel");
m_SizeLabel = m_ItemWidget->findChild<QLabel*>("sizeLabel");
m_Progress = m_ItemWidget->findChild<QProgressBar*>("downloadProgress");
m_InstallLabel = m_ItemWidget->findChild<QLabel*>("installLabel");
@@ -100,6 +101,7 @@ void DownloadListWidgetDelegate::paint(QPainter *painter, const QStyleOptionView
name.append("...");
}
m_NameLabel->setText(name);
m_SizeLabel->setText(QString::number(m_Manager->getFileSize(downloadIndex) / 1024));
DownloadManager::DownloadState state = m_Manager->getState(downloadIndex);
if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR)) {
QPalette labelPalette;
+1
View File
@@ -101,6 +101,7 @@ private:
DownloadManager *m_Manager;
QLabel *m_NameLabel;
QLabel *m_SizeLabel;
QProgressBar *m_Progress;
QLabel *m_InstallLabel;
int m_ContextRow;
+48 -17
View File
@@ -42,23 +42,54 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="nameLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>323</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Placeholder</string>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="nameLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>323</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Placeholder</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="sizeLabel">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>KB</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
+7
View File
@@ -44,6 +44,7 @@ DownloadListWidgetCompactDelegate::DownloadListWidgetCompactDelegate(DownloadMan
: QItemDelegate(parent), m_Manager(manager), m_ItemWidget(new DownloadListWidgetCompact), m_View(view)
{
m_NameLabel = m_ItemWidget->findChild<QLabel*>("nameLabel");
m_SizeLabel = m_ItemWidget->findChild<QLabel*>("sizeLabel");
m_Progress = m_ItemWidget->findChild<QProgressBar*>("downloadProgress");
m_DoneLabel = m_ItemWidget->findChild<QLabel*>("doneLabel");
@@ -106,7 +107,13 @@ void DownloadListWidgetCompactDelegate::paint(QPainter *painter, const QStyleOpt
name.append("...");
}
m_NameLabel->setText(name);
DownloadManager::DownloadState state = m_Manager->getState(downloadIndex);
if ((m_SizeLabel != NULL) && (state >= DownloadManager::STATE_READY)) {
m_SizeLabel->setText(QString::number(m_Manager->getFileSize(downloadIndex) / 1048576));
}
if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR)) {
m_DoneLabel->setVisible(true);
m_Progress->setVisible(false);
+1
View File
@@ -100,6 +100,7 @@ private:
DownloadManager *m_Manager;
QLabel *m_NameLabel;
QLabel *m_SizeLabel;
QProgressBar *m_Progress;
QLabel *m_DoneLabel;
+40 -18
View File
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>315</width>
<height>22</height>
<height>24</height>
</rect>
</property>
<property name="contextMenuPolicy">
@@ -23,14 +23,23 @@
<property name="spacing">
<number>2</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QLabel" name="nameLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
@@ -48,6 +57,19 @@
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="doneLabel">
<property name="sizePolicy">
@@ -60,24 +82,24 @@
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>118</green>
<blue>0</blue>
</color>
</brush>
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>118</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>118</green>
<blue>0</blue>
</color>
</brush>
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>118</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
+52 -2
View File
@@ -33,6 +33,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <boost/bind.hpp>
#include <regex>
#include <QMessageBox>
#include <QCoreApplication>
using QtJson::Json;
@@ -96,6 +97,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con
info->m_DownloadID = s_NextDownloadID++;
info->m_Output.setFileName(filePath);
info->m_TotalSize = QFileInfo(filePath).size();
info->m_ModID = metaFile.value("modID", 0).toInt();
info->m_FileID = metaFile.value("fileID", 0).toInt();
info->m_CurrentUrl = 0;
@@ -162,12 +164,41 @@ bool DownloadManager::downloadsInProgress()
{
for (QVector<DownloadInfo*>::iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end(); ++iter) {
if ((*iter)->m_State < STATE_READY) {
// return true;
return true;
}
}
return false;
}
void DownloadManager::pauseAll()
{
// first loop: pause all downloads
for (int i = 0; i < m_ActiveDownloads.count(); ++i) {
if (m_ActiveDownloads[i]->m_State < STATE_READY) {
pauseDownload(i);
}
}
::Sleep(100);
bool done = false;
// further loops: busy waiting for all downloads to complete. This could be neater...
while (!done) {
QCoreApplication::processEvents();
done = true;
foreach (DownloadInfo *info, m_ActiveDownloads) {
if ((info->m_State < STATE_CANCELED) ||
(info->m_State != STATE_FETCHINGFILEINFO) || (info->m_State != STATE_FETCHINGMODINFO)) {
done = false;
break;
}
}
if (!done) {
::Sleep(100);
}
}
}
void DownloadManager::setOutputDirectory(const QString &outputDirectory)
{
@@ -456,8 +487,18 @@ void DownloadManager::pauseDownload(int index)
}
}
void DownloadManager::resumeDownload(int index)
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
reportError(tr("invalid index %1").arg(index));
return;
}
DownloadInfo *info = m_ActiveDownloads[index];
info->m_Tries = AUTOMATIC_RETRIES;
resumeDownloadInt(index);
}
void DownloadManager::resumeDownloadInt(int index)
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
reportError(tr("invalid index %1").arg(index));
@@ -556,6 +597,15 @@ QString DownloadManager::getFileName(int index) const
return m_ActiveDownloads.at(index)->m_FileName;
}
qint64 DownloadManager::getFileSize(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
throw MyException(tr("invalid index"));
}
return m_ActiveDownloads.at(index)->m_TotalSize;
}
int DownloadManager::getProgress(int index) const
{
+10 -1
View File
@@ -206,6 +206,14 @@ public:
**/
QString getFileName(int index) const;
/**
* @brief retrieve the file size of the download specified by index
*
* @param index index of the file to look up
* @return size of the file (total size during download)
*/
qint64 getFileSize(int index) const;
/**
* @brief retrieve the current progress of the download specified by index
*
@@ -288,6 +296,7 @@ public:
*/
int indexByName(const QString &fileName) const;
void pauseAll();
signals:
void aboutToUpdate();
@@ -357,10 +366,10 @@ private slots:
private:
void createMetaFile(DownloadInfo *info);
// QString getOutputPath(const QUrl &url, const QString &fileName) const;
QString getDownloadFileName(const QString &baseName) const;
void startDownload(QNetworkReply *reply, DownloadInfo *newDownload, bool resume);
void resumeDownloadInt(int index);
/**
* @brief start a download from a url
+119 -51
View File
@@ -100,6 +100,11 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QtConcurrentRun>
#ifdef TEST_MODELS
#include "modeltest.h"
#endif // TEST_MODELS
using namespace MOBase;
using namespace MOShared;
@@ -128,11 +133,6 @@ static bool isOnline()
}
#ifdef TEST_MODELS
#include "modeltest.h"
#endif // TEST_MODELS
MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow), m_Tutorial(this, "MainWindow"),
m_ExeName(exeName), m_OldProfileIndex(-1),
@@ -162,7 +162,6 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
updateProblemsButton();
updateToolBar();
// ui->toolBar->blockSignals(true);
ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure);
@@ -181,43 +180,25 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
ui->modList->setItemDelegateForColumn(ModList::COL_FLAGS, new IconDelegate(ui->modList));
//ui->modList->setAcceptDrops(true);
ui->modList->header()->installEventFilter(&m_ModList);
ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray());
if (initSettings.contains("mod_list_state")) {
ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray());
}
ui->modList->header()->setSectionHidden(0, false); // prevent the name-column from being hidden
ui->modList->installEventFilter(&m_ModList);
// restoreState also seems to restores the resize mode from previous session,
// I don't really like that
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
for (int i = 0; i < ui->modList->header()->count(); ++i) {
ui->modList->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
}
ui->modList->header()->setSectionResizeMode(ModList::COL_NAME, QHeaderView::Stretch);
#else
for (int i = 0; i < ui->modList->header()->count(); ++i) {
ui->modList->header()->setResizeMode(i, QHeaderView::ResizeToContents);
}
ui->modList->header()->setResizeMode(ModList::COL_NAME, QHeaderView::Stretch);
#endif
// set up plugin list
m_PluginListSortProxy = new PluginListSortProxy(this);
m_PluginListSortProxy->setSourceModel(&m_PluginList);
ui->espList->setModel(m_PluginListSortProxy);
ui->espList->sortByColumn(PluginList::COL_PRIORITY, Qt::AscendingOrder);
ui->espList->header()->restoreState(initSettings.value("plugin_list_state").toByteArray());
if (initSettings.contains("plugin_list_state")) {
ui->espList->header()->restoreState(initSettings.value("plugin_list_state").toByteArray());
}
ui->espList->installEventFilter(&m_PluginList);
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
for (int i = 0; i < ui->espList->header()->count(); ++i) {
ui->espList->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
}
ui->espList->header()->setSectionResizeMode(0, QHeaderView::Stretch);
#else
for (int i = 0; i < ui->espList->header()->count(); ++i) {
ui->espList->header()->setResizeMode(i, QHeaderView::ResizeToContents);
}
ui->espList->header()->setResizeMode(0, QHeaderView::Stretch);
#endif
resizeLists(initSettings.contains("mod_list_state"), initSettings.contains("plugin_list_state"));
QMenu *linkMenu = new QMenu(this);
linkMenu->addAction(QIcon(":/MO/gui/link"), tr("Toolbar"), this, SLOT(linkToolbar()));
@@ -316,6 +297,72 @@ MainWindow::~MainWindow()
delete m_DirectoryStructure;
}
void MainWindow::resizeLists(bool modListCustom, bool pluginListCustom)
{
if (!modListCustom) {
// resize mod list to fit content
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
for (int i = 0; i < ui->modList->header()->count(); ++i) {
ui->modList->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
}
ui->modList->header()->setSectionResizeMode(ModList::COL_NAME, QHeaderView::Stretch);
#else
for (int i = 0; i < ui->modList->header()->count(); ++i) {
ui->modList->header()->setResizeMode(i, QHeaderView::ResizeToContents);
}
ui->modList->header()->setResizeMode(ModList::COL_NAME, QHeaderView::Stretch);
#endif
}
if (!pluginListCustom) {
// resize plugin list to fit content
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
for (int i = 0; i < ui->espList->header()->count(); ++i) {
ui->espList->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
}
ui->espList->header()->setSectionResizeMode(0, QHeaderView::Stretch);
#else
for (int i = 0; i < ui->espList->header()->count(); ++i) {
ui->espList->header()->setResizeMode(i, QHeaderView::ResizeToContents);
}
ui->espList->header()->setResizeMode(0, QHeaderView::Stretch);
#endif
}
}
void MainWindow::allowListResize()
{
// allow resize on mod list
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
for (int i = 0; i < ui->modList->header()->count(); ++i) {
ui->modList->header()->setSectionResizeMode(i, QHeaderView::Interactive);
}
ui->modList->header()->setSectionResizeMode(ui->modList->header()->count() - 1, QHeaderView::Stretch);
#else
for (int i = 0; i < ui->modList->header()->count(); ++i) {
ui->modList->header()->setResizeMode(i, QHeaderView::Interactive);
}
ui->modList->header()->setResizeMode(ui->modList->header()->count() - 1, QHeaderView::Stretch);
#endif
// allow resize on plugin list
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
for (int i = 0; i < ui->espList->header()->count(); ++i) {
ui->espList->header()->setSectionResizeMode(i, QHeaderView::Interactive);
}
ui->espList->header()->setSectionResizeMode(ui->espList->header()->count() - 1, QHeaderView::Stretch);
#else
for (int i = 0; i < ui->espList->header()->count(); ++i) {
ui->espList->header()->setResizeMode(i, QHeaderView::Interactive);
}
ui->espList->header()->setResizeMode(ui->espList->header()->count() - 1, QHeaderView::Stretch);
#endif
}
void MainWindow::updateStyle(const QString&)
{
// no effect?
@@ -540,9 +587,12 @@ void MainWindow::saveArchiveList()
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"));
QTreeWidgetItem *tlItem = ui->bsaList->topLevelItem(i);
for (int j = 0; j < tlItem->childCount(); ++j) {
QTreeWidgetItem *item = tlItem->child(j);
if (item->checkState(0) == Qt::Checked) {
archiveFile.write(item->text(0).toUtf8().append("\r\n"));
}
}
}
} else {
@@ -707,17 +757,22 @@ void MainWindow::showEvent(QShowEvent *event)
// this has no visible impact when called before the ui is visible
int grouping = m_Settings.directInterface().value("group_state").toInt();
ui->groupCombo->setCurrentIndex(grouping);
allowListResize();
}
void MainWindow::closeEvent(QCloseEvent* event)
{
if (m_DownloadManager.downloadsInProgress() &&
QMessageBox::question(this, tr("Downloads in progress"),
if (m_DownloadManager.downloadsInProgress()) {
if (QMessageBox::question(this, tr("Downloads in progress"),
tr("There are still downloads in progress, do you really want to quit?"),
QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Cancel) {
event->ignore();
return;
event->ignore();
return;
} else {
m_DownloadManager.pauseAll();
}
}
setCursor(Qt::WaitCursor);
@@ -942,7 +997,7 @@ bool MainWindow::registerPlugin(QObject *plugin)
QObject *proxiedPlugin = proxy->instantiate(pluginName);
if (proxiedPlugin != NULL) {
if (registerPlugin(proxiedPlugin)) {
qDebug("loaded plugin \"%s\"", pluginName.toUtf8().constData());
qDebug("loaded plugin \"%s\"", QDir::toNativeSeparators(pluginName).toUtf8().constData());
} else {
qWarning("plugin \"%s\" failed to load", pluginName.toUtf8().constData());
}
@@ -993,7 +1048,7 @@ void MainWindow::loadPlugins()
pluginName.toUtf8().constData(), pluginLoader.errorString().toUtf8().constData());
} else {
if (registerPlugin(pluginLoader.instance())) {
qDebug("loaded plugin \"%s\"", pluginName.toUtf8().constData());
qDebug("loaded plugin \"%s\"", QDir::toNativeSeparators(pluginName).toUtf8().constData());
} else {
m_UnloadedPlugins.push_back(pluginName);
qWarning("plugin \"%s\" failed to load", pluginName.toUtf8().constData());
@@ -1570,7 +1625,8 @@ void MainWindow::refreshESPList()
m_CurrentProfile->writeModlist();
// clear list
m_PluginList.refresh(m_CurrentProfile->getName(), *m_DirectoryStructure,
m_PluginList.refresh(m_CurrentProfile->getName(),
*m_DirectoryStructure,
m_CurrentProfile->getPluginsFileName(),
m_CurrentProfile->getLoadOrderFileName(),
m_CurrentProfile->getLockedOrderFileName());
@@ -1794,6 +1850,10 @@ void MainWindow::readSettings()
restoreGeometry(settings.value("window_geometry").toByteArray());
}
if (settings.contains("window_split")) {
ui->splitter->restoreState(settings.value("window_split").toByteArray());
}
bool filtersVisible = settings.value("filters_visible", false).toBool();
setCategoryListVisible(filtersVisible);
ui->displayCategoriesBtn->setChecked(filtersVisible);
@@ -1832,7 +1892,8 @@ void MainWindow::storeSettings()
settings.setValue("compact_downloads", ui->compactBox->isChecked());
settings.setValue("ask_for_nexuspw", m_AskForNexusPW);
settings.setValue("window_geometry", this->saveGeometry());
settings.setValue("window_geometry", saveGeometry());
settings.setValue("window_split", ui->splitter->saveState());
settings.setValue("filters_visible", ui->displayCategoriesBtn->isChecked());
@@ -1955,6 +2016,9 @@ QString MainWindow::shortDescription(unsigned int key) const
case PROBLEM_PLUGINSNOTLOADED: {
return tr("Some plugins could not be loaded");
} break;
default: {
return tr("Description missing");
} break;
}
}
@@ -1969,15 +2033,18 @@ QString MainWindow::fullDescription(unsigned int key) const
result += "<ul>";
return result;
} break;
default: {
return tr("Description missing");
} break;
}
}
bool MainWindow::hasGuidedFix(unsigned int key) const
bool MainWindow::hasGuidedFix(unsigned int) const
{
return false;
}
void MainWindow::startGuidedFix(unsigned int key) const
void MainWindow::startGuidedFix(unsigned int) const
{
}
@@ -4254,10 +4321,9 @@ bool MainWindow::extractProgress(QProgressDialog &progress, int percentage, std:
void MainWindow::extractBSATriggered()
{
QTreeWidgetItem *item = ui->bsaList->topLevelItem(m_ContextRow);
QTreeWidgetItem *item = m_ContextItem;
QString targetFolder = FileDialogMemory::getExistingDirectory("extractBSA", this, tr("Extract BSA"));
if (!targetFolder.isEmpty()) {
BSA::Archive archive;
QString originPath = QDir::fromNativeSeparators(ToQString(m_DirectoryStructure->getOriginByName(ToWString(item->text(1))).getPath()));
@@ -4273,10 +4339,8 @@ void MainWindow::extractBSATriggered()
progress.setMaximum(100);
progress.setValue(0);
progress.show();
archive.extractAll(QDir::toNativeSeparators(targetFolder).toUtf8().constData(),
boost::bind(&MainWindow::extractProgress, this, boost::ref(progress), _1, _2));
if (result == BSA::ERROR_INVALIDHASHES) {
reportError(tr("This archive contains invalid hashes. Some files may be broken."));
}
@@ -4318,7 +4382,9 @@ void MainWindow::displayColumnSelection(const QPoint &pos)
void MainWindow::on_bsaList_customContextMenuRequested(const QPoint &pos)
{
m_ContextRow = ui->bsaList->indexOfTopLevelItem(ui->bsaList->itemAt(pos));
m_ContextItem = ui->bsaList->itemAt(pos);
// m_ContextRow = ui->bsaList->indexOfTopLevelItem(ui->bsaList->itemAt(pos));
QMenu menu;
menu.addAction(tr("Extract..."), this, SLOT(extractBSATriggered()));
@@ -4424,6 +4490,8 @@ void MainWindow::on_espList_customContextMenuRequested(const QPoint &pos)
}
}
menu.addSeparator();
if (hasLocked) {
menu.addAction(tr("Unlock load order"), this, SLOT(unlockESPIndex()));
}
+10
View File
@@ -442,6 +442,16 @@ private slots:
void expandModList(const QModelIndex &index);
/**
* @brief resize columns in mod list and plugin list to content
*/
void resizeLists(bool modListCustom, bool pluginListCustom);
/**
* @brief allow columns in mod list and plugin list to be resized
*/
void allowListResize();
private slots: // ui slots
// actions
void on_actionAdd_Profile_triggered();
+7 -52
View File
@@ -31,16 +31,7 @@
<property name="spacing">
<number>4</number>
</property>
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>6</number>
</property>
<item>
@@ -320,7 +311,7 @@ p, li { white-space: pre-wrap; }
<bool>false</bool>
</property>
<attribute name="headerDefaultSectionSize">
<number>10</number>
<number>20</number>
</attribute>
<attribute name="headerShowSortIndicator" stdset="0">
<bool>true</bool>
@@ -730,16 +721,7 @@ p, li { white-space: pre-wrap; }
<string notr="true">Archives</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>6</number>
</property>
<item>
@@ -818,16 +800,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye
<string>Data</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>6</number>
</property>
<item>
@@ -861,7 +834,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye
<bool>true</bool>
</property>
<attribute name="headerDefaultSectionSize">
<number>200</number>
<number>400</number>
</attribute>
<column>
<property name="text">
@@ -897,16 +870,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye
<string>Saves</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>6</number>
</property>
<item>
@@ -935,16 +899,7 @@ p, li { white-space: pre-wrap; }
<string>Downloads</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>2</number>
</property>
<item>
+1 -1
View File
@@ -759,7 +759,7 @@ std::vector<QString> ModInfoRegular::getIniTweaks() const
if (numTweaks != 0) {
qDebug("%d active ini tweaks in %s",
numTweaks, metaFileName.toUtf8().constData());
numTweaks, QDir::toNativeSeparators(metaFileName).toUtf8().constData());
}
for (int i = 0; i < numTweaks; ++i) {
+20
View File
@@ -801,6 +801,26 @@ bool ModList::eventFilter(QObject *obj, QEvent *event)
removeRow(rows[0].data(Qt::UserRole + 1).toInt(), QModelIndex());
}
return true;
} else if (keyEvent->key() == Qt::Key_Space) {
QItemSelectionModel *selectionModel = itemView->selectionModel();
const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel*>(selectionModel->model());
QModelIndex minRow, maxRow;
foreach (QModelIndex idx, selectionModel->selectedRows()) {
if (proxyModel != NULL) {
idx = proxyModel->mapToSource(idx);
}
if (!minRow.isValid() || (idx.row() < minRow.row())) {
minRow = idx;
}
if (!maxRow.isValid() || (idx.row() > maxRow.row())) {
maxRow = idx;
}
int oldState = idx.data(Qt::CheckStateRole).toInt();
setData(idx, oldState == Qt::Unchecked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
}
emit dataChanged(minRow, maxRow);
return true;
}
}
return QObject::eventFilter(obj, event);
+53 -26
View File
@@ -78,6 +78,15 @@ PluginList::PluginList(QObject *parent)
{
m_SaveTimer.setSingleShot(true);
connect(&m_SaveTimer, SIGNAL(timeout()), this, SIGNAL(saveTimer()));
m_Utf8Codec = QTextCodec::codecForName("utf-8");
m_LocalCodec = QTextCodec::codecForName("Windows-1252");
if (m_LocalCodec == NULL) {
qCritical("required 8-bit string-encoding not supported.");
m_LocalCodec = m_Utf8Codec;
}
}
@@ -203,21 +212,27 @@ void PluginList::enableESP(const QString &name)
void PluginList::enableAll()
{
for (std::vector<ESPInfo>::iterator iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
iter->m_Enabled = true;
if (QMessageBox::question(NULL, tr("Confirm"), tr("Really enable all plugins?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
for (std::vector<ESPInfo>::iterator iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
iter->m_Enabled = true;
}
startSaveTime();
}
startSaveTime();
}
void PluginList::disableAll()
{
for (std::vector<ESPInfo>::iterator iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
if (!iter->m_ForceEnabled) {
iter->m_Enabled = false;
if (QMessageBox::question(NULL, tr("Confirm"), tr("Really disable all plugins?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
for (std::vector<ESPInfo>::iterator iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
if (!iter->m_ForceEnabled) {
iter->m_Enabled = false;
}
}
startSaveTime();
}
startSaveTime();
}
@@ -300,7 +315,7 @@ void PluginList::readEnabledFrom(const QString &fileName)
QByteArray line = file.readLine();
QString modName;
if ((line.size() > 0) && (line.at(0) != '#')) {
modName = QString::fromUtf8(line.trimmed().constData());
modName = m_LocalCodec->toUnicode(line.trimmed().constData());
}
if (modName.size() > 0) {
std::map<QString, int>::iterator iter = m_ESPsByName.find(modName.toLower());
@@ -351,22 +366,7 @@ void PluginList::writePlugins(const QString &fileName, bool writeUnchecked) cons
throw MyException(tr("failed to open output file: %1").arg(fileName));
}
QTextCodec *textCodec = writeUnchecked ? QTextCodec::codecForName("utf-8")
: QTextCodec::codecForName("Windows-1252");
if (textCodec == NULL) {
QList<QByteArray> encodingList = QTextCodec::availableCodecs();
QString encodings;
QTextStream temp(&encodings);
foreach (QByteArray encoding, encodingList) {
temp << encoding << ", ";
}
qCritical("required string-encoding not supported. Available codecs: %s",
encodings.toUtf8().constData());
throw std::runtime_error(QObject::tr("encoding error, please report this as a bug and include the file "
"mo_interface.log!").toUtf8().constData());
}
QTextCodec *textCodec = writeUnchecked ? m_Utf8Codec : m_LocalCodec;
file.resize(0);
@@ -823,9 +823,15 @@ bool PluginList::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QAbstractItemView *itemView = qobject_cast<QAbstractItemView*>(obj);
if (itemView == NULL) {
return QObject::eventFilter(obj, event);
}
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if ((itemView != NULL) &&
(keyEvent->modifiers() == Qt::ControlModifier) &&
// ctrl+up and ctrl+down -> increase or decrease priority of selected plugins
if ((keyEvent->modifiers() == Qt::ControlModifier) &&
((keyEvent->key() == Qt::Key_Up) || (keyEvent->key() == Qt::Key_Down))) {
QItemSelectionModel *selectionModel = itemView->selectionModel();
const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel*>(selectionModel->model());
@@ -851,6 +857,27 @@ bool PluginList::eventFilter(QObject *obj, QEvent *event)
}
}
refreshLoadOrder();
return true;
} else if (keyEvent->key() == Qt::Key_Space) {
QItemSelectionModel *selectionModel = itemView->selectionModel();
const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel*>(selectionModel->model());
QModelIndex minRow, maxRow;
foreach (QModelIndex idx, selectionModel->selectedRows()) {
if (proxyModel != NULL) {
idx = proxyModel->mapToSource(idx);
}
if (!minRow.isValid() || (idx.row() < minRow.row())) {
minRow = idx;
}
if (!maxRow.isValid() || (idx.row() > maxRow.row())) {
maxRow = idx;
}
int oldState = idx.data(Qt::CheckStateRole).toInt();
setData(idx, oldState == Qt::Unchecked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
}
emit dataChanged(minRow, maxRow);
return true;
}
}
+3
View File
@@ -223,6 +223,9 @@ private:
QString m_CurrentProfile;
QFontMetrics m_FontMetrics;
QTextCodec *m_Utf8Codec;
QTextCodec *m_LocalCodec;
mutable QTimer m_SaveTimer;
};
+5
View File
@@ -54,6 +54,11 @@ public:
LEAK_TRACE;
}
~OriginConnection()
{
LEAK_UNTRACE;
}
FilesOrigin& createOrigin(const std::wstring &originName, const std::wstring &directory, int priority,
boost::shared_ptr<FileRegister> fileRegister, boost::shared_ptr<OriginConnection> originConnection) {
int newID = createID();
+2 -2
View File
@@ -1,7 +1,7 @@
#include "Winver.h"
#define VER_FILEVERSION 0,99,2,0
#define VER_FILEVERSION_STR "0,99,2,0\0"
#define VER_FILEVERSION 0,99,3,0
#define VER_FILEVERSION_STR "0,99,3,0\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION