Compare commits

..
Author SHA1 Message Date
Tannin b2a7c7c223 Merge 2014-06-23 21:43:40 +02:00
Tannin 7b4582c1b1 - adjusted mod load order in hook.dll to match the one from the UI
- bugfix: fnis checker took files in archives into consideration for hashing
2014-06-23 20:23:59 +02:00
Tannin 5d7b23acef - bugfix: networkaccessmanager of browser dialog wasn't destroyed correctly. As a result the cookie jar doesn't get saved 2014-06-21 12:16:57 +02:00
Tannin 3628ec930b - changed the url used to login on nexus (the previous page was disabled)
- bugfix: download manager might have tried to read from a closed connection
2014-06-21 10:39:28 +02:00
Tannin e22aeca3ff - download read buffer is now limited to 1MB. Might prevent out-of-memory errors during download
- bugfix: plugins are now disabled when deactivating a mod  before the files are removed from the vfs
2014-06-17 18:36:28 +02:00
Tannin cbd6b288eb Merge 2014-06-16 21:50:53 +02:00
Tannin 484749e612 - added pseudo-categories to filter for mo-managed vs. unmanaged mods
- deleted mods are now moved to the recycle bin instead of being deleted permanently
- reduced modinfo dialog for foreign mods
- foreign mods are now displayed with a pseudo-category
- added a signal when a plugin is moved
- bugfix: refreshing of directory structure for mods with bsas didn't work correctly when enabling a mod and on changing display of foreign mods
- bugfix: one mod in the list was assigned the same priority on the directory structure as the data directory
- bugfix: conflicts tab in the mod info dialog offered the hide option for files in bsas
2014-06-16 21:49:57 +02:00
Tannin 5b3cdaa83b bugfix: the warning dialog upon changing the mod directory didn't have an effect, the process couldn't be canceled 2014-06-14 09:17:57 +02:00
Tannin 6d3f88b330 Added tag release v1.2.3 for changeset c503e48f97aa 2014-06-08 15:10:21 +02:00
Tannin 0feb4b702d - loot client now only updates the masterlist once per MO session
- new event to notify plugins of changed mod priority
- overwrite now shows up in the "checked" category instead of "unchecked"
- display of "foreign" mods can now be limited to only official content
- bugfix: bsa extraction dialog showed up even if the plugin was disabled
- bugfix: after detection of foreign mods the priority of the overwrite folder could get messed up
- bugfix: when displaying only the context menu for the mod list as a whole, the menu didn't disappear
- bugfix: MO crashed when trying to download via the integrated browser
2014-06-08 15:10:08 +02:00
Tannin 5a4b6e70fd - plugin-list now displays loot messages 2014-06-02 19:15:23 +02:00
Tannin 18574c2ba8 - removed needless modlist-rewrite 2014-05-31 13:44:26 +02:00
Tannin 1eb783aae3 - added a new mod type that represents files handled externally (i.e. DLCs) as mods in MO
- hashes of file names in bsa files are no longer checked all the time
- author and description is now read from esp files
- rewrote the code that fixes modlists after a rename, should be a bit more robust
- fixes to qt 5 and msvc 2013 compatibility
- started to update the tutorial (not done yet!)
- bugfix: counter for the problems badge wasn't calculated correctly
2014-05-31 13:43:48 +02:00
Tannin 93a19799b8 Merge 2014-05-28 14:23:11 +02:00
Tannin 2a31eb40fb small bugfixes 2014-05-28 14:14:28 +02:00
Tannin cf0a1bc2be - files in bsas are now only displayed in the data tab if they are managed by mo
- number of problems detected by MO is now displayed as a badge on the icon
- rephrased the explanation text on the Archives tab. unchecked plugin-loaded bsas no longer prompt a warning
- bsa extraction is now handled in a plugin
- added a way for plugins to react to mod installation
- re-enabled the automatic fix for asset order problems
- bugfix: In some cases when a download wasn't started successfully the download urls weren't stored in the meta file so no resume was possible
- bugfix: MO tried to resume downloads when it didn't have and download urls
- bugfix: downloads couldn't be paused if the download was already broken on the network layer
- bugfix: download managear did not recognize a file as downloaded if the download completed before signals were hooked up
- bugfix: in-place file replacement was re-broken
2014-05-25 15:39:45 +02:00
Tannin 48c8cca578 - NCC will now report an error if a script tries to extract a non-existent file instead of creating an empty output file
- ncc installer plugin now uses a more reliable method to force the installer window to the foreground
- missing version on TESV.exe will no longer be reported as an error
- bugfix: loot client didn't read list of active mods
- bugfix: invalid free call in error reporting function
2014-05-15 19:11:19 +02:00
Tannin 977b407525 - mod list context menu split into two menus (one for whole list, one for selected mods)
- added option to combine category filters using "or"
- added context menu option for deselecting category filters
- slightly changed ui on the category filters
- added a sample plugin for cpp that can be built without building the rest of MO
- simple installer can now be configured to run without any user interaction
- extended interface for python plugins
- iorganizer implementation moved out of the main window
- nexus requests from plugins will now be identified in the user agent
- bugfix: shortcuts created from MO used the wrong working directory
- bugfix: deactivation of bsas didn't stick
- bugfix: file hiding mechanism wasn't active
- bugfix: executables linked on the toolbar couldn't be removed if the executable was removed first
- bugfix: the endorsement-filter couldn't be combined with other filters
- bugfix: python interface to repository bridge was broken
2014-05-13 21:20:44 +02:00
Tannin f4b1aba61a Added tag release v1.2.1 for changeset 366d0a6ac409 2014-05-06 21:07:34 +02:00
Tannin 0eb1662a0e - very effective optimization to findfirstfile-calls
- several configuration files are now only saved to disk if the content actually changed.
  This should also get rid of a problem where plugins.txt was re-written immediately after starting the game
  (causing a conflict with the game)
