From 7557d1ea51b55c7f01c8ad8518042ee1aebe8f1d 2015-09-29 07:42:48 From: Miikka Heikkinen Date: 2015-09-29 07:42:48 Subject: [PATCH] Fix label clipping issues using QOpenGLWidget as ChartView viewport Task-number: QTRD-3701 Change-Id: I8efc20300d2aa6065918e02190da746463a5d504 Reviewed-by: Titta Heikkala --- diff --git a/src/charts/axis/horizontalaxis.cpp b/src/charts/axis/horizontalaxis.cpp index fa4b038..12d2cf8 100644 --- a/src/charts/axis/horizontalaxis.cpp +++ b/src/charts/axis/horizontalaxis.cpp @@ -141,9 +141,10 @@ void HorizontalAxis::updateGeometry() qreal widthDiff = rect.width() - boundingRect.width(); //ticks and label position + QPointF labelPos; if (axis()->alignment() == Qt::AlignTop) { if (axis()->isReverse()) { - labelItem->setPos(gridRect.right() - layout[layout.size() - i - 1] + labelPos = QPointF(gridRect.right() - layout[layout.size() - i - 1] + gridRect.left() - center.x(), axisRect.bottom() - rect.height() + (heightDiff / 2.0) - labelPadding()); @@ -152,21 +153,21 @@ void HorizontalAxis::updateGeometry() gridRect.right() + gridRect.left() - layout[i], axisRect.bottom() - labelPadding()); } else { - labelItem->setPos(layout[i] - center.x(), axisRect.bottom() - rect.height() + labelPos = QPointF(layout[i] - center.x(), axisRect.bottom() - rect.height() + (heightDiff / 2.0) - labelPadding()); tickItem->setLine(layout[i], axisRect.bottom(), layout[i], axisRect.bottom() - labelPadding()); } } else if (axis()->alignment() == Qt::AlignBottom) { if (axis()->isReverse()) { - labelItem->setPos(gridRect.right() - layout[layout.size() - i - 1] + labelPos = QPointF(gridRect.right() - layout[layout.size() - i - 1] + gridRect.left() - center.x(), axisRect.top() - (heightDiff / 2.0) + labelPadding()); tickItem->setLine(gridRect.right() + gridRect.left() - layout[i], axisRect.top(), gridRect.right() + gridRect.left() - layout[i], axisRect.top() + labelPadding()); } else { - labelItem->setPos(layout[i] - center.x(), axisRect.top() - (heightDiff / 2.0) + labelPos = QPointF(layout[i] - center.x(), axisRect.top() - (heightDiff / 2.0) + labelPadding()); tickItem->setLine(layout[i], axisRect.top(), layout[i], axisRect.top() + labelPadding()); @@ -193,7 +194,7 @@ void HorizontalAxis::updateGeometry() && (leftBound == gridRect.left() || rightBound == gridRect.right())) { forceHide = true; } else { - labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y()); + labelPos.setX(leftBound + (delta / 2.0) - center.x()); } } else { QCategoryAxis *categoryAxis = static_cast(axis()); @@ -202,19 +203,21 @@ void HorizontalAxis::updateGeometry() && (leftBound == gridRect.left() || rightBound == gridRect.right())) { forceHide = true; } else { - labelItem->setPos(leftBound + (delta / 2.0) - center.x(), - labelItem->pos().y()); + labelPos.setX(leftBound + (delta / 2.0) - center.x()); } } else if (categoryAxis->labelsPosition() == QCategoryAxis::AxisLabelsPositionOnValue) { if (axis()->isReverse()) - labelItem->setPos(leftBound - center.x(), labelItem->pos().y()); + labelPos.setX(leftBound - center.x()); else - labelItem->setPos(rightBound - center.x(), labelItem->pos().y()); + labelPos.setX(rightBound - center.x()); } } } + // Round to full pixel via QPoint to avoid one pixel clipping on the edge in some cases + labelItem->setPos(labelPos.toPoint()); + //label overlap detection - compensate one pixel for rounding errors if ((labelItem->pos().x() < width && labelItem->toPlainText() == ellipsis) || forceHide || (labelItem->pos().x() + (widthDiff / 2.0)) < (axisRect.left() - 1.0) || diff --git a/src/charts/axis/verticalaxis.cpp b/src/charts/axis/verticalaxis.cpp index dfa1a3b..0d85870 100644 --- a/src/charts/axis/verticalaxis.cpp +++ b/src/charts/axis/verticalaxis.cpp @@ -143,9 +143,10 @@ void VerticalAxis::updateGeometry() qreal heightDiff = rect.height() - boundingRect.height(); //ticks and label position + QPointF labelPos; if (axis()->alignment() == Qt::AlignLeft) { if (axis()->isReverse()) { - labelItem->setPos(axisRect.right() - rect.width() + (widthDiff / 2.0) + labelPos = QPointF(axisRect.right() - rect.width() + (widthDiff / 2.0) - labelPadding(), gridRect.top() + gridRect.bottom() - layout[layout.size() - i - 1] - center.y()); @@ -154,7 +155,7 @@ void VerticalAxis::updateGeometry() axisRect.right(), gridRect.top() + gridRect.bottom() - layout[i]); } else { - labelItem->setPos(axisRect.right() - rect.width() + (widthDiff / 2.0) + labelPos = QPointF(axisRect.right() - rect.width() + (widthDiff / 2.0) - labelPadding(), layout[i] - center.y()); tickItem->setLine(axisRect.right() - labelPadding(), layout[i], @@ -166,11 +167,11 @@ void VerticalAxis::updateGeometry() gridRect.top() + gridRect.bottom() - layout[i], axisRect.left() + labelPadding(), gridRect.top() + gridRect.bottom() - layout[i]); - labelItem->setPos(axisRect.left() + labelPadding() - (widthDiff / 2.0), + labelPos = QPointF(axisRect.left() + labelPadding() - (widthDiff / 2.0), gridRect.top() + gridRect.bottom() - layout[layout.size() - i - 1] - center.y()); } else { - labelItem->setPos(axisRect.left() + labelPadding() - (widthDiff / 2.0), + labelPos = QPointF(axisRect.left() + labelPadding() - (widthDiff / 2.0), layout[i] - center.y()); tickItem->setLine(axisRect.left(), layout[i], axisRect.left() + labelPadding(), layout[i]); @@ -199,8 +200,7 @@ void VerticalAxis::updateGeometry() && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) { forceHide = true; } else { - labelItem->setPos(labelItem->pos().x(), - lowerBound - (delta / 2.0) - center.y()); + labelPos.setY(lowerBound - (delta / 2.0) - center.y()); } } else { QCategoryAxis *categoryAxis = static_cast(axis()); @@ -209,22 +209,24 @@ void VerticalAxis::updateGeometry() && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) { forceHide = true; } else { - labelItem->setPos(labelItem->pos().x(), - lowerBound - (delta / 2.0) - center.y()); + labelPos.setY(lowerBound - (delta / 2.0) - center.y()); } } else if (categoryAxis->labelsPosition() == QCategoryAxis::AxisLabelsPositionOnValue) { labelOnValue = true; if (axis()->isReverse()) { - labelItem->setPos(labelItem->pos().x(), gridRect.top() + gridRect.bottom() + labelPos.setY(gridRect.top() + gridRect.bottom() - layout[i + 1] - center.y()); } else { - labelItem->setPos(labelItem->pos().x(), upperBound - center.y()); + labelPos.setY(upperBound - center.y()); } } } } + // Round to full pixel via QPoint to avoid one pixel clipping on the edge in some cases + labelItem->setPos(labelPos.toPoint()); + //label overlap detection - compensate one pixel for rounding errors if (axis()->isReverse()) { if (forceHide) diff --git a/src/charts/layout/abstractchartlayout.cpp b/src/charts/layout/abstractchartlayout.cpp index 3215898..223600b 100644 --- a/src/charts/layout/abstractchartlayout.cpp +++ b/src/charts/layout/abstractchartlayout.cpp @@ -156,7 +156,9 @@ QRectF AbstractChartLayout::calculateLegendMinimum(const QRectF &geometry, QLege QRectF AbstractChartLayout::calculateTitleGeometry(const QRectF &geometry, ChartTitle *title) const { title->setGeometry(geometry); - QPointF center = geometry.center() - title->boundingRect().center(); + // Round to full pixel via QPoint to avoid one pixel clipping on the edge in some cases + QPointF center((geometry.center() - title->boundingRect().center()).toPoint()); + title->setPos(center.x(), title->pos().y()); return geometry.adjusted(0, title->boundingRect().height()+1, 0, 0); } diff --git a/src/charts/legend/legendlayout.cpp b/src/charts/legend/legendlayout.cpp index c7d88e1..1d7ea11 100644 --- a/src/charts/legend/legendlayout.cpp +++ b/src/charts/legend/legendlayout.cpp @@ -233,10 +233,13 @@ void LegendLayout::setAttachedGeometry(const QRectF &rect) // Delete structs from the container qDeleteAll(legendWidthList); - if (m_width < geometry.width()) - m_legend->d_ptr->items()->setPos(geometry.width() / 2 - m_width / 2, geometry.top()); - else - m_legend->d_ptr->items()->setPos(geometry.topLeft()); + // Round to full pixel via QPoint to avoid one pixel clipping on the edge in some cases + if (m_width < geometry.width()) { + m_legend->d_ptr->items()->setPos(QPoint(geometry.width() / 2 - m_width / 2, + geometry.top())); + } else { + m_legend->d_ptr->items()->setPos(geometry.topLeft().toPoint()); + } m_height = size.height(); } break; @@ -262,10 +265,13 @@ void LegendLayout::setAttachedGeometry(const QRectF &rect) } } - if (m_height < geometry.height()) - m_legend->d_ptr->items()->setPos(geometry.left(), geometry.height() / 2 - m_height / 2); - else - m_legend->d_ptr->items()->setPos(geometry.topLeft()); + // Round to full pixel via QPoint to avoid one pixel clipping on the edge in some cases + if (m_height < geometry.height()) { + m_legend->d_ptr->items()->setPos(QPoint(geometry.left(), + geometry.height() / 2 - m_height / 2)); + } else { + m_legend->d_ptr->items()->setPos(geometry.topLeft().toPoint()); + } m_width = size.width(); break; } diff --git a/tests/manual/chartviewer/chartviewer.pro b/tests/manual/chartviewer/chartviewer.pro index 693c1ea..19b3549 100644 --- a/tests/manual/chartviewer/chartviewer.pro +++ b/tests/manual/chartviewer/chartviewer.pro @@ -3,7 +3,6 @@ } include(charts/charts.pri) TARGET = chartviewer -QT += opengl INCLUDEPATH += . SOURCES += main.cpp window.cpp view.cpp grid.cpp HEADERS += window.h view.h charts.h model.h grid.h diff --git a/tests/manual/chartviewer/window.cpp b/tests/manual/chartviewer/window.cpp index 73600d9..b9e863e 100644 --- a/tests/manual/chartviewer/window.cpp +++ b/tests/manual/chartviewer/window.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -398,11 +398,11 @@ void Window::checkLegend() void Window::checkOpenGL() { bool opengl = m_openGLCheckBox->isChecked(); - bool isOpengl = qobject_cast(m_view->viewport()); + bool isOpengl = qobject_cast(m_view->viewport()); if ((isOpengl && !opengl) || (!isOpengl && opengl)) { m_view->deleteLater(); m_view = new View(m_scene, m_form); - m_view->setViewport(!opengl ? new QWidget() : new QGLWidget()); + m_view->setViewport(!opengl ? new QWidget() : new QOpenGLWidget()); setCentralWidget(m_view); } diff --git a/tests/manual/chartwidgettest/chartwidgettest.pro b/tests/manual/chartwidgettest/chartwidgettest.pro index 3f4cdbb..9140c64 100644 --- a/tests/manual/chartwidgettest/chartwidgettest.pro +++ b/tests/manual/chartwidgettest/chartwidgettest.pro @@ -4,7 +4,7 @@ TEMPLATE = app -QT += core gui opengl widgets +QT += core gui widgets SOURCES += main.cpp \ mainwidget.cpp \ diff --git a/tests/manual/chartwidgettest/mainwidget.cpp b/tests/manual/chartwidgettest/mainwidget.cpp index fb4b4d4..ddd934c 100644 --- a/tests/manual/chartwidgettest/mainwidget.cpp +++ b/tests/manual/chartwidgettest/mainwidget.cpp @@ -41,7 +41,7 @@ #include #include #include -#include +#include QT_CHARTS_USE_NAMESPACE @@ -164,7 +164,7 @@ void MainWidget::initCheckboxes(QGridLayout *grid) aliasCheckBox->setChecked(false); grid->addWidget(aliasCheckBox, grid->rowCount(), 0); - QCheckBox *openGLCheckBox = new QCheckBox("Use QGLWidget"); + QCheckBox *openGLCheckBox = new QCheckBox("Use QOpenGLWidget"); connect(openGLCheckBox, SIGNAL(toggled(bool)), this, SLOT(openGLToggled(bool))); openGLCheckBox->setChecked(false); grid->addWidget(openGLCheckBox, grid->rowCount(), 0); @@ -178,11 +178,10 @@ void MainWidget::antiAliasToggled(bool enabled) void MainWidget::openGLToggled(bool enabled) { if (enabled) { - QGLFormat f = QGLFormat::defaultFormat(); - f.setSampleBuffers(true); + QSurfaceFormat f = QSurfaceFormat::defaultFormat(); f.setSamples(4); - QGLFormat::setDefaultFormat(f); - QGLWidget *g = new QGLWidget(); + QSurfaceFormat::setDefaultFormat(f); + QOpenGLWidget *g = new QOpenGLWidget(); m_chartView->setViewport(g); } else { m_chartView->setViewport(0); diff --git a/tests/manual/wavechart/main.cpp b/tests/manual/wavechart/main.cpp index 525bfb5..f5415f2 100644 --- a/tests/manual/wavechart/main.cpp +++ b/tests/manual/wavechart/main.cpp @@ -19,7 +19,7 @@ #include "wavechart.h" #include #include -#include +#include int main(int argc, char *argv[]) { @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) QChart *chart = new QChart(); WaveChart *waveChart = new WaveChart(chart,&window); - waveChart->setViewport( new QGLWidget() ); + waveChart->setViewport( new QOpenGLWidget() ); waveChart->setRenderHint(QPainter::Antialiasing); chart->setAnimationOptions(QChart::AllAnimations); chart->setTitle("This is wave generator."); diff --git a/tests/manual/wavechart/wavechart.pro b/tests/manual/wavechart/wavechart.pro index 0da16ed..da5c473 100644 --- a/tests/manual/wavechart/wavechart.pro +++ b/tests/manual/wavechart/wavechart.pro @@ -2,7 +2,6 @@ error( "Couldn't find the test.pri file!" ) } -QT+=opengl TARGET = wavechart SOURCES += main.cpp wavechart.cpp HEADERS += wavechart.h