Skip to content

Commit

Permalink
Added --quit command line option
Browse files Browse the repository at this point in the history
  • Loading branch information
Vitozz committed Jun 17, 2024
1 parent 0c0ed2e commit ff3283e
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 19 deletions.
5 changes: 5 additions & 0 deletions linux/psi-extra-action1.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@
Exec=psi --choose-profile
Name=Start with another profile
Icon=psi

[Desktop Action QuitApplication]
Exec=psi --quit
Name=Quit the application
Icon=application-exit
11 changes: 11 additions & 0 deletions src/activeprofiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,14 @@ ActiveProfiles *ActiveProfiles::instance()
* \fn void ActiveProfiles::raiseRequested()
* \brief Signal emitted when other Psi instance requested to raise main window.
*/

/**
* \fn bool ActiveProfiles::quit(const QString &profile) const
* \brief Closes the active Psi application instance running \a profile.
* If \a profile is empty, other running instance is selected.
*/

/**
* \fn void ActiveProfiles::quitRequested()
* \brief Signal emitted when other Psi instance requested to quit application.
*/
2 changes: 2 additions & 0 deletions src/activeprofiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class ActiveProfiles : public QObject {
bool setStatus(const QString &profile, const QString &status, const QString &message) const;
bool openUri(const QString &profile, const QString &uri) const;
bool raise(const QString &profile, bool withUI) const;
bool quit(const QString &profile) const;

~ActiveProfiles();

Expand All @@ -48,6 +49,7 @@ class ActiveProfiles : public QObject {
void setStatusRequested(const QString &status, const QString &message);
void openUriRequested(const QString &uri);
void raiseRequested();
void quitRequested();

protected:
static ActiveProfiles *instance_;
Expand Down
6 changes: 6 additions & 0 deletions src/activeprofiles_dbus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,9 @@ bool ActiveProfiles::raise(const QString &profile, bool withUI) const
}
return rmsg.type() == QDBusMessage::ReplyMessage;
}

bool ActiveProfiles::quit(const QString &profile) const
{
QDBusInterface(d->dbusName(profile), "/Main", PSIDBUSMAINIF).call(QDBus::NoBlock, "quit");
return true;
}
6 changes: 6 additions & 0 deletions src/activeprofiles_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,9 @@ bool ActiveProfiles::raise(const QString &profile, bool withUI) const
Q_UNUSED(withUI);
return true;
}

bool ActiveProfiles::quit(const QString &profile) const
{
Q_UNUSED(profile);
return true;
}
26 changes: 17 additions & 9 deletions src/activeprofiles_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,20 @@ bool ActiveProfiles::Private::nativeEvent(const QByteArray &eventType, void *mes
}

if (list.count() > 1) {
if (list[0] == "openUri") {
if (list[0] == QStringLiteral("openUri")) {
emit ap->openUriRequested(list.value(1));
*result = TRUE;
} else if (list[0] == "setStatus") {
} else if (list[0] == QStringLiteral("setStatus")) {
emit ap->setStatusRequested(list.value(1), list.value(2));
*result = TRUE;
} else if (list[0] == "recvNextEvent") {
}
} else if (list.count() == 1) {
if (list[0] == QStringLiteral("recvNextEvent")) {
emit ap->recvNextEventRequested();
*result = TRUE;
} else if (list[0] == QStringLiteral("quit")) {
emit ap->quitRequested();
*result = TRUE;
}
}
}
Expand Down Expand Up @@ -324,21 +329,24 @@ bool ActiveProfiles::raise(const QString &profile, bool withUI) const

bool ActiveProfiles::openUri(const QString &profile, const QString &uri) const
{
QStringList list;
list << "openUri" << uri;
QStringList list { QStringLiteral("openUri"), uri };
return d->sendStringList(profile.isEmpty() ? d->pickProfile() : profile, list);
}

bool ActiveProfiles::recvNextEvent(const QString &profile) const
{
QStringList list;
list << "recvNextEvent";
QStringList list { QStringLiteral("recvNextEvent") };
return d->sendStringList(profile.isEmpty() ? d->pickProfile() : profile, list);
}

bool ActiveProfiles::setStatus(const QString &profile, const QString &status, const QString &message) const
{
QStringList list;
list << "setStatus" << status << message;
QStringList list { QStringLiteral("setStatus"), status, message };
return d->sendStringList(profile.isEmpty() ? d->pickProfile() : profile, list);
}

