File indexing completed on 2024-04-21 15:08:18

0001 //
0002 // C++ Implementation: cActionManager
0003 //
0004 // Description: action manager
0005 //
0006 /*
0007 Copyright 2005-2011 Tomas Mecir <kmuddy@kmuddy.com>
0008 
0009 This program is free software; you can redistribute it and/or
0010 modify it under the terms of the GNU General Public License as
0011 published by the Free Software Foundation; either version 2 of 
0012 the License, or (at your option) any later version.
0013 
0014 This program is distributed in the hope that it will be useful,
0015 but WITHOUT ANY WARRANTY; without even the implied warranty of
0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017 GNU General Public License for more details.
0018 
0019 You should have received a copy of the GNU General Public License
0020 along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 
0023 #include "cactionmanager.h"
0024 
0025 #include "cactionbase.h"
0026 
0027 #include <kactioncollection.h>
0028 #include <kmainwindow.h>
0029 
0030 #include <QDebug>
0031 #include <QWidget>
0032 
0033 #include <list>
0034 #include <map>
0035 
0036 struct AMprivAction {
0037   cActionBase *ab;
0038   QString name;
0039   ParamType pt;
0040 };
0041 
0042 struct AMprivEvent {
0043   std::multimap<int, AMprivAction> handlers;
0044 };
0045 
0046 struct AMprivSessionInfo {
0047   // objects, accessible by names
0048   std::map<QString, cActionBase *> objects;  
0049   // event handlers, accessible by event names
0050   std::map<QString, AMprivEvent> events;
0051   // attributes
0052   std::map<QString, int> attribs;
0053   // string attributes
0054   std::map<QString, QString> strattribs;
0055 };
0056 
0057 struct cActionManagerPrivate {
0058   std::map<int, AMprivSessionInfo *> sessions;
0059   std::list<int> sessionList;
0060   int activesess;
0061 
0062   KMainWindow *mainWindow;
0063 
0064   // Shortcuts - only here because I have no better place for them :D
0065   // and I need them in lib/
0066   KActionCollection *acol;
0067 };
0068   
0069 cActionManager *cActionManager::_self = nullptr;
0070 
0071 cActionManager::cActionManager ()
0072 {
0073   d = new cActionManagerPrivate;
0074   d->activesess = 0;
0075   registerSession (0);
0076   d->acol = nullptr;
0077   d->mainWindow = nullptr;
0078 }
0079 
0080 cActionManager::~cActionManager ()
0081 {
0082   unregisterSession (0);
0083   delete d;
0084   _self = nullptr;
0085   if (d->acol) delete d->acol;
0086 }
0087 
0088 cActionManager *cActionManager::self ()
0089 {
0090   if (!_self)
0091     _self = new cActionManager;
0092   return _self;
0093 }
0094 
0095 void cActionManager::registerSession (int id)
0096 {
0097   if (sessionExists (id)) return;
0098   if (id < 0) return;
0099   d->sessions[id] = new AMprivSessionInfo;
0100   if (id) d->sessionList.push_back (id);
0101 }
0102 
0103 void cActionManager::unregisterSession (int id)
0104 {
0105   if (!sessionExists (id)) return;
0106 
0107   // delete all objects within the session
0108   // we need to use a temporary list, because deleting cActionBase would
0109   // invalidate the iterator ...
0110   std::map<QString, cActionBase *>::iterator it;
0111   std::list<cActionBase *> delList;
0112   std::list<cActionBase *>::iterator itl;
0113   
0114   for (it = d->sessions[id]->objects.begin(); it != d->sessions[id]->objects.end(); ++it) {
0115     qWarning() << "Object " << it->first << " in session " << id << " was not deleted properly.";
0116     delList.push_back (it->second);
0117   }
0118   for (itl = delList.begin(); itl != delList.end(); ++itl)
0119     delete *itl;
0120 
0121   // delete the session
0122   delete d->sessions[id];
0123   d->sessions.erase (id);
0124   if (id) d->sessionList.remove (id);
0125 }
0126 
0127 bool cActionManager::sessionExists (int id)
0128 {
0129   return (d->sessions.count (id) != 0);
0130 }
0131 
0132 list<int> cActionManager::sessionList ()
0133 {
0134   return d->sessionList;
0135 }
0136 
0137 int cActionManager::sessions ()
0138 {
0139   return d->sessionList.size();
0140 }
0141 
0142 int cActionManager::activeSession ()
0143 {
0144   return d->activesess;
0145 }
0146 
0147 void cActionManager::setActiveSession (int sess)
0148 {
0149   d->activesess = sess;
0150 }
0151 
0152 void cActionManager::setSessionAttrib (int sess, const QString &name, int value)
0153 {
0154   if (!sessionExists (sess)) return;
0155   d->sessions[sess]->attribs[name] = value;
0156 }
0157 
0158 void cActionManager::setSessionStrAttrib (int sess, const QString &name, const QString &value)
0159 {
0160   if (!sessionExists (sess)) return;
0161   d->sessions[sess]->strattribs[name] = value;
0162 }
0163 
0164 int cActionManager::sessionAttrib (int sess, const QString &name)
0165 {
0166   if (!sessionExists (sess)) return 0;
0167   if (d->sessions[sess]->attribs.count (name))
0168     return d->sessions[sess]->attribs[name];
0169   return 0;
0170 }
0171 
0172 QString cActionManager::sessionStrAttrib (int sess, const QString &name)
0173 {
0174   if (!sessionExists (sess)) return QString();
0175   if (d->sessions[sess]->strattribs.count (name))
0176     return d->sessions[sess]->strattribs[name];
0177   return QString();
0178 }
0179 
0180 void cActionManager::registerObject (cActionBase *ab, int session)
0181 {
0182   if (!sessionExists (session)) return;
0183   d->sessions[session]->objects[ab->objName()] = ab;
0184 }
0185 
0186 void cActionManager::unregisterObject (cActionBase *ab, int session)
0187 {
0188   if (!sessionExists (session)) return;
0189   d->sessions[session]->objects.erase (ab->objName());
0190 
0191   // TODO: remove all event handlers for this object ...
0192 }
0193 
0194 #include <iostream>
0195 cActionBase *cActionManager::object (const QString &name, int session)
0196 {
0197   if (!sessionExists (session)) {
0198     std::cerr << "Requested object " << name.toLatin1().data() << " from non-existant session " << session << std::endl;
0199     return nullptr;
0200   }
0201   if (d->sessions[session]->objects.count (name))
0202   {
0203     cActionBase *ab = d->sessions[session]->objects[name];
0204     return ab;
0205   }
0206   std::cerr << "Object " << name.toLatin1().data() << " from session " << session << " not found." << std::endl;
0207   return nullptr;
0208 }
0209 
0210 void cActionManager::addEventHandler (cActionBase *ab, int session, QString name,
0211     int priority, ParamType pt)
0212 {
0213   if (!sessionExists (session)) return;
0214   AMprivAction a;
0215   a.ab = ab;
0216   a.name = name;
0217   a.pt = pt;
0218   d->sessions[session]->events[name].handlers.insert (
0219       std::pair<int, AMprivAction> (priority, a));
0220 }
0221 
0222 void cActionManager::removeEventHandler (cActionBase *ab, int session, QString name)
0223 {
0224   if (!sessionExists (session)) return;
0225   std::multimap<int, AMprivAction>::iterator it;
0226   for (it = d->sessions[session]->events[name].handlers.begin();
0227       it != d->sessions[session]->events[name].handlers.end(); ++it)
0228   {
0229     if ((it->second.name == name) && (it->second.ab == ab))
0230     {
0231       d->sessions[session]->events[name].handlers.erase (it);
0232       return;
0233     }
0234   }
0235 }
0236 
0237 QString cActionManager::callAction (QString objectName, QString action, int session,
0238     int par1, int par2)
0239 {
0240   if (!sessionExists (session)) return QString();
0241   
0242   cActionBase *ab = object (objectName, session);
0243   if (ab)
0244     return ab->actionIntHandler (action, session, par1, par2);
0245   
0246   return QString();
0247 }
0248 
0249 QString cActionManager::callAction (QString objectName, QString action, int session,
0250     QString &par1, const QString &par2)
0251 {
0252   if (!sessionExists (session)) return QString();
0253 
0254   cActionBase *ab = object (objectName, session);
0255   if (ab)
0256     return ab->actionStringHandler (action, session, par1, par2);
0257   return QString();
0258 }
0259 
0260 QString cActionManager::callAction (QString objectName, QString action, int session,
0261     const QString &par1, const QString &par2)
0262 {
0263   if (!sessionExists (session)) return QString();
0264 
0265   QString p = par1;
0266   cActionBase *ab = object (objectName, session);
0267   if (ab)
0268     return ab->actionStringHandler (action, session, p, par2);
0269   return QString();
0270 }
0271 
0272 QString cActionManager::callAction (QString objectName, QString action, int session)
0273 {
0274   if (!sessionExists (session)) return QString();
0275 
0276   cActionBase *ab = object (objectName, session);
0277   if (ab)
0278     return ab->actionNothingHandler (action, session);
0279   return QString();
0280 }
0281 
0282 QString cActionManager::callAction (QString objectName, QString action, int session,
0283     cTextChunk *par)
0284 {
0285   if (!sessionExists (session)) return QString();
0286 
0287   cActionBase *ab = object (objectName, session);
0288   if (ab)
0289     return ab->actionChunkHandler (action, session, par);
0290   return QString();
0291 }
0292 
0293 QString cActionManager::callAction (QString objectName, QString action, int session,
0294     void *par)
0295 {
0296   if (!sessionExists (session)) return QString();
0297 
0298   cActionBase *ab = object (objectName, session);
0299   if (ab)
0300     return ab->actionVoidHandler (action, session, par);
0301   return QString();
0302 }
0303 
0304 
0305 void cActionManager::invokeEvent (QString event, int session, int par1, int par2)
0306 {
0307   if (!sessionExists (session)) return;
0308 
0309   std::multimap<int, AMprivAction>::iterator it;  
0310   // events for session 0 go to event handlers of all sessions
0311   if (session == 0) {
0312     std::map<int, AMprivSessionInfo *>::iterator it2;
0313     for (it2 = d->sessions.begin(); it2 != d->sessions.end(); ++it2)
0314       for (it = it2->second->events[event].handlers.begin();
0315            it != it2->second->events[event].handlers.end(); ++it)
0316         if (it->second.pt == PT_INT)
0317           it->second.ab->eventIntHandler (event, session, par1, par2);
0318     
0319   }
0320   else
0321   {
0322     // send the event to the target session handlers
0323     for (it = d->sessions[session]->events[event].handlers.begin();
0324             it != d->sessions[session]->events[event].handlers.end(); ++it)
0325       if (it->second.pt == PT_INT)
0326         it->second.ab->eventIntHandler (event, session, par1, par2);
0327     
0328     // objects with session number 0 receive all events
0329     for (it = d->sessions[0]->events[event].handlers.begin();
0330          it != d->sessions[0]->events[event].handlers.end(); ++it)
0331       if (it->second.pt == PT_INT)
0332         it->second.ab->eventIntHandler (event, session, par1, par2);
0333   }
0334 }
0335 
0336 void cActionManager::invokeEvent (QString event, int session,
0337     QString &par1, const QString &par2)
0338 {
0339   if (!sessionExists (session)) return;
0340 
0341   std::multimap<int, AMprivAction>::iterator it;  
0342   // events for session 0 go to event handlers of all session
0343   if (session == 0) {
0344     std::map<int, AMprivSessionInfo *>::iterator it2;
0345     for (it2 = d->sessions.begin(); it2 != d->sessions.end(); ++it2)
0346       for (it = it2->second->events[event].handlers.begin();
0347            it != it2->second->events[event].handlers.end(); ++it)
0348         if (it->second.pt == PT_STRING)
0349           it->second.ab->eventStringHandler (event, session, par1, par2);
0350     
0351   }
0352   else
0353   {
0354     // send the event to the target session handlers
0355     for (it = d->sessions[session]->events[event].handlers.begin();
0356             it != d->sessions[session]->events[event].handlers.end(); ++it)
0357       if (it->second.pt == PT_STRING)
0358         it->second.ab->eventStringHandler (event, session, par1, par2);
0359     
0360     // objects with session number 0 receive all events
0361     for (it = d->sessions[0]->events[event].handlers.begin();
0362          it != d->sessions[0]->events[event].handlers.end(); ++it)
0363       if (it->second.pt == PT_STRING)
0364         it->second.ab->eventStringHandler (event, session, par1, par2);
0365   }
0366   
0367 }
0368 
0369 void cActionManager::invokeEvent (QString event, int session,
0370     const QString &par1, const QString &par2)
0371 {
0372   QString p = par1;
0373   invokeEvent (event, session, p, par2);
0374 }
0375 
0376 void cActionManager::invokeEvent (QString event, int session)
0377 {
0378   if (!sessionExists (session)) return;
0379 
0380   std::multimap<int, AMprivAction>::iterator it;  
0381   // events for session 0 go to event handlers of all session
0382   if (session == 0) {
0383     std::map<int, AMprivSessionInfo *>::iterator it2;
0384     for (it2 = d->sessions.begin(); it2 != d->sessions.end(); ++it2)
0385       for (it = it2->second->events[event].handlers.begin();
0386            it != it2->second->events[event].handlers.end(); ++it)
0387         if (it->second.pt == PT_NOTHING)
0388           it->second.ab->eventNothingHandler (event, session);
0389     
0390   }
0391   else
0392   {
0393     // send the event to the target session handlers
0394     for (it = d->sessions[session]->events[event].handlers.begin();
0395             it != d->sessions[session]->events[event].handlers.end(); ++it)
0396       if (it->second.pt == PT_NOTHING)
0397         it->second.ab->eventNothingHandler (event, session);  
0398     
0399     // objects with session number 0 receive all events
0400     for (it = d->sessions[0]->events[event].handlers.begin();
0401          it != d->sessions[0]->events[event].handlers.end(); ++it)
0402       if (it->second.pt == PT_NOTHING)
0403         it->second.ab->eventNothingHandler (event, session);
0404   }
0405 }
0406 
0407 void cActionManager::invokeEvent (QString event, int session, cTextChunk *par)
0408 {
0409   if (!sessionExists (session)) return;
0410 
0411   std::multimap<int, AMprivAction>::iterator it;  
0412   // events for session 0 go to event handlers of all session
0413   if (session == 0) {
0414     std::map<int, AMprivSessionInfo *>::iterator it2;
0415     for (it2 = d->sessions.begin(); it2 != d->sessions.end(); ++it2)
0416       for (it = it2->second->events[event].handlers.begin();
0417            it != it2->second->events[event].handlers.end(); ++it)
0418         if (it->second.pt == PT_TEXTCHUNK)
0419           it->second.ab->eventChunkHandler (event, session, par);
0420     
0421   }
0422   else
0423   {
0424     // send the event to the target session handlers
0425     for (it = d->sessions[session]->events[event].handlers.begin();
0426             it != d->sessions[session]->events[event].handlers.end(); ++it)
0427       if (it->second.pt == PT_TEXTCHUNK)
0428         it->second.ab->eventChunkHandler (event, session, par);
0429     
0430     // objects with session number 0 receive all events
0431     for (it = d->sessions[0]->events[event].handlers.begin();
0432          it != d->sessions[0]->events[event].handlers.end(); ++it)
0433       if (it->second.pt == PT_TEXTCHUNK)
0434         it->second.ab->eventChunkHandler (event, session, par);
0435   }
0436 }
0437 
0438 void cActionManager::invokeEvent (QString event, int session, void *par)
0439 {
0440   if (!sessionExists (session)) return;
0441 
0442   std::multimap<int, AMprivAction>::iterator it;  
0443   // events for session 0 go to event handlers of all session
0444   if (session == 0) {
0445     std::map<int, AMprivSessionInfo *>::iterator it2;
0446     for (it2 = d->sessions.begin(); it2 != d->sessions.end(); ++it2)
0447       for (it = it2->second->events[event].handlers.begin();
0448            it != it2->second->events[event].handlers.end(); ++it)
0449         if (it->second.pt == PT_TEXTCHUNK)
0450           it->second.ab->eventVoidHandler (event, session, par);
0451     
0452   }
0453   else
0454   {
0455     // send the event to the target session handlers
0456     for (it = d->sessions[session]->events[event].handlers.begin();
0457          it != d->sessions[session]->events[event].handlers.end(); ++it)
0458       if (it->second.pt == PT_POINTER)
0459         it->second.ab->eventVoidHandler (event, session, par);
0460     
0461     // objects with session number 0 receive all events
0462     for (it = d->sessions[0]->events[event].handlers.begin();
0463          it != d->sessions[0]->events[event].handlers.end(); ++it)
0464       if (it->second.pt == PT_POINTER)
0465         it->second.ab->eventVoidHandler (event, session, par);
0466   }
0467 }
0468 
0469 void cActionManager::setMainWindow (KMainWindow *window)
0470 {
0471   if (d->mainWindow) return;   // already set - do not override
0472   d->mainWindow = window;
0473 }
0474 
0475 QWidget *cActionManager::mainWidget ()
0476 {
0477   return d->mainWindow;
0478 }
0479 
0480 KMainWindow *cActionManager::mainWindow ()
0481 {
0482   return d->mainWindow;
0483 }
0484 
0485 void cActionManager::createACol (QWidget *parent)
0486 {
0487   if (!d->acol)
0488     d->acol = new KActionCollection (parent);
0489   //create acol object if needed, but nothing more... readShortcutSettings()
0490   //is called in kmuddy->prepareObjects ();
0491 }
0492 
0493 KActionCollection *cActionManager::getACol ()
0494 {
0495   return d->acol;
0496 }
0497