File indexing completed on 2024-04-28 04:21:18
0001 // SPDX-FileCopyrightText: 2014-2020 The KPhotoAlbum Development Team 0002 // SPDX-FileCopyrightText: 2021 Johannes Zarl-Zierl <johannes@zarl-zierl.at> 0003 // 0004 // SPDX-License-Identifier: GPL-2.0-or-later 0005 0006 // Qt includes 0007 #include <QCalendarWidget> 0008 #include <QComboBox> 0009 #include <QHBoxLayout> 0010 #include <QHeaderView> 0011 #include <QLabel> 0012 #include <QLineEdit> 0013 #include <QLocale> 0014 #include <QPushButton> 0015 #include <QShortcut> 0016 #include <QTableWidget> 0017 #include <QVBoxLayout> 0018 0019 // KDE includes 0020 #include <KColorScheme> 0021 #include <KLocalizedString> 0022 #include <KPageWidgetModel> 0023 0024 // Local includes 0025 #include "BirthdayPage.h" 0026 #include "DateTableWidgetItem.h" 0027 0028 #include <DB/Category.h> 0029 #include <DB/CategoryCollection.h> 0030 #include <DB/ImageDB.h> 0031 #include <MainWindow/DirtyIndicator.h> 0032 0033 Settings::BirthdayPage::BirthdayPage(QWidget *parent) 0034 : QWidget(parent) 0035 { 0036 QVBoxLayout *mainLayout = new QVBoxLayout(this); 0037 0038 QHBoxLayout *dataLayout = new QHBoxLayout; 0039 mainLayout->addLayout(dataLayout); 0040 0041 QVBoxLayout *itemsLayout = new QVBoxLayout; 0042 dataLayout->addLayout(itemsLayout); 0043 0044 QHBoxLayout *itemsHeaderLayout = new QHBoxLayout; 0045 itemsLayout->addLayout(itemsHeaderLayout); 0046 0047 QLabel *categoryText = new QLabel(i18n("Category:")); 0048 itemsHeaderLayout->addWidget(categoryText); 0049 0050 m_categoryBox = new QComboBox; 0051 itemsHeaderLayout->addWidget(m_categoryBox); 0052 connect(m_categoryBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &BirthdayPage::changeCategory); 0053 0054 m_filter = new QLineEdit; 0055 itemsHeaderLayout->addWidget(m_filter); 0056 connect(m_filter, &QLineEdit::textChanged, this, &BirthdayPage::resetCategory); 0057 const auto filterShortcut = new QShortcut(Qt::AltModifier + Qt::Key_F, m_filter, SLOT(setFocus())); 0058 m_filter->setPlaceholderText(i18nc("@label:textedit", "Filter ... (%1)", filterShortcut->key().toString(QKeySequence::NativeText))); 0059 0060 if (QLocale().dateFormat(QLocale::ShortFormat).contains(QString::fromUtf8("yyyy"))) { 0061 m_dateFormats << QLocale().dateFormat(QLocale::ShortFormat); 0062 } else { 0063 m_dateFormats << QLocale().dateFormat(QLocale::ShortFormat).replace(QString::fromUtf8("yy"), QString::fromUtf8("yyyy")); 0064 } 0065 m_dateFormats << QLocale().dateFormat(QLocale::ShortFormat) 0066 << QLocale().dateFormat(QLocale::LongFormat); 0067 0068 m_dataView = new QTableWidget; 0069 m_dataView->setColumnCount(2); 0070 m_dataView->verticalHeader()->hide(); 0071 m_dataView->setShowGrid(false); 0072 itemsLayout->addWidget(m_dataView); 0073 connect(m_dataView, &QTableWidget::cellClicked, this, &BirthdayPage::editDate); 0074 0075 QVBoxLayout *calendarLayout = new QVBoxLayout; 0076 dataLayout->addLayout(calendarLayout); 0077 0078 calendarLayout->addStretch(); 0079 0080 m_birthdayOfLabel = new QLabel; 0081 calendarLayout->addWidget(m_birthdayOfLabel); 0082 0083 m_dateInput = new QLineEdit; 0084 calendarLayout->addWidget(m_dateInput); 0085 connect(m_dateInput, &QLineEdit::textEdited, this, &BirthdayPage::checkDateInput); 0086 connect(m_dateInput, &QLineEdit::editingFinished, this, &BirthdayPage::checkDate); 0087 0088 m_calendar = new QCalendarWidget; 0089 calendarLayout->addWidget(m_calendar); 0090 connect(m_calendar, &QCalendarWidget::clicked, this, &BirthdayPage::setDate); 0091 0092 m_unsetButton = new QPushButton(i18n("Remove birthday")); 0093 calendarLayout->addWidget(m_unsetButton); 0094 connect(m_unsetButton, &QPushButton::clicked, this, &BirthdayPage::removeDate); 0095 0096 calendarLayout->addStretch(); 0097 0098 QLabel *info = new QLabel(i18n("Set the date of birth for items (say people) here, " 0099 "and then see their age when viewing the images.")); 0100 mainLayout->addWidget(info); 0101 0102 m_noDateString = QString::fromUtf8("---"); 0103 m_boldFont.setBold(true); 0104 0105 disableCalendar(); 0106 } 0107 0108 void Settings::BirthdayPage::pageChange(KPageWidgetItem *page) 0109 { 0110 if (page->widget() == this) { 0111 m_lastItem = nullptr; 0112 reload(); 0113 } 0114 } 0115 0116 void Settings::BirthdayPage::reload() 0117 { 0118 m_dateInput->setText(QString()); 0119 m_calendar->setSelectedDate(QDate::currentDate()); 0120 0121 disableCalendar(); 0122 0123 m_categoryBox->blockSignals(true); 0124 m_categoryBox->clear(); 0125 0126 int defaultIndex = 0; 0127 int index = 0; 0128 0129 for (const DB::CategoryPtr &category : DB::ImageDB::instance()->categoryCollection()->categories()) { 0130 if (category->isSpecialCategory()) { 0131 continue; 0132 } 0133 m_categoryBox->addItem(category->name()); 0134 if (category->name() == i18n("People")) { 0135 defaultIndex = index; 0136 } 0137 ++index; 0138 } 0139 0140 m_categoryBox->setCurrentIndex(defaultIndex); 0141 changeCategory(defaultIndex); 0142 0143 m_categoryBox->blockSignals(false); 0144 } 0145 0146 void Settings::BirthdayPage::resetCategory() 0147 { 0148 changeCategory(m_categoryBox->currentIndex()); 0149 } 0150 0151 void Settings::BirthdayPage::changeCategory(int index) 0152 { 0153 m_lastItem = nullptr; 0154 m_dataView->clear(); 0155 m_dataView->setSortingEnabled(false); 0156 m_dataView->setHorizontalHeaderLabels(QStringList() << i18n("Name") << i18n("Birthday")); 0157 0158 const QString categoryName = m_categoryBox->itemText(index); 0159 const DB::CategoryPtr category = DB::ImageDB::instance()->categoryCollection()->categoryForName(categoryName); 0160 QStringList items = category->items(); 0161 0162 m_dataView->setRowCount(items.count()); 0163 int row = 0; 0164 0165 for (const QString &text : items) { 0166 if (!m_filter->text().isEmpty() 0167 && text.indexOf(m_filter->text(), 0, Qt::CaseInsensitive) == -1) { 0168 m_dataView->setRowCount(m_dataView->rowCount() - 1); 0169 continue; 0170 } 0171 0172 QTableWidgetItem *nameItem = new QTableWidgetItem(text); 0173 nameItem->setFlags(nameItem->flags() & ~Qt::ItemIsEditable & ~Qt::ItemIsSelectable); 0174 m_dataView->setItem(row, 0, nameItem); 0175 0176 QDate dateForItem; 0177 if (m_changedData.contains(categoryName)) { 0178 if (m_changedData[categoryName].contains(text)) { 0179 dateForItem = m_changedData[categoryName][text]; 0180 } else { 0181 dateForItem = category->birthDate(text); 0182 } 0183 } else { 0184 dateForItem = category->birthDate(text); 0185 } 0186 0187 DateTableWidgetItem *dateItem = new DateTableWidgetItem(textForDate(dateForItem)); 0188 dateItem->setData(Qt::UserRole, dateForItem); 0189 dateItem->setFlags(dateItem->flags() & ~Qt::ItemIsEditable & ~Qt::ItemIsSelectable); 0190 m_dataView->setItem(row, 1, dateItem); 0191 0192 row++; 0193 } 0194 0195 m_dataView->setSortingEnabled(true); 0196 m_dataView->sortItems(0); 0197 0198 disableCalendar(); 0199 } 0200 0201 QString Settings::BirthdayPage::textForDate(const QDate &date) const 0202 { 0203 if (date.isNull()) { 0204 return m_noDateString; 0205 } else { 0206 return QLocale().toString(date, m_dateFormats.at(0)); 0207 } 0208 } 0209 0210 void Settings::BirthdayPage::editDate(int row, int) 0211 { 0212 m_dateInput->setEnabled(true); 0213 m_calendar->setEnabled(true); 0214 m_unsetButton->setEnabled(m_dataView->item(row, 1)->text() != m_noDateString); 0215 0216 if (m_lastItem != nullptr) { 0217 m_lastItem->setFont(m_font); 0218 m_dataView->item(m_lastItem->row(), 1)->setFont(m_font); 0219 } 0220 0221 m_dataView->item(row, 0)->setFont(m_boldFont); 0222 m_dataView->item(row, 1)->setFont(m_boldFont); 0223 0224 m_birthdayOfLabel->setText(i18n("Birthday of %1:", m_dataView->item(row, 0)->text())); 0225 0226 QString dateString = m_dataView->item(row, 1)->text(); 0227 if (dateString != m_noDateString) { 0228 m_dateInput->setText(dateString); 0229 m_calendar->setSelectedDate(m_dataView->item(row, 1)->data(Qt::UserRole).toDate()); 0230 } else { 0231 m_dateInput->setText(QString()); 0232 m_dateInput->setPlaceholderText(i18n("Enter a date...")); 0233 m_calendar->setSelectedDate(QDate::currentDate()); 0234 } 0235 0236 m_lastItem = m_dataView->item(row, 0); 0237 } 0238 0239 QDate Settings::BirthdayPage::parseDate(QString date) 0240 { 0241 QDate parsedDate = QDate(); 0242 for (const QString &format : m_dateFormats) { 0243 parsedDate = QDate::fromString(date, format); 0244 if (parsedDate.isValid()) { 0245 return parsedDate; 0246 } 0247 } 0248 return parsedDate; 0249 } 0250 0251 void Settings::BirthdayPage::checkDateInput(QString date) 0252 { 0253 QDate parsedDate = parseDate(date); 0254 if (parsedDate.isValid() || date.isEmpty()) { 0255 m_calendar->setSelectedDate(parsedDate); 0256 m_dateInput->setPalette(palette()); 0257 // re-enable palette propagation: 0258 m_dateInput->setAttribute(Qt::WA_SetPalette); 0259 } else { 0260 auto errorPalette = m_dateInput->palette(); 0261 KColorScheme::adjustForeground(errorPalette, KColorScheme::ForegroundRole::NegativeText, QPalette::Text); 0262 KColorScheme::adjustBackground(errorPalette, KColorScheme::BackgroundRole::NegativeBackground, QPalette::Base); 0263 m_dateInput->setPalette(errorPalette); 0264 } 0265 } 0266 0267 void Settings::BirthdayPage::checkDate() 0268 { 0269 QDate parsedDate = parseDate(m_dateInput->text()); 0270 if (parsedDate.isValid()) { 0271 setDate(parsedDate); 0272 } 0273 } 0274 0275 void Settings::BirthdayPage::setDate(const QDate &date) 0276 { 0277 const QString currentCategory = m_categoryBox->currentText(); 0278 if (!m_changedData.contains(currentCategory)) { 0279 m_changedData[currentCategory] = QMap<QString, QDate>(); 0280 } 0281 0282 const QString currentItem = m_dataView->item(m_dataView->currentRow(), 0)->text(); 0283 m_changedData[currentCategory][currentItem] = date; 0284 0285 m_dataView->item(m_dataView->currentRow(), 1)->setText(textForDate(date)); 0286 m_dataView->item(m_dataView->currentRow(), 1)->setData(Qt::UserRole, date); 0287 0288 m_unsetButton->setEnabled(true); 0289 } 0290 0291 void Settings::BirthdayPage::disableCalendar() 0292 { 0293 m_dateInput->setEnabled(false); 0294 m_calendar->setEnabled(false); 0295 m_unsetButton->setEnabled(false); 0296 m_birthdayOfLabel->setText(i18n("<i>Select an item on the left to edit the birthday</i>")); 0297 } 0298 0299 void Settings::BirthdayPage::discardChanges() 0300 { 0301 m_changedData.clear(); 0302 } 0303 0304 void Settings::BirthdayPage::saveSettings() 0305 { 0306 QMapIterator<QString, QMap<QString, QDate>> changedCategory(m_changedData); 0307 while (changedCategory.hasNext()) { 0308 changedCategory.next(); 0309 DB::CategoryPtr category = DB::ImageDB::instance()->categoryCollection()->categoryForName(changedCategory.key()); 0310 0311 QMapIterator<QString, QDate> changedItem(changedCategory.value()); 0312 while (changedItem.hasNext()) { 0313 changedItem.next(); 0314 category->setBirthDate(changedItem.key(), changedItem.value()); 0315 } 0316 } 0317 0318 if (m_changedData.size() > 0) { 0319 MainWindow::DirtyIndicator::markDirty(); 0320 m_changedData.clear(); 0321 } 0322 } 0323 0324 void Settings::BirthdayPage::removeDate() 0325 { 0326 m_dateInput->setText(QString()); 0327 m_calendar->setSelectedDate(QDate::currentDate()); 0328 setDate(QDate()); 0329 } 0330 0331 #include "moc_BirthdayPage.cpp"