bool ActiveProfiles::quit(const QString &profile) const
{
QStringList list { QStringLiteral("quit") };
return d->sendStringList(profile.isEmpty() ? d->pickProfile() : profile, list);
}
9 changes: 6 additions & 3 deletions src/dbus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public Q_SLOTS:
void sleep();
void wake();
void recvNextEvent();
void quit();
/*Q_SIGNALS:
void psi_pong();
*/
Expand All @@ -39,15 +40,15 @@ PsiConAdapter::PsiConAdapter(PsiCon *psicon_) : QDBusAbstractAdaptor(psicon_) {

PsiConAdapter::~PsiConAdapter() { }

void PsiConAdapter::openURI(QString uri) { emit ActiveProfiles::instance() -> openUriRequested(uri); }
void PsiConAdapter::openURI(QString uri) { emit ActiveProfiles::instance()->openUriRequested(uri); }

void PsiConAdapter::setStatus(QString status, QString message)
{
emit ActiveProfiles::instance() -> setStatusRequested(status, message);
emit ActiveProfiles::instance()->setStatusRequested(status, message);
}

// FIXME libguniqueapp uses activate
void PsiConAdapter::raise() { emit ActiveProfiles::instance() -> raiseRequested(); }
void PsiConAdapter::raise() { emit ActiveProfiles::instance()->raiseRequested(); }

void PsiConAdapter::sleep() { psicon->doSleep(); }

Expand All @@ -61,4 +62,6 @@ void addPsiConAdapter(PsiCon *psicon)
QDBusConnection::sessionBus().registerObject("/Main", psicon);
}

void PsiConAdapter::quit() { emit ActiveProfiles::instance()->quitRequested(); }

#include "dbus.moc"
8 changes: 6 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ bool PsiMain::useActiveInstance()
ActiveProfiles::instance()->raise(cmdline.value("profile"), true);
}

if (cmdline.contains("quit")) {
ActiveProfiles::instance()->quit(cmdline.value("profile"));
}

return true;
} else
return cmdline.contains("remote");
Expand Down Expand Up @@ -282,11 +286,11 @@ void PsiMain::sessionStart()
connect(pcon, SIGNAL(quit(int)), SLOT(sessionQuit(int)));

if (cmdline.contains("uri")) {
emit ActiveProfiles::instance() -> openUriRequested(cmdline.value("uri"));
emit ActiveProfiles::instance()->openUriRequested(cmdline.value("uri"));
cmdline.remove("uri");
}
if (cmdline.contains("status") || cmdline.contains("status-message")) {
emit ActiveProfiles::instance() -> setStatusRequested(cmdline.value("status"), cmdline.value("status-message"));
emit ActiveProfiles::instance()->setStatusRequested(cmdline.value("status"), cmdline.value("status-message"));
cmdline.remove("status");
cmdline.remove("status-message");
}
Expand Down
2 changes: 2 additions & 0 deletions src/psicli.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class PsiCli : public SimpleCli {
tr("Use software widgets rendering. In some cases default hardware rendering may lead to graphical "
"glitches and crashes. This option may help."));

defineSwitch("quit", tr("Quit the application"));

defineSwitch("help", tr("Show this help message and exit."));
defineAlias("h", "help");
defineAlias("?", "help");
Expand Down
1 change: 1 addition & 0 deletions src/psicon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ bool PsiCon::init()
SLOT(setStatusFromCommandline(const QString &, const QString &)));
connect(ActiveProfiles::instance(), SIGNAL(openUriRequested(const QString &)), SLOT(openUri(const QString &)));
connect(ActiveProfiles::instance(), SIGNAL(raiseRequested()), SLOT(raiseMainwin()));
connect(ActiveProfiles::instance(), SIGNAL(quitRequested()), SLOT(closeProgram()));

DesktopUtil::setUrlHandler("xmpp", this, "openUri");
DesktopUtil::setUrlHandler("x-psi-atstyle", this, "openAtStyleUri");
Expand Down
5 changes: 4 additions & 1 deletion src/widgets/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ set(HEADERS
stretchwidget.h
)

if(USE_DBUS OR WIN32)
if(USE_TASKBARNOTIFIER)
list(APPEND SOURCES taskbarnotifier.cpp)
list(APPEND HEADERS taskbarnotifier.h)
if(WIN32 AND (${QT_DEFAULT_MAJOR_VERSION} VERSION_LESS "6"))
Expand Down Expand Up @@ -91,6 +91,9 @@ endif()

qt_wrap_ui(UI_FORMS ${FORMS})
add_library(widgets STATIC ${SOURCES} ${HEADERS} ${UI_FORMS})
if(WIN32)
target_link_libraries(widgets shlwapi)
endif()
target_link_libraries(widgets ${QT_LIBRARIES} ${iris_LIB} tools)
target_include_directories(widgets PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR})
if(IS_WEBKIT OR IS_WEBENGINE)
Expand Down
92 changes: 88 additions & 4 deletions src/widgets/taskbarnotifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@
#endif

