feat!: respond to D-Bus activation
Minimal support for requesting window activation in response to activation requests from D-Bus. This provides minimal support for xdg D-Bus activation in Keysmith: only the activation signal itself is handled; the DBus API for opening URLs is not implemented. Issues: #18master
parent
287cbcd480
commit
fb953ed677
|
@ -55,6 +55,7 @@ endif()
|
|||
|
||||
if (BUILD_DBUS_INTERFACE OR (NOT ANDROID AND NOT DEFINED BUILD_DBUS_INTERFACE))
|
||||
find_package(KF5DBusAddons ${KF5_MIN_VERSION} REQUIRED)
|
||||
find_package(KF5WindowSystem ${KF5_MIN_VERSION} REQUIRED)
|
||||
set(ENABLE_DBUS_INTERFACE ON)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -12,4 +12,12 @@ set(keysmith_SRCS
|
|||
)
|
||||
|
||||
add_library(keysmith_lib STATIC ${keysmith_SRCS})
|
||||
target_link_libraries(keysmith_lib Qt5::Core Qt5::Gui Qt5::Concurrent Qt5::Qml KF5::I18n model_lib account_lib)
|
||||
target_link_libraries(keysmith_lib
|
||||
Qt5::Core Qt5::Gui Qt5::Qml Qt5::Concurrent
|
||||
KF5::I18n
|
||||
model_lib account_lib
|
||||
)
|
||||
|
||||
if (ENABLE_DBUS_INTERFACE)
|
||||
target_link_libraries(keysmith_lib KF5::DBusAddons KF5::WindowSystem)
|
||||
endif()
|
||||
|
|
|
@ -12,6 +12,14 @@
|
|||
#include <QCommandLineOption>
|
||||
#include <QtConcurrent>
|
||||
|
||||
#ifdef ENABLE_DBUS_INTERFACE
|
||||
#include <QWindow>
|
||||
#include <Qt>
|
||||
#include <KDBusService>
|
||||
#include <kstartupinfo.h>
|
||||
#include <kwindowsystem.h>
|
||||
#endif
|
||||
|
||||
KEYSMITH_LOGGER(logger, ".app.cli")
|
||||
|
||||
namespace app
|
||||
|
@ -165,8 +173,62 @@ namespace app
|
|||
return false;
|
||||
}
|
||||
|
||||
(new InitialFlow(m_keysmith))->run(parser);
|
||||
if (state->initialFlowDone()) {
|
||||
(new ExternalCommandLineFlow(m_keysmith))->run(parser);
|
||||
} else {
|
||||
(new InitialFlow(m_keysmith))->run(parser);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_DBUS_INTERFACE
|
||||
|
||||
static QWindow * getMainWindow(QGuiApplication *app)
|
||||
{
|
||||
if (!app) {
|
||||
qCDebug(logger) << "Cannot find a valid main window without a QGuiApplication";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto windows = app->topLevelWindows();
|
||||
for (auto *window: windows) {
|
||||
if (window && window->type() == Qt::Window) {
|
||||
return window;
|
||||
}
|
||||
}
|
||||
qCDebug(logger) << "Unable to find main window for QGuiApplication:" << app;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Proxy::handleDBusActivation(const QStringList &arguments, const QString &workingDirectory)
|
||||
{
|
||||
Q_UNUSED(workingDirectory);
|
||||
qCInfo(logger) << "Handling Keysmith activation request";
|
||||
|
||||
auto *s = sender();
|
||||
Q_ASSERT_X(s, Q_FUNC_INFO, "should be triggered with a valid sender()");
|
||||
|
||||
auto *svc = qobject_cast<KDBusService*>(s);
|
||||
Q_ASSERT_X(svc, Q_FUNC_INFO, "should be triggered by a KDBusService instance");
|
||||
|
||||
QCommandLineParser cliParser;
|
||||
bool parseOk = parseCommandLine(cliParser, arguments);
|
||||
if (!proxy(cliParser, parseOk)) {
|
||||
qCDebug(logger) << "Rejected command line arguments";
|
||||
svc->setExitValue(1);
|
||||
}
|
||||
|
||||
const auto mainWindow = getMainWindow(m_app);
|
||||
if (!mainWindow) {
|
||||
qCWarning(logger) << "Unable to activate Keysmith main window: unable to find it";
|
||||
svc->setExitValue(1);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(logger) << "Activating Keysmith main window";
|
||||
KStartupInfo::setNewStartupId(mainWindow, KStartupInfo::startupId());
|
||||
KWindowSystem::activateWindow(mainWindow->winId());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "keysmith.h"
|
||||
#include "../model/input.h"
|
||||
|
||||
#include "../keysmith-features.h"
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QGuiApplication>
|
||||
#include <QObject>
|
||||
|
@ -70,6 +72,10 @@ namespace app
|
|||
explicit Proxy(QGuiApplication *app, QObject *parent = nullptr);
|
||||
bool enable(Keysmith *keysmith);
|
||||
bool proxy(const QCommandLineParser &parser, bool parsedOk);
|
||||
#ifdef ENABLE_DBUS_INTERFACE
|
||||
public Q_SLOTS:
|
||||
void handleDBusActivation(const QStringList &arguments, const QString &workingDirectory);
|
||||
#endif
|
||||
private Q_SLOTS:
|
||||
void disable(void);
|
||||
private:
|
||||
|
|
|
@ -204,4 +204,65 @@ namespace app
|
|||
flowStateOf(m_app)->setFlowRunning(false);
|
||||
QTimer::singleShot(0, this, &QObject::deleteLater);
|
||||
}
|
||||
|
||||
ExternalCommandLineFlow::ExternalCommandLineFlow(Keysmith *app) :
|
||||
QObject(app), m_app(app), m_input(new model::AccountInput(this))
|
||||
{
|
||||
Q_ASSERT_X(app, Q_FUNC_INFO, "should have a Keysmith instance");
|
||||
}
|
||||
|
||||
void ExternalCommandLineFlow::run(const QCommandLineParser &parser)
|
||||
{
|
||||
const auto argv = parser.positionalArguments();
|
||||
if (argv.isEmpty()) {
|
||||
qCDebug(logger) << "No URIs to handle, nothing to do for external commandline:" << this;
|
||||
QTimer::singleShot(0, this, &ExternalCommandLineFlow::deleteLater);
|
||||
return;
|
||||
}
|
||||
|
||||
flowStateOf(m_app)->setFlowRunning(true);
|
||||
overviewStateOf(m_app)->setActionsEnabled(false);
|
||||
qCDebug(logger) << "Will parse given URI(s) from external commandline:" << this;
|
||||
|
||||
auto job = new CommandLineAccountJob(m_input);
|
||||
QObject::connect(job, &CommandLineAccountJob::newAccountProcessed,
|
||||
this, &ExternalCommandLineFlow::onNewAccountProcessed);
|
||||
QObject::connect(job, &CommandLineAccountJob::newAccountInvalid,
|
||||
this, &ExternalCommandLineFlow::onNewAccountInvalid);
|
||||
job->run(argv[0]);
|
||||
}
|
||||
|
||||
void ExternalCommandLineFlow::onNewAccountProcessed(void)
|
||||
{
|
||||
auto vm = new AddAccountViewModel(m_input, accountListOf(m_app), false, true);
|
||||
QObject::connect(vm, &AddAccountViewModel::accepted, this, &ExternalCommandLineFlow::onAccepted);
|
||||
QObject::connect(vm, &AddAccountViewModel::cancelled, this, &ExternalCommandLineFlow::back);
|
||||
navigationFor(m_app)->push(Navigation::Page::AddAccount, vm);
|
||||
}
|
||||
|
||||
void ExternalCommandLineFlow::onNewAccountInvalid(void)
|
||||
{
|
||||
auto vm = new ErrorViewModel(
|
||||
i18nc("@title:window", "Invalid account"),
|
||||
i18nc("@info:label", "The account you are trying to add is invalid. Continue without adding the account."),
|
||||
false
|
||||
);
|
||||
QObject::connect(vm, &ErrorViewModel::dismissed, this, &ExternalCommandLineFlow::back);
|
||||
navigationFor(m_app)->navigate(Navigation::Page::Error, vm);
|
||||
}
|
||||
|
||||
void ExternalCommandLineFlow::onAccepted(void)
|
||||
{
|
||||
accountListOf(m_app)->addAccount(m_input);
|
||||
QTimer::singleShot(0, this, &ExternalCommandLineFlow::back);
|
||||
}
|
||||
|
||||
void ExternalCommandLineFlow::back(void)
|
||||
{
|
||||
auto vm = new AccountsOverviewViewModel(m_app);
|
||||
navigationFor(m_app)->navigate(Navigation::Page::AccountsOverview, vm);
|
||||
overviewStateOf(m_app)->setActionsEnabled(true);
|
||||
flowStateOf(m_app)->setFlowRunning(false);
|
||||
QTimer::singleShot(0, this, &QObject::deleteLater);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,23 @@ namespace app
|
|||
Keysmith * const m_app;
|
||||
model::AccountInput * const m_input;
|
||||
};
|
||||
|
||||
class ExternalCommandLineFlow: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ExternalCommandLineFlow(Keysmith *app);
|
||||
public:
|
||||
void run(const QCommandLineParser &parser);
|
||||
private Q_SLOTS:
|
||||
void onNewAccountInvalid(void);
|
||||
void onNewAccountProcessed(void);
|
||||
void back(void);
|
||||
void onAccepted(void);
|
||||
private:
|
||||
Keysmith * const m_app;
|
||||
model::AccountInput * const m_input;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -79,6 +79,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
|
|||
|
||||
#ifdef ENABLE_DBUS_INTERFACE
|
||||
KDBusService service(KDBusService::Unique);
|
||||
QObject::connect(&service, &KDBusService::activateRequested, &proxy, &app::Proxy::handleDBusActivation);
|
||||
#endif
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
|
Loading…
Reference in New Issue