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

0001 /***************************************************************************
0002     Copyright (C) 2005-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 <config.h>
0026 
0027 #include "filelistingimporter.h"
0028 #include "filereader.h"
0029 #include "filereaderbook.h"
0030 #include "filereadervideo.h"
0031 #include "../collections/bookcollection.h"
0032 #include "../collections/videocollection.h"
0033 #include "../collections/filecatalog.h"
0034 #include "../entry.h"
0035 #include "../gui/collectiontypecombo.h"
0036 #include "../utils/guiproxy.h"
0037 #include "../progressmanager.h"
0038 #include "../tellico_debug.h"
0039 
0040 #include <KLocalizedString>
0041 #include <KJobWidgets/KJobWidgets>
0042 #include <KIO/Job>
0043 
0044 #include <QDate>
0045 #include <QDir>
0046 #include <QCheckBox>
0047 #include <QGroupBox>
0048 #include <QFile>
0049 #include <QFileInfo>
0050 #include <QVBoxLayout>
0051 #include <QApplication>
0052 
0053 using Tellico::Import::FileListingImporter;
0054 
0055 FileListingImporter::FileListingImporter(const QUrl& url_) : Importer(url_), m_coll(nullptr), m_widget(nullptr),
0056     m_recursive(nullptr), m_filePreview(nullptr), m_job(nullptr), m_useFilePreview(false), m_cancelled(false) {
0057 }
0058 
0059 bool FileListingImporter::canImport(int type) const {
0060   return type == Data::Collection::Book ||
0061       type == Data::Collection::Video ||
0062       type == Data::Collection::File;
0063 }
0064 
0065 Tellico::Data::CollPtr FileListingImporter::collection() {
0066   if(m_coll) {
0067     return m_coll;
0068   }
0069 
0070   ProgressItem& item = ProgressManager::self()->newProgressItem(this, i18n("Scanning files..."), true);
0071   item.setTotalSteps(100);
0072   connect(&item, &Tellico::ProgressItem::signalCancelled, this, &FileListingImporter::slotCancel);
0073   ProgressItem::Done done(this);
0074 
0075   // the importer might be running without a gui/widget
0076   m_job = (m_widget && m_recursive->isChecked())
0077           ? KIO::listRecursive(url(), KIO::DefaultFlags, false /* include hidden */)
0078           : KIO::listDir(url(), KIO::DefaultFlags, false /* include hidden */);
0079   KJobWidgets::setWindow(m_job, GUI::Proxy::widget());
0080   void (KIO::ListJob::* jobEntries)(KIO::Job*, const KIO::UDSEntryList&) = &KIO::ListJob::entries;
0081   connect(static_cast<KIO::ListJob*>(m_job.data()), jobEntries, this, &FileListingImporter::slotEntries);
0082 
0083   if(!m_job->exec() || m_cancelled) {
0084     myDebug() << "did not run job:" << m_job->errorString();
0085     return Data::CollPtr();
0086   }
0087 
0088   int collType = Data::Collection::File;
0089   if(m_widget) {
0090     m_useFilePreview = m_filePreview->isChecked();
0091     collType = m_collCombo->currentType();
0092   }
0093 
0094   const uint stepSize = qMax(1, m_files.count()/100);
0095   const bool showProgress = options() & ImportProgress;
0096   item.setTotalSteps(m_files.count());
0097 
0098   std::unique_ptr<AbstractFileReader> reader;
0099   switch(collType) {
0100     case(Data::Collection::Book):
0101       m_coll = new Data::BookCollection(true);
0102       {
0103         auto ptr = new FileReaderBook(url());
0104         ptr->setUseFilePreview(m_useFilePreview);
0105         reader.reset(ptr);
0106       }
0107       break;
0108 
0109     case(Data::Collection::Video):
0110       m_coll = new Data::VideoCollection(true);
0111       {
0112         auto ptr = new FileReaderVideo(url());
0113         ptr->setUseFilePreview(m_useFilePreview);
0114         reader.reset(ptr);
0115       }
0116       break;
0117 
0118     case(Data::Collection::File):
0119       m_coll = new Data::FileCatalog(true);
0120       {
0121         auto ptr = new FileReaderFile(url());
0122         ptr->setUseFilePreview(m_useFilePreview);
0123         reader.reset(ptr);
0124       }
0125       break;
0126   }
0127   Data::EntryList entries;
0128   uint j = 0;
0129   foreach(const KFileItem& item, m_files) {
0130     if(m_cancelled) {
0131       break;
0132     }
0133 
0134     Data::EntryPtr entry(new Data::Entry(m_coll));
0135     if(reader->populate(entry, item)) {
0136       entries += entry;
0137     }
0138 
0139     if(showProgress && j%stepSize == 0) {
0140       ProgressManager::self()->setProgress(this, j);
0141       qApp->processEvents();
0142     }
0143     ++j;
0144   }
0145   m_coll->addEntries(entries);
0146 
0147   if(m_cancelled) {
0148     m_coll = Data::CollPtr();
0149     return m_coll;
0150   }
0151 
0152   return m_coll;
0153 }
0154 
0155 QWidget* FileListingImporter::widget(QWidget* parent_) {
0156   if(m_widget) {
0157     return m_widget;
0158   }
0159 
0160   m_widget = new QWidget(parent_);
0161   QVBoxLayout* l = new QVBoxLayout(m_widget);
0162 
0163   QGroupBox* gbox = new QGroupBox(i18n("File Listing Options"), m_widget);
0164   QVBoxLayout* vlay = new QVBoxLayout(gbox);
0165 
0166   m_recursive = new QCheckBox(i18n("Recursive folder search"), gbox);
0167   m_recursive->setWhatsThis(i18n("If checked, folders are recursively searched for all files."));
0168   // by default, make it checked
0169   m_recursive->setChecked(true);
0170 
0171   m_filePreview = new QCheckBox(i18n("Generate file previews"), gbox);
0172   m_filePreview->setWhatsThis(i18n("If checked, previews of the file contents are generated, which can slow down "
0173                                    "the folder listing."));
0174   // by default, make it no previews
0175   m_filePreview->setChecked(false);
0176 
0177   QList<int> collTypes;
0178   collTypes << Data::Collection::Book << Data::Collection::Video << Data::Collection::File;
0179   m_collCombo = new GUI::CollectionTypeCombo(gbox);
0180   m_collCombo->setIncludedTypes(collTypes);
0181   // default to file catalog
0182   m_collCombo->setCurrentData(Data::Collection::File);
0183 
0184   vlay->addWidget(m_recursive);
0185   vlay->addWidget(m_filePreview);
0186   vlay->addWidget(m_collCombo);
0187 
0188   l->addWidget(gbox);
0189   l->addStretch(1);
0190   return m_widget;
0191 }
0192 
0193 void FileListingImporter::slotEntries(KIO::Job* job_, const KIO::UDSEntryList& list_) {
0194   if(m_cancelled) {
0195     job_->kill();
0196     m_job = nullptr;
0197     return;
0198   }
0199 
0200   for(KIO::UDSEntryList::ConstIterator it = list_.begin(); it != list_.end(); ++it) {
0201     KFileItem item(*it, url(), false, true);
0202     if(item.isFile()) {
0203       m_files.append(item);
0204     }
0205   }
0206 }
0207 
0208 void FileListingImporter::slotCancel() {
0209   m_cancelled = true;
0210   if(m_job) {
0211     m_job->kill();
0212   }
0213 }