#ifdef Q_OS_WIN
#include <QApplication>

#include "applicationinfo.h"
#include "psiiconset.h"

#include <propkey.h>
#include <propvarutil.h>
#include <shobjidl.h>
#include <windows.h>

Expand Down Expand Up @@ -73,13 +80,16 @@ class TaskBarNotifier::Private {
#endif
#ifdef Q_OS_WIN
void setFlashWindow(bool enabled);
void addJumpListItem();
#endif
private:
#ifdef Q_OS_WIN
void setTaskBarIcon(const HICON &icon = {});
HICON makeIconCaption(const QString &number) const;
HICON getHICONfromQImage(const QImage &image) const;
void doFlashTaskbarIcon();
void setTaskBarIcon(const HICON &icon = {});
HICON makeIconCaption(const QString &number) const;
HICON getHICONfromQImage(const QImage &image) const;
void doFlashTaskbarIcon();
IShellLink *createShellLink(const QString &path, const QString &name, const QString &tooltip, const QString &args,
const QString &icon);
#else
QIcon setImageCountCaption(uint count = 0);
#ifdef USE_DBUS
Expand Down Expand Up @@ -300,12 +310,86 @@ void TaskBarNotifier::Private::doFlashTaskbarIcon()
fi.dwTimeout = 0;
FlashWindowEx(&fi);
}

void TaskBarNotifier::Private::addJumpListItem()
{
// Create an object collection
IObjectCollection *pCollection = nullptr;
if (SUCCEEDED(CoCreateInstance(CLSID_EnumerableObjectCollection, nullptr, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pCollection)))) {
// Create shell link object
auto path = qApp->applicationFilePath();
auto nameString = QString("Quit %1 application").arg(qApp->applicationName());
auto cachedIconFile
= ApplicationInfo::homeDir(ApplicationInfo::CacheLocation) + QStringLiteral("/quit_icon.ico");
auto pixmap = PsiIconset::instance()
->system()
.icon("psi/quit")
->pixmap(QSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)) * devicePixelRatio_);
pixmap.save(cachedIconFile, "ICO");
IShellLink *quitShellLink
= createShellLink(path, nameString, nameString, QStringLiteral("--quit"), cachedIconFile);
if (quitShellLink != nullptr) {
pCollection->AddObject(quitShellLink);
quitShellLink->Release();
// Create custom Jump list
ICustomDestinationList *destinationList = nullptr;
if (SUCCEEDED(CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER,
IID_ICustomDestinationList,
reinterpret_cast<void **>(&(destinationList))))) {
IObjectArray *objectArray = nullptr;
UINT cMaxSlots;
// Init Jump list and add items to it
if (SUCCEEDED(destinationList->BeginList(&cMaxSlots, IID_IObjectArray,
reinterpret_cast<void **>(&(objectArray))))) {
destinationList->AddUserTasks(pCollection);
destinationList->CommitList();
objectArray->Release();
}
destinationList->Release();
}
}
pCollection->Release();
}
}

IShellLink *TaskBarNotifier::Private::createShellLink(const QString &path, const QString &name, const QString &tooltip,
const QString &args, const QString &icon)
{
IShellLink *pShellLink = nullptr;
if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pShellLink)))) {
auto wPath = reinterpret_cast<const wchar_t *>(path.utf16());
auto wName = reinterpret_cast<const wchar_t *>(name.utf16());
auto wDesc = reinterpret_cast<const wchar_t *>(tooltip.utf16());
auto wArgs = reinterpret_cast<const wchar_t *>(args.utf16());
auto wIcon = reinterpret_cast<const wchar_t *>(icon.utf16());
pShellLink->SetPath(wPath);
pShellLink->SetArguments(wArgs);
pShellLink->SetDescription(wDesc);
pShellLink->SetIconLocation(wIcon, 0);
// Change shell link object name
IPropertyStore *propertyStore = nullptr;
if (SUCCEEDED(pShellLink->QueryInterface(IID_IPropertyStore, (LPVOID *)&propertyStore))) {
PROPVARIANT pv;
if (SUCCEEDED(InitPropVariantFromString(wName, &pv))) {
if (SUCCEEDED(propertyStore->SetValue(PKEY_Title, pv)))
propertyStore->Commit();
PropVariantClear(&pv);
}
propertyStore->Release();
}
}
return pShellLink;
}
#endif

TaskBarNotifier::TaskBarNotifier(QWidget *parent)
{
d = std::make_unique<Private>(Private());
d->setParent(parent);
#ifdef Q_OS_WIN
d->addJumpListItem();
#endif
}

TaskBarNotifier::~TaskBarNotifier() = default;
Expand Down

0 comments on commit ff3283e

Please sign in to comment.