diff --git a/kparts/CMakeLists.txt b/kparts/CMakeLists.txt index 96fa31f..4909cd3 100644 --- a/kparts/CMakeLists.txt +++ b/kparts/CMakeLists.txt @@ -30,8 +30,21 @@ set(kparts_LIB_SRCS textextension.cpp htmlextension.cpp fileinfoextension.cpp + + # Private classes from libkactivities + private/libkactivities/manager_p.cpp + private/libkactivities/resourceinstance.cpp ) + +# D-Bus connection to the activity manager +qt4_add_dbus_interface( + kparts_LIB_SRCS + private/libkactivities/org.kde.ActivityManager.xml + activitymanager_interface +) + + kde4_add_library(kparts ${LIBRARY_TYPE} ${kparts_LIB_SRCS}) target_link_libraries(kparts ${KDE4_KDECORE_LIBS} kdeui kio) @@ -41,8 +54,8 @@ if(HAVE_NEPOMUK) target_link_libraries(kparts LINK_INTERFACE_LIBRARIES nepomuk nepomukutils ) endif(HAVE_NEPOMUK) -set_target_properties(kparts PROPERTIES VERSION ${GENERIC_LIB_VERSION} - SOVERSION ${GENERIC_LIB_SOVERSION} +set_target_properties(kparts PROPERTIES VERSION ${GENERIC_LIB_VERSION} + SOVERSION ${GENERIC_LIB_SOVERSION} ) diff --git a/kparts/part.cpp b/kparts/part.cpp index b9c8be5..c2854e9 100644 --- a/kparts/part.cpp +++ b/kparts/part.cpp @@ -26,6 +26,9 @@ #include "partmanager.h" #include "browserextension.h" +// the activity manager feeder (kamd) +#include "private/libkactivities/resourceinstance.h" + #include #include #include @@ -380,6 +383,7 @@ public: m_duringSaveAs = false; m_bTemp = false; m_bAutoDetectedMime = false; + m_resourceInstance = 0; } ~ReadOnlyPartPrivate() @@ -389,6 +393,8 @@ public: void _k_slotJobFinished( KJob * job ); void _k_slotStatJobFinished(KJob * job); void _k_slotGotMimeType(KIO::Job *job, const QString &mime); + void _k_slotOpeningCompleted(); + void _k_slotWindowCaptionChanged(const QString & caption); bool openLocalFile(); void openRemoteFile(); @@ -421,6 +427,13 @@ public: QString m_file; OpenUrlArguments m_arguments; + + /** + * Class for talking to the activity manager (kamd) + */ + KActivities::ResourceInstance * m_resourceInstance; + QString m_resourceCaption; + }; class ReadWritePartPrivate: public ReadOnlyPartPrivate @@ -450,11 +463,23 @@ public: ReadOnlyPart::ReadOnlyPart( QObject *parent ) : Part( *new ReadOnlyPartPrivate(this), parent ) { + QObject::connect( + this, SIGNAL(completed()), + this, SLOT(_k_slotOpeningCompleted()) + ); + QObject::connect( + this, SIGNAL(setWindowCaption(QString)), + this, SLOT(_k_slotWindowCaptionChanged(QString)) + ); } ReadOnlyPart::ReadOnlyPart( ReadOnlyPartPrivate &dd, QObject *parent ) : Part( dd, parent ) { + QObject::connect( + this, SIGNAL(completed()), + this, SLOT(_k_slotOpeningCompleted()) + ); } ReadOnlyPart::~ReadOnlyPart() @@ -473,6 +498,10 @@ void ReadOnlyPart::setUrl(const KUrl &url) { Q_D(ReadOnlyPart); + if (d->m_resourceInstance) { + d->m_resourceInstance->setUri(url); + } + d->m_url = url; } @@ -658,6 +687,17 @@ bool ReadOnlyPart::closeUrl() // It always succeeds for a read-only part, // but the return value exists for reimplementations // (e.g. pressing cancel for a modified read-write part) + + // Feeding the data to the activity manager (kamd) + kDebug(1000) + << "A component named" + << KGlobal::mainComponent().componentName() + << "has closed the" + << url(); + delete d->m_resourceInstance; + d->m_resourceInstance = 0; // just in case + // Finished with the activity manager + return true; } @@ -697,9 +737,53 @@ void ReadOnlyPartPrivate::_k_slotJobFinished( KJob * job ) } } +void ReadOnlyPartPrivate::_k_slotOpeningCompleted() +{ + Q_Q(ReadOnlyPart); + + // Feeding the data to the activity manager (kamd) + kDebug(1000) + << "A component named" + << KGlobal::mainComponent().componentName() + << "is opening the" + << q->url() + << ( q->widget() ? q->widget()->topLevelWidget()->winId() : 0 ) + << "mime" + << m_arguments.mimeType() + << "title" + << m_resourceCaption; + + // deleting the previous one + delete m_resourceInstance; + + m_resourceInstance = new KActivities::ResourceInstance( + ( q->widget() ? q->widget()->topLevelWidget()->winId() : 0 ), // wid + q->url(), // resourceUri + m_arguments.mimeType(), // mimetype + m_resourceCaption, // title + KActivities::ResourceInstance::User, // accessReason + KGlobal::mainComponent().componentName(), // application + q // parent + ); + // Finished with the activity manager +} + +void ReadOnlyPartPrivate::_k_slotWindowCaptionChanged(const QString & caption) +{ + kDebug(1000) << "This is the new caption" << caption; + + m_resourceCaption = caption; + + if (m_resourceInstance) { + kDebug(1000) << "KAMD: resource caption" << caption; + m_resourceInstance->setTitle(caption); + } +} + void ReadOnlyPartPrivate::_k_slotGotMimeType(KIO::Job *job, const QString &mime) { - kDebug(1000) << mime; + kDebug(1000) << "This is the mime type we got" << mime; + Q_ASSERT(job == m_job); Q_UNUSED(job) // set the mimetype only if it was not already set (for example, by the host application) if (m_arguments.mimeType().isEmpty()) { @@ -731,6 +815,13 @@ bool ReadOnlyPart::openStream( const QString& mimeType, const KUrl& url ) return false; d->m_arguments = args; d->m_url = url; + + kDebug(1000) + << "A component named" + << KGlobal::mainComponent().componentName() + << "is opening the stream" + << url << mimeType; + return doOpenStream( mimeType ); } @@ -796,6 +887,12 @@ void ReadWritePart::setModified( bool modified ) kError(1000) << "Can't set a read-only document to 'modified' !" << endl; return; } + + if ( modified && d->m_resourceInstance ) { + kDebug(1000) << "Notifying kamd of the change"; + d->m_resourceInstance->notifyModified(); + } + d->m_bModified = modified; } diff --git a/kparts/part.h b/kparts/part.h index 56b64da..f62f2d7 100644 --- a/kparts/part.h +++ b/kparts/part.h @@ -717,6 +717,9 @@ private: Q_PRIVATE_SLOT(d_func(), void _k_slotStatJobFinished(KJob*)) Q_PRIVATE_SLOT(d_func(), void _k_slotGotMimeType(KIO::Job *job, const QString &mime)) + Q_PRIVATE_SLOT(d_func(), void _k_slotOpeningCompleted()) + Q_PRIVATE_SLOT(d_func(), void _k_slotWindowCaptionChanged(const QString & caption)) + Q_DISABLE_COPY(ReadOnlyPart) }; class ReadWritePartPrivate; diff --git a/kparts/private/libkactivities/CMakeLists.txt b/kparts/private/libkactivities/CMakeLists.txt new file mode 100644 index 0000000..e164126 --- /dev/null +++ b/kparts/private/libkactivities/CMakeLists.txt @@ -0,0 +1,152 @@ +project(kactivities) + +cmake_minimum_required(VERSION 2.8) + +FIND_PACKAGE(KDE4 REQUIRED) +INCLUDE(KDE4Defaults) +INCLUDE(MacroLibrary) +INCLUDE(MacroOptionalAddSubdirectory) +INCLUDE(FindPackageHandleStandardArgs) + +# ======================================================= +# Information to update before to release this library. + +# Library version history: +# API ABI +# 0.1.0 => 0.1.0 +# 0.1.1 => 0.1.1 +# 0.2.0 => 0.2.0 + +# Library API version +SET(KACTIVITIES_LIB_MAJOR_VERSION "6") +SET(KACTIVITIES_LIB_MINOR_VERSION "0") +SET(KACTIVITIES_LIB_PATCH_VERSION "0") + +# Suffix to add at end of version string. Usual values are: +# "-git" : alpha code unstable from git. Do not use in production +# "-beta1" : beta1 release. +# "-beta2" : beta2 release. +# "-beta3" : beta3 release. +# "-rc" : release candidate. +# "" : final relase. Can be used in production. +SET(KACTIVITIES_LIB_SUFFIX_VERSION "") + +# Library ABI version used by linker. +# For details : http://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info +SET(KACTIVITIES_LIB_SO_CUR_VERSION "6") +SET(KACTIVITIES_LIB_SO_REV_VERSION "0") +SET(KACTIVITIES_LIB_SO_AGE_VERSION "0") + +# ======================================================= +# Set env. variables accordinly. + +set(KACTIVITIES_INCLUDE_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/.." + "${CMAKE_CURRENT_SOURCE_DIR}/" + CACHE STRING + "Location of libkactivities headers" FORCE) +set(KACTIVITIES_LIBS + "kactivities" + CACHE STRING + "Location of libkactivities binary" FORCE) + +SET(KACTIVITIES_LIB_VERSION_STRING "${KACTIVITIES_LIB_MAJOR_VERSION}.${KACTIVITIES_LIB_MINOR_VERSION}.${KACTIVITIES_LIB_PATCH_VERSION}${KACTIVITIES_LIB_SUFFIX_VERSION}") +SET(KACTIVITIES_LIB_VERSION_ID "0x0${KACTIVITIES_LIB_MAJOR_VERSION}0${KACTIVITIES_LIB_MINOR_VERSION}0${KACTIVITIES_LIB_PATCH_VERSION}") +SET(KACTIVITIES_LIB_SO_VERSION_STRING "${KACTIVITIES_LIB_SO_CUR_VERSION}.${KACTIVITIES_LIB_SO_REV_VERSION}.${KACTIVITIES_LIB_SO_AGE_VERSION}") + +ADD_DEFINITIONS (${QT_DEFINITIONS} ${QT_QTDBUS_DEFINITIONS} ${KDE4_DEFINITIONS}) +INCLUDE_DIRECTORIES (${QDBUS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES}) + +include_directories( + ${CMAKE_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${KDE4_INCLUDES} + ${KDE4_KIO_INCLUDES} + ) + +set( + kactivities_LIB_SRCS + + consumer.cpp + controller.cpp + info.cpp + manager_p.cpp + resourceinstance.cpp + ) + +qt4_add_dbus_interface( + kactivities_LIB_SRCS + + org.kde.ActivityManager.xml + activitymanager_interface +) + + +kde4_add_library( + kactivities SHARED + ${kactivities_LIB_SRCS} + ) + + +set_target_properties( + kactivities + PROPERTIES + VERSION ${KACTIVITIES_LIB_SO_VERSION_STRING} + SOVERSION ${KACTIVITIES_LIB_SO_CUR_VERSION} + ) + +target_link_libraries( + kactivities + ${KDE4_KDECORE_LIBS} + ) + +## install + +set( + kactivities_LIB_HEADERS + consumer.h + controller.h + info.h + resourceinstance.h + ) + +set( + kactivities_LIB_PRETTY_HEADERS + includes/KActivities/Consumer + includes/KActivities/Controller + includes/KActivities/Info + includes/KActivities/ResourceInstance + ) + +install( + FILES ${kactivities_LIB_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/kactivities + COMPONENT Devel + ) + +install( + FILES ${kactivities_LIB_PRETTY_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/KDE/KActivities + COMPONENT Devel + ) + +install( + TARGETS kactivities + EXPORT kdelibsLibraryTargets + ${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 ${LIB_INSTALL_DIR}/pkgconfig ) +ENDIF(NOT WIN32) + +CONFIGURE_FILE( + KActivitiesConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/KActivitiesConfig.cmake @ONLY +) + +INSTALL( + FILES ${CMAKE_CURRENT_BINARY_DIR}/KActivitiesConfig.cmake + DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/cmake/KActivities +) + diff --git a/kparts/private/libkactivities/manager_p.cpp b/kparts/private/libkactivities/manager_p.cpp new file mode 100644 index 0000000..e71aec8 --- /dev/null +++ b/kparts/private/libkactivities/manager_p.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2010 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. + */ + +#include "manager_p.h" + +#include + +#include +#include + +namespace KActivities { + +Manager * Manager::s_instance = NULL; + +// #define ACTIVITY_MANAGER_DBUS_PATH "org.kde.ActivityManager" +#define ACTIVITY_MANAGER_DBUS_PATH "org.kde.kactivitymanagerd" +#define ACTIVITY_MANAGER_DBUS_OBJECT "/ActivityManager" + +Manager::Manager() + : org::kde::ActivityManager( + ACTIVITY_MANAGER_DBUS_PATH, + ACTIVITY_MANAGER_DBUS_OBJECT, + QDBusConnection::sessionBus() + ) +{ + connect(&m_watcher, SIGNAL(serviceOwnerChanged(const QString &, const QString &, const QString &)), + this, SLOT(serviceOwnerChanged(const QString &, const QString &, const QString &))); +} + +Manager * Manager::self() +{ + if (!s_instance) { + // check if the activity manager is already running + if (!isActivityServiceRunning()) { + + // not running, trying to launch it + QString error; + + int ret = KToolInvocation::startServiceByDesktopPath("kactivitymanagerd.desktop", QStringList(), &error); + if (ret > 0) { + kDebug() << "Activity: Couldn't start kactivitymanagerd: " << error << endl; + } + + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(ACTIVITY_MANAGER_DBUS_PATH)) { + kDebug() << "Activity: The kactivitymanagerd service is still not registered"; + } else { + kDebug() << "Activity: The kactivitymanagerd service has been registered"; + } + } + + // creating a new instance of the class + s_instance = new Manager(); + } + + return s_instance; +} + +bool Manager::isActivityServiceRunning() +{ + return QDBusConnection::sessionBus().interface()->isServiceRegistered(ACTIVITY_MANAGER_DBUS_PATH); +} + +void Manager::serviceOwnerChanged(const QString & serviceName, const QString & oldOwner, const QString & newOwner) +{ + Q_UNUSED(oldOwner) + + if (serviceName == ACTIVITY_MANAGER_DBUS_PATH) { + emit presenceChanged(!newOwner.isEmpty()); + } +} + +} // namespace KActivities + diff --git a/kparts/private/libkactivities/manager_p.h b/kparts/private/libkactivities/manager_p.h new file mode 100644 index 0000000..b92a94f --- /dev/null +++ b/kparts/private/libkactivities/manager_p.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 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_MANAGER_P_ +#define ACTIVITIES_MANAGER_P_ + +#include "activitymanager_interface.h" + +#include + +namespace KActivities { + +class Manager: public org::kde::ActivityManager { + Q_OBJECT +public: + static Manager * self(); + + static bool isActivityServiceRunning(); + +public Q_SLOTS: + void serviceOwnerChanged(const QString & serviceName, const QString & oldOwner, const QString & newOwner); + +Q_SIGNALS: + void presenceChanged(bool present); + +private: + Manager(); + + QDBusServiceWatcher m_watcher; + + static Manager * s_instance; +}; + +} // namespace KActivities + +#endif // ACTIVITIES_MANAGER_P_ diff --git a/kparts/private/libkactivities/org.kde.ActivityManager.xml b/kparts/private/libkactivities/org.kde.ActivityManager.xml new file mode 100644 index 0000000..07a5b34 --- /dev/null +++ b/kparts/private/libkactivities/org.kde.ActivityManager.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kparts/private/libkactivities/resourceinstance.cpp b/kparts/private/libkactivities/resourceinstance.cpp new file mode 100644 index 0000000..6bf3925 --- /dev/null +++ b/kparts/private/libkactivities/resourceinstance.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2011 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. + */ + +#include "resourceinstance.h" +#include "manager_p.h" + +#include + +namespace KActivities { + +#ifdef Q_OS_WIN64 +__inline int toInt(WId wid) +{ + return (int)((__int64)wid); +} + +#else +__inline int toInt(WId wid) +{ + return (int)wid; +} +#endif + +class ResourceInstancePrivate { +public: + WId wid; + ResourceInstance::AccessReason reason; + QUrl uri; + QString mimetype; + QString title; + QString application; + + void closeResource(); + void openResource(); + + enum Type { + Accessed = 0, + Opened = 1, + Modified = 2, + Closed = 3, + FocusedIn = 4, + FocusedOut = 5 + }; + + static void registerResourceEvent(const QString &application, WId wid, const QUrl &uri, Type event, ResourceInstance::AccessReason reason) + { + Manager::self()->RegisterResourceEvent(application, toInt(wid), uri.toString(), uint(event), uint(reason)); + } +}; + +void ResourceInstancePrivate::closeResource() +{ + registerResourceEvent(application, wid, uri, Closed, reason); +} + +void ResourceInstancePrivate::openResource() +{ + registerResourceEvent(application, wid, uri, Opened, reason); +} + +ResourceInstance::ResourceInstance(WId wid, AccessReason reason, const QString &application, QObject *parent) + : QObject(parent), d(new ResourceInstancePrivate()) +{ + d->wid = wid; + d->reason = reason; + d->application = application.isEmpty() ? QCoreApplication::instance()->applicationName() : application; + +} + +ResourceInstance::ResourceInstance(WId wid, QUrl resourceUri, const QString &mimetype, const QString &title, AccessReason reason, const QString &application, QObject *parent) + : QObject(parent), d(new ResourceInstancePrivate()) +{ + d->wid = wid; + d->reason = reason; + d->uri = resourceUri; + d->mimetype = mimetype; + d->title = title; + d->application = application.isEmpty() ? QCoreApplication::instance()->applicationName() : application; + + d->openResource(); +} + +ResourceInstance::~ResourceInstance() +{ + d->closeResource(); + delete d; +} + +void ResourceInstance::notifyModified() +{ + d->registerResourceEvent(d->application, d->wid, d->uri, ResourceInstancePrivate::Modified, d->reason); +} + +void ResourceInstance::notifyFocusedIn() +{ + d->registerResourceEvent(d->application, d->wid, d->uri, ResourceInstancePrivate::FocusedIn, d->reason); +} + +void ResourceInstance::notifyFocusedOut() +{ + d->registerResourceEvent(d->application, d->wid, d->uri, ResourceInstancePrivate::FocusedOut, d->reason); +} + +void ResourceInstance::setUri(const QUrl &newUri) +{ + if (d->uri == newUri) + return; + + if (!d->uri.isEmpty()) { + d->closeResource(); + } + + d->uri = newUri; + + d->openResource(); +} + +void ResourceInstance::setMimetype(const QString &mimetype) +{ + d->mimetype = mimetype; + // TODO: update the service info + Manager::self()->RegisterResourceMimeType(d->uri.toString(), mimetype); +} + +void ResourceInstance::setTitle(const QString &title) +{ + d->title = title; + // TODO: update the service info + Manager::self()->RegisterResourceTitle(d->uri.toString(), title); +} + +QUrl ResourceInstance::uri() const +{ + return d->uri; +} + +QString ResourceInstance::mimetype() const +{ + return d->mimetype; +} + +QString ResourceInstance::title() const +{ + return d->title; +} + +WId ResourceInstance::winId() const +{ + return d->wid; +} + +ResourceInstance::AccessReason ResourceInstance::accessReason() const +{ + return d->reason; +} + +void ResourceInstance::notifyAccessed(const QUrl &uri, const QString &application) +{ + ResourceInstancePrivate::registerResourceEvent( + application.isEmpty() ? QCoreApplication::instance()->applicationName() : application, + 0, uri, ResourceInstancePrivate::Accessed, User); +} + +} // namespace KActivities diff --git a/kparts/private/libkactivities/resourceinstance.h b/kparts/private/libkactivities/resourceinstance.h new file mode 100644 index 0000000..d1cbab4 --- /dev/null +++ b/kparts/private/libkactivities/resourceinstance.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2011 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_RESOURCEINSTANCE_H_ +#define ACTIVITIES_RESOURCEINSTANCE_H_ + +#include +#include +#include + +#include + +namespace KActivities { + +class ResourceInstancePrivate; + +/** + * This class is used to notify the system that a file, web page + * or some other resource has been accessed. + * + * It provides methods to notify the system when the resource was + * opened, modified and closed, along with in what window the + * resource is shown. + * + * You should create an instance of this class for every resource + * you open. + * + * "The system" in this case can be the backend for tracking + * and automatically scoring files that are being accessed, the + * system to show the open files per window in the taskbar, + * the share-like-connect, etc. + * + * The user of this class shouldn't care about the backend + * systems - everything is done under-the-hood automatically. + * + */ +class KDE_EXPORT ResourceInstance: public QObject +{ + Q_OBJECT + + Q_PROPERTY(QUrl uri READ uri WRITE setUri) + Q_PROPERTY(QString mimetype READ mimetype WRITE setMimetype) + Q_PROPERTY(QString title READ title WRITE setTitle) + Q_PROPERTY(WId winId READ winId) + Q_PROPERTY(AccessReason accessReason READ accessReason) + +public: + /*** + * The reason for opening the resource + */ + enum AccessReason { + User = 0, ///< Due to an explicit user request + Scheduled = 1, ///< As a result of a user-scheduled action + Heuristic = 2, ///< Deduced from user's activity, or indirectly requested + System = 3, ///< Due to a system event + World = 4 ///< Due to an action performed by an external entity + }; + Q_ENUMS(AccessReason) + + /** + * Creates a new resource instance + * @param wid id of the window that will show the resource + * @param reason reason for opening the resource + * @param application application's name (the name used for the .desktop file). + * If not specified, QCoreApplication::applicationName is used + * @param parent pointer to the parent object + */ + ResourceInstance(WId wid, AccessReason reason = User, const QString &application = QString(), QObject *parent = 0); + + /** + * Creates a new resource instance and automatically + * notifies the system that it was opened. + * + * In some special cases, where the URI of the resource is + * being constantly changed (for example, in the world globe, + * street map applications) you have two options: + * - to pass an empty resourceUri while passing the mimetype + * - to update the uri from time to time (in the example of + * the world map - to send URIs for major objects - cities + * or main streets. + * and in both cases reimplementing the currentUri() method + * which will return the exact URI shown at that specific moment. + * + * @param wid window id in which the resource is shown + * @param resourceUri URI of the resource that is shown + * @param mimetype the mime type of the resource + * @param title the title of the resource + * @param reason reason for opening the resource + * @param application application's name (the name used for the .desktop file). + * If not specified, QCoreApplication::applicationName is used + * @param parent pointer to the parent object + */ + ResourceInstance(WId wid, QUrl resourceUri, const QString &mimetype = QString(), const QString &title = QString(), AccessReason reason = User, const QString &application = QString(), QObject *parent = 0); + + /** + * Destroys the ResourceInstance and notifies the system + * that the resource has been closed + */ + ~ResourceInstance(); + +public Q_SLOTS: + /** + * Call this method to notify the system that you modified + * (the contents of) the resource + */ + void notifyModified(); + + /** + * Call this method to notify the system that the resource + * has the focus in your application + * @note You only need to call this in MDI applications + */ + void notifyFocusedIn(); + + /** + * Call this method to notify the system that the resource + * lost the focus in your application + * @note You only need to call this in MDI applications + */ + void notifyFocusedOut(); + + /** + * This is a convenience method that sets the new URI. + * This is usually handled by sending the close event for + * the previous URI, and an open event for the new one. + */ + void setUri(const QUrl &newUri); + + /** + * Sets the mimetype for this resource + */ + void setMimetype(const QString &mimetype); + + /** + * Sets the title for this resource + */ + void setTitle(const QString &title); + +Q_SIGNALS: + /** + * Emitted when the system wants to show the resource + * represented by this ResourceInstance. + * + * You should listen to this signal if you have multiple + * resources shown in one window (MDI). On catching it, show + * the resource and give it focus. + */ + void requestsFocus(); + +public: + /** + * @returns the current uri + * The default implementation returns the URI that was passed + * to the constructor. + * You need to reimplement it only for the applications with + * frequently updated URIs. + */ + virtual QUrl uri() const; + + /** + * @returns mimetype of the resource + */ + QString mimetype() const; + + /** + * @returns title of the resource + */ + QString title() const; + + /** + * @returns the window id + */ + WId winId() const; + + /** + * @returns the reason for accessing the resource + */ + AccessReason accessReason() const; + + /** + * If there's no way to tell for how long an application is keeping + * the resource open, you can just call this static method - it + * will notify the system that the application has accessed the + * resource + * @param uri URI of the resource + * @param application application's name (the name used for the .desktop file). + * If not specified, QCoreApplication::applicationName is used + * + */ + static void notifyAccessed(const QUrl &uri, const QString &application = QString()); + +private: + ResourceInstancePrivate * const d; +}; + +} + +#endif // ACTIVITIES_RESOURCEINSTANCE_H_