diff --git a/revpipycontrol.e4p b/revpipycontrol.e4p index b5d5115..4e778ae 100644 --- a/revpipycontrol.e4p +++ b/revpipycontrol.e4p @@ -1,7 +1,7 @@ - + en_US @@ -9,7 +9,7 @@ Python3 Console - 0.4.0 + 0.4.1 Sven Sager akira@narux.de diff --git a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po index 73a88ce..0fd8feb 100644 --- a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po +++ b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: RevPiPyControl 0.4.0\n" -"POT-Creation-Date: 2017-06-29 12:59+0200\n" -"PO-Revision-Date: 2017-06-29 13:03+0200\n" +"POT-Creation-Date: 2017-06-29 20:10+0200\n" +"PO-Revision-Date: 2017-06-29 20:10+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: de\n" @@ -43,39 +43,56 @@ msgstr "Aktualisiere automatisch" msgid "Write values to RevPi" msgstr "Schreibe Werte auf RevPi" -#: revpilogfile.py:27 +#: revpilogfile.py:37 msgid "RevPi Python PLC Logs" msgstr "RevPi Python PLC Logdaten" -#: revpilogfile.py:40 +#: revpilogfile.py:50 msgid "RevPiPyLoad - Logfile" msgstr "RevPiPyLoad - Logdatei" -#: revpilogfile.py:44 revpilogfile.py:59 +#: revpilogfile.py:54 revpilogfile.py:69 msgid "Clear screen" msgstr "Leere Ansicht" -#: revpilogfile.py:55 +#: revpilogfile.py:65 msgid "Python PLC program - Logfile" msgstr "Python PLC Programm - Logdatei" -#: revpioption.py:33 +#: revpilogfile.py:145 +msgid "Can not access log file on the RevPi" +msgstr "RevPi kann auf Logdatei nicht zugreifen" + +#: revpioption.py:61 revpioption.py:273 revpioption.py:298 revpiplclist.py:58 +#: revpiplclist.py:175 revpiprogram.py:370 revpiprogram.py:418 +msgid "Question" +msgstr "Frage" + +#: revpioption.py:62 revpiplclist.py:59 +msgid "" +"Do you really want to quit? \n" +"Unsaved changes will be lost" +msgstr "" +"Wollen Sie wirklich beenden? \n" +"Nicht gespeicherte Änderungen gehen verloren" + +#: revpioption.py:72 msgid "RevPi Python PLC Options" msgstr "RevPi Python PLC Einstellungen" -#: revpioption.py:41 +#: revpioption.py:80 msgid "Start / Stop behavior" msgstr "Start / Stop Verhalten" -#: revpioption.py:50 +#: revpioption.py:89 msgid "Start program automatically" msgstr "Starte Programm automatisch" -#: revpioption.py:56 +#: revpioption.py:95 msgid "Restart program after exit" msgstr "Starte Programm nach Beenden neu" -#: revpioption.py:63 +#: revpioption.py:103 msgid "" "Set process image to NULL if program\n" "terminates successfully" @@ -83,7 +100,7 @@ msgstr "" "\"Prozessabbild auf NULL setzen, wenn Programm\n" "\"erfolgreich beendet wird\"" -#: revpioption.py:70 +#: revpioption.py:111 msgid "" "Set process image to NULL if program\n" "terminates with errors" @@ -91,35 +108,35 @@ msgstr "" "Prozessabbild auf NULL setzen, wenn Programm\n" "fehlerhaft beendet wird" -#: revpioption.py:77 +#: revpioption.py:118 msgid "PLC program" msgstr "PLC Programm" -#: revpioption.py:88 +#: revpioption.py:129 msgid "Python version" msgstr "Python Version" -#: revpioption.py:105 +#: revpioption.py:146 msgid "Python PLC program name" msgstr "Python PLC Programmname" -#: revpioption.py:117 +#: revpioption.py:158 msgid "Program arguments" msgstr "Programmargumente" -#: revpioption.py:126 +#: revpioption.py:167 msgid "Use RevPi as PLC-Slave" msgstr "RevPi als PLC-Slave verwenden" -#: revpioption.py:133 +#: revpioption.py:174 msgid "XML-RPC server" msgstr "XML-RPC Server" -#: revpioption.py:145 +#: revpioption.py:186 msgid "Activate XML-RPC server on RevPi" msgstr "Aktiviere XML-RPC Server auf RevPi" -#: revpioption.py:153 +#: revpioption.py:194 msgid "" "Allow download of piCtory configuration and\n" "PLC programm" @@ -127,7 +144,7 @@ msgstr "" "Download von piCtroy Konfiguration und\n" "PLC Programm zulassen" -#: revpioption.py:160 +#: revpioption.py:201 msgid "" "Allow upload of piCtory configuration and\n" "PLC programm" @@ -135,24 +152,19 @@ msgstr "" "Hochladen von piCtroy Konfiguration und\n" "PLC Programm zulassen" -#: revpioption.py:165 +#: revpioption.py:206 msgid "XML-RPC server port" msgstr "XML-RPC Serverport" -#: revpioption.py:179 revpiplclist.py:111 +#: revpioption.py:220 revpiplclist.py:125 msgid "Save" msgstr "Speichern" -#: revpioption.py:184 revpiplclist.py:114 +#: revpioption.py:225 revpiplclist.py:128 msgid "Close" msgstr "Schließen" -#: revpioption.py:230 revpioption.py:254 revpiplclist.py:150 -#: revpiplclist.py:175 revpiprogram.py:370 revpiprogram.py:418 -msgid "Question" -msgstr "Frage" - -#: revpioption.py:231 +#: revpioption.py:274 msgid "" "The settings are now saved on the Revolution Pi. \n" "\n" @@ -164,29 +176,29 @@ msgstr "" "Sollen die neuen Einstellungen sofort in Kraft treten?\n" "Dies bedeutet einen Neustart des Dienstes und des laufenden PLC-Programms!" -#: revpioption.py:239 revpiplclist.py:190 revpiprogram.py:65 +#: revpioption.py:282 revpiplclist.py:190 revpiprogram.py:65 msgid "Information" msgstr "Information" -#: revpioption.py:240 +#: revpioption.py:283 msgid "Settings saved" msgstr "Einstellungen gespeichert" -#: revpioption.py:245 revpiplclist.py:198 revpiprogram.py:306 +#: revpioption.py:288 revpiplclist.py:198 revpiprogram.py:306 #: revpiprogram.py:337 revpiprogram.py:400 revpiprogram.py:433 -#: revpiprogram.py:517 revpiprogram.py:589 revpiprogram.py:620 -#: revpiprogram.py:633 revpiprogram.py:682 revpiprogram.py:702 -#: revpiprogram.py:710 revpipycontrol.py:307 +#: revpiprogram.py:515 revpiprogram.py:587 revpiprogram.py:618 +#: revpiprogram.py:631 revpiprogram.py:686 revpiprogram.py:706 +#: revpiprogram.py:714 revpipycontrol.py:325 msgid "Error" msgstr "Fehler" -#: revpioption.py:246 +#: revpioption.py:289 msgid "The settings could not be saved. This can happen if values are wrong!" msgstr "" "Die Einstellungen konnten nicht gesichert werden. Dies kann passieren, wenn " "Werte falsch sind!" -#: revpioption.py:255 +#: revpioption.py:299 msgid "" "Are you sure you want to deactivate the XML-RPC server? You will NOT be able " "to access the Revolution Pi with this program." @@ -194,42 +206,34 @@ msgstr "" "Soll der XML-RPC Server wirklich beendet werden? Sie können dann NICHT mehr " "mit diesem Programm auf den Revolution Pi zugreifen." -#: revpiplclist.py:54 +#: revpiplclist.py:68 msgid "RevPi Python PLC connections" msgstr "RevPi Python PLC Verbindungen" -#: revpiplclist.py:74 +#: revpiplclist.py:88 msgid "Name" msgstr "Name" -#: revpiplclist.py:81 +#: revpiplclist.py:95 msgid "IP address" msgstr "IP Adresse" -#: revpiplclist.py:89 +#: revpiplclist.py:103 msgid "Port" msgstr "Port" -#: revpiplclist.py:98 +#: revpiplclist.py:112 msgid "New" msgstr "Neu" -#: revpiplclist.py:101 +#: revpiplclist.py:115 msgid "Apply" msgstr "Übernehmen" -#: revpiplclist.py:105 +#: revpiplclist.py:119 msgid "Remove" msgstr "Entfernen" -#: revpiplclist.py:151 -msgid "" -"Do you really want to quit? \n" -"Unsaved changes will be lost" -msgstr "" -"Wollen Sie wirklich beenden? \n" -"Nicht gespeicherte Änderungen gehen verloren" - #: revpiplclist.py:176 msgid "Do you really want to delete the selected connection '{}'" msgstr "Wollen Sie die ausgewählte Verbindung '{}' wirklich löschen?" @@ -268,12 +272,12 @@ msgid "Files" msgstr "Dateien" #: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:465 -#: revpiprogram.py:573 +#: revpiprogram.py:571 msgid "Zip archive" msgstr "Zip Archiv" #: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:478 -#: revpiprogram.py:603 +#: revpiprogram.py:601 msgid "TGZ archive" msgstr "TGZ Archiv" @@ -341,7 +345,7 @@ msgstr "piControlReset ausführen" msgid "execute" msgstr "ausführen" -#: revpiprogram.py:216 revpipycontrol.py:96 +#: revpiprogram.py:216 revpipycontrol.py:95 msgid "Exit" msgstr "Beenden" @@ -355,22 +359,22 @@ msgid "piCtory config" msgstr "piCtory Konfiguration" #: revpiprogram.py:299 revpiprogram.py:330 revpiprogram.py:362 -#: revpiprogram.py:465 revpiprogram.py:478 revpiprogram.py:548 -#: revpiprogram.py:573 revpiprogram.py:603 +#: revpiprogram.py:465 revpiprogram.py:478 revpiprogram.py:546 +#: revpiprogram.py:571 revpiprogram.py:601 msgid "All files" msgstr "Alle Dateien" -#: revpiprogram.py:307 revpiprogram.py:338 revpiprogram.py:518 +#: revpiprogram.py:307 revpiprogram.py:338 revpiprogram.py:516 msgid "Could not load and save file!" msgstr "Datei konnte nicht geladen und gespeichert werden!" #: revpiprogram.py:312 revpiprogram.py:343 revpiprogram.py:381 -#: revpiprogram.py:389 revpiprogram.py:427 revpiprogram.py:523 -#: revpiprogram.py:672 +#: revpiprogram.py:389 revpiprogram.py:427 revpiprogram.py:521 +#: revpiprogram.py:676 msgid "Success" msgstr "Erfolgreich" -#: revpiprogram.py:313 revpiprogram.py:344 revpiprogram.py:524 +#: revpiprogram.py:313 revpiprogram.py:344 revpiprogram.py:522 msgid "File successfully loaded and saved." msgstr "Dateien erfolgreich übertragen und gespeichert." @@ -408,8 +412,8 @@ msgstr "" "Die piCtory Konfiguration konnte auf dem Revolution Pi nicht geschrieben " "werden." -#: revpiprogram.py:407 revpipycontrol.py:199 revpipycontrol.py:246 -#: revpipycontrol.py:266 +#: revpiprogram.py:407 revpipycontrol.py:211 revpipycontrol.py:250 +#: revpipycontrol.py:268 revpipycontrol.py:286 msgid "Warning" msgstr "Warnung" @@ -441,104 +445,124 @@ msgstr "piControl Reset konnte nicht erfolgreich durchgeführt werden" msgid "Directory to save" msgstr "Verzeichnis zum Ablegen" -#: revpiprogram.py:558 +#: revpiprogram.py:556 msgid "Folder to upload" msgstr "Verzeichnis zum Hochladen" -#: revpiprogram.py:569 +#: revpiprogram.py:567 msgid "Upload Zip archive..." msgstr "Zip Archiv hochladen..." -#: revpiprogram.py:590 +#: revpiprogram.py:588 msgid "The specified file is not a ZIP archive." msgstr "Die angegebene Datei ist kein ZIP Archiv" -#: revpiprogram.py:599 +#: revpiprogram.py:597 msgid "Upload TarGz archiv..." msgstr "TarGz Archiv hochladen..." -#: revpiprogram.py:621 +#: revpiprogram.py:619 msgid "The specified file is not a TAR archive." msgstr "Die angegebene Datei ist kein TAR Archiv." -#: revpiprogram.py:634 +#: revpiprogram.py:632 msgid "There was an error deleting the files on the Revolution Pi." msgstr "" "Beim Löschen der Dateien auf dem Revolution Pi ist ein Fehler aufgetreten." -#: revpiprogram.py:673 +#: revpiprogram.py:677 msgid "The transfer was successful." msgstr "Die Übertragung war erfolgreich." -#: revpiprogram.py:683 +#: revpiprogram.py:687 msgid "There is no piCtory configuration in this archive." msgstr "Es wurde keine piCtory Konfiguration im Archiv gefunden." -#: revpiprogram.py:703 +#: revpiprogram.py:707 msgid "The Revolution Pi could not process some parts of the transmission." msgstr "Der Revoluton Pi konnte Teile der Übertragung nicht verarbeiten." -#: revpiprogram.py:711 +#: revpiprogram.py:715 msgid "Errors occurred during transmission" msgstr "Bei der Übertragung traten Fehler auf" -#: revpipycontrol.py:94 +#: revpipycontrol.py:93 msgid "Connections..." msgstr "Verbindungen..." -#: revpipycontrol.py:97 +#: revpipycontrol.py:96 msgid "Main" msgstr "Datei" +#: revpipycontrol.py:104 +msgid "Visit website..." +msgstr "Webseite besuchen..." + +#: revpipycontrol.py:106 +msgid "Info..." +msgstr "Info..." + #: revpipycontrol.py:108 +msgid "Help" +msgstr "Hilfe" + +#: revpipycontrol.py:116 msgid "PLC start" msgstr "PLC Start" -#: revpipycontrol.py:113 +#: revpipycontrol.py:121 msgid "PLC stop" msgstr "PLC Stopp" -#: revpipycontrol.py:118 +#: revpipycontrol.py:126 msgid "PLC restart" msgstr "PLC Neustart" -#: revpipycontrol.py:123 +#: revpipycontrol.py:131 msgid "PLC logs" msgstr "PLC Logs" -#: revpipycontrol.py:134 +#: revpipycontrol.py:142 msgid "PLC watch mode" msgstr "PLC watch Modus" -#: revpipycontrol.py:151 +#: revpipycontrol.py:159 msgid "PLC log..." msgstr "PLC Log..." -#: revpipycontrol.py:153 +#: revpipycontrol.py:161 msgid "PLC options..." msgstr "PLC Optionen..." -#: revpipycontrol.py:155 +#: revpipycontrol.py:163 msgid "PLC program..." msgstr "PLC Programm..." -#: revpipycontrol.py:159 +#: revpipycontrol.py:167 msgid "Disconnect" msgstr "Trennen" -#: revpipycontrol.py:164 +#: revpipycontrol.py:172 msgid "Connect" msgstr "Verbinden" -#: revpipycontrol.py:200 +#: revpipycontrol.py:212 msgid "" "The watch mode ist not supported in version {} of RevPiPyLoad on your RevPi! " "You need at least version 0.4.0." msgstr "" -"Die Debug-Funktion wird von der RevPiPyLoad Version {} auf dem RevPi nicht " +"Der Watch-Modus wird von der RevPiPyLoad Version {} auf dem RevPi nicht " "unterstützt! Sie benötigen mindestens Version 0.4.0." -#: revpipycontrol.py:248 revpipycontrol.py:268 +#: revpipycontrol.py:251 +msgid "" +"This version of Logviewer ist not supported in version {} of RevPiPyLoad on " +"your RevPi! You need at least version 0.4.1." +msgstr "" +"Diese Version vom Logbetrachter wird in der RevPiPyLoad Version {} auf Ihrem " +"RevPi nicht unterstützt! Sie benötigen mindestens Version 0.4.1." + +#: revpipycontrol.py:269 revpipycontrol.py:287 msgid "" "XML-RPC access mode in the RevPiPyLoad configuration is to small to access " "this dialog" @@ -546,6 +570,6 @@ msgstr "" "Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch genug eingestellt, um " "diesen Dialog zu verwenden!" -#: revpipycontrol.py:308 +#: revpipycontrol.py:326 msgid "Can not reach server!" msgstr "Server ist nicht erreichbar!" diff --git a/revpipycontrol/revpilogfile.py b/revpipycontrol/revpilogfile.py index 060ed49..646bea3 100644 --- a/revpipycontrol/revpilogfile.py +++ b/revpipycontrol/revpilogfile.py @@ -5,7 +5,6 @@ # (c) Sven Sager, License: LGPLv3 # # -*- coding: utf-8 -*- -import pickle import tkinter from mytools import gettrans @@ -16,14 +15,25 @@ _ = gettrans() class RevPiLogfile(tkinter.Frame): def __init__(self, master, xmlcli): + u"""Init RevPiLogfile-Class.""" super().__init__(master) + self.master.bind("", self._closewin) self.pack(fill="both", expand=True) self.xmlcli = xmlcli + # Systemvariablen + self.loadblock = 16384 + self.mrkapp = 0 + self.mrkplc = 0 + # Fenster bauen self._createwidgets() + def _closewin(self, event): + self.master.destroy() + def _createwidgets(self): + u"""Erstellt alle Widgets.""" self.master.wm_title(_("RevPi Python PLC Logs")) self.rowconfigure(0, weight=0) @@ -65,47 +75,84 @@ class RevPiLogfile(tkinter.Frame): self.applog["yscrollcommand"] = self.appscr.set self.appscr["command"] = self.applog.yview - self.get_applog() - self.get_plclog() - - # Timer zum nachladen aktivieren - self.master.after(1000, self.get_applines) - self.master.after(1000, self.get_plclines) + # Logtimer zum Laden starten + self.get_applog(full=True) + self.get_plclog(full=True) def btn_clearapp(self): + u"""Leert die Logliste der App.""" self.applog.delete(1.0, tkinter.END) def btn_clearplc(self): + u"""Leert die Logliste des PLC.""" self.plclog.delete(1.0, tkinter.END) - def get_applines(self): - roll = self.applog.yview()[1] == 1.0 - try: - for line in pickle.loads(self.xmlcli.get_applines().data): - self.applog.insert(tkinter.END, line) - except: - pass - if roll: - self.applog.see(tkinter.END) - self.master.after(1000, self.get_applines) + def get_applog(self, full=False): + u"""Ruft App Logbuch ab. + @param full: Ganzes Logbuch laden""" - def get_applog(self): - self.applog.delete(1.0, tkinter.END) - self.applog.insert(1.0, pickle.loads(self.xmlcli.get_applog().data)) - self.applog.see(tkinter.END) + # Logs abrufen und letzte Position merken + self.mrkapp = self._load_log( + self.applog, self.xmlcli.load_applog, self.mrkapp, full + ) - def get_plclines(self): - roll = self.plclog.yview()[1] == 1.0 - try: - for line in pickle.loads(self.xmlcli.get_plclines().data): - self.plclog.insert(tkinter.END, line) - except: - pass - if roll: - self.plclog.see(tkinter.END) - self.master.after(1000, self.get_plclines) + # Timer neu starten + self.master.after(1000, self.get_applog) - def get_plclog(self): - self.plclog.delete(1.0, tkinter.END) - self.plclog.insert(1.0, pickle.loads(self.xmlcli.get_plclog().data)) - self.plclog.see(tkinter.END) + def get_plclog(self, full=False): + u"""Ruft PLC Logbuch ab. + @param full: Ganzes Logbuch laden""" + + # Logs abrufen und letzte Position merken + self.mrkplc = self._load_log( + self.plclog, self.xmlcli.load_plclog, self.mrkplc, full + ) + + # Timer neu starten + self.master.after(1000, self.get_plclog) + + def _load_log(self, textwidget, xmlcall, startposition, full): + u"""Läd die angegebenen Logfiles herunter. + + @param textwidget: Widget in das Logs eingefügt werden sollen + @param xmlcall: xmlrpc Funktion zum Abrufen der Logdaten + @param startposition: Startposition ab der Logdaten kommen sollen + @param full: Komplettes Logbuch laden + @returns: Ende der Datei (neue Startposition) + + """ + roll = textwidget.yview()[1] == 1.0 + startposition = 0 if full else startposition + logbytes = b'' + while True: + # Datenblock vom XML-RPC Server holen + bytebuff = xmlcall(startposition, self.loadblock).data + + logbytes += bytebuff + startposition += len(bytebuff) + + # Prüfen ob alle Daten übertragen wurden + if len(bytebuff) < self.loadblock: + break + + if full: + textwidget.delete(1.0, tkinter.END) + + if bytebuff == b'\x16': #  + # Kein Zugriff auf Logdatei + textwidget.delete(1.0, tkinter.END) + textwidget.insert( + tkinter.END, _("Can not access log file on the RevPi") + ) + elif bytebuff == b'\x19': #  + # Logdatei neu begonnen + startposition = 0 + else: + # Text in Widget übernehmen + textwidget.insert(tkinter.END, logbytes.decode("utf-8")) + + # Automatisch ans Ende rollen + if roll or full: + textwidget.see(tkinter.END) + + return startposition diff --git a/revpipycontrol/revpioption.py b/revpipycontrol/revpioption.py index 2d3c955..2d0afb4 100644 --- a/revpipycontrol/revpioption.py +++ b/revpipycontrol/revpioption.py @@ -16,10 +16,14 @@ _ = gettrans() class RevPiOption(tkinter.Frame): def __init__(self, master, xmlcli, xmlmode): + u"""Init RevPiOption-Class. + @returns: None""" if xmlmode < 2: return None super().__init__(master) + self.master.bind("", self._checkclose) + self.master.protocol("WM_DELETE_WINDOW", self._checkclose) self.pack(expand=True, fill="both") self.xmlcli = xmlcli @@ -30,7 +34,41 @@ class RevPiOption(tkinter.Frame): self._createwidgets() self._loadappdata() + def _changesdone(self): + u"""Prüft ob sich die Einstellungen geändert haben. + @returns: 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_zexit.get() != self.dc.get("zeroonexit", "0") + or self.var_zerr.get() != self.dc.get("zeroonerror", "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_xmlon.get() != (self.dc.get("xmlrpc", 0) >= 1) + or self.var_xmlmod2.get() != (self.dc.get("xmlrpc", 0) >= 2) + or self.var_xmlmod3.get() != (self.dc.get("xmlrpc", 0) >= 3) + or self.var_xmlport.get() != self.dc.get("xmlrpcport", "55123") + ) + + 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 + ) + + if ask: + self.master.destroy() + def _createwidgets(self): + u"""Erstellt Widgets.""" self.master.wm_title(_("RevPi Python PLC Options")) self.master.wm_resizable(width=False, height=False) @@ -183,30 +221,32 @@ class RevPiOption(tkinter.Frame): btn_save.grid(column=0, row=3) btn_close = tkinter.Button(self) - btn_close["command"] = self.master.destroy + btn_close["command"] = self._checkclose btn_close["text"] = _("Close") btn_close.grid(column=1, row=3) def _loadappdata(self): - dc = self.xmlcli.get_config() + u"""Läd aktuelle Einstellungen vom RevPi.""" + self.dc = self.xmlcli.get_config() - self.var_start.set(dc.get("autostart", "1")) - self.var_reload.set(dc.get("autoreload", "1")) - self.var_zexit.set(dc.get("zeroonexit", "0")) - self.var_zerr.set(dc.get("zeroonerror", "0")) + self.var_start.set(self.dc.get("autostart", "1")) + self.var_reload.set(self.dc.get("autoreload", "1")) + self.var_zexit.set(self.dc.get("zeroonexit", "0")) + self.var_zerr.set(self.dc.get("zeroonerror", "0")) - self.var_startpy.set(dc.get("plcprogram", "none.py")) - self.var_startargs.set(dc.get("plcarguments", "")) - self.var_pythonver.set(dc.get("pythonversion", "3")) - self.var_slave.set(dc.get("plcslave", "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_xmlon.set(dc.get("xmlrpc", 0) >= 1) - self.var_xmlmod2.set(dc.get("xmlrpc", 0) >= 2) - self.var_xmlmod3.set(dc.get("xmlrpc", 0) >= 3) + self.var_xmlon.set(self.dc.get("xmlrpc", 0) >= 1) + self.var_xmlmod2.set(self.dc.get("xmlrpc", 0) >= 2) + self.var_xmlmod3.set(self.dc.get("xmlrpc", 0) >= 3) - self.var_xmlport.set(dc.get("xmlrpcport", "55123")) + self.var_xmlport.set(self.dc.get("xmlrpcport", "55123")) def _setappdata(self): + u"""Speichert geänderte Einstellungen auf RevPi.""" dc = {} dc["autostart"] = int(self.var_start.get()) dc["autoreload"] = int(self.var_reload.get()) @@ -252,6 +292,7 @@ class RevPiOption(tkinter.Frame): ) def askxmlon(self): + u"""Fragt Nuter, ob wirklicht abgeschaltet werden soll.""" if not self.var_xmlon.get(): ask = tkmsg.askyesno( _("Question"), @@ -266,6 +307,7 @@ class RevPiOption(tkinter.Frame): self.xmlmods() def xmlmods(self): + u"""Passt XML-Optionszugriff an.""" self.ckb_xmlmod2["state"] = \ "normal" if self.var_xmlon.get() else "disabled" self.ckb_xmlmod3["state"] = \ diff --git a/revpipycontrol/revpiplclist.py b/revpipycontrol/revpiplclist.py index 801b845..309c826 100644 --- a/revpipycontrol/revpiplclist.py +++ b/revpipycontrol/revpiplclist.py @@ -39,6 +39,7 @@ class RevPiPlcList(tkinter.Frame): def __init__(self, master): super().__init__(master) + self.master.bind("", self._checkclose) self.pack() self.changes = False @@ -50,10 +51,23 @@ class RevPiPlcList(tkinter.Frame): self._createwidgets() self._loadappdata() + def _checkclose(self, event=None): + ask = True + if self.changes: + ask = tkmsg.askyesno( + _("Question"), + _("Do you really want to quit? \nUnsaved changes will " + "be lost"), + parent=self.master + ) + + if ask: + self.master.destroy() + def _createwidgets(self): self.master.wm_title(_("RevPi Python PLC connections")) self.master.wm_resizable(width=False, height=False) - self.master.protocol("WM_DELETE_WINDOW", self.evt_btnclose) + self.master.protocol("WM_DELETE_WINDOW", self._checkclose) # Listbox mit vorhandenen Verbindungen self.scr_conn = tkinter.Scrollbar(self) @@ -111,7 +125,7 @@ class RevPiPlcList(tkinter.Frame): self, text=_("Save"), command=self.evt_btnsave) self.btn_save.grid(column=3, row=9, sticky="se") self.btn_close = tkinter.Button( - self, text=_("Close"), command=self.evt_btnclose) + self, text=_("Close"), command=self._checkclose) self.btn_close.grid(column=4, row=9, sticky="se") def _loadappdata(self): @@ -144,20 +158,6 @@ class RevPiPlcList(tkinter.Frame): self.evt_btnnew() self.changes = True - def evt_btnclose(self): - if self.changes: - ask = tkmsg.askyesno( - _("Question"), - _("Do you really want to quit? \nUnsaved changes will " - "be lost"), - parent=self.master - ) - else: - ask = True - - if ask: - self.master.destroy() - def evt_btnnew(self): self.list_conn.select_clear(0, "end") self.evt_listconn() diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index 3047f59..269eddd 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -40,8 +40,8 @@ class RevPiProgram(tkinter.Frame): return None super().__init__(master) - # FIXME: Warnung kann nerven - # self.master.protocol("WM_DELETE_WINDOW", self._checkclose) + self.master.protocol("WM_DELETE_WINDOW", self._checkclose) + self.master.bind("", self._checkclose) self.pack(expand=True, fill="both") self.uploaded = False @@ -59,8 +59,8 @@ class RevPiProgram(tkinter.Frame): self._evt_optdown() self._evt_optup() - def _checkclose(self): - if True or self.uploaded: + def _checkclose(self, event=None): + if self.uploaded: tkmsg.showinfo( _("Information"), _("A PLC program has been uploaded. Please check the " @@ -212,7 +212,7 @@ class RevPiProgram(tkinter.Frame): # Beendenbutton btn = tkinter.Button(self) - btn["command"] = self.master.destroy + btn["command"] = self._checkclose btn["text"] = _("Exit") btn.grid() @@ -374,7 +374,7 @@ class RevPiProgram(tkinter.Frame): ) ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask) - print(ec) + if ec == 0: if ask: tkmsg.showinfo( @@ -496,9 +496,7 @@ class RevPiProgram(tkinter.Frame): fh_pack = tarfile.open(fh.name) # Unterverzeichnis streichen - rootname = "" for taritem in fh_pack.getmembers(): - print(rootname) if not taritem.name == "revpipyload": taritem.name = \ taritem.name.replace("revpipyload/", "") @@ -637,7 +635,9 @@ class RevPiProgram(tkinter.Frame): ) return False - # Flag setzen, weil ab hier Veränderungen existieren + # Aktuell konfiguriertes Programm lesen (für uploaded Flag) + opt_program = self.xmlcli.get_config() + opt_program = opt_program.get("plcprogram", "none.py") self.uploaded = True ec = 0 @@ -655,6 +655,10 @@ class RevPiProgram(tkinter.Frame): else: sendname = fname.replace(dirselect, "")[1:] + # Prüfen ob Dateiname bereits als Startprogramm angegeben ist + if sendname == opt_program: + self.uploaded = False + # Datei übertragen try: ustatus = self.xmlcli.plcupload( diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index 2051e76..a46989b 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 # # RevPiPyControl -# Version: 0.4.0 +# Version: 0.4.1 # # Webpage: https://revpimodio.org/revpipyplc/ # (c) Sven Sager, License: LGPLv3 @@ -19,7 +19,6 @@ from functools import partial from mytools import addroot, gettrans from xmlrpc.client import ServerProxy - # Übersetzung laden _ = gettrans() @@ -99,6 +98,15 @@ class RevPiPyControl(tkinter.Frame): self._fillmbar() self._fillconnbar() + # Hilfe Menü + menu1 = tkinter.Menu(self.mbar, tearoff=False) + menu1.add_command( + label=_("Visit website..."), command=self.visitwebsite) + menu1.add_separator() + menu1.add_command(label=_("Info..."), command=self.infowindow) + # TODO: Menü einbauen + self.mbar.add_cascade(label=_("Help"), menu=menu1) + self.var_conn = tkinter.StringVar(self) self.txt_connect = tkinter.Entry( self, textvariable=self.var_conn, state="readonly", width=30) @@ -190,6 +198,10 @@ class RevPiPyControl(tkinter.Frame): )) self.mbar.entryconfig("PLC", state="normal") + def infowindow(self): + # TODO: Infofenster aufrufen + pass + def plcdebug(self): u"""Baut den Debugframe und packt ihn.""" self.btn_debug["state"] = "disabled" @@ -233,6 +245,16 @@ class RevPiPyControl(tkinter.Frame): def plclogs(self): u"""Öffnet das Fenster für Logdateien.""" + if "load_plclog" not in self.xmlfuncs: + tkmsg.showwarning( + _("Warning"), + _("This version of Logviewer ist not supported in version {} " + "of RevPiPyLoad on your RevPi! You need at least version " + "0.4.1.").format(self.cli.version()), + parent=self.master + ) + return None + if self.tklogs is None or len(self.tklogs.children) == 0: win = tkinter.Toplevel(self) self.tklogs = revpilogfile.RevPiLogfile(win, self.cli) @@ -244,10 +266,8 @@ class RevPiPyControl(tkinter.Frame): if self.xmlmode < 2: tkmsg.showwarning( _("Warning"), - _( - "XML-RPC access mode in the RevPiPyLoad " - "configuration is to small to access this dialog" - ), + _("XML-RPC access mode in the RevPiPyLoad " + "configuration is to small to access this dialog"), parent=self.master ) else: @@ -264,10 +284,8 @@ class RevPiPyControl(tkinter.Frame): if self.xmlmode < 2: tkmsg.showwarning( _("Warning"), - _( - "XML-RPC access mode in the RevPiPyLoad " - "configuration is to small to access this dialog" - ), + _("XML-RPC access mode in the RevPiPyLoad " + "configuration is to small to access this dialog"), parent=self.master ) else: @@ -343,6 +361,9 @@ class RevPiPyControl(tkinter.Frame): self.master.after(1000, self.tmr_plcrunning) + def visitwebsite(self): + # TODO: Webseite besuchen + pass if __name__ == "__main__": root = tkinter.Tk() diff --git a/setup.py b/setup.py index 2d518aa..60d64c8 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ globsetup = { "author_email": "akira@narux.de", "url": "https://revpimodio.org/revpipyplc/", "license": "LGPLv3", - "version": "0.4.0", + "version": "0.4.1", "name": "revpipycontrol",