/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class GraphWidget; #include "statisticsdialog.h" StatisticsDialog::StatisticsDialog(QWidget *parent, Qt::WindowFlags f) : SmDialog(parent, f){ QList > data = queryData("SELECT genres.tgenrename, COUNT(seriesparts_genremap.iseriesparts_id) FROM genres, seriesparts_genremap WHERE genres.igenres_id = seriesparts_genremap.igenres_id GROUP BY genres.tgenrename ORDER BY count DESC;"); GraphWidget *genreWidget = new GraphWidget(data, tr("Genre Distribution")); data = queryData("SELECT files.siquality, COUNT(seriesparts.iseriesparts_id) FROM files, seriesparts WHERE files.iseriespart_id = seriesparts.iseriesparts_id AND files.siquality IS NOT NULL GROUP BY files.siquality ORDER by siquality desc;"); GraphWidget *qualityWidget = new GraphWidget(data, tr("Quality Distribution")); data = queryData("SELECT actors.tactorname, COUNT(seriesparts_actormap.iseriesparts_id) FROM actors, seriesparts_actormap WHERE actors.iactors_id = seriesparts_actormap.iactors_id GROUP BY actors.tactorname ORDER BY count desc LIMIT 20"); GraphWidget *actorWidget = new GraphWidget(data, tr("Top 20 Actors")); GraphWidget *generalWidget = new GraphWidget(generalStatistics(), tr("General Statistics")); //tab QScrollArea *genreScroll = new QScrollArea; genreScroll->setWidgetResizable(true); genreScroll->setWidget(genreWidget); QScrollArea *qualityScroll = new QScrollArea; qualityScroll->setWidgetResizable(true); qualityScroll->setWidget(qualityWidget); QScrollArea *actorScroll = new QScrollArea; actorScroll->setWidgetResizable(true); actorScroll->setWidget(actorWidget); QScrollArea *generalScroll = new QScrollArea; generalScroll->setWidgetResizable(true); generalScroll->setWidget(generalWidget); QTabWidget *tab = new QTabWidget; tab->addTab(genreScroll, tr("Genres")); tab->addTab(qualityScroll, tr("Quality")); tab->addTab(actorScroll, tr("Top 20 actors")); tab->addTab(generalScroll, tr("General Statistics")); //close button QPushButton *close = new QPushButton(tr("Close")); connect(close, SIGNAL(clicked()), this, SLOT(accept())); QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->setAlignment(Qt::AlignCenter); buttonLayout->addWidget(close); //the dialog QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(tab); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); setWindowTitle(tr("SheMov - Statistics")); } QList > StatisticsDialog::queryData(const QString &query) const { QSqlDatabase db = QSqlDatabase::database("treedb"); QSqlQuery q(query, db); QList > retval; while(q.next()){ QList data; data << q.value(0) << q.value(1); retval << data; } return retval; } QString StatisticsDialog::generalStatistics() const{ //get database QSqlDatabase db = QSqlDatabase::database("treedb"); //series count QSqlQuery q1("SELECT COUNT(*) FROM series", db); q1.first(); int numSeries = q1.value(0).toInt(); //movies count QSqlQuery q2("SELECT COUNT(*) FROM seriesparts", db); q2.first(); int numMovies = q2.value(0).toInt(); //files count QSqlQuery q3("SELECT COUNT(*) FROM files", db); q3.first(); int numFiles = q3.value(0).toInt(); //movie files QSqlQuery q4("SELECT COUNT(*) FROM files WHERE sifiletype = 1", db); q4.first(); int numMovieFiles = q4.value(0).toInt(); //cover files QSqlQuery q5("SELECT COUNT(*) FROM files WHERE sifiletype != 1", db); q5.first(); int numCoverFiles = q5.value(0).toInt(); //total archive size QSqlQuery q6("SELECT ROUND(SUM(bisize) / 1024 / 1024 / 1024, 2) FROM files", db); q6.first(); float totalArchiveSize = q6.value(0).toFloat(); //local file size QSqlQuery q7("SELECT ROUND(SUM(bisize) / 1024 / 1024 / 1024, 2) FROM files WHERE idvd = -1", db); q7.first(); float localFileSize = q7.value(0).toFloat(); //archived file size QSqlQuery q8("SELECT ROUND(SUM(bisize) / 1024 / 1024 / 1024, 2) FROM files WHERE idvd != -1", db); q8.first(); float archivedFileSize = q8.value(0).toFloat(); //actor count QSqlQuery q9("SELECT COUNT(*) FROM actors", db); q9.first(); int actorCount = q9.value(0).toInt(); //genre count QSqlQuery q10("SELECT COUNT(*) FROM genres", db); q10.first(); int genreCount = q10.value(0).toInt(); //build the tabel QString retval(""); QLocale loc; retval.append(QString("").arg(numSeries)); retval.append(QString("").arg(numMovies)); retval.append(QString("").arg(numFiles)); retval.append(QString("").arg(numMovieFiles)); retval.append(QString("").arg(numCoverFiles)); retval.append(QString("").arg(loc.toString(totalArchiveSize))); retval.append(QString("").arg(loc.toString(localFileSize))); retval.append(QString("").arg(loc.toString(archivedFileSize))); retval.append(QString("").arg(actorCount)); retval.append(QString("").arg(genreCount)); retval.append("
Number of series%1
Number of movies%1
Number of files%1
Number of movie files%1
Number of cover files%1
Total archive size%1 GB
Local files size%1 GB
Archived files size%1 GB
Number of actors%1
Number of genres%1
"); return retval; } GraphWidget::GraphWidget(const QList > data, const QString header, QWidget *parent) : QWidget(parent), mData(data), mDescWidth(-1), mBarHeight(20), mMargin(10), mHeader(header), mMaxValue(-1), mPercentageWidth(-1), mTotal(0), mIsText(false){ //setup fonts mHeaderFont = QFont("Arial", 20, QFont::Bold, true); mDataFont = QFont("Arial", 12); //calc max width of data, maxData and total QFontMetrics fmd = QFontMetrics(mDataFont); foreach(QList d, mData){ int width = fmd.size(Qt::TextSingleLine, d.at(0).toString()).width(); if(width > mDescWidth){ mDescWidth = width; } int v = d.at(1).toInt(); if(v > mMaxValue){ mMaxValue = v; } mTotal += d.at(1).toInt(); } //set percentage width foreach(QList d, mData){ qreal percentage = d.at(1).toFloat() * 100.0 / static_cast(mTotal); QString pString = QString("%1 (%2%)").arg(QString::number(d.at(1).toInt())).arg(QString::number(percentage, 'f', 2)); int width = fmd.size(Qt::TextSingleLine, pString).width(); if(width > mPercentageWidth){ mPercentageWidth = width; } } //calc heading size QFontMetrics fmh = QFontMetrics(mHeaderFont); mHeaderSize = fmh.size(Qt::TextSingleLine, mHeader); //set minimum size setMinimumWidth(300); setMinimumHeight(sizeHint().height()); } GraphWidget::GraphWidget(const QString &text, const QString header, QWidget *parent): QWidget(parent), mBarHeight(-1), mMargin(20), mHeader(header), mText(text), mIsText(true){ //setup fonts mHeaderFont = QFont("Arial", 20, QFont::Bold, true); mDataFont = QFont("Arial", 12); //calc heading size QFontMetrics fmh = QFontMetrics(mHeaderFont); mHeaderSize = fmh.size(Qt::TextSingleLine, mHeader); //setup textDocument mDoc.setDefaultFont(mDataFont); mDoc.setDefaultStyleSheet("table { color: #004646 }"); mDoc.setHtml(mText); //set minimum size setMinimumWidth(300); setMinimumHeight(sizeHint().height()); } QSize GraphWidget::sizeHint() const { if(mIsText){ return QSize(mDoc.size().width(), mDoc.size().height() + mHeaderSize.height() + mMargin); }else{ int height = mData.size() * mBarHeight; height += (mData.size() - 1) * mMargin; //margins between bars height += 2 * mMargin; //top and bottom margin return QSize(width(), height); } } void GraphWidget::paintEvent(QPaintEvent *event){ Q_UNUSED(event); QPainter p(this); //draw background QColor gColor1(186, 115, 101); QColor gColor2(236, 210, 196); QLinearGradient bgGradient(width() / 2, 0, width() / 2, height()); bgGradient.setColorAt(0, gColor1); bgGradient.setColorAt(1, gColor2); p.fillRect(rect(), bgGradient); //draw heading QColor headerColor(0, 70, 70); const int topHeading = 5; QRect headerRect(QPoint(mMargin * 4, topHeading), mHeaderSize); QPen headerPen(headerColor); headerPen.setWidth(3); p.setPen(headerPen); p.setFont(mHeaderFont); p.drawText(headerRect, mHeader); //draw line left to heading QFontMetrics hfm(mHeaderFont); int starty = topHeading + hfm.height() / 2; int lstopx = mMargin * 4 - 10; p.drawLine(mMargin, starty, lstopx, starty); //draw line right to heading int rstartx = mMargin * 4 + mHeaderSize.width() + 10; int rstopx = width() - mMargin; p.drawLine(rstartx, starty, rstopx, starty); //draw data p.setFont(mDataFont); QPen dataPen(headerPen); dataPen.setWidth(1); p.setPen(dataPen); if(mIsText){ int startx = (width() - mDoc.size().width()) / 2; int starty = mHeaderSize.height() + mMargin; p.translate(startx, starty); mDoc.drawContents(&p); }else{ int startTranslation = mHeaderSize.height() + mMargin; p.translate(mMargin, startTranslation); int curWidth = width() - 4 * mMargin - mDescWidth - mPercentageWidth; //1x margin in translation QTextOption opt; opt.setAlignment(Qt::AlignRight | Qt::AlignVCenter); QTextOption optLeft; opt.setAlignment(Qt::AlignLeft | Qt::AlignVCenter); foreach(QList l, mData){ //draw lead QRect textRect(0, 0, mDescWidth, mBarHeight); p.drawText(textRect, l.at(0).toString(), opt); //draw data rect int dstartx = mDescWidth + mMargin; qreal dwidth = l.at(1).toFloat() * curWidth / mMaxValue; QRectF dataRect(dstartx, 0, dwidth, mBarHeight); QLinearGradient dataGradient(dataRect.x(), dataRect.y() + dataRect.height() / 2.0, curWidth, dataRect.y() + dataRect.height() / 2.0); QColor dgc1(0, 70, 70); QColor dgc2(0, 255, 255); dataGradient.setColorAt(0, dgc1); dataGradient.setColorAt(1, dgc2); p.fillRect(dataRect, dataGradient); p.drawRect(dataRect); //draw absolute and percentage int pstartx = dataRect.width() + 2 * mMargin + mDescWidth; QRect percentageRect(pstartx, 0, mPercentageWidth, 20); qreal percent = l.at(1).toInt() * 100.0 / static_cast(mTotal); QString pString = QString("%1 (%2%)").arg(QString::number(l.at(1).toInt())).arg(QString::number(percent, 'f', 2)); p.drawText(percentageRect, pString, optLeft); //translate p.translate(0, mMargin + mBarHeight); } } }