You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tellico/src/translators/filelistingimporter.cpp

275 lines
9.3 KiB

/***************************************************************************
copyright : (C) 2005-2006 by Robby Stephenson
email : robby@periapsis.org
***************************************************************************/
/***************************************************************************
* *
* 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 <tdeapplication.h>
#include <kmountpoint.h>
#include <tdeio/job.h>
#include <tdeio/netaccess.h>
#include <tqcheckbox.h>
#include <tqvgroupbox.h>
#include <tqlayout.h>
#include <tqwhatsthis.h>
#include <tqfile.h>
#include <tqfileinfo.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, TQ_SIGNAL(signalCancelled(ProgressItem*)), TQ_SLOT(slotCancel()));
ProgressItem::Done done(this);
// going to assume only one volume will ever be imported
TQString volume = volumeName();
m_job = m_recursive->isChecked()
? TDEIO::listRecursive(url(), true, false)
: TDEIO::listDir(url(), true, false);
connect(m_job, TQ_SIGNAL(entries(TDEIO::Job*, const TDEIO::UDSEntryList&)),
TQ_SLOT(slotEntries(TDEIO::Job*, const TDEIO::UDSEntryList&)));
if(!TDEIO::NetAccess::synchronousRun(m_job, Kernel::self()->widget()) || m_cancelled) {
return 0;
}
const bool usePreview = m_filePreview->isChecked();
const TQString title = TQString::fromLatin1("title");
const TQString url = TQString::fromLatin1("url");
const TQString desc = TQString::fromLatin1("description");
const TQString vol = TQString::fromLatin1("volume");
const TQString folder = TQString::fromLatin1("folder");
const TQString type = TQString::fromLatin1("mimetype");
const TQString size = TQString::fromLatin1("size");
const TQString perm = TQString::fromLatin1("permissions");
const TQString owner = TQString::fromLatin1("owner");
const TQString group = TQString::fromLatin1("group");
const TQString created = TQString::fromLatin1("created");
const TQString modified = TQString::fromLatin1("modified");
const TQString metainfo = TQString::fromLatin1("metainfo");
const TQString icon = TQString::fromLatin1("icon");
m_coll = new Data::FileCatalog(true);
TQString tmp;
const uint stepSize = TQMAX(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, TDEIO::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(TDEIO::UDS_CREATION_TIME);
if(t > 0) {
TQDateTime dt;
dt.setTime_t(t);
entry->setField(created, dt.toString(TQt::ISODate));
}
t = it.current()->time(TDEIO::UDS_MODIFICATION_TIME);
if(t > 0) {
TQDateTime dt;
dt.setTime_t(t);
entry->setField(modified, dt.toString(TQt::ISODate));
}
const KFileMetaInfo& meta = it.current()->metaInfo();
if(meta.isValid() && !meta.isEmpty()) {
const TQStringList keys = meta.supportedKeys();
TQStringList strings;
for(TQStringList::ConstIterator it2 = keys.begin(); it2 != keys.end(); ++it2) {
KFileMetaInfoItem item = meta.item(*it2);
if(item.isValid()) {
TQString s = item.string();
if(!s.isEmpty()) {
strings << item.key() + "::" + s;
}
}
}
entry->setField(metainfo, strings.join(TQString::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?
TQString id = ImageFactory::addImage(m_pixmap, TQString::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;
}
TQWidget* FileListingImporter::widget(TQWidget* parent_, const char* name_) {
if(m_widget) {
return m_widget;
}
m_widget = new TQWidget(parent_, name_);
TQVBoxLayout* l = new TQVBoxLayout(m_widget);
TQVGroupBox* box = new TQVGroupBox(i18n("File Listing Options"), m_widget);
m_recursive = new TQCheckBox(i18n("Recursive folder search"), box);
TQWhatsThis::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 TQCheckBox(i18n("Generate file previews"), box);
TQWhatsThis::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(TDEIO::Job* job_, const TDEIO::UDSEntryList& list_) {
if(m_cancelled) {
job_->kill();
m_job = 0;
return;
}
for(TDEIO::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;
}
}
}
TQString FileListingImporter::volumeName() const {
// this functions turns /media/cdrom into /dev/hdc, then reads 32 bytes after the 16 x 2048 header
TQString 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()) {
TQString devName = (*it)->realDeviceName();
if(devName.endsWith(TQChar('/'))) {
devName.truncate(devName.length()-1);
}
// TQFile 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 = TQString::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"