diff --git a/core/app/DigikamGuiTarget.cmake b/core/app/DigikamGuiTarget.cmake index 49849a638b..d98c13e5a9 100644 --- a/core/app/DigikamGuiTarget.cmake +++ b/core/app/DigikamGuiTarget.cmake @@ -1,243 +1,243 @@ # # Copyright (c) 2010-2020 by Gilles Caulier, # Copyright (c) 2015 by Veaceslav Munteanu, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # digiKam GUI shared library if(ENABLE_DBUS) qt5_add_dbus_adaptor(digikamadaptor_SRCS main/org.kde.digikam.xml main/digikamapp.h Digikam::DigikamApp) endif() set(libdigikamgui_SRCS main/digikamapp.cpp main/digikamapp_solid.cpp main/digikamapp_camera.cpp main/digikamapp_import.cpp main/digikamapp_config.cpp main/digikamapp_tools.cpp main/digikamapp_setup.cpp date/dpopupframe.cpp date/ddateedit.cpp date/ddatetable.cpp date/ddatetable_p.cpp date/ddatepicker.cpp date/ddatepicker_p.cpp date/ddatetimeedit.cpp date/ddatepickerpopup.cpp date/datefolderview.cpp date/monthwidget.cpp date/timelinewidget.cpp dragdrop/importdragdrop.cpp dragdrop/albumdragdrop.cpp dragdrop/ddragobjects.cpp dragdrop/itemdragdrop.cpp dragdrop/tagdragdrop.cpp filters/filtersidebarwidget.cpp filters/tagfilterview.cpp items/delegate/digikamitemdelegate.cpp items/delegate/itemdelegate.cpp items/delegate/itemfacedelegate.cpp items/views/digikamitemview.cpp items/views/digikamitemview_p.cpp items/views/itemcategorizedview.cpp items/thumbbar/itemthumbnailbar.cpp items/thumbbar/itemthumbnaildelegate.cpp items/overlays/assignnameoverlay.cpp items/overlays/facerejectionoverlay.cpp items/overlays/groupindicatoroverlay.cpp items/overlays/itemfullscreenoverlay.cpp items/overlays/itemratingoverlay.cpp items/overlays/itemrotationoverlay.cpp items/overlays/itemcoordinatesoverlay.cpp items/overlays/itemselectionoverlay.cpp items/utils/itemviewutilities.cpp items/utils/tooltipfiller.cpp items/utils/contextmenuhelper.cpp items/utils/groupingviewimplementation.cpp items/utils/itemcategorydrawer.cpp utils/digikam_debug.cpp views/tableview/tableview.cpp views/tableview/tableview_treeview.cpp views/tableview/tableview_treeview_delegate.cpp views/tableview/tableview_column_configuration_dialog.cpp views/tableview/tableview_model.cpp views/tableview/tableview_columns.cpp views/tableview/tableview_column_audiovideo.cpp views/tableview/tableview_column_file.cpp views/tableview/tableview_column_geo.cpp views/tableview/tableview_column_digikam.cpp views/tableview/tableview_column_item.cpp views/tableview/tableview_column_photo.cpp views/tableview/tableview_column_thumbnail.cpp views/tableview/tableview_columnfactory.cpp views/tableview/tableview_selection_model_syncer.cpp views/stack/welcomepageview.cpp views/stack/itemiconview.cpp views/stack/trashview.cpp views/stack/stackedview.cpp views/preview/itempreviewcanvas.cpp views/preview/itempreviewview.cpp views/sidebar/leftsidebarwidgets.cpp views/sidebar/sidebarwidget.cpp views/utils/dmodelfactory.cpp views/utils/slideshowbuilder.cpp views/utils/componentsinfodlg.cpp ${digikamadaptor_SRCS} ) if(${Marble_FOUND}) set(libdigikamgui_SRCS ${libdigikamgui_SRCS} views/stack/mapwidgetview.cpp ) endif() add_library(digikamgui_src OBJECT ${libdigikamgui_SRCS} ) ######################### digiKam GUI objects ############################ set(DIGIKAM_OBJECTS $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) if(${Marble_FOUND}) set(DIGIKAM_OBJECTS ${DIGIKAM_OBJECTS} $ $ ) endif() #################### Digikam GUI shared Lib ################################ add_library(digikamgui SHARED ${DIGIKAM_OBJECTS} ) set_target_properties(digikamgui PROPERTIES VERSION ${DIGIKAM_VERSION_SHORT} SOVERSION ${DIGIKAM_VERSION_SHORT}) if(WIN32) set_target_properties(digikamgui PROPERTIES COMPILE_FLAGS -DJPEG_STATIC) endif() target_link_libraries(digikamgui PRIVATE - digikamdatabase digikamcore + digikamdatabase Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Sql Qt5::PrintSupport KF5::XmlGui KF5::Solid KF5::ConfigCore KF5::ConfigGui KF5::Service KF5::WindowSystem KF5::I18n ${OpenCV_LIBRARIES} ) if(ENABLE_QWEBENGINE) target_link_libraries(digikamgui PRIVATE Qt5::WebEngineWidgets) else() target_link_libraries(digikamgui PRIVATE Qt5::WebKitWidgets) endif() if(ENABLE_DBUS) target_link_libraries(digikamgui PRIVATE Qt5::DBus) endif() if(KF5IconThemes_FOUND) target_link_libraries(digikamgui PRIVATE KF5::IconThemes) endif() if(KF5KIO_FOUND) target_link_libraries(digikamgui PRIVATE KF5::KIOWidgets) endif() if(${Marble_FOUND}) target_link_libraries(digikamgui PRIVATE ${MARBLE_LIBRARIES}) endif() if(APPLE) target_link_libraries(digikamgui PRIVATE /System/Library/Frameworks/AppKit.framework) endif() if(NOT WIN32) # To link under Solaris (see bug #274484) target_link_libraries(digikamgui PRIVATE ${MATH_LIBRARY}) endif() if(CMAKE_SYSTEM_NAME STREQUAL FreeBSD) target_link_libraries(digikamcore PRIVATE ${KVM_LIBRARY}) endif() if(Gphoto2_FOUND) # See bug #258931: libgphoto2 library must be the last arg for linker. # See bug #268267 : digiKam need to be linked to libusb to prevent crash # at gphoto2 init if opencv is linked with libdc1394. Libusb linking rules are # add to gphoto2 linking rules by Gphoto2 cmake detection script. target_link_libraries(digikamgui PRIVATE ${GPHOTO2_LIBRARIES}) endif() # --- Install Rules --- install(TARGETS digikamgui EXPORT DigikamGuiConfig ${INSTALL_TARGETS_DEFAULT_ARGS}) install(EXPORT DigikamGuiConfig DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DigikamGui" NAMESPACE Digikam::) write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/DigikamGuiConfigVersion.cmake VERSION ${DIGIKAM_VERSION_SHORT} COMPATIBILITY SameMajorVersion) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/DigikamGuiConfigVersion.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DigikamGui") diff --git a/core/app/views/sidebar/leftsidebarwidgets.cpp b/core/app/views/sidebar/leftsidebarwidgets.cpp index b2830aa3c5..7a19a457ec 100644 --- a/core/app/views/sidebar/leftsidebarwidgets.cpp +++ b/core/app/views/sidebar/leftsidebarwidgets.cpp @@ -1,1581 +1,1582 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2000-12-05 * Description : left sidebar widgets * * Copyright (C) 2009-2010 by Johannes Wienke * Copyright (C) 2010-2020 by Gilles Caulier * Copyright (C) 2012 by Andi Clemens * Copyright (C) 2014 by Mohamed_Anwer + * Copyright (C) 2010 by Aditya Bhatt * * 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 "leftsidebarwidgets.h" // Qt includes #include #include #include #include #include #include #include #include #include #include #include #include #include // KDE includes #include #include // Local includes #include "digikam_debug.h" #include "albummanager.h" #include "albummodificationhelper.h" #include "albumselectiontreeview.h" #include "applicationsettings.h" #include "datefolderview.h" #include "editablesearchtreeview.h" #include "fuzzysearchview.h" #include "searchfolderview.h" #include "searchtabheader.h" #include "searchtextbar.h" #include "searchtreeview.h" #include "coredbsearchxml.h" #include "tagfolderview.h" #include "timelinewidget.h" #include "facescanwidget.h" #include "facesdetector.h" #include "tagsmanager.h" #include "labelstreeview.h" #include "coredb.h" #include "dexpanderbox.h" #include "dnotificationwidget.h" namespace Digikam { class Q_DECL_HIDDEN AlbumFolderViewSideBarWidget::Private { public: explicit Private() : albumModificationHelper(nullptr), albumFolderView(nullptr), searchTextBar(nullptr) { } AlbumModificationHelper* albumModificationHelper; AlbumSelectionTreeView* albumFolderView; SearchTextBar* searchTextBar; }; AlbumFolderViewSideBarWidget::AlbumFolderViewSideBarWidget(QWidget* const parent, AlbumModel* const model, AlbumModificationHelper* const albumModificationHelper) : SidebarWidget(parent), d(new Private) { setObjectName(QLatin1String("AlbumFolderView Sidebar")); setProperty("Shortcut", Qt::CTRL + Qt::SHIFT + Qt::Key_F1); d->albumModificationHelper = albumModificationHelper; const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); QVBoxLayout* const layout = new QVBoxLayout(this); d->albumFolderView = new AlbumSelectionTreeView(this, model, d->albumModificationHelper); d->albumFolderView->setObjectName(QLatin1String("AlbumFolderView")); d->albumFolderView->setConfigGroup(getConfigGroup()); d->albumFolderView->setExpandNewCurrentItem(true); d->albumFolderView->setAlbumManagerCurrentAlbum(true); d->searchTextBar = new SearchTextBar(this, QLatin1String("ItemIconViewFolderSearchBar")); d->searchTextBar->setHighlightOnResult(true); d->searchTextBar->setModel(model, AbstractAlbumModel::AlbumIdRole, AbstractAlbumModel::AlbumTitleRole); d->searchTextBar->setFilterModel(d->albumFolderView->albumFilterModel()); layout->addWidget(d->albumFolderView); layout->addWidget(d->searchTextBar); layout->setContentsMargins(0, 0, spacing, 0); // setup connection connect(d->albumFolderView, SIGNAL(signalFindDuplicates(PAlbum*)), this, SIGNAL(signalFindDuplicates(PAlbum*))); } AlbumFolderViewSideBarWidget::~AlbumFolderViewSideBarWidget() { delete d; } void AlbumFolderViewSideBarWidget::setActive(bool active) { if (active) { AlbumManager::instance()->setCurrentAlbums(QList() << d->albumFolderView->currentAlbum()); } } void AlbumFolderViewSideBarWidget::doLoadState() { d->albumFolderView->loadState(); } void AlbumFolderViewSideBarWidget::doSaveState() { d->albumFolderView->saveState(); } void AlbumFolderViewSideBarWidget::applySettings() { ApplicationSettings* const settings = ApplicationSettings::instance(); d->albumFolderView->setEnableToolTips(settings->getShowAlbumToolTips()); } void AlbumFolderViewSideBarWidget::changeAlbumFromHistory(const QList& album) { d->albumFolderView->setCurrentAlbums(album); } AlbumPointer AlbumFolderViewSideBarWidget::currentAlbum() const { return AlbumPointer (d->albumFolderView->currentAlbum()); } void AlbumFolderViewSideBarWidget::setCurrentAlbum(PAlbum* album) { // Change the current album in list view. d->albumFolderView->setCurrentAlbums(QList() << album); } const QIcon AlbumFolderViewSideBarWidget::getIcon() { return QIcon::fromTheme(QLatin1String("folder-pictures")); } const QString AlbumFolderViewSideBarWidget::getCaption() { return i18n("Albums"); } // ----------------------------------------------------------------------------- class Q_DECL_HIDDEN TagViewSideBarWidget::Private { public: enum TagsSource { NoTags = 0, ExistingTags }; public: explicit Private() : openTagMngr(nullptr), tagSearchBar(nullptr), tagFolderView(nullptr), btnGroup(nullptr), noTagsBtn(nullptr), tagsBtn(nullptr), noTagsWasChecked(false), ExistingTagsWasChecked(false) { } public: QPushButton* openTagMngr; SearchTextBar* tagSearchBar; TagFolderView* tagFolderView; QButtonGroup* btnGroup; QRadioButton* noTagsBtn; QRadioButton* tagsBtn; bool noTagsWasChecked; bool ExistingTagsWasChecked; QString noTagsSearchXml; static const QString configTagsSourceEntry; }; const QString TagViewSideBarWidget::Private::configTagsSourceEntry(QLatin1String("TagsSource")); TagViewSideBarWidget::TagViewSideBarWidget(QWidget* const parent, TagModel* const model) : SidebarWidget(parent), d(new Private) { setObjectName(QLatin1String("TagView Sidebar")); setProperty("Shortcut", Qt::CTRL + Qt::SHIFT + Qt::Key_F2); const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); QVBoxLayout* const layout = new QVBoxLayout(this); d->openTagMngr = new QPushButton( i18n("Open Tag Manager")); d->noTagsBtn = new QRadioButton(i18n("No Tags"), this); d->tagsBtn = new QRadioButton(i18n("Existing Tags"), this); d->btnGroup = new QButtonGroup(this); d->btnGroup->addButton(d->noTagsBtn); d->btnGroup->addButton(d->tagsBtn); d->btnGroup->setId(d->noTagsBtn, 0); d->btnGroup->setId(d->tagsBtn, 1); d->btnGroup->setExclusive(true); d->tagFolderView = new TagFolderView(this, model); d->tagFolderView->setConfigGroup(getConfigGroup()); d->tagFolderView->setExpandNewCurrentItem(true); d->tagFolderView->setAlbumManagerCurrentAlbum(true); //d->tagFolderView->filteredModel()->doNotListTagsWithProperty(TagPropertyName::person()); //d->tagFolderView->filteredModel()->setFilterBehavior(AlbumFilterModel::StrictFiltering); d->tagSearchBar = new SearchTextBar(this, QLatin1String("ItemIconViewTagSearchBar")); d->tagSearchBar->setHighlightOnResult(true); d->tagSearchBar->setModel(model, AbstractAlbumModel::AlbumIdRole, AbstractAlbumModel::AlbumTitleRole); //d->tagSearchBar->setModel(d->tagFolderView->filteredModel(), // AbstractAlbumModel::AlbumIdRole, AbstractAlbumModel::AlbumTitleRole); d->tagSearchBar->setFilterModel(d->tagFolderView->albumFilterModel()); layout->addWidget(d->openTagMngr); layout->addWidget(d->noTagsBtn); layout->addWidget(d->tagsBtn); layout->addWidget(d->tagFolderView); layout->addWidget(d->tagSearchBar); layout->setContentsMargins(0, 0, spacing, 0); connect(d->openTagMngr, SIGNAL(clicked()), this,SLOT(slotOpenTagManager())); connect(d->tagFolderView, SIGNAL(signalFindDuplicates(QList)), this, SIGNAL(signalFindDuplicates(QList))); connect(d->btnGroup, SIGNAL(buttonClicked(int)), this, SLOT(slotToggleTagsSelection(int))); } TagViewSideBarWidget::~TagViewSideBarWidget() { delete d; } void TagViewSideBarWidget::setActive(bool active) { if (active) { if (d->noTagsBtn->isChecked()) { setNoTagsAlbum(); } else { AlbumManager::instance()->setCurrentAlbums(d->tagFolderView->selectedTags()); } } } void TagViewSideBarWidget::doLoadState() { KConfigGroup group = getConfigGroup(); bool noTagsBtnWasChecked = group.readEntry(d->configTagsSourceEntry, false); d->noTagsBtn->setChecked(noTagsBtnWasChecked); d->tagsBtn->setChecked(!noTagsBtnWasChecked); d->noTagsWasChecked = noTagsBtnWasChecked; d->ExistingTagsWasChecked = !noTagsBtnWasChecked; d->tagFolderView->loadState(); d->tagFolderView->setDisabled(noTagsBtnWasChecked); } void TagViewSideBarWidget::doSaveState() { KConfigGroup group = getConfigGroup(); group.writeEntry(d->configTagsSourceEntry, d->noTagsBtn->isChecked()); d->tagFolderView->saveState(); group.sync(); } void TagViewSideBarWidget::applySettings() { } void TagViewSideBarWidget::changeAlbumFromHistory(const QList& album) { if (album.first()->type() == Album::TAG) { d->tagsBtn->setChecked(true); d->tagFolderView->setEnabled(true); d->ExistingTagsWasChecked = true; d->noTagsWasChecked = false; d->tagFolderView->setCurrentAlbums(album); } else { d->noTagsBtn->setChecked(true); d->tagFolderView->setDisabled(true); d->noTagsWasChecked = true; d->ExistingTagsWasChecked = false; } } AlbumPointer TagViewSideBarWidget::currentAlbum() const { return AlbumPointer (d->tagFolderView->currentAlbum()); } void TagViewSideBarWidget::setNoTagsAlbum() { if (d->noTagsSearchXml.isEmpty()) { SearchXmlWriter writer; writer.setFieldOperator((SearchXml::standardFieldOperator())); writer.writeGroup(); writer.writeField(QLatin1String("nottagged"), SearchXml::Equal); writer.finishField(); writer.finishGroup(); writer.finish(); d->noTagsSearchXml = writer.xml(); } QString title = SAlbum::getTemporaryTitle(DatabaseSearch::AdvancedSearch); SAlbum* album = AlbumManager::instance()->findSAlbum(title); int id; if (album) { id = album->id(); CoreDbAccess().db()->updateSearch(id, DatabaseSearch::AdvancedSearch, SAlbum::getTemporaryTitle(DatabaseSearch::AdvancedSearch), d->noTagsSearchXml); } else { id = CoreDbAccess().db()->addSearch(DatabaseSearch::AdvancedSearch, SAlbum::getTemporaryTitle(DatabaseSearch::AdvancedSearch), d->noTagsSearchXml); } album = new SAlbum(i18n("No Tags Album"), id); if (album) { AlbumManager::instance()->setCurrentAlbums(QList() << album); } } const QIcon TagViewSideBarWidget::getIcon() { return QIcon::fromTheme(QLatin1String("tag")); } const QString TagViewSideBarWidget::getCaption() { return i18n("Tags"); } void TagViewSideBarWidget::setCurrentAlbum(TAlbum* album) { d->tagFolderView->setCurrentAlbums(QList() << album); } void TagViewSideBarWidget::slotOpenTagManager() { TagsManager* const tagMngr = TagsManager::instance(); tagMngr->show(); tagMngr->activateWindow(); tagMngr->raise(); } void TagViewSideBarWidget::slotToggleTagsSelection(int radioClicked) { switch (Private::TagsSource(radioClicked)) { case Private::NoTags: { if (!d->noTagsWasChecked) { setNoTagsAlbum(); d->tagFolderView->setDisabled(true); d->noTagsWasChecked = d->noTagsBtn->isChecked(); d->ExistingTagsWasChecked = d->tagsBtn->isChecked(); } break; } case Private::ExistingTags: { if (!d->ExistingTagsWasChecked) { d->tagFolderView->setEnabled(true); setActive(true); d->noTagsWasChecked = d->noTagsBtn->isChecked(); d->ExistingTagsWasChecked = d->tagsBtn->isChecked(); } break; } } } // ----------------------------------------------------------------------------- class Q_DECL_HIDDEN LabelsSideBarWidget::Private { public: explicit Private() : labelsTree(nullptr) { } LabelsTreeView* labelsTree; }; LabelsSideBarWidget::LabelsSideBarWidget(QWidget* const parent) : SidebarWidget(parent), d(new Private) { setObjectName(QLatin1String("Labels Sidebar")); setProperty("Shortcut", Qt::CTRL + Qt::SHIFT + Qt::Key_F3); const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); QVBoxLayout* const layout = new QVBoxLayout(this); d->labelsTree = new LabelsTreeView(this); d->labelsTree->setConfigGroup(getConfigGroup()); layout->addWidget(d->labelsTree); layout->setContentsMargins(0, 0, spacing, 0); } LabelsSideBarWidget::~LabelsSideBarWidget() { delete d; } LabelsTreeView *LabelsSideBarWidget::labelsTree() { return d->labelsTree; } void LabelsSideBarWidget::setActive(bool active) { if (active) { d->labelsTree->setCurrentAlbum(); } } void LabelsSideBarWidget::applySettings() { } void LabelsSideBarWidget::changeAlbumFromHistory(const QList& album) { Q_UNUSED(album); } void LabelsSideBarWidget::doLoadState() { d->labelsTree->doLoadState(); } void LabelsSideBarWidget::doSaveState() { d->labelsTree->doSaveState(); } const QIcon LabelsSideBarWidget::getIcon() { return QIcon::fromTheme(QLatin1String("folder-favorites")); } const QString LabelsSideBarWidget::getCaption() { return i18n("Labels"); } QHash > LabelsSideBarWidget::selectedLabels() { return d->labelsTree->selectedLabels(); } // ----------------------------------------------------------------------------- class Q_DECL_HIDDEN DateFolderViewSideBarWidget::Private { public: explicit Private() : dateFolderView(nullptr) { } DateFolderView* dateFolderView; }; DateFolderViewSideBarWidget::DateFolderViewSideBarWidget(QWidget* const parent, DateAlbumModel* const model, ItemAlbumFilterModel* const imageFilterModel) : SidebarWidget(parent), d(new Private) { setObjectName(QLatin1String("DateFolderView Sidebar")); setProperty("Shortcut", Qt::CTRL + Qt::SHIFT + Qt::Key_F4); const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); QVBoxLayout* const layout = new QVBoxLayout(this); d->dateFolderView = new DateFolderView(this, model); d->dateFolderView->setConfigGroup(getConfigGroup()); d->dateFolderView->setItemModel(imageFilterModel); layout->addWidget(d->dateFolderView); layout->setContentsMargins(0, 0, spacing, 0); } DateFolderViewSideBarWidget::~DateFolderViewSideBarWidget() { delete d; } void DateFolderViewSideBarWidget::setActive(bool active) { d->dateFolderView->setActive(active); } void DateFolderViewSideBarWidget::doLoadState() { d->dateFolderView->loadState(); } void DateFolderViewSideBarWidget::doSaveState() { d->dateFolderView->saveState(); } void DateFolderViewSideBarWidget::applySettings() { } void DateFolderViewSideBarWidget::changeAlbumFromHistory(const QList& album) { d->dateFolderView->changeAlbumFromHistory(dynamic_cast(album.first())); } AlbumPointer DateFolderViewSideBarWidget::currentAlbum() const { return d->dateFolderView->currentAlbum(); } void DateFolderViewSideBarWidget::gotoDate(const QDate& date) { d->dateFolderView->gotoDate(date); } const QIcon DateFolderViewSideBarWidget::getIcon() { return QIcon::fromTheme(QLatin1String("view-calendar-list")); } const QString DateFolderViewSideBarWidget::getCaption() { return i18n("Dates"); } // ----------------------------------------------------------------------------- class Q_DECL_HIDDEN TimelineSideBarWidget::Private { public: explicit Private() : scaleBG(nullptr), cursorCountLabel(nullptr), scrollBar(nullptr), timer(nullptr), resetButton(nullptr), saveButton(nullptr), timeUnitCB(nullptr), nameEdit(nullptr), cursorDateLabel(nullptr), searchDateBar(nullptr), timeLineFolderView(nullptr), timeLineWidget(nullptr), searchModificationHelper(nullptr) { } static const QString configHistogramTimeUnitEntry; static const QString configHistogramScaleEntry; static const QString configCursorPositionEntry; QButtonGroup* scaleBG; QLabel* cursorCountLabel; QScrollBar* scrollBar; QTimer* timer; QToolButton* resetButton; QToolButton* saveButton; QComboBox* timeUnitCB; QLineEdit* nameEdit; DAdjustableLabel* cursorDateLabel; SearchTextBar* searchDateBar; EditableSearchTreeView* timeLineFolderView; TimeLineWidget* timeLineWidget; SearchModificationHelper* searchModificationHelper; AlbumPointer currentTimelineSearch; }; const QString TimelineSideBarWidget::Private::configHistogramTimeUnitEntry(QLatin1String("Histogram TimeUnit")); const QString TimelineSideBarWidget::Private::configHistogramScaleEntry(QLatin1String("Histogram Scale")); const QString TimelineSideBarWidget::Private::configCursorPositionEntry(QLatin1String("Cursor Position")); // -------------------------------------------------------- TimelineSideBarWidget::TimelineSideBarWidget(QWidget* const parent, SearchModel* const searchModel, SearchModificationHelper* const searchModificationHelper) : SidebarWidget(parent), d(new Private) { setObjectName(QLatin1String("TimeLine Sidebar")); setProperty("Shortcut", Qt::CTRL + Qt::SHIFT + Qt::Key_F5); d->searchModificationHelper = searchModificationHelper; d->timer = new QTimer(this); setAttribute(Qt::WA_DeleteOnClose); const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); QVBoxLayout* const vlay = new QVBoxLayout(this); QFrame* const panel = new QFrame(this); panel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); panel->setLineWidth(1); QGridLayout* const grid = new QGridLayout(panel); // --------------------------------------------------------------- QWidget* const hbox1 = new QWidget(panel); QHBoxLayout* const hlay = new QHBoxLayout(hbox1); QLabel* const label1 = new QLabel(i18n("Time Unit:"), hbox1); d->timeUnitCB = new QComboBox(hbox1); d->timeUnitCB->addItem(i18n("Day"), TimeLineWidget::Day); d->timeUnitCB->addItem(i18n("Week"), TimeLineWidget::Week); d->timeUnitCB->addItem(i18n("Month"), TimeLineWidget::Month); d->timeUnitCB->addItem(i18n("Year"), TimeLineWidget::Year); d->timeUnitCB->setCurrentIndex((int)TimeLineWidget::Month); d->timeUnitCB->setFocusPolicy(Qt::NoFocus); d->timeUnitCB->setWhatsThis(i18n("

