1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2005-05-07
7 * Description : a dialog to delete item.
8 *
9 * Copyright (C) 2004 by Michael Pyne <michael dot pyne at kdemail dot net>
10 * Copyright (C) 2006 by Ian Monroe <ian at monroe dot nu>
11 * Copyright (C) 2009 by Andi Clemens <andi dot clemens at gmail dot com>
12 * Copyright (C) 2006-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
13 * Copyright (C) 2008-2021 by Gilles Caulier <caulier dot gilles 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 "deletedialog.h"
29
30 // Qt includes
31
32 #include <QStackedWidget>
33 #include <QPainter>
34 #include <QLayout>
35 #include <QLabel>
36 #include <QTimer>
37 #include <QCheckBox>
38 #include <QKeyEvent>
39 #include <QHeaderView>
40 #include <QApplication>
41 #include <QStyle>
42 #include <QStandardPaths>
43 #include <QIcon>
44 #include <QDialogButtonBox>
45 #include <QVBoxLayout>
46 #include <QPushButton>
47
48 // KDE includes
49
50 #include <klocalizedstring.h>
51
52 // Local includes
53
54 #include "digikam_debug.h"
55 #include "applicationsettings.h"
56 #include "coredburl.h"
57
58 namespace Digikam
59 {
60
61 class Q_DECL_HIDDEN DeleteItem::Private
62 {
63
64 public:
65
Private()66 explicit Private()
67 : hasThumb(false)
68 {
69 }
70
71 bool hasThumb;
72
73 QUrl url;
74 };
75
DeleteItem(QTreeWidget * const parent,const QUrl & url)76 DeleteItem::DeleteItem(QTreeWidget* const parent, const QUrl& url)
77 : QTreeWidgetItem(parent),
78 d (new Private)
79 {
80 d->url = url;
81
82 if (d->url.scheme() == QLatin1String("digikamalbums"))
83 {
84 if (CoreDbUrl(d->url).isAlbumUrl())
85 {
86 setThumb(QIcon::fromTheme(QLatin1String("folder")).pixmap(parent->iconSize().width()));
87 }
88 else
89 {
90 setThumb(QIcon::fromTheme(QLatin1String("tag")).pixmap(parent->iconSize().width()));
91 }
92 }
93 else
94 {
95 setThumb(QIcon::fromTheme(QLatin1String("view-preview")).pixmap(parent->iconSize().width(), QIcon::Disabled), false);
96 }
97
98 setText(1, fileUrl());
99 }
100
~DeleteItem()101 DeleteItem::~DeleteItem()
102 {
103 delete d;
104 }
105
hasValidThumbnail() const106 bool DeleteItem::hasValidThumbnail() const
107 {
108 return d->hasThumb;
109 }
110
url() const111 QUrl DeleteItem::url() const
112 {
113 return d->url;
114 }
115
fileUrl() const116 QString DeleteItem::fileUrl() const
117 {
118 if (d->url.isLocalFile())
119 {
120 return (d->url.toLocalFile());
121 }
122 else if (d->url.scheme() == QLatin1String("digikamalbums"))
123 {
124 return (CoreDbUrl(d->url).fileUrl().toLocalFile());
125 }
126
127 return (d->url.toDisplayString());
128 }
129
setThumb(const QPixmap & pix,bool hasThumb)130 void DeleteItem::setThumb(const QPixmap& pix, bool hasThumb)
131 {
132 int iconSize = treeWidget()->iconSize().width();
133 QPixmap pixmap(iconSize+2, iconSize+2);
134 pixmap.fill(Qt::transparent);
135 QPainter p(&pixmap);
136 p.drawPixmap((pixmap.width()/2) - (pix.width()/2),
137 (pixmap.height()/2) - (pix.height()/2), pix);
138
139 QIcon icon = QIcon(pixmap);
140
141 // We make sure the preview icon stays the same regardless of the role
142
143 icon.addPixmap(pixmap, QIcon::Selected, QIcon::On);
144 icon.addPixmap(pixmap, QIcon::Selected, QIcon::Off);
145 icon.addPixmap(pixmap, QIcon::Active, QIcon::On);
146 icon.addPixmap(pixmap, QIcon::Active, QIcon::Off);
147 icon.addPixmap(pixmap, QIcon::Normal, QIcon::On);
148 icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off);
149 setIcon(0, icon);
150
151 d->hasThumb = hasThumb;
152 }
153
154 //----------------------------------------------------------------------------
155
156 class Q_DECL_HIDDEN DeleteItemList::Private
157 {
158
159 public:
160
Private()161 explicit Private()
162 : iconSize (64),
163 thumbLoadThread(nullptr)
164 {
165 }
166
167 const int iconSize;
168
169 ThumbnailLoadThread* thumbLoadThread;
170 };
171
DeleteItemList(QWidget * const parent)172 DeleteItemList::DeleteItemList(QWidget* const parent)
173 : QTreeWidget(parent),
174 d (new Private)
175 {
176 d->thumbLoadThread = ThumbnailLoadThread::defaultThread();
177
178 setRootIsDecorated(false);
179 setSelectionMode(QAbstractItemView::SingleSelection);
180 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
181 setAllColumnsShowFocus(true);
182 setIconSize(QSize(d->iconSize, d->iconSize));
183 setColumnCount(2);
184 setHeaderLabels(QStringList() << i18n("Thumb") << i18n("Path"));
185 header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
186 header()->setSectionResizeMode(1, QHeaderView::Stretch);
187 setToolTip(i18n("List of items that are about to be deleted."));
188 setWhatsThis(i18n("This is the list of items that are about to be deleted."));
189
190 connect(d->thumbLoadThread, SIGNAL(signalThumbnailLoaded(LoadingDescription,QPixmap)),
191 this, SLOT(slotThumbnailLoaded(LoadingDescription,QPixmap)));
192 }
193
~DeleteItemList()194 DeleteItemList::~DeleteItemList()
195 {
196 delete d;
197 }
198
slotThumbnailLoaded(const LoadingDescription & desc,const QPixmap & pix)199 void DeleteItemList::slotThumbnailLoaded(const LoadingDescription& desc, const QPixmap& pix)
200 {
201 QTreeWidgetItemIterator it(this);
202
203 while (*it)
204 {
205 DeleteItem* const item = dynamic_cast<DeleteItem*>(*it);
206
207 if (item && (item->fileUrl() == desc.filePath))
208 {
209 if (!pix.isNull())
210 {
211 item->setThumb(pix.scaled(d->iconSize, d->iconSize, Qt::KeepAspectRatio));
212 }
213
214 return;
215 }
216
217 ++it;
218 }
219 }
220
drawRow(QPainter * p,const QStyleOptionViewItem & opt,const QModelIndex & index) const221 void DeleteItemList::drawRow(QPainter* p, const QStyleOptionViewItem& opt, const QModelIndex& index) const
222 {
223 DeleteItem* const item = dynamic_cast<DeleteItem*>(itemFromIndex(index));
224
225 if (item && !item->hasValidThumbnail())
226 {
227 d->thumbLoadThread->find(ThumbnailIdentifier(item->fileUrl()));
228 }
229
230 QTreeWidget::drawRow(p, opt, index);
231 }
232
233 //----------------------------------------------------------------------------
234
235 class Q_DECL_HIDDEN DeleteWidget::Private
236 {
237 public:
238
Private()239 explicit Private()
240 : checkBoxStack (nullptr),
241 warningIcon (nullptr),
242 deleteText (nullptr),
243 numFiles (nullptr),
244 shouldDelete (nullptr),
245 doNotShowAgain(nullptr),
246 fileList (nullptr),
247 listMode (DeleteDialogMode::Files),
248 deleteMode (DeleteDialogMode::UseTrash)
249 {
250 }
251
252 QStackedWidget* checkBoxStack;
253
254 QLabel* warningIcon;
255 QLabel* deleteText;
256 QLabel* numFiles;
257
258 QCheckBox* shouldDelete;
259 QCheckBox* doNotShowAgain;
260
261 QTreeWidget* fileList;
262
263 DeleteDialogMode::ListMode listMode;
264 DeleteDialogMode::DeleteMode deleteMode;
265 };
266
DeleteWidget(QWidget * const parent)267 DeleteWidget::DeleteWidget(QWidget* const parent)
268 : QWidget(parent),
269 d (new Private)
270 {
271 setObjectName(QLatin1String("DeleteDialogBase"));
272
273 resize(540, 370);
274 setMinimumSize(QSize(420, 320));
275
276 const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
277
278 d->checkBoxStack = new QStackedWidget(this);
279 QLabel* const logo = new QLabel(this);
280 logo->setPixmap(QIcon::fromTheme(QLatin1String("digikam")).pixmap(QSize(48,48)));
281
282 d->warningIcon = new QLabel(this);
283 d->warningIcon->setWordWrap(false);
284
285 QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
286 sizePolicy.setHeightForWidth(d->warningIcon->sizePolicy().hasHeightForWidth());
287 sizePolicy.setHorizontalStretch(0);
288 sizePolicy.setVerticalStretch(0);
289 d->warningIcon->setSizePolicy(sizePolicy);
290
291 d->deleteText = new QLabel(this);
292 d->deleteText->setAlignment(Qt::AlignCenter);
293 d->deleteText->setWordWrap(true);
294
295 QHBoxLayout* const hbox = new QHBoxLayout();
296 hbox->setSpacing(spacing);
297 hbox->setContentsMargins(QMargins());
298 hbox->addWidget(logo);
299 hbox->addWidget(d->deleteText, 10);
300 hbox->addWidget(d->warningIcon);
301
302 d->fileList = new DeleteItemList(this);
303 d->numFiles = new QLabel(this);
304 d->numFiles->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
305 d->numFiles->setWordWrap(false);
306
307 d->shouldDelete = new QCheckBox(d->checkBoxStack);
308 d->shouldDelete->setGeometry(QRect(0, 0, 542, 32));
309 d->shouldDelete->setToolTip(i18n("If checked, files will be permanently removed instead of being placed "
310 "in the Trash."));
311 d->shouldDelete->setWhatsThis(i18n("<p>If this box is checked, items will be "
312 "<b>permanently removed</b> instead of "
313 "being placed in the Trash.</p>"
314 "<p><em>Use this option with caution</em>: most filesystems "
315 "are unable to "
316 "undelete deleted items reliably.</p>"));
317 d->shouldDelete->setText(i18n("&Delete items instead of moving them to the trash"));
318
319 connect(d->shouldDelete, SIGNAL(toggled(bool)),
320 this, SLOT(slotShouldDelete(bool)));
321
322 d->doNotShowAgain = new QCheckBox(d->checkBoxStack);
323 d->doNotShowAgain->setGeometry(QRect(0, 0, 100, 30));
324 d->doNotShowAgain->setText(i18n("Do not &ask again"));
325
326 QVBoxLayout* const vbox = new QVBoxLayout(this);
327 vbox->setContentsMargins(QMargins());
328 vbox->setSpacing(spacing);
329 vbox->addLayout(hbox);
330 vbox->addWidget(d->fileList, 10);
331 vbox->addWidget(d->numFiles);
332 vbox->addWidget(d->checkBoxStack);
333
334 d->checkBoxStack->addWidget(d->shouldDelete);
335 d->checkBoxStack->addWidget(d->doNotShowAgain);
336 d->checkBoxStack->setCurrentWidget(d->shouldDelete);
337
338 bool deleteInstead = !ApplicationSettings::instance()->getUseTrash();
339 slotShouldDelete(deleteInstead);
340 d->shouldDelete->setChecked(deleteInstead);
341 }
342
~DeleteWidget()343 DeleteWidget::~DeleteWidget()
344 {
345 delete d;
346 }
347
setUrls(const QList<QUrl> & urls)348 void DeleteWidget::setUrls(const QList<QUrl>& urls)
349 {
350 d->fileList->clear();
351
352 foreach (const QUrl& url, urls)
353 {
354 new DeleteItem(d->fileList, url);
355 }
356
357 updateText();
358 }
359
slotShouldDelete(bool shouldDelete)360 void DeleteWidget::slotShouldDelete(bool shouldDelete)
361 {
362 setDeleteMode(shouldDelete ? DeleteDialogMode::DeletePermanently : DeleteDialogMode::UseTrash);
363 }
364
setDeleteMode(DeleteDialogMode::DeleteMode deleteMode)365 void DeleteWidget::setDeleteMode(DeleteDialogMode::DeleteMode deleteMode)
366 {
367 d->deleteMode = deleteMode;
368 updateText();
369 }
370
setListMode(DeleteDialogMode::ListMode listMode)371 void DeleteWidget::setListMode(DeleteDialogMode::ListMode listMode)
372 {
373 d->listMode = listMode;
374 updateText();
375 }
376
updateText()377 void DeleteWidget::updateText()
378 {
379 // set "do not ask again checkbox text
380
381 if (d->deleteMode == DeleteDialogMode::DeletePermanently)
382 {
383 d->doNotShowAgain->setToolTip(i18n("If checked, this dialog will no longer be shown, and items will "
384 "be directly and permanently deleted."));
385 d->doNotShowAgain->setWhatsThis(i18n("If this box is checked, this dialog will no longer be shown, "
386 "and items will be directly and permanently deleted."));
387 }
388 else
389 {
390 d->doNotShowAgain->setToolTip(i18n("If checked, this dialog will no longer be shown, and items will "
391 "be directly moved to the Trash."));
392 d->doNotShowAgain->setWhatsThis(i18n("If this box is checked, this dialog will no longer be shown, "
393 "and items will be directly moved to the Trash."));
394 }
395
396 switch (d->listMode)
397 {
398 case DeleteDialogMode::Files:
399 {
400 // Delete files
401
402 if (d->deleteMode == DeleteDialogMode::DeletePermanently)
403 {
404 d->deleteText->setText(i18n("These items will be <b>permanently "
405 "deleted</b> from your hard disk."));
406 d->warningIcon->setPixmap(QIcon::fromTheme(QLatin1String("dialog-warning")).pixmap(48));
407 }
408 else
409 {
410 d->deleteText->setText(i18n("These items will be moved to Trash."));
411 d->warningIcon->setPixmap(QIcon::fromTheme(QLatin1String("user-trash")).pixmap(48));
412 d->numFiles->setText(i18np("<b>1</b> item selected.", "<b>%1</b> items selected.",
413 d->fileList->topLevelItemCount()));
414 }
415
416 break;
417 }
418
419 case DeleteDialogMode::Albums:
420 {
421 // Delete albums = folders
422
423 if (d->deleteMode == DeleteDialogMode::DeletePermanently)
424 {
425 d->deleteText->setText(i18n("These albums will be <b>permanently "
426 "deleted</b> from your hard disk."));
427 d->warningIcon->setPixmap(QIcon::fromTheme(QLatin1String("dialog-warning")).pixmap(48));
428 }
429 else
430 {
431 d->deleteText->setText(i18n("These albums will be moved to Trash."));
432 d->warningIcon->setPixmap(QIcon::fromTheme(QLatin1String("user-trash")).pixmap(48));
433 }
434
435 d->numFiles->setText(i18np("<b>1</b> album selected.", "<b>%1</b> albums selected.",
436 d->fileList->topLevelItemCount()));
437 break;
438 }
439
440 case DeleteDialogMode::Subalbums:
441 {
442 // As above, but display additional warning
443
444 if (d->deleteMode == DeleteDialogMode::DeletePermanently)
445 {
446 d->deleteText->setText(i18n("<p>These albums will be <b>permanently "
447 "deleted</b> from your hard disk.</p>"
448 "<p>Note that <b>all subalbums</b> "
449 "are included in this list and will "
450 "be deleted permanently as well.</p>"));
451 d->warningIcon->setPixmap(QIcon::fromTheme(QLatin1String("dialog-warning")).pixmap(48));
452 }
453 else
454 {
455 d->deleteText->setText(i18n("<p>These albums will be moved to Trash.</p>"
456 "<p>Note that <b>all subalbums</b> "
457 "are included in this list and will "
458 "be moved to Trash as well.</p>"));
459 d->warningIcon->setPixmap(QIcon::fromTheme(QLatin1String("user-trash")).pixmap(48));
460 }
461
462 d->numFiles->setText(i18np("<b>1</b> album selected.", "<b>%1</b> albums selected.",
463 d->fileList->topLevelItemCount()));
464 break;
465 }
466 }
467 }
468
469 //----------------------------------------------------------------------------
470
471 class Q_DECL_HIDDEN DeleteDialog::Private
472 {
473 public:
474
Private()475 explicit Private()
476 : saveShouldDeleteUserPreference(true),
477 saveDoNotShowAgainTrash (false),
478 saveDoNotShowAgainPermanent (false),
479 page (nullptr),
480 buttons (nullptr)
481 {
482 }
483
484 bool saveShouldDeleteUserPreference;
485 bool saveDoNotShowAgainTrash;
486 bool saveDoNotShowAgainPermanent;
487
488 DeleteWidget* page;
489
490 QDialogButtonBox* buttons;
491 };
492
DeleteDialog(QWidget * const parent)493 DeleteDialog::DeleteDialog(QWidget* const parent)
494 : QDialog(parent),
495 d (new Private)
496 {
497 setModal(true);
498
499 d->buttons = new QDialogButtonBox(QDialogButtonBox::Apply | QDialogButtonBox::Cancel, this);
500 d->buttons->button(QDialogButtonBox::Apply)->setDefault(true);
501
502 d->page = new DeleteWidget(this);
503 d->page->setMinimumSize(400, 300);
504
505 QVBoxLayout* const vbx = new QVBoxLayout(this);
506 vbx->addWidget(d->page);
507 vbx->addWidget(d->buttons);
508 setLayout(vbx);
509
510 setMinimumSize(410, 326);
511 adjustSize();
512
513 slotShouldDelete(shouldDelete());
514
515 connect(d->page->d->shouldDelete, SIGNAL(toggled(bool)),
516 this, SLOT(slotShouldDelete(bool)));
517
518 connect(d->buttons->button(QDialogButtonBox::Apply), SIGNAL(clicked()),
519 this, SLOT(slotUser1Clicked()));
520
521 connect(d->buttons->button(QDialogButtonBox::Cancel), SIGNAL(clicked()),
522 this, SLOT(reject()));
523 }
524
~DeleteDialog()525 DeleteDialog::~DeleteDialog()
526 {
527 delete d;
528 }
529
confirmDeleteList(const QList<QUrl> & condemnedFiles,DeleteDialogMode::ListMode listMode,DeleteDialogMode::DeleteMode deleteMode)530 bool DeleteDialog::confirmDeleteList(const QList<QUrl>& condemnedFiles,
531 DeleteDialogMode::ListMode listMode,
532 DeleteDialogMode::DeleteMode deleteMode)
533 {
534 setUrls(condemnedFiles);
535 presetDeleteMode(deleteMode);
536 setListMode(listMode);
537
538 if (deleteMode == DeleteDialogMode::NoChoiceTrash)
539 {
540 if (!ApplicationSettings::instance()->getShowTrashDeleteDialog())
541 {
542 return true;
543 }
544 }
545 else if (deleteMode == DeleteDialogMode::NoChoiceDeletePermanently)
546 {
547 if (!ApplicationSettings::instance()->getShowPermanentDeleteDialog())
548 {
549 return true;
550 }
551 }
552
553 return (exec() == QDialog::Accepted);
554 }
555
setUrls(const QList<QUrl> & urls)556 void DeleteDialog::setUrls(const QList<QUrl>& urls)
557 {
558 d->page->setUrls(urls);
559 }
560
slotUser1Clicked()561 void DeleteDialog::slotUser1Clicked()
562 {
563 // Save user's preference
564
565 ApplicationSettings* const settings = ApplicationSettings::instance();
566
567 if (d->saveShouldDeleteUserPreference)
568 {
569 settings->setUseTrash(!shouldDelete());
570 }
571
572 if (d->saveDoNotShowAgainTrash)
573 {
574 qCDebug(DIGIKAM_GENERAL_LOG) << "setShowTrashDeleteDialog " << !d->page->d->doNotShowAgain->isChecked();
575 settings->setShowTrashDeleteDialog(!d->page->d->doNotShowAgain->isChecked());
576 }
577
578 if (d->saveDoNotShowAgainPermanent)
579 {
580 qCDebug(DIGIKAM_GENERAL_LOG) << "setShowPermanentDeleteDialog " << !d->page->d->doNotShowAgain->isChecked();
581 settings->setShowPermanentDeleteDialog(!d->page->d->doNotShowAgain->isChecked());
582 }
583
584 settings->saveSettings();
585
586 QDialog::accept();
587 }
588
shouldDelete() const589 bool DeleteDialog::shouldDelete() const
590 {
591 return d->page->d->shouldDelete->isChecked();
592 }
593
slotShouldDelete(bool shouldDelete)594 void DeleteDialog::slotShouldDelete(bool shouldDelete)
595 {
596 // This is called once from constructor, and then when the user changed the checkbox state.
597 // In that case, save the user's preference.
598
599 d->saveShouldDeleteUserPreference = true;
600
601 d->buttons->button(QDialogButtonBox::Apply)->setText(shouldDelete ? i18n("&Delete")
602 : i18n("&Move to Trash"));
603 d->buttons->button(QDialogButtonBox::Apply)->setIcon(shouldDelete ? QIcon::fromTheme(QLatin1String("edit-delete"))
604 : QIcon::fromTheme(QLatin1String("user-trash")));
605 }
606
presetDeleteMode(DeleteDialogMode::DeleteMode mode)607 void DeleteDialog::presetDeleteMode(DeleteDialogMode::DeleteMode mode)
608 {
609 switch (mode)
610 {
611 case DeleteDialogMode::NoChoiceTrash:
612 {
613 // access the widget directly, signals will be fired to DeleteDialog and DeleteWidget
614
615 d->page->d->shouldDelete->setChecked(false);
616 d->page->d->checkBoxStack->setCurrentWidget(d->page->d->doNotShowAgain);
617 d->saveDoNotShowAgainTrash = true;
618 break;
619 }
620
621 case DeleteDialogMode::NoChoiceDeletePermanently:
622 {
623 d->page->d->shouldDelete->setChecked(true);
624 d->page->d->checkBoxStack->setCurrentWidget(d->page->d->doNotShowAgain);
625 d->saveDoNotShowAgainPermanent = true;
626 /*
627 d->page->d->checkBoxStack->hide();
628 */
629 break;
630 }
631
632 case DeleteDialogMode::UserPreference:
633 {
634 break;
635 }
636
637 case DeleteDialogMode::UseTrash:
638 case DeleteDialogMode::DeletePermanently:
639 {
640 // toggles signals which do the rest
641
642 d->page->d->shouldDelete->setChecked(mode == DeleteDialogMode::DeletePermanently);
643
644 // the preference set by this preset method will be ignored
645 // for the next DeleteDialog instance and not stored as user preference.
646 // Only if the user once changes this value, it will be taken as user preference.
647
648 d->saveShouldDeleteUserPreference = false;
649 break;
650 }
651 }
652 }
653
setListMode(DeleteDialogMode::ListMode mode)654 void DeleteDialog::setListMode(DeleteDialogMode::ListMode mode)
655 {
656 d->page->setListMode(mode);
657
658 switch (mode)
659 {
660 case DeleteDialogMode::Files:
661 {
662 setWindowTitle(i18n("About to delete selected items"));
663 break;
664 }
665
666 case DeleteDialogMode::Albums:
667 case DeleteDialogMode::Subalbums:
668 {
669 setWindowTitle(i18n("About to delete selected albums"));
670 break;
671 }
672 }
673 }
674
keyPressEvent(QKeyEvent * e)675 void DeleteDialog::keyPressEvent(QKeyEvent* e)
676 {
677 if (e->modifiers() == 0)
678 {
679 if ((e->key() == Qt::Key_Enter) || (e->key() == Qt::Key_Return))
680 {
681 if (d->buttons->button(QDialogButtonBox::Apply)->hasFocus())
682 {
683 e->accept();
684 d->buttons->button(QDialogButtonBox::Apply)->animateClick();
685 return;
686 }
687 else if (d->buttons->button(QDialogButtonBox::Cancel)->hasFocus())
688 {
689 e->accept();
690 d->buttons->button(QDialogButtonBox::Cancel)->animateClick();
691 return;
692 }
693 }
694 }
695
696 QDialog::keyPressEvent(e);
697 }
698
699 } // namespace Digikam
700