- reduced "noise" from hook.dll
- removed some debugging messages
2014-05-05 18:24:15 +02:00
Tannin 164ec25a75 - bugfix: endless loop in detection of mod order problems 2014-05-04 16:13:35 +02:00
Tannin 6fb36d6c02 - main window now has a small view displaying log messages
- mod list will now be highlighted when grouping is active is active
- download tooltip now supports bbcode markup in the description
- bbcode translator will now translate some named colors
- algorithm for detection of mod order problems is now more sophisticated
- exposed more functionality to python plugins
- updated to qt 4.8.6 dlls
- bugfix: plugin list wasn't
- bugfix: state changes in mod list wasn't always reported
- bugfix: loot client will now create necessary directory
- bugfix: NCC sometimes used wrong source path for extracting
- bugfix: removed noisy debug message
2014-05-04 14:50:01 +02:00
Tannin ea1f959ad5 - download tooltip now also includes the file description
- will now display an error message when the ini file can't be updated (in addition to what windows says)
2014-05-01 10:03:40 +02:00
Tannin 7cf3b3455b Added tag release v1.2.0 for changeset cc9f6dd8ee3f 2014-04-25 20:02:53 +02:00
Tannin 84cfa95254 - bugfix: newly installed files could be added hidden
- bugfix: registered bsas in data aren't ordered correctly
2014-04-25 19:15:12 +02:00
Tannin 264da60929 - updated installer
- prettified a few log messages
2014-04-24 22:07:42 +02:00
Tannin 2db33523a1 - added an option to show meta info on downloads instead of filenames
- MO will now cancel if user tries to run MO vfs-injected
- when saving the MO ini file it is now written to a tmp file first and then overwritten
- updated to link against boost python 1.55
2014-04-23 23:59:30 +02:00
Tannin 540747177a - loot client no longer stalls the process while waiting for masterlist update
- configurator now gives better warning messages when encountering an invalid ini file
- bugfix: crash on cleanup up browser dialog
- bugfix: GetCurrentDirectory returned wrong string length
2014-04-16 22:32:59 +02:00
Tannin 739c3424e7 - loot integration now displays the report
- fixes to the previous merge
- bugfix: cli loot didn't handle non-ascii characters correctly
2014-04-05 20:54:08 +02:00
Tannin cabed9b268 Merge with branch1.1 2014-04-05 15:36:42 +02:00
Tannin c017f4a0d5 - added buttons to backup and restore the modlist and pluginlist
- replaced boss integration with loot
2014-04-05 15:14:37 +02:00
Tannin b1f1682790 - bugfix: the add/remove categories function could fail when a filter/grouping on categories was active 2014-03-26 17:23:26 +01:00
Tannin 28301e7486 - improved NCC compatibility
- crude support for multi-volume archives
- updated imageformats plugins
- nxmhandler now puts the exe to the top of the list when registering an MO instance, even if it is already in the list
- bugfix: WritePrivateProfileString hook attempted to access lpKeyName even when it is null
2014-03-26 15:35:59 +01:00
Tannin 2d0fab4482 Merge 2014-03-18 19:18:17 +01:00
Tannin c19c4820d8 - force-enabled game esms no longer break keyboard-navigation in plugin list 2014-03-18 19:18:04 +01:00
Tannin 8ab1b47943 - bugfix: if resuming a download failed with the server sending a textual error message,
MO tried to display the whole file inside the error message
- bugfix: resuming a download didn't trigger a nexus-login when necessary
- bugfix: integrated fomod installer only used the first block of data inside a description
2014-03-18 18:29:32 +01:00
Tannin ff272dcbbd Merge 2014-03-16 20:05:13 +01:00
Tannin 98354cd1e7 some fixes towards qt5 compatibility 2014-03-16 20:04:57 +01:00
Tannin 129b76d7d2 - unpacking bsas during installation no longer overwrites loose files (since the loose files
would have taken precedence)
2014-03-13 21:57:11 +01:00
Tannin a82b7e9949 - "CreateDirectory" will no longer create directories in original data directory
- bain installer will now be less picky about the archives supported
- updated NCC to be compatible with more recent NMM code base
- hack in NCC to allow it to install arbitrary sized files even in 32-bit builds
- updated the python27.dll to one that links to msvcr100.dll to get rid of the dependency of msvcr90.dll
- bugfix: dll search order wasn't set to allow plugins to load the correct qt dlls
2014-03-13 19:00:32 +01:00
Tannin 0f8f7bf777 Added tag releease v1.1.2 for changeset 4276e1188b42 2014-02-26 22:14:06 +01:00
Tannin f4cf992700 Removed tag 1.1.2 2014-02-26 22:13:53 +01:00
Tannin bec644bac3 Added tag 1.1.2 for changeset 4276e1188b42 2014-02-26 22:13:43 +01:00
Tannin bb98bfade6 - MO will now be elevated if needed 2014-02-23 18:53:38 +01:00
Tannin 00f4e1799f - slightly overworked display of icon delegates
- updated installer
2014-02-23 17:18:20 +01:00
Tannin 35fcf1c25b - made the indicator for drag&drop more visible
- message boxes can now be made to not (re-)activate the window
- executable names for starting from the command line are now case-insensitive
2014-02-22 19:22:12 +01:00
Tannin bed3c08a6d - bugfix: on-demand loading of data tree broke filtering on conflicting files 2014-02-18 19:08:12 +01:00
Tannin f9eba9dc15 - ini file changes that would have to overwrite ini tweaks are now stored in a separate file
and actually get used.
- a warning message advices users to clean out that separate file
- slightly improved default main window layout
- bugfix: newly created ini tweaks were added to the list with incorrect  properties
2014-02-17 21:15:20 +01:00
Tannin 9c8e43853d - a few hooks will now somewhat handle file names starting with \\?\
- mod meta information is now (also) saved by a timer to reduce the likelyhood
of a data loss in case of a crash
- mod meta files are now written to a temporary file and then renamed to real name to
reduce chance of breaking the file
- updated minimum compatible nmm version to 0.47.0
- bugfix: defaults for newestVersion, version and installationFile when creating
an empty mod were integers instead of strings
- bugfix: "Plugins" and "Archives" weren't translatable
2014-02-12 21:00:49 +01:00
Tannin 7aadb47637 - archives.txt is now written using the "safe"-write mechanism
- added the whole boss fork to the repository
- bugfix: boss db is now always re-initialised because otherwise there might have been differing results between runs
- bugfix: locked load order was ignored by integrated boss
- bugfix: archive list wasn't written back on all changes that affected it
- bugfix: CreateFile-hook didn't reroute files created with OPEN_ALWAYS to overwrite directory
- bugfix: NtQueryDirectoryFile-hook didn't return the correct status code when searching for a file that doesn't exist
2014-02-07 21:05:48 +01:00
Tannin 76fbe6effe - tabs in the mod info dialog can now be moved around by the user 2014-02-04 19:55:27 +01:00
Tannin 38ee6ccf0a Added tag release v1.1.1 for changeset 73a1f1438658 2014-02-02 15:14:07 +01:00
Tannin 98e5e57a84 - added support for mod page plugins
- re-introduced the integrated browser
- added a plugin to download from the tes alliance page
- the download list now contains the file description
- nexus interface now stores cookies persistently to reduce number of required log-ins
2013-09-15 15:20:00 +02:00
107 changed files with 12490 additions and 8053 deletions
+13
View File
@@ -18,5 +18,18 @@ staging_prepare/*
staging_trans/*
tools/python_zip/*
Makefile
html
*.vcxproj
*.pdb
*.dll
*.exp
*.tlog
*.user
*.obj
*.suo
*.sln
*.log
*.filters
*.lib
syntax: regexp
Makefile\.(Debug|Release)
+3 -3
View File
@@ -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
View File
@@ -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;
};
+270
View File
@@ -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(this))
{
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());
}
}
+124
View File
@@ -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
+289
View File
@@ -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>
+76
View File
@@ -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);
}
+80
View File
@@ -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
+2
View File
@@ -47,6 +47,8 @@ public:
static const int CATEGORY_SPECIAL_NOCATEGORY = 10003;
static const int CATEGORY_SPECIAL_CONFLICT = 10004;
static const int CATEGORY_SPECIAL_NOTENDORSED = 10005;
static const int CATEGORY_SPECIAL_MANAGED = 10006;
static const int CATEGORY_SPECIAL_UNMANAGED = 10007;
public:
+62 -18
View File
@@ -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,12 +48,20 @@ 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;
}
void DirectoryRefresher::cleanStructure(DirectoryEntry *structure)
{
@@ -61,24 +71,59 @@ 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::addModBSAToStructure(DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &archives)
{
std::wstring directoryW = ToWString(QDir::toNativeSeparators(directory));
directoryStructure->addFromOrigin(ToWString(modName), 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);
foreach (const QString &archive, archives) {
QFileInfo fileInfo(archive);
if (m_EnabledArchives.find(fileInfo.fileName()) != m_EnabledArchives.end()) {
directoryStructure->addFromBSA(ToWString(modName), directoryW,
ToWString(QDir::toNativeSeparators(fileInfo.absoluteFilePath())), priority);
}
}
}
void DirectoryRefresher::addModFilesToStructure(DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &stealFiles)
{
std::wstring directoryW = ToWString(QDir::toNativeSeparators(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
FilesOrigin origin = directoryStructure->createOrigin(ToWString(modName), 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(origin.getID(), file->getFileTime(), L"");
}
}
}
} else {
directoryStructure->addFromOrigin(ToWString(modName), directoryW, priority);
}
}
void DirectoryRefresher::addModToStructure(DirectoryEntry *directoryStructure
, const QString &modName
, int priority
, const QString &directory
, const QStringList &stealFiles
, const QStringList &archives)
{
addModFilesToStructure(directoryStructure, modName, priority, directory, stealFiles);
addModBSAToStructure(directoryStructure, modName, priority, directory, archives);
}
void DirectoryRefresher::refresh()
{
QMutexLocker locker(&m_RefreshLock);
@@ -87,23 +132,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);
+48 -9
View File
@@ -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
@@ -77,12 +79,34 @@ public:
/**
* @brief add files for a mod to the directory structure, including bsas
* @param directoryStructure
* @param modName
* @param priorityBSA
* @param priority
* @param directory
* @param priorityDir
* @param stealFiles
* @param archives
*/
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);
/**
* @brief add only the bsas of a mod to the directory structure
* @param directoryStructure
* @param modName
* @param priority
* @param directory
* @param archives
*/
void addModBSAToStructure(MOShared::DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &archives);
/**
* @brief add only regular files ofr a mod to the directory structure
* @param directoryStructure
* @param modName
* @param priority
* @param directory
* @param stealFiles
*/
void addModFilesToStructure(MOShared::DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &stealFiles);
public slots:
@@ -99,7 +123,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;
+4 -4
View File
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="dlls" version="1.0.0.0" processorArchitecture="x86"/>
<file name="icuin49.dll"/>
<file name="icuuc49.dll"/>
<file name="icudt49.dll"/>
<file name="icuin52.dll"/>
<file name="icuuc52.dll"/>
<file name="icudt52.dll"/>
<file name="Qt5Core.dll"/>
<file name="Qt5Declarative.dll"/>
<file name="Qt5Gui.dll"/>
@@ -14,4 +14,4 @@
<file name="Qt5Widgets.dll"/>
<file name="Qt5Xml.dll"/>
<file name="Qt5XmlPatterns.dll"/>
</assembly>
</assembly>
+2 -2
View File
@@ -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 {
+8 -3
View File
@@ -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("...");
+3 -1
View File
@@ -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;
+7 -3
View File
@@ -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("...");
+3 -1
View File
@@ -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;
+286 -159
View File
File diff suppressed because it is too large Load Diff
+30 -31
View File
@@ -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;
+1 -2
View File
@@ -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),
@@ -106,7 +105,7 @@ const Executable &ExecutablesList::find(const QString &title) const
Executable &ExecutablesList::find(const QString &title)
{
for (std::vector<Executable>::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) {
if (iter->m_Title == title) {
if (QString::compare(iter->m_Title, title, Qt::CaseInsensitive) == 0) {
return *iter;
}
}

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