Add complete support for Equipotential selection in the Controller.

This commit is contained in:
Jean-Paul Chaput 2023-03-26 21:15:15 +02:00
parent e5d9c8808b
commit a0911be50a
14 changed files with 905 additions and 9 deletions

View File

@ -18,12 +18,19 @@
set( pyIncludes tramontana/PyTramontanaEngine.h
tramontana/PyGraphicTramontanaEngine.h
)
set( mocIncludes tramontana/GraphicTramontanaEngine.h )
set( mocIncludes tramontana/GraphicTramontanaEngine.h
tramontana/EquipotentialsModel.h
tramontana/EquipotentialsWidget.h
tramontana/TabEquipotentials.h
)
set( cpps Tile.cpp
SweepLine.cpp
Equipotential.cpp
TramontanaEngine.cpp
GraphicTramontanaEngine.cpp
EquipotentialsModel.cpp
EquipotentialsWidget.cpp
TabEquipotentials.cpp
)
set( pyCpps PyTramontana.cpp
PyTramontanaEngine.cpp

View File

@ -17,6 +17,7 @@
#include <iomanip>
#include <set>
#include "hurricane/utilities/Path.h"
#include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h"
@ -39,6 +40,32 @@
#include "tramontana/TramontanaEngine.h"
namespace {
using Hurricane::Net;
class NetCompareByName {
public:
bool operator() ( const Net* lhs, const Net* rhs ) const;
};
bool NetCompareByName::operator() ( const Net* lhs, const Net* rhs ) const
{
if (lhs->isFused () != rhs->isFused ()) return rhs->isFused();
if (lhs->isAutomatic() != rhs->isAutomatic()) return rhs->isAutomatic();
if (lhs->isGlobal () != rhs->isGlobal ()) return rhs->isGlobal();
if (lhs->getName().size() != rhs->getName().size())
return lhs->getName().size() < rhs->getName().size();
return lhs->getName() < rhs->getName();
}
} // Anonymous namespace.
namespace Tramontana {
using std::cout;
@ -54,6 +81,7 @@ namespace Tramontana {
using std::ostringstream;
using std::setprecision;
using std::vector;
using std::set;
using std::make_pair;
using Hurricane::dbo_ptr;
using Hurricane::UpdateSession;
@ -66,6 +94,7 @@ namespace Tramontana {
using Hurricane::Box;
using Hurricane::Layer;
using Hurricane::Entity;
using Hurricane::Net;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::RoutingPad;
@ -77,11 +106,20 @@ namespace Tramontana {
// Class : "Tramontana::Equipotential".
const char* defaultName = "Unamed (please call consolidate())";
Equipotential::Equipotential ( Cell* owner )
: _owner (owner)
, _boundingBox()
, _components ()
, _childs ()
, _name (defaultName)
, _type (Net::Type::UNDEFINED)
, _direction (Net::Direction::DirUndefined)
, _isExternal (false)
, _isGlobal (false)
, _isAutomatic(false)
{ }
@ -154,6 +192,34 @@ namespace Tramontana {
}
void Equipotential::consolidate ()
{
int containsFused = 0;
set<Net*,NetCompareByName> nets;
for ( Component* component : getComponents() ) {
Net* net = component->getNet();
if (net->isFused ()) containsFused = 1;
if (net->isExternal ()) _isExternal = true;
if (net->isGlobal ()) _isGlobal = true;
if (net->isAutomatic()) _isAutomatic = true;
_type = net->getType();
_direction |= net->getDirection();
nets.insert( component->getNet() );
}
_name = getString( (*nets.begin())->getName() );
_name += " [" + getString(nets.size() - containsFused);
if (containsFused)
_name += "+fused";
_name += "] ";
_name += ((_isExternal ) ? "e" : "-");
_name += ((_isGlobal ) ? "g" : "-");
_name += ((_isAutomatic) ? "a" : "-");
_name += " ";
_name += getString(_type ) + " ";
_name += getString(_direction);
}
void Equipotential::clear ()
{
_components.clear();
@ -168,7 +234,9 @@ namespace Tramontana {
string Equipotential::_getString () const
{
ostringstream os;
os << "<Equipotential id:" << getId() << " " << _owner->getName() << ">";
os << "<Equipotential id:" << getId()
//<< " " << getName()
<< " " << _owner->getName() << ">";
return os.str();
}
@ -181,6 +249,7 @@ namespace Tramontana {
record->add( getSlot( "_boundingBox", &_boundingBox ) );
record->add( getSlot( "_components" , &_components ) );
record->add( getSlot( "_childs" , &_childs ) );
//record->add( getSlot( "_name" , &_name ) );
}
return record;
}

View File

@ -0,0 +1,124 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | T r a m o n t a n a - Extractor & LVX |
// | |
// | Algorithm : Christian MASSON |
// | First impl. : Yifei WU |
// | Second impl. : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./EquipotentialsModel.cpp" |
// +-----------------------------------------------------------------+
#include <QFont>
#include <QApplication>
#include "hurricane/Name.h"
#include "hurricane/Net.h"
#include "hurricane/Cell.h"
#include "hurricane/viewer/Graphics.h"
#include "tramontana/EquipotentialsModel.h"
namespace Tramontana {
using Hurricane::Graphics;
EquipotentialsModel::EquipotentialsModel ( QObject* parent )
: QAbstractTableModel(parent)
, _cell (nullptr)
, _equipotentials ()
{ }
QVariant EquipotentialsModel::data ( const QModelIndex& index, int role ) const
{
static QFont nameFont = Graphics::getFixedFont ( QFont::Bold );
static QFont valueFont = Graphics::getFixedFont ( QFont::Normal, true );
if (role == Qt::FontRole) {
if (index.row() == 0) return QVariant();
switch (index.column()) {
case 0: return nameFont;
default: return valueFont;
}
return QVariant();
}
if (not index.isValid()) return QVariant ();
if (role == Qt::DisplayRole) {
int row = index.row ();
return QString::fromStdString( _equipotentials[row]->getName() );
}
return QVariant();
}
QVariant EquipotentialsModel::headerData ( int section
, Qt::Orientation orientation
, int role ) const
{
if (orientation == Qt::Vertical) return QVariant();
static QFont headerFont = Graphics::getFixedFont( QFont::Bold, false, false, +0 );
if (role == Qt::FontRole ) return headerFont;
if (role != Qt::DisplayRole) return QVariant();
if (section == 0) return QVariant("Equipotential");
// if (section < _equipotentials->getColumnCount())
// return _equipotentials->getColumnName( section );
return QVariant();
}
int EquipotentialsModel::rowCount ( const QModelIndex& parent ) const
{
return _equipotentials.size();
}
int EquipotentialsModel::columnCount ( const QModelIndex& parent ) const
{
return 1;
//return (_equipotentials) ? _equipotentials->getColumnCount() : 1;
}
const Equipotential* EquipotentialsModel::getEqui ( int row )
{
if (row >= (int)_equipotentials.size()) return nullptr;
return _equipotentials[ row ];
}
void EquipotentialsModel::setCell ( Cell* cell )
{
if (_cell != cell) {
emit layoutAboutToBeChanged ();
if (_cell) _equipotentials.clear();
_cell = cell;
if (_cell) {
TramontanaEngine* tramontana = TramontanaEngine::get( _cell );
if (tramontana) {
for ( Equipotential* equi : tramontana->getEquipotentials() )
_equipotentials.push_back( equi );
}
}
emit layoutChanged ();
}
}
} // Tramontana namespace.

View File

@ -0,0 +1,230 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | T r a m o n t a n a - Extractor & LVX |
// | |
// | Algorithm : Christian MASSON |
// | First impl. : Yifei WU |
// | Second impl. : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./EquipotentialsWidget.cpp" |
// +-----------------------------------------------------------------+
#include <QFontMetrics>
#include <QLabel>
#include <QLineEdit>
#include <QHeaderView>
#include <QKeyEvent>
#include <QGroupBox>
#include <QVBoxLayout>
#include <QAction>
#include <QModelIndex>
#include "hurricane/Commons.h"
#include "hurricane/viewer/Graphics.h"
#include "tramontana/EquipotentialsModel.h"
#include "tramontana/EquipotentialsWidget.h"
namespace Tramontana {
using std::cerr;
using std::endl;
using Hurricane::Bug;
using Hurricane::Graphics;
EquipotentialsWidget::EquipotentialsWidget ( QWidget* parent )
: QWidget (parent)
, _cellWidget (NULL)
, _cell (NULL)
, _baseModel (new EquipotentialsModel(this))
, _sortModel (new QSortFilterProxyModel(this))
, _view (new QTableView(this))
, _rowHeight (20)
, _selecteds ()
, _forceReselect(false)
{
setAttribute( Qt::WA_DeleteOnClose );
setAttribute( Qt::WA_QuitOnClose, false );
setContextMenuPolicy( Qt::ActionsContextMenu );
_rowHeight = QFontMetrics( Graphics::getFixedFont() ).height() + 4;
_sortModel->setSourceModel ( _baseModel );
_sortModel->setDynamicSortFilter( true );
_sortModel->setFilterKeyColumn ( 0 );
_view->setShowGrid ( false );
_view->setAlternatingRowColors( true );
_view->setSelectionBehavior ( QAbstractItemView::SelectRows );
_view->setSortingEnabled ( true );
_view->setModel ( _sortModel );
QHeaderView* horizontalHeader = _view->horizontalHeader();
horizontalHeader->setDefaultAlignment ( Qt::AlignHCenter );
horizontalHeader->setMinimumSectionSize( (Graphics::isHighDpi()) ? 300 : 150 );
horizontalHeader->setStretchLastSection( true );
QHeaderView* verticalHeader = _view->verticalHeader();
verticalHeader->setVisible( false );
verticalHeader->setDefaultSectionSize( _rowHeight );
// verticalHeader->setStyleSheet( "QHeaderView::section {"
// "padding-bottom: 0px;"
// "padding-top: 0px;"
// "padding-left: 0px;"
// "padding-right: 1px;"
// "margin: 0px;"
// "}"
// );
_filterPatternLineEdit = new QLineEdit( this );
QLabel* filterPatternLabel = new QLabel( tr("&Filter pattern:"), this );
filterPatternLabel->setBuddy( _filterPatternLineEdit );
QGridLayout* gLayout = new QGridLayout();
gLayout->addWidget( _view , 1, 0, 1, 2 );
gLayout->addWidget( filterPatternLabel , 2, 0 );
gLayout->addWidget( _filterPatternLineEdit, 2, 1 );
setLayout( gLayout );
QAction* fitAction = new QAction( tr("&Fit to Equi"), this );
fitAction->setShortcut ( QKeySequence(tr("CTRL+F")) );
fitAction->setStatusTip( tr("Fit the view to the Equipotentials's bounding box") );
addAction( fitAction );
connect( _filterPatternLineEdit , SIGNAL(textChanged(const QString &))
, this , SLOT (textFilterChanged()) );
connect( _view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&))
, this , SLOT (updateSelecteds (const QItemSelection&,const QItemSelection&)) );
//connect( fitAction, SIGNAL(triggered()), this, SLOT(fitToEqui()) );
resize( 300, 300 );
}
void EquipotentialsWidget::goTo ( int delta )
{
if ( delta == 0 ) return;
QModelIndex newIndex = _sortModel->index( _view->currentIndex().row()+delta, 0, QModelIndex() );
if (newIndex.isValid())
_view->selectRow( newIndex.row() );
}
void EquipotentialsWidget::updateSelecteds ()
{
_forceReselect = true;
QItemSelection dummy;
updateSelecteds( dummy, dummy );
}
void EquipotentialsWidget::updateSelecteds ( const QItemSelection& , const QItemSelection& )
{
if (_cellWidget) _cellWidget->openRefreshSession ();
_selecteds.resetAccesses ();
const Equipotential* equi = nullptr;
QModelIndexList iList = _view->selectionModel()->selectedRows();
for ( int i=0 ; i<iList.size() ; i++ ) {
equi = _baseModel->getEqui( _sortModel->mapToSource(iList[i]).row() );
if ( equi )
_selecteds.insert( equi );
}
if (_forceReselect) {
_selecteds.forceInserteds();
_forceReselect = false;
}
SelectedEquiSet::iterator remove;
SelectedEquiSet::iterator isel = _selecteds.begin ();
while ( isel != _selecteds.end() ) {
switch ( isel->getAccesses() ) {
case 1: break;
case 64:
emit equipotentialSelect ( isel->getEqui()->getComponents() );
break;
case 0:
emit equipotentialUnselect ( isel->getEqui()->getComponents() );
remove = isel;
++isel;
_selecteds.erase( remove );
continue;
default:
cerr << Bug( "EquipotentialsWidget::updateSelecteds(): invalid code %d"
, isel->getAccesses()) << endl;
}
++isel;
}
if (_cellWidget) _cellWidget->closeRefreshSession ();
}
void EquipotentialsWidget::textFilterChanged ()
{
_sortModel->setFilterRegExp( _filterPatternLineEdit->text() );
//updateSelecteds ();
}
// void EquipotentialsWidget::fitToNet ()
// {
// const Equipotential* equi = _baseModel->getEqui( _sortModel->mapToSource(_view->currentIndex()).row() );
// if (equi) emit netFitted ( equi );
// }
void EquipotentialsWidget::setCellWidget ( CellWidget* cw )
{
if (_cellWidget) {
disconnect( this, 0, _cellWidget, 0 );
}
_cellWidget = cw;
if (_cellWidget) {
setCell( _cellWidget->getCell() );
//connect( this, SIGNAL(netFitted(const Equi*)), _cellWidget, SLOT(fitToEqui (const Equi*)) );
} else
setCell( nullptr );
}
void EquipotentialsWidget::setCell ( Cell* cell )
{
_cell = cell;
_view->setVisible( false );
_view->selectionModel()->clear();
_baseModel->setCell( cell );
string windowTitle = "Equis" + getString(cell);
setWindowTitle( tr(windowTitle.c_str()) );
QHeaderView* header = _view->horizontalHeader();
_view->selectRow( 0 );
for ( int i=0 ; i<_baseModel->columnCount() ; ++i ) {
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
header->setSectionResizeMode( i, QHeaderView::Interactive );
#else
header->setResizeMode( i, QHeaderView::Interactive );
#endif
_view->resizeColumnToContents( i );
}
_view->setVisible( true );
}
}

View File

@ -36,6 +36,7 @@
#include <crlcore/Utilities.h>
#include <crlcore/AllianceFramework.h>
#include <anabatic/GCell.h>
#include <tramontana/TabEquipotentials.h>
#include <tramontana/GraphicTramontanaEngine.h>
@ -100,7 +101,6 @@ namespace Tramontana {
fontScale = -5;
halfHeight = 9;
halfWidth = 39;
}
painter.setPen ( pen );
@ -188,6 +188,14 @@ namespace Tramontana {
, "Run the extractor"
, std::bind(&GraphicTramontanaEngine::_extract,this)
);
ControllerWidget* controller = viewer->getControllerWidget();
if (controller) {
TabEquipotentials* tabEqui = new TabEquipotentials ();
tabEqui->setObjectName( "controller.tabEquipotentials" );
tabEqui->setCellWidget( viewer->getCellWidget() );
controller->insertTabAfter( "controller.tabNetlist", tabEqui, "Equipotentials" );
}
}

View File

@ -133,6 +133,7 @@ namespace Tramontana {
void SweepLine::mergeEquipotentials ()
{
cerr << "Tramontana::mergeEquipotentials()" << endl;
Tile::timeTick();
for ( Tile* tile : Tile::getAllTiles() ) {
tile->getRoot( Tile::MergeEqui );

View File

@ -0,0 +1,144 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | T r a m o n t a n a - Extractor & LVX |
// | |
// | Algorithm : Christian MASSON |
// | First impl. : Yifei WU |
// | Second impl. : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./TabEquipotentials.cpp" |
// +-----------------------------------------------------------------+
#include <QAction>
#include <QFrame>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QCheckBox>
#include <QComboBox>
#include "tramontana/TabEquipotentials.h"
namespace Tramontana {
using Hurricane::Graphics;
// -------------------------------------------------------------------
// Class : "Tramontana::TabEquipotentials".
TabEquipotentials::TabEquipotentials ( QWidget* parent )
: ControllerTab (parent)
, _browser (new EquipotentialsWidget())
, _syncEquipotentials (new QCheckBox())
, _syncSelection (new QCheckBox())
, _cwCumulativeSelection(false)
{
_browser->setObjectName ( "controller.tabEquipotentials.browser" );
QVBoxLayout* wLayout = new QVBoxLayout ();
wLayout->setContentsMargins( 10, 0, 10, 0 );
wLayout->setSpacing( 0 );
_syncEquipotentials->setText ( tr("Sync Equipotentials") );
_syncEquipotentials->setChecked( false );
_syncEquipotentials->setFont ( Graphics::getFixedFont(QFont::Bold,false,false) );
connect( _syncEquipotentials, SIGNAL(toggled(bool)), this, SLOT(setSyncEquipotentials(bool)) );
_syncSelection->setText ( tr("Sync Selection") );
_syncSelection->setChecked( false );
_syncSelection->setFont ( Graphics::getFixedFont(QFont::Bold,false,false) );
connect( _syncSelection, SIGNAL(toggled(bool)), this, SLOT(setSyncSelection(bool)) );
QHBoxLayout* commands = new QHBoxLayout ();
commands->setContentsMargins( 0, 0, 0, 0 );
commands->addStretch();
commands->addWidget ( _syncEquipotentials );
commands->addStretch();
commands->addWidget ( _syncSelection );
commands->addStretch();
wLayout->addLayout ( commands );
QFrame* separator = new QFrame ();
separator->setFrameShape ( QFrame::HLine );
separator->setFrameShadow( QFrame::Sunken );
wLayout->addWidget( separator );
wLayout->addWidget( _browser );
setLayout( wLayout );
}
void TabEquipotentials::setSyncEquipotentials ( bool state )
{
if (state and getCellWidget()) {
_browser->setCell( getCellWidget()->getCell() );
} else {
_browser->setCell( nullptr );
}
}
void TabEquipotentials::setSyncSelection ( bool state )
{
if (state and getCellWidget() and _syncEquipotentials->isChecked()) {
_cwCumulativeSelection = getCellWidget()->cumulativeSelection();
if (not _cwCumulativeSelection) {
getCellWidget()->openRefreshSession ();
getCellWidget()->unselectAll ();
getCellWidget()->closeRefreshSession ();
}
getCellWidget()->setShowSelection( true );
connect( _browser, SIGNAL(equipotentialSelect (const ComponentSet&)), getCellWidget(), SLOT(selectSet (const ComponentSet&)) );
connect( _browser, SIGNAL(equipotentialUnselect(const ComponentSet&)), getCellWidget(), SLOT(unselectSet(const ComponentSet&)) );
_browser->updateSelecteds();
} else {
getCellWidget()->setShowSelection( false );
getCellWidget()->setCumulativeSelection( _cwCumulativeSelection );
_browser->disconnect( getCellWidget(), SLOT(selectSet (const ComponentSet&)) );
_browser->disconnect( getCellWidget(), SLOT(unselectSet(const ComponentSet&)) );
}
}
void TabEquipotentials::setCell ( Cell* cell )
{
setSyncEquipotentials( _syncEquipotentials->isChecked() );
}
void TabEquipotentials::setCellWidget ( CellWidget* cellWidget )
{
if (getCellWidget() != cellWidget) {
ControllerTab::setCellWidget( cellWidget );
_browser->setCellWidget( cellWidget );
if (getCellWidget()) {
connect( getCellWidget(), SIGNAL(cellChanged(Cell*)), this, SLOT(setCell(Cell*)) );
}
setSyncEquipotentials( _syncEquipotentials->isChecked() );
}
}
void TabEquipotentials::cellPreModificate ()
{
_browser->setCell( nullptr );
}
void TabEquipotentials::cellPostModificate ()
{
setSyncEquipotentials( _syncEquipotentials->isChecked() );
}
}

View File

@ -157,15 +157,17 @@ namespace Tramontana {
if (flags & MergeEqui) {
Equipotential* rootEqui = root->getEquipotential();
if (not rootEqui)
if (not rootEqui) {
rootEqui = root->newEquipotential();
}
Tile* current = this;
while ( current ) {
if (current->isUpToDate()) break;
if (current->getEquipotential()) {
if (current->getEquipotential() != rootEqui)
if (current->getEquipotential() != rootEqui) {
rootEqui->merge( current->getEquipotential() );
}
} else {
rootEqui->add( current->getOccurrence() );
}

View File

@ -148,6 +148,7 @@ namespace Tramontana {
cerr << "TramontanaEngine::extract() called on " << getCell() << endl;
SweepLine sweepLine ( this );
sweepLine.run();
consolidate();
showEquipotentials();
}
@ -163,6 +164,15 @@ namespace Tramontana {
}
}
void TramontanaEngine::consolidate ()
{
cerr << "Tramontana::consolidate()" << endl;
for ( Equipotential* equi : _equipotentials )
equi->consolidate();
}
void TramontanaEngine::add ( Equipotential* equi )
{
_equipotentials.insert( equi );

View File

@ -38,6 +38,7 @@ namespace Tramontana {
using Hurricane::Net;
using Hurricane::Cell;
using Hurricane::Component;
using Hurricane::ComponentSet;
using Hurricane::Occurrence;
@ -47,16 +48,17 @@ namespace Tramontana {
class Equipotential : public Entity {
public:
typedef Entity Super;
typedef std::set<Component*,DBo::CompareById> ComponentSet;
public:
static Equipotential* create ( Cell* );
inline bool isEmpty () const;
virtual Cell* getCell () const;
virtual Box getBoundingBox () const;
inline std::string getName () const;
inline bool hasComponent ( Component* ) const;
void add ( Component* );
void add ( Occurrence );
void merge ( Equipotential* );
void consolidate ();
void clear ();
inline const ComponentSet& getComponents () const;
inline const std::vector<Occurrence>& getChilds () const;
@ -77,13 +79,20 @@ namespace Tramontana {
Box _boundingBox;
ComponentSet _components;
std::vector<Occurrence> _childs;
std::string _name;
Net::Type _type;
Net::Direction _direction;
bool _isExternal;
bool _isGlobal;
bool _isAutomatic;
};
inline bool Equipotential::isEmpty () const { return _components.empty() and _childs.empty(); }
inline const Equipotential::ComponentSet& Equipotential::getComponents () const { return _components; }
inline const std::vector<Occurrence>& Equipotential::getChilds () const { return _childs; }
inline bool Equipotential::isEmpty () const { return _components.empty() and _childs.empty(); }
inline const ComponentSet& Equipotential::getComponents () const { return _components; }
inline std::string Equipotential::getName () const { return _name; }
inline const std::vector<Occurrence>& Equipotential::getChilds () const { return _childs; }
inline bool Equipotential::hasComponent ( Component* component ) const
{ return _components.find( component ) != _components.end(); }

View File

@ -0,0 +1,62 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | T r a m o n t a n a - Extractor & LVX |
// | |
// | Algorithm : Christian MASSON |
// | First impl. : Yifei WU |
// | Second impl. : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./tramontana/EquipotentialsModel.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <vector>
#include <QFont>
#include <QApplication>
#include <QAbstractTableModel>
#include "hurricane/Commons.h"
#include "hurricane/Name.h"
#include "hurricane/Net.h"
#include "hurricane/Cell.h"
#include "hurricane/viewer/Graphics.h"
#include "tramontana/Equipotential.h"
#include "tramontana/TramontanaEngine.h"
namespace Tramontana {
using Hurricane::Cell;
class EquipotentialsModel : public QAbstractTableModel {
Q_OBJECT;
public:
EquipotentialsModel ( QObject* parent=NULL );
void setCell ( Cell* cell );
int rowCount ( const QModelIndex& parent=QModelIndex() ) const;
int columnCount ( const QModelIndex& parent=QModelIndex() ) const;
QVariant data ( const QModelIndex& index, int role=Qt::DisplayRole ) const;
QVariant headerData ( int section, Qt::Orientation orientation, int role=Qt::DisplayRole ) const;
inline Cell* getCell ();
const Equipotential* getEqui ( int row );
private:
Cell* _cell;
std::vector<Equipotential*> _equipotentials;
};
// Inline Functions.
inline Cell* EquipotentialsModel::getCell () { return _cell; }
} // Hurricane namespace.

View File

@ -0,0 +1,163 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | T r a m o n t a n a - Extractor & LVX |
// | |
// | Algorithm : Christian MASSON |
// | First impl. : Yifei WU |
// | Second impl. : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./tramontana/EquipotentialsWidget.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <set>
#include <QWidget>
#include <QTableView>
#include <QHeaderView>
#include <QItemDelegate>
#include <QSortFilterProxyModel>
#include "hurricane/Commons.h"
#include "hurricane/Bug.h"
#include "hurricane/viewer/CellWidget.h"
#include "hurricane/viewer/CellWidget.h"
#include "tramontana/EquipotentialsModel.h"
class QSortFilterProxyModel;
class QModelIndex;
class QTableView;
class QLineEdit;
class QComboBox;
class QHeaderView;
namespace Tramontana {
using std::string;
using std::set;
using Hurricane::Cell;
using Hurricane::CellWidget;
// -------------------------------------------------------------------
// Class : "SelectedEqui".
class SelectedEqui {
public:
inline SelectedEqui ();
inline SelectedEqui ( const Equipotential*, size_t access=0 );
inline const Equipotential* getEqui () const;
inline size_t getAccesses () const;
inline void incAccesses () const;
inline void setInserted () const;
inline void resetAccesses () const;
private:
const Equipotential* _equi;
mutable size_t _accesses;
};
inline SelectedEqui::SelectedEqui () : _equi(nullptr), _accesses(0) { }
inline SelectedEqui::SelectedEqui ( const Equipotential* equi, size_t accesses ) : _equi(equi), _accesses(accesses) { }
inline const Equipotential* SelectedEqui::getEqui () const { return _equi; }
inline void SelectedEqui::setInserted () const { _accesses = 64; }
inline size_t SelectedEqui::getAccesses () const { return _accesses; }
inline void SelectedEqui::incAccesses () const { ++_accesses; }
inline void SelectedEqui::resetAccesses () const { _accesses = 0; }
struct SelectedEquiCompare {
inline bool operator() ( const SelectedEqui& lhs, const SelectedEqui& rhs ) const;
};
inline bool SelectedEquiCompare::operator() ( const SelectedEqui& lhs, const SelectedEqui& rhs ) const
{
return lhs.getEqui()->getId() < rhs.getEqui()->getId();
}
// -------------------------------------------------------------------
// Class : "SelectedEquiSet".
class SelectedEquiSet : public set<SelectedEqui,SelectedEquiCompare>{
public:
void insert ( const Equipotential* );
void forceInserteds ();
void resetAccesses ();
};
inline void SelectedEquiSet::insert ( const Equipotential* equi )
{
iterator iselected = find(SelectedEqui(equi));
if (iselected != end())
iselected->incAccesses();
else
set<SelectedEqui,SelectedEquiCompare>::insert( SelectedEqui(equi,64) );
}
inline void SelectedEquiSet::forceInserteds ()
{
for ( iterator iselected=begin() ; iselected != end() ; ++iselected )
iselected->setInserted();
}
inline void SelectedEquiSet::resetAccesses ()
{
for ( iterator iselected=begin() ; iselected != end() ; ++iselected )
iselected->resetAccesses();
}
// -------------------------------------------------------------------
// Class : "EquipotentialsWidget".
class EquipotentialsWidget : public QWidget {
Q_OBJECT;
public:
EquipotentialsWidget ( QWidget* parent=nullptr );
inline Cell* getCell ();
void setCellWidget ( CellWidget* );
void setCell ( Cell* );
void goTo ( int );
void updateSelecteds ();
signals:
void equipotentialSelect ( const ComponentSet& );
void equipotentialUnselect ( const ComponentSet& );
void netFitted ( const Equipotential* );
private slots:
void textFilterChanged ();
void updateSelecteds ( const QItemSelection& , const QItemSelection& );
// void fitToEqui ();
private:
CellWidget* _cellWidget;
Cell* _cell;
EquipotentialsModel* _baseModel;
QSortFilterProxyModel* _sortModel;
QTableView* _view;
QLineEdit* _filterPatternLineEdit;
int _rowHeight;
SelectedEquiSet _selecteds;
bool _forceReselect;
};
inline Cell* EquipotentialsWidget::getCell () { return _cell; }
} // Hurricane namespace.

View File

@ -0,0 +1,62 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | T r a m o n t a n a - Extractor & LVX |
// | |
// | Algorithm : Christian MASSON |
// | First impl. : Yifei WU |
// | Second impl. : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./tramontana/TabEquipotentials.h" |
// +-----------------------------------------------------------------+
#pragma once
#include "hurricane/viewer/ControllerWidget.h"
#include "tramontana/EquipotentialsWidget.h"
namespace Tramontana {
using Hurricane::ControllerTab;
// -------------------------------------------------------------------
// Class : "Tramontana::TabEquipotentials".
class TabEquipotentials : public ControllerTab {
Q_OBJECT;
public:
TabEquipotentials ( QWidget* parent=NULL );
inline QCheckBox* getSyncEquipotentials ();
inline QCheckBox* getSyncSelection ();
inline EquipotentialsWidget* getBrowser ();
virtual void cellPreModificate ();
virtual void cellPostModificate ();
public slots:
virtual void setCell ( Cell* );
virtual void setCellWidget ( CellWidget* );
virtual void setSyncEquipotentials ( bool );
virtual void setSyncSelection ( bool );
protected:
EquipotentialsWidget* _browser;
QCheckBox* _syncEquipotentials;
QCheckBox* _syncSelection;
bool _cwCumulativeSelection;
};
inline EquipotentialsWidget* TabEquipotentials::getBrowser () { return _browser; }
inline QCheckBox* TabEquipotentials::getSyncEquipotentials () { return _syncEquipotentials; }
inline QCheckBox* TabEquipotentials::getSyncSelection () { return _syncSelection; }
}

View File

@ -53,9 +53,12 @@ namespace Tramontana {
static TramontanaEngine* get ( const Cell* );
public:
const Name& getName () const;
inline const std::set<Equipotential*,DBo::CompareById>
getEquipotentials () const;
inline void setViewer ( CellViewer* );
inline CellViewer* getViewer ();
void extract ();
void consolidate ();
void showEquipotentials () const;
void add ( Equipotential* );
virtual Record* _getRecord () const;
@ -81,6 +84,8 @@ namespace Tramontana {
inline void TramontanaEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; }
inline CellViewer* TramontanaEngine::getViewer () { return _viewer; }
inline const std::set<Equipotential*,DBo::CompareById>
TramontanaEngine::getEquipotentials () const { return _equipotentials; }
} // Tramontana namespace.