diff --git a/src/common/dbus/org.kde.ActivityManager.Application.xml b/src/common/dbus/org.kde.ActivityManager.Application.xml
new file mode 100644
index 00000000..fc4a36b5
--- /dev/null
+++ b/src/common/dbus/org.kde.ActivityManager.Application.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/core/CMakeLists.txt b/src/lib/core/CMakeLists.txt
index f7636a85..356b7c98 100644
--- a/src/lib/core/CMakeLists.txt
+++ b/src/lib/core/CMakeLists.txt
@@ -1,150 +1,157 @@
# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab:
# =======================================================
# Now that we finished with the boilerplate, start
# with the library definition
set (
KActivities_LIB_SRCS
${KACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Activities.cpp
consumer.cpp
controller.cpp
info.cpp
resourceinstance.cpp
mainthreadexecutor_p.cpp
manager_p.cpp
activitiescache_p.cpp
debug_p.cpp
${KACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/utils/dbusfuture_p.cpp
version.cpp
)
set_source_files_properties (
${KACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Activities.xml
PROPERTIES
INCLUDE ${KACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Activities.h
)
qt5_add_dbus_interface (
KActivities_LIB_SRCS
${KACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Activities.xml
activities_interface
)
qt5_add_dbus_interface (
KActivities_LIB_SRCS
${KACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Resources.xml
resources_interface
)
qt5_add_dbus_interface (
KActivities_LIB_SRCS
${KACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Features.xml
features_interface
)
qt5_add_dbus_interface (
KActivities_LIB_SRCS
${KACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.ResourcesLinking.xml
resources_linking_interface
)
+qt5_add_dbus_interface (
+ KActivities_LIB_SRCS
+
+ ${KACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Application.xml
+ application_interface
+ )
+
add_library (
KF5Activities SHARED
${KActivities_LIB_SRCS}
)
add_library (KF5::Activities ALIAS KF5Activities)
include_directories (
${KACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src
${KDBusAddons_INCLUDE_DIR}
${Boost_INCLUDE_DIR}
)
set_target_properties (
KF5Activities
PROPERTIES
VERSION ${KACTIVITIES_VERSION_STRING}
SOVERSION ${KACTIVITIES_SOVERSION}
EXPORT_NAME Activities
)
target_link_libraries (
KF5Activities
PUBLIC
Qt5::Core
PRIVATE
Qt5::DBus
KF5::DBusAddons
)
target_include_directories (
KF5Activities
INTERFACE "$"
)
# install
generate_export_header (KF5Activities BASE_NAME KActivities)
ecm_generate_headers (
KActivities_CamelCase_HEADERS
HEADER_NAMES
Consumer
Controller
Info
ResourceInstance
Version
PREFIX KActivities
REQUIRED_HEADERS KActivities_HEADERS
)
install (
FILES ${KActivities_CamelCase_HEADERS}
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KActivities/KActivities
COMPONENT Devel
)
install (
FILES ${KActivities_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/kactivities_export.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KActivities/kactivities
COMPONENT Devel
)
install (
TARGETS KF5Activities
EXPORT KF5ActivitiesLibraryTargets
${KF5_INSTALL_TARGETS_DEFAULT_ARGS}
)
if (NOT WIN32)
configure_file (
${CMAKE_CURRENT_SOURCE_DIR}/libKActivities.pc.cmake
${CMAKE_CURRENT_BINARY_DIR}/libKActivities.pc
)
install (
FILES ${CMAKE_CURRENT_BINARY_DIR}/libKActivities.pc
DESTINATION ${KDE_INSTALL_LIBDIR}/pkgconfig
)
endif ()
include (ECMGeneratePriFile)
ecm_generate_pri_file (
BASE_NAME KActivities
LIB_NAME KF5Activities
DEPS "KDBusAddons"
FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KActivities
)
install (
FILES ${PRI_FILENAME}
DESTINATION ${ECM_MKSPECS_INSTALL_DIR}
)
diff --git a/src/lib/core/manager_p.cpp b/src/lib/core/manager_p.cpp
index 8ee766f1..e0276973 100644
--- a/src/lib/core/manager_p.cpp
+++ b/src/lib/core/manager_p.cpp
@@ -1,183 +1,179 @@
/*
* Copyright (C) 2010, 2011, 2012, 2013, 2014 Ivan Cukic
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2,
* or (at your option) any later version, as published by the Free
* Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "manager_p.h"
#include
#include
#include
#include
#include
#include "debug_p.h"
#include "mainthreadexecutor_p.h"
#include "common/dbus/common.h"
#include "utils/dbusfuture_p.h"
#include "utils/continue_with.h"
#include "version.h"
namespace KActivities {
Manager *Manager::s_instance = Q_NULLPTR;
Manager::Manager()
: QObject()
, m_watcher(KAMD_DBUS_SERVICE, QDBusConnection::sessionBus())
+ , m_service(new KAMD_DBUS_CLASS_INTERFACE(Application, Application, this))
, m_activities(new KAMD_DBUS_CLASS_INTERFACE(Activities, Activities, this))
, m_resources(new KAMD_DBUS_CLASS_INTERFACE(Resources, Resources, this))
, m_resourcesLinking(new KAMD_DBUS_CLASS_INTERFACE(Resources/Linking, ResourcesLinking, this))
, m_features(new KAMD_DBUS_CLASS_INTERFACE(Features, Features, this))
, m_serviceRunning(false)
{
connect(&m_watcher, &QDBusServiceWatcher::serviceOwnerChanged,
this, &Manager::serviceOwnerChanged);
if (isServiceRunning()) {
serviceOwnerChanged(KAMD_DBUS_SERVICE, QString(), KAMD_DBUS_SERVICE);
}
}
Manager *Manager::self()
{
static std::mutex singleton;
std::lock_guard singleton_lock(singleton);
if (!s_instance) {
runInMainThread([] () {
// check if the activity manager is already running
if (!Manager::isServiceRunning()) {
#if defined(QT_DEBUG)
QLoggingCategory::setFilterRules(QStringLiteral("org.kde.kactivities.lib.core.debug=true"));
qCDebug(KAMD_CORELIB) << "Should we start the daemon?";
if (!QCoreApplication::instance()
->property("org.kde.KActivities.core.disableAutostart")
.toBool()) {
qCDebug(KAMD_CORELIB) << "Starting the activity manager daemon";
QProcess::startDetached(QStringLiteral("kactivitymanagerd"));
}
#else
QProcess::startDetached(QStringLiteral("kactivitymanagerd"));
#endif
}
// creating a new instance of the class
Manager::s_instance = new Manager();
});
}
return s_instance;
}
bool Manager::isServiceRunning()
{
return
(s_instance ? s_instance->m_serviceRunning : true)
&& QDBusConnection::sessionBus().interface()->isServiceRegistered(KAMD_DBUS_SERVICE);
}
void Manager::serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
{
Q_UNUSED(oldOwner);
if (serviceName == KAMD_DBUS_SERVICE) {
m_serviceRunning = !newOwner.isEmpty();
emit serviceStatusChanged(m_serviceRunning);
if (m_serviceRunning) {
- QDBusInterface service(KAMD_DBUS_SERVICE,
- "/ActivityManager",
- "org.kde.ActivityManager.Application",
- QDBusConnection::sessionBus(),
- Q_NULLPTR);
-
using namespace kamd::utils;
+
continue_with(
- DBusFuture::asyncCall(&service, "serviceVersion"),
+ DBusFuture::fromReply(m_service->serviceVersion()),
[this] (const optional_view &serviceVersion) {
// Test whether the service is older than the library.
// If it is, we need to end this
if (!serviceVersion.is_initialized()) {
qWarning() << "KActivities: FATAL ERROR: Failed to contact the activity manager daemon";
m_serviceRunning = false;
return;
}
auto split = serviceVersion->split('.');
QList version;
const int requiredVersion[] = {
KACTIVITIES_VERSION_MAJOR,
KACTIVITIES_VERSION_MINOR,
KACTIVITIES_VERSION_RELEASE
};
std::transform(
split.cbegin(), split.cend(),
std::back_inserter(version), [] (const QString &component) {
return component.toInt();
});
// if required version is greater than the current version
if (std::lexicographical_compare(
version.cbegin(), version.cend(),
std::begin(requiredVersion), std::end(requiredVersion)
)) {
QString libraryVersion = QString::number(requiredVersion[0]) + '.'
+ QString::number(requiredVersion[1]) + '.'
+ QString::number(requiredVersion[2]);
qDebug() << "KActivities service version: " << serviceVersion.get();
qDebug() << "KActivities library version: " << libraryVersion;
qFatal("KActivities: FATAL ERROR: The service is older than the library");
}
});
}
}
}
Service::Activities *Manager::activities()
{
return self()->m_activities;
}
Service::Resources *Manager::resources()
{
return self()->m_resources;
}
Service::ResourcesLinking *Manager::resourcesLinking()
{
return self()->m_resourcesLinking;
}
Service::Features *Manager::features()
{
return self()->m_features;
}
} // namespace KActivities
diff --git a/src/lib/core/manager_p.h b/src/lib/core/manager_p.h
index 6579e286..73170be1 100644
--- a/src/lib/core/manager_p.h
+++ b/src/lib/core/manager_p.h
@@ -1,74 +1,76 @@
/*
* Copyright (C) 2010, 2011, 2012, 2013, 2014 Ivan Cukic
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2,
* or (at your option) any later version, as published by the Free
* Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef ACTIVITIES_MANAGER_P
#define ACTIVITIES_MANAGER_P
#include
+#include "application_interface.h"
#include "activities_interface.h"
#include "resources_interface.h"
#include "resources_linking_interface.h"
#include "features_interface.h"
#include
namespace Service = org::kde::ActivityManager;
namespace KActivities {
class Manager : public QObject {
Q_OBJECT
public:
static Manager *self();
static bool isServiceRunning();
static Service::Activities *activities();
static Service::Resources *resources();
static Service::ResourcesLinking *resourcesLinking();
static Service::Features *features();
public Q_SLOTS:
void serviceOwnerChanged(const QString &serviceName,
const QString &oldOwner, const QString &newOwner);
Q_SIGNALS:
void serviceStatusChanged(bool status);
private:
Manager();
QDBusServiceWatcher m_watcher;
static Manager *s_instance;
+ Service::Application *const m_service;
Service::Activities *const m_activities;
Service::Resources *const m_resources;
Service::ResourcesLinking *const m_resourcesLinking;
Service::Features *const m_features;
bool m_serviceRunning;
friend class ManagerInstantiator;
};
} // namespace KActivities
#endif // ACTIVITIES_MANAGER_P
diff --git a/src/service/Application.h b/src/service/Application.h
index c63a96ef..43961470 100644
--- a/src/service/Application.h
+++ b/src/service/Application.h
@@ -1,70 +1,71 @@
/*
* Copyright (C) 2012 Ivan Cukic
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* or (at your option) any later version, as published by the Free
* Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef APPLICATION_H
#define APPLICATION_H
// Qt
#include
// Utils
#include
class Resources;
class Activities;
class Features;
/**
* Main application object
* This can *not* be a QGuiApplication because
* we need KWindowSystem widgets.
*/
class Application : public QApplication {
Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.kde.ActivityManager.Application")
public:
Application(int &argc, char **argv);
virtual ~Application();
virtual int newInstance();
// static Application * self();
// static void quit();
Resources &resources() const;
Activities &activities() const;
Features &features() const;
public Q_SLOTS:
void quit();
QString serviceVersion() const;
bool loadPlugin(const QString &plugin);
private Q_SLOTS:
void init();
void loadPlugins();
private:
D_PTR;
friend int main(int, char**);
};
#endif // APPLICATION_H
diff --git a/src/utils/dbusfuture_p.h b/src/utils/dbusfuture_p.h
index 56d75670..e9dcf8b5 100644
--- a/src/utils/dbusfuture_p.h
+++ b/src/utils/dbusfuture_p.h
@@ -1,165 +1,176 @@
/*
* Copyright (C) 2013 Ivan Cukic
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* or (at your option) any later version, as published by the Free
* Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef ACTIVITIES_DBUSFUTURE_P_H
#define ACTIVITIES_DBUSFUTURE_P_H
#include
#include
#include
#include
#include
#include
#include
#include "debug_p.h"
namespace DBusFuture {
namespace detail { //_
template
class DBusCallFutureInterface : public QObject,
public QFutureInterface<_Result> {
public:
DBusCallFutureInterface(QDBusPendingReply<_Result> reply)
: reply(reply),
replyWatcher(Q_NULLPTR)
{
}
~DBusCallFutureInterface()
{
delete replyWatcher;
}
void callFinished();
QFuture<_Result> start()
{
replyWatcher = new QDBusPendingCallWatcher(reply);
QObject::connect(replyWatcher,
&QDBusPendingCallWatcher::finished,
[this] () { callFinished(); });
this->reportStarted();
if (reply.isFinished()) {
this->callFinished();
}
return this->future();
}
private:
QDBusPendingReply<_Result> reply;
QDBusPendingCallWatcher * replyWatcher;
};
template
void DBusCallFutureInterface<_Result>::callFinished()
{
deleteLater();
if (!reply.isError()) {
this->reportResult(reply.value());
}
this->reportFinished();
}
template <>
void DBusCallFutureInterface::callFinished();
template
class ValueFutureInterface : public QObject, QFutureInterface<_Result> {
public:
ValueFutureInterface(const _Result & value)
: value(value)
{
}
QFuture<_Result> start()
{
auto future = this->future();
this->reportResult(value);
this->reportFinished();
deleteLater();
return future;
}
private:
_Result value;
};
template <>
class ValueFutureInterface : public QObject, QFutureInterface {
public:
ValueFutureInterface();
QFuture start();
// {
// auto future = this->future();
// this->reportFinished();
// deleteLater();
// return future;
// }
};
} //^ namespace detail
template
QFuture<_Result>
asyncCall(QDBusAbstractInterface *interface, const QString &method,
const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(),
const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(),
const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(),
const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant())
{
using namespace detail;
auto callFutureInterface = new DBusCallFutureInterface
<_Result>(interface->asyncCall(method, arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8));
return callFutureInterface->start();
}
template
QFuture<_Result>
fromValue(const _Result & value)
{
using namespace detail;
auto valueFutureInterface = new ValueFutureInterface<_Result>(value);
return valueFutureInterface->start();
}
+template
+QFuture<_Result>
+fromReply(const QDBusPendingReply<_Result> &reply)
+{
+ using namespace detail;
+
+ auto callFutureInterface = new DBusCallFutureInterface<_Result>(reply);
+
+ return callFutureInterface->start();
+}
+
QFuture fromVoid();
} // namespace DBusFuture
#endif /* DBUSFUTURE_P_H */