File indexing completed on 2024-04-28 15:40:13

0001 // SPDX-FileCopyrightText: 2008-2022 Jesper K. Pedersen <jesper.pedersen@kdab.com>
0002 // SPDX-FileCopyrightText: 2012 Miika Turkia <miika.turkia@gmail.com>
0003 // SPDX-FileCopyrightText: 2013 Pino Toscano <pino@kde.org>
0004 // SPDX-FileCopyrightText: 2013-2023 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0005 // SPDX-FileCopyrightText: 2015-2020 Tobias Leupold <tl@stonemx.de>
0006 //
0007 // SPDX-License-Identifier: GPL-2.0-or-later
0008 
0009 #include "StatisticsDialog.h"
0010 
0011 #include <DB/Category.h>
0012 #include <DB/CategoryCollection.h>
0013 #include <DB/ImageDB.h>
0014 #include <DB/search/ImageSearchInfo.h>
0015 #include <Utilities/ShowBusyCursor.h>
0016 
0017 #include <KComboBox>
0018 #include <KLocalizedString>
0019 #include <QDialogButtonBox>
0020 #include <QGroupBox>
0021 #include <QHeaderView>
0022 #include <QLabel>
0023 #include <QPushButton>
0024 #include <QTreeWidget>
0025 #include <QVBoxLayout>
0026 
0027 using namespace MainWindow;
0028 
0029 StatisticsDialog::StatisticsDialog(QWidget *parent)
0030     : QDialog(parent)
0031 {
0032     QVBoxLayout *layout = new QVBoxLayout;
0033     setLayout(layout);
0034 
0035     QString txt = i18n("<h1>Description</h1>"
0036                        "<table>"
0037                        "<tr><td># of Items</td><td>This is the number of different items in the category</td></tr>"
0038                        "<tr><td>Tags Total</td><td>This is a count of how many tags was made,<br/>i.e. a simple counting though all the images</td></tr>"
0039                        "<tr><td>Tags Per Picture</td><td>This tells you how many tags are on each picture on average</td></tr>"
0040                        "</table><br/><br/>"
0041                        "Do not get too attached to this dialog, it has the problem that it counts categories AND subcategories,<br/>"
0042                        "so if an image has been taken in Las Vegas, Nevada, USA, then 3 tags are counted for that image,<br/>"
0043                        "while it should only be one.<br/>"
0044                        "I am not really sure if it is worth fixing that bug (as it is pretty hard to fix),<br/>"
0045                        "so maybe the dialog will simply go away again");
0046 
0047     QLabel *label = new QLabel(txt);
0048     layout->addWidget(label);
0049 
0050     layout->addWidget(createAnnotatedGroupBox());
0051 
0052     label = new QLabel(i18n("<h1>Statistics</h1>"));
0053     layout->addWidget(label);
0054 
0055     m_treeWidget = new QTreeWidget;
0056     layout->addWidget(m_treeWidget);
0057 
0058     QStringList labels;
0059     labels << i18n("Category") << i18n("# of Items") << i18n("Tags Totals") << i18n("Tags Per Picture") << QString();
0060     m_treeWidget->setHeaderLabels(labels);
0061 
0062     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
0063     buttonBox->button(QDialogButtonBox::Ok)->setShortcut(Qt::CTRL | Qt::Key_Return);
0064     layout->addWidget(buttonBox);
0065 
0066     connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
0067 }
0068 
0069 void StatisticsDialog::show()
0070 {
0071     populate();
0072     QDialog::show();
0073 }
0074 
0075 QSize MainWindow::StatisticsDialog::sizeHint() const
0076 {
0077     return QSize(800, 800);
0078 }
0079 
0080 QTreeWidgetItem *MainWindow::StatisticsDialog::addRow(const QString &title, int noOfTags, int tagCount, int imageCount, QTreeWidgetItem *parent)
0081 {
0082     QStringList list;
0083     list << title
0084          << QString::number(noOfTags)
0085          << QString::number(tagCount)
0086          << QString::number((double)tagCount / imageCount, 'F', 2);
0087     QTreeWidgetItem *item = new QTreeWidgetItem(parent, list);
0088     for (int col = 1; col < 4; ++col)
0089         item->setTextAlignment(col, Qt::AlignRight);
0090     return item;
0091 }
0092 
0093 void MainWindow::StatisticsDialog::highlightTotalRow(QTreeWidgetItem *item)
0094 {
0095     for (int col = 0; col < 5; ++col) {
0096         QFont font = item->data(col, Qt::FontRole).value<QFont>();
0097         font.setWeight(QFont::Bold);
0098         item->setData(col, Qt::FontRole, font);
0099     }
0100 }
0101 
0102 QGroupBox *MainWindow::StatisticsDialog::createAnnotatedGroupBox()
0103 {
0104     QGroupBox *box = new QGroupBox(i18n("Tag indication completed annotation"));
0105 
0106     m_boxLayout = new QGridLayout(box);
0107     m_boxLayout->setColumnStretch(2, 1);
0108     int row = -1;
0109 
0110     QLabel *label = new QLabel(i18n("If you use a specific tag to indicate that an image has been tagged, then specify it here."));
0111     label->setWordWrap(true);
0112     m_boxLayout->addWidget(label, ++row, 0, 1, 3);
0113 
0114     label = new QLabel(i18n("Category:"));
0115     m_boxLayout->addWidget(label, ++row, 0);
0116 
0117     m_category = new KComboBox;
0118     m_boxLayout->addWidget(m_category, row, 1);
0119 
0120     m_tagLabel = new QLabel(i18n("Tag:"));
0121     m_boxLayout->addWidget(m_tagLabel, ++row, 0);
0122 
0123     m_tag = new KComboBox;
0124     m_tag->setSizeAdjustPolicy(KComboBox::AdjustToContents);
0125     m_boxLayout->addWidget(m_tag, row, 1);
0126 
0127     m_category->addItem(i18nc("@item:inlistbox meaning 'no category'", "None"));
0128 
0129     const QList<DB::CategoryPtr> categories = DB::ImageDB::instance()->categoryCollection()->categories();
0130     for (const DB::CategoryPtr &category : categories) {
0131         if (category->type() == DB::Category::MediaTypeCategory
0132             || category->type() == DB::Category::FolderCategory) {
0133             continue;
0134         }
0135         m_category->addItem(category->name(), category->name());
0136     }
0137 
0138     connect(m_category, static_cast<void (KComboBox::*)(int)>(&KComboBox::activated), this, &StatisticsDialog::categoryChanged);
0139     connect(m_tag, static_cast<void (KComboBox::*)(int)>(&KComboBox::activated), this, &StatisticsDialog::populate);
0140     m_tagLabel->setEnabled(false);
0141     m_tag->setEnabled(false);
0142 
0143     return box;
0144 }
0145 
0146 void MainWindow::StatisticsDialog::categoryChanged(int index)
0147 {
0148     const bool enabled = (index != 0);
0149     m_tagLabel->setEnabled(enabled);
0150     m_tag->setEnabled(enabled);
0151 
0152     m_tag->clear();
0153 
0154     if (enabled) {
0155         const QString name = m_category->itemData(index).value<QString>();
0156         DB::CategoryPtr category = DB::ImageDB::instance()->categoryCollection()->categoryForName(name);
0157         m_tag->addItems(category->items());
0158     }
0159 }
0160 
0161 void MainWindow::StatisticsDialog::populate()
0162 {
0163     Utilities::ShowBusyCursor dummy;
0164     m_treeWidget->clear();
0165 
0166     const int imageCount = DB::ImageDB::instance()->totalCount();
0167     QTreeWidgetItem *top = new QTreeWidgetItem(m_treeWidget, QStringList() << i18nc("As in 'all images'", "All") << QString::number(imageCount));
0168     top->setTextAlignment(1, Qt::AlignRight);
0169     populateSubTree(DB::ImageSearchInfo(), imageCount, top);
0170 
0171     if (m_category->currentIndex() != 0) {
0172         const QString category = m_category->itemData(m_category->currentIndex()).value<QString>();
0173         const QString tag = m_tag->currentText();
0174         DB::ImageSearchInfo info;
0175         info.setCategoryMatchText(category, tag);
0176         const int imageCount = DB::ImageDB::instance()->count(info).total();
0177         QTreeWidgetItem *item = new QTreeWidgetItem(m_treeWidget,
0178                                                     QStringList() << QString::fromLatin1("%1: %2").arg(category, tag)
0179                                                                   << QString::number(imageCount));
0180         item->setTextAlignment(1, Qt::AlignRight);
0181         populateSubTree(info, imageCount, item);
0182     }
0183     m_treeWidget->header()->resizeSections(QHeaderView::ResizeToContents);
0184 }
0185 
0186 void MainWindow::StatisticsDialog::populateSubTree(const DB::ImageSearchInfo &info, int imageCount, QTreeWidgetItem *top)
0187 {
0188     top->setExpanded(true);
0189 
0190     const QList<DB::CategoryPtr> categories = DB::ImageDB::instance()->categoryCollection()->categories();
0191 
0192     int tagsTotal = 0;
0193     int grantTotal = 0;
0194     for (const DB::CategoryPtr &category : categories) {
0195         if (category->type() == DB::Category::MediaTypeCategory
0196             || category->type() == DB::Category::FolderCategory) {
0197             continue;
0198         }
0199 
0200         const QMap<QString, DB::CountWithRange> tags = DB::ImageDB::instance()->classify(info, category->name(), DB::anyMediaType);
0201         int total = 0;
0202         for (auto tagIt = tags.constBegin(); tagIt != tags.constEnd(); ++tagIt) {
0203             // Don't count the NONE tag, and the OK tag
0204             if (tagIt.key() != DB::ImageDB::NONE() && (category->name() != m_category->currentText() || tagIt.key() != m_tag->currentText()))
0205                 total += tagIt.value().count;
0206         }
0207 
0208         addRow(category->name(), tags.count() - 1, total, imageCount, top);
0209         tagsTotal += tags.count() - 1;
0210         grantTotal += total;
0211     }
0212 
0213     QTreeWidgetItem *totalRow = addRow(i18n("Total"), tagsTotal, grantTotal, imageCount, top);
0214     highlightTotalRow(totalRow);
0215 }
0216 // vi:expandtab:tabstop=4 shiftwidth=4:
0217 
0218 #include "moc_StatisticsDialog.cpp"