File indexing completed on 2024-04-28 05:41:37
0001 /* 0002 This file is part of KCachegrind. 0003 0004 SPDX-FileCopyrightText: 2003-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-only 0007 */ 0008 0009 /* 0010 * Tab View, enclosing detailed views for one trace item in 0011 * two tab widgets, separated by a splitter 0012 */ 0013 0014 0015 #include "tabview.h" 0016 0017 #include <QLabel> 0018 #include <QSplitter> 0019 #include <QTabWidget> 0020 #include <QHideEvent> 0021 #include <QMoveEvent> 0022 #include <QEvent> 0023 #include <QShowEvent> 0024 #include <QVBoxLayout> 0025 #include <QResizeEvent> 0026 #include <QMouseEvent> 0027 #include <QAction> 0028 #include <QMenu> 0029 0030 #include "config.h" 0031 #include "globalconfig.h" 0032 #include "eventtypeview.h" 0033 #include "partview.h" 0034 #include "callview.h" 0035 #include "coverageview.h" 0036 #include "callmapview.h" 0037 #include "instrview.h" 0038 #include "sourceview.h" 0039 #include "callgraphview.h" 0040 0041 0042 // defaults for subviews in TabView 0043 0044 #define DEFAULT_TOPTABS \ 0045 "EventTypeView" << "CallerView" << "AllCallerView" \ 0046 << "CalleeMapView" << "SourceView" 0047 #define DEFAULT_BOTTOMTABS \ 0048 "PartView" << "CalleeView" << "CallGraphView" \ 0049 << "AllCalleeView" << "CallerMapView" << "InstrView" 0050 0051 #define DEFAULT_ACTIVETOP "CallerView" 0052 #define DEFAULT_ACTIVEBOTTOM "CalleeView" 0053 0054 #define DEFAULT_RIGHTSIZE 0 0055 #define DEFAULT_TOPSIZE 50 0056 #define DEFAULT_LEFTSIZE 0 0057 0058 // TabBar 0059 0060 TabBar::TabBar(TabView* v, QTabWidget* parent) : 0061 QTabBar(parent) 0062 { 0063 _tabWidget = parent; 0064 _tabView = v; 0065 } 0066 0067 void TabBar::mousePressEvent(QMouseEvent *e) 0068 { 0069 if (e->button() == Qt::RightButton) { 0070 int idx = tabAt(e->pos()); 0071 QWidget* page = nullptr; 0072 if (idx >=0) { 0073 setCurrentIndex(idx); 0074 page = _tabWidget->widget(idx); 0075 } 0076 context(page, e->globalPos()); 0077 } 0078 QTabBar::mousePressEvent(e ); 0079 } 0080 0081 void TabBar::context(QWidget* page, const QPoint & pos) 0082 { 0083 QMenu popup, popup2, popup3; 0084 0085 QAction* pageToTopAction = nullptr; 0086 QAction* areaToTopAction = nullptr; 0087 QAction* showOnTopAction = nullptr; 0088 QAction* pageToRightAction = nullptr; 0089 QAction* areaToRightAction = nullptr; 0090 QAction* showOnRightAction = nullptr; 0091 QAction* pageToBottomAction = nullptr; 0092 QAction* areaToBottomAction = nullptr; 0093 QAction* showOnBottomAction = nullptr; 0094 QAction* pageToLeftAction = nullptr; 0095 QAction* areaToLeftAction = nullptr; 0096 QAction* showOnLeftAction = nullptr; 0097 QAction* hidePageAction = nullptr; 0098 QAction* hideAreaAction = nullptr; 0099 0100 if (page) { 0101 TraceItemView::Position p = _tabView->tabPosition(page); 0102 if (p != TraceItemView::Top) { 0103 pageToTopAction = popup.addAction(tr("Move to Top")); 0104 areaToTopAction = popup2.addAction(tr("Top", "Move to Top")); 0105 } 0106 if (p != TraceItemView::Right) { 0107 pageToRightAction = popup.addAction(tr("Move to Right")); 0108 areaToRightAction = popup2.addAction(tr("Right", "Move to Right")); 0109 } 0110 if (p != TraceItemView::Bottom) { 0111 pageToBottomAction = popup.addAction(tr("Move to Bottom")); 0112 areaToBottomAction = popup2.addAction(tr("Bottom", "Move to Bottom")); 0113 } 0114 if (p != TraceItemView::Left) { 0115 pageToLeftAction = popup.addAction(tr("Move to Bottom Left")); 0116 areaToLeftAction = popup2.addAction(tr("Bottom Left", "Move to Bottom Left")); 0117 } 0118 popup2.setTitle(tr("Move Area To")); 0119 popup.addMenu(&popup2); 0120 popup.addSeparator(); 0121 hidePageAction = popup.addAction(tr("Hide This Tab")); 0122 hideAreaAction = popup.addAction(tr("Hide Area")); 0123 0124 if (_tabView->visibleTabs() <2) { 0125 hidePageAction->setEnabled(false); 0126 hideAreaAction->setEnabled(false); 0127 } else if (_tabView->visibleAreas() <2) 0128 hideAreaAction->setEnabled(false); 0129 } 0130 0131 showOnTopAction = popup3.addAction(tr("Top", "Show on Top")); 0132 showOnRightAction = popup3.addAction(tr("Right", "Show on Right")); 0133 showOnBottomAction = popup3.addAction(tr("Bottom", "Show on Bottom")); 0134 showOnLeftAction = popup3.addAction(tr("Bottom Left", "Show on Bottom Left")); 0135 popup3.setTitle(tr("Show Hidden On")); 0136 popup.addMenu(&popup3); 0137 0138 QAction* a = popup.exec(pos); 0139 if (a == hidePageAction) 0140 _tabView->moveTab(page, TraceItemView::Hidden, false); 0141 else if (a == hideAreaAction) 0142 _tabView->moveTab(page, TraceItemView::Hidden, true); 0143 0144 else if (a == pageToTopAction) 0145 _tabView->moveTab(page, TraceItemView::Top, false); 0146 else if (a == pageToRightAction) 0147 _tabView->moveTab(page, TraceItemView::Right, false); 0148 else if (a == pageToBottomAction) 0149 _tabView->moveTab(page, TraceItemView::Bottom, false); 0150 else if (a == pageToLeftAction) 0151 _tabView->moveTab(page, TraceItemView::Left, false); 0152 0153 else if (a == areaToTopAction) 0154 _tabView->moveTab(page, TraceItemView::Top, true); 0155 else if (a == areaToRightAction) 0156 _tabView->moveTab(page, TraceItemView::Right, true); 0157 else if (a == areaToBottomAction) 0158 _tabView->moveTab(page, TraceItemView::Bottom, true); 0159 else if (a == areaToLeftAction) 0160 _tabView->moveTab(page, TraceItemView::Left, true); 0161 0162 else if (a == showOnTopAction) 0163 _tabView->moveTab(nullptr, TraceItemView::Top, true); 0164 else if (a == showOnRightAction) 0165 _tabView->moveTab(nullptr, TraceItemView::Right, true); 0166 else if (a == showOnBottomAction) 0167 _tabView->moveTab(nullptr, TraceItemView::Bottom, true); 0168 else if (a == showOnLeftAction) 0169 _tabView->moveTab(nullptr, TraceItemView::Left, true); 0170 } 0171 0172 0173 // 0174 // Splitter 0175 // 0176 0177 Splitter::Splitter(Qt::Orientation o, QWidget* parent) 0178 : QSplitter(o, parent) 0179 {} 0180 0181 void Splitter::moveEvent(QMoveEvent* e) 0182 { 0183 QSplitter::moveEvent(e); 0184 0185 if (0) qDebug("Splitter %s: Move", qPrintable(objectName())); 0186 checkVisiblity(); 0187 } 0188 0189 void Splitter::checkVisiblity() 0190 { 0191 #if 0 0192 const QObjectList l = children(); 0193 QObjectList::Iterator it( l ); 0194 QObject *obj; 0195 while ( (obj = it.current()) != 0 ) { 0196 ++it; 0197 if (obj->isA("Splitter")) ((Splitter*)obj)->checkVisiblity(); 0198 else if (obj->isA("TabWidget")) ((TabWidget*)obj)->checkVisibility(); 0199 } 0200 #endif 0201 } 0202 0203 0204 0205 0206 // 0207 // TabWidget 0208 // 0209 0210 TabWidget::TabWidget(TabView* v, QWidget* parent) 0211 : QTabWidget(parent) 0212 { 0213 _hasVisibleRect = false; 0214 setTabBar(new TabBar(v, this)); 0215 } 0216 0217 void TabWidget::checkVisibility() 0218 { 0219 bool hasVisibleRect = (visibleRegion().boundingRect().width()>1) && 0220 (visibleRegion().boundingRect().height()>1); 0221 0222 if (0) qDebug("TabWidget %s: VR (%dx%d) HasVisibleRect: %s => %s", 0223 qPrintable(objectName()), 0224 visibleRegion().boundingRect().width(), 0225 visibleRegion().boundingRect().height(), 0226 _hasVisibleRect ? "Yes":"No", 0227 hasVisibleRect ? "Yes":"No"); 0228 0229 if (hasVisibleRect != _hasVisibleRect) { 0230 _hasVisibleRect = hasVisibleRect; 0231 emit visibleRectChanged(this); 0232 } 0233 } 0234 0235 void TabWidget::resizeEvent(QResizeEvent *e) 0236 { 0237 QTabWidget::resizeEvent(e); 0238 if (0) qDebug("TabWidget %s:\n Resize from (%d/%d) to (%d/%d)", 0239 objectName().toLatin1().constData(), 0240 e->oldSize().width(), e->oldSize().height(), 0241 e->size().width(), e->size().height()); 0242 checkVisibility(); 0243 } 0244 0245 void TabWidget::showEvent(QShowEvent* e) 0246 { 0247 QTabWidget::showEvent(e); 0248 0249 if (0) qDebug("TabWidget %s: Show", objectName().toLatin1().constData()); 0250 checkVisibility(); 0251 } 0252 0253 void TabWidget::hideEvent(QHideEvent* e) 0254 { 0255 QTabWidget::hideEvent(e); 0256 0257 if (0) qDebug("TabWidget %s: Hide", objectName().toLatin1().constData()); 0258 checkVisibility(); 0259 } 0260 0261 void TabWidget::moveEvent(QMoveEvent* e) 0262 { 0263 QTabWidget::moveEvent(e); 0264 0265 if (0) qDebug("TabWidget %s: Move", objectName().toLatin1().constData()); 0266 checkVisibility(); 0267 } 0268 0269 0270 0271 // 0272 // TabView 0273 // 0274 0275 /* 0276 * Areas for child views 0277 * 0278 * leftSplitter 0279 * | 0280 * | ----- ----- 0281 * | _/ \_______________/ \____ 0282 * | | Top | Right | 0283 * | | | | 0284 * -> |---------------------| | 0285 * | BottomLeft | Bottom | | 0286 * | | | | 0287 * -\_____/------\____/-------------- 0288 * 0289 * ^ ^ 0290 * bottomSplitter mainSplitter 0291 */ 0292 0293 TabView::TabView(TraceItemView* parentView, QWidget* parent) 0294 : QWidget(parent), TraceItemView(parentView) 0295 { 0296 setFocusPolicy(Qt::StrongFocus); 0297 0298 _isCollapsed = true; 0299 0300 QVBoxLayout* vbox = new QVBoxLayout( this ); 0301 vbox->setSpacing( 6 ); 0302 vbox->setContentsMargins( 6 , 6 , 6 , 6 ); 0303 0304 _nameLabel = new QLabel(this); //KSqueezedTextLabel( this); 0305 _nameLabel->setSizePolicy(QSizePolicy( QSizePolicy::Ignored, 0306 QSizePolicy::Fixed )); 0307 _nameLabel->setObjectName( QStringLiteral("nameLabel") ); 0308 _nameLabel->setText(tr("(No profile data file loaded)")); 0309 vbox->addWidget( _nameLabel ); 0310 updateNameLabel(tr("(No profile data file loaded)")); 0311 0312 _mainSplitter = new QSplitter(Qt::Horizontal, this); 0313 _leftSplitter = new Splitter(Qt::Vertical, _mainSplitter); 0314 _leftSplitter->setObjectName(QStringLiteral("Left")); 0315 vbox->addWidget( _mainSplitter ); 0316 0317 _rightTW = new TabWidget(this, _mainSplitter); 0318 _rightTW->setObjectName(QStringLiteral("Right")); 0319 connect(_rightTW, &QTabWidget::currentChanged, 0320 this, &TabView::tabChanged); 0321 connect(_rightTW, &TabWidget::visibleRectChanged, 0322 this, &TabView::visibleRectChangedSlot); 0323 0324 _topTW = new TabWidget(this, _leftSplitter); 0325 _topTW->setObjectName(QStringLiteral("Top")); 0326 connect(_topTW, &QTabWidget::currentChanged, 0327 this, &TabView::tabChanged); 0328 connect(_topTW, &TabWidget::visibleRectChanged, 0329 this, &TabView::visibleRectChangedSlot); 0330 0331 _bottomSplitter = new Splitter(Qt::Horizontal, _leftSplitter); 0332 _bottomSplitter->setObjectName(QStringLiteral("Bottom")); 0333 0334 _leftTW = new TabWidget(this, _bottomSplitter); 0335 _leftTW->setObjectName(QStringLiteral("Left")); 0336 _leftTW->setTabPosition(QTabWidget::South); 0337 connect(_leftTW, &QTabWidget::currentChanged, 0338 this, &TabView::tabChanged); 0339 connect(_leftTW, &TabWidget::visibleRectChanged, 0340 this, &TabView::visibleRectChangedSlot); 0341 0342 _bottomTW = new TabWidget(this, _bottomSplitter); 0343 _bottomTW->setObjectName(QStringLiteral("Bottom")); 0344 _bottomTW->setTabPosition(QTabWidget::South); 0345 connect(_bottomTW, &QTabWidget::currentChanged, 0346 this, &TabView::tabChanged); 0347 connect(_bottomTW, &TabWidget::visibleRectChanged, 0348 this, &TabView::visibleRectChangedSlot); 0349 0350 CallView* callerView = new CallView(true, this); 0351 CallView* calleeView = new CallView(false, this); 0352 CoverageView * allCallerView = new CoverageView(true, this); 0353 CoverageView * allCalleeView = new CoverageView(false, this); 0354 SourceView* sourceView = new SourceView(this); 0355 InstrView* instrView = new InstrView(this); 0356 PartView* partView = new PartView(this); 0357 0358 // Options of visualization views are stored by their view name 0359 callerView->setObjectName(QStringLiteral("CallerView")); 0360 calleeView->setObjectName(QStringLiteral("CalleeView")); 0361 allCallerView->setObjectName(QStringLiteral("AllCallerView")); 0362 allCalleeView->setObjectName(QStringLiteral("AllCalleeView")); 0363 sourceView->setObjectName(QStringLiteral("SourceView")); 0364 instrView->setObjectName(QStringLiteral("InstrView")); 0365 partView->setObjectName(QStringLiteral("PartView")); 0366 0367 // default positions... 0368 // Keep following order in sync with DEFAULT_xxxTABS defines! 0369 0370 addTop( addTab( tr("Types"), 0371 new EventTypeView(this, nullptr, 0372 "EventTypeView"))); 0373 addTop( addTab( tr("Callers"), callerView) ); 0374 addTop( addTab( tr("All Callers"), allCallerView) ); 0375 addTop( addTab( tr("Callee Map"), 0376 new CallMapView(false, this, nullptr, 0377 "CalleeMapView"))); 0378 addTop( addTab( tr("Source Code"), sourceView) ); 0379 0380 addBottom( addTab( tr("Parts"), partView ) ); 0381 addBottom( addTab( tr("Callees"), calleeView) ); 0382 addBottom( addTab( tr("Call Graph"), 0383 new CallGraphView(this, nullptr, 0384 "CallGraphView"))); 0385 addBottom( addTab( tr("All Callees"), allCalleeView) ); 0386 addBottom( addTab( tr("Caller Map"), 0387 new CallMapView(true, this, nullptr, 0388 "CallerMapView"))); 0389 addBottom( addTab( tr("Machine Code"), instrView) ); 0390 0391 // after all child widgets are created... 0392 _lastFocus = nullptr; 0393 _active = false; 0394 installFocusFilters(); 0395 0396 updateVisibility(); 0397 0398 this->setWhatsThis( whatsThis() ); 0399 } 0400 0401 void TabView::updateNameLabel(const QString& n) 0402 { 0403 QFontMetrics fm(_nameLabel->fontMetrics()); 0404 0405 if (!n.isNull()) { 0406 _nameLabelText = n; 0407 _textWidth = fm.boundingRect(_nameLabelText).width(); 0408 } 0409 0410 int labelWidth = _nameLabel->size().width(); 0411 if (_textWidth > labelWidth) { 0412 _nameLabel->setText(fm.elidedText(_nameLabelText, 0413 Qt::ElideMiddle, labelWidth)); 0414 _nameLabel->setToolTip(_nameLabelText); 0415 } 0416 else { 0417 _nameLabel->setText(_nameLabelText); 0418 _nameLabel->setToolTip(QString()); 0419 } 0420 if (!_nameLabelTooltip.isEmpty()) 0421 _nameLabel->setToolTip(_nameLabelTooltip); 0422 } 0423 0424 void TabView::setData(TraceData* d) 0425 { 0426 TraceItemView::setData(d); 0427 0428 foreach(TraceItemView* v, _tabs) 0429 v->setData(d); 0430 } 0431 0432 TraceItemView* TabView::addTab(const QString& label, TraceItemView* view) 0433 { 0434 view->setTitle(label); 0435 _tabs.append(view); 0436 return view; 0437 } 0438 0439 void TabView::addTop(TraceItemView* view) 0440 { 0441 view->setPosition(TraceItemView::Top); 0442 _topTW->addTab(view->widget(), view->title()); 0443 } 0444 0445 void TabView::addBottom(TraceItemView* view) 0446 { 0447 view->setPosition(TraceItemView::Bottom); 0448 _bottomTW->addTab(view->widget(), view->title()); 0449 } 0450 0451 TraceItemView::Position TabView::tabPosition(QWidget* w) 0452 { 0453 foreach(TraceItemView* v, _tabs) 0454 if (v->widget() == w) return v->position(); 0455 0456 return Hidden; 0457 } 0458 0459 int TabView::visibleTabs() 0460 { 0461 int c = 0; 0462 foreach(TraceItemView* v, _tabs) { 0463 if (v->position() == Hidden) continue; 0464 c++; 0465 } 0466 return c; 0467 } 0468 0469 // calculate count of tabs in areas 0470 void TabView::tabCounts(int& top, int& bottom, 0471 int& left, int& right) 0472 { 0473 top = bottom = left = right = 0; 0474 0475 foreach(TraceItemView* v, _tabs) { 0476 switch(v->position()) { 0477 case TraceItemView::Top: 0478 top++; 0479 break; 0480 case TraceItemView::Bottom: 0481 bottom++; 0482 break; 0483 case TraceItemView::Left: 0484 left++; 0485 break; 0486 case TraceItemView::Right: 0487 right++; 0488 break; 0489 default: 0490 break; 0491 } 0492 } 0493 0494 if (0) qDebug("TabView::tabCounts top %d, bottom %d, left %d, right %d", 0495 top, bottom, left, right); 0496 } 0497 0498 int TabView::visibleAreas() 0499 { 0500 int count, top, bottom, left, right; 0501 0502 tabCounts(top, bottom, left, right); 0503 count = 0; 0504 if (top>0) count++; 0505 if (bottom>0) count++; 0506 if (left>0) count++; 0507 if (right>0) count++; 0508 0509 return count; 0510 } 0511 0512 // This hides/shows splitters and tabwidgets according to tab children 0513 void TabView::updateVisibility() 0514 { 0515 int top, bottom, left, right; 0516 0517 tabCounts(top, bottom, left, right); 0518 0519 QList<int> s; 0520 s.append(100); 0521 0522 // children of mainSplitter 0523 if (_rightTW->isHidden() != (right == 0)) { 0524 if (right == 0) { 0525 _rightTW->hide(); 0526 } 0527 else 0528 _rightTW->show(); 0529 } 0530 if (_leftSplitter->isHidden() != (top+bottom+left == 0)) { 0531 if (top+bottom+left == 0) { 0532 _leftSplitter->hide(); 0533 } 0534 else 0535 _leftSplitter->show(); 0536 } 0537 0538 // children of leftSplitter 0539 if (_topTW->isHidden() != (top == 0)) { 0540 if (top == 0) { 0541 _topTW->hide(); 0542 } 0543 else 0544 _topTW->show(); 0545 } 0546 0547 if (_bottomSplitter->isHidden() != (bottom+left == 0)) { 0548 if (bottom+left == 0) { 0549 _bottomSplitter->hide(); 0550 } 0551 else 0552 _bottomSplitter->show(); 0553 } 0554 0555 // children of bottomSplitter 0556 if (_bottomTW->isHidden() != (bottom == 0)) { 0557 if (bottom == 0) { 0558 _bottomTW->hide(); 0559 } 0560 else 0561 _bottomTW->show(); 0562 } 0563 if (_leftTW->isHidden() != (left == 0)) { 0564 if (left == 0) { 0565 _leftTW->hide(); 0566 } 0567 else 0568 _leftTW->show(); 0569 } 0570 } 0571 0572 TabWidget* TabView::tabWidget(Position p) 0573 { 0574 switch(p) { 0575 case TraceItemView::Top: 0576 return _topTW; 0577 case TraceItemView::Bottom: 0578 return _bottomTW; 0579 case TraceItemView::Left: 0580 return _leftTW; 0581 case TraceItemView::Right: 0582 return _rightTW; 0583 default: 0584 break; 0585 } 0586 return nullptr; 0587 } 0588 0589 void TabView::moveTab(QWidget* w, Position p, bool wholeArea) 0590 { 0591 Position origPos = Hidden; 0592 if (w) { 0593 TraceItemView* found = nullptr; 0594 foreach(TraceItemView* v, _tabs) 0595 if (v->widget() == w) { found = v; break; } 0596 0597 if (!found) return; 0598 origPos = found->position(); 0599 } 0600 if (origPos == p) return; 0601 0602 TabWidget *from, *to; 0603 from = tabWidget(origPos); 0604 to = tabWidget(p); 0605 0606 QList<TraceItemView*> tabs; 0607 foreach(TraceItemView* v, _tabs) 0608 if ((v->position() == origPos) && 0609 (wholeArea || (v->widget() == w))) tabs.append(v); 0610 0611 bool isEnabled; 0612 foreach(TraceItemView* v, tabs) { 0613 v->setPosition(p); 0614 w = v->widget(); 0615 0616 if (from) { 0617 isEnabled = from->isTabEnabled(from->indexOf(w)); 0618 from->removeTab(from->indexOf(w)); 0619 } 0620 else isEnabled = (v->canShow(_activeItem)!=nullptr); 0621 0622 if (to) { 0623 int idx = -1, i; 0624 foreach(TraceItemView* vv, _tabs) { 0625 if (v == vv) continue; 0626 i = to->indexOf(vv->widget()); 0627 if (i>=0) idx = i; 0628 } 0629 to->insertTab(idx+1, w, v->title()); 0630 to->setTabEnabled(to->indexOf(w), isEnabled); 0631 if (isEnabled) { 0632 to->setCurrentIndex(to->indexOf(w)); 0633 v->updateView(); 0634 } 0635 } 0636 } 0637 updateVisibility(); 0638 } 0639 0640 0641 QString TabView::whatsThis() const 0642 { 0643 return tr( "<b>Information Tabs</b>" 0644 "<p>This widget shows information for the " 0645 "currently selected function in different tabs: " 0646 "<ul>" 0647 "<li>The Costs tab shows a list of available event types " 0648 "and the inclusive and self-costs related to these types.</li>" 0649 "<li>The Parts tab shows a list of trace parts " 0650 "if the trace consists of more than one part (otherwise, " 0651 "this tab is hidden). " 0652 "The cost of the selected function spent in the different " 0653 "parts together with the calls happening is shown.</li>" 0654 "<li>The Call Lists tab shows direct callers and " 0655 "callees of the function in more detail.</li>" 0656 "<li>The Coverage tab shows the same as the Call " 0657 "Lists tab, but also shows indirect callers and callees, " 0658 "not just direct ones.</li>" 0659 "<li>The Call Graph tab shows a graphical " 0660 "visualization of the calls made by this function.</li>" 0661 "<li>The Source Code tab presents annotated source code " 0662 "if debugging information and the source file " 0663 "are available.</li>" 0664 "<li>The Machine Code tab presents annotated assembly " 0665 "instructions if profile information at instruction level " 0666 "is available.</li></ul>" 0667 "For more information, see the <em>What's This?</em> " 0668 "help of the corresponding tab widget.</p>"); 0669 } 0670 0671 void TabView::installFocusFilters() 0672 { 0673 QList<QWidget*> wList = findChildren<QWidget*>(); 0674 foreach(QWidget* w, wList) { 0675 if (w->focusPolicy() != Qt::NoFocus) 0676 w->installEventFilter(this); 0677 } 0678 } 0679 0680 0681 bool TabView::eventFilter(QObject* o, QEvent* e) 0682 { 0683 if (e->type() == QEvent::FocusIn) { 0684 _lastFocus = o->isWidgetType() ? (QWidget*) o : nullptr; 0685 setActive(_lastFocus != nullptr); 0686 } 0687 return QWidget::eventFilter(o,e); 0688 } 0689 0690 void TabView::mousePressEvent(QMouseEvent*) 0691 { 0692 if (_lastFocus) 0693 _lastFocus->setFocus(); 0694 setActive(true); 0695 } 0696 0697 void TabView::setActive(bool a) 0698 { 0699 if (a == _active) return; 0700 _active = a; 0701 0702 QFont nameLabel_font( _nameLabel->font() ); 0703 nameLabel_font.setBold(a); 0704 _nameLabel->setFont( nameLabel_font ); 0705 // force recalculation of label width by passing current label text 0706 updateNameLabel(_nameLabelText); 0707 0708 if (0) qDebug("%s::setActive(%s)", objectName().toLatin1().constData(), 0709 a ? "true":"false"); 0710 0711 if (a) emit tabActivated(this); 0712 } 0713 0714 void TabView::doUpdate(int changeType, bool force) 0715 { 0716 if (changeType & (activeItemChanged | 0717 configChanged | 0718 dataChanged)) 0719 { 0720 if (_data && _activeItem) { 0721 _nameLabelTooltip = _activeItem->formattedName(); 0722 updateNameLabel(_activeItem->prettyName()); 0723 } 0724 else { 0725 _nameLabelTooltip = QString(); 0726 updateNameLabel( !_data ? 0727 tr("(No profile data file loaded)") : 0728 tr("(No function selected)")); 0729 } 0730 } 0731 0732 bool canShow; 0733 foreach(TraceItemView *v, _tabs) { 0734 0735 TabWidget *tw = nullptr; 0736 switch(v->position()) { 0737 case TraceItemView::Top: tw = _topTW; break; 0738 case TraceItemView::Bottom: tw = _bottomTW; break; 0739 case TraceItemView::Left: tw = _leftTW; break; 0740 case TraceItemView::Right: tw = _rightTW; break; 0741 default: break; 0742 } 0743 0744 // update even if hidden 0745 if (tw) { 0746 if (!tw->hasVisibleRect()) continue; 0747 } 0748 canShow = v->set(changeType, _data, _eventType, _eventType2, 0749 _groupType, _partList, 0750 _activeItem, _selectedItem); 0751 v->notifyChange(changeType); 0752 0753 if (!tw) continue; 0754 int idx = tw->indexOf(v->widget()); 0755 if (tw->isTabEnabled(idx) != canShow) 0756 tw->setTabEnabled(idx, canShow); 0757 0758 if (v->widget() == tw->currentWidget()) 0759 v->updateView(force); 0760 } 0761 } 0762 0763 0764 void TabView::tabChanged(int i) 0765 { 0766 TabWidget* tw = qobject_cast<TabWidget*>(sender()); 0767 if (!tw) return; 0768 QWidget* w = tw->widget(i); 0769 0770 foreach(TraceItemView *v, _tabs) 0771 if (v->widget() == w) v->updateView(); 0772 } 0773 0774 void TabView::visibleRectChangedSlot(TabWidget* tw) 0775 { 0776 if (0) qDebug("%s: %svisible !", 0777 tw->objectName().toLatin1().constData(), 0778 tw->hasVisibleRect() ? "":"un"); 0779 0780 if (tw->hasVisibleRect()) doUpdate(0, false); 0781 } 0782 0783 void TabView::resizeEvent(QResizeEvent* e) 0784 { 0785 QWidget::resizeEvent(e); 0786 0787 updateNameLabel(); 0788 0789 bool collapsed = (e->size().width()<=1) || (e->size().height()<=1); 0790 if (_isCollapsed != collapsed) { 0791 _isCollapsed = collapsed; 0792 updateView(); 0793 } 0794 0795 if (0) qDebug("TabView::Resize from (%d/%d) to (%d/%d)", 0796 e->oldSize().width(), e->oldSize().height(), 0797 e->size().width(), e->size().height()); 0798 } 0799 0800 void TabView::selected(TraceItemView*, CostItem* s) 0801 { 0802 // we set selected item for our own children 0803 select(s); 0804 0805 // still forward to parent 0806 if (_parentView) _parentView->selected(this, s); 0807 } 0808 0809 void TabView::restoreLayout(const QString& prefix, const QString& postfix) 0810 { 0811 ConfigGroup* g = ConfigStorage::group(prefix, postfix); 0812 0813 int rightSize = g->value(QStringLiteral("RightSize"), DEFAULT_RIGHTSIZE).toInt(); 0814 int topSize = g->value(QStringLiteral("TopSize"), DEFAULT_TOPSIZE).toInt(); 0815 int leftSize = g->value(QStringLiteral("LeftSize"), DEFAULT_LEFTSIZE).toInt(); 0816 0817 QList<int> mainSizes, leftSizes, bottomSizes; 0818 0819 int mainWidth = _mainSplitter->width(); 0820 mainSizes << (100 - rightSize)*mainWidth/100 << rightSize*mainWidth/100; 0821 _mainSplitter->setSizes(mainSizes); 0822 0823 int leftHeight = _leftSplitter->height(); 0824 leftSizes << topSize*leftHeight/100 << (100 - topSize)*leftHeight/100; 0825 _leftSplitter->setSizes(leftSizes); 0826 0827 int bottomWidth = _bottomSplitter->width(); 0828 bottomSizes << leftSize*bottomWidth/100 << (100 - leftSize)*bottomWidth/100; 0829 _bottomSplitter->setSizes(bottomSizes); 0830 0831 QString activeT = g->value(QStringLiteral("ActiveTop"), QStringLiteral(DEFAULT_ACTIVETOP)).toString(); 0832 QString activeB = g->value(QStringLiteral("ActiveBottom"), QStringLiteral(DEFAULT_ACTIVEBOTTOM)).toString(); 0833 QString activeL = g->value(QStringLiteral("ActiveLeft"), QString()).toString(); 0834 QString activeR = g->value(QStringLiteral("ActiveRight"), QString()).toString(); 0835 0836 QStringList topTabsDefault, bottomTabsDefault; 0837 topTabsDefault << DEFAULT_TOPTABS; 0838 bottomTabsDefault << DEFAULT_BOTTOMTABS; 0839 0840 QStringList topTabs = g->value(QStringLiteral("TopTabs"),topTabsDefault).toStringList(); 0841 QStringList bottomTabs = g->value(QStringLiteral("BottomTabs"),bottomTabsDefault).toStringList(); 0842 QStringList leftTabs = g->value(QStringLiteral("LeftTabs"),QStringList()).toStringList(); 0843 QStringList rightTabs = g->value(QStringLiteral("RightTabs"),QStringList()).toStringList(); 0844 0845 delete g; 0846 0847 if (topTabs.isEmpty() && bottomTabs.isEmpty() && 0848 rightTabs.isEmpty() && leftTabs.isEmpty()) { 0849 // no tabs visible ?! Reset to default 0850 topTabs = topTabsDefault; 0851 bottomTabs = bottomTabsDefault; 0852 } 0853 0854 TraceItemView *activeTop = nullptr, *activeBottom = nullptr; 0855 TraceItemView *activeLeft = nullptr, *activeRight = nullptr; 0856 0857 moveTab(nullptr, TraceItemView::Top, true); 0858 foreach(TraceItemView *v, _tabs) { 0859 QString n = v->widget()->objectName(); 0860 if (topTabs.contains(n)) { 0861 moveTab(v->widget(), TraceItemView::Top); 0862 if (n == activeT) activeTop = v; 0863 } 0864 else if (bottomTabs.contains(n)) { 0865 moveTab(v->widget(), TraceItemView::Bottom); 0866 if (n == activeB) activeBottom = v; 0867 } 0868 else if (leftTabs.contains(n)) { 0869 moveTab(v->widget(), TraceItemView::Left); 0870 if (n == activeL) activeLeft = v; 0871 } 0872 else if (rightTabs.contains(n)) { 0873 moveTab(v->widget(), TraceItemView::Right); 0874 if (n == activeR) activeRight = v; 0875 } 0876 else moveTab(v->widget(), Hidden); 0877 } 0878 if (activeTop) 0879 _topTW->setCurrentIndex(_topTW->indexOf(activeTop->widget())); 0880 if (activeBottom) 0881 _bottomTW->setCurrentIndex(_bottomTW->indexOf(activeBottom->widget())); 0882 if (activeLeft) 0883 _leftTW->setCurrentIndex(_leftTW->indexOf(activeLeft->widget())); 0884 if (activeRight) 0885 _rightTW->setCurrentIndex(_rightTW->indexOf(activeRight->widget())); 0886 0887 if (!_data) return; 0888 0889 updateView(); 0890 } 0891 0892 void TabView::saveLayout(const QString& prefix, const QString& postfix) 0893 { 0894 ConfigGroup* g = ConfigStorage::group(prefix + postfix); 0895 0896 // convert splitter sizes into percentage numbers 0897 QList<int> s; 0898 s = _mainSplitter->sizes(); 0899 int rightSize = (s[0]+s[1]==0) ? 0 : (100 * s[1]/(s[0]+s[1])); 0900 s = _leftSplitter->sizes(); 0901 int topSize = (s[0]+s[1]==0) ? 0 : (100 * s[0]/(s[0]+s[1])); 0902 s = _bottomSplitter->sizes(); 0903 int leftSize = (s[0]+s[1]==0) ? 0 : (100 * s[0]/(s[0]+s[1])); 0904 0905 g->setValue(QStringLiteral("RightSize"), rightSize, DEFAULT_RIGHTSIZE); 0906 g->setValue(QStringLiteral("TopSize"), topSize, DEFAULT_TOPSIZE); 0907 g->setValue(QStringLiteral("LeftSize"), leftSize, DEFAULT_LEFTSIZE); 0908 0909 QString a; 0910 QWidget* w; 0911 w = _topTW->currentWidget(); 0912 if ((_topTW->count()>0) && 0913 (_topTW->isTabEnabled(_topTW->indexOf(w)))) 0914 a = w->objectName(); 0915 g->setValue(QStringLiteral("ActiveTop"), a, QStringLiteral(DEFAULT_ACTIVETOP)); 0916 0917 a = QString(); 0918 w = _bottomTW->currentWidget(); 0919 if ((_bottomTW->count()>0) && 0920 (_bottomTW->isTabEnabled(_bottomTW->indexOf(w)))) 0921 a = w->objectName(); 0922 g->setValue(QStringLiteral("ActiveBottom"), a, QStringLiteral(DEFAULT_ACTIVEBOTTOM)); 0923 0924 a = QString(); 0925 w = _leftTW->currentWidget(); 0926 if ((_leftTW->count()>0) && 0927 (_leftTW->isTabEnabled(_leftTW->indexOf(w)))) 0928 a = w->objectName(); 0929 g->setValue(QStringLiteral("ActiveLeft"), a, QString()); 0930 0931 a= QString(); 0932 w = _rightTW->currentWidget(); 0933 if ((_rightTW->count()>0) && 0934 (_rightTW->isTabEnabled(_rightTW->indexOf(w)))) 0935 a = w->objectName(); 0936 g->setValue(QStringLiteral("ActiveRight"), a, QString()); 0937 0938 QStringList topList, bottomList, leftList, rightList; 0939 foreach(TraceItemView *v, _tabs) { 0940 switch(v->position()) { 0941 case TraceItemView::Top: 0942 topList << v->widget()->objectName(); 0943 break; 0944 0945 case TraceItemView::Bottom: 0946 bottomList << v->widget()->objectName(); 0947 break; 0948 0949 case TraceItemView::Left: 0950 leftList << v->widget()->objectName(); 0951 break; 0952 0953 case TraceItemView::Right: 0954 rightList << v->widget()->objectName(); 0955 break; 0956 0957 default: break; 0958 } 0959 } 0960 0961 QStringList topTabsDefault, bottomTabsDefault; 0962 topTabsDefault << DEFAULT_TOPTABS; 0963 bottomTabsDefault << DEFAULT_BOTTOMTABS; 0964 0965 g->setValue(QStringLiteral("TopTabs"), topList, topTabsDefault); 0966 g->setValue(QStringLiteral("BottomTabs"), bottomList, bottomTabsDefault); 0967 g->setValue(QStringLiteral("LeftTabs"), leftList, QStringList()); 0968 g->setValue(QStringLiteral("RightTabs"), rightList, QStringList()); 0969 0970 delete g; 0971 } 0972 0973 void TabView::restoreOptions(const QString& prefix, const QString& postfix) 0974 { 0975 foreach(TraceItemView *v, _tabs) 0976 v->restoreOptions(QStringLiteral("%1-%2").arg(prefix).arg(v->widget()->objectName()), 0977 postfix); 0978 0979 if (!_data) return; 0980 0981 ConfigGroup* g = ConfigStorage::group(prefix, postfix); 0982 0983 QString activeType = g->value(QStringLiteral("ActiveItemType"), QString()).toString(); 0984 QString activeName = g->value(QStringLiteral("ActiveItemName"), QString()).toString(); 0985 QString selectedType = g->value(QStringLiteral("SelectedItemType"), QString()).toString(); 0986 QString selectedName = g->value(QStringLiteral("SelectedItemName"), QString()).toString(); 0987 0988 delete g; 0989 0990 // restore active item 0991 ProfileContext::Type t = ProfileContext::type(activeType); 0992 if (t==ProfileContext::InvalidType) t = ProfileContext::Function; 0993 ProfileCostArray* activeItem = _data->search(t, activeName, _eventType); 0994 if (!activeItem) return; 0995 activated(activeItem); 0996 0997 // restore selected item 0998 t = ProfileContext::type(selectedType); 0999 if (t==ProfileContext::InvalidType) t = ProfileContext::Function; 1000 ProfileCostArray* selectedItem; 1001 selectedItem = _data->search(t, selectedName, _eventType, activeItem); 1002 if (selectedItem) 1003 selected(this, selectedItem); 1004 } 1005 1006 void TabView::saveOptions(const QString& prefix, const QString& postfix) 1007 { 1008 if (_activeItem) { 1009 ConfigGroup* g = ConfigStorage::group(prefix + postfix); 1010 1011 g->setValue(QStringLiteral("ActiveItemType"), 1012 ProfileContext::typeName(_activeItem->type())); 1013 g->setValue(QStringLiteral("ActiveItemName"), _activeItem->name()); 1014 1015 if (_selectedItem) { 1016 g->setValue(QStringLiteral("SelectedItemType"), 1017 ProfileContext::typeName(_selectedItem->type())); 1018 g->setValue(QStringLiteral("SelectedItemName"), _selectedItem->name()); 1019 } 1020 delete g; 1021 } 1022 1023 foreach(TraceItemView *v, _tabs) 1024 v->saveOptions(QStringLiteral("%1-%2").arg(prefix) 1025 .arg(v->widget()->objectName()), postfix); 1026 } 1027 1028 #include "moc_tabview.cpp"