Commit 8709b1b9 authored by Casper Boemann's avatar Casper Boemann

Introducing a new widget: KoSliderCombo

which is a combox like widget consisting of a numeric input and a popup 
slider, all wrapped up looking like a traditional combobox.

It uses the style to draw itself so it's nicely themeable right out of 
the box.


svn path=/trunk/koffice/; revision=650966
parent c0fff63c
......@@ -105,7 +105,6 @@ KisControlFrame::KisControlFrame( KMainWindow * /*window*/, KisView2 * view, con
setObjectName(name);
KisConfig cfg;
m_font = KGlobalSettings::generalFont();
m_font.setPointSize((int)cfg.dockerFontSize());
m_brushWidget = new KisIconWidget(view, "brushes");
m_brushWidget->setText( i18n("Brush Shapes") );
......
......@@ -49,6 +49,8 @@
#include <klocale.h>
#include <khbox.h>
#include <kicon.h>
#include "KoSliderCombo.h"
#include <KoDocumentSectionView.h>
#include "KoColorSpace.h"
......@@ -59,7 +61,6 @@
#include <kis_group_layer.h>
#include "kis_cmb_composite.h"
#include "kis_int_spinbox.h"
#include "kis_view2.h"
#include "kis_layer_manager.h"
......@@ -126,8 +127,8 @@ KisLayerBox::KisLayerBox()
connect(bnRaise, SIGNAL(clicked()), SLOT(slotRaiseClicked()));
connect(bnLower, SIGNAL(clicked()), SLOT(slotLowerClicked()));
connect(bnProperties, SIGNAL(clicked()), SLOT(slotPropertiesClicked()));
connect(intOpacity, SIGNAL(valueChanged(int, bool)), SIGNAL(sigOpacityChanged(int, bool)));
connect(intOpacity, SIGNAL(finishedChanging(int, int)), SIGNAL(sigOpacityFinishedChanging(int, int)));
connect(doubleOpacity, SIGNAL(valueChanged(int, bool)), SIGNAL(sigOpacityChanged(int, bool)));
connect(doubleOpacity, SIGNAL(finishedChanging(int, int)), SIGNAL(sigOpacityFinishedChanging(int, int)));
connect(cmbComposite, SIGNAL(activated(const KoCompositeOp*)), SIGNAL(sigItemComposite(const KoCompositeOp*)));
}
......@@ -197,7 +198,7 @@ void KisLayerBox::updateUI()
bnDelete->setEnabled(m_image->activeLayer());
bnRaise->setEnabled(m_image->activeLayer() && (m_image->activeLayer()->prevSibling() || m_image->activeLayer()->parent()));
bnLower->setEnabled(m_image->activeLayer() && m_image->activeLayer()->nextSibling());
intOpacity->setEnabled(m_image->activeLayer());
doubleOpacity->setEnabled(m_image->activeLayer());
cmbComposite->setEnabled(m_image->activeLayer());
if (KisLayerSP active = m_image->activeLayer())
{
......@@ -228,9 +229,9 @@ void KisLayerBox::slotSetColorSpace(const KoColorSpace * colorSpace)
void KisLayerBox::slotSetOpacity(int opacity)
{
Q_ASSERT( opacity >= 0 && opacity <= 100 );
intOpacity->blockSignals(true);
intOpacity->setValue(opacity);
intOpacity->blockSignals(false);
doubleOpacity->blockSignals(true);
//doubleOpacity->setValue(opacity);
doubleOpacity->blockSignals(false);
}
void KisLayerBox::slotContextMenuRequested(const QPoint &pos, const QModelIndex &index)
......@@ -383,10 +384,10 @@ void KisLayerBox::slotPropertiesClicked()
void KisLayerBox::setUpdatesAndSignalsEnabled(bool enable)
{
setUpdatesEnabled(enable);
intOpacity->setUpdatesEnabled(enable);
//doubleOpacity->setUpdatesEnabled(enable);
cmbComposite->setUpdatesEnabled(enable);
intOpacity->blockSignals(!enable);
doubleOpacity->blockSignals(!enable);
cmbComposite->blockSignals(!enable);
}
......
......@@ -46,7 +46,7 @@
</widget>
</item>
<item>
<widget class="KisIntSpinbox" name="intOpacity" >
<widget class="KoSliderCombo" name="doubleOpacity" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
......@@ -247,9 +247,9 @@
<pixmap>image4</pixmap>
</customwidget>
<customwidget>
<class>KisIntSpinbox</class>
<class>KoSliderCombo</class>
<extends></extends>
<header location="global" >kis_int_spinbox.h</header>
<header location="global" >KoSliderCombo.h</header>
<sizehint>
<width>-1</width>
<height>-1</height>
......
......@@ -31,6 +31,7 @@ set(kofficeui_LIB_SRCS
KoRuler.cpp
KoShapeSelector.cpp
KoShapeGeometry.cpp
KoSliderCombo.cpp
KoTabBar.cpp
KoTabChooser.cpp
KoTemplateChooseDia.cpp
......
/* 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.
*/
#include <QTimer>
#include <QApplication>
#include <QSize>
#include <QSlider>
#include <QStyle>
#include <QStylePainter>
#include <QLineEdit>
#include <QValidator>
#include <QHBoxLayout>
#include <QFrame>
#include <QMenu>
#include <QMouseEvent>
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include "KoSliderCombo.h"
class KoSliderComboContainer : public QFrame
{
public:
KoSliderComboContainer(KoSliderCombo *parent) : QFrame(parent, Qt::Popup ), 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);
QFrame::mousePressEvent(e);
}
class KoSliderCombo::KoSliderComboPrivate {
public:
QLineEdit * lineEdit;
QValidator *m_validator;
QTimer m_timer;
KoSliderComboContainer *container;
QSlider *slider;
QStyle::StateFlag arrowState;
double minimum;
double maximum;
int decimals;
};
KoSliderCombo::KoSliderCombo(QWidget *parent)
: QWidget(parent)
{
d = new KoSliderComboPrivate();
d->m_timer.setSingleShot(true);
d->arrowState = QStyle::State_None;
d->lineEdit = new QLineEdit(this);
d->lineEdit->setText("0.00");
d->minimum = 0.0;
d->maximum = 100.0;
d->decimals = 2;
d->container = new KoSliderComboContainer(this);
d->container->setAttribute(Qt::WA_WindowPropagation);
QStyleOptionComboBox opt = styleOption();
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);
//d->slider->setTracking(false);
d->container->resize(200, 30);
QHBoxLayout * l = new QHBoxLayout();
l->setMargin(2);
l->setSpacing(2);
l->addWidget(d->slider);
d->container->setLayout(l);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
connect(&(d->m_timer), SIGNAL(timeout()), this, SLOT(slotTimeout()));
connect(d->slider, SIGNAL(valueChanged(int)), SLOT(sliderValueChanged(int)));
connect(d->lineEdit, SIGNAL(editingFinished()), SLOT(lineEditFinished()));
}
KoSliderCombo::~KoSliderCombo()
{
delete d;
}
void KoSliderCombo::updateLineEditGeometry()
{
QStyleOptionComboBox opt = styleOption();
QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
QStyle::SC_ComboBoxEditField, this);
d->lineEdit->setGeometry(editRect);
}
void KoSliderCombo::updateArrow(QStyle::StateFlag state)
{
if (d->arrowState == state)
return;
d->arrowState = state;
QStyleOptionComboBox opt = styleOption();
update(style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow));
}
void KoSliderCombo::resizeEvent(QResizeEvent *)
{
updateLineEditGeometry();
}
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 = styleOption();
sh = style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, this);
return sh.expandedTo(QApplication::globalStrut());
}
QStyleOptionComboBox KoSliderCombo::styleOption() const
{
QStyleOptionComboBox opt;
opt.init(this);
opt.subControls = QStyle::SC_All;
opt.currentText = KGlobal::locale()->formatNumber(666, 0);
opt.editable = true;
if (d->arrowState == QStyle::State_Sunken) {
opt.activeSubControls = QStyle::SC_ComboBoxArrow;
opt.state |= d->arrowState;
}
if (d->container && d->container->isVisible())
opt.state |= QStyle::State_On;
return opt;
}
void KoSliderCombo::showPopup()
{
QStyleOptionComboBox opt = styleOption();
QSize popSize = d->container->size();
QRect popupRect(mapToGlobal(QPoint(size().width() - popSize.width(), size().height())), popSize);
d->container->setGeometry(popupRect);
d->container->raise();
d->container->show();
d->slider->setFocus();
}
void KoSliderCombo::hidePopup()
{
d->container->hide();
}
void KoSliderCombo::hideEvent(QHideEvent *)
{
hidePopup();
}
void KoSliderCombo::changeEvent(QEvent *e)
{
switch (e->type())
{
case QEvent::StyleChange:
updateLineEditGeometry();
break;
case QEvent::EnabledChange:
if (!isEnabled())
hidePopup();
break;
case QEvent::PaletteChange:
d->container->setPalette(palette());
break;
case QEvent::FontChange:
d->container->setFont(font());
updateLineEditGeometry();
break;
default:
break;
}
QWidget::changeEvent(e);
}
void KoSliderCombo::focusInEvent(QFocusEvent *e)
{
update();
d->lineEdit->event((QEvent *)e);
}
void KoSliderCombo::focusOutEvent(QFocusEvent *e)
{
update();
d->lineEdit->event((QEvent *)e);
}
void KoSliderCombo::paintEvent(QPaintEvent *)
{
QStylePainter gc(this);
gc.setPen(palette().color(QPalette::Text));
QStyleOptionComboBox opt = styleOption();
gc.drawComplexControl(QStyle::CC_ComboBox, opt);
gc.drawControl(QStyle::CE_ComboBoxLabel, opt);
}
bool KoSliderCombo::event(QEvent *event)
{
switch(event->type())
{
case QEvent::LayoutDirectionChange:
case QEvent::ApplicationLayoutDirectionChange:
updateLineEditGeometry();
break;
case QEvent::HoverEnter:
case QEvent::HoverLeave:
case QEvent::HoverMove:
/* if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
d->updateHoverControl(he->pos());
*/
break;
case QEvent::ShortcutOverride:
return d->lineEdit->event(event);
break;
default:
break;
}
return QWidget::event(event);
}
void KoSliderCombo::mousePressEvent(QMouseEvent *e)
{
QStyleOptionComboBox opt = styleOption();
QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(),
this);
if (sc == QStyle::SC_ComboBoxArrow && !d->container->isVisible())
{
updateArrow(QStyle::State_Sunken);
showPopup();
}
}
void KoSliderCombo::lineEditFinished()
{
double value = d->lineEdit->text().toDouble();
d->slider->setValue(int((value - d->minimum) * 256 / d->maximum + 0.5));
}
void KoSliderCombo::sliderValueChanged(int slidervalue)
{
d->lineEdit->setText(KGlobal::locale()->formatNumber(d->minimum + d->maximum*slidervalue/256, d->decimals));
double value = d->lineEdit->text().toDouble();
emit valueChanged(value);
}
double KoSliderCombo::maximum() const
{
return d->maximum;
}
double KoSliderCombo::minimum() const
{
return d->minimum;
}
double KoSliderCombo::decimals() const
{
return d->decimals;
}
void KoSliderCombo::setDecimals(int dec)
{
d->decimals = dec;
}
void KoSliderCombo::setMinimum(double min)
{
d->minimum = min;
}
void KoSliderCombo::setMaximum(double max)
{
d->maximum = max;
}
#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 <QWidget>
#include <QStyleOptionComboBox>
#include <kofficeui_export.h>
/**
* @short A widget for double values with a popup slider
*
* KoSliderCombo combines a QLineedit and a dropdown QSlider
* to make an easy to use control for setting a value.
*
*/
class KOFFICEUI_EXPORT KoSliderCombo : public QWidget
{
Q_OBJECT
public:
/**
* Constructor for the widget, where value is set to 0
*
* @param parent parent QWidget
*/
KoSliderCombo(QWidget *parent=0);
/**
* Destructor
*
*
*/
virtual ~KoSliderCombo();
double maximum() const;
double minimum() const;
double decimals() const;
void setDecimals(int d);
void setMinimum(double min);
void setMaximum(double max);
virtual QSize minimumSizeHint() const;
virtual QSize sizeHint() const;
public slots:
signals:
/**
* Emitted every time the value changes (by calling setValue() or
* by user interaction).
* @param value the new value
*/
void valueChanged(double value);
protected:
virtual void paintEvent(QPaintEvent *);
virtual void resizeEvent(QResizeEvent *);
virtual void hideEvent(QHideEvent *);
virtual void changeEvent(QEvent *e);
virtual void focusInEvent(QFocusEvent *e);
virtual void focusOutEvent(QFocusEvent *e);
virtual bool event(QEvent *event);
virtual void mousePressEvent(QMouseEvent *e);
private slots:
void sliderValueChanged(int value);
void lineEditFinished();
private:
QStyleOptionComboBox styleOption() const;
void updateLineEditGeometry();
void updateArrow(QStyle::StateFlag state);
void showPopup();
void hidePopup();
class KoSliderComboPrivate;
KoSliderComboPrivate *d;
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment