From 01b97626a818c4b9ae98e0959c772730a34cf022 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Wed, 25 Jun 2014 19:50:34 +0200 Subject: [PATCH] Support for Python plugins in CellViewer/Unicorn. ClockTree plugin. * New: In Hurricane, in CellViewer, create a simpler API to graft menu and actions into the menubar. Mainly addToMenu() which take care of the QAction creation but also locate the relevant QMenu, base on the Qt object name. Regroup all the widget & action creation inside the body of the constructor, this way almost all actions can be removed from the attributes of the CellViewer. addToMenu() is supplied in three flavors: 1. For C++ callbacks in GraphicToolEngines (with a binded member function method). 2. For running Python scripts to be used by the plugin system. 3. To insert separator in menus (to give a more homogeneous look). Remove the last remnants of Stratus scripts (unificated with basic Python scripts). * New: In Hurricane, in PyCellViewer, export the interface to graft Python scripts into the CellViewer menu tree. * Change: In Etesian, in GraphicEtesianEngine, use the new API to graft menus & callbacks into the CellViewer. * Change: In Mauka, in GraphicMaukaEngine, use the new API to graft menus & callbacks into the CellViewer. * Change: In Kite, in GraphicKiteEngine, use the new API to graft menus & callbacks into the CellViewer. * New: In Cumulus, install Python scripts as plugins for Unicorn under /cumulus/plugins/. * New: In Unicorn, in UnicornGui, make uses of the new API for creating menus in the CellViewer. Creates the stem menu for the P&R tools. Add a Python initialization mechanism to read the plugins installeds into /cumulus/plugins/. --- crlcore/src/cyclop/Cyclop.cpp | 30 +- cumulus/src/CMakeLists.txt | 4 + cumulus/src/ClockTree.py | 567 +++++++++++++++ etesian/src/GraphicEtesianEngine.cpp | 50 +- etesian/src/etesian/GraphicEtesianEngine.h | 3 - hurricane/src/isobar/PyHurricane.cpp | 2 +- hurricane/src/viewer/CellViewer.cpp | 661 +++++++++++------- hurricane/src/viewer/PyCellViewer.cpp | 115 ++- hurricane/src/viewer/PyViewer.cpp | 4 +- hurricane/src/viewer/ScriptWidget.cpp | 32 +- .../src/viewer/hurricane/viewer/CellViewer.h | 114 +-- .../viewer/hurricane/viewer/PyCellViewer.h | 14 +- .../src/viewer/hurricane/viewer/Script.h | 9 +- .../viewer/hurricane/viewer/ScriptWidget.h | 2 +- kite/src/GraphicKiteEngine.cpp | 195 ++---- kite/src/kite/GraphicKiteEngine.h | 13 +- mauka/src/GraphicMaukaEngine.cpp | 95 +-- mauka/src/mauka/GraphicMaukaEngine.h | 7 - unicorn/src/CMakeLists.txt | 2 + unicorn/src/UnicornGui.cpp | 33 +- unicorn/src/init/unicornInit.py | 64 ++ unicorn/src/unicorn/UnicornGui.h | 33 +- 22 files changed, 1401 insertions(+), 648 deletions(-) create mode 100755 cumulus/src/ClockTree.py create mode 100644 unicorn/src/init/unicornInit.py diff --git a/crlcore/src/cyclop/Cyclop.cpp b/crlcore/src/cyclop/Cyclop.cpp index e9b649c1..e286bbda 100644 --- a/crlcore/src/cyclop/Cyclop.cpp +++ b/crlcore/src/cyclop/Cyclop.cpp @@ -1,15 +1,9 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// Copyright (c) UPMC 2008-2014, All Rights Reserved // -// =================================================================== -// -// $Id$ -// -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | C O R I O L I S | // | C y c l o p - S i m p l e V i e w e r | // | | @@ -17,25 +11,19 @@ // | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | =============================================================== | // | C++ Module : "./Cyclop.cpp" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x +// +-----------------------------------------------------------------+ -#include -#include - -#include "hurricane/viewer/CellWidget.h" - -#include "OpenCellDialog.h" -#include "DemoGo.h" -#include "Cyclop.h" +#include +#include +#include "hurricane/viewer/CellWidget.h" +#include "OpenCellDialog.h" +#include "DemoGo.h" +#include "Cyclop.h" namespace CRL { - // ------------------------------------------------------------------- // Class : "Cyclop". diff --git a/cumulus/src/CMakeLists.txt b/cumulus/src/CMakeLists.txt index 97b8fcfb..4424b6da 100644 --- a/cumulus/src/CMakeLists.txt +++ b/cumulus/src/CMakeLists.txt @@ -1,6 +1,10 @@ +# -*- explicit-buffer-name: "CMakeLists.txt" -*- set ( pysources ${CMAKE_CURRENT_SOURCE_DIR}/placeandroute.py ${CMAKE_CURRENT_SOURCE_DIR}/ref.py ) + set ( pyplugins ${CMAKE_CURRENT_SOURCE_DIR}/ClockTree.py + ) install ( FILES ${pysources} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus ) + install ( FILES ${pyplugins} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins ) diff --git a/cumulus/src/ClockTree.py b/cumulus/src/ClockTree.py new file mode 100755 index 00000000..ca33e59d --- /dev/null +++ b/cumulus/src/ClockTree.py @@ -0,0 +1,567 @@ +#!/usr/bin/env python + +try: + import sys + import traceback + import os.path + import optparse + import math + import Cfg + import Hurricane + from Hurricane import DbU + from Hurricane import Box + from Hurricane import Path + from Hurricane import Occurrence + from Hurricane import UpdateSession + from Hurricane import Breakpoint + from Hurricane import Net + from Hurricane import RoutingPad + from Hurricane import Contact + from Hurricane import Horizontal + from Hurricane import Vertical + from Hurricane import Instance + from Hurricane import HyperNet + import Viewer + import CRL + from CRL import RoutingLayerGauge + from helpers import ErrorMessage + import Nimbus + import Metis + import Mauka + import Katabatic + import Kite + import Unicorn +except ImportError, e: + module = str(e).split()[-1] + + print '[ERROR] The <%s> python module or symbol cannot be loaded.' % module + print ' Please check the integrity of the package.' + sys.exit(1) +except Exception, e: + print '[ERROR] A strange exception occurred while loading the basic Coriolis/Python' + print ' modules. Something may be wrong at Python/C API level.\n' + print ' %s' % e + sys.exit(2) + + +# Will be moved away from the students eyes in the future. +def breakpoint ( editor, level, message ): + if editor: + editor.fit() + editor.refresh() + Breakpoint.stop( level, message ) + return + + +def getPlugByName ( instance, netName ): + masterCell = instance.getMasterCell() + masterNet = masterCell.getNet( netName ) + if masterNet: + return instance.getPlug( masterNet ) + return None + + +def getPlugByNet ( instance, net ): + #print 'getPlugByNet:', net, 'connected to', instance + for plug in net.getPlugs(): + #print '|', plug + if plug.getInstance() == instance: + #print '| Found.' + return plug + #print '| NOT Found' + return None + + +def showNet ( cell, netName ): + net = cell.getNet(netName) + if not net: + print ErrorMessage( 3, 'Cell %s doesn\'t have net %s' % cell.getName(), netName ) + return + + print 'Components of', netName + for component in net.getComponents(): + print '| ', component, component.getBoundingBox() + return + + +class HTree ( object ): + + HAccess = 0x0001 + + @staticmethod + def create ( cell, clockBox ): + if clockBox.isEmpty(): raise ErrorMessage( 3, 'ClockTree: The clock area is empty.' ) + + aspectRatio = DbU.toLambda( clockBox.getWidth() ) / DbU.toLambda( clockBox.getHeight() ) + if aspectRatio > 1.5 or aspectRatio < 0.5: + raise ErrorMessage( 3, 'ClockTree: aspect ratio %f is disproportionate, must be between 0.5 and 1.5.' \ + % aspectRatio ) + + ht = HTree( cell, clockBox ) + print ' o Creating Clock H-Tree for <%s>.' % cell.getName() + ht.build() + ht.place() + ht.route() + print ' - H-Tree depth: %d' % ht.getTreeDepth() + return ht + + def __init__ ( self, cell, area ): + self.minSide = DbU.fromLambda( Cfg.getParamInt('clockTree.minimumSide').asInt() ) + if self.minSide < DbU.fromLambda(100.0): + raise ErrorMessage( 3, 'ClockTree: clockTree.minimumSide (%g) is less than 100 lambda.' \ + % DbU.toLambda(self.minSide) ) + + self.framework = CRL.AllianceFramework.get() + self.cell = cell + self.area = area + self.childs = [] + self.bufferCell = self.framework.getCell( 'buf_x2', CRL.Catalog.State.Logical ) + self.cellGauge = self.framework.getCellGauge() + self.routingGauge = self.framework.getRoutingGauge() + self.topBuffer = Instance( self.cell, 'ck_htree', self.bufferCell ) + self.cloneds = [ self.cell ] + self.plugToRp = {} + self._createChildNet( self.topBuffer, 'ck_htree' ) + + topLayer = Cfg.getParamString('katabatic.topRoutingLayer').asString() + self.topLayerDepth = 0 + for layerGauge in self.routingGauge.getLayerGauges(): + if layerGauge.getLayer().getName() == topLayer: + self.topLayerDepth = layerGauge.getDepth() + break + if not self.topLayerDepth: + print '[WARNING] Gauge top layer not defined, using top of gauge (%d).' \ + % self.routingGauge.getDepth() + self.topLayerDepth = self.routingGauge.getDepth() + + self.horizontalDepth = 0 + self.verticalDepth = 0 + for depth in range(0,self.topLayerDepth+1): + if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal: + self.horizontalDepth = depth + if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Vertical: + self.verticalDepth = depth + + self.masterClock = None + for net in cell.getNets(): + if net.isClock(): + self.masterClock = net + break + if not self.masterClock: + print '[WARNING] Cell %s has no clock net.' % cell.getName() + + return + + def _createChildNet ( self, ibuffer, tag ): + childNet = Net( self.cell, tag ) + childNet.setType( Hurricane.TypeCLOCK ) + getPlugByName(ibuffer, 'q').setNet( childNet ) + return + + def _createContact ( self, net, x, y ): + return Contact( net + , self.routingGauge.getContactLayer(self.horizontalDepth) + , x, y + , self.routingGauge.getLayerGauge(self.horizontalDepth).getViaWidth() + , self.routingGauge.getLayerGauge(self.horizontalDepth).getViaWidth() + ) + + def _createHorizontal ( self, source, target, y ): + return Horizontal( source + , target + , self.routingGauge.getRoutingLayer(self.horizontalDepth) + , y + , self.routingGauge.getLayerGauge(self.horizontalDepth).getWireWidth() + ) + + def _createVertical ( self, source, target, x ): + return Vertical( source + , target + , self.routingGauge.getRoutingLayer(self.verticalDepth) + , x + , self.routingGauge.getLayerGauge(self.verticalDepth).getWireWidth() + ) + + def _rpAccess ( self, rp, net, flags=0 ): + contact1 = Contact( rp, self.routingGauge.getContactLayer(0), 0, 0 ) + + if flags & HTree.HAccess: stopDepth = self.horizontalDepth + else: stopDepth = self.verticalDepth + + for depth in range(1,stopDepth): + contact2 = Contact( net + , self.routingGauge.getContactLayer(depth) + , contact1.getX() + , contact1.getY() + , self.routingGauge.getLayerGauge(depth).getViaWidth() + , self.routingGauge.getLayerGauge(depth).getViaWidth() + ) + if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal: + Horizontal( contact1 + , contact2 + , self.routingGauge.getRoutingLayer(depth) + , contact1.getY() + , self.routingGauge.getLayerGauge(depth).getWireWidth() + ) + else: + Vertical( contact1 + , contact2 + , self.routingGauge.getRoutingLayer(depth) + , contact1.getX() + , self.routingGauge.getLayerGauge(depth).getWireWidth() + ) + contact1 = contact2 + + return contact1 + + def _rpAccessByOccurrence ( self, occurrence, net, flags=0 ): + plug = occurrence.getEntity() + if self.plugToRp.has_key(plug): + rp = self.plugToRp[plug] + else: + rp = RoutingPad.create( net, occurrence, RoutingPad.BiggestArea ) + self.plugToRp[plug] = rp + + return self._rpAccess( rp, net, flags ) + + def _rpAccessByPlug ( self, plug, net, flags=0 ): + if self.plugToRp.has_key(plug): + rp = self.plugToRp[plug] + else: + occurrence = Occurrence( plug, Path(self.cell,'') ) + rp = RoutingPad.create( net, occurrence, RoutingPad.BiggestArea ) + self.plugToRp[plug] = rp + + return self._rpAccess( rp, net, flags ) + + def _rpAccessByPlugName ( self, instance, plugName, net, flags=0 ): + return self._rpAccessByPlug( getPlugByName(instance,plugName), net, flags ) + + def toXCellGrid ( self, x ): return x - (x % self.cellGauge.getSliceStep ()) + def toYCellGrid ( self, y ): return y - (y % self.cellGauge.getSliceHeight()) + + def placeInstance ( self, instance, x, y ): + xslice = self.toXCellGrid(x) + yslice = self.toYCellGrid(y) + + transformation = Hurricane.OrientationID + if (yslice / self.cellGauge.getSliceHeight()) % 2 != 0: + transformation = Hurricane.OrientationMY + yslice += self.cellGauge.getSliceHeight() + + instance.setTransformation ( Hurricane.Transformation(xslice, yslice, transformation) ) + instance.setPlacementStatus( Hurricane.PlacementStatusFIXED ) + return + + def getTreeDepth ( self ): + return self.childs[0].getTreeDepth() + + def getLeafBufferUnder ( self, point ): + return self.childs[0].getLeafBufferUnder( point ) + + def build ( self ): + self.childs.append( HTreeNode( self, self.topBuffer, self.area, '', HTreeNode.RootBranch ) ) + return + + def place ( self ): + UpdateSession.open() + center = self.area.getCenter() + self.placeInstance( self.topBuffer, center.getX(), center.getY() ) + self.childs[0].place() + UpdateSession.close() + return + + def route ( self ): + UpdateSession.open() + self.childs[0].route() + UpdateSession.close() + return + + def addDeepPlug ( self, topNet, path ): + if path.isEmpty(): return None + + tailPath = path.getTailPath() + headInstance = path.getHeadInstance() + headPlug = getPlugByNet(headInstance,topNet) + if headPlug: + if tailPath.isEmpty(): return headPlug + return self.addDeepPlug( headPlug.getMasterNet(), tailPath ) + + masterCell = headInstance.getMasterCell() + masterNet = Net( masterCell, topNet.getName() ) + masterNet.setExternal ( True ) + masterNet.setType ( Hurricane.TypeCLOCK ) + masterNet.setDirection( Hurricane.DirectionIN ) + headPlug = headInstance.getPlug( masterNet ) + if not headPlug: + raise ErrorMessage( 3, 'Plug not created for %s on instance %s of %s' \ + % (topNet.getName(),headInstance.getName(),masterCell.getName()) ) + headPlug.setNet( topNet ) + if not masterCell in self.cloneds: self.cloneds.append( masterCell ) + + if tailPath.isEmpty(): return headPlug + return self.addDeepPlug( masterNet, tailPath ) + + def connectLeaf ( self ): + UpdateSession.open() + + leafConnects = [] + hyperMasterClock = HyperNet( Occurrence(self.masterClock) ) + for plugOccurrence in hyperMasterClock.getLeafPlugOccurrences(): + position = plugOccurrence.getBoundingBox().getCenter() + leafBuffer = self.getLeafBufferUnder( position ) + leafCk = getPlugByName(leafBuffer,'q').getNet() + deepPlug = self.addDeepPlug( leafCk, plugOccurrence.getPath() ) + leafConnects.append( (deepPlug,plugOccurrence,leafCk,leafBuffer) ) + + for deepPlug, plugOccurrence, leafCk, leafBuffer in leafConnects: + plugOccurrence.getEntity().setNet( deepPlug.getMasterNet() ) + + bufferContact = self._rpAccessByPlugName( leafBuffer, 'q', leafCk , HTree.HAccess ) + registerContact = self._rpAccessByOccurrence( plugOccurrence, leafCk, 0 ) + turn = self._createContact( leafCk, registerContact.getX(), bufferContact.getY() ) + self._createVertical ( registerContact, turn, registerContact.getX() ) + self._createHorizontal( turn, bufferContact, bufferContact.getY() ) + + getPlugByName( self.topBuffer, 'i' ).setNet( self.masterClock ) + UpdateSession.close() + + return + + def _rsave ( self, cell ): + flags = CRL.Catalog.State.Physical + if cell.getName().endswith('_clocked'): + flags = flags | CRL.Catalog.State.Logical + self.framework.saveCell( cell, flags ) + + for instance in cell.getInstances(): + masterCell = instance.getMasterCell() + if not masterCell.isTerminal(): + self._rsave( masterCell ) + + def save ( self ): + for cell in self.cloneds: + cell.setName( cell.getName()+'_clocked' ) + + self._rsave( self.cell ) + return + + +class HTreeNode ( object ): + + RootBranch = 0x0001 + LeftBranch = 0x0002 + RightBranch = 0x0004 + UpBranch = 0x0008 + DownBranch = 0x0010 + + def __init__ ( self, topTree, sourceBuffer, area, prefix, flags ): + self.topTree = topTree + self.childs = [] + self.flags = flags + self.sourceBuffer = sourceBuffer + self.area = area + self.prefix = prefix + + self.blBuffer = Instance( self.topTree.cell, 'ck_htree'+self.prefix+'_bl_ins', self.topTree.bufferCell ) + self.brBuffer = Instance( self.topTree.cell, 'ck_htree'+self.prefix+'_br_ins', self.topTree.bufferCell ) + self.tlBuffer = Instance( self.topTree.cell, 'ck_htree'+self.prefix+'_tl_ins', self.topTree.bufferCell ) + self.trBuffer = Instance( self.topTree.cell, 'ck_htree'+self.prefix+'_tr_ins', self.topTree.bufferCell ) + self.ckNet = getPlugByName(self.sourceBuffer, 'q').getNet() + getPlugByName(self.blBuffer, 'i').setNet( self.ckNet ) + getPlugByName(self.brBuffer, 'i').setNet( self.ckNet ) + getPlugByName(self.tlBuffer, 'i').setNet( self.ckNet ) + getPlugByName(self.trBuffer, 'i').setNet( self.ckNet ) + + self.topTree._createChildNet( self.blBuffer, 'ck_htree'+self.prefix+'_bl' ) + self.topTree._createChildNet( self.brBuffer, 'ck_htree'+self.prefix+'_br' ) + self.topTree._createChildNet( self.tlBuffer, 'ck_htree'+self.prefix+'_tl' ) + self.topTree._createChildNet( self.trBuffer, 'ck_htree'+self.prefix+'_tr' ) + + halfWidth = self.area.getHalfWidth () + halfHeight = self.area.getHalfHeight() + if halfWidth >= self.topTree.minSide and halfHeight >= self.topTree.minSide: + # Recursive call. + self.childs.append( HTreeNode( self.topTree, self.blBuffer, self.blArea(), self.prefix+'_bl', 0 ) ) + self.childs.append( HTreeNode( self.topTree, self.brBuffer, self.brArea(), self.prefix+'_br', 0 ) ) + self.childs.append( HTreeNode( self.topTree, self.tlBuffer, self.tlArea(), self.prefix+'_tl', 0 ) ) + self.childs.append( HTreeNode( self.topTree, self.trBuffer, self.trArea(), self.prefix+'_tr', 0 ) ) + + return + + def xmin ( self ): return self.area.getXMin() + def xmax ( self ): return self.area.getXMax() + def ymin ( self ): return self.area.getYMin() + def ymax ( self ): return self.area.getYMax() + def halfWidth ( self ): return self.area.getHalfWidth() + def halfHeight( self ): return self.area.getHalfHeight() + + def blArea ( self ): + return Box( self.xmin() , self.ymin() + , self.xmin()+self.halfWidth(), self.ymin()+self.halfHeight() ) + + def brArea ( self ): + return Box( self.xmin()+self.halfWidth(), self.ymin() + , self.xmax() , self.ymin()+self.halfHeight() ) + + def tlArea ( self ): + return Box( self.xmin() , self.ymin()+self.halfHeight() + , self.xmin()+self.halfWidth(), self.ymax() ) + + def trArea ( self ): + return Box( self.xmin()+self.halfWidth(), self.ymin()+self.halfHeight() + , self.xmax() , self.ymax() ) + + def getTreeDepth ( self ): + if self.childs: return self.childs[0].getTreeDepth()+1 + return 1 + + def getLeafBufferUnder ( self, point ): + if self.childs: + if self.blArea().contains(point): return self.childs[0].getLeafBufferUnder(point) + if self.brArea().contains(point): return self.childs[1].getLeafBufferUnder(point) + if self.tlArea().contains(point): return self.childs[2].getLeafBufferUnder(point) + if self.trArea().contains(point): return self.childs[3].getLeafBufferUnder(point) + + if self.blArea().contains(point): return self.blBuffer + if self.brArea().contains(point): return self.brBuffer + if self.tlArea().contains(point): return self.tlBuffer + return self.trBuffer + + def place ( self ): + x = self.area.getXMin() + self.area.getWidth ()/4 + y = self.area.getYMin() + self.area.getHeight()/4 + halfWidth = self.area.getHalfWidth () + halfHeight = self.area.getHalfHeight() + + self.topTree.placeInstance( self.blBuffer, x , y ) + self.topTree.placeInstance( self.brBuffer, x+halfWidth, y ) + self.topTree.placeInstance( self.tlBuffer, x , y+halfHeight ) + self.topTree.placeInstance( self.trBuffer, x+halfWidth, y+halfHeight ) + + for child in self.childs: child.place() + return + + def route ( self ): + sourceContact = self.topTree._rpAccessByPlugName( self.sourceBuffer, 'q', self.ckNet , HTree.HAccess ) + blContact = self.topTree._rpAccessByPlugName( self.blBuffer , 'i', self.ckNet ) + brContact = self.topTree._rpAccessByPlugName( self.brBuffer , 'i', self.ckNet ) + tlContact = self.topTree._rpAccessByPlugName( self.tlBuffer , 'i', self.ckNet ) + trContact = self.topTree._rpAccessByPlugName( self.trBuffer , 'i', self.ckNet ) + leftContact = self.topTree._createContact( self.ckNet, blContact.getX(), sourceContact.getY() ) + rightContact = self.topTree._createContact( self.ckNet, brContact.getX(), sourceContact.getY() ) + self.topTree._createHorizontal( leftContact , sourceContact, sourceContact.getY() ) + self.topTree._createHorizontal( sourceContact, rightContact , sourceContact.getY() ) + self.topTree._createVertical ( leftContact , blContact , leftContact.getX() ) + self.topTree._createVertical ( tlContact , leftContact , leftContact.getX() ) + self.topTree._createVertical ( rightContact , brContact , rightContact.getX() ) + self.topTree._createVertical ( trContact , rightContact , rightContact.getX() ) + + for child in self.childs: child.route() + return + +def computeAbutmentBox ( cell, spaceMargin, aspectRatio, cellGauge ): + sliceHeight = DbU.toLambda( cellGauge.getSliceHeight() ) + + instancesNb = 0 + cellLength = 0 + for occurrence in cell.getLeafInstanceOccurrences(): + instance = occurrence.getEntity() + instancesNb += 1 + cellLength += int( DbU.toLambda(instance.getMasterCell().getAbutmentBox().getWidth()) ) + + # ar = x/y S = x*y = spaceMargin*SH x=S/y ar = S/y^2 + # y = sqrt(S/AR) + gcellLength = float(cellLength)*(1+spaceMargin) / sliceHeight + rows = math.sqrt( gcellLength/aspectRatio ) + if math.trunc(rows) != rows: rows = math.trunc(rows) + 1 + else: rows = math.trunc(rows) + columns = gcellLength / rows + if math.trunc(columns) != columns: columns = math.trunc(columns) + 1 + else: columns = math.trunc(columns) + + print ' o Creating abutment box (margin:%.1f%%, aspect ratio:%.1f%%, g-length:%.1fl)' \ + % (spaceMargin*100.0,aspectRatio*100.0,(cellLength/sliceHeight)) + print ' - GCell grid: [%dx%d]' % (columns,rows) + + UpdateSession.open() + abutmentBox = Box( DbU.fromLambda(0) + , DbU.fromLambda(0) + , DbU.fromLambda(columns*sliceHeight) + , DbU.fromLambda(rows *sliceHeight) + ) + cell.setAbutmentBox( abutmentBox ) + UpdateSession.close() + + return abutmentBox + + +def unicornHook ( editor ): + #print ' o Hooking up ClockTree script.' + moduleFile = sys.modules[__name__].__file__ + if moduleFile.endswith('.pyc') or moduleFile.endswith('.pyo'): + moduleFile = moduleFile[:-1] + + editor.addToMenu( 'plugins.clockTree' + , 'ClockTree' + , 'Build a buffered H-Tree for the clock' + , moduleFile + ) + #print ' <%s>' % moduleFile + return + + +def ScriptMain ( cell=None ): + try: + errorCode = 0 + + print ' o Cleaning up any previous run.' + for fileName in os.listdir('.'): + if fileName.endswith('.ap'): + print ' - <%s>' % fileName + os.unlink(fileName) + + editor = None + if globals().has_key('__editor'): + print ' o Editor detected, running in graphic mode.' + editor = __editor + if cell == None: cell = editor.getCell() + + if cell == None: + raise ErrorMessage( 3, 'ClockTree: No cell loaded yet.' ) + + framework = CRL.AllianceFramework.get() + cellGauge = framework.getCellGauge() + + if cell.getAbutmentBox().isEmpty(): + spaceMargin = Cfg.getParamPercentage('nimbus.spaceMargin').asPercentage() / 100.0 + 0.02 + aspectRatio = Cfg.getParamPercentage('nimbus.aspectRatio').asPercentage() / 100.0 + computeAbutmentBox( cell, spaceMargin, aspectRatio, cellGauge ) + if editor: editor.fit() + + ht = HTree.create( cell, cell.getAbutmentBox() ) + if editor: editor.refresh() + mauka = Mauka.MaukaEngine.create( cell ) + mauka.run() + mauka.destroy() + ht.connectLeaf() + ht.save() + + #showNet( cell, 'ck_htree_bl_bl_bl' ) + #showNet( cell, 'ck_htree_bl_bl_br' ) + #showNet( cell, 'ck_htree_bl_bl_tl' ) + #showNet( cell, 'ck_htree_bl_bl_tr' ) + + except ErrorMessage, e: + print e; errorCode = e.code + except Exception, e: + print '\n\n', e; errorCode = 1 + traceback.print_tb(sys.exc_info()[2]) + + return 0 + + +if __name__ == '__main__': + ScriptMain() + + sys.exit(0) diff --git a/etesian/src/GraphicEtesianEngine.cpp b/etesian/src/GraphicEtesianEngine.cpp index 3b562809..2c889b7f 100644 --- a/etesian/src/GraphicEtesianEngine.cpp +++ b/etesian/src/GraphicEtesianEngine.cpp @@ -94,29 +94,16 @@ namespace Etesian { } - void GraphicEtesianEngine::_resetPlacement () + void GraphicEtesianEngine::_place () { _viewer->clearToolInterrupt(); EtesianEngine* etesian = getForFramework( CreateEngine ); etesian->resetPlacement(); - } - - - void GraphicEtesianEngine::_place () - { - EtesianEngine* etesian = getForFramework( CreateEngine ); etesian->place(); } - void GraphicEtesianEngine::place () - { - ExceptionWidget::catchAllWrapper( std::bind(&GraphicEtesianEngine::_resetPlacement,this) ); - ExceptionWidget::catchAllWrapper( std::bind(&GraphicEtesianEngine::_place ,this) ); - } - - void GraphicEtesianEngine::postEvent () { static unsigned int count = 0; @@ -139,35 +126,16 @@ namespace Etesian { _viewer = viewer; - QMenu* prMenu = _viewer->findChild("viewer.menuBar.placeAndRoute"); - QMenu* stepMenu = _viewer->findChild("viewer.menuBar.placeAndRoute.stepByStep"); - if (prMenu == NULL) { - QMenuBar* menuBar = _viewer->findChild("viewer.menuBar"); - if (menuBar == NULL) { - cerr << Warning( "GraphicEtesianEngine::addToMenu() - No MenuBar in parent widget." ) << endl; - return; - } - prMenu = menuBar->addMenu( tr("P&&R") ); - prMenu->setObjectName( "viewer.menuBar.placeAndRoute" ); - - stepMenu = prMenu->addMenu( tr("&Step by Step") ); - stepMenu->setObjectName( "viewer.menuBar.placeAndRoute.stepByStep" ); - - prMenu->addSeparator(); + if (_viewer->hasMenuAction("placeAndRoute.etesianPlace")) { + cerr << Warning( "GraphicEtesianEngine::addToMenu() - Etesian placer already hooked in." ) << endl; + return; } - QAction* placeAction = _viewer->findChild("viewer.menuBar.placeAndRoute.etesianPlace"); - if (placeAction) - cerr << Warning( "GraphicEtesianEngine::addToMenu() - Etesian detailed router already hooked in." ) << endl; - else { - QAction* placeAction = new QAction ( tr("Etesian - &Place"), _viewer ); - placeAction->setObjectName( "viewer.menuBar.placeAndRoute.etesianPlace" ); - placeAction->setStatusTip ( tr("Place the design") ); - placeAction->setVisible ( true ); - prMenu->addAction( placeAction ); - - connect( placeAction , SIGNAL(triggered()), this, SLOT(place ()) ); - } + _viewer->addToMenu( "placeAndRoute.etesianPlace" + , "Etesian - Plac&e" + , "Run the Etesian placer" + , std::bind(&GraphicEtesianEngine::_place,this) + ); } diff --git a/etesian/src/etesian/GraphicEtesianEngine.h b/etesian/src/etesian/GraphicEtesianEngine.h index 7094ae05..5fdb17ae 100644 --- a/etesian/src/etesian/GraphicEtesianEngine.h +++ b/etesian/src/etesian/GraphicEtesianEngine.h @@ -61,8 +61,6 @@ namespace Etesian { virtual size_t release (); virtual void addToMenu ( CellViewer* ); void postEvent (); - public slots: - void place (); protected: static size_t _references; @@ -71,7 +69,6 @@ namespace Etesian { protected: GraphicEtesianEngine (); virtual ~GraphicEtesianEngine (); - void _resetPlacement (); void _place (); }; diff --git a/hurricane/src/isobar/PyHurricane.cpp b/hurricane/src/isobar/PyHurricane.cpp index b9b65c62..0e28b9dd 100644 --- a/hurricane/src/isobar/PyHurricane.cpp +++ b/hurricane/src/isobar/PyHurricane.cpp @@ -2,7 +2,7 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC 2008-2013, All Rights Reserved +// Copyright (c) UPMC 2008-2014, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | diff --git a/hurricane/src/viewer/CellViewer.cpp b/hurricane/src/viewer/CellViewer.cpp index 0f441580..b6652adb 100644 --- a/hurricane/src/viewer/CellViewer.cpp +++ b/hurricane/src/viewer/CellViewer.cpp @@ -1,7 +1,7 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2014, All Rights Reserved +// Copyright (c) UPMC 2008-2014, All Rights Reserved // // +-----------------------------------------------------------------+ // | H U R R I C A N E | @@ -14,6 +14,7 @@ // +-----------------------------------------------------------------+ +#include #include #include #include @@ -29,10 +30,12 @@ #include #include +#include "vlsisapd/utilities/Path.h" #include "vlsisapd/configuration/Configuration.h" #include "hurricane/DataBase.h" #include "hurricane/Cell.h" //#include "MapView.h" +#include "hurricane/viewer/Script.h" #include "hurricane/viewer/Graphics.h" #include "hurricane/viewer/CellViewer.h" #include "hurricane/viewer/CellPrinter.h" @@ -41,7 +44,6 @@ #include "hurricane/viewer/ControllerWidget.h" #include "hurricane/viewer/ScriptWidget.h" #include "hurricane/viewer/ExceptionWidget.h" -//#include "hurricane/viewer/StratusWidget.h" #include "hurricane/viewer/GotoWidget.h" #include "hurricane/viewer/SelectCommand.h" @@ -69,32 +71,15 @@ namespace Hurricane { // ------------------------------------------------------------------- // Class : "CellViewer". + QString CellViewer::_prefixWPath ( "viewer.menuBar." ); + + CellViewer::CellViewer ( QWidget* parent ) : QMainWindow (parent) , _cellObserver (this) , _applicationName (tr("Viewer")) - , _toolInterruptAction (NULL) - , _openAction (NULL) - , _importAction (NULL) - , _nextAction (NULL) - , _printAction (NULL) - , _imageAction (NULL) - , _saveAction (NULL) - , _exportAction (NULL) - , _closeAction (NULL) - , _exitAction (NULL) - , _refreshAction (NULL) - , _fitToContentsAction (NULL) - , _gotoAction (NULL) , _showSelectionAction (NULL) - , _rubberChangeAction (NULL) - , _clearRulersAction (NULL) - , _controllerAction (NULL) - , _scriptAction (NULL) - , _stratusAction (NULL) - , _fileMenu (NULL) - , _viewMenu (NULL) - , _toolsMenu (NULL) , _debugMenu (NULL) + , _actionCallbacks () //, _mapView (NULL) , _mousePosition (NULL) , _controller (NULL) @@ -112,205 +97,13 @@ namespace Hurricane { , _flags (0) , _updateState (ExternalEmit) { - setObjectName("viewer"); - - createMenus (); - createLayout (); - } - - - CellViewer::~CellViewer () - { - _controller->deleteLater (); - //_script->deleteLater (); - _goto->deleteLater (); - } - - - void CellViewer::createActions () - { - if ( _openAction ) return; - - _toolInterruptAction = new QAction ( tr("Interrupt"), this ); - _toolInterruptAction->setObjectName ( "viewer.interrupt" ); - _toolInterruptAction->setShortcut ( QKeySequence(tr("CTRL+C")) ); - //_toolInterruptAction->setIcon ( QIcon(":/images/stock_open.png") ); - _toolInterruptAction->setStatusTip ( tr("Interrupt the running tool") ); - connect ( _toolInterruptAction, SIGNAL(triggered()), this, SLOT(raiseToolInterrupt()) ); - addAction ( _toolInterruptAction ); - - _openAction = new QAction ( tr("&Open Cell"), this ); - _openAction->setObjectName ( "viewer.menuBar.file.openCell" ); - _openAction->setShortcut ( QKeySequence(tr("CTRL+O")) ); - _openAction->setIcon ( QIcon(":/images/stock_open.png") ); - _openAction->setStatusTip ( tr("Open (load) a new Cell") ); - - _importAction = new QAction ( tr("&Import Cell"), this ); - _importAction->setObjectName ( "viewer.menuBar.file.importCell" ); - _importAction->setStatusTip ( tr("Import (convert) a new Cell") ); - - _nextAction = new QAction ( tr("&Next Breakpoint"), this ); - _nextAction->setObjectName ( "viewer.menuBar.file.nextBreakpoint" ); - _nextAction->setStatusTip ( tr("Proceed to the next breakpoint") ); - - for ( int i=0 ; isetObjectName ( QString("viewer.menuBar.file.cellHistory[%1]").arg(i) ); - _cellHistoryAction[i]->setVisible ( false ); - _cellHistoryAction[i]->setData ( i ); - _cellHistoryAction[i]->setFont ( Graphics::getFixedFont(QFont::Bold,false,false) ); - connect ( _cellHistoryAction[i], SIGNAL(triggered()), this, SLOT(openHistoryCell())); - } - - _printAction = new QAction ( tr("&Print"), this ); - _printAction->setObjectName ( "viewer.menuBar.file.print" ); - _printAction->setStatusTip ( tr("Print the displayed area") ); - _printAction->setShortcut ( QKeySequence(tr("CTRL+P")) ); - _printAction->setVisible ( true ); - connect ( _printAction, SIGNAL(triggered()), this, SLOT(printDisplay()) ); - - _imageAction = new QAction ( tr("Save to &Image"), this ); - _imageAction->setObjectName ( "viewer.menuBar.file.image" ); - _imageAction->setStatusTip ( tr("Save the displayed area to image") ); - _imageAction->setVisible ( true ); - connect ( _imageAction, SIGNAL(triggered()), this, SLOT(imageDisplay()) ); - - _saveAction = new QAction ( tr("&Save Cell"), this ); - _saveAction->setObjectName ( "viewer.menuBar.file.saveCell" ); - _saveAction->setIcon ( QIcon(":/images/stock_save.png") ); - _saveAction->setStatusTip ( tr("Save (write) the current Cell") ); - _saveAction->setVisible ( false ); - - _exportAction = new QAction ( tr("&Export Cell"), this ); - _exportAction->setObjectName ( "viewer.menuBar.file.exportCell" ); - _exportAction->setStatusTip ( tr("Export (convert) Cell") ); - - _closeAction = new QAction ( tr("&Close"), this ); - _closeAction->setObjectName ( "viewer.menuBar.file.close" ); - _closeAction->setStatusTip ( tr("Close This Coriolis CellViewer") ); - _closeAction->setShortcut ( QKeySequence(tr("CTRL+W")) ); - connect ( _closeAction, SIGNAL(triggered()), this, SLOT(close()) ); - - _exitAction = new QAction ( tr("&Exit"), this ); - _exitAction->setObjectName ( "viewer.menuBar.file.exit" ); - _exitAction->setStatusTip ( tr("Exit All Coriolis CellViewer") ); - _exitAction->setShortcut ( QKeySequence(tr("CTRL+Q")) ); - connect ( _exitAction, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()) ); - - _refreshAction = new QAction ( tr("&Refresh"), this ); - _refreshAction->setObjectName ( "viewer.menuBar.view.refresh" ); - _refreshAction->setStatusTip ( tr("Force full redrawing of the display") ); - _refreshAction->setShortcut ( QKeySequence(tr("CTRL+L")) ); - - _fitToContentsAction = new QAction ( tr("&Fit to Contents"), this ); - _fitToContentsAction->setObjectName ( "viewer.menuBar.view.fit" ); - _fitToContentsAction->setStatusTip ( tr("Adjust zoom to fit the whole cell's contents") ); - _fitToContentsAction->setShortcut ( Qt::Key_F ); - - _gotoAction = new QAction ( tr("&Goto"), this ); - _gotoAction->setObjectName ( "viewer.menuBar.view.goto" ); - _gotoAction->setStatusTip ( tr("Center view on that point, with zoom adjustment") ); - _gotoAction->setShortcut ( Qt::Key_G ); - - _showSelectionAction = new QAction ( tr("&Show Selection"), this ); - _showSelectionAction->setObjectName ( "viewer.menuBar.view.showSelection" ); - _showSelectionAction->setStatusTip ( tr("Highlight the selected items (darken others)") ); - _showSelectionAction->setShortcut ( Qt::Key_S ); - _showSelectionAction->setCheckable ( true ); - - _rubberChangeAction = new QAction ( tr("Change Rubber Style"), this ); - _rubberChangeAction->setObjectName ( "viewer.menuBar.view.changeRubber" ); - _rubberChangeAction->setStatusTip ( tr("Cycle through all avalaibles rubber drawing styles") ); - _rubberChangeAction->setShortcut ( Qt::Key_Asterisk ); - - _clearRulersAction = new QAction ( tr("Clear Rulers"), this ); - _clearRulersAction->setObjectName ( "viewer.menuBar.view.clearRulers" ); - _clearRulersAction->setStatusTip ( tr("Remove all rulers") ); - //_clearRulersAction->setShortcut ( QKeySequence(tr("K")) ); - - _controllerAction = new QAction ( tr("Controller"), this ); - _controllerAction->setObjectName ( "viewer.menuBar.tools.controller" ); - _controllerAction->setStatusTip ( tr("Fine Tune && Inspect DataBase") ); - _controllerAction->setIcon ( QIcon(":/images/swiss-knife.png") ); - _controllerAction->setShortcut ( QKeySequence(tr("CTRL+I")) ); - - _scriptAction = new QAction ( tr("Python Script"), this ); - _scriptAction->setObjectName ( "viewer.menuBar.tools.script" ); - _scriptAction->setStatusTip ( tr("Run Python Script. Must provide a ScripMain(cell) function") ); - _scriptAction->setIcon ( QIcon(":/images/python-logo-v3.png") ); - _scriptAction->setShortcut ( QKeySequence(tr("SHIFT+P,SHIFT+S")) ); - - //_stratusAction = new QAction ( tr("Stratus"), this ); - //_stratusAction->setObjectName ( "viewer.menuBar.tools.stratusScript" ); - //_stratusAction->setStatusTip ( tr("Run Stratus Script") ); - //_stratusAction->setIcon ( QIcon(":/images/stratus-cloud.png") ); - //_stratusAction->setShortcut ( QKeySequence(tr("SHIFT+P,SHIFT+S")) ); - } - - - void CellViewer::createMenus () - { - if ( _fileMenu ) return; - if ( !_openAction ) createActions (); - - menuBar()->setObjectName ( tr("viewer.menuBar") ); - - _fileMenu = menuBar()->addMenu ( tr("File") ); - _fileMenu->setObjectName ( "viewer.menuBar.file" ); - _fileMenu->addAction ( _openAction ); - _fileMenu->addSeparator (); - for ( size_t i=0 ; iaddAction ( _cellHistoryAction[i] ); - } - _fileMenu->addSeparator (); - _fileMenu->addAction ( _saveAction ); - _fileMenu->addSeparator (); - _fileMenu->addAction ( _importAction ); - _fileMenu->addAction ( _exportAction ); - _fileMenu->addSeparator (); - _fileMenu->addAction ( _printAction ); - _fileMenu->addAction ( _imageAction ); - _fileMenu->addAction ( _nextAction ); - _fileMenu->addSeparator (); - _fileMenu->addAction ( _closeAction ); - _fileMenu->addAction ( _exitAction ); - - _viewMenu = menuBar()->addMenu ( tr("View") ); - _viewMenu->setObjectName ( "viewer.menuBar.view" ); - _viewMenu->addAction ( _refreshAction ); - _viewMenu->addAction ( _fitToContentsAction ); - _viewMenu->addAction ( _gotoAction ); - _viewMenu->addAction ( _showSelectionAction ); - _viewMenu->addAction ( _rubberChangeAction ); - _viewMenu->addAction ( _clearRulersAction ); - - _toolsMenu = menuBar()->addMenu ( tr("Tools") ); - _toolsMenu->setObjectName ( "viewer.menuBar.tools" ); - _toolsMenu->addAction ( _controllerAction ); - _toolsMenu->addAction ( _scriptAction ); - //_toolsMenu->addAction ( _stratusAction ); - } - - - QMenu* CellViewer::createDebugMenu () - { - if ( !_debugMenu ) { - _debugMenu = menuBar()->addMenu ( tr("Debug") ); - _debugMenu->setObjectName ( "viewer.menuBar.debug" ); - } - return _debugMenu; - } - - - void CellViewer::createLayout () - { - if (_cellWidget) return; + setObjectName( "viewer" ); + menuBar()->setObjectName ( _getAbsWidgetPath("") ); _cellWidget = new CellWidget (); _controller = new ControllerWidget(); _goto = new GotoWidget (); _goto->changeDbuMode( _cellWidget->getDbuMode(), _cellWidget->getUnitPower() ); - //_mapView = _cellWidget->getMapView (); _cellWidget->bindCommand( &_moveCommand ); _cellWidget->bindCommand( &_zoomCommand ); @@ -319,7 +112,7 @@ namespace Hurricane { _cellWidget->bindCommand( &_hierarchyCommand ); _controller->setCellWidget( _cellWidget ); - MousePositionWidget* _mousePosition = new MousePositionWidget(); + _mousePosition = new MousePositionWidget(); statusBar()->addPermanentWidget( _mousePosition ); setCorner( Qt::TopLeftCorner , Qt::LeftDockWidgetArea ); @@ -327,6 +120,7 @@ namespace Hurricane { setCorner( Qt::TopRightCorner , Qt::RightDockWidgetArea ); setCorner( Qt::BottomRightCorner, Qt::RightDockWidgetArea ); + //_mapView = _cellWidget->getMapView (); //QDockWidget* mapViewDock = new QDockWidget ( tr("Map") ); //mapViewDock->setFeatures ( QDockWidget::DockWidgetVerticalTitleBar // | QDockWidget::DockWidgetMovable @@ -339,41 +133,385 @@ namespace Hurricane { setCentralWidget( _cellWidget ); - connect( this , SIGNAL(cellPreModificated()) , _cellWidget, SLOT(cellPreModificate()) ); - connect( this , SIGNAL(cellPostModificated()), _cellWidget, SLOT(cellPostModificate()) ); - connect( this , SIGNAL(redrawCellWidget()) , _cellWidget, SLOT(refresh()) ); - connect( _refreshAction , SIGNAL(triggered()) , _cellWidget, SLOT(refresh()) ); - connect( _fitToContentsAction , SIGNAL(triggered()) , _cellWidget, SLOT(fitToContents()) ); - connect( _showSelectionAction , SIGNAL(toggled(bool)) , this , SLOT(setShowSelection(bool)) ); - connect( _rubberChangeAction , SIGNAL(triggered()) , _cellWidget, SLOT(rubberChange()) ); - connect( _clearRulersAction , SIGNAL(triggered()) , _cellWidget, SLOT(clearRulers()) ); - connect( _controllerAction , SIGNAL(triggered()) , _controller, SLOT(toggleShow()) ); - connect( _scriptAction , SIGNAL(triggered()) , this , SLOT(runScript()) ); - //connect( _stratusAction , SIGNAL(triggered()) , this , SLOT(runStratusScript()) ); - connect( _gotoAction , SIGNAL(triggered()) , this , SLOT(doGoto()) ); + createMenus(); - connect( _cellWidget , SIGNAL(dbuModeChanged(unsigned int,DbU::UnitPower)) - , _goto , SLOT (changeDbuMode (unsigned int,DbU::UnitPower)) ); + connect( this , SIGNAL(cellPreModificated()) , _cellWidget, SLOT(cellPreModificate()) ); + connect( this , SIGNAL(cellPostModificated()), _cellWidget, SLOT(cellPostModificate()) ); + connect( this , SIGNAL(redrawCellWidget()) , _cellWidget, SLOT(refresh()) ); - connect( _cellWidget , SIGNAL(mousePositionChanged(const Point&)) - , _mousePosition , SLOT (setPosition(const Point&)) ); + connect( _cellWidget , SIGNAL(dbuModeChanged(unsigned int,DbU::UnitPower)) + , _goto , SLOT (changeDbuMode (unsigned int,DbU::UnitPower)) ); - connect( _cellWidget , SIGNAL(selectionModeChanged()) - , this , SLOT (changeSelectionMode ()) ); - //connect( &_selectCommand , SIGNAL(selectionToggled (Occurrence)) - // , _cellWidget , SLOT (toggleSelection (Occurrence)) ); - connect( &_selectCommand , SIGNAL(selectionToggled (Occurrence)) - , _cellWidget , SLOT (select (Occurrence)) ); + connect( _cellWidget , SIGNAL(mousePositionChanged(const Point&)) + , _mousePosition , SLOT (setPosition(const Point&)) ); - connect( _cellWidget , SIGNAL(stateChanged(shared_ptr&)) - , this , SLOT (setState (shared_ptr&)) ); - connect( this , SIGNAL(stateChanged(shared_ptr&)) - , _cellWidget , SLOT (setState (shared_ptr&)) ); + connect( _cellWidget , SIGNAL(selectionModeChanged()) + , this , SLOT (changeSelectionMode ()) ); + connect( &_selectCommand, SIGNAL(selectionToggled (Occurrence)) + , _cellWidget , SLOT (select (Occurrence)) ); + + connect( _cellWidget , SIGNAL(stateChanged(shared_ptr&)) + , this , SLOT (setState (shared_ptr&)) ); + connect( this , SIGNAL(stateChanged(shared_ptr&)) + , _cellWidget , SLOT (setState (shared_ptr&)) ); _cellWidget->refresh(); } + CellViewer::~CellViewer () + { + _controller->deleteLater (); + //_script->deleteLater (); + _goto->deleteLater (); + } + + + QString CellViewer::_getAbsWidgetPath ( const QString& relPath ) const + { + if (relPath.startsWith("viewer.")) return relPath; + return QString(_prefixWPath).append( relPath ); + } + + + bool CellViewer::hasMenu( const QString& relativePath ) const + { return findChild(_getAbsWidgetPath(relativePath)) != NULL; } + + + bool CellViewer::hasMenuAction( const QString& relativePath ) const + { return findChild(_getAbsWidgetPath(relativePath)) != NULL; } + + + QMenu* CellViewer::_getParentMenu( const QString& absolutePath ) const + { + QString parentPath = absolutePath.section('.',0,-2); + QMenu* parentMenu = findChild(parentPath); + if (parentMenu == NULL) { + if (parentPath != "viewer") { + cerr << Warning( "CellViewer::_getParentMenu() - Missing parent menu for %s." + , absolutePath.toStdString().c_str() ) << endl; + } + return NULL; + } + return parentMenu; + } + + + QMenu* CellViewer::addMenu ( const QString& path, string text, unsigned int flags ) + { + QString absolutePath = _getAbsWidgetPath( path ); + QMenu* menu = findChild(absolutePath); + + if (menu != NULL) return menu; + + if (flags & TopMenu) { + menu = menuBar()->addMenu( tr(text.c_str()) ); + menu->setObjectName( absolutePath ); + } else { + QMenu* parentMenu = _getParentMenu( absolutePath ); + if (parentMenu == NULL) return NULL; + + menu = parentMenu->addMenu( tr(text.c_str()) ); + menu->setObjectName( absolutePath ); + } + return menu; + } + + + bool CellViewer::addToMenu ( const QString& path ) + { + if (not path.endsWith("====")) return false; + + QMenu* menu = _getParentMenu( _getAbsWidgetPath(path) ); + if (menu == NULL) return false; + + menu->addSeparator(); + return true; + } + + + QAction* CellViewer::addToMenu ( const QString& path + , string text + , string textTip + , std::function< void() > callback + , QIcon icon ) + { + QString absolutePath = _getAbsWidgetPath( path ); + QAction* action = findChild(absolutePath); + if (action == NULL) { + QMenu* parentMenu = _getParentMenu( absolutePath ); + if (parentMenu == NULL) return NULL; + + action = new QAction( tr(text.c_str()), this ); + action->setObjectName( absolutePath ); + action->setStatusTip ( tr(textTip.c_str()) ); + action->setVisible ( true ); + if (not icon.isNull()) action->setIcon( icon ); + parentMenu->addAction( action ); + + _actionCallbacks.insert( make_pair(absolutePath,boost::any(callback)) ); + connect( action, SIGNAL(triggered()), this, SLOT(doAction()) ); + } + return action; + } + + + QAction* CellViewer::addToMenu ( const QString& path + , string text + , string textTip + , string scriptPath ) + { + QString absolutePath = _getAbsWidgetPath( path ); + QAction* action = findChild(absolutePath); + if (action == NULL) { + action = new QAction( tr(text.c_str()), this ); + action->setObjectName( absolutePath ); + action->setStatusTip ( tr(textTip.c_str()) ); + action->setVisible ( true ); + + QMenu* parentMenu = _getParentMenu( absolutePath ); + if (parentMenu != NULL) { + parentMenu->addAction( action ); + } else if (absolutePath == "viewer") { + addAction( action ); + } + + _actionCallbacks.insert( make_pair(absolutePath,boost::any(QString(scriptPath.c_str()))) ); + connect( action, SIGNAL(triggered()), this, SLOT(doAction()) ); + } + return action; + } + + + QAction* CellViewer::addToMenu ( QString path + , QString text + , QString textTip + , const QKeySequence& shortCut + , QIcon icon + //, QWidget* receiver + //, SlotMethod slotMethod + ) + { + QString absolutePath = _getAbsWidgetPath( path ); + QAction* action = findChild(absolutePath); + if (action == NULL) { + action = new QAction( text, this ); + action->setObjectName( absolutePath ); + action->setStatusTip ( textTip ); + action->setShortcut ( shortCut ); + action->setVisible ( true ); + if (not icon.isNull()) action->setIcon( icon ); + + QMenu* parentMenu = _getParentMenu( absolutePath ); + if (parentMenu != NULL) { + parentMenu->addAction( action ); + } else if (absolutePath == "viewer") { + addAction( action ); + } + + //if ((receiver != NULL) and (slotMethod != NULL)) + // connect( action, &QAction::triggered, receiver, slotMethod ); + } + return action; + } + + + void CellViewer::doAction () + { + QString path = sender()->objectName(); + ActionLut::const_iterator iaction = _actionCallbacks.find( path ); + if (iaction == _actionCallbacks.end()) { + cerr << Error( "CellViewer::doAction() - Path \"%s\" in not registered." + , path.toStdString().c_str() ) << endl; + return; + } + + const boost::any& callback = iaction->second; + if (callback.type() == typeid( std::function )) { + cerr << "Called function " << qPrintable(path) << endl; + ExceptionWidget::catchAllWrapper( boost::any_cast< std::function >(callback) ); + } else if (callback.type() == typeid( QString )) { + cerr << "Called script " << qPrintable(path) << ":" + << qPrintable(boost::any_cast(callback)) << endl; + runScript( boost::any_cast(callback) ); + } else { + cerr << Error("CellViewer::doAction(): For action \"%s\",\n" + " cannot cast the callback into QString or std::function." + , path.toStdString().c_str() ) << endl; + } + } + + + void CellViewer::createMenus () + { + addMenu ( "file" , "File" , TopMenu ); + addMenu ( "view" , "View" , TopMenu ); + addMenu ( "tools", "Tools", TopMenu ); + + // Building the "File" menu. + QAction* action = addToMenu( "viewer.interrupt" + , tr("Interrupt") + , tr("Interrupt the running tool") + , QKeySequence(tr("CTRL+C")) + ); + action->setVisible( false ); + addAction( action ); + connect( action, &QAction::triggered, this, &CellViewer::raiseToolInterrupt ); + + action = addToMenu( "file.openCell" + , tr("&Open Cell") + , tr("Open (load) a new Cell") + , QKeySequence(tr("CTRL+O")) + , QIcon(":/images/stock_open.png") + ); + addToMenu( "file.========" ); + + for ( int i=0 ; isetVisible( false ); + _cellHistoryAction[i]->setData ( i ); + _cellHistoryAction[i]->setFont ( Graphics::getFixedFont(QFont::Bold,false,false) ); + connect( _cellHistoryAction[i], &QAction::triggered, this, &CellViewer::openHistoryCell ); + } + addToMenu( "file.========" ); + + action = addToMenu( "file.saveCell" + , tr("&Save Cell") + , tr("Save (write) the current Cell") + , QKeySequence() + , QIcon(":/images/stock_save.png") + ); + action->setVisible( false ); + addToMenu( "file.========" ); + + action = addToMenu( "file.importCell" + , tr("&Import Cell") + , tr("Import (convert) a new Cell") + , QKeySequence() + ); + action = addToMenu( "file.exportCell" + , tr("&Export Cell") + , tr("Export (convert) Cell") + , QKeySequence() + ); + addToMenu( "file.========" ); + + action = addToMenu( "file.print" + , tr("&Print") + , tr("Print the displayed area") + , QKeySequence(tr("CTRL+P")) + ); + connect( action, &QAction::triggered, this, &CellViewer::printDisplay ); + + action = addToMenu( "file.image" + , tr("Save to &Image") + , tr("Save the displayed area to image") + , QKeySequence() + ); + connect( action, &QAction::triggered, this, &CellViewer::imageDisplay ); + + action = addToMenu( "file.nextBreakpoint" + , tr("&Next Breakpoint") + , tr("Proceed to the next breakpoint") + , QKeySequence() + ); + addToMenu( "file.========" ); + + action = addToMenu( "file.close" + , tr("&Close") + , tr("Close This Coriolis CellViewer") + , QKeySequence(tr("CTRL+W")) + ); + connect( action, &QAction::triggered, this, &CellViewer::close ); + + action = addToMenu( "file.close" + , tr("&Close") + , tr("Close This Coriolis CellViewer") + , QKeySequence(tr("CTRL+W")) + ); + + action = addToMenu( "file.exit" + , tr("&Exit") + , tr("Exit All Coriolis CellViewer") + , QKeySequence(tr("CTRL+Q")) + ); + connect ( action, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()) ); + + // Building the "View" menu. + action = addToMenu( "view.refresh" + , tr("&Refresh") + , tr("Force full redrawing of the display") + , QKeySequence(tr("CTRL+L")) + ); + connect( action, &QAction::triggered, _cellWidget, &CellWidget::refresh ); + + action = addToMenu( "view.fit" + , tr("&Fit to Contents") + , tr("Adjust zoom to fit the whole cell's contents") + , Qt::Key_F + ); + connect( action, &QAction::triggered, _cellWidget, &CellWidget::fitToContents ); + + action = addToMenu( "view.goto" + , tr("&Goto") + , tr("Center view on that point, with zoom adjustment") + , Qt::Key_G + ); + connect( action, &QAction::triggered, this, &CellViewer::doGoto ); + + _showSelectionAction = addToMenu( "view.showSelection" + , tr("&Show Selection") + , tr("Highlight the selected items (darken others)") + , Qt::Key_S + ); + _showSelectionAction->setCheckable( true ); + connect( _showSelectionAction, &QAction::toggled, this, &CellViewer::setShowSelection ); + + action = addToMenu( "view.changeRubber" + , tr("Change Rubber Style") + , tr("Cycle through all avalaibles rubber drawing styles") + , Qt::Key_Asterisk + ); + connect( action, &QAction::triggered, _cellWidget, &CellWidget::rubberChange ); + + action = addToMenu( "view.clearRulers" + , tr("Clear Rulers") + , tr("Remove all rulers") + , QKeySequence() + ); + connect( action, &QAction::triggered, _cellWidget, &CellWidget::clearRulers ); + + // Building the "Tools" menu. + action = addToMenu( "tools.controller" + , tr("Controller") + , tr("Fine Tune && Inspect DataBase") + , QKeySequence(tr("CTRL+I")) + , QIcon(":/images/swiss-knife.png") + ); + connect( action, &QAction::triggered, _controller, &ControllerWidget::toggleShow ); + + action = addToMenu( "tools.script" + , tr("Python Script") + , tr("Run Python Script. Must provide a ScripMain(cell) function") + , QKeySequence(tr("SHIFT+P,SHIFT+S")) + , QIcon(":/images/python-logo-v3.png") + ); + connect( action, &QAction::triggered, this, &CellViewer::runScriptWidget ); + } + + + QMenu* CellViewer::createDebugMenu () + { + if (not _debugMenu) + addMenu ( "debug" , "Debug" , TopMenu ); + return _debugMenu; + } + + void CellViewer::refreshTitle () { QString cellName = "None"; @@ -619,18 +757,35 @@ namespace Hurricane { } - void CellViewer::_runScript () + void CellViewer::_runScript ( QString scriptPath ) + { + if (scriptPath.endsWith(".py",Qt::CaseInsensitive)) + scriptPath.truncate( scriptPath.size()-3 ); + + Utilities::Path userScript ( scriptPath.toStdString() ); + Utilities::Path userDirectory ( userScript.dirname() ); + + if (not userDirectory.absolute()) + userDirectory = Utilities::Path::cwd() / userDirectory; + + Isobar::Script::addPath( userDirectory.string() ); + + dbo_ptr script = Isobar::Script::create(userScript.basename().string()); + script->setEditor ( this ); + script->runFunction( "ScriptMain", getCell() ); + + Isobar::Script::removePath( userDirectory.string() ); + } + + + void CellViewer::runScript ( QString scriptPath ) + { ExceptionWidget::catchAllWrapper( std::bind( &CellViewer::_runScript, this, scriptPath ) ); } + + + void CellViewer::runScriptWidget () { ScriptWidget::runScript( this, getCell() ); } - void CellViewer::runScript () - { ExceptionWidget::catchAllWrapper( std::bind( &CellViewer::_runScript, this ) ); } - - -//void CellViewer::runStratusScript () -//{ StratusWidget::runScript ( this ); } - - string CellViewer::_getString () const { ostringstream s; diff --git a/hurricane/src/viewer/PyCellViewer.cpp b/hurricane/src/viewer/PyCellViewer.cpp index 475fc198..55a634b8 100644 --- a/hurricane/src/viewer/PyCellViewer.cpp +++ b/hurricane/src/viewer/PyCellViewer.cpp @@ -1,8 +1,7 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2010-2012, All Rights Reserved +// Copyright (c) UPMC 2010-2014, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -41,6 +40,95 @@ extern "C" { DirectDestroyAttribute(PyCellViewer_destroy, PyCellViewer) + static PyObject* PyCellViewer_hasMenu ( PyCellViewer* self, PyObject* args ) + { + trace << "PyCellViewer_hasMenu()" << endl; + + HTRY + METHOD_HEAD("CellViewer.hasMenu()") + + char* path = NULL; + if (not PyArg_ParseTuple(args,"s:CellViewer.hasMenu()", &path)) { + PyErr_SetString ( ConstructorError, "CellViewer.hasMenu(): Takes exactly one argument." ); + return NULL; + } + + if (cw->hasMenu( path )) Py_RETURN_TRUE; + HCATCH + + Py_RETURN_FALSE; + } + + + static PyObject* PyCellViewer_hasMenuAction ( PyCellViewer* self, PyObject* args ) + { + trace << "PyCellViewer_hasMenuAction()" << endl; + + HTRY + METHOD_HEAD("CellViewer.hasMenuAction()") + + char* path = NULL; + if (not PyArg_ParseTuple(args,"s:CellViewer.hasMenuAction()", &path)) { + PyErr_SetString ( ConstructorError, "CellViewer.hasMenuAction(): Takes exactly one argument." ); + return NULL; + } + + if (cw->hasMenuAction( path )) Py_RETURN_TRUE; + HCATCH + + Py_RETURN_FALSE; + } + + + static PyObject* PyCellViewer_addMenu ( PyCellViewer* self, PyObject* args ) + { + trace << "PyCellViewer_addMenu()" << endl; + + HTRY + METHOD_HEAD("CellViewer.addMenu()") + + char* path = NULL; + char* text = NULL; + long flags = 0; + if (not PyArg_ParseTuple(args,"ssl:CellViewer.addMenu()", &path, &text, &flags)) { + PyErr_SetString ( ConstructorError, "CellViewer.addMenu(): Takes exactly three arguments." ); + return NULL; + } + + if (cw->addMenu( path, text, flags )) Py_RETURN_TRUE; + HCATCH + + Py_RETURN_FALSE; + } + + + static PyObject* PyCellViewer_addToMenu ( PyCellViewer* self, PyObject* args ) + { + trace << "PyCellViewer_addToMenu()" << endl; + + HTRY + METHOD_HEAD("CellViewer.addToMenu()") + + char* path = NULL; + char* text = NULL; + char* textTip = NULL; + char* scriptPath = NULL; + if (not PyArg_ParseTuple(args,"s|sss:CellViewer.addToMenu()", &path, &text, &textTip, &scriptPath)) { + PyErr_SetString ( ConstructorError, "CellViewer.addToMenu(): Takes one or four arguments exactly." ); + return NULL; + } + + if (text != NULL) { + if (cw->addToMenu( path, text, textTip, scriptPath )) Py_RETURN_TRUE; + } else { + if (cw->addToMenu( path )) Py_RETURN_TRUE; + } + HCATCH + + Py_RETURN_FALSE; + } + + static PyObject* PyCellViewer_getCell ( PyCellViewer* self ) { trace << "PyCellViewer_getCell ()" << endl; @@ -170,7 +258,15 @@ extern "C" { // PyCellViewer Attribute Method table. PyMethodDef PyCellViewer_Methods[] = - { { "getCell" , (PyCFunction)PyCellViewer_getCell , METH_NOARGS + { { "hasMenu" , (PyCFunction)PyCellViewer_hasMenu , METH_VARARGS + , "Return true if the menu at \"path\" exists." } + , { "hasMenuAction" , (PyCFunction)PyCellViewer_hasMenuAction , METH_VARARGS + , "Return true if the menu action at \"path\" exists." } + , { "addMenu" , (PyCFunction)PyCellViewer_addMenu , METH_VARARGS + , "Create a new menu at \"path\" and returns true if success." } + , { "addToMenu" , (PyCFunction)PyCellViewer_addToMenu , METH_VARARGS + , "Creates a new action at \"path\" and returns true if success." } + , { "getCell" , (PyCFunction)PyCellViewer_getCell , METH_NOARGS , "Return the currently edited Cell." } , { "setCell" , (PyCFunction)PyCellViewer_setCell , METH_VARARGS , "Load a Cell into the viewer." } @@ -205,6 +301,19 @@ extern "C" { PyTypeRootObjectDefinitions(CellViewer) + static void CellViewerLoadConstants ( PyObject* dictionnary ) { + PyObject* constant; + + LoadObjectConstant( dictionnary, CellViewer::NoFlags, "NoFlags" ) + LoadObjectConstant( dictionnary, CellViewer::TopMenu, "TopMenu" ) + } + + + extern void PyCellViewer_postModuleInit () + { + CellViewerLoadConstants(PyTypeCellViewer.tp_dict); + } + # endif // End of Shared Library Code Part. diff --git a/hurricane/src/viewer/PyViewer.cpp b/hurricane/src/viewer/PyViewer.cpp index 95572f7e..b593eedf 100644 --- a/hurricane/src/viewer/PyViewer.cpp +++ b/hurricane/src/viewer/PyViewer.cpp @@ -1,8 +1,7 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2010-2012, All Rights Reserved +// Copyright (c) UPMC/LIP6 2010-2014, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -113,6 +112,7 @@ extern "C" { PyModule_AddObject ( module, "CellViewer", (PyObject*)&PyTypeCellViewer ); PyDisplayStyle_postModuleInit(); + PyCellViewer_postModuleInit(); trace << "Viewer.so loaded " << (void*)&typeid(string) << endl; } diff --git a/hurricane/src/viewer/ScriptWidget.cpp b/hurricane/src/viewer/ScriptWidget.cpp index 58648ea4..966b8cda 100644 --- a/hurricane/src/viewer/ScriptWidget.cpp +++ b/hurricane/src/viewer/ScriptWidget.cpp @@ -14,7 +14,6 @@ // +-----------------------------------------------------------------+ -#include #include #include using namespace std; @@ -27,9 +26,7 @@ using namespace std; #include #include #include -#include "vlsisapd/utilities/Path.h" #include "hurricane/Warning.h" -#include "hurricane/viewer/Script.h" #include "hurricane/viewer/Graphics.h" #include "hurricane/viewer/ScriptWidget.h" #include "hurricane/viewer/CellViewer.h" @@ -94,34 +91,21 @@ namespace Hurricane { } - bool ScriptWidget::runScript ( QWidget* parent, Cell* cell ) + void ScriptWidget::runScript ( QWidget* parent, Cell* cell ) { ScriptWidget* dialog = new ScriptWidget ( parent ); bool doRunScript = (dialog->exec() == Accepted); QString scriptName = dialog->getScriptName (); delete dialog; - if ( not doRunScript ) return false; + if (not doRunScript) return; - if ( scriptName.endsWith(".py",Qt::CaseInsensitive) ) - scriptName.truncate ( scriptName.size()-3 ); - - Utilities::Path userScript ( scriptName.toStdString() ); - Utilities::Path userDirectory ( userScript.dirname() ); - - if ( not userDirectory.absolute() ) - userDirectory = Utilities::Path::cwd() / userDirectory; - - Isobar::Script::addPath ( userDirectory.string() ); - - dbo_ptr script = Isobar::Script::create(userScript.basename().string()); - script->setEditor ( qobject_cast(parent) ); - - bool returnCode = script->runFunction ( "ScriptMain", cell ); - - Isobar::Script::removePath ( userDirectory.string() ); - - return returnCode; + CellViewer* cw = qobject_cast(parent); + if (not cw) { + cerr << Error("ScriptWidget::runScript(): The parent widget is *not* a CellViewer, cancelling.") << endl; + return; + } + cw->runScript( scriptName ); } diff --git a/hurricane/src/viewer/hurricane/viewer/CellViewer.h b/hurricane/src/viewer/hurricane/viewer/CellViewer.h index 92658f03..2efca82d 100644 --- a/hurricane/src/viewer/hurricane/viewer/CellViewer.h +++ b/hurricane/src/viewer/hurricane/viewer/CellViewer.h @@ -18,9 +18,11 @@ #define HURRICANE_CELL_VIEWER_H #include +#include #include -using namespace std; +#include +#include #include class QEvent; class QKeyEvent; @@ -76,13 +78,39 @@ namespace Hurricane { Q_OBJECT; public: - enum { CellHistorySize = 10 }; - enum Flag { InCellChange = 0x0001 }; + enum { CellHistorySize = 10 }; + enum Flag { InCellChange = 0x0001 }; + enum FunctionFlag { NoFlags = 0x0000 + , TopMenu = 0x0001 }; + private: + typedef std::map< const QString, boost::any > ActionLut; + typedef bool (QWidget::* SlotMethod)(); public: CellViewer ( QWidget* parent=NULL ); virtual ~CellViewer (); inline bool isToolInterrupted () const; QMenu* createDebugMenu (); + bool hasMenu ( const QString& path ) const; + bool hasMenuAction ( const QString& path ) const; + QMenu* addMenu ( const QString& path + , std::string text + , unsigned int flags=NoFlags + ); + bool addToMenu ( const QString& path ); + QAction* addToMenu ( const QString& path + , std::string text + , std::string textTip + , std::function< void() > + , QIcon icon=QIcon() ); + QAction* addToMenu ( const QString& path + , std::string text + , std::string textTip + , std::string scriptPath ); + QAction* addToMenu ( QString path + , QString text + , QString textTip + , const QKeySequence& shortCut + , QIcon icon =QIcon()); inline void setEnableRedrawInterrupt ( bool ); inline void setApplicationName ( const QString& ); inline CellObserver* getCellObserver (); @@ -98,9 +126,10 @@ namespace Hurricane { void unselect ( Occurrence& ); void unselectAll (); inline void setLayerVisible ( const Name& layer, bool visible ); - void _runScript (); + void runScript ( QString scriptPath ); virtual std::string _getString () const; public slots: + void doAction (); void doGoto (); void changeSelectionMode (); void setShowSelection ( bool ); @@ -111,8 +140,7 @@ namespace Hurricane { void imageDisplay (); void raiseToolInterrupt (); void clearToolInterrupt (); - void runScript (); - //void runStratusScript (); + void runScriptWidget (); inline void emitCellAboutToChange (); inline void emitCellChanged (); signals: @@ -122,56 +150,40 @@ namespace Hurricane { void cellPreModificated (); void cellPostModificated (); protected: - void createActions (); void createMenus (); - void createLayout (); void refreshTitle (); void refreshHistory (); + private: + QString _getAbsWidgetPath ( const QString& relPath ) const; + QMenu* _getParentMenu ( const QString& ) const; + void _runScript ( QString scriptPath ); protected: - CellObserver _cellObserver; - QString _applicationName; - QAction* _toolInterruptAction; - QAction* _openAction; - QAction* _importAction; - QAction* _nextAction; - QAction* _cellHistoryAction[CellHistorySize]; - QAction* _printAction; - QAction* _imageAction; - QAction* _saveAction; - QAction* _exportAction; - QAction* _closeAction; - QAction* _exitAction; - QAction* _refreshAction; - QAction* _fitToContentsAction; - QAction* _gotoAction; - QAction* _showSelectionAction; - QAction* _rubberChangeAction; - QAction* _clearRulersAction; - QAction* _controllerAction; - QAction* _scriptAction; - QAction* _stratusAction; - QMenu* _fileMenu; - QMenu* _viewMenu; - QMenu* _toolsMenu; - QMenu* _debugMenu; - //MapView* _mapView; - MousePositionWidget* _mousePosition; - ControllerWidget* _controller; - ScriptWidget* _script; - GotoWidget* _goto; - CellWidget* _cellWidget; - MoveCommand _moveCommand; - ZoomCommand _zoomCommand; - RulerCommand _rulerCommand; - SelectCommand _selectCommand; - HierarchyCommand _hierarchyCommand; - list< shared_ptr > - _cellHistory; - bool _firstShow; - bool _toolInterrupt; - unsigned int _flags; - UpdateState _updateState; + static QString _prefixWPath; + CellObserver _cellObserver; + QString _applicationName; + QAction* _openAction; + QAction* _cellHistoryAction[CellHistorySize]; + QAction* _showSelectionAction; + QMenu* _debugMenu; + ActionLut _actionCallbacks; + // MapView* _mapView; + MousePositionWidget* _mousePosition; + ControllerWidget* _controller; + ScriptWidget* _script; + GotoWidget* _goto; + CellWidget* _cellWidget; + MoveCommand _moveCommand; + ZoomCommand _zoomCommand; + RulerCommand _rulerCommand; + SelectCommand _selectCommand; + HierarchyCommand _hierarchyCommand; + list< shared_ptr > + _cellHistory; + bool _firstShow; + bool _toolInterrupt; + unsigned int _flags; + UpdateState _updateState; }; diff --git a/hurricane/src/viewer/hurricane/viewer/PyCellViewer.h b/hurricane/src/viewer/hurricane/viewer/PyCellViewer.h index 16d8b0b7..ea52e336 100644 --- a/hurricane/src/viewer/hurricane/viewer/PyCellViewer.h +++ b/hurricane/src/viewer/hurricane/viewer/PyCellViewer.h @@ -1,8 +1,7 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2010-2012, All Rights Reserved +// Copyright (c) UPMC 2010-2014, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -15,8 +14,8 @@ // +-----------------------------------------------------------------+ -#ifndef __PY_HURRICANE_CELL_VIEWER__ -#define __PY_HURRICANE_CELL_VIEWER__ +#ifndef PY_HURRICANE_CELL_VIEWER_H +#define PY_HURRICANE_CELL_VIEWER_H #include "hurricane/isobar/PyHurricane.h" #include "hurricane/viewer/CellViewer.h" @@ -42,8 +41,9 @@ extern "C" { extern PyTypeObject PyTypeCellViewer; extern PyMethodDef PyCellViewer_Methods[]; - extern PyObject* PyCellViewer_create ( PyObject* self, PyObject* args ); - extern void PyCellViewer_LinkPyType (); + extern PyObject* PyCellViewer_create ( PyObject* self, PyObject* args ); + extern void PyCellViewer_LinkPyType (); + extern void PyCellViewer_postModuleInit (); #define IsPyCellViewer(v) ( (v)->ob_type == &PyTypeCellViewer ) @@ -57,4 +57,4 @@ extern "C" { } // End of Isobar namespace. -#endif // __PY_HURRICANE_CELL_VIEWER__ +#endif // PY_HURRICANE_CELL_VIEWER_H diff --git a/hurricane/src/viewer/hurricane/viewer/Script.h b/hurricane/src/viewer/hurricane/viewer/Script.h index 0963e440..ddc94f88 100644 --- a/hurricane/src/viewer/hurricane/viewer/Script.h +++ b/hurricane/src/viewer/hurricane/viewer/Script.h @@ -1,8 +1,7 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2012, All Rights Reserved +// Copyright (c) UPMC 2008-2014, All Rights Reserved // // +-----------------------------------------------------------------+ // | H U R R I C A N E | @@ -15,8 +14,8 @@ // +-----------------------------------------------------------------+ -# ifndef __ISOBAR_SCRIPT__ -# define __ISOBAR_SCRIPT__ +# ifndef ISOBAR_SCRIPT_H +# define ISOBAR_SCRIPT_H #include @@ -78,4 +77,4 @@ namespace Isobar { } // End of Isobar namespace. -# endif // __ISOBAR_SCRIPT__ +# endif // ISOBAR_SCRIPT_H diff --git a/hurricane/src/viewer/hurricane/viewer/ScriptWidget.h b/hurricane/src/viewer/hurricane/viewer/ScriptWidget.h index 1b00afe0..b85d066d 100644 --- a/hurricane/src/viewer/hurricane/viewer/ScriptWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/ScriptWidget.h @@ -30,7 +30,7 @@ namespace Hurricane { class ScriptWidget : public QDialog { Q_OBJECT; public: - static bool runScript ( QWidget* parent, Cell* ); + static void runScript ( QWidget* parent, Cell* ); const QString getScriptName () const; protected: ScriptWidget ( QWidget* parent=NULL ); diff --git a/kite/src/GraphicKiteEngine.cpp b/kite/src/GraphicKiteEngine.cpp index c48d6b0b..8f2fcdf2 100644 --- a/kite/src/GraphicKiteEngine.cpp +++ b/kite/src/GraphicKiteEngine.cpp @@ -159,7 +159,7 @@ namespace Kite { void GraphicKiteEngine::_saveGlobalSolution () { - KiteEngine* kite = KiteEngine::get( getCell() ); + KiteEngine* kite = getForFramework( NoFlags ); if (kite) kite->saveGlobalSolution (); } @@ -214,6 +214,13 @@ namespace Kite { } } + + void GraphicKiteEngine::_dumpMeasures () + { + KiteEngine* kite = getForFramework( NoFlags ); + if (kite) kite->dumpMeasures(); + } + void GraphicKiteEngine::_save () { @@ -226,53 +233,20 @@ namespace Kite { } - void GraphicKiteEngine::globalRoute () - { ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_globalRoute,this) ); } - - - void GraphicKiteEngine::loadGlobalSolution () - { ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_loadGlobalSolution,this) ); } - - - void GraphicKiteEngine::saveGlobalSolution () - { ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_saveGlobalSolution,this) ); } - - - void GraphicKiteEngine::detailPreRoute () + void GraphicKiteEngine::_detailRoute () { - ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_runNegociatePreRouted,this) ); + _loadGlobalRouting (); + _balanceGlobalDensity(); + _runNegociate (); } - void GraphicKiteEngine::detailRoute () + void GraphicKiteEngine::_route () { - ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_loadGlobalRouting ,this) ); - ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_balanceGlobalDensity,this) ); - ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_runNegociate ,this) ); - } - - - void GraphicKiteEngine::finalize () - { ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_finalize,this) ); } - - - void GraphicKiteEngine::save () - { ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_save,this) ); } - - - void GraphicKiteEngine::route () - { - detailPreRoute(); - globalRoute (); - detailRoute (); - finalize (); - } - - - void GraphicKiteEngine::dumpMeasures () - { - KiteEngine* kite = getForFramework( NoFlags ); - if (kite) kite->dumpMeasures(); + _runNegociatePreRouted(); + _globalRoute (); + _detailRoute (); + _finalize (); } @@ -298,93 +272,58 @@ namespace Kite { _viewer = viewer; - QMenu* prMenu = _viewer->findChild("viewer.menuBar.placeAndRoute"); - QMenu* stepMenu = _viewer->findChild("viewer.menuBar.placeAndRoute.stepByStep"); - if (prMenu == NULL) { - QMenuBar* menuBar = _viewer->findChild("viewer.menuBar"); - if (menuBar == NULL) { - cerr << Warning( "GraphicKiteEngine::addToMenu() - No MenuBar in parent widget." ) << endl; - return; - } - prMenu = menuBar->addMenu( tr("P&&R") ); - prMenu->setObjectName( "viewer.menuBar.placeAndRoute" ); - - stepMenu = prMenu->addMenu( tr("&Step by Step") ); - stepMenu->setObjectName( "viewer.menuBar.placeAndRoute.stepByStep" ); - - prMenu->addSeparator(); - } - - QAction* dRouteAction = _viewer->findChild("viewer.menuBar.placeAndRoute.detailedRoute"); - if (dRouteAction) + if (_viewer->hasMenuAction("placeAndRoute.route")) { cerr << Warning( "GraphicKiteEngine::addToMenu() - Kite detailed router already hooked in." ) << endl; - else { - stepMenu->addSeparator(); - - QAction* dPreRouteAction = new QAction ( tr("Kite - Detailed Pre-Route"), _viewer ); - dPreRouteAction->setObjectName( "viewer.menuBar.placeAndPreRoute.stepBystep.detailedPreRoute" ); - dPreRouteAction->setStatusTip ( tr("Run the Kite detailed router on pre-routed nets") ); - dPreRouteAction->setVisible ( true ); - stepMenu->addAction( dPreRouteAction ); - - QAction* gRouteAction = new QAction ( tr("Kite - &Global Route"), _viewer ); - gRouteAction->setObjectName( "viewer.menuBar.placeAndRoute.stepBystep.globalRoute" ); - gRouteAction->setStatusTip ( tr("Run the Knik global router") ); - gRouteAction->setVisible ( true ); - stepMenu->addAction( gRouteAction ); - - QAction* gLoadSolutionAction = new QAction ( tr("Kite - &Load Global Routing"), _viewer ); - gLoadSolutionAction->setObjectName( "viewer.menuBar.placeAndRoute.stepByStep.loadGlobalRouting" ); - gLoadSolutionAction->setStatusTip ( tr("Load a solution for the global routing (.kgr)") ); - gLoadSolutionAction->setVisible ( true ); - stepMenu->addAction( gLoadSolutionAction ); - - QAction* gSaveSolutionAction = new QAction ( tr("Kite - &Save Global Routing"), _viewer ); - gSaveSolutionAction->setObjectName( "viewer.menuBar.placeAndRoute.stepByStep.saveGlobalRouting" ); - gSaveSolutionAction->setStatusTip ( tr("Save a global router solution (.kgr)") ); - gSaveSolutionAction->setVisible ( true ); - stepMenu->addAction( gSaveSolutionAction ); - - dRouteAction = new QAction ( tr("Kite - &Detailed Route"), _viewer ); - dRouteAction->setObjectName( "viewer.menuBar.placeAndRoute.stepBystep.detailedRoute" ); - dRouteAction->setStatusTip ( tr("Run the Kite detailed router") ); - dRouteAction->setVisible ( true ); - stepMenu->addAction( dRouteAction ); - - QAction* dFinalizeAction = new QAction( tr("Kite - &Finalize Routing"), _viewer ); - dFinalizeAction->setObjectName( "viewer.menuBar.placeAndRoute.stepBystep.finalize" ); - dFinalizeAction->setStatusTip ( tr("Closing Routing") ); - dFinalizeAction->setVisible ( true ); - stepMenu->addAction( dFinalizeAction ); - - QAction* dDumpMeasuresAction = new QAction ( tr("Kite - Dump &Measures"), _viewer ); - dDumpMeasuresAction->setObjectName( "viewer.menuBar.placeAndRoute.stepBystep.dumpMeasures" ); - dDumpMeasuresAction->setStatusTip ( tr("Dumping Measurements on the disk") ); - dDumpMeasuresAction->setVisible ( true ); - stepMenu->addAction( dDumpMeasuresAction ); - - QAction* dSaveAction = new QAction ( tr("Kite - &Save Design"), _viewer ); - dSaveAction->setObjectName( "viewer.menuBar.placeAndRoute.stepBystep.save" ); - dSaveAction->setStatusTip ( tr("Save routed design (temporary hack)") ); - dSaveAction->setVisible ( true ); - stepMenu->addAction( dSaveAction ); - - QAction* routeAction = new QAction ( tr("Kite - &Route"), _viewer ); - routeAction->setObjectName( "viewer.menuBar.placeAndRoute.route" ); - routeAction->setStatusTip ( tr("Route the design (global & detailed)") ); - routeAction->setVisible ( true ); - prMenu->addAction( routeAction ); - - connect( gLoadSolutionAction, SIGNAL(triggered()), this, SLOT(loadGlobalSolution()) ); - connect( gSaveSolutionAction, SIGNAL(triggered()), this, SLOT(saveGlobalSolution()) ); - connect( gRouteAction , SIGNAL(triggered()), this, SLOT(globalRoute ()) ); - connect( dPreRouteAction , SIGNAL(triggered()), this, SLOT(detailPreRoute ()) ); - connect( dRouteAction , SIGNAL(triggered()), this, SLOT(detailRoute ()) ); - connect( dFinalizeAction , SIGNAL(triggered()), this, SLOT(finalize ()) ); - connect( dSaveAction , SIGNAL(triggered()), this, SLOT(save ()) ); - connect( dDumpMeasuresAction, SIGNAL(triggered()), this, SLOT(dumpMeasures ()) ); - connect( routeAction , SIGNAL(triggered()), this, SLOT(route ()) ); + return; } + + _viewer->addToMenu( "placeAndRoute.route" + , "Kite - &Route" + , "Route the design (global & detailed)" + , std::bind(&GraphicKiteEngine::_route,this) + ); + + _viewer->addToMenu( "placeAndRoute.stepByStep.========" ); + _viewer->addToMenu( "placeAndRoute.stepByStep.detailedPreRoute" + , "Kite - Detailed Pre-Route" + , "Run the Kite detailed router on pre-routed nets" + , std::bind(&GraphicKiteEngine::_runNegociatePreRouted,this) + ); + _viewer->addToMenu( "placeAndRoute.stepByStep.globalRoute" + , "Kite - &Global Route" + , "Run the Knik global router" + , std::bind(&GraphicKiteEngine::_globalRoute,this) + ); + _viewer->addToMenu( "placeAndRoute.stepByStep.loadGlobalRouting" + , "Kite - &Load Global Routing" + , "Load a solution for the global routing (.kgr)" + , std::bind(&GraphicKiteEngine::_loadGlobalSolution,this) + ); + _viewer->addToMenu( "placeAndRoute.stepByStep.saveGlobalRouting" + , "Kite - &Save Global Routing" + , "Save a global router solution (.kgr)" + , std::bind(&GraphicKiteEngine::_saveGlobalSolution,this) + ); + _viewer->addToMenu( "placeAndRoute.stepByStep.detailedRoute" + , "Kite - &Detailed Route" + , "Run the Kite detailed router" + , std::bind(&GraphicKiteEngine::_detailRoute,this) + ); + _viewer->addToMenu( "placeAndRoute.stepByStep.finalize" + , "Kite - &Finalize Routing" + , "Closing Routing" + , std::bind(&GraphicKiteEngine::_finalize,this) + ); + _viewer->addToMenu( "placeAndRoute.stepByStep.dumpMeasures" + , "Kite - Dump &Measures" + , "Dumping Measurements on the disk" + , std::bind(&GraphicKiteEngine::_dumpMeasures,this) + ); + _viewer->addToMenu( "placeAndRoute.stepByStep.save" + , "Kite - &Save Design" + , "Save routed design (temporary hack)" + , std::bind(&GraphicKiteEngine::_save,this) + ); } diff --git a/kite/src/kite/GraphicKiteEngine.h b/kite/src/kite/GraphicKiteEngine.h index 01fc7e92..f409bfe1 100644 --- a/kite/src/kite/GraphicKiteEngine.h +++ b/kite/src/kite/GraphicKiteEngine.h @@ -76,16 +76,6 @@ namespace Kite { virtual size_t release (); virtual void addToMenu ( CellViewer* ); void postEvent (); - public slots: - void detailPreRoute (); - void loadGlobalSolution (); - void saveGlobalSolution (); - void globalRoute (); - void detailRoute (); - void finalize (); - void route (); - void save (); - void dumpMeasures (); protected: static size_t _references; @@ -94,6 +84,7 @@ namespace Kite { protected: GraphicKiteEngine (); virtual ~GraphicKiteEngine (); + void _route (); void _loadGlobalSolution (); void _saveGlobalSolution (); void _globalRoute (); @@ -101,8 +92,10 @@ namespace Kite { void _balanceGlobalDensity (); void _runNegociatePreRouted (); void _runNegociate (); + void _detailRoute (); void _finalize (); void _save (); + void _dumpMeasures (); }; diff --git a/mauka/src/GraphicMaukaEngine.cpp b/mauka/src/GraphicMaukaEngine.cpp index 432f60e0..b1f2ee53 100644 --- a/mauka/src/GraphicMaukaEngine.cpp +++ b/mauka/src/GraphicMaukaEngine.cpp @@ -206,13 +206,13 @@ namespace Mauka { void GraphicMaukaEngine::_place () { if (MetisEngine::isHMetisCapable()) { - doQuadriPart(); + _doQuadriPart(); } else { cerr << Warning("Mauka has not been compiled againts hMETIS.\n" " Quadri-partition step is disabled, simulated annealing may be *very* long." ) << endl; } - doSimulatedAnnealing(); + _doSimulatedAnnealing(); _save(); } @@ -227,85 +227,32 @@ namespace Mauka { } - void GraphicMaukaEngine::doQuadriPart () - { ExceptionWidget::catchAllWrapper( std::bind(&GraphicMaukaEngine::_doQuadriPart,this) ); } - - - void GraphicMaukaEngine::doSimulatedAnnealing () - { ExceptionWidget::catchAllWrapper( std::bind(&GraphicMaukaEngine::_doSimulatedAnnealing,this) ); } - - - void GraphicMaukaEngine::place () - { ExceptionWidget::catchAllWrapper( std::bind(&GraphicMaukaEngine::_place,this) ); } - - - void GraphicMaukaEngine::save () - { ExceptionWidget::catchAllWrapper( std::bind(&GraphicMaukaEngine::_save,this) ); } - - void GraphicMaukaEngine::addToMenu ( CellViewer* viewer ) { - assert ( _viewer == NULL ); + assert( _viewer == NULL ); _viewer = viewer; - QMenu* prMenu = _viewer->findChild("viewer.menuBar.placeAndRoute"); - QMenu* stepMenu = _viewer->findChild("viewer.menuBar.placeAndRoute.stepByStep"); - if ( prMenu == NULL ) { - QMenuBar* menuBar = _viewer->findChild("viewer.menuBar"); - if ( menuBar == NULL ) { - cerr << Warning("GraphicMaukaEngine::addToMenu() - No MenuBar in parent widget.") << endl; - return; - } - prMenu = menuBar->addMenu ( tr("P&&R") ); - prMenu->setObjectName ( "viewer.menuBar.placeAndRoute" ); - - stepMenu = prMenu->addMenu ( tr("&Step by Step") ); - stepMenu->setObjectName ( "viewer.menuBar.placeAndRoute.stepByStep" ); - - prMenu->addSeparator (); + if (_viewer->hasMenuAction("placeAndRoute.maukaPlace")) { + cerr << Warning( "GraphicMaukaEngine::addToMenu() - Mauka placer already hooked in." ) << endl; + return; } - QAction* placeAction = _viewer->findChild("viewer.menuBar.placeAndRoute.maukaPlace"); - if ( placeAction != NULL ) - cerr << Warning("GraphicMaukaEngine::addToMenu() - Mauka placer already hooked in.") << endl; - else { - QAction* quadriPartAction = new QAction ( tr("Mauka - &QuadriPartition"), _viewer ); - quadriPartAction->setObjectName ( "viewer.menuBar.placeAndRoute.quadriPartition" ); - quadriPartAction->setStatusTip ( tr("Run the hMETIS quadri-partitioner") ); - quadriPartAction->setVisible ( true ); - stepMenu->addAction ( quadriPartAction ); - - QAction* annealingAction = new QAction ( tr("Mauka - &Place"), _viewer ); - annealingAction->setObjectName ( "viewer.menuBar.placeAndRoute.maukaPlace" ); - annealingAction->setStatusTip ( tr("Run the Mauka placer") ); - annealingAction->setVisible ( true ); - stepMenu->addAction ( annealingAction ); - - QAction* placeAction = new QAction ( tr("Mauka - &Place"), _viewer ); - placeAction->setObjectName ( "viewer.menuBar.placeAndRoute.place" ); - placeAction->setStatusTip ( tr("Run the Mauka placer") ); - placeAction->setVisible ( true ); - prMenu->addAction ( placeAction ); - - connect ( quadriPartAction, SIGNAL(triggered()), this, SLOT(doQuadriPart()) ); - connect ( annealingAction , SIGNAL(triggered()), this, SLOT(doSimulatedAnnealing()) ); - connect ( placeAction , SIGNAL(triggered()), this, SLOT(place()) ); - } - - // ControllerWidget* controller = _viewer->getControllerWidget(); - // ConfigurationWidget* setting = controller->getSettings() - // ->findChild("controller.tabSettings.setting.mauka"); - - // if ( setting == NULL ) { - // setting = new ConfigurationWidget (); - // setting->setObjectName ( "controller.tabSettings.setting.mauka" ); - // setting->setConfiguration ( Nimbus::Configuration::getDefault() - // , Metis::Configuration::getDefault() - // , Configuration::getDefault() - // ); - // controller->addSetting ( setting, "Mauka" ); - // } + _viewer->addToMenu( "placeAndRoute.maukaPlace" + , "Mauka - &Place" + , "Run the Mauka placer" + , std::bind(&GraphicMaukaEngine::_place,this) + ); + _viewer->addToMenu( "placeAndRoute.stepByStep.quadriPartition" + , "Mauka - &QuadriPartition" + , "Run the hMETIS quadri-partitioner" + , std::bind(&GraphicMaukaEngine::_doQuadriPart,this) + ); + _viewer->addToMenu( "placeAndRoute.stepByStep.simulatedAnnealing" + , "Mauka - &Simulated Annealing" + , "Run the Mauka simulated annealing detailed placer" + , std::bind(&GraphicMaukaEngine::_doSimulatedAnnealing,this) + ); } diff --git a/mauka/src/mauka/GraphicMaukaEngine.h b/mauka/src/mauka/GraphicMaukaEngine.h index 1f3181cc..f3767bce 100644 --- a/mauka/src/mauka/GraphicMaukaEngine.h +++ b/mauka/src/mauka/GraphicMaukaEngine.h @@ -51,7 +51,6 @@ namespace Mauka { public: enum Flags { NoFlags=0x0000, CreateEngine=0x0001 }; - public: MaukaEngine* createEngine (); MaukaEngine* getForFramework ( unsigned int flags ); @@ -68,12 +67,6 @@ namespace Mauka { virtual size_t release (); virtual void addToMenu ( CellViewer* ); void refreshViewer (); - public slots: - void doQuadriPart (); - void doSimulatedAnnealing (); - void place (); - void save (); - protected: static size_t _references; static GraphicMaukaEngine* _singleton; diff --git a/unicorn/src/CMakeLists.txt b/unicorn/src/CMakeLists.txt index 16a398b5..e5468ab8 100644 --- a/unicorn/src/CMakeLists.txt +++ b/unicorn/src/CMakeLists.txt @@ -93,4 +93,6 @@ install ( FILES ${includes} ${mocincludes} ${pyIncludes} DESTINATION include/coriolis2/unicorn ) + install ( FILES init/unicornInit.py + DESTINATION ${PYTHON_SITE_PACKAGES}/unicorn ) diff --git a/unicorn/src/UnicornGui.cpp b/unicorn/src/UnicornGui.cpp index 4d051db4..8feadae5 100644 --- a/unicorn/src/UnicornGui.cpp +++ b/unicorn/src/UnicornGui.cpp @@ -14,9 +14,11 @@ // +-----------------------------------------------------------------+ +#include #include #include #include "hurricane/Warning.h" +#include "hurricane/viewer/Script.h" #include "hurricane/viewer/CellWidget.h" #include "crlcore/Catalog.h" #include "crlcore/AllianceFramework.h" @@ -32,7 +34,9 @@ namespace Unicorn { + using Hurricane::dbo_ptr; using Hurricane::Warning; + using CRL::System; using CRL::Catalog; using CRL::AllianceFramework; using CRL::DefExport; @@ -56,13 +60,40 @@ namespace Unicorn { , _tools () , _importDialog(new ImportCellDialog(this)) , _exportDialog(new ExportCellDialog(this)) - { } + { + addMenu ( "placeAndRoute" , "P&&R" , CellViewer::TopMenu ); + addMenu ( "placeAndRoute.stepByStep", "&Step by Step" ); + addToMenu( "placeAndRoute.========" ); + + _runUnicornInit(); + } UnicornGui::~UnicornGui () { } + void UnicornGui::_runUnicornInit () + { + Utilities::Path pythonSitePackages = System::getPath("pythonSitePackages"); + Utilities::Path systemConfDir = pythonSitePackages / "unicorn"; + Utilities::Path systemConfFile = systemConfDir / "unicornInit.py"; + + if (systemConfFile.exists()) { + Isobar::Script::addPath( systemConfDir.string() ); + + dbo_ptr script = Isobar::Script::create( systemConfFile.stem().string() ); + script->setEditor ( this ); + script->runFunction( "unicornConfigure", getCell() ); + + Isobar::Script::removePath( systemConfDir.string() ); + } else { + cerr << Warning("System configuration file:\n <%s> not found." + ,systemConfFile.string().c_str()) << endl; + } + } + + UnicornGui* UnicornGui::create ( QWidget* parent ) { UnicornGui* unicorn = new UnicornGui ( parent ); diff --git a/unicorn/src/init/unicornInit.py b/unicorn/src/init/unicornInit.py new file mode 100644 index 00000000..d7025ef1 --- /dev/null +++ b/unicorn/src/init/unicornInit.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +try: + import sys + import os.path + from helpers import ErrorMessage + from helpers import WarningMessage + import Viewer +except ImportError, e: + module = str(e).split()[-1] + + print '[ERROR] The <%s> python module or symbol cannot be loaded.' % module + print ' Please check the integrity of the package.' + sys.exit(1) +except Exception, e: + print '[ERROR] A strange exception occurred while loading the basic Coriolis/Python' + print ' modules. Something may be wrong at Python/C API level.\n' + print ' %s' % e + sys.exit(2) + + +def unicornConfigure ( cell=None ): + editor = None + if globals().has_key('__editor'): + editor = __editor + else: + print ErrorMessage( 3, 'unicornConfigure.py: Must be run from a CellView derived class.' ) + return + + cumulusDir = None + for path in sys.path: + if path.endswith('/cumulus'): + cumulusDir = path + if not cumulusDir: + print ErrorMessage( 3, 'unicornConfigure.py: Cannot find in PYTHONPATH.' ) + return + + pluginsDir = os.path.join( cumulusDir, 'plugins' ) + if not os.path.isdir(pluginsDir): + print ErrorMessage( 3, 'unicornConfigure.py: Cannot find directory:' \ + , '<%s>' % pluginsDir ) + return + sys.path.append( pluginsDir ) + + if editor.hasMenu( 'plugins' ): + print WarningMessage( 'The menu has already been created.' ) + return + + editor.addMenu( 'plugins', 'Plu&gins', Viewer.CellViewer.TopMenu ) + + for pluginFile in os.listdir( pluginsDir ): + if not pluginFile.endswith('.py'): continue + + moduleName = os.path.basename(pluginFile)[:-3] + module = __import__( moduleName, globals(), locals(), moduleName ) + + if not module.__dict__.has_key('unicornHook'): + print WarningMessage( 'Module <%s> do not provides the unicornHook() method, skipped.' \ + % moduleName ) + continue + + module.__dict__['unicornHook']( editor ) + + return diff --git a/unicorn/src/unicorn/UnicornGui.h b/unicorn/src/unicorn/UnicornGui.h index e0c5807b..58d71f32 100644 --- a/unicorn/src/unicorn/UnicornGui.h +++ b/unicorn/src/unicorn/UnicornGui.h @@ -47,22 +47,23 @@ namespace Unicorn { class UnicornGui : public CellViewer { Q_OBJECT; public: - static UnicornGui* create ( QWidget* parent=NULL ); - void destroy (); - static inline Banner& getBanner (); - virtual Cell* getCellFromDb ( const char* name ); - void registerTool ( GraphicTool* ); - virtual std::string _getString () const; - public slots: - void openCell (); - void saveCell (); - void importCell (); - void exportCell (); - protected: - UnicornGui ( QWidget* parent ); - virtual ~UnicornGui (); - virtual void _postCreate (); - virtual void _preDestroy (); + static UnicornGui* create ( QWidget* parent=NULL ); + void destroy (); + static inline Banner& getBanner (); + virtual Cell* getCellFromDb ( const char* name ); + void registerTool ( GraphicTool* ); + virtual std::string _getString () const; + public slots: + void openCell (); + void saveCell (); + void importCell (); + void exportCell (); + protected: + UnicornGui ( QWidget* parent ); + virtual ~UnicornGui (); + virtual void _postCreate (); + virtual void _preDestroy (); + void _runUnicornInit (); protected: static Banner _banner; set _tools;