diff --git a/src/Mod/Spreadsheet/Gui/CMakeLists.txt b/src/Mod/Spreadsheet/Gui/CMakeLists.txt
index 35e130667f..f6a6a2f3af 100644
--- a/src/Mod/Spreadsheet/Gui/CMakeLists.txt
+++ b/src/Mod/Spreadsheet/Gui/CMakeLists.txt
@@ -86,6 +86,8 @@ SET(SpreadsheetGui_SRCS
DlgBindSheet.cpp
DlgSheetConf.h
DlgSheetConf.cpp
+ ZoomableView.h
+ ZoomableView.cpp
${SpreadsheetGui_UIC_HDRS}
)
diff --git a/src/Mod/Spreadsheet/Gui/DlgSettings.ui b/src/Mod/Spreadsheet/Gui/DlgSettings.ui
index 947d5e2961..e6f19c4313 100644
--- a/src/Mod/Spreadsheet/Gui/DlgSettings.ui
+++ b/src/Mod/Spreadsheet/Gui/DlgSettings.ui
@@ -6,8 +6,8 @@
0
0
- 322
- 149
+ 392
+ 282
@@ -25,8 +25,8 @@
Display Settings
-
- -
+
+
-
If checked, use the custom presentation to display cell string.
@@ -42,7 +42,62 @@
- -
+
-
+
+
+ Set a zoom level for table view from 60% to 160%.
+
+
+ %
+
+
+ 60
+
+
+ 160
+
+
+ 10
+
+
+ 100
+
+
+ DefaultZoomLevel
+
+
+ Mod/Spreadsheet
+
+
+
+ -
+
+
+ Default zoom level:
+
+
+
+ -
+
+
+ The format of the custom cell string presentation.
+Defaults to: %V = %A
+
+%A - alias name
+%V - cell value
+
+
+ %V = %A
+
+
+ DisplayAliasFormatString
+
+
+ Mod/Spreadsheet
+
+
+
+ -
Qt::Horizontal
@@ -55,26 +110,6 @@
- -
-
-
- %V = %A
-
-
- The format of the custom cell string presentation.
-Defaults to: %V = %A
-
-%A - alias name
-%V - cell value
-
-
- DisplayAliasFormatString
-
-
- Mod/Spreadsheet
-
-
-
@@ -110,10 +145,10 @@ Defaults to: %V = %A
- -
+
-
- <html><head/><body><p>Character to use as field delimiter. Default is tab, but also commonly used are commas (,) and semicolons (;). Select from the list or enter your own in the field. Must be a single character or the words <span style=" font-style:italic;">tab</span>, <span style=" font-style:italic;">comma</span>, or <span style=" font-style:italic;">semicolon</span>.</p></body></html>
+ <html><head/><body><p>Character to use as field delimiter. Default is tab, but also commonly used are commas (,) and semicolons (;). Select from the list or enter your own in the field. Must be a single character or the words <span style=" font-style:italic;">tab</span>, <span style=" font-style:italic;">comma</span>, or <span style=" font-style:italic;">semicolon</span>.</p></body></html>
true
@@ -166,7 +201,7 @@ Defaults to: %V = %A
- "
+ "
ImportExportQuoteCharacter
@@ -205,7 +240,7 @@ Defaults to: %V = %A
-
+
-
@@ -225,22 +260,35 @@ Defaults to: %V = %A
+
+ Gui::PrefCheckBox
+ QCheckBox
+
+
Gui::PrefComboBox
QComboBox
+
+ Gui::PrefSpinBox
+ QSpinBox
+
+
Gui::PrefLineEdit
QLineEdit
-
- Gui::PrefCheckBox
- QCheckBox
-
-
+
+ delimiterComboBox
+ quoteCharLineEdit
+ escapeCharLineEdit
+ dZLSpinBox
+ checkBoxShowAlias
+ formatString
+
diff --git a/src/Mod/Spreadsheet/Gui/DlgSettingsImp.cpp b/src/Mod/Spreadsheet/Gui/DlgSettingsImp.cpp
index d90e4fc54b..f301917e46 100644
--- a/src/Mod/Spreadsheet/Gui/DlgSettingsImp.cpp
+++ b/src/Mod/Spreadsheet/Gui/DlgSettingsImp.cpp
@@ -57,6 +57,7 @@ void DlgSettingsImp::saveSettings()
ui->quoteCharLineEdit->onSave();
ui->escapeCharLineEdit->onSave();
ui->formatString->onSave();
+ ui->dZLSpinBox->onSave();
ui->checkBoxShowAlias->onSave();
}
@@ -94,6 +95,7 @@ void DlgSettingsImp::loadSettings()
ui->quoteCharLineEdit->onRestore();
ui->escapeCharLineEdit->onRestore();
ui->formatString->onRestore();
+ ui->dZLSpinBox->onRestore();
ui->checkBoxShowAlias->onRestore();
}
diff --git a/src/Mod/Spreadsheet/Gui/Sheet.ui b/src/Mod/Spreadsheet/Gui/Sheet.ui
index 0a0c47596e..9d1f78bfe0 100644
--- a/src/Mod/Spreadsheet/Gui/Sheet.ui
+++ b/src/Mod/Spreadsheet/Gui/Sheet.ui
@@ -57,7 +57,154 @@ Spreadsheet.my_alias_name instead of Spreadsheet.B1
-
-
+
+
-
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 5
+
+
+ 20
+
+
+ Qt::Vertical
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ 5
+
+
+ 20
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::NoFocus
+
+
+ Zoom
+
+
+ Qt::ToolButtonTextOnly
+
+
+ true
+
+
+
+ -
+
+
+ Qt::ClickFocus
+
+
+ -
+
+
+ Qt::ToolButtonTextOnly
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::ClickFocus
+
+
+ 60
+
+
+ 160
+
+
+ 10
+
+
+ 20
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBelow
+
+
+ 10
+
+
+
+ -
+
+
+ Qt::ClickFocus
+
+
+ +
+
+
+ Qt::ToolButtonTextOnly
+
+
+ true
+
+
+
+
diff --git a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp
index 3a9f33585c..e956370843 100644
--- a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp
+++ b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp
@@ -119,7 +119,7 @@ SheetTableView::SheetTableView(QWidget* parent)
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
connect(verticalHeader(), &QWidget::customContextMenuRequested, [this](const QPoint& point) {
- QMenu menu(this);
+ QMenu menu {nullptr};
const auto selection = selectionModel()->selectedRows();
const auto& [min, max] = selectedMinMaxRows(selection);
if (bool isContiguous = max - min == selection.size() - 1) {
@@ -141,11 +141,11 @@ SheetTableView::SheetTableView(QWidget* parent)
}
auto remove = menu.addAction(tr("Remove row(s)", "", selection.size()));
connect(remove, &QAction::triggered, this, &SheetTableView::removeRows);
- menu.exec(verticalHeader()->mapToGlobal(point));
+ menu.exec(QCursor::pos());
});
connect(horizontalHeader(), &QWidget::customContextMenuRequested, [this](const QPoint& point) {
- QMenu menu(this);
+ QMenu menu {nullptr};
const auto selection = selectionModel()->selectedColumns();
const auto& [min, max] = selectedMinMaxColumns(selection);
if (bool isContiguous = max - min == selection.size() - 1) {
@@ -171,7 +171,7 @@ SheetTableView::SheetTableView(QWidget* parent)
}
auto remove = menu.addAction(tr("Remove column(s)", "", selection.size()));
connect(remove, &QAction::triggered, this, &SheetTableView::removeColumns);
- menu.exec(horizontalHeader()->mapToGlobal(point));
+ menu.exec(QCursor::pos());
});
actionProperties = new QAction(tr("Properties..."), this);
@@ -180,41 +180,40 @@ SheetTableView::SheetTableView(QWidget* parent)
horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
verticalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
- contextMenu = new QMenu(this);
- contextMenu->addAction(actionProperties);
+ contextMenu.addAction(actionProperties);
connect(actionProperties, &QAction::triggered, this, &SheetTableView::cellProperties);
- contextMenu->addSeparator();
+ contextMenu.addSeparator();
actionRecompute = new QAction(tr("Recompute"), this);
connect(actionRecompute, &QAction::triggered, this, &SheetTableView::onRecompute);
- contextMenu->addAction(actionRecompute);
+ contextMenu.addAction(actionRecompute);
actionBind = new QAction(tr("Bind..."), this);
connect(actionBind, &QAction::triggered, this, &SheetTableView::onBind);
- contextMenu->addAction(actionBind);
+ contextMenu.addAction(actionBind);
actionConf = new QAction(tr("Configuration table..."), this);
connect(actionConf, &QAction::triggered, this, &SheetTableView::onConfSetup);
- contextMenu->addAction(actionConf);
+ contextMenu.addAction(actionConf);
horizontalHeader()->addAction(actionBind);
verticalHeader()->addAction(actionBind);
- contextMenu->addSeparator();
- actionMerge = contextMenu->addAction(tr("Merge cells"));
+ contextMenu.addSeparator();
+ actionMerge = contextMenu.addAction(tr("Merge cells"));
connect(actionMerge, &QAction::triggered, this, &SheetTableView::mergeCells);
- actionSplit = contextMenu->addAction(tr("Split cells"));
+ actionSplit = contextMenu.addAction(tr("Split cells"));
connect(actionSplit, &QAction::triggered, this, &SheetTableView::splitCell);
- contextMenu->addSeparator();
- actionCut = contextMenu->addAction(tr("Cut"));
+ contextMenu.addSeparator();
+ actionCut = contextMenu.addAction(tr("Cut"));
connect(actionCut, &QAction::triggered, this, &SheetTableView::cutSelection);
- actionCopy = contextMenu->addAction(tr("Copy"));
+ actionCopy = contextMenu.addAction(tr("Copy"));
connect(actionCopy, &QAction::triggered, this, &SheetTableView::copySelection);
- actionPaste = contextMenu->addAction(tr("Paste"));
+ actionPaste = contextMenu.addAction(tr("Paste"));
connect(actionPaste, &QAction::triggered, this, &SheetTableView::pasteClipboard);
- actionDel = contextMenu->addAction(tr("Delete"));
+ actionDel = contextMenu.addAction(tr("Delete"));
connect(actionDel, &QAction::triggered, this, &SheetTableView::deleteSelection);
setTabKeyNavigation(false);
@@ -241,7 +240,7 @@ void SheetTableView::onBind()
{
auto ranges = selectedRanges();
if (!ranges.empty() && ranges.size() <= 2) {
- DlgBindSheet dlg(sheet, ranges, this);
+ DlgBindSheet dlg {sheet, ranges};
dlg.exec();
}
}
@@ -252,16 +251,16 @@ void SheetTableView::onConfSetup()
if (ranges.empty()) {
return;
}
- DlgSheetConf dlg(sheet, ranges.back(), this);
+ DlgSheetConf dlg {sheet, ranges.back()};
dlg.exec();
}
void SheetTableView::cellProperties()
{
- std::unique_ptr dialog(new PropertiesDialog(sheet, selectedRanges(), this));
+ PropertiesDialog dialog {sheet, selectedRanges()};
- if (dialog->exec() == QDialog::Accepted) {
- dialog->apply();
+ if (dialog.exec() == QDialog::Accepted) {
+ dialog.apply();
}
}
@@ -1125,7 +1124,7 @@ void SheetTableView::contextMenuEvent(QContextMenuEvent*)
auto ranges = selectedRanges();
actionBind->setEnabled(!ranges.empty() && ranges.size() <= 2);
- contextMenu->exec(QCursor::pos());
+ contextMenu.exec(QCursor::pos());
}
QString SheetTableView::toHtml() const
diff --git a/src/Mod/Spreadsheet/Gui/SheetTableView.h b/src/Mod/Spreadsheet/Gui/SheetTableView.h
index 4c41900974..e63af97da9 100644
--- a/src/Mod/Spreadsheet/Gui/SheetTableView.h
+++ b/src/Mod/Spreadsheet/Gui/SheetTableView.h
@@ -26,7 +26,7 @@
#include
#include
#include
-
+#include
#include
@@ -109,7 +109,7 @@ protected:
Spreadsheet::Sheet* sheet;
int tabCounter;
- QMenu* contextMenu;
+ QMenu contextMenu;
QAction* actionProperties;
QAction* actionRecompute;
diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp b/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp
index 3a7a009943..fb276b562a 100644
--- a/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp
+++ b/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp
@@ -28,7 +28,6 @@
#include
#include
#include
-#include
#endif
#include
@@ -47,6 +46,7 @@
#include "LineEdit.h"
#include "SpreadsheetDelegate.h"
#include "SpreadsheetView.h"
+#include "ZoomableView.h"
#include "qtcolorpicker.h"
#include "ui_Sheet.h"
@@ -74,6 +74,8 @@ SheetView::SheetView(Gui::Document* pcDocument, App::DocumentObject* docObj, QWi
ui->setupUi(w);
setCentralWidget(w);
+ new ZoomableView(ui);
+
delegate = new SpreadsheetDelegate(sheet);
ui->cells->setModel(model);
ui->cells->setItemDelegate(delegate);
diff --git a/src/Mod/Spreadsheet/Gui/ZoomableView.cpp b/src/Mod/Spreadsheet/Gui/ZoomableView.cpp
new file mode 100644
index 0000000000..3efcd32a29
--- /dev/null
+++ b/src/Mod/Spreadsheet/Gui/ZoomableView.cpp
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/****************************************************************************
+ * *
+ * Copyright (c) 2024 xtemp09 *
+ * *
+ * This file is part of FreeCAD. *
+ * *
+ * FreeCAD is free software: you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation, either version 2.1 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * FreeCAD is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with FreeCAD. If not, see *
+ * . *
+ * *
+ ***************************************************************************/
+
+#include
+#include
+
+#include "ZoomableView.h"
+#include "ui_Sheet.h"
+
+
+ZoomableView::ZoomableView(Ui::Sheet* ui)
+ : QGraphicsView {}
+ , stv {ui->cells}
+{
+ if (!stv) {
+ Base::Console().DeveloperWarning("ZoomableView", "Failed to find a SheetTableView object");
+ deleteLater();
+ return;
+ }
+ else {
+ QLayoutItem* li_stv = stv->parentWidget()->layout()->replaceWidget(stv, this);
+ if (li_stv == nullptr) {
+ Base::Console().DeveloperWarning("ZoomableView",
+ "Failed to replace the SheetTableView object");
+ deleteLater();
+ return;
+ }
+ delete li_stv;
+ }
+
+ stv->setParent(nullptr);
+ qpw = m_scene.addWidget(stv);
+ setScene(&m_scene);
+
+ setBackgroundBrush(Qt::transparent);
+ setFrameStyle(QFrame::NoFrame);
+
+ setSizePolicy(QSizePolicy {QSizePolicy::Expanding, QSizePolicy::Expanding});
+
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+ stv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ stv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+ QPointer dummySB_h {stv->horizontalScrollBar()},
+ dummySB_v {stv->verticalScrollBar()}, realSB_h {ui->realSB_h}, realSB_v {ui->realSB_v};
+
+ if (!dummySB_h || !dummySB_v || !realSB_h || !realSB_v) {
+ Base::Console().DeveloperWarning("ZoomableView", "Failed to identify the scrollbars");
+ deleteLater();
+ return;
+ }
+
+ realSB_h->setRange(dummySB_h->minimum(), dummySB_h->maximum());
+ realSB_v->setRange(dummySB_v->minimum(), dummySB_v->maximum());
+
+ realSB_h->setPageStep(dummySB_h->pageStep());
+ realSB_v->setPageStep(dummySB_v->pageStep());
+
+
+ connect(realSB_h, &QAbstractSlider::valueChanged, dummySB_h, &QAbstractSlider::setValue);
+ connect(realSB_v, &QAbstractSlider::valueChanged, dummySB_v, &QAbstractSlider::setValue);
+
+ connect(dummySB_h, &QAbstractSlider::rangeChanged, realSB_h, &QAbstractSlider::setRange);
+ connect(dummySB_v, &QAbstractSlider::rangeChanged, realSB_v, &QAbstractSlider::setRange);
+
+ connect(dummySB_h, &QAbstractSlider::valueChanged, this, &ZoomableView::updateView);
+ connect(dummySB_v, &QAbstractSlider::valueChanged, this, &ZoomableView::updateView);
+
+ connect(this,
+ &ZoomableView::zoomLevelChanged,
+ ui->zoomTB,
+ [zoomTB = ui->zoomTB](int new_zoomLevel) {
+ zoomTB->setText(QStringLiteral("%1%").arg(new_zoomLevel));
+ });
+
+ connect(this,
+ &ZoomableView::zoomLevelChanged,
+ ui->zoomSlider,
+ [zoomSlider = ui->zoomSlider](int new_zoomLevel) {
+ zoomSlider->blockSignals(true);
+ zoomSlider->setValue(new_zoomLevel);
+ zoomSlider->blockSignals(false);
+ });
+
+ connect(ui->zoomPlus, &QToolButton::clicked, this, &ZoomableView::zoomIn);
+ connect(ui->zoomSlider, &QSlider::valueChanged, this, &ZoomableView::setZoomLevel);
+ connect(ui->zoomMinus, &QToolButton::clicked, this, &ZoomableView::zoomOut);
+
+ connect(ui->zoomTB, &QToolButton::clicked, ui->zoomSlider, [zoomSlider = ui->zoomSlider]() {
+ const QString title = tr("Zoom level"), label = tr("New zoom level:");
+ constexpr int min = ZoomableView::min, max = ZoomableView::max, step = 10;
+ const int val = zoomSlider->value();
+ bool ok;
+ const int new_val =
+ QInputDialog::getInt(zoomSlider, title, label, val, min, max, step, &ok);
+
+ if (ok) {
+ zoomSlider->setValue(new_val);
+ }
+ });
+
+ resetZoom();
+}
+
+int ZoomableView::zoomLevel() const
+{
+ return m_zoomLevel;
+}
+
+void ZoomableView::setZoomLevel(int new_zoomLevel)
+{
+ checkLimits(new_zoomLevel);
+
+ if (m_zoomLevel == new_zoomLevel) {
+ return;
+ }
+
+ m_zoomLevel = new_zoomLevel;
+ updateView();
+ Q_EMIT zoomLevelChanged(m_zoomLevel);
+}
+
+inline void ZoomableView::checkLimits(int& zoom_level)
+{
+ zoom_level = qBound(ZoomableView::min, zoom_level, ZoomableView::max);
+}
+
+void ZoomableView::zoomIn(void)
+{
+ setZoomLevel(m_zoomLevel + zoom_step_kb);
+}
+
+void ZoomableView::zoomOut(void)
+{
+ setZoomLevel(m_zoomLevel - zoom_step_kb);
+}
+
+void ZoomableView::resetZoom(void)
+{
+ constexpr const char* path = "User parameter:BaseApp/Preferences/Mod/Spreadsheet";
+ ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(path);
+ const int defaultZoomLevel = static_cast(hGrp->GetInt("DefaultZoomLevel", 100));
+
+ setZoomLevel(defaultZoomLevel);
+}
+
+void ZoomableView::updateView(void)
+{
+ /* QGraphicsView has hardcoded margins therefore we have to avoid fitInView
+ * Find more information at https://bugreports.qt.io/browse/QTBUG-42331 */
+
+ const qreal scale_factor = static_cast(m_zoomLevel) / 100.0,
+ new_w = static_cast(viewport()->rect().width()) / scale_factor,
+ new_h = static_cast(viewport()->rect().height()) / scale_factor;
+
+ const QRectF new_geometry {0.0, 0.0, new_w, new_h};
+
+ const QRect old_geometry {stv->geometry()};
+ stv->setGeometry(1, 1, old_geometry.width() - 1, old_geometry.height() - 1);
+
+ resetTransform();
+ qpw->setGeometry(new_geometry);
+ setSceneRect(new_geometry);
+ scale(scale_factor, scale_factor);
+ centerOn(new_geometry.center());
+}
+
+void ZoomableView::keyPressEvent(QKeyEvent* event)
+{
+ if (event->modifiers() & Qt::ControlModifier) {
+ switch (event->key()) {
+ case Qt::Key_Plus:
+ zoomIn();
+ event->accept();
+ break;
+ case Qt::Key_Minus:
+ zoomOut();
+ event->accept();
+ break;
+ case Qt::Key_0:
+ resetZoom();
+ event->accept();
+ break;
+ default:
+ QGraphicsView::keyPressEvent(event);
+ }
+ }
+ else {
+ QGraphicsView::keyPressEvent(event);
+ }
+}
+
+void ZoomableView::resizeEvent(QResizeEvent* event)
+{
+ QGraphicsView::resizeEvent(event);
+ updateView();
+}
+
+void ZoomableView::wheelEvent(QWheelEvent* event)
+{
+ if (event->modifiers() & Qt::ControlModifier) {
+ const int y = event->angleDelta().y();
+ setZoomLevel(m_zoomLevel + (y > 0 ? zoom_step_mwheel : -zoom_step_mwheel));
+ event->accept();
+ }
+ else {
+ QGraphicsView::wheelEvent(event);
+ }
+}
diff --git a/src/Mod/Spreadsheet/Gui/ZoomableView.h b/src/Mod/Spreadsheet/Gui/ZoomableView.h
new file mode 100644
index 0000000000..7f14abb7ff
--- /dev/null
+++ b/src/Mod/Spreadsheet/Gui/ZoomableView.h
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/****************************************************************************
+ * *
+ * Copyright (c) 2024 xtemp09 *
+ * *
+ * This file is part of FreeCAD. *
+ * *
+ * FreeCAD is free software: you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation, either version 2.1 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * FreeCAD is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with FreeCAD. If not, see *
+ * . *
+ * *
+ ***************************************************************************/
+
+#ifndef ZOOMABLEVIEW_H
+#define ZOOMABLEVIEW_H
+
+#include
+
+#include "SpreadsheetView.h"
+
+namespace SpreadsheetGui
+{
+class SheetTableView;
+}
+
+class ZoomableView: public QGraphicsView
+{
+ Q_OBJECT
+ Q_PROPERTY(int zoomLevel READ zoomLevel() WRITE setZoomLevel NOTIFY zoomLevelChanged)
+public:
+ /*!
+ * \brief A descendant of QGraphicsView to show a SheetTableView object in its viewport,
+ * allowing magnification. \param ui \details The object replaces SheetTableView in layout,
+ * handling mouse and keyboard events.
+ */
+ explicit ZoomableView(Ui::Sheet* ui);
+ ~ZoomableView() override = default;
+
+ int zoomLevel() const;
+ void setZoomLevel(int new_scale);
+
+
+ static constexpr int min {60}, max {160};
+ static void checkLimits(int& zoom_level);
+
+Q_SIGNALS:
+ void zoomLevelChanged(int); /// This signal is emitted whenever zoom level is changed. It is
+ /// used to show the zoom level in the zoom button.
+
+public Q_SLOTS:
+ void zoomIn(void); /// This function is the slot for the zoomIn button and a keyboard shortcut
+ void
+ zoomOut(void); /// This function is the slot for the zoomOut button and a keyboard shortcut
+ void resetZoom(void); /// This function is the slot for a keyboard shortcut
+
+private:
+ void updateView(void);
+
+ QPointer stv;
+ QGraphicsScene m_scene;
+ QGraphicsProxyWidget* qpw;
+
+ int m_zoomLevel;
+
+protected:
+ void keyPressEvent(QKeyEvent* event) override;
+ void resizeEvent(QResizeEvent* event) override;
+ void wheelEvent(QWheelEvent* event) override;
+
+ static constexpr int zoom_step_mwheel {5}, zoom_step_kb {10};
+};
+
+#endif // ZOOMABLEVIEW_H