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 const int deskHeight = KGlobalSettings::desktopGeometry(this).height();
00446 if ( p.y() + height() + d->m_popup->height() > deskHeight )
00447 p.setY( p.y() - d->m_popup->height() );
00448 else
00449 p.setY( p.y() + height( ));
00450
00451 d->m_popup->popup(p);
00452 }
00453
00454 void TKToolBarButton::slotDelayTimeout()
00455 {
00456 d->m_delayTimer->stop();
00457 showMenu();
00458 }
00459
00460 void TKToolBarButton::slotClicked()
00461 {
00462 if ( d->ignoreNextMousePress ) {
00463 d->ignoreNextMousePress=false;
00464 return;
00465 }
00466
00467 if (d->m_popup && !d->m_isPopup)
00468 showMenu();
00469 else
00470 emit buttonClicked();
00471 }
00472
00473 void TKToolBarButton::slotPressed()
00474 {
00475 if ( d->ignoreNextMousePress )
00476 return;
00477
00478 if (d->m_popup) {
00479 if (!d->m_isPopup || d->m_isPopup && d->m_arrowPressed)
00480 showMenu();
00481 }
00482 else
00483 emit buttonPressed();
00484
00485 d->ignoreNextMousePress = false;
00486 }
00487
00488 void TKToolBarButton::slotReleased()
00489 {
00490 if (d->m_popup && d->m_isPopup)
00491 d->m_delayTimer->stop();
00492
00493 emit buttonReleased();
00494 }
00495
00496 void TKToolBarButton::slotToggled()
00497 {
00498 emit buttonToggled();
00499 }
00500
00501 void TKToolBarButton::on(bool flag)
00502 {
00503 d->m_isOn = flag;
00504 repaint();
00505 }
00506
00507 void TKToolBarButton::toggle()
00508 {
00509 on(!d->m_isOn);
00510 }
00511
00512 void TKToolBarButton::setToggle(bool flag)
00513 {
00514 d->m_isToggle = flag;
00515 if (flag == true)
00516 connect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled()));
00517 else
00518 disconnect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled()));
00519
00520 modeChange();
00521 repaint();
00522 }
00523
00524 void TKToolBarButton::setIconMode( TK::IconMode m )
00525 {
00526 d->m_iconMode = m;
00527 modeChange();
00528 repaint();
00529 }
00530
00531 #include <tktoolbarbutton.moc>