Сервис для управления приложением
Для управления приложением, которое может как работать в фоновом режиме,
так и запускать графический интерфейс, создаётся класс ControlService
.
Он наследуется от QDBusAbstractAdaptor
:
class ControlService : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", DBUS_INTERFACE)
public:
explicit ControlService(QObject *parent);
static bool isApplicationRunning();
static int updateApplicationArgs(const QStringList &arguments);
static QString const service;
static QString const path;
static QString const interface;
bool start();
signals:
void startGui();
public slots:
void handleArguments(const QStringList &arguments);
};
Название сервиса, путь и интерфейс, которые может использовать приложение ограничены форматом orgName.appName.
В методе start()
регистрируется D-Bus-сервис:
bool ControlService::start()
{
auto session = QDBusConnection::sessionBus();
if (!session.registerObject(path, parent()))
{
qWarning() << "Cannot register ControlService D-Bus path: " << path << ". Error: "<< session.lastError().message();
return false;
}
qDebug() << "Registered ControlService D-Bus path: " << path;
if (!session.registerService(service))
{
qWarning() << "Cannot register ControlService D-Bus service: " << service << ". Error: " << session.lastError().message();
return false;
}
qDebug() << "Registered ControlService D-Bus service:" << service;
return true;
}
Метод updateApplicationArgs(const QStringList &arguments)
использует этот сервис,
чтобы применить для приложения аргументы командной строки,
вызвав handleArguments(const QStringList &arguments)
:
int ControlService::updateApplicationArgs(const QStringList &arguments)
{
auto message = QDBusMessage::createMethodCall(service, path, interface, QStringLiteral("handleArguments"));
message.setArguments(QList<QVariant>() << arguments);
QDBusReply<void> reply = QDBusConnection::sessionBus().call(message);
if (!reply.isValid())
{
qWarning() << reply.error().message();
}
return 0;
}
Метод handleArguments(const QStringList &arguments)
отправляет сигнал о том,
что нужно открыть графический интерфейс, если в аргументах командной строки имеется --gui
:
void ControlService::handleArguments(const QStringList &arguments)
{
if (arguments.indexOf(QStringLiteral("/no-gui")) == -1)
{
qDebug() << "Ask for run gui";
emit startGui();
}
}
Сервис создаётся и запускается в main.cpp
:
int main(int argc, char *argv[])
{
auto application = AuroraApp::application(argc, argv);
QStringList applicationArguments = application->arguments();
applicationArguments.removeFirst();
if (ControlService::isApplicationRunning())
{
qDebug() << "Application already running, use this runned application";
return ControlService::updateApplicationArgs(applicationArguments);
}
else
{
qDebug() << "Starting application " << application->arguments();
auto controlService = new ControlService(application);
if (!controlService->start())
{
return 0;
}
auto pushExample = new Application(application);
QObject::connect(controlService, &ControlService::startGui, pushExample, &Application::startGui);
pushExample->start(applicationArguments);
return application->exec();
}
}
Сначала проверяется, не был ли сервис уже запущен. В этом случае у него только обновляются аргументы командной строки. Иначе создаётся и запускается новый сервис, а также приложение, которое получает аргументы командной строки.