1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: QtxColorButton.cxx
21 // Author: Sergey TELKOV
23 #include "QtxColorButton.h"
30 #include <QPaintEvent>
31 #include <QColorDialog>
32 #include <QStyleOptionToolButton>
36 \brief The QtxColorButton class implements a widget for color
37 preference items editing.
39 The color preference item is represented as the colored button with
40 assocoiated popup menu whihc is called when the user presses the small
41 arrow button near it. The popup menu allows selecting of the color
42 from the predefined set. In addition it contains the button which
43 invokes standard "Select color" dialog box.
45 Initial color value can be set with setColor() method. Chosen color
46 can be retrieved with the color() method.
51 \param parent parent widget
53 QtxColorButton::QtxColorButton( QWidget* parent )
54 : QToolButton( parent )
56 setCheckable( false );
57 setPopupMode( MenuButtonPopup ); // VSR 11/10/2010 temporarily roolback from InstantPopup (regressions)
59 QMenu* pm = new QMenu( this );
60 QGridLayout* grid = new QGridLayout( pm );
62 grid->setSpacing( 0 );
64 QList<QColor> cList = colorsList();
66 int h = cList.count() / w;
68 for ( int y = 0; y < h; y++ )
70 for ( int x = 0; x < w; x++ )
72 QColor c = cList.at( x * h + y ).toRgb();
73 QToolButton* btn = new QToolButton( pm );
74 btn->setAutoRaise( true );
75 btn->setCheckable( true );
76 myColors.insert( btn, c );
77 grid->addWidget( btn, y + 1, x );
79 btn->installEventFilter( this );
81 connect( btn, SIGNAL( clicked( bool ) ), this, SLOT( onToggled( bool ) ) );
87 myAutoButton = new QToolButton( pm );
88 myAutoButton->setText( tr( "Auto" ) );
89 myAutoButton->setAutoRaise( true );
90 myAutoButton->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
91 grid->addWidget( myAutoButton, 0, 0, 1, grid->columnCount() );
92 connect( myAutoButton, SIGNAL( clicked( bool ) ), this, SLOT( onAutoClicked( bool ) ) );
94 QToolButton* other = new QToolButton( pm );
95 other->setText( tr( "Other colors..." ) );
96 other->setAutoRaise( true );
97 other->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
98 grid->addWidget( other, grid->rowCount(), 0, 1, grid->columnCount() );
99 connect( other, SIGNAL( clicked( bool ) ), this, SLOT( onDialogClicked( bool ) ) );
101 other->installEventFilter( this );
105 connect( this, SIGNAL( clicked( bool ) ), this, SLOT( onClicked( bool ) ) );
106 connect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
108 myAutoButton->setVisible( false );
114 QtxColorButton::~QtxColorButton()
119 \brief Get currently selected color.
121 Returns null QColor if no color is selected.
123 \return selected color
126 QColor QtxColorButton::color() const
128 return myColors.contains( this ) ? myColors[this] : QColor();
133 \param c color to be set as current
136 void QtxColorButton::setColor( const QColor& c )
138 myColors.insert( this, c );
141 updateButton( this );
145 \brief Returns the status of "auto" color button in popup widget.
146 \return \c true if the "auto" button is enabled
148 bool QtxColorButton::isAutoEnabled() const
150 return myAutoButton->isVisibleTo( myAutoButton->parentWidget() );
154 \brief Enable/disable the "auto" color button in popup widget.
155 \param on enable/disable state
157 void QtxColorButton::setAutoEnabled( bool on )
159 myAutoButton->setVisible( on );
163 \brief Returns text of the "auto" color button in popup widget.
165 QString QtxColorButton::autoText() const
167 return myAutoButton->text();
171 \brief Sets text of the "auto" color button in popup widget.
172 \param txt new button text
174 void QtxColorButton::setAutoText( const QString& txt )
176 myAutoButton->setText( txt );
180 \brief Filter events for the child widgets.
181 \param o event receiver object
183 \return \c true if the event should be filtered
185 bool QtxColorButton::eventFilter( QObject* o, QEvent* e )
187 if ( e->type() == QEvent::Leave )
188 updateButton( ::qobject_cast<QToolButton*>( o ) );
189 return QToolButton::eventFilter( o, e );
193 \brief Called when the popup menu is about to show.
195 Updates the menu and child widgets state.
197 void QtxColorButton::onAboutToShow()
203 \brief Called when the button is clicked by the user.
205 Emits the signal clicked( QColor ).
207 \param on button state (not used)
209 void QtxColorButton::onClicked( bool )
211 emit clicked( color() );
215 \brief Called when any color selection button from popup menu
218 Changes the currently selected color and emits the signal
221 \param on button state
223 void QtxColorButton::onToggled( bool on )
225 const QToolButton* tb = ::qobject_cast<QToolButton*>( sender() );
229 QColor old = color();
231 if ( on && myColors.contains( tb ) )
233 myColors.insert( this, myColors[tb] );
234 updateButton( this );
242 if ( old != color() )
243 emit changed( color() );
247 \brief Called the "Auto" child button from popup menu
250 Sets the undefined (auto) color as current.
254 void QtxColorButton::onAutoClicked( bool )
259 setColor( QColor() );
263 \brief Called the "Other colors" child button from popup menu
266 Invokes standard "Select color" dialog box allowing user to select
267 custom color. If the current color is changed by the user, emits
268 the signal changed( QColor ).
272 void QtxColorButton::onDialogClicked( bool )
274 QColor c = QColorDialog::getColor( color(), this );
278 QColor old = color();
282 if ( old != color() )
283 emit changed( color() );
287 \brief Customize paint event for the widget.
290 void QtxColorButton::paintEvent( QPaintEvent* e )
292 QToolButton::paintEvent( e );
294 QStyleOptionToolButton opt;
295 opt.initFrom( this );
298 opt.features = QStyleOptionToolButton::Menu;
300 QRect r = style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton );
301 r.setTopLeft( r.topLeft() + QPoint( 2, 2 ) );
302 r.setBottomRight( r.bottomRight() - QPoint( 2, 2 ) );
304 QPixmap pix( r.size() );
305 pix.fill( palette().color( backgroundRole() ) );
307 if ( color().isValid() )
308 drawColor( &pix, isEnabled() ? color() : palette().mid().color(), isEnabled() ? Qt::black : palette().mid().color() );
310 QPainter pixp( &pix );
311 pixp.setPen( palette().color( isEnabled() ? QPalette::WindowText : QPalette::Mid ) );
312 pixp.drawRect( 2, 2, pix.width() - 4, pix.height() - 4 );
313 pixp.fillRect( 3, 3, pix.width() - 6, pix.height() - 6,
314 QBrush( palette().color( isEnabled() ? QPalette::WindowText : QPalette::Mid ), Qt::BDiagPattern ) );
319 p.drawPixmap( r, pix );
324 \brief Update widget state.
326 void QtxColorButton::updateState()
328 QList<QToolButton*> bList = qFindChildren<QToolButton*>( menu() );
329 for ( QList<QToolButton*>::iterator cit = bList.begin(); cit != bList.end(); ++cit )
330 updateButton( *cit );
334 \brief Update child button state.
335 \param btn child button
337 void QtxColorButton::updateButton( QToolButton* btn )
339 QColor c = color().toRgb();
340 bool block = btn->signalsBlocked();
341 btn->blockSignals( true );
342 btn->setChecked( false );
343 if ( myColors.contains( btn ) ) {
344 btn->setIcon( buttonIcon( myColors[btn] ) );
345 btn->setChecked( myColors[btn].toRgb() == c );
347 btn->setDown( false );
348 btn->blockSignals( block );
352 \brief Generate (if necessary) or get the icon for the button.
353 \param c color to be used for the icon
354 \return icon pixmap for the button
356 QPixmap QtxColorButton::buttonIcon( const QColor& c ) const
358 static QMap<int, QPixmap> pixMap;
360 if ( pixMap.contains( c.rgb() ) )
361 return pixMap[c.rgb()];
363 QPixmap pix( 16, 16 );
365 QColor bg = Qt::white;
370 drawColor( &pix, c );
372 pix.setMask( pix.createHeuristicMask() );
374 pixMap.insert( c.rgb(), pix );
381 \param pd paint device
385 void QtxColorButton::drawColor( QPaintDevice* pd, const QColor& c, const QColor& bc, const int m ) const
392 p.fillRect( m, m, pd->width() - 2 * m - 1, pd->height() - 2 * m - 1, QBrush( c ) );
393 p.drawRect( m, m, pd->width() - 2 * m - 1, pd->height() - 2 * m - 1 );
398 \brief Get predefined list of colors to be used in the popup menu.
399 \return list of colors
401 QList<QColor> QtxColorButton::colorsList() const
405 for ( int g = 0; g < 4; g++ )
407 for ( int r = 0; r < 4; r++ )
409 for ( int b = 0; b < 3; b++ )
410 lst.append( QColor( qRgb( r * 255 / 3, g * 255 / 3, b * 255 / 2 ) ) );
417 \fn void QtxColorButton::clicked( QColor color );
418 \brief This signal is emitted when the widget button is clicked by
420 \param color current color
424 \fn void QtxColorButton::changed( QColor color );
425 \brief This signal is emitted when the current color is changed.
426 \param color new current color