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