00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "kmultitabbar.h"
00026 #include "kmultitabbar_p.h"
00027 #include "kmultitabbar.moc"
00028 #include "kmultitabbar_p.moc"
00029
00030 #include <QtGui/QActionEvent>
00031 #include <QtGui/QLayout>
00032 #include <QtGui/QPainter>
00033 #include <QtGui/QFontMetrics>
00034 #include <QtGui/QStyle>
00035 #include <QStyleOptionButton>
00036
00037 #include <kiconloader.h>
00038 #include <kdebug.h>
00039 #include <QtGui/QApplication>
00040 #include <math.h>
00041
00049 class KMultiTabBarPrivate
00050 {
00051 public:
00052 class KMultiTabBarInternal *m_internal;
00053 QBoxLayout *m_l;
00054 QFrame *m_btnTabSep;
00055 QList<KMultiTabBarButton*> m_buttons;
00056 KMultiTabBar::KMultiTabBarPosition m_position;
00057 };
00058
00059
00060 KMultiTabBarInternal::KMultiTabBarInternal(QWidget *parent, KMultiTabBar::KMultiTabBarPosition pos):QFrame(parent)
00061 {
00062 m_position = pos;
00063 if (pos == KMultiTabBar::Left || pos == KMultiTabBar::Right)
00064 mainLayout=new QVBoxLayout(this);
00065 else
00066 mainLayout=new QHBoxLayout(this);
00067 mainLayout->setMargin(0);
00068 mainLayout->setSpacing(0);
00069 mainLayout->addStretch();
00070 setFrameStyle(NoFrame);
00071 setBackgroundRole(QPalette::Background);
00072 }
00073
00074 KMultiTabBarInternal::~KMultiTabBarInternal()
00075 {
00076 qDeleteAll(m_tabs);
00077 m_tabs.clear();
00078 }
00079
00080 void KMultiTabBarInternal::setStyle(enum KMultiTabBar::KMultiTabBarStyle style)
00081 {
00082 m_style=style;
00083 for (int i=0;i<m_tabs.count();i++)
00084 m_tabs.at(i)->setStyle(m_style);
00085
00086 updateGeometry();
00087 }
00088
00089 void KMultiTabBarInternal::contentsMousePressEvent(QMouseEvent *ev)
00090 {
00091 ev->ignore();
00092 }
00093
00094 void KMultiTabBarInternal::mousePressEvent(QMouseEvent *ev)
00095 {
00096 ev->ignore();
00097 }
00098
00099 KMultiTabBarTab* KMultiTabBarInternal::tab(int id) const
00100 {
00101 QListIterator<KMultiTabBarTab*> it(m_tabs);
00102 while (it.hasNext()) {
00103 KMultiTabBarTab *tab = it.next();
00104 if (tab->id()==id) return tab;
00105 }
00106 return 0;
00107 }
00108
00109 int KMultiTabBarInternal::appendTab(const QPixmap &pic, int id, const QString& text)
00110 {
00111 KMultiTabBarTab *tab;
00112 m_tabs.append(tab= new KMultiTabBarTab(pic,text,id,this,m_position,m_style));
00113
00114
00115 mainLayout->insertWidget(m_tabs.size()-1, tab);
00116 tab->show();
00117 return 0;
00118 }
00119
00120 void KMultiTabBarInternal::removeTab(int id)
00121 {
00122 for (int pos=0;pos<m_tabs.count();pos++)
00123 {
00124 if (m_tabs.at(pos)->id()==id)
00125 {
00126
00127 delete m_tabs.takeAt(pos);
00128 break;
00129 }
00130 }
00131 }
00132
00133 void KMultiTabBarInternal::setPosition(enum KMultiTabBar::KMultiTabBarPosition pos)
00134 {
00135 m_position=pos;
00136 for (int i=0;i<m_tabs.count();i++)
00137 m_tabs.at(i)->setPosition(m_position);
00138 updateGeometry();
00139 }
00140
00141
00143
00144 KMultiTabBarButton::KMultiTabBarButton(const QPixmap& pic, const QString& text,
00145 int id, QWidget *parent)
00146 : QPushButton(QIcon(pic), text, parent), m_id(id), d(0)
00147 {
00148 connect(this,SIGNAL(clicked()),this,SLOT(slotClicked()));
00149 setFlat(true);
00150 }
00151
00152 KMultiTabBarButton::~KMultiTabBarButton()
00153 {
00154 }
00155
00156 void KMultiTabBarButton::setText(const QString &text)
00157 {
00158 QPushButton::setText(text);
00159 }
00160
00161 void KMultiTabBarButton::slotClicked()
00162 {
00163 updateGeometry();
00164 emit clicked(m_id);
00165 }
00166
00167 int KMultiTabBarButton::id() const
00168 {
00169 return m_id;
00170 }
00171
00172 void KMultiTabBarButton::hideEvent( QHideEvent* he) {
00173 QPushButton::hideEvent(he);
00174 KMultiTabBar *tb=dynamic_cast<KMultiTabBar*>(parentWidget());
00175 if (tb) tb->updateSeparator();
00176 }
00177
00178 void KMultiTabBarButton::showEvent( QShowEvent* he) {
00179 QPushButton::showEvent(he);
00180 KMultiTabBar *tb=dynamic_cast<KMultiTabBar*>(parentWidget());
00181 if (tb) tb->updateSeparator();
00182 }
00183
00184
00186
00187 KMultiTabBarTab::KMultiTabBarTab(const QPixmap& pic, const QString& text,
00188 int id, QWidget *parent,
00189 KMultiTabBar::KMultiTabBarPosition pos,
00190 KMultiTabBar::KMultiTabBarStyle style)
00191 : KMultiTabBarButton(pic, text, id, parent), m_style(style), d(0)
00192 {
00193 m_position=pos;
00194 setToolTip(text);
00195 setCheckable(true);
00196 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00197
00198 }
00199
00200 KMultiTabBarTab::~KMultiTabBarTab()
00201 {
00202 }
00203
00204 void KMultiTabBarTab::setPosition(KMultiTabBar::KMultiTabBarPosition pos)
00205 {
00206 m_position=pos;
00207 updateGeometry();
00208 }
00209
00210 void KMultiTabBarTab::setStyle(KMultiTabBar::KMultiTabBarStyle style)
00211 {
00212 m_style=style;
00213 updateGeometry();
00214 }
00215
00216 QPixmap KMultiTabBarTab::iconPixmap() const
00217 {
00218 int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this);
00219 return icon().pixmap(iconSize);
00220 }
00221
00222 void KMultiTabBarTab::initStyleOption(QStyleOptionToolButton* opt) const
00223 {
00224 opt->initFrom(this);
00225
00226
00227 if (!icon().isNull()) {
00228 opt->iconSize = iconPixmap().size();
00229 opt->icon = icon();
00230 }
00231
00232
00233 if (shouldDrawText())
00234 opt->text = text();
00235
00236 if (underMouse())
00237 opt->state |= QStyle::State_AutoRaise | QStyle::State_MouseOver | QStyle::State_Raised;
00238
00239 if (isChecked())
00240 opt->state |= QStyle::State_Sunken | QStyle::State_On;
00241
00242 opt->font = font();
00243 opt->toolButtonStyle = shouldDrawText() ? Qt::ToolButtonTextBesideIcon : Qt::ToolButtonIconOnly;
00244 opt->subControls = QStyle::SC_ToolButton;
00245 }
00246
00247 QSize KMultiTabBarTab::sizeHint() const
00248 {
00249 return computeSizeHint(shouldDrawText());
00250 }
00251
00252 QSize KMultiTabBarTab::minimumSizeHint() const
00253 {
00254 return computeSizeHint(false);
00255 }
00256
00257 void KMultiTabBarTab::computeMargins(int* hMargin, int* vMargin) const
00258 {
00259
00260
00261 QStyleOptionToolButton opt;
00262 initStyleOption(&opt);
00263
00264 QPixmap iconPix = iconPixmap();
00265 QSize trialSize = iconPix.size();
00266 QSize expandSize = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, trialSize, this);
00267
00268 *hMargin = (expandSize.width() - trialSize.width())/2;
00269 *vMargin = (expandSize.height() - trialSize.height())/2;
00270 }
00271
00272 QSize KMultiTabBarTab::computeSizeHint(bool withText) const
00273 {
00274
00275 QStyleOptionToolButton opt;
00276 initStyleOption(&opt);
00277
00278 int hMargin, vMargin;
00279 computeMargins(&hMargin, &vMargin);
00280
00281
00282 QPixmap iconPix = iconPixmap();
00283 QSize size = iconPix.size();
00284
00285
00286
00287 QSize textSize = fontMetrics().size(Qt::TextShowMnemonic, text());
00288 size.setHeight(qMax(size.height(), textSize.height()));
00289
00290
00291 int majorMargin = isVertical() ? vMargin : hMargin;
00292 int minorMargin = isVertical() ? hMargin : vMargin;
00293
00294 size.setWidth (size.width() + 2*majorMargin);
00295 size.setHeight(size.height() + 2*minorMargin);
00296
00297 if (withText)
00298
00299 size.setWidth(size.width() + textSize.width() + majorMargin);
00300
00301
00302 if (isVertical())
00303 return QSize(size.height(), size.width());
00304 else
00305 return size;
00306 }
00307
00308 void KMultiTabBarTab::setState(bool newState)
00309 {
00310 setChecked(newState);
00311 updateGeometry();
00312 }
00313
00314 void KMultiTabBarTab::setIcon(const QString& icon)
00315 {
00316 QPixmap pic=SmallIcon(icon);
00317 setIcon(pic);
00318 }
00319
00320 void KMultiTabBarTab::setIcon(const QPixmap& icon)
00321 {
00322 QPushButton::setIcon(icon);
00323 }
00324
00325 bool KMultiTabBarTab::shouldDrawText() const
00326 {
00327 return (m_style==KMultiTabBar::KDEV3ICON) || isChecked();
00328 }
00329
00330 bool KMultiTabBarTab::isVertical() const
00331 {
00332 return m_position==KMultiTabBar::Right || m_position==KMultiTabBar::Left;
00333 }
00334
00335 void KMultiTabBarTab::paintEvent(QPaintEvent*) {
00336 QPainter painter(this);
00337
00338 QStyleOptionToolButton opt;
00339 initStyleOption(&opt);
00340
00341
00342 if (underMouse() || isChecked())
00343 style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &painter);
00344
00345 int hMargin, vMargin;
00346 computeMargins(&hMargin, &vMargin);
00347
00348
00349
00350
00351 QPixmap icon = iconPixmap();
00352 int textRoom = 0;
00353 int iconRoom = 0;
00354
00355 QString t;
00356 if (shouldDrawText()) {
00357 if (isVertical()) {
00358 iconRoom = icon.height() + 2*vMargin;
00359 textRoom = height() - iconRoom - vMargin;
00360 } else {
00361 iconRoom = icon.width() + 2*hMargin;
00362 textRoom = width() - iconRoom - hMargin;
00363 }
00364
00365 t = painter.fontMetrics().elidedText(text(), Qt::ElideRight, textRoom);
00366
00367
00368
00369 if (t == QLatin1String("...") || t == QChar(0x2026))
00370 t.clear();
00371 }
00372
00373 opt.text = t;
00374
00375
00376
00377
00378 if (!shouldDrawText()) {
00379 style()->drawItemPixmap(&painter, rect(), Qt::AlignCenter | Qt::AlignVCenter, icon);
00380 return;
00381 }
00382
00383
00384 QRect iconArea;
00385 QRect labelArea;
00386
00387 bool bottomIcon = false;
00388 bool rtl = layoutDirection() == Qt::RightToLeft;
00389 if (isVertical()) {
00390 if (m_position == KMultiTabBar::Left && !rtl)
00391 bottomIcon = true;
00392 if (m_position == KMultiTabBar::Right && rtl)
00393 bottomIcon = true;
00394 }
00395
00396
00397 if (isVertical()) {
00398 if (bottomIcon) {
00399 labelArea = QRect(0, vMargin, width(), textRoom);
00400 iconArea = QRect(0, vMargin + textRoom, width(), iconRoom);
00401 } else {
00402 labelArea = QRect(0, iconRoom, width(), textRoom);
00403 iconArea = QRect(0, 0, width(), iconRoom);
00404 }
00405 } else {
00406
00407 if (rtl) {
00408 labelArea = QRect(hMargin, 0, textRoom, height());
00409 iconArea = QRect(hMargin + textRoom, 0, iconRoom, height());
00410 } else {
00411 labelArea = QRect(iconRoom, 0, textRoom, height());
00412 iconArea = QRect(0, 0, iconRoom, height());
00413 }
00414 }
00415
00416 style()->drawItemPixmap(&painter, iconArea, Qt::AlignCenter | Qt::AlignVCenter, icon);
00417
00418 if (t.isEmpty())
00419 return;
00420
00421 QRect labelPaintArea = labelArea;
00422
00423 if (isVertical()) {
00424
00425
00426 labelPaintArea = QRect(0, 0, labelArea.height(), labelArea.width());
00427
00428 QTransform tr;
00429
00430 if (bottomIcon) {
00431 tr.translate(labelArea.x(), labelPaintArea.width() + labelArea.y());
00432 tr.rotate(-90);
00433 } else {
00434 tr.translate(labelPaintArea.height() + labelArea.x(), labelArea.y());
00435 tr.rotate(90);
00436 }
00437 painter.setTransform(tr);
00438 }
00439
00440 style()->drawItemText(&painter, labelPaintArea, Qt::AlignLeading | Qt::AlignVCenter,
00441 palette(), true, t, QPalette::ButtonText);
00442 }
00443
00444
00446
00447 KMultiTabBar::KMultiTabBar(KMultiTabBarPosition pos, QWidget *parent)
00448 : QWidget(parent),
00449 d(new KMultiTabBarPrivate)
00450 {
00451 if (pos == Left || pos == Right)
00452 {
00453 d->m_l=new QVBoxLayout(this);
00454 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
00455 }
00456 else
00457 {
00458 d->m_l=new QHBoxLayout(this);
00459 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
00460 }
00461 d->m_l->setMargin(0);
00462 d->m_l->setSpacing(0);
00463
00464 d->m_internal=new KMultiTabBarInternal(this, pos);
00465 setPosition(pos);
00466 setStyle(VSNET);
00467 d->m_l->insertWidget(0,d->m_internal);
00468 d->m_l->insertWidget(0,d->m_btnTabSep=new QFrame(this));
00469 d->m_btnTabSep->setFixedHeight(4);
00470 d->m_btnTabSep->setFrameStyle(QFrame::Panel | QFrame::Sunken);
00471 d->m_btnTabSep->setLineWidth(2);
00472 d->m_btnTabSep->hide();
00473
00474 updateGeometry();
00475 }
00476
00477 KMultiTabBar::~KMultiTabBar()
00478 {
00479 qDeleteAll( d->m_buttons );
00480 d->m_buttons.clear();
00481 delete d;
00482 }
00483
00484 int KMultiTabBar::appendButton(const QPixmap &pic, int id, QMenu *popup, const QString&)
00485 {
00486 KMultiTabBarButton *btn = new KMultiTabBarButton(pic, QString(), id, this);
00487 btn->setMenu(popup);
00488 d->m_buttons.append(btn);
00489 d->m_l->insertWidget(0,btn);
00490 btn->show();
00491 d->m_btnTabSep->show();
00492 return 0;
00493 }
00494
00495 void KMultiTabBar::updateSeparator() {
00496 bool hideSep=true;
00497 QListIterator<KMultiTabBarButton*> it(d->m_buttons);
00498 while (it.hasNext()){
00499 if (it.next()->isVisibleTo(this)) {
00500 hideSep=false;
00501 break;
00502 }
00503 }
00504 if (hideSep)
00505 d->m_btnTabSep->hide();
00506 else
00507 d->m_btnTabSep->show();
00508 }
00509
00510 int KMultiTabBar::appendTab(const QPixmap &pic, int id, const QString& text)
00511 {
00512 d->m_internal->appendTab(pic,id,text);
00513 return 0;
00514 }
00515
00516 KMultiTabBarButton* KMultiTabBar::button(int id) const
00517 {
00518 QListIterator<KMultiTabBarButton*> it(d->m_buttons);
00519 while ( it.hasNext() ) {
00520 KMultiTabBarButton *button = it.next();
00521 if ( button->id() == id )
00522 return button;
00523 }
00524
00525 return 0;
00526 }
00527
00528 KMultiTabBarTab* KMultiTabBar::tab(int id) const
00529 {
00530 return d->m_internal->tab(id);
00531 }
00532
00533 void KMultiTabBar::removeButton(int id)
00534 {
00535 for (int pos=0;pos<d->m_buttons.count();pos++)
00536 {
00537 if (d->m_buttons.at(pos)->id()==id)
00538 {
00539 d->m_buttons.takeAt(pos)->deleteLater();
00540 break;
00541 }
00542 }
00543
00544 if (d->m_buttons.count()==0)
00545 d->m_btnTabSep->hide();
00546 }
00547
00548 void KMultiTabBar::removeTab(int id)
00549 {
00550 d->m_internal->removeTab(id);
00551 }
00552
00553 void KMultiTabBar::setTab(int id,bool state)
00554 {
00555 KMultiTabBarTab *ttab=tab(id);
00556 if (ttab)
00557 ttab->setState(state);
00558 }
00559
00560 bool KMultiTabBar::isTabRaised(int id) const
00561 {
00562 KMultiTabBarTab *ttab=tab(id);
00563 if (ttab)
00564 return ttab->isChecked();
00565
00566 return false;
00567 }
00568
00569 void KMultiTabBar::setStyle(KMultiTabBarStyle style)
00570 {
00571 d->m_internal->setStyle(style);
00572 }
00573
00574 KMultiTabBar::KMultiTabBarStyle KMultiTabBar::tabStyle() const
00575 {
00576 return d->m_internal->m_style;
00577 }
00578
00579 void KMultiTabBar::setPosition(KMultiTabBarPosition pos)
00580 {
00581 d->m_position=pos;
00582 d->m_internal->setPosition(pos);
00583 }
00584
00585 KMultiTabBar::KMultiTabBarPosition KMultiTabBar::position() const
00586 {
00587 return d->m_position;
00588 }
00589
00590 void KMultiTabBar::fontChange(const QFont& )
00591 {
00592 updateGeometry();
00593 }
00594
00595
00596