[Spreadsheet] Enable zoom in Spreadsheet (#16130)
* [Spreadsheet] Enable zoom in Spreadsheet Closes #6094. This commit also fixes page tab order of Spreadsheet settings in Preferences. * Spreadsheet: apply clang-format --------- Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
This commit is contained in:
@@ -86,6 +86,8 @@ SET(SpreadsheetGui_SRCS
|
||||
DlgBindSheet.cpp
|
||||
DlgSheetConf.h
|
||||
DlgSheetConf.cpp
|
||||
ZoomableView.h
|
||||
ZoomableView.cpp
|
||||
${SpreadsheetGui_UIC_HDRS}
|
||||
)
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,154 @@ Spreadsheet.my_alias_name instead of Spreadsheet.B1</string>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SpreadsheetGui::SheetTableView" name="cells"/>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="SpreadsheetGui::SheetTableView" name="cells"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollBar" name="realSB_v">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QScrollBar" name="realSB_h">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="zoomTB">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom</string>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextOnly</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="zoomMinus">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextOnly</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="zoomSlider">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>60</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>160</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="zoomPlus">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextOnly</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
@@ -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<PropertiesDialog> 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
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <QHeaderView>
|
||||
#include <QTableView>
|
||||
#include <QTimer>
|
||||
|
||||
#include <QMenu>
|
||||
#include <Mod/Spreadsheet/App/Sheet.h>
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ protected:
|
||||
Spreadsheet::Sheet* sheet;
|
||||
int tabCounter;
|
||||
|
||||
QMenu* contextMenu;
|
||||
QMenu contextMenu;
|
||||
|
||||
QAction* actionProperties;
|
||||
QAction* actionRecompute;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <QPrintPreviewDialog>
|
||||
#include <QPrinter>
|
||||
#include <QTextDocument>
|
||||
#include <cmath>
|
||||
#endif
|
||||
|
||||
#include <App/DocumentObject.h>
|
||||
@@ -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);
|
||||
|
||||
231
src/Mod/Spreadsheet/Gui/ZoomableView.cpp
Normal file
231
src/Mod/Spreadsheet/Gui/ZoomableView.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2024 xtemp09 <xtemp09@gmail.com> *
|
||||
* *
|
||||
* 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 *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QGraphicsProxyWidget>
|
||||
|
||||
#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<QScrollBar> 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<int>(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<qreal>(m_zoomLevel) / 100.0,
|
||||
new_w = static_cast<qreal>(viewport()->rect().width()) / scale_factor,
|
||||
new_h = static_cast<qreal>(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);
|
||||
}
|
||||
}
|
||||
83
src/Mod/Spreadsheet/Gui/ZoomableView.h
Normal file
83
src/Mod/Spreadsheet/Gui/ZoomableView.h
Normal file
@@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2024 xtemp09 <xtemp09@gmail.com> *
|
||||
* *
|
||||
* 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 *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef ZOOMABLEVIEW_H
|
||||
#define ZOOMABLEVIEW_H
|
||||
|
||||
#include <QGraphicsView>
|
||||
|
||||
#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<SpreadsheetGui::SheetTableView> 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
|
||||
Reference in New Issue
Block a user