diff --git a/CMakeLists.txt b/CMakeLists.txt
index 01f34ac..956a194 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -74,7 +74,7 @@ endif()
include(OB/FetchQx)
ob_fetch_qx(
- REF "0572d288936afd63ff6f5b6ce4b1fbfc0f03b0eb"
+ REF "98088b18de1ed812f55adaff3b030f273c42a6c2"
COMPONENTS
${FIL_QX_COMPONENTS}
)
@@ -104,7 +104,7 @@ ob_fetch_clifp("7139ae998b292eb595e751ba4cb8599230435358")
# Fetch Neargye's Magic Enum
include(OB/FetchMagicEnum)
-ob_fetch_magicenum("v0.9.3")
+ob_fetch_magicenum("v0.9.7")
# Process Targets
set(APP_TARGET_NAME ${PROJECT_NAMESPACE_LC}_${PROJECT_NAMESPACE_LC})
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index d5e7e9b..5dc495c 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -23,48 +23,53 @@ add_custom_target(fil_copy_clifp
# ------------------ Setup FIL --------------------------
set(FIL_SOURCE
- frontend/fe-data.h
- frontend/fe-data.cpp
- frontend/fe-installfoundation.h
- frontend/fe-installfoundation.cpp
- frontend/fe-installfoundation_win.cpp
- frontend/fe-installfoundation_linux.cpp
- frontend/fe-install.h
- frontend/fe-install.cpp
- frontend/fe-items.h
- frontend/fe-items.cpp
- frontend/attractmode/am-data.h
- frontend/attractmode/am-data.cpp
- frontend/attractmode/am-install.h
- frontend/attractmode/am-install.cpp
- frontend/attractmode/am-install_win.cpp
- frontend/attractmode/am-install_linux.cpp
- frontend/attractmode/am-items.h
- frontend/attractmode/am-items.cpp
- frontend/attractmode/am-settings-data.h
- frontend/attractmode/am-settings-data.cpp
- frontend/attractmode/am-settings-items.h
- frontend/attractmode/am-settings-items.cpp
+ import/properties.h
+ import/properties.cpp
+ import/settings.h
+ import/worker.h
+ import/worker.cpp
+ launcher/lr-data.h
+ launcher/lr-data.cpp
+ launcher/lr-installfoundation.h
+ launcher/lr-installfoundation.cpp
+ launcher/lr-installfoundation_win.cpp
+ launcher/lr-installfoundation_linux.cpp
+ launcher/lr-install.h
+ launcher/lr-install.cpp
+ launcher/lr-items.h
+ launcher/lr-items.cpp
+ launcher/attractmode/am-data.h
+ launcher/attractmode/am-data.cpp
+ launcher/attractmode/am-install.h
+ launcher/attractmode/am-install.cpp
+ launcher/attractmode/am-install_win.cpp
+ launcher/attractmode/am-install_linux.cpp
+ launcher/attractmode/am-items.h
+ launcher/attractmode/am-items.cpp
+ launcher/attractmode/am-settings-data.h
+ launcher/attractmode/am-settings-data.cpp
+ launcher/attractmode/am-settings-items.h
+ launcher/attractmode/am-settings-items.cpp
ui/mainwindow.h
ui/mainwindow.cpp
ui/mainwindow.ui
ui/progresspresenter.h
ui/progresspresenter.cpp
- clifp.h
- clifp.cpp
- import-worker.h
- import-worker.cpp
+ kernel/controller.h
+ kernel/controller.cpp
+ kernel/clifp.h
+ kernel/clifp.cpp
main.cpp
)
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
list(APPEND FIL_SOURCE
- frontend/launchbox/lb-data.h
- frontend/launchbox/lb-data.cpp
- frontend/launchbox/lb-install.h
- frontend/launchbox/lb-install.cpp
- frontend/launchbox/lb-items.h
- frontend/launchbox/lb-items.cpp
+ launcher/launchbox/lb-data.h
+ launcher/launchbox/lb-data.cpp
+ launcher/launchbox/lb-install.h
+ launcher/launchbox/lb-install.cpp
+ launcher/launchbox/lb-items.h
+ launcher/launchbox/lb-items.cpp
)
endif()
@@ -104,6 +109,11 @@ ob_add_standard_executable(${APP_TARGET_NAME}
WIN32
)
+target_sources(fil_fil
+ PRIVATE
+
+)
+
# Note that the executable depends on CLIFp being copied into its build dir
add_dependencies(${APP_TARGET_NAME} fil_copy_clifp)
diff --git a/app/res/frontend/AttractMode/icon.png b/app/res/launcher/AttractMode/icon.png
similarity index 100%
rename from app/res/frontend/AttractMode/icon.png
rename to app/res/launcher/AttractMode/icon.png
diff --git a/app/res/frontend/AttractMode/marquee.png b/app/res/launcher/AttractMode/marquee.png
similarity index 100%
rename from app/res/frontend/AttractMode/marquee.png
rename to app/res/launcher/AttractMode/marquee.png
diff --git a/app/res/frontend/LaunchBox/icon.svg b/app/res/launcher/LaunchBox/icon.svg
similarity index 100%
rename from app/res/frontend/LaunchBox/icon.svg
rename to app/res/launcher/LaunchBox/icon.svg
diff --git a/app/res/resources.qrc b/app/res/resources.qrc
index badfcbb..0ba26f3 100644
--- a/app/res/resources.qrc
+++ b/app/res/resources.qrc
@@ -8,9 +8,9 @@
ui/CLIFp.png
ui/Exit.png
ui/GitHub.png
- frontend/LaunchBox/icon.svg
- frontend/AttractMode/icon.png
- frontend/AttractMode/marquee.png
+ launcher/LaunchBox/icon.svg
+ launcher/AttractMode/icon.png
+ launcher/AttractMode/marquee.png
flashpoint/icon.png
ui/About.png
diff --git a/app/src/import/properties.cpp b/app/src/import/properties.cpp
new file mode 100644
index 0000000..b77d3e8
--- /dev/null
+++ b/app/src/import/properties.cpp
@@ -0,0 +1,65 @@
+// Unit Include
+#include "properties.h"
+
+namespace Import
+{
+
+//===============================================================================================================
+// Properties
+//===============================================================================================================
+
+//-Constructor-------------------------------------------------------------
+//Public:
+Properties::Properties() :
+ mHasLinkPerms(false)
+{}
+
+//-Instance Functions-------------------------------------------------------------
+//Public:
+void Properties::setHasLinkPermissions(bool perms) { mHasLinkPerms = perms; }
+bool Properties::hasLinkPermissions() const { return mHasLinkPerms; }
+
+Qx::Bindable Properties::bindableIsLauncherPresent() { return &mLauncherPresent; }
+bool Properties::isLauncherPresent() const { return mLauncherPresent; }
+
+Qx::Bindable Properties::bindableIsLauncherReady() { return &mLauncherReady; }
+bool Properties::isLauncherReady() const { return mLauncherReady; }
+
+Qx::Bindable Properties::bindableIsFlashpointPresent() { return &mFlashpointPresent; }
+bool Properties::isFlashpointPresent() const { return mFlashpointPresent; }
+
+Qx::Bindable Properties::bindableIsFlashpointReady() { return &mFlashpointReady; }
+bool Properties::isFlashpointReady() const { return mFlashpointReady; }
+
+Qx::Bindable Properties::bindableIsBothTargetsReady() { return &mBothTargetsReady; }
+bool Properties::isBothTargetsReady() const { return mBothTargetsReady; }
+
+Qx::Bindable Properties::bindableIsFlashpointTargetSeries() { return &mFlashpointTargetSeries; }
+bool Properties::isFlashpointTargetSeries() const { return mFlashpointTargetSeries; }
+
+Qx::Bindable> Properties::bindableImageModeOrder() { return &mImageModeOrder; }
+const Qx::Bindable> Properties::bindableImageModeOrder() const { return &mImageModeOrder; }
+QList Properties::imageModeOrder() const { return mImageModeOrder; }
+
+Qx::Bindable Properties::bindableIsImageDownloadable() { return &mImageDownloadable; }
+bool Properties::isImageDownloadable() const { return mImageDownloadable; }
+
+Qx::Bindable Properties::bindableLauncherInfo() { return &mLauncherInfo; }
+QString Properties::launcherInfo() const { return mLauncherInfo; }
+
+Qx::Bindable Properties::bindableFlashpointInfo() { return &mFlashpointInfo; }
+QString Properties::flashpointInfo() const { return mFlashpointInfo; }
+
+Qx::Bindable> Properties::bindableTagMap() { return &mTagMap; }
+const Qx::Bindable> Properties::bindableTagMap() const { return &mTagMap; }
+QMap Properties::tagMap() const { return mTagMap; }
+
+Qx::Bindable> Properties::bindablePlatforms() { return &mPlatforms; }
+const Qx::Bindable> Properties::bindablePlatforms() const { return &mPlatforms; }
+QList Properties::platforms() const { return mPlatforms; }
+
+Qx::Bindable> Properties::bindablePlaylists() { return &mPlaylists; }
+const Qx::Bindable> Properties::bindablePlaylists() const { return &mPlaylists; }
+QList Properties::playlists() const { return mPlaylists; }
+
+}
diff --git a/app/src/import/properties.h b/app/src/import/properties.h
new file mode 100644
index 0000000..ff01d42
--- /dev/null
+++ b/app/src/import/properties.h
@@ -0,0 +1,101 @@
+#ifndef IMPORT_PROPERTIES_H
+#define IMPORT_PROPERTIES_H
+
+// Qt Includes
+#include
+
+// Qx Includes
+#include
+
+// libfp Includes
+#include
+
+// Project Includes
+#include "import/settings.h"
+
+/* TODO: The number of properties here has gotten somewhat out of hand.
+ * Mainwindow should probably just be given access to something like
+ * const QBindable> (and same for
+ * launcher) so that it can setup its own bindings/properties directly
+ * off of that. Since it would be read only, that still lets Controller
+ * have control of the instances.
+ */
+
+namespace Import
+{
+
+class Properties
+{
+//-Instance Variables-------------------------------------------------------------
+private:
+ bool mHasLinkPerms;
+ Qx::Property mLauncherPresent;
+ Qx::Property mLauncherReady;
+ Qx::Property mFlashpointPresent;
+ Qx::Property mFlashpointReady;
+ Qx::Property mBothTargetsReady;
+ Qx::Property mFlashpointTargetSeries;
+ Qx::Property> mImageModeOrder;
+ Qx::Property mImageDownloadable;
+ Qx::Property mLauncherInfo;
+ Qx::Property mFlashpointInfo;
+ Qx::Property> mTagMap;
+ Qx::Property> mPlatforms;
+ Qx::Property> mPlaylists;
+
+//-Constructor-------------------------------------------------------------
+public:
+ Properties();
+
+//-Instance Functions-------------------------------------------------------------
+public:
+ void setHasLinkPermissions(bool perms);
+ bool hasLinkPermissions() const;
+
+ Qx::Bindable bindableIsLauncherPresent();
+ bool isLauncherPresent() const;
+
+ Qx::Bindable bindableIsLauncherReady();
+ bool isLauncherReady() const;
+
+ Qx::Bindable bindableIsFlashpointPresent();
+ bool isFlashpointPresent() const;
+
+ Qx::Bindable bindableIsFlashpointReady();
+ bool isFlashpointReady() const;
+
+ Qx::Bindable bindableIsBothTargetsReady();
+ bool isBothTargetsReady() const;
+
+ Qx::Bindable bindableIsFlashpointTargetSeries();
+ bool isFlashpointTargetSeries() const;
+
+ Qx::Bindable> bindableImageModeOrder();
+ const Qx::Bindable> bindableImageModeOrder() const;
+ QList imageModeOrder() const;
+
+ Qx::Bindable bindableIsImageDownloadable();
+ bool isImageDownloadable() const;
+
+ Qx::Bindable bindableLauncherInfo();
+ QString launcherInfo() const;
+
+ Qx::Bindable bindableFlashpointInfo();
+ QString flashpointInfo() const;
+
+ Qx::Bindable> bindableTagMap();
+ const Qx::Bindable> bindableTagMap() const;
+ QMap tagMap() const;
+
+ Qx::Bindable> bindablePlatforms();
+ const Qx::Bindable> bindablePlatforms() const;
+ QList platforms() const;
+
+ Qx::Bindable> bindablePlaylists();
+ const Qx::Bindable> bindablePlaylists() const;
+ QList playlists() const;
+};
+
+}
+
+#endif // IMPORT_PROPERTIES_H
diff --git a/app/src/import/settings.h b/app/src/import/settings.h
new file mode 100644
index 0000000..40c990c
--- /dev/null
+++ b/app/src/import/settings.h
@@ -0,0 +1,50 @@
+#ifndef IMPORT_SETTINGS_H
+#define IMPORT_SETTINGS_H
+
+// Qt Includes
+#include
+#include
+
+// libfp Includes
+#include
+
+namespace Import
+{
+
+// Enums
+enum class Install{ Launcher, Flashpoint };
+enum class UpdateMode {OnlyNew, NewAndExisting};
+enum class ImageMode {Copy, Reference, Link};
+enum class PlaylistGameMode {SelectedPlatform, ForceAll};
+
+// Structs
+struct Importee
+{
+ QString name;
+ bool existing = false;
+};
+
+struct Selections
+{
+ QStringList platforms;
+ QStringList playlists;
+};
+
+struct UpdateOptions
+{
+ UpdateMode importMode;
+ bool removeObsolete;
+};
+
+struct OptionSet
+{
+ UpdateOptions updateOptions;
+ ImageMode imageMode;
+ bool downloadImages;
+ PlaylistGameMode playlistMode;
+ Fp::Db::InclusionOptions inclusionOptions;
+};
+
+}
+
+#endif // IMPORT_SETTINGS_H
diff --git a/app/src/import-worker.cpp b/app/src/import/worker.cpp
similarity index 85%
rename from app/src/import-worker.cpp
rename to app/src/import/worker.cpp
index 8207e55..0829681 100644
--- a/app/src/import-worker.cpp
+++ b/app/src/import/worker.cpp
@@ -1,5 +1,5 @@
// Unit Include
-#include "import-worker.h"
+#include "worker.h"
// Standard Library Includes
#include
@@ -12,7 +12,10 @@
#include
// Project Includes
-#include "clifp.h"
+#include "kernel/clifp.h"
+
+namespace Import
+{
//===============================================================================================================
// ImageTransferError
@@ -55,16 +58,16 @@ QString ImageTransferError::deriveDetails() const
QString ImageTransferError::deriveCaption() const { return CAPTION_IMAGE_ERR; }
//===============================================================================================================
-// IMPORT WORKER
+// Worker
//===============================================================================================================
//-Constructor---------------------------------------------------------------------------------------------------
-ImportWorker::ImportWorker(std::shared_ptr fpInstallForWork,
- std::shared_ptr feInstallForWork,
- ImportSelections importSelections,
+Worker::Worker(std::shared_ptr fpInstallForWork,
+ std::shared_ptr lrInstallForWork,
+ Selections importSelections,
OptionSet optionSet) :
mFlashpointInstall(fpInstallForWork),
- mFrontendInstall(feInstallForWork),
+ mLauncherInstall(lrInstallForWork),
mImportSelections(importSelections),
mOptionSet(optionSet),
mCurrentProgress(0),
@@ -73,7 +76,7 @@ ImportWorker::ImportWorker(std::shared_ptr fpInstallForWork,
//-Instance Functions--------------------------------------------------------------------------------------------
//Private:
-Qx::ProgressGroup* ImportWorker::initializeProgressGroup(const QString& groupName, quint64 weight)
+Qx::ProgressGroup* Worker::initializeProgressGroup(const QString& groupName, quint64 weight)
{
Qx::ProgressGroup* pg = mProgressManager.addGroup(groupName);
pg->setWeight(weight);
@@ -82,7 +85,7 @@ Qx::ProgressGroup* ImportWorker::initializeProgressGroup(const QString& groupNam
return pg;
}
-Qx::Error ImportWorker::preloadPlaylists(QList& targetPlaylists)
+Qx::Error Worker::preloadPlaylists(QList& targetPlaylists)
{
// Reset playlists
targetPlaylists.clear();
@@ -103,7 +106,7 @@ Qx::Error ImportWorker::preloadPlaylists(QList& targetPlaylists)
return Qx::Error();
}
-QList ImportWorker::getPlaylistSpecificGameIds(const QList& playlists)
+QList Worker::getPlaylistSpecificGameIds(const QList& playlists)
{
QList playlistSpecGameIds;
@@ -114,7 +117,7 @@ QList ImportWorker::getPlaylistSpecificGameIds(const QList&
return playlistSpecGameIds;
}
-ImageTransferError ImportWorker::transferImage(bool symlink, QString sourcePath, QString destinationPath)
+ImageTransferError Worker::transferImage(bool symlink, QString sourcePath, QString destinationPath)
{
/* TODO: Ideally the error handlers here don't need to include "Retry?" text and therefore need less use of QString::arg(); however, this largely
* would require use of a button labeled "Ignore All" so that the errors could presented as is without a prompt, with the prompt being inferred
@@ -156,7 +159,7 @@ ImageTransferError ImportWorker::transferImage(bool symlink, QString sourcePath,
return ImageTransferError(ImageTransferError::CantCreateDirectory, QString(), destinationDir.absolutePath());
// Determine backup path
- QString backupPath = Fe::Install::filePathToBackupPath(destinationInfo.absoluteFilePath());
+ QString backupPath = Lr::Install::filePathToBackupPath(destinationInfo.absoluteFilePath());
// Temporarily backup image if it already exists (also acts as deletion marking in case images for the title were removed in an update)
if(destinationOccupied)
@@ -178,7 +181,7 @@ ImageTransferError ImportWorker::transferImage(bool symlink, QString sourcePath,
else if(QFile::exists(backupPath))
QFile::remove(backupPath);
else
- mFrontendInstall->addRevertableFile(destinationPath); // Only queue image to be removed on failure if its new, so existing images aren't deleted on revert
+ mLauncherInstall->addRevertableFile(destinationPath); // Only queue image to be removed on failure if its new, so existing images aren't deleted on revert
}
else
{
@@ -190,21 +193,21 @@ ImageTransferError ImportWorker::transferImage(bool symlink, QString sourcePath,
else if(QFile::exists(backupPath))
QFile::remove(backupPath);
else
- mFrontendInstall->addRevertableFile(destinationPath); // Only queue image to be removed on failure if its new, so existing images aren't deleted on revert
+ mLauncherInstall->addRevertableFile(destinationPath); // Only queue image to be removed on failure if its new, so existing images aren't deleted on revert
}
// Return null error on success
return ImageTransferError();
}
-bool ImportWorker::performImageJobs(const QList& jobs, bool symlink, Qx::ProgressGroup* pg)
+bool Worker::performImageJobs(const QList& jobs, bool symlink, Qx::ProgressGroup* pg)
{
// Setup for image transfers
ImageTransferError imageTransferError; // Error return reference
*mBlockingErrorResponse = QMessageBox::NoToAll; // Default to choice "NoToAll" in case the signal is not correctly connected using Qt::BlockingQueuedConnection
bool ignoreAllTransferErrors = false; // NoToAll response tracker
- for(const Fe::Install::ImageMap& imageJob : jobs)
+ for(const Lr::Install::ImageMap& imageJob : jobs)
{
while((imageTransferError = transferImage(symlink, imageJob.sourcePath, imageJob.destPath)).isValid() && !ignoreAllTransferErrors)
{
@@ -229,7 +232,7 @@ bool ImportWorker::performImageJobs(const QList& jobs, bo
return true;
}
-ImportWorker::ImportResult ImportWorker::processPlatformGames(Qx::Error& errorReport, std::unique_ptr& platformDoc, Fp::Db::QueryBuffer& gameQueryResult)
+Worker::Result Worker::processPlatformGames(Qx::Error& errorReport, std::unique_ptr& platformDoc, Fp::Db::QueryBuffer& gameQueryResult)
{
const Fp::Toolkit* tk = mFlashpointInstall->toolkit();
@@ -280,7 +283,7 @@ ImportWorker::ImportResult ImportWorker::processPlatformGames(Qx::Error& errorRe
// Add set to doc
QString checkedLogoPath = (logoLocalInfo.exists() || mOptionSet.downloadImages) ? logoLocalInfo.absoluteFilePath() : QString();
QString checkedScreenshotPath = (ssLocalInfo.exists() || mOptionSet.downloadImages) ? ssLocalInfo.absoluteFilePath() : QString();
- platformDoc->addSet(builtSet, Fe::ImageSources(checkedLogoPath, checkedScreenshotPath));
+ platformDoc->addSet(builtSet, Lr::ImageSources(checkedLogoPath, checkedScreenshotPath));
// Add ID to imported game cache
mImportedGameIdsCache.insert(builtGame.id());
@@ -306,7 +309,7 @@ ImportWorker::ImportResult ImportWorker::processPlatformGames(Qx::Error& errorRe
}
// Handle image transfer progress
- if(mOptionSet.imageMode == Fe::ImageMode::Copy || mOptionSet.imageMode == Fe::ImageMode::Link)
+ if(mOptionSet.imageMode == ImageMode::Copy || mOptionSet.imageMode == ImageMode::Link)
{
// Adjust progress if images aren't available
if(checkedLogoPath.isEmpty())
@@ -330,7 +333,7 @@ ImportWorker::ImportResult ImportWorker::processPlatformGames(Qx::Error& errorRe
return Successful;
}
-void ImportWorker::cullUnimportedPlaylistGames(QList& playlists)
+void Worker::cullUnimportedPlaylistGames(QList& playlists)
{
const auto& idCache = mImportedGameIdsCache;
for(auto& pl : playlists)
@@ -341,7 +344,7 @@ void ImportWorker::cullUnimportedPlaylistGames(QList& playlists)
}
}
-ImportWorker::ImportResult ImportWorker::preloadAddApps(Qx::Error& errorReport, Fp::Db::QueryBuffer& addAppQuery)
+Worker::Result Worker::preloadAddApps(Qx::Error& errorReport, Fp::Db::QueryBuffer& addAppQuery)
{
mAddAppsCache.reserve(addAppQuery.size);
for(int i = 0; i < addAppQuery.size; i++)
@@ -380,25 +383,25 @@ ImportWorker::ImportResult ImportWorker::preloadAddApps(Qx::Error& errorReport,
return Successful;
}
-ImportWorker::ImportResult ImportWorker::processGames(Qx::Error& errorReport, QList& primary, QList& playlistSpecific)
+Worker::Result Worker::processGames(Qx::Error& errorReport, QList& primary, QList& playlistSpecific)
{
// Status tracking
- ImportResult platformImportStatus;
+ Result platformImportStatus;
// Track total platforms that have been handled
qsizetype remainingPlatforms = primary.size() + playlistSpecific.size();
// Use lambda to handle both lists due to major overlap
- auto platformsHandler = [&remainingPlatforms, &errorReport, this](QList& platformQueryResults, QString label) -> ImportResult {
- ImportResult result;
+ auto platformsHandler = [&remainingPlatforms, &errorReport, this](QList& platformQueryResults, QString label) -> Result {
+ Result result;
for(int i = 0; i < platformQueryResults.size(); i++)
{
Fp::Db::QueryBuffer& currentQueryResult = platformQueryResults[i];
- // Open frontend platform doc
- std::unique_ptr currentPlatformDoc;
- Fe::DocHandlingError platformReadError = mFrontendInstall->checkoutPlatformDoc(currentPlatformDoc, currentQueryResult.source);
+ // Open launcher platform doc
+ std::unique_ptr currentPlatformDoc;
+ Lr::DocHandlingError platformReadError = mLauncherInstall->checkoutPlatformDoc(currentPlatformDoc, currentQueryResult.source);
// Stop import if error occurred
if(platformReadError.isValid())
@@ -424,8 +427,8 @@ ImportWorker::ImportResult ImportWorker::processGames(Qx::Error& errorReport, QL
}
// Forfeit document lease and save it
- Fe::DocHandlingError saveError;
- if((saveError = mFrontendInstall->commitPlatformDoc(std::move(currentPlatformDoc))).isValid())
+ Lr::DocHandlingError saveError;
+ if((saveError = mLauncherInstall->commitPlatformDoc(std::move(currentPlatformDoc))).isValid())
{
errorReport = saveError;
return Failed;
@@ -453,16 +456,16 @@ ImportWorker::ImportResult ImportWorker::processGames(Qx::Error& errorReport, QL
return Successful;
}
-ImportWorker::ImportResult ImportWorker::processPlaylists(Qx::Error& errorReport, const QList& playlists)
+Worker::Result Worker::processPlaylists(Qx::Error& errorReport, const QList& playlists)
{
for(const auto& currentPlaylist : playlists)
{
// Update progress dialog label
emit progressStepChanged(STEP_IMPORTING_PLAYLISTS.arg(currentPlaylist.title()));
- // Open frontend playlist doc
- std::unique_ptr currentPlaylistDoc;
- Fe::DocHandlingError playlistReadError = mFrontendInstall->checkoutPlaylistDoc(currentPlaylistDoc, currentPlaylist.title());
+ // Open launcher playlist doc
+ std::unique_ptr currentPlaylistDoc;
+ Lr::DocHandlingError playlistReadError = mLauncherInstall->checkoutPlaylistDoc(currentPlaylistDoc, currentPlaylist.title());
// Stop import if error occurred
if(playlistReadError.isValid())
@@ -485,8 +488,8 @@ ImportWorker::ImportResult ImportWorker::processPlaylists(Qx::Error& errorReport
}
// Forfeit document lease and save it
- Fe::DocHandlingError saveError;
- if((saveError = mFrontendInstall->commitPlaylistDoc(std::move(currentPlaylistDoc))).isValid())
+ Lr::DocHandlingError saveError;
+ if((saveError = mLauncherInstall->commitPlaylistDoc(std::move(currentPlaylistDoc))).isValid())
{
errorReport = saveError;
return Failed;
@@ -507,7 +510,7 @@ ImportWorker::ImportResult ImportWorker::processPlaylists(Qx::Error& errorReport
return Successful;
}
-ImportWorker::ImportResult ImportWorker::processImages(Qx::Error& errorReport)
+Worker::Result Worker::processImages(Qx::Error& errorReport)
{
//-Image Download---------------------------------------------------------------------------------
if(mOptionSet.downloadImages && mImageDownloadManager.hasTasks())
@@ -528,8 +531,8 @@ ImportWorker::ImportResult ImportWorker::processImages(Qx::Error& errorReport)
*ignore = *mBlockingErrorResponse == QMessageBox::Yes;
});
- connect(&mImageDownloadManager, &Qx::SyncDownloadManager::authenticationRequired, this, &ImportWorker::authenticationRequired);
- connect(&mImageDownloadManager, &Qx::SyncDownloadManager::proxyAuthenticationRequired, this, &ImportWorker::authenticationRequired);
+ connect(&mImageDownloadManager, &Qx::SyncDownloadManager::authenticationRequired, this, &Worker::authenticationRequired);
+ connect(&mImageDownloadManager, &Qx::SyncDownloadManager::proxyAuthenticationRequired, this, &Worker::authenticationRequired);
connect(&mImageDownloadManager, &Qx::SyncDownloadManager::downloadFinished, this, [this]() { // clazy:exclude=lambda-in-connect
mProgressManager.group(Pg::ImageDownload)->incrementValue();
@@ -558,16 +561,16 @@ ImportWorker::ImportResult ImportWorker::processImages(Qx::Error& errorReport)
// Update progress dialog label
emit progressStepChanged(STEP_IMPORTING_IMAGES);
- // Provide frontend with bulk reference locations and acquire any transfer tasks
- QList imageTransferJobs;
- Fe::ImageSources bulkSources;
- if(mOptionSet.imageMode == Fe::ImageMode::Reference)
+ // Provide launcher with bulk reference locations and acquire any transfer tasks
+ QList imageTransferJobs;
+ Lr::ImageSources bulkSources;
+ if(mOptionSet.imageMode == ImageMode::Reference)
{
bulkSources.setLogoPath(QDir::toNativeSeparators(mFlashpointInstall->entryLogosDirectory().absolutePath()));
bulkSources.setScreenshotPath(QDir::toNativeSeparators(mFlashpointInstall->entryScreenshotsDirectory().absolutePath()));
}
- Qx::Error imageExchangeError = mFrontendInstall->preImageProcessing(imageTransferJobs, bulkSources);
+ Qx::Error imageExchangeError = mLauncherInstall->preImageProcessing(imageTransferJobs, bulkSources);
if(imageExchangeError.isValid())
{
@@ -577,7 +580,7 @@ ImportWorker::ImportResult ImportWorker::processImages(Qx::Error& errorReport)
}
// Perform transfers if required
- if(mOptionSet.imageMode == Fe::ImageMode::Copy || mOptionSet.imageMode == Fe::ImageMode::Link)
+ if(mOptionSet.imageMode == ImageMode::Copy || mOptionSet.imageMode == ImageMode::Link)
{
/*
* Account for potential mismatch between assumed and actual job count.
@@ -587,32 +590,32 @@ ImportWorker::ImportResult ImportWorker::processImages(Qx::Error& errorReport)
if(static_cast(imageTransferJobs.size()) != mProgressManager.group(Pg::ImageTransfer)->maximum())
mProgressManager.group(Pg::ImageTransfer)->setMaximum(imageTransferJobs.size());
- if(!performImageJobs(imageTransferJobs, mOptionSet.imageMode == Fe::ImageMode::Link, mProgressManager.group(Pg::ImageTransfer)))
+ if(!performImageJobs(imageTransferJobs, mOptionSet.imageMode == ImageMode::Link, mProgressManager.group(Pg::ImageTransfer)))
return Canceled;
}
else if(!imageTransferJobs.isEmpty())
- qWarning("the frontend provided image transfers when the mode wasn't link/copy");
+ qWarning("the launcher provided image transfers when the mode wasn't link/copy");
- // Handle frontend specific actions
- mFrontendInstall->postImageProcessing();
+ // Handle launcher specific actions
+ mLauncherInstall->postImageProcessing();
// Report successful step completion
errorReport = Qx::Error();
return Successful;
}
-ImportWorker::ImportResult ImportWorker::processIcons(Qx::Error& errorReport, const QStringList& platforms, const QList& playlists)
+Worker::Result Worker::processIcons(Qx::Error& errorReport, const QStringList& platforms, const QList& playlists)
{
- QList jobs;
- QString mainDest = mFrontendInstall->platformCategoryIconPath();
- std::optional platformDestDir = mFrontendInstall->platformIconsDirectory();
- std::optional playlistDestDir = mFrontendInstall->playlistIconsDirectory();
+ QList jobs;
+ QString mainDest = mLauncherInstall->platformCategoryIconPath();
+ std::optional platformDestDir = mLauncherInstall->platformIconsDirectory();
+ std::optional playlistDestDir = mLauncherInstall->playlistIconsDirectory();
const Fp::Toolkit* tk = mFlashpointInstall->toolkit();
// Main Job
if(!mainDest.isEmpty())
- jobs.emplace_back(Fe::Install::ImageMap{.sourcePath = u":/flashpoint/icon.png"_s, .destPath = mainDest});
+ jobs.emplace_back(Lr::Install::ImageMap{.sourcePath = u":/flashpoint/icon.png"_s, .destPath = mainDest});
// Platform jobs
if(platformDestDir)
@@ -622,7 +625,7 @@ ImportWorker::ImportResult ImportWorker::processIcons(Qx::Error& errorReport, co
{
QString src = tk->platformLogoPath(p);
if(QFile::exists(src))
- jobs.emplace_back(Fe::Install::ImageMap{.sourcePath = src,
+ jobs.emplace_back(Lr::Install::ImageMap{.sourcePath = src,
.destPath = pdd.absoluteFilePath(p + ".png")});
}
}
@@ -650,19 +653,19 @@ ImportWorker::ImportResult ImportWorker::processIcons(Qx::Error& errorReport, co
continue;
/* NOTE: This is LaunchBox specific since it's currently the only FE to support icons. If this changes a general solution is needed
- * Like allowing the frontend to filter out specific icons
+ * Like allowing the launcher to filter out specific icons
*
* Don't copy the favorites icon as LB already has its own.
*/
if(p.title().trimmed() == u"Favorites"_s)
continue;
- /* NOTE: This may not work for all frontends
+ /* NOTE: This may not work for all launchers
*
- * Use translated name for destination since that's what the frontend is expecting
+ * Use translated name for destination since that's what the launcher is expecting
*/
QString sFilename = p.title() + ".png";
- QString dFilename = mFrontendInstall->translateDocName(p.title(), Fe::DataDoc::Type::Playlist) + ".png";;
+ QString dFilename = mLauncherInstall->translateDocName(p.title(), Lr::DataDoc::Type::Playlist) + ".png";;
QString source = iconInflateDir.filePath(sFilename);
QString dest = pdd.absoluteFilePath(dFilename);
@@ -673,7 +676,7 @@ ImportWorker::ImportResult ImportWorker::processIcons(Qx::Error& errorReport, co
return Failed;
}
- jobs.emplace_back(Fe::Install::ImageMap{.sourcePath = source, .destPath = dest});
+ jobs.emplace_back(Lr::Install::ImageMap{.sourcePath = source, .destPath = dest});
}
}
@@ -691,12 +694,12 @@ ImportWorker::ImportResult ImportWorker::processIcons(Qx::Error& errorReport, co
}
//Public
-ImportWorker::ImportResult ImportWorker::doImport(Qx::Error& errorReport)
+Worker::Result Worker::doImport(Qx::Error& errorReport)
{
//-Setup----------------------------------------------------------------
// Import step status
- ImportResult importStepStatus;
+ Result importStepStatus;
// Process query status
Fp::DbError queryError;
@@ -798,7 +801,7 @@ ImportWorker::ImportResult ImportWorker::doImport(Qx::Error& errorReport)
}
// Screenshot and Logo transfer
- if(mOptionSet.imageMode != Fe::ImageMode::Reference)
+ if(mOptionSet.imageMode != ImageMode::Reference)
{
Qx::ProgressGroup* pgImageTransfer = initializeProgressGroup(Pg::ImageTransfer, 3);
pgImageTransfer->setMaximum(totalGameCount * 2);
@@ -807,11 +810,11 @@ ImportWorker::ImportResult ImportWorker::doImport(Qx::Error& errorReport)
// Icon transfers
// TOD: Somewhat wasteful because these create a temporary copy, but not a big deal for now
quint64 iconCount = 0;
- if(!mFrontendInstall->platformCategoryIconPath().isEmpty())
+ if(!mLauncherInstall->platformCategoryIconPath().isEmpty())
iconCount++;
- if(mFrontendInstall->platformIconsDirectory())
+ if(mLauncherInstall->platformIconsDirectory())
iconCount += involvedPlatforms.size();
- if(mFrontendInstall->playlistIconsDirectory())
+ if(mLauncherInstall->playlistIconsDirectory())
iconCount += targetPlaylists.size();
if(iconCount > 0)
@@ -828,10 +831,10 @@ ImportWorker::ImportResult ImportWorker::doImport(Qx::Error& errorReport)
}
// Connect progress manager signal
- connect(&mProgressManager, &Qx::GroupedProgressManager::progressUpdated, this, &ImportWorker::pmProgressUpdated);
+ connect(&mProgressManager, &Qx::GroupedProgressManager::progressUpdated, this, &Worker::pmProgressUpdated);
- //-Handle Frontend Specific Import Setup------------------------------
- Fe::Install::ImportDetails details{
+ //-Handle Launcher Specific Import Setup------------------------------
+ Lr::Install::ImportDetails details{
.updateOptions = mOptionSet.updateOptions,
.imageMode = mOptionSet.imageMode,
.clifpPath = CLIFp::standardCLIFpPath(*mFlashpointInstall),
@@ -839,7 +842,7 @@ ImportWorker::ImportResult ImportWorker::doImport(Qx::Error& errorReport)
.involvedPlaylists = mImportSelections.playlists
};
- errorReport = mFrontendInstall->preImport(details);
+ errorReport = mLauncherInstall->preImport(details);
if(errorReport.isValid())
return Failed;
@@ -853,8 +856,8 @@ ImportWorker::ImportResult ImportWorker::doImport(Qx::Error& errorReport)
if((importStepStatus = preloadAddApps(errorReport, addAppQuery)) != Successful)
return importStepStatus;
- // Handle Frontend specific pre-platform tasks
- errorReport = mFrontendInstall->prePlatformsImport();
+ // Handle Launcher specific pre-platform tasks
+ errorReport = mLauncherInstall->prePlatformsImport();
if(errorReport.isValid())
return Failed;
@@ -862,8 +865,8 @@ ImportWorker::ImportResult ImportWorker::doImport(Qx::Error& errorReport)
if((importStepStatus = processGames(errorReport, gameQueries, playlistSpecGameQueries)) != Successful)
return importStepStatus;
- // Handle Frontend specific post-platform tasks
- errorReport = mFrontendInstall->postPlatformsImport();
+ // Handle Launcher specific post-platform tasks
+ errorReport = mLauncherInstall->postPlatformsImport();
if(errorReport.isValid())
return Failed;
@@ -881,23 +884,23 @@ ImportWorker::ImportResult ImportWorker::doImport(Qx::Error& errorReport)
// Remove un-imported games from playlists
cullUnimportedPlaylistGames(targetPlaylists);
- // Handle Frontend specific pre-playlist tasks
- errorReport = mFrontendInstall->prePlaylistsImport();
+ // Handle Launcher specific pre-playlist tasks
+ errorReport = mLauncherInstall->prePlaylistsImport();
if(errorReport.isValid())
return Failed;
if((importStepStatus = processPlaylists(errorReport, targetPlaylists)) != Successful)
return importStepStatus;
- // Handle Frontend specific pre-playlist tasks
- errorReport = mFrontendInstall->postPlaylistsImport();
+ // Handle Launcher specific pre-playlist tasks
+ errorReport = mLauncherInstall->postPlaylistsImport();
if(errorReport.isValid())
return Failed;
}
- // Handle Frontend specific cleanup
+ // Handle Launcher specific cleanup
emit progressStepChanged(STEP_FINALIZING);
- errorReport = mFrontendInstall->postImport();
+ errorReport = mLauncherInstall->postImport();
if(errorReport.isValid())
return Failed;
@@ -909,7 +912,7 @@ ImportWorker::ImportResult ImportWorker::doImport(Qx::Error& errorReport)
}
// Reset install
- mFrontendInstall->softReset();
+ mLauncherInstall->softReset();
// Report successful import completion
errorReport = Qx::Error();
@@ -918,7 +921,7 @@ ImportWorker::ImportResult ImportWorker::doImport(Qx::Error& errorReport)
//-Slots---------------------------------------------------------------------------------------------------------
//Private Slots:
-void ImportWorker::pmProgressUpdated(quint64 currentProgress)
+void Worker::pmProgressUpdated(quint64 currentProgress)
{
/* NOTE: This is required because if the value isn't actually different than the current when
* the connected QProgressDialog::setValue() is triggered then processEvents() won't be called.
@@ -940,4 +943,6 @@ void ImportWorker::pmProgressUpdated(quint64 currentProgress)
}
//Public Slots:
-void ImportWorker::notifyCanceled() { mCanceled = true; }
+void Worker::notifyCanceled() { mCanceled = true; }
+
+}
diff --git a/app/src/import-worker.h b/app/src/import/worker.h
similarity index 76%
rename from app/src/import-worker.h
rename to app/src/import/worker.h
index 7f0a9a9..57182a2 100644
--- a/app/src/import-worker.h
+++ b/app/src/import/worker.h
@@ -1,5 +1,5 @@
-#ifndef COREIMPORTWORKER_H
-#define COREIMPORTWORKER_H
+#ifndef IMPORT_WORKER_H
+#define IMPORT_WORKER_H
// Qt Includes
#include
@@ -13,7 +13,10 @@
#include
// Project Includes
-#include "frontend/fe-install.h"
+#include "launcher/lr-install.h"
+
+namespace Import
+{
class QX_ERROR_TYPE(ImageTransferError, "ImageTransferError", 1351)
{
@@ -69,14 +72,13 @@ class QX_ERROR_TYPE(ImageTransferError, "ImageTransferError", 1351)
QString deriveCaption() const override;
};
-class ImportWorker : public QObject
+class Worker : public QObject
{
Q_OBJECT // Required for classes that use Qt elements
//-Class Enums---------------------------------------------------------------------------------------------------
public:
- enum ImportResult {Failed, Canceled, Taskless, Successful};
- enum PlaylistGameMode {SelectedPlatform, ForceAll};
+ enum Result {Failed, Canceled, Taskless, Successful};
//-Inner Classes------------------------------------------------------------------------------------------------
private:
@@ -91,23 +93,6 @@ class ImportWorker : public QObject
static inline const QString PlaylistImport = u"PlaylistImport"_s;
};
-//-Class Structs-------------------------------------------------------------------------------------------------
-public:
- struct ImportSelections
- {
- QStringList platforms;
- QStringList playlists;
- };
-
- struct OptionSet
- {
- Fe::UpdateOptions updateOptions;
- Fe::ImageMode imageMode;
- bool downloadImages;
- PlaylistGameMode playlistMode;
- Fp::Db::InclusionOptions inclusionOptions;
- };
-
//-Class Variables-----------------------------------------------------------------------------------------------
public:
// Import Steps
@@ -123,13 +108,13 @@ class ImportWorker : public QObject
private:
// Install links
std::shared_ptr mFlashpointInstall;
- std::shared_ptr mFrontendInstall;
+ std::shared_ptr mLauncherInstall;
// Image processing
Qx::SyncDownloadManager mImageDownloadManager;
// Job details
- ImportSelections mImportSelections;
+ Selections mImportSelections;
OptionSet mOptionSet;
// Job Caches
@@ -148,9 +133,9 @@ class ImportWorker : public QObject
//-Constructor---------------------------------------------------------------------------------------------------
public:
- ImportWorker(std::shared_ptr fpInstallForWork,
- std::shared_ptr feInstallForWork,
- ImportSelections importSelections,
+ Worker(std::shared_ptr fpInstallForWork,
+ std::shared_ptr feInstallForWork,
+ Selections importSelections,
OptionSet optionSet);
//-Instance Functions---------------------------------------------------------------------------------------------------------
@@ -159,18 +144,18 @@ class ImportWorker : public QObject
Qx::Error preloadPlaylists(QList& targetPlaylists);
QList getPlaylistSpecificGameIds(const QList& playlists);
ImageTransferError transferImage(bool symlink, QString sourcePath, QString destPath);
- bool performImageJobs(const QList& jobs, bool symlink, Qx::ProgressGroup* pg = nullptr);
- ImportResult processPlatformGames(Qx::Error& errorReport, std::unique_ptr& platformDoc, Fp::Db::QueryBuffer& gameQueryResult);
+ bool performImageJobs(const QList& jobs, bool symlink, Qx::ProgressGroup* pg = nullptr);
+ Result processPlatformGames(Qx::Error& errorReport, std::unique_ptr& platformDoc, Fp::Db::QueryBuffer& gameQueryResult);
void cullUnimportedPlaylistGames(QList& playlists);
- ImportResult preloadAddApps(Qx::Error& errorReport, Fp::Db::QueryBuffer& addAppQuery);
- ImportResult processGames(Qx::Error& errorReport, QList& primary, QList& playlistSpecific);
- ImportResult processPlaylists(Qx::Error& errorReport, const QList& playlists);
- ImportResult processImages(Qx::Error& errorReport);
- ImportResult processIcons(Qx::Error& errorReport, const QStringList& platforms, const QList& playlists);
+ Result preloadAddApps(Qx::Error& errorReport, Fp::Db::QueryBuffer& addAppQuery);
+ Result processGames(Qx::Error& errorReport, QList& primary, QList& playlistSpecific);
+ Result processPlaylists(Qx::Error& errorReport, const QList& playlists);
+ Result processImages(Qx::Error& errorReport);
+ Result processIcons(Qx::Error& errorReport, const QStringList& platforms, const QList& playlists);
public:
- ImportResult doImport(Qx::Error& errorReport);
+ Result doImport(Qx::Error& errorReport);
//-Slots----------------------------------------------------------------------------------------------------------
private slots:
@@ -191,10 +176,12 @@ public slots:
void authenticationRequired(const QString& prompt, QAuthenticator* authenticator);
// Finished
- void importCompleted(ImportWorker::ImportResult importResult, const Qx::Error& errorReport);
+ void importCompleted(Worker::Result importResult, const Qx::Error& errorReport);
};
+}
+
//-Metatype declarations-------------------------------------------------------------------------------------------
-Q_DECLARE_METATYPE(ImportWorker::ImportResult);
+Q_DECLARE_METATYPE(Import::Worker::Result);
-#endif // COREIMPORTWORKER_H
+#endif // IMPORT_WORKER_H
diff --git a/app/src/clifp.cpp b/app/src/kernel/clifp.cpp
similarity index 100%
rename from app/src/clifp.cpp
rename to app/src/kernel/clifp.cpp
diff --git a/app/src/clifp.h b/app/src/kernel/clifp.h
similarity index 100%
rename from app/src/clifp.h
rename to app/src/kernel/clifp.h
diff --git a/app/src/kernel/controller.cpp b/app/src/kernel/controller.cpp
new file mode 100644
index 0000000..f435b79
--- /dev/null
+++ b/app/src/kernel/controller.cpp
@@ -0,0 +1,418 @@
+// Unit Include
+#include "controller.h"
+
+// Qt Includes
+#include
+#include
+
+// Qx Includes
+#include
+#include
+#include
+
+// libfp Includes
+#include
+
+// Project Includes
+#include "launcher/lr-install.h"
+
+/* TODO: Consider having this tool deploy a .ini file (or the like) into the target launcher install
+ * (with the exact location probably being guided by the specific Install child) that saves the settings
+ * used for the import, so that they can be loaded again when that install is targeted by future versions
+ * of the tool. Would have to account for an initial import vs update (likely just leaving the update settings
+ * blank). Wouldn't be a huge difference but could be a nice little time saver.
+ */
+
+//===============================================================================================================
+// Controller
+//===============================================================================================================
+
+//-Constructor-------------------------------------------------------------
+//Public:
+Controller::Controller() :
+ mMainWindow(mImportProperties), // Shared by reference, so OK that it's not setup yet
+ mProgressPresenter(&mMainWindow)
+{
+ QApplication::setApplicationName(PROJECT_FULL_NAME);
+
+ /*Register metatypes
+ * NOTE: Qt docs note these should be needed, as always, but since Qt6 signals/slots with these types seem to
+ * work fine without the following calls.
+ * See https://forum.qt.io/topic/136627/undocumented-automatic-metatype-registration-in-qt6
+ */
+ //qRegisterMetaType();
+ //qRegisterMetaType();
+ //qRegisterMetaType>();
+
+ // Ensure built-in CLIFp version is valid
+ if(CLIFp::internalVersion().isNull())
+ {
+ QMessageBox::critical(&mMainWindow, CAPTION_GENERAL_FATAL_ERROR, MSG_FATAL_NO_INTERNAL_CLIFP_VER);
+ QApplication::exit(1);
+ return;
+ }
+
+ // Check if Flashpoint is running
+ if(Qx::processIsRunning(Fp::Install::LAUNCHER_NAME))
+ QMessageBox::warning(&mMainWindow, QApplication::applicationName(), MSG_FP_CLOSE_PROMPT);
+
+ // Setup properties
+ mImportProperties.setHasLinkPermissions(testForLinkPermissions());
+ mImportProperties.bindableIsLauncherPresent().setBinding([this]{ return *mLauncher != nullptr; });
+ mImportProperties.bindableIsLauncherReady().setBinding([this]{ return mImportProperties.isLauncherPresent() && mLauncher->isValid() && !mLauncherError; });
+ mImportProperties.bindableIsFlashpointPresent().setBinding([this]{ return *mFlashpoint != nullptr; });
+ mImportProperties.bindableIsFlashpointReady().setBinding([this]{ return mImportProperties.isFlashpointPresent() && mFlashpoint->isValid(); });
+ mImportProperties.bindableIsBothTargetsReady().setBinding([this]{ return mImportProperties.isLauncherReady() && mImportProperties.isFlashpointPresent(); });
+ mImportProperties.bindableIsBothTargetsReady().lifetimeOnValueChanged([this]{ if(mImportProperties.isBothTargetsReady()) gatherTargetData(); });
+ mImportProperties.bindableIsFlashpointTargetSeries().setBinding([this]{ return mImportProperties.isFlashpointReady() && installMatchesTargetSeries(*mFlashpoint.value()); });
+ mImportProperties.bindableImageModeOrder().setBinding([this]{
+ /* Even though technically we only need the launcher, check for both installs to prevent the selection
+ * from moving until its section is available
+ */
+ static QList defOrder{Import::ImageMode::Link, Import::ImageMode::Reference, Import::ImageMode::Copy};
+ bool def = !mImportProperties.isBothTargetsReady();
+ auto order = def ? defOrder : mLauncher->preferredImageModeOrder();
+ if(!mImportProperties.hasLinkPermissions())
+ order.removeAll(Import::ImageMode::Link);
+
+ return order;
+ });
+ mImportProperties.bindableIsImageDownloadable().setBinding([this]{
+ return mImportProperties.isFlashpointReady() && mFlashpoint->preferences().onDemandImages;
+ } );
+ mImportProperties.bindableLauncherInfo().setBinding([this]{ return mImportProperties.isLauncherReady() ? mLauncher->name() + ' ' + mLauncher->versionString() : QString(); });
+ mImportProperties.bindableLauncherInfo().setBinding([this]{ return mImportProperties.isFlashpointReady() ? mFlashpoint->versionInfo()->fullString() : QString(); });
+ mImportProperties.bindableTagMap().setBinding([this]{ return mImportProperties.isFlashpointReady() ? mFlashpoint->database()->tags() : QMap(); });
+
+ // Connect main window
+ connect(&mMainWindow, &MainWindow::installPathChanged, this, &Controller::updateInstallPath);
+ connect(&mMainWindow, &MainWindow::importTriggered, this, &Controller::startImport);
+ connect(&mMainWindow, &MainWindow::standaloneDeployTriggered, this, &Controller::standaloneCLIFpDeploy);
+
+ // Spawn main window
+ mMainWindow.show();
+ mProgressPresenter.attachWindow(mMainWindow.windowHandle()); // Must be after show() for handle to be valid
+}
+
+//-Class Functions-------------------------------------------------------------
+//Private:
+bool Controller::testForLinkPermissions()
+{
+ QTemporaryDir testLinkDir;
+ if(testLinkDir.isValid())
+ {
+ QFile testLinkTarget(testLinkDir.filePath(u"linktarget.tmp"_s));
+
+ if(testLinkTarget.open(QIODevice::WriteOnly))
+ {
+ testLinkTarget.close();
+ std::error_code symlinkError;
+ std::filesystem::create_symlink(testLinkTarget.fileName().toStdString(), testLinkDir.filePath(u"testlink.tmp"_s).toStdString(), symlinkError);
+
+ if(!symlinkError)
+ return true;
+ }
+ }
+
+ // Default
+ return false;
+}
+
+bool Controller::installMatchesTargetSeries(const Fp::Install& fpInstall)
+{
+ Qx::VersionNumber fpVersion = fpInstall.versionInfo()->version();
+ return TARGET_FP_VERSION_PREFIX.isPrefixOf(fpVersion) ||
+ TARGET_FP_VERSION_PREFIX.normalized() == fpVersion; // Accounts for if FP doesn't use a trailing zero for major releases
+}
+
+
+//-Instance Functions-------------------------------------------------------------
+//Private:
+void Controller::gatherTargetData()
+{
+ // IO Error check instance
+ Qx::Error existingCheck;
+
+ // Get list of existing platforms and playlists
+ existingCheck = mLauncher->refreshExistingDocs();
+
+ // IO Error Check
+ if(existingCheck.isValid())
+ {
+ Qx::postBlockingError(existingCheck);
+ mLauncherError = true;
+ return;
+ }
+
+ /* We set the platform/playlist properties here instead of using a binding because gatherLauncherData()
+ * might need to be called in contexts where there is no trivail way to cause the binding to re-evaluate
+ * without adding a hacky bool property specifically for that purpose.
+ */
+ QList plats;
+ for(const QString& p : mFlashpoint->database()->platformNames())
+ plats.append({.name = p, .existing = mLauncher->containsPlatform(p)});
+
+ QList plays;
+ for(const QString& p : mFlashpoint->playlistManager()->playlistTitles())
+ plays.append({.name = p, .existing = mLauncher->containsPlaylist(p)});
+
+ mImportProperties.bindablePlatforms().setValue(plats); //clazy:exclude=writing-to-temporary
+ mImportProperties.bindablePlaylists().setValue(plays); //clazy:exclude=writing-to-temporary
+}
+
+void Controller::processImportResult(Import::Worker::Result importResult, const Qx::Error& errorReport)
+{
+ // Reset progress presenter
+ mProgressPresenter.reset();
+
+ // Post error report if present
+ if(errorReport.isValid())
+ Qx::postBlockingError(errorReport, QMessageBox::Ok);
+
+ if(importResult == Import::Worker::Successful)
+ {
+ deployCLIFp(**mFlashpoint, QMessageBox::Ignore);
+
+ // Post-import message
+ QMessageBox::information(&mMainWindow, QApplication::applicationName(), MSG_POST_IMPORT);
+
+ // Update selection lists to reflect newly existing platforms
+ gatherTargetData();
+ }
+ else if(importResult == Import::Worker::Taskless)
+ {
+ QMessageBox::warning(&mMainWindow, CAPTION_TASKLESS_IMPORT, MSG_NO_WORK);
+ }
+ else if(importResult == Import::Worker::Canceled)
+ {
+ QMessageBox::critical(&mMainWindow, CAPTION_REVERT, MSG_USER_CANCELED);
+ revertAllLauncherChanges();
+ }
+ else if(importResult == Import::Worker::Failed)
+ {
+ // Show general next steps message
+ QMessageBox::warning(&mMainWindow, CAPTION_REVERT, MSG_HAVE_TO_REVERT);
+ revertAllLauncherChanges();
+ }
+ else
+ qCritical("unhandled import worker result type.");
+}
+
+void Controller::revertAllLauncherChanges()
+{
+ // Trackers
+ bool tempSkip = false;
+ bool alwaysSkip = false;
+ Lr::RevertError currentError;
+ int retryChoice;
+
+ // Progress
+ mProgressPresenter.setMinimum(0);
+ mProgressPresenter.setMaximum(mLauncher->revertQueueCount());
+ mProgressPresenter.setCaption(CAPTION_REVERT);
+ while(mLauncher->revertNextChange(currentError, alwaysSkip || tempSkip) != 0)
+ {
+ // Check for error
+ if(!currentError.isValid())
+ {
+ tempSkip = false;
+ mProgressPresenter.setValue(mProgressPresenter.value() + 1);
+ }
+ else
+ {
+ retryChoice = Qx::postBlockingError(currentError, QMessageBox::Retry | QMessageBox::Ignore | QMessageBox::Abort, QMessageBox::Retry);
+
+ if(retryChoice == QMessageBox::Ignore)
+ tempSkip = true;
+ else if(retryChoice == QMessageBox::Abort)
+ alwaysSkip = true;
+ }
+ }
+
+ // Ensure progress dialog is closed
+ mProgressPresenter.reset();
+
+ // Reset instance
+ mLauncher->softReset();
+}
+
+void Controller::deployCLIFp(const Fp::Install& fp, QMessageBox::Button abandonButton)
+{
+ bool willDeploy = true;
+
+ // Check for existing CLIFp
+ if(CLIFp::hasCLIFp(fp))
+ {
+ // Notify user if this will be a downgrade
+ if(CLIFp::internalVersion() < CLIFp::installedVersion(fp))
+ willDeploy = (QMessageBox::warning(&mMainWindow, CAPTION_CLIFP_DOWNGRADE, MSG_FP_CLFIP_WILL_DOWNGRADE, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes);
+ }
+
+ // Deploy CLIFp if applicable
+ if(willDeploy)
+ {
+ // Deploy exe
+ QString deployError;
+ while(!CLIFp::deployCLIFp(deployError, fp))
+ if(QMessageBox::critical(&mMainWindow, CAPTION_CLIFP_ERR, MSG_FP_CANT_DEPLOY_CLIFP.arg(deployError), QMessageBox::Retry | abandonButton, QMessageBox::Retry) == abandonButton)
+ break;
+ }
+}
+
+//-Signals & Slots-------------------------------------------------------------
+//Private Slots:
+void Controller::handleBlockingError(std::shared_ptr response, const Qx::Error& blockingError, QMessageBox::StandardButtons choices)
+{
+ mProgressPresenter.setErrorState();
+
+ // Post error and get response
+ int userChoice = Qx::postBlockingError(blockingError, choices);
+
+ // If applicable return selection
+ if(response)
+ *response = userChoice;
+
+ mProgressPresenter.resetState();
+}
+
+void Controller::handleAuthRequest(const QString& prompt, QAuthenticator* authenticator)
+{
+ Qx::LoginDialog ld;
+ ld.setPrompt(prompt);
+
+ int choice = ld.exec();
+
+ if(choice == QDialog::Accepted)
+ {
+ authenticator->setUser(ld.username());
+ authenticator->setPassword(ld.password());
+ }
+}
+
+//Public Slots:
+void Controller::updateInstallPath(const QString& installPath, Import::Install type)
+{
+ QString cleanPath = QDir::cleanPath(installPath);
+
+ using enum Import::Install;
+ switch(type)
+ {
+ case Launcher:
+ {
+ // Reset any past operational error state
+ mLauncherError = false;
+ std::shared_ptr launcher;
+ if(cleanPath.isEmpty())
+ launcher = nullptr;
+ else
+ {
+ launcher = Lr::Install::acquireMatch(cleanPath);
+ if(!launcher->isValid())
+ QMessageBox::critical(&mMainWindow, QApplication::applicationName(), MSG_LR_INSTALL_INVALID);
+ }
+
+ mLauncher = launcher;
+ break;
+ }
+ case Flashpoint:
+ {
+ std::shared_ptr flashpoint;
+ if(cleanPath.isEmpty())
+ flashpoint = nullptr;
+ else
+ {
+ flashpoint = std::make_shared(cleanPath, true);
+ if(!flashpoint->isValid())
+ Qx::postBlockingError(mFlashpoint->error(), QMessageBox::Ok);
+ }
+
+ mFlashpoint = flashpoint; // Updates target series property
+ if(!mImportProperties.isFlashpointTargetSeries())
+ QMessageBox::warning(&mMainWindow, QApplication::applicationName(), MSG_FP_VER_NOT_TARGET);
+ break;
+ }
+ }
+}
+
+void Controller::startImport(Import::Selections sel, Import::OptionSet opt, bool mayModify)
+{
+ // Ensure launcher hasn't changed
+ bool changed = true; // Assume true for if error occurs
+ mLauncher->refreshExistingDocs(&changed);
+ if(changed)
+ {
+ QMessageBox::warning(&mMainWindow, QApplication::applicationName(), MSG_INSTALL_CONTENTS_CHANGED);
+ updateInstallPath(mLauncher->path(), Import::Install::Launcher); // Reprocess launcher to make sure it's the same install
+ return;
+ }
+
+ // Warn user if they are changing existing files
+ if(mayModify)
+ if(QMessageBox::warning(&mMainWindow, QApplication::applicationName(), MSG_PRE_EXISTING_IMPORT, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Cancel)
+ return;
+
+ // Warn user if Flashpoint is running
+ // Check if Flashpoint is running
+ if(Qx::processIsRunning(Fp::Install::LAUNCHER_NAME))
+ QMessageBox::warning(&mMainWindow, QApplication::applicationName(), MSG_FP_CLOSE_PROMPT);
+
+ // Only allow proceeding if launcher isn't running
+ bool lrRunning;
+ while((lrRunning = mLauncher->isRunning()))
+ if(QMessageBox::critical(&mMainWindow, QApplication::applicationName(), MSG_LAUNCHER_CLOSE_PROMPT, QMessageBox::Retry | QMessageBox::Cancel, QMessageBox::Retry) == QMessageBox::Cancel)
+ break;
+
+ if(lrRunning)
+ return;
+
+ // Start progress presentation
+ mProgressPresenter.setCaption(CAPTION_IMPORTING);
+ mProgressPresenter.setMinimum(0);
+ mProgressPresenter.setMaximum(0);
+ mProgressPresenter.setValue(0);
+ mProgressPresenter.setBusyState();
+ mProgressPresenter.setLabelText(STEP_FP_DB_INITIAL_QUERY);
+ QApplication::processEvents(); // Force show progress immediately
+
+ // Setup import worker
+ Import::Worker importWorker(*mFlashpoint, *mLauncher, sel, opt);
+
+ // Setup blocking error connection
+ connect(&importWorker, &Import::Worker::blockingErrorOccured, this, &Controller::handleBlockingError);
+
+ // Setup auth handler
+ connect(&importWorker, &Import::Worker::authenticationRequired, this, &Controller::handleAuthRequest);
+
+ // Create process update connections
+ connect(&importWorker, &Import::Worker::progressStepChanged, &mProgressPresenter, &ProgressPresenter::setLabelText);
+ connect(&importWorker, &Import::Worker::progressValueChanged, &mProgressPresenter, &ProgressPresenter::setValue);
+ connect(&importWorker, &Import::Worker::progressMaximumChanged, &mProgressPresenter, &ProgressPresenter::setMaximum);
+ connect(&mProgressPresenter, &ProgressPresenter::canceled, &importWorker, &Import::Worker::notifyCanceled);
+
+ // Import error tracker
+ Qx::Error importError;
+
+ // Start import and forward result to handler
+ Import::Worker::Result importResult = importWorker.doImport(importError);
+ processImportResult(importResult, importError);
+}
+
+void Controller::standaloneCLIFpDeploy()
+{
+ // Browse for install
+ QString selectedDir = QFileDialog::getExistingDirectory(&mMainWindow, CAPTION_FLASHPOINT_BROWSE, QDir::currentPath());
+
+ if(!selectedDir.isEmpty())
+ {
+ Fp::Install tempFlashpointInstall(selectedDir);
+ if(tempFlashpointInstall.isValid())
+ {
+ if(!installMatchesTargetSeries(tempFlashpointInstall))
+ QMessageBox::warning(&mMainWindow, QApplication::applicationName(), MSG_FP_VER_NOT_TARGET);
+
+ deployCLIFp(tempFlashpointInstall, QMessageBox::Cancel);
+ }
+ else
+ Qx::postBlockingError(tempFlashpointInstall.error(), QMessageBox::Ok);
+ }
+}
diff --git a/app/src/kernel/controller.h b/app/src/kernel/controller.h
new file mode 100644
index 0000000..4735a5f
--- /dev/null
+++ b/app/src/kernel/controller.h
@@ -0,0 +1,129 @@
+#ifndef CONTROLLER_H
+#define CONTROLLER_H
+
+// Qt Includes
+#include
+#include
+
+// Qx Includes
+#include
+
+// Project Includes
+#include "import/properties.h"
+#include "import/worker.h"
+#include "kernel/clifp.h"
+#include "ui/mainwindow.h"
+#include "ui/progresspresenter.h"
+#include "project_vars.h"
+
+namespace Lr { class Install; }
+namespace Fp { class Install; }
+
+class Controller : public QObject
+{
+ Q_OBJECT
+ Q_OBJECT_BINDABLE_PROPERTY(Controller, std::shared_ptr, mLauncher);
+ Q_OBJECT_BINDABLE_PROPERTY(Controller, std::shared_ptr, mFlashpoint);
+
+ // This is a bodge for before this is handled as part of the launcher's regular validity
+ Q_OBJECT_BINDABLE_PROPERTY(Controller, bool, mLauncherError);
+
+//-Class Variables---------------------------------------------------------------
+private:
+ // Flashpoint version check
+ static inline const Qx::VersionNumber TARGET_FP_VERSION_PREFIX = Qx::VersionNumber::fromString(PROJECT_TARGET_FP_VER_PFX_STR);
+
+ // Messages - General
+ static inline const QString MSG_FATAL_NO_INTERNAL_CLIFP_VER = u"Failed to get version information from the internal copy of CLIFp.exe!\n"
+ "\n"
+ "Execution cannot continue."_s;
+
+ // Messages - FP General
+ static inline const QString MSG_FP_CLOSE_PROMPT = u"It is strongly recommended to close Flashpoint before proceeding as it can severely slow or interfere with the import process"_s;
+
+ // Messages - Input
+ static inline const QString MSG_LR_INSTALL_INVALID = u"The specified directory either doesn't contain a valid launcher install, or it contains a version that is incompatible with this tool."_s;
+ static inline const QString MSG_FP_INSTALL_INVALID = u"The specified directory either doesn't contain a valid Flashpoint install, or it contains a version that is incompatible with this tool."_s;
+ static inline const QString MSG_FP_VER_NOT_TARGET = u"The selected Flashpoint install contains a version of Flashpoint that is different from the target version series (" PROJECT_TARGET_FP_VER_PFX_STR "), but appears to have a compatible structure. "
+ "You may proceed at your own risk as the tool is not guaranteed to work correctly in this circumstance. Please use a newer version of " PROJECT_SHORT_NAME " if available."_s;
+
+ static inline const QString MSG_INSTALL_CONTENTS_CHANGED = u"The contents of your installs have been changed since the initial scan and therefore must be re-evaluated. You will need to make your selections again."_s;
+
+ // Messages - General import procedure
+ static inline const QString MSG_PRE_EXISTING_IMPORT = u"One or more existing Platforms/Playlists may be affected by this import. These will be altered even if they did not originate from this program (i.e. if you "
+ "already happened to have a Platform/Playlist with the same name as one present in Flashpoint).\n"
+ "\n"
+ "Are you sure you want to proceed?"_s;
+ static inline const QString MSG_LAUNCHER_CLOSE_PROMPT = u"The importer has detected that the selected launcher is running. It must be closed in order to continue. If recently closed, wait a few moments before trying to proceed again as it performs significant cleanup in the background."_s;
+
+ // Initial import status
+ static inline const QString STEP_FP_DB_INITIAL_QUERY = u"Making initial Flashpoint database queries..."_s;
+
+ // Messages - Import Result
+ static inline const QString MSG_POST_IMPORT = u"The Flashpoint import has completed successfully. Next time you start the launcher it may take longer than usual as it may have to fill in some default fields for the imported Platforms/Playlists.\n"
+ "\n"
+ "If you wish to import further selections or update to a newer version of Flashpoint, simply re-run this procedure after pointing it to the desired Flashpoint installation."_s;
+ static inline const QString MSG_NO_WORK = u"The provided import selections/options resulted in no tasks to perform. Double-check your settings."_s;
+ static inline const QString MSG_USER_CANCELED = u"Import canceled by user, all changes that occurred during import will now be reverted (other than existing images that were replaced with newer versions)."_s;
+ static inline const QString MSG_HAVE_TO_REVERT = u"Due to previous unrecoverable errors, all changes that occurred during import will now be reverted (other than existing images that were replaced with newer versions).\n"
+ "\n"
+ "Afterwards, check to see if there is a newer version of " PROJECT_SHORT_NAME " and try again using that version. If not ask for help on the relevant forums where this tool was released (see Help).\n"
+ "\n"
+ "If you believe this to be due to a bug with this software, please submit an issue to its GitHub page (listed under help)"_s;
+
+ // Messages - FP CLIFp
+ static inline const QString MSG_FP_CLFIP_WILL_DOWNGRADE = u"The existing version of "_s + CLIFp::EXE_NAME + u" in your Flashpoint install is newer than the version package with this tool.\n"
+ "\n"
+ "Replacing it with the packaged Version (downgrade) will likely cause compatibility issues unless you are specifically re-importing after downgrading your Flashpoint install to a previous version.\n"
+ "\n"
+ "Do you wish to downgrade "_s + CLIFp::EXE_NAME + u"?"_s;
+
+ static inline const QString MSG_FP_CANT_DEPLOY_CLIFP = u"Failed to deploy "_s + CLIFp::EXE_NAME + u" to the selected Flashpoint install.\n"
+ "\n"
+ "%1\n"
+ "\n"
+ "If you choose to ignore this you will have to place CLIFp in your Flashpoint install directory manually."_s;
+ // Dialog captions
+ static inline const QString CAPTION_GENERAL_FATAL_ERROR = u"Fatal Error!"_s;
+ static inline const QString CAPTION_TASKLESS_IMPORT = u"Nothing to do"_s;
+ static inline const QString CAPTION_IMPORTING = u"FP Import"_s;
+ static inline const QString CAPTION_REVERT = u"Reverting changes..."_s;
+ static inline const QString CAPTION_FLASHPOINT_BROWSE = u"Select the root directory of your Flashpoint install..."_s;
+ static inline const QString CAPTION_CLIFP_DOWNGRADE = u"Downgrade CLIFp?"_s;
+ static inline const QString CAPTION_CLIFP_ERR = u"Error deploying CLIFp"_s;
+
+//-Instance Variables-------------------------------------------------------------
+private:
+ Import::Properties mImportProperties;
+ MainWindow mMainWindow;
+ ProgressPresenter mProgressPresenter;
+
+//-Constructor-------------------------------------------------------------
+public:
+ Controller();
+
+//-Class Functions-------------------------------------------------------------
+private:
+ bool testForLinkPermissions();
+ bool installMatchesTargetSeries(const Fp::Install& fpInstall);
+
+//-Instance Functions-------------------------------------------------------------
+private:
+ void gatherTargetData();
+ void processImportResult(Import::Worker::Result importResult, const Qx::Error& errorReport);
+ void revertAllLauncherChanges();
+ void deployCLIFp(const Fp::Install& fp, QMessageBox::Button abandonButton);
+
+//-Signals & Slots-------------------------------------------------------------
+private slots:
+ // Import Handlers
+ void handleBlockingError(std::shared_ptr response, const Qx::Error& blockingError, QMessageBox::StandardButtons choices);
+ void handleAuthRequest(const QString& prompt, QAuthenticator* authenticator);
+
+public slots:
+ void updateInstallPath(const QString& installPath, Import::Install type);
+ void startImport(Import::Selections sel, Import::OptionSet opt, bool mayModify);
+ void standaloneCLIFpDeploy();
+};
+
+#endif // CONTROLLER_H
diff --git a/app/src/frontend/attractmode/am-data.cpp b/app/src/launcher/attractmode/am-data.cpp
similarity index 93%
rename from app/src/frontend/attractmode/am-data.cpp
rename to app/src/launcher/attractmode/am-data.cpp
index f0f4e68..794d843 100644
--- a/app/src/frontend/attractmode/am-data.cpp
+++ b/app/src/launcher/attractmode/am-data.cpp
@@ -8,7 +8,7 @@
#include
// Project Includes
-#include "am-install.h"
+#include "launcher/attractmode/am-install.h"
namespace Am
{
@@ -18,8 +18,8 @@ namespace Am
//-Constructor--------------------------------------------------------------------------------------------------------
//Protected:
-CommonDocReader::CommonDocReader(Fe::DataDoc* targetDoc) :
- Fe::DataDoc::Reader(targetDoc),
+CommonDocReader::CommonDocReader(Lr::DataDoc* targetDoc) :
+ Lr::DataDoc::Reader(targetDoc),
mStreamReader(targetDoc->path())
{}
@@ -39,22 +39,22 @@ QString CommonDocReader::readLineIgnoringComments(qint64 maxlen)
}
//Public:
-Fe::DocHandlingError CommonDocReader::readInto()
+Lr::DocHandlingError CommonDocReader::readInto()
{
// Open file
Qx::IoOpReport openError = mStreamReader.openFile();
if(openError.isFailure())
- return Fe::DocHandlingError(*mTargetDocument, Fe::DocHandlingError::DocCantOpen, openError.outcomeInfo());
+ return Lr::DocHandlingError(*mTargetDocument, Lr::DocHandlingError::DocCantOpen, openError.outcomeInfo());
// Check that doc is valid
bool isValid = false;
if(!checkDocValidity(isValid))
- return Fe::DocHandlingError(*mTargetDocument, Fe::DocHandlingError::DocWriteFailed, mStreamReader.status().outcomeInfo());
+ return Lr::DocHandlingError(*mTargetDocument, Lr::DocHandlingError::DocWriteFailed, mStreamReader.status().outcomeInfo());
else if(!isValid)
- return Fe::DocHandlingError(*mTargetDocument, Fe::DocHandlingError::DocInvalidType);
+ return Lr::DocHandlingError(*mTargetDocument, Lr::DocHandlingError::DocInvalidType);
// Read doc
- Fe::DocHandlingError parseError = readTargetDoc();
+ Lr::DocHandlingError parseError = readTargetDoc();
// Close file
mStreamReader.closeFile();
@@ -63,9 +63,9 @@ Fe::DocHandlingError CommonDocReader::readInto()
if(parseError.isValid())
return parseError;
else if(mStreamReader.hasError())
- return Fe::DocHandlingError(*mTargetDocument, Fe::DocHandlingError::DocWriteFailed, mStreamReader.status().outcomeInfo());
+ return Lr::DocHandlingError(*mTargetDocument, Lr::DocHandlingError::DocWriteFailed, mStreamReader.status().outcomeInfo());
else
- return Fe::DocHandlingError();
+ return Lr::DocHandlingError();
}
//===============================================================================================================
@@ -74,19 +74,19 @@ Fe::DocHandlingError CommonDocReader::readInto()
//-Constructor--------------------------------------------------------------------------------------------------------
//Protected:
-CommonDocWriter::CommonDocWriter(Fe::DataDoc* sourceDoc) :
- Fe::DataDoc::Writer(sourceDoc),
+CommonDocWriter::CommonDocWriter(Lr::DataDoc* sourceDoc) :
+ Lr::DataDoc::Writer(sourceDoc),
mStreamWriter(sourceDoc->path(), Qx::WriteMode::Truncate)
{}
//-Instance Functions-------------------------------------------------------------------------------------------------
//Public:
-Fe::DocHandlingError CommonDocWriter::writeOutOf()
+Lr::DocHandlingError CommonDocWriter::writeOutOf()
{
// Open file
Qx::IoOpReport openError = mStreamWriter.openFile();
if(openError.isFailure())
- return Fe::DocHandlingError(*mSourceDocument, Fe::DocHandlingError::DocCantOpen, openError.outcomeInfo());
+ return Lr::DocHandlingError(*mSourceDocument, Lr::DocHandlingError::DocCantOpen, openError.outcomeInfo());
// Write doc
bool writeSuccess = writeSourceDoc();
@@ -95,8 +95,8 @@ Fe::DocHandlingError CommonDocWriter::writeOutOf()
mStreamWriter.closeFile();
// Return outcome
- return writeSuccess ? Fe::DocHandlingError() :
- Fe::DocHandlingError(*mSourceDocument, Fe::DocHandlingError::DocWriteFailed, mStreamWriter.status().outcomeInfo());
+ return writeSuccess ? Lr::DocHandlingError() :
+ Lr::DocHandlingError(*mSourceDocument, Lr::DocHandlingError::DocWriteFailed, mStreamWriter.status().outcomeInfo());
}
//===============================================================================================================
@@ -106,7 +106,7 @@ Fe::DocHandlingError CommonDocWriter::writeOutOf()
//-Constructor--------------------------------------------------------------------------------------------------------
//Public:
ConfigDoc::ConfigDoc(Install* const parent, const QString& filePath, QString docName) :
- Fe::DataDoc(parent, filePath, docName)
+ Lr::DataDoc(parent, filePath, docName)
{}
//-Instance Functions--------------------------------------------------------------------------------------------------
@@ -204,7 +204,7 @@ bool ConfigDoc::Writer::writeSourceDoc()
//-Constructor--------------------------------------------------------------------------------------------------------
//Public:
Taglist::Taglist(Install* const parent, const QString& listPath, QString docName) :
- Fe::DataDoc(parent, listPath, docName)
+ Lr::DataDoc(parent, listPath, docName)
{}
//-Instance Functions--------------------------------------------------------------------------------------------------
@@ -254,7 +254,7 @@ PlatformTaglist::PlatformTaglist(Install* const parent, const QString& listPath,
//-Instance Functions--------------------------------------------------------------------------------------------------
//Public:
-Fe::DataDoc::Type PlatformTaglist::type() const { return Fe::DataDoc::Type::Platform; }
+Lr::DataDoc::Type PlatformTaglist::type() const { return Lr::DataDoc::Type::Platform; }
//===============================================================================================================
// PlaylistTaglist
@@ -268,7 +268,7 @@ PlaylistTaglist::PlaylistTaglist(Install* const parent, const QString& listPath,
//-Instance Functions--------------------------------------------------------------------------------------------------
//Public:
-Fe::DataDoc::Type PlaylistTaglist::type() const { return Fe::DataDoc::Type::Playlist; }
+Lr::DataDoc::Type PlaylistTaglist::type() const { return Lr::DataDoc::Type::Playlist; }
//===============================================================================================================
// Romlist
@@ -276,14 +276,14 @@ Fe::DataDoc::Type PlaylistTaglist::type() const { return Fe::DataDoc::Type::Play
//-Constructor--------------------------------------------------------------------------------------------------------
//Public:
-Romlist::Romlist(Install* const parent, const QString& listPath, QString docName, const Fe::UpdateOptions& updateOptions,
+Romlist::Romlist(Install* const parent, const QString& listPath, QString docName, const Import::UpdateOptions& updateOptions,
const DocKey&) :
- Fe::UpdateableDoc(parent, listPath, docName, updateOptions)
+ Lr::UpdateableDoc(parent, listPath, docName, updateOptions)
{}
//-Instance Functions--------------------------------------------------------------------------------------------------
//Public:
-Fe::DataDoc::Type Romlist::type() const { return Fe::DataDoc::Type::Config; }
+Lr::DataDoc::Type Romlist::type() const { return Lr::DataDoc::Type::Config; }
bool Romlist::isEmpty() const
{
@@ -295,7 +295,7 @@ const QHash>& Romlist::finalEntries() const { r
bool Romlist::containsGame(QUuid gameId) const { return mEntriesExisting.contains(gameId) || mEntriesFinal.contains(gameId); }
bool Romlist::containsAddApp(QUuid addAppId) const { return mEntriesExisting.contains(addAppId) || mEntriesFinal.contains(addAppId); }
-void Romlist::addSet(const Fp::Set& set, const Fe::ImageSources& images)
+void Romlist::addSet(const Fp::Set& set, const Lr::ImageSources& images)
{
// Convert to romlist entry
std::shared_ptr mainRomEntry = std::make_shared(set.game());
@@ -325,7 +325,7 @@ void Romlist::addSet(const Fp::Set& set, const Fe::ImageSources& images)
void Romlist::finalize()
{
finalizeUpdateableItems(mEntriesExisting, mEntriesFinal);
- Fe::UpdateableDoc::finalize();
+ Lr::UpdateableDoc::finalize();
}
//===============================================================================================================
@@ -355,7 +355,7 @@ bool Romlist::Reader::checkDocValidity(bool& isValid)
return !mStreamReader.hasError();
}
-Fe::DocHandlingError Romlist::Reader::readTargetDoc()
+Lr::DocHandlingError Romlist::Reader::readTargetDoc()
{
// Read all romlist entries
while(!mStreamReader.atEnd())
@@ -365,7 +365,7 @@ Fe::DocHandlingError Romlist::Reader::readTargetDoc()
}
// Only can have stream errors
- return Fe::DocHandlingError();
+ return Lr::DocHandlingError();
}
void Romlist::Reader::parseRomEntry(const QString& rawEntry)
@@ -586,7 +586,7 @@ bool BulkOverviewWriter::writeOverview(const QUuid& gameId, const QString& overv
//Public:
PlatformInterface::PlatformInterface(Install* const parent, const QString& platformTaglistPath, QString platformName,
const QDir& overviewDir,const DocKey&) :
- Fe::PlatformDoc(parent, {}, platformName, {}),
+ Lr::PlatformDoc(parent, {}, platformName, {}),
mPlatformTaglist(parent, platformTaglistPath, platformName),
mOverviewWriter(overviewDir)
{}
@@ -613,7 +613,7 @@ bool PlatformInterface::containsAddApp(QUuid addAppId) const
return static_cast(parent())->mRomlist->containsAddApp(addAppId);
};
-void PlatformInterface::addSet(const Fp::Set& set, const Fe::ImageSources& images)
+void PlatformInterface::addSet(const Fp::Set& set, const Lr::ImageSources& images)
{
if(!hasError())
{
@@ -633,7 +633,7 @@ void PlatformInterface::addSet(const Fp::Set& set, const Fe::ImageSources& image
if(written)
parent()->addRevertableFile(mOverviewWriter.currentFilePath());
else
- mError = Fe::DocHandlingError(*this, Fe::DocHandlingError::DocWriteFailed, mOverviewWriter.fileErrorString());
+ mError = Lr::DocHandlingError(*this, Lr::DocHandlingError::DocWriteFailed, mOverviewWriter.fileErrorString());
}
//-Handle add apps-------------------------------------------------------
@@ -662,14 +662,14 @@ void PlatformInterface::addSet(const Fp::Set& set, const Fe::ImageSources& image
//-Constructor--------------------------------------------------------------------------------------------------------
//Public:
PlatformInterface::Writer::Writer(PlatformInterface* sourceDoc) :
- Fe::DataDoc::Writer(sourceDoc),
- Fe::PlatformDoc::Writer(sourceDoc),
+ Lr::DataDoc::Writer(sourceDoc),
+ Lr::PlatformDoc::Writer(sourceDoc),
mTaglistWriter(&sourceDoc->mPlatformTaglist)
{}
//-Instance Functions--------------------------------------------------------------------------------------------------
//Public:
-Fe::DocHandlingError PlatformInterface::Writer::writeOutOf() { return mTaglistWriter.writeOutOf(); }
+Lr::DocHandlingError PlatformInterface::Writer::writeOutOf() { return mTaglistWriter.writeOutOf(); }
//===============================================================================================================
// PlaylistInterface
@@ -679,7 +679,7 @@ Fe::DocHandlingError PlatformInterface::Writer::writeOutOf() { return mTaglistWr
//Public:
PlaylistInterface::PlaylistInterface(Install* const parent, const QString& playlistTaglistPath, QString playlistName,
const DocKey&) :
- Fe::PlaylistDoc(parent, {}, playlistName, {}),
+ Lr::PlaylistDoc(parent, {}, playlistName, {}),
mPlaylistTaglist(parent, playlistTaglistPath, playlistName)
{}
@@ -705,14 +705,14 @@ void PlaylistInterface::setPlaylistData(const Fp::Playlist& playlist)
//-Constructor--------------------------------------------------------------------------------------------------------
//Public:
PlaylistInterface::Writer::Writer(PlaylistInterface* sourceDoc) :
- Fe::DataDoc::Writer(sourceDoc),
- Fe::PlaylistDoc::Writer(sourceDoc),
+ Lr::DataDoc::Writer(sourceDoc),
+ Lr::PlaylistDoc::Writer(sourceDoc),
mTaglistWriter(&sourceDoc->mPlaylistTaglist)
{}
//-Instance Functions--------------------------------------------------------------------------------------------------
//Public:
-Fe::DocHandlingError PlaylistInterface::Writer::writeOutOf() { return mTaglistWriter.writeOutOf(); }
+Lr::DocHandlingError PlaylistInterface::Writer::writeOutOf() { return mTaglistWriter.writeOutOf(); }
//===============================================================================================================
// Emulator
@@ -727,7 +727,7 @@ Emulator::Emulator(Install* const parent, const QString& filePath, const DocKey&
//-Instance Functions--------------------------------------------------------------------------------------------------
//Public:
bool Emulator::isEmpty() const { return false; } // Can have blank fields, but always has field keys
-Fe::DataDoc::Type Emulator::type() const { return Fe::DataDoc::Type::Config; }
+Lr::DataDoc::Type Emulator::type() const { return Lr::DataDoc::Type::Config; }
QString Emulator::executable() const { return mExecutable; }
QString Emulator::args() const { return mArgs; }
@@ -762,7 +762,7 @@ EmulatorReader::EmulatorReader(Emulator* targetDoc) :
//-Instance Functions--------------------------------------------------------------------------------------------------
//Private:
-Fe::DocHandlingError EmulatorReader::readTargetDoc()
+Lr::DocHandlingError EmulatorReader::readTargetDoc()
{
while(!mStreamReader.atEnd())
{
@@ -774,7 +774,7 @@ Fe::DocHandlingError EmulatorReader::readTargetDoc()
}
// Only can have stream related errors
- return Fe::DocHandlingError();
+ return Lr::DocHandlingError();
}
void EmulatorReader::parseKeyValue(const QString& key, const QString& value)
diff --git a/app/src/frontend/attractmode/am-data.h b/app/src/launcher/attractmode/am-data.h
similarity index 93%
rename from app/src/frontend/attractmode/am-data.h
rename to app/src/launcher/attractmode/am-data.h
index be477a9..c891c28 100644
--- a/app/src/frontend/attractmode/am-data.h
+++ b/app/src/launcher/attractmode/am-data.h
@@ -9,8 +9,8 @@
#include
// Project Includes
-#include "am-items.h"
-#include "frontend/fe-data.h"
+#include "launcher/lr-data.h"
+#include "launcher/attractmode/am-items.h"
namespace Am
{
@@ -25,7 +25,7 @@ class DocKey
DocKey(const DocKey&) = default;
};
-class CommonDocReader : public Fe::DataDoc::Reader
+class CommonDocReader : public Lr::DataDoc::Reader
{
//-Instance Variables--------------------------------------------------------------------------------------------------
protected:
@@ -33,20 +33,20 @@ class CommonDocReader : public Fe::DataDoc::Reader
//-Constructor--------------------------------------------------------------------------------------------------------
protected:
- CommonDocReader(Fe::DataDoc* targetDoc);
+ CommonDocReader(Lr::DataDoc* targetDoc);
//-Instance Functions-------------------------------------------------------------------------------------------------
protected:
bool lineIsComment(const QString& line);
QString readLineIgnoringComments(qint64 maxlen = 0);
virtual bool checkDocValidity(bool& isValid) = 0;
- virtual Fe::DocHandlingError readTargetDoc() = 0;
+ virtual Lr::DocHandlingError readTargetDoc() = 0;
public:
- Fe::DocHandlingError readInto() override;
+ Lr::DocHandlingError readInto() override;
};
-class CommonDocWriter : public Fe::DataDoc::Writer
+class CommonDocWriter : public Lr::DataDoc::Writer
{
//-Instance Variables--------------------------------------------------------------------------------------------------
protected:
@@ -54,17 +54,17 @@ class CommonDocWriter : public Fe::DataDoc::Writer
//-Constructor--------------------------------------------------------------------------------------------------------
protected:
- CommonDocWriter(Fe::DataDoc* sourceDoc);
+ CommonDocWriter(Lr::DataDoc* sourceDoc);
//-Instance Functions-------------------------------------------------------------------------------------------------
protected:
virtual bool writeSourceDoc() = 0;
public:
- Fe::DocHandlingError writeOutOf() override;
+ Lr::DocHandlingError writeOutOf() override;
};
-class ConfigDoc : public Fe::DataDoc
+class ConfigDoc : public Lr::DataDoc
{
//-Inner Classes----------------------------------------------------------------------------------------------------
public:
@@ -117,7 +117,7 @@ class ConfigDoc::Writer : public CommonDocWriter
bool writeSourceDoc() override;
};
-class Taglist : public Fe::DataDoc
+class Taglist : public Lr::DataDoc
{
//-Inner Classes----------------------------------------------------------------------------------------------------
public:
@@ -174,7 +174,7 @@ class PlaylistTaglist : public Taglist
Type type() const override;
};
-class Romlist : public Fe::UpdateableDoc
+class Romlist : public Lr::UpdateableDoc
{
/* This class looks like it should inherit PlatformDoc, but it isn't truly one in the context of an Am install
* since those are represented by tag lists, and if it did there would be the issue that once modified it would
@@ -199,7 +199,7 @@ class Romlist : public Fe::UpdateableDoc
//-Constructor--------------------------------------------------------------------------------------------------------
public:
- explicit Romlist(Install* const parent, const QString& listPath, QString docName, const Fe::UpdateOptions& updateOptions,
+ explicit Romlist(Install* const parent, const QString& listPath, QString docName, const Import::UpdateOptions& updateOptions,
const DocKey&);
//-Instance Functions--------------------------------------------------------------------------------------------------
@@ -212,7 +212,7 @@ class Romlist : public Fe::UpdateableDoc
bool containsGame(QUuid gameId) const;
bool containsAddApp(QUuid addAppId) const;
- void addSet(const Fp::Set& set, const Fe::ImageSources& images);
+ void addSet(const Fp::Set& set, const Lr::ImageSources& images);
void finalize() override;
};
@@ -227,7 +227,7 @@ class Romlist::Reader : public CommonDocReader
private:
QHash>& targetDocExistingRomEntries();
bool checkDocValidity(bool& isValid) override;
- Fe::DocHandlingError readTargetDoc() override;
+ Lr::DocHandlingError readTargetDoc() override;
void parseRomEntry(const QString& rawEntry);
void addFieldToBuilder(RomEntry::Builder& builder, QString field, quint8 index);
};
@@ -263,7 +263,7 @@ class BulkOverviewWriter
bool writeOverview(const QUuid& gameId, const QString& overview);
};
-class PlatformInterface : public Fe::PlatformDoc
+class PlatformInterface : public Lr::PlatformDoc
{
//-Inner Classes----------------------------------------------------------------------------------------------------
public:
@@ -289,10 +289,10 @@ class PlatformInterface : public Fe::PlatformDoc
bool containsGame(QUuid gameId) const override;
bool containsAddApp(QUuid addAppId) const override;
- void addSet(const Fp::Set& set, const Fe::ImageSources& images) override;
+ void addSet(const Fp::Set& set, const Lr::ImageSources& images) override;
};
-class PlatformInterface::Writer : public Fe::PlatformDoc::Writer
+class PlatformInterface::Writer : public Lr::PlatformDoc::Writer
{
// Shell for writing the taglist of the interface
@@ -306,10 +306,10 @@ class PlatformInterface::Writer : public Fe::PlatformDoc::Writer
//-Instance Functions-------------------------------------------------------------------------------------------------
public:
- Fe::DocHandlingError writeOutOf() override;
+ Lr::DocHandlingError writeOutOf() override;
};
-class PlaylistInterface : public Fe::PlaylistDoc
+class PlaylistInterface : public Lr::PlaylistDoc
{
//-Inner Classes----------------------------------------------------------------------------------------------------
public:
@@ -333,7 +333,7 @@ class PlaylistInterface : public Fe::PlaylistDoc
void setPlaylistData(const Fp::Playlist& playlist) override;
};
-class PlaylistInterface::Writer : public Fe::PlaylistDoc::Writer
+class PlaylistInterface::Writer : public Lr::PlaylistDoc::Writer
{
// Shell for writing the taglist of the interface
@@ -347,7 +347,7 @@ class PlaylistInterface::Writer : public Fe::PlaylistDoc::Writer
//-Instance Functions-------------------------------------------------------------------------------------------------
private:
- Fe::DocHandlingError writeOutOf() override;
+ Lr::DocHandlingError writeOutOf() override;
};
class Emulator : public ConfigDoc
@@ -437,7 +437,7 @@ class EmulatorReader : public ConfigDoc::Reader
//-Instance Functions-------------------------------------------------------------------------------------------------
private:
- Fe::DocHandlingError readTargetDoc() override;
+ Lr::DocHandlingError readTargetDoc() override;
void parseKeyValue(const QString& key, const QString& value);
void parseExecutable(const QString& value);
void parseArgs(const QString& value);
diff --git a/app/src/frontend/attractmode/am-install.cpp b/app/src/launcher/attractmode/am-install.cpp
similarity index 84%
rename from app/src/frontend/attractmode/am-install.cpp
rename to app/src/launcher/attractmode/am-install.cpp
index adc9a82..636175d 100644
--- a/app/src/frontend/attractmode/am-install.cpp
+++ b/app/src/launcher/attractmode/am-install.cpp
@@ -9,7 +9,7 @@
#include
// Project Includes
-#include "clifp.h"
+#include "kernel/clifp.h"
namespace Am
{
@@ -20,7 +20,7 @@ namespace Am
//-Constructor------------------------------------------------------------------------------------------------
//Public:
Install::Install(const QString& installPath) :
- Fe::Install(installPath),
+ Lr::Install(installPath),
mEmulatorsDirectory(installPath + '/' + EMULATORS_PATH),
mRomlistsDirectory(installPath + '/' + ROMLISTS_PATH),
mMainConfigFile(installPath + '/' + MAIN_CFG_PATH),
@@ -55,7 +55,7 @@ Install::Install(const QString& installPath) :
//Private:
void Install::nullify()
{
- Fe::Install::nullify();
+ Lr::Install::nullify();
mEmulatorsDirectory = QDir();
mRomlistsDirectory = QDir();
@@ -89,7 +89,7 @@ Qx::Error Install::populateExistingDocs()
return existingCheck;
for(const QFileInfo& platformFile : qAsConst(existingList))
- catalogueExistingDoc(Fe::DataDoc::Identifier(Fe::DataDoc::Type::Platform, platformFile.baseName()));
+ catalogueExistingDoc(Lr::DataDoc::Identifier(Lr::DataDoc::Type::Platform, platformFile.baseName()));
// Check for playlists
existingCheck = Qx::dirContentInfoList(existingList, mFpTagDirectory, {u"[[]Playlist[]] *."_s + TAG_EXT},
@@ -98,27 +98,27 @@ Qx::Error Install::populateExistingDocs()
return existingCheck;
for(const QFileInfo& playlistFile : qAsConst(existingList))
- catalogueExistingDoc(Fe::DataDoc::Identifier(Fe::DataDoc::Type::Playlist, playlistFile.baseName()));
+ catalogueExistingDoc(Lr::DataDoc::Identifier(Lr::DataDoc::Type::Playlist, playlistFile.baseName()));
// Check for special "Flashpoint" platform (more like a config doc but OK for now)
QFileInfo mainRomlistInfo(mFpRomlist);
if(mainRomlistInfo.exists())
- catalogueExistingDoc(Fe::DataDoc::Identifier(Fe::DataDoc::Type::Platform, mainRomlistInfo.baseName()));
+ catalogueExistingDoc(Lr::DataDoc::Identifier(Lr::DataDoc::Type::Platform, mainRomlistInfo.baseName()));
}
// Check for config docs
QFileInfo mainCfgInfo(mMainConfigFile);
- catalogueExistingDoc(Fe::DataDoc::Identifier(Fe::DataDoc::Type::Config, mainCfgInfo.baseName())); // Must exist
+ catalogueExistingDoc(Lr::DataDoc::Identifier(Lr::DataDoc::Type::Config, mainCfgInfo.baseName())); // Must exist
QFileInfo emulatorCfgInfo(mEmulatorConfigFile);
if(emulatorCfgInfo.exists())
- catalogueExistingDoc(Fe::DataDoc::Identifier(Fe::DataDoc::Type::Config, emulatorCfgInfo.baseName()));
+ catalogueExistingDoc(Lr::DataDoc::Identifier(Lr::DataDoc::Type::Config, emulatorCfgInfo.baseName()));
// Return success
return Qx::Error();
}
-QString Install::imageDestinationPath(Fp::ImageType imageType, const Fe::Game* game) const
+QString Install::imageDestinationPath(Fp::ImageType imageType, const Lr::Game* game) const
{
return mFpScraperDirectory.absolutePath() + '/' +
(imageType == Fp::ImageType::Logo ? LOGO_FOLDER_NAME : SCREENSHOT_FOLDER_NAME) + '/' +
@@ -126,7 +126,7 @@ QString Install::imageDestinationPath(Fp::ImageType imageType, const Fe::Game* g
'.' + IMAGE_EXT;
}
-std::shared_ptr Install::preparePlatformDocCheckout(std::unique_ptr& platformDoc, const QString& translatedName)
+std::shared_ptr Install::preparePlatformDocCheckout(std::unique_ptr& platformDoc, const QString& translatedName)
{
// Determine path to the taglist that corresponds with the interface
QString taglistPath = mFpTagDirectory.absoluteFilePath(translatedName + u"."_s + TAG_EXT) ;
@@ -138,10 +138,10 @@ std::shared_ptr Install::preparePlatformDocCheckout(std
platformDoc = std::make_unique(this, taglistPath, translatedName, overviewDir, DocKey{});
// No reading to be done for this interface (tag lists are always overwritten)
- return std::shared_ptr();
+ return std::shared_ptr();
}
-std::shared_ptr Install::preparePlaylistDocCheckout(std::unique_ptr& playlistDoc, const QString& translatedName)
+std::shared_ptr Install::preparePlaylistDocCheckout(std::unique_ptr& playlistDoc, const QString& translatedName)
{
// Determine path to the taglist that corresponds with the interface
QString taglistPath = mFpTagDirectory.absoluteFilePath(translatedName + u"."_s + TAG_EXT) ;
@@ -150,28 +150,28 @@ std::shared_ptr Install::preparePlaylistDocCheckout(std
playlistDoc = std::make_unique(this, taglistPath, translatedName, DocKey{});
// No reading to be done for this interface (tag lists are always overwritten)
- return std::shared_ptr();
+ return std::shared_ptr();
}
-std::shared_ptr Install::preparePlatformDocCommit(const std::unique_ptr& platformDoc)
+std::shared_ptr Install::preparePlatformDocCommit(const std::unique_ptr& platformDoc)
{
// Construct doc writer
- std::shared_ptr docWriter = std::make_shared(static_cast(platformDoc.get()));
+ std::shared_ptr docWriter = std::make_shared(static_cast(platformDoc.get()));
// Return writer
return docWriter;
}
-std::shared_ptr Install::preparePlaylistDocCommit(const std::unique_ptr& playlistDoc)
+std::shared_ptr Install::preparePlaylistDocCommit(const std::unique_ptr& playlistDoc)
{
// Construct doc writer
- std::shared_ptr docWriter = std::make_shared(static_cast(playlistDoc.get()));
+ std::shared_ptr docWriter = std::make_shared(static_cast(playlistDoc.get()));
// Return writer
return docWriter;
}
-Fe::DocHandlingError Install::checkoutMainConfig(std::unique_ptr& returnBuffer)
+Lr::DocHandlingError Install::checkoutMainConfig(std::unique_ptr& returnBuffer)
{
// Construct unopened document
returnBuffer = std::make_unique(this, mMainConfigFile.fileName(), DocKey{});
@@ -180,7 +180,7 @@ Fe::DocHandlingError Install::checkoutMainConfig(std::unique_ptr&
std::shared_ptr docReader = std::make_shared(returnBuffer.get());
// Open document
- Fe::DocHandlingError readErrorStatus = checkoutDataDocument(returnBuffer.get(), docReader);
+ Lr::DocHandlingError readErrorStatus = checkoutDataDocument(returnBuffer.get(), docReader);
// Set return null on failure
if(readErrorStatus.isValid())
@@ -190,7 +190,7 @@ Fe::DocHandlingError Install::checkoutMainConfig(std::unique_ptr&
return readErrorStatus;
}
-Fe::DocHandlingError Install::checkoutFlashpointRomlist(std::unique_ptr& returnBuffer)
+Lr::DocHandlingError Install::checkoutFlashpointRomlist(std::unique_ptr& returnBuffer)
{
// Construct unopened document
returnBuffer = std::make_unique(this, mFpRomlist.fileName(), Fp::NAME, mImportDetails->updateOptions, DocKey{});
@@ -199,7 +199,7 @@ Fe::DocHandlingError Install::checkoutFlashpointRomlist(std::unique_ptr
std::shared_ptr docReader = std::make_shared(returnBuffer.get());
// Open document
- Fe::DocHandlingError readErrorStatus = checkoutDataDocument(returnBuffer.get(), docReader);
+ Lr::DocHandlingError readErrorStatus = checkoutDataDocument(returnBuffer.get(), docReader);
// Set return null on failure
if(readErrorStatus.isValid())
@@ -209,7 +209,7 @@ Fe::DocHandlingError Install::checkoutFlashpointRomlist(std::unique_ptr
return readErrorStatus;
}
-Fe::DocHandlingError Install::checkoutClifpEmulatorConfig(std::unique_ptr& returnBuffer)
+Lr::DocHandlingError Install::checkoutClifpEmulatorConfig(std::unique_ptr& returnBuffer)
{
// Construct unopened document
returnBuffer = std::make_unique(this, mEmulatorConfigFile.fileName(), DocKey{});
@@ -218,7 +218,7 @@ Fe::DocHandlingError Install::checkoutClifpEmulatorConfig(std::unique_ptr docReader = std::make_shared(returnBuffer.get());
// Open document
- Fe::DocHandlingError readErrorStatus = checkoutDataDocument(returnBuffer.get(), docReader);
+ Lr::DocHandlingError readErrorStatus = checkoutDataDocument(returnBuffer.get(), docReader);
// Set return null on failure
if(readErrorStatus.isValid())
@@ -228,7 +228,7 @@ Fe::DocHandlingError Install::checkoutClifpEmulatorConfig(std::unique_ptr document)
+Lr::DocHandlingError Install::commitMainConfig(std::unique_ptr document)
{
assert(document->parent() == this);
@@ -236,7 +236,7 @@ Fe::DocHandlingError Install::commitMainConfig(std::unique_ptr do
std::shared_ptr docWriter = std::make_shared(document.get());
// Write
- Fe::DocHandlingError writeErrorStatus = commitDataDocument(document.get(), docWriter);
+ Lr::DocHandlingError writeErrorStatus = commitDataDocument(document.get(), docWriter);
// Ensure document is cleared
document.reset();
@@ -245,7 +245,7 @@ Fe::DocHandlingError Install::commitMainConfig(std::unique_ptr do
return writeErrorStatus;
}
-Fe::DocHandlingError Install::commitFlashpointRomlist(std::unique_ptr document)
+Lr::DocHandlingError Install::commitFlashpointRomlist(std::unique_ptr document)
{
assert(document->parent() == this);
@@ -253,7 +253,7 @@ Fe::DocHandlingError Install::commitFlashpointRomlist(std::unique_ptr d
std::shared_ptr docWriter = std::make_shared(document.get());
// Write
- Fe::DocHandlingError writeErrorStatus = commitDataDocument(document.get(), docWriter);
+ Lr::DocHandlingError writeErrorStatus = commitDataDocument(document.get(), docWriter);
// Ensure document is cleared
document.reset();
@@ -263,7 +263,7 @@ Fe::DocHandlingError Install::commitFlashpointRomlist(std::unique_ptr d
}
-Fe::DocHandlingError Install::commitClifpEmulatorConfig(std::unique_ptr document)
+Lr::DocHandlingError Install::commitClifpEmulatorConfig(std::unique_ptr document)
{
assert(document->parent() == this);
@@ -271,7 +271,7 @@ Fe::DocHandlingError Install::commitClifpEmulatorConfig(std::unique_ptr docWriter = std::make_shared(document.get());
// Write
- Fe::DocHandlingError writeErrorStatus = commitDataDocument(document.get(), docWriter);
+ Lr::DocHandlingError writeErrorStatus = commitDataDocument(document.get(), docWriter);
// Ensure document is cleared
document.reset();
@@ -283,7 +283,7 @@ Fe::DocHandlingError Install::commitClifpEmulatorConfig(std::unique_ptr Install::preferredImageModeOrder() const { return IMAGE_MODE_ORDER; }
+QList Install::preferredImageModeOrder() const { return IMAGE_MODE_ORDER; }
bool Install::isRunning() const
{
@@ -324,18 +324,18 @@ QString Install::versionString() const
}
// Can't determine version
- return Fe::Install::versionString();
+ return Lr::Install::versionString();
}
-QString Install::translateDocName(const QString& originalName, Fe::DataDoc::Type type) const
+QString Install::translateDocName(const QString& originalName, Lr::DataDoc::Type type) const
{
// Perform general kosherization
QString translatedName = Qx::kosherizeFileName(originalName);
// Prefix platforms/playlists
- if(type == Fe::DataDoc::Type::Platform)
+ if(type == Lr::DataDoc::Type::Platform)
translatedName.prepend(PLATFORM_TAG_PREFIX);
- else if(type == Fe::DataDoc::Type::Playlist)
+ else if(type == Lr::DataDoc::Type::Playlist)
translatedName.prepend(PLAYLIST_TAG_PREFIX);
return translatedName;
@@ -357,7 +357,7 @@ Qx::Error Install::preImport(const ImportDetails& details)
return Qx::IoOpReport(Qx::IO_OP_WRITE, Qx::IO_ERR_CANT_CREATE, overviewDir);
// Logo and screenshot dir
- if(details.imageMode == Fe::ImageMode::Copy || details.imageMode == Fe::ImageMode::Link)
+ if(details.imageMode == Import::ImageMode::Copy || details.imageMode == Import::ImageMode::Link)
{
QDir logoDir(mFpScraperDirectory.absoluteFilePath(LOGO_FOLDER_NAME));
if(!logoDir.exists())
@@ -371,7 +371,7 @@ Qx::Error Install::preImport(const ImportDetails& details)
}
// Perform base tasks
- return Fe::Install::preImport(details);
+ return Lr::Install::preImport(details);
}
Qx::Error Install::prePlatformsImport()
@@ -389,17 +389,17 @@ Qx::Error Install::postPlatformsImport()
return commitFlashpointRomlist(std::move(mRomlist));
}
-Qx::Error Install::preImageProcessing(QList& workerTransfers, const Fe::ImageSources& bulkSources)
+Qx::Error Install::preImageProcessing(QList& workerTransfers, const Lr::ImageSources& bulkSources)
{
Q_UNUSED(bulkSources);
switch(mImportDetails->imageMode)
{
- case Fe::ImageMode::Link:
- case Fe::ImageMode::Copy:
+ case Import::ImageMode::Link:
+ case Import::ImageMode::Copy:
workerTransfers.swap(mWorkerImageJobs);
return Qx::Error();
- case Fe::ImageMode::Reference:
+ case Import::ImageMode::Reference:
qWarning("unsupported image mode");
return Qx::Error();
default:
@@ -414,7 +414,7 @@ Qx::Error Install::postImport()
// Checkout emulator config
std::unique_ptr emulatorConfig;
- Fe::DocHandlingError emulatorConfigReadError = checkoutClifpEmulatorConfig(emulatorConfig);
+ Lr::DocHandlingError emulatorConfigReadError = checkoutClifpEmulatorConfig(emulatorConfig);
// Stop import if error occurred
if(emulatorConfigReadError.isValid())
@@ -445,7 +445,7 @@ Qx::Error Install::postImport()
emulatorConfig->setArtworkEntry(aeb.build());
// Commit emulator config
- Fe::DocHandlingError emulatorConfigWriteError = commitClifpEmulatorConfig(std::move(emulatorConfig));
+ Lr::DocHandlingError emulatorConfigWriteError = commitClifpEmulatorConfig(std::move(emulatorConfig));
// Stop import if error occurred
if(emulatorConfigWriteError.isValid())
@@ -455,7 +455,7 @@ Qx::Error Install::postImport()
// Checkout main config
std::unique_ptr mainConfig;
- Fe::DocHandlingError mainConfigReadError = checkoutMainConfig(mainConfig);
+ Lr::DocHandlingError mainConfigReadError = checkoutMainConfig(mainConfig);
// Stop import if error occurred
if(mainConfigReadError.isValid())
@@ -511,6 +511,7 @@ Qx::Error Install::postImport()
for(const QString& tagFile : tagFiles)
{
// Escape brackets in name since AM uses regex for value
+ // TODO: Use Qx for this
QString escaped = tagFile;
escaped.replace(u"["_s, u"\\["_s).replace(u"]"_s, u"\\]"_s);
@@ -524,7 +525,7 @@ Qx::Error Install::postImport()
}
// Commit main config
- Fe::DocHandlingError configCommitError = commitMainConfig(std::move(mainConfig));
+ Lr::DocHandlingError configCommitError = commitMainConfig(std::move(mainConfig));
// Stop import if error occurred
if(configCommitError.isValid())
@@ -540,10 +541,10 @@ Qx::Error Install::postImport()
return Qx::Error();
}
-void Install::processDirectGameImages(const Fe::Game* game, const Fe::ImageSources& imageSources)
+void Install::processDirectGameImages(const Lr::Game* game, const Lr::ImageSources& imageSources)
{
- Fe::ImageMode mode = mImportDetails->imageMode;
- if(mode == Fe::ImageMode::Link || mode == Fe::ImageMode::Copy)
+ Import::ImageMode mode = mImportDetails->imageMode;
+ if(mode == Import::ImageMode::Link || mode == Import::ImageMode::Copy)
{
if(!imageSources.logoPath().isEmpty())
{
diff --git a/app/src/frontend/attractmode/am-install.h b/app/src/launcher/attractmode/am-install.h
similarity index 70%
rename from app/src/frontend/attractmode/am-install.h
rename to app/src/launcher/attractmode/am-install.h
index 81b7540..a9c4058 100644
--- a/app/src/frontend/attractmode/am-install.h
+++ b/app/src/launcher/attractmode/am-install.h
@@ -5,14 +5,14 @@
#include
// Project Includes
-#include "frontend/fe-install.h"
-#include "am-data.h"
-#include "am-settings-data.h"
+#include "launcher/lr-install.h"
+#include "launcher/attractmode/am-data.h"
+#include "launcher/attractmode/am-settings-data.h"
namespace Am
{
-class Install : public Fe::Install
+class Install : public Lr::Install
{
friend class PlatformInterface;
friend class PlaylistInterface;
@@ -21,7 +21,7 @@ class Install : public Fe::Install
public:
// Identity
static inline const QString NAME = u"AttractMode"_s;
- static inline const QString ICON_PATH = u":/frontend/AttractMode/icon.png"_s;
+ static inline const QString ICON_PATH = u":/launcher/AttractMode/icon.png"_s;
static inline const QUrl HELP_URL = QUrl(u""_s);
// Naming
@@ -52,9 +52,9 @@ class Install : public Fe::Install
static inline const QString CFG_EXT = u"cfg"_s;
// Support
- static inline const QList IMAGE_MODE_ORDER {
- Fe::ImageMode::Link,
- Fe::ImageMode::Copy
+ static inline const QList IMAGE_MODE_ORDER {
+ Import::ImageMode::Link,
+ Import::ImageMode::Copy
};
/*
* NOTE: In order to support reference, thousands of folders would have to be added to the image search list which is likely impractical.
@@ -62,7 +62,7 @@ class Install : public Fe::Install
*/
// Extra
- static inline const QString MARQUEE_PATH = u":/frontend/AttractMode/marquee.png"_s;
+ static inline const QString MARQUEE_PATH = u":/launcher/AttractMode/marquee.png"_s;
//-Instance Variables-----------------------------------------------------------------------------------------------
private:
@@ -97,20 +97,20 @@ class Install : public Fe::Install
QString versionFromExecutable() const;
// Image Processing
- QString imageDestinationPath(Fp::ImageType imageType, const Fe::Game* game) const;
+ QString imageDestinationPath(Fp::ImageType imageType, const Lr::Game* game) const;
// Doc handling
- std::shared_ptr preparePlatformDocCheckout(std::unique_ptr& platformDoc, const QString& translatedName) override;
- std::shared_ptr preparePlaylistDocCheckout(std::unique_ptr& playlistDoc, const QString& translatedName) override;
- std::shared_ptr preparePlatformDocCommit(const std::unique_ptr& platformDoc) override;
- std::shared_ptr preparePlaylistDocCommit(const std::unique_ptr& playlistDoc) override;
-
- Fe::DocHandlingError checkoutMainConfig(std::unique_ptr