You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdesdk/tdecachegrind/tdecachegrind/partselection.cpp

568 lines
14 KiB

/* 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) {
//tqDebug("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
tqDebug("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
tqDebug("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(TDEConfigGroup* 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(TDEConfigGroup* 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"