• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KIO

kfilemetainfo.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002 
00003    Copyright (c) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org>
00004                  2007 Jos van den Oever <jos@vandenoever.info>
00005                  2010 Sebastian Trueg <trueg@kde.org>
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Library General Public
00009    License (LGPL) as published by the Free Software Foundation; either
00010    version 2 of the License, or (at your option) any later version.
00011 
00012    This library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Library General Public License for more details.
00016 
00017    You should have received a copy of the GNU Library General Public License
00018    along with this library; see the file COPYING.LIB.  If not, write to
00019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020    Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include "kfilemetainfo.h"
00024 #include "kfilemetainfoitem.h"
00025 #include "kfilemetainfoitem_p.h"
00026 #include "kfilewriteplugin.h"
00027 #include "kfilewriteplugin_p.h"
00028 
00029 #include <strigi/bufferedstream.h>
00030 #include <strigi/analyzerconfiguration.h>
00031 #include <strigi/indexwriter.h>
00032 #include <strigi/analysisresult.h>
00033 #include <strigi/fieldtypes.h>
00034 
00035 #include <kurl.h>
00036 #include <kdebug.h>
00037 
00038 #include <QFileInfo>
00039 #include <QDateTime>
00040 #include <QStringList>
00041 
00042 class KFileMetaInfoGroupPrivate : public QSharedData {
00043 public:
00044     QString name;
00045 };
00046 
00047 KFileMetaInfoGroup::~KFileMetaInfoGroup()
00048 {
00049 }
00050 
00051 KFileMetaInfoGroup::KFileMetaInfoGroup ( KFileMetaInfoGroup const& g )
00052 {
00053     d = g.d;
00054 }
00055 
00056 QDataStream& operator >> ( QDataStream& s, KFileMetaInfo& )
00057 {
00058     return s;
00059 }
00060 
00061 QDataStream& operator << ( QDataStream& s, const KFileMetaInfo& )
00062 {
00063     return s;
00064 }
00065 
00069 class QIODeviceInputStream : public Strigi::BufferedInputStream {
00070 private:
00071     QIODevice& in;
00072     const qint64 m_maxRead;
00073     qint64 m_read;
00074     int32_t fillBuffer ( char* start, int32_t space );
00075 public:
00076     QIODeviceInputStream ( QIODevice& i, qint64 max );
00077 };
00078 
00079 int32_t
00080 QIODeviceInputStream::fillBuffer ( char* start, int32_t space )
00081 {
00082     if ( !in.isOpen() || !in.isReadable() )
00083         return -1;
00084 
00085     // we force a max stream read length according to the config since some Strigi
00086     // plugins simply ignore the value which will lead to frozen client apps
00087     qint64 max = m_maxRead;
00088     if(max < 0)
00089         max = space;
00090     else
00091         max = qMin(qint64(space), qMax(max-m_read,qint64(0)));
00092 
00093     // read into the buffer
00094     int32_t nwritten = in.read ( start, max );
00095 
00096     // check the file stream status
00097     if ( nwritten < 0 ) {
00098         m_error = "Could not read from QIODevice.";
00099         in.close();
00100         return -1;
00101     }
00102     if ( nwritten == 0 || in.atEnd() ) {
00103         in.close();
00104     }
00105     m_read += nwritten;
00106     return nwritten;
00107 }
00108 
00109 QIODeviceInputStream::QIODeviceInputStream ( QIODevice& i, qint64 max )
00110     : in ( i ),
00111       m_maxRead(max),
00112       m_read(0)
00113 {
00114     // determine if we have a character device, which will likely never eof and thereby
00115     // potentially cause an infinite loop.
00116     if ( i.isSequential() ) {
00117         in.close(); // cause fillBuffer to return -1
00118     }
00119 }
00120 
00125 class KMetaInfoWriter : public Strigi::IndexWriter {
00126 public:
00127     // irrelevant for KFileMetaInfo
00128     void startAnalysis(const Strigi::AnalysisResult*) {
00129     }
00130 
00131     // irrelevant for KFileMetaInfo
00132     // we do not store text as metainfo
00133     void addText(const Strigi::AnalysisResult*, const char* /*s*/, int32_t /*n*/) {
00134     }
00135     void addValue(const Strigi::AnalysisResult* idx, const Strigi::RegisteredField* field,
00136             const std::string& value) {
00137         if (idx->writerData()) {
00138             QString val = QString::fromUtf8(value.c_str(), value.size());
00139             if( !val.startsWith(':') )
00140                 addValue(idx, field, val);
00141         }
00142     }
00143     void addValue(const Strigi::AnalysisResult* idx, const Strigi::RegisteredField* field,
00144         const unsigned char* data, uint32_t size) {
00145         if (idx->writerData()) {
00146             QByteArray d((const char*)data, size);
00147             addValue(idx, field, QVariant(d));
00148         }
00149     }
00150     void addValue(const Strigi::AnalysisResult* idx, const Strigi::RegisteredField* field,
00151             uint32_t value) {
00152         if (idx->writerData()) {
00153             addValue(idx, field, QVariant((quint32)value));
00154         }
00155     }
00156     void addValue(const Strigi::AnalysisResult* idx, const Strigi::RegisteredField* field,
00157             int32_t value) {
00158         if (idx->writerData()) {
00159             addValue(idx, field, QVariant((qint32)value));
00160         }
00161     }
00162     void addValue(const Strigi::AnalysisResult* idx, const Strigi::RegisteredField* field,
00163             double value) {
00164         if (idx->writerData()) {
00165             addValue(idx, field, QVariant(value));
00166         }
00167     }
00168     void addValue(const Strigi::AnalysisResult* idx,
00169                   const Strigi::RegisteredField* field, const QVariant& value) {
00170         QHash<QString, KFileMetaInfoItem>* info
00171             = static_cast<QHash<QString, KFileMetaInfoItem>*>(
00172             idx->writerData());
00173         if (info) {
00174             std::string name(field->key());
00175             QString key = QString::fromUtf8(name.c_str(), name.size());
00176             QHash<QString, KFileMetaInfoItem>::iterator i = info->find(key);
00177             if (i == info->end()) {
00178                 info->insert(key, KFileMetaInfoItem(key, value, 0, true));
00179             } else {
00180                 i.value().addValue(value);
00181             }
00182         }
00183     }
00184     void addValue(const Strigi::AnalysisResult* ar,
00185                   const Strigi::RegisteredField* field, const std::string& name,
00186             const std::string& value) {
00187         if (ar->writerData()) {
00188             QVariantMap m;
00189             m.insert ( name.c_str(), value.c_str() );
00190             addValue ( ar, field, m );
00191         }
00192     }
00193 
00194     /* irrelevant for KFileMetaInfo: These triples does not convey information
00195      * about this file, so we ignore it
00196      */
00197     void addTriplet ( const std::string& /*subject*/,
00198                       const std::string& /*predicate*/, const std::string& /*object*/ ) {
00199     }
00200 
00201     // irrelevant for KFileMetaInfo
00202     void finishAnalysis(const Strigi::AnalysisResult*) {}
00203     // irrelevant for KFileMetaInfo
00204     void deleteEntries(const std::vector<std::string>&) {}
00205     // irrelevant for KFileMetaInfo
00206     void deleteAllEntries() {}
00207 };
00208 
00209 
00210 class KFileMetaInfoPrivate : public QSharedData
00211 {
00212 public:
00213     QHash<QString, KFileMetaInfoItem> items;
00214     KUrl m_url;
00215 
00216     void init ( QIODevice& stream, const KUrl& url, time_t mtime, KFileMetaInfo::WhatFlags w = KFileMetaInfo::Everything );
00217     void initWriters ( const KUrl& /*file*/ );
00218     void operator= ( const KFileMetaInfoPrivate& k ) {
00219         items = k.items;
00220     }
00221 };
00222 static const KFileMetaInfoItem nullitem;
00223 
00224 class KFileMetaInfoAnalysisConfiguration : public Strigi::AnalyzerConfiguration
00225 {
00226 public:
00227     KFileMetaInfoAnalysisConfiguration( KFileMetaInfo::WhatFlags indexDetail )
00228     : m_indexDetail(indexDetail) {
00229     }
00230 
00231     int64_t maximalStreamReadLength ( const Strigi::AnalysisResult& ar ) {
00232         if(ar.depth() > 0)
00233             return 0; // ignore all data that has a depth > 0, i.e. files in archives
00234         else if(m_indexDetail == KFileMetaInfo::Everything)
00235             return -1;
00236         else
00237             return 65536; // do not read the whole file - this is used for on-the-fly analysis
00238     }
00239 
00240 private:
00241     KFileMetaInfo::WhatFlags m_indexDetail;
00242 };
00243 
00244 void KFileMetaInfoPrivate::init ( QIODevice& stream, const KUrl& url, time_t mtime, KFileMetaInfo::WhatFlags w )
00245 {
00246     m_url = url;
00247 
00248     // get data from Strigi
00249     KFileMetaInfoAnalysisConfiguration c( w );
00250     Strigi::StreamAnalyzer indexer ( c );
00251     KMetaInfoWriter writer;
00252     kDebug ( 7033 ) << url;
00253     Strigi::AnalysisResult idx ( url.toLocalFile().toUtf8().constData(), mtime, writer, indexer );
00254     idx.setWriterData ( &items );
00255 
00256     QIODeviceInputStream strigiStream ( stream, c.maximalStreamReadLength(idx) );
00257     indexer.analyze ( idx, &strigiStream );
00258 
00259     // TODO: get data from Nepomuk
00260 }
00261 
00262 void KFileMetaInfoPrivate::initWriters ( const KUrl& file )
00263 {
00264     QStringList mimetypes;
00265     QHash<QString, KFileMetaInfoItem>::iterator i;
00266     for ( i = items.begin(); i != items.end(); ++i ) {
00267         KFileWritePlugin *w =
00268             KFileWriterProvider::self()->loadPlugin ( i.key() );
00269         if ( w && w->canWrite ( file, i.key() ) ) {
00270             i.value().d->writer = w;
00271         }
00272     }
00273 }
00274 
00275 KFileMetaInfo::KFileMetaInfo ( const QString& path, const QString& /*mimetype*/,
00276                                KFileMetaInfo::WhatFlags w )
00277         : d ( new KFileMetaInfoPrivate() )
00278 {
00279     QFileInfo fileinfo ( path );
00280     QFile file ( path );
00281     // only open the file if it is a filetype Qt understands
00282     // if e.g. the path points to a pipe, it is not opened
00283     if ( ( fileinfo.isFile() || fileinfo.isDir() || fileinfo.isSymLink() )
00284             && file.open ( QIODevice::ReadOnly ) ) {
00285         KUrl u ( path );
00286         d->init ( file, u, fileinfo.lastModified().toTime_t(), w );
00287         if ( fileinfo.isWritable() ) {
00288             d->initWriters ( u );
00289         }
00290     }
00291 }
00292 
00293 KFileMetaInfo::KFileMetaInfo ( const KUrl& url )
00294         : d ( new KFileMetaInfoPrivate() )
00295 {
00296     QFileInfo fileinfo ( url.toLocalFile() );
00297     QFile file ( url.toLocalFile() );
00298     if ( file.open ( QIODevice::ReadOnly ) ) {
00299         d->init ( file, url, fileinfo.lastModified().toTime_t() );
00300         if ( fileinfo.isWritable() ) {
00301             d->initWriters ( url );
00302         }
00303     }
00304 }
00305 
00306 KFileMetaInfo::KFileMetaInfo() : d ( new KFileMetaInfoPrivate() )
00307 {
00308 }
00309 
00310 KFileMetaInfo::KFileMetaInfo ( const KFileMetaInfo& k ) : d ( k.d )
00311 {
00312 }
00313 
00314 const KFileMetaInfo& KFileMetaInfo::operator= ( KFileMetaInfo const & kfmi )
00315 {
00316     d = kfmi.d;
00317     return kfmi;
00318 }
00319 
00320 KFileMetaInfo::~KFileMetaInfo()
00321 {
00322 }
00323 
00324 bool KFileMetaInfo::applyChanges()
00325 {
00326     // go through all editable fields and group them by writer
00327     QHash<KFileWritePlugin*, QVariantMap> data;
00328     QHash<QString, KFileMetaInfoItem>::const_iterator i;
00329     for ( i = d->items.constBegin(); i != d->items.constEnd(); ++i ) {
00330         if ( i.value().isModified() && i.value().d->writer ) {
00331             data[i.value().d->writer][i.key() ] = i.value().value();
00332         }
00333     }
00334 
00335     // call the writers on the data they can write
00336     bool ok = true;
00337     QHash<KFileWritePlugin*, QVariantMap>::const_iterator j;
00338     for ( j = data.constBegin(); j != data.constEnd(); ++j ) {
00339         ok &= j.key()->write ( d->m_url, j.value() );
00340     }
00341     return ok;
00342 }
00343 
00344 const KUrl& KFileMetaInfo::url() const
00345 {
00346     return d->m_url;
00347 }
00348 
00349 const QHash<QString, KFileMetaInfoItem>& KFileMetaInfo::items() const
00350 {
00351     return d->items;
00352 }
00353 
00354 const KFileMetaInfoItem& KFileMetaInfo::item ( const QString& key ) const
00355 {
00356     QHash<QString, KFileMetaInfoItem>::const_iterator i = d->items.constFind ( key );
00357     return ( i == d->items.constEnd() ) ? nullitem : i.value();
00358 }
00359 
00360 QStringList KFileMetaInfo::keys() const
00361 {
00362     return d->items.keys();
00363 }
00364 
00365 KFileMetaInfoItem& KFileMetaInfo::item ( const QString& key )
00366 {
00367     return d->items[key];
00368 }
00369 
00370 bool KFileMetaInfo::isValid() const
00371 {
00372     return !d->m_url.isEmpty();
00373 }
00374 
00375 QStringList KFileMetaInfo::preferredKeys() const
00376 {
00377     return QStringList();
00378 }
00379 
00380 QStringList KFileMetaInfo::supportedKeys() const
00381 {
00382     return QStringList();
00383 }
00384 
00385 #ifndef KDE_NO_DEPRECATED
00386 KFileMetaInfoGroupList KFileMetaInfo::preferredGroups() const
00387 {
00388     return KFileMetaInfoGroupList();
00389 }
00390 #endif
00391 
00392 #ifndef KDE_NO_DEPRECATED
00393 KFileMetaInfoGroupList KFileMetaInfo::supportedGroups() const
00394 {
00395     return KFileMetaInfoGroupList();
00396 }
00397 #endif
00398 
00399 KFileMetaInfoItemList KFileMetaInfoGroup::items() const
00400 {
00401     return KFileMetaInfoItemList();
00402 }
00403 
00404 const QString& KFileMetaInfoGroup::name() const
00405 {
00406     return d->name;
00407 }

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal