File indexing completed on 2023-10-03 03:28:40
0001 /********************************************f******************************* 0002 cmapzonemanager.cpp 0003 ------------------- 0004 begin : Sat Aug 15, 2015 0005 copyright : (C) 2015 Tomas Mecir 0006 email : mecirt@gmail.com 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * * 0011 * This program is free software; you can redistribute it and/or modify * 0012 * it under the terms of the GNU General Public License as published by * 0013 * the Free Software Foundation; either version 2 of the License, or * 0014 * (at your option) any later version. * 0015 * * 0016 ***************************************************************************/ 0017 0018 #include "cmapzonemanager.h" 0019 0020 #include <QStandardItemModel> 0021 #include <QDir> 0022 #include <QXmlStreamReader> 0023 #include <QXmlStreamWriter> 0024 #include <kdebug.h> 0025 #include <klocale.h> 0026 #include <kmessagebox.h> 0027 0028 #include "cmapmanager.h" 0029 #include "cprofilemanager.h" 0030 0031 struct CMapZoneManager::Private { 0032 QStandardItemModel zones; 0033 int sessId; 0034 CMapManager *manager; 0035 int currentZone; 0036 }; 0037 0038 0039 CMapZoneManager::CMapZoneManager(int sessId, CMapManager *manager) 0040 { 0041 d = new Private; 0042 d->sessId = sessId; 0043 d->manager = manager; 0044 d->currentZone = -1; 0045 loadMapList(); 0046 } 0047 0048 CMapZoneManager::~CMapZoneManager() 0049 { 0050 for (int i = 0; i < d->zones.rowCount(); ++i) 0051 delete getZoneEntry(i); 0052 0053 delete d; 0054 } 0055 0056 0057 QStandardItemModel *CMapZoneManager::zonesModel() 0058 { 0059 return &d->zones; 0060 } 0061 0062 QString CMapZoneManager::getPath(int idx) 0063 { 0064 cZoneInformation *i = getZoneEntry(idx); 0065 if (!i) return QString(); 0066 0067 cProfileManager *pm = cProfileManager::self(); 0068 if (!pm->settings(d->sessId)) return QString(); 0069 0070 QString path = pm->profilePath (d->sessId) + "/maps/"; 0071 QDir dir = QDir (path); 0072 if (!dir.exists()) QDir::root().mkpath (dir.absolutePath()); 0073 return path + "/" + i->file; 0074 } 0075 0076 void CMapZoneManager::save(bool always) 0077 { 0078 // first save the current zone 0079 QString savePath = getPath (d->currentZone); 0080 if (!savePath.length()) return; 0081 0082 CMapFileFilterBase *filter = d->manager->nativeFilter(false); 0083 if (filter && (always || (!d->manager->isClean()))) 0084 d->manager->exportMap (savePath, filter); 0085 } 0086 0087 void CMapZoneManager::loadZone(int idx) 0088 { 0089 if (d->currentZone == idx) return; 0090 0091 save(true); 0092 0093 // and load, replacing the existing data 0094 QString loadPath = getPath(idx); 0095 CMapFileFilterBase *filter = d->manager->nativeFilter(true); 0096 if (filter) { 0097 d->currentZone = idx; 0098 d->manager->importMap (loadPath, filter); 0099 } 0100 } 0101 0102 void CMapZoneManager::deleteZone(int idx) 0103 { 0104 cZoneInformation *i = getZoneEntry(idx); 0105 if (!i) return; 0106 0107 // wipe the data, if loaded 0108 if (idx == d->currentZone) 0109 d->manager->eraseMap(); 0110 0111 // wipe the file 0112 QString fName = getPath(idx); 0113 QFile f(fName); 0114 f.remove(); 0115 0116 // wipe the record and the model entry 0117 d->zones.removeRows(idx, 1); 0118 delete i; 0119 0120 if (!d->zones.rowCount()) 0121 createZone (i18n ("Map #1")); 0122 0123 // and load whichever zone is next, if this one was the current one 0124 // TODO: won't this happen automatically? 0125 d->currentZone = -1; 0126 loadZone(0); 0127 0128 saveMapList(); 0129 } 0130 0131 void CMapZoneManager::createZone(const QString &name, const QString &file) 0132 { 0133 // generate file name if needed 0134 QString fName = file; 0135 if (!fName.length()) { 0136 cProfileManager *pm = cProfileManager::self(); 0137 if (!pm->settings(d->sessId)) fName = "map.xml"; 0138 else 0139 { 0140 int id = 1; 0141 QString path = pm->profilePath (d->sessId) + "/maps/"; 0142 do { 0143 QFile f(path + QString::number(id) + ".xml"); 0144 if (!f.exists()) break; 0145 id++; 0146 } while (1); 0147 fName = QString::number(id) + ".xml"; 0148 } 0149 } 0150 0151 int id = createZoneEntry(name, fName); 0152 loadZone(id); 0153 0154 saveMapList(); 0155 } 0156 0157 void CMapZoneManager::renameZone(int idx, const QString &name) 0158 { 0159 QStandardItem *item = d->zones.item(idx, 0); 0160 if (item && (item->text() != name)) item->setText(name); 0161 cZoneInformation *i = getZoneEntry(idx); 0162 if (i) i->name = name; 0163 } 0164 0165 int CMapZoneManager::createZoneEntry(const QString &name, const QString &file) 0166 { 0167 cZoneInformation *i = new cZoneInformation; 0168 i->name = name; 0169 i->file = file; 0170 0171 QStandardItem *item = new QStandardItem(name); 0172 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); 0173 item->setData(QVariant(qVariantFromValue((void *) i)), Qt::UserRole + 1); 0174 0175 d->zones.appendRow(item); 0176 return d->zones.rowCount() - 1; 0177 } 0178 0179 cZoneInformation *CMapZoneManager::getZoneEntry(int idx) 0180 { 0181 QModelIndex index = d->zones.index(idx, 0); 0182 if (!index.isValid()) return nullptr; 0183 cZoneInformation *i = static_cast<cZoneInformation*>(index.data(Qt::UserRole + 1).value<void *>()); 0184 return i; 0185 } 0186 0187 int CMapZoneManager::activeZone() { 0188 return d->currentZone; 0189 } 0190 0191 void CMapZoneManager::loadMapList() 0192 { 0193 cProfileManager *pm = cProfileManager::self(); 0194 if (!pm->settings(d->sessId)) return; 0195 0196 d->zones.clear(); 0197 QString path = pm->profilePath (d->sessId); 0198 QDir dir = QDir (path); 0199 if (!dir.exists()) QDir::root().mkpath (dir.absolutePath()); 0200 QString fName = "maps.xml"; 0201 0202 QFile f (path + "/" + fName); 0203 if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { 0204 kDebug() << "No " << fName << " file - nothing to do." << endl; 0205 return; 0206 } 0207 0208 QXmlStreamReader *reader = new QXmlStreamReader (&f); 0209 0210 reader->readNext (); // read the document start 0211 reader->readNext (); 0212 if (reader->isStartElement ()) 0213 if (reader->name() == "maps") 0214 if (reader->attributes().value ("version") == "1.0") { 0215 // all is well, we can start loading the list 0216 while (!reader->atEnd()) { 0217 reader->readNext (); 0218 0219 if (reader->isEndElement() && (reader->name() == "maps")) break; 0220 0221 if (reader->isStartElement () && (reader->name() == "map")) { 0222 QString name = reader->attributes().value ("name").toString(); 0223 QString file = reader->attributes().value ("file").toString(); 0224 createZoneEntry(name, file); 0225 } 0226 } 0227 } 0228 else 0229 reader->raiseError (i18n ("This file was created by a newer version of KMuddy, and this version is unable to open it.")); 0230 else 0231 reader->raiseError (i18n ("This is not a KMuddy map list.")); 0232 else if (!reader->hasError()) 0233 reader->raiseError (i18n ("This file is corrupted.")); 0234 0235 if (reader->hasError()) { 0236 kDebug() << i18n ("Error at line %1, column %2: %3", 0237 QString::number (reader->lineNumber()), 0238 QString::number (reader->columnNumber()), 0239 reader->errorString()); 0240 } 0241 0242 d->zones.sort(0); // not perfect, we should sort on the go, but as this class operates by indexes, it'll have to do for now 0243 0244 f.close (); 0245 delete reader; 0246 } 0247 0248 0249 void CMapZoneManager::saveMapList() 0250 { 0251 // save the list contents 0252 cProfileManager *pm = cProfileManager::self(); 0253 if (!pm->settings(d->sessId)) return; 0254 0255 QString path = pm->profilePath (d->sessId); 0256 QDir dir = QDir (path); 0257 if (!dir.exists()) QDir::root().mkpath (dir.absolutePath()); 0258 QString fName = "maps.xml"; 0259 0260 dir.remove ("maps.backup"); 0261 if (!QFile(path + "/" + fName).copy (path + "/" + "maps.backup")) { 0262 kDebug() << "Unable to backup " << fName << endl; // not fatal, may simply not exist 0263 } 0264 0265 QFile f (path + "/" + fName); 0266 if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { 0267 kDebug() << "Unable to open " << (path + "/" + fName) << " for writing." << endl; 0268 return; // problem 0269 } 0270 0271 QXmlStreamWriter *writer = new QXmlStreamWriter (&f); 0272 writer->setAutoFormatting (true); // make the generated XML more readable 0273 0274 writer->writeStartDocument (); 0275 writer->writeStartElement ("maps"); 0276 writer->writeAttribute ("version", "1.0"); 0277 0278 for (int i = 0; i < d->zones.rowCount(); ++i) { 0279 cZoneInformation *zi = getZoneEntry(i); 0280 if (!zi) continue; 0281 0282 writer->writeStartElement ("map"); 0283 writer->writeAttribute ("name", zi->name); 0284 writer->writeAttribute ("file", zi->file); 0285 writer->writeEndElement (); // end the map element 0286 } 0287 0288 writer->writeEndElement (); // end the maps element 0289 writer->writeEndDocument (); 0290 0291 f.close (); 0292 delete writer; 0293 } 0294