File indexing completed on 2024-09-22 05:16:07
0001 /* 0002 This file is part of the Kasten Framework, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2008-2009 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "zoomslider.hpp" 0010 0011 // Kasten gui 0012 #include <Kasten/Zoomable> 0013 // Kasten core 0014 #include <Kasten/AbstractModel> 0015 // KF 0016 #include <KLocalizedString> 0017 // Qt 0018 #include <QSlider> 0019 #include <QToolButton> 0020 #include <QHBoxLayout> 0021 #include <QApplication> 0022 #include <QHelpEvent> 0023 0024 namespace Kasten { 0025 0026 static constexpr int ZoomSliderWidth = 150; 0027 0028 // TODO: look at Dolphin/Krita/KOffice zoom tool 0029 0030 // TODO: different zoom strategies: fixed step size, relative step size 0031 // where to put this, behind interface? or better into a zoomtool? 0032 0033 ZoomSlider::ZoomSlider(QWidget* parent) 0034 : QWidget(parent) 0035 { 0036 mZoomOutButton = new QToolButton(this); 0037 mZoomOutButton->setIcon(QIcon::fromTheme(QStringLiteral("zoom-out"))); 0038 mZoomOutButton->setAutoRaise(true); 0039 0040 mSlider = new QSlider(Qt::Horizontal, this); 0041 0042 mZoomInButton = new QToolButton(this); 0043 mZoomInButton->setIcon(QIcon::fromTheme(QStringLiteral("zoom-in"))); 0044 mZoomInButton->setAutoRaise(true); 0045 0046 auto* layout = new QHBoxLayout(this); 0047 layout->setSpacing(0); 0048 layout->setContentsMargins(0, 0, 0, 0); 0049 layout->addWidget(mZoomOutButton); 0050 layout->addWidget(mSlider); 0051 layout->addWidget(mZoomInButton); 0052 0053 connect(mZoomOutButton, &QAbstractButton::clicked, 0054 this, &ZoomSlider::zoomOut); 0055 connect(mZoomInButton, &QAbstractButton::clicked, 0056 this, &ZoomSlider::zoomIn); 0057 connect(mSlider, &QSlider::valueChanged, 0058 this, &ZoomSlider::onSliderValueChanged); 0059 connect(mSlider, &QSlider::sliderMoved, 0060 this, &ZoomSlider::onSliderMoved); 0061 0062 setFixedWidth(ZoomSliderWidth); 0063 0064 setTargetModel(nullptr); 0065 } 0066 0067 ZoomSlider::~ZoomSlider() = default; 0068 0069 void ZoomSlider::setTargetModel(AbstractModel* model) 0070 { 0071 if (mModel) { 0072 mModel->disconnect(this); 0073 } 0074 0075 mModel = model ? model->findBaseModelWithInterface<If::Zoomable*>() : nullptr; 0076 mZoomControl = mModel ? qobject_cast<If::Zoomable*>(mModel) : nullptr; 0077 0078 const bool hasView = (mZoomControl != nullptr); 0079 if (hasView) { 0080 mSlider->setSingleStep(1); // mZoomControl->zoomLevelSingleStep()? 0081 mSlider->setPageStep(5); // mZoomControl->zoomLevelPageStep()? 0082 0083 const int min = 0; // mZoomControl->minimumZoomLevel(); 0084 const int max = 99; // mZoomControl->maximumZoomLevel(); 0085 mSlider->setRange(min, max); 0086 0087 onZoomLevelChange(mZoomControl->zoomLevel()); 0088 const int sliderValue = mSlider->value(); 0089 mZoomOutButton->setEnabled(sliderValue > mSlider->minimum()); 0090 mZoomInButton->setEnabled(sliderValue < mSlider->maximum()); 0091 connect(mModel, SIGNAL(zoomLevelChanged(double)), SLOT(onZoomLevelChange(double))); 0092 } else { 0093 mZoomOutButton->setEnabled(false); 0094 mZoomInButton->setEnabled(false); 0095 // put slider in the middle 0096 mSlider->setRange(0, 99); 0097 mSlider->setValue(50); 0098 } 0099 0100 mSlider->setEnabled(hasView); 0101 } 0102 0103 void ZoomSlider::updateToolTip(int sliderValue) 0104 { 0105 const float zoomLevel = 50.0 / (100 - sliderValue); 0106 const int zoomPercent = static_cast<int>(zoomLevel * 100 + 0.5); 0107 mSlider->setToolTip(i18nc("@info:tooltip", "Zoom: %1%", zoomPercent)); 0108 // TODO: get the text by a signal toolTipNeeded( int zoomLevel, QString* toolTipText ); ? 0109 } 0110 0111 void ZoomSlider::zoomOut() 0112 { 0113 const int newValue = mSlider->value() - mSlider->singleStep(); 0114 mSlider->setValue(newValue); 0115 } 0116 0117 void ZoomSlider::zoomIn() 0118 { 0119 const int newValue = mSlider->value() + mSlider->singleStep(); 0120 mSlider->setValue(newValue); 0121 } 0122 0123 void ZoomSlider::onSliderValueChanged(int sliderValue) 0124 { 0125 updateToolTip(sliderValue); 0126 mZoomOutButton->setEnabled(sliderValue > mSlider->minimum()); 0127 mZoomInButton->setEnabled(sliderValue < mSlider->maximum()); 0128 0129 if (mZoomControl) { 0130 mZoomControl->setZoomLevel(50.0 / (100 - sliderValue)); 0131 } 0132 } 0133 0134 // TODO: which signal comes first, valueChanged or sliderMoved? 0135 // ensure correct calculation of zoomLevel, best by model 0136 // but can be timeconsuming? 0137 // use timer to delay resize, so that sliding is not delayed by resizing 0138 void ZoomSlider::onSliderMoved(int sliderValue) 0139 { 0140 Q_UNUSED(sliderValue) 0141 0142 QPoint toolTipPoint = mSlider->rect().topLeft(); 0143 toolTipPoint.ry() += mSlider->height() / 2; 0144 toolTipPoint = mSlider->mapToGlobal(toolTipPoint); 0145 0146 QHelpEvent toolTipEvent(QEvent::ToolTip, QPoint(0, 0), toolTipPoint); 0147 QApplication::sendEvent(mSlider, &toolTipEvent); 0148 } 0149 0150 void ZoomSlider::onZoomLevelChange(double level) 0151 { 0152 mZoomLevel = level; 0153 const int newSliderValue = 100 - static_cast<int>(50.0 / mZoomLevel + 0.5); 0154 if (newSliderValue != mSlider->value()) { 0155 disconnect(mSlider, &QSlider::valueChanged, 0156 this, &ZoomSlider::onSliderValueChanged); 0157 mSlider->setSliderPosition(newSliderValue); 0158 updateToolTip(mSlider->value()); 0159 connect(mSlider, &QSlider::valueChanged, 0160 this, &ZoomSlider::onSliderValueChanged); 0161 } 0162 } 0163 0164 } 0165 0166 #include "moc_zoomslider.cpp"