From 02188f8892627bffa8c7b3a971a9be8624e370bc Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Thu, 7 Jan 2010 00:48:48 +0000 Subject: [PATCH] Re-use KOffice widget in the titler to gain space (spin box with popup slider) svn path=/trunk/kdenlive/; revision=4212 --- src/CMakeLists.txt | 1 + src/KoSliderCombo.cpp | 336 ++++++++++++++++++++++++++++++++++ src/KoSliderCombo.h | 141 ++++++++++++++ src/titlewidget.cpp | 26 ++- src/widgets/titlewidget_ui.ui | 101 +++++----- 5 files changed, 548 insertions(+), 57 deletions(-) create mode 100644 src/KoSliderCombo.cpp create mode 100644 src/KoSliderCombo.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 03a591a8..d116edd6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -184,6 +184,7 @@ set(kdenlive_SRCS folderprojectitem.cpp addclipcutcommand.cpp editclipcutcommand.cpp + KoSliderCombo.cpp ) add_definitions( ${KDE4_DEFINITIONS} ) diff --git a/src/KoSliderCombo.cpp b/src/KoSliderCombo.cpp new file mode 100644 index 00000000..5b8744f6 --- /dev/null +++ b/src/KoSliderCombo.cpp @@ -0,0 +1,336 @@ +/* This file is part of the KDE project + Copyright (c) 2007 Casper Boemann + Copyright (c) 2010 Jean-Baptiste Mardelle + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ +#include "KoSliderCombo.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class KoSliderComboContainer : public QMenu +{ +public: + KoSliderComboContainer(KoSliderCombo *parent) : QMenu(parent ), m_parent(parent) {} + +protected: + virtual void mousePressEvent(QMouseEvent *e); +private: + KoSliderCombo *m_parent; +}; + +void KoSliderComboContainer::mousePressEvent(QMouseEvent *e) +{ + QStyleOptionComboBox opt; + opt.init(m_parent); + opt.subControls = QStyle::SC_All; + opt.activeSubControls = QStyle::SC_ComboBoxArrow; + QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, + m_parent->mapFromGlobal(e->globalPos()), + m_parent); + if (sc == QStyle::SC_ComboBoxArrow) + setAttribute(Qt::WA_NoMouseReplay); + QMenu::mousePressEvent(e); +} + +class KoSliderCombo::KoSliderComboPrivate { +public: + KoSliderCombo *thePublic; + QValidator *m_validator; + QTimer m_timer; + KoSliderComboContainer *container; + QSlider *slider; + QStyle::StateFlag arrowState; + qreal minimum; + qreal maximum; + int decimals; + bool firstShowOfSlider; + + void showPopup(); + void hidePopup(); + + void sliderValueChanged(int value); + void sliderReleased(); + void lineEditFinished(); +}; + +KoSliderCombo::KoSliderCombo(QWidget *parent) + : QComboBox(parent) + ,d(new KoSliderComboPrivate()) +{ + d->thePublic = this; + d->minimum = 0.0; + d->maximum = 100.0; + d->decimals = 2; + d->container = new KoSliderComboContainer(this); + d->container->setAttribute(Qt::WA_WindowPropagation); + QStyleOptionComboBox opt; + opt.init(this); +// d->container->setFrameStyle(style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, this)); + + d->slider = new QSlider(Qt::Horizontal); + d->slider->setMinimum(0); + d->slider->setMaximum(256); + d->slider->setPageStep(10); + d->slider->setValue(0); + // When set to true, causes flicker on Qt 4.6. Any reason to keep it? + d->firstShowOfSlider = false; //true; + + QHBoxLayout * l = new QHBoxLayout(); + l->setMargin(2); + l->setSpacing(2); + l->addWidget(d->slider); + d->container->setLayout(l); + d->container->resize(200, 30); + + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + setEditable(true); + setEditText(KGlobal::locale()->formatNumber(0, d->decimals)); + + connect(d->slider, SIGNAL(valueChanged(int)), SLOT(sliderValueChanged(int))); + connect(d->slider, SIGNAL(sliderReleased()), SLOT(sliderReleased())); + connect(lineEdit(), SIGNAL(editingFinished()), SLOT(lineEditFinished())); +} + +KoSliderCombo::~KoSliderCombo() +{ + delete d; +} + +QSize KoSliderCombo::sizeHint() const +{ + return minimumSizeHint(); +} + +QSize KoSliderCombo::minimumSizeHint() const +{ + QSize sh; + + const QFontMetrics &fm = fontMetrics(); + + sh.setWidth(5 * fm.width(QLatin1Char('8'))); + sh.setHeight(qMax(fm.lineSpacing(), 14) + 2); + + // add style and strut values + QStyleOptionComboBox opt; + opt.init(this); + opt.subControls = QStyle::SC_All; + opt.editable = true; + sh = style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, this); + + return sh.expandedTo(QApplication::globalStrut()); +} + +void KoSliderCombo::KoSliderComboPrivate::showPopup() +{ + if(firstShowOfSlider) { + container->show(); //show container a bit early so the slider can be layout'ed + firstShowOfSlider = false; + } + + QStyleOptionSlider opt; + opt.init(slider); + opt.maximum=256; + opt.sliderPosition = opt.sliderValue = slider->value(); + int hdlPos = thePublic->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle).center().x(); + + QStyleOptionComboBox optThis; + optThis.init(thePublic); + optThis.subControls = QStyle::SC_All; + optThis.editable = true; + int arrowPos = thePublic->style()->subControlRect(QStyle::CC_ComboBox, &optThis, QStyle::SC_ComboBoxArrow).center().x(); + + QSize popSize = container->size(); + QRect popupRect(thePublic->mapToGlobal(QPoint(arrowPos - hdlPos - slider->x(), thePublic->size().height())), popSize); + + // Make sure the popup is not drawn outside the screen area + QRect screenRect = QApplication::desktop()->availableGeometry(container); + if (popupRect.right() > screenRect.right()) + popupRect.translate(screenRect.right() - popupRect.right(), 0); + if (popupRect.left() < screenRect.left()) + popupRect.translate(screenRect.left() - popupRect.left(), 0); + if (popupRect.bottom() > screenRect.bottom()) + popupRect.translate(0, -(thePublic->height() + container->height())); + + container->setGeometry(popupRect); + container->raise(); + container->show(); + slider->setFocus(); +} + +void KoSliderCombo::KoSliderComboPrivate::hidePopup() +{ + container->hide(); +} + +void KoSliderCombo::hideEvent(QHideEvent *) +{ + d->hidePopup(); +} + +void KoSliderCombo::changeEvent(QEvent *e) +{ + switch (e->type()) + { + case QEvent::EnabledChange: + if (!isEnabled()) + d->hidePopup(); + break; + case QEvent::PaletteChange: + d->container->setPalette(palette()); + break; + default: + break; + } + QComboBox::changeEvent(e); +} + +void KoSliderCombo::paintEvent(QPaintEvent *) +{ + QStylePainter gc(this); + + gc.setPen(palette().color(QPalette::Text)); + + QStyleOptionComboBox opt; + opt.init(this); + opt.subControls = QStyle::SC_All; + opt.editable = true; + gc.drawComplexControl(QStyle::CC_ComboBox, opt); + gc.drawControl(QStyle::CE_ComboBoxLabel, opt); +} + +void KoSliderCombo::mousePressEvent(QMouseEvent *e) +{ + QStyleOptionComboBox opt; + opt.init(this); + opt.subControls = QStyle::SC_All; + opt.editable = true; + QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(), + this); + if (sc == QStyle::SC_ComboBoxArrow && !d->container->isVisible()) + { + d->showPopup(); + } + else + QComboBox::mousePressEvent(e); +} + +void KoSliderCombo::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Up) setValue(value() + d->slider->singleStep() * maximum() / 256 + 0.5); + else if (e->key() == Qt::Key_Down) setValue(value() - d->slider->singleStep() * maximum() / 256 - 0.5); + else QComboBox::keyPressEvent(e); +} + +void KoSliderCombo::wheelEvent(QWheelEvent *e) +{ + if (e->delta() > 0) setValue(value() + d->slider->singleStep() * maximum() / 256 + 0.5); + else setValue(value() - d->slider->singleStep() * maximum() / 256 - 0.5); +} + +void KoSliderCombo::KoSliderComboPrivate::lineEditFinished() +{ + qreal value = thePublic->currentText().toDouble(); + slider->blockSignals(true); + slider->setValue(int((value - minimum) * 256 / maximum + 0.5)); + slider->blockSignals(false); + emit thePublic->valueChanged(value, true); +} + +void KoSliderCombo::KoSliderComboPrivate::sliderValueChanged(int slidervalue) +{ + thePublic->setEditText(KGlobal::locale()->formatNumber(minimum + maximum*slidervalue/256, decimals)); + + qreal value = thePublic->currentText().toDouble(); + emit thePublic->valueChanged(value, false); +} + +void KoSliderCombo::KoSliderComboPrivate::sliderReleased() +{ + qreal value = thePublic->currentText().toDouble(); + emit thePublic->valueChanged(value, true); +} + +qreal KoSliderCombo::maximum() const +{ + return d->maximum; +} + +qreal KoSliderCombo::minimum() const +{ + return d->minimum; +} + +qreal KoSliderCombo::decimals() const +{ + return d->decimals; +} + +qreal KoSliderCombo::value() const +{ + return currentText().toDouble(); +} + +void KoSliderCombo::setDecimals(int dec) +{ + d->decimals = dec; + if (dec == 0) lineEdit()->setValidator(new QIntValidator(this)); + else lineEdit()->setValidator(new QDoubleValidator(this)); +} + +void KoSliderCombo::setMinimum(qreal min) +{ + d->minimum = min; +} + +void KoSliderCombo::setMaximum(qreal max) +{ + d->maximum = max; +} + +void KoSliderCombo::setValue(qreal value) +{ + if(value < d->minimum) + value = d->minimum; + if(value > d->maximum) + value = d->maximum; + setEditText(KGlobal::locale()->formatNumber(value, d->decimals)); + d->slider->blockSignals(true); + d->slider->setValue(int((value - d->minimum) * 256 / d->maximum + 0.5)); + d->slider->blockSignals(false); + emit valueChanged(value, true); +} + +#include diff --git a/src/KoSliderCombo.h b/src/KoSliderCombo.h new file mode 100644 index 00000000..557cb372 --- /dev/null +++ b/src/KoSliderCombo.h @@ -0,0 +1,141 @@ +/* This file is part of the KDE project + Copyright (c) 2007 Casper Boemann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef KOSLIDERCOMBO_H_ +#define KOSLIDERCOMBO_H_ + +#include + +#include "kowidgets_export.h" + +/** + * @short A widget for qreal values with a popup slider + * + * KoSliderCombo combines a numerical input and a dropdown slider in a way that takes up as + * little screen space as possible. + * + * It allows the user to either enter a floating point value or quickly set the value using a slider + * + * One signal is emitted when the value changes. The signal is even emitted when the slider + * is moving. The second argument of the signal however tells you if the value is final or not. A + * final value is produced by entering a value numerically or by releasing the slider. + * + * The input of the numerical line edit is constrained to numbers and decimal signs. + */ +class KOWIDGETS_EXPORT KoSliderCombo : public QComboBox +{ + + Q_OBJECT + +public: + + /** + * Constructor for the widget, where value is set to 0 + * + * @param parent parent QWidget + */ + KoSliderCombo(QWidget *parent=0); + + /** + * Destructor + */ + virtual ~KoSliderCombo(); + + /** + * The precision of values given as the number of digits after the period. + * default is 2 + */ + qreal decimals() const; + + /** + * The minimum value that can be entered. + * default is 0 + */ + qreal minimum() const; + + /** + * The maximum value that can be entered. + * default is 100 + */ + qreal maximum() const; + + /** + * Sets the precision of the entered values. + * @param number the number of digits after the period + */ + + void setDecimals(int number); + + /** + * Sets the minimum value that can be entered. + * @param min the minimum value + */ + void setMinimum(qreal min); + + /** + * Sets the maximum value that can be entered. + * @param max the maximum value + */ + void setMaximum(qreal max); + + /** + * The value shown. + */ + qreal value() const; + + virtual QSize minimumSizeHint() const; ///< reimplemented from QComboBox + virtual QSize sizeHint() const; ///< reimplemented from QComboBox + +public slots: + + /** + * Sets the value. + * The value actually set is forced to be within the legal range: minimum <= value <= maximum + * @param value the new value + */ + void setValue(qreal value); + +signals: + + /** + * Emitted every time the value changes (by calling setValue() or + * by user interaction). + * @param value the new value + * @param final if the value is final ie not produced during sliding (on slider release it's final) + */ + void valueChanged(qreal value, bool final); + +protected: + virtual void paintEvent(QPaintEvent *); ///< reimplemented from QComboBox + virtual void hideEvent(QHideEvent *); ///< reimplemented from QComboBox + virtual void changeEvent(QEvent *e); ///< reimplemented from QComboBox + virtual void mousePressEvent(QMouseEvent *e); ///< reimplemented from QComboBox + virtual void keyPressEvent(QKeyEvent *e); ///< reimplemented from QComboBox + virtual void wheelEvent(QWheelEvent *e); ///< reimplemented from QComboBox + +private: + Q_PRIVATE_SLOT(d, void sliderValueChanged(int value)) + Q_PRIVATE_SLOT(d, void sliderReleased()) + Q_PRIVATE_SLOT(d, void lineEditFinished()) + + class KoSliderComboPrivate; + KoSliderComboPrivate * const d; +}; + +#endif diff --git a/src/titlewidget.cpp b/src/titlewidget.cpp index 1ac12394..7ccffdf0 100644 --- a/src/titlewidget.cpp +++ b/src/titlewidget.cpp @@ -17,6 +17,7 @@ #include "titlewidget.h" #include "kdenlivesettings.h" +#include "KoSliderCombo.h" #include @@ -71,6 +72,25 @@ TitleWidget::TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render frame_properties->setEnabled(false); frame_properties->setFixedHeight(frame_toolbar->height()); + // Set combo sliders values + textAlpha->setMinimum(0); + textAlpha->setMaximum(255); + textAlpha->setDecimals(0); + textAlpha->setValue(255); + textAlpha->setToolTip(i18n("Font color opacity")); + + textOutlineAlpha->setMinimum(0); + textOutlineAlpha->setMaximum(255); + textOutlineAlpha->setDecimals(0); + textOutlineAlpha->setValue(255); + textOutlineAlpha->setToolTip(i18n("Outline color opacity")); + + textOutline->setMinimum(0); + textOutline->setMaximum(200); + textOutline->setDecimals(0); + textOutline->setValue(0); + textOutline->setToolTip(i18n("Outline width")); + itemzoom->setSuffix(i18n("%")); m_frameWidth = render->renderWidth(); m_frameHeight = render->renderHeight(); @@ -86,9 +106,9 @@ TitleWidget::TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render connect(textOutlineColor, SIGNAL(clicked()), this, SLOT(slotUpdateText())) ; connect(font_family, SIGNAL(currentFontChanged(const QFont &)), this, SLOT(slotUpdateText())) ; connect(font_size, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateText())) ; - connect(textAlpha, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateText())); - connect(textOutline, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateText())); - connect(textOutlineAlpha, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateText())); + connect(textAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText())); + connect(textOutline, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText())); + connect(textOutlineAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText())); connect(font_weight_box, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateText())); connect(font_family, SIGNAL(editTextChanged(const QString &)), this, SLOT(slotFontText(const QString&))); diff --git a/src/widgets/titlewidget_ui.ui b/src/widgets/titlewidget_ui.ui index 88ab6874..ae97c982 100644 --- a/src/widgets/titlewidget_ui.ui +++ b/src/widgets/titlewidget_ui.ui @@ -6,8 +6,8 @@ 0 0 - 1414 - 720 + 900 + 579 @@ -39,7 +39,7 @@ - + 0 0 @@ -890,15 +890,15 @@ - - - - + - Size + Font + + + @@ -920,6 +920,9 @@ 0 + + false + 0 @@ -937,52 +940,7 @@ - - - 255 - - - 1 - - - 255 - - - Qt::Horizontal - - - - - - - - - - 200 - - - 1 - - - Qt::Horizontal - - - - - - - 255 - - - 1 - - - 255 - - - Qt::Horizontal - - + @@ -1007,6 +965,36 @@ + + + + Qt::Vertical + + + + + + + Outline + + + + + + + + + + + + + + + + Qt::Vertical + + + @@ -1148,6 +1136,11 @@ KLineEdit
krestrictedline.h
+ + KoSliderCombo + QComboBox +
KoSliderCombo.h
+
-- 2.39.2