File indexing completed on 2024-04-28 04:21:22
0001 // SPDX-FileCopyrightText: 2003-2020 The KPhotoAlbum Development Team 0002 // SPDX-FileCopyrightText: 2022-2023 Johannes Zarl-Zierl <johannes@zarl-zierl.at> 0003 // 0004 // SPDX-License-Identifier: GPL-2.0-or-later 0005 0006 #include "ThumbnailDND.h" 0007 0008 #include "ThumbnailModel.h" 0009 #include "ThumbnailWidget.h" 0010 0011 #include <Browser/BrowserWidget.h> 0012 #include <DB/ImageDB.h> 0013 0014 #include <KLocalizedString> 0015 #include <KMessageBox> 0016 #include <QMimeData> 0017 #include <QTimer> 0018 #include <kwidgetsaddons_version.h> 0019 0020 ThumbnailView::ThumbnailDND::ThumbnailDND(ThumbnailFactory *factory) 0021 : ThumbnailComponent(factory) 0022 { 0023 } 0024 0025 void ThumbnailView::ThumbnailDND::contentsDragMoveEvent(QDragMoveEvent *event) 0026 { 0027 if (event->mimeData()->hasUrls() && widget()->m_selectionInteraction.isDragging()) 0028 event->accept(); 0029 else { 0030 event->ignore(); 0031 return; 0032 } 0033 0034 removeDropIndications(); 0035 0036 const DB::FileName fileName = widget()->mediaIdUnderCursor(); 0037 if (fileName.isNull()) { 0038 // cursor not in drop zone (e.g. empty space right/below of the thumbnails) 0039 return; 0040 } 0041 0042 const QRect rect = widget()->visualRect(widget()->indexUnderCursor()); 0043 0044 if ((event->pos().y() < 10)) 0045 widget()->scrollTo(widget()->indexUnderCursor(), QAbstractItemView::PositionAtCenter); 0046 if ((event->pos().y() > widget()->viewport()->visibleRegion().cbegin()->height() - 10)) 0047 widget()->scrollTo(widget()->indexUnderCursor(), QAbstractItemView::PositionAtCenter); 0048 const bool isLeftHalfOfItem = (event->pos().x() - rect.x() < rect.width() / 2); 0049 if (isLeftHalfOfItem) { 0050 model()->setLeftDropItem(fileName); 0051 const int index = model()->indexOf(fileName) - 1; 0052 if (index != -1) 0053 model()->setRightDropItem(model()->imageAt(index)); 0054 } 0055 0056 else { 0057 model()->setRightDropItem(fileName); 0058 const int index = model()->indexOf(fileName) + 1; 0059 if (index != model()->imageCount()) 0060 model()->setLeftDropItem(model()->imageAt(index)); 0061 } 0062 0063 model()->updateCell(model()->leftDropItem()); 0064 model()->updateCell(model()->rightDropItem()); 0065 } 0066 0067 void ThumbnailView::ThumbnailDND::contentsDragLeaveEvent(QDragLeaveEvent *) 0068 { 0069 removeDropIndications(); 0070 } 0071 0072 void ThumbnailView::ThumbnailDND::contentsDropEvent(QDropEvent *event) 0073 { 0074 if (model()->leftDropItem().isNull() && model()->rightDropItem().isNull()) { 0075 // drop outside drop zone 0076 removeDropIndications(); 0077 event->ignore(); 0078 } else { 0079 QTimer::singleShot(0, this, SLOT(realDropEvent())); 0080 } 0081 } 0082 0083 /** 0084 * Do the real work for the drop event. 0085 * We can't bring up the dialog in the contentsDropEvent, as Qt is still in drag and drop mode with a different cursor etc. 0086 * That's why we use a QTimer to get this call back executed. 0087 */ 0088 void ThumbnailView::ThumbnailDND::realDropEvent() 0089 { 0090 const QString question = i18n("<p><b>Really reorder thumbnails?</b></p>" 0091 "<p>By dragging images around in the thumbnail viewer, you actually reorder them. " 0092 "This is very useful where you do not know the exact date for the images. On the other hand, " 0093 "if the images have valid timestamps, you should use " 0094 "<b>Maintenance -> Sort All By Date and Time</b> or " 0095 "<b>View -> Sort Selected By Date and Time</b>.</p>"); 0096 0097 const QString title = i18nc("@title", "Reorder Thumbnails"); 0098 const QString dontAskAgainName = QString::fromLatin1("reorder_images"); 0099 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0100 const auto answer = KMessageBox::questionTwoActions(widget(), 0101 question, 0102 title, 0103 KStandardGuiItem::ok(), 0104 KStandardGuiItem::cancel(), dontAskAgainName); 0105 if (answer == KMessageBox::ButtonCode::PrimaryAction) { 0106 #else 0107 const auto answer = KMessageBox::questionYesNo(widget(), question, title, KStandardGuiItem::yes(), KStandardGuiItem::no(), dontAskAgainName); 0108 if (answer == KMessageBox::Yes) { 0109 #endif 0110 // expand selection so that stacks are always selected as a whole: 0111 const DB::FileNameList selected = widget()->selection(IncludeAllStacks); 0112 0113 // protect against self drop 0114 if (selected.indexOf(model()->leftDropItem()) == -1 && selected.indexOf(model()->rightDropItem()) == -1) { 0115 if (model()->rightDropItem().isNull()) { 0116 // We dropped onto the first image. 0117 DB::ImageDB::instance()->reorder(model()->leftDropItem(), selected, false); 0118 } else 0119 DB::ImageDB::instance()->reorder(model()->rightDropItem(), selected, true); 0120 0121 Browser::BrowserWidget::instance()->reload(); 0122 } 0123 } 0124 removeDropIndications(); 0125 } 0126 0127 void ThumbnailView::ThumbnailDND::removeDropIndications() 0128 { 0129 const DB::FileName left = model()->leftDropItem(); 0130 const DB::FileName right = model()->rightDropItem(); 0131 model()->setLeftDropItem(DB::FileName()); 0132 model()->setRightDropItem(DB::FileName()); 0133 0134 model()->updateCell(left); 0135 model()->updateCell(right); 0136 } 0137 0138 void ThumbnailView::ThumbnailDND::contentsDragEnterEvent(QDragEnterEvent *event) 0139 { 0140 if (event->mimeData()->hasUrls() && widget()->m_selectionInteraction.isDragging()) 0141 event->accept(); 0142 else 0143 event->ignore(); 0144 } 0145 0146 // vi:expandtab:tabstop=4 shiftwidth=4: 0147 0148 #include "moc_ThumbnailDND.cpp"