diff --git a/revpipycontrol.e4p b/revpipycontrol.e4p index 2908aac..b5d5115 100644 --- a/revpipycontrol.e4p +++ b/revpipycontrol.e4p @@ -1,7 +1,7 @@ - + en_US @@ -21,6 +21,7 @@ revpipycontrol/revpilogfile.py revpipycontrol/revpioption.py revpipycontrol/revpiprogram.py + revpipycontrol/mytools.py diff --git a/revpipycontrol/mytools.py b/revpipycontrol/mytools.py new file mode 100644 index 0000000..858d53a --- /dev/null +++ b/revpipycontrol/mytools.py @@ -0,0 +1,46 @@ +# +# RevPiPyControl +# +# Webpage: https://revpimodio.org/revpipyplc/ +# (c) Sven Sager, License: LGPLv3 +# +# -*- coding: utf-8 -*- +import gettext +import locale +import sys +from os.path import dirname +from os.path import join as pathjoin + + +def addroot(filename): + u"""Hängt root-dir der Anwendung vor Dateinamen. + + Je nach Ausführungsart der Anwendung muss das root-dir über + andere Arten abgerufen werden. + + @param filename: Datei oder Ordnername + @returns: root dir + + """ + if getattr(sys, "frozen", False): + return pathjoin(dirname(sys.executable), filename) + else: + return pathjoin(dirname(__file__), filename) + + +def gettrans(proglang=None): + + # Sprache auswählen + if proglang is None: + # Autodetect Language or switch to static + # proglang = "de" + proglang = locale.getdefaultlocale()[0].split('_')[0] + + # Übersetzungen laden + trans = gettext.translation( + "revpipycontrol", + addroot("locale"), + languages=[proglang], + fallback=True + ) + return trans.gettext diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index 284ec88..c15c6ad 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -22,10 +22,7 @@ class RevPiCheckClient(tkinter.Frame): # XML-Daten abrufen self.xmlmode = xmlmode self.cli = xmlcli - - # FIXME: Fehlerabfang self.cli.psstart() - self.lst_devices = self.cli.ps_devices() self.dict_inps = pickle.loads(self.cli.ps_inps().data) self.dict_outs = pickle.loads(self.cli.ps_outs().data) @@ -62,12 +59,35 @@ class RevPiCheckClient(tkinter.Frame): def _createiogroup(self, device, frame, iotype): """Erstellt IO-Gruppen.""" - # IOs generieren - canvas = tkinter.Canvas(frame, borderwidth=0, width=180, heigh=800) + + # IO-Typen festlegen + if iotype == "inp": + lst_io = self.dict_inps[device] + else: + lst_io = self.dict_outs[device] + + # Fensterinhalt aufbauen + calc_heigh = len(lst_io) * 21 + canvas = tkinter.Canvas( + frame, + borderwidth=0, + width=180, + heigh=calc_heigh if calc_heigh <= 600 else 600 + ) s_frame = tkinter.Frame(canvas) vsb = tkinter.Scrollbar(frame, orient="vertical", command=canvas.yview) canvas.configure(yscrollcommand=vsb.set) + # Scrollrad Linux + canvas.bind( + "", + lambda x: canvas.yview_scroll(-1, "units") + ) + canvas.bind( + "", + lambda x: canvas.yview_scroll(1, "units") + ) + vsb.pack(side="right", fill="y") canvas.pack(side="left", fill="both", expand=True) @@ -76,13 +96,8 @@ class RevPiCheckClient(tkinter.Frame): "", lambda event, canvas=canvas: self._onfrmconf(canvas) ) + # IOs generieren rowcount = 0 - - if iotype == "inp": - lst_io = self.dict_inps[device] - else: - lst_io = self.dict_outs[device] - for io in lst_io: # io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] @@ -101,8 +116,10 @@ class RevPiCheckClient(tkinter.Frame): check.grid(column=1, row=rowcount) else: var = tkinter.IntVar() + # FIXME: Mehrere Bytes möglich txt = tkinter.Spinbox(s_frame, to=255 * io[1]) + txt["command"] = \ lambda device=device, io=io: self.__chval(device, io) txt["state"] = "disabled" if iotype == "inp" else "normal" @@ -129,6 +146,7 @@ class RevPiCheckClient(tkinter.Frame): "WM_DELETE_WINDOW", lambda win=win: self.__hidewin(win) ) + win.resizable(False, True) win.withdraw() self.lst_wins.append(win) diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index 55f41df..96d733e 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -13,6 +13,7 @@ import tkinter import tkinter.filedialog as tkfd import tkinter.messagebox as tkmsg import zipfile +from mytools import gettrans from os import environ from os import makedirs from shutil import rmtree @@ -20,6 +21,8 @@ from sys import platform from tempfile import mkstemp, mkdtemp from xmlrpc.client import Binary +# Übersetzung laden +_ = gettrans() # Systemwerte if platform == "linux": @@ -37,7 +40,8 @@ class RevPiProgram(tkinter.Frame): return None super().__init__(master) -# master.protocol("WM_DELETE_WINDOW", self._checkclose) + # FIXME: Warnung kann nerven + # self.master.protocol("WM_DELETE_WINDOW", self._checkclose) self.pack(expand=True, fill="both") self.uploaded = False @@ -55,15 +59,20 @@ class RevPiProgram(tkinter.Frame): self._evt_optdown() self._evt_optup() -# def _checkclose(self): -# if self.uploaded: -# tkmsg.showinfo("Ein PLC Programm wurde hochgeladen. " -# "Bitte die PLC options prüfen ob dort das neue Programm" -# "eingestellt werden muss.") -# self.master.destroy() + def _checkclose(self): + if True or self.uploaded: + tkmsg.showinfo( + parent=self.master, title=_("Information"), + message=_( + "A PLC program has been uploaded. Please check the " + "PLC options to see if the correct program is specified " + "as the start program." + ) + ) + self.master.destroy() def _createwidgets(self): - self.master.wm_title("RevPi Python PLC Programm") + self.master.wm_title(_("RevPi python PLC programm")) self.master.wm_resizable(width=False, height=False) self.rowconfigure(0, weight=1) @@ -77,7 +86,7 @@ class RevPiProgram(tkinter.Frame): # Gruppe Programm prog = tkinter.LabelFrame(self) prog.columnconfigure(0, weight=1) - prog["text"] = "PLC Python programm" + prog["text"] = _("PLC python programm") prog.grid(columnspan=2, pady=2, sticky="we") # Variablen vorbereiten @@ -87,16 +96,26 @@ class RevPiProgram(tkinter.Frame): self.var_typedown = tkinter.StringVar(prog) self.var_typeup = tkinter.StringVar(prog) - self.lst_typedown = ["Dateien", "Zip Archiv", "TGZ Archiv"] - self.lst_typeup = ["Dateien", "Ordner", "Zip Archiv", "TGZ Archiv"] + self.lst_typedown = [_("Files"), _("Zip archive"), _("TGZ archive")] + self.lst_typeup = [ + _("Files"), _("Folder"), _("Zip archive"), _("TGZ archive") + ] self.var_picdown.set(self.opt.get("picdown", False)) self.var_picup.set(self.opt.get("picup", False)) - self.var_typedown.set(self.opt.get("typedown", self.lst_typedown[0])) - self.var_typeup.set(self.opt.get("typeup", self.lst_typeup[0])) + + # Gespeicherte Werte übernehmen + saved_val = self.opt.get("typedown", self.lst_typedown[0]) + self.var_typedown.set( + saved_val if saved_val in self.lst_typedown else _("Files") + ) + saved_val = self.opt.get("typeup", self.lst_typeup[0]) + self.var_typeup.set( + saved_val if saved_val in self.lst_typeup else _("Files") + ) r = 0 lbl = tkinter.Label(prog) - lbl["text"] = "PLC Programm herunterladen als:" + lbl["text"] = _("Download PLC program as:") lbl.grid(column=0, row=r, **cpadw) opt = tkinter.OptionMenu( prog, self.var_typedown, *self.lst_typedown, @@ -106,17 +125,17 @@ class RevPiProgram(tkinter.Frame): r = 1 self.ckb_picdown = tkinter.Checkbutton(prog) - self.ckb_picdown["text"] = "inkl. piCtory Konfiguration" + self.ckb_picdown["text"] = _("include piCtory configuration") self.ckb_picdown["variable"] = self.var_picdown self.ckb_picdown.grid(column=0, row=r, **cpadw) btn = tkinter.Button(prog) btn["command"] = self.plcdownload - btn["text"] = "Download" + btn["text"] = _("Download") btn.grid(column=1, row=r, **cpad) r = 2 lbl = tkinter.Label(prog) - lbl["text"] = "PLC Programm hochladen als:" + lbl["text"] = _("Upload PLC program as:") lbl.grid(column=0, row=r, **cpadw) opt = tkinter.OptionMenu( prog, self.var_typeup, *self.lst_typeup, @@ -128,74 +147,74 @@ class RevPiProgram(tkinter.Frame): r = 3 ckb = tkinter.Checkbutton(prog) ckb["state"] = self.xmlstate - ckb["text"] = "vorher alles im Uploadverzeichnis löschen" + ckb["text"] = _("clean upload folder before upload") ckb["variable"] = self.var_cleanup ckb.grid(column=0, row=r, columnspan=2, **cpadw) r = 4 self.ckb_picup = tkinter.Checkbutton(prog) self.ckb_picup["state"] = self.xmlstate - self.ckb_picup["text"] = "enthält piCtory Konfiguration" + self.ckb_picup["text"] = _("includes piCtory configuration") self.ckb_picup["variable"] = self.var_picup self.ckb_picup.grid(column=0, row=r, **cpadw) btn = tkinter.Button(prog) btn["command"] = self.plcupload btn["state"] = self.xmlstate - btn["text"] = "Upload" + btn["text"] = _("Upload") btn.grid(column=1, row=r, **cpad) # Gruppe piCtory picto = tkinter.LabelFrame(self) picto.columnconfigure(0, weight=1) - picto["text"] = "piCtory Konfiguration" + picto["text"] = _("piCtory configuration") picto.grid(columnspan=2, pady=2, sticky="we") lbl = tkinter.Label(picto) - lbl["text"] = "piCtory Konfiguration herunterladen" + lbl["text"] = _("Download piCtory configuration") lbl.grid(column=0, row=0, **cpadw) btn = tkinter.Button(picto) btn["command"] = self.getpictoryrsc - btn["text"] = "Download" + btn["text"] = _("Download") btn.grid(column=1, row=0, **cpad) lbl = tkinter.Label(picto) - lbl["text"] = "piCtory Konfiguration hochladen" + lbl["text"] = _("Upload piCtory configuration") lbl.grid(column=0, row=1, **cpadw) btn = tkinter.Button(picto) btn["command"] = self.setpictoryrsc btn["state"] = self.xmlstate - btn["text"] = "Upload" + btn["text"] = _("Upload") btn.grid(column=1, row=1, **cpad) # Gruppe ProcImg proc = tkinter.LabelFrame(self) proc.columnconfigure(0, weight=1) - proc["text"] = "piControl0 Prozessabbild" + proc["text"] = _("piControl0 prozess image") proc.grid(columnspan=2, pady=2, sticky="we") lbl = tkinter.Label(proc) - lbl["text"] = "Prozessabbild-Dump herunterladen" + lbl["text"] = _("Download process image dump") lbl.grid(column=0, row=0, **cpadw) btn = tkinter.Button(proc) btn["command"] = self.getprocimg - btn["text"] = "Download" + btn["text"] = _("Download") btn.grid(column=1, row=0, **cpad) # Gruppe piControlReset picon = tkinter.LabelFrame(self) picon.columnconfigure(0, weight=1) - picon["text"] = "piControl Reset" + picon["text"] = _("Reset piControl") picon.grid(columnspan=2, pady=2, sticky="we") lbl = tkinter.Label(picon) - lbl["text"] = "piControlReset ausführen" + lbl["text"] = _("Execute piControlReset") lbl.grid(column=0, row=0, **cpadw) btn = tkinter.Button(picon) btn["command"] = self.picontrolreset - btn["text"] = "ausführen" + btn["text"] = _("execute") btn.grid(column=1, row=0, **cpad) # Beendenbutton btn = tkinter.Button(self) btn["command"] = self.master.destroy - btn["text"] = "Beenden" + btn["text"] = _("Exit") btn.grid() def _evt_optdown(self, text=""): @@ -275,25 +294,23 @@ class RevPiProgram(tkinter.Frame): fh = tkfd.asksaveasfile( mode="wb", parent=self.master, confirmoverwrite=True, - title="Speichern als...", + title=_("Save as..."), initialdir=self.opt.get("getpictoryrsc_dir", ""), initialfile=self.revpi + ".rsc", - filetypes=(("piCtory Config", "*.rsc"), ("All Files", "*.*")) + filetypes=((_("piCtory Config"), "*.rsc"), (_("All files"), "*.*")) ) if fh is not None: try: fh.write(self.xmlcli.get_pictoryrsc().data) except: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Datei konnte nicht geladen und gespeichert " - "werden!" + parent=self.master, title=_("Error"), + message=_("Could not load and save file!") ) else: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Datei erfolgreich vom Revolution Pi geladen " - "und gespeichert.", + parent=self.master, title=_("Success"), + message=_("File successfully loaded and saved.") ) # Einstellungen speichern self.opt["getpictoryrsc_dir"] = os.path.dirname(fh.name) @@ -306,25 +323,23 @@ class RevPiProgram(tkinter.Frame): fh = tkfd.asksaveasfile( mode="wb", parent=self.master, confirmoverwrite=True, - title="Speichern als...", + title=_("Save as..."), initialdir=self.opt.get("getprocimg_dir", ""), initialfile=self.revpi + ".img", - filetypes=(("Imagefiles", "*.img"), ("All Files", "*.*")) + filetypes=((_("Imagefiles"), "*.img"), (_("All files"), "*.*")) ) if fh is not None: try: fh.write(self.xmlcli.get_procimg().data) except: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Datei konnte nicht geladen und gespeichert" - "werden!" + parent=self.master, title=_("Error"), + message=_("Could not load and save file!") ) else: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Datei erfolgreich vom Revolution Pi geladen " - "und gespeichert.", + parent=self.master, title=_("Success"), + message=_("File successfully loaded and saved.") ) # Einstellungen speichern self.opt["getprocimg_dir"] = os.path.dirname(fh.name) @@ -337,19 +352,23 @@ class RevPiProgram(tkinter.Frame): if filename is None: fh = tkfd.askopenfile( mode="rb", parent=self.master, - title="piCtory Datei öffnen...", + title=_("Open piCtory file..."), initialdir=self.opt.get("setpictoryrsc_dir", ""), initialfile=self.revpi + ".rsc", - filetypes=(("piCtory Config", "*.rsc"), ("All Files", "*.*")) + filetypes=( + (_("piCtory config"), "*.rsc"), (_("All files"), "*.*") + ) ) else: fh = open(filename, "rb") if fh is not None: ask = tkmsg.askyesno( - parent=self.master, title="Frage", - message="Soll nach dem Hochladen der piCtory Konfiguration " - "ein Reset am piControl Treiber durchgeführt werden?" + parent=self.master, title=_("Question"), + message=_( + "Should the piControl driver be reset after " + "uploading the piCtory configuration?" + ) ) ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask) @@ -357,52 +376,66 @@ class RevPiProgram(tkinter.Frame): if ec == 0: if ask: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Die Übertragung der piCtory Konfiguration " - "und der Reset von piControl wurden erfolgreich " - "ausgeführt") + parent=self.master, title=_("Success"), + message=_( + "The transfer of the piCtory configuration " + "and the reset of piControl have been " + "successfully executed" + ) + ) else: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Die Übertragung der piCtory Konfiguration " - "wurde erfolgreich ausgeführt") + parent=self.master, title=_("Success"), + message=_( + "The piCtory configuration was " + "successfully transferred" + ) + ) # Einstellungen speichern self.opt["setpictoryrsc_dir"] = os.path.dirname(fh.name) self._savedefaults() elif ec < 0: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Die piCtory Konfiguration konnte auf dem " - "Revolution Pi nicht geschrieben werden.") + parent=self.master, title=_("Error"), + message=_( + "The piCtory configuration could not be " + "written on the Revolution Pi." + ) + ) elif ec > 0: tkmsg.showwarning( - parent=self.master, title="Warnung", - message="Die piCtroy Konfiguration wurde erfolgreich " - "gespeichert. \nBeim piControl Reset trat allerdings ein " - "Fehler auf!") + parent=self.master, title=_("Warning"), + message=_( + "The piCtroy configuration has been saved " + "successfully. \nAn error occurred on piControl reset!" + ) + ) fh.close() def picontrolreset(self): u"""Fürt ein Reset der piBridge durch.""" ask = tkmsg.askyesno( - parent=self.master, title="Frage...", - message="Soll piControlReset wirklich durchgeführt werden? \n" - "Das Prozessabbild und die Steuerung werden dann unterbrochen!!!" + parent=self.master, title=_("Question"), + message=_( + "Are you sure to reset piControl? \nThe process image " + "and the piBridge are interrupted !!!" + ) ) if ask: ec = self.xmlcli.resetpicontrol() if ec == 0: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="piControlReset erfolgreich durchgeführt" + parent=self.master, title=_("Success"), + message=_("piControlReset executed successfully") ) else: tkmsg.showerror( - parten=self.master, title="Fehler", - message="piControlReset konnte nicht erfolgreich " - "durchgeführt werden" + parten=self.master, title=_("Error"), + message=_( + "piControl reset could not be executed successfully" + ) ) def plcdownload(self): @@ -415,7 +448,7 @@ class RevPiProgram(tkinter.Frame): # Ordner dirselect = tkfd.askdirectory( parent=self.master, - title="Verzeichnis zum Ablegen", + title=_("Directory to save"), mustexist=False, initialdir=self.opt.get("plcdownload_dir", self.revpi) ) @@ -428,10 +461,12 @@ class RevPiProgram(tkinter.Frame): fh = tkfd.asksaveasfile( mode="wb", parent=self.master, confirmoverwrite=True, - title="Speichern als...", + title=_("Save as..."), initialdir=self.opt.get("plcdownload_file", ""), initialfile=self.revpi + ".zip", - filetypes=(("Zip Archiv", "*.zip"), ("All Files", "*.*")) + filetypes=( + (_("Zip archive"), "*.zip"), (_("All files"), "*.*") + ) ) elif tdown == 2: @@ -439,10 +474,12 @@ class RevPiProgram(tkinter.Frame): fh = tkfd.asksaveasfile( mode="wb", parent=self.master, confirmoverwrite=True, - title="Speichern als...", + title=_("Save as..."), initialdir=self.opt.get("plcdownload_file", ""), initialfile=self.revpi + ".tar.gz", - filetypes=(("Tar Archiv", "*.tar.gz"), ("All Files", "*.*")) + filetypes=( + (_("TGZ archive"), "*.tar.gz"), (_("All files"), "*.*") + ) ) if fh is not None: @@ -480,15 +517,13 @@ class RevPiProgram(tkinter.Frame): except: raise tkmsg.showerror( - parent=self.master, title="Fehler", - message="Datei konnte nicht geladen und gespeichert " - "werden!" + parent=self.master, title=_("Error"), + message=_("Could not load and save file!") ) else: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Datei erfolgreich vom Revolution Pi geladen " - "und gespeichert.", + parent=self.master, title=_("Success"), + message=_("File successfully loaded and saved.") ) # Einstellungen speichern @@ -509,9 +544,9 @@ class RevPiProgram(tkinter.Frame): # Datei fileselect = tkfd.askopenfilenames( parent=self.master, - title="Python Programm übertragen...", + title="Upload Python program...", initialdir=self.opt.get("plcupload_dir", ""), - filetypes=(("Python", "*.py"), ("All Files", "*.*")) + filetypes=(("Python", "*.py"), (_("All files"), "*.*")) ) if type(fileselect) == tuple and len(fileselect) > 0: for file in fileselect: @@ -521,7 +556,7 @@ class RevPiProgram(tkinter.Frame): # Ordner dirselect = tkfd.askdirectory( parent=self.master, - title="Verzeichnis zum Hochladen", + title=_("Folder to upload"), mustexist=True, initialdir=self.opt.get("plcupload_dir", self.revpi) ) @@ -532,10 +567,12 @@ class RevPiProgram(tkinter.Frame): # Zip fileselect = tkfd.askopenfilename( parent=self.master, - title="Zip-Archive übertragen...", + title=_("Upload Zip archive..."), initialdir=self.opt.get("plcupload_file", ""), initialfile=self.revpi + ".zip", - filetypes=(("Zip Archiv", "*.zip"), ("All Files", "*.*")) + filetypes=( + (_("Zip archive"), "*.zip"), (_("All files"), "*.*") + ) ) if type(fileselect) == str and fileselect != "": # Zipdatei prüfen @@ -550,18 +587,21 @@ class RevPiProgram(tkinter.Frame): else: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Die angegebene Datei ist kein ZIP-Archiv.") + parent=self.master, title=_("Error"), + message=_("The specified file is not a ZIP archive.") + ) return False elif tup == 3: # TarGz fileselect = tkfd.askopenfilename( parent=self.master, - title="TarGz-Archiv übertragen...", + title=_("Upload TarGz archiv..."), initialdir=self.opt.get("plcupload_file", ""), initialfile=self.revpi + ".tar.gz", - filetypes=(("Tar Archiv", "*.tar.gz"), ("All Files", "*.*")) + filetypes=( + (_("TGZ archive"), "*.tar.gz"), (_("All files"), "*.*") + ) ) if type(fileselect) == str and fileselect != "": @@ -577,8 +617,9 @@ class RevPiProgram(tkinter.Frame): else: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Die angegebene Datei ist kein TAR-Archiv.") + parent=self.master, title=_("Error"), + message=_("The specified file is not a TAR archive.") + ) return False # Wenn keine Dateien gewählt @@ -588,9 +629,12 @@ class RevPiProgram(tkinter.Frame): # Vor Übertragung aufräumen wenn ausgewählt if self.var_cleanup.get() and not self.xmlcli.plcuploadclean(): tkmsg.showerror( - parent=self.masger, title="Fehler", - message="Beim Löschen der Dateien auf dem Revolution Pi ist " - "ein Fehler aufgetreten.") + parent=self.masger, title=_("Error"), + message=_( + "There was an error deleting the files on the " + "Revolution Pi." + ) + ) return False # Flag setzen, weil ab hier Veränderungen existieren @@ -625,17 +669,21 @@ class RevPiProgram(tkinter.Frame): if ec == 0: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Die Übertragung war erfolgreich.") + parent=self.master, title=_("Success"), + message=_("The transfer was successful.") + ) if self.var_picup.get(): if rscfile is not None: self.setpictoryrsc(rscfile) else: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Es wurde im Archiv keine piCtory " - "Konfiguration gefunden") + parent=self.master, title=_("Error"), + message=_( + "There is no piCtory configuration in this " + "archive." + ) + ) # Einstellungen speichern if tup == 0: @@ -651,14 +699,18 @@ class RevPiProgram(tkinter.Frame): elif ec == -1: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Der Revoluton Pi konnte Teile der Übertragung nicht " - "verarbeiten.") + parent=self.master, title=_("Error"), + message=_( + "The Revolution Pi could not process some parts of the " + "transmission." + ) + ) elif ec == -2: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Bei der Übertragung traten Fehler auf") + parent=self.master, title=_("Error"), + message=_("Errors occurred during transmission") + ) # Temp-Dir aufräumen if dirtmp is not None: diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index de8cfb5..dd131cf 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -13,29 +13,15 @@ import revpioption import revpiplclist import revpiprogram import socket -import sys import tkinter import tkinter.messagebox as tkmsg from functools import partial -from os.path import dirname -from os.path import join as pathjoin +from mytools import addroot, gettrans from xmlrpc.client import ServerProxy -def addroot(filename): - u"""Hängt root-dir der Anwendung vor Dateinamen. - - Je nach Ausführungsart der Anwendung muss das root-dir über - andere Arten abgerufen werden. - - @param filename: Datei oder Ordnername - @returns: root dir - - """ - if getattr(sys, "frozen", False): - return pathjoin(dirname(sys.executable), filename) - else: - return pathjoin(dirname(__file__), filename) +# Übersetzung laden +_ = gettrans() class RevPiPyControl(tkinter.Frame): @@ -105,10 +91,10 @@ class RevPiPyControl(tkinter.Frame): self.master.config(menu=self.mbar) menu1 = tkinter.Menu(self.mbar, tearoff=False) - menu1.add_command(label="Connections...", command=self.plclist) + menu1.add_command(label=_("Connections..."), command=self.plclist) menu1.add_separator() - menu1.add_command(label="Exit", command=self.master.destroy) - self.mbar.add_cascade(label="Main", menu=menu1) + menu1.add_command(label=_("Exit"), command=self.master.destroy) + self.mbar.add_cascade(label=_("Main"), menu=menu1) self._fillmbar() self._fillconnbar() @@ -119,22 +105,22 @@ class RevPiPyControl(tkinter.Frame): self.txt_connect.pack(fill="x") self.btn_plcstart = tkinter.Button(self) - self.btn_plcstart["text"] = "PLC Start" + self.btn_plcstart["text"] = _("PLC start") self.btn_plcstart["command"] = self.plcstart self.btn_plcstart.pack(fill="x") self.btn_plcstop = tkinter.Button(self) - self.btn_plcstop["text"] = "PLC Stop" + self.btn_plcstop["text"] = _("PLC stop") self.btn_plcstop["command"] = self.plcstop self.btn_plcstop.pack(fill="x") self.btn_plcrestart = tkinter.Button(self) - self.btn_plcrestart["text"] = "PLC Restart" + self.btn_plcrestart["text"] = _("PLC restart") self.btn_plcrestart["command"] = self.plcrestart self.btn_plcrestart.pack(fill="x") self.btn_plclogs = tkinter.Button(self) - self.btn_plclogs["text"] = "PLC Logs" + self.btn_plclogs["text"] = _("PLC logs") self.btn_plclogs["command"] = self.plclogs self.btn_plclogs.pack(fill="x") @@ -145,7 +131,7 @@ class RevPiPyControl(tkinter.Frame): self.txt_status.pack(fill="x") self.btn_debug = tkinter.Button(self) - self.btn_debug["text"] = "PLC Debugmodus" + self.btn_debug["text"] = _("PLC watch mode") self.btn_debug["command"] = self.plcdebug self.btn_debug.pack(fill="x") @@ -162,20 +148,20 @@ class RevPiPyControl(tkinter.Frame): # PLC Menü self.mplc = tkinter.Menu(self.mbar, tearoff=False) self.mplc.add_command( - label="PLC log...", command=self.plclogs) + label=_("PLC log..."), command=self.plclogs) self.mplc.add_command( - label="PLC options...", command=self.plcoptions) + label=_("PLC options..."), command=self.plcoptions) self.mplc.add_command( - label="PLC program...", command=self.plcprogram) + label=_("PLC program..."), command=self.plcprogram) self.mplc.add_separator() self.mplc.add_command( - label="Disconnect", command=self.serverdisconnect) + label=_("Disconnect"), command=self.serverdisconnect) self.mbar.add_cascade(label="PLC", menu=self.mplc, state="disabled") # Connection Menü self.mconn = tkinter.Menu(self.mbar, tearoff=False) - self.mbar.add_cascade(label="Connect", menu=self.mconn) + self.mbar.add_cascade(label=_("Connect"), menu=self.mconn) def _opt_conn(self, text): socket.setdefaulttimeout(2) @@ -208,23 +194,33 @@ class RevPiPyControl(tkinter.Frame): u"""Baut den Debugframe und packt ihn.""" self.btn_debug["state"] = "disabled" - # Debugfenster laden - if self.debugframe is None: - self.debugframe = revpicheckclient.RevPiCheckClient( - self, self.cli, self.xmlmode + if "psstart" not in self.xmlfuncs: + tkmsg.showwarning( + parent=self.master, title=_("Warning"), + message=_( + "The watch mode ist not supported in version {} " + "of RevPiPyLoad on your RevPi! You need at least version " + "0.4.0." + ).format(self.cli.version()) ) - - # Show/Hide wechseln - if self.debugframe.winfo_viewable(): - self.debugframe.hideallwindows() - self.debugframe.autorw.set(False) - self.debugframe.toggleauto() - self.debugframe.dowrite.set(False) - self.debugframe.pack_forget() else: - self.debugframe.pack(fill="y") + # Debugfenster laden + if self.debugframe is None: + self.debugframe = revpicheckclient.RevPiCheckClient( + self, self.cli, self.xmlmode + ) - self.btn_debug["state"] = "normal" + # Show/Hide wechseln + if self.debugframe.winfo_viewable(): + self.debugframe.hideallwindows() + self.debugframe.autorw.set(False) + self.debugframe.toggleauto() + self.debugframe.dowrite.set(False) + self.debugframe.pack_forget() + else: + self.debugframe.pack(fill="y") + + self.btn_debug["state"] = "normal" def plclist(self): u"""Öffnet das Fenster für die Verbindungen.""" @@ -249,8 +245,10 @@ class RevPiPyControl(tkinter.Frame): if self.xmlmode < 2: tkmsg.showwarning( parent=self.master, title="Warnung", - message="Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch " - "genug eingestellt, um diesen Dialog zu verwenden!" + message=_( + "XML-RPC access mode in the RevPiPyLoad " + "configuration is to small to access this dialog" + ) ) else: win = tkinter.Toplevel(self) @@ -266,8 +264,10 @@ class RevPiPyControl(tkinter.Frame): if self.xmlmode < 2: tkmsg.showwarning( parent=self.master, title="Warnung", - message="Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch " - "genug eingestellt, um diesen Dialog zu verwenden!" + message=_( + "XML-RPC access mode in the RevPiPyLoad " + "configuration is to small to access this dialog" + ) ) else: win = tkinter.Toplevel(self) @@ -302,20 +302,20 @@ class RevPiPyControl(tkinter.Frame): def servererror(self): u"""Setzt alles zurück für neue Verbindungen.""" self.serverdisconnect() - tkmsg.showerror("Fehler", "Server ist nicht erreichbar!") + tkmsg.showerror(_("Fehler"), _("Server ist nicht erreichbar!")) def tmr_plcrunning(self): self._btnstate() if self.cli is None: self.txt_status["readonlybackground"] = "lightblue" - self.var_status.set("NOT CONNECTED") + self.var_status.set(_("NOT CONNECTED")) else: try: plcec = self.cli.plcexitcode() except: self.errcount += 1 if self.errcount >= 5: - self.var_status.set("SERVER ERROR") + self.var_status.set(_("SERVER ERROR")) self.servererror() else: self.errcount = 0 @@ -323,15 +323,17 @@ class RevPiPyControl(tkinter.Frame): "green" if plcec == -1 else "red" if plcec == -1: - plcec = "RUNNING" + plcec = _("RUNNING") elif plcec == -2: - plcec = "FILE NOT FOUND" + plcec = _("FILE NOT FOUND") + elif plcec == -3: + plcec = _("NOT RUNNING (NO STATUS)") elif plcec == -9: - plcec = "PROGRAM KILLED" + plcec = _("PROGRAM KILLED") elif plcec == -15: - plcec = "PROGRAMS TERMED" + plcec = _("PROGRAM TERMED") elif plcec == 0: - plcec = "NOT RUNNING" + plcec = _("NOT RUNNING") self.var_status.set(plcec) self.master.after(1000, self.tmr_plcrunning)