Skip to content

Commit

Permalink
Merge pull request #75 from oblivioncth/feature/simple_link
Browse files Browse the repository at this point in the history
Simplify c-link by adding dedicated name argument
  • Loading branch information
oblivioncth authored Nov 7, 2023
2 parents b6d3622 + 6106212 commit 8448e2e
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 70 deletions.
51 changes: 22 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,23 +146,23 @@ or
--msg="I am a message"

### Global Options:
- **-h | --help | -?:** Prints usage information
- **-v | --version:** Prints the current version of the tool
- **-q | --quiet:** Silences all non-critical messages
- **-s | --silent:** Silences all messages (takes precedence over quiet mode)
- **-h | --help | -?:** Prints usage information
- **-v | --version:** Prints the current version of the tool
- **-q | --quiet:** Silences all non-critical messages
- **-s | --silent:** Silences all messages (takes precedence over quiet mode)

Every command also has a corresponding help switch for command specific usage information.

### Title Commands:
Many of CLIFp's commands require a game/animation to be specified, which can be done in several ways. These commands, are known as *title commands* and are noted as such below. The explanation for these common options are shown here instead of being repeated under each individually.

Title Comamnd Shared Options:
- **-i | --id:** UUID of a game
- **-t | --title:** The title of a game.
- **-T | --title-strict:** Same as **-t**, but only exact matches are considered
- **-s | --subtitle:** Name of an additional-app under a game. Must be used with **-t**/**-T**
- **-S | --subtitle-strict:** Same as **-s**, but only exact matches are considered
- **-r | --random:** Selects a random title from the database. Must be followed by a library filter: `all`/`any`, `game`/`arcade`, or `animation`/`theatre`
- **-i | --id:** UUID of a game
- **-t | --title:** The title of a game.
- **-T | --title-strict:** Same as **-t**, but only exact matches are considered
- **-s | --subtitle:** Name of an additional-app under a game. Must be used with **-t**/**-T**
- **-S | --subtitle-strict:** Same as **-s**, but only exact matches are considered
- **-r | --random:** Selects a random title from the database. Must be followed by a library filter: `all`/`any`, `game`/`arcade`, or `animation`/`theatre`

The **-title** and **-subtitle** options are case-insensitive and will match any title that contains the value provided; however, the provided title should match as closely as possible to how it appears within Flashpoint, as checks for close matches are limited due to technical restrictions. If more than one entry is found, a dialog window with more information will be displayed so that the intended title can be selected, though there is a limit to the number of matches.

Expand All @@ -174,18 +174,11 @@ Tip: You can use **-subtitle** with an empty string (i.e. `-s ""`) to see all of
**link** - Creates a shortcut to a Flashpoint title

