File indexing completed on 2025-01-19 06:54:49
0001 // 0002 // C++ Implementation: clistmanager 0003 // 0004 // Description: 0005 // 0006 /* 0007 Copyright 2007-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 "clistmanager.h" 0024 0025 #include "clist.h" 0026 #include "cprofilemanager.h" 0027 0028 #include <map> 0029 0030 #include <QDebug> 0031 #include <QDir> 0032 #include <QFile> 0033 #include <QStandardItemModel> 0034 #include <QXmlStreamReader> 0035 #include <QXmlStreamWriter> 0036 0037 0038 using namespace std; 0039 0040 struct cListManager::Private { 0041 map<QString, cList *(*)()> listTypes; 0042 map<QString, QStandardItem *> modelItems; 0043 map<int, map<QString, cList *> > lists; 0044 QStandardItemModel *model; 0045 map<int, cListObject *> objects; 0046 map<cListObject *, int> objectIDs; 0047 int maxObjectID; 0048 }; 0049 0050 cListManager *cListManager::_self = nullptr; 0051 0052 cListManager *cListManager::self() 0053 { 0054 if (!_self) 0055 _self = new cListManager; 0056 return _self; 0057 } 0058 0059 cListManager::cListManager () : cActionBase ("listmanager", 0) 0060 { 0061 d = new Private; 0062 d->model = new QStandardItemModel; 0063 d->maxObjectID = 0; 0064 0065 // properly react on session connect/disconnect 0066 addEventHandler ("profile-init", 5, PT_STRING); 0067 addEventHandler ("profile-load", 5, PT_STRING); 0068 addEventHandler ("disconnected", 5, PT_NOTHING); 0069 addEventHandler ("save", 20, PT_NOTHING); 0070 } 0071 0072 cListManager::~cListManager () 0073 { 0074 removeEventHandler ("profile-init"); 0075 removeEventHandler ("profile-load"); 0076 removeEventHandler ("disconnected"); 0077 removeEventHandler ("save"); 0078 0079 delete d->model; 0080 delete d; 0081 } 0082 0083 void cListManager::eventNothingHandler (QString event, int session) 0084 { 0085 if (event == "disconnected") { 0086 // these will get called for both profile and non-profile sessions - 0087 // for the latter, they'll simply do nothing 0088 cProfileManager::self()->unassignSession (sess()); 0089 removeSession (session); 0090 } 0091 if (event == "save") { 0092 saveAll (session); 0093 } 0094 } 0095 0096 0097 void cListManager::eventStringHandler (QString event, int session, QString &par1, const QString &) 0098 { 0099 if (event == "profile-init") { 0100 // tie the session to the profile 0101 cProfileManager::self()->assignSession (session, par1); 0102 } 0103 if (event == "profile-load") { 0104 // load all the lists 0105 addSession (session); 0106 } 0107 } 0108 0109 void cListManager::registerType (const QString &name, const QString &visibleName, cList *(*factory)()) 0110 { 0111 // type already registered - do nothing 0112 if (d->listTypes.count (name)) 0113 return; 0114 d->listTypes[name] = factory; 0115 0116 // add the type to the model 0117 QStandardItem *item = new QStandardItem (visibleName); 0118 item->setData (name); // remember real name 0119 d->modelItems[name] = item; 0120 d->model->invisibleRootItem()->appendRow (item); 0121 d->model->sort (0); 0122 0123 // create the object in every existing session 0124 // this will ensure that data will be loaded, events hooked, and so on 0125 map<int, map<QString, cList *> >::iterator it; 0126 for (it = d->lists.begin(); it != d->lists.end(); ++it) 0127 getList (it->first, name); 0128 } 0129 0130 void cListManager::unregisterType (const QString &name) 0131 { 0132 // delete all lists of this type 0133 map<int, map<QString, cList *> >::iterator it; 0134 for (it = d->lists.begin(); it != d->lists.end(); ++it) { 0135 if (it->second.count (name)) { 0136 saveList (it->first, it->second[name]); 0137 delete it->second[name]; 0138 it->second.erase (name); 0139 } 0140 } 0141 0142 // unregister the type 0143 d->listTypes.erase (name); 0144 if (d->modelItems.count (name)) 0145 delete d->modelItems[name]; 0146 d->modelItems.erase (name); 0147 } 0148 0149 QStandardItemModel *cListManager::typeModel () const 0150 { 0151 return d->model; 0152 } 0153 0154 cList *cListManager::getList (int sessId, const QString &name) 0155 { 0156 if (!d->lists.count (sessId)) return nullptr; // session must exist 0157 if (!d->listTypes.count (name)) return nullptr; // type must be registered 0158 if (d->lists[sessId].count (name)) 0159 return d->lists[sessId][name]; // list exists - return it 0160 0161 // list doesn't exist yet - create it 0162 cList *list = d->listTypes[name](); // call the list factory 0163 list->initRootGroup (); 0164 d->lists[sessId][name] = list; 0165 list->setSession (sessId); // set list's session ID 0166 0167 // also load list contents 0168 loadList (sessId, list); 0169 0170 return list; 0171 } 0172 0173 void cListManager::addSession (int sessId) 0174 { 0175 if (d->lists.count (sessId)) return; // already exists 0176 map<QString, cList *> empty; 0177 d->lists[sessId] = empty; 0178 0179 // create every registered list in this session 0180 // this will ensure that data will be loaded, events hooked, and so on 0181 map<QString, cList *(*)()>::iterator it; 0182 for (it = d->listTypes.begin(); it != d->listTypes.end(); ++it) 0183 getList (sessId, it->first); 0184 } 0185 0186 void cListManager::removeSession (int sessId) 0187 { 0188 if (!d->lists.count (sessId)) return; 0189 map<QString, cList *>::iterator it; 0190 for (it = d->lists[sessId].begin(); it != d->lists[sessId].end(); ++it) { 0191 saveList (sessId, it->second); 0192 it->second->clear (); // remove all elements from the list 0193 delete it->second; 0194 } 0195 d->lists.erase (sessId); 0196 } 0197 0198 int cListManager::registerObject (cListObject *obj) 0199 { 0200 int id = objectId (obj); 0201 if (id) return id; // already registered 0202 id = ++d->maxObjectID; // generate new object ID 0203 d->objectIDs[obj] = id; 0204 d->objects[id] = obj; 0205 return id; 0206 } 0207 0208 void cListManager::unregisterObject (cListObject *obj) 0209 { 0210 int id = objectId (obj); 0211 if (!id) return; // not registered 0212 d->objectIDs.erase (obj); 0213 d->objects.erase (id); 0214 } 0215 0216 int cListManager::objectId (cListObject *obj) const 0217 { 0218 if (d->objectIDs.count (obj)) 0219 return d->objectIDs[obj]; 0220 return 0; 0221 } 0222 0223 cListObject *cListManager::object (int id) const 0224 { 0225 if (d->objects.count (id)) 0226 return d->objects[id]; 0227 return nullptr; 0228 } 0229 0230 void cListManager::loadList (int sessId, cList *list) 0231 { 0232 // load the list contents 0233 cProfileManager *pm = cProfileManager::self(); 0234 0235 QString path = pm->profilePath (sessId); 0236 QDir dir = QDir (path); 0237 if (!dir.exists()) QDir::root().mkpath (dir.absolutePath()); 0238 0239 QString fName = list->name() + ".xml"; 0240 0241 QFile f (path + "/" + fName); 0242 if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { 0243 qDebug() << "No " << fName << " file - nothing to do."; 0244 list->listLoaded (); // mark the list as loaded 0245 return; // no profiles - nothing to do 0246 } 0247 0248 QXmlStreamReader *reader = new QXmlStreamReader (&f); 0249 list->load (reader); 0250 0251 f.close (); 0252 delete reader; 0253 } 0254 0255 void cListManager::saveList (int sessId, cList *list) 0256 { 0257 if (!list) return; 0258 0259 // save the list contents 0260 cProfileManager *pm = cProfileManager::self(); 0261 0262 QString path = pm->profilePath (sessId); 0263 QDir dir = QDir (path); 0264 if (!dir.exists()) QDir::root().mkpath (dir.absolutePath()); 0265 0266 dir.remove (list->name() + ".backup"); 0267 QString fName = list->name() + ".xml"; 0268 if (!QFile(path + "/" + fName).copy (path + "/" + list->name() + ".backup")) { 0269 qDebug() << "Unable to backup " << fName; // not fatal, may simply not exist 0270 } 0271 0272 QFile f (path + "/" + fName); 0273 if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { 0274 qDebug() << "Unable to open " << (path + "/" + fName) << " for writing."; 0275 return; // problem 0276 } 0277 0278 QXmlStreamWriter *writer = new QXmlStreamWriter (&f); 0279 list->save (writer); 0280 0281 f.close (); 0282 delete writer; 0283 } 0284 0285 void cListManager::saveAll (int sessId) 0286 { 0287 map<QString, cList *(*)()>::iterator it; 0288 for (it = d->listTypes.begin(); it != d->listTypes.end(); ++it) 0289 saveList (sessId, getList (sessId, it->first)); 0290 } 0291 0292 0293