File indexing completed on 2022-09-27 13:16:03

0001 /*
0002     SPDX-FileCopyrightText: 2002 Nicolas Hadacek <hadacek@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #include "kexthighscore_tab.h"
0008 
0009 
0010 #include <QApplication>
0011 #include <QGroupBox>
0012 #include <QHeaderView>
0013 #include <QLayout>
0014 #include <QLabel>
0015 #include <QPixmap>
0016 #include <QTreeWidget>
0017 
0018 
0019 #include "kexthighscore.h"
0020 #include "kexthighscore_internal.h"
0021 
0022 namespace KExtHighscore
0023 {
0024 
0025 //-----------------------------------------------------------------------------
0026 PlayersCombo::PlayersCombo(QWidget *parent)
0027     : QComboBox(parent)
0028 {
0029     const PlayerInfos &p = internal->playerInfos();
0030     for (uint i = 0; i<p.nbEntries(); i++)
0031         addItem(p.prettyName(i));
0032     addItem(QStringLiteral("<") + i18n("all") + QLatin1Char( '>' ));
0033     connect(this, static_cast<void (PlayersCombo::*)(int)>(&PlayersCombo::activated), this, &PlayersCombo::activatedSlot);
0034 }
0035 
0036 void PlayersCombo::activatedSlot(int i)
0037 {
0038     const PlayerInfos &p = internal->playerInfos();
0039     if ( i==(int)p.nbEntries() ) Q_EMIT allSelected();
0040     else if ( i==(int)p.nbEntries()+1 ) Q_EMIT noneSelected();
0041     else Q_EMIT playerSelected(i);
0042 }
0043 
0044 void PlayersCombo::load()
0045 {
0046     const PlayerInfos &p = internal->playerInfos();
0047     for (uint i = 0; i<p.nbEntries(); i++)
0048         setItemText(i, p.prettyName(i));
0049 }
0050 
0051 //-----------------------------------------------------------------------------
0052 AdditionalTab::AdditionalTab(QWidget *parent)
0053     : QWidget(parent)
0054 {
0055     QVBoxLayout *top = new QVBoxLayout(this);
0056     //top->setMargin( QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin) );
0057     //top->setSpacing( QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing) );
0058 
0059     QHBoxLayout *hbox = new QHBoxLayout;
0060     top->addLayout(hbox);
0061     QLabel *label = new QLabel(i18n("Select player:"), this);
0062     hbox->addWidget(label);
0063     _combo = new PlayersCombo(this);
0064     connect(_combo, &PlayersCombo::playerSelected, this, &AdditionalTab::playerSelected);
0065     connect(_combo, &PlayersCombo::allSelected, this, &AdditionalTab::allSelected);
0066     hbox->addWidget(_combo);
0067     hbox->addStretch(1);
0068 }
0069 
0070 void AdditionalTab::init()
0071 {
0072     uint id = internal->playerInfos().id();
0073     _combo->setCurrentIndex(id);
0074     playerSelected(id);
0075 }
0076 
0077 void AdditionalTab::allSelected()
0078 {
0079     display(internal->playerInfos().nbEntries());
0080 }
0081 
0082 QString AdditionalTab::percent(uint n, uint total, bool withBraces)
0083 {
0084     if ( n==0 || total==0 ) return QString();
0085     QString s =  QStringLiteral( "%1%").arg(100.0 * n / total, 0, 'f', 1);
0086     return (withBraces ? QLatin1Char('(') + s + QLatin1Char( ')' ) : s);
0087 }
0088 
0089 void AdditionalTab::load()
0090 {
0091     _combo->load();
0092 }
0093 
0094 
0095 //-----------------------------------------------------------------------------
0096 const KLazyLocalizedString StatisticsTab::COUNT_LABELS[Nb_Counts] = {
0097     kli18n("Total:"), kli18n("Won:"), kli18n("Lost:"),
0098     kli18n("Draw:")
0099 };
0100 const KLazyLocalizedString StatisticsTab::TREND_LABELS[Nb_Trends] = {
0101     kli18n("Current:"), kli18n("Max won:"), kli18n("Max lost:")
0102 };
0103 
0104 StatisticsTab::StatisticsTab(QWidget *parent)
0105     : AdditionalTab(parent)
0106 {
0107     setObjectName( QStringLiteral("statistics_tab" ));
0108     // construct GUI
0109     QVBoxLayout *top = static_cast<QVBoxLayout *>(layout());
0110 
0111     QHBoxLayout *hbox = new QHBoxLayout;
0112     QVBoxLayout *vbox = new QVBoxLayout;
0113     hbox->addLayout(vbox);
0114     top->addLayout(hbox);
0115 
0116     QGroupBox *group = new QGroupBox(i18n("Game Counts"), this);
0117     vbox->addWidget(group);
0118     QGridLayout *gridLay = new QGridLayout(group);
0119     //gridLay->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
0120     for (uint k=0; k<Nb_Counts; k++) {
0121         if ( Count(k)==Draw && !internal->showDrawGames ) continue;
0122         gridLay->addWidget(new QLabel(COUNT_LABELS[k].toString(), group), k, 0);
0123         _nbs[k] = new QLabel(group);
0124         gridLay->addWidget(_nbs[k], k, 1);
0125         _percents[k] = new QLabel(group);
0126         gridLay->addWidget(_percents[k], k, 2);
0127     }
0128 
0129     group = new QGroupBox(i18n("Trends"), this);
0130     vbox->addWidget(group);
0131     gridLay = new QGridLayout(group);
0132     //gridLay->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
0133     for (uint k=0; k<Nb_Trends; k++) {
0134         gridLay->addWidget(new QLabel(TREND_LABELS[k].toString(), group), k, 0);
0135         _trends[k] = new QLabel(group);
0136         gridLay->addWidget(_trends[k], k, 1);
0137     }
0138 
0139     hbox->addStretch(1);
0140     top->addStretch(1);
0141 }
0142 
0143 void StatisticsTab::load()
0144 {
0145     AdditionalTab::load();
0146     const PlayerInfos &pi = internal->playerInfos();
0147     uint nb = pi.nbEntries();
0148     _data.resize(nb+1);
0149     for (int i=0; i<_data.size()-1; i++) {
0150         _data[i].count[Total] = pi.item(QStringLiteral( "nb games" ))->read(i).toUInt();
0151         _data[i].count[Lost] = pi.item(QStringLiteral( "nb lost games" ))->read(i).toUInt()
0152                        + pi.item(QStringLiteral( "nb black marks" ))->read(i).toUInt(); // legacy
0153         _data[i].count[Draw] = pi.item(QStringLiteral( "nb draw games" ))->read(i).toUInt();
0154         _data[i].count[Won] = _data[i].count[Total] - _data[i].count[Lost]
0155                               - _data[i].count[Draw];
0156         _data[i].trend[CurrentTrend] =
0157             pi.item(QStringLiteral( "current trend" ))->read(i).toInt();
0158         _data[i].trend[WonTrend] = pi.item(QStringLiteral( "max won trend" ))->read(i).toUInt();
0159         _data[i].trend[LostTrend] =
0160             -(int)pi.item(QStringLiteral( "max lost trend" ))->read(i).toUInt();
0161     }
0162 
0163     for (int k=0; k<Nb_Counts; k++) _data[nb].count[k] = 0;
0164     for (int k=0; k<Nb_Trends; k++) _data[nb].trend[k] = 0;
0165     for (int i=0; i<_data.size()-1; i++) {
0166         for (uint k=0; k<Nb_Counts; k++)
0167             _data[nb].count[k] += _data[i].count[k];
0168         for (uint k=0; k<Nb_Trends; k++)
0169             _data[nb].trend[k] += _data[i].trend[k];
0170     }
0171     for (uint k=0; k<Nb_Trends; k++)
0172         _data[nb].trend[k] /= (_data.size()-1);
0173 
0174     init();
0175 }
0176 
0177 QString StatisticsTab::percent(const Data &d, Count count) const
0178 {
0179     if ( count==Total ) return QString();
0180     return AdditionalTab::percent(d.count[count], d.count[Total], true);
0181 }
0182 
0183 void StatisticsTab::display(uint i)
0184 {
0185     const Data &d = _data[i];
0186     for (uint k=0; k<Nb_Counts; k++) {
0187         if ( Count(k) && !internal->showDrawGames ) continue;
0188         _nbs[k]->setText(QString::number(d.count[k]));
0189         _percents[k]->setText(percent(d, Count(k)));
0190     }
0191     for (uint k=0; k<Nb_Trends; k++) {
0192         QString s;
0193         if ( d.trend[k]>0 ) s = QLatin1Char( '+' );
0194         int prec = (i==internal->playerInfos().nbEntries() ? 1 : 0);
0195         _trends[k]->setText(s + QString::number(d.trend[k], 'f', prec));
0196     }
0197 }
0198 
0199 //-----------------------------------------------------------------------------
0200 HistogramTab::HistogramTab(QWidget *parent)
0201     : AdditionalTab(parent)
0202 {
0203     setObjectName( QStringLiteral("histogram_tab" ));
0204     // construct GUI
0205     QVBoxLayout *top = static_cast<QVBoxLayout *>(layout());
0206 
0207     _list = new QTreeWidget(this);
0208     _list->setSelectionMode(QAbstractItemView::NoSelection);
0209 /// @todo to port or no more necessary ?
0210 //     _list->setItemMargin(3);
0211     _list->setAllColumnsShowFocus(true);
0212     _list->setSortingEnabled(false);
0213     _list->header()->setSectionsClickable(false);
0214     _list->header()->setSectionsMovable(false);
0215     top->addWidget(_list);
0216 
0217     _list->headerItem()->setText(0,i18n("From"));
0218     _list->headerItem()->setText(1,i18n("To"));
0219     _list->headerItem()->setText(2,i18n("Count"));
0220     _list->headerItem()->setText(3,i18n("Percent"));
0221     for (int i=0; i<4; i++) _list->headerItem()->setTextAlignment(i, Qt::AlignRight);
0222     _list->headerItem()->setText(4,QString());
0223 
0224     const Item *sitem = internal->scoreInfos().item(QStringLiteral( "score" ))->item();
0225     const PlayerInfos &pi = internal->playerInfos();
0226     const QVector<uint> &sh = pi.histogram();
0227     for (int k=1; k<( int )pi.histoSize(); k++) {
0228         QString s1 = sitem->pretty(0, sh[k-1]);
0229         QString s2;
0230         if ( k==sh.size() ) s2 = QStringLiteral( "..." );
0231         else if ( sh[k]!=sh[k-1]+1 ) s2 = sitem->pretty(0, sh[k]);
0232     QStringList items; items << s1 << s2;
0233         (void)new QTreeWidgetItem(_list, items);
0234     }
0235 }
0236 
0237 void HistogramTab::load()
0238 {
0239     AdditionalTab::load();
0240     const PlayerInfos &pi = internal->playerInfos();
0241     uint n = pi.nbEntries();
0242     uint s = pi.histoSize() - 1;
0243     _counts.resize((n+1) * s);
0244     _data.fill(0, n+1);
0245     for (uint k=0; k<s; k++) {
0246         _counts[n*s + k] = 0;
0247         for (uint i=0; i<n; i++) {
0248             uint nb = pi.item(pi.histoName(k+1))->read(i).toUInt();
0249             _counts[i*s + k] = nb;
0250             _counts[n*s + k] += nb;
0251             _data[i] += nb;
0252             _data[n] += nb;
0253         }
0254     }
0255 
0256     init();
0257 }
0258 
0259 void HistogramTab::display(uint i)
0260 {
0261     const PlayerInfos &pi = internal->playerInfos();
0262     uint itemNum = 0;
0263     QTreeWidgetItem *item = _list->topLevelItem(itemNum);
0264     uint s = pi.histoSize() - 1;
0265     for (int k=s-1; k>=0; k--) {
0266         uint nb = _counts[i*s + k];
0267         item->setText(2, QString::number(nb));
0268         item->setText(3, percent(nb, _data[i]));
0269         uint width = (_data[i]==0 ? 0 : qRound(150.0 * nb / _data[i]));
0270         QPixmap pixmap(width, 10);
0271         pixmap.fill(Qt::blue);
0272         item->setData(4, Qt::DecorationRole, pixmap);
0273     itemNum++;
0274         item = _list->topLevelItem(itemNum);
0275     }
0276 }
0277 
0278 } // namespace