File indexing completed on 2024-04-28 15:39:46
0001 // SPDX-FileCopyrightText: 2009 Laurent Montel <montel@kde.org> 0002 // SPDX-FileCopyrightText: 2009-2010 Hassan Ibraheem <hasan.ibraheem@gmail.com> 0003 // SPDX-FileCopyrightText: 2010 Tuomas Suutari <tuomas@nepnep.net> 0004 // SPDX-FileCopyrightText: 2010-2022 Jesper K. Pedersen <jesper.pedersen@kdab.com> 0005 // SPDX-FileCopyrightText: 2013-2024 Johannes Zarl-Zierl <johannes@zarl-zierl.at> 0006 // SPDX-FileCopyrightText: 2014-2019 Tobias Leupold <tl@stonemx.de> 0007 // 0008 // SPDX-License-Identifier: GPL-2.0-or-later 0009 0010 #include "ImagePreviewWidget.h" 0011 0012 #include <DB/ImageDB.h> 0013 #include <DB/ImageInfo.h> 0014 #include <MainWindow/DeleteDialog.h> 0015 0016 #include <KActionCollection> 0017 #include <KLocalizedString> 0018 #include <QApplication> 0019 #include <QCheckBox> 0020 #include <QComboBox> 0021 #include <QHBoxLayout> 0022 #include <QPushButton> 0023 #include <QVBoxLayout> 0024 #include <QWidget> 0025 0026 using namespace AnnotationDialog; 0027 0028 ImagePreviewWidget::ImagePreviewWidget(KActionCollection *actions) 0029 : QWidget() 0030 , m_singleEdit(false) 0031 , m_actions(actions) 0032 { 0033 Q_ASSERT(actions); 0034 QVBoxLayout *layout = new QVBoxLayout(this); 0035 m_preview = new ImagePreview(this); 0036 layout->addWidget(m_preview, 1); 0037 connect(this, &ImagePreviewWidget::areaVisibilityChanged, m_preview, &ImagePreview::setAreaCreationEnabled); 0038 0039 m_controlWidget = new QWidget; 0040 layout->addWidget(m_controlWidget); 0041 QVBoxLayout *controlLayout = new QVBoxLayout(m_controlWidget); 0042 QHBoxLayout *controlButtonsLayout = new QHBoxLayout; 0043 controlLayout->addLayout(controlButtonsLayout); 0044 controlButtonsLayout->addStretch(1); 0045 0046 m_prevBut = new QPushButton(this); 0047 m_prevBut->setIcon(QIcon::fromTheme(QString::fromLatin1("arrow-left"))); 0048 m_prevBut->setFixedWidth(40); 0049 controlButtonsLayout->addWidget(m_prevBut); 0050 m_prevBut->setToolTip(i18n("Annotate previous image (Page Up)")); 0051 0052 m_nextBut = new QPushButton(this); 0053 m_nextBut->setIcon(QIcon::fromTheme(QString::fromLatin1("arrow-right"))); 0054 m_nextBut->setFixedWidth(40); 0055 controlButtonsLayout->addWidget(m_nextBut); 0056 m_nextBut->setToolTip(i18n("Annotate next image (Page Down)")); 0057 0058 controlButtonsLayout->addStretch(1); 0059 0060 m_toggleFullscreenPreview = new QPushButton; 0061 m_toggleFullscreenPreview->setIcon(QIcon::fromTheme(QString::fromUtf8("file-zoom-in"))); 0062 m_toggleFullscreenPreview->setFixedWidth(40); 0063 0064 controlButtonsLayout->addWidget(m_toggleFullscreenPreview); 0065 connect(m_toggleFullscreenPreview, &QPushButton::clicked, this, &ImagePreviewWidget::toggleFullscreenPreview); 0066 0067 m_rotateLeft = new QPushButton(this); 0068 controlButtonsLayout->addWidget(m_rotateLeft); 0069 m_rotateLeft->setIcon(QIcon::fromTheme(QString::fromLatin1("object-rotate-left"))); 0070 m_rotateLeft->setFixedWidth(40); 0071 0072 m_rotateRight = new QPushButton(this); 0073 controlButtonsLayout->addWidget(m_rotateRight); 0074 m_rotateRight->setIcon(QIcon::fromTheme(QString::fromLatin1("object-rotate-right"))); 0075 m_rotateRight->setFixedWidth(40); 0076 0077 m_copyPreviousBut = new QPushButton(this); 0078 controlButtonsLayout->addWidget(m_copyPreviousBut); 0079 m_copyPreviousBut->setIcon(QIcon::fromTheme(QString::fromLatin1("go-bottom"))); 0080 m_copyPreviousBut->setFixedWidth(40); 0081 m_copyPreviousBut->setWhatsThis(i18nc("@info:whatsthis", "<para>Set the same tags on this image than on the previous one. The image date, label, rating, and description are left unchanged.</para>")); 0082 0083 m_toggleAreasBut = new QPushButton(this); 0084 controlButtonsLayout->addWidget(m_toggleAreasBut); 0085 m_toggleAreasBut->setIcon(QIcon::fromTheme(QString::fromLatin1("document-preview"))); 0086 m_toggleAreasBut->setFixedWidth(40); 0087 m_toggleAreasBut->setCheckable(true); 0088 m_toggleAreasBut->setChecked(true); 0089 // tooltip text is set in updateTexts() 0090 0091 controlButtonsLayout->addStretch(1); 0092 m_delBut = new QPushButton(this); 0093 m_delBut->setIcon(QIcon::fromTheme(QString::fromLatin1("edit-delete"))); 0094 controlButtonsLayout->addWidget(m_delBut); 0095 m_delBut->setAutoDefault(false); 0096 0097 controlButtonsLayout->addStretch(1); 0098 0099 connect(m_copyPreviousBut, &QPushButton::clicked, this, &ImagePreviewWidget::slotCopyPrevious); 0100 connect(m_delBut, &QPushButton::clicked, this, &ImagePreviewWidget::slotDeleteImage); 0101 connect(m_nextBut, &QPushButton::clicked, this, &ImagePreviewWidget::slotNext); 0102 connect(m_prevBut, &QPushButton::clicked, this, &ImagePreviewWidget::slotPrev); 0103 connect(m_rotateLeft, &QPushButton::clicked, this, &ImagePreviewWidget::rotateLeft); 0104 connect(m_rotateRight, &QPushButton::clicked, this, &ImagePreviewWidget::rotateRight); 0105 connect(m_toggleAreasBut, &QPushButton::clicked, this, &ImagePreviewWidget::slotShowAreas); 0106 0107 QHBoxLayout *defaultAreaCategoryLayout = new QHBoxLayout; 0108 controlLayout->addLayout(defaultAreaCategoryLayout); 0109 m_defaultAreaCategoryLabel = new QLabel(i18n("Category for new areas:")); 0110 m_defaultAreaCategoryLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); 0111 defaultAreaCategoryLayout->addWidget(m_defaultAreaCategoryLabel); 0112 m_defaultAreaCategory = new QComboBox(this); 0113 defaultAreaCategoryLayout->addWidget(m_defaultAreaCategory); 0114 0115 m_current = -1; 0116 updateTexts(); 0117 } 0118 0119 void ImagePreviewWidget::updatePositionableCategories(QList<QString> positionableCategories) 0120 { 0121 if (positionableCategories.size() <= 1) { 0122 m_defaultAreaCategoryLabel->hide(); 0123 m_defaultAreaCategory->hide(); 0124 } else { 0125 m_defaultAreaCategoryLabel->show(); 0126 m_defaultAreaCategory->show(); 0127 } 0128 0129 m_defaultAreaCategory->clear(); 0130 0131 for (const QString &categoryName : positionableCategories) { 0132 m_defaultAreaCategory->addItem(categoryName); 0133 } 0134 } 0135 0136 QString ImagePreviewWidget::defaultPositionableCategory() const 0137 { 0138 return m_defaultAreaCategory->currentText(); 0139 } 0140 0141 int ImagePreviewWidget::angle() const 0142 { 0143 return m_preview->angle(); 0144 } 0145 0146 void ImagePreviewWidget::anticipate(DB::ImageInfo &info1) 0147 { 0148 m_preview->anticipate(info1); 0149 } 0150 0151 void ImagePreviewWidget::configure(QList<DB::ImageInfo> *imageList, bool singleEdit) 0152 { 0153 m_imageList = imageList; 0154 m_current = 0; 0155 setImage(m_imageList->at(m_current)); 0156 m_singleEdit = singleEdit; 0157 0158 m_delBut->setEnabled(m_singleEdit); 0159 m_copyPreviousBut->setEnabled(m_singleEdit); 0160 m_rotateLeft->setEnabled(m_singleEdit); 0161 m_rotateRight->setEnabled(m_singleEdit); 0162 } 0163 0164 void ImagePreviewWidget::reconfigure(QList<DB::ImageInfo> *imageList, int index) 0165 { 0166 m_imageList = imageList; 0167 m_current = index; 0168 setImage(m_imageList->at(m_current)); 0169 } 0170 0171 void ImagePreviewWidget::slotPrev() 0172 { 0173 if ((m_current <= 0)) 0174 return; 0175 0176 m_current--; 0177 if (m_current != 0) 0178 m_preview->anticipate((*m_imageList)[m_current - 1]); 0179 setImage(m_imageList->at(m_current)); 0180 0181 Q_EMIT indexChanged(m_current); 0182 } 0183 0184 void ImagePreviewWidget::slotNext() 0185 { 0186 if ((m_current == -1) || (m_current == (int)m_imageList->count() - 1)) 0187 return; 0188 0189 m_current++; 0190 0191 if (m_current != (int)m_imageList->count() - 1) 0192 m_preview->anticipate((*m_imageList)[m_current + 1]); 0193 setImage(m_imageList->at(m_current)); 0194 0195 Q_EMIT indexChanged(m_current); 0196 } 0197 0198 void ImagePreviewWidget::slotCopyPrevious() 0199 { 0200 Q_EMIT copyPrevClicked(); 0201 } 0202 0203 void ImagePreviewWidget::rotateLeft() 0204 { 0205 rotate(-90); 0206 } 0207 0208 void ImagePreviewWidget::rotateRight() 0209 { 0210 rotate(90); 0211 } 0212 0213 void ImagePreviewWidget::rotate(int angle) 0214 { 0215 if (!m_singleEdit) 0216 return; 0217 0218 m_preview->rotate(angle); 0219 0220 Q_EMIT imageRotated(angle); 0221 } 0222 0223 void ImagePreviewWidget::slotDeleteImage() 0224 { 0225 if (!m_singleEdit) 0226 return; 0227 0228 MainWindow::DeleteDialog dialog(this); 0229 DB::ImageInfo info = m_imageList->at(m_current); 0230 0231 const DB::FileNameList deleteList = DB::FileNameList() << info.fileName(); 0232 0233 int ret = dialog.exec(deleteList); 0234 if (ret == QDialog::Rejected) // Delete Dialog rejected, do nothing 0235 return; 0236 } 0237 0238 void ImagePreviewWidget::setImage(const DB::ImageInfo &info) 0239 { 0240 m_nextBut->setEnabled(m_current != (int)m_imageList->count() - 1); 0241 m_prevBut->setEnabled(m_current != 0); 0242 m_copyPreviousBut->setEnabled(m_current != 0 && m_singleEdit); 0243 0244 m_preview->setImage(info); 0245 0246 Q_EMIT imageChanged(info); 0247 } 0248 0249 void ImagePreviewWidget::setImage(const int index) 0250 { 0251 m_current = index; 0252 0253 setImage(m_imageList->at(m_current)); 0254 } 0255 0256 void ImagePreviewWidget::setImage(const QString &fileName) 0257 { 0258 m_preview->setImage(fileName); 0259 m_current = -1; 0260 0261 m_nextBut->setEnabled(false); 0262 m_prevBut->setEnabled(false); 0263 m_rotateLeft->setEnabled(false); 0264 m_rotateRight->setEnabled(false); 0265 m_delBut->setEnabled(false); 0266 m_copyPreviousBut->setEnabled(false); 0267 } 0268 0269 ImagePreview *ImagePreviewWidget::preview() const 0270 { 0271 return m_preview; 0272 } 0273 0274 void ImagePreviewWidget::slotShowAreas(bool show) 0275 { 0276 // slot can be triggered by something else than the button: 0277 m_toggleAreasBut->setChecked(show); 0278 0279 Q_EMIT areaVisibilityChanged(show); 0280 } 0281 0282 bool ImagePreviewWidget::showAreas() const 0283 { 0284 return m_toggleAreasBut->isChecked(); 0285 } 0286 0287 void ImagePreviewWidget::canCreateAreas(bool state) 0288 { 0289 if (m_toggleAreasBut->isEnabled() != state) { 0290 m_toggleAreasBut->setChecked(state); 0291 m_toggleAreasBut->setEnabled(state); 0292 Q_EMIT areaVisibilityChanged(state); 0293 } 0294 m_preview->setAreaCreationEnabled(state); 0295 updateTexts(); 0296 } 0297 0298 void ImagePreviewWidget::updateTexts() 0299 { 0300 if (m_toggleAreasBut->isEnabled()) { 0301 // positionable tags enabled 0302 m_toggleAreasBut->setToolTip(i18nc("@info:tooltip", "Hide or show areas on the image")); 0303 } else { 0304 if (m_singleEdit) { 0305 // positionable tags disabled 0306 m_toggleAreasBut->setToolTip(i18nc("@info:tooltip", 0307 "If you enable <emphasis>positionable tags</emphasis> for at least one category in " 0308 "<interface>Settings|Configure KPhotoAlbum...|Categories</interface>, you can " 0309 "associate specific image areas with tags.")); 0310 } else { 0311 m_toggleAreasBut->setToolTip(i18nc("@info:tooltip", 0312 "Areas on an image can only be shown in single-image annotation mode.")); 0313 } 0314 } 0315 } 0316 0317 void ImagePreviewWidget::setSearchMode(bool state) 0318 { 0319 m_controlWidget->setVisible(!state); 0320 } 0321 0322 void ImagePreviewWidget::toggleFullscreenPreview() 0323 { 0324 Q_EMIT togglePreview(); 0325 } 0326 0327 void ImagePreviewWidget::setToggleFullscreenPreviewEnabled(bool state) 0328 { 0329 m_toggleFullscreenPreview->setEnabled(state); 0330 } 0331 0332 void AnnotationDialog::ImagePreviewWidget::showEvent(QShowEvent *) 0333 { 0334 auto setToolTip = [this](QWidget *widget, QString tooltip, const char *key) { 0335 const auto action = m_actions->action(QString::fromLatin1(key)); 0336 QKeySequence shortcut = action ? action->shortcut() : QKeySequence(); 0337 if (!shortcut.isEmpty()) 0338 tooltip += QString::fromLatin1(" (%1)").arg(shortcut.toString()); 0339 widget->setToolTip(tooltip); 0340 }; 0341 0342 setToolTip(m_toggleFullscreenPreview, i18nc("@info:tooltip", "Toggle full-screen preview"), "annotationdialog-toggle-viewer"); 0343 setToolTip(m_rotateLeft, i18nc("@info:tooltip", "Rotate counterclockwise"), "annotationdialog-rotate-left"); 0344 setToolTip(m_rotateRight, i18nc("@info:tooltip", "Rotate clockwise"), "annotationdialog-rotate-right"); 0345 setToolTip(m_copyPreviousBut, i18nc("@info:tooltip", "Copy tags from previously tagged image"), "annotationdialog-copy-previous"); 0346 setToolTip(m_delBut, i18nc("@info:tooltip", "Delete image"), "annotationdialog-delete-image"); 0347 } 0348 // vi:expandtab:tabstop=4 shiftwidth=4: 0349 0350 #include "moc_ImagePreviewWidget.cpp"