1
/* ============================================================
3
* This file is a part of digiKam project
4
* http://www.digikam.org
7
* Description : Albums manager interface.
9
* Copyright (C) 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
10
* Copyright (C) 2006-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
11
* Copyright (C) 2006-2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
13
* This program is free software; you can redistribute it
14
* and/or modify it under the terms of the GNU General
15
* Public License as published by the Free Software Foundation;
16
* either version 2, or (at your option)
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU General Public License for more details.
24
* ============================================================ */
26
/** @file albummanager.h */
28
#ifndef ALBUMMANAGER_H
29
#define ALBUMMANAGER_H
44
#include "albuminfo.h"
45
#include "databaseparameters.h"
46
#include "digikam_export.h"
59
class CollectionLocation;
67
class SearchChangeset;
68
class CollectionImageChangeset;
69
class ImageTagChangeset;
70
class AlbumManagerPriv;
72
typedef QList<Album*> AlbumList;
77
* There are two primary managers which manage the listing and
78
* lifetime of Album and ImageInfo: AlbumManager and AlbumLister
80
* AlbumManager manages albums: does listing of albums and controls the lifetime of it.
81
* For PAlbums and TAlbums, the listing is done by reading the db directly and
82
* building the hierarchy of the albums. For DAlbums, since the listing takes
83
* time, the work is delegated to a kioslave. Interested frontend entities can
84
* connect to the albummanager to receive notifications of new Albums, when
85
* Albums are deleted and when the current album is changed.
87
* Additional operations are provided for: creating/deleting/rename Albums,
88
* updating icons and moving Albums.
91
class AlbumManager : public QObject
98
* A convenience function to get the instance of the AlbumManager
100
static AlbumManager* instance();
102
/** @name Library path And Scanning
106
* Initialize. Informs the user about failures.
107
* Returns true on success, false on failure.
108
* A return value of false during startup indicates termination of the program
111
bool setDatabase(const DatabaseParameters& params, bool priority, const QString suggestedAlbumRoot = QString());
113
/** Some checks for settings done in first run wizard */
114
static void checkDatabaseDirsAfterFirstRun(const QString& dbPath, const QString& albumPath);
117
* Sets new database when chosen by the user in setup.
118
* Handles user notification about problems.
119
* Call this instead of setDatabase when digikam is up and running.
121
void changeDatabase(const DatabaseParameters& params);
124
* Stop ongoing operations, prepare for application shutdown
129
* Checks if the given database path is equal to the current one
131
bool databaseEqual(const QString& dbType, const QString& dbName, const QString& dbHostName, int dbPort, bool dbInternalServer) const;
134
* starts scanning the libraryPath and listing the albums. If the
135
* libraryPath has not changed since the lastscan, then nothing happens
136
* @see setLibraryPath
142
* This is similar to startScan, except that it assumes you have run
143
* startScan at least once. It checks the database to see if any new albums
144
* have been added and updates them accordingly. Use this when a change in the
145
* filesystem is detected (but the album library path hasn't changed)
151
* Ensures that valid item counts for physical and tag albums are available
153
void prepareItemCounts();
156
/** @name List of Albums and current Album
160
* @return a list of all PAlbums
162
AlbumList allPAlbums() const;
165
* @return a list of all TAlbums
167
AlbumList allTAlbums() const;
170
* @return a list of all SAlbums
172
AlbumList allSAlbums() const;
175
* @return a list of all DAlbums
177
AlbumList allDAlbums() const;
180
* set the current album to @p album. Call this from views which show
181
* listing of albums. This also causes it to fire the signal
182
* signalAlbumCurrentChanged()
184
void setCurrentAlbum(Album* album);
187
* @returns the current album
189
Album* currentAlbum() const;
192
* @returns the current PAlbum or null if no one is selected
194
PAlbum* currentPAlbum() const;
197
* @returns the current TAlbum or null if no one is selected
199
TAlbum* currentTAlbum() const;
202
/** @name Finding Albums
206
* Given a complete file url (kde url with file protocol), it will try to find
207
* a PAlbum corresponding to it.
208
* \warning This should not be used, unless really necessary
209
* @return PAlbum corresponding to supplied @p url
210
* @param url the url we need to check
212
PAlbum* findPAlbum(const KUrl& url) const;
215
* @return a PAlbum with given ID
216
* @param id the id for the PAlbum
218
PAlbum* findPAlbum(int id) const;
221
* @return a TAlbum with given ID
222
* @param id the id for the TAlbum
224
TAlbum* findTAlbum(int id) const;
227
* @return a SAlbum with given ID
228
* @param id the id for the SAlbum
230
SAlbum* findSAlbum(int id) const;
233
* @return a DAlbum with given ID
234
* @param id the id for the DAlbum
236
DAlbum* findDAlbum(int id) const;
239
* @return a Album with the given globalID
240
* @param gid the global id for the album
242
Album* findAlbum(int gid) const;
245
* @return a TAlbum with given tag path, or 0 if not found
246
* @param tagPath the tag path ("People/Friend/John")
248
TAlbum* findTAlbum(const QString& tagPath) const;
251
* @return a SAlbum with given name, or 0 if not found
252
* @param name the name of the search
254
SAlbum* findSAlbum(const QString& name) const;
257
/** @name Operations on PAlbum
261
* Create a new PAlbum with supplied properties as a child of the parent
262
* This is equivalent to creating a new folder on the disk with supplied
263
* name in the parent's folder path. Also the supplied attributes are written
264
* out to the database
265
* \note the signalAlbumAdded will be fired before this function returns. Its
266
* recommended to connect to that signal to get notification of new album added
267
* @return the newly created PAlbum or 0 if it fails
268
* @param parent The parent album under which to create the new Album.
269
* Parent must not be root. Otherwise, use the other variants of this method.
270
* If parent is root, the albumRootPath must be supplied.
271
* @param name the name of the new album
272
* @param caption the caption for the new album
273
* @param date the date for the new album
274
* @param errMsg this will contain the error message describing why the
277
PAlbum* createPAlbum(PAlbum* parent, const QString& name,
278
const QString& caption, const QDate& date,
279
const QString& category,
283
* Overloaded method. Here you can supply an albumRootPath which must
284
* correspond to an available collection location.
286
PAlbum* createPAlbum(const QString& albumRootPath, const QString& name,
287
const QString& caption, const QDate& date,
288
const QString& category,
292
* Overloaded method. Here you can supply a collection location (which
293
* must be available).
295
* @param location the collection for the new album
297
PAlbum* createPAlbum(const CollectionLocation& location, const QString& name,
298
const QString& caption, const QDate& date,
299
const QString& category,
303
* Renames a PAlbum. This is equivalent to actually renaming the corresponding
304
* folder on the disk.
305
* @return true if the operation succeeds, false otherwise
306
* @param album the Album which should be renamed
307
* @param newName the new name for the album
308
* @param errMsg this will contain the error message describing why the
311
bool renamePAlbum(PAlbum* album, const QString& newName,
315
* Update the icon for an album. The @p icon is the name (and not full path)
316
* of the file in the album
317
* @return true if the operation succeeds, false otherwise
318
* @param album the album for which icon should be changed
319
* @param iconID the filename of the new icon
320
* @param errMsg if the operation fails, this will contain the error message
321
* describing why the operation failed
323
bool updatePAlbumIcon(PAlbum* album, qlonglong iconID, QString& errMsg);
327
* @return A hash with the titles for all album IDs.
329
QHash<int, QString> albumTitles() const;
331
/** @name Operations on TAlbum
335
* Create a new TAlbum with supplied properties as a child of the parent
336
* The tag is added to the database
337
* \note the signalAlbumAdded will be fired before this function returns. Its
338
* recommended to connect to that signal to get notification of new album added
339
* @return the newly created TAlbum or 0 if it fails
340
* @param parent the parent album under which to create the new Album
341
* @param name the name of the new album
342
* @param iconkde the iconkde for the new album (this is a filename which
343
* kde iconloader can load up
344
* @param errMsg this will contain the error message describing why the
347
TAlbum* createTAlbum(TAlbum* parent, const QString& name,
348
const QString& iconkde, QString& errMsg);
351
* A list of tag paths is supplied.
352
* If no corresponding TAlbum exists, a new one will be created.
353
* @param tagPaths A list of tag paths
354
* @returns A list of all TAlbums for the list (already existing or newly created)
356
AlbumList findOrCreateTAlbums(const QStringList& tagPaths);
360
* The tag is removed from the database
361
* \note the signalAlbumDeleted will be fired before this function returns. Its
362
* recommended to connect to that signal to get notification of album deletes
363
* @return true if the operation succeeds or false otherwise
364
* @param album the TAlbum to delete
365
* @param errMsg this will contain the error message describing why the
368
bool deleteTAlbum(TAlbum* album, QString& errMsg);
372
* This updates the tag name in the database
373
* @return true if the operation succeeds, false otherwise
374
* @param album the Album which should be renamed
375
* @param name the new name for the album
376
* @param errMsg this will contain the error message describing why the
379
bool renameTAlbum(TAlbum* album, const QString& name, QString& errMsg);
382
* Move a TAlbum to a new parent.
383
* This updates the tag parent ID in the database
384
* @return true if the operation succeeds, false otherwise
385
* @param album the Album which should be moved
386
* @param newParent the Parent Album to which album should be moved
387
* @param errMsg this will contain the error message describing why the
390
bool moveTAlbum(TAlbum* album, TAlbum* newParent, QString& errMsg);
393
* Update the icon for a TAlbum.
394
* @return true if the operation succeeds, false otherwise
395
* @param album the album for which icon should be changed
396
* @param iconKDE a simple filename which can be loaded by KIconLoader
397
* @param iconID id of the icon image file
398
* @param errMsg this will contain the error message describing why the
400
* \note if iconKDE is not empty then iconID is used. So if you want to set
401
* the icon to a file which can be loaded by KIconLoader, pass it in as
402
* iconKDE. otherwise pass a null QString to iconKDE and set iconID
404
bool updateTAlbumIcon(TAlbum* album, const QString& iconKDE,
405
qlonglong iconID, QString& errMsg);
408
* Get a list of recently assigned tags (only last 6 tags are listed)
409
* @return the list of recently assigned TAlbums
411
AlbumList getRecentlyAssignedTags() const;
414
* @return A list with the tag paths for a list of tag IDs.
415
* @param tagIDs list of tag album IDs
416
* @param leadingSlash if <code>true</code> return tags with a leading slash
418
QStringList tagPaths(const QList<int>& tagIDs, bool leadingSlash=true) const;
421
* @return A list with the tag names for a list of tag IDs.
422
* @param tagIDs list of tag album IDs
424
QStringList tagNames(const QList<int>& tagIDs) const;
427
* @return A hash with the tag paths for all tag IDs.
429
QHash<int, QString> tagPaths(bool leadingSlash=true) const;
432
* @return A hash with the tag names for all tag IDs.
434
QHash<int, QString> tagNames() const;
438
/** @name Operations on SAlbum
442
* Create a new SAlbum with supplied url. If an existing SAlbum with same name
443
* exists this function will return a pointer to that album, instead of creating
444
* a new one. A newly created search album is added to the database. For an
445
* existing SAlbum, the url is updated and written out to the database
446
* \note the signalAlbumAdded will be fired before this function returns. Its
447
* recommended to connect to that signal to get notification of new album added
448
* @return the newly created SAlbum or an existing SAlbum with same name
449
* @param name name for the new search
450
* @param type the type of the search
451
* @param query search query to use
453
SAlbum* createSAlbum(const QString& name, DatabaseSearch::Type type, const QString& query);
456
* Update the url for a SAlbum
457
* @return true if the operation succeeds, false otherwise
458
* @param album the album to update
459
* @param changedQuery the new query data of the album
460
* @param changedName a new name, or null to keep the current name
461
* @param type a new type, or UndefinedType to keep the current type
463
bool updateSAlbum(SAlbum* album, const QString& changedQuery,
464
const QString& changedName = QString(), DatabaseSearch::Type type = DatabaseSearch::UndefinedType);
467
* Delete a SAlbum from the database
468
* \note the signalAlbumDeleted will be fired before this function returns. Its
469
* recommended to connect to that signal to get notification of album deletes
470
* @return true if the operation succeeds, false otherwise
471
* @param album the album to delete
473
bool deleteSAlbum(SAlbum* album);
476
/** @name Accessors to counting maps
481
* Returns the latest count for PAlbums as also emitted via
482
* signalPAlbumsDirty.
484
* @return count map for PAlbums
486
QMap<int, int> getPAlbumsCount() const;
489
* Returns the latest count for TAlbums as also emitted via
490
* signalTAlbumsDirty.
492
* @return count map for TAlbums
494
QMap<int, int> getTAlbumsCount() const;
497
* Returns the latest count for DAlbums as also emitted via
498
* signalDAlbumsDirty.
500
* @return count map for DAlbums
502
QMap<YearMonth, int> getDAlbumsCount() const;
505
* Returns if the given album is currently being moved, that is,
506
* if this album is in between signalAlbumAboutToBeMoved and
507
* signalAlbumMoved. In this case, you can preserve state of such an album
508
* because the object is guaranteed not to be deleted, even if
509
* signalAlbumAboutToBeDeleted is emitted.
511
bool isMovingAlbum(Album* album) const;
517
/// An album is about to be added to the given parent (0 if album is root)
518
/// after the item given by prev (prev is 0 if parent has no children yet)
519
void signalAlbumAboutToBeAdded(Album* album, Album* parent, Album* prev);
520
/// The album has been added.
521
void signalAlbumAdded(Album* album);
522
/// The album is about to be deleted, but is still fully valid.
523
void signalAlbumAboutToBeDeleted(Album* album);
524
/// The album is deleted, but the object can still be accessed.
525
void signalAlbumDeleted(Album* album);
526
/// The album is deleted, the object can no longer be accessed.
527
/// For identification purposes, the former album pointer is passed.
528
void signalAlbumHasBeenDeleted(void*);
529
void signalAlbumsCleared();
530
void signalAlbumCurrentChanged(Album* album);
531
void signalAllAlbumsLoaded();
532
void signalAllDAlbumsLoaded();
533
void signalAlbumIconChanged(Album* album);
534
void signalAlbumRenamed(Album* album);
535
void signalSearchUpdated(SAlbum* album);
536
/// Indicates that an album is about to be moved. Signals for deleting and adding will be
537
/// sent afterwards, but the album object is guaranteed not to be deleted until after signalAlbumMoved.
538
void signalAlbumAboutToBeMoved(Album* album);
539
/// Emitted when the album is moved to its new parent. After signalAlbumAboutToBeMoved,
540
/// all four signals for first deleting and then adding will have been sent.
541
void signalAlbumMoved(Album* album);
542
void signalPAlbumsDirty(const QMap<int, int>&);
543
void signalTAlbumsDirty(const QMap<int, int>&);
544
void signalDAlbumsDirty(const QMap<YearMonth, int>&);
545
void signalDatesMapDirty(const QMap<QDateTime, int>&);
549
void slotDatesJobResult(KJob* job);
550
void slotDatesJobData(KIO::Job* job, const QByteArray& data);
551
void slotAlbumsJobResult(KJob* job);
552
void slotAlbumsJobData(KIO::Job* job, const QByteArray& data);
553
void slotTagsJobResult(KJob* job);
554
void slotTagsJobData(KIO::Job* job, const QByteArray& data);
555
void slotDirWatchDirty(const QString& path);
556
void slotKioFileMoved(const QString& urlFrom, const QString& urlTo);
557
void slotKioFilesDeleted(const QStringList& urls);
558
void slotKioFilesAdded(const QString& directory);
559
void slotNotifyFileChange(const QString& directory);
560
void slotCollectionLocationStatusChanged(const CollectionLocation&, int);
561
void slotCollectionLocationPropertiesChanged(const CollectionLocation& location);
562
void slotAlbumChange(const AlbumChangeset& changeset);
563
void slotTagChange(const TagChangeset& changeset);
564
void slotSearchChange(const SearchChangeset& changeset);
565
void slotCollectionImageChange(const CollectionImageChangeset& changeset);
566
void slotImageTagChange(const ImageTagChangeset& changeset);
569
* Scan albums directly from database and creates new PAlbums
570
* It only creates those PAlbums which haven't already been
574
void updateChangedPAlbums();
576
* Scan tags directly from database and creates new TAlbums
577
* It only creates those TAlbums which haven't already been
582
* Scan searches directly from database and creates new SAlbums
583
* It only creates those SAlbums which haven't already been
588
* Scan dates from the database (via IOSlave) and
589
* updates the DAlbums.
593
void getAlbumItemsCount();
594
void getTagItemsCount();
598
friend class AlbumManagerCreator;
603
* Checks whether an Album has a direct child with the given name.
605
* @param parent album to check children for
606
* @param title title to search for
607
* @return <code>true</code> if there is a child with name, else
610
bool hasDirectChildAlbumWithTitle(Album* parent, const QString& title);
612
void insertPAlbum(PAlbum* album, PAlbum* parent);
613
void removePAlbum(PAlbum* album);
614
void insertTAlbum(TAlbum* album, TAlbum* parent);
615
void removeTAlbum(TAlbum* album);
616
void updateAlbumPathHash();
618
void notifyAlbumDeletion(Album* album);
620
void addAlbumRoot(const CollectionLocation& location);
621
void removeAlbumRoot(const CollectionLocation& location);
623
void handleKioNotification(const KUrl& url);
625
template <class T> friend class AlbumPointer;
627
static AlbumManager* internalInstance;
628
void addGuardedPointer(Album* a, Album** pointer);
629
void removeGuardedPointer(Album* a, Album** pointer);
630
void changeGuardedPointer(Album* oldAlbum, Album* a, Album** pointer);
631
void invalidateGuardedPointers(Album* album);
633
bool checkNepomukService();
637
AlbumManagerPriv* const d;
641
* You can use AlbumPointer to store a guarded pointer to Album
642
* or one of the subclasses (use template parameter).
643
* The pointer will be set to 0 when the album object is deleted.
645
template <class T = Album>
651
AlbumPointer() : album(0) {}
652
AlbumPointer(T* a) : album(a)
654
AlbumManager::instance()->addGuardedPointer(album, &album);
656
AlbumPointer(const AlbumPointer<T>& p) : album(p.album)
658
AlbumManager::instance()->addGuardedPointer(album, &album);
663
AlbumManager::instance()->removeGuardedPointer(album, &album);
666
AlbumPointer<T> operator=(T* a)
668
Album* oldAlbum = album;
670
AlbumManager::instance()->changeGuardedPointer(oldAlbum, album, &album);
673
AlbumPointer<T> operator=(const AlbumPointer<T>& p)
675
Album* oldAlbum = album;
677
AlbumManager::instance()->changeGuardedPointer(oldAlbum, album, &album);
681
T* operator->() const
683
return static_cast<T*>(const_cast<Album*>(album));
687
return *static_cast<T*>(const_cast<Album*>(album));
691
return static_cast<T*>(const_cast<Album*>(album));
696
friend class AlbumManager;
700
} // namespace Digikam
702
#endif /* ALBUMMANAGER_H */