Warning, file /office/calligra/libs/widgets/KoZoomAction.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE libraries 0002 Copyright (C) 2004 Ariya Hidayat <ariya@kde.org> 0003 Copyright (C) 2006 Peter Simonsson <peter.simonsson@gmail.com> 0004 Copyright (C) 2006-2007 C. Boemann <cbo@boemann.dk> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License version 2 as published by the Free Software Foundation. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 #include "KoZoomAction.h" 0021 #include "KoZoomMode.h" 0022 #include "KoZoomWidget.h" 0023 0024 #include <KoIcon.h> 0025 0026 #include <QString> 0027 #include <QLocale> 0028 #include <QStringList> 0029 #include <QRegExp> 0030 #include <QList> 0031 #include <QSlider> 0032 #include <QLineEdit> 0033 #include <QToolButton> 0034 #include <QLabel> 0035 #include <QGridLayout> 0036 #include <QMenu> 0037 #include <QStatusBar> 0038 #include <QButtonGroup> 0039 #include <QComboBox> 0040 0041 0042 #include <klocalizedstring.h> 0043 #include <WidgetsDebug.h> 0044 0045 #include <math.h> 0046 #include <algorithm> 0047 0048 class Q_DECL_HIDDEN KoZoomAction::Private 0049 { 0050 public: 0051 0052 Private(KoZoomAction *_parent) 0053 : parent(_parent) 0054 , minimumZoomValue(-1) 0055 , maximumZoomValue(-1) 0056 {} 0057 0058 KoZoomAction *parent; 0059 0060 KoZoomMode::Modes zoomModes; 0061 QList<qreal> sliderLookup; 0062 0063 qreal effectiveZoom; 0064 0065 KoZoomAction::SpecialButtons specialButtons; 0066 0067 QList<qreal> generateSliderZoomLevels() const; 0068 QList<qreal> filterMenuZoomLevels(const QList<qreal> &zoomLevels) const; 0069 0070 qreal minimumZoomValue; 0071 qreal maximumZoomValue; 0072 }; 0073 0074 QList<qreal> KoZoomAction::Private::generateSliderZoomLevels() const 0075 { 0076 QList<qreal> zoomLevels; 0077 0078 qreal defaultZoomStep = sqrt(2.0); 0079 0080 zoomLevels << 0.25 / 2.0; 0081 zoomLevels << 0.25 / 1.5; 0082 zoomLevels << 0.25; 0083 zoomLevels << 1.0 / 3.0; 0084 zoomLevels << 0.5; 0085 zoomLevels << 2.0 / 3.0; 0086 zoomLevels << 1.0; 0087 0088 for (qreal zoom = zoomLevels.first() / defaultZoomStep; 0089 zoom > parent->minimumZoom(); 0090 zoom /= defaultZoomStep) { 0091 0092 zoomLevels.prepend(zoom); 0093 } 0094 0095 for (qreal zoom = zoomLevels.last() * defaultZoomStep; 0096 zoom < parent->maximumZoom(); 0097 zoom *= defaultZoomStep) { 0098 0099 zoomLevels.append(zoom); 0100 } 0101 0102 return zoomLevels; 0103 } 0104 0105 QList<qreal> KoZoomAction::Private::filterMenuZoomLevels(const QList<qreal> &zoomLevels) const 0106 { 0107 QList<qreal> filteredZoomLevels; 0108 0109 foreach(qreal zoom, zoomLevels) { 0110 if (zoom >= 0.2 && zoom <= 10) { 0111 filteredZoomLevels << zoom; 0112 } 0113 } 0114 0115 return filteredZoomLevels; 0116 } 0117 0118 KoZoomAction::KoZoomAction(KoZoomMode::Modes zoomModes, const QString& text, QObject *parent) 0119 : KSelectAction(text, parent) 0120 , d(new Private(this)) 0121 { 0122 d->zoomModes = zoomModes; 0123 d->specialButtons = nullptr; 0124 setIcon(koIcon("zoom-original")); 0125 setEditable( true ); 0126 setMaxComboViewCount( 15 ); 0127 0128 d->sliderLookup = d->generateSliderZoomLevels(); 0129 0130 d->effectiveZoom = 1.0; 0131 regenerateItems(d->effectiveZoom, true); 0132 0133 connect( this, SIGNAL(triggered(QString)), SLOT(triggered(QString)) ); 0134 } 0135 0136 KoZoomAction::~KoZoomAction() 0137 { 0138 delete d; 0139 } 0140 0141 qreal KoZoomAction::effectiveZoom() const 0142 { 0143 return d->effectiveZoom; 0144 } 0145 0146 void KoZoomAction::setZoom(qreal zoom) 0147 { 0148 setEffectiveZoom(zoom); 0149 regenerateItems(d->effectiveZoom, true); 0150 } 0151 0152 void KoZoomAction::triggered(const QString& text) 0153 { 0154 QString zoomString = text; 0155 zoomString = zoomString.remove( '&' ); 0156 0157 KoZoomMode::Mode mode = KoZoomMode::toMode(zoomString); 0158 int zoom = 0; 0159 0160 if( mode == KoZoomMode::ZOOM_CONSTANT ) { 0161 bool ok; 0162 QRegExp regexp( ".*(\\d+).*" ); // "Captured" non-empty sequence of digits 0163 int pos = regexp.indexIn( zoomString ); 0164 0165 if( pos > -1 ) { 0166 zoom = regexp.cap( 1 ).toInt( &ok ); 0167 0168 if( !ok ) { 0169 zoom = 0; 0170 } 0171 } 0172 } 0173 0174 emit zoomChanged( mode, zoom/100.0 ); 0175 } 0176 0177 void KoZoomAction::setZoomModes( KoZoomMode::Modes zoomModes ) 0178 { 0179 d->zoomModes = zoomModes; 0180 regenerateItems( d->effectiveZoom ); 0181 } 0182 0183 void KoZoomAction::regenerateItems(const qreal zoom, bool asCurrent) 0184 { 0185 QList<qreal> zoomLevels = d->filterMenuZoomLevels(d->sliderLookup); 0186 0187 if( !zoomLevels.contains( zoom ) ) 0188 zoomLevels << zoom; 0189 0190 std::sort(zoomLevels.begin(), zoomLevels.end()); 0191 0192 // update items with new sorted zoom values 0193 QStringList values; 0194 if(d->zoomModes & KoZoomMode::ZOOM_WIDTH) { 0195 values << KoZoomMode::toString(KoZoomMode::ZOOM_WIDTH); 0196 } 0197 if(d->zoomModes & KoZoomMode::ZOOM_TEXT) { 0198 values << KoZoomMode::toString(KoZoomMode::ZOOM_TEXT); 0199 } 0200 if(d->zoomModes & KoZoomMode::ZOOM_PAGE) { 0201 values << KoZoomMode::toString(KoZoomMode::ZOOM_PAGE); 0202 } 0203 0204 foreach(qreal value, zoomLevels) { 0205 const qreal valueInPercent = value * 100; 0206 const int precision = (value > 10.0) ? 0 : 1; 0207 0208 values << i18n("%1%", QLocale().toString(valueInPercent, 'f', precision)); 0209 } 0210 0211 setItems( values ); 0212 0213 emit zoomLevelsChanged(values); 0214 0215 if(asCurrent) 0216 { 0217 const qreal zoomInPercent = zoom * 100; 0218 // TODO: why zoomInPercent and not zoom here? different from above 0219 const int precision = (zoomInPercent > 10.0) ? 0 : 1; 0220 0221 const QString valueString = i18n("%1%", QLocale().toString(zoomInPercent, 'f', precision)); 0222 0223 setCurrentAction(valueString); 0224 0225 emit currentZoomLevelChanged(valueString); 0226 } 0227 } 0228 0229 void KoZoomAction::sliderValueChanged(int value) 0230 { 0231 setZoom(d->sliderLookup[value]); 0232 0233 emit zoomChanged(KoZoomMode::ZOOM_CONSTANT, d->sliderLookup[value]); 0234 } 0235 0236 qreal KoZoomAction::nextZoomLevel() const 0237 { 0238 const qreal eps = 1e-5; 0239 int i = 0; 0240 while (d->effectiveZoom > d->sliderLookup[i] - eps && 0241 i < d->sliderLookup.size() - 1) i++; 0242 0243 return qMax(d->effectiveZoom, d->sliderLookup[i]); 0244 } 0245 0246 qreal KoZoomAction::prevZoomLevel() const 0247 { 0248 const qreal eps = 1e-5; 0249 int i = d->sliderLookup.size() - 1; 0250 while (d->effectiveZoom < d->sliderLookup[i] + eps && i > 0) i--; 0251 0252 return qMin(d->effectiveZoom, d->sliderLookup[i]); 0253 } 0254 0255 void KoZoomAction::zoomIn() 0256 { 0257 qreal zoom = nextZoomLevel(); 0258 0259 if (zoom > d->effectiveZoom) { 0260 setZoom(zoom); 0261 emit zoomChanged(KoZoomMode::ZOOM_CONSTANT, d->effectiveZoom); 0262 } 0263 } 0264 0265 void KoZoomAction::zoomOut() 0266 { 0267 qreal zoom = prevZoomLevel(); 0268 0269 if (zoom < d->effectiveZoom) { 0270 setZoom(zoom); 0271 emit zoomChanged(KoZoomMode::ZOOM_CONSTANT, d->effectiveZoom); 0272 } 0273 } 0274 0275 QWidget * KoZoomAction::createWidget(QWidget *parent) 0276 { 0277 KoZoomWidget* zoomWidget = new KoZoomWidget(parent, d->specialButtons, d->sliderLookup.size() - 1); 0278 connect(this, SIGNAL(zoomLevelsChanged(QStringList)), zoomWidget, SLOT(setZoomLevels(QStringList))); 0279 connect(this, SIGNAL(currentZoomLevelChanged(QString)), zoomWidget, SLOT(setCurrentZoomLevel(QString))); 0280 connect(this, SIGNAL(sliderChanged(int)), zoomWidget, SLOT(setSliderValue(int))); 0281 connect(this, SIGNAL(aspectModeChanged(bool)), zoomWidget, SLOT(setAspectMode(bool))); 0282 connect(zoomWidget, SIGNAL(sliderValueChanged(int)), this, SLOT(sliderValueChanged(int))); 0283 connect(zoomWidget, SIGNAL(zoomLevelChanged(QString)), this, SLOT(triggered(QString))); 0284 connect(zoomWidget, SIGNAL(aspectModeChanged(bool)), this, SIGNAL(aspectModeChanged(bool))); 0285 connect(zoomWidget, SIGNAL(zoomedToSelection()), this, SIGNAL(zoomedToSelection())); 0286 connect(zoomWidget, SIGNAL(zoomedToAll()), this, SIGNAL(zoomedToAll())); 0287 regenerateItems( d->effectiveZoom, true ); 0288 syncSliderWithZoom(); 0289 return zoomWidget; 0290 } 0291 0292 void KoZoomAction::setEffectiveZoom(qreal zoom) 0293 { 0294 if(d->effectiveZoom == zoom) 0295 return; 0296 0297 zoom = clampZoom(zoom); 0298 d->effectiveZoom = zoom; 0299 syncSliderWithZoom(); 0300 } 0301 0302 void KoZoomAction::setSelectedZoomMode(KoZoomMode::Mode mode) 0303 { 0304 QString modeString(KoZoomMode::toString(mode)); 0305 setCurrentAction(modeString); 0306 0307 emit currentZoomLevelChanged(modeString); 0308 } 0309 0310 void KoZoomAction::setSpecialButtons( SpecialButtons buttons ) 0311 { 0312 d->specialButtons = buttons; 0313 } 0314 0315 void KoZoomAction::setAspectMode(bool status) 0316 { 0317 emit aspectModeChanged(status); 0318 } 0319 0320 void KoZoomAction::syncSliderWithZoom() 0321 { 0322 const qreal eps = 1e-5; 0323 int i = d->sliderLookup.size() - 1; 0324 while (d->effectiveZoom < d->sliderLookup[i] + eps && i > 0) i--; 0325 0326 emit sliderChanged(i); 0327 } 0328 0329 qreal KoZoomAction::minimumZoom() 0330 { 0331 if (d->minimumZoomValue < 0) { 0332 return KoZoomMode::minimumZoom(); 0333 } 0334 return d->minimumZoomValue; 0335 } 0336 0337 qreal KoZoomAction::maximumZoom() 0338 { 0339 if (d->maximumZoomValue < 0) { 0340 return KoZoomMode::maximumZoom(); 0341 } 0342 return d->maximumZoomValue; 0343 } 0344 0345 qreal KoZoomAction::clampZoom(qreal zoom) 0346 { 0347 return qMin(maximumZoom(), qMax(minimumZoom(), zoom)); 0348 } 0349 0350 void KoZoomAction::setMinimumZoom(qreal zoom) 0351 { 0352 Q_ASSERT(zoom > 0.0f); 0353 KoZoomMode::setMinimumZoom(zoom); 0354 d->minimumZoomValue = zoom; 0355 d->generateSliderZoomLevels(); 0356 d->sliderLookup = d->generateSliderZoomLevels(); 0357 regenerateItems(d->effectiveZoom, true); 0358 syncSliderWithZoom(); 0359 } 0360 0361 void KoZoomAction::setMaximumZoom(qreal zoom) 0362 { 0363 Q_ASSERT(zoom > 0.0f); 0364 KoZoomMode::setMaximumZoom(zoom); 0365 d->maximumZoomValue = zoom; 0366 d->sliderLookup = d->generateSliderZoomLevels(); 0367 regenerateItems(d->effectiveZoom, true); 0368 syncSliderWithZoom(); 0369 }