#!/usr/bin/env python import sys from PyQt4.QtCore import * from PyQt4.QtGui import * # -------------------------------------------------------------------------- factories = { } class Area (QGraphicsRectItem): def __init__ (self, parent=None) : QGraphicsRectItem.__init__ (self, parent) self.Title = "" self.topLevel = False self.setRect (0, 0, 100, 100) self.setFlag (QGraphicsItem.ItemIsMovable) self.setFlag (QGraphicsItem.ItemIsSelectable) self.setFlag (QGraphicsItem.ItemSendsScenePositionChanges) self.setAcceptDrops (True) def setTitle (self, text) : self.Title = text def addArea (self, area) : area.setParentItem (self) def addSource (self, source) : source.setParentItem (self) def addTarget (self, target) : target.setParentItem (self) def updateAllConnections (self) : for item in self.childItems () : if isinstance (item, Area) : item.updateAllConnections () if isinstance (item, Source) : for conn in item.connections : conn.updateConnection () if isinstance (item, Target) : for conn in item.connections : conn.updateConnection () def itemChange (self, change, value) : if change == QGraphicsItem.ItemPositionChange : # and scene () != None # self.setBrush (QBrush (QColor (Qt.red))) # update connections with source in this area for src in self.childItems () : if isinstance (src, Source) : for conn in src.connections : conn.updateConnection () if isinstance (src, Target) : for conn in src.connections : conn.updateConnection () return QGraphicsItem.itemChange (self, change, value) def dragEnterEvent (self, event) : mime = event.mimeData () if (mime.hasColor () and not self.topLevel or mime.hasFormat ("application/x-qview-component") ) : event.setAccepted (True) else : event.setAccepted (False) def dropEvent (self, event) : mime = event.mimeData () if mime.hasColor() and not self.topLevel : color = QColor (mime.colorData()) self.setBrush (color) if mime.hasFormat ("application/x-qview-component") : name = str (mime.data ("application/x-qview-component")) if name in factories : func = factories [name] item = func () if isinstance (item, QWidget) : proxy = QGraphicsProxyWidget () proxy.setWidget (item) proxy.setWindowFlags (Qt.Dialog) item = proxy item.setFlag (QGraphicsItem.ItemIsMovable) item.setFlag (QGraphicsItem.ItemIsSelectable) item.setParentItem (self) item.setPos (event.scenePos() - self.scenePos()) # -------------------------------------------------------------------------- class Scene (QGraphicsScene): def __init__ (self, parent=None) : QGraphicsScene.__init__ (self, parent) def dragEnterEvent (self, event) : if self.itemAt (event.pos()) == None: mime = event.mimeData () if mime.hasFormat ("application/x-qview-component") : event.setAccepted (True) else : event.setAccepted (False) def dropEvent (self, event) : mime = event.mimeData () if mime.hasFormat ("application/x-qview-component") : name = str (mime.data ("application/x-qview-component")) if name in factories : func = factories [name] item = func () self.addItem (item) item.setPos (event.scenePos() - self.scenePos()) # -------------------------------------------------------------------------- class Source (QGraphicsRectItem) : def __init__ (self, parent=None) : QGraphicsRectItem.__init__ (self, parent) self.connections = [ ] self.setRect (0, 0, 10, 10) self.setPen (QPen (Qt.red)) self.setBrush (QBrush (Qt.green)) self.setFlag (QGraphicsItem.ItemIsMovable) self.setFlag (QGraphicsItem.ItemIsSelectable) def getArea (self) : return self.parentItem () # -------------------------------------------------------------------------- class Target (QGraphicsRectItem) : def __init__ (self, parent=None) : QGraphicsRectItem.__init__ (self, parent) self.connections = [ ] self.setRect (0, 0, 10, 10) self.setPen (QPen (Qt.red)) self.setBrush (QBrush (Qt.yellow)) self.setFlag (QGraphicsItem.ItemIsMovable) self.setFlag (QGraphicsItem.ItemIsSelectable) def getArea (self) : return self.parentItem () # -------------------------------------------------------------------------- class Connection : def __init__ (self) : self.source = None self.target = None self.x1 = 0 self.y1 = 0 self.group = None self.pen = None def setSource (self, item) : self.source = item if item != None : item.connections.append (self) def setTarget (self, item) : self.target = item item.connections.append (self) def addLine (self, x2, y2) : if self.x1 != x2 or self.y1 != y2 : line = QGraphicsLineItem () line.setLine (self.x1, self.y1, x2, y2) line.setPen (self.pen) line.setParentItem (self.group) self.x1 = x2 self.y1 = y2 def horizLine (self, x2) : self.addLine (x2, self.y1) def vertLine (self, y2) : self.addLine (self.x1, y2) def updateConnection (self) : scene = self.source.scene () # delete previous group if self.group != None and scene != None: scene.removeItem (self.group) self.group = None # create new group self.group = QGraphicsItemGroup () self.group.setFlag (QGraphicsItem.ItemHasNoContents) pt1 = self.source.mapToScene (self.source.rect().center ()) pt2 = self.target.mapToScene (self.target.rect().center ()) self.x1 = pt1.x() self.y1 = pt1.y() x2 = pt2.x() y2 = pt2.y() self.pen = QPen (Qt.red) a1 = self.source.getArea () r1 = a1.rect() tr1 = a1.mapToScene (r1.topRight()) br1 = a1.mapToScene (r1.bottomRight()) src_right = tr1.x() src_top = tr1.y() src_bottom = br1.y() a2 = self.target.getArea () r2 = a2.rect() tr2 = a2.mapToScene (r2.topRight()) br2 = a2.mapToScene (r2.bottomRight()) tgt_right = tr2.x() tgt_top = tr2.y() tgt_bottom = br2.y() delta = 20 if self.x1 + 2*delta < x2 : x = (self.x1 + x2) / 2 self.horizLine (x) # half way in horizontal direction self.vertLine (y2) self.horizLine (x2) else : # real target x3 = x2 y3 = y2 # point behind target x2 -= delta y2 -= delta self.horizLine (self.x1 + delta) # small starting line y = (self.y1 + y2) / 2 if src_bottom + delta <= tgt_top : y = (src_bottom + tgt_top)/2 self.vertLine (y) # half way in vertical direction self.horizLine (x2) # line in horizontal direction elif tgt_bottom + delta <= src_top : y = (tgt_bottom + src_top)/2 self.vertLine (y) # half way in vertical direction self.horizLine (x2) # line in horizontal direction elif self.y1 < y2 : # go below target if tgt_right > src_right : self.horizLine (tgt_right + delta) else : self.horizLine (src_right + delta) self.vertLine (tgt_bottom + delta) self.horizLine (x2) else : # go above target if tgt_right > src_right : self.horizLine (tgt_right + delta) else : self.horizLine (src_right + delta) self.vertLine (tgt_top - delta) self.horizLine (x2) # to center of target self.vertLine (y3) self.horizLine (x3) if scene != None : scene.addItem (self.group) # -------------------------------------------------------------------------- class Palette (QTabWidget): def __init__ (self, parent=None) : QTabWidget.__init__ (self, parent) initPalette (self) def addPage (self, name, page) : self.addTab (page, name) class PalettePage (QToolBar): def __init__ (self, parent=None) : QToolBar.__init__ (self, parent) def addItem (self, name, item) : item.setText (name) item.setToolTip (name) self.addWidget (item) class PaletteItem (QToolButton): def __init__ (self, parent=None) : QToolBar.__init__ (self, parent) def setupPixmap (self, drag) : pass def mousePressEvent (self, event) : if event.button() == Qt.LeftButton : drag = QDrag (self) mimeData = QMimeData () self.setupMimeData (mimeData) drag.setMimeData (mimeData) self.setupPixmap (drag) dropAction = drag.exec_ (Qt.MoveAction | Qt.CopyAction | Qt.LinkAction) # -------------------------------------------------------------------------- class ColorItem (PaletteItem): def __init__ (self, parent=None) : PaletteItem.__init__ (self, parent) self.color = None def setColor (self, color) : self.color = color p = self.palette () p.setColor (QPalette.ButtonText, self.color) self.setPalette (p) pixmap = QPixmap (12, 12) pixmap.fill (Qt.transparent) painter = QPainter (pixmap) painter.setPen (Qt.NoPen) painter.setBrush (QBrush (self.color)) painter.drawEllipse (0, 0, 12, 12) painter.end () self.setIcon (QIcon (pixmap)) def setupMimeData (self, data) : data.setColorData (self.color) def setupPixmap (self, drag) : pixmap = QPixmap (12, 12) pixmap.fill (Qt.transparent) painter = QPainter (pixmap) painter.setPen (Qt.NoPen) painter.setBrush (QBrush (self.color)) painter.drawEllipse (0, 0, 12, 12) painter.end () drag.setPixmap (pixmap) drag.setHotSpot (QPoint (6, 6)) # -------------------------------------------------------------------------- class ComponentItem (PaletteItem): def __init__ (self, page, name, func, parent=None) : PaletteItem.__init__ (self, parent) self.name = name factories [self.name] = func page.addItem (self.name, self) def setupMimeData (self, data) : data.setData ("application/x-qview-component", QByteArray (self.name)) # -------------------------------------------------------------------------- def ellipse () : item = QGraphicsEllipseItem () item.setRect (0, 0, 100, 50) item.setPen (QColor (Qt.blue)) item.setBrush (QBrush (Qt.yellow)) item.setFlag (QGraphicsItem.ItemIsMovable) item.setFlag (QGraphicsItem.ItemIsSelectable) return item def triangle () : item = QGraphicsPolygonItem () polygon = QPolygonF () polygon.append (QPointF (25, 0)) polygon.append (QPointF (0, 50)) polygon.append (QPointF (50, 50)) item.setPolygon (polygon) item.setPen (QColor (Qt.red)) item.setBrush (QBrush (Qt.green)) item.setFlag (QGraphicsItem.ItemIsMovable) item.setFlag (QGraphicsItem.ItemIsSelectable) return item def wave () : item = QGraphicsPathItem () path = QPainterPath () path.cubicTo (QPointF (50, 0), QPointF (0, 50), QPointF (50, 50)); item.setPath (path) item.setPen (QColor ("brown")) brush = QLinearGradient (QPointF (0, 0), QPointF (50, 50)) brush.setColorAt (0, QColor ("yellow")) brush.setColorAt (1, QColor ("orange")) item.setBrush (brush) item.setFlag (QGraphicsItem.ItemIsMovable) item.setFlag (QGraphicsItem.ItemIsSelectable) return item def createArea () : item = Area () item.setPen (QColor (Qt.green)) item.setBrush (QColor (Qt.yellow)) item.setTitle ("Cecko") item.setToolTip ("Cecko") return item def createSubArea () : item = Area () item.setTitle ("orange"); item.setPen (QColor (Qt.red)) item.setBrush (QColor ("orange")) item.setToolTip ("Subitem") item.setRect (10, 10, 80, 20) return item def createSource () : return Source () def createTarget () : return Target () def createButton () : return QPushButton () def createEdit () : return QLineEdit () def createTree () : widget = QTreeWidget () branch = QTreeWidgetItem () branch.setText (0, "abc") widget.addTopLevelItem (branch) node = QTreeWidgetItem () node.setText (0, "def") branch.addChild (node) return widget def createList () : return QListWidget () def initPalette (self) : page = PalettePage () colors = [ "red", "blue", "green", "yellow", "orange", "silver", "gold", "goldenrod", "lime", "lime green", "yellow green", "green yellow", "forest green", "coral", "cornflower blue", "dodger blue", "royal blue", "wheat", "chocolate", "peru", "sienna", "brown" ] for color_name in colors : item = ColorItem () item.setColor (QColor (color_name)) page.addItem (color_name, item) self.addPage ("Colors", page) page = PalettePage () ComponentItem (page, "ellipse", ellipse) ComponentItem (page, "triangle", triangle) ComponentItem (page, "wave", wave) self.addPage ("Shapes", page) page = PalettePage () ComponentItem (page, "area", createArea) ComponentItem (page, "sub-area", createSubArea) ComponentItem (page, "source", createSource) ComponentItem (page, "target", createTarget) ComponentItem (page, "button", createButton) ComponentItem (page, "edit", createEdit) ComponentItem (page, "tree", createTree) ComponentItem (page, "list", createList) self.addPage ("Components", page) # -------------------------------------------------------------------------- class GraphicsWin (QGraphicsView): def __init__ (self, parent=None) : QGraphicsView.__init__ (self, parent) scene = QGraphicsScene () scene.setSceneRect (0, 0, 800, 600) self.setScene (scene) # background n = 16 texture = QBitmap (n, n) texture.clear () painter = QPainter (texture) painter.drawLine (0, 0, n-1, 0) painter.drawLine (0, 0, 0, n-1) brush = QBrush (QColor ("cornflowerblue")) brush.setTexture (texture) scene.setBackgroundBrush (brush) # plane plane = Area () plane.topLevel = True plane.setPen (QPen (Qt.NoPen)) plane.setBrush (QBrush (Qt.NoBrush)) # plane.setFlags (0) plane.setRect (10, 10, 630, 470) scene.addItem (plane) # connect # self.connect (scene, SIGNAL ("selectionChanged()"), SLOT ("onSelectionChanged()")) # example a = Area () a.setPen (QPen (Qt.green)) a.setBrush (QBrush (Qt.yellow)) a.setPos (10, 10) a.setTitle ("Acko") a.setToolTip ("A") scene.addItem (a) a_source = Source () a_source.setPos (90, 0) a.addSource (a_source) a_target = Target () a.addTarget (a_target) b = Area () b.setPen (Qt.red) b.setBrush (QColor ("cornflowerblue")) b.setPos (320, 10) b.setTitle ("Becko") b.setToolTip ("B") scene.addItem (b) b_target = Target () b.addTarget (b_target) b_source = Source () b_source.setPos (90, 0) b.addSource (b_source) c = Connection () c.setSource (a_source) c.setTarget (b_target) c.updateConnection () s = Area () s.setTitle ("orange") s.setPen (QPen (Qt.red)) s.setBrush (QColor ("orange")) s.setToolTip ("Subitem") s.setRect (10, 10, 80, 20) a.addArea (s) t = Area () t.setTitle ("orange 2") t.setPen (QPen (Qt.red)) t.setBrush (QColor ("orange")) t.setToolTip ("Subitem 2") t.setRect (10, 10, 80, 20) b.addArea (t) # exampe 2 d = Area () d.setPen (QColor ("lime")) d.setBrush (Qt.yellow) d.setPos (10, 200) d.setRect (0, 0, 140, 200) scene.addItem (d) for i in range (3) : e = Area () e.setPen (Qt.red) e.setBrush (QColor ("orange")) e.setPos (10, 10 + 30*i) e.setRect (0, 0, 120, 20) d.addArea (e) f = QGraphicsSimpleTextItem () f.setText ("column" + str (i+1) + ": type" + str (i+1)) # f.setPen (QColor ("blue")) # f.setBrush (QBrush (Qt.yellow)) f.setPos (10, 5) f.setParentItem (e) # example 3 pixmap = QPixmap (12, 12) pixmap.fill (Qt.transparent) painter = QPainter (pixmap) painter.setPen (Qt.NoPen) painter.setBrush (QBrush (QColor ("orange"))) painter.drawEllipse (0, 0, 12, 12) painter.end () icon = QIcon (pixmap) tree = QTreeWidget () branch = QTreeWidgetItem () branch.setText (0, "abc") branch.setIcon (0, icon) node = QTreeWidgetItem () node.setText (0, "def") branch.addChild (node) tree.addTopLevelItem (branch) treeWidget = scene.addWidget (tree) pushButton = scene.addWidget (QPushButton ()) layout = QGraphicsLinearLayout () layout.setOrientation (Qt.Vertical) layout.addItem (treeWidget) layout.addItem(pushButton) form = QGraphicsWidget () form.setLayout (layout) form.setWindowFlags (Qt.Dialog) form.setWindowTitle ("Window") form.setPos (320, 200) scene.addItem (form) # -------------------------------------------------------------------------- class GraphicsWithPalette (QWidget) : def __init__ (self, parent=None) : QWidget.__init__ (self, parent) layout = QVBoxLayout () self.setLayout (layout) palette = Palette () layout.addWidget (palette) design = GraphicsWin () layout.addWidget (design) # -------------------------------------------------------------------------- if __name__ == '__main__' : app = QApplication (sys.argv) win = GraphicsWithPalette () win.show () app.exec_ () # -------------------------------------------------------------------------- # kate: indent-width 1; show-tabs true; replace-tabs true; remove-trailing-spaces all