📄 bookcasedoc.cpp
字号:
/*************************************************************************** bookcasedoc.cpp ------------------- begin : Sun Sep 9 2001 copyright : (C) 2001 by Robby Stephenson email : robby@periapsis.org ***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of version 2 of the GNU General Public License as * * published by the Free Software Foundation; * * * ***************************************************************************/#include "bookcasedoc.h"#include "bookcase.h"#include "bcunititem.h"#include "bookcollection.h"#include "bcutils.h"#include <kio/netaccess.h>#include <kio/job.h>#include <kdebug.h>#include <kmessagebox.h>#include <ktempfile.h>#include <klocale.h>#include <qwidget.h>#include <qfile.h>#include <qstring.h>#include <qtextstream.h>#include <qregexp.h>/* * VERSION 2 added namespaces, changed to multiple elements, * and changed the "keywords" attribute to "keyword" */static const int SYNTAX_VERSION = 2;static const int OPEN_SIGNAL_STEP_SIZE = 10;//static const int SAVE_SIGNAL_STEP_SIZE = 10;BookcaseDoc::BookcaseDoc(QWidget* parent_, const char* name_/*=0*/) : QObject(parent_, name_), m_isModified(false) { m_collList.setAutoDelete(true); newDocument();}void BookcaseDoc::setModified(bool m_) { m_isModified = m_; if(m_) { emit signalModified(); }}bool BookcaseDoc::isModified() const { return m_isModified;}void BookcaseDoc::setURL(const KURL& url_) { m_url = url_;}const KURL& BookcaseDoc::URL() const { return m_url;}bool BookcaseDoc::newDocument() {// kdDebug() << "BookcaseDoc::newDocument()" << endl; deleteContents(); // a new document always has an empty book collection // the 0 is the collection number BookCollection* coll = new BookCollection(0); // can't call slotAddCollection() because setModified(true) gets called m_collList.append(coll); emit signalCollectionAdded(coll); setModified(false); m_url.setFileName(i18n("Untitled")); return true;}QDomDocument* BookcaseDoc::readDocument(const KURL& url_) const { QString tmpfile; if(!KIO::NetAccess::download(url_, tmpfile)) { Bookcase* app = bookcaseParent(parent()); QString str; if(url_.isLocalFile()) { str = i18n("Bookcase is unable to find the file - %1.").arg(url_.fileName()); } else { str = i18n("Bookcase is unable to download the file - %1.").arg(url_.url()); } KMessageBox::sorry(app, str); return 0; } QFile f(tmpfile); if(!f.open(IO_ReadOnly)) { Bookcase* app = bookcaseParent(parent()); QString str(i18n("Bookcase is unable to open the file - %1.").arg(tmpfile)); KMessageBox::sorry(app, str); KIO::NetAccess::removeTempFile(tmpfile); return 0; } char buf[6]; if(f.readBlock(buf, 5) < 5) { f.close(); Bookcase* app = bookcaseParent(parent()); QString str(i18n("Bookcase is unable to read the file - %1.").arg(tmpfile)); KMessageBox::sorry(app, str); KIO::NetAccess::removeTempFile(tmpfile); return 0; } // Is it plain XML ? if(strncasecmp(buf, "<?xml", 5) != 0) { f.close(); Bookcase* app = bookcaseParent(parent()); QString str(i18n("Bookcase is unable to load the file - %1.").arg(url_.fileName())); KMessageBox::sorry(app, str); KIO::NetAccess::removeTempFile(tmpfile); return 0; } f.at(0); // reset file pointer to beginning QDomDocument* dom = new QDomDocument(); QString errorMsg; int errorLine, errorColumn; if(!dom->setContent(&f, false, &errorMsg, &errorLine, &errorColumn)) { f.close(); Bookcase* app = bookcaseParent(parent()); QString str = i18n("Bookcase is unable to load the file - %1.").arg(url_.fileName()); QString details = i18n("There is an XML parsing error in line %1, column %1.").arg(errorLine).arg(errorColumn); details += QString::fromLatin1("\n"); details += i18n("The error message from Qt is:"); details += QString::fromLatin1("\n"); details += QString::fromLatin1("\t") + errorMsg; KMessageBox::detailedSorry(app, str, details); KIO::NetAccess::removeTempFile(tmpfile); delete dom; return 0; } f.close(); KIO::NetAccess::removeTempFile(tmpfile); return dom;}bool BookcaseDoc::openDocument(const KURL& url_) { QDomDocument* dom = readDocument(url_); if(!dom) { return false; } bool success = loadDomDocument(url_, *dom); delete dom; if(success) { setModified(false); } return success;}bool BookcaseDoc::loadDomDocument(const KURL& url_, const QDomDocument& dom_) { Bookcase* app = bookcaseParent(parent()); QDomElement root = dom_.documentElement(); if(root.tagName() != QString::fromLatin1("bookcase")) { QString str(i18n("Bookcase is unable to load the file - %1.").arg(url_.fileName())); KMessageBox::sorry(app, str); return false; } // the syntax version attribute name changed from "version" to "syntaxVersion" int syntaxVersion; if(root.hasAttribute(QString::fromLatin1("syntaxVersion"))) { syntaxVersion = root.attribute(QString::fromLatin1("syntaxVersion")).toInt(); } else if (root.hasAttribute(QString::fromLatin1("version"))) { syntaxVersion = root.attribute(QString::fromLatin1("version")).toInt(); } else { QString str(i18n("Bookcase is unable to load the file - %1.").arg(url_.fileName())); KMessageBox::sorry(app, str); return false; } if(syntaxVersion > SYNTAX_VERSION) { QString str(i18n("Bookcase is unable to load the file - %1.").arg(url_.fileName())); str += QString::fromLatin1("\n"); str += i18n("It is from a future version of Bookcase."); KMessageBox::sorry(app, str); return false; } else if(syntaxVersion < SYNTAX_VERSION) { kdDebug() << "BookcaseDoc::loadDomDocument() - converting from syntax version " << syntaxVersion << " to " << SYNTAX_VERSION << endl; } // now the document can finally be loaded deleteContents(); setURL(url_); QDomNodeList collelems = root.elementsByTagName(QString::fromLatin1("collection")); if(collelems.count() > 1) { kdWarning() << "BookcaseDoc::openDocument() - There is more than one collection." "This isn't supported at the moment. Only the first will be loaded." << endl; }// for now, don't support more than one collection// for(unsigned i = 0; i < collelems.count(); ++i) { for(unsigned i = 0; i < 1; ++i) { QDomElement collelem = collelems.item(i).toElement(); QString title = collelem.attribute(QString::fromLatin1("title")); QString unit = collelem.attribute(QString::fromLatin1("unit")); QString unitTitle = collelem.attribute(QString::fromLatin1("unitTitle")); BCCollection* coll; if(unit == QString::fromLatin1("book")) { coll = new BookCollection(collectionCount());#if 0 } else if(unit == QString::fromLatin1("cd")) { coll = BCCollection::CDs(collectionCount()); } else if(unit == QString::fromLatin1("video")) { coll = BCCollection::Videos(collectionCount());#endif } else { coll = new BCCollection(collectionCount(), title, unit, unitTitle); } // since the static operators have default titles if(!title.isEmpty()) { coll->setTitle(title); } // do not do this yet, we want the collection to have all of its attributes first // slotAddCollection(coll); // there will only be attributes if it's a custom collection QDomNodeList attelems = collelem.elementsByTagName(QString::fromLatin1("attribute"));// kdDebug() << QString("BookcaseDoc::openDocument() - There are %1 attribute(s).\n").arg(attelems.count()); for(unsigned j = 0; j < attelems.count(); ++j) { QDomElement attelem = attelems.item(j).toElement(); QString attName = attelem.attribute(QString::fromLatin1("name"), QString::fromLatin1("unknown")); QString attTitle = attelem.attribute(QString::fromLatin1("title"), i18n("Unknown")); QString attTypeStr = attelem.attribute(QString::fromLatin1("type")); // is it ok to cast from an enum to an int? BCAttribute::AttributeType attType = static_cast<BCAttribute::AttributeType>(attTypeStr.toInt()); BCAttribute* att; if(attType == BCAttribute::Choice) { QString attAllowed = attelem.attribute(QString::fromLatin1("allowed")); att = new BCAttribute(attName, attTitle, QStringList::split(QString::fromLatin1(";"), attAllowed)); } else { att = new BCAttribute(attName, attTitle, attType); } if(attelem.hasAttribute(QString::fromLatin1("category"))) { att->setCategory(attelem.attribute(QString::fromLatin1("category"))); } if(attelem.hasAttribute(QString::fromLatin1("flags"))) { att->setFlags(attelem.attribute(QString::fromLatin1("flags")).toInt()); } if(attelem.hasAttribute(QString::fromLatin1("description"))) { att->setDescription(attelem.attribute(QString::fromLatin1("description"))); } coll->addAttribute(att);// kdDebug() << QString(" Added attribute: %1, %2").arg(att->name()).arg(att->title()) << endl; } coll->blockSignals(true); // do this now that we have all the attributes slotAddCollection(coll); QDomNodeList unitelems = collelem.elementsByTagName(unit);// kdDebug() << QString("BookcaseDoc::openDocument() - There are %1 %2(s) in the collection.").arg(unitelems.count()).arg(unit) << endl; for(unsigned j = 0; j < unitelems.count(); ++j) { BCUnit* unit = new BCUnit(coll); QDomNode attNode = unitelems.item(j).firstChild(); for( ; !attNode.isNull(); attNode = attNode.nextSibling()) { // BCUnit::setAttribute checks to see if an attribute of 'name' is allowed // checkbox attributes have no text(), set it to "1" if(attNode.toElement().text().isEmpty()) { // "1" means checked unit->setAttribute(attNode.toElement().tagName(), QString::fromLatin1("1")); } else { QString attName = attNode.toElement().tagName(); // if the first child of the attNode is a text node, just add it // otherwise, recurse over the attNode's children // this is the case for <authors><author>..</author></authors> if(attNode.firstChild().nodeType() == QDomNode::TextNode) { // in version 2, "keywords" changed to "keyword" if(syntaxVersion < 2 && attName == QString::fromLatin1("keywords")) { attName = QString::fromLatin1("keyword"); } unit->setAttribute(attName, attNode.toElement().text()); } else { QString attValue; QDomNode attChildNode = attNode.firstChild(); for( ; !attChildNode.isNull(); attChildNode = attChildNode.nextSibling()) { attValue += attChildNode.toElement().text() + QString::fromLatin1("; "); } // remove the last semi-color and space attValue.truncate(attValue.length() - 2); // now the attName has the final 's', so remove it unit->setAttribute(attName.left(attName.length()-1), attValue); } } } // end attribute list slotAddUnit(unit); // emit a signal every 5 units loaded float f; if(j%OPEN_SIGNAL_STEP_SIZE == 0) { // allocate equal time to each collection in document // i is number of collection // j is number of unit f = i+static_cast<float>(j)/static_cast<float>(unitelems.count()); f *= 1.0/static_cast<float>(collelems.count()); emit signalFractionDone(f); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -