From 41d0f91a2592d8cc4ff3cba591bc67e3c736386f Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Thu, 14 Nov 2024 17:35:17 -0500 Subject: [PATCH] Add console frontend executeable --- CMakeLists.txt | 11 +- app/console/CMakeLists.txt | 29 +++ app/console/res/app/CLIFp.ico | Bin 29371 -> 0 bytes app/console/src/frontend/console.cpp | 224 +++++++++++++++++++ app/console/src/frontend/console.h | 71 ++++++ app/console/src/frontend/input.cpp | 28 +++ app/console/src/frontend/input.h | 36 +++ app/console/src/frontend/progressprinter.cpp | 97 ++++++++ app/console/src/frontend/progressprinter.h | 43 ++++ app/console/src/main.cpp | 13 ++ app/gui/CMakeLists.txt | 6 +- app/gui/src/frontend/gui.cpp | 4 +- app/gui/src/frontend/gui.h | 14 +- lib/backend/include/kernel/directive.h | 11 +- lib/backend/src/kernel/core.h | 2 +- lib/backend/src/task/t-download.cpp | 4 +- lib/backend/src/task/t-mount.cpp | 6 +- 17 files changed, 572 insertions(+), 27 deletions(-) delete mode 100644 app/console/res/app/CLIFp.ico create mode 100644 app/console/src/frontend/console.cpp create mode 100644 app/console/src/frontend/console.h create mode 100644 app/console/src/frontend/input.cpp create mode 100644 app/console/src/frontend/input.h create mode 100644 app/console/src/frontend/progressprinter.cpp create mode 100644 app/console/src/frontend/progressprinter.h create mode 100644 app/console/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 645636d..4096dd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ project(CLIFp # Get helper scripts include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake) -fetch_ob_cmake("19d33b5bb1752b50767f78ca3e17796868354ac3") +fetch_ob_cmake("ed633b61c87f34757c5c26da32563543665940b7") # Initialize project according to standard rules include(OB/Project) @@ -77,7 +77,7 @@ endif() include(OB/FetchQx) ob_fetch_qx( - REF "44a5b020784044d130765cddc0d3514bb01180c1" + REF "62f9e486d8a850123d9a4d834509282ad15e3382" COMPONENTS ${CLIFP_QX_COMPONENTS} ) @@ -111,8 +111,10 @@ string(TOLOWER "${BACKEND_ALIAS_NAME}" BACKEND_ALIAS_NAME_LC) set(FRONTEND_FRAMEWORK_TARGET_NAME ${PROJECT_NAMESPACE_LC}_frontend_framework) set(FRONTEND_FRAMEWORK_ALIAS_NAME FrontendFramework) add_subdirectory(lib) -set(APP_GUI_TARGET_NAME ${PROJECT_NAMESPACE_LC}_${PROJECT_NAMESPACE_LC}) -set(APP_GUI_ALIAS_NAME ${PROJECT_NAMESPACE}) +set(APP_GUI_TARGET_NAME ${PROJECT_NAMESPACE_LC}_frontend_gui) +set(APP_GUI_ALIAS_NAME FrontendGui) +set(APP_CONSOLE_TARGET_NAME ${PROJECT_NAMESPACE_LC}_frontend_console) +set(APP_CONSOLE_ALIAS_NAME FrontendConsole) add_subdirectory(app) #--------------------Package Config----------------------- @@ -122,6 +124,7 @@ ob_standard_project_package_config( CONFIG STANDARD TARGET_CONFIGS TARGET "${PROJECT_NAMESPACE}::${APP_GUI_ALIAS_NAME}" COMPONENT "${APP_GUI_ALIAS_NAME}" DEFAULT + TARGET "${PROJECT_NAMESPACE}::${APP_CONSOLE_ALIAS_NAME}" COMPONENT "${APP_CONSOLE_ALIAS_NAME}" ) #================= Install ========================== diff --git a/app/console/CMakeLists.txt b/app/console/CMakeLists.txt index e69de29..41d99f7 100644 --- a/app/console/CMakeLists.txt +++ b/app/console/CMakeLists.txt @@ -0,0 +1,29 @@ +#================= Common Build ========================= + +set(PRETTY_NAME "${PROJECT_NAME}-C") + +# Add via ob standard executable +include(OB/Executable) +ob_add_standard_executable(${APP_CONSOLE_TARGET_NAME} + ALIAS "${APP_CONSOLE_ALIAS_NAME}" + OUTPUT_NAME "${PRETTY_NAME}" + SOURCE + frontend/console.h + frontend/console.cpp + frontend/input.h + frontend/input.cpp + frontend/progressprinter.h + frontend/progressprinter.cpp + main.cpp + LINKS + PRIVATE + CLIFp::FrontendFramework + magic_enum::magic_enum + CONFIG STANDARD +) + +# Add exe details on Windows +if(CMAKE_SYSTEM_NAME STREQUAL Windows) + include(FrontendFramework) + set_clip_exe_details(${APP_CONSOLE_TARGET_NAME} ${PRETTY_NAME}) +endif() diff --git a/app/console/res/app/CLIFp.ico b/app/console/res/app/CLIFp.ico deleted file mode 100644 index 0e3d89e5c2b988c7ebb232227c09c76c88e021a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29371 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 diff --git a/app/console/src/frontend/console.cpp b/app/console/src/frontend/console.cpp new file mode 100644 index 0000000..8a44e1d --- /dev/null +++ b/app/console/src/frontend/console.cpp @@ -0,0 +1,224 @@ +// Unit Include +#include "console.h" + +// Qt Includes +#include +#include +#include + +// Qx Includes +#include +#include + +// Magic enum +#include "magic_enum.hpp" + +#define ENUM_NAME(eenum) QString(magic_enum::enum_name(eenum).data()) + +/* NOTE: Unlike the GUI frontend, this one blocks fully when the user is prompted for input because + * the standard cin read methods block and of course don't spin the event loop internally like + * QMessageBox, QFileDialog, etc. do. Technically, this isn't a problem because whenever the driver + * thread prompts for input it also blocks, but if that ever changes then console input will have + * to be handled asynchronously using a technique like this: https://github.com/juangburgos/QConsoleListener + */ + +//=============================================================================================================== +// FrontendConsole +//=============================================================================================================== + +//-Constructor------------------------------------------------------------------------------------------------------- +//Public: +FrontendConsole::FrontendConsole(QGuiApplication* app) : + FrontendFramework(app) +{ + // We don't make windows in this frontend, but just to be safe + app->setQuitOnLastWindowClosed(false); +} + +//-Class Functions-------------------------------------------------------------------------------------------------------- +//Private: + +//-Instance Functions------------------------------------------------------------------------------------------------------ +//Private: +void FrontendConsole::handleDirective(const DMessage& d) +{ + /* TODO: Probably should add a heading like "Notice)" or something. + * + * TODO: Look into escape codes (console support per platform varies) + * to replicate bold/italic/underlined. + * + * Also, might want to replace the html tags with some kind of more + * complex message object or just some other way to better communicate + * the message in a frontend agnostic matter, so we could even have something + * like Underlined Text for GUI and: + * + * Underlined Text + * --------------- + * + * for console. + */ + + // Replace possible HTML tags/entities with something more sensible for console + QString txt = Qx::String::mapArg(d.text, { + {u""_s, u""_s}, + {u""_s, u""_s}, + {u""_s, u"*"_s}, + {u""_s, u"*"_s}, + {u""_s, u"`"_s}, + {u""_s, u"`"_s}, + {u"
"_s, u"\n"_s}, + {u"<"_s, u"<"_s}, + {u">"_s, u">"_s}, + {u" "_s, u" "_s}, + }); + print(txt); +} + +void FrontendConsole::handleDirective(const DError& d) { print(d.error, Stream::Error);} + +void FrontendConsole::handleDirective(const DProcedureStart& d) +{ + print(d.label); + mProgressPrinter.start(d.label); +} + +void FrontendConsole::handleDirective(const DProcedureStop& d) +{ + Q_UNUSED(d); + mProgressPrinter.finish(); +} + +void FrontendConsole::handleDirective(const DProcedureProgress& d) { mProgressPrinter.setValue(d.current); } +void FrontendConsole::handleDirective(const DProcedureScale& d) { mProgressPrinter.setMaximum(d.max); } +void FrontendConsole::handleDirective(const DStatusUpdate& d) { print(d.heading + u"] "_s + d.message);} + +// Sync directive handlers +void FrontendConsole::handleDirective(const DBlockingMessage& d) +{ + // TODO: Probably should add a heading like "Notice)" or something + print(d.text); +} + +// Request directive handlers +void FrontendConsole::handleDirective(const DBlockingError& d, DBlockingError::Choice* response) +{ + Q_ASSERT(d.choices != DBlockingError::Choice::NoChoice); + bool validDef = d.choices.testFlag(d.defaultChoice); + + // Print Error + print(d.error, Stream::Error); + print(); + + // Print Prompt + print(validDef ? INSTR_CHOICE_SEL : INSTR_CHOICE_SEL_NO_DEF); + + // Print Choices + QList choices; + for(auto c : magic_enum::enum_values()) + { + if(!d.choices.testFlag(c)) + continue; + + choices.append(c); + QString cStr = TEMPL_OPTION.arg(choices.count()).arg(ENUM_NAME(c)); + if(validDef && c == d.defaultChoice) + cStr += '*'; + print(cStr); + } + + // Get selection + auto sel = prompt([c = choices.count()](int i){ return i > 0 && i <= c; }); + *response = sel ? choices[*sel - 1] : d.defaultChoice; +} + +void FrontendConsole::handleDirective(const DSaveFilename& d, QString* response) +{ + // Print Prompt + QString cap = d.caption + (!d.extFilterDesc.isEmpty() ? u" ("_s + d.extFilterDesc + u")"_s : QString()); + QString inst = INSTR_FILE_ENTER.arg(Qx::String::join(d.extFilter, u" "_s, u"*."_s)); + print(cap); + print(inst); + + // Get selection + auto path = prompt([ef = d.extFilter](const QString& i){ + QFileInfo fi(i); + return ef.contains(fi.suffix()); + }); + *response = path ? *path : QString(); +} + +void FrontendConsole::handleDirective(const DExistingDir& d, QString* response) +{ + // Print Prompt + print(d.caption); + print(INSTR_DIR_ENTER_EXIST); + + // Get selection + auto path = prompt([](const QString& i){ + QDir dir(i); + return dir.exists(); + }); + *response = path ? *path: QString(); +} + +void FrontendConsole::handleDirective(const DItemSelection& d, QString* response) +{ + Q_ASSERT(!d.items.isEmpty()); + + // Print Prompt + print(d.caption); + print(d.label); + print(INSTR_ITEM_SEL); + + // Print Choices + for(auto i = 0; const QString& itm : d.items) + print(TEMPL_OPTION.arg(++i).arg(itm)); + + // Get selection + auto sel = prompt([c = d.items.count()](int i){ return i > 0 && i <= c; }); + *response = sel ? d.items[*sel - 1] : d.items.first(); +} + +void FrontendConsole::handleDirective(const DYesOrNo& d, bool* response) +{ + // Print Prompt + print(d.question); + print(INSTR_YES_OR_NO); + + // Get selection + static QSet yes{u"yes"_s, u"y"_s}; + static QSet no{u"no"_s, u"n"_s}; + auto answer = prompt([](const QString& i){ + QString lc = i.toLower(); + return yes.contains(lc) || no.contains(lc); + }); + *response = answer && yes.contains(answer->toLower()); +} + +template + requires Qx::defines_left_shift_for +void FrontendConsole::print(const P& p, Stream s) +{ + auto& cs = s == Stream::Out ? Qx::cout : Qx::cerr; + + mProgressPrinter.checkAndResetEndlCtrl(); + cs << p << Qt::endl; +} + +template + requires Input::Validator +std::optional FrontendConsole::prompt(V v) +{ + forever + { + QString str = Qx::cin.readLine(); + if(str.isEmpty()) + return std::nullopt; + + R convIn; + if(Input::to(str, convIn) && v(convIn)) + return convIn; + + print(INSTR_TRY_AGAIN); + } +} diff --git a/app/console/src/frontend/console.h b/app/console/src/frontend/console.h new file mode 100644 index 0000000..2d275b2 --- /dev/null +++ b/app/console/src/frontend/console.h @@ -0,0 +1,71 @@ +#ifndef CONSOLE_H +#define CONSOLE_H + +// Qx Includes +#include + +// Project Includes +#include "frontend/framework.h" +#include "frontend/progressprinter.h" +#include "input.h" + +class FrontendConsole final : public FrontendFramework +{ +//-Class Enums-------------------------------------------------------------------------------------------------------- +private: + enum class Stream { Out, Error }; + +//-Class Variables-------------------------------------------------------------------------------------------------------- +private: + // Instructions + static inline const QString INSTR_TRY_AGAIN = u"Invalid response, try again..."_s; + static inline const QString INSTR_CHOICE_SEL = u"Select Action (or ENTER for *):"_s; + static inline const QString INSTR_CHOICE_SEL_NO_DEF = u"Select Action:"_s; + static inline const QString INSTR_FILE_ENTER = u"File Path (or ENTER to cancel):"_s; + static inline const QString INSTR_DIR_ENTER_EXIST = u"Existing Directory (or ENTER to cancel):"_s; + static inline const QString INSTR_YES_OR_NO = u"Yes or No/ENTER:"_s; + static inline const QString INSTR_ITEM_SEL = u"Select Item (or ENTER for 1):"_s; + + // Templates + static inline const QString TEMPL_OPTION = u"%1) %2"_s; + +//-Instance Variables---------------------------------------------------------------------------------------------- +private: + ProgressPrinter mProgressPrinter; + +//-Constructor------------------------------------------------------------------------------------------------------- +public: + explicit FrontendConsole(QGuiApplication* app); + +//-Instance Functions------------------------------------------------------------------------------------------------------ +private: + // Async directive handlers + void handleDirective(const DMessage& d) override; + void handleDirective(const DError& d) override; + void handleDirective(const DProcedureStart& d) override; + void handleDirective(const DProcedureStop& d) override; + void handleDirective(const DProcedureProgress& d) override; + void handleDirective(const DProcedureScale& d) override; + void handleDirective(const DStatusUpdate& d) override; + + // Sync directive handlers + void handleDirective(const DBlockingMessage& d) override; + + // Request directive handlers + void handleDirective(const DBlockingError& d, DBlockingError::Choice* response) override; + void handleDirective(const DSaveFilename& d, QString* response) override; + void handleDirective(const DExistingDir& d, QString* response) override; + void handleDirective(const DItemSelection& d, QString* response) override; + void handleDirective(const DYesOrNo& d, bool* response) override; + + // Derived + template + requires Qx::defines_left_shift_for + void print(const P& p = QString(), Stream s = Stream::Out); + + template + requires Input::Validator + std::optional prompt(V v); +}; + +#endif // CONSOLE_H diff --git a/app/console/src/frontend/input.cpp b/app/console/src/frontend/input.cpp new file mode 100644 index 0000000..b6f26fc --- /dev/null +++ b/app/console/src/frontend/input.cpp @@ -0,0 +1,28 @@ +// Unit Include +#include "input.h" + +namespace +{ + +template +bool numericConversion(const QString& s, MF&& mf, T& out) +{ + bool ok; + if constexpr(std::integral) + out = std::invoke(std::forward(mf), s, &ok, 10); + else + out = std::invoke(std::forward(mf), s, &ok); + return ok; +} + +} + +namespace Input +{ + +//-Functions------------------------------------------------------------------------------------------------------ +bool to(const QString& in, QString& out) { out = in; return true; } +bool to(const QString& in, int& out) { return numericConversion(in, &QString::toInt, out); } +bool to(const QString& in, double& out) { return numericConversion(in, &QString::toDouble, out); } + +} diff --git a/app/console/src/frontend/input.h b/app/console/src/frontend/input.h new file mode 100644 index 0000000..62f5903 --- /dev/null +++ b/app/console/src/frontend/input.h @@ -0,0 +1,36 @@ +#ifndef INPUT_H +#define INPUT_H + +// Qt Includes +#include + +/* Technically we could use QVariant or QTextStream::operator>>() to facilitate + * parsing an entire line as a given type, but both of those methods have + * caveats that IMO make this explicit, albeit annoying, conversion setup + * better. + * + * QVariant/QMetaType - Cannot check that QString can be converted to T at compile + * time, so a runtime assert would be needed, a failure of which might not be discovered + * for a while. + * + * Qx::cin >> - will accept things like "123 non-number-text" and stops once a space is hit + * so that case would have to be checked for and in all cases we'd have to manually read + * until '\n' is hit + */ + +namespace Input +{ + +bool to(const QString& in, QString& out); +bool to(const QString& in, int& out); +bool to(const QString& in, double& out); + +template +concept Validator = std::predicate; + +template +concept Type = requires(T t){ to({}, t); }; + +} + +#endif // INPUT_H diff --git a/app/console/src/frontend/progressprinter.cpp b/app/console/src/frontend/progressprinter.cpp new file mode 100644 index 0000000..9d2adeb --- /dev/null +++ b/app/console/src/frontend/progressprinter.cpp @@ -0,0 +1,97 @@ +// Unit Include +#include "progressprinter.h" + +using namespace Qt::StringLiterals; + +//=============================================================================================================== +// ProgressPrinter +//=============================================================================================================== + +//-Constructor------------------------------------------------------------------------------------------------------- +//Public: +ProgressPrinter::ProgressPrinter() { reset(); } + +//-Instance Functions------------------------------------------------------------------------------------------------------ +//Private: +void ProgressPrinter::rescale() +{ + // Check for busy state special case + if(mCurrent == 0 && mMax == 0) + { + Qx::cout << u"..."_s << Qt::endl; + return; + } + + qint64 scaled = (100.0 * mCurrent)/mMax; + if(scaled != mScaled) + { + mScaled = scaled; + print(); + } +} + +void ProgressPrinter::print() +{ + Qx::cout << '\r' << mScaled << Qt::flush; + mHoldsEndlCtrl = true; +} + +void ProgressPrinter::reset() +{ + mCurrent = 0; + mMax = 100; + mScaled = -1; + mProcedure = {}; + mActive = false; + mHoldsEndlCtrl = false; +} + +//Public: +void ProgressPrinter::start(const QString& procedure) +{ + mProcedure = procedure; + mActive = true; +} + +void ProgressPrinter::finish() +{ + if(!mActive) + return; + + // Maybe have DProcedureStart pass a short name that's unused in GUI (or used as window label) + // so that here can we can print "Short Name: Done" in case there's other messages printed between + checkAndResetEndlCtrl(); + Qx::cout << u"Done"_s << Qt::endl; + reset(); +} + +void ProgressPrinter::setValue(qint64 value) +{ + if(!mActive || mCurrent == value || value > mMax) + return; + mCurrent = value; + rescale(); +} + +void ProgressPrinter::setMaximum(qint64 max) +{ + if(mMax == max) + return; + mMax = max; + if(mCurrent > mMax) + mCurrent = mMax; + + if(mActive) + rescale(); +} + +bool ProgressPrinter::isActive() const { return mActive; } +bool ProgressPrinter::checkAndResetEndlCtrl() +{ + if(!mHoldsEndlCtrl) + return false; + + Qx::cout << Qt::endl; + mHoldsEndlCtrl = false; + return true; +} diff --git a/app/console/src/frontend/progressprinter.h b/app/console/src/frontend/progressprinter.h new file mode 100644 index 0000000..316d597 --- /dev/null +++ b/app/console/src/frontend/progressprinter.h @@ -0,0 +1,43 @@ +#ifndef PROGRESSPRINTER_H +#define PROGRESSPRINTER_H + +// Qt Includes +#include +#include + +// Qx Includes +#include + +class ProgressPrinter +{ +//-Instance Variables---------------------------------------------------------------------------------------------- +private: + qint64 mCurrent; + qint64 mMax; + qint64 mScaled; + + QString mProcedure; // NOTE: Unused + bool mActive; + bool mHoldsEndlCtrl; + +//-Constructor------------------------------------------------------------------------------------------------------- +public: + ProgressPrinter(); + +//-Instance Functions------------------------------------------------------------------------------------------------------ +private: + void rescale(); + void print(); + void reset(); + +public: + void start(const QString& procedure); + void finish(); + + void setValue(qint64 value); + void setMaximum(qint64 max); + bool isActive() const; + bool checkAndResetEndlCtrl(); +}; + +#endif // PROGRESSPRINTER_H diff --git a/app/console/src/main.cpp b/app/console/src/main.cpp new file mode 100644 index 0000000..0ba2e58 --- /dev/null +++ b/app/console/src/main.cpp @@ -0,0 +1,13 @@ +// Qt Includes +#include // Seems odd, but that's just what we need for this + +// Project Includes +#include "frontend/console.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + FrontendConsole frontend(&app); + return frontend.exec(); +} + diff --git a/app/gui/CMakeLists.txt b/app/gui/CMakeLists.txt index d420beb..b39dfd4 100644 --- a/app/gui/CMakeLists.txt +++ b/app/gui/CMakeLists.txt @@ -1,10 +1,12 @@ #================= Common Build ========================= +set(PRETTY_NAME "${PROJECT_NAME}") + # Add via ob standard executable include(OB/Executable) ob_add_standard_executable(${APP_GUI_TARGET_NAME} - NAMESPACE "${PROJECT_NAMESPACE}" ALIAS "${APP_GUI_ALIAS_NAME}" + OUTPUT_NAME "${PROJECT_NAME}" SOURCE frontend/gui.h frontend/gui.cpp @@ -23,5 +25,5 @@ ob_add_standard_executable(${APP_GUI_TARGET_NAME} # Add exe details on Windows if(CMAKE_SYSTEM_NAME STREQUAL Windows) include(FrontendFramework) - set_clip_exe_details(${APP_GUI_TARGET_NAME} ${APP_GUI_ALIAS_NAME}) + set_clip_exe_details(${APP_GUI_TARGET_NAME} ${PRETTY_NAME}) endif() diff --git a/app/gui/src/frontend/gui.cpp b/app/gui/src/frontend/gui.cpp index d620886..a6e94f6 100644 --- a/app/gui/src/frontend/gui.cpp +++ b/app/gui/src/frontend/gui.cpp @@ -9,6 +9,7 @@ // Qx Includes #include +#include // Magic enum #include "magic_enum_utility.hpp" @@ -130,7 +131,8 @@ void FrontendGui::handleDirective(const DBlockingError& d, DBlockingError::Choic void FrontendGui::handleDirective(const DSaveFilename& d, QString* response) { - *response = QFileDialog::getSaveFileName(nullptr, d.caption, d.dir, d.filter, d.selectedFilter); + QString filter = d.extFilterDesc + u" ("_s + Qx::String::join(d.extFilter, u" "_s, u"*."_s) + u")"_s; + *response = QFileDialog::getSaveFileName(nullptr, d.caption, d.dir, filter); } void FrontendGui::handleDirective(const DExistingDir& d, QString* response) diff --git a/app/gui/src/frontend/gui.h b/app/gui/src/frontend/gui.h index fb66221..531c87d 100644 --- a/app/gui/src/frontend/gui.h +++ b/app/gui/src/frontend/gui.h @@ -40,16 +40,16 @@ class FrontendGui final : public FrontendFramework explicit FrontendGui(QApplication* app); //-Class Functions-------------------------------------------------------------------------------------------------------- -//Private: -static QMessageBox::StandardButtons choicesToButtons(DBlockingError::Choices cs); +private: + static QMessageBox::StandardButtons choicesToButtons(DBlockingError::Choices cs); -template - requires Qx::any_of -static QMessageBox* prepareMessageBox(const MessageT& dMsg); + template + requires Qx::any_of + static QMessageBox* prepareMessageBox(const MessageT& dMsg); -static bool windowsAreOpen(); + static bool windowsAreOpen(); -static QIcon& trayExitIconFromResources(); + static QIcon& trayExitIconFromResources(); //-Instance Functions------------------------------------------------------------------------------------------------------ private: diff --git a/lib/backend/include/kernel/directive.h b/lib/backend/include/kernel/directive.h index 255058a..568408f 100644 --- a/lib/backend/include/kernel/directive.h +++ b/lib/backend/include/kernel/directive.h @@ -1,9 +1,6 @@ #ifndef DIRECTIVE_H #define DIRECTIVE_H -// Shared Library Support -#include "clifp_backend_export.h" - // Qt Includes #include @@ -59,12 +56,12 @@ struct DProcedureStop {}; struct DProcedureProgress { - quint64 current; + qint64 current; }; struct DProcedureScale { - quint64 max; + qint64 max; }; struct DClipboardUpdate @@ -128,8 +125,8 @@ struct DSaveFilename { QString caption; QString dir; - QString filter; - QString* selectedFilter = nullptr; + QStringList extFilter; + QString extFilterDesc; using response_type = QString; }; diff --git a/lib/backend/src/kernel/core.h b/lib/backend/src/kernel/core.h index f49af92..e16c866 100644 --- a/lib/backend/src/kernel/core.h +++ b/lib/backend/src/kernel/core.h @@ -170,7 +170,7 @@ class Core : public QObject, public Directorate // Help template static inline const QString HELP_TEMPL = u"Usage:
" - PROJECT_SHORT_NAME "<global options> command <command options>
" + PROJECT_SHORT_NAME " <global options> command <command options>
" "
" "Global Options:%1
" "
" diff --git a/lib/backend/src/task/t-download.cpp b/lib/backend/src/task/t-download.cpp index f5aae9f..444f3e1 100644 --- a/lib/backend/src/task/t-download.cpp +++ b/lib/backend/src/task/t-download.cpp @@ -72,10 +72,10 @@ TDownload::TDownload(Core& core) : logEvent(LOG_EVENT_DOWNLOAD_AUTH.arg(prompt)); }); - connect(&mDownloadManager, &Qx::AsyncDownloadManager::downloadTotalChanged, this, [this](quint64 total){ + connect(&mDownloadManager, &Qx::AsyncDownloadManager::downloadTotalChanged, this, [this](qint64 total){ postDirective(total); }); - connect(&mDownloadManager, &Qx::AsyncDownloadManager::downloadProgress, this, [this](quint64 bytes){ + connect(&mDownloadManager, &Qx::AsyncDownloadManager::downloadProgress, this, [this](qint64 bytes){ postDirective(bytes); }); connect(&mDownloadManager, &Qx::AsyncDownloadManager::finished, this, &TDownload::postDownload); diff --git a/lib/backend/src/task/t-mount.cpp b/lib/backend/src/task/t-mount.cpp index e99a2ad..afced88 100644 --- a/lib/backend/src/task/t-mount.cpp +++ b/lib/backend/src/task/t-mount.cpp @@ -69,8 +69,8 @@ void TMount::perform() postDirective(label); // Update state - postDirective(0u); - postDirective(0u); // Cause busy state + postDirective(0); + postDirective(0); // Cause busy state //-Setup Mounter(s)------------------------------------ @@ -172,7 +172,7 @@ void TMount::postMount(Qx::Error errorStatus) { mMounting = false; - // Reset mounter pointers ('this' will delete them due to parenting so there's no leak) + // Reset mounter pointers ('this' will delete them due to parenting so there's no leak) mMounterProxy = nullptr; mMounterQmp = nullptr; mMounterRouter = nullptr;