mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
20
Commits
1.1.2
...
release_v1.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84cfa95254 | ||
|
|
264da60929 | ||
|
|
2db33523a1 | ||
|
|
540747177a | ||
|
|
739c3424e7 | ||
|
|
cabed9b268 | ||
|
|
c017f4a0d5 | ||
|
|
b1f1682790 | ||
|
|
28301e7486 | ||
|
|
2d0fab4482 | ||
|
|
c19c4820d8 | ||
|
|
8ab1b47943 | ||
|
|
ff272dcbbd | ||
|
|
98354cd1e7 | ||
|
|
129b76d7d2 | ||
|
|
a82b7e9949 | ||
|
|
0f8f7bf777 | ||
|
|
f4cf992700 | ||
|
|
bec644bac3 | ||
|
|
98e5e57a84 |
@@ -13,12 +13,12 @@ SUBDIRS = bsatk \
|
||||
nxmhandler \
|
||||
BossDummy \
|
||||
pythonRunner \
|
||||
boss_modified \
|
||||
esptk
|
||||
esptk \
|
||||
loot_cli
|
||||
|
||||
plugins.depends = pythonRunner
|
||||
hookdll.depends = shared
|
||||
organizer.depends = shared uibase plugins boss_modified
|
||||
organizer.depends = shared uibase plugins loot_cli
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
DESTDIR = outputd
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
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 "browserdialog.h"
|
||||
#include "ui_browserdialog.h"
|
||||
|
||||
#include "messagedialog.h"
|
||||
#include "report.h"
|
||||
#include "json.h"
|
||||
#include "persistentcookiejar.h"
|
||||
|
||||
#include <gameinfo.h>
|
||||
|
||||
#include <utility.h>
|
||||
#include <gameinfo.h>
|
||||
#include <QNetworkCookieJar>
|
||||
#include <QNetworkCookie>
|
||||
#include <QMenu>
|
||||
#include <QInputDialog>
|
||||
#include <QWebHistory>
|
||||
#include <QDir>
|
||||
#include <QWebFrame>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
|
||||
|
||||
BrowserDialog::BrowserDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::BrowserDialog)
|
||||
, m_AccessManager(new QNetworkAccessManager)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_AccessManager->setCookieJar(new PersistentCookieJar(
|
||||
QDir::fromNativeSeparators(MOBase::ToQString(MOShared::GameInfo::instance().getCacheDir())) + "/cookies.dat", this));
|
||||
|
||||
Qt::WindowFlags flags = windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint;
|
||||
Qt::WindowFlags helpFlag = Qt::WindowContextHelpButtonHint;
|
||||
flags = flags & (~helpFlag);
|
||||
setWindowFlags(flags);
|
||||
|
||||
m_Tabs = this->findChild<QTabWidget*>("browserTabWidget");
|
||||
|
||||
connect(m_Tabs, SIGNAL(tabCloseRequested(int)), this, SLOT(tabCloseRequested(int)));
|
||||
}
|
||||
|
||||
|
||||
BrowserDialog::~BrowserDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void BrowserDialog::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
// m_AccessManager->showCookies();
|
||||
QDialog::closeEvent(event);
|
||||
}
|
||||
|
||||
void BrowserDialog::initTab(BrowserView *newView)
|
||||
{
|
||||
newView->page()->setNetworkAccessManager(m_AccessManager);
|
||||
newView->page()->setForwardUnsupportedContent(true);
|
||||
|
||||
connect(newView, SIGNAL(loadProgress(int)), this, SLOT(progress(int)));
|
||||
connect(newView, SIGNAL(titleChanged(QString)), this, SLOT(titleChanged(QString)));
|
||||
connect(newView, SIGNAL(initTab(BrowserView*)), this, SLOT(initTab(BrowserView*)));
|
||||
connect(newView, SIGNAL(startFind()), this, SLOT(startSearch()));
|
||||
connect(newView, SIGNAL(urlChanged(QUrl)), this, SLOT(urlChanged(QUrl)));
|
||||
connect(newView, SIGNAL(openUrlInNewTab(QUrl)), this, SLOT(openInNewTab(QUrl)));
|
||||
connect(newView->page(), SIGNAL(downloadRequested(QNetworkRequest)), this, SLOT(downloadRequested(QNetworkRequest)));
|
||||
connect(newView->page(), SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(unsupportedContent(QNetworkReply*)));
|
||||
|
||||
ui->backBtn->setEnabled(false);
|
||||
ui->fwdBtn->setEnabled(false);
|
||||
m_Tabs->addTab(newView, tr("new"));
|
||||
newView->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
|
||||
newView->settings()->setAttribute(QWebSettings::AutoLoadImages, true);
|
||||
}
|
||||
|
||||
|
||||
void BrowserDialog::openInNewTab(const QUrl &url)
|
||||
{
|
||||
BrowserView *newView = new BrowserView(this);
|
||||
initTab(newView);
|
||||
newView->setUrl(url);
|
||||
}
|
||||
|
||||
|
||||
BrowserView *BrowserDialog::getCurrentView()
|
||||
{
|
||||
return qobject_cast<BrowserView*>(m_Tabs->currentWidget());
|
||||
}
|
||||
|
||||
|
||||
void BrowserDialog::urlChanged(const QUrl&)
|
||||
{
|
||||
BrowserView *currentView = getCurrentView();
|
||||
if (currentView != NULL) {
|
||||
ui->backBtn->setEnabled(currentView->history()->canGoBack());
|
||||
ui->fwdBtn->setEnabled(currentView->history()->canGoForward());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BrowserDialog::openUrl(const QUrl &url)
|
||||
{
|
||||
if (isHidden()) {
|
||||
show();
|
||||
}
|
||||
openInNewTab(url);
|
||||
}
|
||||
|
||||
|
||||
void BrowserDialog::maximizeWidth()
|
||||
{
|
||||
int viewportWidth = getCurrentView()->page()->viewportSize().width();
|
||||
int frameWidth = width() - viewportWidth;
|
||||
|
||||
int contentWidth = getCurrentView()->page()->mainFrame()->contentsSize().width();
|
||||
|
||||
QDesktopWidget screen;
|
||||
int currentScreen = screen.screenNumber(this);
|
||||
int screenWidth = screen.screenGeometry(currentScreen).size().width();
|
||||
|
||||
int targetWidth = std::min<int>(std::max<int>(viewportWidth, contentWidth) + frameWidth, screenWidth);
|
||||
this->resize(targetWidth, height());
|
||||
}
|
||||
|
||||
|
||||
void BrowserDialog::progress(int value)
|
||||
{
|
||||
ui->loadProgress->setValue(value);
|
||||
if (value == 100) {
|
||||
maximizeWidth();
|
||||
ui->loadProgress->setVisible(false);
|
||||
} else {
|
||||
ui->loadProgress->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BrowserDialog::titleChanged(const QString &title)
|
||||
{
|
||||
BrowserView *view = qobject_cast<BrowserView*>(sender());
|
||||
for (int i = 0; i < m_Tabs->count(); ++i) {
|
||||
if (m_Tabs->widget(i) == view) {
|
||||
m_Tabs->setTabText(i, title.mid(0, 15));
|
||||
m_Tabs->setTabToolTip(i, title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString BrowserDialog::guessFileName(const QString &url)
|
||||
{
|
||||
QRegExp uploadsExp(QString("http://.+/uploads/([^/]+)$"));
|
||||
if (uploadsExp.indexIn(url) != -1) {
|
||||
// these seem to be premium downloads
|
||||
return uploadsExp.cap(1);
|
||||
}
|
||||
|
||||
QRegExp filesExp(QString("http://.+\\?file=([^&]+)"));
|
||||
if (filesExp.indexIn(url) != -1) {
|
||||
// a regular manual download?
|
||||
return filesExp.cap(1);
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
void BrowserDialog::unsupportedContent(QNetworkReply *reply)
|
||||
{
|
||||
try {
|
||||
QWebPage *page = qobject_cast<QWebPage*>(sender());
|
||||
if (page == NULL) {
|
||||
qCritical("sender not a page");
|
||||
return;
|
||||
}
|
||||
BrowserView *view = qobject_cast<BrowserView*>(page->view());
|
||||
if (view == NULL) {
|
||||
qCritical("no view?");
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("unsupported: %s - %s", view->url().toString().toUtf8().constData(), reply->url().toString().toUtf8().constData());
|
||||
emit requestDownload(view->url(), reply);
|
||||
} catch (const std::exception &e) {
|
||||
if (isVisible()) {
|
||||
MessageDialog::showMessage(tr("failed to start download"), this);
|
||||
}
|
||||
qCritical("exception downloading unsupported content: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BrowserDialog::downloadRequested(const QNetworkRequest &request)
|
||||
{
|
||||
qCritical("download request %s ignored", request.url().toString().toUtf8().constData());
|
||||
}
|
||||
|
||||
|
||||
void BrowserDialog::tabCloseRequested(int index)
|
||||
{
|
||||
if (m_Tabs->count() == 1) {
|
||||
this->close();
|
||||
} else {
|
||||
m_Tabs->widget(index)->deleteLater();
|
||||
m_Tabs->removeTab(index);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserDialog::on_backBtn_clicked()
|
||||
{
|
||||
BrowserView *currentView = getCurrentView();
|
||||
if (currentView != NULL) {
|
||||
currentView->back();
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserDialog::on_fwdBtn_clicked()
|
||||
{
|
||||
BrowserView *currentView = getCurrentView();
|
||||
if (currentView != NULL) {
|
||||
currentView->forward();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BrowserDialog::startSearch()
|
||||
{
|
||||
ui->searchEdit->setFocus();
|
||||
}
|
||||
|
||||
|
||||
void BrowserDialog::on_searchEdit_returnPressed()
|
||||
{
|
||||
BrowserView *currentView = getCurrentView();
|
||||
if (currentView != NULL) {
|
||||
currentView->findText(ui->searchEdit->text(), QWebPage::FindWrapsAroundDocument);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserDialog::on_browserTabWidget_currentChanged(QWidget *current)
|
||||
{
|
||||
BrowserView *currentView = qobject_cast<BrowserView*>(current);
|
||||
if (currentView != NULL) {
|
||||
ui->backBtn->setEnabled(currentView->history()->canGoBack());
|
||||
ui->fwdBtn->setEnabled(currentView->history()->canGoForward());
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserDialog::on_refreshBtn_clicked()
|
||||
{
|
||||
getCurrentView()->reload();
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
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 BROWSERDIALOG_H
|
||||
#define BROWSERDIALOG_H
|
||||
|
||||
#include "browserview.h"
|
||||
#include "tutorialcontrol.h"
|
||||
#include <QDialog>
|
||||
#include <QProgressBar>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QTimer>
|
||||
#include <QWebView>
|
||||
#include <QQueue>
|
||||
#include <QTabWidget>
|
||||
#include <QAtomicInt>
|
||||
|
||||
|
||||
namespace Ui {
|
||||
class BrowserDialog;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief a dialog containing a webbrowser that is intended to browse the nexus network
|
||||
**/
|
||||
class BrowserDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief constructor
|
||||
*
|
||||
* @param accessManager the access manager to use for network requests
|
||||
* @param parent parent widget
|
||||
**/
|
||||
explicit BrowserDialog(QWidget *parent = 0);
|
||||
~BrowserDialog();
|
||||
|
||||
/**
|
||||
* @brief set the url to open. If automatic login is enabled, the url is opened after login
|
||||
*
|
||||
* @param url the url to open
|
||||
**/
|
||||
void openUrl(const QUrl &url);
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
* @brief emitted when the user starts a download
|
||||
* @param pageUrl url of the current web site from which the download was started
|
||||
* @param reply network reply of the started download
|
||||
*/
|
||||
void requestDownload(const QUrl &pageUrl, QNetworkReply *reply);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void closeEvent(QCloseEvent *);
|
||||
|
||||
private slots:
|
||||
|
||||
void initTab(BrowserView *newView);
|
||||
void openInNewTab(const QUrl &url);
|
||||
|
||||
void progress(int value);
|
||||
|
||||
void titleChanged(const QString &title);
|
||||
void unsupportedContent(QNetworkReply *reply);
|
||||
void downloadRequested(const QNetworkRequest &request);
|
||||
|
||||
void tabCloseRequested(int index);
|
||||
|
||||
void urlChanged(const QUrl &url);
|
||||
|
||||
void on_backBtn_clicked();
|
||||
|
||||
void on_fwdBtn_clicked();
|
||||
|
||||
void on_searchEdit_returnPressed();
|
||||
|
||||
void startSearch();
|
||||
|
||||
void on_browserTabWidget_currentChanged(QWidget *arg1);
|
||||
|
||||
void on_refreshBtn_clicked();
|
||||
|
||||
private:
|
||||
|
||||
QString guessFileName(const QString &url);
|
||||
|
||||
BrowserView *getCurrentView();
|
||||
|
||||
void maximizeWidth();
|
||||
|
||||
private:
|
||||
|
||||
Ui::BrowserDialog *ui;
|
||||
|
||||
QNetworkAccessManager *m_AccessManager;
|
||||
|
||||
QTabWidget *m_Tabs;
|
||||
|
||||
};
|
||||
|
||||
#endif // BROWSERDIALOG_H
|
||||
@@ -0,0 +1,289 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BrowserDialog</class>
|
||||
<widget class="QDialog" name="BrowserDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1008</width>
|
||||
<height>750</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Some Page</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="toolBar" native="true">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>226</red>
|
||||
<green>226</green>
|
||||
<blue>226</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>106</red>
|
||||
<green>106</green>
|
||||
<blue>106</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>199</red>
|
||||
<green>199</green>
|
||||
<blue>199</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>81</red>
|
||||
<green>81</green>
|
||||
<blue>81</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>226</red>
|
||||
<green>226</green>
|
||||
<blue>226</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>106</red>
|
||||
<green>106</green>
|
||||
<blue>106</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>199</red>
|
||||
<green>199</green>
|
||||
<blue>199</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>81</red>
|
||||
<green>81</green>
|
||||
<blue>81</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>120</red>
|
||||
<green>120</green>
|
||||
<blue>120</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>106</red>
|
||||
<green>106</green>
|
||||
<blue>106</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>120</red>
|
||||
<green>120</green>
|
||||
<blue>120</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>81</red>
|
||||
<green>81</green>
|
||||
<blue>81</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>81</red>
|
||||
<green>81</green>
|
||||
<blue>81</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="backBtn">
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/previous</normaloff>:/MO/gui/previous</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fwdBtn">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/next</normaloff>:/MO/gui/next</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="refreshBtn">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/refresh</normaloff>:/MO/gui/refresh</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</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="label_2">
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="searchEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="browserTabWidget">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
</property>
|
||||
<property name="tabsClosable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="loadProgress">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
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 "browserview.h"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QWebFrame>
|
||||
#include <QWebElement>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QMenu>
|
||||
#include <Shlwapi.h>
|
||||
#include "utility.h"
|
||||
|
||||
BrowserView::BrowserView(QWidget *parent)
|
||||
: QWebView(parent)
|
||||
{
|
||||
installEventFilter(this);
|
||||
|
||||
page()->settings()->setMaximumPagesInCache(10);
|
||||
}
|
||||
|
||||
|
||||
QWebView *BrowserView::createWindow(QWebPage::WebWindowType)
|
||||
{
|
||||
BrowserView *newView = new BrowserView(parentWidget());
|
||||
emit initTab(newView);
|
||||
return newView;
|
||||
}
|
||||
|
||||
|
||||
bool BrowserView::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::ShortcutOverride) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
||||
if (keyEvent->matches(QKeySequence::Find)) {
|
||||
emit startFind();
|
||||
} else if (keyEvent->matches(QKeySequence::FindNext)) {
|
||||
emit findAgain();
|
||||
}
|
||||
} else if (event->type() == QEvent::MouseButtonPress) {
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
if (mouseEvent->button() == Qt::MidButton) {
|
||||
mouseEvent->ignore();
|
||||
return true;
|
||||
}
|
||||
} else if (event->type() == QEvent::MouseButtonRelease) {
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
if (mouseEvent->button() == Qt::MidButton) {
|
||||
QWebHitTestResult hitTest = page()->frameAt(mouseEvent->pos())->hitTestContent(mouseEvent->pos());
|
||||
if (hitTest.linkUrl().isValid()) {
|
||||
emit openUrlInNewTab(hitTest.linkUrl());
|
||||
}
|
||||
mouseEvent->ignore();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QWebView::eventFilter(obj, event);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
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 NEXUSVIEW_H
|
||||
#define NEXUSVIEW_H
|
||||
|
||||
#include "finddialog.h"
|
||||
|
||||
#include <QWebView>
|
||||
#include <QWebPage>
|
||||
#include <QTabWidget>
|
||||
|
||||
/**
|
||||
* @brief web view used to display a nexus page
|
||||
**/
|
||||
class BrowserView : public QWebView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BrowserView(QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
* @brief emitted when the user opens a new window to be displayed in another tab
|
||||
*
|
||||
* @param newView the view for the newly opened window
|
||||
**/
|
||||
void initTab(BrowserView *newView);
|
||||
|
||||
/**
|
||||
* @brief emitted when the user requests a link to be opened in a new tab by middle-clicking
|
||||
*
|
||||
* @param url the url to open
|
||||
*/
|
||||
void openUrlInNewTab(const QUrl &url);
|
||||
|
||||
/**
|
||||
* @brief Ctrl-f was clicked. The containing dialog should activate its find-facility
|
||||
*/
|
||||
void startFind();
|
||||
|
||||
/**
|
||||
* @brief F3 was pressed. The containing dialog should search again
|
||||
*/
|
||||
void findAgain();
|
||||
|
||||
protected:
|
||||
|
||||
virtual QWebView *createWindow(QWebPage::WebWindowType type);
|
||||
|
||||
virtual bool eventFilter(QObject *obj, QEvent *event);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
QString m_FindPattern;
|
||||
bool m_MiddleClick;
|
||||
|
||||
};
|
||||
|
||||
#endif // NEXUSVIEW_H
|
||||
@@ -81,8 +81,8 @@ QVariant DownloadList::data(const QModelIndex &index, int role) const
|
||||
if (m_Manager->isInfoIncomplete(index.row())) {
|
||||
text += tr("Information missing, please select \"Query Info\" from the context menu to re-retrieve.");
|
||||
} else {
|
||||
NexusInfo info = m_Manager->getNexusInfo(index.row());
|
||||
text += QString("%1 (ID %2) %3").arg(info.m_ModName).arg(m_Manager->getModID(index.row())).arg(info.m_Version);
|
||||
const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(index.row());
|
||||
return QString("%1 (ID %2) %3").arg(info->modName).arg(m_Manager->getModID(index.row())).arg(info->version.canonicalString());
|
||||
}
|
||||
return text;
|
||||
} else {
|
||||
|
||||
@@ -40,8 +40,13 @@ DownloadListWidget::~DownloadListWidget()
|
||||
}
|
||||
|
||||
|
||||
DownloadListWidgetDelegate::DownloadListWidgetDelegate(DownloadManager *manager, QTreeView *view, QObject *parent)
|
||||
: QItemDelegate(parent), m_Manager(manager), m_ItemWidget(new DownloadListWidget), m_ContextRow(0), m_View(view)
|
||||
DownloadListWidgetDelegate::DownloadListWidgetDelegate(DownloadManager *manager, bool metaDisplay, QTreeView *view, QObject *parent)
|
||||
: QItemDelegate(parent)
|
||||
, m_Manager(manager)
|
||||
, m_MetaDisplay(metaDisplay)
|
||||
, m_ItemWidget(new DownloadListWidget)
|
||||
, m_ContextRow(0)
|
||||
, m_View(view)
|
||||
{
|
||||
m_NameLabel = m_ItemWidget->findChild<QLabel*>("nameLabel");
|
||||
m_SizeLabel = m_ItemWidget->findChild<QLabel*>("sizeLabel");
|
||||
@@ -95,7 +100,7 @@ void DownloadListWidgetDelegate::paintPendingDownload(int downloadIndex) const
|
||||
|
||||
void DownloadListWidgetDelegate::paintRegularDownload(int downloadIndex) const
|
||||
{
|
||||
QString name = m_Manager->getFileName(downloadIndex);
|
||||
QString name = m_MetaDisplay ? m_Manager->getDisplayName(downloadIndex) : m_Manager->getFileName(downloadIndex);
|
||||
if (name.length() > 53) {
|
||||
name.truncate(50);
|
||||
name.append("...");
|
||||
|
||||
@@ -54,7 +54,7 @@ class DownloadListWidgetDelegate : public QItemDelegate
|
||||
|
||||
public:
|
||||
|
||||
DownloadListWidgetDelegate(DownloadManager *manager, QTreeView *view, QObject *parent = 0);
|
||||
DownloadListWidgetDelegate(DownloadManager *manager, bool metaDisplay, QTreeView *view, QObject *parent = 0);
|
||||
~DownloadListWidgetDelegate();
|
||||
|
||||
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
@@ -105,6 +105,8 @@ private:
|
||||
DownloadListWidget *m_ItemWidget;
|
||||
DownloadManager *m_Manager;
|
||||
|
||||
bool m_MetaDisplay;
|
||||
|
||||
QLabel *m_NameLabel;
|
||||
QLabel *m_SizeLabel;
|
||||
QProgressBar *m_Progress;
|
||||
|
||||
@@ -40,8 +40,12 @@ DownloadListWidgetCompact::~DownloadListWidgetCompact()
|
||||
}
|
||||
|
||||
|
||||
DownloadListWidgetCompactDelegate::DownloadListWidgetCompactDelegate(DownloadManager *manager, QTreeView *view, QObject *parent)
|
||||
: QItemDelegate(parent), m_Manager(manager), m_ItemWidget(new DownloadListWidgetCompact), m_View(view)
|
||||
DownloadListWidgetCompactDelegate::DownloadListWidgetCompactDelegate(DownloadManager *manager, bool metaDisplay, QTreeView *view, QObject *parent)
|
||||
: QItemDelegate(parent)
|
||||
, m_Manager(manager)
|
||||
, m_MetaDisplay(metaDisplay)
|
||||
, m_ItemWidget(new DownloadListWidgetCompact)
|
||||
, m_View(view)
|
||||
{
|
||||
m_NameLabel = m_ItemWidget->findChild<QLabel*>("nameLabel");
|
||||
m_SizeLabel = m_ItemWidget->findChild<QLabel*>("sizeLabel");
|
||||
@@ -97,7 +101,7 @@ void DownloadListWidgetCompactDelegate::paintPendingDownload(int downloadIndex)
|
||||
|
||||
void DownloadListWidgetCompactDelegate::paintRegularDownload(int downloadIndex) const
|
||||
{
|
||||
QString name = m_Manager->getFileName(downloadIndex);
|
||||
QString name = m_MetaDisplay ? m_Manager->getDisplayName(downloadIndex) : m_Manager->getFileName(downloadIndex);
|
||||
if (name.length() > 53) {
|
||||
name.truncate(50);
|
||||
name.append("...");
|
||||
|
||||
@@ -54,7 +54,7 @@ class DownloadListWidgetCompactDelegate : public QItemDelegate
|
||||
|
||||
public:
|
||||
|
||||
DownloadListWidgetCompactDelegate(DownloadManager *manager, QTreeView *view, QObject *parent = 0);
|
||||
DownloadListWidgetCompactDelegate(DownloadManager *manager, bool metaDisplay, QTreeView *view, QObject *parent = 0);
|
||||
~DownloadListWidgetCompactDelegate();
|
||||
|
||||
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
@@ -103,6 +103,8 @@ private:
|
||||
DownloadListWidgetCompact *m_ItemWidget;
|
||||
DownloadManager *m_Manager;
|
||||
|
||||
bool m_MetaDisplay;
|
||||
|
||||
QLabel *m_NameLabel;
|
||||
QLabel *m_SizeLabel;
|
||||
QProgressBar *m_Progress;
|
||||
|
||||
+167
-79
@@ -49,7 +49,7 @@ static const char UNFINISHED[] = ".unfinished";
|
||||
unsigned int DownloadManager::DownloadInfo::s_NextDownloadID = 1U;
|
||||
|
||||
|
||||
DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const NexusInfo &nexusInfo, int modID, int fileID, const QStringList &URLs)
|
||||
DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const ModRepositoryFileInfo *fileInfo, const QStringList &URLs)
|
||||
{
|
||||
DownloadInfo *info = new DownloadInfo;
|
||||
info->m_DownloadID = s_NextDownloadID++;
|
||||
@@ -57,9 +57,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const Ne
|
||||
info->m_PreResumeSize = 0LL;
|
||||
info->m_Progress = 0;
|
||||
info->m_ResumePos = 0;
|
||||
info->m_ModID = modID;
|
||||
info->m_FileID = fileID;
|
||||
info->m_NexusInfo = nexusInfo;
|
||||
info->m_FileInfo = new ModRepositoryFileInfo(*fileInfo);
|
||||
info->m_Urls = URLs;
|
||||
info->m_CurrentUrl = 0;
|
||||
info->m_Tries = AUTOMATIC_RETRIES;
|
||||
@@ -104,17 +102,28 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con
|
||||
info->m_Output.setFileName(filePath);
|
||||
info->m_TotalSize = QFileInfo(filePath).size();
|
||||
info->m_PreResumeSize = info->m_TotalSize;
|
||||
info->m_ModID = metaFile.value("modID", 0).toInt();
|
||||
info->m_FileID = metaFile.value("fileID", 0).toInt();
|
||||
info->m_CurrentUrl = 0;
|
||||
info->m_Urls = metaFile.value("url", "").toString().split(";");
|
||||
info->m_Tries = 0;
|
||||
info->m_TaskProgressId = TaskProgressManager::instance().getId();
|
||||
info->m_NexusInfo.m_Name = metaFile.value("name", 0).toString();
|
||||
info->m_NexusInfo.m_ModName = metaFile.value("modName", "").toString();
|
||||
info->m_NexusInfo.m_Version = metaFile.value("version", 0).toString();
|
||||
info->m_NexusInfo.m_NewestVersion = metaFile.value("newestVersion", "").toString();
|
||||
info->m_NexusInfo.m_Category = metaFile.value("category", 0).toInt();
|
||||
int modID = metaFile.value("modID", 0).toInt();
|
||||
int fileID = metaFile.value("fileID", 0).toInt();
|
||||
info->m_FileInfo = new ModRepositoryFileInfo(modID, fileID);
|
||||
info->m_FileInfo->name = metaFile.value("name", "").toString();
|
||||
if (info->m_FileInfo->name == "0") {
|
||||
// bug in earlier version
|
||||
info->m_FileInfo->name = "";
|
||||
}
|
||||
info->m_FileInfo->modName = metaFile.value("modName", "").toString();
|
||||
info->m_FileInfo->modID = modID;
|
||||
info->m_FileInfo->fileID = fileID;
|
||||
info->m_FileInfo->description = metaFile.value("description").toString();
|
||||
info->m_FileInfo->version.parse(metaFile.value("version", "0").toString());
|
||||
info->m_FileInfo->newestVersion.parse(metaFile.value("newestVersion", "0").toString());
|
||||
info->m_FileInfo->categoryID = metaFile.value("category", 0).toInt();
|
||||
info->m_FileInfo->fileCategory = metaFile.value("fileCategory", 0).toInt();
|
||||
info->m_FileInfo->repository = metaFile.value("repository", "Nexus").toString();
|
||||
info->m_FileInfo->userData = metaFile.value("userData").toMap();
|
||||
|
||||
return info;
|
||||
}
|
||||
@@ -308,7 +317,7 @@ void DownloadManager::refreshList()
|
||||
|
||||
|
||||
bool DownloadManager::addDownload(const QStringList &URLs,
|
||||
int modID, int fileID, const NexusInfo &nexusInfo)
|
||||
int modID, int fileID, const ModRepositoryFileInfo *fileInfo)
|
||||
{
|
||||
QString fileName = QFileInfo(URLs.first()).fileName();
|
||||
if (fileName.isEmpty()) {
|
||||
@@ -316,20 +325,31 @@ bool DownloadManager::addDownload(const QStringList &URLs,
|
||||
}
|
||||
|
||||
QNetworkRequest request(URLs.first());
|
||||
return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, modID, fileID, nexusInfo);
|
||||
return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, modID, fileID, fileInfo);
|
||||
}
|
||||
|
||||
|
||||
bool DownloadManager::addDownload(QNetworkReply *reply, const ModRepositoryFileInfo *fileInfo)
|
||||
{
|
||||
QString fileName = getFileNameFromNetworkReply(reply);
|
||||
if (fileName.isEmpty()) {
|
||||
fileName = "unknown";
|
||||
}
|
||||
|
||||
return addDownload(reply, QStringList(reply->url().toString()), fileName, fileInfo->modID, fileInfo->fileID, fileInfo);
|
||||
}
|
||||
|
||||
|
||||
bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName,
|
||||
int modID, int fileID, const NexusInfo &nexusInfo)
|
||||
int modID, int fileID, const ModRepositoryFileInfo *fileInfo)
|
||||
{
|
||||
// download invoked from an already open network reply (i.e. download link in the browser)
|
||||
DownloadInfo *newDownload = DownloadInfo::createNew(nexusInfo, modID, fileID, URLs);
|
||||
DownloadInfo *newDownload = DownloadInfo::createNew(fileInfo, URLs);
|
||||
|
||||
QString baseName = fileName;
|
||||
|
||||
if (!nexusInfo.m_FileName.isEmpty()) {
|
||||
baseName = nexusInfo.m_FileName;
|
||||
if (!fileInfo->fileName.isEmpty()) {
|
||||
baseName = fileInfo->fileName;
|
||||
} else {
|
||||
QString dispoName = getFileNameFromNetworkReply(reply);
|
||||
|
||||
@@ -397,8 +417,7 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl
|
||||
|
||||
if (!resume) {
|
||||
newDownload->m_PreResumeSize = newDownload->m_Output.size();
|
||||
|
||||
removePending(newDownload->m_ModID, newDownload->m_FileID);
|
||||
removePending(newDownload->m_FileInfo->modID, newDownload->m_FileInfo->fileID);
|
||||
|
||||
emit aboutToUpdate();
|
||||
|
||||
@@ -424,7 +443,6 @@ void DownloadManager::addNXMDownload(const QString &url)
|
||||
}
|
||||
|
||||
emit aboutToUpdate();
|
||||
|
||||
m_PendingDownloads.append(std::make_pair(nxmInfo.modId(), nxmInfo.fileId()));
|
||||
|
||||
emit update(-1);
|
||||
@@ -635,16 +653,21 @@ void DownloadManager::queryInfo(int index)
|
||||
}
|
||||
DownloadInfo *info = m_ActiveDownloads[index];
|
||||
|
||||
if (info->m_FileInfo->repository != "Nexus") {
|
||||
qWarning("re-querying file info is currently only possible with Nexus");
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->m_State < DownloadManager::STATE_READY) {
|
||||
// UI shouldn't allow this
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->m_ModID == 0UL) {
|
||||
if (info->m_FileInfo->modID == 0UL) {
|
||||
QString fileName = getFileName(index);
|
||||
QString ignore;
|
||||
NexusInterface::interpretNexusFileName(fileName, ignore, info->m_ModID, true);
|
||||
if (info->m_ModID < 0) {
|
||||
NexusInterface::interpretNexusFileName(fileName, ignore, info->m_FileInfo->modID, true);
|
||||
if (info->m_FileInfo->modID < 0) {
|
||||
QString modIDString;
|
||||
while (modIDString.isEmpty()) {
|
||||
modIDString = QInputDialog::getText(NULL, tr("Please enter the nexus mod id"), tr("Mod ID:"), QLineEdit::Normal,
|
||||
@@ -657,12 +680,11 @@ void DownloadManager::queryInfo(int index)
|
||||
modIDString.clear();
|
||||
}
|
||||
}
|
||||
info->m_ModID = modIDString.toInt(NULL, 10);
|
||||
info->m_FileInfo->modID = modIDString.toInt(NULL, 10);
|
||||
}
|
||||
}
|
||||
info->m_ReQueried = true;
|
||||
setState(info, STATE_FETCHINGMODINFO);
|
||||
// m_RequestIDs.insert(m_NexusInterface->requestFiles(info->m_ModID, this, qVariantFromValue(static_cast<void*>(info))));
|
||||
}
|
||||
|
||||
|
||||
@@ -694,6 +716,34 @@ QString DownloadManager::getFilePath(int index) const
|
||||
return m_OutputDirectory + "/" + m_ActiveDownloads.at(index)->m_FileName;
|
||||
}
|
||||
|
||||
QString DownloadManager::getFileTypeString(int fileType)
|
||||
{
|
||||
switch (fileType) {
|
||||
case 1: return tr("Main");
|
||||
case 2: return tr("Update");
|
||||
case 3: return tr("Optional");
|
||||
case 4: return tr("Old");
|
||||
case 5: return tr("Misc");
|
||||
default: return tr("Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
QString DownloadManager::getDisplayName(int index) const
|
||||
{
|
||||
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
|
||||
throw MyException(tr("invalid index"));
|
||||
}
|
||||
|
||||
DownloadInfo *info = m_ActiveDownloads.at(index);
|
||||
|
||||
if (!info->m_FileInfo->name.isEmpty()) {
|
||||
return QString("%1 (%2, v%3)").arg(info->m_FileInfo->name)
|
||||
.arg(getFileTypeString(info->m_FileInfo->fileCategory))
|
||||
.arg(info->m_FileInfo->version.displayString());
|
||||
} else {
|
||||
return info->m_FileName;
|
||||
}
|
||||
}
|
||||
|
||||
QString DownloadManager::getFileName(int index) const
|
||||
{
|
||||
@@ -755,7 +805,11 @@ bool DownloadManager::isInfoIncomplete(int index) const
|
||||
}
|
||||
|
||||
DownloadInfo *info = m_ActiveDownloads.at(index);
|
||||
return (info->m_FileID == 0) || (info->m_ModID == 0) || info->m_NexusInfo.m_Version.isEmpty();
|
||||
if (info->m_FileInfo->repository != "Nexus") {
|
||||
// other repositories currently don't support re-querying info anyway
|
||||
return false;
|
||||
}
|
||||
return (info->m_FileInfo->fileID == 0) || (info->m_FileInfo->modID == 0) || !info->m_FileInfo->version.isValid();
|
||||
}
|
||||
|
||||
|
||||
@@ -764,7 +818,7 @@ int DownloadManager::getModID(int index) const
|
||||
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
|
||||
throw MyException(tr("invalid index"));
|
||||
}
|
||||
return m_ActiveDownloads.at(index)->m_ModID;
|
||||
return m_ActiveDownloads.at(index)->m_FileInfo->modID;
|
||||
}
|
||||
|
||||
bool DownloadManager::isHidden(int index) const
|
||||
@@ -776,13 +830,13 @@ bool DownloadManager::isHidden(int index) const
|
||||
}
|
||||
|
||||
|
||||
NexusInfo DownloadManager::getNexusInfo(int index) const
|
||||
const ModRepositoryFileInfo *DownloadManager::getFileInfo(int index) const
|
||||
{
|
||||
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
|
||||
throw MyException(tr("invalid index"));
|
||||
}
|
||||
|
||||
return m_ActiveDownloads.at(index)->m_NexusInfo;
|
||||
return m_ActiveDownloads.at(index)->m_FileInfo;
|
||||
}
|
||||
|
||||
|
||||
@@ -864,10 +918,10 @@ void DownloadManager::setState(DownloadManager::DownloadInfo *info, DownloadMana
|
||||
info->m_Reply->abort();
|
||||
} break;
|
||||
case STATE_FETCHINGMODINFO: {
|
||||
m_RequestIDs.insert(m_NexusInterface->requestDescription(info->m_ModID, this, info->m_DownloadID));
|
||||
m_RequestIDs.insert(m_NexusInterface->requestDescription(info->m_FileInfo->modID, this, info->m_DownloadID));
|
||||
} break;
|
||||
case STATE_FETCHINGFILEINFO: {
|
||||
m_RequestIDs.insert(m_NexusInterface->requestFiles(info->m_ModID, this, info->m_DownloadID));
|
||||
m_RequestIDs.insert(m_NexusInterface->requestFiles(info->m_FileInfo->modID, this, info->m_DownloadID));
|
||||
} break;
|
||||
case STATE_READY: {
|
||||
createMetaFile(info);
|
||||
@@ -933,16 +987,19 @@ void DownloadManager::downloadReadyRead()
|
||||
void DownloadManager::createMetaFile(DownloadInfo *info)
|
||||
{
|
||||
QSettings metaFile(QString("%1.meta").arg(info->m_Output.fileName()), QSettings::IniFormat);
|
||||
metaFile.setValue("modID", info->m_ModID);
|
||||
metaFile.setValue("fileID", info->m_FileID);
|
||||
metaFile.setValue("modID", info->m_FileInfo->modID);
|
||||
metaFile.setValue("fileID", info->m_FileInfo->fileID);
|
||||
metaFile.setValue("url", info->m_Urls.join(";"));
|
||||
metaFile.setValue("name", info->m_NexusInfo.m_Name);
|
||||
metaFile.setValue("modName", info->m_NexusInfo.m_ModName);
|
||||
metaFile.setValue("version", info->m_NexusInfo.m_Version);
|
||||
metaFile.setValue("fileTime", info->m_NexusInfo.m_FileTime);
|
||||
metaFile.setValue("fileCategory", info->m_NexusInfo.m_FileCategory);
|
||||
metaFile.setValue("newestVersion", info->m_NexusInfo.m_NewestVersion);
|
||||
metaFile.setValue("category", info->m_NexusInfo.m_Category);
|
||||
metaFile.setValue("name", info->m_FileInfo->name);
|
||||
metaFile.setValue("description", info->m_FileInfo->description);
|
||||
metaFile.setValue("modName", info->m_FileInfo->modName);
|
||||
metaFile.setValue("version", info->m_FileInfo->version.canonicalString());
|
||||
metaFile.setValue("newestVersion", info->m_FileInfo->newestVersion.canonicalString());
|
||||
metaFile.setValue("fileTime", info->m_FileInfo->fileTime);
|
||||
metaFile.setValue("fileCategory", info->m_FileInfo->fileCategory);
|
||||
metaFile.setValue("category", info->m_FileInfo->categoryID);
|
||||
metaFile.setValue("repository", info->m_FileInfo->repository);
|
||||
metaFile.setValue("userData", info->m_FileInfo->userData);
|
||||
metaFile.setValue("installed", info->m_State == DownloadManager::STATE_INSTALLED);
|
||||
metaFile.setValue("uninstalled", info->m_State == DownloadManager::STATE_UNINSTALLED);
|
||||
metaFile.setValue("paused", (info->m_State == DownloadManager::STATE_PAUSED) ||
|
||||
@@ -971,10 +1028,10 @@ void DownloadManager::nxmDescriptionAvailable(int, QVariant userData, QVariant r
|
||||
|
||||
DownloadInfo *info = downloadInfoByID(userData.toInt());
|
||||
if (info == NULL) return;
|
||||
info->m_NexusInfo.m_Category = result["category_id"].toInt();
|
||||
info->m_NexusInfo.m_ModName = result["name"].toString().trimmed();
|
||||
info->m_NexusInfo.m_NewestVersion = result["version"].toString();
|
||||
if (info->m_FileID != 0) {
|
||||
info->m_FileInfo->categoryID = result["category_id"].toInt();
|
||||
info->m_FileInfo->modName = result["name"].toString().trimmed();
|
||||
info->m_FileInfo->newestVersion.parse(result["version"].toString());
|
||||
if (info->m_FileInfo->fileID != 0) {
|
||||
setState(info, STATE_READY);
|
||||
} else {
|
||||
setState(info, STATE_FETCHINGFILEINFO);
|
||||
@@ -993,6 +1050,18 @@ QDateTime DownloadManager::matchDate(const QString &timeString)
|
||||
}
|
||||
|
||||
|
||||
EFileCategory convertFileCategory(int id)
|
||||
{
|
||||
// TODO: need to handle file categories in the mod page plugin
|
||||
switch (id) {
|
||||
case 0: return TYPE_MAIN;
|
||||
case 1: return TYPE_UPDATE;
|
||||
case 2: return TYPE_OPTION;
|
||||
default: return TYPE_MAIN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultData, int requestID)
|
||||
{
|
||||
std::set<int>::iterator idIter = m_RequestIDs.find(requestID);
|
||||
@@ -1024,14 +1093,14 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD
|
||||
QString fileNameVariant = fileName.mid(0).replace(' ', '_');
|
||||
if ((fileName == info->m_FileName) || (fileName == alternativeLocalName) ||
|
||||
(fileNameVariant == info->m_FileName) || (fileNameVariant == alternativeLocalName)) {
|
||||
info->m_NexusInfo.m_Name = fileInfo["name"].toString();
|
||||
info->m_NexusInfo.m_Version = fileInfo["version"].toString();
|
||||
if (info->m_NexusInfo.m_Version.isEmpty()) {
|
||||
info->m_NexusInfo.m_Version = info->m_NexusInfo.m_NewestVersion;
|
||||
info->m_FileInfo->name = fileInfo["name"].toString();
|
||||
info->m_FileInfo->version.parse(fileInfo["version"].toString());
|
||||
if (!info->m_FileInfo->version.isValid()) {
|
||||
info->m_FileInfo->version = info->m_FileInfo->newestVersion;
|
||||
}
|
||||
info->m_NexusInfo.m_FileCategory = fileInfo["category_id"].toInt();
|
||||
info->m_NexusInfo.m_FileTime = matchDate(fileInfo["date"].toString());
|
||||
info->m_FileID = fileInfo["id"].toInt();
|
||||
info->m_FileInfo->fileCategory = convertFileCategory(fileInfo["category_id"].toInt());
|
||||
info->m_FileInfo->fileTime = matchDate(fileInfo["date"].toString());
|
||||
info->m_FileInfo->fileID = fileInfo["id"].toInt();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -1050,16 +1119,16 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD
|
||||
}
|
||||
if (selection.exec() == QDialog::Accepted) {
|
||||
QVariantMap fileInfo = selection.getChoiceData().toMap();
|
||||
info->m_NexusInfo.m_Name = fileInfo["name"].toString();
|
||||
info->m_NexusInfo.m_Version = fileInfo["version"].toString();
|
||||
info->m_NexusInfo.m_FileCategory = fileInfo["category_id"].toInt();
|
||||
info->m_FileID = fileInfo["id"].toInt();
|
||||
info->m_FileInfo->name = fileInfo["name"].toString();
|
||||
info->m_FileInfo->version.parse(fileInfo["version"].toString());
|
||||
info->m_FileInfo->fileCategory = convertFileCategory(fileInfo["category_id"].toInt());
|
||||
info->m_FileInfo->fileID = fileInfo["id"].toInt();
|
||||
} else {
|
||||
emit showMessage(tr("No matching file found on Nexus! Maybe this file is no longer available or it was renamed?"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (info->m_FileID == 0) {
|
||||
if (info->m_FileInfo->fileID == 0) {
|
||||
qWarning("could not determine file id for %s (state %d)",
|
||||
info->m_FileName.toUtf8().constData(), info->m_State);
|
||||
}
|
||||
@@ -1078,19 +1147,26 @@ void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userD
|
||||
m_RequestIDs.erase(idIter);
|
||||
}
|
||||
|
||||
NexusInfo info;
|
||||
ModRepositoryFileInfo *info = new ModRepositoryFileInfo();
|
||||
|
||||
QVariantMap result = resultData.toMap();
|
||||
info.m_Name = result["name"].toString();
|
||||
qDebug("file info received for %s", qPrintable(info.m_Name));
|
||||
info.m_Version = result["version"].toString();
|
||||
if (info.m_Version.isEmpty()) {
|
||||
info.m_Version = info.m_NewestVersion;
|
||||
info->name = result["name"].toString();
|
||||
qDebug("file info received for %s", qPrintable(info->name));
|
||||
info->version.parse(result["version"].toString());
|
||||
if (!info->version.isValid()) {
|
||||
info->version = info->newestVersion;
|
||||
}
|
||||
info.m_FileName = result["uri"].toString();
|
||||
info.m_FileTime = matchDate(result["date"].toString());
|
||||
info->fileName = result["uri"].toString();
|
||||
info->fileCategory = result["category_id"].toInt();
|
||||
info->fileTime = matchDate(result["date"].toString());
|
||||
info->description = result["description"].toString();
|
||||
|
||||
m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, QVariant::fromValue(info)));
|
||||
info->repository = "Nexus";
|
||||
info->modID = modID;
|
||||
info->fileID = fileID;
|
||||
|
||||
QObject *test = info;
|
||||
m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(test)));
|
||||
}
|
||||
|
||||
|
||||
@@ -1138,7 +1214,7 @@ bool DownloadManager::ServerByPreference(const std::map<QString, int> &preferred
|
||||
|
||||
int DownloadManager::startDownloadURLs(const QStringList &urls)
|
||||
{
|
||||
addDownload(urls, -1);
|
||||
addDownload(urls, -1, -1, nullptr);
|
||||
return m_ActiveDownloads.size() - 1;
|
||||
}
|
||||
|
||||
@@ -1173,7 +1249,7 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u
|
||||
m_RequestIDs.erase(idIter);
|
||||
}
|
||||
|
||||
NexusInfo info = userData.value<NexusInfo>();
|
||||
ModRepositoryFileInfo *info = qobject_cast<ModRepositoryFileInfo*>(qvariant_cast<QObject*>(userData));
|
||||
QVariantList resultList = resultData.toList();
|
||||
if (resultList.length() == 0) {
|
||||
removePending(modID, fileID);
|
||||
@@ -1183,7 +1259,7 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u
|
||||
|
||||
std::sort(resultList.begin(), resultList.end(), boost::bind(&DownloadManager::ServerByPreference, m_PreferredServers, _1, _2));
|
||||
|
||||
info.m_DownloadMap = resultList;
|
||||
info->userData["downloadMap"] = resultList;
|
||||
|
||||
QStringList URLs;
|
||||
|
||||
@@ -1208,7 +1284,7 @@ void DownloadManager::nxmRequestFailed(int modID, int fileID, QVariant userData,
|
||||
|
||||
for (QVector<DownloadInfo*>::iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end(); ++iter, ++index) {
|
||||
DownloadInfo *info = *iter;
|
||||
if (info->m_ModID == modID) {
|
||||
if (info->m_FileInfo->modID == modID) {
|
||||
if (info->m_State < STATE_FETCHINGMODINFO) {
|
||||
m_ActiveDownloads.erase(iter);
|
||||
delete info;
|
||||
@@ -1246,7 +1322,7 @@ void DownloadManager::downloadFinished()
|
||||
textData) {
|
||||
if (info->m_Tries == 0) {
|
||||
if (textData && (reply->error() == QNetworkReply::NoError)) {
|
||||
emit showMessage(tr("Download failed. Server reported: %1").arg(readFileText(info->m_Output.fileName())));
|
||||
emit showMessage(tr("Download failed. Server reported: %1").arg(QString(data)));
|
||||
} else {
|
||||
emit showMessage(tr("Download failed: %1 (%2)").arg(reply->errorString()).arg(reply->error()));
|
||||
}
|
||||
@@ -1281,18 +1357,26 @@ void DownloadManager::downloadFinished()
|
||||
} else {
|
||||
|
||||
QString url = info->m_Urls[info->m_CurrentUrl];
|
||||
foreach (const QVariant &server, info->m_NexusInfo.m_DownloadMap) {
|
||||
QVariantMap serverMap = server.toMap();
|
||||
if (serverMap["URI"].toString() == url) {
|
||||
int deltaTime = info->m_StartTime.secsTo(QTime::currentTime());
|
||||
if (deltaTime > 5) {
|
||||
emit downloadSpeed(serverMap["Name"].toString(), (info->m_TotalSize - info->m_PreResumeSize) / deltaTime);
|
||||
} // no division by zero please! Also, if the download is shorter than a few seconds, the result is way to inprecise
|
||||
break;
|
||||
if (info->m_FileInfo->userData.contains("downloadMap")) {
|
||||
foreach (const QVariant &server, info->m_FileInfo->userData["downloadMap"].toList()) {
|
||||
QVariantMap serverMap = server.toMap();
|
||||
if (serverMap["URI"].toString() == url) {
|
||||
int deltaTime = info->m_StartTime.secsTo(QTime::currentTime());
|
||||
if (deltaTime > 5) {
|
||||
emit downloadSpeed(serverMap["Name"].toString(), (info->m_TotalSize - info->m_PreResumeSize) / deltaTime);
|
||||
} // no division by zero please! Also, if the download is shorter than a few seconds, the result is way to inprecise
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setState(info, STATE_FETCHINGMODINFO); // need to set this state before changing the file name, otherwise .unfinished is appended
|
||||
bool isNexus = info->m_FileInfo->repository == "Nexus";
|
||||
// need to change state before changing the file name, otherwise .unfinished is appended
|
||||
if (isNexus) {
|
||||
setState(info, STATE_FETCHINGMODINFO);
|
||||
} else {
|
||||
setState(info, STATE_NOFETCH);
|
||||
}
|
||||
|
||||
QString newName = getFileNameFromNetworkReply(reply);
|
||||
QString oldName = QFileInfo(info->m_Output).fileName();
|
||||
@@ -1302,6 +1386,10 @@ void DownloadManager::downloadFinished()
|
||||
info->setName(m_OutputDirectory + "/" + info->m_FileName, true); // don't rename but remove the ".unfinished" extension
|
||||
}
|
||||
|
||||
if (!isNexus) {
|
||||
setState(info, STATE_READY);
|
||||
}
|
||||
|
||||
emit update(index);
|
||||
}
|
||||
reply->close();
|
||||
|
||||
+29
-31
@@ -36,22 +36,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QSettings>
|
||||
|
||||
|
||||
struct NexusInfo {
|
||||
NexusInfo() : m_Category(0), m_FileCategory(0), m_Set(false) {}
|
||||
int m_Category;
|
||||
int m_FileCategory;
|
||||
QString m_Name;
|
||||
QString m_ModName;
|
||||
QString m_Version;
|
||||
QString m_NewestVersion;
|
||||
QString m_FileName;
|
||||
QVariantList m_DownloadMap;
|
||||
QDateTime m_FileTime;
|
||||
bool m_Set;
|
||||
};
|
||||
Q_DECLARE_METATYPE(NexusInfo)
|
||||
|
||||
|
||||
/*!
|
||||
* \brief manages downloading of files and provides progress information for gui elements
|
||||
**/
|
||||
@@ -71,6 +55,7 @@ public:
|
||||
STATE_ERROR,
|
||||
STATE_FETCHINGMODINFO,
|
||||
STATE_FETCHINGFILEINFO,
|
||||
STATE_NOFETCH,
|
||||
STATE_READY,
|
||||
STATE_INSTALLED,
|
||||
STATE_UNINSTALLED
|
||||
@@ -79,6 +64,7 @@ public:
|
||||
private:
|
||||
|
||||
struct DownloadInfo {
|
||||
~DownloadInfo() { delete m_FileInfo; }
|
||||
unsigned int m_DownloadID;
|
||||
QString m_FileName;
|
||||
QFile m_Output;
|
||||
@@ -86,14 +72,11 @@ private:
|
||||
QTime m_StartTime;
|
||||
qint64 m_PreResumeSize;
|
||||
int m_Progress;
|
||||
int m_ModID;
|
||||
int m_FileID;
|
||||
DownloadState m_State;
|
||||
int m_CurrentUrl;
|
||||
QStringList m_Urls;
|
||||
qint64 m_ResumePos;
|
||||
qint64 m_TotalSize;
|
||||
|
||||
QDateTime m_Created; // used as a cache in DownloadManager::getFileTime, may not be valid elsewhere
|
||||
|
||||
int m_Tries;
|
||||
@@ -101,11 +84,11 @@ private:
|
||||
|
||||
quint32 m_TaskProgressId;
|
||||
|
||||
NexusInfo m_NexusInfo;
|
||||
MOBase::ModRepositoryFileInfo *m_FileInfo;
|
||||
|
||||
bool m_Hidden;
|
||||
|
||||
static DownloadInfo *createNew(const NexusInfo &nexusInfo, int modID, int fileID, const QStringList &URLs);
|
||||
static DownloadInfo *createNew(const MOBase::ModRepositoryFileInfo *fileInfo, const QStringList &URLs);
|
||||
static DownloadInfo *createFromMeta(const QString &filePath, bool showHidden);
|
||||
|
||||
/**
|
||||
@@ -180,13 +163,20 @@ public:
|
||||
* @brief download from an already open network connection
|
||||
*
|
||||
* @param reply the network reply to download from
|
||||
* @param fileName the name to use for the file. This may be overridden by the name in the nexusInfo-structure or if the http stream specifies a name
|
||||
* @param modID the nexus mod id this download belongs to
|
||||
* @param fileID the nexus file id this download belongs to, if known. Defaults to 0.
|
||||
* @param nexusInfo information previously retrieved from the nexus network
|
||||
* @param fileInfo information about the file, like mod id, file id, version, ...
|
||||
* @return true if the download was started, false if it wasn't. The latter currently only happens if there is a duplicate and the user decides not to download again
|
||||
**/
|
||||
bool addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName, int modID, int fileID = 0, const NexusInfo &nexusInfo = NexusInfo());
|
||||
bool addDownload(QNetworkReply *reply, const MOBase::ModRepositoryFileInfo *fileInfo);
|
||||
|
||||
/**
|
||||
* @brief download from an already open network connection
|
||||
*
|
||||
* @param reply the network reply to download from
|
||||
* @param fileName the name to use for the file. This may be overridden by the name in the fileInfo-structure or if the http stream specifies a name
|
||||
* @param fileInfo information previously retrieved from the nexus network
|
||||
* @return true if the download was started, false if it wasn't. The latter currently only happens if there is a duplicate and the user decides not to download again
|
||||
**/
|
||||
bool addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName, int modID, int fileID = 0, const MOBase::ModRepositoryFileInfo *fileInfo = new MOBase::ModRepositoryFileInfo());
|
||||
|
||||
/**
|
||||
* @brief start a download using a nxm-link
|
||||
@@ -226,6 +216,14 @@ public:
|
||||
**/
|
||||
QString getFilePath(int index) const;
|
||||
|
||||
/**
|
||||
* @brief retrieve a descriptive name of the download specified by index
|
||||
*
|
||||
* @param index index of the file to look up
|
||||
* @return display name of the file
|
||||
**/
|
||||
QString getDisplayName(int index) const;
|
||||
|
||||
/**
|
||||
* @brief retrieve the filename of the download specified by index
|
||||
*
|
||||
@@ -297,7 +295,7 @@ public:
|
||||
* @param index index of the file to look up
|
||||
* @return the nexus mod information
|
||||
**/
|
||||
NexusInfo getNexusInfo(int index) const;
|
||||
const MOBase::ModRepositoryFileInfo *getFileInfo(int index) const;
|
||||
|
||||
/**
|
||||
* @brief mark a download as installed
|
||||
@@ -434,12 +432,10 @@ private:
|
||||
* @brief start a download from a url
|
||||
*
|
||||
* @param url the url to download from
|
||||
* @param modID the nexus mod id this download belongs to
|
||||
* @param fileID the nexus file id this download belongs to, if known. Defaults to 0.
|
||||
* @param nexusInfo information previously retrieved from the nexus network
|
||||
* @param fileInfo information previously retrieved from the mod page
|
||||
* @return true if the download was started, false if it wasn't. The latter currently only happens if there is a duplicate and the user decides not to download again
|
||||
**/
|
||||
bool addDownload(const QStringList &URLs, int modID, int fileID = 0, const NexusInfo &nexusInfo = NexusInfo());
|
||||
bool addDownload(const QStringList &URLs, int modID, int fileID, const MOBase::ModRepositoryFileInfo *fileInfo);
|
||||
|
||||
// important: the caller has to lock the list-mutex, otherwise the DownloadInfo-pointer might get invalidated at any time
|
||||
DownloadInfo *findDownload(QObject *reply, int *index = NULL) const;
|
||||
@@ -460,6 +456,8 @@ private:
|
||||
|
||||
void removePending(int modID, int fileID);
|
||||
|
||||
static QString getFileTypeString(int fileType);
|
||||
|
||||
private:
|
||||
|
||||
static const int AUTOMATIC_RETRIES = 3;
|
||||
|
||||
@@ -68,7 +68,6 @@ void ExecutablesList::init()
|
||||
{
|
||||
std::vector<ExecutableInfo> executables = GameInfo::instance().getExecutables();
|
||||
for (std::vector<ExecutableInfo>::const_iterator iter = executables.begin(); iter != executables.end(); ++iter) {
|
||||
ExecutableInfo test = *iter;
|
||||
addExecutableInternal(ToQString(iter->title),
|
||||
QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())).append("/").append(ToQString(iter->binary)),
|
||||
ToQString(iter->arguments), ToQString(iter->workingDirectory),
|
||||
|
||||
@@ -69,7 +69,7 @@ template <typename T> T resolveFunction(QLibrary &lib, const char *name)
|
||||
|
||||
InstallationManager::InstallationManager(QWidget *parent)
|
||||
: QObject(parent), m_ParentWidget(parent),
|
||||
m_InstallationProgress(parent), m_SupportedExtensions(boost::assign::list_of("zip")("rar")("7z")("fomod"))
|
||||
m_InstallationProgress(parent), m_SupportedExtensions(boost::assign::list_of("zip")("rar")("7z")("fomod")("001"))
|
||||
{
|
||||
QLibrary archiveLib("dlls\\archive.dll");
|
||||
if (!archiveLib.load()) {
|
||||
@@ -659,7 +659,9 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
|
||||
// open the archive and construct the directory tree the installers work on
|
||||
bool archiveOpen = m_CurrentArchive->open(ToWString(QDir::toNativeSeparators(fileName)).c_str(),
|
||||
new MethodCallback<InstallationManager, void, LPSTR>(this, &InstallationManager::queryPassword));
|
||||
|
||||
if (!archiveOpen) {
|
||||
qDebug("integrated archiver can't open %s. errorcode %d", qPrintable(fileName), m_CurrentArchive->getLastError());
|
||||
}
|
||||
ON_BLOCK_EXIT(std::bind(&InstallationManager::postInstallCleanup, this));
|
||||
|
||||
QScopedPointer<DirectoryTree> filesTree(archiveOpen ? createFilesTree() : NULL);
|
||||
@@ -676,8 +678,12 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
|
||||
}
|
||||
|
||||
// try only manual installers if that was requested
|
||||
if ((installResult == IPluginInstaller::RESULT_MANUALREQUESTED) && !installer->isManualInstaller()) {
|
||||
continue;
|
||||
if (installResult == IPluginInstaller::RESULT_MANUALREQUESTED) {
|
||||
if (!installer->isManualInstaller()) {
|
||||
continue;
|
||||
}
|
||||
} else if (installResult != IPluginInstaller::RESULT_NOTATTEMPTED) {
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -719,7 +725,8 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
|
||||
case IPluginInstaller::RESULT_FAILED: {
|
||||
return false;
|
||||
} break;
|
||||
case IPluginInstaller::RESULT_SUCCESS: {
|
||||
case IPluginInstaller::RESULT_SUCCESS:
|
||||
case IPluginInstaller::RESULT_SUCCESSCANCEL: {
|
||||
if (filesTree != NULL) {
|
||||
DirectoryTree::node_iterator iniTweakNode = filesTree->nodeFind(DirectoryTreeInformation("INI Tweaks"));
|
||||
hasIniTweaks = (iniTweakNode != filesTree->nodesEnd()) &&
|
||||
|
||||
+17
-24
@@ -80,24 +80,6 @@ using namespace MOBase;
|
||||
using namespace MOShared;
|
||||
|
||||
|
||||
void removeOldLogfiles()
|
||||
{
|
||||
QFileInfoList files = QDir(ToQString(GameInfo::instance().getLogDir())).entryInfoList(QStringList("ModOrganizer*.log"),
|
||||
QDir::Files, QDir::Name);
|
||||
|
||||
if (files.count() > 5) {
|
||||
QStringList deleteFiles;
|
||||
for (int i = 0; i < files.count() - 5; ++i) {
|
||||
deleteFiles.append(files.at(i).absoluteFilePath());
|
||||
}
|
||||
|
||||
if (!shellDelete(deleteFiles)) {
|
||||
qWarning("failed to remove log files: %s", qPrintable(windowsErrorString(::GetLastError())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set up required folders (for a first install or after an update or to fix a broken installation)
|
||||
bool bootstrap()
|
||||
{
|
||||
@@ -111,7 +93,7 @@ bool bootstrap()
|
||||
}
|
||||
|
||||
// cycle logfile
|
||||
removeOldLogfiles();
|
||||
removeOldFiles(ToQString(GameInfo::instance().getLogDir()), "ModOrganizer*.log", 5, QDir::Name);
|
||||
|
||||
// create organizer directories
|
||||
QString dirNames[] = {
|
||||
@@ -120,8 +102,7 @@ bool bootstrap()
|
||||
QDir::fromNativeSeparators(ToQString(gameInfo.getDownloadDir())),
|
||||
QDir::fromNativeSeparators(ToQString(gameInfo.getOverwriteDir())),
|
||||
QDir::fromNativeSeparators(ToQString(gameInfo.getLogDir())),
|
||||
QDir::fromNativeSeparators(ToQString(gameInfo.getTutorialDir())),
|
||||
QDir::fromNativeSeparators(ToQString(gameInfo.getOrganizerDirectory()) + "/boss")
|
||||
QDir::fromNativeSeparators(ToQString(gameInfo.getTutorialDir()))
|
||||
};
|
||||
static const int NUM_DIRECTORIES = sizeof(dirNames) / sizeof(QString);
|
||||
|
||||
@@ -158,6 +139,10 @@ bool bootstrap()
|
||||
// verify the hook-dll exists
|
||||
QString dllName = qApp->applicationDirPath() + "/" + ToQString(AppConfig::hookDLLName());
|
||||
|
||||
if (::GetModuleHandleW(ToWString(dllName).c_str()) != NULL) {
|
||||
throw std::runtime_error("hook.dll already loaded! You can't start Mod Organizer from within itself (not even indirectly)");
|
||||
}
|
||||
|
||||
HMODULE dllMod = ::LoadLibraryW(ToWString(dllName).c_str());
|
||||
if (dllMod == NULL) {
|
||||
throw windows_error("hook.dll is missing or invalid");
|
||||
@@ -330,7 +315,6 @@ bool HaveWriteAccess(const std::wstring &path)
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
MOApplication application(argc, argv);
|
||||
@@ -545,7 +529,11 @@ int main(int argc, char *argv[])
|
||||
arguments.removeAt(profileIndex);
|
||||
arguments.removeAt(profileIndex);
|
||||
}
|
||||
qDebug("configured profile: %s", qPrintable(selectedProfileName));
|
||||
if (selectedProfileName.isEmpty()) {
|
||||
qDebug("no configured profile");
|
||||
} else {
|
||||
qDebug("configured profile: %s", qPrintable(selectedProfileName));
|
||||
}
|
||||
|
||||
// if we have a command line parameter, it is either a nxm link or
|
||||
// a binary to start
|
||||
@@ -555,7 +543,12 @@ int main(int argc, char *argv[])
|
||||
arguments.removeFirst(); // remove application name (ModOrganizer.exe)
|
||||
arguments.removeFirst(); // remove binary name
|
||||
// pass the remaining parameters to the binary
|
||||
mainWindow.startApplication(exeName, arguments, QString(), selectedProfileName);
|
||||
try {
|
||||
mainWindow.startApplication(exeName, arguments, QString(), selectedProfileName);
|
||||
} catch (const std::exception &e) {
|
||||
reportError(QObject::tr("failed to start application: %1").arg(e.what()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+446
-121
File diff suppressed because it is too large
Load Diff
+28
-5
@@ -39,6 +39,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <imoinfo.h>
|
||||
#include <iplugintool.h>
|
||||
#include <iplugindiagnose.h>
|
||||
#include <ipluginmodpage.h>
|
||||
#include "settings.h"
|
||||
#include "downloadmanager.h"
|
||||
#include "installationmanager.h"
|
||||
@@ -49,6 +50,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "tutorialcontrol.h"
|
||||
#include "savegameinfowidgetgamebryo.h"
|
||||
#include "previewgenerator.h"
|
||||
#include "browserdialog.h"
|
||||
#include <guessedvalue.h>
|
||||
#include <directoryentry.h>
|
||||
#include <boost/signals2.hpp>
|
||||
@@ -104,7 +106,6 @@ public:
|
||||
|
||||
void setModListSorting(int index);
|
||||
void setESPListSorting(int index);
|
||||
void setCompactDownloads(bool compact);
|
||||
|
||||
bool setCurrentProfile(int index);
|
||||
bool setCurrentProfile(const QString &name);
|
||||
@@ -154,6 +155,9 @@ public:
|
||||
|
||||
void saveArchiveList();
|
||||
|
||||
void createStdoutPipe(HANDLE *stdOutRead, HANDLE *stdOutWrite);
|
||||
std::string readFromPipe(HANDLE stdOutRead);
|
||||
void processLOOTOut(const std::string &lootOut, std::string &reportURL, std::string &errorMessages, QProgressDialog &dialog);
|
||||
public slots:
|
||||
|
||||
void displayColumnSelection(const QPoint &pos);
|
||||
@@ -164,6 +168,7 @@ public slots:
|
||||
void directory_refreshed();
|
||||
|
||||
void toolPluginInvoke();
|
||||
void modPagePluginInvoke();
|
||||
|
||||
signals:
|
||||
|
||||
@@ -198,6 +203,7 @@ private:
|
||||
void actionToToolButton(QAction *&sourceAction);
|
||||
bool verifyPlugin(MOBase::IPlugin *plugin);
|
||||
void registerPluginTool(MOBase::IPluginTool *tool);
|
||||
void registerModPage(MOBase::IPluginModPage *modPage);
|
||||
bool registerPlugin(QObject *pluginObj, const QString &fileName);
|
||||
|
||||
void updateToolBar();
|
||||
@@ -207,8 +213,6 @@ private:
|
||||
|
||||
bool nexusLogin();
|
||||
|
||||
void saveCurrentESPList();
|
||||
|
||||
bool testForSteam();
|
||||
void startSteam();
|
||||
|
||||
@@ -236,8 +240,9 @@ private:
|
||||
* the changes made in the menu (which is the delta between the current menu selection and the reference mod)
|
||||
* @param menu the menu after editing by the user
|
||||
* @param modRow index of the mod to edit
|
||||
* @param referenceRow row of the reference mod
|
||||
*/
|
||||
void addRemoveCategoriesFromMenu(QMenu *menu, int modRow);
|
||||
void addRemoveCategoriesFromMenu(QMenu *menu, int modRow, int referenceRow);
|
||||
|
||||
/**
|
||||
* Sets category selections from menu; for multiple mods, this will completely
|
||||
@@ -288,12 +293,20 @@ private:
|
||||
static void setupNetworkProxy(bool activate);
|
||||
void activateProxy(bool activate);
|
||||
void installTranslator(const QString &name);
|
||||
void setBrowserGeometry(const QByteArray &geometry);
|
||||
|
||||
bool createBackup(const QString &filePath, const QDateTime &time);
|
||||
QString queryRestore(const QString &filePath);
|
||||
|
||||
private:
|
||||
|
||||
static const unsigned int PROBLEM_PLUGINSNOTLOADED = 1;
|
||||
static const unsigned int PROBLEM_TOOMANYPLUGINS = 2;
|
||||
|
||||
static const char *PATTERN_BACKUP_GLOB;
|
||||
static const char *PATTERN_BACKUP_REGEX;
|
||||
static const char *PATTERN_BACKUP_DATE;
|
||||
|
||||
private:
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
@@ -324,6 +337,7 @@ private:
|
||||
QString m_GamePath;
|
||||
|
||||
int m_ContextRow;
|
||||
QPersistentModelIndex m_ContextIdx;
|
||||
QTreeWidgetItem *m_ContextItem;
|
||||
QAction *m_ContextAction;
|
||||
|
||||
@@ -360,6 +374,7 @@ private:
|
||||
MOBase::IGameInfo *m_GameInfo;
|
||||
|
||||
std::vector<MOBase::IPluginDiagnose*> m_DiagnosisPlugins;
|
||||
std::vector<MOBase::IPluginModPage*> m_ModPages;
|
||||
std::vector<QString> m_UnloadedPlugins;
|
||||
|
||||
QFile m_PluginsCheck;
|
||||
@@ -370,6 +385,7 @@ private:
|
||||
std::vector<QTranslator*> m_Translators;
|
||||
|
||||
PreviewGenerator m_PreviewGenerator;
|
||||
BrowserDialog m_IntegratedBrowser;
|
||||
|
||||
QFileSystemWatcher m_SavesWatcher;
|
||||
|
||||
@@ -483,6 +499,7 @@ private slots:
|
||||
|
||||
void hookUpWindowTutorials();
|
||||
|
||||
void resumeDownload(int downloadIndex);
|
||||
void endorseMod(ModInfo::Ptr mod);
|
||||
void cancelModListEditor();
|
||||
|
||||
@@ -536,6 +553,8 @@ private slots:
|
||||
void about();
|
||||
void delayedRemove();
|
||||
|
||||
void requestDownload(const QUrl &url, QNetworkReply *reply);
|
||||
|
||||
private slots: // ui slots
|
||||
// actions
|
||||
void on_actionAdd_Profile_triggered();
|
||||
@@ -551,7 +570,6 @@ private slots: // ui slots
|
||||
void bsaList_itemMoved();
|
||||
void on_btnRefreshData_clicked();
|
||||
void on_categoriesList_customContextMenuRequested(const QPoint &pos);
|
||||
void on_compactBox_toggled(bool checked);
|
||||
void on_conflictsCheckBox_toggled(bool checked);
|
||||
void on_dataTree_customContextMenuRequested(const QPoint &pos);
|
||||
void on_executablesListBox_currentIndexChanged(int index);
|
||||
@@ -571,6 +589,11 @@ private slots: // ui slots
|
||||
void on_showHiddenBox_toggled(bool checked);
|
||||
void on_bsaList_itemChanged(QTreeWidgetItem *item, int column);
|
||||
void on_bossButton_clicked();
|
||||
|
||||
void on_saveButton_clicked();
|
||||
void on_restoreButton_clicked();
|
||||
void on_restoreModsButton_clicked();
|
||||
void on_saveModsButton_clicked();
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
||||
+118
-16
@@ -115,7 +115,7 @@
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6" stretch="0,1,0,0,0,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
@@ -170,6 +170,47 @@ p, li { white-space: pre-wrap; }
|
||||
</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="QPushButton" name="restoreModsButton">
|
||||
<property name="toolTip">
|
||||
<string>Restore Backup...</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/restore</normaloff>:/MO/gui/restore</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="saveModsButton">
|
||||
<property name="toolTip">
|
||||
<string>Create Backup</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/backup</normaloff>:/MO/gui/backup</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@@ -617,6 +658,68 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QPushButton" name="bossButton">
|
||||
<property name="text">
|
||||
<string>Sort</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/sort</normaloff>:/MO/gui/sort</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<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="QPushButton" name="restoreButton">
|
||||
<property name="toolTip">
|
||||
<string>Restore Backup...</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/restore</normaloff>:/MO/gui/restore</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="saveButton">
|
||||
<property name="toolTip">
|
||||
<string>Create Backup</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/backup</normaloff>:/MO/gui/backup</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="espList">
|
||||
<property name="minimumSize">
|
||||
@@ -725,13 +828,6 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="bossButton">
|
||||
<property name="text">
|
||||
<string>Sort</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -1025,14 +1121,7 @@ p, li { white-space: pre-wrap; }
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="compactBox">
|
||||
<property name="text">
|
||||
<string>Compact</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="showHiddenBox">
|
||||
<property name="text">
|
||||
@@ -1040,6 +1129,19 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<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="MOBase::LineEditClear" name="downloadFilterEdit">
|
||||
<property name="placeholderText">
|
||||
|
||||
@@ -23,8 +23,10 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <appconfig.h>
|
||||
#include <QFile>
|
||||
#include <QStringList>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
#include <QPlastiqueStyle>
|
||||
#include <QCleanlooksStyle>
|
||||
#endif
|
||||
#include <QProxyStyle>
|
||||
#include <QStyleFactory>
|
||||
#include <QPainter>
|
||||
@@ -123,12 +125,18 @@ bool MOApplication::notify(QObject *receiver, QEvent *event)
|
||||
|
||||
void MOApplication::updateStyle(const QString &fileName)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
if (fileName == "Fusion") {
|
||||
setStyle(QStyleFactory::create("fusion"));
|
||||
setStyleSheet("");
|
||||
#else
|
||||
if (fileName == "Plastique") {
|
||||
setStyle(new ProxyStyle(new QPlastiqueStyle));
|
||||
setStyleSheet("");
|
||||
} else if (fileName == "Cleanlooks") {
|
||||
setStyle(new ProxyStyle(new QCleanlooksStyle));
|
||||
setStyleSheet("");
|
||||
#endif
|
||||
} else {
|
||||
setStyle(new ProxyStyle(QStyleFactory::create(m_DefaultStyle)));
|
||||
if (QFile::exists(fileName)) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user