34 #include <QVBoxLayout>
35 #include <QResizeEvent>
36 #include <QMouseEvent>
54 #define DEFAULT_TOPTABS \
55 "EventTypeView" << "CallerView" << "AllCallerView" \
56 << "CalleeMapView" << "SourceView"
57 #define DEFAULT_BOTTOMTABS \
58 "PartView" << "CalleeView" << "CallGraphView" \
59 << "AllCalleeView" << "CallerMapView" << "InstrView"
61 #define DEFAULT_ACTIVETOP "CallerView"
62 #define DEFAULT_ACTIVEBOTTOM "CalleeView"
64 #define DEFAULT_RIGHTSIZE 0
65 #define DEFAULT_TOPSIZE 50
66 #define DEFAULT_LEFTSIZE 0
80 if (e->button() == Qt::RightButton) {
81 int idx = tabAt(e->pos());
85 page = _tabWidget->widget(idx);
87 context(page, e->globalPos());
89 QTabBar::mousePressEvent(e );
92 void TabBar::context(
QWidget* page,
const QPoint & pos)
94 QMenu popup, popup2, popup3;
96 QAction* pageToTopAction = 0;
97 QAction* areaToTopAction = 0;
98 QAction* showOnTopAction = 0;
99 QAction* pageToRightAction = 0;
100 QAction* areaToRightAction = 0;
101 QAction* showOnRightAction = 0;
102 QAction* pageToBottomAction = 0;
103 QAction* areaToBottomAction = 0;
104 QAction* showOnBottomAction = 0;
105 QAction* pageToLeftAction = 0;
106 QAction* areaToLeftAction = 0;
107 QAction* showOnLeftAction = 0;
108 QAction* hidePageAction = 0;
109 QAction* hideAreaAction = 0;
114 pageToTopAction = popup.addAction(tr(
"Move to Top"));
115 areaToTopAction = popup2.addAction(tr(
"Top",
"Move to Top"));
118 pageToRightAction = popup.addAction(tr(
"Move to Right"));
119 areaToRightAction = popup2.addAction(tr(
"Right",
"Move to Right"));
122 pageToBottomAction = popup.addAction(tr(
"Move to Bottom"));
123 areaToBottomAction = popup2.addAction(tr(
"Bottom",
"Move to Bottom"));
126 pageToLeftAction = popup.addAction(tr(
"Move to Bottom Left"));
127 areaToLeftAction = popup2.addAction(tr(
"Bottom Left",
"Move to Bottom Left"));
129 popup2.setTitle(tr(
"Move Area To"));
130 popup.addMenu(&popup2);
131 popup.addSeparator();
132 hidePageAction = popup.addAction(tr(
"Hide This Tab"));
133 hideAreaAction = popup.addAction(tr(
"Hide Area"));
136 hidePageAction->setEnabled(
false);
137 hideAreaAction->setEnabled(
false);
139 hideAreaAction->setEnabled(
false);
142 showOnTopAction = popup3.addAction(tr(
"Top",
"Show on Top"));
143 showOnRightAction = popup3.addAction(tr(
"Right",
"Show on Right"));
144 showOnBottomAction = popup3.addAction(tr(
"Bottom",
"Show on Bottom"));
145 showOnLeftAction = popup3.addAction(tr(
"Bottom Left",
"Show on Bottom Left"));
146 popup3.setTitle(tr(
"Show Hidden On"));
147 popup.addMenu(&popup3);
149 QAction* a = popup.exec(pos);
150 if (a == hidePageAction)
152 else if (a == hideAreaAction)
155 else if (a == pageToTopAction)
157 else if (a == pageToRightAction)
159 else if (a == pageToBottomAction)
161 else if (a == pageToLeftAction)
164 else if (a == areaToTopAction)
166 else if (a == areaToRightAction)
168 else if (a == areaToBottomAction)
170 else if (a == areaToLeftAction)
173 else if (a == showOnTopAction)
175 else if (a == showOnRightAction)
177 else if (a == showOnBottomAction)
179 else if (a == showOnLeftAction)
194 QSplitter::moveEvent(e);
196 if (0) qDebug(
"Splitter %s: Move", qPrintable(objectName()));
203 const QObjectList l = children();
204 QObjectList::Iterator it( l );
206 while ( (obj = it.current()) != 0 ) {
209 else if (obj->isA(
"TabWidget")) ((
TabWidget*)obj)->checkVisibility();
224 _hasVisibleRect =
false;
225 setTabBar(
new TabBar(v,
this));
230 bool hasVisibleRect = (visibleRegion().boundingRect().width()>1) &&
231 (visibleRegion().boundingRect().height()>1);
233 if (0) qDebug(
"TabWidget %s: VR (%dx%d) HasVisibleRect: %s => %s",
234 qPrintable(objectName()),
235 visibleRegion().boundingRect().width(),
236 visibleRegion().boundingRect().height(),
237 _hasVisibleRect ?
"Yes":
"No",
238 hasVisibleRect ?
"Yes":
"No");
240 if (hasVisibleRect != _hasVisibleRect) {
248 QTabWidget::resizeEvent(e);
249 if (0) qDebug(
"TabWidget %s:\n Resize from (%d/%d) to (%d/%d)",
250 objectName().toLatin1().constData(),
251 e->oldSize().width(), e->oldSize().height(),
252 e->size().width(), e->size().height());
258 QTabWidget::showEvent(e);
260 if (0) qDebug(
"TabWidget %s: Show", objectName().toLatin1().constData());
266 QTabWidget::hideEvent(e);
268 if (0) qDebug(
"TabWidget %s: Hide", objectName().toLatin1().constData());
274 QTabWidget::moveEvent(e);
276 if (0) qDebug(
"TabWidget %s: Move", objectName().toLatin1().constData());
307 setFocusPolicy(Qt::StrongFocus);
311 QVBoxLayout* vbox =
new QVBoxLayout(
this );
312 vbox->setSpacing( 6 );
313 vbox->setMargin( 6 );
315 _nameLabel =
new QLabel(
this);
316 _nameLabel->setSizePolicy(QSizePolicy( QSizePolicy::Ignored,
317 QSizePolicy::Fixed ));
318 _nameLabel->setObjectName(
"nameLabel" );
319 _nameLabel->setText(tr(
"(No profile data file loaded)"));
320 vbox->addWidget( _nameLabel );
321 updateNameLabel(tr(
"(No profile data file loaded)"));
323 _mainSplitter =
new QSplitter(Qt::Horizontal,
this);
324 _leftSplitter =
new Splitter(Qt::Vertical, _mainSplitter);
325 _leftSplitter->setObjectName(
"Left");
326 vbox->addWidget( _mainSplitter );
328 _rightTW =
new TabWidget(
this, _mainSplitter);
329 _rightTW->setObjectName(
"Right");
330 connect(_rightTW, SIGNAL(currentChanged(
int)),
332 connect(_rightTW, SIGNAL(visibleRectChanged(
TabWidget*)),
335 _topTW =
new TabWidget(
this, _leftSplitter);
336 _topTW->setObjectName(
"Top");
337 connect(_topTW, SIGNAL(currentChanged(
int)),
339 connect(_topTW, SIGNAL(visibleRectChanged(
TabWidget*)),
342 _bottomSplitter =
new Splitter(Qt::Horizontal, _leftSplitter);
343 _bottomSplitter->setObjectName(
"Bottom");
345 _leftTW =
new TabWidget(
this, _bottomSplitter);
346 _leftTW->setObjectName(
"Left");
347 _leftTW->setTabPosition(QTabWidget::South);
348 connect(_leftTW, SIGNAL(currentChanged(
int)),
350 connect(_leftTW, SIGNAL(visibleRectChanged(
TabWidget*)),
353 _bottomTW =
new TabWidget(
this, _bottomSplitter);
354 _bottomTW->setObjectName(
"Bottom");
355 _bottomTW->setTabPosition(QTabWidget::South);
356 connect(_bottomTW, SIGNAL(currentChanged(
int)),
358 connect(_bottomTW, SIGNAL(visibleRectChanged(
TabWidget*)),
370 callerView->setObjectName(
"CallerView");
371 calleeView->setObjectName(
"CalleeView");
372 allCallerView->setObjectName(
"AllCallerView");
373 allCalleeView->setObjectName(
"AllCalleeView");
374 sourceView->setObjectName(
"SourceView");
375 instrView->setObjectName(
"InstrView");
376 partView->setObjectName(
"PartView");
381 addTop( addTab( tr(
"Types"),
384 addTop( addTab( tr(
"Callers"), callerView) );
385 addTop( addTab( tr(
"All Callers"), allCallerView) );
386 addTop( addTab( tr(
"Callee Map"),
389 addTop( addTab( tr(
"Source Code"), sourceView) );
391 addBottom( addTab( tr(
"Parts"), partView ) );
392 addBottom( addTab( tr(
"Callees"), calleeView) );
393 addBottom( addTab( tr(
"Call Graph"),
396 addBottom( addTab( tr(
"All Callees"), allCalleeView) );
397 addBottom( addTab( tr(
"Caller Map"),
400 addBottom( addTab( tr(
"Machine Code"), instrView) );
405 installFocusFilters();
412 void TabView::updateNameLabel(QString n)
414 QFontMetrics fm(_nameLabel->fontMetrics());
418 _textWidth = fm.width(_nameLabelText);
421 int labelWidth = _nameLabel->size().width();
422 if (_textWidth > labelWidth) {
423 _nameLabel->setText(fm.elidedText(_nameLabelText,
424 Qt::ElideMiddle, labelWidth));
425 _nameLabel->setToolTip(_nameLabelText);
428 _nameLabel->setText(_nameLabelText);
429 _nameLabel->setToolTip(QString());
431 if (!_nameLabelTooltip.isEmpty())
432 _nameLabel->setToolTip(_nameLabelTooltip);
481 void TabView::tabCounts(
int& top,
int& bottom,
482 int& left,
int& right)
484 top = bottom = left = right = 0;
505 if (0) qDebug(
"TabView::tabCounts top %d, bottom %d, left %d, right %d",
506 top, bottom, left, right);
511 int count, top, bottom, left, right;
513 tabCounts(top, bottom, left, right);
516 if (bottom>0) count++;
518 if (right>0) count++;
524 void TabView::updateVisibility()
526 int top, bottom, left, right;
528 tabCounts(top, bottom, left, right);
534 if (_rightTW->isHidden() != (right == 0)) {
541 if (_leftSplitter->isHidden() != (top+bottom+left == 0)) {
542 if (top+bottom+left == 0) {
543 _leftSplitter->hide();
546 _leftSplitter->show();
550 if (_topTW->isHidden() != (top == 0)) {
558 if (_bottomSplitter->isHidden() != (bottom+left == 0)) {
559 if (bottom+left == 0) {
560 _bottomSplitter->hide();
563 _bottomSplitter->show();
567 if (_bottomTW->isHidden() != (bottom == 0)) {
574 if (_leftTW->isHidden() != (left == 0)) {
583 TabWidget* TabView::tabWidget(Position p)
606 if (v->
widget() == w) { found = v;
break; }
611 if (origPos == p)
return;
614 from = tabWidget(origPos);
620 (wholeArea || (v->
widget() == w))) tabs.append(v);
628 isEnabled = from->isTabEnabled(from->indexOf(w));
629 from->removeTab(from->indexOf(w));
636 if (v == vv)
continue;
637 i = to->indexOf(vv->
widget());
640 to->insertTab(idx+1, w, v->
title());
641 to->setTabEnabled(to->indexOf(w), isEnabled);
643 to->setCurrentIndex(to->indexOf(w));
654 return tr(
"<b>Information Tabs</b>"
655 "<p>This widget shows information for the "
656 "currently selected function in different tabs: "
658 "<li>The Costs tab shows a list of available event types "
659 "and the inclusive and self-costs related to these types.</li>"
660 "<li>The Parts tab shows a list of trace parts "
661 "if the trace consists of more than one part (otherwise, "
662 "this tab is hidden). "
663 "The cost of the selected function spent in the different "
664 "parts together with the calls happening is shown.</li>"
665 "<li>The Call Lists tab shows direct callers and "
666 "callees of the function in more detail.</li>"
667 "<li>The Coverage tab shows the same as the Call "
668 "Lists tab, but also shows indirect callers and callees, "
669 "not just direct ones.</li>"
670 "<li>The Call Graph tab shows a graphical "
671 "visualization of the calls made by this function.</li>"
672 "<li>The Source Code tab presents annotated source code "
673 "if debugging information and the source file "
674 "are available.</li>"
675 "<li>The Machine Code tab presents annotated assembly "
676 "instructions if profile information at instruction level "
677 "is available.</li></ul>"
678 "For more information, see the <em>What's This?</em> "
679 "help of the corresponding tab widget.</p>");
682 void TabView::installFocusFilters()
686 if (w->focusPolicy() != Qt::NoFocus)
687 w->installEventFilter(
this);
694 if (e->type() == QEvent::FocusIn) {
695 _lastFocus = o->isWidgetType() ? (
QWidget*) o : 0;
698 return QWidget::eventFilter(o,e);
704 _lastFocus->setFocus();
710 if (a == _active)
return;
713 QFont nameLabel_font( _nameLabel->font() );
714 nameLabel_font.setBold(a);
715 _nameLabel->setFont( nameLabel_font );
717 updateNameLabel(_nameLabelText);
719 if (0) qDebug(
"%s::setActive(%s)", objectName().toLatin1().constData(),
725 void TabView::doUpdate(
int changeType,
bool force)
736 _nameLabelTooltip = QString();
737 updateNameLabel( !
_data ?
738 tr(
"(No profile data file loaded)") :
739 tr(
"(No function selected)"));
765 int idx = tw->indexOf(v->
widget());
766 if (tw->isTabEnabled(idx) !=
canShow)
767 tw->setTabEnabled(idx, canShow);
769 if (v->
widget() == tw->currentWidget())
787 if (0) qDebug(
"%s: %svisible !",
788 tw->objectName().toLatin1().constData(),
796 QWidget::resizeEvent(e);
800 bool collapsed = (e->size().width()<=1) || (e->size().height()<=1);
801 if (_isCollapsed != collapsed) {
802 _isCollapsed = collapsed;
806 if (0) qDebug(
"TabView::Resize from (%d/%d) to (%d/%d)",
807 e->oldSize().width(), e->oldSize().height(),
808 e->size().width(), e->size().height());
830 int mainWidth = _mainSplitter->width();
831 mainSizes << (100 - rightSize)*mainWidth/100 << rightSize*mainWidth/100;
832 _mainSplitter->setSizes(mainSizes);
834 int leftHeight = _leftSplitter->height();
835 leftSizes << topSize*leftHeight/100 << (100 - topSize)*leftHeight/100;
836 _leftSplitter->setSizes(leftSizes);
838 int bottomWidth = _bottomSplitter->width();
839 bottomSizes << leftSize*bottomWidth/100 << (100 - leftSize)*bottomWidth/100;
840 _bottomSplitter->setSizes(bottomSizes);
844 QString activeL = g->
value(
"ActiveLeft", QString()).toString();
845 QString activeR = g->
value(
"ActiveRight", QString()).toString();
847 QStringList topTabsDefault, bottomTabsDefault;
851 QStringList topTabs = g->
value(
"TopTabs",topTabsDefault).toStringList();
852 QStringList bottomTabs = g->
value(
"BottomTabs",bottomTabsDefault).toStringList();
853 QStringList leftTabs = g->
value(
"LeftTabs",QStringList()).toStringList();
854 QStringList rightTabs = g->
value(
"RightTabs",QStringList()).toStringList();
858 if (topTabs.isEmpty() && bottomTabs.isEmpty() &&
859 rightTabs.isEmpty() && leftTabs.isEmpty()) {
861 topTabs = topTabsDefault;
862 bottomTabs = bottomTabsDefault;
870 QString n = v->
widget()->objectName();
871 if (topTabs.contains(n)) {
873 if (n == activeT) activeTop = v;
875 else if (bottomTabs.contains(n)) {
877 if (n == activeB) activeBottom = v;
879 else if (leftTabs.contains(n)) {
881 if (n == activeL) activeLeft = v;
883 else if (rightTabs.contains(n)) {
885 if (n == activeR) activeRight = v;
890 _topTW->setCurrentIndex(_topTW->indexOf(activeTop->
widget()));
892 _bottomTW->setCurrentIndex(_bottomTW->indexOf(activeBottom->widget()));
894 _leftTW->setCurrentIndex(_leftTW->indexOf(activeLeft->
widget()));
896 _rightTW->setCurrentIndex(_rightTW->indexOf(activeRight->widget()));
909 s = _mainSplitter->sizes();
910 int rightSize = (s[0]+s[1]==0) ? 0 : (100 * s[1]/(s[0]+s[1]));
911 s = _leftSplitter->sizes();
912 int topSize = (s[0]+s[1]==0) ? 0 : (100 * s[0]/(s[0]+s[1]));
913 s = _bottomSplitter->sizes();
914 int leftSize = (s[0]+s[1]==0) ? 0 : (100 * s[0]/(s[0]+s[1]));
922 w = _topTW->currentWidget();
923 if ((_topTW->count()>0) &&
924 (_topTW->isTabEnabled(_topTW->indexOf(w))))
929 w = _bottomTW->currentWidget();
930 if ((_bottomTW->count()>0) &&
931 (_bottomTW->isTabEnabled(_bottomTW->indexOf(w))))
936 w = _leftTW->currentWidget();
937 if ((_leftTW->count()>0) &&
938 (_leftTW->isTabEnabled(_leftTW->indexOf(w))))
940 g->
setValue(
"ActiveLeft", a, QString());
943 w = _rightTW->currentWidget();
944 if ((_rightTW->count()>0) &&
945 (_rightTW->isTabEnabled(_rightTW->indexOf(w))))
947 g->
setValue(
"ActiveRight", a, QString());
949 QStringList topList, bottomList, leftList, rightList;
953 topList << v->
widget()->objectName();
957 bottomList << v->
widget()->objectName();
961 leftList << v->
widget()->objectName();
965 rightList << v->
widget()->objectName();
972 QStringList topTabsDefault, bottomTabsDefault;
976 g->
setValue(
"TopTabs", topList, topTabsDefault);
977 g->
setValue(
"BottomTabs", bottomList, bottomTabsDefault);
978 g->
setValue(
"LeftTabs", leftList, QStringList());
979 g->
setValue(
"RightTabs", rightList, QStringList());
994 QString activeType = g->
value(
"ActiveItemType", QString()).toString();
995 QString activeName = g->
value(
"ActiveItemName", QString()).toString();
996 QString selectedType = g->
value(
"SelectedItemType", QString()).toString();
997 QString selectedName = g->
value(
"SelectedItemName", QString()).toString();
1005 if (!activeItem)
return;
1036 .arg(v->
widget()->objectName()), postfix);
1039 #include "tabview.moc"
void selected(TraceItemView *, CostItem *)
Notification from child views.
#define DEFAULT_RIGHTSIZE
TabView(TraceItemView *parentView, QWidget *parent=0)
ProfileContext::Type type()
TraceItemView * _parentView
void set(ProfileContext::Type g)
#define DEFAULT_BOTTOMTABS
void resizeEvent(QResizeEvent *)
bool eventFilter(QObject *, QEvent *)
static QString typeName(Type)
ProfileCostArray * search(ProfileContext::Type, QString, EventType *ct=0, ProfileCostArray *parent=0)
Search for item with given name and highest subcost of given cost type.
ProfileContext::Type type() const
void setData(TraceData *)
virtual void setValue(const QString &key, const QVariant &value, const QVariant &defaultValue=QVariant())
Base class for cost items.
#define DEFAULT_ACTIVETOP
void updateView(bool force=false)
Position position() const
ProfileContext::Type _groupType
static ConfigGroup * group(const QString &group, const QString &optSuffix=QString())
Abstract Base Class for KCachegrind Views.
virtual void setData(TraceData *d)
virtual QString formattedName() const
A HTMLified version of name, can return empty string.
CostItem * selectedItem() const
An array of basic cost metrics for a trace item.
void moveTab(QWidget *w, Position, bool wholeArea=false)
Rearrange tabs if == 0, move hidden tabs.
void moveEvent(QMoveEvent *)
virtual QString name() const
Returns dynamic name info (without type)
void visibleRectChangedSlot(TabWidget *)
#define DEFAULT_ACTIVEBOTTOM
virtual CostItem * canShow(CostItem *i)
This function is called when a new item should become active.
void tabActivated(TabView *)
Position tabPosition(QWidget *)
void restoreOptions(const QString &prefix, const QString &postfix)
A group of configuration settings.
void notifyChange(int changeType)
virtual void selected(TraceItemView *sender, CostItem *)
Notification from child views.
virtual void activated(TraceItemView *sender, CostItem *)
TabBar(TabView *, QTabWidget *parent, const char *name=0)
QString whatsThis() const
Splitter(Qt::Orientation o, QWidget *parent=0)
virtual void saveOptions(const QString &prefix, const QString &postfix)
virtual void restoreOptions(const QString &prefix, const QString &postfix)
void restoreLayout(const QString &prefix, const QString &postfix)
CostItem * activeItem() const
void saveLayout(const QString &prefix, const QString &postfix)
void mousePressEvent(QMouseEvent *e)
Subclass of QTabBar to enable context menu on tabs.
void saveOptions(const QString &prefix, const QString &postfix)
A QGraphicsView showing a part of the call graph and another zoomed out CanvasView in a border acting...
void setPosition(Position p)
void mousePressEvent(QMouseEvent *)
virtual QWidget * widget()=0
This class holds profiling data of multiple tracefiles generated with cachegrind on one command...
virtual QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
virtual QVariant value(const QString &key, const QVariant &defaultValue) const
Own Splitter: Call checkVisiblity for all TabWidget children of the splitter on a MoveEvent...