summaryrefslogtreecommitdiffstats
path: root/src/translators/filelistingimporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/translators/filelistingimporter.cpp')
-rw-r--r--src/translators/filelistingimporter.cpp274
1 files changed, 274 insertions, 0 deletions
diff --git a/src/translators/filelistingimporter.cpp b/src/translators/filelistingimporter.cpp
new file mode 100644
index 0000000..bef9288
--- /dev/null
+++ b/src/translators/filelistingimporter.cpp
@@ -0,0 +1,274 @@
+/***************************************************************************
+ copyright : (C) 2005-2006 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "filelistingimporter.h"
+#include "../collections/filecatalog.h"
+#include "../entry.h"
+#include "../field.h"
+#include "../latin1literal.h"
+#include "../imagefactory.h"
+#include "../tellico_utils.h"
+#include "../tellico_kernel.h"
+#include "../progressmanager.h"
+#include "../core/netaccess.h"
+#include "../tellico_debug.h"
+
+#include <kapplication.h>
+#include <kmountpoint.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+
+#include <qcheckbox.h>
+#include <qvgroupbox.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+
+#include <stdio.h>
+
+namespace {
+ static const int FILE_PREVIEW_SIZE = 128;
+ // volume name starts at 16*2048+40 bytes into the header
+ static const int VOLUME_NAME_POS = 32808;
+ static const int VOLUME_NAME_SIZE = 32;
+}
+
+using Tellico::Import::FileListingImporter;
+
+FileListingImporter::FileListingImporter(const KURL& url_) : Importer(url_), m_coll(0), m_widget(0),
+ m_job(0), m_cancelled(false) {
+ m_files.setAutoDelete(true);
+}
+
+bool FileListingImporter::canImport(int type) const {
+ return type == Data::Collection::File;
+}
+
+Tellico::Data::CollPtr FileListingImporter::collection() {
+ if(m_coll) {
+ return m_coll;
+ }
+
+ ProgressItem& item = ProgressManager::self()->newProgressItem(this, i18n("Scanning files..."), true);
+ item.setTotalSteps(100);
+ connect(&item, SIGNAL(signalCancelled(ProgressItem*)), SLOT(slotCancel()));
+ ProgressItem::Done done(this);
+
+ // going to assume only one volume will ever be imported
+ QString volume = volumeName();
+
+ m_job = m_recursive->isChecked()
+ ? KIO::listRecursive(url(), true, false)
+ : KIO::listDir(url(), true, false);
+ connect(m_job, SIGNAL(entries(KIO::Job*, const KIO::UDSEntryList&)),
+ SLOT(slotEntries(KIO::Job*, const KIO::UDSEntryList&)));
+
+ if(!KIO::NetAccess::synchronousRun(m_job, Kernel::self()->widget()) || m_cancelled) {
+ return 0;
+ }
+
+ const bool usePreview = m_filePreview->isChecked();
+
+ const QString title = QString::fromLatin1("title");
+ const QString url = QString::fromLatin1("url");
+ const QString desc = QString::fromLatin1("description");
+ const QString vol = QString::fromLatin1("volume");
+ const QString folder = QString::fromLatin1("folder");
+ const QString type = QString::fromLatin1("mimetype");
+ const QString size = QString::fromLatin1("size");
+ const QString perm = QString::fromLatin1("permissions");
+ const QString owner = QString::fromLatin1("owner");
+ const QString group = QString::fromLatin1("group");
+ const QString created = QString::fromLatin1("created");
+ const QString modified = QString::fromLatin1("modified");
+ const QString metainfo = QString::fromLatin1("metainfo");
+ const QString icon = QString::fromLatin1("icon");
+
+ m_coll = new Data::FileCatalog(true);
+ QString tmp;
+ const uint stepSize = QMAX(1, m_files.count()/100);
+ const bool showProgress = options() & ImportProgress;
+
+ item.setTotalSteps(m_files.count());
+ uint j = 0;
+ for(KFileItemListIterator it(m_files); !m_cancelled && it.current(); ++it, ++j) {
+ Data::EntryPtr entry = new Data::Entry(m_coll);
+
+ const KURL u = it.current()->url();
+ entry->setField(title, u.fileName());
+ entry->setField(url, u.url());
+ entry->setField(desc, it.current()->mimeComment());
+ entry->setField(vol, volume);
+ tmp = KURL::relativePath(this->url().path(), u.directory());
+ // remove "./" from the string
+ entry->setField(folder, tmp.right(tmp.length()-2));
+ entry->setField(type, it.current()->mimetype());
+ entry->setField(size, KIO::convertSize(it.current()->size()));
+ entry->setField(perm, it.current()->permissionsString());
+ entry->setField(owner, it.current()->user());
+ entry->setField(group, it.current()->group());
+
+ time_t t = it.current()->time(KIO::UDS_CREATION_TIME);
+ if(t > 0) {
+ QDateTime dt;
+ dt.setTime_t(t);
+ entry->setField(created, dt.toString(Qt::ISODate));
+ }
+ t = it.current()->time(KIO::UDS_MODIFICATION_TIME);
+ if(t > 0) {
+ QDateTime dt;
+ dt.setTime_t(t);
+ entry->setField(modified, dt.toString(Qt::ISODate));
+ }
+ const KFileMetaInfo& meta = it.current()->metaInfo();
+ if(meta.isValid() && !meta.isEmpty()) {
+ const QStringList keys = meta.supportedKeys();
+ QStringList strings;
+ for(QStringList::ConstIterator it2 = keys.begin(); it2 != keys.end(); ++it2) {
+ KFileMetaInfoItem item = meta.item(*it2);
+ if(item.isValid()) {
+ QString s = item.string();
+ if(!s.isEmpty()) {
+ strings << item.key() + "::" + s;
+ }
+ }
+ }
+ entry->setField(metainfo, strings.join(QString::fromLatin1("; ")));
+ }
+
+ if(!m_cancelled && usePreview) {
+ m_pixmap = NetAccess::filePreview(it.current(), FILE_PREVIEW_SIZE);
+ if(m_pixmap.isNull()) {
+ m_pixmap = it.current()->pixmap(0);
+ }
+ } else {
+ m_pixmap = it.current()->pixmap(0);
+ }
+
+ if(!m_pixmap.isNull()) {
+ // is png best option?
+ QString id = ImageFactory::addImage(m_pixmap, QString::fromLatin1("PNG"));
+ if(!id.isEmpty()) {
+ entry->setField(icon, id);
+ }
+ }
+
+ m_coll->addEntries(entry);
+
+ if(showProgress && j%stepSize == 0) {
+ ProgressManager::self()->setProgress(this, j);
+ kapp->processEvents();
+ }
+ }
+
+ if(m_cancelled) {
+ m_coll = 0;
+ return 0;
+ }
+
+ return m_coll;
+}
+
+QWidget* FileListingImporter::widget(QWidget* parent_, const char* name_) {
+ if(m_widget) {
+ return m_widget;
+ }
+
+ m_widget = new QWidget(parent_, name_);
+ QVBoxLayout* l = new QVBoxLayout(m_widget);
+
+ QVGroupBox* box = new QVGroupBox(i18n("File Listing Options"), m_widget);
+
+ m_recursive = new QCheckBox(i18n("Recursive folder search"), box);
+ QWhatsThis::add(m_recursive, i18n("If checked, folders are recursively searched for all files."));
+ // by default, make it checked
+ m_recursive->setChecked(true);
+
+ m_filePreview = new QCheckBox(i18n("Generate file previews"), box);
+ QWhatsThis::add(m_filePreview, i18n("If checked, previews of the file contents are generated, which can slow down "
+ "the folder listing."));
+ // by default, make it no previews
+ m_filePreview->setChecked(false);
+
+ l->addWidget(box);
+ l->addStretch(1);
+ return m_widget;
+}
+
+void FileListingImporter::slotEntries(KIO::Job* job_, const KIO::UDSEntryList& list_) {
+ if(m_cancelled) {
+ job_->kill();
+ m_job = 0;
+ return;
+ }
+
+ for(KIO::UDSEntryList::ConstIterator it = list_.begin(); it != list_.end(); ++it) {
+ KFileItem* item = new KFileItem(*it, url(), false, true);
+ if(item->isFile()) {
+ m_files.append(item);
+ } else {
+ delete item;
+ }
+ }
+}
+
+QString FileListingImporter::volumeName() const {
+ // this functions turns /media/cdrom into /dev/hdc, then reads 32 bytes after the 16 x 2048 header
+ QString volume;
+ const KMountPoint::List mountPoints = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName);
+ for(KMountPoint::List::ConstIterator it = mountPoints.begin(), end = mountPoints.end(); it != end; ++it) {
+ // path() could be /media/cdrom
+ // which could be the mount point of the device
+ // I know it works for iso9660 (cdrom) and udf (dvd)
+ if(url().path() == (*it)->mountPoint()
+ && ((*it)->mountType() == Latin1Literal("iso9660")
+ || (*it)->mountType() == Latin1Literal("udf"))) {
+ volume = (*it)->mountPoint();
+ if(!(*it)->realDeviceName().isEmpty()) {
+ QString devName = (*it)->realDeviceName();
+ if(devName.endsWith(QChar('/'))) {
+ devName.truncate(devName.length()-1);
+ }
+ // QFile can't do a sequential seek, and I don't want to do a 32808x loop on getch()
+ FILE* dev = 0;
+ if((dev = fopen(devName.latin1(), "rb")) != 0) {
+ // returns 0 on success
+ if(fseek(dev, VOLUME_NAME_POS, SEEK_SET) == 0) {
+ char buf[VOLUME_NAME_SIZE];
+ int ret = fread(buf, 1, VOLUME_NAME_SIZE, dev);
+ if(ret == VOLUME_NAME_SIZE) {
+ volume = QString::fromLatin1(buf, VOLUME_NAME_SIZE).stripWhiteSpace();
+ }
+ } else {
+ myDebug() << "FileListingImporter::volumeName() - can't seek " << devName << endl;
+ }
+ fclose(dev);
+ } else {
+ myDebug() << "FileListingImporter::volumeName() - can't read " << devName << endl;
+ }
+ }
+ break;
+ }
+ }
+ return volume;
+}
+
+void FileListingImporter::slotCancel() {
+ m_cancelled = true;
+ if(m_job) {
+ m_job->kill();
+ }
+}
+
+#include "filelistingimporter.moc"