File indexing completed on 2024-05-12 05:10:14
0001 /*************************************************************************** 0002 Copyright (C) 2020 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #include "tellicoxmlreader.h" 0026 #include "tellico_xml.h" 0027 #include "xmlstatehandler.h" 0028 #include "../collection.h" 0029 #include "../tellico_debug.h" 0030 0031 #include <KLocalizedString> 0032 0033 using Tellico::Import::TellicoXmlReader; 0034 0035 TellicoXmlReader::TellicoXmlReader(const QUrl& baseUrl_) : m_data(new SAX::StateData) { 0036 m_data->baseUrl = baseUrl_; 0037 m_handlers.push(new SAX::RootHandler(m_data)); 0038 } 0039 0040 TellicoXmlReader::~TellicoXmlReader() { 0041 delete m_data; 0042 m_data = nullptr; 0043 qDeleteAll(m_handlers); 0044 m_handlers.clear(); 0045 } 0046 0047 bool TellicoXmlReader::readNext(const QByteArray& data_) { 0048 Q_ASSERT(!m_handlers.isEmpty()); 0049 if(m_handlers.isEmpty()) { 0050 return false; 0051 } 0052 0053 m_xml.addData(data_); 0054 while(!m_xml.atEnd()) { 0055 const auto tokenType = m_xml.readNext(); 0056 switch(tokenType) { 0057 case QXmlStreamReader::StartElement: 0058 handleStart(); 0059 break; 0060 case QXmlStreamReader::EndElement: 0061 handleEnd(); 0062 break; 0063 case QXmlStreamReader::Characters: 0064 handleCharacters(); 0065 break; 0066 case QXmlStreamReader::Invalid: 0067 if(m_xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) { 0068 myDebug() << "Error!" << m_xml.errorString(); 0069 } 0070 continue; // break out of while loop 0071 default: 0072 // not handling anything else 0073 break; 0074 } 0075 } 0076 // success is no error or error being simply premature end of document 0077 return !m_xml.hasError() || m_xml.error() == QXmlStreamReader::PrematureEndOfDocumentError; 0078 } 0079 0080 QString TellicoXmlReader::errorString() const { 0081 // for custom errors, include the line and column number 0082 return m_xml.error() == QXmlStreamReader::CustomError ? 0083 QString::fromLatin1("Fatal parsing error in line %1, column %2. %3") 0084 .arg(m_xml.lineNumber()) 0085 .arg(m_xml.columnNumber()) 0086 .arg(m_xml.errorString()) : 0087 m_xml.errorString(); 0088 } 0089 0090 bool TellicoXmlReader::isNotWellFormed() const { 0091 return m_xml.error() == QXmlStreamReader::NotWellFormedError; 0092 } 0093 0094 Tellico::Data::CollPtr TellicoXmlReader::collection() const { 0095 return m_data->coll; 0096 } 0097 0098 bool TellicoXmlReader::hasImages() const { 0099 return m_data->hasImages; 0100 } 0101 0102 void TellicoXmlReader::setLoadImages(bool loadImages_) { 0103 m_data->loadImages = loadImages_; 0104 } 0105 0106 void TellicoXmlReader::setShowImageLoadErrors(bool showImageErrors_) { 0107 m_data->showImageLoadErrors = showImageErrors_; 0108 } 0109 0110 void TellicoXmlReader::handleStart() { 0111 SAX::StateHandler* handler = m_handlers.top()->nextHandler(m_xml.namespaceUri(), m_xml.name()); 0112 Q_ASSERT(handler); 0113 m_handlers.push(handler); 0114 if(!handler->start(m_xml.namespaceUri(), m_xml.name(), m_xml.attributes())) { 0115 m_xml.raiseError(m_data->error); 0116 } 0117 } 0118 0119 void TellicoXmlReader::handleEnd() { 0120 m_data->text = m_data->text.trimmed(); 0121 SAX::StateHandler* handler = m_handlers.pop(); 0122 if(!handler->end(m_xml.namespaceUri(), m_xml.name())) { 0123 m_xml.raiseError(m_data->error); 0124 } 0125 // need to reset character data, too 0126 m_data->text.clear(); 0127 delete handler; 0128 } 0129 0130 void TellicoXmlReader::handleCharacters() { 0131 m_data->text.append(m_xml.text()); 0132 }