comparison python/apps/diagrameditor.py @ 91:7ad4c66dd092

Fixed save function
author windel
date Mon, 10 Dec 2012 18:55:40 +0100
parents 4b1892054744
children 0c4bdbf0aead
comparison
equal deleted inserted replaced
90:499183b99c71 91:7ad4c66dd092
3 from PyQt4.QtGui import * 3 from PyQt4.QtGui import *
4 from PyQt4.QtCore import * 4 from PyQt4.QtCore import *
5 import sys, json, base64 5 import sys, json, base64
6 6
7 from diagramitems import Connection, ResizeSelectionHandle, Block, DiagramScene 7 from diagramitems import Connection, ResizeSelectionHandle, Block, DiagramScene
8 from icons import newicon, saveicon, loadicon
8 9
9 """ 10 """
10 Author: Windel Bouwman 11 Author: Windel Bouwman
11 Year: 2012 12 Year: 2012
12 Description: This script implements a diagram editor. 13 Description: This script implements a diagram editor.
13 run with python 3.x as: 14 run with python 3.x as:
14 $ python [thisfile.py] 15 $ python [thisfile.py]
15 """ 16 """
16 saveicon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAGGklEQVR42s2XeWxURRjAv7d3L9ay\nlJBCbAx/SIIpCWilhNLSFsrR0qUgyCmnnKVFa/xDjNbUKGIUSrlaLhEREWlZaQoC24VymBivoGJB\n/MuEtEpjoNt2z/H7Zt+8fdPdGk2MOu23MzvvzXy/+Y6ZWQX+46L8bwC2vLTlZte9e6MMRiMYjQYY\nPWYsZGXngM1iBkUxoERej1RYayJmYGrF1Dbj/31+P1xtuwQ3vvmaP6M/h8Nx69Xq6kclgDWrn2W3\nbt+G5KQkSE9Ph/E5eTB1xixIQID+yIraEMoVJYLGay4KGNS2ty8Aza4muHqpVZvClmCDHbW1igSw\neuUq1tPTA2EWRohkmJCbD9OLS+Fu14M4ZlP6M8lwSvSdEUNTwNXYCFc87iiAzQY7d9XJACuXr2Dd\n3d1gNpvBarXCxMmFUDzLCUk2S3zfKTrlqmIlYgqtTfWDXh80NZ6CNvdFnQUSYNfuXTLAimXLmV5B\nTn4hlDrLICUxHoAC+tHSTNz1jIcCw48HvX60AAK0RgGsaIE9e/fIAMuWPiMB5BZMAWfZHBiUaI1r\nAaZ+Mi32VKVqX5h/ZzwGzpxuRAtckFywt36fDLB08RIZoHAqlDhnQ0eXdwDlosFAP1APRGVoahK0\nYBBedp+XLNCwv0EGWLxwUT+AIphZ6ozNghhlEQCtrZqeqRC+QAjOftqEFogCkAX2HzwgAyxasFAC\nmFQwFaaVEIAJ5P2K6T5ln2uu0LnEHwzBZ2ea4Epr1AUU5AcPH5IBFsx/Wg5CBCgqdoLVbBxg5Xov\nDGyFQCgMF5tPI8B5CeDwkfdkgPlPzYsBmDLTCffu98b3f78OzS4s+g7Vg5Ot4G5xwdV+AEeOvi8D\nzJszV5p7IgLkT3equ9zAAPo4EMpFAIpnnrMuuKYDsCDA0WMfyABzy+bIAPlTIG9aKfzZecV0y5dc\nIdosMvzyORdc90RjwGKxwLHjH8oAZc7ZEoBj6DAYOeoxPJiMYKIDymTkbYPBoB5CkRpABByDcDjM\nJUQSDEIwFIIwyk83b0DXrx0SwPETH8kAs2eVxrhXKsrfPLnZwNOZEeDEyY9lgNLiEvYXpv1HCgGc\nPPWJDFAys/jfA8AD71RTowxQPH3GgAAK+t2IQv7X4oC+q5cSKiIORCyEyP9qLfr1AI2u0zLAjKJp\ncQHWblgPGRkZ0Q7G4uwFch8d6xXlm3jw0qEUCARgOF5yRDGZTOBqPiMDFBUUxsxLh8aa9evAbrfz\nVYuVRvVG2uKZ6COrvFj1Ao92fiL2eME+yK4pM6EFms+2yAAFeZNjAawWWF9eDqmpqVBT/ZqWZn1+\nH7y5dat2LxRmp1qY/pUtL/NgY9ju6e3lVz29Bc5dOC8D5OVMigNghfLKCg7wXOVm3kd53e31Qv3+\nBq6clAUx5/v7/I2a17mvOXBfHyTgLUgDQNdc8LTKADnZE2IAiHRz1fPgGDIEKjeW8z7aZPwBP9TW\n1WlK9QAC4p1tb2sAPp8PbLgYunFb8HgPBILgabssA0zIejIGgHy4uaoKARywacPGCABO7sOr9rs7\ntsdEOwnBkNRu34EAJnQBAz++TwB8V0WoIAZl2/VrMkDWuMdjAJISE2EjuoCCsBKjOuJrVISTbt32\nlqZMrJyiXQDt2VnHldGYYDCA7rSBGS0awvEmowmufH5dBhibOeYu+nSYHiABAdZhGg4igIoKbkqa\nnLKjpqZGWrneErTihn31XGEEIAgJOIZixqim5hdffRkFSElOUfDX0LgR6cNbMECGaBbAyF21dg2v\n+UBdkFGu6wH0z0jhgfp6vlIeuPiMrmGiUNr+0P5jcp/P5xUWoDoN/bT8kYczqjH4rCILFi5ZAvaH\n7JKPRZtMLtJPCE1Oz44cOsSh1X0KrBaLHiD47fffjcTmL/ojLhFlNCovtJjNDmRi2dnjk57IyhqM\nsWBBf1pxQjMJzmgke6rKmULJwVgQm36E8nd2dNxv9Xh+//nOHR9Ivxj4WjGRQu24+mb88psegNqE\nSQlrJH9lZmYacnNzjWlpaQpmBBdKLXXHU9QNiIkdEa0T9nq94c7OzpDb7Q63t7crTD6WFRXEj0J3\nveAfetNmUUsM6bsAAAAASUVORK5CYII=\n'
17
18 loadicon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACsElEQVR42u2Xf0hTURTHv++ZczlD\n6SeUREVRiRT9gFWM1rbAwr+iYAathPqjMosIQQqJQAhLLDI0CMwflRa1vyQst0oNLKxhCGWR9UfB\nwFCRaqC2vc6d7+1tr/7YnuwW5IEv95y79875vHvP7t4E/GUTpgGmAaL8vaRzpDlx3iuRXpEOkz5N\nFWDhrHR8bL+LtGXLKUqRJcoKyeUk1Q8Fges3gLIKeGlm+1QBHA4rPJ7WxG4eHqLlWoJRcvfJaPHY\nV1LPbwB5Dnja7if+BFUVQEdX7OqETdL48vD+C/DODze5e9iUCmAjgDt6FzJ+m/gG5GyD9OEz1lPY\nqwLQFrQ1JR+Amc0JPO0O941XBbAQQB0nABcBvNACbCGAWk4ABwngpRbATACXEksU7rsJGlnzUSZB\nkEdAbW9lXgnJtx0jAJ8WYCMBnE8MIESFx7+rRQRRLiaPESANmL2EAF6jgaLSCIA9Bx53sZokJpEY\nm4zFzP85BgTn0mUZUL9y7CPpz8CCvAJdA0DrE6D6NnxsLp9UaV2KVfW7Jy8QWcGUyUJhP0piFJA0\nmw6iAn19EAgAmdkICpRw5EEdsjabgXQDYo9gRZENVxVeIJO8Gjqs7y2wxoJ+IXUGxkcHkDrTqC+R\nXrt5D3AVoYU9yJs+L1bnruQLUFJO+34NpxlAc2MVCly7+ALkHQAedSKfAZwq3o/KK2X8ikvUT4ss\nkPyDWMwAtm5ai47uZn4Ag8PAAgvoxxzzGUCGMQ1DI89gMBr4ADymtwHHIXSSa1UOIt/zBqwz5/IB\nqG4Bjl9EDblFCkDN5ZM4csLJB+DoBaDWDTp3cVUBcDntaLx1hg/AzlKgvQc7yH2oAGSbjOg/WwjT\nvMzkFvdT65U34UdgDCtYGP1avoFUSMpK8gKw7q8n9bLgn/pj8n8C/ALihrxpNKi7hQAAAABJRU5E\nrkJggg==\n'
19
20 newicon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADSUlEQVR42r2XO0xaURjHLzYmdXRi\nYXBwdDScJl3djQNLw0TSAR88FR9JU6P4QKMCaTqQdGgXsQQMQXFwcGXhCCG+4iNEo6mDMZL45kK/\n76THUO+9Qi/efskJcm4O3+/+v8f51Al/LBaLmTs6Or43gAkq7eHhoXh2dmZva2v7WusZHf9jZGTE\nPz4+blfjuFwuC6IoCsViUbi8vCwDhM1oNH75V4AAANjUAJRKJeYc183NjXB1dVU+Pj7+CIp+qxlg\neHg44PV6VQHg2z8+PjKAu7s7oampSQAVxL29PUtnZ+eP/waA6/r6WtDr9UyJ09NTcXd319LV1aUI\n8QQwNDQUmJiYqBsA5BcMBgPLC4Q4OTkRt7e3LSaTSRbiCWBwcDAwOTmpOgfQOVSBcHFxIbS0tLB9\nDgH5IGYyGYvZbJZAvAoAOsL4IwTEngGxH9fp2MJnhUJBTKfT5t7e3rAsgMfjYQB4oB4V+OJAuI+A\naGtra6nz8/P3o6OjJQnAwMBAYGpqSjUAh8Aw8JLE3OBqIMTGxgbNZrPE5/MVFQFUe6+A4M5xoWMe\nIg4ASksB+vv761aAG3eKMFwBBFhfX6ebm5sEyl0eAHOgjqvgRSBUA3KAghHouFIAt9vNFNACgIci\nmUxSKEcyNjYmBXC5XK8Wgudvz8OAAJgDigD1lGE155UAsiFwOp2vUgVKzisBZJMQAdR2wlqco62s\nrNBcLkfgzpECOByOuhXg5cc733NLJBIMQLYP2O12BqB0uJrjyk8li8fjdGtri4AfeQAMAUpXayJW\ne2MlANlWbLPZGAB2LPagCoQapZaXl+nOzg6ZmZmRB8CBhANoYTB5U5iQyOzsrDwAjmR4hWpl0WiU\nwpxI5ubmpAAwKLAQ4HWqlUUiEbq/v0/m5+flATAEWiqwtLREDw4OyMLCgjyA1iEIh8P08PCQ+P1+\nKUBPTw8D0DIEi4uL9OjoiASDQSlAd3c3A7i/v9cUAKsgFApJAaxWa2B6etp2e3v71yGlen++X60v\n4EwAAOlUKvUO+oEUoLW19UNfX9/nxsbGhsoOxy+Wl75X2+drdXX1J/zX9AkmI+lU3N7e/hYSxAAT\n0Rs+FdX69rXsA1y5ubn5Vz6fL1Q++w30VO4/0/9IewAAAABJRU5ErkJggg==\n'
21
22 def uniqify(name, names):
23 newname, i = name, 1
24 while newname in names: newname, i = name + str(i), i + 1
25 return newname
26
27 def indent(lines): 17 def indent(lines):
28 return [' ' + line for line in lines] 18 return [' ' + line for line in lines]
29 19
30 class ParameterDialog(QDialog): 20 class ParameterDialog(QDialog):
31 def __init__(self, block, parent = None): 21 def __init__(self, block, parent = None):
53 self._model = None 43 self._model = None
54 self.treeView = QTreeView() 44 self.treeView = QTreeView()
55 def setDiagram(self, d): 45 def setDiagram(self, d):
56 self.setScene(d) 46 self.setScene(d)
57 self.delShort.activated.connect(d.deleteItems) 47 self.delShort.activated.connect(d.deleteItems)
58 def getModel(self): return self._model 48 def getModel(self):
49 return self._model
59 def setModel(self, m): 50 def setModel(self, m):
60 self._model = m 51 self._model = m
61 if m: 52 if m:
62 self.treeView.setModel(m) 53 self.treeView.setModel(m)
63 self.diagram = m.rootDiagram 54 self.diagram = m.rootDiagram
120 if event.mimeData().hasFormat('component/name'): event.accept() 111 if event.mimeData().hasFormat('component/name'): event.accept()
121 def dropEvent(self, event): 112 def dropEvent(self, event):
122 if event.mimeData().hasFormat('component/name'): 113 if event.mimeData().hasFormat('component/name'):
123 name = bytes(event.mimeData().data('component/name')).decode() 114 name = bytes(event.mimeData().data('component/name')).decode()
124 pos = self.mapToScene(event.pos()) 115 pos = self.mapToScene(event.pos())
125 self.scene().addNewBlock(pos, name) 116 s = self.scene()
117 b = Block(s.uniqify(name))
118 b.setPos(pos)
119 s.addItem(b)
126 # TODO: do this in a cleaner way: 120 # TODO: do this in a cleaner way:
127 self.model.modelReset.emit() 121 self.model.modelReset.emit()
128 122
129 class LibraryModel(QStandardItemModel): 123 class LibraryModel(QStandardItemModel):
130 mimeTypes = lambda self: ['component/name'] 124 mimeTypes = lambda self: ['component/name']
142 self.rootDiagram = DiagramScene() 136 self.rootDiagram = DiagramScene()
143 self.filename = None 137 self.filename = None
144 def setDict(self, d): 138 def setDict(self, d):
145 self.rootDiagram.Dict = d 139 self.rootDiagram.Dict = d
146 self.modelReset.emit() 140 self.modelReset.emit()
147 Dict = property(lambda s: s.rootDiagram.Dict, setDict) 141 def getDict(self):
142 return self.rootDiagram.Dict
143 Dict = property(getDict, setDict)
148 def gencode(self): 144 def gencode(self):
149 c = ['def topLevel():'] 145 c = ['def topLevel():']
150 c += indent(self.rootDiagram.gencode()) 146 c += indent(self.rootDiagram.gencode())
151 c.append('print("Running model")') 147 c.append('print("Running model")')
152 c.append('topLevel()') 148 c.append('topLevel()')
178 return b.name 174 return b.name
179 def headerData(self, section, orientation, role): 175 def headerData(self, section, orientation, role):
180 if orientation == Qt.Horizontal and role == Qt.DisplayRole: 176 if orientation == Qt.Horizontal and role == Qt.DisplayRole:
181 return "Element" 177 return "Element"
182 def rowCount(self, parent): 178 def rowCount(self, parent):
183 if parent.column() > 0: return 0 179 if parent.column() > 0:
180 return 0
184 if parent.isValid(): 181 if parent.isValid():
185 parent = parent.internalPointer().subModel 182 block = parent.internalPointer()
183 if hasattr(block, 'subModel'):
184 return len(block.subModel.blocks)
185 else:
186 return 0
186 else: 187 else:
187 parent = self.rootDiagram 188 return len(self.rootDiagram.blocks)
188 return len(parent.blocks)
189 def columnCount(self, parent): 189 def columnCount(self, parent):
190 return 1 190 return 1
191
192 191
193 class LibraryWidget(QListView): 192 class LibraryWidget(QListView):
194 def __init__(self): 193 def __init__(self):
195 super(LibraryWidget, self).__init__(None) 194 super(LibraryWidget, self).__init__(None)
196 self.libraryModel = LibraryModel(self) 195 self.libraryModel = LibraryModel(self)