23 #define TRACE_UPDATES 0
24 #define ENABLE_DUMPDOCK 0
30 #include <QDockWidget>
34 #include <QProgressBar>
38 #include <QtDBus/QDBusConnection>
40 #include <ktoggleaction.h>
41 #include <ktoolbarpopupaction.h>
42 #include <kactioncollection.h>
43 #include <kselectaction.h>
44 #include <krecentfilesaction.h>
46 #include <kstandardguiitem.h>
49 #include <kstatusbar.h>
50 #include <kstandardshortcut.h>
51 #include <kstandardaction.h>
54 #include <kfiledialog.h>
55 #include <kio/netaccess.h>
56 #include <kedittoolbar.h>
57 #include <kshortcutsdialog.h>
60 #include <kmessagebox.h>
63 #include <kconfiggroup.h>
64 #include <kfilterdev.h>
65 #include <kmimetype.h>
88 _statusbar = statusBar();
89 _statusLabel =
new QLabel(_statusbar);
90 _statusbar->addWidget(_statusLabel, 1);
98 KConfig *kconfig = KGlobal::config().data();
105 setCentralWidget(_multiView);
109 _partDockShown->setChecked(!_partDock->
isHidden());
110 _stackDockShown->setChecked(!_stackDock->
isHidden());
111 _functionDockShown->setChecked(!_functionDock->
isHidden());
113 connect(_partDock, SIGNAL(visibilityChanged(
bool)),
115 connect(_stackDock, SIGNAL(visibilityChanged(
bool)),
117 connect(_functionDock, SIGNAL(visibilityChanged(
bool)),
121 _dumpDockShown->setChecked(!_dumpDock->
isHidden());
122 connect(_dumpDock, SIGNAL(visibilityChanged(
bool)),
132 _taPercentage->setChecked(_showPercentage);
133 _taExpanded->setChecked(_showExpanded);
134 _taCycles->setChecked(_showCycles);
135 _taHideTemplates->setChecked(_hideTemplates);
137 setupPartSelection(_partSelection);
140 setStandardToolBarMenuEnabled(
true);
141 _openRecent->loadEntries( KConfigGroup( kconfig,
"" ) );
146 setAutoSaveSettings();
149 restoreCurrentState(QString::null);
152 if (memberList().count() == 1)
156 void TopLevel::resetState()
158 _activeParts.
clear();
159 _hiddenParts.
clear();
169 _traceItemDelayed = 0;
170 _eventTypeDelayed = 0;
171 _eventType2Delayed = 0;
187 connect(ps, SIGNAL(partsHideSelected()),
189 connect(ps, SIGNAL(partsUnhideAll()),
200 void TopLevel::saveCurrentState(
const QString& postfix)
206 stateConfig->
setValue(
"EventType", eventType);
207 stateConfig->
setValue(
"EventType2", eventType2);
220 void TopLevel::saveTraceSettings()
241 saveCurrentState(key);
253 void TopLevel::restoreCurrentState(
const QString& postfix)
259 _taSplit->setChecked(_multiView->
childCount()>1);
260 _taSplitDir->setEnabled(_multiView->
childCount()>1);
261 _taSplitDir->setChecked(_multiView->
orientation() == Qt::Horizontal);
280 "<b>The Top Cost Call Stack</b>"
281 "<p>This is a purely fictional 'most probable' call stack. "
282 "It is built up by starting with the current selected "
283 "function and adds the callers/callees with highest cost "
284 "at the top and to bottom.</p>"
285 "<p>The <b>Cost</b> and <b>Calls</b> columns show the "
286 "cost used for all calls from the function in the line "
289 connect(_stackSelection, SIGNAL(functionSelected(
CostItem*)),
296 _functionDock->
setWidget(_functionSelection);
306 _dumpSelection->setWhatsThis( i18n(
307 "<b>Profile Dumps</b>"
308 "<p>This dockable shows in the top part the list of "
309 "loadable profile dumps in all subdirectories of: "
310 "<ul><li>current working directory of KCachegrind, "
311 "i.e. where it was started from, and </li>"
312 "<li>the default profile dump directory given in the "
313 "configuration.</li></ul> "
314 "The list is sorted according to the target command "
315 "profiled in the corresponding dump.</p>"
316 "<p>On selecting a profile dump, information for it "
317 "is shown in the bottom area of the dockable: "
318 "<ul><li><b>Options</b> allows you to view the profiled "
319 "command and profile options of this dump. By changing "
320 "any item, a new (yet unexisting) profile template "
321 "is created. Press <b>Run Profile</b> to start a "
322 "profile run with these options in the background. </li>"
323 "<li><b>Info</b> gives detailed info on the selected "
324 "dump like event cost summary and properties of the "
325 "simulated cache. </li>"
326 "<li><b>State</b> is only available for current happening "
327 "profiles runs. Press <b>Update</b> to see different "
328 "counters of the run, and a stack trace of the current "
329 "position in the program profiled. Check the <b>Every</b> "
330 "option to let KCachegrind regularly poll these data. "
331 "Check the <b>Sync</b> option to let the dockable activate "
332 "the top function in the current loaded dump.</li></ul></p>"));
336 addDockWidget(Qt::LeftDockWidgetArea, _partDock );
337 addDockWidget(Qt::LeftDockWidgetArea, _stackDock );
338 addDockWidget(Qt::LeftDockWidgetArea, _functionDock );
343 addDockWidget( Qt::LeftDockWidgetArea, _dumpDock );
347 KConfigGroup dockConfig(KGlobal::config(),
"Docks");
348 _forcePartDock = dockConfig.readEntry(
"ForcePartDockVisible",
false);
361 c.writeEntry(
"TraceName", _data->
traceName());
366 QString traceName = c.readEntry(
"TraceName");
368 openDataFile(traceName);
372 void TopLevel::createLayoutActions()
377 action = actionCollection()->addAction(
"layout_duplicate" );
378 action->setText( i18n(
"&Duplicate" ) );
380 action->setShortcuts(KShortcut(Qt::CTRL+Qt::Key_Plus));
381 hint = i18n(
"<b>Duplicate Current Layout</b>"
382 "<p>Make a copy of the current layout.</p>");
383 action->setWhatsThis( hint );
385 action = actionCollection()->addAction(
"layout_remove" );
386 action->setText( i18n(
"&Remove" ) );
387 connect(action, SIGNAL(triggered(
bool) ), SLOT(
layoutRemove()));
388 hint = i18n(
"<b>Remove Current Layout</b>"
389 "<p>Delete current layout and make the previous active.</p>");
390 action->setWhatsThis( hint );
392 action = actionCollection()->addAction(
"layout_next" );
393 action->setText( i18n(
"&Go to Next" ) );
394 connect(action, SIGNAL(triggered(
bool)), SLOT(
layoutNext()));
395 action->setShortcuts(KShortcut(Qt::CTRL+Qt::Key_Right));
396 hint = i18n(
"Go to Next Layout");
397 action->setWhatsThis( hint );
399 action = actionCollection()->addAction(
"layout_previous" );
400 action->setText( i18n(
"&Go to Previous" ) );
402 action->setShortcuts(KShortcut(Qt::CTRL+Qt::Key_Left));
403 hint = i18n(
"Go to Previous Layout");
404 action->setWhatsThis( hint );
406 action = actionCollection()->addAction(
"layout_restore" );
407 action->setText( i18n(
"&Restore to Default" ) );
408 connect(action, SIGNAL(triggered(
bool) ), SLOT(
layoutRestore()));
409 hint = i18n(
"Restore Layouts to Default");
410 action->setWhatsThis( hint );
412 action = actionCollection()->addAction(
"layout_save" );
413 action->setText( i18n(
"&Save as Default" ) );
414 connect(action, SIGNAL(triggered(
bool) ), SLOT(
layoutSave()));
415 hint = i18n(
"Save Layouts as Default");
416 action->setWhatsThis( hint );
420 void TopLevel::createMiscActions()
425 action = KStandardAction::openNew(
this, SLOT(
newWindow()), actionCollection());
426 hint = i18n(
"<b>New</b><p>Open new empty KCachegrind window.</p>");
427 action->setWhatsThis( hint );
429 action = actionCollection()->addAction(
"file_add" );
430 action->setText( i18n(
"&Add..." ) );
431 connect(action, SIGNAL(triggered(
bool) ), SLOT(
add()));
432 hint = i18n(
"<b>Add Profile Data</b>"
433 "<p>This opens an additional profile data file in the current window.</p>");
434 action->setWhatsThis( hint );
436 action = actionCollection()->addAction(
"reload" );
437 action->setIcon( KIcon(
"view-refresh") );
438 action->setText( i18nc(
"Reload a document",
"&Reload" ) );
439 connect(action, SIGNAL(triggered(
bool) ), SLOT(
reload() ));
440 action->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::Reload));
441 hint = i18n(
"<b>Reload Profile Data</b>"
442 "<p>This loads any new created parts, too.</p>");
443 action->setWhatsThis( hint );
445 action = actionCollection()->addAction(
"export" );
446 action->setText( i18n(
"&Export Graph" ) );
447 connect(action, SIGNAL(triggered(
bool) ), SLOT(
exportGraph()));
449 hint = i18n(
"<b>Export Call Graph</b>"
450 "<p>Generates a file with extension .dot for the tools "
451 "of the GraphViz package.</p>");
452 action->setWhatsThis( hint );
455 _taDump = actionCollection()->add<KToggleAction>(
"dump" );
456 _taDump->setIcon( KIcon(
"edit-redo") );
457 _taDump->setText( i18n(
"&Force Dump" ) );
458 connect(_taDump, SIGNAL(triggered(
bool) ), SLOT(
forceTrace() ));
459 _taDump->setShortcut(KStandardShortcut::shortcut(KStandardShortcut::Redo));
460 hint = i18n(
"<b>Force Dump</b>"
461 "<p>This forces a dump for a Callgrind profile run "
462 "in the current directory. This action is checked while "
463 "KCachegrind looks for the dump. If the dump is "
464 "finished, it automatically reloads the current trace. "
465 "If this is the one from the running Callgrind, the new "
466 "created trace part will be loaded, too.</p>"
467 "<p>Force dump creates a file 'callgrind.cmd', and "
468 "checks every second for its existence. A running "
469 "Callgrind will detect this file, dump a trace part, "
470 "and delete 'callgrind.cmd'. "
471 "The deletion is detected by KCachegrind, "
472 "and it does a Reload. If there is <em>no</em> Callgrind "
473 "running, press 'Force Dump' again to cancel the dump "
474 "request. This deletes 'callgrind.cmd' itself and "
475 "stops polling for a new dump.</p>"
476 "<p>Note: A Callgrind run <em>only</em> detects "
477 "existence of 'callgrind.cmd' when actively running "
478 "a few milliseconds, i.e. "
479 "<em>not</em> sleeping. Tip: For a profiled GUI program, "
480 "you can awake Callgrind e.g. by resizing a window "
481 "of the program.</p>");
482 _taDump->setWhatsThis( hint );
484 action = KStandardAction::open(
this, SLOT(
load()), actionCollection());
485 hint = i18n(
"<b>Open Profile Data</b>"
486 "<p>This opens a profile data file, with possible multiple parts</p>");
487 action->setToolTip( hint );
488 action->setWhatsThis( hint );
490 _openRecent = KStandardAction::openRecent(
this, SLOT(
load(
const KUrl&)),
493 KStandardAction::showStatusbar(
this,
496 _partDockShown = actionCollection()->add<KToggleAction>(
"settings_show_partdock");
497 _partDockShown->setText(i18n(
"Parts Overview"));
498 connect(_partDockShown, SIGNAL(triggered(
bool) ), SLOT(
togglePartDock()));
500 hint = i18n(
"Show/Hide the Parts Overview Dockable");
501 _partDockShown->setToolTip( hint );
502 _partDockShown->setWhatsThis( hint );
504 _stackDockShown = actionCollection()->add<KToggleAction>(
"settings_show_stackdock");
505 _stackDockShown->setText(i18n(
"Call Stack"));
506 connect(_stackDockShown, SIGNAL(triggered(
bool) ), SLOT(
toggleStackDock()));
508 hint = i18n(
"Show/Hide the Call Stack Dockable");
509 _stackDockShown->setToolTip( hint );
510 _stackDockShown->setWhatsThis( hint );
512 _functionDockShown = actionCollection()->add<KToggleAction>(
"settings_show_profiledock");
513 _functionDockShown->setText(i18n(
"Function Profile"));
516 hint = i18n(
"Show/Hide the Function Profile Dockable");
517 _functionDockShown->setToolTip( hint );
518 _functionDockShown->setWhatsThis( hint );
521 _dumpDockShown = actionCollection()->add<KToggleAction>(
"settings_show_dumpdock",
523 _dumpDockShown->setText(i18n(
"Profile Dumps"));
524 hint = i18n(
"Show/Hide the Profile Dumps Dockable");
525 _dumpDockShown->setToolTip( hint );
526 _dumpDockShown->setWhatsThis( hint );
529 _taPercentage = actionCollection()->add<KToggleAction>(
"view_percentage");
530 _taPercentage->setIcon(KIcon(
"percent"));
531 _taPercentage->setText(i18n(
"Relative"));
533 hint = i18n(
"Show relative instead of absolute costs");
534 _taPercentage->setToolTip( hint );
535 _taPercentage->setWhatsThis( hint );
537 _taExpanded = actionCollection()->add<KToggleAction>(
"view_expanded");
538 _taExpanded->setIcon(KIcon(
"move"));
539 _taExpanded->setText(i18n(
"Relative to Parent"));
540 connect(_taExpanded, SIGNAL(triggered(
bool) ), SLOT(
toggleExpanded()));
542 hint = i18n(
"Show percentage costs relative to parent");
543 _taExpanded->setToolTip( hint );
544 _taExpanded->setWhatsThis( hint );
546 hint = i18n(
"<b>Show percentage costs relative to parent</b>"
547 "<p>If this is switched off, percentage costs are always shown "
548 "relative to the total cost of the profile part(s) that are "
549 "currently browsed. By turning on this option, percentage cost "
550 "of shown cost items will be relative to the parent cost item.</p>"
552 "<tr><td><b>Cost Type</b></td><td><b>Parent Cost</b></td></tr>"
553 "<tr><td>Function Cumulative</td><td>Total</td></tr>"
554 "<tr><td>Function Self</td><td>Function Group (*) / Total</td></tr>"
555 "<tr><td>Call</td><td>Function Inclusive</td></tr>"
556 "<tr><td>Source Line</td><td>Function Inclusive</td></tr>"
558 "<p>(*) Only if function grouping is switched on (e.g. ELF object grouping).</p>");
559 _taExpanded->setWhatsThis( hint );
561 _taCycles = actionCollection()->add<KToggleAction>(
"view_cycles");
562 _taCycles->setIcon(KIcon(
"edit-undo"));
563 _taCycles->setText(i18n(
"Cycle Detection" ));
564 connect(_taCycles, SIGNAL(triggered(
bool) ), SLOT(
toggleCycles() ));
566 hint = i18n(
"<b>Detect recursive cycles</b>"
567 "<p>If this is switched off, the treemap drawing will show "
568 "black areas when a recursive call is made instead of drawing the "
569 "recursion ad infinitum. Note that "
570 "the size of black areas often will be wrong, as inside recursive "
571 "cycles the cost of calls cannot be determined; the error is small, "
572 "however, for false cycles (see documentation).</p>"
573 "<p>The correct handling for cycles is to detect them and collapse all "
574 "functions of a cycle into an artificial function, which is done when this "
575 "option is selected. Unfortunately, with GUI applications, this often will "
576 "lead to huge false cycles, making the analysis impossible; therefore, there "
577 "is the option to switch this off.</p>");
578 _taCycles->setWhatsThis( hint );
580 _taHideTemplates = actionCollection()->add<KToggleAction>(
"hide_templates");
581 _taHideTemplates->setIcon(KIcon(
"hidetemplates"));
582 _taHideTemplates->setText(i18n(
"Shorten Templates" ));
584 _taHideTemplates->setToolTip(i18n(
"Hide Template Parameters in C++ Symbols" ));
585 hint = i18n(
"<b>Hide Template Parameters in C++ Symbols</b>"
586 "<p>If this is switched on, every symbol displayed will have "
587 "any C++ template parameters hidden, just showing <> "
588 "instead of a potentially nested template parameter.</p>"
589 "<p>In this mode, you can hover the mouse pointer over the "
590 "activated symbol label to show a tooltip with the "
591 "unabbreviated symbol.</p>");
592 _taHideTemplates->setWhatsThis(hint);
594 KStandardAction::quit(
this, SLOT(close()), actionCollection());
595 KStandardAction::preferences(
this, SLOT(
configure()), actionCollection());
596 KStandardAction::keyBindings(
this, SLOT(
configureKeys()), actionCollection());
600 action = KStandardAction::back(_stackSelection, SLOT(browserBack()),
602 hint = i18n(
"Go back in function selection history");
603 action->setToolTip( hint );
604 action->setWhatsThis( hint );
606 action = KStandardAction::forward(_stackSelection, SLOT(browserForward()),
608 hint = i18n(
"Go forward in function selection history");
609 action->setToolTip( hint );
610 action->setWhatsThis( hint );
612 action = KStandardAction::up(_stackSelection, SLOT(browserUp()),
614 hint = i18n(
"<b>Go Up</b>"
615 "<p>Go to last selected caller of current function. "
616 "If no caller was visited, use that with highest cost.</p>");
617 action->setToolTip( hint );
618 action->setWhatsThis( hint );
620 _paUp =
new KToolBarPopupAction( KIcon(
"go-up" ), i18n(
"&Up" ),
this );
621 _paUp->setShortcuts( KShortcut(Qt::ALT+Qt::Key_Up) );
622 connect( _paUp, SIGNAL( triggered(
bool ) ), _stackSelection, SLOT( browserUp() ) );
623 actionCollection()->addAction(
"go_up", _paUp );
624 connect( _paUp->menu(), SIGNAL( aboutToShow() ),
626 connect( _paUp->menu(), SIGNAL( triggered(
QAction* ) ),
628 hint = i18n(
"<b>Go Up</b>"
629 "<p>Go to last selected caller of current function. "
630 "If no caller was visited, use that with highest cost.</p>");
631 _paUp->setToolTip( hint );
632 _paUp->setWhatsThis( hint );
635 _paBack =
new KToolBarPopupAction( backForward.first.icon(), backForward.first.text(), this );
636 _paBack->setShortcuts( KShortcut(Qt::ALT+Qt::Key_Left) );
637 connect( _paBack, SIGNAL( triggered(
bool ) ), _stackSelection, SLOT( browserBack() ) );
638 actionCollection()->addAction(
"go_back", _paBack );
639 connect( _paBack->menu(), SIGNAL( aboutToShow() ),
641 connect( _paBack->menu(), SIGNAL( triggered(
QAction* ) ),
643 hint = i18n(
"Go back in function selection history");
644 _paBack->setToolTip( hint );
645 _paBack->setWhatsThis( hint );
647 _paForward =
new KToolBarPopupAction( backForward.second.icon(), backForward.second.text(), this );
648 _paForward->setShortcuts( KShortcut(Qt::ALT+Qt::Key_Right) );
649 connect( _paForward, SIGNAL( triggered(
bool ) ), _stackSelection, SLOT( browserForward() ) );
650 actionCollection()->addAction(
"go_forward", _paForward );
651 connect( _paForward->menu(), SIGNAL( aboutToShow() ),
653 connect( _paForward->menu(), SIGNAL( triggered(
QAction* ) ),
655 hint = i18n(
"Go forward in function selection history");
656 _paForward->setToolTip( hint );
657 _paForward->setWhatsThis( hint );
660 _saCost = actionCollection()->add<KSelectAction>(
"view_cost_type");
661 _saCost->setText(i18n(
"Primary Event Type"));
662 hint = i18n(
"Select primary event type of costs");
663 _saCost->setComboWidth(300);
664 _saCost->setToolTip( hint );
665 _saCost->setWhatsThis( hint );
675 dummyItems <<
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
676 _saCost->setItems(dummyItems);
680 connect( _saCost, SIGNAL(triggered(
const QString&)),
683 _saCost2 = actionCollection()->add<KSelectAction>(
"view_cost_type2");
684 _saCost2->setText(i18n(
"Secondary Event Type"));
685 hint = i18n(
"Select secondary event type for cost e.g. shown in annotations");
686 _saCost2->setComboWidth(300);
687 _saCost2->setToolTip( hint );
688 _saCost2->setWhatsThis( hint );
689 _saCost2->setItems(dummyItems);
691 connect( _saCost2, SIGNAL(triggered(
const QString&)),
694 saGroup = actionCollection()->add<KSelectAction>(
"view_group_type");
695 saGroup->setText(i18n(
"Grouping"));
697 hint = i18n(
"Select how functions are grouped into higher level cost items");
698 saGroup->setToolTip( hint );
699 saGroup->setWhatsThis( hint );
703 args << i18n(
"(No Grouping)")
709 saGroup->setItems(args);
710 connect( saGroup, SIGNAL(triggered(
int)),
713 _taSplit = actionCollection()->add<KToggleAction>(
"view_split");
714 _taSplit->setIcon(KIcon(
"view-split-left-right"));
715 _taSplit->setText(i18n(
"Split"));
716 connect(_taSplit, SIGNAL(triggered(
bool) ), SLOT(
splitSlot()));
718 hint = i18n(
"Show two information panels");
719 _taSplit->setToolTip( hint );
720 _taSplit->setWhatsThis( hint );
722 _taSplitDir = actionCollection()->add<KToggleAction>(
"view_split_dir");
723 _taSplitDir->setIcon(KIcon(
"view-split-left-right"));
724 _taSplitDir->setText(i18n(
"Split Horizontal"));
725 connect(_taSplitDir, SIGNAL(triggered(
bool) ), SLOT(
splitDirSlot()));
727 hint = i18n(
"Change Split Orientation when main window is split.");
728 _taSplitDir->setToolTip( hint );
729 _taSplitDir->setWhatsThis( hint );
732 KStandardAction::tipOfDay(
this, SLOT(
slotShowTip() ), actionCollection() );
738 createLayoutActions();
743 if (statusBar()->isVisible())
778 _functionDock->
show();
780 _functionDock->
hide();
798 void TopLevel::updateViewsOnChange(
int change)
807 if (_showPercentage == show)
return;
808 _showPercentage = show;
809 if (_taPercentage->isChecked() != show)
810 _taPercentage->setChecked(show);
821 bool show = _taExpanded->isChecked();
822 if (_showExpanded == show)
return;
823 _showExpanded = show;
834 bool show = _taCycles->isChecked();
835 if (_showCycles == show)
return;
852 bool b = _taHideTemplates->isChecked();
853 if (_hideTemplates == b)
return;
865 _partDockShown->setChecked(v);
870 _stackDockShown->setChecked(v);
880 _dumpDockShown->setChecked(v);
886 _functionDockShown->setChecked(v);
894 _functionSelection->
query(queryLineEdit->
text());
899 KShortcutsDialog::configure(actionCollection(), KShortcutsEditor::LetterShortcutsAllowed,
this);
905 KEditToolBar *dlg =
new KEditToolBar(guiFactory(),
this);
923 KUrl url = KFileDialog::getOpenUrl(KUrl(
"kfiledialog:///"),
924 i18n(
"cachegrind.out* callgrind.out*|Callgrind Profile Data\n*|All Files"),
926 i18n(
"Select Callgrind Profile Data"));
932 if (url.isEmpty())
return;
937 if(KIO::NetAccess::download( url, tmpFile,
this )) {
938 _openRecent->addUrl(url);
939 _openRecent->saveEntries( KConfigGroup( KGlobal::config(),
QString() ) );
942 KIO::NetAccess::removeTempFile( tmpFile );
944 KMessageBox::error(
this, i18n(
"Could not open the file \"%1\". "
945 "Check it exists and you have enough "
946 "permissions to read it.", url.prettyUrl()));
957 bool showError =
true;
970 bool loaded = openDataFile(file);
971 if (!loaded && showError)
972 KMessageBox::error(
this, i18n(
"Could not open the file \"%1\". "
973 "Check it exists and you have enough "
974 "permissions to read it.", file));
980 KUrl url = KFileDialog::getOpenUrl(KUrl(),
981 i18n(
"cachegrind.out* callgrind.out*|Callgrind Profile Data\n*|All Files"),
983 i18n(
"Add Callgrind Profile Data"));
989 if (url.isEmpty())
return;
993 if(KIO::NetAccess::download( url, tmpFile,
this )) {
994 _openRecent->addUrl(url);
995 _openRecent->saveEntries( KGlobal::config()->group(
QString() ) );
998 KIO::NetAccess::removeTempFile( tmpFile );
1021 _loadFilesDelayed << file;
1027 _loadFilesDelayed << files;
1033 if (_loadFilesDelayed.
isEmpty())
return;
1035 if (_loadFilesDelayed.
count()>1) {
1038 d->
load(_loadFilesDelayed);
1042 QString file = _loadFilesDelayed[0];
1045 if (KUrl::isRelativeUrl(file))
1050 _loadFilesDelayed.
clear();
1063 openDataFile(trace);
1068 if (!_data || !_function)
return;
1071 GraphExporter ge(_data, _function, _eventType, _groupType, n);
1079 qDebug() <<
"TopLevel::exportGraph: can not run " << cmd;
1124 if (_eventType == ct)
return false;
1131 _saCost->setCurrentItem(idx);
1146 if (_eventType2 == ct)
return false;
1151 int idx = l.
indexOf(longName);
1153 _saCost2->setCurrentItem(idx);
1199 if (_groupType == gt)
return false;
1213 if (idx==-1)
return false;
1215 if (saGroup->currentItem() != idx)
1216 saGroup->setCurrentItem(idx);
1219 _partSelection->
set(_groupType);
1220 _functionSelection->
set(_groupType);
1221 _multiView->
set(_groupType);
1240 if (_group == g)
return false;
1251 if (!_data)
return false;
1254 if (!f)
return false;
1261 if (_function == f)
return false;
1277 qDebug(
"TopLevel::setFunction(%s), lastSender %s",
1279 _lastSender ? _lastSender->
name() :
"0" );
1295 _eventTypeDelayed = ct;
1301 _eventType2Delayed = ct;
1317 _groupTypeDelayed = gt;
1329 qDebug(
"TopLevel::setGroupDelayed(%s), sender %s",
1331 _lastSender ? _lastSender->
name() :
"0" );
1345 _directionDelayed = d;
1351 switch(_directionDelayed) {
1382 if (_traceItemDelayed == i)
return;
1383 _traceItemDelayed = i;
1384 _lastSender = sender();
1386 kDebug() <<
"Selected " << (i ? i->
prettyName() :
"(none)");
1389 qDebug(
"TopLevel::setTraceItemDelayed(%s), sender %s",
1391 _lastSender ? _lastSender->
name() :
"0" );
1399 if (!_traceItemDelayed)
return;
1401 switch(_traceItemDelayed->
type()) {
1410 _multiView->
activate(_traceItemDelayed);
1418 _multiView->
activate(_traceItemDelayed);
1425 _traceItemDelayed = 0;
1437 if (data == _data)
return;
1441 saveTraceSettings();
1446 _functionSelection->
setData(0);
1473 _saCost->setItems(types);
1474 _saCost->setComboWidth(300);
1476 if (types.
count()>0) {
1478 types.
prepend(i18n(
"(Hidden)"));
1480 _saCost2->setItems(types);
1481 _saCost2->setComboWidth(300);
1483 if (types.
count()>0)
1484 _saCost2->setCurrentItem(0);
1486 _partSelection->
setData(_data);
1487 _stackSelection->
setData(_data);
1488 _functionSelection->
setData(_data);
1495 restoreTraceTypes();
1497 restoreTraceSettings();
1503 caption +=
" [" + _data->
command() +
']';
1505 setWindowTitle(caption);
1507 if (!_data || (!_forcePartDock && _data->
parts().
count()<2)) {
1509 _partDockShown->setChecked(
false);
1513 _partDockShown->setChecked(
true);
1522 QMenu *popup1, *popup2 = 0;
1525 popup1 = popup->
addMenu(i18n(
"Primary Event Type"));
1526 connect(popup1, SIGNAL(triggered(
QAction*)),
1530 popup2 = popup->
addMenu(i18n(
"Secondary Event Type"));
1531 connect(popup2, SIGNAL(triggered(
QAction*)),
1535 action = popup2->
addAction(i18n(
"Hide"));
1549 if (_eventType == ct) action->
setChecked(
true);
1555 if (_eventType2 == ct) action->
setChecked(
true);
1565 if (_eventType == ct) action->
setChecked(
true);
1571 if (_eventType2 == ct) action->
setChecked(
true);
1576 if (_showPercentage)
1577 popup->
addAction(i18n(
"Show Absolute Cost"),
1580 popup->
addAction(i18n(
"Show Relative Cost"),
1586 if (!_data)
return false;
1591 if (
id >=100 &&
id<199) ct = m->
realType(
id-100);
1592 if (
id >=200 &&
id<299) ct = m->
derivedType(
id-200);
1599 if (!_data)
return false;
1604 if (
id >=100 &&
id<199) ct = m->
realType(
id-100);
1605 if (
id >=200 &&
id<299) ct = m->
derivedType(
id-200);
1638 for (
int l=0;l<name.
length();l++)
1639 if (name[l].isLetterOrNumber()) key += name[l];
1645 void TopLevel::restoreTraceTypes()
1670 if (!_eventType && !_saCost->items().isEmpty())
1688 void TopLevel::restoreTraceSettings()
1694 restoreCurrentState(key);
1704 if (!_traceItemDelayed) {
1719 _layoutCurrent = _layoutCount;
1724 if (0) kDebug() <<
"TopLevel::layoutDuplicate: count " << _layoutCount;
1729 if (_layoutCount <2)
return;
1731 int from = _layoutCount-1;
1732 if (_layoutCurrent == from) { _layoutCurrent--; from--; }
1744 if (_layoutCount <2)
return;
1749 _multiView->
saveLayout(layoutPrefix.
arg(_layoutCurrent), key);
1751 if (_layoutCurrent == _layoutCount) _layoutCurrent = 0;
1754 if (0) kDebug() <<
"TopLevel::layoutNext: current "
1755 << _layoutCurrent << endl;
1760 if (_layoutCount <2)
return;
1765 _multiView->
saveLayout(layoutPrefix.
arg(_layoutCurrent), key);
1767 if (_layoutCurrent <0) _layoutCurrent = _layoutCount-1;
1770 if (0) kDebug() <<
"TopLevel::layoutPrevious: current "
1771 << _layoutCurrent << endl;
1779 _multiView->
saveLayout(layoutPrefix.
arg(_layoutCurrent), key);
1782 for(
int i=0;i<_layoutCount;i++) {
1790 layoutConfig->
setValue(
"DefaultCount", _layoutCount);
1791 layoutConfig->
setValue(
"DefaultCurrent", _layoutCurrent);
1792 delete layoutConfig;
1797 KConfig *config = KGlobal::config().data();
1798 KConfigGroup aConfig(config,
"Layouts");
1799 _layoutCount = aConfig.readEntry(
"DefaultCount", 0);
1800 _layoutCurrent = aConfig.readEntry(
"DefaultCurrent", 0);
1801 if (_layoutCount == 0) {
1817 ka = actionCollection()->action(
"layout_next");
1820 ka = actionCollection()->action(
"layout_previous");
1823 ka = actionCollection()->action(
"layout_remove");
1826 _statusbar->showMessage(i18n(
"Layout Count: %1", _layoutCount), 1000);
1833 _statusLabel->
setText(i18n(
"No profile data file loaded."));
1842 status += i18n(
"Total %1 Cost: %2",
1854 status += i18n(
"No event type selected");
1865 _statusLabel->
setText(status);
1882 saveTraceSettings();
1897 _forcePartDock =
false;
1899 _forcePartDock=
true;
1900 KConfigGroup dockConfig(KGlobal::config(),
"Docks");
1901 dockConfig.writeEntry(
"ForcePartDockVisible", _forcePartDock);
1910 if (count<1) count = 1;
1911 if (count>2) count = 2;
1915 _taSplit->setChecked(count>1);
1916 _taSplitDir->setEnabled(count>1);
1917 _taSplitDir->setChecked(_multiView->
orientation() == Qt::Horizontal);
1923 Qt::Horizontal : Qt::Vertical );
1942 KTipDialog::showTip(
this);
1946 KTipDialog::showTip(
this,
QString(),
true );
1961 _activeParts = list;
1963 _partSelection->
set(list);
1964 _multiView->
set(list);
1965 _functionSelection->
set(list);
1991 _hiddenParts = newHidden;
1995 _mainWidget1->hiddenPartsChangedSlot(_hiddenParts);
1996 _mainWidget2->hiddenPartsChangedSlot(_hiddenParts);
2012 _hiddenParts.
clear();
2015 _mainWidget1->hiddenPartsChangedSlot(_hiddenParts);
2016 _mainWidget2->hiddenPartsChangedSlot(_hiddenParts);
2024 qDebug(
"TopLevel::forceTrace: killing old callgrind_control");
2030 if (!_taDump->isChecked())
return;
2036 if (_data) pl = _data->
parts();
2040 showMessage(i18n(
"Cannot determine receiver PID for dump request"),
2042 _taDump->setChecked(
false);
2046 qDebug(
"TopLevel::forceTrace: run 'callgrind_control -d %d'", pid);
2049 connect(_ccProcess, SIGNAL(readyReadStandardOutput()),
2051 connect(_ccProcess, SIGNAL(error(QProcess::ProcessError)),
2052 SLOT(
ccError(QProcess::ProcessError)));
2053 connect(_ccProcess, SIGNAL(finished(
int,QProcess::ExitStatus)),
2054 SLOT(
ccExit(
int,QProcess::ExitStatus)));
2055 _ccProcess->
start(
QString(
"callgrind_control -d %1").arg(pid),
2056 QIODevice::ReadOnly);
2062 qDebug(
"TopLevel::ccReadOutput: QProcess %p", p);
2065 if (!_ccProcess)
return;
2066 if (p != _ccProcess)
return;
2074 qDebug(
"TopLevel::ccError: Got %d from QProcess %p",
2078 if (!_ccProcess)
return;
2079 if (p != _ccProcess)
return;
2081 showMessage(i18n(
"Error running callgrind_control"), 5000);
2090 qDebug(
"TopLevel::ccExit: QProcess %p, exitCode %d",
2094 if (!_ccProcess)
return;
2095 if (p != _ccProcess)
return;
2098 _taDump->setChecked(
false);
2101 if ((s == QProcess::CrashExit) || (exitCode != 0))
2111 QMenu *popup = _paForward->menu();
2126 popup->
addAction(i18n(
"(No next function)"));
2139 action->setData(count);
2148 QMenu *popup = _paBack->menu();
2163 popup->
addAction(i18n(
"(No previous function)"));
2176 action->setData(count);
2185 QMenu *popup = _paUp->menu();
2199 popup->
addAction(i18n(
"(No Function Up)"));
2208 action->setData(count);
2263 while (count>0 && f) {
2276 _statusbar->showMessage(msg, ms);
2281 static bool msgUpdateNeeded =
true;
2283 if (!_statusbar)
return;
2288 _statusbar->removeWidget(_progressBar);
2289 delete _progressBar;
2292 _statusbar->clearMessage();
2298 _progressStart.
start();
2300 if (msg != _progressMsg) {
2302 msgUpdateNeeded =
true;
2306 if (_progressStart.
elapsed() < 500)
2309 if (!_progressBar) {
2312 _statusbar->addPermanentWidget(_progressBar, 1);
2313 _progressBar->
show();
2314 msgUpdateNeeded =
true;
2319 if (msgUpdateNeeded) {
2320 _statusbar->showMessage(msg);
2321 msgUpdateNeeded =
false;
2326 qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
2331 showStatus(i18n(
"Loading %1").arg(filename), 0);
2350 kError() <<
"Loading" <<
_filename <<
":" << line <<
": " << msg;
2355 kWarning() <<
"Loading" <<
_filename <<
":" << line <<
": " << msg;
2358 bool TopLevel::openDataFile(
const QString& file)
2364 QString mimeType = KMimeType::findByFileContent(file)->name ();
2365 QIODevice* compressed = KFilterDev::deviceForFile (file, mimeType,
true);
2367 filesLoaded = d->
load(compressed, file);
2370 filesLoaded = d->
load(file);
2372 if (filesLoaded > 0) {
2381 #include "toplevel.moc"
StackBrowser * browser() const
void setEventType2(EventType *)
void setDirectionDelayed()
virtual void saveProperties(KConfigGroup &)
ProfileContext::Type type()
static void setShowPercentage(bool)
TraceFunction * function()
static bool showPercentage()
QString & append(QChar ch)
const char * ascii() const
void toggleHideTemplates()
void saveLayout(const QString &prefix, const QString &postfix)
void set(ProfileContext::Type g)
void setEventType2Delayed()
void setEventType2(EventType *t)
static QString typeName(Type)
void toggleFunctionDock()
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 setFunction(TraceFunction *)
QString prettySubCost(EventType *)
Returns a cost attribute converted to a string (with space after every 3 digits)
void forwardTriggered(QAction *)
void setEventType(EventType *t)
void slotShowTipOnStart()
bool registerObject(const QString &path, QObject *object, QFlags< QDBusConnection::RegisterOption > options)
virtual void loadError(int line, const QString &msg)
virtual void setValue(const QString &key, const QVariant &value, const QVariant &defaultValue=QVariant())
Base class for cost items.
bool setEventType2(EventType *)
void setGroup(TraceCostItem *)
QDBusConnection sessionBus()
void activePartsChangedSlot(const TracePartList &list)
void partVisibilityChanged(bool)
void updateView(bool force=false)
void showMessage(const QString &, int msec)
int addKnownDerivedTypes()
Adds all known derived event types that can be parsed.
EventTypeSet * eventTypes()
QString activePartRange()
TraceFunction * caller(TraceFunction *, bool extend)
HistoryItem * goForward()
virtual void loadProgress(int progress)
void backTriggered(QAction *)
bool activateParts(const TracePartList &)
returns true if something changed.
void setData(TraceData *)
void hiddenPartsChangedSlot(const TracePartList &list)
void stackVisibilityChanged(bool)
void functionVisibilityChanged(bool)
EventType * typeForLong(const QString &)
static ConfigGroup * group(const QString &group, const QString &optSuffix=QString())
void restoreOptions(const QString &prefix, const QString &postfix)
TracePartList parts() const
virtual void loadWarning(int line, const QString &msg)
const char * name() const
void upTriggered(QAction *)
An array of basic cost metrics for a trace item.
int count(const T &value) const
static void setShowCycles(bool)
void restoreOptions(const QString &prefix, const QString &postfix)
bool setFunction(TraceFunction *)
void setTraceItemDelayed()
void append(const T &value)
int toInt(bool *ok) const
void setData(TraceData *)
void addEventTypeMenu(QMenu *, bool)
void updateFunctionCycles()
void setGroupTypeDelayed()
int load(QStringList files)
Loads profile data files.
static QString i18nTypeName(Type)
void setObjectName(const QString &name)
void updateLayoutActions()
void partsUnhideAllSlotDelayed()
void eventTypeSelected(const QString &)
virtual QString name() const
Returns dynamic name info (without type)
QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
void setEventType(EventType *)
void setText(const QString &)
bool activate(CostItem *i)
static QString shortenSymbol(const QString &)
A group of configuration settings.
void notifyChange(int changeType)
void partsHideSelectedSlotDelayed()
static GlobalGUIConfig * config()
void setData(const QVariant &userData)
void saveOptions(const QString &prefix, const QString &postfix)
void forwardAboutToShow()
void partsHideSelectedSlot()
void showStatus(const QString &msg, int progress)
void setData(TraceData *)
bool contains(const T &value) const
void groupTypeSelected(int)
void ccError(QProcess::ProcessError)
EventType * realType(int)
A Trace Part: All data read from a trace file, containing all costs that happened in a specified time...
void writeDot(QIODevice *=0)
static void setHideTemplates(bool)
static bool showExpanded()
void partsUnhideAllSlot()
QString shortTraceName() const
void restoreLayout(const QString &prefix, const QString &postfix)
static bool hideTemplates()
void eventType2Selected(const QString &)
virtual void loadFinished(const QString &msg)
void ccExit(int, QProcess::ExitStatus)
ProfileContext::Type groupType()
const QString & longName()
A class for managing a set of event types.
void setTopLevel(TopLevelBase *t)
int indexOf(const QRegExp &rx, int from) const
void prepend(const T &value)
void loadDelayed(QString)
void setEventTypeDelayed()
static bool configure(GlobalGUIConfig *, TraceData *, QWidget *)
bool setEventType(EventType *)
void setData(TraceData *)
A TraceData object cannot be viewed many times in different toplevel windows.
This class holds profiling data of multiple tracefiles generated with cachegrind on one command...
void setGroupType(ProfileContext::Type)
virtual QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
EventType * derivedType(int)
bool setGroupType(ProfileContext::Type)
static void setShowExpanded(bool)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
void saveOptions(const QString &prefix, const QString &postfix)
QByteArray readAllStandardOutput()
bool setGroup(TraceCostItem *)
void start(const QString &program, const QStringList &arguments, QFlags< QIODevice::OpenModeFlag > mode)
static int maxSymbolCount()
QString traceName() const
QByteArray encodeName(const QString &fileName)
virtual void readProperties(const KConfigGroup &)
void setData(TraceData *)
void dumpVisibilityChanged(bool)
virtual QVariant value(const QString &key, const QVariant &defaultValue) const
void invalidateDynamicCost()
virtual void loadStart(const QString &filename)