Index: trunk/extragear/graphics/digikam/digikam/digikamview.cpp =================================================================== --- trunk/extragear/graphics/digikam/digikam/digikamview.cpp (revision 1028323) +++ trunk/extragear/graphics/digikam/digikam/digikamview.cpp (revision 1028324) @@ -1,1837 +1,1840 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2002-16-10 * Description : implementation of album view interface. * * Copyright (C) 2002-2005 by Renchi Raju * Copyright (C) 2002-2009 by Gilles Caulier * * 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, 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. * * ============================================================ */ #include "digikamview.h" #include "digikamview.moc" // Qt includes #include #include #include #include #include #include #include #include #include #include #include #include #include // KDE includes #include #include #include #include #include #include #include #include #include #include #include #include #include // LibKDcraw includes #include // Local includes #include "config-digikam.h" #include "album.h" #include "albumfolderview.h" #include "albumhistory.h" #include "albumiconviewfilter.h" #include "albummanager.h" #include "albummodel.h" #include "albumsettings.h" #include "albumwidgetstack.h" #include "batchsyncmetadata.h" #include "collectionmanager.h" #include "datefolderview.h" #include "digikamapp.h" #include "digikamimageview.h" #include "dio.h" #include "dmetadata.h" #include "fuzzysearchfolderview.h" #include "fuzzysearchview.h" #include "gpssearchfolderview.h" #include "gpssearchview.h" #include "imagealbumfiltermodel.h" #include "imagealbummodel.h" #include "imageinfoalbumsjob.h" #include "imagepreviewview.h" #include "imagepropertiessidebardb.h" #include "imageviewutilities.h" #include "loadingcacheinterface.h" #include "metadatamanager.h" #include "queuemgrwindow.h" #include "scancontroller.h" #include "searchfolderview.h" #include "searchtabheader.h" #include "sidebar.h" #include "slideshow.h" #include "statusprogressbar.h" #include "tagfilterview.h" #include "tagfolderview.h" #include "themeengine.h" #include "thumbnailsize.h" #include "timelinefolderview.h" #include "timelineview.h" namespace Digikam { class DigikamViewPriv { public: DigikamViewPriv() { folderBox = 0; tagBox = 0; searchBox = 0; tagFilterBox = 0; folderSearchBar = 0; tagSearchBar = 0; searchSearchBar = 0; tagFilterSearchBar = 0; dockArea = 0; splitter = 0; parent = 0; iconView = 0; folderView = 0; albumManager = 0; albumHistory = 0; leftSideBar = 0; rightSideBar = 0; dateFolderView = 0; timeLineView = 0; tagFolderView = 0; searchFolderView = 0; tagFilterView = 0; albumWidgetStack = 0; selectionTimer = 0; thumbSizeTimer = 0; fuzzySearchView = 0; gpsSearchView = 0; needDispatchSelection = false; cancelSlideShow = false; thumbSize = ThumbnailSize::Medium; } QString userPresentableAlbumTitle(const QString& album); bool needDispatchSelection; bool cancelSlideShow; int initialAlbumID; int thumbSize; QMainWindow *dockArea; SidebarSplitter *splitter; QTimer *selectionTimer; QTimer *thumbSizeTimer; KVBox *folderBox; KVBox *tagBox; KVBox *searchBox; KVBox *tagFilterBox; SearchTextBar *folderSearchBar; SearchTextBar *tagSearchBar; SearchTextBar *searchSearchBar; SearchTextBar *tagFilterSearchBar; DigikamApp *parent; DigikamImageView *iconView; AlbumFolderView *folderView; AlbumManager *albumManager; AlbumHistory *albumHistory; AlbumWidgetStack *albumWidgetStack; Sidebar *leftSideBar; ImagePropertiesSideBarDB *rightSideBar; DateFolderView *dateFolderView; TimeLineView *timeLineView; TagFolderView *tagFolderView; SearchFolderView *searchFolderView; SearchTabHeader *searchTabHeader; TagFilterView *tagFilterView; FuzzySearchView *fuzzySearchView; GPSSearchView *gpsSearchView; }; DigikamView::DigikamView(QWidget *parent) : KHBox(parent), d(new DigikamViewPriv) { d->parent = static_cast(parent); d->albumManager = AlbumManager::instance(); d->splitter = new SidebarSplitter; d->splitter->setFrameStyle( QFrame::NoFrame ); d->splitter->setFrameShadow( QFrame::Plain ); d->splitter->setFrameShape( QFrame::NoFrame ); d->splitter->setOpaqueResize(false); d->leftSideBar = new Sidebar(this, d->splitter, KMultiTabBar::Left); d->leftSideBar->setObjectName("Digikam Left Sidebar"); d->splitter->setParent(this); // The dock area where the thumbnail bar is allowed to go. d->dockArea = new QMainWindow(this, Qt::Widget); d->splitter->addWidget(d->dockArea); d->albumWidgetStack = new AlbumWidgetStack(d->dockArea); d->dockArea->setCentralWidget(d->albumWidgetStack); d->albumWidgetStack->setDockArea(d->dockArea); d->iconView = d->albumWidgetStack->imageIconView(); d->rightSideBar = new ImagePropertiesSideBarDB(this, d->splitter, KMultiTabBar::Right, true); d->rightSideBar->setObjectName("Digikam Right Sidebar"); // To the left. // Folders sidebar tab contents. d->folderBox = new KVBox(this); d->folderView = new AlbumFolderView(d->folderBox); d->folderSearchBar = new SearchTextBar(d->folderBox, "DigikamViewFolderSearchBar"); d->folderBox->setSpacing(KDialog::spacingHint()); d->folderBox->setMargin(0); // Tags sidebar tab contents. d->tagBox = new KVBox(this); d->tagFolderView = new TagFolderView(d->tagBox); d->tagSearchBar = new SearchTextBar(d->tagBox, "DigikamViewTagSearchBar"); d->tagBox->setSpacing(KDialog::spacingHint()); d->tagBox->setMargin(0); // Search sidebar tab contents. d->searchBox = new KVBox(this); d->searchTabHeader = new SearchTabHeader(d->searchBox); d->searchFolderView = new SearchFolderView(d->searchBox); d->searchSearchBar = new SearchTextBar(d->searchBox, "DigikamViewSearchSearchBar"); d->searchBox->setStretchFactor(d->searchFolderView, 1); d->searchBox->setSpacing(KDialog::spacingHint()); d->searchBox->setMargin(0); d->dateFolderView = new DateFolderView(this); d->dateFolderView->setImageModel(d->iconView->imageFilterModel()); d->timeLineView = new TimeLineView(this); d->fuzzySearchView = new FuzzySearchView(this); #ifdef HAVE_MARBLEWIDGET d->gpsSearchView = new GPSSearchView(this); #endif d->leftSideBar->appendTab(d->folderBox, SmallIcon("folder-image"), i18n("Albums")); d->leftSideBar->appendTab(d->dateFolderView, SmallIcon("view-calendar-list"), i18n("Calendar")); d->leftSideBar->appendTab(d->tagBox, SmallIcon("tag"), i18n("Tags")); d->leftSideBar->appendTab(d->timeLineView, SmallIcon("player-time"), i18n("Timeline")); d->leftSideBar->appendTab(d->searchBox, SmallIcon("edit-find"), i18n("Searches")); d->leftSideBar->appendTab(d->fuzzySearchView, SmallIcon("tools-wizard"), i18n("Fuzzy Searches")); #ifdef HAVE_MARBLEWIDGET d->leftSideBar->appendTab(d->gpsSearchView, SmallIcon("applications-internet"), i18n("Map Searches")); #endif // To the right. // Tags Filter sidebar tab contents. d->tagFilterBox = new KVBox(this); d->tagFilterView = new TagFilterView(d->tagFilterBox); d->tagFilterSearchBar = new SearchTextBar(d->tagFilterBox, "DigikamViewTagFilterSearchBar"); d->tagFilterBox->setSpacing(KDialog::spacingHint()); d->tagFilterBox->setMargin(0); d->rightSideBar->appendTab(d->tagFilterBox, SmallIcon("tag-assigned"), i18n("Tag Filters")); d->selectionTimer = new QTimer(this); d->selectionTimer->setSingleShot(true); d->selectionTimer->setInterval(75); d->thumbSizeTimer = new QTimer(this); d->thumbSizeTimer->setSingleShot(true); d->thumbSizeTimer->setInterval(300); setupConnections(); d->albumHistory = new AlbumHistory(); slotSidebarTabTitleStyleChanged(); } DigikamView::~DigikamView() { saveViewState(); delete d->albumHistory; delete d; } void DigikamView::applySettings() { AlbumSettings *settings = AlbumSettings::instance(); d->albumWidgetStack->applySettings(); d->folderView->setEnableToolTips(settings->getShowAlbumToolTips()); refreshView(); } void DigikamView::refreshView() { d->folderView->refresh(); d->dateFolderView->refresh(); d->tagFolderView->refresh(); d->tagFilterView->refresh(); d->rightSideBar->refreshTagsView(); } void DigikamView::setupConnections() { // -- DigikamApp connections ---------------------------------- connect(d->parent, SIGNAL(signalEscapePressed()), this, SLOT(slotEscapePreview())); connect(d->parent, SIGNAL(signalEscapePressed()), d->albumWidgetStack, SLOT(slotEscapePreview())); connect(d->parent, SIGNAL(signalNextItem()), this, SLOT(slotNextItem())); connect(d->parent, SIGNAL(signalPrevItem()), this, SLOT(slotPrevItem())); connect(d->parent, SIGNAL(signalFirstItem()), this, SLOT(slotFirstItem())); connect(d->parent, SIGNAL(signalLastItem()), this, SLOT(slotLastItem())); connect(d->parent, SIGNAL(signalCopyAlbumItemsSelection()), d->iconView, SLOT(copy())); connect(d->parent, SIGNAL(signalPasteAlbumItemsSelection()), d->iconView, SLOT(paste())); connect(this, SIGNAL(signalProgressBarMode(int, const QString&)), d->parent, SLOT(slotProgressBarMode(int, const QString&))); connect(this, SIGNAL(signalProgressValue(int)), d->parent, SLOT(slotProgressValue(int))); connect(d->parent, SIGNAL(signalCancelButtonPressed()), this, SLOT(slotCancelSlideShow())); // -- AlbumManager connections -------------------------------- connect(d->albumManager, SIGNAL(signalAlbumCurrentChanged(Album*)), this, SLOT(slotAlbumSelected(Album*))); connect(d->albumManager, SIGNAL(signalAllAlbumsLoaded()), this, SLOT(slotAllAlbumsLoaded())); connect(d->albumManager, SIGNAL(signalAlbumAdded(Album*)), this, SLOT(slotAlbumAdded(Album*))); connect(d->albumManager, SIGNAL(signalAlbumDeleted(Album*)), this, SLOT(slotAlbumDeleted(Album*))); connect(d->albumManager, SIGNAL(signalAlbumRenamed(Album*)), this, SLOT(slotAlbumRenamed(Album*))); connect(d->albumManager, SIGNAL(signalAlbumsCleared()), this, SLOT(slotAlbumsCleared())); // -- IconView Connections ------------------------------------- connect(d->iconView->model(), SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(slotImageSelected())); connect(d->iconView->model(), SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(slotImageSelected())); connect(d->iconView->model(), SIGNAL(layoutChanged()), this, SLOT(slotImageSelected())); connect(d->iconView, SIGNAL(selectionChanged()), this, SLOT(slotImageSelected())); connect(d->iconView, SIGNAL(previewRequested(const ImageInfo &)), this, SLOT(slotTogglePreviewMode(const ImageInfo &))); connect(d->iconView, SIGNAL(gotoAlbumAndImageRequested(const ImageInfo&)), this, SLOT(slotGotoAlbumAndItem(const ImageInfo&))); connect(d->iconView, SIGNAL(gotoDateAndImageRequested(const ImageInfo&)), this, SLOT(slotGotoDateAndItem(const ImageInfo&))); connect(d->iconView, SIGNAL(gotoTagAndImageRequested(int)), this, SLOT(slotGotoTagAndItem(int))); connect(d->iconView, SIGNAL(zoomOutStep()), this, SLOT(slotZoomOut())); connect(d->iconView, SIGNAL(zoomInStep()), this, SLOT(slotZoomIn())); // -- Sidebar Connections ------------------------------------- connect(d->leftSideBar, SIGNAL(signalChangedTab(QWidget*)), this, SLOT(slotLeftSidebarChangedTab(QWidget*))); connect(d->rightSideBar, SIGNAL(signalFirstItem()), this, SLOT(slotFirstItem())); connect(d->rightSideBar, SIGNAL(signalNextItem()), this, SLOT(slotNextItem())); connect(d->rightSideBar, SIGNAL(signalPrevItem()), this, SLOT(slotPrevItem())); connect(d->rightSideBar, SIGNAL(signalLastItem()), this, SLOT(slotLastItem())); connect(this, SIGNAL(signalNoCurrentItem()), d->rightSideBar, SLOT(slotNoCurrentItem())); connect(d->rightSideBar, SIGNAL(signalProgressBarMode(int, const QString&)), d->parent, SLOT(slotProgressBarMode(int, const QString&))); connect(d->rightSideBar, SIGNAL(signalProgressValue(int)), d->parent, SLOT(slotProgressValue(int))); connect(d->tagFilterView, SIGNAL(signalProgressBarMode(int, const QString&)), d->parent, SLOT(slotProgressBarMode(int, const QString&))); connect(d->tagFilterView, SIGNAL(signalProgressValue(int)), d->parent, SLOT(slotProgressValue(int))); connect(d->tagFolderView, SIGNAL(signalProgressBarMode(int, const QString&)), d->parent, SLOT(slotProgressBarMode(int, const QString&))); connect(d->tagFolderView, SIGNAL(signalProgressValue(int)), d->parent, SLOT(slotProgressValue(int))); connect(d->fuzzySearchView, SIGNAL(signalUpdateFingerPrints()), d->parent, SLOT(slotRebuildAllFingerPrints())); // -- Filter Bars Connections --------------------------------- connect(d->folderSearchBar, SIGNAL(signalSearchTextSettings(const SearchTextSettings&)), d->folderView, SLOT(slotTextFolderFilterChanged(const SearchTextSettings&))); connect(d->tagSearchBar, SIGNAL(signalSearchTextSettings(const SearchTextSettings&)), d->tagFolderView, SLOT(slotTextTagFilterChanged(const SearchTextSettings&))); connect(d->searchSearchBar, SIGNAL(signalSearchTextSettings(const SearchTextSettings&)), d->searchFolderView, SLOT(slotTextSearchFilterChanged(const SearchTextSettings&))); connect(d->tagFilterSearchBar, SIGNAL(signalSearchTextSettings(const SearchTextSettings&)), d->tagFilterView, SLOT(slotTextTagFilterChanged(const SearchTextSettings&))); connect(d->folderView, SIGNAL(signalTextFolderFilterMatch(bool)), d->folderSearchBar, SLOT(slotSearchResult(bool))); connect(d->folderView, SIGNAL(signalFindDuplicatesInAlbum(Album*)), this, SLOT(slotNewDuplicatesSearch(Album*))); connect(d->tagFolderView, SIGNAL(signalFindDuplicatesInTag(Album*)), this, SLOT(slotNewDuplicatesSearch(Album*))); connect(d->tagFolderView, SIGNAL(signalTextTagFilterMatch(bool)), d->tagSearchBar, SLOT(slotSearchResult(bool))); connect(d->searchFolderView, SIGNAL(newSearch()), d->searchTabHeader, SLOT(newAdvancedSearch())); connect(d->searchFolderView, SIGNAL(signalTextSearchFilterMatch(bool)), d->searchSearchBar, SLOT(slotSearchResult(bool))); connect(d->searchFolderView, SIGNAL(editSearch(SAlbum *)), d->searchTabHeader, SLOT(editSearch(SAlbum *))); connect(d->searchFolderView, SIGNAL(selectedSearchChanged(SAlbum *)), d->searchTabHeader, SLOT(selectedSearchChanged(SAlbum *))); connect(d->searchTabHeader, SIGNAL(searchShallBeSelected(SAlbum *)), d->searchFolderView, SLOT(slotSelectSearch(SAlbum *))); connect(d->tagFilterView, SIGNAL(signalTextTagFilterMatch(bool)), d->tagFilterSearchBar, SLOT(slotSearchResult(bool))); connect(d->tagFilterView, SIGNAL(tagFilterChanged(const QList&, ImageFilterSettings::MatchingCondition, bool)), d->iconView->imageFilterModel(), SLOT(setTagFilter(const QList&, ImageFilterSettings::MatchingCondition, bool))); // -- Preview image widget Connections ------------------------ connect(d->albumWidgetStack, SIGNAL(signalNextItem()), this, SLOT(slotNextItem())); connect(d->albumWidgetStack, SIGNAL(signalPrevItem()), this, SLOT(slotPrevItem())); connect(d->albumWidgetStack, SIGNAL(signalEditItem()), this, SLOT(slotImageEdit())); connect(d->albumWidgetStack, SIGNAL(signalDeleteItem()), this, SLOT(slotImageDelete())); connect(d->albumWidgetStack, SIGNAL(signalToggledToPreviewMode(bool)), this, SLOT(slotToggledToPreviewMode(bool))); connect(d->albumWidgetStack, SIGNAL(signalBack2Album()), this, SLOT(slotEscapePreview())); connect(d->albumWidgetStack, SIGNAL(signalSlideShow()), this, SLOT(slotSlideShowAll())); connect(d->albumWidgetStack, SIGNAL(signalZoomFactorChanged(double)), this, SLOT(slotZoomFactorChanged(double))); connect(d->albumWidgetStack, SIGNAL(signalInsert2LightTable()), this, SLOT(slotImageAddToLightTable())); connect(d->albumWidgetStack, SIGNAL(signalInsert2QueueMgr()), this, SLOT(slotImageAddToCurrentQueue())); connect(d->albumWidgetStack, SIGNAL(signalFindSimilar()), this, SLOT(slotImageFindSimilar())); connect(d->albumWidgetStack, SIGNAL(signalUrlSelected(const KUrl&)), this, SLOT(slotSelectItemByUrl(const KUrl&))); connect(d->albumWidgetStack, SIGNAL(signalAddToExistingQueue(int)), this, SLOT(slotImageAddToExistingQueue(int))); connect(d->albumWidgetStack, SIGNAL(signalGotoAlbumAndItem(const ImageInfo&)), this, SLOT(slotGotoAlbumAndItem(const ImageInfo&))); connect(d->albumWidgetStack, SIGNAL(signalGotoDateAndItem(const ImageInfo&)), this, SLOT(slotGotoDateAndItem(const ImageInfo&))); connect(d->albumWidgetStack, SIGNAL(signalGotoTagAndItem(int)), this, SLOT(slotGotoTagAndItem(int))); // -- MetadataManager progress --------------- connect(MetadataManager::instance(), SIGNAL(progressMessageChanged(const QString&)), this, SLOT(slotProgressMessageChanged(const QString&))); connect(MetadataManager::instance(), SIGNAL(progressValueChanged(float)), this, SLOT(slotProgressValueChanged(float))); connect(MetadataManager::instance(), SIGNAL(progressFinished()), this, SLOT(slotProgressFinished())); connect(MetadataManager::instance(), SIGNAL(orientationChangeFailed(const QStringList&)), this, SLOT(slotOrientationChangeFailed(const QStringList&))); // -- timers --------------- connect(d->selectionTimer, SIGNAL(timeout()), this, SLOT(slotDispatchImageSelected())); connect(d->thumbSizeTimer, SIGNAL(timeout()), this, SLOT(slotThumbSizeEffect()) ); // -- Album Settings ---------------- connect(AlbumSettings::instance(), SIGNAL(setupChanged()), this, SLOT(slotSidebarTabTitleStyleChanged())); } void DigikamView::connectIconViewFilter(AlbumIconViewFilter *filter) { ImageAlbumFilterModel *model = d->iconView->imageFilterModel(); connect(filter, SIGNAL(ratingFilterChanged(int, ImageFilterSettings::RatingCondition)), model, SLOT(setRatingFilter(int, ImageFilterSettings::RatingCondition))); connect(filter, SIGNAL(mimeTypeFilterChanged(int)), model, SLOT(setMimeTypeFilter(int))); connect(filter, SIGNAL(textFilterChanged(const SearchTextSettings&)), model, SLOT(setTextFilter(const SearchTextSettings&))); connect(model, SIGNAL(filterMatches(bool)), filter, SLOT(slotFilterMatches(bool))); connect(model, SIGNAL(filterMatchesForText(bool)), filter, SLOT(slotFilterMatchesForText(bool))); connect(model, SIGNAL(filterSettingsChanged(const ImageFilterSettings&)), filter, SLOT(slotFilterSettingsChanged(const ImageFilterSettings&))); connect(filter, SIGNAL(resetTagFilters()), d->tagFilterView, SLOT(slotResetTagFilters())); } void DigikamView::loadViewState() { KSharedConfig::Ptr config = KGlobal::config(); KConfigGroup group = config->group("MainWindow"); // Restore the splitter d->splitter->restoreState(group); // Restore the thumbnail bar dock. QByteArray thumbbarState; thumbbarState = group.readEntry("ThumbbarState", thumbbarState); d->dockArea->restoreState(QByteArray::fromBase64(thumbbarState)); d->initialAlbumID = group.readEntry("InitialAlbumID", 0); } void DigikamView::saveViewState() { KSharedConfig::Ptr config = KGlobal::config(); KConfigGroup group = config->group("MainWindow"); // Save the splitter states. d->splitter->saveState(group); // Save the position and size of the thumbnail bar. The thumbnail bar dock // needs to be closed explicitly, because when it is floating and visible // (when the user is in image preview mode) when the layout is saved, it // also reappears when restoring the view, while it should always be hidden. d->albumWidgetStack->thumbBarDock()->close(); group.writeEntry("ThumbbarState", d->dockArea->saveState().toBase64()); Album *album = AlbumManager::instance()->currentAlbum(); if(album) { group.writeEntry("InitialAlbumID", album->globalID()); } else { group.writeEntry("InitialAlbumID", 0); } } KUrl::List DigikamView::allUrls() const { return d->iconView->urls(); } KUrl::List DigikamView::selectedUrls() const { return d->iconView->selectedUrls(); } void DigikamView::showSideBars() { d->leftSideBar->restore(); d->rightSideBar->restore(); } void DigikamView::hideSideBars() { d->leftSideBar->backup(); d->rightSideBar->backup(); } void DigikamView::slotFirstItem() { d->iconView->toFirstIndex(); } void DigikamView::slotPrevItem() { d->iconView->toPreviousIndex(); } void DigikamView::slotNextItem() { d->iconView->toNextIndex(); } void DigikamView::slotLastItem() { d->iconView->toLastIndex(); } void DigikamView::slotSelectItemByUrl(const KUrl& url) { d->iconView->toIndex(url); } void DigikamView::slotAllAlbumsLoaded() { disconnect(d->albumManager, SIGNAL(signalAllAlbumsLoaded()), this, SLOT(slotAllAlbumsLoaded())); loadViewState(); Album *album = d->albumManager->findAlbum(d->initialAlbumID); d->albumManager->setCurrentAlbum(album); d->leftSideBar->loadViewState(); d->rightSideBar->loadViewState(); d->rightSideBar->populateTags(); slotAlbumSelected(album); } void DigikamView::slotSortAlbums(int order) { AlbumSettings* settings = AlbumSettings::instance(); if (!settings) return; settings->setAlbumSortOrder((AlbumSettings::AlbumSortOrder) order); d->folderView->resort(); } void DigikamView::slotNewAlbum() { d->folderView->albumNew(); } void DigikamView::slotNewAlbumFromSelection() { d->iconView->createNewAlbumForSelected(); } void DigikamView::slotDeleteAlbum() { d->folderView->albumDelete(); } void DigikamView::slotNewTag() { d->tagFolderView->tagNew(); } void DigikamView::slotDeleteTag() { d->tagFolderView->tagDelete(); } void DigikamView::slotEditTag() { d->tagFolderView->tagEdit(); } void DigikamView::slotNewKeywordSearch() { if (d->leftSideBar->getActiveTab() != d->searchBox) d->leftSideBar->setActiveTab(d->searchBox); d->searchTabHeader->newKeywordSearch(); } void DigikamView::slotNewAdvancedSearch() { if (d->leftSideBar->getActiveTab() != d->searchBox) d->leftSideBar->setActiveTab(d->searchBox); d->searchTabHeader->newAdvancedSearch(); } void DigikamView::slotNewDuplicatesSearch(Album* album) { if (d->leftSideBar->getActiveTab() != d->fuzzySearchView) d->leftSideBar->setActiveTab(d->fuzzySearchView); d->fuzzySearchView->newDuplicatesSearch(album); } void DigikamView::slotAlbumAdded(Album *album) { if (!album->isRoot()) { switch (album->type()) { case Album::PHYSICAL: { d->folderSearchBar->completionObject()->addItem(album->title()); break; } case Album::TAG: { d->tagSearchBar->completionObject()->addItem(album->title()); d->tagFilterSearchBar->completionObject()->addItem(album->title()); break; } case Album::SEARCH: { SAlbum* salbum = (SAlbum*)(album); if (salbum->isNormalSearch() || salbum->isKeywordSearch() || salbum->isAdvancedSearch()) d->searchSearchBar->completionObject()->addItem(salbum->title()); else if (salbum->isTimelineSearch()) d->timeLineView->searchBar()->completionObject()->addItem(salbum->title()); else if (salbum->isHaarSearch()) d->fuzzySearchView->searchBar()->completionObject()->addItem(salbum->title()); #ifdef HAVE_MARBLEWIDGET else if (salbum->isMapSearch()) d->gpsSearchView->searchBar()->completionObject()->addItem(salbum->title()); #endif break; } default: { // Nothing to do with Album::DATE break; } } } } void DigikamView::slotAlbumDeleted(Album *album) { d->albumHistory->deleteAlbum(album); /* // For what is this needed? Album *a; QWidget *widget; d->albumHistory->getCurrentAlbum(&a, &widget); changeAlbumFromHistory(a, widget); */ if (!album->isRoot()) { switch (album->type()) { case Album::PHYSICAL: { d->folderSearchBar->completionObject()->removeItem(album->title()); break; } case Album::TAG: { d->tagSearchBar->completionObject()->removeItem(album->title()); d->tagFilterSearchBar->completionObject()->removeItem(album->title()); break; } case Album::SEARCH: { SAlbum* salbum = (SAlbum*)(album); if (salbum->isNormalSearch() || salbum->isKeywordSearch() || salbum->isAdvancedSearch()) d->searchSearchBar->completionObject()->removeItem(salbum->title()); else if (salbum->isTimelineSearch()) d->timeLineView->searchBar()->completionObject()->removeItem(salbum->title()); else if (salbum->isHaarSearch()) d->fuzzySearchView->searchBar()->completionObject()->removeItem(salbum->title()); #ifdef HAVE_MARBLEWIDGET else if (salbum->isMapSearch()) d->gpsSearchView->searchBar()->completionObject()->removeItem(salbum->title()); #endif break; } default: { // Nothing to do with Album::DATE break; } } } } void DigikamView::slotAlbumRenamed(Album *album) { // display changed names if (!album->isRoot()) { switch (album->type()) { case Album::PHYSICAL: { d->folderSearchBar->completionObject()->addItem(album->title()); d->folderView->slotTextFolderFilterChanged(d->folderSearchBar->searchTextSettings()); break; } case Album::TAG: { d->tagSearchBar->completionObject()->addItem(album->title()); d->tagFolderView->slotTextTagFilterChanged(d->tagSearchBar->searchTextSettings()); d->tagFilterSearchBar->completionObject()->addItem(album->title()); d->tagFilterView->slotTextTagFilterChanged(d->tagFilterSearchBar->searchTextSettings()); break; } case Album::SEARCH: { SAlbum* salbum = (SAlbum*)(album); if (salbum->isNormalSearch() || salbum->isKeywordSearch() || salbum->isAdvancedSearch()) { d->searchSearchBar->completionObject()->addItem(salbum->title()); d->searchFolderView->slotTextSearchFilterChanged(d->searchSearchBar->searchTextSettings()); } else if (salbum->isTimelineSearch()) { d->timeLineView->searchBar()->completionObject()->addItem(salbum->title()); d->timeLineView->folderView()->slotTextSearchFilterChanged(d->timeLineView->searchBar()->searchTextSettings()); } else if (salbum->isHaarSearch()) { d->fuzzySearchView->searchBar()->completionObject()->addItem(salbum->title()); d->fuzzySearchView->folderView()->slotTextSearchFilterChanged(d->fuzzySearchView->searchBar()->searchTextSettings()); } #ifdef HAVE_MARBLEWIDGET else if (salbum->isMapSearch()) { d->gpsSearchView->searchBar()->completionObject()->addItem(salbum->title()); d->gpsSearchView->folderView()->slotTextSearchFilterChanged(d->gpsSearchView->searchBar()->searchTextSettings()); } #endif break; } default: { // Nothing to do with Album::DATE break; } } } } void DigikamView::slotAlbumsCleared() { emit signalAlbumSelected(false); d->folderSearchBar->completionObject()->clear(); d->tagSearchBar->completionObject()->clear(); d->tagFilterSearchBar->completionObject()->clear(); d->searchSearchBar->completionObject()->clear(); d->timeLineView->searchBar()->completionObject()->clear(); d->fuzzySearchView->searchBar()->completionObject()->clear(); #ifdef HAVE_MARBLEWIDGET d->gpsSearchView->searchBar()->completionObject()->clear(); #endif } void DigikamView::slotAlbumHistoryBack(int steps) { Album *album=0; QWidget *widget=0; d->albumHistory->back(&album, &widget, steps); changeAlbumFromHistory(album, widget); } void DigikamView::slotAlbumHistoryForward(int steps) { Album *album=0; QWidget *widget=0; d->albumHistory->forward(&album, &widget, steps); changeAlbumFromHistory(album, widget); } void DigikamView::changeAlbumFromHistory(Album *album, QWidget *widget) { if (album && widget) { Q3ListViewItem *item = 0; // Check if widget is a vbox used to host folderview, tagview or searchview. if (KVBox *v = dynamic_cast(widget)) { if (v == d->folderBox) { item = (Q3ListViewItem*)album->extraData(d->folderView); if(!item) return; d->folderView->setSelected(item, true); d->folderView->ensureItemVisible(item); } else if (v == d->tagBox) { item = (Q3ListViewItem*)album->extraData(d->tagFolderView); if(!item) return; d->tagFolderView->setSelected(item, true); d->tagFolderView->ensureItemVisible(item); } else if (v == d->searchBox) { item = (Q3ListViewItem*)album->extraData(d->searchFolderView); if(!item) return; d->searchFolderView->setSelected(item, true); d->searchFolderView->ensureItemVisible(item); } } else if (DateFolderView *v = dynamic_cast(widget)) { item = (Q3ListViewItem*)album->extraData(v); if(!item) return; v->setSelected(item); } else if (TimeLineView *v = dynamic_cast(widget)) { item = (Q3ListViewItem*)album->extraData(v->folderView()); if(!item) return; v->folderView()->setSelected(item, true); v->folderView()->ensureItemVisible(item); } else if (FuzzySearchView *v = dynamic_cast(widget)) { item = (Q3ListViewItem*)album->extraData(v->folderView()); if(!item) return; v->folderView()->setSelected(item, true); v->folderView()->ensureItemVisible(item); } d->leftSideBar->setActiveTab(widget); d->parent->enableAlbumBackwardHistory(!d->albumHistory->isBackwardEmpty()); d->parent->enableAlbumForwardHistory(!d->albumHistory->isForwardEmpty()); } } void DigikamView::clearHistory() { d->albumHistory->clearHistory(); d->parent->enableAlbumBackwardHistory(false); d->parent->enableAlbumForwardHistory(false); } void DigikamView::getBackwardHistory(QStringList& titles) { d->albumHistory->getBackwardHistory(titles); for (int i=0; iuserPresentableAlbumTitle(titles[i]); } void DigikamView::getForwardHistory(QStringList& titles) { d->albumHistory->getForwardHistory(titles); for (int i=0; iuserPresentableAlbumTitle(titles[i]); } QString DigikamViewPriv::userPresentableAlbumTitle(const QString& title) { if (title == FuzzySearchFolderView::currentFuzzySketchSearchName()) return i18n("Fuzzy Sketch Search"); else if (title == FuzzySearchFolderView::currentFuzzyImageSearchName()) return i18n("Fuzzy Image Search"); else if (title == GPSSearchFolderView::currentGPSSearchName()) return i18n("Map Search"); else if (title == SearchFolderView::currentSearchViewSearchName()) return i18n("Last Search"); else if (title == TimeLineFolderView::currentTimeLineSearchName()) return i18n("Timeline"); return title; } void DigikamView::slotSelectAlbum(const KUrl &) { /* TODO if (url.isEmpty()) return; Album *album = d->albumManager->findPAlbum(url); if(album && album->getViewItem()) { AlbumFolderItem_Deprecated *item; item = static_cast(album->getViewItem()); mFolderView_Deprecated->setSelected(item); d->parent->enableAlbumBackwardHistory(!d->albumHistory->isBackwardEmpty()); d->parent->enableAlbumForwardHistory(!d->albumHistory->isForwardEmpty()); } */ } void DigikamView::slotGotoAlbumAndItem(const ImageInfo& imageInfo) { emit signalNoCurrentItem(); Album* album = dynamic_cast(AlbumManager::instance()->findPAlbum(imageInfo.albumId())); // Change the current album in list view. d->folderView->setCurrentAlbum(album); // Change to (physical) Album view. // Note, that this also opens the side bar if it is closed; this is // considered as a feature, because it highlights that the view was changed. d->leftSideBar->setActiveTab(d->folderBox); // Set the activate item url to find in the Album View after // all items have be reloaded. - d->iconView->scrollToWhenAvailable(imageInfo.id()); + d->iconView->setCurrentWhenAvailable(imageInfo.id()); // And finally toggle album manager to handle album history and // reload all items. d->albumManager->setCurrentAlbum(album); } void DigikamView::slotGotoDateAndItem(const ImageInfo& imageInfo) { QDate date = imageInfo.dateTime().date(); emit signalNoCurrentItem(); // Change to Date Album view. // Note, that this also opens the side bar if it is closed; this is // considered as a feature, because it highlights that the view was changed. d->leftSideBar->setActiveTab(d->dateFolderView); // Set the activate item url to find in the Album View after // all items have be reloaded. - d->iconView->scrollToWhenAvailable(imageInfo.id()); + d->iconView->setCurrentWhenAvailable(imageInfo.id()); // Change the year and month of the iconItem (day is unused). d->dateFolderView->gotoDate(date); } void DigikamView::slotGotoTagAndItem(int tagID) { // FIXME: Arnd: don't know yet how to get the iconItem passed through ... // FIXME: then we would know how to use the following ... // KURL url( iconItem->imageInfo()->kurl() ); // url.cleanPath(); emit signalNoCurrentItem(); // Change to Tag Folder view. // Note, that this also opens the side bar if it is closed; this is // considered as a feature, because it highlights that the view was changed. d->leftSideBar->setActiveTab(d->tagBox); // Set the current tag in the tag folder view. d->tagFolderView->selectItem(tagID); // Set the activate item url to find in the Tag View after // all items have be reloaded. // FIXME: see above // d->iconView->setAlbumItemToFind(url); } void DigikamView::slotAlbumSelected(Album* album) { emit signalNoCurrentItem(); if (!album) { d->iconView->openAlbum(0); emit signalAlbumSelected(false); emit signalTagSelected(false); return; } if (album->type() == Album::PHYSICAL) { emit signalAlbumSelected(true); emit signalTagSelected(false); } else if (album->type() == Album::TAG) { emit signalAlbumSelected(false); emit signalTagSelected(true); } d->albumHistory->addAlbum(album, d->leftSideBar->getActiveTab()); d->parent->enableAlbumBackwardHistory(!d->albumHistory->isBackwardEmpty()); d->parent->enableAlbumForwardHistory(!d->albumHistory->isForwardEmpty()); d->iconView->openAlbum(album); if (album->isRoot()) d->albumWidgetStack->setPreviewMode(AlbumWidgetStack::WelcomePageMode); else d->albumWidgetStack->setPreviewMode(AlbumWidgetStack::PreviewAlbumMode); } void DigikamView::slotAlbumOpenInKonqui() { Album *album = d->albumManager->currentAlbum(); if (!album || album->type() != Album::PHYSICAL) return; PAlbum* palbum = dynamic_cast(album); new KRun(KUrl(palbum->folderPath()), this); // KRun will delete itself. } void DigikamView::slotAlbumRefresh() { // force reloading of thumbnails LoadingCacheInterface::cleanThumbnailCache(); Album *album = d->iconView->currentAlbum(); // if physical album, schedule a collection scan of current album's path if (album && album->type() == Album::PHYSICAL) ScanController::instance()->scheduleCollectionScan(static_cast(album)->folderPath()); // force reload. Should normally not be necessary, but we may have bugs + qlonglong currentId = d->iconView->currentInfo().id(); d->iconView->imageModel()->refresh(); + if (currentId != -1) + d->iconView->setCurrentWhenAvailable(currentId); } void DigikamView::slotImageSelected() { // delay to slotDispatchImageSelected d->needDispatchSelection = true; d->selectionTimer->start(); emit signalSelectionChanged(d->iconView->numberOfSelectedIndexes()); } void DigikamView::slotDispatchImageSelected() { if (d->needDispatchSelection) { // the list of ImageInfos of currently selected items, currentItem first ImageInfoList list = d->iconView->selectedImageInfosCurrentFirst(); ImageInfoList allImages = d->iconView->imageInfos(); if (list.isEmpty()) { d->albumWidgetStack->setPreviewItem(); emit signalImageSelected(list, false, false, allImages); emit signalNoCurrentItem(); } else { d->rightSideBar->itemChanged(list); ImageInfo previousInfo = d->iconView->previousInfo(list.first()); ImageInfo nextInfo = d->iconView->nextInfo(list.first()); if (!d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) d->albumWidgetStack->setPreviewItem(list.first(), previousInfo, nextInfo); emit signalImageSelected(list, !previousInfo.isNull(), !nextInfo.isNull(), allImages); } d->needDispatchSelection = false; } } void DigikamView::setThumbSize(int size) { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewImageMode) { double h = (double)ThumbnailSize::Huge; double s = (double)ThumbnailSize::Small; double zmin = d->albumWidgetStack->zoomMin(); double zmax = d->albumWidgetStack->zoomMax(); double b = (zmin-(zmax*s/h))/(1-s/h); double a = (zmax-b)/h; double z = a*size+b; d->albumWidgetStack->setZoomFactorSnapped(z); } else if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) { if (size > ThumbnailSize::Huge) d->thumbSize = ThumbnailSize::Huge; else if (size < ThumbnailSize::Small) d->thumbSize = ThumbnailSize::Small; else d->thumbSize = size; emit signalThumbSizeChanged(d->thumbSize); d->thumbSizeTimer->start(); } } void DigikamView::slotThumbSizeEffect() { emit signalNoCurrentItem(); d->iconView->setThumbnailSize(d->thumbSize); toggleZoomActions(); AlbumSettings::instance()->setDefaultIconSize(d->thumbSize); } void DigikamView::toggleZoomActions() { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewImageMode) { d->parent->enableZoomMinusAction(true); d->parent->enableZoomPlusAction(true); if (d->albumWidgetStack->maxZoom()) d->parent->enableZoomPlusAction(false); if (d->albumWidgetStack->minZoom()) d->parent->enableZoomMinusAction(false); } else if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) { d->parent->enableZoomMinusAction(true); d->parent->enableZoomPlusAction(true); if (d->thumbSize >= ThumbnailSize::Huge) d->parent->enableZoomPlusAction(false); if (d->thumbSize <= ThumbnailSize::Small) d->parent->enableZoomMinusAction(false); } } void DigikamView::slotZoomIn() { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) { setThumbSize(d->thumbSize + ThumbnailSize::Step); toggleZoomActions(); emit signalThumbSizeChanged(d->thumbSize); } else if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewImageMode) { d->albumWidgetStack->increaseZoom(); } } void DigikamView::slotZoomOut() { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) { setThumbSize(d->thumbSize - ThumbnailSize::Step); toggleZoomActions(); emit signalThumbSizeChanged(d->thumbSize); } else if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewImageMode) { d->albumWidgetStack->decreaseZoom(); } } void DigikamView::slotZoomTo100Percents() { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewImageMode) { d->albumWidgetStack->toggleFitToWindowOr100(); } } void DigikamView::slotFitToWindow() { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewImageMode) { d->albumWidgetStack->fitToWindow(); } } void DigikamView::slotZoomFactorChanged(double zoom) { toggleZoomActions(); double h = (double)ThumbnailSize::Huge; double s = (double)ThumbnailSize::Small; double zmin = d->albumWidgetStack->zoomMin(); double zmax = d->albumWidgetStack->zoomMax(); double b = (zmin-(zmax*s/h))/(1-s/h); double a = (zmax-b)/h; int size = (int)((zoom - b) /a); emit signalZoomChanged(zoom, size); } void DigikamView::slotAlbumPropsEdit() { d->folderView->albumEdit(); } void DigikamView::connectBatchSyncMetadata(BatchSyncMetadata *syncMetadata) { connect(syncMetadata, SIGNAL(signalProgressBarMode(int, const QString&)), d->parent, SLOT(slotProgressBarMode(int, const QString&))); connect(syncMetadata, SIGNAL(signalProgressValue(int)), d->parent, SLOT(slotProgressValue(int))); //connect(syncMetadata, SIGNAL(signalComplete()), // this, SLOT(slotAlbumSyncPicturesMetadataDone())); connect(d->parent, SIGNAL(signalCancelButtonPressed()), syncMetadata, SLOT(slotAbort())); } void DigikamView::slotAlbumWriteMetadata() { Album *album = d->albumManager->currentAlbum(); if (!album) return; BatchSyncMetadata *syncMetadata = new BatchSyncMetadata(album, BatchSyncMetadata::WriteFromDatabaseToFile, this); connectBatchSyncMetadata(syncMetadata); syncMetadata->parseAlbum(); } void DigikamView::slotAlbumReadMetadata() { Album *album = d->albumManager->currentAlbum(); if (!album) return; BatchSyncMetadata *syncMetadata = new BatchSyncMetadata(album, BatchSyncMetadata::ReadFromFileToDatabase, this); connectBatchSyncMetadata(syncMetadata); syncMetadata->parseAlbum(); } void DigikamView::slotImageWriteMetadata() { ImageInfoList selected = d->iconView->selectedImageInfos(); BatchSyncMetadata *syncMetadata = new BatchSyncMetadata(selected, BatchSyncMetadata::WriteFromDatabaseToFile, this); connectBatchSyncMetadata(syncMetadata); syncMetadata->parseList(); } void DigikamView::slotImageReadMetadata() { ImageInfoList selected = d->iconView->selectedImageInfos(); BatchSyncMetadata *syncMetadata = new BatchSyncMetadata(selected, BatchSyncMetadata::ReadFromFileToDatabase, this); connectBatchSyncMetadata(syncMetadata); syncMetadata->parseList(); } // ---------------------------------------------------------------- void DigikamView::slotEscapePreview() { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode || d->albumWidgetStack->previewMode() == AlbumWidgetStack::WelcomePageMode) return; slotTogglePreviewMode(d->iconView->currentInfo()); } void DigikamView::slotImagePreview() { ImageInfo info = d->iconView->currentInfo(); if (!info.isNull()) slotTogglePreviewMode(info); } // This method toggle between AlbumView and ImagePreview Modes, depending of context. void DigikamView::slotTogglePreviewMode(const ImageInfo &info) { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode && !info.isNull()) { d->albumWidgetStack->setPreviewItem(info, d->iconView->previousInfo(info), d->iconView->nextInfo(info)); } else { // We go back to AlbumView Mode. d->albumWidgetStack->setPreviewMode( AlbumWidgetStack::PreviewAlbumMode ); } } void DigikamView::slotToggledToPreviewMode(bool b) { toggleZoomActions(); if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) emit signalThumbSizeChanged(d->iconView->thumbnailSize().size()); else if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewImageMode) slotZoomFactorChanged(d->albumWidgetStack->zoomFactor()); emit signalTogglePreview(b); } void DigikamView::slotImageEdit() { d->iconView->openCurrentInEditor(); } void DigikamView::slotImageFindSimilar() { ImageInfo current = d->iconView->currentInfo(); if (!current.isNull()) { d->fuzzySearchView->setImageInfo(current); if (d->leftSideBar->getActiveTab() != d->fuzzySearchView) d->leftSideBar->setActiveTab(d->fuzzySearchView); } } void DigikamView::slotImageExifOrientation(int orientation) { d->iconView->setExifOrientationOfSelected(orientation); } void DigikamView::slotLightTable() { d->iconView->utilities()->insertToLightTable(ImageInfoList(), ImageInfo(), true); } void DigikamView::slotQueueMgr() { d->iconView->utilities()->insertToQueueManager(ImageInfoList(), ImageInfo(), false); } void DigikamView::slotImageLightTable() { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) { // put images into an emptied light table d->iconView->insertSelectedToLightTable(false); } else { ImageInfoList list; ImageInfo info = d->albumWidgetStack->imagePreviewView()->getImageInfo(); list.append(info); // put images into an emptied light table d->iconView->utilities()->insertToLightTable(list, info, false); } } void DigikamView::slotImageAddToLightTable() { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) { // add images to the existing images in the light table d->iconView->insertSelectedToLightTable(true); } else { ImageInfoList list; ImageInfo info = d->albumWidgetStack->imagePreviewView()->getImageInfo(); list.append(info); // add images to the existing images in the light table d->iconView->utilities()->insertToLightTable(list, info, true); } } void DigikamView::slotImageAddToCurrentQueue() { if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) { d->iconView->insertSelectedToCurrentQueue(); } else { ImageInfoList list; ImageInfo info = d->albumWidgetStack->imagePreviewView()->getImageInfo(); list.append(info); d->iconView->utilities()->insertToQueueManager(list, info, false); } } void DigikamView::slotImageAddToNewQueue() { bool newQueue = QueueMgrWindow::queueManagerWindowCreated() && !QueueMgrWindow::queueManagerWindow()->queuesMap().isEmpty(); if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) { if (newQueue) d->iconView->insertSelectedToNewQueue(); else d->iconView->insertSelectedToCurrentQueue(); } else { //FIXME. ImageInfoList list; ImageInfo info = d->albumWidgetStack->imagePreviewView()->getImageInfo(); list.append(info); d->iconView->utilities()->insertToQueueManager(list, info, newQueue); } } void DigikamView::slotImageAddToExistingQueue(int queueid) { ImageInfoList list; if (d->albumWidgetStack->previewMode() == AlbumWidgetStack::PreviewAlbumMode) list = d->albumWidgetStack->imageIconView()->selectedImageInfos(); else list << d->albumWidgetStack->imagePreviewView()->getImageInfo(); d->iconView->utilities()->insertSilentToQueueManager(list, list.first(), queueid); } void DigikamView::slotImageRename() { d->iconView->rename(); } void DigikamView::slotImageDelete() { d->iconView->deleteSelected(false); } void DigikamView::slotImageDeletePermanently() { d->iconView->deleteSelected(true); } void DigikamView::slotImageDeletePermanentlyDirectly() { d->iconView->deleteSelectedDirectly(false); } void DigikamView::slotImageTrashDirectly() { d->iconView->deleteSelectedDirectly(true); } void DigikamView::slotSelectAll() { d->iconView->selectAll(); } void DigikamView::slotSelectNone() { d->iconView->clearSelection(); } void DigikamView::slotSelectInvert() { d->iconView->invertSelection(); } void DigikamView::slotSortImages(int sortRole) { AlbumSettings* settings = AlbumSettings::instance(); if (!settings) return; settings->setImageSortOrder(sortRole); d->iconView->imageFilterModel()->setSortRole((ImageSortSettings::SortRole) sortRole); } void DigikamView::slotGroupImages(int categoryMode) { AlbumSettings* settings = AlbumSettings::instance(); if (!settings) return; settings->setImageGroupMode(categoryMode); d->iconView->imageFilterModel()->setCategorizationMode((ImageSortSettings::CategorizationMode) categoryMode); } void DigikamView::slotLeftSidebarChangedTab(QWidget* w) { // setActive means that selection changes are propagated, nothing more. // Additionally, when it is set to true, the selectionChanged signal will be emitted. // So this is the place which causes the behavior that when the left sidebar // tab is changed, the current album is changed as well. d->dateFolderView->setActive(w == d->dateFolderView); d->folderView->setActive(w == d->folderBox); d->tagFolderView->setActive(w == d->tagBox); d->searchFolderView->setActive(w == d->searchBox); d->timeLineView->setActive(w == d->timeLineView); d->fuzzySearchView->setActive(w == d->fuzzySearchView); #ifdef HAVE_MARBLEWIDGET d->gpsSearchView->setActive(w == d->gpsSearchView); #endif } void DigikamView::slotAssignRating(int rating) { d->iconView->assignRatingToSelected(rating); } void DigikamView::slotAssignRatingNoStar() { d->iconView->assignRatingToSelected(0); } void DigikamView::slotAssignRatingOneStar() { d->iconView->assignRatingToSelected(1); } void DigikamView::slotAssignRatingTwoStar() { d->iconView->assignRatingToSelected(2); } void DigikamView::slotAssignRatingThreeStar() { d->iconView->assignRatingToSelected(3); } void DigikamView::slotAssignRatingFourStar() { d->iconView->assignRatingToSelected(4); } void DigikamView::slotAssignRatingFiveStar() { d->iconView->assignRatingToSelected(5); } void DigikamView::slotSlideShowAll() { slideShow(d->iconView->imageInfos()); } void DigikamView::slotSlideShowSelection() { slideShow(d->iconView->selectedImageInfos()); } void DigikamView::slotSlideShowRecursive() { Album *album = AlbumManager::instance()->currentAlbum(); if(album) { AlbumList albumList; albumList.append(album); AlbumIterator it(album); while (it.current()) { albumList.append(*it); ++it; } ImageInfoAlbumsJob *job = new ImageInfoAlbumsJob; connect(job, SIGNAL(signalCompleted(const ImageInfoList&)), this, SLOT(slotItemsInfoFromAlbums(const ImageInfoList&))); job->allItemsFromAlbums(albumList); } } void DigikamView::slotItemsInfoFromAlbums(const ImageInfoList& infoList) { ImageInfoList list = infoList; slideShow(list); } void DigikamView::slideShow(const ImageInfoList& infoList) { KSharedConfig::Ptr config = KGlobal::config(); KConfigGroup group = config->group("ImageViewer Settings"); bool startWithCurrent = group.readEntry("SlideShowStartCurrent", false); int i = 0; float cnt = (float)infoList.count(); emit signalProgressBarMode(StatusProgressBar::CancelProgressBarMode, i18np("Preparing slideshow of 1 image. Please wait...","Preparing slideshow of %1 images. Please wait...", infoList.count())); SlideShowSettings settings; settings.exifRotate = AlbumSettings::instance()->getExifRotate(); settings.ratingColor = ThemeEngine::instance()->textSpecialRegColor(); settings.delay = group.readEntry("SlideShowDelay", 5) * 1000; settings.printName = group.readEntry("SlideShowPrintName", true); settings.printDate = group.readEntry("SlideShowPrintDate", false); settings.printApertureFocal = group.readEntry("SlideShowPrintApertureFocal", false); settings.printExpoSensitivity = group.readEntry("SlideShowPrintExpoSensitivity", false); settings.printMakeModel = group.readEntry("SlideShowPrintMakeModel", false); settings.printComment = group.readEntry("SlideShowPrintComment", false); settings.printRating = group.readEntry("SlideShowPrintRating", false); settings.loop = group.readEntry("SlideShowLoop", false); d->cancelSlideShow = false; for (ImageInfoList::const_iterator it = infoList.constBegin(); !d->cancelSlideShow && (it != infoList.constEnd()) ; ++it) { ImageInfo info = *it; settings.fileList.append(info.fileUrl()); SlidePictureInfo pictInfo; pictInfo.comment = info.comment(); pictInfo.rating = info.rating(); pictInfo.photoInfo = info.photoInfoContainer(); settings.pictInfoMap.insert(info.fileUrl(), pictInfo); emit signalProgressValue((int)((i++/cnt)*100.0)); kapp->processEvents(); } emit signalProgressBarMode(StatusProgressBar::TextMode, QString()); if (!d->cancelSlideShow) { SlideShow *slide = new SlideShow(settings); if (startWithCurrent) { slide->setCurrent(d->iconView->currentUrl()); } slide->show(); } } void DigikamView::slotCancelSlideShow() { d->cancelSlideShow = true; } void DigikamView::toggleShowBar(bool b) { d->albumWidgetStack->thumbBarDock()->showThumbBar(b); } void DigikamView::setRecurseAlbums(bool recursive) { d->iconView->imageModel()->setRecurseAlbums(recursive); } void DigikamView::setRecurseTags(bool recursive) { d->iconView->imageModel()->setRecurseTags(recursive); } void DigikamView::slotSidebarTabTitleStyleChanged() { d->leftSideBar->setStyle(AlbumSettings::instance()->getSidebarTitleStyle()); d->rightSideBar->setStyle(AlbumSettings::instance()->getSidebarTitleStyle()); d->rightSideBar->applySettings(); } void DigikamView::slotProgressMessageChanged(const QString& descriptionOfAction) { emit signalProgressBarMode(StatusProgressBar::ProgressBarMode, descriptionOfAction); } void DigikamView::slotProgressValueChanged(float percent) { emit signalProgressValue(lround(percent * 100)); } void DigikamView::slotProgressFinished() { emit signalProgressBarMode(StatusProgressBar::TextMode, QString()); } void DigikamView::slotOrientationChangeFailed(const QStringList& failedFileNames) { if (failedFileNames.isEmpty()) return; if (failedFileNames.count() == 1) { KMessageBox::error(0, i18n("Failed to revise Exif orientation for file %1.", failedFileNames[0])); } else { KMessageBox::errorList(0, i18n("Failed to revise Exif orientation these files:"), failedFileNames); } } } // namespace Digikam Index: trunk/extragear/graphics/digikam/digikam/imagecategorizedview.cpp =================================================================== --- trunk/extragear/graphics/digikam/digikam/imagecategorizedview.cpp (revision 1028323) +++ trunk/extragear/graphics/digikam/digikam/imagecategorizedview.cpp (revision 1028324) @@ -1,1049 +1,1051 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2009-04-22 * Description : Qt item view for images * * Copyright (C) 2009 by Marcel Wiesweg * * 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, 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. * * ============================================================ */ #include "imagecategorizedview.h" #include "imagecategorizedview.moc" // Qt includes #include #include #include // KDE includes #include #include // Local includes #include "album.h" #include "albummanager.h" #include "albumsettings.h" #include "databasefields.h" #include "imagealbummodel.h" #include "imagealbumfiltermodel.h" #include "imagecategorydrawer.h" #include "imagedelegate.h" #include "imagedelegateoverlay.h" #include "imagemodeldragdrophandler.h" #include "imagethumbnailmodel.h" #include "imageselectionoverlay.h" #include "itemviewtooltip.h" #include "loadingcacheinterface.h" #include "thumbnailloadthread.h" #include "tooltipfiller.h" namespace Digikam { class ImageItemViewToolTip : public ItemViewToolTip { public: ImageItemViewToolTip(ImageCategorizedView *view) : ItemViewToolTip(view) { } ImageCategorizedView *view() const { return static_cast(ItemViewToolTip::view()); } protected: virtual QString tipContents() { ImageInfo info = ImageModel::retrieveImageInfo(currentIndex()); return ToolTipFiller::imageInfoTipContents(info); } }; // ------------------------------------------------------------------------------- class ImageCategorizedViewPriv { public: ImageCategorizedViewPriv() { model = 0; filterModel = 0; delegate = 0; toolTip = 0; scrollToItemId = 0; currentMouseEvent = 0; showToolTip = false; ensureOneSelectedItem = false; ensureInitialSelectedItem = false; hintAtSelectionRow = -1; } ImageAlbumModel *model; ImageAlbumFilterModel *filterModel; ImageDelegate *delegate; ImageItemViewToolTip *toolTip; bool showToolTip; ThumbnailSize thumbnailSize; qlonglong scrollToItemId; QMouseEvent *currentMouseEvent; bool ensureOneSelectedItem; bool ensureInitialSelectedItem; QPersistentModelIndex hintAtSelectionIndex; int hintAtSelectionRow; }; // ------------------------------------------------------------------------------- ImageCategorizedView::ImageCategorizedView(QWidget *parent) : KCategorizedView(parent), d(new ImageCategorizedViewPriv) { setViewMode(QListView::IconMode); setLayoutDirection(Qt::LeftToRight); setFlow(QListView::LeftToRight); setResizeMode(QListView::Adjust); setMovement(QListView::Static); setWrapping(true); // important optimization for layouting setUniformItemSizes(true); // disable "feature" from KCategorizedView setDrawDraggedItems(false); setSelectionMode(QAbstractItemView::ExtendedSelection); setDragEnabled(true); setEditTriggers(QAbstractItemView::NoEditTriggers); viewport()->setAcceptDrops(true); setMouseTracking(true); d->model = new ImageAlbumModel(this); d->filterModel = new ImageAlbumFilterModel(this); d->filterModel->setSourceImageModel(d->model); d->filterModel->setSortRole(ImageSortSettings::SortByFileName); d->filterModel->setCategorizationMode(ImageSortSettings::CategoryByAlbum); d->filterModel->sort(0); // an initial sorting is necessary // set flags that we want to get dataChanged() signals for d->model->setWatchFlags(d->filterModel->suggestedWatchFlags()); d->delegate = new ImageDelegate(this); d->delegate->setSpacing(10); setItemDelegate(d->delegate); setCategoryDrawer(d->delegate->categoryDrawer()); d->toolTip = new ImageItemViewToolTip(this); setModel(d->filterModel); connect(d->filterModel, SIGNAL(layoutAboutToBeChanged()), this, SLOT(layoutAboutToBeChanged())); connect(d->filterModel, SIGNAL(layoutChanged()), this, SLOT(layoutWasChanged()), Qt::QueuedConnection); connect(d->model, SIGNAL(imageInfosAdded(const QList &)), this, SLOT(slotImageInfosAdded())); connect(d->delegate, SIGNAL(gridSizeChanged(const QSize &)), this, SLOT(slotGridSizeChanged(const QSize &))); connect(this, SIGNAL(activated(const QModelIndex &)), this, SLOT(slotActivated(const QModelIndex &))); connect(this, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotClicked(const QModelIndex &))); connect(this, SIGNAL(entered(const QModelIndex &)), this, SLOT(slotEntered(const QModelIndex &))); LoadingCacheInterface::connectToSignalFileChanged(this, SLOT(slotFileChanged(const QString &))); updateDelegateSizes(); addSelectionOverlay(); /* if (KGlobalSettings::singleClick()) { connect(this, SIGNAL(clicked(const QModelIndex&)), controller, SLOT(triggerItem(const QModelIndex&))); } else { connect(this, SIGNAL(doubleClicked(const QModelIndex&)), controller, SLOT(triggerItem(const QModelIndex&))); } */ } ImageCategorizedView::~ImageCategorizedView() { d->delegate->removeAllOverlays(); delete d->toolTip; delete d; } ImageAlbumModel *ImageCategorizedView::imageModel() const { return d->model; } ImageAlbumFilterModel *ImageCategorizedView::imageFilterModel() const { return d->filterModel; } ImageDelegate *ImageCategorizedView::delegate() const { return d->delegate; } Album *ImageCategorizedView::currentAlbum() const { return d->model->currentAlbum(); } ImageInfo ImageCategorizedView::currentInfo() const { return d->filterModel->imageInfo(currentIndex()); } KUrl ImageCategorizedView::currentUrl() const { return currentInfo().fileUrl(); } QList ImageCategorizedView::selectedImageInfos() const { return d->filterModel->imageInfos(selectedIndexes()); } QList ImageCategorizedView::selectedImageInfosCurrentFirst() const { QList indexes = selectedIndexes(); QModelIndex current = currentIndex(); QList infos; foreach (const QModelIndex& index, indexes) { ImageInfo info = d->filterModel->imageInfo(index); if (index == current) infos.prepend(info); else infos.append(info); } return infos; } int ImageCategorizedView::numberOfSelectedIndexes() const { return selectedIndexes().size(); } QList ImageCategorizedView::imageInfos() const { return d->filterModel->imageInfosSorted(); } KUrl::List ImageCategorizedView::urls() const { QList infos = imageInfos(); KUrl::List urls; foreach (const ImageInfo& info, infos) urls << info.fileUrl(); return urls; } KUrl::List ImageCategorizedView::selectedUrls() const { QList infos = selectedImageInfos(); KUrl::List urls; foreach (const ImageInfo& info, infos) urls << info.fileUrl(); return urls; } ImageInfo ImageCategorizedView::nextInOrder(const ImageInfo &startingPoint, int nth) { QModelIndex index = d->filterModel->indexForImageInfo(startingPoint); if (!index.isValid()) return ImageInfo(); return d->filterModel->imageInfo(d->filterModel->index(index.row() + nth, 0, QModelIndex())); } void ImageCategorizedView::toFirstIndex() { QModelIndex index = moveCursor(MoveHome, Qt::NoModifier); clearSelection(); setCurrentIndex(index); scrollToTop(); } void ImageCategorizedView::toLastIndex() { QModelIndex index = moveCursor(MoveEnd, Qt::NoModifier); clearSelection(); setCurrentIndex(index); scrollToBottom(); } void ImageCategorizedView::toNextIndex() { toIndex(moveCursor(MoveNext, Qt::NoModifier)); } void ImageCategorizedView::toPreviousIndex() { toIndex(moveCursor(MovePrevious, Qt::NoModifier)); } void ImageCategorizedView::toIndex(const KUrl& url) { QModelIndex index = d->model->indexForPath(url.toLocalFile()); toIndex(d->filterModel->mapFromSource(index)); } void ImageCategorizedView::toIndex(const QModelIndex& index) { if (!index.isValid()) return; clearSelection(); setCurrentIndex(index); scrollTo(index); } void ImageCategorizedView::invertSelection() { const QModelIndex topLeft = d->filterModel->index(0, 0); const QModelIndex bottomRight = d->filterModel->index(d->filterModel->rowCount() - 1, 0); const QItemSelection selection(topLeft, bottomRight); selectionModel()->select(selection, QItemSelectionModel::Toggle); } void ImageCategorizedView::openAlbum(Album *album) { d->model->openAlbum(album); } ThumbnailSize ImageCategorizedView::thumbnailSize() const { return d->model->thumbnailSize(); } void ImageCategorizedView::setThumbnailSize(int size) { setThumbnailSize(ThumbnailSize(size)); } void ImageCategorizedView::setThumbnailSize(const ThumbnailSize& size) { d->model->setThumbnailSize(size); d->delegate->setThumbnailSize(size); //viewport()->update(); } void ImageCategorizedView::setToolTipEnabled(bool enable) { d->showToolTip = enable; } bool ImageCategorizedView::isToolTipEnabled() const { return d->showToolTip; } -void ImageCategorizedView::scrollToWhenAvailable(qlonglong imageId) +void ImageCategorizedView::setCurrentWhenAvailable(qlonglong imageId) { d->scrollToItemId = imageId; } void ImageCategorizedView::setCurrentUrl(const KUrl& url) { QString path = url.toLocalFile(); QModelIndex index = d->filterModel->indexForPath(path); if (!index.isValid()) { kWarning() << "no QModelIndex found for" << url; return; } clearSelection(); setCurrentIndex(index); } void ImageCategorizedView::addOverlay(ImageDelegateOverlay *overlay) { overlay->setView(this); d->delegate->installOverlay(overlay); } void ImageCategorizedView::removeOverlay(ImageDelegateOverlay *overlay) { d->delegate->removeOverlay(overlay); overlay->setView(0); } void ImageCategorizedView::addSelectionOverlay() { addOverlay(new ImageSelectionOverlay(this)); } void ImageCategorizedView::scrollToStoredItem() { if (d->scrollToItemId) { if (d->model->hasImage(d->scrollToItemId)) { - scrollTo(d->filterModel->indexForImageId(d->scrollToItemId)); + QModelIndex index = d->filterModel->indexForImageId(d->scrollToItemId); + setCurrentIndex(index); + scrollTo(index, QAbstractItemView::PositionAtCenter); d->scrollToItemId = 0; } } } void ImageCategorizedView::slotImageInfosAdded() { if (d->scrollToItemId) scrollToStoredItem(); } void ImageCategorizedView::slotThemeChanged() { viewport()->update(); } void ImageCategorizedView::slotSetupChanged() { viewport()->update(); } void ImageCategorizedView::slotGridSizeChanged(const QSize& gridSize) { setGridSize(gridSize); horizontalScrollBar()->setSingleStep(gridSize.width() / 20); verticalScrollBar()->setSingleStep(gridSize.height() / 20); } void ImageCategorizedView::updateDelegateSizes() { QStyleOptionViewItem option = viewOptions(); /*int frameAroundContents = 0; if (style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents)) { frameAroundContents = style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2; } const int contentWidth = viewport()->width() - 1 - frameAroundContents - style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, verticalScrollBar()); const int contentHeight = viewport()->height() - 1 - frameAroundContents - style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, horizontalScrollBar()); option.rect = QRect(0, 0, contentWidth, contentHeight); */ option.rect = QRect(QPoint(0,0), viewport()->size()); d->delegate->setDefaultViewOptions(option); } void ImageCategorizedView::slotFileChanged(const QString& filePath) { QModelIndex index = d->filterModel->indexForPath(filePath); if (index.isValid()) update(index); } void ImageCategorizedView::slotActivated(const QModelIndex& index) { if (d->currentMouseEvent) { // ignore activation if Ctrl or Shift is pressed (for selection) Qt::KeyboardModifiers modifiers = d->currentMouseEvent->modifiers(); const bool shiftKeyPressed = modifiers & Qt::ShiftModifier; const bool controlKeyPressed = modifiers & Qt::ControlModifier; if (shiftKeyPressed || controlKeyPressed) return; // if the activation is caused by mouse click (not keyboard) // we need to check the hot area if (!d->delegate->acceptsActivation(d->currentMouseEvent->pos(), visualRect(index), index)) return; } ImageInfo info = d->filterModel->imageInfo(index); if (!info.isNull()) activated(info); } void ImageCategorizedView::slotClicked(const QModelIndex& index) { if (d->currentMouseEvent) emit clicked(d->currentMouseEvent, index); } void ImageCategorizedView::slotEntered(const QModelIndex& index) { if (d->currentMouseEvent) emit entered(d->currentMouseEvent, index); } void ImageCategorizedView::reset() { KCategorizedView::reset(); emit selectionChanged(); emit selectionCleared(); d->ensureInitialSelectedItem = true; } void ImageCategorizedView::currentChanged(const QModelIndex& index, const QModelIndex& previous) { KCategorizedView::currentChanged(index, previous); emit currentChanged(d->filterModel->imageInfo(index)); } void ImageCategorizedView::selectionChanged(const QItemSelection& selectedItems, const QItemSelection& deselectedItems) { KCategorizedView::selectionChanged(selectedItems, deselectedItems); emit selectionChanged(); if (!selectedItems.isEmpty()) emit selected(d->filterModel->imageInfos(selectedItems.indexes())); if (!deselectedItems.isEmpty()) emit deselected(d->filterModel->imageInfos(deselectedItems.indexes())); if (!selectionModel()->hasSelection()) emit selectionCleared(); userInteraction(); } void ImageCategorizedView::rowsInserted(const QModelIndex &parent, int start, int end) { KCategorizedView::rowsInserted(parent, start, end); if (start == 0) ensureSelectionAfterChanges(); } void ImageCategorizedView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { KCategorizedView::rowsAboutToBeRemoved(parent, start, end); // Ensure one selected item int totalToRemove = end - start + 1; if (selectionModel()->hasSelection() && model()->rowCount(parent) > totalToRemove) { // find out which selected indexes are left after rows are removed QItemSelection selected = selectionModel()->selection(); QItemSelection removed(model()->index(start, 0), model()->index(end, 0)); selected.merge(removed, QItemSelectionModel::Deselect); if (selected.isEmpty()) { QModelIndex newCurrent; if (end == model()->rowCount(parent) - 1) newCurrent = model()->index(start - 1, 0); // last remaining, no next one left else newCurrent = model()->index(end + 1, 0); // next remaining selectionModel()->select(newCurrent, QItemSelectionModel::SelectCurrent); } } } void ImageCategorizedView::layoutAboutToBeChanged() { d->ensureOneSelectedItem = selectionModel()->hasSelection(); // store some hints so that if all selected items were removed dont need to default to 0,0. if (d->ensureOneSelectedItem) { QItemSelection currentSelection = selectionModel()->selection(); QModelIndex current = currentIndex(); QModelIndex indexToAnchor; if (currentSelection.contains(current)) indexToAnchor = current; else if (!currentSelection.isEmpty()) indexToAnchor = currentSelection.first().topLeft(); if (indexToAnchor.isValid()) { d->hintAtSelectionRow = indexToAnchor.row(); d->hintAtSelectionIndex = model()->index(d->hintAtSelectionRow == model()->rowCount() ? d->hintAtSelectionRow : d->hintAtSelectionRow + 1, 0); } } } void ImageCategorizedView::layoutWasChanged() { // connected queued to layoutChanged() ensureSelectionAfterChanges(); } void ImageCategorizedView::userInteraction() { // as soon as the user did anything affecting selection, we don't interfere anymore d->ensureInitialSelectedItem = false; d->hintAtSelectionIndex = QModelIndex(); } void ImageCategorizedView::ensureSelectionAfterChanges() { if (d->ensureInitialSelectedItem && model()->rowCount()) { // Ensure the item (0,0) is selected, if the model was reset previously // and the user did not change the selection since reset. // Caveat: Item at (0,0) may have changed. bool hadInitial = d->ensureInitialSelectedItem; d->ensureInitialSelectedItem = false; d->ensureOneSelectedItem = false; QModelIndex index = model()->index(0,0); if (index.isValid()) { selectionModel()->select(index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Clear); setCurrentIndex(index); // we want ensureInitial set to false if and only if the selection // is done from any other place than the previous line (i.e., by user action) // Effect: we select whatever is the current index(0,0) if (hadInitial) d->ensureInitialSelectedItem = true; } } else if (d->ensureOneSelectedItem) { // ensure we have a selection if there was one before d->ensureOneSelectedItem = false; if (model()->rowCount() && selectionModel()->selection().isEmpty()) { QModelIndex index; if (d->hintAtSelectionIndex.isValid()) index = d->hintAtSelectionIndex; else if (d->hintAtSelectionRow != -1) index = model()->index(qMin(model()->rowCount(), d->hintAtSelectionRow), 0); else index = currentIndex(); if (!index.isValid()) index = model()->index(0,0); d->hintAtSelectionRow = -1; d->hintAtSelectionIndex = QModelIndex(); if (index.isValid()) { selectionModel()->select(index, QItemSelectionModel::SelectCurrent); setCurrentIndex(index); } } } } Album *ImageCategorizedView::albumAt(const QPoint& pos) { if (d->filterModel->imageSortSettings().categorizationMode == ImageSortSettings::CategoryByAlbum) { QModelIndex categoryIndex = indexForCategoryAt(pos); if (categoryIndex.isValid()) { int albumId = categoryIndex.data(ImageFilterModel::CategoryAlbumIdRole).toInt(); return AlbumManager::instance()->findPAlbum(albumId); } } return currentAlbum(); } /* //Remove when API changes are accepted for KCategorizedView QModelIndex ImageCategorizedView::indexForCategoryAt(const QPoint& pos) const { QModelIndex index = indexAt(pos); if (index.isValid()) return index; QRect viewportRect = viewport()->rect(); if (!viewportRect.contains(pos)) return QModelIndex(); // There is no indexesInRect() method. And no categoryRect(). We have to probe. // Assumption: we test at the same y pos, going right from the left edge; // then we go down in the middle of the first column until the bottom of the viewport is reached. const int horizontalStep = 10; const int rightEnd = qMin(gridSize().width() + 2*spacing() + 2*horizontalStep, viewportRect.width()); int y = pos.y(); for (int x=0; xdelegate->categoryDrawer()->maximumHeight() + 2*gridSize().height() + 4*spacing(), viewportRect.height()); const int x = (gridSize().width() + 2*spacing()) / 2; // middle of first column for (; yfilterModel->index(current.row() + 1, 0); if (next.isValid()) return next; else return current; break; } case MovePrevious: case MoveLeft: { QModelIndex previous = d->filterModel->index(current.row() - 1, 0); if (previous.isValid()) return previous; else return current; break; } default: break; } return KCategorizedView::moveCursor(cursorAction, modifiers); } void ImageCategorizedView::activated(const ImageInfo &) { // implemented in subclass } void ImageCategorizedView::showContextMenu(QContextMenuEvent *, const ImageInfo &) { // implemented in subclass } void ImageCategorizedView::showContextMenu(QContextMenuEvent *) { // implemented in subclass } void ImageCategorizedView::copy() { // implemented in subclass } void ImageCategorizedView::paste() { // implemented in subclass } void ImageCategorizedView::contextMenuEvent(QContextMenuEvent* event) { userInteraction(); QModelIndex index = indexAt(event->pos()); if (index.isValid()) { ImageInfo info = d->filterModel->imageInfo(index); showContextMenu(event, info); } else showContextMenu(event); } void ImageCategorizedView::mousePressEvent(QMouseEvent *event) { userInteraction(); const QModelIndex index = indexAt(event->pos()); // Clear selection on click on empty area. Standard behavior, but not done by QAbstractItemView for some reason. if (!index.isValid()) { Qt::KeyboardModifiers modifiers = event->modifiers(); const Qt::MouseButton button = event->button(); const bool rightButtonPressed = button & Qt::RightButton; const bool shiftKeyPressed = modifiers & Qt::ShiftModifier; const bool controlKeyPressed = modifiers & Qt::ControlModifier; if (!index.isValid() && !rightButtonPressed && !shiftKeyPressed && !controlKeyPressed) clearSelection(); } // store event for entered(), clicked(), activated() signal handlers d->currentMouseEvent = event; KCategorizedView::mousePressEvent(event); d->currentMouseEvent = 0; } void ImageCategorizedView::mouseReleaseEvent(QMouseEvent *event) { userInteraction(); d->currentMouseEvent = event; KCategorizedView::mouseReleaseEvent(event); d->currentMouseEvent = 0; } void ImageCategorizedView::mouseMoveEvent(QMouseEvent *event) { QModelIndex index = indexAt(event->pos()); QRect indexVisualRect; if (index.isValid()) { indexVisualRect = visualRect(index); if (KGlobalSettings::changeCursorOverIcon() && d->delegate->acceptsActivation(event->pos(), indexVisualRect, index)) { setCursor(Qt::PointingHandCursor); } else { unsetCursor(); } } else { unsetCursor(); } d->currentMouseEvent = event; KCategorizedView::mouseMoveEvent(event); d->currentMouseEvent = 0; d->delegate->mouseMoved(event, indexVisualRect, index); } void ImageCategorizedView::wheelEvent(QWheelEvent* event) { // KCategorizedView updates the single step at some occasions in a private methody horizontalScrollBar()->setSingleStep(d->delegate->gridSize().height() / 10); verticalScrollBar()->setSingleStep(d->delegate->gridSize().width() / 10); if (event->modifiers() & Qt::ControlModifier) { const int delta = event->delta(); if (delta > 0) emit zoomInStep(); else if (delta < 0) emit zoomOutStep(); event->accept(); } KCategorizedView::wheelEvent(event); } void ImageCategorizedView::keyPressEvent(QKeyEvent *event) { userInteraction(); if (event == QKeySequence::Copy) { copy(); event->accept(); return; } else if (event == QKeySequence::Paste) { paste(); event->accept(); return; } /* // from dolphincontroller.cpp const QItemSelectionModel* selModel = m_itemView->selectionModel(); const QModelIndex currentIndex = selModel->currentIndex(); const bool trigger = currentIndex.isValid() && ((event->key() == Qt::Key_Return) || (event->key() == Qt::Key_Enter)) && (selModel->selectedIndexes().count() > 0); if (trigger) { const QModelIndexList indexList = selModel->selectedIndexes(); foreach (const QModelIndex& index, indexList) { emit itemTriggered(itemForIndex(index)); } } */ KCategorizedView::keyPressEvent(event); emit keyPressed(event); } /* //Remove when API changes are accepted for KCategorizedView //Also remove code from delegate. connect(d->delegate, SIGNAL(waitingForThumbnail(const QModelIndex &)), this, SLOT(slotDelegateWaitsForThumbnail(const QModelIndex &))); bool modelIndexByRowLessThan(const QModelIndex& i1, const QModelIndex& i2) { return i1.row() < i2.row(); } void ImageCategorizedView::slotDelegateWaitsForThumbnail(const QModelIndex& index) { d->indexesToThumbnail << index; } void ImageCategorizedView::paintEvent(QPaintEvent *e) { // We want the thumbnails to be loaded in order. // We cannot easily know which indexes are repainted, so we have to listen // to our delegate telling us for which thumbnails he waits. // After that we reorder them. See slotDelegateWaitsForThumbnail(). d->indexesToThumbnail.clear(); KCategorizedView::paintEvent(e); if (!d->indexesToThumbnail.isEmpty()) { qSort(d->indexesToThumbnail.begin(), d->indexesToThumbnail.end(), modelIndexByRowLessThan); d->filterModel->prepareThumbnails(d->indexesToThumbnail); d->indexesToThumbnail.clear(); } } */ void ImageCategorizedView::paintEvent(QPaintEvent *e) { // We want the thumbnails to be loaded in order. QModelIndexList indexesToThumbnail = categorizedIndexesIn(viewport()->rect()); d->filterModel->prepareThumbnails(indexesToThumbnail); KCategorizedView::paintEvent(e); } void ImageCategorizedView::resizeEvent(QResizeEvent *e) { KCategorizedView::resizeEvent(e); updateDelegateSizes(); } bool ImageCategorizedView::viewportEvent(QEvent *event) { switch (event->type()) { case QEvent::FontChange: { updateDelegateSizes(); break; } case QEvent::ToolTip: { if (!d->showToolTip) return true; QHelpEvent *he = static_cast(event); const QModelIndex index = indexAt(he->pos()); if (!index.isValid()) break; QStyleOptionViewItem option = viewOptions(); option.rect = visualRect(index); option.state |= (index == currentIndex() ? QStyle::State_HasFocus : QStyle::State_None); QRect innerRect; if (d->delegate->acceptsToolTip(he->pos(), option.rect, index, &innerRect)) { if (!innerRect.isNull()) option.rect = innerRect; d->toolTip->show(he, option, index); } return true; } default: break; } return KCategorizedView::viewportEvent(event); } void ImageCategorizedView::startDrag(Qt::DropActions supportedActions) { QModelIndexList indexes = selectedIndexes(); if (indexes.count() > 0) { QMimeData *data = d->filterModel->mimeData(indexes); if (!data) return; QStyleOptionViewItem option = viewOptions(); option.rect = viewport()->rect(); QPixmap pixmap = d->delegate->pixmapForDrag(option, indexes); QDrag *drag = new QDrag(this); drag->setPixmap(pixmap); drag->setMimeData(data); drag->exec(supportedActions); } } void ImageCategorizedView::dragEnterEvent(QDragEnterEvent *e) { ImageModelDragDropHandler *handler = d->model->dragDropHandler(); if (handler && handler->acceptsMimeData(e->mimeData())) e->accept(); else e->ignore(); } void ImageCategorizedView::dragMoveEvent(QDragMoveEvent *e) { KCategorizedView::dragMoveEvent(e); ImageModelDragDropHandler *handler = d->model->dragDropHandler(); if (handler) { QModelIndex index = indexAt(e->pos()); Qt::DropAction action = handler->accepts(e, d->filterModel->mapToSource(index)); if (action == Qt::IgnoreAction) e->ignore(); else { e->setDropAction(action); e->accept(); } } } void ImageCategorizedView::dropEvent(QDropEvent *e) { KCategorizedView::dropEvent(e); ImageModelDragDropHandler *handler = d->model->dragDropHandler(); if (handler) { QModelIndex index = indexAt(e->pos()); if (handler->dropEvent(this, e, d->filterModel->mapToSource(index))) e->accept(); } } } // namespace Digikam Index: trunk/extragear/graphics/digikam/digikam/imagecategorizedview.h =================================================================== --- trunk/extragear/graphics/digikam/digikam/imagecategorizedview.h (revision 1028323) +++ trunk/extragear/graphics/digikam/digikam/imagecategorizedview.h (revision 1028324) @@ -1,211 +1,211 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2009-04-22 * Description : Qt item view for images * * Copyright (C) 2009 by Marcel Wiesweg * * 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, 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. * * ============================================================ */ #ifndef IMAGECATEGORIZEDVIEW_H #define IMAGECATEGORIZEDVIEW_H // Qt includes // KDE includes // Local includes #include "imageinfo.h" #include "kcategorizedview.h" #include "thumbnailsize.h" namespace Digikam { class Album; class ImageAlbumModel; class ImageAlbumFilterModel; class ImageDelegate; class ImageDelegateOverlay; class ImageCategorizedViewPriv; class ImageCategorizedView : public KCategorizedView { Q_OBJECT public: ImageCategorizedView(QWidget *parent = 0); ~ImageCategorizedView(); ImageAlbumModel *imageModel() const; ImageAlbumFilterModel *imageFilterModel() const; ImageDelegate *delegate() const; Album *currentAlbum() const; ImageInfo currentInfo() const; KUrl currentUrl() const; QList selectedImageInfos() const; QList selectedImageInfosCurrentFirst() const; KUrl::List selectedUrls() const; int numberOfSelectedIndexes() const; QList imageInfos() const; KUrl::List urls() const; /** Selects the index as current and scrolls to it */ void toFirstIndex(); void toLastIndex(); void toNextIndex(); void toPreviousIndex(); void toIndex(const KUrl& url); void toIndex(const QModelIndex& index); /** Returns the n-th info after the given one. * Specifically, return the previous info for nth = -1 * and the next info for n = 1. * Returns a null info if either startingPoint or the nth info are * not contained in the model */ ImageInfo nextInOrder(const ImageInfo &startingPoint, int nth); ImageInfo previousInfo(const ImageInfo &info) { return nextInOrder(info, -1); } ImageInfo nextInfo(const ImageInfo &info) { return nextInOrder(info, 1); } void invertSelection(); ThumbnailSize thumbnailSize() const; void setThumbnailSize(const ThumbnailSize& size); /** If the model is categorized by an album, returns the album of the category * that contains the position. * If this is not applicable, return the current album. May return 0. */ Album *albumAt(const QPoint& pos); /// Add and remove an overlay. It will as well be removed automatically when destroyed. void addOverlay(ImageDelegateOverlay *overlay); void removeOverlay(ImageDelegateOverlay *overlay); void setToolTipEnabled(bool enabled); bool isToolTipEnabled() const; void addSelectionOverlay(); public Q_SLOTS: void openAlbum(Album *album); void setThumbnailSize(int size); /** Scroll the view to the given item when it becomes available */ - void scrollToWhenAvailable(qlonglong imageId); + void setCurrentWhenAvailable(qlonglong imageId); /** Set as current item the item identified by its file url */ void setCurrentUrl(const KUrl& url); Q_SIGNALS: void currentChanged(const ImageInfo& info); /// Emitted when any selection change occurs. Any of the signals below will be emitted before. void selectionChanged(); /// Emitted when new items are selected. The parameter includes only the newly selected infos, /// there may be other already selected infos. void selected(const QList& newSelectedInfos); /// Emitted when items are deselected. There may be other selected infos left. /// This signal is not emitted when the model is reset; then only selectionCleared is emitted. void deselected(const QList& nowDeselectedInfos); /// Emitted when the selection is completely cleared. void selectionCleared(); void zoomOutStep(); void zoomInStep(); /** For overlays: Like the respective parent class signals, but with additional info. * Do not change the mouse events. */ void clicked(const QMouseEvent *e, const QModelIndex& index); void entered(const QMouseEvent *e, const QModelIndex& index); /** Remember you may want to check if the event is accepted or ignored. * This signal is emitted after being handled by this widget. * You can accept it if ignored. */ void keyPressed(QKeyEvent *e); protected Q_SLOTS: virtual void slotThemeChanged(); virtual void slotSetupChanged(); void slotImageInfosAdded(); void slotActivated(const QModelIndex& index); void slotClicked(const QModelIndex& index); void slotEntered(const QModelIndex& index); void layoutAboutToBeChanged(); void layoutWasChanged(); protected: /// Reimplement these in a subclass virtual void activated(const ImageInfo& info); virtual void showContextMenu(QContextMenuEvent *event, const ImageInfo& info); virtual void showContextMenu(QContextMenuEvent *event); virtual void copy(); virtual void paste(); /** Returns an index that is representative for the category at position pos */ QModelIndex indexForCategoryAt(const QPoint& pos) const; // reimplemented from parent class void contextMenuEvent(QContextMenuEvent* event); void currentChanged(const QModelIndex& index, const QModelIndex& previous); void dragEnterEvent(QDragEnterEvent *event); void dragMoveEvent(QDragMoveEvent *e); void dropEvent(QDropEvent *e); void keyPressEvent(QKeyEvent *event); void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers); void paintEvent(QPaintEvent *e); void resizeEvent(QResizeEvent *e); void reset(); void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); void rowsInserted(const QModelIndex &parent, int start, int end); void selectionChanged(const QItemSelection &, const QItemSelection &); void startDrag(Qt::DropActions supportedActions); bool viewportEvent(QEvent *event); void wheelEvent(QWheelEvent* event); private Q_SLOTS: void slotGridSizeChanged(const QSize &); void slotFileChanged(const QString& filePath); private: void updateDelegateSizes(); void scrollToStoredItem(); void userInteraction(); void ensureSelectionAfterChanges(); private: ImageCategorizedViewPriv* const d; }; } // namespace Digikam #endif /* IMAGECATEGORIZEDVIEW_H */ Index: trunk/extragear/graphics/digikam/NEWS =================================================================== --- trunk/extragear/graphics/digikam/NEWS (revision 1028323) +++ trunk/extragear/graphics/digikam/NEWS (revision 1028324) @@ -1,386 +1,387 @@ ********************************************************************************************************* digiKam 1.0.0-beta5 - Release date: 2009-09-xx NEW FEATURES: General : Metadata fields can be used for renaming in BQM and CameraUI. ImageEditor : New menu option to switch image color space quickly. ImageEditor : Black and White converter: add standard Blue and Yellow-Green color filters. BUGFIXES FROM KDE BUGZILLA (alias B.K.O | http://bugs.kde.org): 001 ==> 193482 : XMP/IPTC fields in Batch Rename tool. 002 ==> 183435 : No more file manager at media:/camera. 003 ==> 200758 : digiKam, dolphin, dc is not is perepherals list. 004 ==> 206071 : Not reading image properties. 005 ==> 191113 : digiKam doesn't recognize images with colorspace adobergb. 006 ==> 206487 : Unsharp mask algorithm in batch processing should equal the one in kipi. 007 ==> 206570 : Crashed when scrolling through thumbnails in edit mode. 008 ==> 206712 : Raw Import Tool: RGB (linear) provides gamma corrected output and should be named as such. 009 ==> 206857 : Unclear English in sentence. 010 ==> 149485 : Advanced image resize for the digikam editor. 011 ==> 206426 : Default ICC profile locations reads the same directory twice. 012 ==> 203176 : Deleting 2 files still shows one afterwards. 013 ==> 205059 : The default path for image library is not localizable. 014 ==> 204084 : Showfoto claims that there are no images in directory that contains symlinks to images. 015 ==> 197817 : digiKam should utilize _icc_profile X property. 016 ==> 205756 : Copy and paste fails silently when pasting file back into the same folder. 017 ==> 207239 : When pressing Enter thumbnails should be enlarged, also after changing from Tags to Collection or similar. 018 ==> 200830 : 100 % CPU usage without obvious reason. 019 ==> 204480 : Unable to access albums on drives other than C:. 020 ==> 154463 : Autorename while transferring pictures from cam to PC adds lots of '0'. 021 ==> 207882 : Manual: RAW decoder settings: 16 bit not clearly explained. 022 ==> 208004 : Geolocation tool needs higher zoom levels. 023 ==> 207293 : when showing whole collection status bar filters don't work. 024 ==> 206670 : after deleting an image the image before the deleted image is displayed/selected instead of the image after the deleted one. 025 ==> 208160 : After edition image has different colors in QT nad GTK+ applications. 026 ==> 207332 : editor works on the wrong image if a new one was chosen while processing. 027 ==> 206666 : thumbnail borders are drawn inside instead of outside the images thus hiding parts of the image 028 ==> 195050 : Color management doesn't work in thumbnails and view mode. 029 ==> 200357 : digikam, exif rotation, thumbnail not rotated. 030 ==> 203485 : consider using KGlobalSettings::picturesPath() instead of KGlobalSettings::documentPath(). -031 ==> +031 ==> 204053 : Remember cursor position in album view after refresh / sync. +032 ==> ********************************************************************************************************* digiKam 1.0.0-beta4 - Release date: 2009-08-30 NEW FEATURES: General : Add OpenStreetMap support in Geolocation panels. General : Showfoto, Editor, Preview, LightTable: Thumbbar is now dockable everywhere. General : Complete re-write of Color Management code. Add support of thumbs and preview CM. BUGFIXES FROM KDE BUGZILLA (alias B.K.O | http://bugs.kde.org): 001 ==> 192534 : Rename a folder, then rename a photo and you get an error. 002 ==> 193522 : First run (with existing v3 database) fails, "No album library path...". 003 ==> 147885 : Update metadata doesn't work correctly for creation date. 004 ==> 196462 : IconView (Qt4 Model/view based): Navigation broken after delete. 005 ==> 195871 : Image tool tip does not show all tags if too long. 006 ==> 201560 : Crash at start up when scanning images. 007 ==> 197508 : Geo-localisation integration missing, but marble is installed. 008 ==> 201640 : Opportunity to compile digiKam without Nepomuk service. 009 ==> 201692 : No thumbnails in album view. 010 ==> 185098 : digiKam craches sometimes on raw files selection. 011 ==> 201624 : Showfoto => color-management => input-profile => search => crash. 012 ==> 151712 : Adjust Exif orientation tag - wrong permission interpretation. 013 ==> 171983 : Enable display of Openstreetmap maps in the Map Widget. 014 ==> 155097 : Performance problems with recursive view and filtering. 015 ==> 200392 : Slideshow displays "Headline" field as "image caption" and has no way to display "Caption" field. 016 ==> 201302 : Crash due to memory access problem on Mac OS X. 017 ==> 133094 : Exif-changes by external prog has no affect inside digiKam. 018 ==> 201746 : Invalid TIFF output in Editor and Batch queue manager. 019 ==> 196692 : Red and blue channels in images are reversed when saving. 020 ==> 202332 : View mode: Zooming using Ctrl+Scroll is broken. 021 ==> 197254 : digikam crash at startup. 022 ==> 202779 : When pressing 'enter', thumbnails should be enlarged, also when a collection is selected. 023 ==> 203574 : Showfoto crashes when opening jpeg file. 024 ==> 203498 : No drop-down menu for export. 025 ==> 203589 : Crash in the noise reduction plugin when 'Threshold' equals zero. 026 ==> 198006 : digiKam crash after assistant finished. 027 ==> 203083 : Crash starting digikam (after kde 4.3 upgrade). 028 ==> 202954 : digiKam crashes on start while scaning picture directory. 029 ==> 203031 : Album list doesn't show pictures even after tons of new pictures were imported. 030 ==> 201810 : Segfault moving files to trash. 031 ==> 193763 : digiKam doesn'd display any photos. 032 ==> 202532 : Wrong rename sequence when downloading. 033 ==> 163161 : Adding ICC profiles confuses digiKam. 034 ==> 148151 : Problem with icc profle Color Management in digiKam with feisty fawn. 035 ==> 162944 : Cms/editor: converting colorspace doesn't work. 036 ==> 165650 : digiKam appears to add a color profile for printing? 037 ==> 182272 : Color profile and white balance. 038 ==> 204656 : Import: "Device Information": linebreaks not HTMLified in KTextEdits [patch]. 039 ==> 189073 : Does not save embedded color profile. 040 ==> 195144 : Editor shows wrong colors when loading image without color profile and color management is on. 041 ==> 152521 : digiKam Edit / Showfoto: Use Color Managed View setting in config page is ignored. 042 ==> 163160 : Remember color management status between sessions. 043 ==> 204797 : Click lock icon crash digiKam. 044 ==> 204871 : digiKam crash when rating a picture on the lighttable. 045 ==> 203594 : Option to display a vertical thumb bar. 046 ==> 195050 : Color management doesn't work in thumbnails and view mode. 047 ==> 179802 : After raw import image not shown in editor. 048 ==> 172196 : Color managed view is inaccurate. 049 ==> 197537 : Program crashes when starting import from usb camera (canon 450d). 050 ==> 194950 : digiKam endlessly spewing text to stderr. ********************************************************************************************************* digiKam 1.0.0-beta3 - Release date: 2009-07-24 NEW FEATURES: General : Exif, Makernotes, Iptc, and Xmp metadata tags filtering can be customized in setup config dialog. General : Metadata Template: add support of Contact, Location, and Subjects IPTC information. General : Add support of Author properties to multi-language Captions. User can set an author name for each caption value. ImageEditor : Close tools by pressing ESC. BUGFIXES FROM KDE BUGZILLA (alias B.K.O | http://bugs.kde.org): 001 ==> 199168 : Tags in db but not in IPTC. 002 ==> 184445 : Deleting multiple files in folder view gives me multiple errors. 003 ==> 151749 : External URLs from pictures for related information. 004 ==> 192701 : Application: digiKam (digiKam), signal SIGSEGV --Crash under Gnome (Ubuntu 9.04). 005 ==> 199394 : Request: "regenerate folder thumbnails" menu item. 006 ==> 199420 : Duplication of Albums when naming them using upper case letters. 007 ==> 192535 : digiKam collections on removable media are treated as local collections. 008 ==> 199497 : Open camera rejected with: "Fehler beim Auflisten der Dateien in /store_00010001/DCIM/100CANON.". 009 ==> 199602 : Exif rotation not interpreted the same way in different tools. 010 ==> 191522 : Crash on use default action "Download Photos with digiKam". 011 ==> 196463 : Crash on device action Download Photos with Digikam. 012 ==> 199617 : When clicking on "My Tags", the view switches automatically after 2 seconds. 013 ==> 199076 : Sudden crash of digiKam during work. 014 ==> 195121 : digiKam crashes on view image (exiv2). 015 ==> 142566 : Update metadata doesn't work correctly for creation date. 016 ==> 199251 : digiKam crashes when setting exif orientation tag. 017 ==> 199482 : Caption can't be canged. 018 ==> 174586 : Loading video from camera consumes ll memory. 019 ==> 199667 : Make writing of metadata to picture enabled by default. 020 ==> 199981 : XMP synchronization of digiKam namespace occurs for second tag. 021 ==> 199967 : Creation date newer than last modified date. 022 ==> 200190 : Tag filters: unlike older versions AND-condition doesn't match anymore. 023 ==> 193616 : Location not shown digiKam right sidebar after geolocating in external program. 024 ==> 189156 : digikam crashes on importing directories with some (cyrillic?) file names. 025 ==> 191963 : Calender sort by wrong dates on images without properties. 026 ==> 189072 : Right click popup menu. 027 ==> 200223 : Default language of spellchecker is ignored. 028 ==> 126086 : Besides the basic and full exif info I would like a page with selectable fields. 029 ==> 200637 : Too small fonts in collections setup page. 030 ==> 135476 : Support for multiple comment authors. 031 ==> 200246 : digiKam does not recognize GPS EXIF information. 032 ==> 188999 : XMP tags not imported properly. 033 ==> 199148 : Iptc ascii vs unicode pb. 034 ==> 169685 : Tags lost on copy via context menu. 035 ==> 200162 : EXIF tags not updated if digiKam tag is renamed. 036 ==> 200854 : Option to clear light table on close. 037 ==> 200805 : List of supported file types can not be edited, just extended. 038 ==> 200187 : Save and restore selected filter tags. 039 ==> 196999 : Calendar is ignoring selection of date/week but respecting month. 040 ==> 190795 : USB PTP Class does not work anymore with the KDE4 version. 041 ==> 188905 : Edit view goes 100% instead of fit window. 042 ==> 187810 : In import window images are sorted in reverse order but folders are not. 043 ==> 199619 : Deleting image and switching to next fastly seems to confuse album list. 044 ==> 121804 : Image overwritten with blank file when importing into same folder 045 ==> 200783 : digiKam crashes while loading JPEG images. 046 ==> 200979 : Trust 715 LCD camera no driver. 047 ==> 179902 : Picture numbering fails if pics taken at more than 1 image per second. 048 ==> 184541 : Resize error when sharpening in image editor. 049 ==> 134389 : Sort images by date - even when spanning albums. 050 ==> 195109 : Integrate lighttable in digiKam. 051 ==> 199373 : LightTable Crash with Image Drag and Drop. 052 ==> 192563 : Zooming into the earth map buggy. ********************************************************************************************************* digiKam 1.0.0-beta2 - Release date: 2009-07-05 NEW FEATURES: General : Added support of Metadata Template to set easily image copyright. General : Added support of LightRoom keywords path for interoperability purpose. General : digiKam use a new database to cache thumbnails instead ~./thumbnails. File format used to store image is PGF (http://www.libpgf.org). PGF is a wavelets based image compression format and give space optimizations. General : Added Multi-languages support to Caption and Tags right side-bar. AlbumGui : Find Duplicates search can be limited to an album and tag range. BUGFIXES FROM KDE BUGZILLA (alias B.K.O | http://bugs.kde.org): 001 ==> 178189 : Do not create preview automatically for large pictures. 002 ==> 172807 : Warning: JPEG format error, rc = 5. 003 ==> 188936 : Not finding all pictures on camera. 004 ==> 195812 : Crash when rotating image in album overlay (rightest rotate icon). 005 ==> 094562 : Renaming an album recreates all thumbnails. 006 ==> 193124 : Import image should allow both direct and reverse ordering. 007 ==> 188051 : Sort order of filenames in camera - no way to set or choose. 008 ==> 183435 : No more file manager at media:/camera. 009 ==> 189979 : All displays of the same caption don't show the same text when it contains "éèà". 010 ==> 195902 : digiKam crashes on first startup if album folder is not empty. 011 ==> 154606 : Changing the date for multiple pictures simultaneously changes all of the times too. 012 ==> 143932 : UTF-8 displayed with wrong encoding when restoring photo to digiKam. 013 ==> 179227 : Generation of XMP tags crashes the application. 014 ==> 188988 : digiKam crash while scanning images. 015 ==> 192085 : digiKam suddenly crashed when managing pictures. 016 ==> 196465 : Missing reset button for curve in monochrome conversion tool. 017 ==> 196329 : Renaming album causes problems (until re-opening). 018 ==> 191288 : CRC error in chunk zTXt. 019 ==> 189982 : digiKam crashes during start-up. 020 ==> 098462 : Support for comments in different languages. 021 ==> 159158 : Tags moved in tree are duplicated in the IPTC metadata. 022 ==> 186308 : Moving tags in hierarchy not reflected in XMP metadata "TagsList". 023 ==> 141912 : Sync Metadata Batch Tool does not reflect changes in tags properly. 024 ==> 175321 : Synchronize tags to IPTC keywords adds instead of copying. 025 ==> 195663 : Crash while adding new tag. 026 ==> 195735 : digiKam-svn fails to compile on Mac OS X. 027 ==> 196768 : With 4.2.90 digiKam always crashes on startup - worked fine with 4.2.3. 028 ==> 190719 : Compiling digikam-0.10.0 on Gentoo fails. 029 ==> 197129 : Hierarchical setting of keywords. 030 ==> 195079 : digiKam albums appear empty. 031 ==> 195494 : Deleting and canceling a picture with the keyboard still delete the picture. 032 ==> 195975 : Images are not visible. 033 ==> 196462 : IconView (Qt4 Model/view based): Navigation broken after delete. 034 ==> 192055 : Typo digiKam tip of the day. 035 ==> 164026 : Wish: use embedded thumbs within jpegs to speedup album display. 036 ==> 197152 : Startup wizard has problems creating directories. 037 ==> 196726 : digiKam crashes while creating thumbnails. 038 ==> 182852 : Timeline: click area small an unintuitive. 039 ==> 173899 : Timeline does not show any photos. 040 ==> 196994 : digiKam 1.0.0-0.1.beta1.f11 from kde-redhat crash on startup. 041 ==> 180076 : Moving a big folder to another subfolder folder does ... nothing. 042 ==> 191557 : Previous and next image is showing weird results. 043 ==> 197360 : In the "edit captions" sidebar moving a tag to white space crashes digiKam. 044 ==> 195799 : digiKam takes 100% CPU when exiting and finally crashes. 045 ==> 152219 : Impossible to clear comments in metadata. 046 ==> 197198 : Libpng not detected during configure. 047 ==> 152199 : Deleting tags can leave orphaned IPTC keywords inside files. 048 ==> 197285 : Understand keyword hierarchies with different delimiters. 049 ==> 197640 : Add the "New folder" Option while dragging items to folders. 050 ==> 197744 : Lists of languages miss en-US. 051 ==> 197622 : digiKam crashes on exit. 052 ==> 197808 : Bad images sort order when starting digiKam. 053 ==> 197641 : Can't delete Exif x-default caption once set. 054 ==> 196437 : digiKam crashes at startup. 055 ==> 197868 : digiKam crashes on startup (digikam-0.10.0-2/x86_64/Archlinux). 056 ==> 196686 : IconView (Qt4 Model/View based) : Select multiple images with CTRL + Mouse not working anymore in 1.0.0-beta1. 057 ==> 197961 : CameraUI freezes digiKam when starting to download images from camera. 058 ==> 197445 : digiKam freezes while attempting to import images from canon Powershot a540. 059 ==> 198067 : digiKam does not show any pictures. 060 ==> 186638 : Canon 450D import issues. 061 ==> 195809 : Radio buttons in "Search Group" "Options" in "Advanced search" dialog do not show selection status. 062 ==> 177686 : Menu text is invisible. 063 ==> 198509 : Tagging by drag and drop not possible anymore. 064 ==> 198531 : Compilation error in libpgf [PATCH]. 065 ==> 198530 : Compilation error in imagecategorizedview.cpp. 066 ==> 139361 : Templates for meta data. 067 ==> 175923 : digiKam uses wrong album root path/wrong disk uuid. 068 ==> 185065 : Image editor loads new image without being asked to. 069 ==> 188017 : Video colors inverted after digiKam started. 070 ==> 194950 : digiKam endlessly spewing text to stderr. 071 ==> 189080 : Comments not saved with digiKam 0.10.0 on KDE 4.2.2. 072 ==> 198868 : Pictures are not displayed in the main view i just can see them in the batch menu. ********************************************************************************************************* digiKam 1.0.0-beta1 - Release date: 2009-06-07 NEW FEATURES: General : Add new Batch Queue Manager (http://www.digikam.org/node/427). General : New tool bar animation banner. General : Fix compilation under MSVC 9. General : New first run assistant (http://www.digikam.org/node/442). General : New dialog to show Database statistics. General : Add support of wavelets image file format PGF (http://www.libpgf.org). AlbumGui : Icon view is now based on pure Qt4 model/view. AlbumGui : New overlay button over icon view items to perform lossless rotations. ImageEditor : New Liquid Rescale tool (http://www.digikam.org/node/439). CameraGUI : New history of camera actions processed. BUGFIXES FROM KDE BUGZILLA (alias B.K.O | http://bugs.kde.org): 001 ==> 091742 : Batch process auto levels. 002 ==> 149361 : Not all edit actions are available as batch commands (for example auto-levels and gamma correction). 003 ==> 187523 : digiKam crashes on startup (undefined symbol). 004 ==> 187569 : Crash on star removing when filtering by stars. 005 ==> 186549 : digiKam crashes when hovering the bottom part of its. 006 ==> 187641 : Error while loading shared libraries: libkdcraw.so.5. 007 ==> 187429 : Crash on Launch after disable KIPI plugins rotate. 008 ==> 187937 : Writing tags to files doesn't update modification timestamp. 009 ==> 184687 : Crash after deleting an empty album. 010 ==> 186766 : Crash after finish resize and rename of images in folder. 011 ==> 184953 : Zooming and panning in slideshow / without toolbars. 012 ==> 187508 : Spontaneous crash whilst doing nothing in particular. 013 ==> 188235 : Assigning a color profile to TIFF images does not work anymore with 0.10.0. 014 ==> 187748 : Install application icons to right path for non-KDE desktops. 015 ==> 186255 : digiKam crashes when switching collection database. 016 ==> 178292 : AspectRatioCrop is slow and jumps around in first second. 017 ==> 181892 : AspectRatioCrop: some properties should be disabled. 018 ==> 188573 : RW2 converter broken for low light images. 019 ==> 188642 : GPS data in Digikam shows the wrong places on the map. 020 ==> 188907 : Album view should display subfolders, like tag view does. 021 ==> 183038 : "Select All" action interrupts other widgets. 022 ==> 189022 : Better guessing of proportions with 'inverse transformation' option. 023 ==> 189286 : EXIF info lost while converting from NEF to TIFF. 024 ==> 189336 : Preview of RAW look different than actual image. 025 ==> 189413 : Images without GPS-data are shown on the equator in the geolocation-view. 026 ==> 184954 : Unable to delete items from camera - canon sx10is. 027 ==> 189168 : You do not have write access to your home directory base path. 028 ==> 185617 : Images are invalid / not found when an album is moved. 029 ==> 187265 : Advanced search crashes if a selected album has been deleted. 030 ==> 185177 : Searches are not updated when changes are made to the resulting image set. 031 ==> 189542 : Crash on opening download dialog. 032 ==> 114225 : Free rotation using an horizontal line. 033 ==> 189843 : Crash on Ubuntu jaunty beta. 034 ==> 167836 : Image preview is too large. 035 ==> 189250 : Editing a canon camera jpeg adds broken sRGB profile. 036 ==> 187733 : Cannot turn off sidebar after Infrared filter usage? 037 ==> 188755 : Strange behavior on selection. 038 ==> 185884 : Empty view after clicking the left thumbnail image in Image Editor filter view. 039 ==> 188062 : Synchronize Images with Database does not save Copyright, Credit, Source, By-line, By-line Title in IPTC. 040 ==> 186823 : Several bugs in lens defect auto-correction plugin. 041 ==> 190612 : digiKam and showFoto crash. 042 ==> 191092 : No images shown in digiKam albums. 043 ==> 191203 : digiKam crashed on first load, after being installed on Ubuntu 9.04. 044 ==> 151321 : Remaining space incorrectly calculated when using symlinks (import from camera). 045 ==> 189742 : Thumbnails not saved between sessions. 046 ==> 180507 : Crash when dragging picture to another app with kwin_composite enabled. 047 ==> 190296 : Can not save images on Windows. 048 ==> 141240 : Camera download: file rename with regexps. 049 ==> 181951 : digiKam crashes (SIGABRT) during the importing of pictures from Kodak V530 camera. 050 ==> 166392 : File-Renaming: custom sequence-number doesn't work. 051 ==> 182332 : Can't stop generating of thumbnails when import from a card reader. 052 ==> 152382 : Unable to view photo. 053 ==> 161744 : Filenames are lower case when imported via sd card reader, upper case when imported via usb cable directly from camera. 054 ==> 187560 : IPTC data for author are missing while downloading images. 055 ==> 192294 : digiKam crash when i try to import photos from my card reader. 056 ==> 192413 : Missing items from right-click search menu. 057 ==> 131551 : Camera port info deleted when editing camera title. 058 ==> 181726 : digiKam collect video, music when I connect USB key. 059 ==> 154626 : Autodetect starting number for "appending numbers" when downloading images. 060 ==> 188316 : Missing NEF files when importing from USB disk. 061 ==> 193163 : digiKam ignores settings on the rating stars. 062 ==> 189168 : You do not have write access to your home directory base path. 063 ==> 193226 : Data loss on downloading photos from camera. 064 ==> 189460 : digiKam crash when goelocating image in the marble tab. 065 ==> 186046 : Crash after calling settings. 066 ==> 193348 : Can't build digiKam on kde 4.2.3. 067 ==> 150072 : Download with digiKam doesn't work with the first start of digiKam. 068 ==> 193738 : Have the image editor status bar show the current color depth. 069 ==> 191678 : Exif rotation for Pentax Pef not working. 070 ==> 146455 : Image rotation and auto-rotate don't work. 071 ==> 152877 : Thumbnails: URI does not follow Thumbnail Managing Standard. 072 ==> 140615 : Pre-Creating of image thumbnails in whole digiKam/all subfolders. 073 ==> 193967 : VERY fast loading of thumbnails [PATCH]. 074 ==> 191492 : digiKam hangs on startup "reading database". 075 ==> 171950 : Lost pictures after 'download/delete all' when target dir had same file names. 076 ==> 191774 : digiKam download sorting slow, and wrong with multiple folders. 077 ==> 191842 : digiKam download forgets to download some pictures (multiple big folders). 078 ==> 187902 : Status bar gives wrong picture filename and position in list after "Save As". 079 ==> 193894 : Pop up "Copy Finished!" dialogue when done downloading from camera. 080 ==> 193870 : digiKam freezes after second exif rotation on same file. 081 ==> 194342 : What is the right rename pattern to get names like 2009.02.18_09h56m30s? 082 ==> 194177 : digiKam crashes always on startup and causes signal 11 (SIGSEGSV) - app not useable. 083 ==> 169213 : digiKam should not enter new album after creating it. 084 ==> 191634 : Statistics of the database, and all pictures? 085 ==> 193228 : Experimental option "write metadata to RAW files" corrupts Nikon NEFs. 086 ==> 194116 : digiKam crashed for no obvious reason. 087 ==> 179766 : Auto crop does not fully remove black corners created by free rotation. 088 ==> 134308 : Add arrow buttons on thumbnail to perform lossless rotation. 089 ==> 194804 : Tag, rate, rotate and delete via slideshow. 090 ==> 192425 : Star rating setting under thumbnails is a nuisance. 091 ==> 194330 : digiKam crashed when deleting image. 092 ==> 188959 : On first use, digiKam should not scan for images without user confirmation. 093 ==> 195202 : Thumbnail rename fails (cross-device link) and so cache doesn't work. 094 ==> 161749 : Raw Converter needs more options. 095 ==> 150598 : File rename during image upload fails silently. 096 ==> 161865 : Image not placed in New Tag category. 097 ==> 136897 : THM files are not uploaded. 098 ==> 195494 : Deleting and cancelling a picture with the keyboard still delete the picture. 099 ==> 120994 : Print preview generates HUGE postscript files. 100 ==> 191633 : Rename a folder, press F5 and see thumbnails go away. 101 ==> 195565 : Loading next image while in curves tool does not confirm and loads nothing. 102 ==> 189046 : digiKam crashes finding duplicates in fingerprints. 103 ==> 185726 : SIGSERV 11 by choosing an image for fullscreen. 104 ==> 193616 : Location not shown digiKam right sidebar after geolocating in external program.