-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #82 from oblivioncth/dev
Merge to master for v0.9.10
- Loading branch information
Showing
54 changed files
with
1,127 additions
and
1,047 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// Unit Include | ||
#include "c-download.h" | ||
|
||
// Project Includes | ||
#include "task/t-download.h" | ||
#include "task/t-generic.h" | ||
|
||
//=============================================================================================================== | ||
// CDownloadError | ||
//=============================================================================================================== | ||
|
||
//-Constructor------------------------------------------------------------- | ||
//Private: | ||
CDownloadError::CDownloadError(Type t, const QString& s) : | ||
mType(t), | ||
mSpecific(s) | ||
{} | ||
|
||
//-Instance Functions------------------------------------------------------------- | ||
//Public: | ||
bool CDownloadError::isValid() const { return mType != NoError; } | ||
QString CDownloadError::specific() const { return mSpecific; } | ||
CDownloadError::Type CDownloadError::type() const { return mType; } | ||
|
||
//Private: | ||
Qx::Severity CDownloadError::deriveSeverity() const { return Qx::Critical; } | ||
quint32 CDownloadError::deriveValue() const { return mType; } | ||
QString CDownloadError::derivePrimary() const { return ERR_STRINGS.value(mType); } | ||
QString CDownloadError::deriveSecondary() const { return mSpecific; } | ||
|
||
//=============================================================================================================== | ||
// CDownload | ||
//=============================================================================================================== | ||
|
||
//-Constructor------------------------------------------------------------- | ||
//Public: | ||
CDownload::CDownload(Core& coreRef) : Command(coreRef) {} | ||
|
||
//-Instance Functions------------------------------------------------------------- | ||
//Protected: | ||
QList<const QCommandLineOption*> CDownload::options() const { return CL_OPTIONS_SPECIFIC + Command::options(); } | ||
QSet<const QCommandLineOption*> CDownload::requiredOptions() const { return CL_OPTIONS_REQUIRED + Command::requiredOptions(); } | ||
QString CDownload::name() const { return NAME; } | ||
|
||
Qx::Error CDownload::perform() | ||
{ | ||
QString playlistName = mParser.value(CL_OPTION_PLAYLIST).trimmed(); | ||
mCore.setStatus(STATUS_DOWNLOAD, playlistName); | ||
|
||
Fp::Db* db = mCore.fpInstall().database(); | ||
Fp::PlaylistManager* pm = mCore.fpInstall().playlistManager(); | ||
if(Qx::Error pError = pm->populate(); pError.isValid()) | ||
return pError; | ||
|
||
// Find playlist | ||
QList<Fp::Playlist> playlists = pm->playlists(); | ||
auto pItr = std::find_if(playlists.cbegin(), playlists.cend(), [&playlistName](auto p){ | ||
return p.title() == playlistName || p.title().trimmed() == playlistName; // Some playlists have spaces for sorting purposes | ||
}); | ||
|
||
if(pItr == playlists.cend()) | ||
{ | ||
CDownloadError err(CDownloadError::InvalidPlaylist, playlistName); | ||
postError(err); | ||
return err; | ||
} | ||
logEvent(LOG_EVENT_PLAYLIST_MATCH.arg(pItr->id().toString(QUuid::WithoutBraces))); | ||
|
||
// Queue downloads for each game | ||
TDownload* downloadTask = new TDownload(&mCore); | ||
downloadTask->setStage(Task::Stage::Primary); | ||
downloadTask->setDescription(u"playlist data packs"_s); | ||
QList<int> dataIds; | ||
|
||
const Fp::Toolkit* tk = mCore.fpInstall().toolkit(); | ||
for(const auto& pg : pItr->playlistGames()) | ||
{ | ||
// Get data | ||
Fp::GameData gameData; | ||
if(Fp::DbError gdErr = db->getGameData(gameData, pg.gameId()); gdErr.isValid()) | ||
{ | ||
postError(gdErr); | ||
return gdErr; | ||
} | ||
|
||
if(gameData.isNull()) | ||
{ | ||
logEvent(LOG_EVENT_NON_DATAPACK.arg(pg.gameId().toString(QUuid::WithoutBraces))); | ||
continue; | ||
} | ||
|
||
if(tk->datapackIsPresent(gameData)) | ||
continue; | ||
|
||
// Queue download | ||
downloadTask->addFile({.target = tk->datapackUrl(gameData), .dest = tk->datapackPath(gameData), .checksum = gameData.sha256()}); | ||
|
||
// Note data id | ||
dataIds.append(gameData.id()); | ||
} | ||
|
||
if(downloadTask->isEmpty()) | ||
{ | ||
logEvent(LOG_EVENT_NO_OP); | ||
return CDownloadError(); | ||
} | ||
|
||
// Enqueue download task | ||
mCore.enqueueSingleTask(downloadTask); | ||
|
||
// Enqueue onDiskState update task | ||
Core* corePtr = &mCore; // Safe, will outlive task | ||
TGeneric* onDiskUpdateTask = new TGeneric(corePtr); | ||
onDiskUpdateTask->setStage(Task::Stage::Primary); | ||
onDiskUpdateTask->setDescription(u"Update GameData onDisk state."_s); | ||
onDiskUpdateTask->setAction([dataIds, corePtr]{ | ||
return corePtr->fpInstall().database()->updateGameDataOnDiskState(dataIds, true); | ||
}); | ||
mCore.enqueueSingleTask(onDiskUpdateTask); | ||
|
||
// Return success | ||
return CDownloadError(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
#ifndef CDOWNLOAD_H | ||
#define CDOWNLOAD_H | ||
|
||
// Qx Includes | ||
#include <qx/utility/qx-macros.h> | ||
|
||
// Project Includes | ||
#include "command/command.h" | ||
|
||
class QX_ERROR_TYPE(CDownloadError, "CDownloadError", 1217) | ||
{ | ||
friend class CDownload; | ||
//-Class Enums------------------------------------------------------------- | ||
public: | ||
enum Type | ||
{ | ||
NoError, | ||
InvalidPlaylist | ||
}; | ||
|
||
//-Class Variables------------------------------------------------------------- | ||
private: | ||
static inline const QHash<Type, QString> ERR_STRINGS{ | ||
{NoError, u""_s}, | ||
{InvalidPlaylist, u""_s} | ||
}; | ||
|
||
//-Instance Variables------------------------------------------------------------- | ||
private: | ||
Type mType; | ||
QString mSpecific; | ||
|
||
//-Constructor------------------------------------------------------------- | ||
private: | ||
CDownloadError(Type t = NoError, const QString& s = {}); | ||
|
||
//-Instance Functions------------------------------------------------------------- | ||
public: | ||
bool isValid() const; | ||
Type type() const; | ||
QString specific() const; | ||
|
||
private: | ||
Qx::Severity deriveSeverity() const override; | ||
quint32 deriveValue() const override; | ||
QString derivePrimary() const override; | ||
QString deriveSecondary() const override; | ||
}; | ||
|
||
class CDownload : public Command | ||
{ | ||
//-Class Variables------------------------------------------------------------------------------------------------------ | ||
private: | ||
// Status | ||
static inline const QString STATUS_DOWNLOAD = u"Downloading data packs"_s; | ||
|
||
// Logging | ||
static inline const QString LOG_EVENT_PLAYLIST_MATCH = u"Playlist matches ID: %1"_s; | ||
static inline const QString LOG_EVENT_NON_DATAPACK = u"Game %1 does not use a data pack."_s; | ||
static inline const QString LOG_EVENT_NO_OP = u"No datapacks to download."_s; | ||
|
||
// Command line option strings | ||
static inline const QString CL_OPT_PLAYLIST_S_NAME = u"p"_s; | ||
static inline const QString CL_OPT_PLAYLIST_L_NAME = u"playlist"_s; | ||
static inline const QString CL_OPT_PLAYLIST_DESC = u"Name of the playlist to download games for."_s; | ||
|
||
// Command line options | ||
static inline const QCommandLineOption CL_OPTION_PLAYLIST{{CL_OPT_PLAYLIST_S_NAME, CL_OPT_PLAYLIST_L_NAME}, CL_OPT_PLAYLIST_DESC, u"playlist"_s}; // Takes value | ||
static inline const QList<const QCommandLineOption*> CL_OPTIONS_SPECIFIC{&CL_OPTION_PLAYLIST}; | ||
static inline const QSet<const QCommandLineOption*> CL_OPTIONS_REQUIRED{&CL_OPTION_PLAYLIST}; | ||
|
||
public: | ||
// Meta | ||
static inline const QString NAME = u"download"_s; | ||
static inline const QString DESCRIPTION = u"Download game data packs in bulk"_s; | ||
|
||
//-Constructor---------------------------------------------------------------------------------------------------------- | ||
public: | ||
CDownload(Core& coreRef); | ||
|
||
//-Instance Functions------------------------------------------------------------------------------------------------------ | ||
protected: | ||
QList<const QCommandLineOption*> options() const override; | ||
QSet<const QCommandLineOption*> requiredOptions() const override; | ||
QString name() const override; | ||
Qx::Error perform() override; | ||
}; | ||
REGISTER_COMMAND(CDownload::NAME, CDownload, CDownload::DESCRIPTION); | ||
|
||
#endif // CDOWNLOAD_H |
Oops, something went wrong.