Commit 527e88ed authored by Scott Wheeler's avatar Scott Wheeler

Port the Cache over to being FileHandle based and make the needed changes

everywhere else...

svn path=/trunk/kdemultimedia/juk/; revision=295979
parent a9a6d203
......@@ -55,9 +55,9 @@ void Cache::save()
QByteArray data;
QDataStream s(data, IO_WriteOnly);
for(QDictIterator<Tag>it(*this); it.current(); ++it) {
s << it.current()->fileName();
s << *(it.current());
for(Iterator it = begin(); it != end(); ++it) {
s << (*it).absFilePath();
s << *it;
}
QDataStream fs(&f);
......@@ -77,7 +77,7 @@ void Cache::save()
// protected methods
////////////////////////////////////////////////////////////////////////////////
Cache::Cache() : QDict<Tag>(m_cacheSize)
Cache::Cache() : FileHandleHash()
{
}
......@@ -134,7 +134,8 @@ void Cache::load()
s >> fileName;
fileName.squeeze();
Tag *t = new Tag(fileName);
s >> *t;
FileHandle f(fileName);
s >> f;
// f.setFile(fileName);
}
}
......@@ -18,11 +18,13 @@
#ifndef CACHE_H
#define CACHE_H
#include <qdict.h>
#include <qdatastream.h>
#include "stringhash.h"
class Tag;
class Cache : public QDict<Tag>
class Cache : public FileHandleHash
{
public:
static Cache *instance();
......@@ -34,11 +36,6 @@ protected:
private:
static Cache *m_cache;
/**
* Note this number is a prime number that should be larger than the target
* size of the dict.
*/
static const int m_cacheSize = 5003;
static const int m_currentVersion = 1;
};
......
......@@ -22,9 +22,9 @@
#include <kpopupmenu.h>
#include <kiconloader.h>
#include "collectionlist.h"
#include "splashscreen.h"
#include "cache.h"
////////////////////////////////////////////////////////////////////////////////
// static methods
......@@ -43,9 +43,14 @@ void CollectionList::initialize(QWidget *parent, bool restoreOnLoad)
// TODO: don't fetch the fileInfo from the tag, but rather from the FileHandle
if(restoreOnLoad)
for(QDictIterator<Tag>it(*Cache::instance()); it.current(); ++it)
new CollectionListItem(it.current()->fileInfo(), it.current()->fileName());
if(restoreOnLoad) {
for(FileHandleHash::Iterator it = Cache::instance()->begin();
it != Cache::instance()->end();
++it)
{
new CollectionListItem((*it).fileInfo(), (*it).absFilePath());
}
}
}
////////////////////////////////////////////////////////////////////////////////
......
......@@ -21,6 +21,7 @@
#include <kapplication.h>
#include <kdirwatch.h>
#include <qdict.h>
#include <qclipboard.h>
#include "playlist.h"
......
......@@ -15,10 +15,13 @@
* *
***************************************************************************/
#include <kdebug.h>
#include <qfileinfo.h>
#include "filehandle.h"
#include "tag.h"
#include "cache.h"
/**
* A simple reference counter -- pasted from TagLib.
......@@ -42,8 +45,10 @@ public:
tag(0) {}
mutable Tag *tag;
QFileInfo fileInfo;
mutable QString absFilePath;
QFileInfo fileInfo;
QDateTime modificationTime;
QDateTime lastModified;
};
////////////////////////////////////////////////////////////////////////////////
......@@ -52,26 +57,27 @@ public:
FileHandle::FileHandle()
{
d = new FileHandlePrivate;
static FileHandlePrivate *nullPrivate = new FileHandlePrivate;
d = nullPrivate;
d->ref();
}
FileHandle::FileHandle(const FileHandle &f) : d(f.d)
FileHandle::FileHandle(const FileHandle &f) :
d(f.d)
{
d->ref();
}
FileHandle::FileHandle(const QFileInfo &info, const QString &path)
FileHandle::FileHandle(const QFileInfo &info, const QString &path) :
d(0)
{
d = new FileHandlePrivate;
d->fileInfo = info;
d->absFilePath = path.isNull() ? info.absFilePath() : path;
setup(info, path);
}
FileHandle::FileHandle(const QString &path)
FileHandle::FileHandle(const QString &path) :
d(0)
{
d = new FileHandlePrivate;
d->absFilePath = path;
d->fileInfo.setFile(path);
setup(QFileInfo(path), path);
}
FileHandle::~FileHandle()
......@@ -89,8 +95,12 @@ void FileHandle::refresh()
void FileHandle::setFile(const QString &path)
{
d->fileInfo.setFile(path);
d->absFilePath = d->fileInfo.absFilePath();
if(!d || isNull())
setup(QFileInfo(path), path);
else {
d->absFilePath = path;
d->fileInfo.setFile(path);
}
}
Tag *FileHandle::tag() const
......@@ -113,18 +123,38 @@ const QFileInfo &FileHandle::fileInfo() const
return d->fileInfo;
}
bool FileHandle::isNull() const
{
return *this == null();
}
bool FileHandle::current() const
{
return(d->tag->m_modificationTime.isValid() &&
return(d->modificationTime.isValid() &&
lastModified().isValid() &&
d->tag->m_modificationTime >= lastModified());
d->modificationTime >= lastModified());
}
const QDateTime &FileHandle::lastModified() const
{
// TODO: this should be done internally once the cache is FileHandle based
if(d->lastModified.isNull())
d->lastModified = d->fileInfo.lastModified();
return d->lastModified;
}
void FileHandle::read(CacheDataStream &s)
{
switch(s.cacheVersion()) {
case 1:
default:
if(!d->tag)
d->tag = new Tag(d->absFilePath);
return d->tag->lastModified();
s >> *(d->tag);
s >> d->modificationTime;
break;
}
}
FileHandle &FileHandle::operator=(const FileHandle &f)
......@@ -145,3 +175,57 @@ bool FileHandle::operator==(const FileHandle &f) const
{
return d == f.d;
}
bool FileHandle::operator!=(const FileHandle &f) const
{
return d != f.d;
}
const FileHandle &FileHandle::null() // static
{
static FileHandle f;
return f;
}
////////////////////////////////////////////////////////////////////////////////
// private methods
////////////////////////////////////////////////////////////////////////////////
void FileHandle::setup(const QFileInfo &info, const QString &path)
{
if(d && !isNull())
return;
QString fileName = path.isNull() ? info.absFilePath() : path;
FileHandle cached = Cache::instance()->value(fileName);
if(cached != null()) {
d = cached.d;
d->ref();
}
else {
d = new FileHandlePrivate;
d->fileInfo = info;
d->absFilePath = fileName;
Cache::instance()->insert(*this);
}
}
////////////////////////////////////////////////////////////////////////////////
// related functions
////////////////////////////////////////////////////////////////////////////////
QDataStream &operator<<(QDataStream &s, const FileHandle &f)
{
s << *(f.tag())
<< f.lastModified();
return s;
}
CacheDataStream &operator>>(CacheDataStream &s, FileHandle &f)
{
f.read(s);
return s;
}
......@@ -16,9 +16,14 @@
***************************************************************************/
#ifndef JUK_FILEHANDLE_H
#define JUK_FILEHANLDE_H
#define JUK_FILEHANDLE_H
class QFileInfo;
class QDateTime;
class QDataStream;
class Tag;
class CacheDataStream;
/**
* An value based, explicitly shared wrapper around file related information
......@@ -30,7 +35,7 @@ class FileHandle
public:
FileHandle();
FileHandle(const FileHandle &f);
FileHandle(const QFileInfo &info, const QString &path = QString::null);
explicit FileHandle(const QFileInfo &info, const QString &path = QString::null);
explicit FileHandle(const QString &path);
~FileHandle();
......@@ -44,15 +49,26 @@ public:
QString absFilePath() const;
const QFileInfo &fileInfo() const;
bool isNull() const;
bool current() const;
const QDateTime &lastModified() const;
void read(CacheDataStream &s);
FileHandle &operator=(const FileHandle &f);
bool operator==(const FileHandle &f) const;
bool operator!=(const FileHandle &f) const;
static const FileHandle &null();
private:
class FileHandlePrivate;
FileHandlePrivate *d;
void setup(const QFileInfo &info, const QString &path);
};
QDataStream &operator<<(QDataStream &s, const FileHandle &f);
CacheDataStream &operator>>(CacheDataStream &s, FileHandle &f);
#endif
......@@ -31,6 +31,7 @@
#include "tagguesserconfigdlg.h"
#include "filerenamerconfigdlg.h"
#include "actioncollection.h"
#include "cache.h"
using namespace ActionCollection;
......
......@@ -47,6 +47,7 @@ FileHandle PlaylistItem::file() const
QString PlaylistItem::text(int column) const
{
// kdDebug(65432) << k_funcinfo << "column == " << column << ", title == "<< d->fileHandle.tag()->title() << endl;
if(!d->fileHandle.tag())
return QString::null;
......
......@@ -30,7 +30,6 @@
#include "musicbrainzquery.h"
#include "tagguesser.h"
#include "tag.h"
#include "cache.h"
#include "filehandle.h"
#if HAVE_MUSICBRAINZ == 0
......
......@@ -18,8 +18,11 @@
#ifndef STRINGHASH_H
#define STRINGHASH_H
#include <qstringlist.h>
#include <qstring.h>
#include <qptrvector.h>
#include <qvaluelist.h>
#include "filehandle.h"
/**
* A simple hash representing an (un-mapped) set of data.
......@@ -27,6 +30,7 @@
template <class T> class Hash
{
friend class Iterator;
public:
Hash() : m_table(m_tableSize) {}
......@@ -55,16 +59,57 @@ public:
static inline int tableSize() { return m_tableSize; }
private:
protected:
struct Node
{
Node(T value) : key(value), next(0) {}
~Node() {}
T key;
Node *next;
};
public:
class Iterator
{
friend class Hash<T>;
public:
Iterator(const Hash<T> &hash) : m_hash(hash), m_index(0), m_node(hash.m_table[0]) {}
const T &operator*() const { return m_node->key; }
T &operator*() { return m_node->key; }
bool operator==(const Iterator &it) const { return m_index == it.m_index && m_node == it.m_node; }
bool operator!=(const Iterator &it) const { return !(it == *this); }
T &operator++();
private:
const Hash<T> &m_hash;
int m_index;
Node *m_node;
};
Iterator begin() const
{
Iterator it(*this);
while(!it.m_node && it.m_index < m_tableSize - 1) {
it.m_index++;
it.m_node = m_table[it.m_index];
}
return it;
}
Iterator end() const
{
Iterator it(*this);
it.m_node = 0;
it.m_index = m_tableSize - 1;
return it;
}
protected:
void deleteNode(Node *n);
QPtrVector<Node> m_table;
......@@ -109,12 +154,47 @@ inline int hashString(const StringType &s)
// specializations
////////////////////////////////////////////////////////////////////////////////
template<> inline int Hash<QString>::hash(QString key) const { return hashString(key) % tableSize(); }
// StringHash
template<> inline int Hash<QString>::hash(QString key) const
{
return hashString(key) % tableSize();
}
typedef Hash<QString> StringHash;
template<> inline int Hash<void *>::hash(void *key) const { return long(key) % tableSize(); }
// PtrHash
template<> inline int Hash<void *>::hash(void *key) const
{
return long(key) % tableSize();
}
typedef Hash<void *> PtrHash;
// FileHandleHash
template<> inline int Hash<FileHandle>::hash(FileHandle key) const
{
return hashString(key.absFilePath()) % tableSize();
}
class FileHandleHash : public Hash<FileHandle>
{
public:
FileHandleHash() : Hash<FileHandle>() {}
FileHandle FileHandleHash::value(const QString &key) const
{
int h = hashString(key) % tableSize();
Node *i = m_table[h];
while(i && i->key.absFilePath() != key)
i = i->next;
return i ? i->key : FileHandle::null();
}
};
////////////////////////////////////////////////////////////////////////////////
// template method implementations
////////////////////////////////////////////////////////////////////////////////
......@@ -218,4 +298,19 @@ void Hash<T>::deleteNode(Node *n)
}
}
template <class T>
T &Hash<T>::Iterator::operator++()
{
if(m_node)
m_node = m_node->next;
while(!m_node && m_index < m_tableSize - 1) {
m_index++;
m_node = m_hash.m_table[m_index];
}
return m_node->key;
}
#endif
......@@ -36,16 +36,8 @@
// public members
////////////////////////////////////////////////////////////////////////////////
Tag *Tag::createTag(const QString &fileName, bool ignoreCache)
Tag *Tag::createTag(const QString &fileName)
{
Tag *cachedItem = 0;
if(!ignoreCache)
cachedItem = Cache::instance()->find(fileName);
if(cachedItem)
return cachedItem;
if(MediaFiles::isMP3(fileName)) {
TagLib::MPEG::File file(QFile::encodeName(fileName).data());
if(!file.isValid())
......@@ -73,11 +65,6 @@ Tag *Tag::createTag(const QString &fileName, bool ignoreCache)
return 0;
}
Tag::~Tag()
{
Cache::instance()->remove(m_fileName);
}
void Tag::save()
{
TagLib::ID3v2::FrameFactory::instance()->setDefaultTextEncoding(TagLib::String::UTF8);
......@@ -109,14 +96,6 @@ void Tag::save()
delete file;
}
const QDateTime &Tag::lastModified() const
{
if(m_lastModified.isNull())
m_lastModified = m_info.lastModified();
return m_lastModified;
}
CacheDataStream &Tag::read(CacheDataStream &s)
{
switch(s.cacheVersion()) {
......@@ -135,8 +114,7 @@ CacheDataStream &Tag::read(CacheDataStream &s)
>> m_comment
>> bitrate
>> m_lengthString
>> seconds
>> m_modificationTime;
>> seconds;
m_track = track;
m_year = year;
......@@ -163,8 +141,7 @@ CacheDataStream &Tag::read(CacheDataStream &s)
>> bitrateString
>> m_lengthString
>> m_seconds
>> dummyString
>> m_modificationTime;
>> dummyString;
bool ok;
m_bitrate = bitrateString.toInt(&ok);
......@@ -199,7 +176,7 @@ Tag::Tag(const QString &file) :
m_seconds(0),
m_bitrate(0)
{
Cache::instance()->insert(file, this);
}
Tag::Tag(const QString &fileName, TagLib::File *file) :
......@@ -227,8 +204,6 @@ Tag::Tag(const QString &fileName, TagLib::File *file) :
int i = m_fileName.findRev('.');
m_title = i > 0 ? m_fileName.left(i) : m_fileName;
}
Cache::instance()->insert(fileName, this);
}
////////////////////////////////////////////////////////////////////////////////
......@@ -246,8 +221,7 @@ QDataStream &operator<<(QDataStream &s, const Tag &t)
<< t.comment()
<< Q_INT32(t.bitrate())
<< t.lengthString()
<< Q_INT32(t.seconds())
<< t.lastModified();
<< Q_INT32(t.seconds());
return s;
}
......
......@@ -39,9 +39,7 @@ public:
* the appropriate concrete subclass and instantiates that. It's servering
* as a mini-factory; a full blown abstract factory is an overkill here.
*/
static Tag *createTag(const QString &fileName, bool ignoreCache = false);
~Tag();
static Tag *createTag(const QString &fileName);
void save();
......@@ -72,7 +70,6 @@ public:
CacheDataStream &read(CacheDataStream &s);
// TODO -- REMOVE THESE METHODS ONCE THE CACHE IS FILEHANDLE BASED
const QDateTime &lastModified() const;
const QFileInfo &fileInfo() const { return m_info; }
const QString &fileName() const { return m_fileName; }
......@@ -87,7 +84,6 @@ private:
QFileInfo m_info;
QString m_fileName;
mutable QDateTime m_lastModified;
QString m_title;
QString m_artist;
QString m_album;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment