summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTannin <devnull@localhost>2013-08-30 20:59:12 +0200
committerTannin <devnull@localhost>2013-08-30 20:59:12 +0200
commit9c31cfa915f71adee8579aa97c12b64903ec9446 (patch)
tree63f1b92b8a596df17849f1c5d2ee7e911d879a61
parent91dd38cb292035b5ca23c531f0383bb283c8700e (diff)
- the download manager now registers download speed. Right now this is only used
to display an average speed on the settings menu - added a python27.dll compiled with vc100. This can now be bundled without introducing more dependencies - bugfix: extracting now stops after an error - bugfix: the way hook.dll caused CREATE_ALWAYS/CREATE_NEW to always write into overwrite could lead to the file being created when the call should have failed (because the file existed and was protected) - bugfix: GetPrivateProfileString does NOT properly report files as missing. This means that the ini-query optimization could optimize away requests that should work - bugfix: fomod installer couldn't display images because they were unpacked to the wrong temporary location - bugfix: When disabling local saves and choosing to delete the saves nothing happened - bugfix: the python plugin couldn't find the pyqt libraries
-rw-r--r--src/downloadmanager.cpp14
-rw-r--r--src/downloadmanager.h6
-rw-r--r--src/installationmanager.cpp35
-rw-r--r--src/installationmanager.h2
-rw-r--r--src/main.cpp10
-rw-r--r--src/mainwindow.cpp10
-rw-r--r--src/mainwindow.h2
-rw-r--r--src/mainwindow.ui65
-rw-r--r--src/profile.cpp3
-rw-r--r--src/settings.cpp41
-rw-r--r--src/settings.h7
-rw-r--r--src/shared/directoryentry.cpp15
-rw-r--r--src/version.rc4
13 files changed, 163 insertions, 51 deletions
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index ca6744aa..8c2615ea 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -283,6 +283,7 @@ bool DownloadManager::addDownload(const QStringList &URLs,
return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, modID, fileID, nexusInfo);
}
+
bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName,
int modID, int fileID, const NexusInfo &nexusInfo)
{
@@ -1034,6 +1035,8 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u
std::sort(resultList.begin(), resultList.end(), boost::bind(&DownloadManager::ServerByPreference, m_PreferredServers, _1, _2));
+ info.m_DownloadMap = resultList;
+
QStringList URLs;
foreach (const QVariant &server, resultList) {
@@ -1121,6 +1124,17 @@ void DownloadManager::downloadFinished()
createMetaFile(info);
emit update(index);
} else {
+
+ QString url = info->m_Urls[info->m_CurrentUrl];
+ foreach (const QVariant &server, info->m_NexusInfo.m_DownloadMap) {
+ QVariantMap serverMap = server.toMap();
+ if (serverMap["URI"].toString() == url) {
+ int deltaTime = info->m_StartTime.secsTo(QTime::currentTime());
+ emit downloadSpeed(serverMap["Name"].toString(), info->m_TotalSize / deltaTime);
+ break;
+ }
+ }
+
setState(info, STATE_FETCHINGMODINFO); // need to set this state before changing the file name, otherwise .unfinished is appended
QString newName = getFileNameFromNetworkReply(reply);
diff --git a/src/downloadmanager.h b/src/downloadmanager.h
index b4cb2786..01d45582 100644
--- a/src/downloadmanager.h
+++ b/src/downloadmanager.h
@@ -45,6 +45,7 @@ struct NexusInfo {
QString m_Version;
QString m_NewestVersion;
QString m_FileName;
+ QVariantList m_DownloadMap;
bool m_Set;
};
Q_DECLARE_METATYPE(NexusInfo)
@@ -322,6 +323,11 @@ signals:
*/
void stateChanged(int row, DownloadManager::DownloadState state);
+ /**
+ * @brief emitted whenever a download completes successfully, reporting the download speed for the server used
+ */
+ void downloadSpeed(const QString &serverName, int bytesPerSecond);
+
public slots:
/**
diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp
index a6d86f36..5d00142d 100644
--- a/src/installationmanager.cpp
+++ b/src/installationmanager.cpp
@@ -114,7 +114,8 @@ void InstallationManager::mapToArchive(const DirectoryTree::Node *node, std::wst
for (DirectoryTree::const_node_iterator iter = node->nodesBegin(); iter != node->nodesEnd(); ++iter) {
if ((*iter)->getData().index != -1) {
data[(*iter)->getData().index]->setSkip(false);
- data[(*iter)->getData().index]->setOutputFileName(path.substr().append(ToWString((*iter)->getData().name)).c_str());
+ std::wstring temp = path.substr().append(ToWString((*iter)->getData().name));
+ data[(*iter)->getData().index]->setOutputFileName(temp.c_str());
}
mapToArchive(*iter, path.substr().append(ToWString((*iter)->getData().name)), data);
}
@@ -151,6 +152,7 @@ bool InstallationManager::unpackSingleFile(const QString &fileName)
if (_wcsicmp(data[i]->getFileName(), ToWString(fileName).c_str()) == 0) {
available = true;
data[i]->setSkip(false);
+qDebug("usf %ls -> %s", data[i]->getFileName(), qPrintable(baseName));
data[i]->setOutputFileName(ToWString(baseName).c_str());
m_TempFilesToDelete.insert(baseName);
} else {
@@ -206,7 +208,7 @@ QString canonicalize(const QString &name)
}
-QStringList InstallationManager::extractFiles(const QStringList &filesOrig)
+QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool flatten)
{
QStringList files;
@@ -222,20 +224,26 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig)
for (size_t i = 0; i < size; ++i) {
if (files.contains(ToQString(data[i]->getFileName()), Qt::CaseInsensitive)) {
- const wchar_t *baseName = wcsrchr(data[i]->getFileName(), '\\');
- if (baseName == NULL) {
- baseName = wcsrchr(data[i]->getFileName(), '/');
- }
- if (baseName == NULL) {
- qCritical("failed to find backslash in %ls", data[i]->getFileName());
- continue;
+ const wchar_t *targetFile = data[i]->getFileName();
+ if (flatten) {
+ targetFile = wcsrchr(data[i]->getFileName(), '\\');
+ if (targetFile == NULL) {
+ targetFile = wcsrchr(data[i]->getFileName(), '/');
+ }
+ if (targetFile == NULL) {
+ qCritical("failed to find backslash in %ls", data[i]->getFileName());
+ continue;
+ } else {
+ // skip the slash
+ ++targetFile;
+ }
}
- data[i]->setOutputFileName(baseName);
+ data[i]->setOutputFileName(targetFile);
- result.append(QDir::tempPath().append("/").append(ToQString(baseName)));
+ result.append(QDir::tempPath().append("/").append(ToQString(targetFile)));
data[i]->setSkip(false);
- m_TempFilesToDelete.insert(ToQString(baseName));
+ m_TempFilesToDelete.insert(ToQString(targetFile));
} else {
data[i]->setSkip(true);
}
@@ -252,6 +260,7 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig)
new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::dummyProgressFile),
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::report7ZipError))) {
+ m_InstallationProgress.hide();
throw std::runtime_error("extracting failed");
}
@@ -401,6 +410,7 @@ void InstallationManager::report7ZipError(LPCWSTR errorMessage)
#else
reportError(QString::fromUtf16(errorMessage));
#endif
+ m_CurrentArchive->cancel();
}
@@ -527,6 +537,7 @@ bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID,
new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::updateProgressFile),
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::report7ZipError))) {
+ m_InstallationProgress.hide();
if (m_CurrentArchive->getLastError() == Archive::ERROR_EXTRACT_CANCELLED) {
return false;
} else {
diff --git a/src/installationmanager.h b/src/installationmanager.h
index 818558b8..ca2a5b67 100644
--- a/src/installationmanager.h
+++ b/src/installationmanager.h
@@ -114,7 +114,7 @@ public:
* @note the temporary file is automatically cleaned up after the installation
* @note This call can be very slow if the archive is large and "solid"
*/
- virtual QStringList extractFiles(const QStringList &files);
+ virtual QStringList extractFiles(const QStringList &files, bool flatten);
/**
* @brief installs an archive
diff --git a/src/main.cpp b/src/main.cpp
index 5be0f374..b6e2a7e9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -283,15 +283,15 @@ void registerMetaTypes()
int main(int argc, char *argv[])
{
MOApplication application(argc, argv);
- qApp->addLibraryPath(application.applicationDirPath() + "/dlls");
+
+ application.addLibraryPath(application.applicationDirPath() + "/dlls");
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
LogBuffer::init(20, QtDebugMsg, application.applicationDirPath() + "/logs/mo_interface.log");
- qDebug("Working directory: %s", qPrintable(QDir::currentPath()));
- qDebug("MO at: %s", qPrintable(application.applicationDirPath()));
- qDebug("user name: %s", getenv("USERNAME"));
+ qDebug("Working directory: %s", qPrintable(QDir::toNativeSeparators(QDir::currentPath())));
+ qDebug("MO at: %s", qPrintable(QDir::toNativeSeparators(application.applicationDirPath())));
QPixmap pixmap(":/MO/gui/splash");
QSplashScreen splash(pixmap);
splash.show();
@@ -404,7 +404,7 @@ int main(int argc, char *argv[])
settings.setValue("gamePath", gamePath.toUtf8().constData());
}
- qDebug("managing game at %s", qPrintable(gamePath));
+ qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(gamePath)));
ExecutablesList executablesList;
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index ebfdfc42..8d5429b4 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -218,6 +218,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
ui->savegameList->setMouseTracking(true);
connect(&m_DownloadManager, SIGNAL(showMessage(QString)), this, SLOT(showMessage(QString)));
+ connect(&m_DownloadManager, SIGNAL(downloadSpeed(QString,int)), this, SLOT(downloadSpeed(QString,int)));
connect(ui->savegameList, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(saveSelectionChanged(QListWidgetItem*)));
@@ -1035,7 +1036,7 @@ void MainWindow::loadPlugins()
}
QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
- qDebug("looking for plugins in %s", pluginPath.toUtf8().constData());
+ qDebug("looking for plugins in %s", QDir::toNativeSeparators(pluginPath).toUtf8().constData());
QDirIterator iter(pluginPath, QDir::Files | QDir::NoDotAndDotDot);
while (iter.hasNext()) {
iter.next();
@@ -3592,6 +3593,12 @@ void MainWindow::linkMenu()
}
}
+void MainWindow::downloadSpeed(const QString &serverName, int bytesPerSecond)
+{
+ m_Settings.setDownloadSpeed(serverName, bytesPerSecond);
+}
+
+
void MainWindow::on_actionSettings_triggered()
{
QString oldModDirectory(m_Settings.getModDirectory());
@@ -4098,7 +4105,6 @@ void MainWindow::updateDownloadListDelegate()
ui->downloadView->setModel(sortProxy);
ui->downloadView->sortByColumn(1, Qt::AscendingOrder);
ui->downloadView->header()->resizeSections(QHeaderView::Fixed);
-// ui->downloadView->setFirstColumnSpanned(0, QModelIndex(), true);
connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), this, SLOT(installDownload(int)));
connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), &m_DownloadManager, SLOT(queryInfo(int)));
diff --git a/src/mainwindow.h b/src/mainwindow.h
index e9115e06..c56a98c6 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -452,6 +452,8 @@ private slots:
*/
void allowListResize();
+ void downloadSpeed(const QString &serverName, int bytesPerSecond);
+
private slots: // ui slots
// actions
void on_actionAdd_Profile_triggered();
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index eb587911..3a65ca27 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -31,7 +31,16 @@
<property name="spacing">
<number>4</number>
</property>
- <property name="margin">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
<number>6</number>
</property>
<item>
@@ -721,7 +730,16 @@ p, li { white-space: pre-wrap; }
<string notr="true">Archives</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
- <property name="margin">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
<number>6</number>
</property>
<item>
@@ -800,7 +818,16 @@ BSAs checked here are loaded in such a way that your installation order is obeye
<string>Data</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
- <property name="margin">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
<number>6</number>
</property>
<item>
@@ -870,7 +897,16 @@ BSAs checked here are loaded in such a way that your installation order is obeye
<string>Saves</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
- <property name="margin">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
<number>6</number>
</property>
<item>
@@ -899,7 +935,16 @@ p, li { white-space: pre-wrap; }
<string>Downloads</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
- <property name="margin">
+ <property name="leftMargin">
+ <number>2</number>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <property name="rightMargin">
+ <number>2</number>
+ </property>
+ <property name="bottomMargin">
<number>2</number>
</property>
<item>
@@ -927,8 +972,14 @@ p, li { white-space: pre-wrap; }
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
- <property name="showDropIndicator" stdset="0">
- <bool>false</bool>
+ <property name="dragEnabled">
+ <bool>true</bool>
+ </property>
+ <property name="dragDropMode">
+ <enum>QAbstractItemView::DragDrop</enum>
+ </property>
+ <property name="defaultDropAction">
+ <enum>Qt::MoveAction</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
diff --git a/src/profile.cpp b/src/profile.cpp
index eb2eff87..a6d8f49d 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -675,14 +675,13 @@ bool Profile::enableLocalSaves(bool enable)
m_Directory.mkdir("saves");
}
} else {
-
QMessageBox::StandardButton res = QMessageBox::question(QApplication::activeModalWidget(), tr("Delete savegames?"),
tr("Do you want to delete local savegames? (If you select \"No\", the save games "
"will show up again if you re-enable local savegames)"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
QMessageBox::Cancel);
if (res == QMessageBox::Yes) {
- shellDelete(QStringList(m_Directory.absoluteFilePath("_saves")));
+ shellDelete(QStringList(m_Directory.absoluteFilePath("saves")));
} else if (res == QMessageBox::No) {
m_Directory.rename("saves", "_saves");
} else {
diff --git a/src/settings.cpp b/src/settings.cpp
index 61c8dd6d..39b6dba7 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -153,6 +153,24 @@ QString Settings::getDownloadDirectory() const
return QDir::toNativeSeparators(m_Settings.value("Settings/download_directory", ToQString(GameInfo::instance().getDownloadDir())).toString());
}
+
+void Settings::setDownloadSpeed(const QString &serverName, int bytesPerSecond)
+{
+ m_Settings.beginGroup("Servers");
+
+ foreach (const QString &serverKey, m_Settings.childKeys()) {
+ QVariantMap data = m_Settings.value(serverKey).toMap();
+ if (serverKey == serverName) {
+ data["downloadCount"] = data["downloadCount"].toInt() + 1;
+ data["downloadSpeed"] = data["downloadSpeed"].toDouble() + static_cast<double>(bytesPerSecond);
+ m_Settings.setValue(serverKey, data);
+ }
+ }
+
+ m_Settings.endGroup();
+ m_Settings.sync();
+}
+
std::map<QString, int> Settings::getPreferredServers()
{
std::map<QString, int> result;
@@ -293,8 +311,11 @@ void Settings::updateServers(const QList<ServerInfo> &servers)
// not yet known server
QVariantMap newVal;
newVal["premium"] = server.premium;
- newVal["preferred"] = server.preferred;
+ newVal["preferred"] = server.preferred ? 1 : 0;
newVal["lastSeen"] = server.lastSeen;
+ newVal["downloadCount"] = 0;
+ newVal["downloadSpeed"] = 0.0;
+
m_Settings.setValue(server.name, newVal);
} else {
QVariantMap data = m_Settings.value(server.name).toMap();
@@ -493,14 +514,6 @@ void Settings::query(QWidget *parent)
passwordEdit->setText(deObfuscate(m_Settings.value("Settings/nexus_password", "").toString()));
}
-/* bool registryWritable = false;
- bool nxmHandler = isNXMHandler(&registryWritable);
- handleNXMBox->setChecked(nxmHandler);
- if (!registryWritable) {
- handleNXMBox->setIcon(QIcon(":/MO/gui/locked"));
- handleNXMBox->setToolTip(tr("Administrative rights required to change this."));
- }*/
-
downloadDirEdit->setText(getDownloadDirectory());
modDirEdit->setText(getModDirectory());
cacheDirEdit->setText(getCacheDirectory());
@@ -520,7 +533,15 @@ void Settings::query(QWidget *parent)
foreach (const QString &key, m_Settings.childKeys()) {
QVariantMap val = m_Settings.value(key).toMap();
QString type = val["premium"].toBool() ? "(premium)" : "(free)";
- QListWidgetItem *newItem = new QListWidgetItemEx<int>(key + " " + type, Qt::UserRole + 1);
+
+ QString descriptor = key + " " + type;
+ if (val.contains("downloadSpeed") && val.contains("downloadCount") && (val["downloadCount"].toInt() > 0)) {
+ int bps = static_cast<int>(val["downloadSpeed"].toDouble() / val["downloadCount"].toInt());
+ descriptor += QString(" (%1 kbps)").arg(bps / 1024);
+ }
+
+ QListWidgetItem *newItem = new QListWidgetItemEx<int>(descriptor, Qt::UserRole + 1);
+
newItem->setData(Qt::UserRole, key);
newItem->setData(Qt::UserRole + 1, val["preferred"].toInt());
if (val["preferred"].toInt() > 0) {
diff --git a/src/settings.h b/src/settings.h
index f1d29bd7..bf17d162 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -83,6 +83,13 @@ public:
bool forceEnableCoreFiles() const;
/**
+ * @brief register download speed
+ * @param url complete download url
+ * @param bytesPerSecond download size in bytes per second
+ */
+ void setDownloadSpeed(const QString &serverName, int bytesPerSecond);
+
+ /**
* the steam appid is assigned by the steam platform to each product sold there.
* The appid may differ between different versions of a game so it may be impossible
* for Mod Organizer to automatically recognize it, though usually it does
diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp
index 802c3696..bd33fef6 100644
--- a/src/shared/directoryentry.cpp
+++ b/src/shared/directoryentry.cpp
@@ -27,6 +27,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "util.h"
#include "windows_error.h"
#include <boost/bind.hpp>
+#include <boost/scoped_array.hpp>
#include "util.h"
#include "leaktrace.h"
@@ -443,16 +444,10 @@ FilesOrigin &DirectoryEntry::createOrigin(const std::wstring &originName, const
void DirectoryEntry::addFromOrigin(const std::wstring &originName, const std::wstring &directory, int priority)
{
FilesOrigin &origin = createOrigin(originName, directory, priority);
- wchar_t *buffer = new wchar_t[MAXPATH_UNICODE + 1];
- memset(buffer, L'\0', MAXPATH_UNICODE + 1);
- try {
- int offset = _snwprintf(buffer, MAXPATH_UNICODE, L"%ls", directory.c_str());
- addFiles(origin, buffer, offset);
- } catch (...) {
- delete [] buffer;
- buffer = NULL;
- }
- delete [] buffer;
+ boost::scoped_array<wchar_t> buffer(new wchar_t[MAXPATH_UNICODE + 1]);
+ memset(buffer.get(), L'\0', MAXPATH_UNICODE + 1);
+ int offset = _snwprintf(buffer.get(), MAXPATH_UNICODE, L"%ls", directory.c_str());
+ addFiles(origin, buffer.get(), offset);
m_Populated = true;
}
diff --git a/src/version.rc b/src/version.rc
index 42e947f5..80ee070f 100644
--- a/src/version.rc
+++ b/src/version.rc
@@ -1,7 +1,7 @@
#include "Winver.h"
-#define VER_FILEVERSION 0,99,3,0
-#define VER_FILEVERSION_STR "0,99,3,0\0"
+#define VER_FILEVERSION 0,99,4,0
+#define VER_FILEVERSION_STR "0,99,4,0\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION