mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-04-24 07:07:28 +02:00
Statistics graph painting
This commit is contained in:
parent
97f838e733
commit
de35529129
@ -22,7 +22,7 @@ namespace pdfplugin
|
|||||||
{
|
{
|
||||||
|
|
||||||
ObjectStatisticsDialog::ObjectStatisticsDialog(const pdf::PDFDocument* document, QWidget *parent) :
|
ObjectStatisticsDialog::ObjectStatisticsDialog(const pdf::PDFDocument* document, QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent, Qt::Dialog | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint),
|
||||||
ui(new Ui::ObjectStatisticsDialog),
|
ui(new Ui::ObjectStatisticsDialog),
|
||||||
m_document(document)
|
m_document(document)
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Dialog</string>
|
<string>Object Statistics</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
#include "ui_statisticsgraphwidget.h"
|
#include "ui_statisticsgraphwidget.h"
|
||||||
|
|
||||||
#include "pdfwidgetutils.h"
|
#include "pdfwidgetutils.h"
|
||||||
|
#include "pdfpainterutils.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
namespace pdfplugin
|
namespace pdfplugin
|
||||||
{
|
{
|
||||||
@ -51,11 +54,16 @@ StatisticsGraphWidget::GeometryHint StatisticsGraphWidget::getGeometryHint() con
|
|||||||
|
|
||||||
int fivePixelsX = pdf::PDFWidgetUtils::scaleDPI_x(this, 5);
|
int fivePixelsX = pdf::PDFWidgetUtils::scaleDPI_x(this, 5);
|
||||||
int fivePixelsY = pdf::PDFWidgetUtils::scaleDPI_y(this, 5);
|
int fivePixelsY = pdf::PDFWidgetUtils::scaleDPI_y(this, 5);
|
||||||
|
int textMargin = fivePixelsX;
|
||||||
|
|
||||||
hint.margins = QMargins(fivePixelsX, fivePixelsY, fivePixelsX, fivePixelsY);
|
hint.margins = QMargins(fivePixelsX, fivePixelsY, fivePixelsX, fivePixelsY);
|
||||||
hint.colorRectangleWidth = pdf::PDFWidgetUtils::scaleDPI_x(this, 40);
|
hint.colorRectangleWidth = pdf::PDFWidgetUtils::scaleDPI_x(this, 80);
|
||||||
hint.linesWidthLeft = pdf::PDFWidgetUtils::scaleDPI_x(this, 15);
|
hint.linesWidthLeft = pdf::PDFWidgetUtils::scaleDPI_x(this, 15);
|
||||||
hint.linesWidthRight = pdf::PDFWidgetUtils::scaleDPI_x(this, 5);
|
hint.linesWidthRight = pdf::PDFWidgetUtils::scaleDPI_x(this, 5);
|
||||||
|
hint.markerSize = fivePixelsX;
|
||||||
|
hint.normalLineWidth = pdf::PDFWidgetUtils::scaleDPI_y(this, 2);
|
||||||
|
hint.selectedLineWidth = pdf::PDFWidgetUtils::scaleDPI_y(this, 3);
|
||||||
|
hint.colorRectangeLeftMargin = pdf::PDFWidgetUtils::scaleDPI_x(this, 40);
|
||||||
|
|
||||||
QFontMetrics fontMetricsTitle(getTitleFont());
|
QFontMetrics fontMetricsTitle(getTitleFont());
|
||||||
hint.titleWidth = fontMetricsTitle.horizontalAdvance(m_statistics.title);
|
hint.titleWidth = fontMetricsTitle.horizontalAdvance(m_statistics.title);
|
||||||
@ -67,12 +75,176 @@ StatisticsGraphWidget::GeometryHint StatisticsGraphWidget::getGeometryHint() con
|
|||||||
QFontMetrics fontMetricsText(getTextFont());
|
QFontMetrics fontMetricsText(getTextFont());
|
||||||
hint.textHeight += fontMetricsText.lineSpacing() * int(m_statistics.items.size());
|
hint.textHeight += fontMetricsText.lineSpacing() * int(m_statistics.items.size());
|
||||||
|
|
||||||
|
hint.textMargin = textMargin;
|
||||||
|
hint.textLineHeight = fontMetricsText.lineSpacing();
|
||||||
|
|
||||||
// Determine text header width
|
// Determine text header width
|
||||||
s
|
hint.textWidths.resize(m_statistics.headers.size(), 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < m_statistics.headers.size(); ++i)
|
||||||
|
{
|
||||||
|
hint.textWidths[i] = fontMetricsHeader.horizontalAdvance(m_statistics.headers[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& item : m_statistics.items)
|
||||||
|
{
|
||||||
|
Q_ASSERT(item.texts.size() == hint.textWidths.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < item.texts.size(); ++i)
|
||||||
|
{
|
||||||
|
hint.textWidths[i] = qMax(hint.textWidths[i], fontMetricsHeader.horizontalAdvance(m_statistics.headers[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int totalTextWidth = textMargin;
|
||||||
|
for (int& textWidth : hint.textWidths)
|
||||||
|
{
|
||||||
|
textWidth += 2 * textMargin;
|
||||||
|
totalTextWidth += textWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int widthHint = hint.margins.left() + hint.colorRectangeLeftMargin + hint.colorRectangleWidth + hint.linesWidthLeft + hint.linesWidthRight + qMax(totalTextWidth, hint.titleWidth) + hint.margins.right();
|
||||||
|
const int heightHint = hint.margins.top() + hint.titleHeight + qMax(pdf::PDFWidgetUtils::scaleDPI_y(this, 100), hint.textHeight) + hint.margins.bottom();
|
||||||
|
|
||||||
|
hint.minimalWidgetSize = QSize(widthHint, heightHint).expandedTo(pdf::PDFWidgetUtils::scaleDPI(this, QSize(400, 300)));
|
||||||
|
|
||||||
return hint;
|
return hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StatisticsGraphWidget::paintEvent(QPaintEvent* event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
|
||||||
|
QPainter painter(this);
|
||||||
|
QRect rect = this->rect();
|
||||||
|
|
||||||
|
painter.fillRect(rect, Qt::white);
|
||||||
|
|
||||||
|
GeometryHint geometryHint = getGeometryHint();
|
||||||
|
rect = rect.marginsRemoved(geometryHint.margins);
|
||||||
|
|
||||||
|
if (!m_statistics.title.isEmpty())
|
||||||
|
{
|
||||||
|
pdf::PDFPainterStateGuard guard(&painter);
|
||||||
|
|
||||||
|
QRect titleRect = rect;
|
||||||
|
titleRect.setHeight(geometryHint.titleHeight);
|
||||||
|
|
||||||
|
painter.setFont(getHeaderFont());
|
||||||
|
painter.drawText(titleRect, Qt::AlignCenter, m_statistics.title);
|
||||||
|
|
||||||
|
rect.setTop(titleRect.bottom());
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.setLeft(rect.left() + geometryHint.colorRectangeLeftMargin);
|
||||||
|
|
||||||
|
// Color boxes
|
||||||
|
m_colorBoxes.clear();
|
||||||
|
const int height = rect.height();
|
||||||
|
|
||||||
|
QColor selectedColor = Qt::darkYellow;
|
||||||
|
|
||||||
|
int top = rect.top();
|
||||||
|
for (size_t i = 0; i < m_statistics.items.size(); ++i)
|
||||||
|
{
|
||||||
|
const StatisticsItem& item = m_statistics.items[i];
|
||||||
|
QRect currentRect(rect.left(), top, geometryHint.colorRectangleWidth, height * item.portion);
|
||||||
|
top = currentRect.bottom();
|
||||||
|
|
||||||
|
QColor color = (m_selectedColorBox == i) ? selectedColor: item.color;
|
||||||
|
painter.fillRect(currentRect, color);
|
||||||
|
m_colorBoxes.push_back(currentRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint minLinePoint;
|
||||||
|
QPoint maxLinePoint;
|
||||||
|
|
||||||
|
// Marked lines
|
||||||
|
{
|
||||||
|
pdf::PDFPainterStateGuard guard(&painter);
|
||||||
|
for (size_t i = 0; i < m_statistics.items.size(); ++i)
|
||||||
|
{
|
||||||
|
QPen pen = painter.pen();
|
||||||
|
pen.setColor((i == m_selectedColorBox) ? selectedColor : Qt::black);
|
||||||
|
pen.setWidth(geometryHint.markerSize);
|
||||||
|
pen.setCapStyle(Qt::RoundCap);
|
||||||
|
painter.setPen(pen);
|
||||||
|
|
||||||
|
QRect colorBox = m_colorBoxes[i];
|
||||||
|
QPoint marker = colorBox.center();
|
||||||
|
marker.setX(colorBox.right());
|
||||||
|
|
||||||
|
painter.drawPoint(marker);
|
||||||
|
|
||||||
|
pen.setWidth((i == m_selectedColorBox) ? geometryHint.selectedLineWidth : geometryHint.normalLineWidth);
|
||||||
|
painter.setPen(pen);
|
||||||
|
|
||||||
|
QPoint lineEnd = marker + QPoint(geometryHint.linesWidthLeft, 0);
|
||||||
|
painter.drawLine(marker, lineEnd);
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
minLinePoint = lineEnd;
|
||||||
|
}
|
||||||
|
maxLinePoint = lineEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Texts
|
||||||
|
{
|
||||||
|
pdf::PDFPainterStateGuard guard(&painter);
|
||||||
|
|
||||||
|
QFont headerFont = getHeaderFont();
|
||||||
|
QFont textFont = getTextFont();
|
||||||
|
|
||||||
|
QRect textRect = rect;
|
||||||
|
textRect.setLeft(maxLinePoint.x() + geometryHint.textMargin);
|
||||||
|
textRect.setHeight(geometryHint.textLineHeight);
|
||||||
|
|
||||||
|
auto drawTexts = [&](const QStringList& texts, bool isHeader)
|
||||||
|
{
|
||||||
|
pdf::PDFPainterStateGuard guard(&painter);
|
||||||
|
painter.setFont(isHeader ? headerFont : textFont);
|
||||||
|
|
||||||
|
const int y = textRect.center().y();
|
||||||
|
minLinePoint.ry() = qMin(minLinePoint.ry(), y);
|
||||||
|
maxLinePoint.ry() = qMax(maxLinePoint.ry(), y);
|
||||||
|
|
||||||
|
QRect cellRect = textRect;
|
||||||
|
for (int i = 0; i < texts.size(); ++i)
|
||||||
|
{
|
||||||
|
cellRect.setWidth(geometryHint.textWidths[i]);
|
||||||
|
QRect finalCellRect = cellRect.marginsRemoved(QMargins(geometryHint.textMargin, 0, geometryHint.textMargin, 0));
|
||||||
|
QString text = texts[i];
|
||||||
|
Qt::Alignment alignment = (i == 0) ? Qt::Alignment(Qt::AlignLeft | Qt::AlignVCenter) : Qt::Alignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
painter.drawText(finalCellRect, alignment, text);
|
||||||
|
cellRect.translate(cellRect.width(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
textRect.translate(0, textRect.height());
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!m_statistics.headers.isEmpty())
|
||||||
|
{
|
||||||
|
drawTexts(m_statistics.headers, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_statistics.items.size(); ++i)
|
||||||
|
{
|
||||||
|
const StatisticsItem& item = m_statistics.items[i];
|
||||||
|
drawTexts(item.texts, i == m_selectedColorBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPen pen = painter.pen();
|
||||||
|
pen.setColor(Qt::black);
|
||||||
|
pen.setWidth(geometryHint.normalLineWidth);
|
||||||
|
pen.setCapStyle(Qt::RoundCap);
|
||||||
|
painter.setPen(pen);
|
||||||
|
|
||||||
|
painter.drawLine(minLinePoint, maxLinePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QFont StatisticsGraphWidget::getTitleFont() const
|
QFont StatisticsGraphWidget::getTitleFont() const
|
||||||
{
|
{
|
||||||
QFont font = this->font();
|
QFont font = this->font();
|
||||||
@ -93,4 +265,15 @@ QFont StatisticsGraphWidget::getTextFont() const
|
|||||||
return this->font();
|
return this->font();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize StatisticsGraphWidget::sizeHint() const
|
||||||
|
{
|
||||||
|
return getGeometryHint().minimalWidgetSize + pdf::PDFWidgetUtils::scaleDPI(this, QSize(100, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize StatisticsGraphWidget::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
return getGeometryHint().minimalWidgetSize;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdfplugin
|
} // namespace pdfplugin
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
class StatisticsGraphWidget;
|
class StatisticsGraphWidget;
|
||||||
@ -55,8 +57,14 @@ public:
|
|||||||
explicit StatisticsGraphWidget(QWidget* parent);
|
explicit StatisticsGraphWidget(QWidget* parent);
|
||||||
virtual ~StatisticsGraphWidget() override;
|
virtual ~StatisticsGraphWidget() override;
|
||||||
|
|
||||||
|
virtual QSize sizeHint() const override;
|
||||||
|
virtual QSize minimumSizeHint() const override;
|
||||||
|
|
||||||
void setStatistics(Statistics statistics);
|
void setStatistics(Statistics statistics);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void paintEvent(QPaintEvent* event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::StatisticsGraphWidget* ui;
|
Ui::StatisticsGraphWidget* ui;
|
||||||
|
|
||||||
@ -66,14 +74,20 @@ private:
|
|||||||
int colorRectangleWidth = 0;
|
int colorRectangleWidth = 0;
|
||||||
int linesWidthLeft = 0;
|
int linesWidthLeft = 0;
|
||||||
int linesWidthRight = 0;
|
int linesWidthRight = 0;
|
||||||
|
int markerSize = 0;
|
||||||
|
int normalLineWidth = 0;
|
||||||
|
int selectedLineWidth = 0;
|
||||||
|
int colorRectangeLeftMargin = 0;
|
||||||
|
|
||||||
int titleWidth = 0;
|
int titleWidth = 0;
|
||||||
int titleHeight = 0;
|
int titleHeight = 0;
|
||||||
int textHeight = 0;
|
int textHeight = 0;
|
||||||
|
int textMargin = 0;
|
||||||
|
int textLineHeight = 0;
|
||||||
|
|
||||||
std::vector<int> textWidths;
|
std::vector<int> textWidths;
|
||||||
|
|
||||||
QSize minimalWidgetSize = 0;
|
QSize minimalWidgetSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
GeometryHint getGeometryHint() const;
|
GeometryHint getGeometryHint() const;
|
||||||
@ -83,6 +97,8 @@ private:
|
|||||||
QFont getTextFont() const;
|
QFont getTextFont() const;
|
||||||
|
|
||||||
Statistics m_statistics;
|
Statistics m_statistics;
|
||||||
|
std::vector<QRect> m_colorBoxes;
|
||||||
|
size_t m_selectedColorBox = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdfplugin
|
} // namespace pdfplugin
|
||||||
|
Loading…
x
Reference in New Issue
Block a user