Warning, file /office/calligra/libs/widgets/KoSliderCombo.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 project 0002 Copyright (c) 2007 C. Boemann <cbo@boemann.dk> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 #include "KoSliderCombo.h" 0020 #include "KoSliderCombo_p.h" 0021 0022 #include <QTimer> 0023 #include <QApplication> 0024 #include <QSize> 0025 #include <QSlider> 0026 #include <QStyle> 0027 #include <QStylePainter> 0028 #include <QStyleOptionSlider> 0029 #include <QLineEdit> 0030 #include <QValidator> 0031 #include <QHBoxLayout> 0032 #include <QFrame> 0033 #include <QMenu> 0034 #include <QMouseEvent> 0035 #include <QDoubleSpinBox> 0036 #include <QDesktopWidget> 0037 0038 0039 #include <klocalizedstring.h> 0040 #include <WidgetsDebug.h> 0041 0042 KoSliderCombo::KoSliderCombo(QWidget *parent) 0043 : QComboBox(parent) 0044 ,d(new KoSliderComboPrivate()) 0045 { 0046 d->thePublic = this; 0047 d->minimum = 0.0; 0048 d->maximum = 100.0; 0049 d->decimals = 2; 0050 d->container = new KoSliderComboContainer(this); 0051 d->container->setAttribute(Qt::WA_WindowPropagation); 0052 QStyleOptionComboBox opt; 0053 opt.initFrom(this); 0054 // d->container->setFrameStyle(style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, this)); 0055 0056 d->slider = new QSlider(Qt::Horizontal); 0057 d->slider->setMinimum(0); 0058 d->slider->setMaximum(256); 0059 d->slider->setPageStep(10); 0060 d->slider->setValue(0); 0061 // When set to true, causes flicker on Qt 4.6. Any reason to keep it? 0062 d->firstShowOfSlider = false; //true; 0063 0064 QHBoxLayout * l = new QHBoxLayout(); 0065 l->setMargin(2); 0066 l->setSpacing(2); 0067 l->addWidget(d->slider); 0068 d->container->setLayout(l); 0069 d->container->resize(200, 30); 0070 0071 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); 0072 0073 setEditable(true); 0074 setEditText(QLocale().toString(0.0, d->decimals)); 0075 0076 connect(d->slider, SIGNAL(valueChanged(int)), SLOT(sliderValueChanged(int))); 0077 connect(d->slider, SIGNAL(sliderReleased()), SLOT(sliderReleased())); 0078 connect(lineEdit(), SIGNAL(editingFinished()), SLOT(lineEditFinished())); 0079 } 0080 0081 KoSliderCombo::~KoSliderCombo() 0082 { 0083 delete d; 0084 } 0085 0086 QSize KoSliderCombo::sizeHint() const 0087 { 0088 return minimumSizeHint(); 0089 } 0090 0091 QSize KoSliderCombo::minimumSizeHint() const 0092 { 0093 QSize sh; 0094 0095 const QFontMetrics &fm = fontMetrics(); 0096 0097 sh.setWidth(5 * fm.width(QLatin1Char('8'))); 0098 sh.setHeight(qMax(fm.lineSpacing(), 14) + 2); 0099 0100 // add style and strut values 0101 QStyleOptionComboBox opt; 0102 opt.initFrom(this); 0103 opt.subControls = QStyle::SC_All; 0104 opt.editable = true; 0105 sh = style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, this); 0106 0107 return sh.expandedTo(QApplication::globalStrut()); 0108 } 0109 0110 void KoSliderCombo::KoSliderComboPrivate::showPopup() 0111 { 0112 if(firstShowOfSlider) { 0113 container->show(); //show container a bit early so the slider can be layout'ed 0114 firstShowOfSlider = false; 0115 } 0116 0117 QStyleOptionSlider opt; 0118 opt.initFrom(slider); 0119 opt.maximum=256; 0120 opt.sliderPosition = opt.sliderValue = slider->value(); 0121 int hdlPos = thePublic->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle).center().x(); 0122 0123 QStyleOptionComboBox optThis; 0124 optThis.initFrom(thePublic); 0125 optThis.subControls = QStyle::SC_All; 0126 optThis.editable = true; 0127 int arrowPos = thePublic->style()->subControlRect(QStyle::CC_ComboBox, &optThis, QStyle::SC_ComboBoxArrow).center().x(); 0128 0129 QSize popSize = container->size(); 0130 QRect popupRect(thePublic->mapToGlobal(QPoint(arrowPos - hdlPos - slider->x(), thePublic->size().height())), popSize); 0131 0132 // Make sure the popup is not drawn outside the screen area 0133 QRect screenRect = QApplication::desktop()->availableGeometry(thePublic); 0134 if (popupRect.right() > screenRect.right()) 0135 popupRect.translate(screenRect.right() - popupRect.right(), 0); 0136 if (popupRect.left() < screenRect.left()) 0137 popupRect.translate(screenRect.left() - popupRect.left(), 0); 0138 if (popupRect.bottom() > screenRect.bottom()) 0139 popupRect.translate(0, -(thePublic->height() + container->height())); 0140 0141 container->setGeometry(popupRect); 0142 container->raise(); 0143 container->show(); 0144 slider->setFocus(); 0145 } 0146 0147 void KoSliderCombo::KoSliderComboPrivate::hidePopup() 0148 { 0149 container->hide(); 0150 } 0151 0152 void KoSliderCombo::hideEvent(QHideEvent *) 0153 { 0154 d->hidePopup(); 0155 } 0156 0157 void KoSliderCombo::changeEvent(QEvent *e) 0158 { 0159 switch (e->type()) 0160 { 0161 case QEvent::EnabledChange: 0162 if (!isEnabled()) 0163 d->hidePopup(); 0164 break; 0165 case QEvent::PaletteChange: 0166 d->container->setPalette(palette()); 0167 break; 0168 default: 0169 break; 0170 } 0171 QComboBox::changeEvent(e); 0172 } 0173 0174 void KoSliderCombo::paintEvent(QPaintEvent *) 0175 { 0176 QStylePainter gc(this); 0177 0178 gc.setPen(palette().color(QPalette::Text)); 0179 0180 QStyleOptionComboBox opt; 0181 opt.initFrom(this); 0182 opt.subControls = QStyle::SC_All; 0183 opt.editable = true; 0184 gc.drawComplexControl(QStyle::CC_ComboBox, opt); 0185 gc.drawControl(QStyle::CE_ComboBoxLabel, opt); 0186 } 0187 0188 void KoSliderCombo::mousePressEvent(QMouseEvent *e) 0189 { 0190 QStyleOptionComboBox opt; 0191 opt.initFrom(this); 0192 opt.subControls = QStyle::SC_All; 0193 opt.editable = true; 0194 QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(), 0195 this); 0196 if (sc == QStyle::SC_ComboBoxArrow && !d->container->isVisible()) 0197 { 0198 d->showPopup(); 0199 } 0200 else 0201 QComboBox::mousePressEvent(e); 0202 } 0203 0204 void KoSliderCombo::keyPressEvent(QKeyEvent *e) 0205 { 0206 if (e->key() == Qt::Key_Up) setValue(value() + d->slider->singleStep() * (maximum() - minimum()) / 256 + 0.5); 0207 else if (e->key() == Qt::Key_Down) setValue(value() - d->slider->singleStep() * (maximum() - minimum()) / 256 - 0.5); 0208 else QComboBox::keyPressEvent(e); 0209 } 0210 0211 void KoSliderCombo::wheelEvent(QWheelEvent *e) 0212 { 0213 if (e->delta() > 0) setValue(value() + d->slider->singleStep() * (maximum() - minimum()) / 256 + 0.5); 0214 else setValue(value() - d->slider->singleStep() * (maximum() - minimum()) / 256 - 0.5); 0215 } 0216 0217 void KoSliderCombo::KoSliderComboPrivate::lineEditFinished() 0218 { 0219 qreal value = QLocale().toDouble(thePublic->currentText()); 0220 slider->blockSignals(true); 0221 slider->setValue(int((value - minimum) * 256 / (maximum - minimum) + 0.5)); 0222 slider->blockSignals(false); 0223 emit thePublic->valueChanged(value, true); 0224 } 0225 0226 void KoSliderCombo::KoSliderComboPrivate::sliderValueChanged(int slidervalue) 0227 { 0228 thePublic->setEditText(QLocale().toString(minimum + (maximum - minimum)*slidervalue/256, decimals)); 0229 0230 qreal value = QLocale().toDouble(thePublic->currentText()); 0231 emit thePublic->valueChanged(value, false); 0232 } 0233 0234 void KoSliderCombo::KoSliderComboPrivate::sliderReleased() 0235 { 0236 qreal value = QLocale().toDouble(thePublic->currentText()); 0237 emit thePublic->valueChanged(value, true); 0238 } 0239 0240 qreal KoSliderCombo::maximum() const 0241 { 0242 return d->maximum; 0243 } 0244 0245 qreal KoSliderCombo::minimum() const 0246 { 0247 return d->minimum; 0248 } 0249 0250 qreal KoSliderCombo::decimals() const 0251 { 0252 return d->decimals; 0253 } 0254 0255 qreal KoSliderCombo::value() const 0256 { 0257 return QLocale().toDouble(currentText()); 0258 } 0259 0260 void KoSliderCombo::setDecimals(int dec) 0261 { 0262 d->decimals = dec; 0263 if (dec == 0) lineEdit()->setValidator(new QIntValidator(this)); 0264 else lineEdit()->setValidator(new QDoubleValidator(this)); 0265 } 0266 0267 void KoSliderCombo::setMinimum(qreal min) 0268 { 0269 d->minimum = min; 0270 } 0271 0272 void KoSliderCombo::setMaximum(qreal max) 0273 { 0274 d->maximum = max; 0275 } 0276 0277 void KoSliderCombo::setValue(qreal value) 0278 { 0279 if(value < d->minimum) 0280 value = d->minimum; 0281 if(value > d->maximum) 0282 value = d->maximum; 0283 setEditText(QLocale().toString(value, d->decimals)); 0284 d->slider->blockSignals(true); 0285 d->slider->setValue(int((value - d->minimum) * 256 / (d->maximum - d->minimum) + 0.5)); 0286 d->slider->blockSignals(false); 0287 emit valueChanged(value, true); 0288 } 0289 0290 void KoSliderComboContainer::mousePressEvent(QMouseEvent *e) 0291 { 0292 QStyleOptionComboBox opt; 0293 opt.init(m_parent); 0294 opt.subControls = QStyle::SC_All; 0295 opt.activeSubControls = QStyle::SC_ComboBoxArrow; 0296 QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, 0297 m_parent->mapFromGlobal(e->globalPos()), 0298 m_parent); 0299 if (sc == QStyle::SC_ComboBoxArrow) 0300 setAttribute(Qt::WA_NoMouseReplay); 0301 QMenu::mousePressEvent(e); 0302 } 0303 0304 //have to include this because of Q_PRIVATE_SLOT 0305 #include <moc_KoSliderCombo.cpp>