aboutsummaryrefslogtreecommitdiff
path: root/src/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'src/extensions')
-rw-r--r--src/extensions/applicationextension/mapplicationextensionarea.cpp4
-rw-r--r--src/extensions/applicationextension/mapplicationextensionarea.h4
-rw-r--r--src/extensions/applicationextension/mapplicationextensionareaview.cpp5
-rw-r--r--src/extensions/applicationextension/mapplicationextensionmanager.cpp171
-rw-r--r--src/extensions/applicationextension/mapplicationextensionmanager.h76
-rw-r--r--src/extensions/applicationextension/mapplicationextensionmetadata.cpp16
-rw-r--r--src/extensions/applicationextension/mapplicationextensionmetadata.h2
-rw-r--r--src/extensions/applicationextension/mextensionareaview.cpp27
-rw-r--r--src/extensions/applicationextension/mextensionrunner.cpp6
-rw-r--r--src/extensions/extensions.pro5
-rw-r--r--src/extensions/mashup/mashup/mappletinstancemanager.cpp73
-rw-r--r--src/extensions/mashup/mashup/mappletinstancemanager.h13
-rw-r--r--src/extensions/mextensionwatcher.cpp68
-rw-r--r--src/extensions/mextensionwatcher.h98
14 files changed, 467 insertions, 101 deletions
diff --git a/src/extensions/applicationextension/mapplicationextensionarea.cpp b/src/extensions/applicationextension/mapplicationextensionarea.cpp
index f06a9545..63215ea9 100644
--- a/src/extensions/applicationextension/mapplicationextensionarea.cpp
+++ b/src/extensions/applicationextension/mapplicationextensionarea.cpp
@@ -42,8 +42,8 @@ void MApplicationExtensionAreaPrivate::init(const QString &interface)
{
Q_Q(MApplicationExtensionArea);
extensionManager = QSharedPointer<MApplicationExtensionManager>(new MApplicationExtensionManager(interface));
- QObject::connect(extensionManager.data(), SIGNAL(extensionInstantiated(MApplicationExtensionInterface *)), q, SIGNAL(extensionInstantiated(MApplicationExtensionInterface *)), Qt::QueuedConnection);
- QObject::connect(extensionManager.data(), SIGNAL(extensionRemoved(MApplicationExtensionInterface*)), q, SIGNAL(extensionRemoved(MApplicationExtensionInterface*)), Qt::QueuedConnection);
+ QObject::connect(extensionManager.data(), SIGNAL(extensionInstantiated(MApplicationExtensionInterface *)), q, SIGNAL(extensionInstantiated(MApplicationExtensionInterface *)));
+ QObject::connect(extensionManager.data(), SIGNAL(extensionRemoved(MApplicationExtensionInterface*)), q, SIGNAL(extensionRemoved(MApplicationExtensionInterface*)));
QObject::connect(extensionManager.data(), SIGNAL(widgetCreated(QGraphicsWidget*, MDataStore&)), q, SLOT(addWidget(QGraphicsWidget*, MDataStore&)));
QObject::connect(extensionManager.data(), SIGNAL(widgetRemoved(QGraphicsWidget*)), q, SLOT(removeWidget(QGraphicsWidget*)));
}
diff --git a/src/extensions/applicationextension/mapplicationextensionarea.h b/src/extensions/applicationextension/mapplicationextensionarea.h
index a443a3ff..d068cee9 100644
--- a/src/extensions/applicationextension/mapplicationextensionarea.h
+++ b/src/extensions/applicationextension/mapplicationextensionarea.h
@@ -94,7 +94,9 @@ public:
/*!
* Initializes the application extension area. All setters introduced by
- * this class must be called before the area is initialized. Initialization
+ * this class must be called before the area is initialized, and the
+ * signals must be connected, because calling init() will result in
+ * the extensions being created. Initialization
* will fail if no interface name has been provided or if the area has
* already been initialized.
*
diff --git a/src/extensions/applicationextension/mapplicationextensionareaview.cpp b/src/extensions/applicationextension/mapplicationextensionareaview.cpp
index 5253a28a..c27ccdbf 100644
--- a/src/extensions/applicationextension/mapplicationextensionareaview.cpp
+++ b/src/extensions/applicationextension/mapplicationextensionareaview.cpp
@@ -38,8 +38,11 @@ void MApplicationExtensionAreaViewPrivate::init(MApplicationExtensionArea *contr
{
this->controller = controller;
- layout = new QGraphicsLinearLayout(Qt::Vertical);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
controller->setLayout(layout);
+ this->layout = layout;
}
void MApplicationExtensionAreaViewPrivate::addToLayout(QGraphicsWidget *widget, int index)
diff --git a/src/extensions/applicationextension/mapplicationextensionmanager.cpp b/src/extensions/applicationextension/mapplicationextensionmanager.cpp
index 9da4d619..637e493a 100644
--- a/src/extensions/applicationextension/mapplicationextensionmanager.cpp
+++ b/src/extensions/applicationextension/mapplicationextensionmanager.cpp
@@ -28,6 +28,7 @@
#include "mdesktopentry.h"
#include "mextensionhandle.h"
#include "mfiledatastore.h"
+#include "msubdatastore.h"
#include "mdebug.h"
MApplicationExtensionManager::MApplicationExtensionManager(const QString &interface) :
@@ -76,15 +77,34 @@ bool MApplicationExtensionManager::init()
updateAvailableExtensions(APPLICATION_EXTENSION_DATA_DIR);
// Start watching the application extensions directory for changes
- connect(&watcher, SIGNAL(directoryChanged(const QString)), this, SLOT(updateAvailableExtensions(QString)));
- watcher.addPath(APPLICATION_EXTENSION_DATA_DIR);
-
+ connectSignals();
+ desktopDirectoryWatcher.addPath(APPLICATION_EXTENSION_DATA_DIR);
return true;
}
+void MApplicationExtensionManager::parseAndInstantiateExtension(
+ const QString& desktopFile,
+ QSet<QString>* currentExtensionsList)
+{
+ QSharedPointer<const MApplicationExtensionMetaData>
+ metadata(new MApplicationExtensionMetaData(desktopFile));
+ if (metadata->isValid() && metadata->type() == "X-MeeGoApplicationExtension" && metadata->interface() == interface) {
+ if (currentExtensionsList != NULL) {
+ currentExtensionsList->insert(desktopFile);
+ }
+ if (!extensionMetaDatas.contains(desktopFile)) {
+ // This extension is a new one. Instantiate it
+ if (instantiateExtension(metadata)) {
+ extensionMetaDatas[desktopFile] = metadata;
+ }
+ }
+ }
+}
+
void MApplicationExtensionManager::updateAvailableExtensions(const QString &path)
{
- QList<QString> currentExtensionsList;
+ disconnectSignals();
+ QSet<QString> currentExtensionsList;
QDir applicationExtensionsDir(path);
if (applicationExtensionsDir.exists()) {
@@ -92,33 +112,38 @@ void MApplicationExtensionManager::updateAvailableExtensions(const QString &path
filter << "*.desktop";
foreach(const QString &fileName, applicationExtensionsDir.entryList(filter, QDir::Files)) {
const QString desktopFile = QFileInfo(applicationExtensionsDir, fileName).absoluteFilePath();
- QSharedPointer<MApplicationExtensionMetaData> metadata(new MApplicationExtensionMetaData(desktopFile));
- if (metadata->isValid() && metadata->type() == "X-MeeGoApplicationExtension" && metadata->interface() == interface) {
- currentExtensionsList.append(fileName);
-
- if (!extensionMetaDatas.contains(fileName)) {
- // This extension is a new one. Instantiate it
- if (instantiateExtension(*metadata.data())) {
- extensionMetaDatas[fileName] = metadata;
- }
- }
- }
+ parseAndInstantiateExtension(desktopFile,
+ &currentExtensionsList);
}
-
// Find what extensions got removed
- QList<QString> toBeRemovedExtensions;
+ QSet<QString> toBeRemovedExtensions;
MetaDataEntryHash::const_iterator itEnd = extensionMetaDatas.constEnd();
for (MetaDataEntryHash::const_iterator it = extensionMetaDatas.constBegin(); it != itEnd; ++it) {
if (!currentExtensionsList.contains(it.key())) {
- toBeRemovedExtensions.append(it.key());
+ toBeRemovedExtensions.insert(it.key());
}
}
// Remove extensions that no longer exist
foreach (const QString &fileName, toBeRemovedExtensions) {
- removeExtension(*extensionMetaDatas[fileName].data());
- extensionMetaDatas.remove(fileName);
+ removeExtension(*extensionMetaDatas[fileName]);
}
}
+ connectSignals();
+}
+
+void MApplicationExtensionManager::updateExtension(
+ const MDesktopEntry &extensionData)
+{
+ const MApplicationExtensionMetaData* metadata =
+ dynamic_cast<const MApplicationExtensionMetaData*>(&extensionData);
+ if (!metadata) {
+ return;
+ }
+ disconnectSignals();
+ QString fileName = metadata->fileName();
+ removeExtension(*metadata);
+ parseAndInstantiateExtension(fileName, NULL);
+ connectSignals();
}
bool MApplicationExtensionManager::isInProcess(const MApplicationExtensionMetaData &metaData)
@@ -126,25 +151,28 @@ bool MApplicationExtensionManager::isInProcess(const MApplicationExtensionMetaDa
return metaData.runnerBinary().isEmpty();
}
-bool MApplicationExtensionManager::instantiateExtension(const MApplicationExtensionMetaData &metadata)
+bool MApplicationExtensionManager::instantiateExtension(QSharedPointer<const MApplicationExtensionMetaData> &metadata)
{
bool success = false;
- if (isInProcess(metadata)) {
- if (metadata.fileName().indexOf(inProcessFilter) >= 0) {
- success = instantiateInProcessExtension(metadata.extensionBinary());
+ if (isInProcess(*metadata)) {
+ if (metadata->fileName().indexOf(inProcessFilter) >= 0) {
+ success = instantiateInProcessExtension(metadata);
}
} else {
- if (metadata.fileName().indexOf(outOfProcessFilter) >= 0) {
+ if (metadata->fileName().indexOf(outOfProcessFilter) >= 0) {
success = instantiateOutOfProcessExtension(metadata);
}
}
-
+ if (success) {
+ extensionWatcher.addExtension(metadata);
+ }
return success;
}
-bool MApplicationExtensionManager::instantiateInProcessExtension(const QString &binary)
+bool MApplicationExtensionManager::instantiateInProcessExtension(QSharedPointer<const MApplicationExtensionMetaData> &metadata)
{
+ QString binary = metadata->extensionBinary();
QPluginLoader loader(binary);
QObject *object = loader.instance();
@@ -157,14 +185,16 @@ bool MApplicationExtensionManager::instantiateInProcessExtension(const QString &
if (success) {
QGraphicsWidget *widget = extension->widget();
if (widget) {
- // Inform about the added extension widget
- emit widgetCreated(widget, *extensionDataStore.data());
+ QString tmp = metadata->fileName();
+ QSharedPointer<MDataStore> dataStore =
+ createSubDataStore(*metadata);
+ inProcessDataStores[metadata.data()] = dataStore;
+ emit widgetCreated(widget, *dataStore);
}
+ // Store the instantiated extension
+ inProcessExtensions[metadata.data()] = qMakePair(extension, widget);
// Inform interested parties about the new extension
emit extensionInstantiated(extension);
-
- // Store the instantiated extension
- inProcessExtensions[binary] = qMakePair(extension, widget);
}
}
}
@@ -176,12 +206,15 @@ bool MApplicationExtensionManager::instantiateInProcessExtension(const QString &
return success;
}
-bool MApplicationExtensionManager::instantiateOutOfProcessExtension(const MApplicationExtensionMetaData &metadata)
+bool MApplicationExtensionManager::instantiateOutOfProcessExtension(
+ QSharedPointer<const MApplicationExtensionMetaData> &metadata)
{
MExtensionHandle *handle = new MExtensionHandle;
- handle->init(metadata.runnerBinary(), metadata.fileName());
- outOfProcessHandles.insert(metadata.fileName(), handle);
- emit widgetCreated(handle, *extensionDataStore.data());
+ handle->init(metadata->runnerBinary(), metadata->fileName());
+ outOfProcessHandles.insert(metadata.data(), handle);
+ QSharedPointer<MDataStore> dataStore = createSubDataStore(*metadata);
+ outOfProcessDataStores[metadata.data()] = dataStore;
+ emit widgetCreated(handle, *dataStore);
return true;
}
@@ -194,35 +227,41 @@ QString MApplicationExtensionManager::dataPath() const
void MApplicationExtensionManager::removeExtension(const MApplicationExtensionMetaData &metadata)
{
+ QString fileName = metadata.fileName();
if (isInProcess(metadata)) {
- removeInProcessExtension(metadata.extensionBinary());
+ removeInProcessExtension(metadata);
} else {
removeOutOfProcessExtension(metadata);
}
+ extensionMetaDatas.remove(fileName);
+ extensionWatcher.removeExtension(metadata.fileName());
}
-void MApplicationExtensionManager::removeInProcessExtension(const QString &binary)
+void MApplicationExtensionManager::removeInProcessExtension(
+ const MApplicationExtensionMetaData &metadata)
{
- if (inProcessExtensions.contains(binary)) {
- InProcessExtensionData extension = inProcessExtensions.take(binary);
+ if (inProcessExtensions.contains(&metadata)) {
+ InProcessExtensionData extension = inProcessExtensions.take(&metadata);
emit extensionRemoved(extension.first);
if (extension.second) {
emit widgetRemoved(extension.second);
}
+ inProcessDataStores.remove(&metadata);
delete extension.first;
+ QPluginLoader loader(metadata.extensionBinary());
+ loader.unload();
}
}
void MApplicationExtensionManager::removeOutOfProcessExtension(const MApplicationExtensionMetaData &metadata)
{
QString desktopFileName = metadata.fileName();
- if (outOfProcessHandles.contains(desktopFileName)) {
- MExtensionHandle *handle = outOfProcessHandles.take(desktopFileName);
- if (handle) {
- emit widgetRemoved(handle);
- handle->kill();
- delete handle;
- }
+ MExtensionHandle *handle = outOfProcessHandles.take(&metadata);
+ if (handle) {
+ emit widgetRemoved(handle);
+ handle->kill();
+ outOfProcessDataStores.remove(&metadata);
+ delete handle;
}
}
@@ -259,3 +298,41 @@ bool MApplicationExtensionManager::createDataStore()
return false;
}
}
+
+QSharedPointer<MDataStore> MApplicationExtensionManager::createSubDataStore(
+ const MApplicationExtensionMetaData &metadata)
+{
+ return QSharedPointer<MDataStore>(
+ new MSubDataStore(
+ metadata.fileName().replace('/', '\\')
+ + QString("/"), *extensionDataStore));
+}
+
+void MApplicationExtensionManager::connectSignals()
+{
+ connect(&extensionWatcher,
+ SIGNAL(extensionChanged(
+ const MDesktopEntry &)),
+ this,
+ SLOT(updateExtension(
+ const MDesktopEntry &)));
+ connect(&desktopDirectoryWatcher,
+ SIGNAL(directoryChanged(const QString)),
+ this,
+ SLOT(updateAvailableExtensions(QString)));
+}
+
+void MApplicationExtensionManager::disconnectSignals()
+{
+ disconnect(&extensionWatcher,
+ SIGNAL(extensionChanged(
+ const MDesktopEntry &)),
+ this,
+ SLOT(updateExtension(
+ const MDesktopEntry &)));
+ disconnect(&desktopDirectoryWatcher,
+ SIGNAL(directoryChanged(const QString)),
+ this,
+ SLOT(updateAvailableExtensions(QString)));
+}
+
diff --git a/src/extensions/applicationextension/mapplicationextensionmanager.h b/src/extensions/applicationextension/mapplicationextensionmanager.h
index 5eb80e1e..99acbe0b 100644
--- a/src/extensions/applicationextension/mapplicationextensionmanager.h
+++ b/src/extensions/applicationextension/mapplicationextensionmanager.h
@@ -24,8 +24,8 @@
#include <QFileSystemWatcher>
#include <QHash>
#include <QSharedPointer>
-#include <QHash>
#include <QRegExp>
+#include "mextensionwatcher.h"
class MApplicationExtensionMetaData;
class MDataStore;
@@ -124,13 +124,22 @@ private slots:
*/
void updateAvailableExtensions(const QString &path);
+ /*!
+ * \brief Slot for updating an extension when the files for the extension
+ * have been updated.
+ * \param extensionData the extension to update
+ */
+ void updateExtension(const MDesktopEntry &extensionData);
+
private:
//! Whether the manager has been initialized or not
bool initialized;
//! A file system watcher for the desktop entry file directory
- QFileSystemWatcher watcher;
+ QFileSystemWatcher desktopDirectoryWatcher;
+ //! An extension watcher for observing modifications to the extensions
+ MExtensionWatcher extensionWatcher;
//! The name of the interface extensions to be instantiated should implement
QString interface;
@@ -145,13 +154,19 @@ private:
typedef QPair<MApplicationExtensionInterface*, QGraphicsWidget*> InProcessExtensionData;
- //! Instantiated in-process extensions. A map from the shared library name to the extension instance.
- QHash<QString, InProcessExtensionData> inProcessExtensions;
+ //! In-process extensions and datastores
+ QHash<const MApplicationExtensionMetaData*, InProcessExtensionData> inProcessExtensions;
+
+ QHash<const MApplicationExtensionMetaData*,
+ QSharedPointer<MDataStore> > inProcessDataStores;
- //! Hash of desktop file name versus the widget (handle) created
- QHash<QString, MExtensionHandle*> outOfProcessHandles;
+ //! Ouf-of-process extensions and datastores
+ QHash<const MApplicationExtensionMetaData*, MExtensionHandle*> outOfProcessHandles;
- typedef QHash<QString, QSharedPointer<MApplicationExtensionMetaData> > MetaDataEntryHash;
+ QHash<const MApplicationExtensionMetaData*, QSharedPointer<MDataStore> >
+ outOfProcessDataStores;
+
+ typedef QHash<QString, QSharedPointer<const MApplicationExtensionMetaData> > MetaDataEntryHash;
/*!
* A container for application extension desktop entries with the correct application extension interface defined.
* This container also only contains the entries that succeeded to instantiate.
@@ -179,38 +194,67 @@ private:
bool createDataStore();
/*!
+ * Creates a subdatastore for an extension
+ * \param metaData Metadata for the extension
+ */
+ QSharedPointer<MDataStore> createSubDataStore(
+ const MApplicationExtensionMetaData &metaData);
+ /*!
+ * Connects the signals for the directory watcher and the extension
+ * watcher.
+ */
+ void connectSignals();
+ /*!
+ * Disconnects the signals for the directory watcher and the extension
+ * watcher.
+ */
+ void disconnectSignals();
+
+ /*!
+ * Creates extension metadata and instantiates an extension
+ * if it isn't already instantiated.
+ * \param desktopFile Full path of the desktop file to parse.
+ * \param currentExtensionsList List of current extensions.
+ * Used by updateAvailableExtensions to keep track of which
+ * extensions exist and which need to be removed.
+ */
+ void parseAndInstantiateExtension(const QString& desktopFile,
+ QSet<QString>* currentExtensionsList);
+ /*!
* Instantiate an extension for an application extension metadata
* \param metadata the metadata object of the extension
* \return \c true if extension instantiated succesfully, \c false otherwise
*/
- bool instantiateExtension(const MApplicationExtensionMetaData &metadata);
+ bool instantiateExtension(
+ QSharedPointer<const MApplicationExtensionMetaData> &metadata);
/*!
* Instantiates an in process extension.
- *
- * \param binary the name of the in process extension binary
+ * \param metadata metadata for the extension
* \return \c true if the instantiation succeeds, \c false otherwise
*/
- bool instantiateInProcessExtension(const QString &binary);
+ bool instantiateInProcessExtension(
+ QSharedPointer<const MApplicationExtensionMetaData> &metadata);
/*!
* Instantiate out of process extensions
- * \param metadata for the extension
+ * \param metadata metadata for the extension
* \return bool True if extension instantiated, else return false
*/
- bool instantiateOutOfProcessExtension(const MApplicationExtensionMetaData &metadata);
+ bool instantiateOutOfProcessExtension(
+ QSharedPointer<const MApplicationExtensionMetaData> &metadata);
/*!
* Removes an extension that was defined in the desktop entry given as a parameter.
- * \param metadata the relevant metadata.
+ * \param metadata metadata for the extension
*/
void removeExtension(const MApplicationExtensionMetaData &metadata);
/*!
* Removes an in process extension that was loaded from the specified library.
- * \param library the path name to the library
+ * \param metadata metadata for the extension
*/
- void removeInProcessExtension(const QString &library);
+ void removeInProcessExtension(const MApplicationExtensionMetaData &metadata);
/*!
* Removes an out of process extension that was loaded from the specified metadata
diff --git a/src/extensions/applicationextension/mapplicationextensionmetadata.cpp b/src/extensions/applicationextension/mapplicationextensionmetadata.cpp
index cd73f112..81d11d91 100644
--- a/src/extensions/applicationextension/mapplicationextensionmetadata.cpp
+++ b/src/extensions/applicationextension/mapplicationextensionmetadata.cpp
@@ -21,9 +21,9 @@
#include <QDir>
#include <MDebug>
-const QString ExtensionBinaryKey("X-MeeGoApplicationExtension/Extension");
-const QString IdentifierKey("X-MeeGoApplicationExtension/Identifier");
-const QString InterfaceKey("X-MeeGoApplicationExtension/Interface");
+const QString EXTENSION_BINARY_KEY("X-MeeGoApplicationExtension/Extension");
+const QString IDENTIFIER_KEY("X-MeeGoApplicationExtension/Identifier");
+const QString INTERFACE_KEY("X-MeeGoApplicationExtension/Interface");
MApplicationExtensionMetaData::MApplicationExtensionMetaData(const QString &fileName) : MDesktopEntry(fileName)
{
@@ -42,7 +42,7 @@ bool MApplicationExtensionMetaData::isValid() const
// Loop through keys and check that all are found
QStringList requiredKeys;
- requiredKeys << ExtensionBinaryKey << InterfaceKey;
+ requiredKeys << EXTENSION_BINARY_KEY << INTERFACE_KEY;
foreach(const QString &key, requiredKeys) {
if (!contains(key)) {
return false;
@@ -80,7 +80,7 @@ QString MApplicationExtensionMetaData::runnerBinary() const
QString MApplicationExtensionMetaData::extensionBinary() const
{
// Fetch the absolute file path and return it.
- QFileInfo extension(QString(APPLICATION_EXTENSION_LIBS), value(ExtensionBinaryKey));
+ QFileInfo extension(QString(APPLICATION_EXTENSION_LIBS), value(EXTENSION_BINARY_KEY));
if (extension.exists() && extension.isFile()) {
return extension.absoluteFilePath();
} else {
@@ -91,7 +91,7 @@ QString MApplicationExtensionMetaData::extensionBinary() const
QString MApplicationExtensionMetaData::interface() const
{
- return value(InterfaceKey);
+ return value(INTERFACE_KEY);
}
QString MApplicationExtensionMetaData::extractLibraryName(const QString &libFileName)
@@ -114,8 +114,8 @@ QString MApplicationExtensionMetaData::resourceIdentifier() const
QString resourceId;
QString binary = extensionBinary();
- if (contains(IdentifierKey)) {
- resourceId = value(IdentifierKey);
+ if (contains(IDENTIFIER_KEY)) {
+ resourceId = value(IDENTIFIER_KEY);
} else if (!binary.isNull()) {
resourceId = extractLibraryName(binary);
} else {
diff --git a/src/extensions/applicationextension/mapplicationextensionmetadata.h b/src/extensions/applicationextension/mapplicationextensionmetadata.h
index 6ee05884..f3651182 100644
--- a/src/extensions/applicationextension/mapplicationextensionmetadata.h
+++ b/src/extensions/applicationextension/mapplicationextensionmetadata.h
@@ -55,7 +55,7 @@ public:
* file in that is given as a construction parameter.
* \param filename Location of .desktop file to be read by constructed MApplicationExtensionMetaData instance.
*/
- MApplicationExtensionMetaData(const QString &filename);
+ explicit MApplicationExtensionMetaData(const QString &filename);
/*!
* Destructor
diff --git a/src/extensions/applicationextension/mextensionareaview.cpp b/src/extensions/applicationextension/mextensionareaview.cpp
index ad89c7c2..a1aadefb 100644
--- a/src/extensions/applicationextension/mextensionareaview.cpp
+++ b/src/extensions/applicationextension/mextensionareaview.cpp
@@ -24,6 +24,8 @@
#include "mdatastore.h"
#include "mcontainer.h"
+static const QString LAYOUT_INDEX = "layoutIndex";
+
MExtensionAreaViewPrivate::MExtensionAreaViewPrivate()
: controller(0),
layout(0),
@@ -80,8 +82,8 @@ void MExtensionAreaViewPrivate::updateData()
// Change the data in the store if item is still valid and geometry has changed.
if (centralWidget != NULL && dsMap->contains(centralWidget) &&
- (*dsMap)[centralWidget]->value("layoutIndex") != i) {
- (*dsMap)[centralWidget]->createValue("layoutIndex", i);
+ (*dsMap)[centralWidget]->value(LAYOUT_INDEX) != i) {
+ (*dsMap)[centralWidget]->createValue(LAYOUT_INDEX, i);
}
}
}
@@ -114,7 +116,8 @@ void MExtensionAreaViewPrivate::updateLayout()
bool alreadyInLayout = false;
const int count = layout->count();
for (int i = 0; i < count; ++i) {
- MContainer *theContainer = dynamic_cast<MContainer *>(layout->itemAt(i));
+ MContainer *theContainer =
+ dynamic_cast<MContainer *>(layout->itemAt(i));
if (widget == theContainer->centralWidget()) {
// Widget found from the layout, don't add again
alreadyInLayout = true;
@@ -131,21 +134,19 @@ void MExtensionAreaViewPrivate::updateLayout()
if (container) {
setContainerEnabled(*container, q->style()->containerMode());
}
-
- int layoutIndex = 0;
-
// Add widget to the layout policy
- if (store->allKeys().contains("layoutIndex") &&
- store->value("layoutIndex").type() == QVariant::Int) {
- layoutIndex = store->value("layoutIndex").toInt();
- addToLayout(container, layoutIndex);
+ int layoutIndex = 0;
+ bool layoutIndexFound = false;
+ int tmpIndex =
+ store->value(LAYOUT_INDEX).toInt(&layoutIndexFound);
+ if (layoutIndexFound) {
+ layoutIndex = tmpIndex;
} else {
layoutIndex = layout->count();
- addToLayout(container);
}
-
+ addToLayout(container, layoutIndex);
// Write the layout data to the permanent store
- store->createValue("layoutIndex", layoutIndex);
+ store->createValue(LAYOUT_INDEX, layoutIndex);
}
}
}
diff --git a/src/extensions/applicationextension/mextensionrunner.cpp b/src/extensions/applicationextension/mextensionrunner.cpp
index 4cbebff0..805874df 100644
--- a/src/extensions/applicationextension/mextensionrunner.cpp
+++ b/src/extensions/applicationextension/mextensionrunner.cpp
@@ -167,7 +167,6 @@ bool MExtensionRunner::init(const QString &serverName)
teardown();
return false;
}
-
return true;
}
@@ -383,10 +382,7 @@ void MExtensionRunner::createAppletPixmap(Qt::HANDLE handle)
pixmap = QPixmap::fromX11Pixmap(handle, QPixmap::ExplicitlyShared);
#ifdef QT_OPENGL_LIB
- // Try to use opengl to render directly to the pixmap
- if (context != NULL)
- delete context;
-
+ // The QGLWidget takes the ownership of the context
context = new QGLContext(QGLFormat::defaultFormat(), &pixmap);
context->create();
if (context->isValid()) {
diff --git a/src/extensions/extensions.pro b/src/extensions/extensions.pro
index 3c5a58ce..4798d970 100644
--- a/src/extensions/extensions.pro
+++ b/src/extensions/extensions.pro
@@ -22,6 +22,9 @@ contains(DEFINES, HAVE_DBUS) {
LIBS += -lmeegotouchviews -lmeegotouchsettings -lmeegotouchcore
-SOURCES += mextensionslibrary.cpp
+SOURCES += mextensionwatcher.cpp \
+ mextensionslibrary.cpp
+
+HEADERS += mextensionwatcher.h
include(../common_bot.pri)
diff --git a/src/extensions/mashup/mashup/mappletinstancemanager.cpp b/src/extensions/mashup/mashup/mappletinstancemanager.cpp
index 99f2f11f..2a9ec44d 100644
--- a/src/extensions/mashup/mashup/mappletinstancemanager.cpp
+++ b/src/extensions/mashup/mashup/mappletinstancemanager.cpp
@@ -33,6 +33,8 @@
#include "mscenemanager.h"
#include "morientationtracker.h"
#include "maction.h"
+#include "mextensionwatcher.h"
+#include <algorithm>
const QString MAppletInstanceManager::PACKAGE_MANAGER_DBUS_SERVICE = "com.nokia.package_manager";
const QString MAppletInstanceManager::PACKAGE_MANAGER_DBUS_PATH = "/com/nokia/package_manager";
@@ -50,6 +52,7 @@ MAppletInstanceManager::~MAppletInstanceManager()
{
qDeleteAll(applets.values());
delete fileDataStore;
+ delete watcher;
}
void MAppletInstanceManager::init(const QString &mashupCanvasName, MDataStore *dataStore)
@@ -57,6 +60,7 @@ void MAppletInstanceManager::init(const QString &mashupCanvasName, MDataStore *d
this->applicationName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
this->mashupCanvasName = mashupCanvasName;
this->dataStore = dataStore;
+ this->watcher = new MExtensionWatcher;
if (dataStore == NULL) {
// Create a file datastore if a data store was not provided
@@ -75,6 +79,8 @@ void MAppletInstanceManager::init(const QString &mashupCanvasName, MDataStore *d
// Connect to the system bus to receive the Package Manager signals
QDBusConnection::systemBus().connect(QString(), PACKAGE_MANAGER_DBUS_PATH, PACKAGE_MANAGER_DBUS_INTERFACE, "OperationComplete", this, SLOT(operationComplete(QString, QString, QString)));
+ connect(watcher, SIGNAL(extensionChanged(const MDesktopEntry &)),
+ this, SLOT(updateApplet(const MDesktopEntry &)));
}
bool MAppletInstanceManager::restoreApplets()
@@ -114,6 +120,29 @@ void MAppletInstanceManager::instantiateAppletFromPackage(const QString &package
instantiateApplet(appletId);
}
+/*!
+ * A helper functor class for finding remaining applet instances
+ * after removing one instance
+ */
+struct FindAppletByFileName
+{
+ QString fileName_;
+ /**
+ * Constructs the functor
+ * \param fileName File name to compare against
+ */
+ explicit FindAppletByFileName(const QString& fileName)
+ : fileName_(fileName){
+ }
+ /**
+ * Compares an applet instance against the wanted file name
+ * \param data Instance to compare
+ */
+ bool operator()(const MAppletInstanceData* data) {
+ return data->desktopFile == fileName_;
+ }
+};
+
bool MAppletInstanceManager::removeApplet(MAppletId appletId)
{
// Make sure the applet instance exists in this particular applet instance manager
@@ -121,12 +150,20 @@ bool MAppletInstanceManager::removeApplet(MAppletId appletId)
appletId.mashupCanvasName() == mashupCanvasName && applets.contains(appletId.instanceId())) {
// Get the data for the applet
MAppletInstanceData *data = applets.value(appletId.instanceId());
-
+ QString fileName = data->desktopFile;
// Let interested parties know that the applet's widget should be removed
emit appletRemoved(data->widget);
// Remove the applet instance data
removeAppletInstanceData(appletId);
+
+ if (std::find_if(applets.constBegin(), applets.constEnd(),
+ FindAppletByFileName(fileName))
+ == applets.constEnd()) {
+ // this was the last instance, remove from watcher
+ watcher->removeExtension(data->desktopFile);
+ }
+
return true;
}
@@ -169,21 +206,24 @@ bool MAppletInstanceManager::instantiateApplet(MAppletId appletId)
QFile desktopFile(data->desktopFile);
if ((!data->desktopFile.isEmpty() && desktopFile.exists()) || data->installationStatus == MAppletInstanceData::Installing) {
// The desktop file exists, so the applet is installed or the applet was being installed: instantiate the applet
- MAppletMetaData metadata(data->desktopFile);
- if (metadata.isValid()) {
+ QSharedPointer<const MAppletMetaData>
+ metadata(new MAppletMetaData(data->desktopFile));
+ if (metadata->isValid()) {
// Check whether a runner is defined
bool success;
- if (metadata.runnerBinary().isEmpty()) {
+ if (metadata->runnerBinary().isEmpty()) {
// Runner not defined: create an in-process applet
- success = instantiateInProcessApplet(data, metadata);
+ // IN PROCESS APPLETS ARE NOT FULLY SUPPORTED AT THE MOMENT
+ success = instantiateInProcessApplet(data, *metadata);
} else {
// Runner is defined: create an out-of-process applet
- success = instantiateOutOfProcessApplet(data, metadata);
+ success = instantiateOutOfProcessApplet(data, *metadata);
}
if (success) {
// Notify that the applet placeholder instantiation is done
emit appletInstantiated(data->widget, *data->mashupCanvasDataStore);
+ watcher->addExtension(metadata);
return true;
}
}
@@ -208,6 +248,26 @@ bool MAppletInstanceManager::instantiateApplet(MAppletId appletId)
return false;
}
+void MAppletInstanceManager::updateApplet(const MDesktopEntry &updatedExtension)
+{
+ const MAppletMetaData* metadata =
+ dynamic_cast<const MAppletMetaData*>(&updatedExtension);
+ if (metadata->runnerBinary().isEmpty()) {
+ // Runner not defined: create an in-process applet
+ // IN PROCESS APPLETS ARE NOT FULLY SUPPORTED AT THE MOMENT
+ qWarning() << "In-process applet updates are not supported at the moment";
+ } else {
+ AppletContainerIterator appletIterator(applets);
+ while (appletIterator.hasNext()) {
+ appletIterator.next();
+ if (appletIterator.value()->desktopFile == metadata->fileName()) {
+ MAppletHandle *handle = dynamic_cast<MAppletHandle *>(appletIterator.value()->widget);
+ handle->reinit();
+ }
+ }
+ }
+}
+
bool MAppletInstanceManager::instantiateOutOfProcessApplet(MAppletInstanceData *data, const MAppletMetaData &metadata)
{
// Create an applet handle if one doesn't exist already
@@ -245,6 +305,7 @@ bool MAppletInstanceManager::instantiateOutOfProcessApplet(MAppletInstanceData *
return true;
}
+// IN PROCESS APPLETS ARE NOT FULLY SUPPORTED AT THE MOMENT
bool MAppletInstanceManager::instantiateInProcessApplet(MAppletInstanceData *data, const MAppletMetaData &metadata)
{
MFileDataStore *instanceDataStore = new MFileDataStore(data->instanceDataFilePath);
diff --git a/src/extensions/mashup/mashup/mappletinstancemanager.h b/src/extensions/mashup/mashup/mappletinstancemanager.h
index 52e1067b..b00fc81b 100644
--- a/src/extensions/mashup/mashup/mappletinstancemanager.h
+++ b/src/extensions/mashup/mashup/mappletinstancemanager.h
@@ -32,6 +32,8 @@ class MAppletMetaData;
class MAppletHandle;
class MFileDataStore;
class QDBusPendingCallWatcher;
+class MExtensionWatcher;
+class MDesktopEntry;
//! \internal
@@ -160,6 +162,14 @@ private slots:
*/
void receiveOperation(QDBusPendingCallWatcher *watcher);
+ /*!
+ * Tells us that we need to update the applet. Currently the \c watcher informs the manager
+ * that the update desktop file has changed
+ *
+ * \param appletData The applet that has changed.
+ */
+ void updateApplet(const MDesktopEntry &appletData);
+
private:
/*!
* Initializes the instance manager.
@@ -380,6 +390,9 @@ private:
//! A map for keeping track of running applets
AppletContainer applets;
+ //! The watcher used to monitor changes in the applets
+ MExtensionWatcher *watcher;
+
//! The last applet ID that used to be free
MAppletId::AppletInstanceID lastAppletInstanceID;
diff --git a/src/extensions/mextensionwatcher.cpp b/src/extensions/mextensionwatcher.cpp
new file mode 100644
index 00000000..44464d84
--- /dev/null
+++ b/src/extensions/mextensionwatcher.cpp
@@ -0,0 +1,68 @@
+/***************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (directui@nokia.com)
+**
+** This file is part of libmeegotouch.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at directui@nokia.com.
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation
+** and appearing in the file LICENSE.LGPL included in the packaging
+** of this file.
+**
+****************************************************************************/
+
+#include "mextensionwatcher.h"
+#include "mdesktopentry.h"
+#include "mapplicationextensionmetadata.h"
+#include <QFile>
+#include <QStringList>
+
+
+MExtensionWatcher::MExtensionWatcher()
+{
+ connect(&watcher, SIGNAL(fileChanged(const QString &)), this, SLOT(notifyDataChanged(const QString &)));
+}
+
+MExtensionWatcher::~MExtensionWatcher()
+{
+}
+
+void MExtensionWatcher::addExtension(
+ QSharedPointer<const MDesktopEntry> extension)
+{
+ QString fileName = extension->fileName();
+ if (!extensionsToWatch.contains(fileName)) {
+ extensionsToWatch.insert(fileName, extension);
+ watcher.addPath(fileName);
+ }
+}
+
+void MExtensionWatcher::removeExtension(const QString &fileName)
+{
+ extensionsToWatch.remove(fileName);
+}
+
+void MExtensionWatcher::notifyDataChanged(const QString &path) const
+{
+ // If the file does not exist anymore no need to signal an update for it
+ // observation of the file removal is handled by the instance managers
+ if (!QFile::exists(path)) {
+ return;
+ }
+ QHash<QString, QSharedPointer<const MDesktopEntry> >::const_iterator
+ extension = extensionsToWatch.find(path);
+ if (extension != extensionsToWatch.constEnd()) {
+ emit extensionChanged(*extension.value());
+ }
+ if (!watcher.files().contains(path)) {
+ // if the file is removed and recreated, we need to re-add
+ // the path to the watcher
+ watcher.addPath(path);
+ }
+}
diff --git a/src/extensions/mextensionwatcher.h b/src/extensions/mextensionwatcher.h
new file mode 100644
index 00000000..bc0a227e
--- /dev/null
+++ b/src/extensions/mextensionwatcher.h
@@ -0,0 +1,98 @@
+/***************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (directui@nokia.com)
+**
+** This file is part of libmeegotouch.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at directui@nokia.com.
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation
+** and appearing in the file LICENSE.LGPL included in the packaging
+** of this file.
+**
+****************************************************************************/
+
+#ifndef MEXTENSIONWATCHER_H
+#define MEXTENSIONWATCHER_H
+
+#include <QFileSystemWatcher>
+#include <QHash>
+#include <QSharedPointer>
+
+class MDesktopEntry;
+
+/*!
+ * \brief \c MExtensionWatcher provides means to watch if either a given
+ * applet or a application extension has been updated by the package manager.
+ * If the change happens a corresponding signal will be emitted.
+ *
+ * The user of this class is responsible for the lifecycle management of the
+ * watched entries. This class does not assume ownership of the items nor can
+ * it detect if they are deleted. The user must remove the item from this
+ * watcher before deleting the item. Otherwise desktop file modification
+ * notification leads to undefined behaviour, because the target item of the
+ * notification will not exist.
+ */
+class MExtensionWatcher : public QObject
+{
+ Q_OBJECT
+
+public:
+ /*!
+ * Constructs the watcher instance
+ */
+ MExtensionWatcher();
+
+
+ /*!
+ * Destroys the wathcer instance
+ */
+ virtual ~MExtensionWatcher();
+
+ /*!
+ * Add an extension to the list of watched extensions.
+ * If the extension (its desktop entry) changes,
+ * a signal \see extensionChanged will be emitted.
+ *
+ * \param extension The extension to watch.
+ */
+ void addExtension(QSharedPointer<const MDesktopEntry> extension);
+
+ /*!
+ * Removes an extension from the list of watched extension
+ *
+ * \param fileName Name of the desktop file of the extension to
+ * remove
+ */
+ void removeExtension(const QString &fileName);
+
+Q_SIGNALS:
+
+ /*!
+ * Informs that an extension (its desktop file) has changed.
+ *
+ * \param extension The extension that has changed
+ */
+ void extensionChanged(const MDesktopEntry &extension) const;
+
+private slots:
+ //! Listens in on the actual changes
+ void notifyDataChanged(const QString &path) const;
+
+private:
+ //! The watcher instance for observing changes to desktop files
+ mutable QFileSystemWatcher watcher;
+ //! The list of applets to watch
+ QHash<QString, QSharedPointer<const MDesktopEntry> > extensionsToWatch;
+
+#ifdef UNIT_TEST
+ friend class Ut_MExtensionWatcher;
+#endif
+};
+
+#endif //MEXTENSIONWATCHER_H