00001 #include <QDomDocument>
00002 #include <QCoreApplication>
00003 #include <QTextStream>
00004 #include <QDebug>
00005 #include <QFile>
00006 #include <QtAlgorithms>
00007 #include "dataproject.h"
00008 #include "datafolderhistory.h"
00009 #include "datahash.h"
00010 #include "project.h"
00011
00012 bool DataProject::loadXml(const QString &path)
00013 {
00014 QFile file(path);
00015 QDomDocument doc;
00016 unsigned int fileHash = 0, myHash;
00017
00018 if(!file.open(QIODevice::ReadOnly))
00019 {
00020 emit error(ErrorFile, "Dateizugriffsfehler beim Laden von \"" + path + "\", prüfen Sie die Zugriffsberechtigung!");
00021 qDebug() << "DataProject::loadXml(): can't open file, check permissions!";
00022 return false;
00023 }
00024
00025 if(!doc.setContent(&file))
00026 {
00027 emit error(ErrorXml, "Ungültiges Dateiformat von \"" + path + "\": XML Syntaxfehler!");
00028 qDebug() << "DataProject::loadXml(): can't set DOM content, check XML syntax!";
00029 file.close();
00030 return false;
00031 }
00032 file.close();
00033
00034 QDomElement root = doc.documentElement();
00035 if(root.nodeName() != "Allevo")
00036 {
00037 emit error(ErrorFormat, "Ungültiges Dateiformat von \"" + path + "\": Fehler im XML-Aufbau!");
00038 qDebug() << "Root element not called Allevo";
00039 return false;
00040 }
00041 QDomNode node = root.firstChild();
00042 while(!node.isNull())
00043 {
00044 if(node.nodeName() == "chapter")
00045 {
00046 DataChapter *chap = new DataChapter();
00047 if(!chap->loadDataNode(node))
00048 {
00049 emit error(ErrorFormat, "Ungültiges Dateiformat von \"" + path + "\": Fehler im XML-Aufbau!");
00050 qDebug() << "loading a chapter returned an error";
00051 delete chap;
00052 return false;
00053 }
00054 connect(chap, SIGNAL(changed()), this, SLOT(dataChanged()));
00055
00056
00057
00058 chapters.append(chap);
00059 }
00060 else if(node.nodeName() == "tableOfAccounts")
00061 {
00062 QDomNode nodeAcc = node.firstChild();
00063 while(!nodeAcc.isNull())
00064 {
00065 if(nodeAcc.nodeName() == "account")
00066 {
00067 DataTableAccount *acc = new DataTableAccount();
00068 if(!acc->loadDataNode(nodeAcc))
00069 {
00070 emit error(ErrorFormat, "Ungültiges Dateiformat von \"" + path + "\": Fehler im XML-Aufbau!");
00071 qDebug() << "loading an account returned an error";
00072 delete acc;
00073 return false;
00074 }
00075
00076
00077 accountList.append(acc);
00078 }
00079 else if(nodeAcc.nodeName() != "#comment")
00080 {
00081 qDebug() << "Unknown element in accounts tag:" << nodeAcc.nodeName();
00082 }
00083 nodeAcc = nodeAcc.nextSibling();
00084 }
00085 }
00086 else if(node.nodeName() == "folder")
00087 {
00088 QDomNode historyEntry = node.firstChild();
00089 while(!historyEntry.isNull())
00090 {
00091 if(historyEntry.nodeName() == "historyEntry")
00092 {
00093 DataFolderHistory *folder = new DataFolderHistory();
00094 if(!folder->loadDataNode(historyEntry))
00095 {
00096 emit error(ErrorFormat, "Ungültiges Dateiformat von \"" + path + "\": Fehler im XML-Aufbau!");
00097 qDebug() << "loading a history entry returned an error";
00098 delete folder;
00099 return false;
00100 }
00101 if(!changeHistory.size())
00102 folder->updateProjectData();
00103
00104 changeHistory.append(folder);
00105 }
00106 else if(historyEntry.nodeName() != "#comment")
00107 {
00108 qDebug() << "Unknown element in folder tag:" << historyEntry.nodeName();
00109 }
00110 historyEntry = historyEntry.nextSibling();
00111 }
00112 }
00113 else if(node.nodeName() == "hash")
00114 {
00115 bool ok;
00116 fileHash = node.firstChild().nodeValue().simplified().toUInt(&ok);
00117 }
00118 else if(node.nodeName() != "#comment")
00119 {
00120 qDebug() << "Unknown element in Allevo tag:" << node.nodeName();
00121 }
00122 node = node.nextSibling();
00123 }
00124 myHash = hash();
00125
00126 if(myHash != fileHash)
00127 {
00128
00129
00130
00131
00132
00133
00134 qDebug() << "Warning: Calculated hash of" << path << "(" << myHash << ") differs from the value stored (" << fileHash << ")";
00135 }
00136 changed = false;
00137 return true;
00138 }
00139
00140 bool DataProject::saveXml(const QString &path)
00141 {
00142 QDomDocument xml;
00143
00144 QDomElement root = xml.createElement(QCoreApplication::applicationName());
00145 root.setAttribute("program", QCoreApplication::organizationDomain());
00146 root.setAttribute("version", QCoreApplication::applicationVersion());
00147 xml.appendChild(root);
00148
00149
00150 if(!Project::dateCreation().isValid())
00151 {
00152 Project::setDateCreation(QDateTime::currentDateTime());
00153 }
00154
00155
00156 Project::setDateModified(QDateTime::currentDateTime());
00157
00158
00159 qDebug()<<"CRASH: save file in teacher mode -- changehistory -- dataproject.cpp";
00160 if(changeHistory.count() > 0)
00161 {
00162
00163 if(changeHistory[0]->differsFromProject())
00164 {
00165 changeHistory.prepend(DataFolderHistory::fromProject());
00166 }
00167 else
00168 {
00169 changeHistory[0]->refreshModificationDate();
00170 }
00171 }
00172 else
00173 {
00174 changeHistory.prepend(DataFolderHistory::fromProject());
00175 }
00176
00177 QDomElement eFolder = xml.createElement("folder");
00178 for(int i = 0; i < changeHistory.size(); i++)
00179 {
00180 eFolder.appendChild(changeHistory[i]->saveDataNode(&xml));
00181 }
00182 root.appendChild(eFolder);
00183
00184
00185 root.appendChild(createTextElement(&xml, "hash", QString::number(hash())));
00186
00187 for(int i = 0; i < chapters.size(); i++)
00188 {
00189 root.appendChild(chapters[i]->saveDataNode(&xml));
00190 }
00191
00192 QDomElement eAccounts = xml.createElement("tableOfAccounts");
00193 for(int i = 0; i < accountList.size(); i++)
00194 {
00195 eAccounts.appendChild(accountList[i]->saveDataNode(&xml));
00196 }
00197 root.appendChild(eAccounts);
00198
00199 qDebug()<<"Path before extension: " << path;
00200 QString tPath = addFileExtension(path);
00201 qDebug()<<"Path after extension: " << tPath;
00202
00203 QFile file(tPath);
00204 if(!file.open(QIODevice::WriteOnly))
00205 {
00206 emit error(ErrorFile, "Kein Schreibzugriff auf Datei \"" + path + "\": Prüfen Sie die Zugriffsberechtigung!");
00207 return false;
00208 }
00209 QTextStream ts(&file);
00210 ts << xml.toString();
00211 file.close();
00212
00213 changed = false;
00214 return true;
00215 }
00216
00217 QString DataProject::addFileExtension(const QString path)
00218 {
00219 QString tPath = path;
00220 switch(p_projectType)
00221 {
00222 case FileType::Exercise:
00223 {
00224 tPath.remove(".dbku");
00225 tPath += ".dbku";
00226 break;
00227 }
00228 case FileType::Task:
00229 {
00230 tPath.remove(".dbka");
00231 tPath += ".dbka";
00232 break;
00233 }
00234 }
00235 return tPath;
00236 }
00237
00238 QDomElement DataProject::createTextElement(QDomDocument *xml, const QString &tagName, const QString &content)
00239 {
00240 QDomElement element = xml->createElement(tagName);
00241 element.appendChild(xml->createTextNode(content));
00242 return element;
00243 }
00244
00245 void DataProject::setProjectType(FileType::Type type)
00246 {
00247 p_projectType = type;
00248 }
00249
00250 FileType::Type DataProject::projectType()
00251 {
00252 return p_projectType;
00253 }
00254
00255 DataProject::DataProject()
00256 {
00257 changed = false;
00258 }
00259
00260 DataProject::~DataProject()
00261 {
00262 qDeleteAll(chapters);
00263 qDeleteAll(accountList);
00264 qDeleteAll(changeHistory);
00265 chapters.clear();
00266 accountList.clear();
00267 changeHistory.clear();
00268 }
00269
00270 unsigned int DataProject::hash()
00271 {
00272
00273
00274 unsigned int startValue = 0;
00275
00276 for(int i = 0; i < changeHistory.size(); i++)
00277 {
00278 changeHistory[i]->hash(startValue);
00279 }
00280
00281 for(int i = 0; i < chapters.size(); i++)
00282 {
00283 chapters[i]->hash(startValue);
00284 }
00285 return startValue;
00286 }
00287
00288 DataExercise* DataProject::exercise(const QString &chapter, const QString &exercise) const
00289 {
00290 for(int i = 0; i < chapters.size(); i++)
00291 {
00292 if(chapters.value(i)->name() == chapter)
00293 {
00294 QList<DataExercise *> ex = chapters.value(i)->exercises();
00295 for(int j = 0; j < ex.size(); j++)
00296 {
00297 if(ex.value(j)->name() == exercise)
00298 {
00299 return ex.value(j);
00300 }
00301 }
00302 }
00303 }
00304 return NULL;
00305 }
00306
00307 DataChapter* DataProject::chapter(const QString &name) const
00308 {
00309 for(int i = 0; i < chapters.size(); i++)
00310 {
00311 if(chapters.value(i)->name() == name)
00312 {
00313 return chapters.value(i);
00314 }
00315 }
00316 return NULL;
00317 }
00318
00319 void DataProject::dataChanged()
00320 {
00321 changed = true;
00322 }