File indexing completed on 2024-05-12 05:09:45
0001 /*************************************************************************** 0002 Copyright (C) 2008-2009 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 "xmlfetcher.h" 0026 #include "../translators/xslthandler.h" 0027 #include "../translators/tellicoimporter.h" 0028 #include "../utils/guiproxy.h" 0029 #include "../utils/xmlhandler.h" 0030 #include "../utils/string_utils.h" 0031 #include "../utils/datafileregistry.h" 0032 #include "../tellico_debug.h" 0033 0034 #include <KIO/Job> 0035 #include <KIO/JobUiDelegate> 0036 0037 #include <QFile> 0038 #include <QTextStream> 0039 #include <QTextCodec> 0040 #include <KJobWidgets/KJobWidgets> 0041 0042 using Tellico::Fetch::XMLFetcher; 0043 0044 XMLFetcher::XMLFetcher(QObject* parent_) : Fetcher(parent_) 0045 , m_xsltHandler(nullptr) 0046 , m_started(false) 0047 , m_limit(0) { 0048 } 0049 0050 XMLFetcher::~XMLFetcher() { 0051 delete m_xsltHandler; 0052 m_xsltHandler = nullptr; 0053 } 0054 0055 void XMLFetcher::search() { 0056 m_started = true; 0057 resetSearch(); 0058 doSearch(); 0059 } 0060 0061 void XMLFetcher::continueSearch() { 0062 m_started = true; 0063 doSearch(); 0064 } 0065 0066 void XMLFetcher::doSearch() { 0067 const QUrl u = searchUrl(); 0068 if(u.isEmpty()) { 0069 myDebug() << source() << "- empty search url"; 0070 stop(); 0071 return; 0072 } 0073 // myDebug() << "url: " << u.url(); 0074 0075 m_job = KIO::storedGet(u, KIO::NoReload, KIO::HideProgressInfo); 0076 KJobWidgets::setWindow(m_job, GUI::Proxy::widget()); 0077 connect(m_job.data(), &KJob::result, this, &XMLFetcher::slotComplete); 0078 } 0079 0080 void XMLFetcher::stop() { 0081 if(!m_started) { 0082 return; 0083 } 0084 if(m_job) { 0085 m_job->kill(); 0086 m_job = nullptr; 0087 } 0088 m_started = false; 0089 emit signalDone(this); 0090 } 0091 0092 void XMLFetcher::slotComplete(KJob* ) { 0093 Q_ASSERT(m_job); 0094 if(m_job->error()) { 0095 myDebug() << source() << ":" << m_job->errorString(); 0096 m_job->uiDelegate()->showErrorMessage(); 0097 stop(); 0098 return; 0099 } 0100 0101 if(!m_xsltHandler) { 0102 initXSLTHandler(); 0103 if(!m_xsltHandler) { // probably an error somewhere in the stylesheet loading 0104 stop(); 0105 return; 0106 } 0107 } 0108 0109 QByteArray data = m_job->data(); 0110 if(data.isEmpty()) { 0111 myDebug() << "no data"; 0112 stop(); 0113 return; 0114 } 0115 // see bug 319662. If fetcher is cancelled, job is killed 0116 // if the pointer is retained, it gets double-deleted 0117 m_job = nullptr; 0118 0119 #if 0 0120 myWarning() << "Remove debug from xmlfetcher.cpp"; 0121 QFile f(QStringLiteral("/tmp/test.xml")); 0122 if(f.open(QIODevice::WriteOnly)) { 0123 QTextStream t(&f); 0124 t.setCodec("utf-8"); 0125 t << data; 0126 } 0127 f.close(); 0128 #endif 0129 0130 parseData(data); 0131 0132 const QString str = m_xsltHandler->applyStylesheet(XMLHandler::readXMLData(data)); 0133 #if 0 0134 myWarning() << "Remove debug from xmlfetcher.cpp"; 0135 QFile f2(QStringLiteral("/tmp/test-tellico.xml")); 0136 if(f2.open(QIODevice::WriteOnly)) { 0137 QTextStream t(&f2); 0138 t.setCodec("utf-8"); 0139 t << str; 0140 } 0141 f2.close(); 0142 #endif 0143 Import::TellicoImporter imp(str); 0144 // be quiet when loading images 0145 imp.setOptions(imp.options() ^ Import::ImportShowImageErrors); 0146 Data::CollPtr coll = imp.collection(); 0147 if(!coll) { 0148 myDebug() << "no collection pointer"; 0149 stop(); 0150 return; 0151 } 0152 0153 if(m_limit < 1) { 0154 myDebug() << "Limit < 1, changing to 1"; 0155 m_limit = 1; 0156 } 0157 0158 int count = 0; 0159 foreach(Data::EntryPtr entry, coll->entries()) { 0160 if(count >= m_limit) { 0161 break; 0162 } 0163 if(!m_started) { 0164 // might get aborted 0165 break; 0166 } 0167 0168 FetchResult* r = new FetchResult(this, entry); 0169 m_entries.insert(r->uid, entry); 0170 emit signalResultFound(r); 0171 ++count; 0172 } 0173 0174 checkMoreResults(m_entries.count()); 0175 stop(); // required 0176 } 0177 0178 Tellico::Data::EntryPtr XMLFetcher::fetchEntryHook(uint uid_) { 0179 Data::EntryPtr entry = m_entries[uid_]; 0180 if(!entry) { 0181 myWarning() << "no entry in dict"; 0182 return Data::EntryPtr(); 0183 } 0184 0185 // the fetcher might end up creating a new entry 0186 return fetchEntryHookData(entry); 0187 } 0188 0189 void XMLFetcher::initXSLTHandler() { 0190 Q_ASSERT(!m_xsltFilename.isEmpty()); 0191 QString xsltfile = DataFileRegistry::self()->locate(m_xsltFilename); 0192 if(xsltfile.isEmpty()) { 0193 myWarning() << "can not locate" << m_xsltFilename; 0194 return; 0195 } 0196 0197 QUrl u = QUrl::fromLocalFile(xsltfile); 0198 0199 delete m_xsltHandler; 0200 m_xsltHandler = new XSLTHandler(u); 0201 if(!m_xsltHandler->isValid()) { 0202 myWarning() << "error in" << m_xsltFilename; 0203 delete m_xsltHandler; 0204 m_xsltHandler = nullptr; 0205 return; 0206 } 0207 } 0208 0209 void XMLFetcher::setXSLTFilename(const QString& filename_) { 0210 if(!filename_.isEmpty() && filename_ != m_xsltFilename) { 0211 m_xsltFilename = filename_; 0212 delete m_xsltHandler; 0213 m_xsltHandler = nullptr; 0214 } 0215 } 0216 0217 void XMLFetcher::setLimit(int limit_) { 0218 Q_ASSERT(limit_ > 0); 0219 m_limit = limit_; 0220 } 0221 0222 Tellico::XSLTHandler* XMLFetcher::xsltHandler() { 0223 Q_ASSERT(m_xsltHandler); 0224 return m_xsltHandler; 0225 }