39
39
#include "signalblocker.h"
40
40
#include "statusbartoolbutton.h"
44
45
static const qreal MAGIC_K = 1.04;
45
46
static const qreal MAGIC_OFFSET = 16.;
46
47
static const qreal PRECISION = 100.;
47
inline int sliderValueForZoom(qreal zoom) {
48
return int( PRECISION * (log(zoom) / log(MAGIC_K) + MAGIC_OFFSET) );
52
inline qreal zoomForSliderValue(int sliderValue) {
53
return pow(MAGIC_K, sliderValue / PRECISION - MAGIC_OFFSET);
48
inline int sliderValueForZoom(qreal zoom)
50
return int(PRECISION * (log(zoom) / log(MAGIC_K) + MAGIC_OFFSET));
53
inline qreal zoomForSliderValue(int sliderValue)
55
return pow(MAGIC_K, sliderValue / PRECISION - MAGIC_OFFSET);
59
58
struct ZoomWidgetPrivate {
62
StatusBarToolButton* mZoomToFitButton;
63
StatusBarToolButton* mActualSizeButton;
65
ZoomSlider* mZoomSlider;
66
QAction* mZoomToFitAction;
67
QAction* mActualSizeAction;
69
bool mZoomUpdatedBySlider;
71
void emitZoomChanged() {
72
// Use QSlider::sliderPosition(), not QSlider::value() because when we are
73
// called from slotZoomSliderActionTriggered(), QSlider::value() has not
75
qreal zoom = zoomForSliderValue(mZoomSlider->slider()->sliderPosition());
76
mZoomUpdatedBySlider = true;
77
emit that->zoomChanged(zoom);
78
mZoomUpdatedBySlider = false;
61
StatusBarToolButton* mZoomToFitButton;
62
StatusBarToolButton* mActualSizeButton;
64
ZoomSlider* mZoomSlider;
65
QAction* mZoomToFitAction;
66
QAction* mActualSizeAction;
68
bool mZoomUpdatedBySlider;
70
void emitZoomChanged()
72
// Use QSlider::sliderPosition(), not QSlider::value() because when we are
73
// called from slotZoomSliderActionTriggered(), QSlider::value() has not
75
qreal zoom = zoomForSliderValue(mZoomSlider->slider()->sliderPosition());
76
mZoomUpdatedBySlider = true;
77
emit q->zoomChanged(zoom);
78
mZoomUpdatedBySlider = false;
83
82
ZoomWidget::ZoomWidget(QWidget* parent)
85
, d(new ZoomWidgetPrivate) {
87
d->mZoomUpdatedBySlider = false;
89
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
91
d->mZoomToFitButton = new StatusBarToolButton;
92
d->mActualSizeButton = new StatusBarToolButton;
94
if (QApplication::isLeftToRight()) {
95
d->mZoomToFitButton->setGroupPosition(StatusBarToolButton::GroupLeft);
96
d->mActualSizeButton->setGroupPosition(StatusBarToolButton::GroupRight);
98
d->mActualSizeButton->setGroupPosition(StatusBarToolButton::GroupLeft);
99
d->mZoomToFitButton->setGroupPosition(StatusBarToolButton::GroupRight);
102
d->mZoomLabel = new QLabel;
103
d->mZoomLabel->setFixedWidth(d->mZoomLabel->fontMetrics().width(" 1000% "));
104
d->mZoomLabel->setAlignment(Qt::AlignCenter);
106
d->mZoomSlider = new ZoomSlider;
107
d->mZoomSlider->setMinimumWidth(150);
108
d->mZoomSlider->slider()->setSingleStep(int(PRECISION));
109
d->mZoomSlider->slider()->setPageStep(3 * int(PRECISION));
110
connect(d->mZoomSlider->slider(), SIGNAL(actionTriggered(int)), SLOT(slotZoomSliderActionTriggered()) );
113
QHBoxLayout* layout = new QHBoxLayout(this);
114
layout->setMargin(0);
115
layout->setSpacing(0);
116
layout->addWidget(d->mZoomToFitButton);
117
layout->addWidget(d->mActualSizeButton);
118
layout->addWidget(d->mZoomSlider);
119
layout->addWidget(d->mZoomLabel);
123
ZoomWidget::~ZoomWidget() {
128
void ZoomWidget::setActions(QAction* zoomToFitAction, QAction* actualSizeAction, QAction* zoomInAction, QAction* zoomOutAction) {
129
d->mZoomToFitAction = zoomToFitAction;
130
d->mActualSizeAction = actualSizeAction;
132
d->mZoomToFitButton->setDefaultAction(zoomToFitAction);
133
d->mActualSizeButton->setDefaultAction(actualSizeAction);
135
d->mZoomSlider->setZoomInAction(zoomInAction);
136
d->mZoomSlider->setZoomOutAction(zoomOutAction);
139
int width = qMax(d->mZoomToFitButton->sizeHint().width(), d->mActualSizeButton->sizeHint().width());
140
d->mZoomToFitButton->setFixedWidth(width);
141
d->mActualSizeButton->setFixedWidth(width);
145
void ZoomWidget::slotZoomSliderActionTriggered() {
146
// The slider value changed because of the user (not because of range
147
// changes). In this case disable zoom and apply slider value.
148
d->emitZoomChanged();
152
void ZoomWidget::setZoom(qreal zoom) {
153
int intZoom = qRound(zoom * 100);
154
d->mZoomLabel->setText(QString("%1%").arg(intZoom));
156
// Don't change slider value if we come here because the slider change,
157
// avoids choppy sliding scroll.
158
if (!d->mZoomUpdatedBySlider) {
159
QSlider* slider = d->mZoomSlider->slider();
160
SignalBlocker blocker(slider);
161
int value = sliderValueForZoom(zoom);
163
if (value < slider->minimum()) {
164
// It is possible that we are called *before* setMinimumZoom() as
165
// been called. In this case, define the minimum ourself.
166
d->mZoomSlider->setMinimum(value);
168
d->mZoomSlider->setValue(value);
173
void ZoomWidget::setMinimumZoom(qreal minimumZoom) {
174
d->mZoomSlider->setMinimum(sliderValueForZoom(minimumZoom));
178
void ZoomWidget::setMaximumZoom(qreal zoom) {
179
d->mZoomSlider->setMaximum(sliderValueForZoom(zoom));
84
, d(new ZoomWidgetPrivate)
87
d->mZoomUpdatedBySlider = false;
89
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
91
d->mZoomToFitButton = new StatusBarToolButton;
92
d->mActualSizeButton = new StatusBarToolButton;
94
if (QApplication::isLeftToRight()) {
95
d->mZoomToFitButton->setGroupPosition(StatusBarToolButton::GroupLeft);
96
d->mActualSizeButton->setGroupPosition(StatusBarToolButton::GroupRight);
98
d->mActualSizeButton->setGroupPosition(StatusBarToolButton::GroupLeft);
99
d->mZoomToFitButton->setGroupPosition(StatusBarToolButton::GroupRight);
102
d->mZoomLabel = new QLabel;
103
d->mZoomLabel->setFixedWidth(d->mZoomLabel->fontMetrics().width(" 1000% "));
104
d->mZoomLabel->setAlignment(Qt::AlignCenter);
106
d->mZoomSlider = new ZoomSlider;
107
d->mZoomSlider->setMinimumWidth(150);
108
d->mZoomSlider->slider()->setSingleStep(int(PRECISION));
109
d->mZoomSlider->slider()->setPageStep(3 * int(PRECISION));
110
connect(d->mZoomSlider->slider(), SIGNAL(actionTriggered(int)), SLOT(slotZoomSliderActionTriggered()));
113
QHBoxLayout* layout = new QHBoxLayout(this);
114
layout->setMargin(0);
115
layout->setSpacing(0);
116
layout->addWidget(d->mZoomToFitButton);
117
layout->addWidget(d->mActualSizeButton);
118
layout->addWidget(d->mZoomSlider);
119
layout->addWidget(d->mZoomLabel);
122
ZoomWidget::~ZoomWidget()
127
void ZoomWidget::setActions(QAction* zoomToFitAction, QAction* actualSizeAction, QAction* zoomInAction, QAction* zoomOutAction)
129
d->mZoomToFitAction = zoomToFitAction;
130
d->mActualSizeAction = actualSizeAction;
132
d->mZoomToFitButton->setDefaultAction(zoomToFitAction);
133
d->mActualSizeButton->setDefaultAction(actualSizeAction);
135
d->mZoomSlider->setZoomInAction(zoomInAction);
136
d->mZoomSlider->setZoomOutAction(zoomOutAction);
139
int width = qMax(d->mZoomToFitButton->sizeHint().width(), d->mActualSizeButton->sizeHint().width());
140
d->mZoomToFitButton->setFixedWidth(width);
141
d->mActualSizeButton->setFixedWidth(width);
144
void ZoomWidget::slotZoomSliderActionTriggered()
146
// The slider value changed because of the user (not because of range
147
// changes). In this case disable zoom and apply slider value.
148
d->emitZoomChanged();
151
void ZoomWidget::setZoom(qreal zoom)
153
int intZoom = qRound(zoom * 100);
154
d->mZoomLabel->setText(QString("%1%").arg(intZoom));
156
// Don't change slider value if we come here because the slider change,
157
// avoids choppy sliding scroll.
158
if (!d->mZoomUpdatedBySlider) {
159
QSlider* slider = d->mZoomSlider->slider();
160
SignalBlocker blocker(slider);
161
int value = sliderValueForZoom(zoom);
163
if (value < slider->minimum()) {
164
// It is possible that we are called *before* setMinimumZoom() as
165
// been called. In this case, define the minimum ourself.
166
d->mZoomSlider->setMinimum(value);
168
d->mZoomSlider->setValue(value);
172
void ZoomWidget::setMinimumZoom(qreal minimumZoom)
174
d->mZoomSlider->setMinimum(sliderValueForZoom(minimumZoom));
177
void ZoomWidget::setMaximumZoom(qreal zoom)
179
d->mZoomSlider->setMaximum(sliderValueForZoom(zoom));