Commit 66da8062 authored by Michael Büsch's avatar Michael Büsch

gui: Add standard library dialog

Signed-off-by: Michael Büsch's avatarMichael Buesch <m@bues.ch>
parent c48b62eb
......@@ -26,13 +26,6 @@ from awlsim.gui.util import *
from awlsim.gui.cpuwidget import *
def _setFontParams(font):
font.setFamily("courier")
font.setPointSize(10)
font.setKerning(False)
font.setFixedPitch(True)
font.setStyleHint(QFont.TypeWriter, QFont.PreferBitmap)
class EditSubWidget(QWidget):
needRepaint = Signal(QPaintEvent)
wasScrolled = Signal(QWheelEvent)
......@@ -52,7 +45,7 @@ class EditSubWidget(QWidget):
def getPainter(self):
p = QPainter(self)
font = p.font()
_setFontParams(font)
setFixedFontParams(font)
p.setFont(font)
return p
......@@ -479,11 +472,11 @@ class EditWidget(QPlainTextEdit):
def __updateFonts(self):
fmt = self.currentCharFormat()
font = fmt.font()
_setFontParams(font)
setFixedFontParams(font)
fmt.setFont(font)
self.setCurrentCharFormat(fmt)
font = self.font()
_setFontParams(font)
setFixedFontParams(font)
self.setFont(font)
self.__charHeight = self.fontMetrics().height()
self.setTabStopWidth(self.fontMetrics().width("X") * 8)
......
......@@ -23,10 +23,12 @@ document-new-3.svg | gnome | GPLv2
document-open-5.svg | tango | PD
document-save-all.svg | oxygen | CC-BY-SA 3.0 or LGPL
edit-4.svg | nuvola | LGPL-2.1
emblem-package-2.svg | gnome | GPLv2
go-next-7.svg | oxygen | CC-BY-SA 3.0 or LGPL
inputs.png | network-server.svg and | CC-BY-SA 3.0 or LGPL
| go-next-7.svg |
lcd.png | awlsim | PD
stdlib-package.png | emblem-package-2.svg | GPLv2
media-playback-start-4.svg | gnome | GPLv2
media-playback-stop-4.svg | gnome | GPLv2
memory_bits.png | view-calendar-workweek-2.svg | CC-BY-SA 3.0 or LGPL
......
This diff is collapsed.
......@@ -38,6 +38,7 @@ from awlsim.gui.icons.glasses import *
from awlsim.gui.icons.open import *
from awlsim.gui.icons.save import *
from awlsim.gui.icons.new import *
from awlsim.gui.icons.stdlib import *
import base64
......@@ -57,6 +58,7 @@ __icons = {
"open" : icon_open,
"save" : icon_save,
"new" : icon_new,
"stdlib" : icon_stdlib,
}
def getIcon(iconName):
......
# AUTOMATICALLY GENERATED FILE
# DO NOT EDIT
# Generated from stdlib-package.png
icon_stdlib = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAA'\
b'BHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAA'\
b'CcxJREFUaIHtmmtsHcUVx39nZvfuvde+fsWOnacdnDgJEDUh'\
b'QYQ2IeTBI6S0pS00kJKqVP1UKqqqUqUKqaJfqlalQAFV6ifU'\
b'wieKhFTEIy0Jj1YttDwDpEnzTgiNE8d24vhx7+6cfti96+sk'\
b'foSYIKSOtPLMzu7M/3fmzJmZuxZV5bOczKct4ELT/wEmmh77'\
b'tmQ/iXYvGkBtfe1Hf/heTe+D3/LXTWa7Fw2gKiN1N3330ZoZ'\
b'LW3PPHxn9v4nbxM7Ge1eNIDANwSFKVx/58+CxStuvruzuuof'\
b'j9wu0y+03YsGoOrAOYpH3+KyJasyN2269wrJFXY8uNFbfyHt'\
b'ymStA49sljlhaNcG2fyXPc9eE/i6Y/OjPcvL9dvurddlmx9j'\
b'YP9LuKiIBDW4oImtT/12oKfrw98ePzjw459u0/B8+/U+ruD7'\
b'75BGT+xqm8ldZ62/tq554fSFy28xM+YtzeTrZ/D8rzcsGfGC'\
b'okShIAICUf9xXP8J1mzYmNu145273zPbbnxks3zx7t/rvk8E'\
b'4Hdfknx/wfu8MXa952VuLlQ3t3ZcsTZqW7QqW988R4wxuNIA'\
b'rjSANRbvLOcUnDoQEDEgBsIixd79tM1qykxt2bRg67NPvPvQ'\
b'puCue54YenJSAR7eKO22qfDGJe1L7bxFK/JTprebTDaHugh1'\
b'JcKTB1EFjAWxKIolyjxwu1Vig7OorYC6EBBETHIJghIN9ZFx'\
b'kbl+/S3Vf33phcce+qY3cM/j4TOTBmBy+Z9cu+GuQsuMNqOq'\
b'aPEEpZJBjA/ly3ogHhhDqRRR3zSTm275EVW5gKp8wL+f/iFo'\
b'hDE+zoWICFSAoBEMdrHsyuX5V1/e+n1gQgDjRqH77hOjql9r'\
b'bJlpomIfLhpCkQrhmfgy8V8xAS4KITxFf9c+hroPUOo5QHXT'\
b'XA7983GkeiY2NwUxNnUlEUnzgQlxUWnlfRNcuccFqN3JVXUN'\
b'06wVYr81PhgvsX4mBRGbQWwGbIBGSTAJByDqh7CflvmryVU3'\
b'snPLL+k+ug9baI3fGTESBtWImbNaXe2AXT0RgHFdyIj/9cuX'\
b'XJ1TjWIXkbJ4D2wiPgWJ77nSIBoVKR57l75ejzDwkaS9KbM/'\
b'R++hNzi26yWmdKyluroOFx0fMRKzZrfmDx8+eCvw3AUDWM/b'\
b'OHV6m1XVRKwXCzX+MIyXwXhViJ/DeDmK3R8iXp7ctGUUqrLU'\
b'VGdjSyepCTjZdZj/vv88JwuzaZh5KdYdRaWEiKEq6wvqvoLI'\
b'dxhnoRoT4DebZF6uqq4uE+RQDIhNrJxBvDzi5xE/R3/fKXr3'\
b'v07f0R1EvXtxJ/ehQQvhqQ8JowxhFFChP+5YI2pmr6Cncy8H'\
b'tm8laOxgal0BiboRHaKuvj7z4DeOLvkBvPmxARTv1ssXL/cV'\
b'A9ZH/BzF0KO3+wTdx9+nr+sAxa6d2KibyBmGqEIzDWSrllGo'\
b'ziZtnN2qIEnYBameQYl6+o4d5UhnQNOUOlqqIubOnZ890d31'\
b'VS4EwPczd0ydNsvv7DzG7kNdnOg+RXGgG1+KCBGqlhJ1lHQq'\
b'IhbrWWr9HLkgj2RymCCHl89jq7JxlEFiJFU8v4R1A9hSP6bo'\
b'Uwp8+k/1smN/D2buNJqbCtYz/m3AvR8boFQaWpDzwSv1sLg1'\
b'g86ZivFmY71sHIG8LMbPY7wgzntZjJfD+AHGZjF+gPWyiPXj'\
b'RU8jNBzEhUN44SDZ0gANpQFcqZ9o6DRR8TSu2A9aJMhVUyr9'\
b'sX0sfeMCqKpVF2KNolpEI8W4AdyQggiCEIkQIYixaBIKEYNi'\
b'UqtrYvi4TQfq4rnpIlRDNIpAQzQqoRqCwmBxCqo6bpgfNwop'\
b'oE5Rdag6oqTzVAgai1HSUBkLTnw9UR4/M/yecwpEOOdQF+Ki'\
b'CFxI5EJUhaDGjSdtYgAgqXiSvymAO6NckU/LrrJ8Rl257M6o'\
b'K4fqSQEQgxJVCDpT8DkA3Bh1ZZHuHLBJWdB41Z8MAFVBnVZY'\
b'+2xrxv7sRpbPBXAW/DkM4RwikwiAmDPEli2oYwOV826MurPg'\
b'h5+TyQOwKC4Ogefhz1u2vQrA2muu4sVXXgNg9ReuGH7XOV5+'\
b'bTsAK5ctGAGk6dQfP42PKSa2tnNnCI7S8nNbXozr02ci1q26'\
b'GojD5poVy+K8i33/nR17UHWsvHJh+syIueEcwzFt7DSxSTye'\
b'P0MCNNL3gdQ9ykJRx6KO1mHBCVjlyMbtT+x8P0GAWOiu/+xm'\
b'3779hGEJgBvWreaFv2wDYMvWV1m6+DKKxRIf7NzDtObGVHQl'\
b'wCuvvQfAiqXz0/t7DnXSeaKPubMaaKjJxguciyYEMK4LCSaN'\
b'Dnv37GX+vHZuvG4NN6y7FtWI69esBGDdqqupqymwe99BLl/Y'\
b'TmNDzVkAOMfKZQvS+yT3G2pzdLQ2cuBIT+qKLixOCGD8ETDJ'\
b'JMaxaNFl7N69lwMHD9PRcQmN9bUjtpsiMDg4RF1tIY7lkESx'\
b'cr2JV2lAjKFcqK3OEzllKOyMj5rGAJO0Eov14+OeGqY1N9PS'\
b'PJWjncfYvv191l67AnWKNZbe0wO89fZ7ZIOA3t5+jGgqWowk'\
b'tvBSqxtjY38HTg2WcKGS9X2M58cQE5I/BoCIZB643YDxUECM'\
b'8OxzfwbA9zza2lpBBBVlxvQW/vXmu7TNnEGhpprtO3YxrbkJ'\
b'gG1/eyNtc9vf307zr7z+QZrv6j5N5/Fe5s2ZjjE+Yv0ROlR1'\
b'VH8aawRyAMb4GLE4MWxYf2McoZ1CsokzxnDpwvlcuqAjieGO'\
b'luYmcMrC+e2g4FAkjUwaGz6NaoqosqDd4cpl42GMVOo4PwAR'\
b'8YAAQKwXuwESb5dVUaOIAuLiI0oiDKfppBerqFpUFQ8X5ynv'\
b'SJXYxxVVSdwqBlEccfcpQCAinuq5fzcdbQQ8IAOARokfx1sK'\
b'THnrrPEkVBBc7GY2tm5cBxADSnl1La8NKURyJWVN6sRYrE0D'\
b'ZCbRc14ABrBxe1Hye6YgEp9lRcqhJxZWhhs+tzhQobwpKD9u'\
b'ymKTN2NXTIAqwpkxFjO8nbaMEe7HD6POpe4znMoRhjRcDls9'\
b'7lPKIkkGrgycjJAAasujM7JlEamcA2Om0QAcEAGq4ZCI52OE'\
b'1JplcZJYmbIbi2Kp4JBKqPKBvrITTc5skhpBVTFll42fjhhj'\
b'URgNIASKxguODPbsnxHUziS2oUujRjwhy1sETTuXCjdJ+1Xi'\
b'YRAXzxkRnHN4KaAOu1EykUv9p7A2+AgGiozi/6MCqGooIkNH'\
b'joe/+NPTT/1KNcqM1sAnlURs8Ug3PweGRotAMMYnJhHJADVA'\
b'HvCZ6P52cpICJaAfODnWQjbmNzIRyQJZPj2AQVUdHOvBcT/y'\
b'iYjlAr6lXUAKVXXcPfWkfaX8tNJn/p89/gf/IS6GlkdtNwAA'\
b'AABJRU5ErkJggg=='
# -*- coding: utf-8 -*-
#
# AWL simulator - GUI standard library window
#
# Copyright 2014 Michael Buesch <m@bues.ch>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
from __future__ import division, absolute_import, print_function, unicode_literals
from awlsim.common.compat import *
from awlsim.gui.util import *
from awlsim.gui.icons import *
from awlsim.core.systemblocks.system_sfc import *
from awlsim.core.systemblocks.system_sfb import *
class GenericActionWidget(QWidget):
# Signal: Code paste request.
paste = Signal(str)
# Signal: Finish the library selection
finish = Signal()
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setLayout(QGridLayout())
self.layout().setContentsMargins(QMargins(5, 0, 5, 0))
def _pasteCallGeneric(self, targetName, needDB, interfaceFields):
fields = []
for ftype in (BlockInterfaceField.FTYPE_IN,
BlockInterfaceField.FTYPE_OUT,
BlockInterfaceField.FTYPE_INOUT):
try:
fields.extend(interfaceFields[ftype])
except KeyError:
pass
ret = [ "\tCALL %s%s%s" %\
(targetName,
", DB ..." if needDB else "",
" (" if fields else "")
]
for field in fields:
ret.append("\t\t%s := ...\t, // %s" % (field.name, str(field.dataType)))
if fields:
ret.append("\t)")
ret.append("")
self.paste.emit("\n".join(ret))
def defaultPaste(self):
pass
class SysActionWidget(GenericActionWidget):
def __init__(self, parent=None):
GenericActionWidget.__init__(self, parent)
self.systemBlockCls = None
self.blockPrefix = None
self.desc = QLabel(self)
font = self.desc.font()
setFixedFontParams(font)
self.desc.setFont(font)
self.layout().addWidget(self.desc, 0, 0)
self.pasteCallButton = QPushButton(self)
self.layout().addWidget(self.pasteCallButton, 1, 0)
self.pasteCallSymButton = QPushButton(self)
self.layout().addWidget(self.pasteCallSymButton, 2, 0)
self.pasteCallButton.released.connect(self.__pasteCall)
self.pasteCallSymButton.released.connect(self.__pasteCallSym)
def update(self, prefix, systemBlockCls):
self.systemBlockCls = systemBlockCls
self.blockPrefix = prefix
blockNumber, blockName, blockDesc = systemBlockCls.name
desc = [ "%s %d \"%s\"" % (prefix, blockNumber, blockName) ]
for ftype, fname in ((BlockInterfaceField.FTYPE_IN, "VAR_INPUT"),
(BlockInterfaceField.FTYPE_OUT, "VAR_OUTPUT"),
(BlockInterfaceField.FTYPE_INOUT, "VAR_IN_OUT")):
try:
fields = systemBlockCls.interfaceFields[ftype]
except KeyError:
continue
if not fields:
continue
desc.append(" " + fname)
for field in fields:
field.fieldType = ftype
desc.append(" %s : %s;" % (field.name, str(field.dataType)))
self.desc.setText("\n".join(desc))
self.pasteCallButton.setText("Paste CALL %s %d" %\
(prefix, blockNumber))
self.pasteCallSymButton.setText("Paste CALL \"%s\"" % blockName)
def __pasteCall(self):
blockNumber, blockName, blockDesc = self.systemBlockCls.name
self._pasteCallGeneric("%s %d" % (self.blockPrefix, blockNumber),
self.systemBlockCls.isFB,
self.systemBlockCls.interfaceFields)
self.finish.emit()
def __pasteCallSym(self):
#TODO add the symbol to the symbol table
blockNumber, blockName, blockDesc = self.systemBlockCls.name
self._pasteCallGeneric('"%s"' % blockName,
self.systemBlockCls.isFB,
self.systemBlockCls.interfaceFields)
self.finish.emit()
def defaultPaste(self):
self.__pasteCall()
class LibraryDialog(QDialog):
ITEM_SFC = QListWidgetItem.UserType + 0
ITEM_SFB = QListWidgetItem.UserType + 1
BLOCK_OFFSET = QListWidgetItem.UserType + 0xFFFF
def __init__(self, withExtensions, parent=None):
QDialog.__init__(self, parent)
self.setLayout(QGridLayout())
self.setWindowTitle("AWL/STL - Standard library")
self.setWindowIcon(getIcon("stdlib"))
self.withExtensions = withExtensions
self.pasteText = None
self.currentActionWidget = None
self.libList = QListWidget(self)
QListWidgetItem("System functions (SFC)", self.libList, self.ITEM_SFC)
QListWidgetItem("System function blocks (SFB)", self.libList, self.ITEM_SFB)
self.layout().addWidget(self.libList, 0, 0, 2, 1)
self.libElemList = QListWidget(self)
font = self.libElemList.font()
setFixedFontParams(font)
self.libElemList.setFont(font)
self.layout().addWidget(self.libElemList, 0, 1, 2, 1)
self.iconLabel = QLabel(self)
self.iconLabel.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
self.iconLabel.setPixmap(getIcon("stdlib").pixmap(QSize(64, 64)))
self.layout().addWidget(self.iconLabel, 0, 2)
self.sysAction = SysActionWidget(self)
self.sysAction.hide()
self.layout().addWidget(self.sysAction, 1, 2)
self.libList.currentItemChanged.connect(self.__libItemChanged)
self.libElemList.currentItemChanged.connect(self.__libElemItemChanged)
self.libElemList.itemDoubleClicked.connect(self.__libElemDoubleClicked)
self.sysAction.paste.connect(self.__actionPaste)
self.sysAction.finish.connect(self.accept)
self.libList.setCurrentRow(0)
self.libList.setMinimumWidth(200)
self.libElemList.setMinimumWidth(380)
self.iconLabel.setMinimumWidth(220)
self.sysAction.setMinimumWidth(self.iconLabel.minimumWidth())
def __addSystemBlockTable(self, prefix, table):
biggestNum = ""
biggestName = ""
for blockCls in table.values():
if blockCls.broken:
continue
number, name, desc = blockCls.name
if number < 0 and not self.withExtensions:
continue
number = "%d" % number
if len(number) > len(biggestNum):
biggestNum = number
if len(name) > len(biggestName):
biggestName = name
for blockCls in sorted(table.values(), key=lambda c: c.name[0]):
if blockCls.broken:
continue
number, name, desc = blockCls.name
if number < 0 and not self.withExtensions:
continue
absName = "%s %d" % (prefix, number)
absName += " " * (len(prefix) + 1 + len(biggestNum) - len(absName))
symName = '"%s"' % name
symName += " " * (len(biggestName) - len(name))
if desc:
desc = " (%s)" % desc
else:
desc = ""
QListWidgetItem("%s %s%s" % (absName, symName, desc),
self.libElemList,
number + self.BLOCK_OFFSET)
def __libItemChanged(self, item, prevItem):
self.currentActionWidget = None
self.sysAction.hide()
self.libElemList.clear()
if item.type() == self.ITEM_SFC:
self.__addSystemBlockTable("SFC", SFC_table)
elif item.type() == self.ITEM_SFB:
self.__addSystemBlockTable("SFB", SFB_table)
else:
assert(0)
def __libElemItemChanged(self, item, prevItem):
if not item:
self.currentActionWidget = None
self.sysAction.hide()
return
libType = self.libList.currentItem().type()
if libType in (self.ITEM_SFC, self.ITEM_SFB):
blockNum = item.type() - self.BLOCK_OFFSET
self.sysAction.show()
self.currentActionWidget = self.sysAction
if libType == self.ITEM_SFC:
self.sysAction.update("SFC", SFC_table[blockNum])
else:
self.sysAction.update("SFB", SFB_table[blockNum])
else:
assert(0)
def __libElemDoubleClicked(self, item):
if self.currentActionWidget:
self.currentActionWidget.defaultPaste()
def __actionPaste(self, text):
self.pasteText = text
......@@ -225,6 +225,9 @@ class MainWidget(QWidget):
def insertFBcall(self):
self.projectWidget.insertFBcall()
def openLibrary(self):
self.projectWidget.openLibrary()
class MainWindow(QMainWindow):
@classmethod
def start(cls,
......@@ -252,16 +255,18 @@ class MainWindow(QMainWindow):
menu.addAction("&Exit...", self.close)
self.menuBar().addMenu(menu)
menu = QMenu("&Templates", self)
menu.addAction("Insert &OB...", self.insertOB)
menu.addAction("Insert F&C...", self.insertFC)
menu.addAction("Insert F&B...", self.insertFB)
menu.addAction("Insert &instance-DB...", self.insertInstanceDB)
menu.addAction("Insert &DB...", self.insertGlobalDB)
menu.addAction("Insert &UDT...", self.insertUDT)
menu = QMenu("&Library", self)
menu.addAction("Insert &OB template...", self.insertOB)
menu.addAction("Insert F&C template...", self.insertFC)
menu.addAction("Insert F&B template...", self.insertFB)
menu.addAction("Insert &instance-DB template...", self.insertInstanceDB)
menu.addAction("Insert &DB template...", self.insertGlobalDB)
menu.addAction("Insert &UDT template...", self.insertUDT)
menu.addSeparator()
menu.addAction("Insert FC C&ALL template...", self.insertFCcall)
menu.addAction("Insert FB CA&LL template...", self.insertFBcall)
menu.addSeparator()
menu.addAction("Insert FC C&ALL...", self.insertFCcall)
menu.addAction("Insert FB CA&LL...", self.insertFBcall)
menu.addAction(getIcon("stdlib"), "&Standard library...", self.openLibrary)
self.menuBar().addMenu(menu)
menu = QMenu("&PLC", self)
......@@ -269,7 +274,7 @@ class MainWindow(QMainWindow):
menu.addAction("&CPU config...", self.cpuConfig)
self.menuBar().addMenu(menu)
menu = QMenu("Help", self)
menu = QMenu("&Help", self)
menu.addAction(getIcon("cpu"), "&About...", self.about)
self.menuBar().addMenu(menu)
......@@ -277,6 +282,8 @@ class MainWindow(QMainWindow):
self.tb.addAction(getIcon("new"), "New project", self.new)
self.tb.addAction(getIcon("open"), "Open project", self.load)
self.tbSaveAct = self.tb.addAction(getIcon("save"), "Save project", self.save)
self.tb.addSeparator()
self.tb.addAction(getIcon("stdlib"), "Standard library", self.openLibrary)
self.addToolBar(self.tb)
self.__dirtyChanged(False)
......@@ -399,6 +406,9 @@ class MainWindow(QMainWindow):
def coreConfig(self):
self.centralWidget().coreConfig()
def openLibrary(self):
self.centralWidget().openLibrary()
# If invoked as script, run a new instance.
if __name__ == "__main__":
fn = sys.argv[1] if (len(sys.argv) >= 2) else None
......
......@@ -26,6 +26,7 @@ from awlsim.common.templates import *
from awlsim.gui.util import *
from awlsim.gui.sourcetabs import *
from awlsim.gui.library import *
class TemplateDialog(QDialog):
......@@ -270,3 +271,9 @@ class ProjectWidget(QTabWidget):
self.__pasteAwlText(Templates.getFBcall(dlg.getBlockNumber(),
dlg.getExtraNumber(),
dlg.getVerbose()))
def openLibrary(self):
dlg = LibraryDialog(self.__project.getExtInsnsEn(), self)
if dlg.exec_() == QDialog.Accepted:
if dlg.pasteText:
self.__pasteAwlText(dlg.pasteText)
......@@ -59,6 +59,14 @@ def intToDualString(value, bitWidth):
string.append('_')
return ''.join(string)
# Set the specified QFont to fixed-font
def setFixedFontParams(font, pointSize=10):
font.setFamily("courier")
font.setPointSize(pointSize)
font.setKerning(False)
font.setFixedPitch(True)
font.setStyleHint(QFont.TypeWriter, QFont.PreferBitmap)
def handleFatalException(parentWidget=None):
text = str(traceback.format_exc())
print("Fatal exception:\n", text)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment