diff --git a/include/local_resources_provider.h b/include/local_resources_provider.h index 4ada250c0..6b7352300 100644 --- a/include/local_resources_provider.h +++ b/include/local_resources_provider.h @@ -32,17 +32,17 @@ class LocalResourcesProvider : public ResourcesProvider { public: LocalResourcesProvider( const QString & _url, - ResourcesDB::Item::BaseDirectory _baseDir ); + ResourcesItem::BaseDirectory _baseDir ); virtual ~LocalResourcesProvider() { } virtual ResourcesDB * createResourcesDB( void ); - virtual QByteArray fetchData( const ResourcesDB::Item * _item ); + virtual QByteArray fetchData( const ResourcesItem * _item ); private: - ResourcesDB::Item::BaseDirectory m_baseDir; + ResourcesItem::BaseDirectory m_baseDir; } ; diff --git a/include/resources_db.h b/include/resources_db.h index 34505cf7a..eca8b32c1 100644 --- a/include/resources_db.h +++ b/include/resources_db.h @@ -31,361 +31,14 @@ #include #include -#define foreachTreeItem(list) \ - for(ResourcesDB::TreeItemList::Iterator it=list.begin();\ - it!=list.end();++it) +#include "resources_tree_item.h" -#define foreachConstTreeItem(list) \ - for(ResourcesDB::TreeItemList::ConstIterator it=list.begin(); \ - it!=list.end();++it) class ResourcesDB : public QObject { Q_OBJECT public: - class Item; - class TreeItem; - typedef QHash ItemList; - typedef QList TreeItemList; - - class Item - { - public: - enum BaseDirectories - { - BaseRoot, - BaseWorkingDir, - BaseDataDir, - BaseHome, - NumBaseDirectories - } ; - typedef BaseDirectories BaseDirectory; - - enum Types - { - TypeUnknown, - TypeDirectory, - TypeSample, - TypeSoundFont, - TypePreset, - TypeProject, - TypeMidiFile, - TypeForeignProject, - TypePlugin, - TypeImage, - NumTypes - } ; - typedef Types Type; - - Item( const QString & _name, - Types _type, - BaseDirectories _base_dir = BaseWorkingDir, - const QString & _path = QString::null, - const QString & _hash = QString::null, - const QString & _tags = QString::null, - int _size = -1, - const QDateTime & _last_mod = QDateTime() ) : - m_name( _name ), - m_nameHash( 0 ), - m_type( _type ), - m_baseDir( _base_dir ), - m_path( _path ), - m_hash( _hash ), - m_size( _size ), - m_lastMod( _last_mod ), - m_tags( _tags ), - m_treeItem( NULL ) - { - init(); - } - - Item() : - m_name(), - m_nameHash( 0 ), - m_type( TypeUnknown ), - m_baseDir( BaseRoot ), - m_path(), - m_hash(), - m_size( -1 ), - m_lastMod(), - m_tags(), - m_treeItem( NULL ) - { - init(); - } - - - const QString & name( void ) const - { - return m_name; - } - - inline int nameHash( void ) const - { - return m_nameHash; - } - - Types type( void ) const - { - return m_type; - } - - const QString & path( void ) const - { - return m_path; - } - - BaseDirectories baseDir( void ) const - { - return m_baseDir; - } - - QString fullPath( void ) const - { - return getBaseDirectory( m_baseDir ) + m_path; - } - - QString fullName( void ) const - { - if( m_type == TypeDirectory ) - { - return fullPath(); - } - return fullPath()+name(); - } - - const QString & hash( void ) const - { - return m_hash; - } - - int size( void ) const - { - return m_size; - } - - bool isShippedResource( void ) const - { - return baseDir() == BaseDataDir; - } - - const QString & tags( void ) const - { - return m_tags; - } - - bool isValid( void ) const - { - return m_type != TypeUnknown && !m_name.isEmpty(); - } - - void setTreeItem( TreeItem * _ti ) - { - m_treeItem = _ti; - } - - TreeItem * treeItem( void ) - { - return m_treeItem; - } - - const QDateTime & lastMod( void ) const - { - return m_lastMod; - } - - void setLastMod( const QDateTime & _date ) - { - m_lastMod = _date; - } - - void reload( void ); - - bool operator==( const Item & _other ) const; - - // rates equality with given item - int equalityLevel( const Item & _other ) const; - - Types guessType( void ) const; - - static QString getBaseDirectory( BaseDirectories _bd ); - - - private: - void init( void ); - - QString m_name; - int m_nameHash; - Types m_type; - BaseDirectories m_baseDir; - QString m_path; - QString m_hash; - int m_size; - QDateTime m_lastMod; - QString m_tags; - - TreeItem * m_treeItem; - - } ; - - class TreeItem - { - public: - TreeItem( TreeItem * _parent = NULL, Item * _item = NULL ) : - m_parent( _parent ), - m_hidden( false ), - m_temporaryMarker( false ), - m_item( _item ) - { - if( m_parent ) - { - m_parent->addChild( this ); - } - if( m_item ) - { - m_item->setTreeItem( this ); - } - } - - ~TreeItem() - { - foreachTreeItem( m_children ) - { - delete *it; - } - if( m_item ) - { - m_item->setTreeItem( NULL ); - } - if( m_parent ) - { - m_parent->removeChild( this ); - } - } - - inline void setHidden( bool _h ) - { - m_hidden = _h; - } - - inline bool isHidden( void ) const - { - return m_hidden; - } - - inline int rowCount( void ) const - { - int rc = 0; - foreachConstTreeItem( m_children ) - { - if( !(*it)->isHidden() ) - { - ++rc; - } - } - return rc; - } - - TreeItem * getChild( int _row ) - { - int rc = 0; - foreachTreeItem( m_children ) - { - if( !(*it)->isHidden() ) - { - if( rc == _row ) - { - return *it; - } - ++rc; - } - } - return NULL; - } - - int row( void ) const - { - if( !m_parent ) - { - return 0; - } - - int row = 0; - foreachConstTreeItem( m_parent->m_children ) - { - if( !(*it)->isHidden() ) - { - if( *it == this ) - { - return row; - } - ++row; - } - } - return 0; - } - - inline void addChild( TreeItem * _it ) - { - m_children.push_back( _it ); - } - - inline void removeChild( TreeItem * _it ) - { - m_children.removeAll( _it ); - } - - inline TreeItemList & children( void ) - { - return m_children; - } - - inline const TreeItemList & children( void ) const - { - return m_children; - } - - TreeItem * findChild( const QString & _name, - Item::BaseDirectories _base_dir ); - - inline Item * item( void ) - { - return m_item; - } - - inline const Item * item( void ) const - { - return m_item; - } - - inline TreeItem * parent( void ) - { - return m_parent; - } - - inline bool temporaryMarker( void ) const - { - return m_temporaryMarker; - } - - inline void setTemporaryMarker( bool _on ) - { - m_temporaryMarker = _on; - } - - - private: - // hide copy-ctor - TreeItem( const TreeItem & ) { } - - TreeItem * m_parent; - QList m_children; - - bool m_hidden; - bool m_temporaryMarker; - - Item * m_item; - } ; + typedef QHash ItemList; ResourcesDB( const QString & _db_file ); @@ -400,30 +53,32 @@ public: return m_items; } - inline TreeItem * topLevelNode( void ) + inline ResourcesTreeItem * topLevelNode( void ) { return &m_topLevelNode; } - const Item * nearestMatch( const Item & _item ); + const ResourcesItem * nearestMatch( const ResourcesItem & _item ); private slots: void reloadDirectory( const QString & _path ); + private: - void readDir( const QString & _dir, TreeItem * _parent, - Item::BaseDirectories _base_dir ); - void replaceItem( Item * newItem ); - void recursiveRemoveItems( TreeItem * parent, + void readDir( const QString & _dir, ResourcesTreeItem * _parent, + ResourcesItem::BaseDirectory _base_dir ); + void replaceItem( ResourcesItem * newItem ); + void recursiveRemoveItems( ResourcesTreeItem * parent, bool removeTopLevelParent = true ); - void saveTreeItem( const TreeItem * _i, QDomDocument & _doc, + void saveTreeItem( const ResourcesTreeItem * _i, QDomDocument & _doc, QDomElement & _de ); - void loadTreeItem( TreeItem * _i, QDomElement & _de ); + void loadTreeItem( ResourcesTreeItem * _i, QDomElement & _de ); - typedef QList > FolderList; + typedef QList > + FolderList; FolderList m_folders; QStringList m_scannedFolders; QFileSystemWatcher m_watcher; @@ -431,7 +86,7 @@ private: QString m_dbFile; ItemList m_items; - TreeItem m_topLevelNode; + ResourcesTreeItem m_topLevelNode; signals: diff --git a/include/resources_item.h b/include/resources_item.h new file mode 100644 index 000000000..45a941548 --- /dev/null +++ b/include/resources_item.h @@ -0,0 +1,187 @@ +/* + * resources_item.h - header file for ResourcesItem + * + * Copyright (c) 2009 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef _RESOURCES_ITEM_H +#define _RESOURCES_ITEM_H + +#include + + +class ResourcesTreeItem; + +class ResourcesItem +{ +public: + enum BaseDirectories + { + BaseRoot, + BaseWorkingDir, + BaseDataDir, + BaseHome, + NumBaseDirectories + } ; + typedef BaseDirectories BaseDirectory; + + enum Types + { + TypeUnknown, + TypeDirectory, + TypeSample, + TypeSoundFont, + TypePreset, + TypeProject, + TypeMidiFile, + TypeForeignProject, + TypePlugin, + TypeImage, + NumTypes + } ; + typedef Types Type; + + ResourcesItem(); + ResourcesItem( const QString & _name, + Type _type, + BaseDirectory _base_dir = BaseWorkingDir, + const QString & _path = QString::null, + const QString & _hash = QString::null, + const QString & _tags = QString::null, + int _size = -1, + const QDateTime & _last_mod = QDateTime() ); + + + const QString & name( void ) const + { + return m_name; + } + + inline int nameHash( void ) const + { + return m_nameHash; + } + + Type type( void ) const + { + return m_type; + } + + const QString & path( void ) const + { + return m_path; + } + + BaseDirectory baseDir( void ) const + { + return m_baseDir; + } + + QString fullPath( void ) const + { + return getBaseDirectory( m_baseDir ) + m_path; + } + + QString fullName( void ) const + { + if( m_type == TypeDirectory ) + { + return fullPath(); + } + return fullPath()+name(); + } + + const QString & hash( void ) const + { + return m_hash; + } + + int size( void ) const + { + return m_size; + } + + bool isShippedResource( void ) const + { + return baseDir() == BaseDataDir; + } + + const QString & tags( void ) const + { + return m_tags; + } + + bool isValid( void ) const + { + return m_type != TypeUnknown && !m_name.isEmpty(); + } + + void setTreeItem( ResourcesTreeItem * _ti ) + { + m_treeItem = _ti; + } + + ResourcesTreeItem * treeItem( void ) + { + return m_treeItem; + } + + const QDateTime & lastMod( void ) const + { + return m_lastMod; + } + + void setLastMod( const QDateTime & _date ) + { + m_lastMod = _date; + } + + void reload( void ); + + bool operator==( const ResourcesItem & _other ) const; + + // rates equality with given item + int equalityLevel( const ResourcesItem & _other ) const; + + Type guessType( void ) const; + + static QString getBaseDirectory( BaseDirectory _bd ); + + +private: + void init( void ); + + QString m_name; + int m_nameHash; + Type m_type; + BaseDirectory m_baseDir; + QString m_path; + QString m_hash; + int m_size; + QDateTime m_lastMod; + QString m_tags; + + ResourcesTreeItem * m_treeItem; + +} ; + + +#endif diff --git a/include/resources_provider.h b/include/resources_provider.h index 3866b7252..d8638ef9c 100644 --- a/include/resources_provider.h +++ b/include/resources_provider.h @@ -27,22 +27,28 @@ #include -#include "resources_db.h" +#include "resources_item.h" + +class ResourcesDB; class ResourcesProvider { public: - ResourcesProvider( const QString & url ); + ResourcesProvider( const QString & url ) : + m_url( url ) + { + } virtual ResourcesDB * createResourcesDB( void ) = 0; - virtual QByteArray fetchData( const ResourcesDB::Item * item ) = 0; + virtual QByteArray fetchData( const ResourcesItem * item ) = 0; inline const QString & url( void ) const { return m_url; } + private: QString m_url; } ; diff --git a/include/resources_tree_item.h b/include/resources_tree_item.h new file mode 100644 index 000000000..553ed3b2b --- /dev/null +++ b/include/resources_tree_item.h @@ -0,0 +1,133 @@ +/* + * resources_tree_item.h - header file for ResourcesTreeItem + * + * Copyright (c) 2009 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef _RESOURCES_TREE_ITEM_H +#define _RESOURCES_TREE_ITEM_H + +#include + +#include "resources_item.h" + +#define foreachResourcesTreeItem(list) \ + for(ResourcesTreeItemList::Iterator it=list.begin(); \ + it!=list.end();++it) + +#define foreachConstResourcesTreeItem(list) \ + for(ResourcesTreeItemList::ConstIterator it=list.begin();\ + it!=list.end();++it) + + +class ResourcesTreeItem; +typedef QList ResourcesTreeItemList; + + +class ResourcesTreeItem +{ +public: + ResourcesTreeItem( ResourcesTreeItem * _parent = NULL, + ResourcesItem * _item = NULL ); + + ~ResourcesTreeItem(); + + inline void setHidden( bool _h ) + { + m_hidden = _h; + } + + inline bool isHidden( void ) const + { + return m_hidden; + } + + int rowCount( void ) const; + + ResourcesTreeItem * getChild( int _row ); + + int row( void ) const; + + inline void addChild( ResourcesTreeItem * _it ) + { + m_children.push_back( _it ); + } + + inline void removeChild( ResourcesTreeItem * _it ) + { + m_children.removeAll( _it ); + } + + inline ResourcesTreeItemList & children( void ) + { + return m_children; + } + + inline const ResourcesTreeItemList & children( void ) const + { + return m_children; + } + + ResourcesTreeItem * findChild( const QString & _name, + ResourcesItem::BaseDirectory _base_dir ); + + inline ResourcesItem * item( void ) + { + return m_item; + } + + inline const ResourcesItem * item( void ) const + { + return m_item; + } + + inline ResourcesTreeItem * parent( void ) + { + return m_parent; + } + + inline bool temporaryMarker( void ) const + { + return m_temporaryMarker; + } + + inline void setTemporaryMarker( bool _on ) + { + m_temporaryMarker = _on; + } + + +private: + // hide copy-ctor + ResourcesTreeItem( const ResourcesTreeItem & ) { } + + ResourcesTreeItem * m_parent; + ResourcesTreeItemList m_children; + + bool m_hidden; + bool m_temporaryMarker; + + ResourcesItem * m_item; + +} ; + + +#endif diff --git a/include/resources_tree_model.h b/include/resources_tree_model.h index e617a438e..6b5d8b4c1 100644 --- a/include/resources_tree_model.h +++ b/include/resources_tree_model.h @@ -1,7 +1,7 @@ /* * resources_tree_model.h - tree-model for ResourcesDB * - * Copyright (c) 2008 Tobias Doerffel + * Copyright (c) 2008-2009 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -64,10 +64,10 @@ public: private: - bool filterItems( ResourcesDB::TreeItem * _item, + bool filterItems( ResourcesTreeItem * _item, const QModelIndex & _parent, const QStringList & _keywords ); - void setHidden( ResourcesDB::TreeItem * _item, + void setHidden( ResourcesTreeItem * _item, const QModelIndex & _parent, bool _hidden, bool _recursive = true ); diff --git a/include/web_resources_provider.h b/include/web_resources_provider.h index 8bb76ab52..cae9f47db 100644 --- a/include/web_resources_provider.h +++ b/include/web_resources_provider.h @@ -39,7 +39,7 @@ public: } virtual ResourcesDB * createResourcesDB( void ); - virtual QByteArray fetchData( const ResourcesDB::Item * item ); + virtual QByteArray fetchData( const ResourcesItem * item ); private: diff --git a/src/core/resources_db.cpp b/src/core/resources_db.cpp index 10c845fe3..dd74d71f2 100644 --- a/src/core/resources_db.cpp +++ b/src/core/resources_db.cpp @@ -23,7 +23,6 @@ */ -#include #include #include "resources_db.h" @@ -33,259 +32,12 @@ -void ResourcesDB::Item::reload( void ) -{ - m_hash.clear(); - m_size = -1; - init(); -} - - -bool ResourcesDB::Item::operator==( const Item & _other ) const -{ - return m_nameHash == _other.m_nameHash && - m_name == _other.m_name && - m_type == _other.m_type && - m_path == _other.m_path && - m_hash == _other.m_hash && - m_size == _other.m_size && - m_tags == _other.m_tags; -} - - - - -int ResourcesDB::Item::equalityLevel( const Item & _other ) const -{ - int l = 0; - if( m_nameHash == _other.m_nameHash && - m_name == _other.m_name && - m_path == _other.m_path ) - { - l += 40; - } - else if( m_nameHash == _other.m_nameHash && m_name == _other.m_name ) - { - l += 30; - } - else if( m_path == _other.m_path ) - { - l += 10; - } - - if( m_type == _other.m_type ) - { - l += 5; - } - - if( !m_tags.isEmpty() && !_other.m_tags.isEmpty() ) - { - QStringList my_tags = m_tags.split( " " ); - QStringList o_tags = _other.m_tags.split( " " ); - foreach( const QString & tag, o_tags ) - { - if( my_tags.contains( tag ) ) - { - l += 10; - } - } - } - - if( m_size == _other.m_size ) - { - l += 20; - } - - if( m_hash == _other.m_hash ) - { - l += 100; - } - return l; -} - - - - -ResourcesDB::Item::Types ResourcesDB::Item::guessType( void ) const -{ - static QMap typeMap; - if( typeMap.isEmpty() ) - { - typeMap["wav"] = TypeSample; - typeMap["ogg"] = TypeSample; - typeMap["mp3"] = TypeSample; - typeMap["ds"] = TypeSample; - typeMap["flac"] = TypeSample; - typeMap["spx"] = TypeSample; - typeMap["voc"] = TypeSample; - typeMap["au"] = TypeSample; - typeMap["raw"] = TypeSample; - typeMap["aif"] = TypeSample; - typeMap["aiff"] = TypeSample; - - typeMap["sf2"] = TypeSoundFont; - - typeMap["xpf"] = TypePreset; - - typeMap["mmp"] = TypeProject; - typeMap["mmpz"] = TypeProject; - - typeMap["mid"] = TypeMidiFile; - - typeMap["flp"] = TypeForeignProject; - - typeMap["dll"] = TypePlugin; - typeMap["so"] = TypePlugin; - - typeMap["png"] = TypeImage; - typeMap["jpg"] = TypeImage; - typeMap["jpeg"] = TypeImage; - } - - const QString s = QFileInfo( fullName() ).suffix().toLower(); - QMap::ConstIterator it = typeMap.find( s ); - if( it != typeMap.end() ) - { - return it.value(); - } - return TypeUnknown; -} - - - - -void ResourcesDB::Item::init( void ) -{ - if( m_name.isEmpty() ) - { - return; - } - - // ensure trailing slash for path property - if( !m_path.isEmpty() && m_path.right( 1 ) != QDir::separator() ) - { - m_path += QDir::separator(); - } - - if( m_type == TypeUnknown ) - { - m_type = guessType(); - } - - // if item is a directory, ensure a trailing slash - if( m_type == TypeDirectory ) - { - if( !m_name.isEmpty() && - m_name.right( 1 ) != QDir::separator() ) - { - m_name += QDir::separator(); - } - if( m_hash.isEmpty() ) - { - QCryptographicHash h( QCryptographicHash::Sha1 ); - h.addData( fullName().toUtf8() ); - m_hash = h.result().toHex(); - } - } - // only stat file if we really need to - else if( ( m_hash.isEmpty() || m_size < 0 ) && - QFile::exists( fullName() ) ) - { - if( m_size < 0 ) - { - m_size = QFileInfo( fullName() ).size(); - } - if( m_hash.isEmpty() ) - { - QCryptographicHash h( QCryptographicHash::Sha1 ); - - QFile f( fullName() ); - f.open( QFile::ReadOnly ); - - const int chunkSize = 1024*1024; // 1 MB - for( int i = 0; i < f.size() / chunkSize; ++i ) - { - h.addData( f.read( chunkSize ) ); - } - h.addData( f.readAll() ); - - m_hash = h.result().toHex(); - } - } - - m_nameHash = qHash( m_name ); -} - - - - -QString ResourcesDB::Item::getBaseDirectory( BaseDirectories _bd ) -{ - QString d; - switch( _bd ) - { - case BaseRoot: - d = QDir::rootPath(); - break; - case BaseWorkingDir: - d = configManager::inst()->workingDir(); - break; - case BaseDataDir: - d = configManager::inst()->dataDir(); - break; - case BaseHome: - default: - d = QDir::homePath(); - break; - } - if( !d.isEmpty() && d.right( 1 ) != QDir::separator() ) - { - d += QDir::separator(); - } - - return d; -} - - - - - -ResourcesDB::TreeItem * ResourcesDB::TreeItem::findChild( - const QString & _name, - Item::BaseDirectories _base_dir ) -{ - if( _name.isNull() || _name.isEmpty() ) - { - return NULL; - } - - const int hash = qHash( _name ); - - foreachTreeItem( m_children ) - { - TreeItem * ti = *it; - if( ti->item() && - ti->item()->nameHash() == hash && - ti->item()->name() == _name && - ti->item()->baseDir() == _base_dir ) - { - return ti; - } - } - return NULL; -} - - - - - - ResourcesDB::ResourcesDB( const QString & _db_file ) : m_watcher( this ), m_dbFile( _db_file ) { - m_folders += qMakePair( Item::BaseDataDir, QString() ); - m_folders += qMakePair( Item::BaseWorkingDir, QString() ); + m_folders += qMakePair( ResourcesItem::BaseDataDir, QString() ); + m_folders += qMakePair( ResourcesItem::BaseWorkingDir, QString() ); if( QFile::exists( m_dbFile ) ) { @@ -333,17 +85,18 @@ void ResourcesDB::save( void ) -void ResourcesDB::saveTreeItem( const TreeItem * _i, QDomDocument & _doc, +void ResourcesDB::saveTreeItem( const ResourcesTreeItem * _i, + QDomDocument & _doc, QDomElement & _de ) { QDomElement e = _i->item() ? _doc.createElement( "item" ) : _de; - foreachConstTreeItem( _i->children() ) + foreachConstResourcesTreeItem( _i->children() ) { saveTreeItem( *it, _doc, e ); } if( _i->item() ) { - const Item * it = _i->item(); + const ResourcesItem * it = _i->item(); e.setAttribute( "name", it->name() ); e.setAttribute( "type", it->type() ); e.setAttribute( "basedir", it->baseDir() ); @@ -360,7 +113,7 @@ void ResourcesDB::saveTreeItem( const TreeItem * _i, QDomDocument & _doc, -void ResourcesDB::loadTreeItem( TreeItem * _i, QDomElement & _de ) +void ResourcesDB::loadTreeItem( ResourcesTreeItem * _i, QDomElement & _de ) { QDomNode node = _de.firstChild(); while( !node.isNull() ) @@ -371,22 +124,23 @@ void ResourcesDB::loadTreeItem( TreeItem * _i, QDomElement & _de ) const QString h = e.attribute( "hash" ); if( !h.isEmpty() ) { - Item * item = new Item( e.attribute( "name" ), - static_cast( e.attribute( "type" ).toInt() ), - static_cast( e.attribute( "basedir" ).toInt() ), +ResourcesItem * item = new ResourcesItem( e.attribute( "name" ), + static_cast( e.attribute( "type" ).toInt() ), + static_cast( + e.attribute( "basedir" ).toInt() ), e.attribute( "path" ), h, e.attribute( "tags" ), e.attribute( "size" ).toInt(), QDateTime::fromString( e.attribute( "lastmod" ), Qt::ISODate ) ); - replaceItem( item ); - TreeItem * treeItem = new TreeItem( _i, item ); - if( item->type() == Item::TypeDirectory && - QFileInfo( item->fullPath() ).isDir() ) - { - m_watcher.addPath( item->fullPath() ); - } - loadTreeItem( treeItem, e ); +replaceItem( item ); +ResourcesTreeItem * treeItem = new ResourcesTreeItem( _i, item ); +if( item->type() == ResourcesItem::TypeDirectory && + QFileInfo( item->fullPath() ).isDir() ) +{ + m_watcher.addPath( item->fullPath() ); +} +loadTreeItem( treeItem, e ); } } node = node.nextSibling(); @@ -408,7 +162,7 @@ void ResourcesDB::scanResources( void ) -const ResourcesDB::Item * ResourcesDB::nearestMatch( const Item & _item ) +const ResourcesItem * ResourcesDB::nearestMatch( const ResourcesItem & _item ) { if( !_item.hash().isEmpty() ) { @@ -420,9 +174,9 @@ const ResourcesDB::Item * ResourcesDB::nearestMatch( const Item & _item ) } int max_level = -1; - const Item * max_item = NULL; + const ResourcesItem * max_item = NULL; - foreach( const Item * it, m_items ) + foreach( const ResourcesItem * it, m_items ) { const int l = it->equalityLevel( _item ); if( l > max_level ) @@ -441,12 +195,12 @@ const ResourcesDB::Item * ResourcesDB::nearestMatch( const Item & _item ) void ResourcesDB::reloadDirectory( const QString & _path ) { - TreeItem * dirTreeItem = NULL; + ResourcesTreeItem * dirTreeItem = NULL; - foreach( Item * it, m_items ) + foreach( ResourcesItem * it, m_items ) { - if( it->type() == Item::TypeDirectory && - it->fullPath() == _path ) + if( it->type() == ResourcesItem::TypeDirectory && + it->fullPath() == _path ) { dirTreeItem = it->treeItem(); } @@ -454,7 +208,7 @@ void ResourcesDB::reloadDirectory( const QString & _path ) if( dirTreeItem ) { - Item * dirItem = dirTreeItem->item(); + ResourcesItem * dirItem = dirTreeItem->item(); if( dirItem ) { m_scannedFolders.clear(); @@ -470,19 +224,19 @@ void ResourcesDB::reloadDirectory( const QString & _path ) -void ResourcesDB::replaceItem( Item * newItem ) +void ResourcesDB::replaceItem( ResourcesItem * newItem ) { const QString hash = newItem->hash(); - Item * oldItem = m_items[hash]; + ResourcesItem * oldItem = m_items[hash]; if( oldItem ) { - TreeItem * oldTreeItem = oldItem->treeItem(); + ResourcesTreeItem * oldTreeItem = oldItem->treeItem(); if( oldTreeItem ) { recursiveRemoveItems( oldTreeItem, false ); delete oldTreeItem; } - if( oldItem->type() == Item::TypeDirectory ) + if( oldItem->type() == ResourcesItem::TypeDirectory ) { m_watcher.removePath( oldItem->fullPath() ); } @@ -495,7 +249,7 @@ void ResourcesDB::replaceItem( Item * newItem ) -void ResourcesDB::recursiveRemoveItems( TreeItem * parent, +void ResourcesDB::recursiveRemoveItems( ResourcesTreeItem * parent, bool removeTopLevelParent ) { if( !parent ) @@ -510,7 +264,7 @@ void ResourcesDB::recursiveRemoveItems( TreeItem * parent, if( removeTopLevelParent && parent->item() ) { - if( parent->item()->type() == Item::TypeDirectory ) + if( parent->item()->type() == ResourcesItem::TypeDirectory ) { m_watcher.removePath( parent->item()->fullPath() ); } @@ -526,8 +280,8 @@ void ResourcesDB::recursiveRemoveItems( TreeItem * parent, -void ResourcesDB::readDir( const QString & _dir, TreeItem * _parent, - Item::BaseDirectories _base_dir ) +void ResourcesDB::readDir( const QString & _dir, ResourcesTreeItem * _parent, + ResourcesItem::BaseDirectory _base_dir ) { #ifdef LMMS_BUILD_LINUX if( _dir.startsWith( "/dev" ) || @@ -538,18 +292,18 @@ void ResourcesDB::readDir( const QString & _dir, TreeItem * _parent, } #endif - QDir d( Item::getBaseDirectory( _base_dir ) + _dir ); + QDir d( ResourcesItem::getBaseDirectory( _base_dir ) + _dir ); m_scannedFolders << d.canonicalPath(); - Item * parentItem; - TreeItem * curParent = _parent->findChild( d.dirName() + + ResourcesItem * parentItem; + ResourcesTreeItem * curParent = _parent->findChild( d.dirName() + QDir::separator(), _base_dir ); printf("read dir: %s\n", d.canonicalPath().toAscii().constData() ); if( curParent ) { parentItem = curParent->item(); - foreachTreeItem( curParent->children() ) + foreachResourcesTreeItem( curParent->children() ) { (*it)->setTemporaryMarker( false ); } @@ -557,15 +311,17 @@ printf("read dir: %s\n", d.canonicalPath().toAscii().constData() ); else { // create new item for current dir - parentItem = new Item( d.dirName(), Item::TypeDirectory, - _base_dir, _parent->item() ? + parentItem = new ResourcesItem( d.dirName(), + ResourcesItem::TypeDirectory, + _base_dir, + _parent->item() ? _parent->item()->path() + d.dirName() + QDir::separator() : QString::null ); parentItem->setLastMod( QFileInfo( d.canonicalPath() ).lastModified() ); replaceItem( parentItem ); - curParent = new TreeItem( _parent, parentItem ); + curParent = new ResourcesTreeItem( _parent, parentItem ); curParent->setTemporaryMarker( true ); m_watcher.addPath( parentItem->fullPath() ); } @@ -587,7 +343,8 @@ printf("read dir: %s\n", d.canonicalPath().toAscii().constData() ); { fname += QDir::separator(); } - TreeItem * curChild = curParent->findChild( fname, _base_dir ); + ResourcesTreeItem * curChild = + curParent->findChild( fname, _base_dir ); if( curChild ) { curChild->setTemporaryMarker( true ); @@ -597,7 +354,7 @@ printf("read dir: %s\n", d.canonicalPath().toAscii().constData() ); curChild->item()->setLastMod( f.lastModified() ); if( curChild->item()->type() == - Item::TypeDirectory ) + ResourcesItem::TypeDirectory ) { readDir( _dir + fname, curParent, _base_dir ); @@ -619,20 +376,21 @@ printf("read dir: %s\n", d.canonicalPath().toAscii().constData() ); } else if( f.isFile() ) { - Item * newItem = - new Item( f.fileName(), - Item::TypeUnknown, + ResourcesItem * newItem = + new ResourcesItem( f.fileName(), + ResourcesItem::TypeUnknown, _base_dir, _dir ); newItem->setLastMod( f.lastModified() ); replaceItem( newItem ); - TreeItem * ti = new TreeItem( curParent, + ResourcesTreeItem * ti = + new ResourcesTreeItem( curParent, newItem ); ti->setTemporaryMarker( true ); } } } - for( TreeItemList::Iterator it = curParent->children().begin(); + for( ResourcesTreeItemList::Iterator it = curParent->children().begin(); it != curParent->children().end(); ) { if( (*it)->temporaryMarker() == false ) diff --git a/src/core/resources_item.cpp b/src/core/resources_item.cpp new file mode 100644 index 000000000..f81ebecd3 --- /dev/null +++ b/src/core/resources_item.cpp @@ -0,0 +1,295 @@ +/* + * resources_item.cpp - implementation of ResourcesItem + * + * Copyright (c) 2009 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#include +#include +#include + +#include "resources_item.h" +#include "config_mgr.h" + + + +ResourcesItem::ResourcesItem() : + m_name(), + m_nameHash( 0 ), + m_type( TypeUnknown ), + m_baseDir( BaseRoot ), + m_path(), + m_hash(), + m_size( -1 ), + m_lastMod(), + m_tags(), + m_treeItem( NULL ) +{ + init(); +} + + + + +ResourcesItem::ResourcesItem( const QString & _name, + Type _type, + BaseDirectory _base_dir, + const QString & _path, + const QString & _hash, + const QString & _tags, + int _size, + const QDateTime & _last_mod ) : + m_name( _name ), + m_nameHash( 0 ), + m_type( _type ), + m_baseDir( _base_dir ), + m_path( _path ), + m_hash( _hash ), + m_size( _size ), + m_lastMod( _last_mod ), + m_tags( _tags ), + m_treeItem( NULL ) +{ + init(); +} + + + + +void ResourcesItem::reload( void ) +{ + m_hash.clear(); + m_size = -1; + init(); +} + + + + +bool ResourcesItem::operator==( const ResourcesItem & _other ) const +{ + return m_nameHash == _other.m_nameHash && + m_name == _other.m_name && + m_type == _other.m_type && + m_path == _other.m_path && + m_hash == _other.m_hash && + m_size == _other.m_size && + m_tags == _other.m_tags; +} + + + + +int ResourcesItem::equalityLevel( const ResourcesItem & _other ) const +{ + int l = 0; + if( m_nameHash == _other.m_nameHash && + m_name == _other.m_name && + m_path == _other.m_path ) + { + l += 40; + } + else if( m_nameHash == _other.m_nameHash && m_name == _other.m_name ) + { + l += 30; + } + else if( m_path == _other.m_path ) + { + l += 10; + } + + if( m_type == _other.m_type ) + { + l += 5; + } + + if( !m_tags.isEmpty() && !_other.m_tags.isEmpty() ) + { + QStringList my_tags = m_tags.split( " " ); + QStringList o_tags = _other.m_tags.split( " " ); + foreach( const QString & tag, o_tags ) + { + if( my_tags.contains( tag ) ) + { + l += 10; + } + } + } + + if( m_size == _other.m_size ) + { + l += 20; + } + + if( m_hash == _other.m_hash ) + { + l += 100; + } + return l; +} + + + + +ResourcesItem::Type ResourcesItem::guessType( void ) const +{ + static QMap typeMap; + if( typeMap.isEmpty() ) + { + typeMap["wav"] = TypeSample; + typeMap["ogg"] = TypeSample; + typeMap["mp3"] = TypeSample; + typeMap["ds"] = TypeSample; + typeMap["flac"] = TypeSample; + typeMap["spx"] = TypeSample; + typeMap["voc"] = TypeSample; + typeMap["au"] = TypeSample; + typeMap["raw"] = TypeSample; + typeMap["aif"] = TypeSample; + typeMap["aiff"] = TypeSample; + + typeMap["sf2"] = TypeSoundFont; + + typeMap["xpf"] = TypePreset; + + typeMap["mmp"] = TypeProject; + typeMap["mmpz"] = TypeProject; + + typeMap["mid"] = TypeMidiFile; + + typeMap["flp"] = TypeForeignProject; + + typeMap["dll"] = TypePlugin; + typeMap["so"] = TypePlugin; + + typeMap["png"] = TypeImage; + typeMap["jpg"] = TypeImage; + typeMap["jpeg"] = TypeImage; + } + + const QString s = QFileInfo( fullName() ).suffix().toLower(); + QMap::ConstIterator it = typeMap.find( s ); + if( it != typeMap.end() ) + { + return it.value(); + } + + return TypeUnknown; +} + + + + +void ResourcesItem::init( void ) +{ + if( m_name.isEmpty() ) + { + return; + } + + // ensure trailing slash for path property + if( !m_path.isEmpty() && m_path.right( 1 ) != QDir::separator() ) + { + m_path += QDir::separator(); + } + + if( m_type == TypeUnknown ) + { + m_type = guessType(); + } + + // if item is a directory, ensure a trailing slash + if( m_type == TypeDirectory ) + { + if( !m_name.isEmpty() && + m_name.right( 1 ) != QDir::separator() ) + { + m_name += QDir::separator(); + } + if( m_hash.isEmpty() ) + { + QCryptographicHash h( QCryptographicHash::Sha1 ); + h.addData( fullName().toUtf8() ); + m_hash = h.result().toHex(); + } + } + // only stat file if we really need to + else if( ( m_hash.isEmpty() || m_size < 0 ) && + QFile::exists( fullName() ) ) + { + if( m_size < 0 ) + { + m_size = QFileInfo( fullName() ).size(); + } + if( m_hash.isEmpty() ) + { + QCryptographicHash h( QCryptographicHash::Sha1 ); + + QFile f( fullName() ); + f.open( QFile::ReadOnly ); + + const int chunkSize = 1024*1024; // 1 MB + for( int i = 0; i < f.size() / chunkSize; ++i ) + { + h.addData( f.read( chunkSize ) ); + } + h.addData( f.readAll() ); + + m_hash = h.result().toHex(); + } + } + + m_nameHash = qHash( m_name ); +} + + + + +QString ResourcesItem::getBaseDirectory( BaseDirectory _bd ) +{ + QString d; + switch( _bd ) + { + case BaseRoot: + d = QDir::rootPath(); + break; + case BaseWorkingDir: + d = configManager::inst()->workingDir(); + break; + case BaseDataDir: + d = configManager::inst()->dataDir(); + break; + case BaseHome: + default: + d = QDir::homePath(); + break; + } + if( !d.isEmpty() && d.right( 1 ) != QDir::separator() ) + { + d += QDir::separator(); + } + + return d; +} + + + diff --git a/src/core/resources_tree_item.cpp b/src/core/resources_tree_item.cpp new file mode 100644 index 000000000..dc64497ce --- /dev/null +++ b/src/core/resources_tree_item.cpp @@ -0,0 +1,156 @@ +/* + * resources_tree_item.cpp - implementation of ResourcesTreeItem + * + * Copyright (c) 2009 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#include + +#include "resources_tree_item.h" + + +ResourcesTreeItem::ResourcesTreeItem( ResourcesTreeItem * _parent, + ResourcesItem * _item ) : + m_parent( _parent ), + m_hidden( false ), + m_temporaryMarker( false ), + m_item( _item ) +{ + if( m_parent ) + { + m_parent->addChild( this ); + } + if( m_item ) + { + m_item->setTreeItem( this ); + } +} + + + + +ResourcesTreeItem::~ResourcesTreeItem() +{ + foreachResourcesTreeItem( m_children ) + { + delete *it; + } + if( m_item ) + { + m_item->setTreeItem( NULL ); + } + if( m_parent ) + { + m_parent->removeChild( this ); + } +} + + + + +int ResourcesTreeItem::rowCount( void ) const +{ + int rc = 0; + foreachConstResourcesTreeItem( m_children ) + { + if( !(*it)->isHidden() ) + { + ++rc; + } + } + return rc; +} + + + + +ResourcesTreeItem * ResourcesTreeItem::getChild( int _row ) +{ + int rc = 0; + foreachResourcesTreeItem( m_children ) + { + if( !(*it)->isHidden() ) + { + if( rc == _row ) + { + return *it; + } + ++rc; + } + } + return NULL; +} + + + + +int ResourcesTreeItem::row( void ) const +{ + if( !m_parent ) + { + return 0; + } + + int row = 0; + foreachConstResourcesTreeItem( m_parent->m_children ) + { + if( !(*it)->isHidden() ) + { + if( *it == this ) + { + return row; + } + ++row; + } + } + return 0; +} + + + + +ResourcesTreeItem * ResourcesTreeItem::findChild( + const QString & _name, + ResourcesItem::BaseDirectory _base_dir ) +{ + if( _name.isNull() || _name.isEmpty() ) + { + return NULL; + } + + const int hash = qHash( _name ); + + foreachResourcesTreeItem( m_children ) + { + ResourcesTreeItem * rti = *it; + if( rti->item() && + rti->item()->nameHash() == hash && + rti->item()->name() == _name && + rti->item()->baseDir() == _base_dir ) + { + return rti; + } + } + return NULL; +} + + diff --git a/src/core/resources_tree_model.cpp b/src/core/resources_tree_model.cpp index a21e03382..565f0df18 100644 --- a/src/core/resources_tree_model.cpp +++ b/src/core/resources_tree_model.cpp @@ -42,8 +42,8 @@ QVariant ResourcesTreeModel::data( const QModelIndex & _idx, int _role ) const { if( _idx.isValid() ) { - ResourcesDB::TreeItem * item = - static_cast( + ResourcesTreeItem * item = + static_cast( _idx.internalPointer() ); if( _role == Qt::DisplayRole ) { @@ -51,9 +51,9 @@ QVariant ResourcesTreeModel::data( const QModelIndex & _idx, int _role ) const { switch( item->item()->baseDir() ) { - case ResourcesDB::Item::BaseWorkingDir: + case ResourcesItem::BaseWorkingDir: return tr( "My LMMS files" ); - case ResourcesDB::Item::BaseDataDir: + case ResourcesItem::BaseDataDir: return tr( "Shipped LMMS files" ); default: break; @@ -67,9 +67,9 @@ QVariant ResourcesTreeModel::data( const QModelIndex & _idx, int _role ) const { switch( item->item()->baseDir() ) { - case ResourcesDB::Item::BaseWorkingDir: + case ResourcesItem::BaseWorkingDir: return embed::getIconPixmap( "mimetypes/folder-workingdir", 24, 24 ); - case ResourcesDB::Item::BaseDataDir: + case ResourcesItem::BaseDataDir: return embed::getIconPixmap( "mimetypes/folder-datadir", 24, 24 ); default: break; @@ -77,19 +77,19 @@ QVariant ResourcesTreeModel::data( const QModelIndex & _idx, int _role ) const } switch( item->item()->type() ) { -case ResourcesDB::Item::TypeDirectory: +case ResourcesItem::TypeDirectory: return embed::getIconPixmap( "mimetypes/folder", 24, 24 ); -case ResourcesDB::Item::TypeSample: +case ResourcesItem::TypeSample: return embed::getIconPixmap( "mimetypes/sample", 24, 24 ); -case ResourcesDB::Item::TypePreset: +case ResourcesItem::TypePreset: return embed::getIconPixmap( "mimetypes/preset", 24, 24 ); -case ResourcesDB::Item::TypeProject: +case ResourcesItem::TypeProject: return embed::getIconPixmap( "project_file", 24, 24 ); -case ResourcesDB::Item::TypeMidiFile: +case ResourcesItem::TypeMidiFile: return embed::getIconPixmap( "mimetypes/midi", 24, 24 ); -case ResourcesDB::Item::TypeImage: +case ResourcesItem::TypeImage: return embed::getIconPixmap( "mimetypes/image", 24, 24 ); -case ResourcesDB::Item::TypePlugin: +case ResourcesItem::TypePlugin: return embed::getIconPixmap( "mimetypes/plugin", 24, 24 ); default: return embed::getIconPixmap( "mimetypes/unknown", 24, 24 ); @@ -104,7 +104,7 @@ default: int ResourcesTreeModel::rowCount( const QModelIndex & _parent ) const { - ResourcesDB::TreeItem * parentItem; + ResourcesTreeItem * parentItem; if( _parent.column() > 0 ) { @@ -117,7 +117,7 @@ int ResourcesTreeModel::rowCount( const QModelIndex & _parent ) const } else { - parentItem = static_cast( + parentItem = static_cast( _parent.internalPointer() ); } return parentItem->rowCount(); @@ -134,7 +134,7 @@ QModelIndex ResourcesTreeModel::index( int _row, int _col, return QModelIndex(); } - ResourcesDB::TreeItem * parentItem; + ResourcesTreeItem * parentItem; if( !_parent.isValid() ) { @@ -142,7 +142,7 @@ QModelIndex ResourcesTreeModel::index( int _row, int _col, } else { - parentItem = static_cast( + parentItem = static_cast( _parent.internalPointer() ); } @@ -163,10 +163,10 @@ QModelIndex ResourcesTreeModel::parent( const QModelIndex & _idx ) const return QModelIndex(); } - ResourcesDB::TreeItem * childItem = - static_cast( + ResourcesTreeItem * childItem = + static_cast( _idx.internalPointer() ); - ResourcesDB::TreeItem * parentItem = childItem->parent(); + ResourcesTreeItem * parentItem = childItem->parent(); if( parentItem == m_db->topLevelNode() ) { return QModelIndex(); @@ -197,13 +197,13 @@ void ResourcesTreeModel::setFilter( const QString & _s ) -bool ResourcesTreeModel::filterItems( ResourcesDB::TreeItem * _item, +bool ResourcesTreeModel::filterItems( ResourcesTreeItem * _item, const QModelIndex & _parent, const QStringList & _keywords ) { if( _item->item() ) { - ResourcesDB::Item * i = _item->item(); + ResourcesItem * i = _item->item(); bool accept = true; for( QStringList::ConstIterator it = _keywords.begin(); it != _keywords.end(); ++it ) @@ -225,7 +225,7 @@ bool ResourcesTreeModel::filterItems( ResourcesDB::TreeItem * _item, int row = 0; bool hide = true; - for( ResourcesDB::TreeItemList::Iterator it = _item->children().begin(); + for( ResourcesTreeItemList::Iterator it = _item->children().begin(); it != _item->children().end(); ++it ) { QModelIndex idx = createIndex( row, 0, *it ); @@ -243,14 +243,14 @@ bool ResourcesTreeModel::filterItems( ResourcesDB::TreeItem * _item, -void ResourcesTreeModel::setHidden( ResourcesDB::TreeItem * _item, +void ResourcesTreeModel::setHidden( ResourcesTreeItem * _item, const QModelIndex & _parent, bool _hide, bool _recursive ) { if( _recursive ) { int row = 0; - for( ResourcesDB::TreeItemList::Iterator it = + for( ResourcesTreeItemList::Iterator it = _item->children().begin(); it != _item->children().end(); ++it ) {