File indexing completed on 2024-05-12 05:10:14

0001 /***************************************************************************
0002     Copyright (C) 2003-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 "tellicozipexporter.h"
0026 #include "tellicoxmlexporter.h"
0027 #include "../collection.h"
0028 #include "../images/imagefactory.h"
0029 #include "../images/image.h"
0030 #include "../images/imageinfo.h"
0031 #include "../core/filehandler.h"
0032 #include "../tellico_debug.h"
0033 #include "../progressmanager.h"
0034 
0035 #include <KLocalizedString>
0036 #include <KZip>
0037 
0038 #include <QDomDocument>
0039 #include <QBuffer>
0040 #include <QApplication>
0041 
0042 using namespace Tellico;
0043 using Tellico::Export::TellicoZipExporter;
0044 
0045 TellicoZipExporter::TellicoZipExporter(Data::CollPtr coll) : Exporter(coll)
0046     , m_includeImages(true), m_cancelled(false) {
0047 }
0048 
0049 QString TellicoZipExporter::formatString() const {
0050   return QStringLiteral("Zip");
0051 }
0052 
0053 QString TellicoZipExporter::fileFilter() const {
0054   return i18n("Tellico Files") + QLatin1String(" (*.tc *.bc)") + QLatin1String(";;") + i18n("All Files") + QLatin1String(" (*)");
0055 }
0056 
0057 bool TellicoZipExporter::exec() {
0058   m_cancelled = false;
0059   Data::CollPtr coll = collection();
0060   if(!coll) {
0061     return false;
0062   }
0063 
0064   // TODO: maybe need label?
0065   ProgressItem& item = ProgressManager::self()->newProgressItem(this, QString(), true);
0066   item.setTotalSteps(100);
0067   connect(&item, &Tellico::ProgressItem::signalCancelled, this, &Tellico::Export::TellicoZipExporter::slotCancel);
0068   ProgressItem::Done done(this);
0069 
0070   TellicoXMLExporter exp(coll);
0071   exp.setEntries(entries());
0072   exp.setFields(fields());
0073   exp.setURL(url()); // needed in case of relative URL values
0074   long opt = options();
0075   opt |= Export::ExportUTF8; // always export to UTF-8
0076   opt |= Export::ExportImages; // always list the images in the xml
0077   opt &= ~Export::ExportProgress; // don't show progress for xml export
0078   exp.setOptions(opt);
0079   exp.setIncludeImages(false); // do not include the images themselves in XML
0080   QByteArray xml = exp.exportXML().toByteArray(); // encoded in utf-8
0081   ProgressManager::self()->setProgress(this, 5);
0082 
0083   QByteArray data;
0084   QBuffer buf(&data);
0085 
0086   if(m_cancelled) {
0087     return true; // intentionally cancelled
0088   }
0089 
0090   KZip zip(&buf);
0091   zip.open(QIODevice::WriteOnly);
0092   zip.writeFile(QStringLiteral("tellico.xml"), xml);
0093 
0094   if(m_includeImages) {
0095     ProgressManager::self()->setProgress(this, 10);
0096     const QString imagesDir = QStringLiteral("images/");
0097     StringSet imageSet;
0098     // take intersection with the fields to be exported
0099     Data::FieldList imageFields = Tellico::listIntersection(coll->imageFields(), fields());
0100     // already took 10%, only 90% left
0101     const int stepSize = qMax(1, (coll->entryCount() * imageFields.count()) / 90);
0102     int j = 0;
0103     foreach(Data::EntryPtr entry, entries()) {
0104       if(m_cancelled) {
0105         break;
0106       }
0107       foreach(Data::FieldPtr imageField, imageFields) {
0108         const QString id = entry->field(imageField);
0109         if(id.isEmpty() || imageSet.has(id)) {
0110           continue;
0111         }
0112         const Data::ImageInfo& info = ImageFactory::imageInfo(id);
0113         if(info.linkOnly) {
0114           myLog() << "not copying linked image: " << id;
0115           continue;
0116         }
0117         const Data::Image& img = ImageFactory::imageById(id);
0118         // if no image, continue
0119         if(img.isNull()) {
0120           myWarning() << "no image found for " << imageField->title() << " field";
0121           myWarning() << "...for the entry titled " << entry->title();
0122           continue;
0123         }
0124         QByteArray ba = img.byteArray();
0125 //        myDebug() << "adding image id = " << it->field(fIt);
0126         zip.writeFile(imagesDir + id, ba);
0127         imageSet.add(id);
0128         if(j%stepSize == 0) {
0129           ProgressManager::self()->setProgress(this, qMin(10+j/stepSize, 99));
0130           qApp->processEvents();
0131         }
0132         ++j;
0133       }
0134     }
0135   } else {
0136     ProgressManager::self()->setProgress(this, 80);
0137   }
0138 
0139   zip.close();
0140   if(m_cancelled) {
0141     return true;
0142   }
0143 
0144   return FileHandler::writeDataURL(url(), data, options() & Export::ExportForce);
0145 }
0146 
0147 void TellicoZipExporter::slotCancel() {
0148   m_cancelled = true;
0149 }