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