summaryrefslogtreecommitdiffstats
path: root/tdecachegrind/tdecachegrind/partselection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tdecachegrind/tdecachegrind/partselection.cpp')
-rw-r--r--tdecachegrind/tdecachegrind/partselection.cpp567
1 files changed, 567 insertions, 0 deletions
diff --git a/tdecachegrind/tdecachegrind/partselection.cpp b/tdecachegrind/tdecachegrind/partselection.cpp
new file mode 100644
index 00000000..703dd75f
--- /dev/null
+++ b/tdecachegrind/tdecachegrind/partselection.cpp
@@ -0,0 +1,567 @@
+/* This file is part of KCachegrind.
+ Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+ KCachegrind is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation, version 2.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * For part file selection, to be put into a TQDockWindow
+ */
+
+#include <tqtimer.h>
+#include <tqlistview.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcombobox.h>
+#include <tqlineedit.h>
+#include <tqpopupmenu.h>
+#include <tqlayout.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "partselection.h"
+#include "partgraph.h"
+
+PartSelection::PartSelection( TQWidget* parent, const char* name)
+ : PartSelectionBase(parent, name)
+{
+ _data = 0;
+ _costType = 0;
+ _costType2 = 0;
+ _groupType = TraceItem::NoCostType;
+ _group = 0;
+ _function = 0;
+ _inSelectionUpdate = false;
+
+ _diagramMode = false;
+ _drawFrames = true;
+
+ partAreaWidget->setAllowRotation(false);
+ partAreaWidget->setMaxSelectDepth(2);
+ partAreaWidget->setSelectionMode(TreeMapWidget::Extended);
+ partAreaWidget->setSplitMode(TreeMapItem::HAlternate);
+ partAreaWidget->setVisibleWidth(2, true);
+ partAreaWidget->setFieldType(0, i18n( "Name" ));
+ partAreaWidget->setFieldType(1, i18n( "Cost" ));
+
+ connect(partAreaWidget, TQT_SIGNAL(selectionChanged()),
+ this, TQT_SLOT(selectionChanged()));
+ connect(partAreaWidget, TQT_SIGNAL(currentChanged(TreeMapItem*, bool)),
+ this, TQT_SLOT(currentChangedSlot(TreeMapItem*, bool)));
+ connect(partAreaWidget, TQT_SIGNAL(doubleClicked(TreeMapItem*)),
+ this, TQT_SLOT(doubleClicked(TreeMapItem*)));
+ connect(partAreaWidget,
+ TQT_SIGNAL(contextMenuRequested(TreeMapItem*,const TQPoint &)),
+ this,
+ TQT_SLOT(contextMenuRequested(TreeMapItem*,const TQPoint &)));
+
+ _showInfo = true;
+ showInfo(false);
+}
+
+PartSelection::~PartSelection()
+{
+}
+
+void PartSelection::setData(TraceData* data)
+{
+ if (_data == data) return;
+
+ _data = data;
+ partAreaWidget->setData(data);
+ fillInfo();
+}
+
+
+void PartSelection::refresh()
+{
+ partAreaWidget->redraw();
+ fillInfo();
+}
+
+void PartSelection::setCostType(TraceCostType* ct)
+{
+ if (ct == _costType) return;
+ _costType = ct;
+
+ partAreaWidget->setCostType(ct);
+}
+
+void PartSelection::setCostType2(TraceCostType* ct)
+{
+ if (ct == _costType2) return;
+ _costType2 = ct;
+ if (!_diagramMode) return;
+
+ //TODO: get max cost(type1)/cost(type2) of shown parts
+ //partAreaWidget->setCostType(ct);
+}
+
+void PartSelection::setGroupType(TraceItem::CostType gt)
+{
+ if (gt == _groupType) return;
+ _groupType = gt;
+
+ partAreaWidget->setGroupType(gt);
+}
+
+void PartSelection::setGroup(TraceCostItem*)
+{
+}
+
+void PartSelection::setFunction(TraceFunction* f)
+{
+ if (_function == f) return;
+ _function = f;
+
+ //kdDebug() << "PartSelection::setFunction " << f->name() << endl;
+
+ // FIXME: The TreeMap shouldn't produce spurious selectionChanged events
+ _inSelectionUpdate = true;
+ partAreaWidget->setFunction(_function);
+ _inSelectionUpdate = false;
+}
+
+void PartSelection::setPart(TracePart*)
+{}
+
+void PartSelection::currentChangedSlot(TreeMapItem* i, bool kbd)
+{
+ if (!i) return;
+ if (!kbd) return;
+ if (i->text(0).isEmpty()) return;
+
+ TQString str = i->text(0);
+ if (!i->text(1).isEmpty())
+ str += " (" + i->text(1) + ")";
+ TQString msg = i18n("Profile Part Overview: Current is '%1'").arg(str);
+ emit showMessage(msg, 5000);
+
+ if (_showInfo) fillInfo();
+}
+
+
+void PartSelection::doubleClicked(TreeMapItem* i)
+{
+ if (!i || i->rtti() != 3) return;
+
+ TraceCost* c = ((SubPartItem*) i)->partCostItem();
+ TraceCostItem* ci = 0;
+
+ switch(c->type()) {
+ case TraceItem::PartFunction:
+ {
+ TraceFunction* f = ((TracePartFunction*)c)->function();
+ if (f)
+ emit functionChanged(f);
+ }
+ return;
+
+ case TraceItem::PartObject:
+ ci = ((TracePartObject*)c)->object();
+ break;
+ case TraceItem::PartClass:
+ ci = ((TracePartClass*)c)->cls();
+ break;
+ case TraceItem::PartFile:
+ ci = ((TracePartFile*)c)->file();
+ break;
+ default:
+ break;
+ }
+
+ if (ci)
+ emit groupChanged(ci);
+}
+
+
+void PartSelection::selectionChanged()
+{
+ if (_inSelectionUpdate) return;
+
+ kdDebug() << "PartSelection::selectionChanged" << endl;
+
+ bool something_changed = false;
+ bool nothingSelected = true;
+
+ TracePartList pList;
+ TreeMapItem* i;
+ TracePart* part;
+
+ // if nothing is selected, activate all parts
+ TreeMapItemList* list = partAreaWidget->base()->children();
+ if (!list) return;
+
+ for (i=list->first();i;i=list->next())
+ if (partAreaWidget->isSelected(i)) {
+ nothingSelected = false;
+ break;
+ }
+
+ for (i=list->first();i;i=list->next()) {
+ part = ((PartItem*)i)->part();
+ bool active = nothingSelected || partAreaWidget->isSelected(i);
+ if (active) {
+ pList.append(part);
+ something_changed = true;
+ }
+ }
+
+ if (something_changed) {
+ //qDebug("PartSelection: Something changed.");
+ emit activePartsChanged(pList);
+ }
+}
+
+/* this makes the graph selection the same to the parts in the list */
+void PartSelection::activePartsChangedSlot(const TracePartList& list)
+{
+ _inSelectionUpdate = true;
+
+ kdDebug() << "Entering PartSelection::activePartsChangedSlot" << endl;
+
+ TreeMapItem* i;
+ TreeMapItemList l = *partAreaWidget->base()->children();
+ // first deselect inactive, then select active (makes current active)
+ for (i=l.first();i;i=l.next()) {
+ TracePart* part = ((PartItem*)i)->part();
+ bool active = (list.containsRef(part)>0);
+ if (!active && partAreaWidget->isSelected(i)) {
+#if 0
+ qDebug("PartSelection::partsChangedSlot: Part %s changed to unselected.",
+ ((PartItem*)i)->part()->shortName().ascii());
+#endif
+
+ partAreaWidget->setSelected(i, false);
+ }
+ }
+ for (i=l.first();i;i=l.next()) {
+ TracePart* part = ((PartItem*)i)->part();
+ bool active = (list.containsRef(part)>0);
+ if (active && !partAreaWidget->isSelected(i)) {
+#if 0
+ qDebug("PartSelection::partsChangedSlot: Part %s changed to selected.",
+ ((PartItem*)i)->part()->shortName().ascii());
+#endif
+ partAreaWidget->setSelected(i, true);
+ }
+ }
+
+ _inSelectionUpdate = false;
+
+ kdDebug() << "Leaving PartSelection::activePartsChangedSlot" << endl;
+
+ fillInfo();
+}
+
+void PartSelection::contextMenuRequested(TreeMapItem* i,
+ const TQPoint & p)
+{
+ if (!i) return;
+
+ TQPopupMenu popup;
+ TQPopupMenu ppopup;
+ TQPopupMenu vpopup;
+
+ TQString str;
+ TreeMapItem* s = 0;
+
+ if (_data && (_data->parts().count()>1)) {
+ s = partAreaWidget->possibleSelection(i);
+ if (!s->text(0).isEmpty()) {
+ str = (partAreaWidget->isSelected(s)) ?
+ i18n("Deselect") : i18n("Select");
+ str += " '" + s->text(0) + "'";
+ popup.insertItem(str, 1);
+ }
+
+ popup.insertItem(i18n("Select All Parts"), 2);
+
+ popup.insertItem(i18n("Visible Parts"), &ppopup, 10);
+
+ ppopup.insertItem(i18n("Hide Selected Parts"), 3);
+ ppopup.insertItem(i18n("Unhide Hidden Parts"), 4);
+
+ popup.insertSeparator();
+ }
+
+ popup.insertItem(i18n("Go Back"), 99);
+ if (i->rtti() == 3) {
+ TreeMapItem* ni = i;
+ int id = 100;
+ while (ni && ni->rtti() == 3) {
+ TraceCost* c = ((SubPartItem*)ni)->partCostItem();
+ if (c->type() == TraceItem::PartFunction)
+ if ( ((TracePartFunction*)c)->function() == _function) break;
+
+ str = i18n("Select") + " '" + ni->text(0) + "'";
+ popup.insertItem(str, id);
+ ni = ni->parent();
+ id++;
+ }
+ }
+ popup.insertSeparator();
+
+ vpopup.setCheckable(true);
+ popup.insertItem(i18n("Visualization"), &vpopup, 10);
+
+ vpopup.insertItem(i18n("Partitioning Mode"), 30);
+ vpopup.insertItem(i18n("Diagram Mode"), 34);
+ vpopup.insertItem(i18n("Zoom Function"), 31);
+ vpopup.insertItem(i18n("Show Direct Calls"), 32);
+ vpopup.insertItem(i18n("Increment Shown Call Levels"), 33);
+ if (partAreaWidget->visualisation() == PartAreaWidget::Partitioning) {
+ vpopup.setItemChecked(30, true);
+ vpopup.setItemEnabled(31, false);
+ vpopup.setItemEnabled(32, false);
+ vpopup.setItemEnabled(33, false);
+ }
+ else {
+ vpopup.setItemChecked(31, partAreaWidget->zoomFunction());
+ }
+ vpopup.setItemChecked(34, _diagramMode);
+
+ vpopup.insertSeparator();
+
+ vpopup.insertItem(i18n("Draw Names"), 20);
+ vpopup.insertItem(i18n("Draw Costs"), 21);
+ vpopup.insertItem(i18n("Ignore Proportions"), 22);
+ vpopup.insertItem(i18n("Draw Frames"), 24);
+ vpopup.insertItem(i18n("Allow Rotation"), 23);
+ if (!partAreaWidget->fieldVisible(0) &&
+ !partAreaWidget->fieldVisible(1)) {
+ vpopup.setItemEnabled(22, false);
+ vpopup.setItemEnabled(23, false);
+ }
+ else {
+ vpopup.setItemChecked(20,partAreaWidget->fieldVisible(0));
+ vpopup.setItemChecked(21,partAreaWidget->fieldVisible(1));
+ vpopup.setItemChecked(22,partAreaWidget->fieldForced(0));
+ vpopup.setItemChecked(23,partAreaWidget->allowRotation());
+ vpopup.setItemChecked(24,_drawFrames);
+ }
+
+ if (_showInfo)
+ popup.insertItem(i18n("Hide Info"), 40);
+ else
+ popup.insertItem(i18n("Show Info"), 41);
+
+ int r = popup.exec(partAreaWidget->mapToGlobal(p));
+
+ if (r>=100) {
+ TreeMapItem* ci = i;
+ while (ci && r>100) {
+ ci = ci->parent();
+ r--;
+ }
+ doubleClicked(ci);
+ return;
+ }
+
+ switch(r) {
+ case 1:
+ // select/deselect part under mouse
+ partAreaWidget->setSelected(s, !partAreaWidget->isSelected(s));
+ break;
+
+ case 2:
+ // select all parts
+ {
+ TreeMapItemList list = *partAreaWidget->base()->children();
+ partAreaWidget->setRangeSelection(list.first(), list.last(), true);
+ }
+ break;
+
+ case 3:
+ emit partsHideSelected();
+ break;
+
+ case 4:
+ emit partsUnhideAll();
+ break;
+
+ case 99:
+ // last selected function
+ emit goBack();
+ break;
+
+ case 20:
+ partAreaWidget->setFieldVisible(0, !vpopup.isItemChecked(20));
+ break;
+
+ case 21:
+ partAreaWidget->setFieldVisible(1, !vpopup.isItemChecked(21));
+ break;
+
+ case 22:
+ partAreaWidget->setFieldForced(0, !vpopup.isItemChecked(22));
+ partAreaWidget->setFieldForced(1, !vpopup.isItemChecked(22));
+ break;
+
+ case 23: partAreaWidget->setAllowRotation(!vpopup.isItemChecked(23)); break;
+
+ case 24:
+ _drawFrames = !_drawFrames;
+ partAreaWidget->drawFrame(2,_drawFrames);
+ partAreaWidget->drawFrame(3,_drawFrames);
+ break;
+
+ case 30:
+ partAreaWidget->setVisualisation(!vpopup.isItemChecked(30) ?
+ PartAreaWidget::Partitioning :
+ PartAreaWidget::Inclusive);
+ break;
+
+ case 31:
+ // zoom/unzoom function
+ partAreaWidget->setZoomFunction(!vpopup.isItemChecked(31));
+ break;
+
+ case 32:
+ case 33:
+ // change call Levels
+ {
+ int l = (r==32) ? 1 : partAreaWidget->callLevels()+1;
+ partAreaWidget->setCallLevels(l);
+ }
+ break;
+
+ case 34:
+ _diagramMode = !_diagramMode;
+ partAreaWidget->setTransparent(2,_diagramMode);
+ break;
+
+
+ case 40:
+ case 41:
+ showInfo(r==41);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void PartSelection::hiddenPartsChangedSlot(const TracePartList& list)
+{
+ partAreaWidget->changeHidden(list);
+}
+
+void PartSelection::readVisualisationConfig(KConfigGroup* config)
+{
+ bool enable;
+
+ TQString mode = config->readEntry("PartitionMode", "Inclusive");
+ if (mode == "Inclusive")
+ partAreaWidget->setVisualisation(PartAreaWidget::Inclusive);
+ else
+ partAreaWidget->setVisualisation(PartAreaWidget::Partitioning);
+
+ _diagramMode = config->readBoolEntry("DiagramMode", false);
+ partAreaWidget->setTransparent(2,_diagramMode);
+
+ _drawFrames = config->readBoolEntry("DrawFrames", true);
+ partAreaWidget->drawFrame(2,_drawFrames);
+ partAreaWidget->drawFrame(3,_drawFrames);
+
+ enable = config->readBoolEntry("GraphZoom", false);
+ partAreaWidget->setZoomFunction(enable);
+
+ int levels = config->readNumEntry("GraphLevels", 1);
+ partAreaWidget->setCallLevels(levels);
+
+ enable = config->readBoolEntry("GraphDrawName", true);
+ partAreaWidget->setFieldVisible(0, enable);
+
+ enable = config->readBoolEntry("GraphDrawCost", true);
+ partAreaWidget->setFieldVisible(1, enable);
+
+ enable = config->readBoolEntry("GraphForceStrings", false);
+ partAreaWidget->setFieldForced(0, enable);
+ partAreaWidget->setFieldForced(1, enable);
+
+ enable = config->readBoolEntry("GraphAllowRotation", true);
+ partAreaWidget->setAllowRotation(enable);
+
+ showInfo(config->readBoolEntry("ShowInfo", false));
+}
+
+void PartSelection::saveVisualisationConfig(KConfigGroup* config)
+{
+ TQString mode;
+ if (partAreaWidget->visualisation() == PartAreaWidget::Inclusive)
+ mode = "Inclusive";
+ else
+ mode = "Partitioning";
+ config->writeEntry("PartitionMode", mode);
+
+ config->writeEntry("DiagramMode", _diagramMode);
+ config->writeEntry("DrawFrames", _drawFrames);
+
+ config->writeEntry("GraphZoom", partAreaWidget->zoomFunction());
+ config->writeEntry("GraphLevels", partAreaWidget->callLevels());
+ config->writeEntry("GraphDrawName", partAreaWidget->fieldVisible(0));
+ config->writeEntry("GraphDrawCosts", partAreaWidget->fieldVisible(1));
+ config->writeEntry("GraphForceStrings", partAreaWidget->fieldForced(0));
+ config->writeEntry("GraphAllowRotation", partAreaWidget->allowRotation());
+
+ config->writeEntry("ShowInfo", _showInfo);
+}
+
+void PartSelection::showInfo(bool enable)
+{
+ if (_showInfo == enable) return;
+
+ _showInfo = enable;
+ if (enable) {
+ rangeLabel->show();
+ fillInfo();
+ }
+ else
+ rangeLabel->hide();
+}
+
+void PartSelection::fillInfo()
+{
+ if (!_data) {
+ rangeLabel->setText(i18n("(no trace loaded)"));
+ return;
+ }
+
+ TQString info = _data->activePartRange();
+
+ TreeMapItem* i = partAreaWidget->current();
+ while (i && i->rtti()!=2) i = i->parent();
+ if (i) {
+ TracePart* part = ((PartItem*)i)->part();
+
+ //if (!part->trigger().isEmpty()) info += ", " + part->trigger();
+ if (!part->timeframe().isEmpty())
+ info += ", Time " + part->timeframe() + " BBs";
+ }
+ else {
+ TracePart* part = _data->parts().first();
+
+ if (part && !part->version().isEmpty())
+ info += ", Cachegrind " + part->version();
+ }
+
+
+ rangeLabel->setText(info);
+}
+
+#include "partselection.moc"