Not crap after all...
[amarok.git] / src / collectiondb.h
blob92fa505d1e7ab97851be91e6855a4d7b9c2c3a47
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"
20 #include <kurl.h>
21 #include <QDir> //stack allocated
22 #include <QDateTime>
23 #include <QImage>
24 #include <QMutex>
25 #include <QObject> //baseclass
26 #include <q3ptrqueue.h> //baseclass
27 #include <q3semaphore.h> //stack allocated
28 #include <QStringList> //stack allocated
29 #include <q3ptrvector.h>
30 #include <QThread>
31 #include <q3valuestack.h>
32 //Added by qt3to4:
33 #include <QTimerEvent>
34 #include <QPixmap>
35 #include <Q3ValueList>
36 #include <QCustomEvent>
37 #include <QByteArray>
39 namespace KIO { class Job; }
41 class DbConnection;
42 class CoverFetcher;
43 class MetaBundle;
44 class OrganizeCollectionDialog;
45 class PodcastChannelBundle;
46 class PodcastEpisodeBundle;
47 class Q3ListViewItem;
48 class Scrobbler;
50 class DbConfig
51 {};
54 class SqliteConfig : public DbConfig
56 public:
57 SqliteConfig( const QString& /* dbfile */ );
59 QString dbFile() const { return m_dbfile; }
61 private:
62 QString m_dbfile;
66 class MySqlConfig : public DbConfig
68 public:
69 MySqlConfig(
70 const QString& /* host */,
71 const int /* port */,
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; }
82 private:
83 QString m_host;
84 int m_port;
85 QString m_database;
86 QString m_username;
87 QString m_password;
91 class PostgresqlConfig : public DbConfig
93 public:
94 PostgresqlConfig(
95 const QString& /* host */,
96 const int /* port */,
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; }
107 private:
108 QString m_host;
109 int m_port;
110 QString m_database;
111 QString m_username;
112 QString m_password;
116 class AMAROK_EXPORT DbConnection
118 public:
119 enum DbConnectionType { sqlite = 0, mysql = 1, postgresql = 2 };
121 DbConnection();
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"; }
130 protected:
131 bool m_initialized;
135 typedef struct sqlite3 sqlite3;
136 typedef struct sqlite3_context sqlite3_context;
137 typedef struct Mem sqlite3_value;
139 class SqliteConnection : public DbConnection
141 public:
142 SqliteConnection( const SqliteConfig* /* config */ );
143 ~SqliteConnection();
145 QStringList query( const QString& /* statement */, bool suppressDebug = false );
146 int insert( const QString& /* statement */, const QString& /* table */ );
147 bool isConnected()const { return true; }
148 private:
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 );
153 sqlite3* m_db;
157 #ifdef USE_MYSQL
158 typedef struct st_mysql MYSQL;
160 class MySqlConnection : public DbConnection
162 public:
163 MySqlConnection( const MySqlConfig* /* config */ );
164 ~MySqlConnection();
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; }
170 private:
171 void setMysqlError();
172 MYSQL* m_db;
173 bool m_connected;
174 QString m_error;
176 #endif
179 #ifdef USE_POSTGRESQL
180 typedef struct pg_conn PGconn;
182 class PostgresqlConnection : public DbConnection
184 public:
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; }
192 private:
193 void setPostgresqlError();
194 PGconn* m_db;
195 bool m_connected;
196 QString m_error;
198 #endif
201 class CollectionDB : public QObject, public EngineObserver
203 Q_OBJECT
205 friend class SimilarArtistsInsertionJob;
207 signals:
208 void scanStarted();
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
235 public:
236 CollectionDB();
237 ~CollectionDB();
239 AMAROK_EXPORT static CollectionDB *instance();
242 * performs all initializations which require directory or URL data stored in the
243 * database.
245 void initDirOperations();
247 enum labelTypes { typeUser = 1 }; //add new types add the end!
249 QString escapeString(QString string ) const
251 return
252 #ifdef USE_MYSQL
253 // We have to escape "\" for mysql, but can't do so for sqlite
254 ( m_dbConnType == DbConnection::mysql )
255 ? string.replace("\\", "\\\\").replace( '\'', "''" ) :
256 #endif
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(); }
279 //sql helper methods
280 AMAROK_EXPORT QStringList query( const QString& statement, bool suppressDebug = false );
281 AMAROK_EXPORT int insert( const QString& statement, const QString& table );
284 * TODO: write doc
285 * @param showAll
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
305 bool isEmpty();
306 bool isValid();
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 );
331 //song methods
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 );
345 //podcast methods
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 );
385 //statistics methods
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 );
399 //artist methods
400 QStringList similarArtists( const QString &artist, uint count );
402 //album methods
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();
409 //label methods
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 );
415 void cleanLabels();
417 QStringList favoriteLabels( int type = CollectionDB::typeUser, int count = 10 );
419 //list methods
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; }
498 bool isConnected();
499 void releasePreviousConnection(QThread *currThread);
501 void invalidateArtistAlbumCache() { m_validArtistCache=false; m_validComposerCache=false; m_validAlbumCache=false; };
503 void vacuum();
506 * Cancel the underlying move/copy file action
508 void cancelMovingFileJob();
510 protected:
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 );
516 public slots:
517 void fetchCover( QWidget* parent, const QString& artist, const QString& album, bool noedit, Q3ListViewItem* item = 0 );
518 void scanMonitor();
519 void startScan();
520 void stopScan();
521 void scanModifiedDirs();
522 void disableAutoScoring( bool disable = true ) { m_autoScoring = !disable; }
524 void checkDatabase();
526 private slots:
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 );
535 private:
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();
556 void initialize();
557 void destroy();
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
566 //of Composer table
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
586 //stays the same
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 );
611 //member variables
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];
623 bool m_monitor;
624 bool m_autoScoring;
626 static QMap<Q3ListViewItem*, CoverFetcher*> *itemCoverMap;
627 static QMutex *itemCoverMapMutex;
628 QImage m_noCover;
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
650 QMutex m_mutex;
653 class INotify : public ThreadManager::DependentJob
655 Q_OBJECT
657 public:
658 INotify( CollectionDB *parent, int fd );
659 ~INotify();
661 static INotify *instance() { return s_instance; }
663 bool watchDir( const QString directory );
664 int fd() { return m_fd; }
666 private:
667 virtual bool doJob();
669 CollectionDB* m_parent;
670 int m_fd;
672 static INotify* s_instance;
675 #endif /* AMAROK_COLLECTIONDB_H */