| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #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(); |
| |
|
| | auto connectCursorChangedSignal = [this](QHeaderView* hv) { |
| | auto header = qobject_cast<SpreadsheetGui::SheetViewHeader*>(hv); |
| | connect( |
| | header, |
| | &SpreadsheetGui::SheetViewHeader::cursorChanged, |
| | this, |
| | [this](const QCursor& newerCursor) { qpw->setCursor(newerCursor); } |
| | ); |
| | }; |
| | connectCursorChangedSignal(stv->horizontalHeader()); |
| | connectCursorChangedSignal(stv->verticalHeader()); |
| | } |
| |
|
| | 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) |
| | { |
| | |
| | |
| |
|
| | 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::focusOutEvent(QFocusEvent* event) |
| | { |
| | Q_UNUSED(event); |
| | } |
| |
|
| | 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); |
| | } |
| | } |
| |
|