Options:
- [Title Command](#title-commands) options
- **-p | --path:** Path to new shortcut, defaults to the desktop. Path's ending with ".lnk" (Windows) or ".desktop" (Linux) will be interpreted as a named shortcut file. Any other path will be interpreted as a directory and the title will automatically be used as the filename
- [Title Command](#title-commands) options
- **-p | --path:** Path to directory in which to place the shortcut. Prompts if not provided.
- **-n | --name:** Name of the shortcut. Defaults to the name of the title

Notes:

- On Linux, when providing a full shortcut path via the **--path** switch, the filename component is re-interpreted as the shortcut's display name and the actual filename is set automatically.

For example, when specifying:

CLIFp link -p "~/Desktop/Cool Name.desktop" ...

the display name of the desktop entry will be set to "Cool Name".
- On some Linux desktop environments (i.e. GNOME) the shortcut might need to manually be set to "trusted" in order to be used and displayed correctly after it is created. This option is usually available in the file's right-click context menu.

--------------------------------------------------------------------------------
Expand All @@ -194,23 +187,23 @@ Notes:

Options:

- [Title Command](#title-commands) options
- [Title Command](#title-commands) options

--------------------------------------------------------------------------------

**prepare** - Initializes Flashpoint for playing the provided Data Pack based title by UUID. If the title does not use a Data Pack this command has no effect.

Options:

- [Title Command](#title-commands) options
- [Title Command](#title-commands) options

--------------------------------------------------------------------------------

**run** - Start Flashpoint's webserver and then execute the provided application

Options:
- **-a | --app:** Relative (to Flashpoint Directory) path of application to launch
- **-p | --param:** Command-line parameters to use when starting the application
- **-a | --app:** Relative (to Flashpoint Directory) path of application to launch
- **-p | --param:** Command-line parameters to use when starting the application

Requires:
**-a**
Expand All @@ -235,8 +228,8 @@ See http://www.robvanderwoude.com/escapechars.php for more information.
**share** - Generates a URL for starting a Flashpoint title that can be shared to other users.

Options:
- [Title Command](#title-commands) options
- **-u | --universal:** Creates a standard HTTPS link that utilizes a redirect page. May be easier to share on some platforms.
- [Title Command](#title-commands) options
- **-u | --universal:** Creates a standard HTTPS link that utilizes a redirect page. May be easier to share on some platforms.
- **-c | --configure:** Registers CLIFp as the default handler for "flashpoint" protocol links.
- **-C | --unconfigure:** Removes CLIFp as the default handler for "flashpoint" protocol links.

Expand All @@ -250,9 +243,9 @@ Notes:
**show** - Display a message or extra folder

Options:
- **-m | --msg:** Displays an pop-up dialog with the supplied message. Used primarily for some additional apps
- **-e | --extra:** Opens an explorer window to the specified extra. Used primarily for some additional apps
- **-h | --help | -?:** Prints command specific usage information
- **-m | --msg:** Displays an pop-up dialog with the supplied message. Used primarily for some additional apps
- **-e | --extra:** Opens an explorer window to the specified extra. Used primarily for some additional apps
- **-h | --help | -?:** Prints command specific usage information

Requires:
**-m** or **-e**
Expand Down
39 changes: 12 additions & 27 deletions app/src/command/c-link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Qx::Error CLink::perform()
// Get database
Fp::Db* database = mCore.fpInstall().database();

// Get entry (also confirms that ID is present in database)
// Get entry (also confirms that ID is present in database, which is why we do this even if a custom name is set)
std::variant<Fp::Game, Fp::AddApp> entry_v;
Fp::DbError dbError = database->getEntry(entry_v, shortcutId);
if(dbError.isValid())
Expand All @@ -66,7 +66,7 @@ Qx::Error CLink::perform()
if(std::holds_alternative<Fp::Game>(entry_v))
{
Fp::Game game = std::get<Fp::Game>(entry_v);
shortcutName = Qx::kosherizeFileName(game.title());
shortcutName = game.title();
}
else if(std::holds_alternative<Fp::AddApp>(entry_v))
{
Expand All @@ -82,38 +82,28 @@ Qx::Error CLink::perform()
Q_ASSERT(std::holds_alternative<Fp::Game>(entry_v));

Fp::Game parent = std::get<Fp::Game>(entry_v);
shortcutName = Qx::kosherizeFileName(parent.title() + u" ("_s + addApp.name() + u")"_s);
shortcutName = parent.title() + u" ("_s + addApp.name() + u")"_s;
}
else
qCritical("Invalid variant state for std::variant<Fp::Game, Fp::AddApp>.");

// Override shortcut name with user input
if(mParser.isSet(CL_OPTION_NAME))
shortcutName = mParser.value(CL_OPTION_NAME);

// Get shortcut path
if(mParser.isSet(CL_OPTION_PATH))
{
QFileInfo inputPathInfo(mParser.value(CL_OPTION_PATH));
if(inputPathInfo.suffix() == shortcutExtension()) // Path is file
{
mCore.logEvent(NAME, LOG_EVENT_FILE_PATH);
shortcutDir = inputPathInfo.absoluteDir();
shortcutName = inputPathInfo.baseName();
}
else // Path is directory
{
mCore.logEvent(NAME, LOG_EVENT_DIR_PATH);
shortcutDir = QDir(inputPathInfo.absoluteFilePath());
}
}
shortcutDir = mParser.value(CL_OPTION_PATH);
else
{
mCore.logEvent(NAME, LOG_EVENT_NO_PATH);

// Prompt user for path
Core::SaveFileRequest sfr{
Core::ExistingDirRequest edr{
.caption = DIAG_CAPTION,
.dir = QDir::homePath() + u"/Desktop/"_s + shortcutName,
.filter = u"Shortcuts (*. "_s + shortcutExtension() + u")"_s
.dir = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)
};
QString selectedPath = mCore.requestSaveFilePath(sfr);
QString selectedPath = mCore.requestExistingDirPath(edr);

if(selectedPath.isEmpty())
{
Expand All @@ -122,13 +112,8 @@ Qx::Error CLink::perform()
}
else
{
if(!selectedPath.endsWith(u"."_s + shortcutExtension(), Qt::CaseInsensitive))
selectedPath += u"."_s + shortcutExtension();

mCore.logEvent(NAME, LOG_EVENT_SEL_PATH.arg(QDir::toNativeSeparators(selectedPath)));
QFileInfo pathInfo(selectedPath);
shortcutDir = pathInfo.absoluteDir();
shortcutName = pathInfo.baseName();
shortcutDir = selectedPath;
}
}

Expand Down
14 changes: 7 additions & 7 deletions app/src/command/c-link.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ class CLink : public TitleCommand
static inline const QString DIAG_CAPTION = u"Select a shortcut destination..."_s;

// Logging - Messages
static inline const QString LOG_EVENT_FILE_PATH = u"Shortcut path provided is for a file"_s;
static inline const QString LOG_EVENT_DIR_PATH = u"Shortcut path provided is for a folder"_s;
static inline const QString LOG_EVENT_NO_PATH = u"No shortcut path provided, user will be prompted"_s;
static inline const QString LOG_EVENT_SEL_PATH = u"Shortcut path selected: %1"_s;
static inline const QString LOG_EVENT_DIAG_CANCEL = u"Shortcut path selection canceled."_s;
Expand All @@ -71,14 +69,17 @@ class CLink : public TitleCommand
// Command line option strings
static inline const QString CL_OPT_PATH_S_NAME = u"p"_s;
static inline const QString CL_OPT_PATH_L_NAME = u"path"_s;
static inline const QString CL_OPT_PATH_DESC = u"Path to new shortcut. Path's ending with "".lnk""//"".desktop"" will be interpreted as a named shortcut file. "
"Any other path will be interpreted as a directory and the title will automatically be used "
"as the filename"_s;
static inline const QString CL_OPT_PATH_DESC = u"Path to a directory for the new shortcut"_s;

static inline const QString CL_OPT_NAME_S_NAME = u"n"_s;
static inline const QString CL_OPT_NAME_L_NAME = u"name"_s;
static inline const QString CL_OPT_NAME_DESC = u"Name of the shortcut. Defaults to the name of the title"_s;

// Command line options
static inline const QCommandLineOption CL_OPTION_PATH{{CL_OPT_PATH_S_NAME, CL_OPT_PATH_L_NAME}, CL_OPT_PATH_DESC, u"path"_s}; // Takes value
static inline const QCommandLineOption CL_OPTION_NAME{{CL_OPT_NAME_S_NAME, CL_OPT_NAME_L_NAME}, CL_OPT_NAME_DESC, u"name"_s}; // Takes value

static inline const QList<const QCommandLineOption*> CL_OPTIONS_SPECIFIC{&CL_OPTION_PATH};
static inline const QList<const QCommandLineOption*> CL_OPTIONS_SPECIFIC{&CL_OPTION_PATH, &CL_OPTION_NAME};
static inline const QSet<const QCommandLineOption*> CL_OPTIONS_REQUIRED{};

public:
Expand All @@ -93,7 +94,6 @@ class CLink : public TitleCommand
//-Instance Functions------------------------------------------------------------------------------------------------------
private:
Qx::Error createShortcut(const QString& name, const QDir& dir, QUuid id);
QString shortcutExtension() const;

protected:
QList<const QCommandLineOption*> options() override;
Expand Down
5 changes: 1 addition & 4 deletions app/src/command/c-link_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ Qx::Error CLink::createShortcut(const QString& name, const QDir& dir, QUuid id)
ade.setComment(u"Generated by "_s PROJECT_SHORT_NAME " " PROJECT_VERSION_STR);

// Create entry
QString filename = u"org.flashpoint.clifp."_s + id.toString(QUuid::WithoutBraces) +
'.' + shortcutExtension();
QString filename = u"org.flashpoint.clifp."_s + id.toString(QUuid::WithoutBraces) + u".desktop"_s;
QString fullEntryPath = dir.absoluteFilePath(filename);
Qx::IoOpReport writeReport = Qx::DesktopEntry::writeToDisk(fullEntryPath, &ade);

Expand All @@ -51,5 +50,3 @@ Qx::Error CLink::createShortcut(const QString& name, const QDir& dir, QUuid id)
// Return success
return CLinkError();
}

QString CLink::shortcutExtension() const { return u"desktop"_s; };
6 changes: 3 additions & 3 deletions app/src/command/c-link_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@
//Private:
Qx::Error CLink::createShortcut(const QString& name, const QDir& dir, QUuid id)
{
QString filename = Qx::kosherizeFileName(name);

// Create shortcut properties
Qx::ShortcutProperties sp;
sp.target = CLIFP_PATH;
sp.targetArgs = CPlay::NAME + u" -"_s + TitleCommand::CL_OPTION_ID.names().constFirst() + ' ' + id.toString(QUuid::WithoutBraces);
sp.comment = name;

// Create shortcut
QString fullShortcutPath = dir.absolutePath() + '/' + name + '.' + shortcutExtension();
QString fullShortcutPath = dir.absolutePath() + '/' + filename + u".lnk"_s;
Qx::SystemError shortcutError = Qx::createShortcut(fullShortcutPath, sp);

// Check for creation failure
Expand All @@ -38,5 +40,3 @@ Qx::Error CLink::createShortcut(const QString& name, const QDir& dir, QUuid id)
// Return success
return CLinkError();
}

QString CLink::shortcutExtension() const { return u"lnk"_s; };
1 change: 1 addition & 0 deletions app/src/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Controller::Controller(QObject* parent) :
connect(driver, &Driver::message, &mStatusRelay, &StatusRelay::messageHandler, Qt::BlockingQueuedConnection); // Allows optional blocking
connect(driver, &Driver::blockingErrorOccurred, &mStatusRelay, &StatusRelay::blockingErrorHandler, Qt::BlockingQueuedConnection);
connect(driver, &Driver::saveFileRequested, &mStatusRelay, &StatusRelay::saveFileRequestHandler, Qt::BlockingQueuedConnection);
connect(driver, &Driver::existingDirRequested, &mStatusRelay, &StatusRelay::existingDirectoryRequestHandler, Qt::BlockingQueuedConnection);
connect(driver, &Driver::itemSelectionRequested, &mStatusRelay, &StatusRelay::itemSelectionRequestHandler, Qt::BlockingQueuedConnection);
connect(driver, &Driver::questionAnswerRequested, &mStatusRelay, &StatusRelay::questionAnswerRequestHandler, Qt::BlockingQueuedConnection);

Expand Down
10 changes: 10 additions & 0 deletions app/src/frontend/statusrelay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,16 @@ void StatusRelay::saveFileRequestHandler(QSharedPointer<QString> file, Core::Sav
qFatal("No response argument provided!");
}

void StatusRelay::existingDirectoryRequestHandler(QSharedPointer<QString> dir, Core::ExistingDirRequest request)
{
if(dir)
{
*dir = QFileDialog::getExistingDirectory(nullptr, request.caption, request.dir, request.options);
}
else
qFatal("No response argument provided!");
}

void StatusRelay::itemSelectionRequestHandler(QSharedPointer<QString> item, const Core::ItemSelectionRequest& request)
{
if(item)
Expand Down
1 change: 1 addition & 0 deletions app/src/frontend/statusrelay.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public slots:
void blockingErrorHandler(QSharedPointer<int> response, Core::BlockingError blockingError);
void messageHandler(const Message& message);
void saveFileRequestHandler(QSharedPointer<QString> file, Core::SaveFileRequest request);
void existingDirectoryRequestHandler(QSharedPointer<QString> dir, Core::ExistingDirRequest request);
void itemSelectionRequestHandler(QSharedPointer<QString> item, const Core::ItemSelectionRequest& request);
void clipboardUpdateRequestHandler(const QString& text);
void questionAnswerRequestHandler(QSharedPointer<bool> response, const QString& question);
Expand Down
12 changes: 12 additions & 0 deletions app/src/kernel/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,18 @@ QString Core::requestSaveFilePath(const SaveFileRequest& request)
return *file;
}

QString Core::requestExistingDirPath(const ExistingDirRequest& request)
{
// Response holder
QSharedPointer<QString> dir = QSharedPointer<QString>::create();

// Emit and get response
emit existingDirRequested(dir, request);

// Return response
return *dir;
}

QString Core::requestItemSelection(const ItemSelectionRequest& request)
{
// Response holder
Expand Down
9 changes: 9 additions & 0 deletions app/src/kernel/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ class Core : public QObject
QFileDialog::Options options;
};

struct ExistingDirRequest
{
QString caption;
QString dir;
QFileDialog::Options options = QFileDialog::ShowDirsOnly;
};

struct ItemSelectionRequest
{
QString caption;
Expand Down Expand Up @@ -310,6 +317,7 @@ class Core : public QObject
int postBlockingError(QString src, Qx::Error error, bool log = true, QMessageBox::StandardButtons bs = QMessageBox::Ok, QMessageBox::StandardButton def = QMessageBox::NoButton);
void postMessage(const Message& msg);
QString requestSaveFilePath(const SaveFileRequest& request);
QString requestExistingDirPath(const ExistingDirRequest& request);
QString requestItemSelection(const ItemSelectionRequest& request);
void requestClipboardUpdate(const QString& text);
bool requestQuestionAnswer(const QString& question);
Expand Down Expand Up @@ -337,6 +345,7 @@ class Core : public QObject
void errorOccurred(const Core::Error& error);
void blockingErrorOccurred(QSharedPointer<int> response, const Core::BlockingError& blockingError);
void saveFileRequested(QSharedPointer<QString> file, const Core::SaveFileRequest& request);
void existingDirRequested(QSharedPointer<QString> dir, const Core::ExistingDirRequest& request);
void itemSelectionRequested(QSharedPointer<QString> item, const Core::ItemSelectionRequest& request);
void message(const Message& message);
void clipboardUpdateRequested(const QString& text);
Expand Down
1 change: 1 addition & 0 deletions app/src/kernel/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ void Driver::init()
connect(mCore, &Core::blockingErrorOccurred, this, &Driver::blockingErrorOccurred);
connect(mCore, &Core::message, this, &Driver::message);
connect(mCore, &Core::saveFileRequested, this, &Driver::saveFileRequested);
connect(mCore, &Core::existingDirRequested, this, &Driver::existingDirRequested);
connect(mCore, &Core::itemSelectionRequested, this, &Driver::itemSelectionRequested);
connect(mCore, &Core::clipboardUpdateRequested, this, &Driver::clipboardUpdateRequested);
connect(mCore, &Core::questionAnswerRequested, this, &Driver::questionAnswerRequested);
Expand Down
1 change: 1 addition & 0 deletions app/src/kernel/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public slots:
void blockingErrorOccurred(QSharedPointer<int> response, const Core::BlockingError& blockingError);
void message(const Message& message);
void saveFileRequested(QSharedPointer<QString> file, const Core::SaveFileRequest& request);
void existingDirRequested(QSharedPointer<QString> dir, const Core::ExistingDirRequest& request);
void itemSelectionRequested(QSharedPointer<QString> item, const Core::ItemSelectionRequest& request);
void clipboardUpdateRequested(const QString& text);
void questionAnswerRequested(QSharedPointer<bool> response, const QString& question);
Expand Down

0 comments on commit 8448e2e

Please sign in to comment.