From 9166bd9c5bf02484bd7486374e508ca304111f5a Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 6 Jul 2019 18:50:28 -0400 Subject: added new Shortcut class, moved stuff that was in MainWindow into it added more error handling and logging, some was missing removed some redundancy of setting the menu icons for add/remove, they're all set when clicking the button anyway --- src/shared/util.h | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'src/shared/util.h') diff --git a/src/shared/util.h b/src/shared/util.h index 4df1d13c..a40fa201 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -29,6 +29,8 @@ along with Mod Organizer. If not, see . #include +class Executable; + namespace MOShared { /// Test if a file (or directory) by the specified name exists @@ -52,6 +54,100 @@ bool CaseInsensitiveEqual(const std::wstring &lhs, const std::wstring &rhs); namespace env { +// an application shortcut that can be either on the desktop or the start menu +// +class Shortcut +{ +public: + // location of a shortcut + // + enum Locations + { + None = 0, + + // on the desktop + Desktop, + + // in the start menu + StartMenu + }; + + + // empty shortcut + // + Shortcut(); + + // shortcut from an executable + // + explicit Shortcut(const Executable& exe); + + // sets the name of the shortcut, shown on icons and start menu entries + // + Shortcut& name(const QString& s); + + // the program to start + // + Shortcut& target(const QString& s); + + // arguments to pass + // + Shortcut& arguments(const QString& s); + + // shows in the status bar of explorer, for example + // + Shortcut& description(const QString& s); + + // path to a binary that contains the icon and its index + // + Shortcut& icon(const QString& s, int index=0); + + // "start in" option for this shortcut + // + Shortcut& workingDirectory(const QString& s); + + + // returns whether this shortcut already exists at the given location; this + // does not check whether the shortcut parameters are different, it merely if + // the .lnk file exists + // + bool exists(Locations loc) const; + + // calls remove() if exists(), or add() + // + bool toggle(Locations loc); + + // adds the shortcut to the given location + // + bool add(Locations loc); + + // removes the shortcut from the given location + // + bool remove(Locations loc); + +private: + QString m_name; + QString m_target; + QString m_arguments; + QString m_description; + QString m_icon; + int m_iconIndex; + QString m_workingDirectory; + + + // returns the path where the shortcut file should be saved + // + QString shortcutPath(Locations loc) const; + + // returns the directory where the shortcut file should be saved + // + QString shortcutDirectory(Locations loc) const; + + // returns the filename of the shortcut file that should be used when saving + // + QString shortcutFilename() const; +}; + + // represents one module // class Module -- cgit v1.3.1 From f7c844fcf7684cbde0a3290b1950c52f88236be3 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 6 Jul 2019 19:23:52 -0400 Subject: put the error message in the ShellLinkException instead added more debug logging when creating and deleting shortcuts --- src/shared/util.cpp | 111 ++++++++++++++++++++++++++++++++++++++-------------- src/shared/util.h | 13 ++++++ 2 files changed, 95 insertions(+), 29 deletions(-) (limited to 'src/shared/util.h') diff --git a/src/shared/util.cpp b/src/shared/util.cpp index 2bf1dba6..17df3b92 100644 --- a/src/shared/util.cpp +++ b/src/shared/util.cpp @@ -314,7 +314,22 @@ template using COMPtr = std::unique_ptr; -class ShellLinkException {}; +class ShellLinkException +{ +public: + ShellLinkException(QString s) + : m_what(std::move(s)) + { + } + + const QString& what() const + { + return m_what; + } + +private: + QString m_what; +}; // just a wrapper around IShellLink operations that throws ShellLinkException // on errors @@ -331,8 +346,7 @@ public: void setPath(const QString& s) { if (s.isEmpty()) { - critical() << "path cannot be empty"; - throw ShellLinkException(); + throw ShellLinkException("path cannot be empty"); } const auto r = m_link->SetPath(s.toStdWString().c_str()); @@ -385,16 +399,12 @@ private: COMPtr m_link; COMPtr m_file; - QDebug critical() - { - return qCritical().noquote().nospace() << "system shortcut: "; - } - void throwOnFail(HRESULT r, const QString& s) { if (FAILED(r)) { - critical() << s << ", " << formatSystemMessageQ(r); - throw ShellLinkException(); + throw ShellLinkException(QString("%1, %2") + .arg(s) + .arg(formatSystemMessageQ(r))); } } @@ -409,8 +419,7 @@ private: throwOnFail(r, "failed to create IShellLink instance"); if (!link) { - critical() << "creating IShellLink worked, but pointer is null"; - throw ShellLinkException(); + throw ShellLinkException("creating IShellLink worked, pointer is null"); } return COMPtr(static_cast(link)); @@ -424,8 +433,7 @@ private: throwOnFail(r, "failed to get IPersistFile interface"); if (!file) { - critical() << "querying IPersistFile worked, but pointer is null"; - throw ShellLinkException(); + throw ShellLinkException("querying IPersistFile worked, pointer is null"); } return COMPtr(static_cast(file)); @@ -515,16 +523,27 @@ bool Shortcut::toggle(Locations loc) bool Shortcut::add(Locations loc) { - const auto path = shortcutPath(loc); - if (path.isEmpty()) { + debug() + << "adding shortcut to " << toString(loc) << ":\n" + << " . name: '" << m_name << "'\n" + << " . target: '" << m_target << "'\n" + << " . arguments: '" << m_arguments << "'\n" + << " . description: '" << m_description << "'\n" + << " . icon: '" << m_icon << "' @ " << m_iconIndex << "\n" + << " . working directory: '" << m_workingDirectory << "'"; + + if (m_target.isEmpty()) { + critical() << "target is empty"; return false; } - if (m_target.isEmpty()) { - qCritical() << "system shortcut: target is empty"; + const auto path = shortcutPath(loc); + if (path.isEmpty()) { return false; } + debug() << "shorcut file will be saved at '" << path << "'"; + try { ShellLinkWrapper link; @@ -539,8 +558,9 @@ bool Shortcut::add(Locations loc) return true; } - catch(ShellLinkException&) + catch(ShellLinkException& e) { + critical() << e.what() << "\nshortcut file was not saved"; } return false; @@ -548,21 +568,26 @@ bool Shortcut::add(Locations loc) bool Shortcut::remove(Locations loc) { + debug() << "removing shortcut for '" << m_name << "' from " << toString(loc); + const auto path = shortcutPath(loc); if (path.isEmpty()) { return false; } - if (!QFile::exists(path)) { - qCritical().nospace().noquote() - << "system shortcut: can't remove '" << path << "', file not found"; + debug() << "path to shortcut file is '" << path << "'"; + if (!QFile::exists(path)) { + critical() << "can't remove '" << path << "', file not found"; return false; } - if (!QFile::remove(path)) { - qCritical().nospace().noquote() - << "system shortcut: failed to remove '" << path << "'"; + if (!MOBase::shellDelete({path})) { + const auto e = ::GetLastError(); + + critical() + << "failed to remove '" << path << "', " + << formatSystemMessageQ(e); return false; } @@ -603,13 +628,12 @@ QString Shortcut::shortcutDirectory(Locations loc) const case None: default: - qCritical() << "system shortcut: bad location " << loc; - return {}; + critical() << "bad location " << loc; + break; } } catch(std::exception&) { - return {}; } return QDir::toNativeSeparators(dir); @@ -618,13 +642,42 @@ QString Shortcut::shortcutDirectory(Locations loc) const QString Shortcut::shortcutFilename() const { if (m_name.isEmpty()) { - qCritical() << "system shortcut: name is empty"; + critical() << "name is empty"; return {}; } return m_name + ".lnk"; } +QDebug Shortcut::debug() const +{ + return qDebug().noquote().nospace() << "system shortcut: "; +} + +QDebug Shortcut::critical() const +{ + return qCritical().noquote().nospace() << "system shortcut: "; +} + + +QString toString(Shortcut::Locations loc) +{ + switch (loc) + { + case Shortcut::None: + return "none"; + + case Shortcut::Desktop: + return "desktop"; + + case Shortcut::StartMenu: + return "start menu"; + + default: + return QString("? (%1)").arg(static_cast(loc)); + } +} + class WMI diff --git a/src/shared/util.h b/src/shared/util.h index a40fa201..c4a2ed7d 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -133,6 +133,14 @@ private: int m_iconIndex; QString m_workingDirectory; + // returns a qCritical() logger with a prefix already logged + // + QDebug critical() const; + + // returns a qDebug() logger with a prefix already logged + // + QDebug debug() const; + // returns the path where the shortcut file should be saved // @@ -148,6 +156,11 @@ private: }; +// returns a string representation of the given location +// +QString toString(Shortcut::Locations loc); + + // represents one module // class Module -- cgit v1.3.1