00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <tktoolbarbutton.h>
00021
00022 #include <qtimer.h>
00023 #include <qtooltip.h>
00024 #include <qpopupmenu.h>
00025 #include <qcursor.h>
00026 #include <qpainter.h>
00027 #include <qdrawutil.h>
00028 #include <qstyle.h>
00029
00030 #include <kdeversion.h>
00031 #include <kapplication.h>
00032 #include <kiconeffect.h>
00033 #include <kiconloader.h>
00034 #include <kglobalsettings.h>
00035
00036
00037 #define POPUP_DELAY 500
00038
00039 class TKToolBarButton::TKToolBarButtonPrivate
00040 {
00041 public:
00042 TKToolBarButtonPrivate()
00043 {
00044 m_iconMode = TK::IconOnly;
00045 m_isPopup = false;
00046 m_isToggle = false;
00047 m_isOn = false;
00048 m_isRaised = false;
00049 m_autoRaised = true;
00050 ignoreNextMousePress = false;
00051
00052 m_text = QString::null;
00053 m_iconName = QString::null;
00054 m_arrowPressed = false;
00055 m_delayTimer = 0L;
00056 m_popup = 0L;
00057
00058 m_disabledIconName = QString::null;
00059 m_defaultIconName = QString::null;
00060
00061 m_instance = KGlobal::instance();
00062 }
00063
00064 ~TKToolBarButtonPrivate()
00065 {
00066 delete m_delayTimer;
00067 m_delayTimer = 0;
00068 }
00069
00070 bool m_isPopup;
00071 bool m_isToggle;
00072 bool m_isOn;
00073 bool m_isRaised;
00074 bool m_autoRaised;
00075 bool m_arrowPressed;
00076 bool ignoreNextMousePress;
00077
00078 QString m_text;
00079 QString m_iconName;
00080 QString m_disabledIconName;
00081 QString m_defaultIconName;
00082
00083 TK::IconMode m_iconMode;
00084
00085 QTimer *m_delayTimer;
00086 QPopupMenu *m_popup;
00087
00088 KInstance *m_instance;
00089 };
00090
00091 TKToolBarButton::TKToolBarButton( const QString& icon, const QString& txt,
00092 QWidget* parent, const char* name,
00093 KInstance *instance )
00094 : QToolButton(parent,name)
00095 {
00096 d = new TKToolBarButtonPrivate;
00097 d->m_text = txt;
00098 d->m_instance = instance;
00099
00100 setFocusPolicy( NoFocus );
00101
00102 connect(this, SIGNAL(clicked()), SLOT(slotClicked()) );
00103 connect(this, SIGNAL(pressed()), SLOT(slotPressed()) );
00104 connect(this, SIGNAL(released()), SLOT(slotReleased()) );
00105
00106 installEventFilter(this);
00107
00108 setIcon(icon);
00109 modeChange();
00110 }
00111
00112 TKToolBarButton::TKToolBarButton( const QPixmap& pixmap, const QString& txt, QWidget* parent, const char* name )
00113 : QToolButton(parent,name )
00114 {
00115 d = new TKToolBarButtonPrivate;
00116 d->m_text = txt;
00117
00118 setFocusPolicy( NoFocus );
00119
00120 connect(this, SIGNAL(clicked()), SLOT(slotClicked()) );
00121 connect(this, SIGNAL(pressed()), SLOT(slotPressed()) );
00122 connect(this, SIGNAL(released()), SLOT(slotReleased()) );
00123
00124 installEventFilter(this);
00125
00126 setPixmap(pixmap);
00127 modeChange();
00128 }
00129
00130 TKToolBarButton::~TKToolBarButton()
00131 {
00132 delete d;
00133 }
00134
00135 QString TKToolBarButton::text()
00136 {
00137 return d->m_text;
00138 }
00139
00140 void TKToolBarButton::modeChange()
00141 {
00142 QToolTip::add(this,d->m_text);
00143
00144 int border = 3;
00145 int w = 2*border;
00146 int h = 2*border;
00147
00148 if (pixmap()) {
00149 w += pixmap()->width();
00150 h = QMAX(h,pixmap()->height()+2*border);
00151 if (d->m_iconMode == TK::IconAndText && !d->m_text.isEmpty())
00152 w += border;
00153 }
00154
00155 if ((d->m_iconMode==TK::IconAndText||d->m_iconMode==TK::TextOnly) && !d->m_text.isEmpty())
00156 {
00157 QFont tmp_font = KGlobalSettings::toolBarFont();
00158 QFontMetrics fm(tmp_font);
00159
00160 h = QMAX(h,fm.lineSpacing()+2*border);
00161 w += fm.width(d->m_text);
00162 }
00163
00164 if (d->m_popup && !d->m_isToggle)
00165 w += 11;
00166
00167 QSize size(w,h);
00168 setMinimumSize(size);
00169
00170 updateGeometry();
00171 }
00172
00173 void TKToolBarButton::setEnabled( bool enabled )
00174 {
00175 if (isEnabled()==enabled)
00176 return;
00177
00178 QToolButton::setPixmap( (enabled ? defaultPixmap : disabledPixmap) );
00179 QToolButton::setEnabled( enabled );
00180 }
00181
00182 void TKToolBarButton::setText( const QString& text)
00183 {
00184 d->m_text = text;
00185 repaint(false);
00186 }
00187
00188 void TKToolBarButton::setIcon( const QString& icon )
00189 {
00190 d->m_iconName = icon;
00191 int iconSize = 16;
00192
00193 setPixmap( BarIcon(icon, iconSize, KIcon::ActiveState, d->m_instance), false );
00194 setDisabledPixmap( BarIcon(icon, iconSize, KIcon::DisabledState, d->m_instance) );
00195 setDefaultPixmap( BarIcon(icon, iconSize, KIcon::DefaultState, d->m_instance) );
00196 }
00197
00198 void TKToolBarButton::setDisabledIcon( const QString &icon )
00199 {
00200 d->m_disabledIconName = icon;
00201 int iconSize = 16;
00202 setDisabledPixmap( BarIcon(icon, iconSize, KIcon::DisabledState, d->m_instance) );
00203 }
00204
00205 void TKToolBarButton::setDefaultIcon( const QString &icon )
00206 {
00207 d->m_defaultIconName = icon;
00208 int iconSize = 16;
00209 setDefaultPixmap( BarIcon(icon, iconSize, KIcon::DefaultState, d->m_instance) );
00210 }
00211
00212 QPixmap TKToolBarButton::getActivePixmap() const
00213 {
00214 return activePixmap;
00215 }
00216
00217 void TKToolBarButton::setPixmap( const QPixmap &pixmap )
00218 {
00219 setPixmap( pixmap, true );
00220 }
00221
00222 void TKToolBarButton::setPixmap( const QPixmap &pixmap, bool generate )
00223 {
00224 activePixmap = pixmap;
00225
00226 if ( generate )
00227 {
00228 makeDefaultPixmap();
00229 makeDisabledPixmap();
00230 }
00231 else
00232 {
00233 if (defaultPixmap.isNull())
00234 defaultPixmap = activePixmap;
00235 if (disabledPixmap.isNull())
00236 disabledPixmap = activePixmap;
00237 }
00238
00239 QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
00240 }
00241
00242 void TKToolBarButton::setDefaultPixmap( const QPixmap &pixmap )
00243 {
00244 defaultPixmap = pixmap;
00245 QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
00246 }
00247
00248 void TKToolBarButton::setDisabledPixmap( const QPixmap &pixmap )
00249 {
00250 disabledPixmap = pixmap;
00251 QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
00252 }
00253
00254 void TKToolBarButton::setPopup(QPopupMenu *p)
00255 {
00256 d->m_popup = p;
00257 d->m_popup->setFont(KGlobalSettings::toolBarFont());
00258 p->installEventFilter(this);
00259
00260 modeChange();
00261 }
00262
00263 QPopupMenu *TKToolBarButton::popup()
00264 {
00265 return d->m_popup;
00266 }
00267
00268 void TKToolBarButton::setDelayedPopup (QPopupMenu *p, bool toggle )
00269 {
00270 d->m_isPopup = true;
00271 setToggle(toggle);
00272
00273 if (!d->m_delayTimer) {
00274 d->m_delayTimer = new QTimer(this);
00275 connect(d->m_delayTimer, SIGNAL(timeout()), this, SLOT(slotDelayTimeout()));
00276 }
00277
00278 setPopup(p);
00279 }
00280
00281 void TKToolBarButton::setRaised(bool f)
00282 {
00283 d->m_isRaised = f;
00284 repaint(false);
00285 }
00286
00287 void TKToolBarButton::setAutoRaised(bool f)
00288 {
00289 d->m_autoRaised = f;
00290 }
00291
00292 void TKToolBarButton::leaveEvent(QEvent *)
00293 {
00294 if (!d->m_isToggle && !(d->m_popup && d->m_popup->isVisible()) ) {
00295 QToolButton::setPixmap(isEnabled() ? defaultPixmap : disabledPixmap);
00296 if (d->m_autoRaised)
00297 setRaised(false);
00298 }
00299 }
00300
00301 void TKToolBarButton::enterEvent(QEvent *)
00302 {
00303 if (!d->m_isToggle) {
00304 if (isEnabled()) {
00305 QToolButton::setPixmap(activePixmap);
00306 if (d->m_autoRaised)
00307 setRaised(true);
00308 } else {
00309 QToolButton::setPixmap(disabledPixmap);
00310 }
00311 repaint(false);
00312 }
00313 }
00314
00315 bool TKToolBarButton::eventFilter(QObject *o, QEvent *ev)
00316 {
00317 if ( o == this )
00318 if (ev->type() == QEvent::MouseButtonPress && d->m_popup && d->m_isPopup ) {
00319 if (!d->m_isToggle) {
00320 d->m_arrowPressed = arrowPressed( mapFromGlobal(QCursor::pos()) );
00321 } else {
00322 d->m_delayTimer->start(POPUP_DELAY);
00323 }
00324 }
00325
00326 if ( o == d->m_popup) {
00327 switch (ev->type())
00328 {
00329 case QEvent::Show:
00330 on(true);
00331 return false;
00332 case QEvent::Hide:
00333 on(false);
00334 setDown(false);
00335 if ( !geometry().contains(parentWidget()->mapFromGlobal(QCursor::pos())) )
00336 leaveEvent(0L);
00337 return false;
00338 break;
00339 case QEvent::MouseButtonPress: {
00340 d->m_arrowPressed = arrowPressed( mapFromGlobal(QCursor::pos()) );
00341 d->ignoreNextMousePress = d->m_arrowPressed;
00342 break;
00343 }
00344 default:
00345 break;
00346 }
00347 }
00348 return false;
00349 }
00350
00351 void TKToolBarButton::drawButton( QPainter* p )
00352 {
00353 #define DRAW_PIXMAP_AND_TEXT \
00354 int x = 3;\
00355 if (pixmap()) {\
00356 style().drawItem( p, QRect( x, 0, pixmap()->width(), height() ), AlignCenter, colorGroup(), isEnabled(), pixmap(), QString::null );\
00357 if (d->m_iconMode==TK::IconAndText && !d->m_text.isEmpty()) {\
00358 x += pixmap()->width() + 3;\
00359 }\
00360 }\
00361 if ((d->m_iconMode==TK::IconAndText||d->m_iconMode==TK::TextOnly) && !d->m_text.isEmpty()) {\
00362 QFontMetrics fm(KGlobalSettings::toolBarFont());\
00363 style().drawItem( p, QRect( x, 0, fm.width(d->m_text), height() ), AlignCenter, colorGroup(), isEnabled(), 0, d->m_text );\
00364 }
00365
00366 const char* arrow[] = {
00367 "7 4 2 1",
00368 "# c Black",
00369 ". c None",
00370 "#######",
00371 ".#####.",
00372 "..###..",
00373 "...#..."};
00374 QPixmap arrow_pix(arrow);
00375 bool f = d->m_isOn || isDown();
00376
00377 if (d->m_popup && !d->m_isToggle)
00378 {
00379 if (d->m_isPopup)
00380 {
00381 QStyle::SFlags flags = QStyle::Style_Default;
00382 if (isEnabled()) flags |= QStyle::Style_Enabled;
00383 if (isOn()) flags |= QStyle::Style_On;
00384 if (d->m_isRaised) flags |= QStyle::Style_Raised;
00385 if (hasFocus()) flags |= QStyle::Style_HasFocus;
00386
00387 style().drawComplexControl( QStyle::CC_ToolButton, p, this, QRect( 0, 0, width()-12, height() ), colorGroup(), flags, QStyle::SC_ToolButton );
00388 style().drawComplexControl( QStyle::CC_ToolButton, p, this, QRect( width()-13, 0, 13, height() ), colorGroup(), flags, QStyle::SC_ToolButton );
00389 style().drawItem( p, QRect( width()-13, 0, 13, height() ), AlignCenter, colorGroup(), isEnabled(), &arrow_pix, QString::null );
00390 if ( d->m_isRaised )
00391 qDrawShadeLine( p, width()-12, 0, width()-12, height(), colorGroup(), true );
00392 DRAW_PIXMAP_AND_TEXT
00393 } else {
00394 style().drawControl( QStyle::CE_PushButton, p, this, QRect( 0, 0, width(), height() ), isEnabled() ? colorGroup() : palette().disabled(), f );
00395 DRAW_PIXMAP_AND_TEXT
00396 int z = f ? 1:0;
00397 p->drawPixmap(width()-11+z,(height()-4)/2+z ,arrow_pix);
00398 }
00399 } else {
00400 style().drawControl( QStyle::CE_PushButton, p, this, QRect( 0, 0, width(), height() ), isEnabled() ? colorGroup() : palette().disabled(), f );
00401 DRAW_PIXMAP_AND_TEXT
00402 }
00403 }
00404
00405 void TKToolBarButton::paletteChange(const QPalette &)
00406 {
00407 makeDisabledPixmap();
00408 if ( !isEnabled() )
00409 QToolButton::setPixmap( disabledPixmap );
00410 else
00411 QToolButton::setPixmap( defaultPixmap );
00412 repaint(false);
00413 }
00414
00415 void TKToolBarButton::makeDefaultPixmap()
00416 {
00417 if (activePixmap.isNull())
00418 return;
00419
00420 KIconEffect effect;
00421 defaultPixmap = effect.apply(activePixmap, KIcon::Toolbar, KIcon::DefaultState);
00422 }
00423
00424 void TKToolBarButton::makeDisabledPixmap()
00425 {
00426 if (activePixmap.isNull())
00427 return;
00428
00429 KIconEffect effect;
00430 disabledPixmap = effect.apply(activePixmap, KIcon::Toolbar, KIcon::DisabledState);
00431 }
00432
00433 QSize TKToolBarButton::sizeHint() const
00434 {
00435 return minimumSize();
00436 }
00437
00438 QSize TKToolBarButton::minimumSizeHint() const
00439 {
00440 return minimumSize();
00441 }
00442
00443 void TKToolBarButton::showMenu()
00444 {
00445 QPoint p ( mapToGlobal( QPoint( 0, 0 ) ) );
00446 const int deskHeight = KGlobalSettings::desktopGeometry(this).height();
00447 if ( p.y() + height() + d->m_popup->height() > deskHeight )
00448 p.setY( p.y() - d->m_popup->height() );
00449 else
00450 p.setY( p.y() + height( ));
00451
00452 d->m_popup->popup(p);
00453 }
00454
00455 void TKToolBarButton::slotDelayTimeout()
00456 {
00457 d->m_delayTimer->stop();
00458 showMenu();
00459 }
00460
00461 void TKToolBarButton::slotClicked()
00462 {
00463 if ( d->ignoreNextMousePress ) {
00464 d->ignoreNextMousePress=false;
00465 return;
00466 }
00467
00468 if (d->m_popup && !d->m_isPopup)
00469 showMenu();
00470 else
00471 emit buttonClicked();
00472 }
00473
00474 void TKToolBarButton::slotPressed()
00475 {
00476 if ( d->ignoreNextMousePress )
00477 return;
00478
00479 if (d->m_popup) {
00480 if (!d->m_isPopup || d->m_isPopup && d->m_arrowPressed)
00481 showMenu();
00482 }
00483 else
00484 emit buttonPressed();
00485
00486 d->ignoreNextMousePress = false;
00487 }
00488
00489 void TKToolBarButton::slotReleased()
00490 {
00491 if (d->m_popup && d->m_isPopup)
00492 d->m_delayTimer->stop();
00493
00494 emit buttonReleased();
00495 }
00496
00497 void TKToolBarButton::slotToggled()
00498 {
00499 emit buttonToggled();
00500 }
00501
00502 void TKToolBarButton::on(bool flag)
00503 {
00504 d->m_isOn = flag;
00505 repaint();
00506 }
00507
00508 void TKToolBarButton::toggle()
00509 {
00510 on(!d->m_isOn);
00511 }
00512
00513 void TKToolBarButton::setToggle(bool flag)
00514 {
00515 d->m_isToggle = flag;
00516 if (flag == true)
00517 connect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled()));
00518 else
00519 disconnect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled()));
00520
00521 modeChange();
00522 repaint();
00523 }
00524
00525 void TKToolBarButton::setIconMode( TK::IconMode m )
00526 {
00527 d->m_iconMode = m;
00528 modeChange();
00529 repaint();
00530 }
00531
00532 #include <tktoolbarbutton.moc>