Select the histogram time unit.

" "

You can change the graph decade to zoom in or zoom out over time.

")); QWidget* const scaleBox = new QWidget(hbox1); QHBoxLayout* const hlay2 = new QHBoxLayout(scaleBox); d->scaleBG = new QButtonGroup(scaleBox); d->scaleBG->setExclusive(true); scaleBox->setWhatsThis( i18n("

Select the histogram scale.

" "

If the date's maximal counts are small, you can use the linear scale.

" "

Logarithmic scale can be used when the maximal counts are big; " "if it is used, all values (small and large) will be visible on the " "graph.

")); QToolButton* const linHistoButton = new QToolButton(scaleBox); linHistoButton->setToolTip( i18n( "Linear" ) ); linHistoButton->setIcon(QIcon::fromTheme(QLatin1String("view-object-histogram-linear"))); linHistoButton->setCheckable(true); d->scaleBG->addButton(linHistoButton, TimeLineWidget::LinScale); QToolButton* const logHistoButton = new QToolButton(scaleBox); logHistoButton->setToolTip( i18n( "Logarithmic" ) ); logHistoButton->setIcon(QIcon::fromTheme(QLatin1String("view-object-histogram-logarithmic"))); logHistoButton->setCheckable(true); d->scaleBG->addButton(logHistoButton, TimeLineWidget::LogScale); hlay2->setContentsMargins(QMargins()); hlay2->setSpacing(0); hlay2->addWidget(linHistoButton); hlay2->addWidget(logHistoButton); hlay->setContentsMargins(QMargins()); hlay->setSpacing(spacing); hlay->addWidget(label1); hlay->addWidget(d->timeUnitCB); hlay->addItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum)); hlay->addWidget(scaleBox); // --------------------------------------------------------------- d->timeLineWidget = new TimeLineWidget(panel); d->scrollBar = new QScrollBar(panel); d->scrollBar->setOrientation(Qt::Horizontal); d->scrollBar->setMinimum(0); d->scrollBar->setSingleStep(1); d->cursorDateLabel = new DAdjustableLabel(panel); d->cursorCountLabel = new QLabel(panel); d->cursorCountLabel->setAlignment(Qt::AlignRight); // --------------------------------------------------------------- DHBox* const hbox2 = new DHBox(panel); hbox2->setContentsMargins(QMargins()); hbox2->setSpacing(spacing); d->resetButton = new QToolButton(hbox2); d->resetButton->setIcon(QIcon::fromTheme(QLatin1String("document-revert"))); d->resetButton->setToolTip(i18n("Clear current selection")); d->resetButton->setWhatsThis(i18n("If you press this button, the current date selection on the time-line will be cleared.")); d->nameEdit = new QLineEdit(hbox2); d->nameEdit->setClearButtonEnabled(true); d->nameEdit->setWhatsThis(i18n("Enter the name of the current dates search to save in the " "\"Searches\" view")); d->saveButton = new QToolButton(hbox2); d->saveButton->setIcon(QIcon::fromTheme(QLatin1String("document-save"))); d->saveButton->setEnabled(false); d->saveButton->setToolTip(i18n("Save current selection to a new virtual Album")); d->saveButton->setWhatsThis(i18n("If you press this button, the dates selected on the time-line will be " "saved to a new search virtual Album using the name set on the left.")); // --------------------------------------------------------------- grid->addWidget(hbox1, 0, 0, 1, 4); grid->addWidget(d->cursorDateLabel, 1, 0, 1, 3); grid->addWidget(d->cursorCountLabel, 1, 3, 1, 1); grid->addWidget(d->timeLineWidget, 2, 0, 1, 4); grid->addWidget(d->scrollBar, 3, 0, 1, 4); grid->addWidget(hbox2, 4, 0, 1, 4); grid->setColumnStretch(2, 10); grid->setContentsMargins(spacing, spacing, spacing, spacing); grid->setSpacing(spacing); // --------------------------------------------------------------- d->timeLineFolderView = new EditableSearchTreeView(this, searchModel, searchModificationHelper); d->timeLineFolderView->setConfigGroup(getConfigGroup()); d->timeLineFolderView->filteredModel()->listTimelineSearches(); d->timeLineFolderView->filteredModel()->setListTemporarySearches(false); d->timeLineFolderView->setAlbumManagerCurrentAlbum(false); d->searchDateBar = new SearchTextBar(this, QLatin1String("TimeLineViewSearchDateBar")); d->searchDateBar->setModel(d->timeLineFolderView->filteredModel(), AbstractAlbumModel::AlbumIdRole, AbstractAlbumModel::AlbumTitleRole); d->searchDateBar->setFilterModel(d->timeLineFolderView->albumFilterModel()); vlay->addWidget(panel); vlay->addWidget(d->timeLineFolderView); vlay->addItem(new QSpacerItem(spacing, spacing, QSizePolicy::Minimum, QSizePolicy::Minimum)); vlay->addWidget(d->searchDateBar); vlay->setContentsMargins(0, 0, spacing, 0); vlay->setSpacing(0); // --------------------------------------------------------------- connect(AlbumManager::instance(), SIGNAL(signalDatesMapDirty(QMap)), d->timeLineWidget, SLOT(slotDatesMap(QMap))); connect(d->timeLineFolderView, SIGNAL(currentAlbumChanged(Album*)), this, SLOT(slotAlbumSelected(Album*))); connect(d->timeUnitCB, SIGNAL(activated(int)), this, SLOT(slotTimeUnitChanged(int))); connect(d->scaleBG, SIGNAL(buttonReleased(int)), this, SLOT(slotScaleChanged(int))); connect(d->timeLineWidget, SIGNAL(signalDateMapChanged()), this, SLOT(slotInit())); connect(d->timeLineWidget, SIGNAL(signalCursorPositionChanged()), this, SLOT(slotCursorPositionChanged())); connect(d->timeLineWidget, SIGNAL(signalSelectionChanged()), this, SLOT(slotSelectionChanged())); connect(d->timeLineWidget, SIGNAL(signalRefDateTimeChanged()), this, SLOT(slotRefDateTimeChanged())); connect(d->timer, SIGNAL(timeout()), this, SLOT(slotUpdateCurrentDateSearchAlbum())); connect(d->resetButton, SIGNAL(clicked()), this, SLOT(slotResetSelection())); connect(d->saveButton, SIGNAL(clicked()), this, SLOT(slotSaveSelection())); connect(d->scrollBar, SIGNAL(valueChanged(int)), this, SLOT(slotScrollBarValueChanged(int))); connect(d->nameEdit, SIGNAL(textChanged(QString)), this, SLOT(slotCheckAboutSelection())); connect(d->nameEdit, SIGNAL(returnPressed()), d->saveButton, SLOT(animateClick())); } TimelineSideBarWidget::~TimelineSideBarWidget() { delete d; } void TimelineSideBarWidget::slotInit() { // Date Maps are loaded from AlbumManager to TimeLineWidget after than GUI is initialized. // AlbumManager query Date KIO slave to stats items from database and it can take a while. // We waiting than TimeLineWidget is ready before to set last config from users. loadState(); disconnect(d->timeLineWidget, SIGNAL(signalDateMapChanged()), this, SLOT(slotInit())); connect(d->timeLineWidget, SIGNAL(signalDateMapChanged()), this, SLOT(slotCursorPositionChanged())); } void TimelineSideBarWidget::setActive(bool active) { if (active) { if (!d->currentTimelineSearch) { d->currentTimelineSearch = d->timeLineFolderView->currentAlbum(); } if (d->currentTimelineSearch) { AlbumManager::instance()->setCurrentAlbums(QList() << d->currentTimelineSearch); } else { slotUpdateCurrentDateSearchAlbum(); } } } void TimelineSideBarWidget::doLoadState() { KConfigGroup group = getConfigGroup(); d->timeUnitCB->setCurrentIndex(group.readEntry(d->configHistogramTimeUnitEntry, (int)TimeLineWidget::Month)); slotTimeUnitChanged(d->timeUnitCB->currentIndex()); int id = group.readEntry(d->configHistogramScaleEntry, (int)TimeLineWidget::LinScale); if (d->scaleBG->button(id)) { d->scaleBG->button(id)->setChecked(true); } slotScaleChanged(d->scaleBG->checkedId()); QDateTime now = QDateTime::currentDateTime(); d->timeLineWidget->setCursorDateTime(group.readEntry(d->configCursorPositionEntry, now)); d->timeLineWidget->setCurrentIndex(d->timeLineWidget->indexForCursorDateTime()); d->timeLineFolderView->loadState(); } void TimelineSideBarWidget::doSaveState() { KConfigGroup group = getConfigGroup(); group.writeEntry(d->configHistogramTimeUnitEntry, d->timeUnitCB->currentIndex()); group.writeEntry(d->configHistogramScaleEntry, d->scaleBG->checkedId()); group.writeEntry(d->configCursorPositionEntry, d->timeLineWidget->cursorDateTime()); d->timeLineFolderView->saveState(); group.sync(); } void TimelineSideBarWidget::applySettings() { // nothing to do here right now } void TimelineSideBarWidget::changeAlbumFromHistory(const QList& album) { d->timeLineFolderView->setCurrentAlbums(album); } const QIcon TimelineSideBarWidget::getIcon() { return QIcon::fromTheme(QLatin1String("player-time")); } const QString TimelineSideBarWidget::getCaption() { return i18n("Timeline"); } void TimelineSideBarWidget::slotRefDateTimeChanged() { d->scrollBar->blockSignals(true); d->scrollBar->setMaximum(d->timeLineWidget->totalIndex()-1); d->scrollBar->setValue(d->timeLineWidget->indexForRefDateTime()-1); d->scrollBar->blockSignals(false); } void TimelineSideBarWidget::slotTimeUnitChanged(int mode) { d->timeLineWidget->setTimeUnit((TimeLineWidget::TimeUnit)mode); } void TimelineSideBarWidget::slotScrollBarValueChanged(int val) { d->timeLineWidget->setCurrentIndex(val); } void TimelineSideBarWidget::slotScaleChanged(int mode) { d->timeLineWidget->setScaleMode((TimeLineWidget::ScaleMode)mode); } void TimelineSideBarWidget::slotCursorPositionChanged() { QString txt; int val = d->timeLineWidget->cursorInfo(txt); d->cursorDateLabel->setAdjustedText(txt); d->cursorCountLabel->setText((val == 0) ? i18n("no item") : i18np("1 item", "%1 items", val)); } void TimelineSideBarWidget::slotSelectionChanged() { d->timer->setSingleShot(true); d->timer->start(500); } /** * Called from d->timer event. */ void TimelineSideBarWidget::slotUpdateCurrentDateSearchAlbum() { slotCheckAboutSelection(); int totalCount = 0; DateRangeList dateRanges = d->timeLineWidget->selectedDateRange(totalCount); d->currentTimelineSearch = d->searchModificationHelper-> slotCreateTimeLineSearch(SAlbum::getTemporaryTitle(DatabaseSearch::TimeLineSearch), dateRanges, true); // NOTE: "temporary" search is not listed in view d->timeLineFolderView->setCurrentAlbum(0); } void TimelineSideBarWidget::slotSaveSelection() { QString name = d->nameEdit->text(); int totalCount = 0; DateRangeList dateRanges = d->timeLineWidget->selectedDateRange(totalCount); d->currentTimelineSearch = d->searchModificationHelper->slotCreateTimeLineSearch(name, dateRanges); } void TimelineSideBarWidget::slotAlbumSelected(Album* album) { if (d->currentTimelineSearch == album) { return; } SAlbum* const salbum = dynamic_cast(album); if (!salbum) { return; } d->currentTimelineSearch = salbum; AlbumManager::instance()->setCurrentAlbums(QList() << salbum); SearchXmlReader reader(salbum->query()); // The timeline query consists of groups, with two date time fields each DateRangeList list; while (!reader.atEnd()) { // read groups if (reader.readNext() == SearchXml::Group) { QDateTime start, end; int numberOfFields = 0; while (!reader.atEnd()) { // read fields reader.readNext(); if (reader.isEndElement()) { break; } if (reader.isFieldElement()) { if (numberOfFields == 0) { start = reader.valueToDateTime(); } else if (numberOfFields == 1) { end = reader.valueToDateTime(); } ++numberOfFields; } } if (numberOfFields) { list << DateRange(start, end); } } } d->timeLineWidget->setSelectedDateRange(list); } void TimelineSideBarWidget::slotResetSelection() { d->timeLineWidget->slotResetSelection(); slotCheckAboutSelection(); AlbumManager::instance()->clearCurrentAlbums(); } void TimelineSideBarWidget::slotCheckAboutSelection() { int totalCount = 0; DateRangeList list = d->timeLineWidget->selectedDateRange(totalCount); if (!list.isEmpty()) { d->nameEdit->setEnabled(true); if (!d->nameEdit->text().isEmpty()) { d->saveButton->setEnabled(true); } } else { d->nameEdit->setEnabled(false); d->saveButton->setEnabled(false); } } // ----------------------------------------------------------------------------- class Q_DECL_HIDDEN SearchSideBarWidget::Private { public: explicit Private() : searchSearchBar(nullptr), searchTreeView(nullptr), searchTabHeader(nullptr) { } SearchTextBar* searchSearchBar; NormalSearchTreeView* searchTreeView; SearchTabHeader* searchTabHeader; }; SearchSideBarWidget::SearchSideBarWidget(QWidget* const parent, SearchModel* const searchModel, SearchModificationHelper* const searchModificationHelper) : SidebarWidget(parent), d(new Private) { setObjectName(QLatin1String("Search Sidebar")); setProperty("Shortcut", Qt::CTRL + Qt::SHIFT + Qt::Key_F6); const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); QVBoxLayout* const layout = new QVBoxLayout(this); d->searchTabHeader = new SearchTabHeader(this); d->searchTreeView = new NormalSearchTreeView(this, searchModel, searchModificationHelper); d->searchTreeView->setConfigGroup(getConfigGroup()); d->searchTreeView->filteredModel()->listNormalSearches(); d->searchTreeView->filteredModel()->setListTemporarySearches(true); d->searchTreeView->setAlbumManagerCurrentAlbum(true); d->searchSearchBar = new SearchTextBar(this, QLatin1String("ItemIconViewSearchSearchBar")); d->searchSearchBar->setModel(d->searchTreeView->filteredModel(), AbstractAlbumModel::AlbumIdRole, AbstractAlbumModel::AlbumTitleRole); d->searchSearchBar->setFilterModel(d->searchTreeView->albumFilterModel()); layout->addWidget(d->searchTabHeader); layout->addWidget(d->searchTreeView); layout->setStretchFactor(d->searchTreeView, 1); layout->addWidget(d->searchSearchBar); layout->setContentsMargins(0, 0, spacing, 0); connect(d->searchTreeView, SIGNAL(newSearch()), d->searchTabHeader, SLOT(newAdvancedSearch())); connect(d->searchTreeView, SIGNAL(editSearch(SAlbum*)), d->searchTabHeader, SLOT(editSearch(SAlbum*))); connect(d->searchTreeView, SIGNAL(currentAlbumChanged(Album*)), d->searchTabHeader, SLOT(selectedSearchChanged(Album*))); connect(d->searchTabHeader, SIGNAL(searchShallBeSelected(QList)), d->searchTreeView, SLOT(setCurrentAlbums(QList))); } SearchSideBarWidget::~SearchSideBarWidget() { delete d; } void SearchSideBarWidget::setActive(bool active) { if (active) { AlbumManager::instance()->setCurrentAlbums(QList() << d->searchTreeView->currentAlbum()); d->searchTabHeader->selectedSearchChanged(d->searchTreeView->currentAlbum()); } } void SearchSideBarWidget::doLoadState() { d->searchTreeView->loadState(); } void SearchSideBarWidget::doSaveState() { d->searchTreeView->saveState(); } void SearchSideBarWidget::applySettings() { } void SearchSideBarWidget::changeAlbumFromHistory(const QList& album) { d->searchTreeView->setCurrentAlbums(album); } const QIcon SearchSideBarWidget::getIcon() { return QIcon::fromTheme(QLatin1String("edit-find")); } const QString SearchSideBarWidget::getCaption() { return i18nc("Advanced search images, access stored searches", "Search"); } void SearchSideBarWidget::newKeywordSearch() { d->searchTabHeader->newKeywordSearch(); } void SearchSideBarWidget::newAdvancedSearch() { d->searchTabHeader->newAdvancedSearch(); } // ----------------------------------------------------------------------------- class Q_DECL_HIDDEN FuzzySearchSideBarWidget::Private { public: explicit Private() : fuzzySearchView(nullptr), searchModificationHelper(nullptr) { } FuzzySearchView* fuzzySearchView; SearchModificationHelper* searchModificationHelper; }; FuzzySearchSideBarWidget::FuzzySearchSideBarWidget(QWidget* const parent, SearchModel* const searchModel, SearchModificationHelper* const searchModificationHelper) : SidebarWidget(parent), d(new Private) { setObjectName(QLatin1String("Fuzzy Search Sidebar")); setProperty("Shortcut", Qt::CTRL + Qt::SHIFT + Qt::Key_F7); const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); d->fuzzySearchView = new FuzzySearchView(searchModel, searchModificationHelper, this); d->fuzzySearchView->setConfigGroup(getConfigGroup()); connect(d->fuzzySearchView, SIGNAL(signalNofificationError(QString,int)), this, SIGNAL(signalNofificationError(QString,int))); QVBoxLayout* const layout = new QVBoxLayout(this); layout->addWidget(d->fuzzySearchView); layout->setContentsMargins(0, 0, spacing, 0); } FuzzySearchSideBarWidget::~FuzzySearchSideBarWidget() { delete d; } void FuzzySearchSideBarWidget::setActive(bool active) { d->fuzzySearchView->setActive(active); if (active) { AlbumManager::instance()->setCurrentAlbums(QList() << d->fuzzySearchView->currentAlbum()); } emit signalActive(active); } void FuzzySearchSideBarWidget::doLoadState() { d->fuzzySearchView->loadState(); } void FuzzySearchSideBarWidget::doSaveState() { d->fuzzySearchView->saveState(); } void FuzzySearchSideBarWidget::applySettings() { } void FuzzySearchSideBarWidget::changeAlbumFromHistory(const QList& album) { SAlbum* const salbum = dynamic_cast(album.first()); d->fuzzySearchView->setCurrentAlbum(salbum); } const QIcon FuzzySearchSideBarWidget::getIcon() { return QIcon::fromTheme(QLatin1String("tools-wizard")); } const QString FuzzySearchSideBarWidget::getCaption() { return i18nc("Fuzzy Search images, as duplicates, sketch, searches by similarities", "Similarity"); } void FuzzySearchSideBarWidget::newDuplicatesSearch(PAlbum* album) { d->fuzzySearchView->newDuplicatesSearch(album); } void FuzzySearchSideBarWidget::newDuplicatesSearch(const QList& albums) { d->fuzzySearchView->newDuplicatesSearch(albums); } void FuzzySearchSideBarWidget::newDuplicatesSearch(const QList& albums) { d->fuzzySearchView->newDuplicatesSearch(albums); } void FuzzySearchSideBarWidget::newSimilarSearch(const ItemInfo& imageInfo) { if (imageInfo.isNull()) { return; } d->fuzzySearchView->setItemInfo(imageInfo); } // ----------------------------------------------------------------------------- #ifdef HAVE_MARBLE class Q_DECL_HIDDEN GPSSearchSideBarWidget::Private { public: explicit Private() : gpsSearchView(nullptr) { } GPSSearchView* gpsSearchView; }; GPSSearchSideBarWidget::GPSSearchSideBarWidget(QWidget* const parent, SearchModel* const searchModel, SearchModificationHelper* const searchModificationHelper, ItemFilterModel* const imageFilterModel, QItemSelectionModel* const itemSelectionModel) : SidebarWidget(parent), d(new Private) { setObjectName(QLatin1String("GPS Search Sidebar")); setProperty("Shortcut", Qt::CTRL + Qt::SHIFT + Qt::Key_F8); d->gpsSearchView = new GPSSearchView(this, searchModel, searchModificationHelper, imageFilterModel, itemSelectionModel); d->gpsSearchView->setConfigGroup(getConfigGroup()); const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); QScrollArea* const scrollArea = new QScrollArea(this); QVBoxLayout* const layout = new QVBoxLayout(this); layout->addWidget(scrollArea); layout->setContentsMargins(0, 0, spacing, 0); scrollArea->setWidget(d->gpsSearchView); scrollArea->setWidgetResizable(true); connect(d->gpsSearchView, SIGNAL(signalMapSoloItems(QList,QString)), this, SIGNAL(signalMapSoloItems(QList,QString))); } GPSSearchSideBarWidget::~GPSSearchSideBarWidget() { delete d; } void GPSSearchSideBarWidget::setActive(bool active) { d->gpsSearchView->setActive(active); } void GPSSearchSideBarWidget::doLoadState() { d->gpsSearchView->loadState(); } void GPSSearchSideBarWidget::doSaveState() { d->gpsSearchView->saveState(); } void GPSSearchSideBarWidget::applySettings() { } void GPSSearchSideBarWidget::changeAlbumFromHistory(const QList& album) { d->gpsSearchView->changeAlbumFromHistory(dynamic_cast(album.first())); } const QIcon GPSSearchSideBarWidget::getIcon() { return QIcon::fromTheme(QLatin1String("globe")); } const QString GPSSearchSideBarWidget::getCaption() { return i18nc("Search images on a map", "Map"); } #endif // HAVE_MARBLE // ----------------------------------------------------------------------------- class Q_DECL_HIDDEN PeopleSideBarWidget::Private : public TagViewSideBarWidget::Private { public: explicit Private() : personIcon(nullptr), textLabel(nullptr), rescanButton(nullptr), searchModificationHelper(nullptr), settingsWdg(nullptr) { } QLabel* personIcon; QLabel* textLabel; QPushButton* rescanButton; SearchModificationHelper* searchModificationHelper; FaceScanWidget* settingsWdg; }; PeopleSideBarWidget::PeopleSideBarWidget(QWidget* const parent, TagModel* const model, SearchModificationHelper* const searchModificationHelper) : SidebarWidget(parent), d(new Private) { setObjectName(QLatin1String("People Sidebar")); setProperty("Shortcut", Qt::CTRL + Qt::SHIFT + Qt::Key_F9); const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); d->searchModificationHelper = searchModificationHelper; QVBoxLayout* const layout = new QVBoxLayout; QHBoxLayout* const hlay = new QHBoxLayout; d->tagFolderView = new TagFolderView(this, model); d->tagFolderView->setConfigGroup(getConfigGroup()); d->tagFolderView->setExpandNewCurrentItem(true); d->tagFolderView->setAlbumManagerCurrentAlbum(true); d->tagFolderView->setShowDeleteFaceTagsAction(true); d->tagFolderView->filteredModel()->listOnlyTagsWithProperty(TagPropertyName::person()); d->tagFolderView->filteredModel()->setFilterBehavior(AlbumFilterModel::StrictFiltering); d->tagSearchBar = new SearchTextBar(this, QLatin1String("ItemIconViewPeopleSearchBar")); d->tagSearchBar->setHighlightOnResult(true); d->tagSearchBar->setModel(d->tagFolderView->filteredModel(), AbstractAlbumModel::AlbumIdRole, AbstractAlbumModel::AlbumTitleRole); d->tagSearchBar->setFilterModel(d->tagFolderView->albumFilterModel()); d->personIcon = new QLabel; d->personIcon->setPixmap(QIcon::fromTheme(QLatin1String("edit-image-face-show")).pixmap(48)); d->textLabel = new QLabel; d->textLabel->setWordWrap(true); d->textLabel->setText(i18nc("@info", "digiKam can search for faces in your photos. " "When you have identified your friends on a number of photos, " "it can also recognize the people shown on your photos.")); d->settingsWdg = new FaceScanWidget(this); d->rescanButton = new QPushButton; d->rescanButton->setText(i18n("Scan collection for faces")); hlay->addWidget(d->personIcon); hlay->addWidget(d->textLabel); layout->addLayout(hlay); layout->addWidget(d->tagFolderView, 10); layout->addWidget(d->tagSearchBar); layout->addWidget(d->settingsWdg); layout->addWidget(d->rescanButton); layout->setContentsMargins(0, 0, spacing, 0); setLayout(layout); connect(d->tagFolderView, SIGNAL(signalFindDuplicates(QList)), this, SIGNAL(signalFindDuplicates(QList))); connect(d->rescanButton, SIGNAL(pressed()), this, SLOT(slotScanForFaces()) ); } PeopleSideBarWidget::~PeopleSideBarWidget() { delete d; } void PeopleSideBarWidget::slotInit() { loadState(); } void PeopleSideBarWidget::setActive(bool active) { emit requestFaceMode(active); if (active) { d->tagFolderView->setCurrentAlbums(QList() << d->tagFolderView->currentAlbum()); } } void PeopleSideBarWidget::doLoadState() { d->tagFolderView->loadState(); d->settingsWdg->loadState(); } void PeopleSideBarWidget::doSaveState() { d->tagFolderView->saveState(); d->settingsWdg->saveState(); } void PeopleSideBarWidget::applySettings() { } void PeopleSideBarWidget::changeAlbumFromHistory(const QList& album) { d->tagFolderView->setCurrentAlbums(album); } void PeopleSideBarWidget::slotScanForFaces() { FaceScanSettings faceScanSettings = d->settingsWdg->settings(); if (!d->settingsWdg->settingsConflicted()) { FacesDetector* const tool = new FacesDetector(faceScanSettings); tool->start(); d->settingsWdg->setEnabled(false); d->rescanButton->setEnabled(false); connect(tool, SIGNAL(signalComplete()), this, SLOT(slotScanComplete())); connect(tool, SIGNAL(signalCanceled()), this, SLOT(slotScanComplete())); } else { emit signalNofificationError(i18n("Face recognition is aborted, because " "there are no identities to recognize. " "Please add new identities."), DNotificationWidget::Information); } } void PeopleSideBarWidget::slotScanComplete() { d->settingsWdg->setEnabled(true); d->rescanButton->setEnabled(true); } const QIcon PeopleSideBarWidget::getIcon() { return QIcon::fromTheme(QLatin1String("edit-image-face-show")); } const QString PeopleSideBarWidget::getCaption() { return i18nc("Browse images sorted by depicted people", "People"); } } // namespace Digikam diff --git a/core/app/views/sidebar/leftsidebarwidgets.h b/core/app/views/sidebar/leftsidebarwidgets.h index cb981b4fef..3fe42dfc7b 100644 --- a/core/app/views/sidebar/leftsidebarwidgets.h +++ b/core/app/views/sidebar/leftsidebarwidgets.h @@ -1,422 +1,405 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2000-12-05 * Description : left sidebar widgets * * Copyright (C) 2009-2010 by Johannes Wienke * Copyright (C) 2010-2020 by Gilles Caulier * Copyright (C) 2014 by Mohamed_Anwer + * Copyright (C) 2010 by Aditya Bhatt * * 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 DIGIKAM_LEFT_SIDE_BAR_WIDGETS_H #define DIGIKAM_LEFT_SIDE_BAR_WIDGETS_H // Local includes #include "digikam_config.h" #include "albummodel.h" #include "albummodificationhelper.h" #include "itemalbumfiltermodel.h" #include "searchmodificationhelper.h" #include "sidebarwidget.h" #include "itemfiltermodel.h" #include "labelstreeview.h" #ifdef HAVE_MARBLE # include "gpssearchview.h" #endif // HAVE_MARBLE namespace Digikam { template class AlbumPointer; /** * SideBarWidget for the folder view. - * - * @author jwienke */ class AlbumFolderViewSideBarWidget : public SidebarWidget { Q_OBJECT public: explicit AlbumFolderViewSideBarWidget(QWidget* const parent, AlbumModel* const model, AlbumModificationHelper* const albumModificationHelper); virtual ~AlbumFolderViewSideBarWidget(); void setActive(bool active) override; void doLoadState() override; void doSaveState() override; void applySettings() override; void changeAlbumFromHistory(const QList& album) override; const QIcon getIcon() override; const QString getCaption() override; AlbumPointer currentAlbum() const; public Q_SLOTS: void setCurrentAlbum(PAlbum* album); Q_SIGNALS: void signalFindDuplicates(PAlbum* album); private: class Private; Private* const d; }; // ----------------------------------------------------------------------------------------- /** * SideBarWidget for the tag view. - * - * @author jwienke */ class TagViewSideBarWidget : public SidebarWidget { Q_OBJECT public: explicit TagViewSideBarWidget(QWidget* const parent, TagModel* const model); virtual ~TagViewSideBarWidget(); void setActive(bool active) override; void doLoadState() override; void doSaveState() override; void applySettings() override; void changeAlbumFromHistory(const QList& album) override; const QIcon getIcon() override; const QString getCaption() override; AlbumPointer currentAlbum() const; private: void setNoTagsAlbum(); public Q_SLOTS: void setCurrentAlbum(TAlbum* album); void slotOpenTagManager(); void slotToggleTagsSelection(int radioClicked); Q_SIGNALS: void signalFindDuplicates(const QList& albums); public: // Declared as public due to use by Private class Private; private: Private* const d; }; // ----------------------------------------------------------------------------------------- /** * SideBarWidget for the Labels. - * - * @author Mohamed_Anwer */ class LabelsSideBarWidget : public SidebarWidget { Q_OBJECT public: explicit LabelsSideBarWidget(QWidget* const parent); virtual ~LabelsSideBarWidget(); LabelsTreeView* labelsTree(); void setActive(bool active) override; void applySettings() override; void changeAlbumFromHistory(const QList& album) override; void doLoadState() override; void doSaveState() override; const QIcon getIcon() override; const QString getCaption() override; QHash > selectedLabels(); private: class Private; Private* const d; }; // ----------------------------------------------------------------------------------------- /** * SideBarWidget for the date folder view. - * - * @author jwienke */ class DateFolderViewSideBarWidget : public SidebarWidget { Q_OBJECT public: explicit DateFolderViewSideBarWidget(QWidget* const parent, DateAlbumModel* const model, ItemAlbumFilterModel* const imageFilterModel); virtual ~DateFolderViewSideBarWidget(); void setActive(bool active) override; void doLoadState() override; void doSaveState() override; void applySettings() override; void changeAlbumFromHistory(const QList& album) override; const QIcon getIcon() override; const QString getCaption() override; AlbumPointer currentAlbum() const; void gotoDate(const QDate& date); private: class Private; Private* const d; }; // ----------------------------------------------------------------------------------------- /** * SideBarWidget for the date folder view. - * - * @author jwienke */ class TimelineSideBarWidget : public SidebarWidget { Q_OBJECT public: explicit TimelineSideBarWidget(QWidget* const parent, SearchModel* const searchModel, SearchModificationHelper* const searchModificationHelper); virtual ~TimelineSideBarWidget(); void setActive(bool active) override; void doLoadState() override; void doSaveState() override; void applySettings() override; void changeAlbumFromHistory(const QList& album) override; const QIcon getIcon() override; const QString getCaption() override; private Q_SLOTS: void slotInit(); void slotScrollBarValueChanged(int); void slotRefDateTimeChanged(); void slotScaleChanged(int); void slotTimeUnitChanged(int); void slotCursorPositionChanged(); void slotSelectionChanged(); void slotResetSelection(); void slotSaveSelection(); void slotUpdateCurrentDateSearchAlbum(); void slotAlbumSelected(Album*); void slotCheckAboutSelection(); private: class Private; Private* const d; }; // ----------------------------------------------------------------------------------------- /** * SideBarWidget for the search. - * - * @author jwienke */ class SearchSideBarWidget : public SidebarWidget { Q_OBJECT public: explicit SearchSideBarWidget(QWidget* const parent, SearchModel* const searchModel, SearchModificationHelper* const searchModificationHelper); virtual ~SearchSideBarWidget(); void setActive(bool active) override; void doLoadState() override; void doSaveState() override; void applySettings() override; void changeAlbumFromHistory(const QList& album) override; const QIcon getIcon() override; const QString getCaption() override; void newKeywordSearch(); void newAdvancedSearch(); private: class Private; Private* const d; }; // ----------------------------------------------------------------------------------------- /** * SideBarWidget for the fuzzy search. - * - * @author jwienke */ class FuzzySearchSideBarWidget : public SidebarWidget { Q_OBJECT public: explicit FuzzySearchSideBarWidget(QWidget* const parent, SearchModel* const searchModel, SearchModificationHelper* const searchModificationHelper); virtual ~FuzzySearchSideBarWidget(); void setActive(bool active) override; void doLoadState() override; void doSaveState() override; void applySettings() override; void changeAlbumFromHistory(const QList& album) override; const QIcon getIcon() override; const QString getCaption() override; void newDuplicatesSearch(PAlbum* album); void newDuplicatesSearch(const QList& albums); void newDuplicatesSearch(const QList& albums); void newSimilarSearch(const ItemInfo& imageInfo); Q_SIGNALS: void signalActive(bool); private: class Private; Private* const d; }; // ----------------------------------------------------------------------------------------- #ifdef HAVE_MARBLE /** * SideBarWidget for the gps search. - * - * @author jwienke */ class GPSSearchSideBarWidget : public SidebarWidget { Q_OBJECT public: explicit GPSSearchSideBarWidget(QWidget* const parent, SearchModel* const searchModel, SearchModificationHelper* const searchModificationHelper, ItemFilterModel* const imageFilterModel, QItemSelectionModel* const itemSelectionModel); virtual ~GPSSearchSideBarWidget(); void setActive(bool active) override; void doLoadState() override; void doSaveState() override; void applySettings() override; void changeAlbumFromHistory(const QList& album) override; const QIcon getIcon() override; const QString getCaption() override; Q_SIGNALS: void signalMapSoloItems(const QList&, const QString&); private: class Private; Private* const d; }; #endif // HAVE_MARBLE // ----------------------------------------------------------------------------------------- /** * SideBarWidget for People - * - * @author Aditya Bhatt */ class PeopleSideBarWidget : public SidebarWidget { Q_OBJECT public: explicit PeopleSideBarWidget(QWidget* const parent, TagModel* const tagModel, SearchModificationHelper* const searchModificationHelper); virtual ~PeopleSideBarWidget(); void setActive(bool active) override; void doLoadState() override; void doSaveState() override; void applySettings() override; void changeAlbumFromHistory(const QList& album) override; const QIcon getIcon() override; const QString getCaption() override; private Q_SLOTS: void slotInit(); void slotScanForFaces(); void slotScanComplete(); Q_SIGNALS: void requestFaceMode(bool on); void signalFindDuplicates(const QList& albums); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_LEFT_SIDE_BAR_WIDGETS_H diff --git a/core/app/views/sidebar/sidebarwidget.cpp b/core/app/views/sidebar/sidebarwidget.cpp index a2b7bf625b..7100ca6c71 100644 --- a/core/app/views/sidebar/sidebarwidget.cpp +++ b/core/app/views/sidebar/sidebarwidget.cpp @@ -1,39 +1,40 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * - * Date : 2000-12-05 + * Date : 2009-12-05 * Description : base class for sidebar widgets * - * Copyright (C) 2009 by Johannes Wienke + * Copyright (C) 2009 by Johannes Wienke + * Copyright (C) 2010-2020 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 "sidebarwidget.h" namespace Digikam { SidebarWidget::SidebarWidget(QWidget* const parent) : QWidget(parent), StateSavingObject(this) { } SidebarWidget::~SidebarWidget() { } } // namespace Digikam diff --git a/core/app/views/sidebar/sidebarwidget.h b/core/app/views/sidebar/sidebarwidget.h index 08b1888477..2c71832803 100644 --- a/core/app/views/sidebar/sidebarwidget.h +++ b/core/app/views/sidebar/sidebarwidget.h @@ -1,115 +1,114 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * - * Date : 2000-12-05 + * Date : 2009-12-05 * Description : base class for sidebar widgets * - * Copyright (C) 2009 by Johannes Wienke + * Copyright (C) 2009 by Johannes Wienke + * Copyright (C) 2010-2020 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. * * ============================================================ */ #ifndef DIGIKAM_SIDE_BAR_WIDGET_H #define DIGIKAM_SIDE_BAR_WIDGET_H // QT includes #include #include // Local includes #include "album.h" #include "iteminfo.h" #include "statesavingobject.h" namespace Digikam { /** * Abstract base class for widgets that are use in one of digikams's sidebars. - * - * @author jwienke */ class SidebarWidget : public QWidget, public StateSavingObject { Q_OBJECT public: /** * Constructor. * * @param parent parent of this widget, may be null */ explicit SidebarWidget(QWidget* const parent); /** * Destructor. */ virtual ~SidebarWidget(); /** * This method is called if the visible sidebar widget is changed. * * @param active if true, this widget is the new active widget, if false another * widget is active */ - virtual void setActive(bool active) = 0; + virtual void setActive(bool active) = 0; /** * This method is invoked when the application settings should be (re-) * applied to this widget. */ - virtual void applySettings() = 0; + virtual void applySettings() = 0; /** * This is called on this widget when the history requires to move back to * the specified album */ virtual void changeAlbumFromHistory(const QList& album) = 0; /** * Must be implemented and return the icon that shall be visible for this * sidebar widget. * * @return pixmap icon */ - virtual const QIcon getIcon() = 0; + virtual const QIcon getIcon() = 0; /** * Must be implemented to return the title of this sidebar's tab. * * @return localized title string */ - virtual const QString getCaption() = 0; + virtual const QString getCaption() = 0; Q_SIGNALS: /** * This signal can be emitted if this sidebar widget wants to be the one * that is active. */ void requestActiveTab(SidebarWidget*); /** * To dispatch error message to temporized pop-up notification widget hosted with icon-view. */ void signalNofificationError(const QString& message, int type); }; } // namespace Digikam #endif // DIGIKAM_SIDE_BAR_WIDGET_H