From 1c9018e9fdba7878b0ef605f81529c20ef3bbffe Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 13 Apr 2013 19:23:18 +0200 Subject: - bugfix: wrong multibyte to widechar conversion in hookdll breaks internationalization - bugfix: mod names not checked for validity on rename - bugfix: mod list wasn't invalidated after rename (regression?) - problem reports moved to separate dialog - ncc plugin now does the check for dotNet - python plugin wrapper started (only supports tools currently) - new ini editor plugin in python (non-functional currently) --- src/installationmanager.cpp | 2 - src/main.cpp | 19 ++++++++ src/mainwindow.cpp | 75 +++++++++++++++++++++++++------- src/mainwindow.h | 3 +- src/modlist.cpp | 15 ++++--- src/organizer.pro | 9 ++-- src/problemsdialog.cpp | 58 ++++++++++++++++++++++++ src/problemsdialog.h | 35 +++++++++++++++ src/problemsdialog.ui | 104 ++++++++++++++++++++++++++++++++++++++++++++ src/resources.qrc | 3 -- 10 files changed, 293 insertions(+), 30 deletions(-) create mode 100644 src/problemsdialog.cpp create mode 100644 src/problemsdialog.h create mode 100644 src/problemsdialog.ui (limited to 'src') diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp index 1abb19da..63945150 100644 --- a/src/installationmanager.cpp +++ b/src/installationmanager.cpp @@ -18,9 +18,7 @@ along with Mod Organizer. If not, see . */ #include "installationmanager.h" - #include "utility.h" - #include "report.h" #include "categories.h" #include "questionboxmemory.h" diff --git a/src/main.cpp b/src/main.cpp index 268bb98f..ab740467 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -64,6 +64,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #pragma comment(linker, "/manifestDependency:\"name='dlls' processorArchitecture='x86' version='1.0.0.0' type='win32' \"") @@ -284,6 +285,24 @@ int main(int argc, char *argv[]) QSplashScreen splash(pixmap); splash.show(); + { // extend path to include dll directory so plugins don't need a manifest + static const int BUFSIZE = 4096; + + boost::scoped_array oldPath(new TCHAR[BUFSIZE]); + DWORD offset = ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), BUFSIZE); + if (offset > BUFSIZE) { + oldPath.reset(new TCHAR[offset]); + ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), offset); + } + + std::tstring newPath(oldPath.get()); + newPath += TEXT(";"); + newPath += ToWString(QDir::toNativeSeparators(QCoreApplication::applicationDirPath())).c_str(); + newPath += TEXT("\\dlls"); + + ::SetEnvironmentVariable(TEXT("PATH"), newPath.c_str()); + } + registerMetaTypes(); QStringList arguments = application.arguments(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6b546d4d..2fd47537 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -54,9 +54,11 @@ along with Mod Organizer. If not, see . #include "csvbuilder.h" #include "gameinfoimpl.h" #include "savetextasdialog.h" +#include "problemsdialog.h" #include #include #include +#include #include #include #include @@ -84,14 +86,13 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include #include #include #include #include #include - - #include @@ -394,8 +395,7 @@ void MainWindow::updateToolBar() void MainWindow::updateProblemsButton() { - QString problemDescription; - if (checkForProblems(problemDescription)) { + if (checkForProblems()) { ui->actionProblems->setEnabled(true); ui->actionProblems->setIconText(tr("Problems")); ui->actionProblems->setToolTip(tr("There are potential problems with your setup")); @@ -436,17 +436,19 @@ bool MainWindow::errorReported(QString &logFile) } -bool MainWindow::checkForProblems(QString &problemDescription) +bool MainWindow::checkForProblems() { - problemDescription = ""; +// problemDescription = ""; foreach (IPluginDiagnose *diagnose, m_DiagnosisPlugins) { std::vector activeProblems = diagnose->activeProblems(); - foreach (unsigned int key, activeProblems) { - problemDescription.append(tr("
  • %1
  • ").arg(diagnose->shortDescription(key))); + if (activeProblems.size() > 0) { + return true; } } + return false; +/* QString NCCBinary = QCoreApplication::applicationDirPath().mid(0).append("/NCC/NexusClientCLI.exe"); if (!QFile::exists(NCCBinary)) { problemDescription.append(tr("
  • NCC not installed. You won't be able to install some scripted mod-installers. Get NCC from the MO page on nexus
  • ")); @@ -479,7 +481,7 @@ bool MainWindow::checkForProblems(QString &problemDescription) } else { ui->actionProblems->setToolTip(tr("Everything seems to be in order")); } - return res; + return res;*/ } @@ -886,6 +888,8 @@ void MainWindow::toolPluginInvoke() plugin->display(); } catch (const std::exception &e) { reportError(tr("Plugin \"%1\" failed: %2").arg(plugin->name()).arg(e.what())); + } catch (...) { + reportError(tr("Plugin \"%1\" failed").arg(plugin->name())); } } @@ -912,13 +916,15 @@ bool MainWindow::registerPlugin(QObject *plugin) m_Settings.registerPlugin(pluginObj); } + bool addon = false; + { // diagnosis plugins IPluginDiagnose *diagnose = qobject_cast(plugin); if (diagnose != NULL) { m_DiagnosisPlugins.push_back(diagnose); + addon = true; } } - { // tool plugins IPluginTool *tool = qobject_cast(plugin); if (verifyPlugin(tool)) { @@ -934,7 +940,25 @@ bool MainWindow::registerPlugin(QObject *plugin) return true; } } - return false; + { // proxy plugins + IPluginProxy *proxy = qobject_cast(plugin); + if (verifyPlugin(proxy)) { + QStringList pluginNames = proxy->pluginList(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath())); + foreach (const QString &pluginName, pluginNames) { + QObject *proxiedPlugin = proxy->instantiate(pluginName); + if (proxiedPlugin != NULL) { + if (registerPlugin(proxiedPlugin)) { + qDebug("loaded plugin \"%s\"", pluginName.toUtf8().constData()); + } else { + qWarning("plugin \"%s\" failed to load", pluginName.toUtf8().constData()); + } + } + } + return true; + } + } + + return addon; } @@ -978,12 +1002,20 @@ IGameInfo &MainWindow::gameInfo() const QString MainWindow::profileName() const { - return m_CurrentProfile->getName(); + if (m_CurrentProfile != NULL) { + return m_CurrentProfile->getName(); + } else { + return ""; + } } QString MainWindow::profilePath() const { - return m_CurrentProfile->getPath(); + if (m_CurrentProfile != NULL) { + return m_CurrentProfile->getPath(); + } else { + return ""; + } } QString MainWindow::downloadsPath() const @@ -1045,6 +1077,12 @@ QVariant MainWindow::pluginSetting(const QString &pluginName, const QString &key return m_Settings.pluginSetting(pluginName, key); } +QString MainWindow::pluginDataPath() const +{ + QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath()); + return pluginPath + "/data"; +} + void MainWindow::startSteam() { @@ -4058,11 +4096,16 @@ void MainWindow::on_bsaList_itemChanged(QTreeWidgetItem*, int) m_CheckBSATimer.start(500); } + void MainWindow::on_actionProblems_triggered() { - QString problemDescription; - checkForProblems(problemDescription); - QMessageBox::information(this, tr("Problems"), problemDescription); +// QString problemDescription; +// checkForProblems(problemDescription); +// QMessageBox::information(this, tr("Problems"), problemDescription); + ProblemsDialog problems(m_DiagnosisPlugins, this); + if (problems.hasProblems()) { + problems.exec(); + } } void MainWindow::setCategoryListVisible(bool visible) diff --git a/src/mainwindow.h b/src/mainwindow.h index 5880fcb8..e50a8c23 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -103,6 +103,7 @@ public: virtual bool removeMod(MOBase::IModInterface *mod); virtual void modDataChanged(MOBase::IModInterface *mod); virtual QVariant pluginSetting(const QString &pluginName, const QString &key) const; + virtual QString pluginDataPath() const; void addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, ModInfo::Ptr info); @@ -205,7 +206,7 @@ private: bool extractProgress(QProgressDialog &extractProgress, int percentage, std::string fileName); - bool checkForProblems(QString &problemDescription); + bool checkForProblems(); int getBinaryExecuteInfo(const QFileInfo &targetInfo, QFileInfo &binaryInfo, QString &arguments); QTreeWidgetItem *addFilterItem(QTreeWidgetItem *root, const QString &name, int categoryID); diff --git a/src/modlist.cpp b/src/modlist.cpp index f186ce8e..2183ce09 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -20,12 +20,11 @@ along with Mod Organizer. If not, see . #include "modlist.h" #include "report.h" -#include "utility.h" #include "messagedialog.h" #include "installationtester.h" #include "qtgroupingproxy.h" #include - +#include #include #include #include @@ -301,19 +300,25 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const bool ModList::renameMod(int index, const QString &newName) { + QString nameFixed = newName; + if (!fixDirectoryName(nameFixed) || nameFixed.isEmpty()) { + MessageDialog::showMessage(tr("Invalid name"), NULL); + return false; + } + // before we rename, write back the current profile so we don't lose changes and to ensure // there is no scheduled asynchronous rewrite anytime soon m_Profile->writeModlistNow(); ModInfo::Ptr modInfo = ModInfo::getByIndex(index); QString oldName = modInfo->name(); - modInfo->setName(newName); + modInfo->setName(nameFixed); // this just broke all profiles! The recipient of modRenamed has to do some magic // to can't write the currently active profile back - emit modRenamed(oldName, newName); + emit modRenamed(oldName, nameFixed); // invalidate the currently displayed state of this list -// notifyChange(-1); + notifyChange(-1); return true; } diff --git a/src/organizer.pro b/src/organizer.pro index 582ba633..cfdf990b 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -78,7 +78,8 @@ SOURCES += \ csvbuilder.cpp \ savetextasdialog.cpp \ qtgroupingproxy.cpp \ - modlistview.cpp + modlistview.cpp \ + problemsdialog.cpp HEADERS += \ transfersavesdialog.h \ @@ -144,7 +145,8 @@ HEADERS += \ csvbuilder.h \ savetextasdialog.h \ qtgroupingproxy.h \ - modlistview.h + modlistview.h \ + problemsdialog.h FORMS += \ transfersavesdialog.ui \ @@ -174,7 +176,8 @@ FORMS += \ baincomplexinstallerdialog.ui \ activatemodsdialog.ui \ profileinputdialog.ui \ - savetextasdialog.ui + savetextasdialog.ui \ + problemsdialog.ui INCLUDEPATH += ../shared ../archive ../uibase ../bsatk "$(BOOSTPATH)" diff --git a/src/problemsdialog.cpp b/src/problemsdialog.cpp new file mode 100644 index 00000000..e0837f45 --- /dev/null +++ b/src/problemsdialog.cpp @@ -0,0 +1,58 @@ +#include "problemsdialog.h" +#include "ui_problemsdialog.h" +#include +#include +#include +#include + + +using namespace MOBase; + + +ProblemsDialog::ProblemsDialog(std::vector diagnosePlugins, QWidget *parent) + : QDialog(parent), ui(new Ui::ProblemsDialog) +{ + ui->setupUi(this); + + foreach (IPluginDiagnose *diagnose, diagnosePlugins) { + std::vector activeProblems = diagnose->activeProblems(); + foreach (unsigned int key, activeProblems) { + QTreeWidgetItem *newItem = new QTreeWidgetItem(); + newItem->setText(0, diagnose->shortDescription(key)); + newItem->setData(0, Qt::UserRole, diagnose->fullDescription(key)); + + if (diagnose->hasGuidedFix(key)) { + ui->problemsWidget->setItemWidget(newItem, 1, new QPushButton(tr("Fix"))); + } else { + newItem->setText(1, tr("No guided fix :(")); + } + ui->problemsWidget->addTopLevelItem(newItem); + } + } + connect(ui->problemsWidget, SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged())); + connect(ui->descriptionText, SIGNAL(anchorClicked(QUrl)), this, SLOT(urlClicked(QUrl))); +} + + +ProblemsDialog::~ProblemsDialog() +{ + delete ui; +} + + +bool ProblemsDialog::hasProblems() const +{ + return ui->problemsWidget->topLevelItemCount() != 0; +} + +void ProblemsDialog::selectionChanged() +{ + QString text = ui->problemsWidget->currentItem()->data(0, Qt::UserRole).toString(); + ui->descriptionText->setText(text); + ui->descriptionText->setLineWrapMode(text.contains('\n') ? QTextEdit::NoWrap : QTextEdit::WidgetWidth); +} + +void ProblemsDialog::urlClicked(const QUrl &url) +{ + ::ShellExecuteW(NULL, L"open", ToWString(url.toString()).c_str(), NULL, NULL, SW_SHOWNORMAL); +} diff --git a/src/problemsdialog.h b/src/problemsdialog.h new file mode 100644 index 00000000..299faf8d --- /dev/null +++ b/src/problemsdialog.h @@ -0,0 +1,35 @@ +#ifndef PROBLEMSDIALOG_H +#define PROBLEMSDIALOG_H + + +#include +#include +#include + + +namespace Ui { +class ProblemsDialog; +} + + +class ProblemsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ProblemsDialog(std::vector diagnosePlugins, QWidget *parent = 0); + ~ProblemsDialog(); + + bool hasProblems() const; + +private slots: + + void selectionChanged(); + void urlClicked(const QUrl &url); + +private: + + Ui::ProblemsDialog *ui; +}; + +#endif // PROBLEMSDIALOG_H diff --git a/src/problemsdialog.ui b/src/problemsdialog.ui new file mode 100644 index 00000000..b194bf31 --- /dev/null +++ b/src/problemsdialog.ui @@ -0,0 +1,104 @@ + + + ProblemsDialog + + + + 0 + 0 + 574 + 376 + + + + Problems + + + + + + 2 + + + false + + + 420 + + + + 1 + + + + + 2 + + + + + + + + QTextEdit::NoWrap + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + ProblemsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ProblemsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/resources.qrc b/src/resources.qrc index a743ba39..855a23fc 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -50,8 +50,5 @@ resources/conflict-overwritten.png resources/conflict-redundant.png resources/accessories-text-editor.png - resources/network-idle.png - resources/network-offline.png - resources/network-error.png -- cgit v1.3.1