Commit 02188f88 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Re-use KOffice widget in the titler to gain space (spin box with popup slider)

svn path=/trunk/kdenlive/; revision=4212
parent cd9fce69
......@@ -184,6 +184,7 @@ set(kdenlive_SRCS
folderprojectitem.cpp
addclipcutcommand.cpp
editclipcutcommand.cpp
KoSliderCombo.cpp
)
add_definitions( ${KDE4_DEFINITIONS} )
......
/* This file is part of the KDE project
Copyright (c) 2007 Casper Boemann <cbr@boemann.dk>
Copyright (c) 2010 Jean-Baptiste Mardelle <jb@kdenlive.org>
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 <QTimer>
#include <QApplication>
#include <QSize>
#include <QSlider>
#include <QStyle>
#include <QStylePainter>
#include <QStyleOptionSlider>
#include <QLineEdit>
#include <QValidator>
#include <QHBoxLayout>
#include <QFrame>
#include <QMenu>
#include <QMouseEvent>
#include <QDoubleSpinBox>
#include <QDesktopWidget>
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
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 <KoSliderCombo.moc>
/* This file is part of the KDE project
Copyright (c) 2007 Casper Boemann <cbr@boemann.dk>
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 <QComboBox>
#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
......@@ -17,6 +17,7 @@
#include "titlewidget.h"
#include "kdenlivesettings.h"
#include "KoSliderCombo.h"
#include <cmath>
......@@ -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&)));
......
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1414</width>
<height>720</height>
<width>900</width>
<height>579</height>
</rect>
</property>
<property name="sizePolicy">
......@@ -39,7 +39,7 @@
<item row="0" column="5" colspan="4">
<widget class="QFrame" name="frame_properties">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -890,15 +890,15 @@
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QFontComboBox" name="font_family"/>
</item>
<item>
<widget class="QLabel" name="label_20">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Size</string>
<string>Font</string>
</property>
</widget>
</item>
<item>
<widget class="QFontComboBox" name="font_family"/>
</item>
<item>
<widget class="QSpinBox" name="font_size">
<property name="minimum">
......@@ -920,6 +920,9 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="color">
<color>
<red>0</red>
......@@ -937,52 +940,7 @@
</widget>
</item>
<item>
<widget class="QSlider" name="textAlpha">
<property name="maximum">
<number>255</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>255</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="KColorButton" name="textOutlineColor"/>
</item>
<item>
<widget class="QSlider" name="textOutline">
<property name="maximum">
<number>200</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="textOutlineAlpha">
<property name="maximum">
<number>255</number>
</property>