File indexing completed on 2024-04-28 05:41:38

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  * Trace Item View
0011  */
0012 
0013 #include "traceitemview.h"
0014 
0015 #include <QtGlobal>
0016 #include <QWidget>
0017 
0018 #include "toplevelbase.h"
0019 
0020 #define TRACE_UPDATES 0
0021 
0022 
0023 // TraceItemViewUpdateTimer
0024 
0025 TraceItemViewUpdateTimer::TraceItemViewUpdateTimer(TraceItemView* view)
0026 {
0027     _view = view;
0028     setSingleShot(true);
0029     connect(this, &QTimer::timeout, this, &TraceItemViewUpdateTimer::timeoutTriggered);
0030 }
0031 
0032 void TraceItemViewUpdateTimer::timeoutTriggered()
0033 {
0034     _view->triggerUpdate(false);
0035 }
0036 
0037 // TraceItemView
0038 
0039 TraceItemView::TraceItemView(TraceItemView* parentView, TopLevelBase* top)
0040 {
0041     _parentView = parentView;
0042     _topLevel = top ? top : parentView->topLevel();
0043 
0044     _data = _newData = nullptr;
0045     // _partList and _newPartList is empty
0046     _activeItem = _newActiveItem = nullptr;
0047     _selectedItem = _newSelectedItem = nullptr;
0048     _eventType = _newEventType = nullptr;
0049     _eventType2 = _newEventType2 = nullptr;
0050     _groupType = _newGroupType = ProfileContext::InvalidType;
0051 
0052     _status = nothingChanged;
0053     _needsUpdate = false;
0054     _pos = Hidden;
0055 
0056     _mergeUpdates = true;
0057     _updateTimer = new TraceItemViewUpdateTimer(this);
0058 }
0059 
0060 TraceItemView::~TraceItemView()
0061 {
0062     delete _updateTimer;
0063 }
0064 
0065 QString TraceItemView::whatsThis() const
0066 {
0067     return QObject::tr("No description available");
0068 }
0069 
0070 void TraceItemView::select(CostItem* i)
0071 {
0072     if (_selectedItem == i) return;
0073 
0074     _newSelectedItem = i;
0075     updateView();
0076 }
0077 
0078 void TraceItemView::saveLayout(const QString&, const QString&)
0079 {
0080 #if 0
0081     qDebug("In '%s', saveLayout not implemented",
0082            widget()->name());
0083 #endif
0084 }
0085 
0086 void TraceItemView::saveOptions(const QString&, const QString&)
0087 {
0088 #if 0
0089     qDebug("In '%s', saveOptions not implemented",
0090            widget()->name());
0091 #endif
0092 }
0093 
0094 void TraceItemView::restoreLayout(const QString&, const QString&)
0095 {}
0096 
0097 void TraceItemView::restoreOptions(const QString&, const QString&)
0098 {}
0099 
0100 
0101 bool TraceItemView::activate(CostItem* i)
0102 {
0103     _newActiveItem = canShow(i);
0104     if (_activeItem != _newActiveItem) {
0105         // new item activated, start with empty selection
0106         _newSelectedItem = nullptr;
0107         updateView();
0108     }
0109 
0110     return (_newActiveItem != nullptr);
0111 }
0112 
0113 TraceFunction* TraceItemView::activeFunction()
0114 {
0115     if (!_activeItem) return nullptr;
0116 
0117     ProfileContext::Type t = _activeItem->type();
0118     switch(t) {
0119     case ProfileContext::Function:
0120     case ProfileContext::FunctionCycle:
0121         return (TraceFunction*) _activeItem;
0122     default:
0123         break;
0124     }
0125     return nullptr;
0126 }
0127 
0128 bool TraceItemView::set(int changeType, TraceData* d,
0129                         EventType* t1, EventType* t2,
0130                         ProfileContext::Type g, const TracePartList& l,
0131                         CostItem* a, CostItem* s)
0132 {
0133     _status |= changeType;
0134     _newData = d;
0135     _newGroupType = g;
0136     _newEventType = t1;
0137     _newEventType2 = t2;
0138     _newPartList = l;
0139     _newSelectedItem = s;
0140     _newActiveItem = canShow(a);
0141     if (_activeItem != _newActiveItem) {
0142         // new item activated, start with empty selection
0143         _newSelectedItem = nullptr;
0144     }
0145     updateView();
0146 
0147     return (_newActiveItem != nullptr);
0148 }
0149 
0150 
0151 bool TraceItemView::isViewVisible()
0152 {
0153     QWidget* w = widget();
0154     if (w)
0155         return w->isVisible();
0156     return false;
0157 }
0158 
0159 void TraceItemView::setData(TraceData* d)
0160 {
0161     if (_data == d) return;
0162     _newData = d;
0163 
0164     // invalidate all pointers to old data
0165     _activeItem = _newActiveItem = nullptr;
0166     _selectedItem = _newSelectedItem = nullptr;
0167     _eventType = _newEventType = nullptr;
0168     _eventType2 = _newEventType2 = nullptr;
0169     _groupType = _newGroupType = ProfileContext::InvalidType;
0170     _partList.clear();
0171     _newPartList.clear();
0172 
0173     // updateView will change this to dataChanged
0174     _status = nothingChanged;
0175     updateView();
0176 }
0177 
0178 // force: update immediately even if invisible and no change was detected
0179 void TraceItemView::updateView(bool force)
0180 {
0181     if (!_mergeUpdates || force) {
0182         _needsUpdate = true;
0183         _updateTimer->stop();
0184         triggerUpdate(force);
0185         return;
0186     }
0187 
0188     // if _needsUpdate is true, an update is already scheduled
0189     if (_needsUpdate) return;
0190 
0191     _needsUpdate = true;
0192     _updateTimer->start(1);
0193 }
0194 
0195 
0196 void TraceItemView::triggerUpdate(bool force)
0197 {
0198     // If already updated no need to update again.
0199     // This can happen if a update by timer is scheduled, but a "force"d
0200     // update is done before the timer triggers
0201     if (!_needsUpdate) return;
0202     _needsUpdate = false;
0203 
0204     if (!force) {
0205         if (!isViewVisible()) return;
0206     }
0207 
0208     if (_newData != _data) {
0209         _status |= dataChanged;
0210         _data = _newData;
0211     }
0212     else {
0213         _status &= ~dataChanged;
0214 
0215         // if there is no data change and data is 0, no update needed
0216         if (!_data) return;
0217     }
0218 
0219     if (!(_newPartList == _partList)) {
0220         _status |= partsChanged;
0221         _partList = _newPartList;
0222     }
0223     else
0224         _status &= ~partsChanged;
0225 
0226     if (_newActiveItem != _activeItem) {
0227 
0228         // when setting a new active item, there is no selection
0229         _selectedItem = nullptr;
0230 
0231         _status |= activeItemChanged;
0232         _activeItem = _newActiveItem;
0233     }
0234     else
0235         _status &= ~activeItemChanged;
0236 
0237     if (_newEventType != _eventType) {
0238         _status |= eventTypeChanged;
0239         _eventType = _newEventType;
0240     }
0241     else
0242         _status &= ~eventTypeChanged;
0243 
0244     if (_newEventType2 != _eventType2) {
0245         _status |= eventType2Changed;
0246         _eventType2 = _newEventType2;
0247     }
0248     else
0249         _status &= ~eventType2Changed;
0250 
0251     if (_newGroupType != _groupType) {
0252         _status |= groupTypeChanged;
0253         _groupType = _newGroupType;
0254     }
0255     else
0256         _status &= ~groupTypeChanged;
0257 
0258 
0259     if (_newSelectedItem != _selectedItem) {
0260         _status |= selectedItemChanged;
0261         _selectedItem = _newSelectedItem;
0262     }
0263     else
0264         _status &= ~selectedItemChanged;
0265 
0266 
0267     if (!force && (_status == nothingChanged)) return;
0268 
0269 #if TRACE_UPDATES
0270     qDebug("%s::doUpate",
0271            widget() ? qPrintable(widget()->objectName()) : "TraceItemView");
0272 
0273     if (_status & dataChanged)
0274         qDebug("  data changed");
0275 
0276     if (_status & configChanged)
0277         qDebug("  config changed");
0278 
0279     if (_status & partsChanged)
0280         qDebug("  parts changed: %s", qPrintable(_partList[0]->name()) );
0281 
0282     if (_status & eventTypeChanged)
0283         qDebug("  event type 1 changed: %s",
0284                _eventType ? qPrintable( _eventType->name() ) : "(None)");
0285 
0286     if (_status & eventType2Changed)
0287         qDebug("  event type 2 changed: %s",
0288                _eventType2 ? qPrintable( _eventType2->name() ) : "(None)");
0289 
0290     if (_status & groupTypeChanged)
0291         qDebug("  group type changed: %s",
0292                qPrintable(ProfileContext::typeName(_groupType)));
0293 
0294     if (_status & activeItemChanged)
0295         qDebug("  active item changed: %s",
0296                _activeItem ? qPrintable( _activeItem->fullName() ) : "(none)");
0297 
0298     if (_status & selectedItemChanged)
0299         qDebug("  selected item changed: %s",
0300                _selectedItem ? qPrintable( _selectedItem->fullName() ) : "(none)");
0301 #endif
0302 
0303     int st = _status;
0304     _status = nothingChanged;
0305     doUpdate(st, force);
0306 }
0307 
0308 
0309 void TraceItemView::selected(TraceItemView* /*sender*/, CostItem* i)
0310 {
0311 #if 0 // TRACE_UPDATES
0312     qDebug("%s::selected( item %s, sender %s )",
0313            widget() ? qPrintable(widget()->objectName()) : "TraceItemView",
0314            i ? qPrintable( i->name() ): "(none)",
0315            qPrintable(sender->widget()->objectName()) );
0316 #endif
0317 
0318     if (_parentView) _parentView->selected(this, i);
0319 }
0320 
0321 void TraceItemView::partsSelected(TraceItemView* /*sender*/, const TracePartList& l)
0322 {
0323 #if 0 // TRACE_UPDATES
0324     qDebug() << (widget() ? widget()->name() : "TraceItemView")
0325              << "::selected "
0326              << l.names()
0327              << ", sender "
0328              << sender->widget()->name();
0329 #endif
0330 
0331     if (_parentView)
0332         _parentView->partsSelected(this, l);
0333     else
0334         if (_topLevel) _topLevel->activePartsChangedSlot(l);
0335 }
0336 
0337 void TraceItemView::activated(TraceItemView* /*sender*/, CostItem* i)
0338 {
0339 #if 0 // TRACE_UPDATES
0340     qDebug("%s::activated( item %s, sender %s )",
0341            widget() ? qPrintable(widget()->objectName()) : "TraceItemView",
0342            i ? qPrintable( i->name() ): "(none)",
0343            qPrintable(sender->widget()->objectName()) );
0344 #endif
0345 
0346     if (_parentView)
0347         _parentView->activated(this, i);
0348     else
0349         if (_topLevel) _topLevel->setTraceItemDelayed(i);
0350 }
0351 
0352 void TraceItemView::selectedEventType(TraceItemView*, EventType* t)
0353 {
0354     if (_parentView)
0355         _parentView->selectedEventType(this, t);
0356     else
0357         if (_topLevel) _topLevel->setEventTypeDelayed(t);
0358 }
0359 
0360 void TraceItemView::selectedEventType2(TraceItemView*, EventType* t)
0361 {
0362     if (_parentView)
0363         _parentView->selectedEventType2(this, t);
0364     else
0365         if (_topLevel) _topLevel->setEventType2Delayed(t);
0366 }
0367 
0368 void TraceItemView::selectedGroupType(TraceItemView*, ProfileContext::Type t)
0369 {
0370     if (_parentView)
0371         _parentView->selectedGroupType(this, t);
0372     else
0373         if (_topLevel) _topLevel->setGroupTypeDelayed(t);
0374 }
0375 
0376 
0377 void TraceItemView::directionActivated(TraceItemView*, TraceItemView::Direction d)
0378 {
0379     if (_parentView)
0380         _parentView->directionActivated(this, d);
0381     else
0382         if (_topLevel) _topLevel->setDirectionDelayed(d);
0383 }
0384 
0385 void TraceItemView::doUpdate(int, bool)
0386 {
0387 }
0388 
0389 void TraceItemView::selected(CostItem* i)
0390 {
0391 #if TRACE_UPDATES
0392     qDebug("%s::selected( item %s )",
0393            widget() ? qPrintable(widget()->objectName()) : "TraceItemView",
0394            i ? qPrintable( i->name() ): "(none)" );
0395 #endif
0396 
0397     if (_parentView)
0398         _parentView->selected(this, i);
0399 
0400 }
0401 
0402 void TraceItemView::partsSelected(const TracePartList& l)
0403 {
0404     if (_parentView)
0405         _parentView->partsSelected(this, l);
0406     else
0407         if (_topLevel) _topLevel->activePartsChangedSlot(l);
0408 }
0409 
0410 void TraceItemView::activated(CostItem* i)
0411 {
0412 #if TRACE_UPDATES
0413     qDebug("%s::activated( item %s )",
0414            widget() ? qPrintable(widget()->objectName()) : "TraceItemView",
0415            i ? qPrintable( i->name() ): "(none)" );
0416 #endif
0417 
0418     if (_parentView)
0419         _parentView->activated(this, i);
0420     else
0421         if (_topLevel) _topLevel->setTraceItemDelayed(i);
0422 }
0423 
0424 void TraceItemView::selectedEventType(EventType* t)
0425 {
0426     if (_parentView)
0427         _parentView->selectedEventType(this, t);
0428     else
0429         if (_topLevel) _topLevel->setEventTypeDelayed(t);
0430 }
0431 
0432 void TraceItemView::selectedEventType2(EventType* t)
0433 {
0434     if (_parentView)
0435         _parentView->selectedEventType2(this, t);
0436     else
0437         if (_topLevel) _topLevel->setEventType2Delayed(t);
0438 }
0439 
0440 void TraceItemView::selectedGroupType(ProfileContext::Type t)
0441 {
0442     if (_parentView)
0443         _parentView->selectedGroupType(this, t);
0444     else
0445         if (_topLevel) _topLevel->setGroupTypeDelayed(t);
0446 }
0447 
0448 void TraceItemView::directionActivated(TraceItemView::Direction d)
0449 {
0450     if (_parentView)
0451         _parentView->directionActivated(this, d);
0452     else
0453         if (_topLevel) _topLevel->setDirectionDelayed(d);
0454 }
0455 
0456 void TraceItemView::addEventTypeMenu(QMenu* p, bool withCost2)
0457 {
0458     if (_topLevel) _topLevel->addEventTypeMenu(p, withCost2);
0459 }
0460 
0461 void TraceItemView::addGoMenu(QMenu* p)
0462 {
0463     if (_topLevel) _topLevel->addGoMenu(p);
0464 }
0465 
0466 #include "moc_traceitemview.cpp"