1
0
mirror of https://github.com/naruxde/revpipycontrol.git synced 2025-11-08 15:43:52 +01:00
Files
revpipycontrol/revpipycontrol/revpioption.py
NaruX 3c05f9f024 Umbau f?r make_py Script
msg-Fenster hatte falschen parent
2018-04-07 14:34:49 +02:00

401 lines
14 KiB
Python

# -*- coding: utf-8 -*-
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
u"""Optionsfenster."""
import tkinter
import tkinter.messagebox as tkmsg
from aclmanager import AclManager
from mytools import gettrans
# Übersetzung laden
_ = gettrans()
class RevPiOption(tkinter.Frame):
u"""Zeigt Optionen von RevPiPyLoad an."""
def __init__(self, master, xmlcli):
u"""Init RevPiOption-Class.
@return None"""
try:
self.dc = xmlcli.get_config()
except:
self.dc = None
return None
super().__init__(master)
self.master.bind("<KeyPress-Escape>", self._checkclose)
self.master.protocol("WM_DELETE_WINDOW", self._checkclose)
self.pack(expand=True, fill="both")
# XML-RPC Server konfigurieren
self.xmlcli = xmlcli
self.xmlmodus = self.xmlcli.xmlmodus()
self.mrk_xmlmodask = False
self.dorestart = False
# Fenster bauen
self._createwidgets()
self._loadappdata()
def _changesdone(self):
u"""Prüft ob sich die Einstellungen geändert haben.
@return True, wenn min. eine Einstellung geändert wurde"""
return (
self.var_start.get() != self.dc.get("autostart", 1)
or self.var_reload.get() != self.dc.get("autoreload", 1)
or self.var_reload_delay.get() !=
str(self.dc.get("autoreloaddelay", 5))
or self.var_zexit.get() != self.dc.get("zeroonexit", 0)
or self.var_zerr.get() != self.dc.get("zeroonerror", 0)
# TODO: rtlevel (0)
or self.var_startpy.get() != self.dc.get("plcprogram", "none.py")
or self.var_startargs.get() != self.dc.get("plcarguments", "")
or self.var_pythonver.get() != self.dc.get("pythonversion", 3)
or self.var_slave.get() != self.dc.get("plcslave", 0)
or self.var_slaveacl.get() != self.dc.get("plcslaveacl", "")
or self.var_xmlon.get() != self.dc.get("xmlrpc", 0)
or self.var_xmlacl.get() != self.dc.get("xmlrpcacl", "")
)
def _checkclose(self, event=None):
u"""Prüft ob Fenster beendet werden soll.
@param event tkinter-Event"""
ask = True
if self._changesdone():
ask = tkmsg.askyesno(
_("Question"),
_("Do you really want to quit? \nUnsaved changes will "
"be lost"),
parent=self.master, default="no"
)
if ask:
self.master.destroy()
def _checkvalues(self):
u"""Prüft alle Werte auf Gültigkeit.
@return True, wenn alle Werte gültig sind"""
if not self.var_reload_delay.get().isdigit():
tkmsg.showerror(
_("Error"),
_("The value of 'restart delay' ist not valid."),
parent=self.master
)
return False
return True
def _createwidgets(self):
u"""Erstellt Widgets."""
self.master.wm_title(_("RevPi Python PLC Options"))
self.master.wm_resizable(width=False, height=False)
xmlstate = "normal" if self.xmlmodus >= 4 else "disabled"
cpade = {"padx": 4, "pady": 2, "sticky": "e"}
cpadw = {"padx": 4, "pady": 2, "sticky": "w"}
cpadwe = {"padx": 4, "pady": 2, "sticky": "we"}
# Gruppe Start/Stop
stst = tkinter.LabelFrame(self)
stst["text"] = _("Start / Stop behavior")
stst.grid(columnspan=2, pady=2, sticky="we")
self.var_start = tkinter.BooleanVar(stst)
self.var_reload = tkinter.BooleanVar(stst)
self.var_reload_delay = tkinter.StringVar(stst)
self.var_zexit = tkinter.BooleanVar(stst)
self.var_zerr = tkinter.BooleanVar(stst)
ckb_start = tkinter.Checkbutton(stst)
ckb_start["text"] = _("Start program automatically")
ckb_start["state"] = xmlstate
ckb_start["variable"] = self.var_start
ckb_start.grid(columnspan=2, **cpadw)
ckb_reload = tkinter.Checkbutton(stst)
ckb_reload["text"] = _("Restart program after exit")
ckb_reload["state"] = xmlstate
ckb_reload["variable"] = self.var_reload
ckb_reload.grid(columnspan=2, **cpadw)
lbl = tkinter.Label(stst)
lbl["text"] = _("Restart after n seconds of delay")
lbl.grid(**cpadw)
sbx = tkinter.Spinbox(stst)
sbx["to"] = 60
sbx["from_"] = 5
sbx["textvariable"] = self.var_reload_delay
sbx["width"] = 4
sbx.grid(column=1, row=2, **cpade)
lbl = tkinter.Label(stst)
lbl["text"] = _("Set process image to NULL if program terminates...")
lbl.grid(columnspan=2, **cpadw)
ckb_zexit = tkinter.Checkbutton(stst, justify="left")
ckb_zexit["state"] = xmlstate
ckb_zexit["text"] = _("... successfully")
ckb_zexit["variable"] = self.var_zexit
ckb_zexit.grid(**cpadw)
ckb_zerr = tkinter.Checkbutton(stst, justify="left")
ckb_zerr["state"] = xmlstate
ckb_zerr["text"] = _("... with errors")
ckb_zerr["variable"] = self.var_zerr
ckb_zerr.grid(**cpadw)
# Gruppe Programm
prog = tkinter.LabelFrame(self)
prog.columnconfigure(0, weight=1)
prog.columnconfigure(1, weight=1)
prog["text"] = _("PLC program")
prog.grid(columnspan=2, pady=2, sticky="we")
self.var_pythonver = tkinter.IntVar(prog)
self.var_startpy = tkinter.StringVar(prog)
self.var_startargs = tkinter.StringVar(prog)
self.var_slaveacl = tkinter.StringVar(prog)
self.var_pythonver.set(3)
lbl = tkinter.Label(prog)
lbl["text"] = _("Python version") + ":"
lbl.grid(columnspan=2, row=0, **cpadw)
rbn = tkinter.Radiobutton(prog)
rbn["state"] = xmlstate
rbn["text"] = "Python2"
rbn["value"] = 2
rbn["variable"] = self.var_pythonver
rbn.grid(column=0, row=1, **cpade)
rbn = tkinter.Radiobutton(prog)
rbn["state"] = xmlstate
rbn["text"] = "Python3"
rbn["value"] = 3
rbn["variable"] = self.var_pythonver
rbn.grid(column=1, row=1, **cpadw)
# Row 2
lbl = tkinter.Label(prog)
lbl["text"] = _("Python PLC program name")
lbl.grid(columnspan=2, **cpadw)
# Row 3
lst = self.xmlcli.get_filelist()
if len(lst) == 0:
lst.append("none")
opt_startpy = tkinter.OptionMenu(
prog, self.var_startpy, *lst
)
opt_startpy["state"] = xmlstate
opt_startpy.grid(columnspan=2, **cpadwe)
# Row 4
lbl = tkinter.Label(prog)
lbl["text"] = _("Program arguments")
lbl.grid(columnspan=2, **cpadw)
# Row 5
txt = tkinter.Entry(prog)
txt["textvariable"] = self.var_startargs
txt.grid(columnspan=2, **cpadw)
# Gruppe Services
services = tkinter.LabelFrame(self)
services["text"] = _("RevPiPyLoad server services")
services.grid(columnspan=2, pady=2, sticky="we")
self.var_slave = tkinter.BooleanVar(services)
self.var_xmlon = tkinter.BooleanVar(services)
self.var_xmlacl = tkinter.StringVar(services)
# RevPiSlave Service
row = 0
ckb_slave = tkinter.Checkbutton(services, justify="left")
ckb_slave["state"] = xmlstate
ckb_slave["text"] = _("Use RevPi as PLC-Slave")
ckb_slave["variable"] = self.var_slave
ckb_slave.grid(column=0, **cpadw)
btn_slaveacl = tkinter.Button(services, justify="center")
btn_slaveacl["command"] = self.btn_slaveacl
btn_slaveacl["text"] = _("Edit ACL")
btn_slaveacl.grid(column=1, row=row, **cpade)
row = 1
lbl = tkinter.Label(services)
lbl["text"] = _("RevPi-Slave service is:")
lbl.grid(column=0, **cpade)
status = self.xmlcli.plcslaverunning()
lbl = tkinter.Label(services)
lbl["fg"] = "green" if status else "red"
lbl["text"] = _("running") if status else _("stopped")
lbl.grid(column=1, row=row, **cpadwe)
# XML-RPC Service
row = 2
ckb_xmlon = tkinter.Checkbutton(services)
ckb_xmlon["command"] = self.askxmlon
ckb_xmlon["state"] = xmlstate
ckb_xmlon["text"] = _("Activate XML-RPC server on RevPi")
ckb_xmlon["variable"] = self.var_xmlon
ckb_xmlon.grid(**cpadw)
btn_slaveacl = tkinter.Button(services, justify="center")
btn_slaveacl["command"] = self.btn_xmlacl
btn_slaveacl["text"] = _("Edit ACL")
btn_slaveacl.grid(column=1, row=row, **cpade)
# Buttons am Ende
btn_save = tkinter.Button(self)
btn_save["command"] = self._setappdata
btn_save["state"] = xmlstate
btn_save["text"] = _("Save")
btn_save.grid(column=0, row=3)
btn_close = tkinter.Button(self)
btn_close["command"] = self._checkclose
btn_close["text"] = _("Close")
btn_close.grid(column=1, row=3)
def _loadappdata(self, refresh=False):
u"""Läd aktuelle Einstellungen vom RevPi.
@param refresh Wenn True, werden Einstellungen heruntergeladen."""
if refresh:
self.dc = self.xmlcli.get_config()
self.var_start.set(self.dc.get("autostart", 1))
self.var_reload.set(self.dc.get("autoreload", 1))
self.var_reload_delay.set(self.dc.get("autoreloaddelay", 5))
self.var_zexit.set(self.dc.get("zeroonexit", 0))
self.var_zerr.set(self.dc.get("zeroonerror", 0))
# TODO: rtlevel (0)
self.var_startpy.set(self.dc.get("plcprogram", "none.py"))
self.var_startargs.set(self.dc.get("plcarguments", ""))
self.var_pythonver.set(self.dc.get("pythonversion", 3))
self.var_slave.set(self.dc.get("plcslave", 0))
self.var_slaveacl.set(self.dc.get("plcslaveacl", ""))
self.var_xmlon.set(self.dc.get("xmlrpc", 0))
self.var_xmlacl.set(self.dc.get("xmlrpcacl", ""))
def _setappdata(self):
u"""Speichert geänderte Einstellungen auf RevPi.
@return None"""
if not self._changesdone():
tkmsg.showinfo(
_("Information"),
_("You have not made any changes to save."),
parent=self.master
)
self._checkclose()
return None
# Gültigkeitsprüfung
if not self._checkvalues():
return None
ask = tkmsg.askokcancel(
_("Question"),
_("The settings will be set on the Revolution Pi now. \n\n"
"If you made changes on the 'PCL Program' section, your plc "
"program will restart! \n"
"ACL changes and service settings are applied immediately."),
parent=self.master
)
if ask:
self.dc["autoreload"] = int(self.var_reload.get())
self.dc["autoreloaddelay"] = int(self.var_reload_delay.get())
self.dc["autostart"] = int(self.var_start.get())
self.dc["plcprogram"] = self.var_startpy.get()
self.dc["plcarguments"] = self.var_startargs.get()
self.dc["pythonversion"] = self.var_pythonver.get()
# TODO: rtlevel (0)
self.dc["zeroonerror"] = int(self.var_zerr.get())
self.dc["zeroonexit"] = int(self.var_zexit.get())
self.dc["plcslave"] = int(self.var_slave.get())
self.dc["plcslaveacl"] = self.var_slaveacl.get()
self.dc["xmlrpc"] = int(self.var_xmlon.get())
self.dc["xmlrpcacl"] = self.var_xmlacl.get()
if self.xmlcli.set_config(self.dc, ask):
tkmsg.showinfo(
_("Information"),
_("Settings saved"),
parent=self.master
)
self.dorestart = ask
self._checkclose()
else:
tkmsg.showerror(
_("Error"),
_("The settings could not be saved. This can happen if "
"values are wrong!"),
parent=self.master
)
def askxmlon(self):
u"""Fragt Nuter, ob wirklicht abgeschaltet werden soll."""
if not (self.var_xmlon.get() or self.mrk_xmlmodask):
self.mrk_xmlmodask = tkmsg.askyesno(
_("Question"),
_("Are you sure you want to deactivate the XML-RPC server? "
"You will NOT be able to access the Revolution Pi with "
"this program."),
parent=self.master
)
if not self.mrk_xmlmodask:
self.var_xmlon.set(True)
def btn_slaveacl(self):
u"""Öffnet Fenster für ACL-Verwaltung."""
win = tkinter.Toplevel(self)
win.focus_set()
win.grab_set()
slaveacl = AclManager(
win, 0, 1,
self.var_slaveacl.get(),
readonly=self.xmlmodus < 4
)
slaveacl.acltext = {
0: _("read only"),
1: _("read and write")
}
self.wait_window(win)
self.var_slaveacl.set(slaveacl.acl)
def btn_xmlacl(self):
u"""Öffnet Fenster für ACL-Verwaltung."""
win = tkinter.Toplevel(self)
win.focus_set()
win.grab_set()
slaveacl = AclManager(
win, 0, 4,
self.var_xmlacl.get(),
readonly=self.xmlmodus < 4
)
slaveacl.acltext = {
0: _("Start/Stop PLC program and read logs"),
1: _("+ read IOs in watch modus"),
2: _("+ read properties and download PLC program"),
3: _("+ upload PLC program"),
4: _("+ set properties")
}
self.wait_window(win)
self.var_xmlacl.set(slaveacl.acl)