File indexing completed on 2024-04-28 04:21:03

0001 // SPDX-FileCopyrightText: 2012-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 #include "Grid.h"
0007 
0008 #include <kpaexif/Info.h>
0009 
0010 #include <kpabase/SettingsData.h>
0011 
0012 #include <QColor>
0013 #include <QGridLayout>
0014 #include <QLabel>
0015 #include <QPainter>
0016 #include <QPalette>
0017 #include <QResizeEvent>
0018 #include <QScrollBar>
0019 #include <QTimer>
0020 
0021 Exif::Grid::Grid(QWidget *parent)
0022     : QScrollArea(parent)
0023 {
0024     setFocusPolicy(Qt::WheelFocus);
0025     setWidgetResizable(true);
0026     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0027     viewport()->installEventFilter(this);
0028     setMinimumSize(800, 400);
0029 }
0030 
0031 class Background : public QWidget
0032 {
0033 protected:
0034     void paintEvent(QPaintEvent *event) override
0035     {
0036         QPainter painter(this);
0037         painter.fillRect(event->rect(), QColor(palette().window().color()));
0038     }
0039 };
0040 
0041 void Exif::Grid::setupUI(const QString &charset)
0042 {
0043     delete this->widget();
0044     m_labels.clear();
0045     Background *widget = new Background;
0046 
0047     QGridLayout *layout = new QGridLayout(widget);
0048     layout->setSpacing(0);
0049     int row = 0;
0050 
0051     const QMap<QString, QStringList> map = Exif::Info::instance()->infoForDialog(m_fileName, charset);
0052     const StringSet groups = exifGroups(map);
0053 
0054     for (const QString &group : groups) {
0055         layout->addWidget(headerLabel(group), row++, 0, 1, 4);
0056 
0057         // Items of group
0058         const QMap<QString, QStringList> items = itemsForGroup(group, map);
0059         QStringList sorted = items.keys();
0060         sorted.sort();
0061         int elements = sorted.size();
0062         int perCol = (elements + 1) / 2;
0063         int count = 0;
0064         for (const QString &key : sorted) {
0065             const int subrow = (count % perCol);
0066             const QPalette::ColorRole role = (subrow & 1) ? QPalette::Base : QPalette::AlternateBase;
0067             QPair<QLabel *, QLabel *> pair = infoLabelPair(exifNameNoGroup(key), items[key].join(QLatin1String(", ")), role);
0068 
0069             int col = (count / perCol) * 2;
0070             layout->addWidget(pair.first, row + subrow, col);
0071             layout->addWidget(pair.second, row + subrow, col + 1);
0072             count++;
0073         }
0074         row += perCol;
0075     }
0076 
0077     setWidget(widget);
0078     widget->show();
0079     QTimer::singleShot(0, this, SLOT(updateWidgetSize()));
0080 }
0081 
0082 QLabel *Exif::Grid::headerLabel(const QString &title)
0083 {
0084     QLabel *label = new QLabel(title);
0085 
0086     label->setBackgroundRole(QPalette::Dark);
0087     label->setForegroundRole(QPalette::BrightText);
0088     label->setAutoFillBackground(true);
0089     label->setAlignment(Qt::AlignCenter);
0090 
0091     return label;
0092 }
0093 
0094 QPair<QLabel *, QLabel *> Exif::Grid::infoLabelPair(const QString &title, const QString &value, const QPalette::ColorRole backgroundRole)
0095 {
0096     QLabel *keyLabel = new QLabel(title);
0097     QLabel *valueLabel = new QLabel(value);
0098 
0099     keyLabel->setBackgroundRole(backgroundRole);
0100     valueLabel->setBackgroundRole(backgroundRole);
0101     keyLabel->setAutoFillBackground(true);
0102     valueLabel->setAutoFillBackground(true);
0103     m_labels.append(qMakePair(keyLabel, valueLabel));
0104     return qMakePair(keyLabel, valueLabel);
0105 }
0106 
0107 void Exif::Grid::updateWidgetSize()
0108 {
0109     widget()->setFixedSize(viewport()->width(), widget()->height());
0110 }
0111 
0112 StringSet Exif::Grid::exifGroups(const QMap<QString, QStringList> &exifInfo)
0113 {
0114     StringSet result;
0115     for (QMap<QString, QStringList>::ConstIterator it = exifInfo.begin(); it != exifInfo.end(); ++it) {
0116         result.insert(groupName(it.key()));
0117     }
0118     return result;
0119 }
0120 
0121 QMap<QString, QStringList> Exif::Grid::itemsForGroup(const QString &group, const QMap<QString, QStringList> &exifInfo)
0122 {
0123     QMap<QString, QStringList> result;
0124     for (QMap<QString, QStringList>::ConstIterator it = exifInfo.begin(); it != exifInfo.end(); ++it) {
0125         if (groupName(it.key()) == group)
0126             result.insert(it.key(), it.value());
0127     }
0128     return result;
0129 }
0130 
0131 QString Exif::Grid::groupName(const QString &exifName)
0132 {
0133     QStringList list = exifName.split(QString::fromLatin1("."));
0134     list.pop_back();
0135     return list.join(QString::fromLatin1("."));
0136 }
0137 
0138 QString Exif::Grid::exifNameNoGroup(const QString &fullName)
0139 {
0140     return fullName.split(QString::fromLatin1(".")).last();
0141 }
0142 
0143 void Exif::Grid::scroll(int dy)
0144 {
0145     verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);
0146 }
0147 
0148 void Exif::Grid::updateSearchString(const QString &search)
0149 {
0150     for (QPair<QLabel *, QLabel *> tuple : m_labels) {
0151         const bool matches = tuple.first->text().contains(search, Qt::CaseInsensitive) && search.length() != 0;
0152         const auto fgRole = matches ? QPalette::HighlightedText : QPalette::Text;
0153         const auto bgRole = matches ? QPalette::Highlight : QPalette::Base;
0154         tuple.first->setForegroundRole(fgRole);
0155         tuple.first->setBackgroundRole(bgRole);
0156         tuple.second->setForegroundRole(fgRole);
0157         tuple.second->setBackgroundRole(bgRole);
0158         QFont fnt = tuple.first->font();
0159         fnt.setBold(matches);
0160         tuple.first->setFont(fnt);
0161         tuple.second->setFont(fnt);
0162     }
0163 }
0164 
0165 void Exif::Grid::keyPressEvent(QKeyEvent *e)
0166 {
0167     switch (e->key()) {
0168     case Qt::Key_Down:
0169         scroll(20);
0170         return;
0171     case Qt::Key_Up:
0172         scroll(-20);
0173         return;
0174     case Qt::Key_PageDown:
0175         scroll(viewport()->height() - 20);
0176         return;
0177     case Qt::Key_PageUp:
0178         scroll(-(viewport()->height() - 20));
0179         return;
0180     case Qt::Key_Escape:
0181         QScrollArea::keyPressEvent(e); // Propagate to close dialog.
0182         return;
0183     }
0184 }
0185 
0186 bool Exif::Grid::eventFilter(QObject *object, QEvent *event)
0187 {
0188     if (object == viewport() && event->type() == QEvent::Resize) {
0189         QResizeEvent *re = static_cast<QResizeEvent *>(event);
0190         widget()->setFixedSize(re->size().width(), widget()->height());
0191     }
0192     return false;
0193 }
0194 
0195 void Exif::Grid::setFileName(const DB::FileName &fileName)
0196 {
0197     m_fileName = fileName;
0198     setupUI(Settings::SettingsData::instance()->iptcCharset());
0199 }
0200 // vi:expandtab:tabstop=4 shiftwidth=4:
0201 
0202 #include "moc_Grid.cpp"