summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArno <am@disconnect.de>2011-02-12 14:59:36 +0100
committerArno <am@disconnect.de>2011-02-12 14:59:36 +0100
commita2e6438b97a8b9055bee400ccc40a062f0a0e9db (patch)
tree9ad9d23a390fa8749fcad3e09d32e3cacd76e1f7
parent1cba003449f2c875b3be81a9f7c5835b183e78c8 (diff)
downloadSheMov-a2e6438b97a8b9055bee400ccc40a062f0a0e9db.tar.gz
SheMov-a2e6438b97a8b9055bee400ccc40a062f0a0e9db.tar.bz2
SheMov-a2e6438b97a8b9055bee400ccc40a062f0a0e9db.zip
Revamp statisticsdialog
Once again redesign the statisticsdialog. Switch back from WebKit and HTML/CSS graph bars to a QWidget. Never forget about QPainter::translate() again :)
-rw-r--r--shemov.pro1
-rw-r--r--shemov.qrc1
-rw-r--r--statistics.html67
-rw-r--r--statisticsdialog.cpp256
-rw-r--r--statisticsdialog.h35
5 files changed, 217 insertions, 143 deletions
diff --git a/shemov.pro b/shemov.pro
index bf6a368..3123d26 100644
--- a/shemov.pro
+++ b/shemov.pro
@@ -5,7 +5,6 @@ CONFIG += warn_on \
debug
CONFIG -= release
QT += sql
-QT += webkit
SOURCES = main.cpp \
filesystemdirproxy.cpp \
filesystemwidget.cpp \
diff --git a/shemov.qrc b/shemov.qrc
index 5c5368c..71c039b 100644
--- a/shemov.qrc
+++ b/shemov.qrc
@@ -6,7 +6,6 @@
<file>shemov.png</file>
<file>archive.svg</file>
<file>shemov_splash.png</file>
- <file>statistics.html</file>
<file>back_dick.png</file>
<file>up_dick.png</file>
<file>chastity_belt.png</file>
diff --git a/statistics.html b/statistics.html
deleted file mode 100644
index d4432c2..0000000
--- a/statistics.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>{title}</title>
-<style type="text/css">
-body, html {
- margin: 10px;
- padding: 10px;
- background: #0015F2;
- color: #d9ed1b;
-}
-body {
- min-width: 100%;
-}
-h1 {
- text-align:center;
- margin-top: 0;
- padding-top: 0;
-}
-.overview {
- border: 1px solid;
- margin-left: auto;
- margin-right: auto;
-}
-td.desc {
- width: 15%;
-}
-td.total {
- width: 15%;
- text-align: right;
-}
-.bar {
- width: 60%;
- background-color: #0FE6FD;
- text-align: right;
- border-left: solid 1px;
- padding-right: 0.5em;
-}
-.bar div {
- border-top: 2px solid #066FF7;
- border-bottom: 2px solid #066FF7;
- background-color: #d9ed1b;
- text-align: right;
- float: left;
- padding-top: 0;
- height: 1em;
-}
-</style>
-</head>
-<body>
-<h1>{title}</h1>
-<table class="overview">
-<thead>
-<tr>
-<th>{desc}</th>
-<th>Graph</th>
-<th>Number</th>
-</tr>
-</thead>
-<tbody>
-{table}
-</tbody>
-</table>
-</body>
-</html>
diff --git a/statisticsdialog.cpp b/statisticsdialog.cpp
index 30141c2..c25ceee 100644
--- a/statisticsdialog.cpp
+++ b/statisticsdialog.cpp
@@ -13,61 +13,52 @@
#include <QPushButton>
#include <QLocale>
#include <QFile>
-#include <QWebView>
+#include <QFontMetrics>
+#include <QFont>
+#include <QApplication>
+#include <QPainter>
+#include <QBrush>
+#include <QPen>
+#include <QPaintEvent>
+#include <QLinearGradient>
+#include <QColor>
+#include <QPainterPath>
+#include <QTextOption>
+#include <QScrollArea>
+#include <QPalette>
+#include <QLabel>
+
+class GraphWidget;
#include "statisticsdialog.h"
StatisticsDialog::StatisticsDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f){
- //html skeleton
- QFile htmlFile(":/statistics.html");
- htmlFile.open(QIODevice::ReadOnly);
- QString html = htmlFile.readAll();
-
- //genre distribution
- QWebView *genreView = new QWebView;
- QString genreHtml = html;
- genreHtml.replace("{title}", tr("Genre distribution"));
- genreHtml.replace("{desc}", tr("Genres"));
QList<QList<QVariant> > 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;");
- QString tableData = table(data, max(data));
- genreHtml.replace("{table}", tableData);
- genreView->setHtml(genreHtml);
-
- //quality distribution
- QWebView *qualityView = new QWebView;
- QString qualityHtml = html;
- qualityHtml.replace("{title}", tr("Quality distribution"));
- qualityHtml.replace("{desc}", tr("Quality"));
+ 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;");
- tableData = table(data, max(data));
- qualityHtml.replace("{table}", tableData);
- qualityView->setHtml(qualityHtml);
-
- //top 20 actors
- QWebView *topActorView = new QWebView;
- QString topActorHtml = html;
- topActorHtml.replace("{title}", tr("Top 20 actors"));
- topActorHtml.replace("{desc}", tr("Actor"));
+ 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");
- tableData = table(data, max(data));
- topActorHtml.replace("{table}", tableData);
- topActorView->setHtml(topActorHtml);
-
- //general statistics
- QWebView *generalView = new QWebView;
- QString generalHtml = html;
- generalHtml.remove(QRegExp("<thead>.*</thead>"));
- tableData = generalStatistics();
- generalHtml.replace("{title}", tr("General statistics"));
- generalHtml.replace("{table}", tableData);
- generalView->setHtml(generalHtml);
+ 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(genreView, tr("Genres"));
- tab->addTab(qualityView, tr("Quality"));
- tab->addTab(topActorView, tr("Top 20 actors"));
- tab->addTab(generalView, tr("General statistics"));
+ 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"));
@@ -84,21 +75,6 @@ StatisticsDialog::StatisticsDialog(QWidget *parent, Qt::WindowFlags f) : QDialog
setWindowTitle(tr("SheMov - Statistics"));
}
-QString StatisticsDialog::table(const QList<QList<QVariant> > &data, int max) const {
- QString table;
- QLocale loc;
- foreach(QList<QVariant> l, data){
- table.append("<tr>");
- int percent = l.at(1).toInt() * 100 / max - 1;
- percent = percent < 1 ? 1 : percent;
- table.append(QString("<td class=\"descr\">%1</td>").arg(l.at(0).toString()));
- table.append(QString("<td class=\"bar\"><div style=\"width: %1%\" class=\"bar\"></div></td>").arg(percent));
- table.append(QString("<td class=\"total\">%1</td>").arg(loc.toString(l.at(1).toInt())));
- table.append("</tr>");
- }
- return table;
-}
-
QList<QList<QVariant> > StatisticsDialog::queryData(const QString &query) const {
QSqlDatabase db = QSqlDatabase::database("treedb");
QSqlQuery q(query, db);
@@ -111,17 +87,6 @@ QList<QList<QVariant> > StatisticsDialog::queryData(const QString &query) const
return retval;
}
-int StatisticsDialog::max(const QList<QList<QVariant> > &data) const{
- int retval = 0;
- foreach(QList<QVariant> l, data){
- int value = l.at(1).toInt();
- if(value > retval){
- retval = value;
- }
- }
- return retval;
-}
-
QString StatisticsDialog::generalStatistics() const{
//get database
QSqlDatabase db = QSqlDatabase::database("treedb");
@@ -177,7 +142,7 @@ QString StatisticsDialog::generalStatistics() const{
int genreCount = q10.value(0).toInt();
//build the tabel
- QString retval;
+ QString retval("<table>");
QLocale loc;
retval.append(QString("<tr><td>Number of series</td><td style=\"padding-left: 30px\">%1</td></tr>").arg(numSeries));
retval.append(QString("<tr><td>Number of movies</td><td style=\"padding-left: 30px\">%1</td></tr>").arg(numMovies));
@@ -189,5 +154,152 @@ QString StatisticsDialog::generalStatistics() const{
retval.append(QString("<tr><td>Archived files size</td><td style=\"padding-left: 30px\">%1 GB</td></tr>").arg(loc.toString(archivedFileSize)));
retval.append(QString("<tr><td>Number of actors</td><td style=\"padding-left: 30px\">%1</td></tr>").arg(actorCount));
retval.append(QString("<tr><td>Number of genres</td><td style=\"padding-left: 30px\">%1</td></tr>").arg(genreCount));
+ retval.append("</table>");
return retval;
}
+
+GraphWidget::GraphWidget(const QList<QList<QVariant> > 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<QVariant> 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<QVariant> d, mData){
+ qreal percentage = d.at(1).toFloat() * 100.0 / static_cast<float>(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<QVariant> 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<float>(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);
+ }
+ }
+}
diff --git a/statisticsdialog.h b/statisticsdialog.h
index 70f2e55..4e7107a 100644
--- a/statisticsdialog.h
+++ b/statisticsdialog.h
@@ -11,6 +11,11 @@
#include <QDialog>
#include <QList>
#include <QVariant>
+#include <QSize>
+#include <QFont>
+#include <QTextDocument>
+
+class QPaintEvent;
class StatisticsDialog : public QDialog {
Q_OBJECT
@@ -19,11 +24,37 @@ class StatisticsDialog : public QDialog {
~StatisticsDialog() {}
private:
- QString table(const QList<QList<QVariant> > &data, int max) const;
QList<QList<QVariant> > queryData(const QString &query) const;
- int max(const QList<QList<QVariant> > &data) const;
QString generalStatistics() const;
};
+class GraphWidget : public QWidget {
+ Q_OBJECT
+ public:
+ GraphWidget(const QList<QList<QVariant> > data, const QString header, QWidget *parent = 0);
+ GraphWidget(const QString &text, const QString header, QWidget *parent = 0);
+ virtual ~GraphWidget() {}
+ virtual QSize sizeHint() const;
+
+ protected:
+ virtual void paintEvent(QPaintEvent *event);
+
+ private:
+ QList<QList<QVariant> > mData;
+ int mDescWidth;
+ const int mBarHeight;
+ const int mMargin;
+ const QString mHeader;
+ QSize mHeaderSize;
+ QFont mHeaderFont;
+ QFont mDataFont;
+ int mMaxValue;
+ int mPercentageWidth;
+ int mTotal;
+ const QString mText;
+ bool mIsText;
+ QTextDocument mDoc;
+};
+
#endif