Cube GUI Plugin User Guide  (CubeGUI 4.6, revision ff50a50d)
How to develop a Cube GUI Plugin, road map and examples
/****************************************************************************
** CUBE http://www.scalasca.org/ **
*****************************************************************************
** Copyright (c) 1998-2021 **
** Forschungszentrum Juelich GmbH, Juelich Supercomputing Centre **
** **
** This software may be modified and distributed under the terms of **
** a BSD-style license. See the COPYING file in the package base **
** directory for details. **
****************************************************************************/
#include <QVBoxLayout>
#include <QtPlugin>
#include "DemoPlugin.h"
#include "PluginServices.h"
#include "TreeItemMarker.h"
using namespace cubepluginapi;
using namespace demoplugin;
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2( DemoPlugin, DemoPlugin );
#endif
/******************************************************************************************************
* CubePlugin implementation
* start with cube -verbose to see debug output
******************************************************************************************************/
DemoPlugin::DemoPlugin()
{
// The constructor should be empty, use cubeOpened to initialize. If Qt widgets or
// signals/slots are used in constructor, they have to be deleted in destructor,
// otherwise cube may crash if the plugin is unloaded.
}
void
DemoPlugin::version( int& major, int& minor, int& bugfix ) const
{
major = 1;
minor = 0;
bugfix = 0;
}
QString
DemoPlugin::name() const
{
return "Simple Demo";
}
QString
DemoPlugin::getHelpText() const
{
return "Just a simple demo plugin";
}
bool
DemoPlugin::cubeOpened( PluginServices* service )
{
this->service = service;
widget_ = new QWidget();
QVBoxLayout* layout = new QVBoxLayout();
layout->addSpacing( 20 );
qlabel_ = new QLabel( "Selected tree item:" );
layout->addWidget( qlabel_ );
layout->addWidget( new QLabel( "Text to be saved in settings:" ) );
lineEdit_ = new QLineEdit();
lineEdit_->setToolTip( "If File->Settings->Restore last state is active, the text ist persistant. The state is also saved in bookmarks." );
layout->addWidget( lineEdit_ );
layout->addStretch( 1 );
widget_->setLayout( layout );
// add tab to the system tab widget with the label this->label() and content this->widget()
service->addTab( SYSTEM, this );
// add menu item and submenu to the Plugin Menu
QMenu* menu = service->enablePluginMenu();
QAction* menuAction = menu->addAction( "Demo Menu Item" );
connect( menuAction, SIGNAL( triggered() ), this, SLOT( menuItemIsSelected() ) );
// registered plugins may load and save settings
service->addSettingsHandler( this );
// react on signals emitted by PluginServices
connect( service, SIGNAL( contextMenuIsShown( cubepluginapi::DisplayType, cubepluginapi::TreeItem* ) ),
this, SLOT( contextMenuIsShown( cubepluginapi::DisplayType, cubepluginapi::TreeItem* ) ) );
connect( service, SIGNAL( globalValueChanged( QString ) ),
this, SLOT( globalValueChanged( QString ) ) );
connect( service, SIGNAL( orderHasChanged( const QList<cubepluginapi::DisplayType> & ) ),
this, SLOT( orderHasChanged( const QList<cubepluginapi::DisplayType> & ) ) );
connect( service, SIGNAL( genericUserAction( cubepluginapi::UserAction ) ),
this, SLOT( checkLoop( cubepluginapi::UserAction ) ) );
defineTreeItemMarker();
return true; // initialisation is ok => plugin should be shown
}
void
DemoPlugin::cubeClosed()
{
delete widget_;
markerList.clear();
}
/******************************************************************************************************
* start of TabInterface implementation
******************************************************************************************************/
QString
DemoPlugin::label() const
{
return "Demo Plugin Tab";
}
QIcon
DemoPlugin::icon() const
{
return QIcon( ":/icon.png" );
}
QWidget*
DemoPlugin::widget()
{
return widget_;
}
void
DemoPlugin::setActive( bool active )
{
if ( active )
{
connect( service, SIGNAL( treeItemIsSelected( cubepluginapi::TreeItem* ) ),
this, SLOT( treeItemIsSelected( cubepluginapi::TreeItem* ) ) );
QString txt = service->getSelection( METRIC )->getName();
// debug messages are printed on status line and stdout if cube is started with -verbose
service->debug() << "setActive: last selected metric: " << txt << Qt::endl;
}
else
{
service->disconnect( SIGNAL( treeItemIsSelected( cubepluginapi::TreeItem* ) ) );
}
}
void
DemoPlugin::valuesChanged()
{
// debug messages are written to console and to the extended status bar (click on status bar) if cube is started with -verbose
service->debug() << "valuesChanged" << Qt::endl;
}
QSize
DemoPlugin::sizeHint() const
{
return QSize( 100, 100 );
}
void
DemoPlugin::valueModusChanged( ValueModus modus )
{
service->debug() << "valueModusChanged " << modus << Qt::endl;
}
/******************************************************************************************************
* implementation of slots to handle signals of PluginServices
******************************************************************************************************/
void
DemoPlugin::contextMenuIsShown( cubepluginapi::DisplayType type, TreeItem* item )
{
if ( !item )
{
return;
}
contextItem = item;
contextType = type;
QAction* contextAction = service->addContextMenuItem( type, "demo context menu item (no action)" );
QString text;
QTextStream st( &text );
st << "context for tree type " << item->getDisplayType() << " label " << item->getName();
connect( contextAction, SIGNAL( triggered() ), new DemoSlot( text ), SLOT( print() ) );
for ( int idx = 0; idx < markerList.size() / 2; idx++ )
{
contextAction = service->addContextMenuItem( type, "add marker " + QString::number( idx ) );
contextAction->setProperty( "index", idx );
connect( contextAction, SIGNAL( triggered() ), this, SLOT( setMarker() ) );
}
for ( int idx = markerList.size() / 2; idx < markerList.size(); idx++ )
{
contextAction = service->addContextMenuItem( type, "add marker for current selection " + QString::number( idx ) );
contextAction->setProperty( "index", idx );
connect( contextAction, SIGNAL( triggered() ), this, SLOT( setMarkerWithDependencies() ) );
}
service->setMessage( "context menu is shown" ); // write the message to status bar
}
void
DemoPlugin::setMarker()
{
int index = sender()->property( "index" ).toInt();
service->addMarker( contextItem, markerList.at( index ) );
service->updateTreeView( contextType );
}
void
DemoPlugin::setMarkerWithDependencies()
{
int index = sender()->property( "index" ).toInt();
// set example marker which consists of the 3 items of the current selection
// dependencies are automatically marked
service->addMarker( markerList.at( index ),
service->getSelection( METRIC ),
service->getSelection( CALL ),
service->getSelection( SYSTEM ) );
}
void
DemoPlugin::defineTreeItemMarker()
{
QStringList images;
images << ":images/left_small.png" << ":images/right_small.png" << ":images/up_small.png" << ":images/down_small.png";
for ( int i = 0; i < images.size(); i++ )
{
QList<QPixmap> icons;
icons.append( QPixmap( images.at( i ) ) );
bool insignificantMarker = i == images.size() - 1 ? 1 : 0; // last marker marks insignificant items
if ( insignificantMarker )
{
markerList.append( service->getTreeItemMarker( "insignificant marker", icons, true ) );
}
else
{
markerList.append( service->getTreeItemMarker( "marker" + QString::number( i ), icons ) );
}
}
}
void
DemoPlugin::treeItemIsSelected( TreeItem* item )
{
// use formatNumber() to format value according to user settings in Display->Precision
QString txt = item->getName() + " " + service->formatNumber( item->getValue() );
qlabel_->setText( "Selected tree item: " + txt );
service->debug() << "treeItemIsSelected " << txt << item->getCubeObject() << Qt::endl;
/* handle special case: item is a loop in the call tree, which may be aggregated */
if ( item->isAggregatedLoopItem() )
{
QList<cube::Cnode*> iterations = ( static_cast<AggregatedTreeItem*> ( item ) )->getIterations();
int min = std::min( 10, iterations.size() );
if ( min > 0 )
{
service->debug() << "selected loop item: cnode_ids of first 10 iterations:" << Qt::endl;
}
for ( int i = 0; i < min; i++ )
{
cube::Cnode* cnode = iterations.at( i );
service->debug() << cnode->get_id() << Qt::endl;
}
}
if ( item->getCubeObject() == 0 )
{
service->debug() << "selected aggregated item" << item->getName() << Qt::endl;
}
else
{
cube::Cnode* cnode = static_cast<cube::Cnode*> ( item->getCubeObject() );
service->debug() << "selected single item: " << cnode->get_id() << Qt::endl;
}
}
void
DemoPlugin::orderHasChanged( const QList<DisplayType>& order )
{
service->debug() << "orderHasChanged user has changed the dimension order" << Qt::endl;
// example: disable demo plugin, if system widget is first
bool enabled = order.at( 0 ) != SYSTEM;
service->enableTab( this, enabled );
}
void
DemoPlugin::globalValueChanged( const QString& name )
{
service->debug() << "globalValueChanged " << name << service->getGlobalValue( "testVal" ).toString() << Qt::endl;
}
void
DemoPlugin::menuItemIsSelected()
{
service->debug() << "menu item is selected and global value incremented" << Qt::endl;
// increment global value "testVal", which can also used by other plugins
int val = service->getGlobalValue( "testVal" ).toInt();
service->setGlobalValue( "testVal", QVariant( ++val ), true ); // true = notify myself
}
void
DemoPlugin::checkLoop( UserAction type )
{
if ( type == LoopMarkAction )
{
service->debug() << "user has marked tree item as loop" << Qt::endl;
}
}
/******************************************************************************************************
* implementation of settings to save the state of the plugin
******************************************************************************************************/
void
DemoPlugin::loadGlobalSettings( QSettings& settings )
{
int numCalls = settings.value( "DemoPluginCalls", 0 ).toInt();
service->debug() << "load global Settings: " << numCalls << Qt::endl;
}
void
DemoPlugin::saveGlobalSettings( QSettings& settings )
{
int numCalls = settings.value( "DemoPluginCalls", 0 ).toInt(); // 0 is default, if no value exists
settings.setValue( "DemoPluginCalls", ++numCalls );
}
void
DemoPlugin::loadExperimentSettings( QSettings& settings )
{
lineEdit_->setText( settings.value( "Text", "Text to be saved" ).toString() );
}
void
DemoPlugin::saveExperimentSettings( QSettings& settings )
{
settings.setValue( "Text", lineEdit_->text() );
}
QString
DemoPlugin::settingName()
{
return "DemoPlugin";
}

Cube Writer Library    Copyright © 1998–2021 Forschungszentrum Jülich GmbH, Jülich Supercomputing Centre
Copyright © 2009–2015 German Research School for Simulation Sciences GmbH, Laboratory for Parallel Programming