Merge pull request #1603 from DaTweety/feature/grid-zoom
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m38s

Grid hidden when its dots crowd, at a distance you set; zoom in the status bar
This commit is contained in:
ispyisail
2026-10-26 11:31:08 +13:00
committed by GitHub
44 changed files with 48960 additions and 42995 deletions
+1443 -1271
View File
File diff suppressed because it is too large Load Diff
+1428 -1256
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1442 -1270
View File
File diff suppressed because it is too large Load Diff
+1403 -1263
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1411 -1263
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1459 -1287
View File
File diff suppressed because it is too large Load Diff
+1413 -1265
View File
File diff suppressed because it is too large Load Diff
+1443 -1271
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1442 -1270
View File
File diff suppressed because it is too large Load Diff
+1442 -1270
View File
File diff suppressed because it is too large Load Diff
+1438 -1266
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+25
View File
@@ -6377,6 +6377,21 @@ Any setting other than “No rounding” may cause rendering errors in the proje
3 - editing the project on another computer and/or screen that does not have the same settings as in points 1 and 2.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../sources/ui/configpage/generalconfigurationpage.ui" line="162"/>
<source>Hide the grid when its dots are closer on screen than</source>
<translation>Raster verbergen als de punten op het scherm dichter bij elkaar staan dan</translation>
</message>
<message>
<location filename="../sources/ui/configpage/generalconfigurationpage.ui" line="172"/>
<source>Zoomed out further, the dots of any grid step are left out; the zoom shown in the status bar tells where</source>
<translation>Verder uitgezoomd vallen de punten van elke rasterstap weg; de zoom in de statusbalk toont waar</translation>
</message>
<message>
<location filename="../sources/ui/configpage/generalconfigurationpage.ui" line="175"/>
<source> px</source>
<translation> px</translation>
</message>
</context>
<context>
<name>GenericPanel</name>
@@ -11807,6 +11822,16 @@ Unbridge and/or remove the levels from the affected terminals so that they can b
<comment>message box title</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../sources/qetdiagrameditor.cpp" line="4285"/>
<source>Zoom %1 %</source>
<translation>Zoom %1 %</translation>
</message>
<message>
<location filename="../sources/qetdiagrameditor.cpp" line="811"/>
<source>Zoom of the folio on screen</source>
<translation>Zoom van het blad op het scherm</translation>
</message>
<message>
<location filename="../sources/qetdiagrameditor.cpp" line="702"/>
<source>Snap to the grid</source>
+1459 -1287
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1443 -1271
View File
File diff suppressed because it is too large Load Diff
+1459 -1287
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1459 -1287
View File
File diff suppressed because it is too large Load Diff
+1459 -1287
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1430 -1258
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+1427 -1255
View File
File diff suppressed because it is too large Load Diff
+35 -31
View File
@@ -351,42 +351,46 @@ void Diagram::drawBackground(QPainter *p, const QRectF &r) {
const int xGrid = FolioGrid::step(settings.value(FolioGrid::x_key), Diagram::xGrid);
const int yGrid = FolioGrid::step(settings.value(FolioGrid::y_key), Diagram::yGrid);
qreal limit_x = rect.x() + rect.width();
qreal limit_y = rect.y() + rect.height();
//Left out when they would crowd, whatever the grid step
const qreal zoom_factor = p->transform().m11();
if (FolioGrid::dotsShown(xGrid, yGrid, zoom_factor,
FolioGrid::minDotSpacing(settings.value(FolioGrid::min_dot_spacing_key))))
{
qreal limit_x = rect.x() + rect.width();
qreal limit_y = rect.y() + rect.height();
int g_x = (int)ceil(rect.x());
while (g_x % xGrid) ++ g_x;
int g_y = (int)ceil(rect.y());
while (g_y % yGrid) ++ g_y;
int g_x = (int)ceil(rect.x());
while (g_x % xGrid) ++ g_x;
int g_y = (int)ceil(rect.y());
while (g_y % yGrid) ++ g_y;
QPolygon points;
for (int gx = g_x ; gx < limit_x ; gx += xGrid) {
for (int gy = g_y ; gy < limit_y ; gy += yGrid) {
points << QPoint(gx, gy);
}
}
qreal zoom_factor = p->transform().m11();
int minWidthPen = settings.value(QStringLiteral("diagrameditor/grid_pointsize_min"), 1).toInt();
int maxWidthPen = settings.value(QStringLiteral("diagrameditor/grid_pointsize_max"), 1).toInt();
pen.setWidth(minWidthPen);
if (minWidthPen != maxWidthPen) {
qreal stepPen = (maxWidthPen - minWidthPen) / (qreal)maxWidthPen;
qreal stepZoom = (5.0 - 1.0) / maxWidthPen;
for (int n=0; n<maxWidthPen; n++) {
if ((zoom_factor > (1.0 + n * stepZoom)) && (zoom_factor <= (1.0 + (n+1) * stepZoom))) {
int widthPen = minWidthPen + qRound(n * stepPen);
pen.setWidth(widthPen);
QPolygon points;
for (int gx = g_x ; gx < limit_x ; gx += xGrid) {
for (int gy = g_y ; gy < limit_y ; gy += yGrid) {
points << QPoint(gx, gy);
}
}
if (zoom_factor <= 1.0)
pen.setWidth(minWidthPen);
else if (zoom_factor > (1.0 + stepZoom * maxWidthPen))
pen.setWidth(maxWidthPen);
int minWidthPen = settings.value(QStringLiteral("diagrameditor/grid_pointsize_min"), 1).toInt();
int maxWidthPen = settings.value(QStringLiteral("diagrameditor/grid_pointsize_max"), 1).toInt();
pen.setWidth(minWidthPen);
if (minWidthPen != maxWidthPen) {
qreal stepPen = (maxWidthPen - minWidthPen) / (qreal)maxWidthPen;
qreal stepZoom = (5.0 - 1.0) / maxWidthPen;
for (int n=0; n<maxWidthPen; n++) {
if ((zoom_factor > (1.0 + n * stepZoom)) && (zoom_factor <= (1.0 + (n+1) * stepZoom))) {
int widthPen = minWidthPen + qRound(n * stepPen);
pen.setWidth(widthPen);
}
}
if (zoom_factor <= 1.0)
pen.setWidth(minWidthPen);
else if (zoom_factor > (1.0 + stepZoom * maxWidthPen))
pen.setWidth(maxWidthPen);
}
p -> setPen(pen);
p -> drawPoints(points);
}
p -> setPen(pen);
if (zoom_factor > 0.5) // no grid below ... !
p -> drawPoints(points);
}
if (draw_guides_) {
+6
View File
@@ -2337,6 +2337,12 @@ void DiagramView::paintEvent(QPaintEvent *event)
{
PaletteGraphicsView::paintEvent(event);
//Every way of zooming ends in a repaint
if (transform().m11() != m_shown_zoom) {
m_shown_zoom = transform().m11();
emit zoomChanged(m_shown_zoom);
}
//Scrolling and zooming both repaint the viewport: follow them.
//Showing or hiding a ruler resizes the viewport, which cannot be
//done while it paints.
+3
View File
@@ -113,6 +113,7 @@ class DiagramView : public PaletteGraphicsView
bool m_cell_rulers_shown = false;
/// Last viewport transform the rulers were painted for
QTransform m_rulers_transform;
qreal m_shown_zoom = 0;
bool m_cell_lines_shown = false;
@@ -229,6 +230,8 @@ class DiagramView : public PaletteGraphicsView
/// Signal emitted when the placement mode is entered for an
/// element (not a macro), whether from a drop or not.
void elementPlacementStarted(const ElementsLocation &);
/// The view's scale changed: 1 is 100 %
void zoomChanged(qreal factor);
public slots:
void setVisualisationMode();
+42
View File
@@ -19,7 +19,9 @@
#define FOLIOGRID_H
#include <QString>
#include <QtGlobal>
#include <QVariant>
#include <cmath>
#include <limits>
/**
@@ -49,6 +51,46 @@ namespace FolioGrid
return fallback;
return int(s);
}
/// QSettings key of the smallest distance, in pixels on screen,
/// at which grid dots are still drawn (General > Appearance)
inline const QString min_dot_spacing_key{QStringLiteral("diagrameditor/grid_min_dot_spacing")};
/// Grid dots closer than this on screen, in pixels, read as a
/// gray haze rather than as a grid. With the default step of 10,
/// the dots go below a zoom of 75 %.
constexpr double default_min_dot_spacing = 7.5;
/// The smallest and largest distance the preferences page offers
constexpr double min_dot_spacing_lowest = 1.0;
constexpr double min_dot_spacing_highest = 50.0;
/**
@return the smallest dot distance held in @p value, a settings
entry, or the default when it is missing, not a number, not
finite, or outside what the preferences page offers: a hand-edited
"inf" or 1e9 would hide the grid for good while the page showed
another value.
*/
inline double minDotSpacing(const QVariant &value)
{
bool ok = false;
const double spacing = value.toDouble(&ok);
return ok && std::isfinite(spacing)
&& spacing >= min_dot_spacing_lowest && spacing <= min_dot_spacing_highest
? spacing : default_min_dot_spacing;
}
/**
@return true when the grid dots are drawn: when two of them, @p x_step
and @p y_step apart on the folio, stand at least @p min_spacing
pixels apart on screen at @p zoom (1 is 100 %). Whatever the step,
they go when they would crowd; with the default step of 10 and
spacing of 7.5, below a zoom of 75 %.
*/
inline bool dotsShown(int x_step, int y_step, double zoom,
double min_spacing = default_min_dot_spacing)
{
return qMin(x_step, y_step) * zoom >= min_spacing;
}
}
#endif // FOLIOGRID_H
+22
View File
@@ -838,6 +838,9 @@ void QETDiagramEditor::setUpActions()
m_hidden_kinds_label = new QLabel(this);
m_hidden_kinds_label->setToolTip(tr("See Display > Show"));
statusBar()->addPermanentWidget(m_hidden_kinds_label);
m_zoom_label = new QLabel(this);
m_zoom_label->setToolTip(tr("Zoom of the folio on screen"));
statusBar()->addPermanentWidget(m_zoom_label);
connect(QETApp::instance(), &QETApp::shownKindsChanged,
this, &QETDiagramEditor::updateShownKinds);
updateShownKinds();
@@ -3184,6 +3187,7 @@ void QETDiagramEditor::slot_updateActions()
bool opened_project = pv;
bool opened_diagram = dv;
bool editable_project = (pv && !pv -> project() -> isReadOnly());
updateZoomLabel();
m_close_file-> setEnabled(opened_project);
m_save_file-> setEnabled(opened_project);
@@ -4273,6 +4277,24 @@ void QETDiagramEditor::diagramWasAdded(DiagramView *dv)
&QETDiagramEditor::slot_updateComplexActions);
connect(dv, &DiagramView::modeChanged, this, &QETDiagramEditor::slot_updateModeActions);
connect(dv, &DiagramView::elementPlacementStarted, this, &QETDiagramEditor::rememberPlacedElement);
connect(dv, &DiagramView::zoomChanged, this, &QETDiagramEditor::updateZoomLabel);
}
/**
@brief QETDiagramEditor::updateZoomLabel
Show the zoom of the folio on screen in the status bar, nothing when
no folio is shown.
*/
void QETDiagramEditor::updateZoomLabel()
{
if (!m_zoom_label)
return;
DiagramView *dv = currentDiagramView();
//Four digits, not rounded to a whole percent: the grid's cutoff
//(Settings > General) compares the exact zoom, so 77.6 % shows as
//such, not as 78 %
m_zoom_label->setText(dv ? tr("Zoom %1 %").arg(QLocale().toString(dv->transform().m11() * 100, 'g', 4))
: QString());
}
/**
+2
View File
@@ -148,6 +148,7 @@ class QETDiagramEditor : public QETMainWindow
void alignGroupTriggered (QAction *action);
void rowColumnGroupTriggered (QAction *action);
void slot_updateActions();
void updateZoomLabel();
void slot_updateUndoStack();
void slot_updateModeActions();
void slot_updateComplexActions();
@@ -330,6 +331,7 @@ class QETDiagramEditor : public QETMainWindow
QToolButton *m_text_grid_button = nullptr;
QMenu *m_shown_kinds_menu = nullptr; ///< View > Show, kinds of items (#301)
QLabel *m_hidden_kinds_label = nullptr; ///< Status bar: how many kinds are hidden
QLabel *m_zoom_label = nullptr; ///< Status bar: the zoom of the folio on screen
QList <QAction *> m_zoom_action_toolBar; ///Only zoom action must displayed in the toolbar
@@ -29,6 +29,7 @@
#include "../../utils/qetutils.h"
#include "../../utils/previousversions.h"
#include "../../qetmessagebox.h"
#include "../../foliogrid.h"
#include "../../textgrid.h"
#include "../../wiringrules.h"
#include "../wiringruleswarning.h"
@@ -110,6 +111,10 @@ GeneralConfigurationPage::GeneralConfigurationPage(QWidget *parent) :
}
ui->grid_startup_cb->setChecked(settings.value("diagrameditor/grid_display_startup", true).toBool());
ui->m_grid_min_spacing_sb->setRange(FolioGrid::min_dot_spacing_lowest,
FolioGrid::min_dot_spacing_highest);
ui->m_grid_min_spacing_sb->setValue(
FolioGrid::minDotSpacing(settings.value(FolioGrid::min_dot_spacing_key)));
ui->guides_startup_cb->setChecked(settings.value("diagrameditor/guides_display_startup", false).toBool());
//Stored as "inserts" but presented as "edits", so the default (insert)
//is the unchecked state -- a preference reads better as an opt-out.
@@ -425,6 +430,7 @@ void GeneralConfigurationPage::applyConf()
PreviousVersions::setCount(ui->m_previous_versions_sb->value());
settings.setValue("diagrameditor/grid_display_startup", ui->grid_startup_cb->isChecked());
settings.setValue(FolioGrid::min_dot_spacing_key, ui->m_grid_min_spacing_sb->value());
settings.setValue("diagrameditor/guides_display_startup", ui->guides_startup_cb->isChecked());
settings.setValue("elementscollection/double-click-inserts", !ui->m_collection_dblclick_edits->isChecked());
settings.setValue("elementscollection/search-flat-list", ui->m_collection_search_flat_cb->isChecked());
@@ -154,6 +154,58 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="m_grid_min_spacing_layout">
<item>
<widget class="QLabel" name="m_grid_min_spacing_label">
<property name="text">
<string>Hide the grid when its dots are closer on screen than</string>
</property>
<property name="buddy">
<cstring>m_grid_min_spacing_sb</cstring>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="m_grid_min_spacing_sb">
<property name="toolTip">
<string>Zoomed out further, the dots of any grid step are left out; the zoom shown in the status bar tells where. In pixels as the system scales them, so the same value suits a HiDPI screen</string>
</property>
<property name="suffix">
<string> px</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>50.000000000000000</double>
</property>
<property name="singleStep">
<double>0.500000000000000</double>
</property>
<property name="value">
<double>7.500000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="m_grid_min_spacing_spacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="m_collection_dblclick_edits">
<property name="toolTip">
+35
View File
@@ -32,6 +32,41 @@ class tst_foliogrid : public QObject
Q_OBJECT
private slots:
void dotsGoWhenTheyCrowd()
{
//The default step and spacing: the dots go below 75 %
QVERIFY(FolioGrid::dotsShown(10, 10, 0.75));
QVERIFY(!FolioGrid::dotsShown(10, 10, 0.74));
//A finer step goes sooner, a coarser one later; the finer of
//the two directions decides
QVERIFY(!FolioGrid::dotsShown(5, 5, 1.4));
QVERIFY(FolioGrid::dotsShown(20, 20, 0.4));
QVERIFY(!FolioGrid::dotsShown(20, 5, 1.0));
//A spacing set in the settings: 7.8 px keeps them down to 78 %
QVERIFY(FolioGrid::dotsShown(10, 10, 0.78, 7.8));
QVERIFY(!FolioGrid::dotsShown(10, 10, 0.77, 7.8));
}
void dotSpacingFromSettings()
{
QCOMPARE(FolioGrid::minDotSpacing(QVariant()), 7.5);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(7.8)), 7.8);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(QStringLiteral("12"))), 12.0);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(0)), 7.5);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(-3)), 7.5);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(QStringLiteral("ten"))), 7.5);
//Only what the preferences page offers, 1 to 50 px: no
//endless or huge value hides the grid for good
QCOMPARE(FolioGrid::minDotSpacing(QVariant(1.0)), 1.0);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(50.0)), 50.0);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(0.5)), 7.5);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(50.5)), 7.5);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(1e9)), 7.5);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(QStringLiteral("inf"))), 7.5);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(std::numeric_limits<double>::infinity())), 7.5);
QCOMPARE(FolioGrid::minDotSpacing(QVariant(std::numeric_limits<double>::quiet_NaN())), 7.5);
}
void usableValuesAreKept_data()
{
QTest::addColumn<QVariant>("value");