mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
35
Commits
1.1.2
...
release_v1.2.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0feb4b702d | ||
|
|
5a4b6e70fd | ||
|
|
18574c2ba8 | ||
|
|
1eb783aae3 | ||
|
|
93a19799b8 | ||
|
|
2a31eb40fb | ||
|
|
cf0a1bc2be | ||
|
|
48c8cca578 | ||
|
|
977b407525 | ||
|
|
f4b1aba61a | ||
|
|
0eb1662a0e | ||
|
|
164ec25a75 | ||
|
|
6fb36d6c02 | ||
|
|
ea1f959ad5 | ||
|
|
7cf3b3455b | ||
|
|
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
|
||||
|
||||
+33
-10
@@ -22,6 +22,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QRegExp>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
|
||||
namespace BBCode {
|
||||
@@ -43,7 +44,6 @@ public:
|
||||
// extract the tag name
|
||||
m_TagNameExp.indexIn(input, 1, QRegExp::CaretAtOffset);
|
||||
QString tagName = m_TagNameExp.cap(0).toLower();
|
||||
//qDebug("tag name %s", tagName.toUtf8().constData());
|
||||
TagMap::iterator tagIter = m_TagMap.find(tagName);
|
||||
if (tagIter != m_TagMap.end()) {
|
||||
// recognized tag
|
||||
@@ -60,7 +60,21 @@ public:
|
||||
length = closeTagPos + closeTag.length();
|
||||
QString temp = input.mid(0, length);
|
||||
if (tagIter->second.first.indexIn(temp) == 0) {
|
||||
return temp.replace(tagIter->second.first, tagIter->second.second);
|
||||
if (tagIter->second.second.isEmpty()) {
|
||||
if (tagName == "color") {
|
||||
QString color = tagIter->second.first.cap(1);
|
||||
QString content = tagIter->second.first.cap(2);
|
||||
auto colIter = m_ColorMap.find(color.toLower());
|
||||
if (colIter != m_ColorMap.end()) {
|
||||
color = colIter->second;
|
||||
}
|
||||
return temp.replace(tagIter->second.first, QString("<font style=\"color: #%1;\">%2</font>").arg(color, content));
|
||||
} else {
|
||||
qWarning("don't know how to deal with tag %s", qPrintable(tagName));
|
||||
}
|
||||
} else {
|
||||
return temp.replace(tagIter->second.first, tagIter->second.second);
|
||||
}
|
||||
} else {
|
||||
// expression doesn't match. either the input string is invalid
|
||||
// or the expression is
|
||||
@@ -96,7 +110,7 @@ private:
|
||||
m_TagMap["size="] = std::make_pair(QRegExp("\\[size=([^\\]]*)\\](.*)\\[/size\\]"),
|
||||
"<font size=\"\\1\">\\2</font>");
|
||||
m_TagMap["color="] = std::make_pair(QRegExp("\\[color=([^\\]]*)\\](.*)\\[/color\\]"),
|
||||
"<font style=\"color: #\\1;\">\\2</font>");
|
||||
"");
|
||||
m_TagMap["font="] = std::make_pair(QRegExp("\\[font=([^\\]]*)\\](.*)\\[/font\\]"),
|
||||
"<font face=\\1>\\2</font>");
|
||||
m_TagMap["center"] = std::make_pair(QRegExp("\\[center\\](.*)\\[/center\\]"),
|
||||
@@ -139,17 +153,25 @@ private:
|
||||
"<a href=\"\\1\">\\1</a>");
|
||||
m_TagMap["url="] = std::make_pair(QRegExp("\\[url=([^\\]]*)\\](.*)\\[/url\\]"),
|
||||
"<a href=\"\\1\">\\2</a>");
|
||||
/* m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"),
|
||||
"<img src=\"\\1\"/>");
|
||||
m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"),
|
||||
"<img src=\"\\2\" align=\"\\1\" />");*/
|
||||
m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"), "");
|
||||
m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"), "");
|
||||
m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"), " ");
|
||||
m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"), " ");
|
||||
m_TagMap["email="] = std::make_pair(QRegExp("\\[email=\"?([^\\]]*)\"?\\](.*)\\[/email\\]"),
|
||||
"<a href=\"mailto:\\1\">\\2</a>");
|
||||
m_TagMap["youtube"] = std::make_pair(QRegExp("\\[youtube\\](.*)\\[/youtube\\]"),
|
||||
"<a href=\"http://www.youtube.com/v/\\1\">http://www.youtube.com/v/\\1</a>");
|
||||
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("red", "FF0000"));
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("green", "00FF00"));
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("blue", "0000FF"));
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("black", "000000"));
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("gray", "7F7F7F"));
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("white", "FFFFFF"));
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("yellow", "FFFF00"));
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("cyan", "00FFFF"));
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("magenta", "FF00FF"));
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("brown", "A52A2A"));
|
||||
m_ColorMap.insert(std::make_pair<QString, QString>("orange", "FFCC00"));
|
||||
|
||||
// make all patterns non-greedy and case-insensitive
|
||||
for (TagMap::iterator iter = m_TagMap.begin(); iter != m_TagMap.end(); ++iter) {
|
||||
iter->second.first.setCaseSensitivity(Qt::CaseInsensitive);
|
||||
@@ -157,10 +179,11 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
QRegExp m_TagNameExp;
|
||||
TagMap m_TagMap;
|
||||
std::map<QString, QString> m_ColorMap;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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_refreshBtn_clicked()
|
||||
{
|
||||
getCurrentView()->reload();
|
||||
}
|
||||
|
||||
void BrowserDialog::on_browserTabWidget_currentChanged(int index)
|
||||
{
|
||||
BrowserView *currentView = qobject_cast<BrowserView*>(ui->browserTabWidget->widget(index));
|
||||
if (currentView != NULL) {
|
||||
ui->backBtn->setEnabled(currentView->history()->canGoBack());
|
||||
ui->fwdBtn->setEnabled(currentView->history()->canGoForward());
|
||||
}
|
||||
}
|
||||
@@ -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_refreshBtn_clicked();
|
||||
|
||||
void on_browserTabWidget_currentChanged(int index);
|
||||
|
||||
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
|
||||
+60
-15
@@ -20,8 +20,10 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "directoryrefresher.h"
|
||||
#include "utility.h"
|
||||
#include "report.h"
|
||||
#include "modinfo.h"
|
||||
#include <gameinfo.h>
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
|
||||
|
||||
using namespace MOBase;
|
||||
@@ -46,10 +48,19 @@ DirectoryEntry *DirectoryRefresher::getDirectoryStructure()
|
||||
return result;
|
||||
}
|
||||
|
||||
void DirectoryRefresher::setMods(const std::vector<std::tuple<QString, QString, int> > &mods)
|
||||
void DirectoryRefresher::setMods(const std::vector<std::tuple<QString, QString, int> > &mods
|
||||
, const std::set<QString> &managedArchives)
|
||||
{
|
||||
QMutexLocker locker(&m_RefreshLock);
|
||||
m_Mods = mods;
|
||||
|
||||
m_Mods.clear();
|
||||
for (auto mod = mods.begin(); mod != mods.end(); ++mod) {
|
||||
QString name = std::get<0>(*mod);
|
||||
ModInfo::Ptr info = ModInfo::getByIndex(ModInfo::getIndex(name));
|
||||
m_Mods.push_back(EntryInfo(name, std::get<1>(*mod), info->stealFiles(), info->archives(), std::get<2>(*mod)));
|
||||
}
|
||||
|
||||
m_EnabledArchives = managedArchives;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,21 +72,56 @@ void DirectoryRefresher::cleanStructure(DirectoryEntry *structure)
|
||||
}
|
||||
|
||||
static wchar_t *dirs[] = { L"fomod" };
|
||||
for (int i = 0; i < sizeof(files) / sizeof(wchar_t*); ++i) {
|
||||
structure->removeDir(dirs[i]);
|
||||
for (int i = 0; i < sizeof(dirs) / sizeof(wchar_t*); ++i) {
|
||||
structure->removeDir(std::wstring(dirs[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void DirectoryRefresher::addModToStructure(DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory)
|
||||
void DirectoryRefresher::addModToStructure(DirectoryEntry *directoryStructure
|
||||
, const QString &modName
|
||||
, int priority
|
||||
, const QString &directory
|
||||
, const QStringList &stealFiles
|
||||
, const QStringList &archives)
|
||||
{
|
||||
std::wstring directoryW = ToWString(QDir::toNativeSeparators(directory));
|
||||
std::wstring modNameW = ToWString(modName);
|
||||
|
||||
directoryStructure->addFromOrigin(ToWString(modName), directoryW, priority);
|
||||
QDir dir(directory);
|
||||
|
||||
if (stealFiles.length() > 0) {
|
||||
// instead of adding all the files of the target directory, we just change the root of the specified
|
||||
// files to this mod
|
||||
directoryStructure->createOrigin(modNameW, directoryW, priority);
|
||||
foreach (const QString &filename, stealFiles) {
|
||||
QFileInfo fileInfo(filename);
|
||||
FileEntry::Ptr file = directoryStructure->findFile(ToWString(fileInfo.fileName()));
|
||||
if (file.get() != NULL) {
|
||||
if (file->getOrigin() == 0) {
|
||||
// replace data as the origin on this bsa
|
||||
file->removeOrigin(0);
|
||||
file->addOrigin(directoryStructure->getOriginByName(modNameW).getID(),
|
||||
file->getFileTime(), L"");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
directoryStructure->addFromOrigin(modNameW, directoryW, priority);
|
||||
}
|
||||
/* QDir dir(directory);
|
||||
QFileInfoList bsaFiles = dir.entryInfoList(QStringList("*.bsa"), QDir::Files);
|
||||
foreach (QFileInfo file, bsaFiles) {
|
||||
directoryStructure->addFromBSA(ToWString(modName), directoryW,
|
||||
ToWString(QDir::toNativeSeparators(file.absoluteFilePath())), priority);
|
||||
if (m_EnabledArchives.find(file.fileName()) != m_EnabledArchives.end()) {
|
||||
directoryStructure->addFromBSA(ToWString(modName), directoryW,
|
||||
ToWString(QDir::toNativeSeparators(file.absoluteFilePath())), priority);
|
||||
}
|
||||
}*/
|
||||
|
||||
foreach (const QString &archive, archives) {
|
||||
QFileInfo fileInfo(archive);
|
||||
if (m_EnabledArchives.find(fileInfo.fileName()) != m_EnabledArchives.end()) {
|
||||
directoryStructure->addFromBSA(modNameW, directoryW,
|
||||
ToWString(QDir::toNativeSeparators(fileInfo.absoluteFilePath())), priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,23 +133,22 @@ void DirectoryRefresher::refresh()
|
||||
|
||||
m_DirectoryStructure = new DirectoryEntry(L"data", NULL, 0);
|
||||
|
||||
std::wstring dataDirectory = GameInfo::instance().getGameDirectory() + L"\\data";
|
||||
m_DirectoryStructure->addFromOrigin(L"data", dataDirectory, 0);
|
||||
|
||||
// TODO what was the point of having the priority in this tuple? the list is already sorted by priority
|
||||
std::vector<std::tuple<QString, QString, int> >::const_iterator iter = m_Mods.begin();
|
||||
auto iter = m_Mods.begin();
|
||||
|
||||
//TODO i is the priority here, where higher = more important. the input vector is also sorted by priority but inverted!
|
||||
for (int i = 1; iter != m_Mods.end(); ++iter, ++i) {
|
||||
QString modName = std::get<0>(*iter);
|
||||
try {
|
||||
addModToStructure(m_DirectoryStructure, modName, i, std::get<1>(*iter));
|
||||
addModToStructure(m_DirectoryStructure, iter->modName, i, iter->absolutePath, iter->stealFiles, iter->archives);
|
||||
} catch (const std::exception &e) {
|
||||
emit error(tr("failed to read bsa: %1").arg(e.what()));
|
||||
}
|
||||
emit progress((i * 100) / m_Mods.size() + 1);
|
||||
}
|
||||
|
||||
std::wstring dataDirectory = GameInfo::instance().getGameDirectory() + L"\\data";
|
||||
m_DirectoryStructure->addFromOrigin(L"data", dataDirectory, 0);
|
||||
|
||||
emit progress(100);
|
||||
|
||||
cleanStructure(m_DirectoryStructure);
|
||||
|
||||
@@ -20,11 +20,13 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef DIRECTORYREFRESHER_H
|
||||
#define DIRECTORYREFRESHER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <vector>
|
||||
#include <QMutex>
|
||||
#include <tuple>
|
||||
#include <directoryentry.h>
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QStringList>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
|
||||
|
||||
/**
|
||||
@@ -60,7 +62,7 @@ public:
|
||||
*
|
||||
* @param mods list of the mods to include
|
||||
**/
|
||||
void setMods(const std::vector<std::tuple<QString, QString, int> > &mods);
|
||||
void setMods(const std::vector<std::tuple<QString, QString, int> > &mods, const std::set<QString> &managedArchives);
|
||||
|
||||
/**
|
||||
* @brief sets up the directory where mods are stored
|
||||
@@ -82,7 +84,7 @@ public:
|
||||
* @param directory
|
||||
* @param priorityDir
|
||||
*/
|
||||
static void addModToStructure(MOShared::DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory);
|
||||
void addModToStructure(MOShared::DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &stealFiles, const QStringList &archives);
|
||||
|
||||
public slots:
|
||||
|
||||
@@ -99,7 +101,22 @@ signals:
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::tuple<QString, QString, int> > m_Mods;
|
||||
struct EntryInfo {
|
||||
EntryInfo(const QString &modName, const QString &absolutePath,
|
||||
const QStringList &stealFiles, const QStringList &archives, int priority)
|
||||
: modName(modName), absolutePath(absolutePath), stealFiles(stealFiles)
|
||||
, archives(archives), priority(priority) {}
|
||||
QString modName;
|
||||
QString absolutePath;
|
||||
QStringList stealFiles;
|
||||
QStringList archives;
|
||||
int priority;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
std::vector<EntryInfo> m_Mods;
|
||||
std::set<QString> m_EnabledArchives;
|
||||
MOShared::DirectoryEntry *m_DirectoryStructure;
|
||||
QMutex m_RefreshLock;
|
||||
|
||||
|
||||
@@ -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<br><span>%4</span>").arg(info->modName).arg(m_Manager->getModID(index.row())).arg(info->version.canonicalString()).arg(info->description);
|
||||
}
|
||||
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;
|
||||
|
||||
+283
-157
File diff suppressed because it is too large
Load Diff
+30
-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
|
||||
@@ -419,6 +417,7 @@ private slots:
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void downloadReadyRead();
|
||||
void downloadFinished();
|
||||
void downloadError(QNetworkReply::NetworkError error);
|
||||
void metaDataChanged();
|
||||
void directoryChanged(const QString &dirctory);
|
||||
|
||||
@@ -434,12 +433,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 +457,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()) {
|
||||
@@ -522,9 +522,10 @@ bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID,
|
||||
return false;
|
||||
}
|
||||
|
||||
QString targetDirectory = QDir::fromNativeSeparators(m_ModsDirectory.mid(0).append("\\").append(modName));
|
||||
QString targetDirectoryNative = m_ModsDirectory.mid(0).append("\\").append(modName);
|
||||
QString targetDirectory = QDir::fromNativeSeparators(targetDirectoryNative);
|
||||
|
||||
qDebug("installing to \"%s\"", targetDirectory.toUtf8().constData());
|
||||
qDebug("installing to \"%s\"", targetDirectoryNative.toUtf8().constData());
|
||||
|
||||
m_InstallationProgress.setWindowTitle(tr("Extracting files"));
|
||||
m_InstallationProgress.setLabelText(QString());
|
||||
@@ -659,7 +660,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 +679,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 +726,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()) &&
|
||||
|
||||
+106
-18
@@ -21,6 +21,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "report.h"
|
||||
#include <QMutexLocker>
|
||||
#include <QFile>
|
||||
#include <QIcon>
|
||||
#include <QDateTime>
|
||||
#include <Windows.h>
|
||||
|
||||
@@ -29,7 +30,7 @@ QMutex LogBuffer::s_Mutex;
|
||||
|
||||
|
||||
LogBuffer::LogBuffer(int messageCount, QtMsgType minMsgType, const QString &outputFileName)
|
||||
: QObject(NULL), m_OutFileName(outputFileName), m_ShutDown(false),
|
||||
: QAbstractItemModel(NULL), m_OutFileName(outputFileName), m_ShutDown(false),
|
||||
m_MinMsgType(minMsgType), m_NumMessages(0)
|
||||
{
|
||||
m_Messages.resize(messageCount);
|
||||
@@ -51,7 +52,16 @@ LogBuffer::~LogBuffer()
|
||||
void LogBuffer::logMessage(QtMsgType type, const QString &message)
|
||||
{
|
||||
if (type >= m_MinMsgType) {
|
||||
m_Messages.at(m_NumMessages % m_Messages.size()) = message;
|
||||
Message msg = { type, QTime::currentTime(), message };
|
||||
if (m_NumMessages < m_Messages.size()) {
|
||||
beginInsertRows(QModelIndex(), m_NumMessages, m_NumMessages + 1);
|
||||
}
|
||||
m_Messages.at(m_NumMessages % m_Messages.size()) = msg;
|
||||
if (m_NumMessages < m_Messages.size()) {
|
||||
endInsertRows();
|
||||
} else {
|
||||
emit dataChanged(createIndex(0, 0), createIndex(m_Messages.size(), 0));
|
||||
}
|
||||
++m_NumMessages;
|
||||
if (type >= QtCriticalMsg) {
|
||||
write();
|
||||
@@ -77,7 +87,7 @@ void LogBuffer::write() const
|
||||
unsigned int i = (m_NumMessages > m_Messages.size()) ? m_NumMessages - m_Messages.size()
|
||||
: 0U;
|
||||
for (; i < m_NumMessages; ++i) {
|
||||
file.write(m_Messages.at(i % m_Messages.size()).toUtf8());
|
||||
file.write(m_Messages.at(i % m_Messages.size()).toString().toUtf8());
|
||||
file.write("\r\n");
|
||||
}
|
||||
::SetLastError(lastError);
|
||||
@@ -99,21 +109,6 @@ void LogBuffer::init(int messageCount, QtMsgType minMsgType, const QString &outp
|
||||
#endif
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
void LogBuffer::log(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
QMutexLocker guard(&s_Mutex);
|
||||
if (!s_Instance.isNull()) {
|
||||
s_Instance->logMessage(type, message);
|
||||
}
|
||||
fprintf(stdout, "(%s:%u) %s\n", context.file, context.line, qPrintable(message));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
char LogBuffer::msgTypeID(QtMsgType type)
|
||||
{
|
||||
switch (type) {
|
||||
@@ -125,6 +120,26 @@ char LogBuffer::msgTypeID(QtMsgType type)
|
||||
}
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
void LogBuffer::log(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
QMutexLocker guard(&s_Mutex);
|
||||
if (!s_Instance.isNull()) {
|
||||
s_Instance->logMessage(type, message);
|
||||
}
|
||||
// fprintf(stdout, "(%s:%u) %s\n", context.file, context.line, qPrintable(message));
|
||||
if (type == QtDebugMsg) {
|
||||
fprintf(stdout, "%s [%c] %s\n", qPrintable(QTime::currentTime().toString()), msgTypeID(type), qPrintable(message));
|
||||
} else {
|
||||
fprintf(stdout, "%s [%c] (%s:%u) %s\n", qPrintable(QTime::currentTime().toString()), msgTypeID(type),
|
||||
context.file, context.line, qPrintable(message));
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void LogBuffer::log(QtMsgType type, const char *message)
|
||||
{
|
||||
QMutexLocker guard(&s_Mutex);
|
||||
@@ -137,6 +152,73 @@ void LogBuffer::log(QtMsgType type, const char *message)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
QModelIndex LogBuffer::index(int row, int column, const QModelIndex&) const
|
||||
{
|
||||
return createIndex(row, column, row);
|
||||
}
|
||||
|
||||
QModelIndex LogBuffer::parent(const QModelIndex&) const
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int LogBuffer::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
else
|
||||
return std::min(m_NumMessages, m_Messages.size());
|
||||
}
|
||||
|
||||
int LogBuffer::columnCount(const QModelIndex&) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
QVariant LogBuffer::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
unsigned offset = m_NumMessages < m_Messages.size() ? 0
|
||||
: m_NumMessages - m_Messages.size();
|
||||
unsigned int msgIndex = (offset + index.row() + 1) % m_Messages.size();
|
||||
switch (role) {
|
||||
case Qt::DisplayRole: {
|
||||
if (index.column() == 0) {
|
||||
return m_Messages.at(msgIndex).time;
|
||||
} else if (index.column() == 1) {
|
||||
const QString &msg = m_Messages.at(msgIndex).message;
|
||||
if (msg.length() < 200) {
|
||||
return msg;
|
||||
} else {
|
||||
return msg.mid(0, 200) + "...";
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Qt::DecorationRole: {
|
||||
if (index.column() == 1) {
|
||||
switch (m_Messages.at(msgIndex).type) {
|
||||
case QtDebugMsg: return QIcon(":/MO/gui/information");
|
||||
case QtWarningMsg: return QIcon(":/MO/gui/warning");
|
||||
case QtCriticalMsg: return QIcon(":/MO/gui/important");
|
||||
case QtFatalMsg: return QIcon(":/MO/gui/problem");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Qt::UserRole: {
|
||||
if (index.column() == 1) {
|
||||
switch (m_Messages.at(msgIndex).type) {
|
||||
case QtDebugMsg: return "D";
|
||||
case QtWarningMsg: return "W";
|
||||
case QtCriticalMsg: return "C";
|
||||
case QtFatalMsg: return "F";
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void LogBuffer::writeNow()
|
||||
{
|
||||
QMutexLocker guard(&s_Mutex);
|
||||
@@ -171,3 +253,9 @@ void log(const char *format, ...)
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
QString LogBuffer::Message::toString() const
|
||||
{
|
||||
return QString("%1 [%2] %3").arg(time.toString()).arg(msgTypeID(type)).arg(message);
|
||||
}
|
||||
|
||||
+23
-2
@@ -23,10 +23,12 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QScopedPointer>
|
||||
#include <QStringListModel>
|
||||
#include <QTime>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class LogBuffer : public QObject
|
||||
class LogBuffer : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -42,12 +44,22 @@ public:
|
||||
static void writeNow();
|
||||
static void cleanQuit();
|
||||
|
||||
static LogBuffer *instance() { return s_Instance.data(); }
|
||||
|
||||
public:
|
||||
|
||||
virtual ~LogBuffer();
|
||||
|
||||
void logMessage(QtMsgType type, const QString &message);
|
||||
|
||||
// QAbstractItemModel interface
|
||||
public:
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent) const;
|
||||
QModelIndex parent(const QModelIndex &child) const;
|
||||
int rowCount(const QModelIndex &parent) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
@@ -62,6 +74,15 @@ private:
|
||||
|
||||
static char msgTypeID(QtMsgType type);
|
||||
|
||||
private:
|
||||
|
||||
struct Message {
|
||||
QtMsgType type;
|
||||
QTime time;
|
||||
QString message;
|
||||
QString toString() const;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static QScopedPointer<LogBuffer> s_Instance;
|
||||
@@ -71,7 +92,7 @@ private:
|
||||
bool m_ShutDown;
|
||||
QtMsgType m_MinMsgType;
|
||||
unsigned int m_NumMessages;
|
||||
std::vector<QString> m_Messages;
|
||||
std::vector<Message> m_Messages;
|
||||
|
||||
};
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user