1 // (c) 2004 Mark Kretschmann <markey@web.de>
2 // (c) 2004 Christian Muehlhaeuser <chris@chris.de>
3 // (c) 2004 Sami Nieminen <sami.nieminen@iki.fi>
4 // (c) 2005 Ian Monroe <ian@monroe.nu>
5 // (c) 2005 Jeff Mitchell <kde-dev@emailgoeshere.com>
6 // (c) 2005 Isaiah Damron <xepo@trifault.net>
7 // (c) 2005 Alexandre Pereira de Oliveira <aleprj@gmail.com>
8 // (c) 2006 Jonas Hurrelmann <j@outpo.st>
9 // (c) 2006 Shane King <kde@dontletsstart.com>
10 // (c) 2006 Peter C. Ndikuwera <pndiku@gmail.com>
11 // See COPYING file for licensing information.
13 #ifndef AMAROK_COLLECTIONDB_H
14 #define AMAROK_COLLECTIONDB_H
16 #include "engineobserver.h"
17 #include "threadmanager.h" //baseclass
18 #include "amarok_export.h"
21 #include <QDir> //stack allocated
25 #include <QObject> //baseclass
26 #include <q3ptrqueue.h> //baseclass
27 #include <q3semaphore.h> //stack allocated
28 #include <QStringList> //stack allocated
29 #include <q3ptrvector.h>
31 #include <q3valuestack.h>
33 #include <QTimerEvent>
35 #include <Q3ValueList>
36 #include <QCustomEvent>
39 namespace KIO
{ class Job
; }
44 class OrganizeCollectionDialog
;
45 class PodcastChannelBundle
;
46 class PodcastEpisodeBundle
;
54 class SqliteConfig
: public DbConfig
57 SqliteConfig( const QString
& /* dbfile */ );
59 QString
dbFile() const { return m_dbfile
; }
66 class MySqlConfig
: public DbConfig
70 const QString
& /* host */,
72 const QString
& /* database */,
73 const QString
& /* username */,
74 const QString
& /* password */);
76 QString
host() const { return m_host
; }
77 int port() const { return m_port
; }
78 QString
database() const { return m_database
; }
79 QString
username() const { return m_username
; }
80 QString
password() const { return m_password
; }
91 class PostgresqlConfig
: public DbConfig
95 const QString
& /* host */,
97 const QString
& /* database */,
98 const QString
& /* username */,
99 const QString
& /* password */);
101 QString
host() const { return m_host
; }
102 int port() const { return m_port
; }
103 QString
database() const { return m_database
; }
104 QString
username() const { return m_username
; }
105 QString
password() const { return m_password
; }
116 class AMAROK_EXPORT DbConnection
119 enum DbConnectionType
{ sqlite
= 0, mysql
= 1, postgresql
= 2 };
122 virtual ~DbConnection() {}
124 virtual QStringList
query( const QString
& /* statement */, bool suppressDebug
) = 0;
125 virtual int insert( const QString
& /* statement */, const QString
& /* table */ ) = 0;
126 bool isInitialized() const { return m_initialized
; }
127 virtual bool isConnected() const = 0;
128 virtual QString
lastError() const { return "None"; }
135 typedef struct sqlite3 sqlite3
;
136 typedef struct sqlite3_context sqlite3_context
;
137 typedef struct Mem sqlite3_value
;
139 class SqliteConnection
: public DbConnection
142 SqliteConnection( const SqliteConfig
* /* config */ );
145 QStringList
query( const QString
& /* statement */, bool suppressDebug
= false );
146 int insert( const QString
& /* statement */, const QString
& /* table */ );
147 bool isConnected()const { return true; }
149 static void sqlite_rand( sqlite3_context
*context
, int /*argc*/, sqlite3_value
** /*argv*/ );
150 static void sqlite_power( sqlite3_context
*context
, int argc
, sqlite3_value
**argv
);
151 static void sqlite_like_new( sqlite3_context
*context
, int argc
, sqlite3_value
**argv
);
158 typedef struct st_mysql MYSQL
;
160 class MySqlConnection
: public DbConnection
163 MySqlConnection( const MySqlConfig
* /* config */ );
166 QStringList
query( const QString
& /* statement */, bool suppressDebug
= false );
167 int insert( const QString
& /* statement */, const QString
& /* table */ );
168 bool isConnected()const { return m_connected
; }
169 QString
lastError() const { return m_error
; }
171 void setMysqlError();
179 #ifdef USE_POSTGRESQL
180 typedef struct pg_conn PGconn
;
182 class PostgresqlConnection
: public DbConnection
185 PostgresqlConnection( const PostgresqlConfig
* /* config */ );
186 ~PostgresqlConnection();
188 QStringList
query( const QString
& /* statement */, bool suppressDebug
= false );
189 int insert( const QString
& /* statement */, const QString
& /* table */ );
190 bool isConnected()const { return m_connected
; }
191 QString
lastError() const { return m_error
; }
193 void setPostgresqlError();
201 class CollectionDB
: public QObject
, public EngineObserver
205 friend class SimilarArtistsInsertionJob
;
209 void scanDone( bool changed
);
210 void databaseEngineChanged();
212 void databaseUpdateDone();
214 void scoreChanged( const QString
&url
, float score
);
215 void ratingChanged( const QString
&url
, int rating
);
216 void labelsChanged( const QString
&url
);
217 void fileMoved( const QString
&srcUrl
, const QString
&dstUrl
);
218 void fileMoved( const QString
&srcUrl
, const QString
&dstUrl
, const QString
&uniqueid
);
219 void fileDeleted( const QString
&absPath
);
220 void fileDeleted( const QString
&absPath
, const QString
&uniqueid
);
221 void fileAdded( const QString
&absPath
);
222 void fileAdded( const QString
&absPath
, const QString
&uniqueid
);
223 void filesAdded( const QMap
<QString
,QString
> &map
);
224 void uniqueIdChanged( const QString
&url
, const QString
&originalid
, const QString
&newid
);
225 void coverChanged( const QString
&artist
, const QString
&album
); //whenever a cover changes
226 void coverFetched( const QString
&artist
, const QString
&album
); //only when fetching from amazon
227 void coverRemoved( const QString
&artist
, const QString
&album
);
228 void coverFetcherError( const QString
&error
);
230 void similarArtistsFetched( const QString
&artist
);
231 void tagsChanged( const MetaBundle
&bundle
);
232 void tagsChanged( const QString
&oldArtist
, const QString
&oldAlbum
);
233 void imageFetched( const QString
&remoteURL
); //for fetching remote podcast images
239 AMAROK_EXPORT
static CollectionDB
*instance();
242 * performs all initializations which require directory or URL data stored in the
245 void initDirOperations();
247 enum labelTypes
{ typeUser
= 1 }; //add new types add the end!
249 QString
escapeString(QString string
) const
253 // We have to escape "\" for mysql, but can't do so for sqlite
254 ( m_dbConnType
== DbConnection::mysql
)
255 ? string
.replace("\\", "\\\\").replace( '\'', "''" ) :
257 string
.replace( '\'', "''" );
260 QString
boolT() const { if (getDbConnectionType() == DbConnection::postgresql
) return "true"; else return "1"; }
261 QString
boolF() const { if (getDbConnectionType() == DbConnection::postgresql
) return "false"; else return "0"; }
262 //textColumnType should be used for normal strings, which need to be compared
263 //either case-sensitively or -insensitively
264 QString
textColumnType( int length
=255 ) const { if ( getDbConnectionType() == DbConnection::postgresql
) return "TEXT"; else return QString("VARCHAR(%1)").arg(length
); }
265 //exactTextColumnType should be used for strings that must be stored exactly, such
266 //as URLs (necessary for holding control chars etc. if present in URL), except for
267 //trailing spaces. Comparisions should always be done case-sensitively.
268 //As we create indices on these columns, we have to restrict them to
269 //<= 255 chars for mysql < 5.0.3
270 QString
exactTextColumnType( int length
=1024 ) const { if ( getDbConnectionType() == DbConnection::mysql
) return QString( "VARBINARY(%1)" ).arg( length
>255 ? 255 : length
); else return textColumnType( length
); }
271 // We might consider using LONGTEXT type, as some lyrics could be VERY long..???
272 QString
longTextColumnType() const { if ( getDbConnectionType() == DbConnection::postgresql
) return "TEXT"; else return "TEXT"; }
273 QString
randomFunc() const { if ( getDbConnectionType() == DbConnection::postgresql
) return "random()"; else return "RAND()"; }
275 static QString
exactCondition( const QString
&right
);
276 static QString
likeCondition( const QString
&right
, bool anyBegin
=false, bool anyEnd
=false );
277 int getType() { return getDbConnectionType(); }
280 AMAROK_EXPORT QStringList
query( const QString
& statement
, bool suppressDebug
= false );
281 AMAROK_EXPORT
int insert( const QString
& statement
, const QString
& table
);
286 * @return a string which can be appended to an existing sql where statement
288 QString
deviceidSelection( const bool showAll
= false );
291 * converts the result of a query which contains a deviceid and a relative path
292 * to a list of absolute paths. the order of entries in each result row must be
293 * deviceid first, relative path second.
294 * @param result the result of the sql query, deviceid first, relative path second
295 * @return a list of urls
297 QStringList
URLsFromQuery( const QStringList
&result
) const;
300 * converts the result list of a amarok-sql query to a list of urls
302 KUrl::List
URLsFromSqlDrag( const QStringList
&values
) const;
304 //table management methods
307 QString
adminValue( QString noption
);
308 void setAdminValue( QString noption
, QString value
);
309 void createTables( const bool temporary
= false );
310 void createIndices( );
311 void createPermanentIndices();
312 void dropTables( const bool temporary
= false);
313 void clearTables( const bool temporary
= false);
314 void copyTempTables( );
315 void prepareTempTables();
317 uint
artistID( QString value
, bool autocreate
= true, const bool temporary
= false, bool exact
= true );
318 uint
composerID( QString value
, bool autocreate
= true, const bool temporary
= false, bool exact
= true );
319 uint
albumID( QString value
, bool autocreate
= true, const bool temporary
= false, bool exact
= true );
320 uint
genreID( QString value
, bool autocreate
= true, const bool temporary
= false, bool exact
= true );
321 uint
yearID( QString value
, bool autocreate
= true, const bool temporary
= false, bool exact
= true );
323 bool isDirInCollection( QString path
);
324 bool isFileInCollection( const QString
&url
);
325 QString
getURL( const MetaBundle
&bundle
);
326 void removeDirFromCollection( QString path
);
327 void removeSongsInDir( QString path
, QMap
<QString
,QString
> *tagsRemoved
= 0 );
328 void removeSongs( const KUrl::List
& urls
);
329 void updateDirStats( QString path
, const long datetime
, const bool temporary
= false );
332 bool addSong( MetaBundle
* bundle
, const bool incremental
= false );
333 void aftCheckPermanentTables( const QString
&currdeviceid
, const QString
&currid
, const QString
&currurl
);
334 void doAFTStuff( MetaBundle
*bundle
, const bool tempTables
= true );
335 void emitFileAdded( const QString
&absPath
,
336 const QString
&uniqueid
= QString() );
337 void emitFilesAdded( const QMap
<QString
,QString
> &map
) { emit
filesAdded( map
); }
338 void emitFileDeleted( const QString
&absPath
,
339 const QString
&uniqueid
= QString() );
340 bool newUniqueIdForFile( const QString
&path
);
341 bool removeUniqueIdFromFile( const QString
&path
);
342 QString
urlFromUniqueId( const QString
&id
);
343 QString
uniqueIdFromUrl( const KUrl
&url
);
346 /// Insert a podcast channel into the database. If @param replace is true, replace the row
347 /// use updatePodcastChannel() always in preference
348 bool addPodcastChannel( const PodcastChannelBundle
&pcb
, const bool &replace
=false );
349 /// Insert a podcast episode into the database. If @param idToUpdate is provided, replace the row
350 /// use updatePodcastEpisode() always in preference
351 int addPodcastEpisode( const PodcastEpisodeBundle
&episode
, const int idToUpdate
=0 );
352 int addPodcastFolder( const QString
&name
, const int parent_id
=0, const bool isOpen
=false );
353 Q3ValueList
<PodcastChannelBundle
> getPodcastChannels();
354 PodcastEpisodeBundle
getPodcastEpisodeById( int id
);
355 Q3ValueList
<PodcastEpisodeBundle
> getPodcastEpisodes( const KUrl
&parent
, bool newOnly
=false, int limit
=-1 );
356 void removePodcastChannel( const KUrl
&url
); // will remove all episodes too
357 void removePodcastEpisode( const int id
);
358 void removePodcastFolder( const int id
);
359 void updatePodcastChannel( const PodcastChannelBundle
&b
);
360 void updatePodcastEpisode( const int id
, const PodcastEpisodeBundle
&b
);
361 void updatePodcastFolder( const int folder_id
, const QString
&name
, const int parent_id
=0, const bool isOpen
=false );
362 // these return false when no bundle was available
363 bool getPodcastChannelBundle( const KUrl
&url
, PodcastChannelBundle
*channel
);
364 bool getPodcastEpisodeBundle( const KUrl
&url
, PodcastEpisodeBundle
*channel
);
366 MetaBundle
bundleFromQuery( QStringList::const_iterator
*iter
);
368 * The @p bundle parameter's url() will be looked up in the Collection
369 * @param bundle this will be filled in with tags for you
370 * @return true if in the collection
372 bool bundleForUrl( MetaBundle
* bundle
);
373 Q3ValueList
<MetaBundle
> bundlesByUrls( const KUrl::List
& urls
);
374 void addAudioproperties( const MetaBundle
& bundle
);
376 //Helper function for updateTags
377 void deleteRedundantName( const QString
&table
, const QString
&id
);
379 void deleteAllRedundant( const QString
&table
);
381 void updateTags( const QString
&url
, const MetaBundle
&bundle
, const bool updateView
= true);
382 void updateURL( const QString
&url
, const bool updateView
= true );
383 QString
getUniqueId( const QString
&url
);
386 void addSongPercentage( const QString
&url
, float percentage
,
387 const QString
&reason
, const QDateTime
*playtime
= 0 );
388 float getSongPercentage( const QString
&url
);
389 int getSongRating( const QString
&url
);
390 void setSongPercentage( const QString
&url
, float percentage
);
391 void setSongRating( const QString
&url
, int percentage
, bool toggleHalf
= false );
392 int getPlayCount( const QString
&url
);
393 QDateTime
getFirstPlay( const QString
&url
);
394 QDateTime
getLastPlay( const QString
&url
);
395 void migrateFile( const QString
&oldURL
, const QString
&newURL
);
396 bool moveFile( const QString
&src
, const QString
&dest
, bool overwrite
, bool copy
= false );
397 bool organizeFile( const KUrl
&src
, const OrganizeCollectionDialog
&dialog
, bool copy
);
400 QStringList
similarArtists( const QString
&artist
, uint count
);
403 void checkCompilations( const QString
&path
, const bool temporary
= false );
404 void setCompilation( const KUrl::List
&urls
, bool enabled
, bool updateView
);
405 QString
albumSongCount( const QString
&artist_id
, const QString
&album_id
);
406 bool albumIsCompilation( const QString
&album_id
);
407 void sanitizeCompilations();
410 QStringList
getLabels( const QString
&url
, const uint type
);
411 void removeLabels( const QString
&url
, const QStringList
&labels
, const uint type
);
412 bool addLabel( const QString
&url
, const QString
&label
, const QString
&uid
, const uint type
);
413 void setLabels( const QString
&url
, const QStringList
&labels
, const QString
&uid
, const uint type
);
417 QStringList
favoriteLabels( int type
= CollectionDB::typeUser
, int count
= 10 );
420 QStringList
artistList( bool withUnknowns
= true, bool withCompilations
= true );
421 QStringList
composerList( bool withUnknowns
= true, bool withCompilations
= true );
422 QStringList
albumList( bool withUnknowns
= true, bool withCompilations
= true );
423 QStringList
genreList( bool withUnknowns
= true, bool withCompilations
= true );
424 QStringList
yearList( bool withUnknowns
= true, bool withCompilations
= true );
425 QStringList
labelList();
427 QStringList
albumListOfArtist( const QString
&artist
, bool withUnknown
= true, bool withCompilations
= true );
428 QStringList
artistAlbumList( bool withUnknown
= true, bool withCompilations
= true );
430 QStringList
albumTracks( const QString
&artist_id
, const QString
&album_id
);
431 QStringList
albumDiscTracks( const QString
&artist_id
, const QString
&album_id
, const QString
&discNumber
);
432 QStringList
artistTracks( const QString
&artist_id
);
434 //cover management methods
435 /** Returns the image from a given URL, network-transparently.
436 * You must run KIO::NetAccess::removeTempFile( tmpFile ) when you are finished using the image;
438 static QImage
fetchImage( const KUrl
& url
, QString
&tmpFile
);
439 /** Saves images located on the user's filesystem */
440 bool setAlbumImage( const QString
& artist
, const QString
& album
, const KUrl
& url
);
441 /** Saves images obtained from CoverFetcher */
442 bool setAlbumImage( const QString
& artist
, const QString
& album
, QImage img
, const QString
& amazonUrl
= QString(), const QString
& asin
= QString() );
444 QString
findAmazonImage( const QString
&artist
, const QString
&album
, const uint width
= 1 );
445 QString
findDirectoryImage( const QString
& artist
, const QString
& album
, uint width
= 0 );
446 QString
findEmbeddedImage( const QString
& artist
, const QString
& album
, uint width
= 1 );
447 QString
findMetaBundleImage( const MetaBundle
&trackInformation
, const uint
= 1 );
449 /// ensure the sql only return urls to tracks for efficiency
450 static QPixmap
createDragPixmapFromSQL( const QString
&sql
, QString textOverRide
=QString() );
451 static QPixmap
createDragPixmap( const KUrl::List
&urls
, QString textOverRide
=QString() );
452 static const int DRAGPIXMAP_OFFSET_X
= -12;
453 static const int DRAGPIXMAP_OFFSET_Y
= -28;
456 * Retrieves the path to the local copy of the image pointed to by url,
457 * initiates fetching of the remote image if necessary.
458 * @param width the size of the image. 0 == full size, 1 == preview size
460 QString
podcastImage( const MetaBundle
&bundle
, const bool withShadow
= false, uint width
= 1 );
461 QString
podcastImage( const QString
&remoteURL
, const bool withShadow
= false, uint width
= 1 );
464 * Retrieves the path to the image for the album of the requested item
465 * @param width the size of the image. 0 == full size, 1 == preview size
466 * @param embedded if not NULL, sets a bool indicating whether the path is an embedded image
468 QString
albumImage( const MetaBundle
&trackInformation
, const bool withShadow
= false, uint width
= 1, bool* embedded
= 0 );
469 QString
albumImage( const uint artist_id
, const uint album_id
, const bool withShadow
= false, uint width
= 1, bool* embedded
= 0 );
470 QString
albumImage( const QString
&artist
, const QString
&album
, const bool withShadow
= false, uint width
= 1, bool* embedded
= 0 );
471 QMap
<Q3ListViewItem
*, CoverFetcher
*> * getItemCoverMap() { return itemCoverMap
; }
472 QMutex
* getItemCoverMapMutex() { return itemCoverMapMutex
; }
474 bool removeAlbumImage( const uint artist_id
, const uint album_id
);
475 bool removeAlbumImage( const QString
&artist
, const QString
&album
);
477 static QString
makeShadowedImage( const QString
& albumImage
, bool cache
= true );
479 //local cover methods
480 void addImageToAlbum( const QString
& image
, Q3ValueList
< QPair
<QString
, QString
> > info
, const bool temporary
);
481 QString
notAvailCover( const bool withShadow
= false, int width
= 1 );
483 //embedded cover methods
484 void addEmbeddedImage( const QString
& path
, const QString
& hash
, const QString
& description
);
485 void removeOrphanedEmbeddedImages();
487 void applySettings();
489 void setLyrics( const QString
& url
, const QString
& lyrics
, const QString
&uniqueid
= QString() );
490 QString
getLyrics( const QString
& url
);
492 /** Remove from the amazon table the item with the specified md5sum **/
493 void removeInvalidAmazonInfo( const QString
& md5sum
);
494 void newAmazonReloadDate( const QString
& asin
, const QString
& locale
, const QString
& md5sum
);
495 QStringList
staleImages();
497 AMAROK_EXPORT
DbConnection::DbConnectionType
getDbConnectionType() const { return m_dbConnType
; }
499 void releasePreviousConnection(QThread
*currThread
);
501 void invalidateArtistAlbumCache() { m_validArtistCache
=false; m_validComposerCache
=false; m_validAlbumCache
=false; };
506 * Cancel the underlying move/copy file action
508 void cancelMovingFileJob();
511 QByteArray
md5sum( const QString
& artist
, const QString
& album
, const QString
& file
= QString() );
512 void engineTrackEnded( int finalPosition
, int trackLength
, const QString
&reason
);
513 /** Manages regular folder monitoring scan */
514 void timerEvent( QTimerEvent
* e
);
517 void fetchCover( QWidget
* parent
, const QString
& artist
, const QString
& album
, bool noedit
, Q3ListViewItem
* item
= 0 );
521 void scanModifiedDirs();
522 void disableAutoScoring( bool disable
= true ) { m_autoScoring
= !disable
; }
524 void checkDatabase();
527 void dirDirty( const QString
& path
);
528 void coverFetcherResult( CoverFetcher
* );
529 void similarArtistsFetched( const QString
& artist
, const QStringList
& suggestions
);
530 void fileOperationResult( KIO::Job
*job
); // moveFile depends on it
531 void podcastImageResult( KIO::Job
*job
); //for fetching remote podcast images
532 void aftMigratePermanentTablesUrl( const QString
& oldUrl
, const QString
& newUrl
, const QString
& uniqueid
); //AFT-enable stats
533 void aftMigratePermanentTablesUniqueId( const QString
& url
, const QString
& oldid
, const QString
& newid
);
536 //bump DATABASE_VERSION whenever changes to the table structure are made.
537 // This erases tags, album, artist, composer, genre, year, images, embed, directory and related_artists tables.
538 static const int DATABASE_VERSION
;
539 // Persistent Tables hold data that is somehow valuable to the user, and can't be erased when rescaning.
540 // When bumping this, write code to convert the data!
541 static const int DATABASE_PERSISTENT_TABLES_VERSION
;
542 // Bumping this erases stats table. If you ever need to, write code to convert the data!
543 static const int DATABASE_STATS_VERSION
;
544 // When bumping this, you should provide code to convert the data.
545 static const int DATABASE_PODCAST_TABLES_VERSION
;
546 static const int DATABASE_AFT_VERSION
;
547 // persistent table. you should provide code to convert the data when bumping this
548 static const int DATABASE_DEVICES_VERSION
;
550 static const int MONITOR_INTERVAL
; //sec
552 static QDir
largeCoverDir();
553 static QDir
tagCoverDir();
554 static QDir
cacheCoverDir();
558 DbConnection
* getMyConnection();
560 //helper methods which perform updates of amarok's database
561 void updateStatsTables();
562 void updatePersistentTables();
563 void updatePodcastTables();
565 //A dirty hack to preserve Group By settings in Collection Browser after addition
567 void updateGroupBy();
569 void customEvent( QEvent
* );
571 // helpers for embedded images
572 QString
loadHashFile( const QByteArray
& hash
, uint width
);
573 bool extractEmbeddedImage( const MetaBundle
&trackInformation
, QByteArray
& hash
);
575 //general management methods
576 void createStatsTable();
577 void dropStatsTable();
578 void createPersistentTables();
579 void dropPersistentTables();
580 void createPodcastTables();
581 void dropPodcastTables();
582 void createDevicesTable();
583 void dropDevicesTable();
585 //Archived forms of the above. useful for providing a linear upgrade routine that
587 void createStatsTableV8();
588 void createStatsTableV10( bool temp
);
589 void dropStatsTableV1();
590 void createPersistentTablesV12();
591 void createPersistentTablesV14( bool temp
);
592 void dropPersistentTablesV14();
593 void createPodcastTablesV2( bool temp
);
594 void dropPodcastTablesV2();
597 QByteArray
makeWidthKey( uint width
);
598 QString
artistValue( uint id
);
599 QString
composerValue( uint id
);
600 QString
albumValue( uint id
);
601 QString
genreValue( uint id
);
602 QString
yearValue( uint id
);
604 //These should be avoided as they will be slow and potentially unsafe.
605 //Use the Exact version where possible (faster and safer).
606 //To convert output from Exact version from QString to uint, use .toUInt()
607 uint
IDFromValue( QString name
, QString value
, bool autocreate
= true, const bool temporary
= false );
608 QString
IDFromExactValue( QString table
, QString value
, bool autocreate
= true, bool temporary
= false );
609 QString
valueFromID( QString table
, uint id
);
612 QString m_amazonLicense
;
613 bool m_validArtistCache
;
614 bool m_validComposerCache
;
615 bool m_validAlbumCache
;
616 QString m_cacheArtist
[2];
617 uint m_cacheArtistID
[2];
618 QString m_cacheComposer
[2];
619 uint m_cacheComposerID
[2];
620 QString m_cacheAlbum
[2];
621 uint m_cacheAlbumID
[2];
626 static QMap
<Q3ListViewItem
*, CoverFetcher
*> *itemCoverMap
;
627 static QMutex
*itemCoverMapMutex
;
630 static QMap
<QThread
*, DbConnection
*> *threadConnections
;
631 static QMutex
*connectionMutex
;
632 DbConnection::DbConnectionType m_dbConnType
;
633 DbConfig
*m_dbConfig
;
635 //organize files stuff
636 bool m_waitForFileOperation
;
637 bool m_fileOperationFailed
;
638 bool m_scanInProgress
;
639 bool m_rescanRequired
;
641 QStringList m_aftEnabledPersistentTables
;
643 // Cancel move/copy job
644 bool m_moveFileJobCancelled
;
646 // for handling podcast image url redirects
647 QMap
<KIO::Job
*, QString
> m_podcastImageJobs
;
649 // protect against multiple simultaneous queries/inserts
653 class INotify
: public ThreadManager::DependentJob
658 INotify( CollectionDB
*parent
, int fd
);
661 static INotify
*instance() { return s_instance
; }
663 bool watchDir( const QString directory
);
664 int fd() { return m_fd
; }
667 virtual bool doJob();
669 CollectionDB
* m_parent
;
672 static INotify
* s_instance
;
675 #endif /* AMAROK_COLLECTIONDB_H */