easyer way of loading plugins :D

This commit is contained in:
Patrick von Reth 2012-01-28 15:21:04 +01:00
parent 22c80b007c
commit dc34eda1d7
7 changed files with 240 additions and 148 deletions

View File

@ -18,13 +18,56 @@
#include "snoreserver.h"
#include <QTimer>
#include <QPluginLoader>
#include <QDir>
#include <QDebug>
namespace Snore{
SnorePluginInfo::type SnorePluginInfo::typeFromString(const QString &t){
SnorePluginInfo::SnorePluginInfo(QString fileName, QString pluginName, SnorePluginInfo::PluginType type)
:m_pluginFile(fileName),
m_pluginName(pluginName),
m_pluginType(type),
m_instance(NULL)
{
}
SnorePlugin *SnorePluginInfo::load(){
if(m_instance != NULL)
return m_instance;
QPluginLoader loader ( SnoreServer::pluginDir().absoluteFilePath(file()));
qDebug()<<"Trying to load"<<file();
if ( !loader.load())
{
qDebug() <<"Failed loading plugin: "<<loader.errorString();
return NULL;
}
m_instance = qobject_cast<SnorePlugin*> ( loader.instance());
return m_instance;
}
const QString & SnorePluginInfo::file()
{
return m_pluginFile;
}
const QString & SnorePluginInfo::name()
{
return m_pluginName;
}
const SnorePluginInfo::PluginType SnorePluginInfo::type()
{
return m_pluginType;
}
SnorePluginInfo::PluginType SnorePluginInfo::typeFromString(const QString &t){
if(t == QLatin1String("backend"))
return BACKEND;
if(t == QLatin1String("secondary_backend"))
return SECONDARY_BACKEND;
if(t == QLatin1String("frontend"))
return FRONTEND;
return PLUGIN;
@ -34,7 +77,7 @@ const QStringList &SnorePluginInfo::types(){
static QStringList *list =NULL;
if(list == NULL){
list = new QStringList();
*list<<"backend"<<"frontend"<<"plugin";
*list<<"backend"<<"secondary_backend"<<"frontend"<<"plugin";
}
return *list;
}
@ -106,6 +149,7 @@ Notification_Backend::Notification_Backend ( QString name ) :
Notification_Backend::~Notification_Backend()
{
qDebug()<<"Deleting"<<name();
}
bool Notification_Backend::init( SnoreServer *snore )
@ -115,8 +159,6 @@ bool Notification_Backend::init( SnoreServer *snore )
connect( snore,SIGNAL( closeNotify( Snore::Notification ) ),this,SLOT( closeNotification( Snore::Notification) ) );
connect( snore,SIGNAL( applicationInitialized( Snore::Application* ) ),this,SLOT( registerApplication( Snore::Application* ) ) );
connect( snore,SIGNAL( applicationRemoved( Snore::Application* ) ),this,SLOT( unregisterApplication( Snore::Application* ) ) );
if(!isPrimaryNotificationBackend())
connect( snore,SIGNAL( notify(Snore::Notification) ),this,SLOT( notify( Snore::Notification ) ) );
foreach(Application *a,snore->aplications()){
this->registerApplication(a);
@ -126,7 +168,24 @@ bool Notification_Backend::init( SnoreServer *snore )
}
Notification_Frontend::Notification_Frontend ( QString name ) :
Secondary_Notification_Backend::Secondary_Notification_Backend(const QString &name)
:Notification_Backend(name)
{
}
Secondary_Notification_Backend::~Secondary_Notification_Backend()
{
qDebug()<<"Deleting"<<name();
}
bool Secondary_Notification_Backend::init(SnoreServer *snore)
{
connect( snore,SIGNAL( notify(Snore::Notification) ),this,SLOT( notify( Snore::Notification ) ) );
return Notification_Backend::init(snore);
}
Notification_Frontend::Notification_Frontend ( const QString &name ) :
SnorePlugin ( name )
{
@ -134,6 +193,7 @@ Notification_Frontend::Notification_Frontend ( QString name ) :
Notification_Frontend::~Notification_Frontend()
{
qDebug()<<"Deleting"<<name();
}
bool Notification_Frontend::init( SnoreServer *snore )
{

View File

@ -20,23 +20,38 @@
#include "notification/notification.h"
#include <QPointer>
#include <QFlag>
namespace Snore{
class Application;
class SnoreServer;
class SnorePlugin;
class SNORE_EXPORT SnorePluginInfo{
public:
enum type{
BACKEND,
FRONTEND,
PLUGIN
enum PluginType{
ALL = 0x0,//dor loading plugins
BACKEND = 0x1,
SECONDARY_BACKEND = 0x2,
FRONTEND = 0x4,
PLUGIN = 0x8
};
QString pluginFile;
QString pluginName;
type pluginType;
static type typeFromString(const QString &t);
Q_DECLARE_FLAGS(PluginTypes, PluginType)
SnorePluginInfo(QString fileName,QString pluginName,PluginType type);
SnorePlugin *load();
const QString &file();
const QString &name();
const SnorePluginInfo::PluginType type();
static Snore::SnorePluginInfo::PluginType typeFromString(const QString &t);
static const QStringList &types();
private:
QPointer<SnorePlugin> m_instance;
QString m_pluginFile;
QString m_pluginName;
Snore::SnorePluginInfo::PluginType m_pluginType;
};
class SNORE_EXPORT SnorePlugin:public QObject
@ -68,6 +83,7 @@ private:
};
}
Q_DECLARE_OPERATORS_FOR_FLAGS(Snore::SnorePluginInfo::PluginTypes)
Q_DECLARE_INTERFACE ( Snore::SnorePlugin,
"org.Snore.SnorePlugin/1.0" )
@ -81,7 +97,6 @@ public:
Notification_Backend ( QString name );
virtual ~Notification_Backend();
virtual bool init(SnoreServer *snore);
virtual bool isPrimaryNotificationBackend() =0;
@ -95,13 +110,36 @@ public slots:
};
}
Q_DECLARE_INTERFACE ( Snore::Notification_Backend,
"org.Snore.NotificationBackend/1.0" )
namespace Snore{
class SNORE_EXPORT Secondary_Notification_Backend:public Notification_Backend
{
Q_OBJECT
Q_INTERFACES(Snore::SnorePlugin Snore::Notification_Backend)
public:
Secondary_Notification_Backend(const QString &name);
virtual ~Secondary_Notification_Backend();
virtual bool init(SnoreServer *snore);
};
}
Q_DECLARE_INTERFACE ( Snore::Secondary_Notification_Backend,
"org.Snore.SecondaryNotificationBackend/1.0" )
namespace Snore{
class SNORE_EXPORT Notification_Frontend:public SnorePlugin
{
Q_OBJECT
Q_INTERFACES(Snore::SnorePlugin)
public:
Notification_Frontend ( QString name);
Notification_Frontend ( const QString &name);
virtual ~Notification_Frontend();
virtual bool init(SnoreServer *snore);
@ -110,15 +148,10 @@ public slots:
virtual void notificationClosed( Snore::Notification notification )=0;
};
}
Q_DECLARE_INTERFACE ( Snore::Notification_Frontend,
"org.Snore.NotificationFrontend/1.0" )
Q_DECLARE_INTERFACE ( Snore::Notification_Backend,
"org.Snore.NotificationBackend/1.0" )
#endif//INTERFACE_H

View File

@ -29,7 +29,9 @@
namespace Snore{
QHash<QString,SnorePluginInfo*> SnoreServer::m_pluginCache = QHash<QString,SnorePluginInfo*>() ;
QHash<QString,SnorePluginInfo*> SnoreServer::s_pluginCache = QHash<QString,SnorePluginInfo*>() ;
QString SnoreServer::s_pluginPath = QString(qApp->applicationDirPath()+"/snoreplugins");
QString const SnoreServer::version(){
return QString().append(Version::major()).append(".").append(Version::minor()).append(Version::suffix());
@ -44,7 +46,7 @@ QString const SnoreServer::snoreTMP(){
SnoreServer::SnoreServer ( QSystemTrayIcon *trayIcon ) :
m_notificationBackend ( NULL ),
m_trayIcon ( trayIcon )
{
{
QDir home ( snoreTMP() );
if ( !home.exists() ){
home.cdUp();
@ -53,36 +55,36 @@ SnoreServer::SnoreServer ( QSystemTrayIcon *trayIcon ) :
}
QHash<QString, SnorePluginInfo *> SnoreServer::pluginCache(const QString &pluginPath){
if(!m_pluginCache.isEmpty())
return m_pluginCache;
QSettings cache(SnoreServer::pluginDir(pluginPath).absoluteFilePath("plugin.cache"),QSettings::IniFormat);
QHash<QString, SnorePluginInfo *> SnoreServer::pluginCache(){
if(!s_pluginCache.isEmpty())
return s_pluginCache;
QSettings cache(SnoreServer::pluginDir().absoluteFilePath("plugin.cache"),QSettings::IniFormat);
int size = cache.beginReadArray("plugins");
if(size == 0)
return updatePluginCache(pluginPath);
for(int i=0;i<size;++i) {
cache.setArrayIndex(i);
SnorePluginInfo *info = new SnorePluginInfo();
info->pluginFile = cache.value("fileName").toString();
info->pluginName = cache.value("name").toString();
info->pluginType = (SnorePluginInfo::type)cache.value("type").toInt();
m_pluginCache.insert(info->pluginName,info);
if(size == 0){
updatePluginCache();
}else{
for(int i=0;i<size;++i) {
cache.setArrayIndex(i);
SnorePluginInfo::PluginType type = (SnorePluginInfo::PluginType)cache.value("type").toInt();
SnorePluginInfo *info = new SnorePluginInfo(cache.value("fileName").toString(),cache.value("name").toString(),type);
s_pluginCache.insert(info->name(),info);
}
cache.endArray();
}
cache.endArray();
return m_pluginCache;
return s_pluginCache;
}
QHash<QString, SnorePluginInfo *> SnoreServer::updatePluginCache(const QString &pluginPath){
QSettings cache(SnoreServer::pluginDir(pluginPath).absoluteFilePath("plugin.cache"),QSettings::IniFormat);
void SnoreServer::updatePluginCache(const QString &pluginPath){
if(!pluginPath.isEmpty())
s_pluginPath = pluginPath;
QSettings cache(SnoreServer::pluginDir().absoluteFilePath("plugin.cache"),QSettings::IniFormat);
qDebug()<<"Updating plugin cache"<<cache.fileName();
m_pluginCache.clear();
s_pluginCache.clear();
foreach(const QString &type,SnorePluginInfo::types()){
QDir plPath(SnoreServer::pluginDir(pluginPath).absoluteFilePath(type));
QDir plPath(SnoreServer::pluginDir().absoluteFilePath(type));
qDebug()<<"Searching for plugins in"<<plPath.path();
foreach (QString fileName, plPath.entryList(QDir::Files)) {
QString filepath(plPath.absoluteFilePath(fileName));
@ -99,93 +101,84 @@ QHash<QString, SnorePluginInfo *> SnoreServer::updatePluginCache(const QString &
plugin->deleteLater();
continue;
}
SnorePluginInfo *info = new SnorePluginInfo();
info->pluginFile = SnoreServer::pluginDir(pluginPath).relativeFilePath(filepath);
info->pluginName = sp->name();
info->pluginType = SnorePluginInfo::typeFromString(type);
m_pluginCache.insert(info->pluginName,info);
SnorePluginInfo *info = new SnorePluginInfo( SnoreServer::pluginDir().relativeFilePath(filepath),sp->name(),SnorePluginInfo::typeFromString(type));
s_pluginCache.insert(info->name(),info);
sp->deleteLater();
qDebug()<<"added "<<info->pluginFile<<"to cache";
qDebug()<<"added "<<info->name()<<"to cache";
}
}
qDebug()<<m_pluginCache.keys();
QList<SnorePluginInfo*> plugins = m_pluginCache.values();
qDebug()<<s_pluginCache.keys();
QList<SnorePluginInfo*> plugins = s_pluginCache.values();
cache.beginWriteArray("plugins");
for(int i=0;i< plugins.size();++i) {
cache.setArrayIndex(i);
cache.setValue("fileName",plugins[i]->pluginFile);
cache.setValue("name", plugins[i]->pluginName);
cache.setValue("type",plugins[i]->pluginType);
cache.setValue("fileName",plugins[i]->file());
cache.setValue("name", plugins[i]->name());
cache.setValue("type",(int)plugins[i]->type());
}
cache.endArray();
return m_pluginCache;
}
const QDir &SnoreServer::pluginDir(const QString &pluginPath){
const QDir &SnoreServer::pluginDir()
{
//TODO:fix logic
static QDir *plDir = NULL;
if(plDir == NULL){
if(!pluginPath.isEmpty())
plDir = new QDir(pluginPath);
if(pluginPath.isEmpty() || plDir->exists()){
plDir = new QDir(qApp->applicationDirPath()+"/snoreplugins");
if(!plDir->exists())
plDir = new QDir(LIBSNORE_PLUGIN_PATH);
}
plDir = new QDir(s_pluginPath);
if(!plDir->exists())
plDir = new QDir(LIBSNORE_PLUGIN_PATH);
}
return *plDir;
}
void SnoreServer::publicatePlugin ( const SnorePluginInfo *info )
void SnoreServer::publicatePlugin ( SnorePluginInfo::PluginTypes types )
{
QPluginLoader loader ( SnoreServer::pluginDir(QString()).absoluteFilePath(info->pluginFile ));
qDebug()<<"Trying to load"<<info->pluginFile;
if ( !loader.load())
foreach ( SnorePluginInfo *info, SnoreServer::pluginCache().values())
{
qDebug() <<"Failed loading plugin: "<<loader.errorString();
return;
}
SnorePlugin *plugin = qobject_cast<SnorePlugin*> ( loader.instance());
m_plugins.insert ( info->pluginName ,plugin );
switch(info->pluginType){
case SnorePluginInfo::BACKEND:{
Notification_Backend * nb = qobject_cast<Notification_Backend *> ( plugin );
qDebug() <<info->pluginName<<"is a Notification_Backend";
if ( nb->isPrimaryNotificationBackend() )
{
m_primaryNotificationBackends.append( info->pluginName);
if ( m_notificationBackend == NULL )
{
m_notificationBackend = nb;
if(types == SnorePluginInfo::ALL or types.testFlag(info->type())){
switch(info->type()){
case SnorePluginInfo::BACKEND:{
qDebug() <<info->name()<<"is a Notification_Backend";
m_notificationBackends.append( info->name());
break;
}
case SnorePluginInfo::SECONDARY_BACKEND:{
Secondary_Notification_Backend *nb = qobject_cast<Secondary_Notification_Backend *> ( info->load() );
if(!nb->init( this )){
nb->deleteLater();
break;
}
m_secondaryNotificationBackends.append(info->name());
break;
}
case SnorePluginInfo::FRONTEND:{
Notification_Frontend * nf = qobject_cast<Notification_Frontend*> (info->load());
qDebug() <<info->name()<<"is a Notification_Frontend";
if(!nf->init( this )){
nf->deleteLater();
break;
}
m_Frontends.append(info->name());
break;
}
case SnorePluginInfo::PLUGIN:{
qDebug() <<info->name()<<"is a SnorePlugin";
if(!info->load()->init(this)){
info->load()->deleteLater();
break;
}
m_plugins.append(info->name());
break;
}
default:{
std::cerr<<"Plugin Cache corrupted"<<std::endl;
std::cerr<<info->file().toLatin1().constData()<<QString::number((int)info->type()).toLatin1().constData()<<std::endl;
}
}
}else{
if(!nb->init( this )){
nb->deleteLater();
return;
}
m_notyfier.insert ( info->pluginName,nb );
qDebug()<<"dont load "<<info->file()<<info->type();
}
break;
}
case SnorePluginInfo::FRONTEND:{
Notification_Frontend * nf = qobject_cast<Notification_Frontend*> (plugin);
qDebug() <<info->pluginName<<"is a Notification_Frontend";
if(nf->init( this ))
m_frontends.insert(nf->name(),nf);
else
nf->deleteLater();
break;
}
case SnorePluginInfo::PLUGIN:
qDebug() <<info->pluginName<<"is a SnorePlugin";
plugin->init(this);
break;
default:
std::cerr<<"Plugin Cache corrupted"<<std::endl ;
break;
}
}
@ -245,17 +238,27 @@ const ApplicationsList &SnoreServer::aplications() const
}
const QStringList &SnoreServer::primaryNotificationBackends() const
const QStringList &SnoreServer::notificationBackends() const
{
return m_primaryNotificationBackends;
return m_notificationBackends;
}
const QStringList &SnoreServer::notificationFrontends() const
{
return m_Frontends;
}
const QStringList &SnoreServer::secondaryNotificationBackends() const
{
return m_secondaryNotificationBackends;
}
void SnoreServer::setPrimaryNotificationBackend ( const QString &backend )
{
if(!m_primaryNotificationBackends.contains(backend))
if(!m_notificationBackends.contains(backend))
return;
qDebug()<<"Setting Notification Backend to:"<<backend;
m_notificationBackend = qobject_cast<Notification_Backend*>(m_plugins[backend]);
m_notificationBackend = qobject_cast<Notification_Backend*>(pluginCache()[backend]->load());
if(!m_notificationBackend->isInitialized())
m_notificationBackend->init(this);
}

View File

@ -30,14 +30,14 @@ class SNORE_EXPORT SnoreServer:public QObject
{
Q_OBJECT
public:
static const QString version();
static const QString version();
static const QString snoreTMP();
static QHash<QString,SnorePluginInfo*> pluginCache(const QString &pluginPath = QString());
static QHash<QString,SnorePluginInfo*> updatePluginCache(const QString &pluginPath = QString());
static void updatePluginCache(const QString &pluginPath = "");
static const QDir &pluginDir();
public:
SnoreServer (QSystemTrayIcon *trayIcon=0 );
void publicatePlugin ( const SnorePluginInfo *info );
void publicatePlugin ( SnorePluginInfo::PluginTypes types );
uint broadcastNotification ( Notification notification );
@ -49,7 +49,10 @@ public:
void removeApplication ( const QString& appName );
const ApplicationsList &aplications() const;
const QStringList &primaryNotificationBackends() const;
const QStringList &notificationBackends() const;
const QStringList &notificationFrontends() const;
const QStringList &secondaryNotificationBackends() const;
void setPrimaryNotificationBackend ( const QString &backend );
const QString &primaryNotificationBackend();
QSystemTrayIcon *trayIcon();
@ -57,20 +60,21 @@ public:
private:
static const QDir &pluginDir(const QString &pluginPath);
static QHash<QString,SnorePluginInfo*> pluginCache();
static QHash<QString,SnorePluginInfo*> m_pluginCache;
static QHash<QString,SnorePluginInfo*> s_pluginCache;
ApplicationsList m_applications;
QHash<QString,Notification_Backend*> m_notyfier;
QHash<QString,Notification_Frontend*> m_frontends;
QStringList m_primaryNotificationBackends;
QStringList m_notificationBackends;
QStringList m_Frontends;
QStringList m_secondaryNotificationBackends;
QStringList m_plugins;
Notification_Backend * m_notificationBackend;
QHash<QString,SnorePlugin*> m_plugins;
QSystemTrayIcon *m_trayIcon;
static QString s_pluginPath;
signals:

View File

@ -1,5 +1,6 @@
set(CMAKE_SHARED_MODULE_PREFIX)
set(SNORE_BACKEND_INSTALL_PATH ${PLUGIN_INSTALL_PATH}/backend)
set(SNORE_SECONDARY_BACKEND_INSTALL_PATH ${PLUGIN_INSTALL_PATH}/secondary_backend)
set(SNORE_FRONTEND_INSTALL_PATH ${PLUGIN_INSTALL_PATH}/frontend)
set(SNORE_PLUGINS_INSTALL_PATH ${PLUGIN_INSTALL_PATH}/plugin)

View File

@ -36,16 +36,7 @@ SnoreNotify::SnoreNotify():
{
m_trayIcon = new TrayIcon();
m_snore = new Snore::SnoreServer(m_trayIcon->trayIcon());
QHash<QString,SnorePluginInfo*> plugins = SnoreServer::pluginCache();
qDebug()<<"Plugins"<<plugins.keys();
foreach ( SnorePluginInfo *info, plugins.values())
{
qDebug()<<"Grr loading "<< info->pluginFile<<info->pluginName;
m_snore->publicatePlugin ( info );
}
m_snore->publicatePlugin(SnorePluginInfo::ALL);
load();
m_trayIcon->initConextMenu(m_snore);
@ -58,7 +49,7 @@ SnoreNotify::~SnoreNotify(){
}
void SnoreNotify::load(){
m_snore->setPrimaryNotificationBackend(m_settings.value("notificationBackend").toString());
m_snore->setPrimaryNotificationBackend(m_settings.value("notificationBackend","SystemTray").toString());
}
void SnoreNotify::save(){

View File

@ -25,23 +25,23 @@ using namespace Snore;
TrayIcon::TrayIcon()
{
_trayIcon = new QSystemTrayIcon(QIcon(":/root/snore.png"));
_trayIcon = new QSystemTrayIcon(QIcon(":/root/snore.png"));
}
void TrayIcon::initConextMenu(SnoreServer *snore){
_snore = snore;
_snore = snore;
_trayIcon->setVisible(true);
_trayMenu = new QMenu("SnoreNotify");
_trayMenu->addAction(QString("SnoreNotify ").append(_snore->version()));
_trayMenu->addSeparator();
foreach(const QString &back,_snore->primaryNotificationBackends()){
foreach(const QString &back,_snore->notificationBackends()){
QAction *b= new QAction(back,this);
connect(b,SIGNAL(triggered()),this,SLOT(setPrimaryBackend()));
b->setCheckable(true);
if(back == _snore->primaryNotificationBackend())
b->setChecked(true);
_backendActions.append(b);
b->setCheckable(true);
if(back == _snore->primaryNotificationBackend())
b->setChecked(true);
_backendActions.append(b);
_trayMenu->addAction(b);
}
_trayMenu->addSeparator();
@ -56,17 +56,17 @@ void TrayIcon::hide(){
}
QSystemTrayIcon* TrayIcon::trayIcon(){
return _trayIcon;
return _trayIcon;
}
void TrayIcon::setPrimaryBackend(){
QAction *a= dynamic_cast<QAction*>(sender());
_snore->setPrimaryNotificationBackend(a->text());
foreach(QAction *action,_backendActions){
action->setChecked(false);
}
a->setChecked(true);
foreach(QAction *action,_backendActions){
action->setChecked(false);
}
a->setChecked(true);
}