1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2009-12-05
7 * Description : Side Bar Widget for People
8 *
9 * Copyright (C) 2009-2010 by Johannes Wienke <languitar at semipol dot de>
10 * Copyright (C) 2010-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
11 * Copyright (C) 2012 by Andi Clemens <andi dot clemens at gmail dot com>
12 * Copyright (C) 2014 by Mohamed_Anwer <m_dot_anwer at gmx dot com>
13 * Copyright (C) 2010 by Aditya Bhatt <adityabhatt1991 at gmail dot com>
14 *
15 * This program is free software; you can redistribute it
16 * and/or modify it under the terms of the GNU General
17 * Public License as published by the Free Software Foundation;
18 * either version 2, or (at your option)
19 * any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * ============================================================ */
27
28 #include "peoplesidebarwidget.h"
29
30 // Qt includes
31
32 #include <QLabel>
33 #include <QScrollArea>
34 #include <QApplication>
35 #include <QStyle>
36 #include <QPushButton>
37 #include <QIcon>
38 #include <QHBoxLayout>
39 #include <QVBoxLayout>
40
41 // KDE includes
42
43 #include <kconfiggroup.h>
44 #include <klocalizedstring.h>
45
46 // Local includes
47
48 #include "digikam_debug.h"
49 #include "searchtextbardb.h"
50 #include "tagfolderview.h"
51 #include "timelinewidget.h"
52 #include "facescanwidget.h"
53 #include "facesdetector.h"
54 #include "dnotificationwidget.h"
55 #include "applicationsettings.h"
56
57 namespace Digikam
58 {
59
60 class Q_DECL_HIDDEN PeopleSideBarWidget::Private
61 {
62 public:
63
Private()64 explicit Private()
65 : rescanButton (nullptr),
66 searchModificationHelper(nullptr),
67 settingsWdg (nullptr),
68 tagFolderView (nullptr),
69 tagSearchBar (nullptr)
70 {
71 }
72
73 QPushButton* rescanButton;
74 SearchModificationHelper* searchModificationHelper;
75 FaceScanWidget* settingsWdg;
76 TagFolderView* tagFolderView;
77 SearchTextBarDb* tagSearchBar;
78 };
79
PeopleSideBarWidget(QWidget * const parent,TagModel * const model,SearchModificationHelper * const searchModificationHelper)80 PeopleSideBarWidget::PeopleSideBarWidget(QWidget* const parent,
81 TagModel* const model,
82 SearchModificationHelper* const searchModificationHelper)
83 : SidebarWidget(parent),
84 d (new Private)
85 {
86 setObjectName(QLatin1String("People Sidebar"));
87 setProperty("Shortcut", Qt::CTRL + Qt::SHIFT + Qt::Key_F9);
88 d->searchModificationHelper = searchModificationHelper;
89
90 const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
91
92 QWidget* const mainView = new QWidget(this);
93 QScrollArea* const scrollArea = new QScrollArea(this);
94 QVBoxLayout* const mainLayout = new QVBoxLayout(this);
95
96 mainLayout->addWidget(scrollArea);
97 mainLayout->setContentsMargins(0, 0, spacing, 0);
98 scrollArea->setWidget(mainView);
99 scrollArea->setWidgetResizable(true);
100
101 model->setColumnHeader(getCaption());
102
103 QVBoxLayout* const vlay = new QVBoxLayout;
104 d->tagFolderView = new TagFolderView(this, model);
105 d->tagFolderView->setConfigGroup(getConfigGroup());
106 d->tagFolderView->setAlbumManagerCurrentAlbum(true);
107 d->tagFolderView->setShowDeleteFaceTagsAction(true);
108
109 d->tagFolderView->filteredModel()->listOnlyTagsWithProperty(TagPropertyName::person());
110 d->tagFolderView->filteredModel()->setFilterBehavior(AlbumFilterModel::StrictFiltering);
111
112 d->tagSearchBar = new SearchTextBarDb(this, QLatin1String("ItemIconViewPeopleSearchBar"));
113 d->tagSearchBar->setHighlightOnResult(true);
114 d->tagSearchBar->setModel(d->tagFolderView->filteredModel(),
115 AbstractAlbumModel::AlbumIdRole, AbstractAlbumModel::AlbumTitleRole);
116 d->tagSearchBar->setFilterModel(d->tagFolderView->albumFilterModel());
117
118 d->settingsWdg = new FaceScanWidget(this);
119
120 d->rescanButton = new QPushButton;
121 d->rescanButton->setText(i18n("Scan collection for faces"));
122
123 vlay->addWidget(d->tagFolderView, 10);
124 vlay->addWidget(d->tagSearchBar);
125 vlay->addWidget(d->settingsWdg);
126 vlay->addWidget(d->rescanButton);
127 vlay->setContentsMargins(spacing, spacing, spacing, spacing);
128
129 mainView->setLayout(vlay);
130
131 connect(d->tagFolderView, SIGNAL(signalFindDuplicates(QList<TAlbum*>)),
132 this, SIGNAL(signalFindDuplicates(QList<TAlbum*>)));
133
134 connect(d->rescanButton, SIGNAL(pressed()),
135 this, SLOT(slotScanForFaces()) );
136 }
137
~PeopleSideBarWidget()138 PeopleSideBarWidget::~PeopleSideBarWidget()
139 {
140 delete d;
141 }
142
slotInit()143 void PeopleSideBarWidget::slotInit()
144 {
145 loadState();
146 }
147
setActive(bool active)148 void PeopleSideBarWidget::setActive(bool active)
149 {
150 emit requestFaceMode(active);
151
152 if (active)
153 {
154 d->tagFolderView->setCurrentAlbums(QList<Album*>() << d->tagFolderView->currentAlbum());
155
156 if (!ApplicationSettings::instance()->getHelpBoxNotificationSeen())
157 {
158 QString msg = i18n("Welcome to Face Management in digiKam. "
159 "If this is your first time using this feature, please consider "
160 "using the Help Box in the Bottom Left Side Panel.");
161 emit signalNotificationError(msg, DNotificationWidget::Information);
162 ApplicationSettings::instance()->setHelpBoxNotificationSeen(true);
163 }
164 }
165 }
166
doLoadState()167 void PeopleSideBarWidget::doLoadState()
168 {
169 d->tagFolderView->loadState();
170 d->settingsWdg->loadState();
171 }
172
doSaveState()173 void PeopleSideBarWidget::doSaveState()
174 {
175 d->tagFolderView->saveState();
176 d->settingsWdg->saveState();
177 }
178
applySettings()179 void PeopleSideBarWidget::applySettings()
180 {
181 ApplicationSettings* const settings = ApplicationSettings::instance();
182 d->tagFolderView->setExpandNewCurrentItem(settings->getExpandNewCurrentItem());
183 }
184
changeAlbumFromHistory(const QList<Album * > & album)185 void PeopleSideBarWidget::changeAlbumFromHistory(const QList<Album*>& album)
186 {
187 d->tagFolderView->setCurrentAlbums(album);
188 }
189
slotScanForFaces()190 void PeopleSideBarWidget::slotScanForFaces()
191 {
192 FaceScanSettings faceScanSettings = d->settingsWdg->settings();
193
194 if (!d->settingsWdg->settingsConflicted())
195 {
196 FacesDetector* const tool = new FacesDetector(faceScanSettings);
197 tool->start();
198
199 d->settingsWdg->setEnabled(false);
200 d->rescanButton->setEnabled(false);
201
202 connect(tool, SIGNAL(signalComplete()),
203 this, SLOT(slotScanComplete()));
204
205 connect(tool, SIGNAL(signalCanceled()),
206 this, SLOT(slotScanComplete()));
207 }
208 else
209 {
210 emit signalNotificationError(i18n("Face recognition is aborted, because "
211 "there are no identities to recognize. "
212 "Please add new identities."),
213 DNotificationWidget::Information);
214 }
215 }
216
slotScanComplete()217 void PeopleSideBarWidget::slotScanComplete()
218 {
219 d->settingsWdg->setEnabled(true);
220 d->rescanButton->setEnabled(true);
221 }
222
getIcon()223 const QIcon PeopleSideBarWidget::getIcon()
224 {
225 return QIcon::fromTheme(QLatin1String("edit-image-face-show"));
226 }
227
getCaption()228 const QString PeopleSideBarWidget::getCaption()
229 {
230 return i18nc("Browse images sorted by depicted people", "People");
231 }
232
233 } // namespace Digikam
234