File indexing completed on 2025-01-19 03:53:22

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2003-03-09
0007  * Description : Album properties dialog.
0008  *
0009  * SPDX-FileCopyrightText: 2003-2004 by Renchi Raju <renchi dot raju at gmail dot com>
0010  * SPDX-FileCopyrightText: 2005      by Tom Albers <tomalbers at kde dot nl>
0011  * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "albumpropsedit.h"
0018 
0019 // Qt includes
0020 
0021 #include <QCheckBox>
0022 #include <QDateTime>
0023 #include <QGridLayout>
0024 #include <QLabel>
0025 #include <QPointer>
0026 #include <QApplication>
0027 #include <QStyle>
0028 #include <QComboBox>
0029 #include <QLineEdit>
0030 #include <QStandardPaths>
0031 #include <QMessageBox>
0032 #include <QDialogButtonBox>
0033 #include <QVBoxLayout>
0034 #include <QPushButton>
0035 
0036 // KDE includes
0037 
0038 #include <klocalizedstring.h>
0039 
0040 // Local includes
0041 
0042 #include "digikam_globals.h"
0043 #include "dlayoutbox.h"
0044 #include "coredb.h"
0045 #include "album.h"
0046 #include "albummanager.h"
0047 #include "applicationsettings.h"
0048 #include "collectionmanager.h"
0049 #include "coredbaccess.h"
0050 #include "dexpanderbox.h"
0051 #include "ddatepicker.h"
0052 #include "dtextedit.h"
0053 
0054 namespace Digikam
0055 {
0056 
0057 class Q_DECL_HIDDEN AlbumDatePicker : public DDatePicker
0058 {
0059     Q_OBJECT
0060 
0061 public:
0062 
0063     explicit AlbumDatePicker(QWidget* const widget)
0064         : DDatePicker(widget)
0065     {
0066     }
0067 
0068     ~AlbumDatePicker() override
0069     {
0070     }
0071 
0072     void dateLineEnterPressed()
0073     {
0074         lineEnterPressed();
0075     }
0076 };
0077 
0078 // --------------------------------------------------------------------------------
0079 
0080 class Q_DECL_HIDDEN AlbumPropsEdit::Private
0081 {
0082 
0083 public:
0084 
0085     explicit Private()
0086       : buttons         (nullptr),
0087         topLabel        (nullptr),
0088         categoryCombo   (nullptr),
0089         parentCombo     (nullptr),
0090         titleEdit       (nullptr),
0091         commentsEdit    (nullptr),
0092         datePicker      (nullptr),
0093         album           (nullptr)
0094     {
0095     }
0096 
0097     QDialogButtonBox* buttons;
0098 
0099     QLabel*           topLabel;
0100     QComboBox*        categoryCombo;
0101     QComboBox*        parentCombo;
0102     DTextEdit*        titleEdit;
0103     DPlainTextEdit*   commentsEdit;
0104 
0105     AlbumDatePicker*  datePicker;
0106 
0107     PAlbum*           album;
0108 };
0109 
0110 AlbumPropsEdit::AlbumPropsEdit(PAlbum* const album, bool create)
0111     : QDialog(nullptr),
0112       d      (new Private)
0113 {
0114     setModal(true);
0115     setWindowTitle(create ? i18nc("@title:window, album properties", "New Album") : i18nc("@title:window, album properties", "Edit Album"));
0116 
0117     d->buttons          = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
0118     d->buttons->button(QDialogButtonBox::Ok)->setDefault(true);
0119 
0120     d->album            = album;
0121     QWidget* const page = new QWidget(this);
0122     QLabel* const logo  = new QLabel(page);
0123 
0124     logo->setPixmap(QIcon::fromTheme(QLatin1String("digikam")).pixmap(QSize(48,48)));
0125 
0126     d->topLabel         = new QLabel(page);
0127     d->topLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
0128     d->topLabel->setWordWrap(false);
0129 
0130     if (create)
0131     {
0132         slotNewAlbumTextChanged(0);
0133     }
0134     else
0135     {
0136         d->topLabel->setText(i18nc("@label: album properties", "\"%1\"\nAlbum Properties", album->title()));
0137     }
0138 
0139     // --------------------------------------------------------
0140 
0141     DLineWidget* const topLine        = new DLineWidget(Qt::Horizontal);
0142 
0143     QLabel* const titleLabel          = new QLabel(page);
0144     titleLabel->setText(i18nc("@label: album properties", "&Title:"));
0145 
0146     d->titleEdit                      = new DTextEdit(page);
0147     d->titleEdit->setLinesVisible(1);
0148     d->titleEdit->setPlaceholderText(i18nc("@label: album properties", "Set here the new album title"));
0149     d->titleEdit->setIgnoredCharacters(QLatin1String("/:"));
0150     titleLabel->setBuddy(d->titleEdit);
0151 
0152     QLabel* const categoryLabel       = new QLabel(page);
0153     categoryLabel->setText(i18nc("@label: album properties", "Ca&tegory:"));
0154 
0155     d->categoryCombo                  = new QComboBox(page);
0156     d->categoryCombo->setEditable(true);
0157     categoryLabel->setBuddy(d->categoryCombo);
0158 
0159     QLabel* const parentLabel         = new QLabel(page);
0160     parentLabel->setText(i18nc("@label: album properties", "Ch&ild Of:"));
0161 
0162     d->parentCombo                    = new QComboBox(page);
0163     parentLabel->setBuddy(d->parentCombo);
0164 
0165     QLabel* const commentsLabel       = new QLabel(page);
0166     commentsLabel->setText(i18nc("@label: album properties", "Ca&ption:"));
0167 
0168     d->commentsEdit                   = new DPlainTextEdit(page);
0169     commentsLabel->setBuddy(d->commentsEdit);
0170     d->commentsEdit->setWordWrapMode(QTextOption::WordWrap);
0171     d->commentsEdit->setPlaceholderText(i18nc("@label: album properties", "Enter album caption here..."));
0172 
0173     QLabel* const dateLabel           = new QLabel(page);
0174     dateLabel->setText(i18nc("@label: album properties", "Album &date:"));
0175 
0176     d->datePicker                     = new AlbumDatePicker(page);
0177     dateLabel->setBuddy(d->datePicker);
0178 
0179     DHBox* const buttonRow            = new DHBox(page);
0180     QPushButton* const dateLowButton  = new QPushButton(i18nc("@action: Selects the date of the oldest image", "&Oldest"),  buttonRow);
0181     dateLowButton->setWhatsThis(i18nc("@info", "Use this button to select the date of the oldest image from album."));
0182     QPushButton* const dateAvgButton  = new QPushButton(i18nc("@action: Calculates the average date",          "&Average"), buttonRow);
0183     dateAvgButton->setWhatsThis(i18nc("@info", "Use this button to calculate the average date of images from album."));
0184     QPushButton* const dateHighButton = new QPushButton(i18nc("@action: Selects the date of the newest image", "Newest"),   buttonRow);
0185     dateHighButton->setWhatsThis(i18nc("@info", "Use this button to select the date of the newest image from album."));
0186 
0187     if (create)
0188     {
0189         setTabOrder(d->titleEdit,     d->categoryCombo);
0190         setTabOrder(d->categoryCombo, d->parentCombo);
0191         setTabOrder(d->parentCombo,   d->commentsEdit);
0192         setTabOrder(d->commentsEdit,  d->datePicker);
0193         dateHighButton->hide();
0194         dateAvgButton->hide();
0195         dateLowButton->hide();
0196     }
0197     else
0198     {
0199         setTabOrder(d->titleEdit,     d->categoryCombo);
0200         setTabOrder(d->categoryCombo, d->commentsEdit);
0201         setTabOrder(d->commentsEdit,  d->datePicker);
0202         d->parentCombo->hide();
0203         parentLabel->hide();
0204     }
0205 
0206     d->commentsEdit->setTabChangesFocus(true);
0207 
0208     // --------------------------------------------------------
0209 
0210     QGridLayout* const grid = new QGridLayout();
0211     grid->addWidget(logo,             0, 0, 1, 1);
0212     grid->addWidget(d->topLabel,      0, 1, 1, 1);
0213     grid->addWidget(topLine,          1, 0, 1, 2);
0214     grid->addWidget(titleLabel,       2, 0, 1, 1);
0215     grid->addWidget(d->titleEdit,     2, 1, 1, 1);
0216     grid->addWidget(categoryLabel,    3, 0, 1, 1);
0217     grid->addWidget(d->categoryCombo, 3, 1, 1, 1);
0218 
0219     if (create)
0220     {
0221         grid->addWidget(parentLabel,      4, 0, 1, 1);
0222         grid->addWidget(d->parentCombo,   4, 1, 1, 1);
0223         grid->addWidget(commentsLabel,    5, 0, 1, 1, Qt::AlignLeft | Qt::AlignTop);
0224         grid->addWidget(d->commentsEdit,  5, 1, 1, 1);
0225         grid->addWidget(dateLabel,        6, 0, 1, 1, Qt::AlignLeft | Qt::AlignTop);
0226         grid->addWidget(d->datePicker,    6, 1, 1, 1);
0227         grid->addWidget(buttonRow,        7, 1, 1, 1);
0228     }
0229     else
0230     {
0231         grid->addWidget(commentsLabel,    4, 0, 1, 1, Qt::AlignLeft | Qt::AlignTop);
0232         grid->addWidget(d->commentsEdit,  4, 1, 1, 1);
0233         grid->addWidget(dateLabel,        5, 0, 1, 1, Qt::AlignLeft | Qt::AlignTop);
0234         grid->addWidget(d->datePicker,    5, 1, 1, 1);
0235         grid->addWidget(buttonRow,        6, 1, 1, 1);
0236     }
0237 
0238     grid->setSpacing(qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0239                           QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)));
0240     grid->setContentsMargins(QMargins());
0241     page->setLayout(grid);
0242 
0243     QVBoxLayout* const vbx = new QVBoxLayout(this);
0244     vbx->addWidget(page);
0245     vbx->addWidget(d->buttons);
0246     setLayout(vbx);
0247 
0248     // Initialize ---------------------------------------------
0249 
0250     ApplicationSettings* const settings = ApplicationSettings::instance();
0251 
0252     if (settings)
0253     {
0254         d->categoryCombo->addItem(QString());
0255         QStringList Categories = settings->getAlbumCategoryNames();
0256         d->categoryCombo->addItems(Categories);
0257         int categoryIndex      = Categories.indexOf(album->category());
0258 
0259         if (categoryIndex != -1)
0260         {
0261             // + 1 because of the empty item
0262 
0263             d->categoryCombo->setCurrentIndex(categoryIndex + 1);
0264         }
0265     }
0266 
0267     if (create)
0268     {
0269         d->titleEdit->setText(i18nc("@label: album properties", "New Album"));
0270         d->datePicker->setDate(QDate::currentDate());
0271         d->parentCombo->addItem(i18nc("@item: album properties", "Selected Album (Default)"));
0272         d->parentCombo->addItem(i18nc("@item: top level folder of album","Root of current collection"));
0273     }
0274     else
0275     {
0276         d->titleEdit->setText(album->title());
0277         d->commentsEdit->setPlainText(album->caption());
0278         d->datePicker->setDate(album->date());
0279     }
0280 
0281     d->titleEdit->selectAll();
0282     d->titleEdit->setFocus();
0283 
0284     // -- slots connections -------------------------------------------
0285 
0286     connect(d->titleEdit, SIGNAL(textChanged()),
0287             this, SLOT(slotTitleChanged()));
0288 
0289     connect(dateLowButton, SIGNAL(clicked()),
0290             this, SLOT(slotDateLowButtonClicked()));
0291 
0292     connect(dateAvgButton, SIGNAL(clicked()),
0293             this, SLOT(slotDateAverageButtonClicked()));
0294 
0295     connect(dateHighButton, SIGNAL(clicked()),
0296             this, SLOT(slotDateHighButtonClicked()));
0297 
0298     connect(d->parentCombo, SIGNAL(activated(int)),
0299             this, SLOT(slotNewAlbumTextChanged(int)));
0300 
0301     connect(d->buttons->button(QDialogButtonBox::Ok), SIGNAL(clicked()),
0302             this, SLOT(accept()));
0303 
0304     connect(d->buttons->button(QDialogButtonBox::Cancel), SIGNAL(clicked()),
0305             this, SLOT(reject()));
0306 
0307     connect(d->buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()),
0308             this, SLOT(slotHelp()));
0309 }
0310 
0311 AlbumPropsEdit::~AlbumPropsEdit()
0312 {
0313     delete d;
0314 }
0315 
0316 QString AlbumPropsEdit::title() const
0317 {
0318     return d->titleEdit->text().trimmed();
0319 }
0320 
0321 QString AlbumPropsEdit::comments() const
0322 {
0323     return d->commentsEdit->toPlainText();
0324 }
0325 
0326 QDate AlbumPropsEdit::date() const
0327 {
0328     // See bug #267944 : update calendar view if user enter a date in text field.
0329 
0330     d->datePicker->dateLineEnterPressed();
0331 
0332     return d->datePicker->date();
0333 }
0334 
0335 int AlbumPropsEdit::parent() const
0336 {
0337     return d->parentCombo->currentIndex();
0338 }
0339 
0340 QString AlbumPropsEdit::category() const
0341 {
0342     QString name = d->categoryCombo->currentText();
0343 
0344     if (name.isEmpty())
0345     {
0346         name = i18nc("@info: album properties", "Uncategorized Album");
0347     }
0348 
0349     return name;
0350 }
0351 
0352 QStringList AlbumPropsEdit::albumCategories() const
0353 {
0354     QStringList Categories;
0355     ApplicationSettings* const settings = ApplicationSettings::instance();
0356 
0357     if (settings)
0358     {
0359         Categories = settings->getAlbumCategoryNames();
0360     }
0361 
0362     QString currentCategory = d->categoryCombo->currentText();
0363 
0364     if (Categories.indexOf(currentCategory) == -1)
0365     {
0366         Categories.append(currentCategory);
0367     }
0368 
0369     Categories.sort();
0370 
0371     return Categories;
0372 }
0373 
0374 bool AlbumPropsEdit::editProps(PAlbum* const album, QString& title,
0375                                QString& comments, QDate& date, QString& category,
0376                                QStringList& albumCategories)
0377 {
0378     QPointer<AlbumPropsEdit> dlg = new AlbumPropsEdit(album);
0379 
0380     bool ok = (dlg->exec() == QDialog::Accepted);
0381 
0382     title           = dlg->title();
0383     comments        = dlg->comments();
0384     date            = dlg->date();
0385     category        = dlg->category();
0386     albumCategories = dlg->albumCategories();
0387 
0388     delete dlg;
0389     return ok;
0390 }
0391 
0392 bool AlbumPropsEdit::createNew(PAlbum* const parent, QString& title, QString& comments,
0393                                QDate& date, QString& category, QStringList& albumCategories,
0394                                int& parentSelector)
0395 {
0396     QPointer<AlbumPropsEdit> dlg = new AlbumPropsEdit(parent, true);
0397 
0398     bool ok = (dlg->exec() == QDialog::Accepted);
0399 
0400     title           = dlg->title();
0401     comments        = dlg->comments();
0402     date            = dlg->date();
0403     category        = dlg->category();
0404     albumCategories = dlg->albumCategories();
0405     parentSelector  = dlg->parent();
0406 
0407     delete dlg;
0408     return ok;
0409 }
0410 
0411 void AlbumPropsEdit::slotTitleChanged()
0412 {
0413     QString newtitle = d->titleEdit->text();
0414     QRegularExpression emptyTitle(QRegularExpression::anchoredPattern(QLatin1String("^\\s*$")));
0415     bool enable      = (!emptyTitle.match(newtitle).hasMatch() && !newtitle.isEmpty());
0416     d->buttons->button(QDialogButtonBox::Ok)->setEnabled(enable);
0417 }
0418 
0419 void AlbumPropsEdit::slotNewAlbumTextChanged(int index)
0420 {
0421     QString title;
0422 
0423     if (index == 0)
0424     {
0425         title = d->album->title();
0426     }
0427     else
0428     {
0429         title = CollectionManager::instance()->albumRootLabel(d->album->albumRootId());
0430     }
0431 
0432     d->topLabel->setText(i18nc("@label: album properties", "Create new Album in\n\"%1\"", title));
0433 }
0434 
0435 void AlbumPropsEdit::slotDateLowButtonClicked()
0436 {
0437     setCursor(Qt::WaitCursor);
0438 
0439     QDate lowDate = CoreDbAccess().db()->getAlbumLowestDate(d->album->id());
0440 
0441     if (lowDate.isValid())
0442     {
0443         d->datePicker->setDate(lowDate);
0444     }
0445 
0446     setCursor(Qt::ArrowCursor);
0447 }
0448 
0449 void AlbumPropsEdit::slotDateHighButtonClicked()
0450 {
0451     setCursor(Qt::WaitCursor);
0452 
0453     QDate highDate = CoreDbAccess().db()->getAlbumHighestDate(d->album->id());
0454 
0455     if (highDate.isValid())
0456     {
0457         d->datePicker->setDate(highDate);
0458     }
0459 
0460     setCursor(Qt::ArrowCursor);
0461 }
0462 
0463 void AlbumPropsEdit::slotDateAverageButtonClicked()
0464 {
0465     setCursor(Qt::WaitCursor);
0466 
0467     QDate avDate = CoreDbAccess().db()->getAlbumAverageDate(d->album->id());
0468 
0469     setCursor(Qt::ArrowCursor);
0470 
0471     if (avDate.isValid())
0472     {
0473         d->datePicker->setDate(avDate);
0474     }
0475     else
0476     {
0477         QMessageBox::critical(this, i18nc("@title:window, album properties", "Could not Calculate Average"),
0478                                     i18nc("@info: album properties", "Could not calculate date average for this album."));
0479     }
0480 }
0481 
0482 void AlbumPropsEdit::slotHelp()
0483 {
0484     openOnlineDocumentation(QLatin1String("main_window"), QLatin1String("albums_view"), QLatin1String("managing-albums"));
0485 }
0486 
0487 } // namespace Digikam
0488 
0489 #include "albumpropsedit.moc"
0490 
0491 #include "moc_albumpropsedit.cpp"