File indexing completed on 2024-05-05 04:45:39
0001 /* 0002 SnoreNotify is a Notification Framework based on Qt 0003 Copyright (C) 2014-2015 Hannah von Reth <vonreth@kde.org> 0004 0005 SnoreNotify is free software: you can redistribute it and/or modify 0006 it under the terms of the GNU Lesser General Public License as published by 0007 the Free Software Foundation, either version 3 of the License, or 0008 (at your option) any later version. 0009 0010 SnoreNotify is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 GNU Lesser General Public License for more details. 0014 0015 You should have received a copy of the GNU Lesser General Public License 0016 along with SnoreNotify. If not, see <http://www.gnu.org/licenses/>. 0017 */ 0018 0019 #include <libsnore/snore.h> 0020 #include <libsnore/notification/notification.h> 0021 #include <libsnore/version.h> 0022 #include <libsnore/utils.h> 0023 #include <libsnore/snore_static_plugins.h> 0024 0025 0026 #include <QGuiApplication> 0027 #include <QCommandLineParser> 0028 0029 #include <iostream> 0030 0031 #ifdef Q_OS_WIN 0032 #include <windows.h> 0033 #include <windowsx.h> 0034 #include <shellapi.h> 0035 #include <winuser.h> 0036 #endif 0037 0038 using namespace Snore; 0039 using namespace std; 0040 0041 void bringToFront(const QString &pid) 0042 { 0043 qCDebug(SNORE) << pid; 0044 #ifdef Q_OS_WIN 0045 auto findWindowForPid = [](ulong pid) { 0046 // based on http://stackoverflow.com/a/21767578 0047 pair<ulong, HWND> data = make_pair(pid, (HWND)0); 0048 ::EnumWindows((WNDENUMPROC)static_cast<BOOL(*)(HWND, LPARAM)>([](HWND handle, LPARAM lParam) -> BOOL { 0049 auto isMainWindow = [](HWND handle) 0050 { 0051 return ::GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle); 0052 }; 0053 pair<ulong, HWND> &data = *(pair<ulong, HWND> *)lParam; 0054 ulong process_id = 0; 0055 ::GetWindowThreadProcessId(handle, &process_id); 0056 if (data.first != process_id || !isMainWindow(handle)) 0057 { 0058 return TRUE; 0059 } 0060 data.second = handle; 0061 return FALSE; 0062 }), (LPARAM)&data); 0063 return data.second; 0064 }; 0065 0066 HWND wid = findWindowForPid(pid.toInt()); 0067 if (wid) { 0068 Utils::bringWindowToFront(wid, true); 0069 } 0070 #endif 0071 } 0072 0073 int main(int argc, char *argv[]) 0074 { 0075 QGuiApplication app(argc, argv); 0076 app.setApplicationName(QStringLiteral("snoresend")); 0077 app.setOrganizationName(QStringLiteral("Snorenotify")); 0078 app.setApplicationVersion(Snore::Version::version()); 0079 0080 QCommandLineParser parser; 0081 parser.setApplicationDescription(QStringLiteral("A command line interface for Snorenotify.")); 0082 parser.addHelpOption(); 0083 parser.addVersionOption(); 0084 0085 QCommandLineOption title(QStringList() << QStringLiteral("t") << QStringLiteral("title"), QStringLiteral("Set the notification title."), QStringLiteral("title")); 0086 parser.addOption(title); 0087 0088 QCommandLineOption message(QStringList() << QStringLiteral("m") << QStringLiteral("message"), QStringLiteral("Set the notification body."), QStringLiteral("message")); 0089 parser.addOption(message); 0090 0091 QCommandLineOption applicationName(QStringList() << QStringLiteral("a") << QStringLiteral("application"), QStringLiteral("Set the notification applicattion."), QStringLiteral("application"), app.applicationName()); 0092 parser.addOption(applicationName); 0093 0094 QCommandLineOption alertName(QStringList() << QStringLiteral("c") << QStringLiteral("alert"), QStringLiteral("Set the notification alert class."), QStringLiteral("alert"), QStringLiteral("Default")); 0095 parser.addOption(alertName); 0096 0097 QCommandLineOption iconPath(QStringList() << QStringLiteral("i") << QStringLiteral("icon"), QStringLiteral("Set the notification icon."), QStringLiteral("icon")); 0098 parser.addOption(iconPath); 0099 0100 QCommandLineOption priority(QStringList() << QStringLiteral("p") << QStringLiteral("priority"), QStringLiteral("Set the notification's priority."), QStringLiteral("[-2, 2]"), QStringLiteral("0")); 0101 parser.addOption(priority); 0102 0103 QCommandLineOption markup(QStringList() << QStringLiteral("markup"), QStringLiteral("Enable markup support."), QStringLiteral("[0,1]"), QStringLiteral("0")); 0104 parser.addOption(markup); 0105 0106 QCommandLineOption silent(QStringList() << QStringLiteral("silent"), QStringLiteral("Don't print to stdout.")); 0107 parser.addOption(silent); 0108 0109 #ifdef Q_OS_WIN 0110 QCommandLineOption _bringProcessToFront(QStringList() << QStringLiteral("bring-process-to-front"), QStringLiteral("Bring process with pid to front if notification is clicked."), QStringLiteral("pid")); 0111 parser.addOption(_bringProcessToFront); 0112 0113 QCommandLineOption _bringWindowToFront(QStringList() << QStringLiteral("bring-window-to-front"), QStringLiteral("Bring window with wid to front if notification is clicked."), QStringLiteral("wid")); 0114 parser.addOption(_bringWindowToFront); 0115 #endif 0116 parser.process(app); 0117 qCDebug(SNORE) << app.arguments(); 0118 if (parser.isSet(title) && parser.isSet(message)) { 0119 SnoreCore &core = SnoreCore::instance(); 0120 0121 core.loadPlugins(Snore::SnorePlugin::Backend | Snore::SnorePlugin::SecondaryBackend); 0122 0123 Icon icon = Icon::defaultIcon(); 0124 if (parser.isSet(iconPath)) { 0125 icon = Icon(parser.value(iconPath)); 0126 } 0127 Application application(parser.value(applicationName), icon); 0128 Alert alert(parser.value(alertName), icon); 0129 application.addAlert(alert); 0130 0131 if (parser.value(markup).toInt() == 1) { 0132 application.hints().setValue("use-markup", true); 0133 } 0134 0135 core.registerApplication(application); 0136 0137 int prio = parser.value(priority).toInt(); 0138 if (prio < -2 || prio > 2) { 0139 parser.showHelp(-1); 0140 } 0141 Notification n(application, alert, parser.value(title), parser.value(message), icon, Notification::defaultTimeout(), static_cast<Notification::Prioritys>(prio)); 0142 #ifdef Q_OS_WIN 0143 if (parser.isSet(_bringProcessToFront) || parser.isSet(_bringWindowToFront)) { 0144 n.addAction(Action(1, qApp->translate("SnoreSend", "Bring to Front"))); 0145 } 0146 #endif 0147 int returnCode = -1; 0148 0149 app.connect(&core, &SnoreCore::notificationClosed, [&](Notification noti) { 0150 if (!parser.isSet(silent)) { 0151 QString reason; 0152 QDebug(&reason) << noti.closeReason(); 0153 cout << qPrintable(reason) << endl; 0154 } 0155 if (noti.closeReason() == Notification::Closed) { 0156 #ifdef Q_OS_WIN 0157 if (parser.isSet(_bringProcessToFront)) { 0158 bringToFront(parser.value(_bringProcessToFront)); 0159 } else if (parser.isSet(_bringWindowToFront)) { 0160 Utils::bringWindowToFront((HWND)parser.value(_bringWindowToFront).toULongLong(), true); 0161 } 0162 #endif 0163 } 0164 returnCode = noti.closeReason(); 0165 }); 0166 app.connect(&core, &SnoreCore::notificationClosed, &app, &QGuiApplication::quit); 0167 app.processEvents(); 0168 core.broadcastNotification(n); 0169 0170 app.exec(); 0171 return returnCode; 0172 } 0173 parser.showHelp(1); 0174 } 0175