mirror of
https://github.com/naruxde/revpicommander.git
synced 2025-11-09 17:08:05 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9202aedf7f | |||
| 8e2b8311ef | |||
| 15058feb7e | |||
| d14b6dccdd | |||
| feb55fe2b5 |
@@ -2,7 +2,7 @@ recursive-include data *
|
|||||||
recursive-include src/revpicommander *.py *.qm
|
recursive-include src/revpicommander *.py *.qm
|
||||||
recursive-include ui_dev *
|
recursive-include ui_dev *
|
||||||
include LICENSE.txt
|
include LICENSE.txt
|
||||||
include make_installer_win.bat
|
include make.bat
|
||||||
include Makefile
|
include Makefile
|
||||||
include MANIFEST.in
|
include MANIFEST.in
|
||||||
include README.md
|
include README.md
|
||||||
|
|||||||
63
Makefile
63
Makefile
@@ -4,9 +4,12 @@ MAKEFLAGS = --no-print-directory --no-builtin-rules
|
|||||||
|
|
||||||
# Variables
|
# Variables
|
||||||
PACKAGE = revpicommander
|
PACKAGE = revpicommander
|
||||||
|
APP_NAME = RevPi\ Commander
|
||||||
|
APP_IDENT = org.revpimodio.revpicommander
|
||||||
|
APPLE_SIG = "Developer ID Application: Sven Sager (U3N5843D9K)"
|
||||||
|
|
||||||
# If virtualenv exists, use it. If not, use PATH to find
|
# If virtualenv exists, use it. If not, use PATH to find, except python3
|
||||||
SYSTEM_PYTHON = $(or $(shell which python3), $(shell which python))
|
SYSTEM_PYTHON = /usr/bin/python3
|
||||||
PYTHON = $(or $(wildcard venv/bin/python), $(SYSTEM_PYTHON))
|
PYTHON = $(or $(wildcard venv/bin/python), $(SYSTEM_PYTHON))
|
||||||
SYSTEM_PYUIC5 = $(shell which pyuic5)
|
SYSTEM_PYUIC5 = $(shell which pyuic5)
|
||||||
PYUIC5 = $(or $(wildcard venv/bin/pyuic5), $(SYSTEM_PYUIC5))
|
PYUIC5 = $(or $(wildcard venv/bin/pyuic5), $(SYSTEM_PYUIC5))
|
||||||
@@ -15,10 +18,22 @@ PYRCC5 = $(or $(wildcard venv/bin/pyrcc5), $(SYSTEM_PYRCC5))
|
|||||||
SYSTEM_PYLUP5 = $(shell which pylupdate5)
|
SYSTEM_PYLUP5 = $(shell which pylupdate5)
|
||||||
PYLUP5 = $(or $(wildcard venv/bin/pylupdate5), $(SYSTEM_PYLUP5))
|
PYLUP5 = $(or $(wildcard venv/bin/pylupdate5), $(SYSTEM_PYLUP5))
|
||||||
|
|
||||||
|
APP_VERSION = $(shell $(PYTHON) src/$(PACKAGE) --version)
|
||||||
|
|
||||||
all: build_ui build_rc build
|
all: build_ui build_rc build
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
|
## Environment
|
||||||
|
venv:
|
||||||
|
$(SYSTEM_PYTHON) -m venv venv
|
||||||
|
source venv/bin/activate && \
|
||||||
|
python3 -m pip install --upgrade pip && \
|
||||||
|
python3 -m pip install -r requirements.txt
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
.PHONY: venv
|
||||||
|
|
||||||
## Compile Qt UI files to python code
|
## Compile Qt UI files to python code
|
||||||
build_ui:
|
build_ui:
|
||||||
cd ui_dev && for ui_file in *.ui; do \
|
cd ui_dev && for ui_file in *.ui; do \
|
||||||
@@ -39,16 +54,6 @@ update_translation:
|
|||||||
|
|
||||||
.PHONY: build_ui build_rc update_translation
|
.PHONY: build_ui build_rc update_translation
|
||||||
|
|
||||||
## Environment
|
|
||||||
venv:
|
|
||||||
rm -rf venv
|
|
||||||
$(SYSTEM_PYTHON) -m venv venv
|
|
||||||
|
|
||||||
deps:
|
|
||||||
$(PYTHON) -m pip install --upgrade pip -r requirements.txt
|
|
||||||
|
|
||||||
.PHONY: venv deps
|
|
||||||
|
|
||||||
## Build, install
|
## Build, install
|
||||||
build: build_ui build_rc
|
build: build_ui build_rc
|
||||||
$(PYTHON) -m setup sdist
|
$(PYTHON) -m setup sdist
|
||||||
@@ -60,24 +65,44 @@ install:
|
|||||||
.PHONY: build install
|
.PHONY: build install
|
||||||
|
|
||||||
## PyInstaller
|
## PyInstaller
|
||||||
installer_mac: build
|
installer_mac: build_ui build_rc
|
||||||
$(PYTHON) -m PyInstaller -n "RevPi Commander" \
|
$(PYTHON) -m PyInstaller -n $(APP_NAME) \
|
||||||
--add-data="src/$(PACKAGE)/locale:./revpicommander/locale" \
|
--add-data="src/$(PACKAGE)/locale:./$(PACKAGE)/locale" \
|
||||||
--add-data="data/$(PACKAGE).icns:." \
|
--add-data="data/$(PACKAGE).icns:." \
|
||||||
--icon=data/$(PACKAGE).icns \
|
--icon=data/$(PACKAGE).icns \
|
||||||
--noconfirm \
|
--noconfirm \
|
||||||
--clean \
|
--clean \
|
||||||
--onedir \
|
--onedir \
|
||||||
--windowed \
|
--windowed \
|
||||||
|
--osx-bundle-identifier $APP_IDENT \
|
||||||
|
--codesign-identity $(APPLE_SIG) \
|
||||||
src/$(PACKAGE)/__main__.py
|
src/$(PACKAGE)/__main__.py
|
||||||
|
|
||||||
installer_win: all
|
installer_mac_dmg: installer_mac
|
||||||
make_installer_win.bat
|
mkdir dist/dmg
|
||||||
|
mv dist/$(APP_NAME).app dist/dmg
|
||||||
|
create-dmg \
|
||||||
|
--volname $(APP_NAME) \
|
||||||
|
--background data/dmg_background.png \
|
||||||
|
--window-pos 200 120 \
|
||||||
|
--window-size 480 300 \
|
||||||
|
--icon-size 64 \
|
||||||
|
--icon $(APP_NAME).app 64 64 \
|
||||||
|
--hide-extension $(APP_NAME).app \
|
||||||
|
--app-drop-link 288 64 \
|
||||||
|
--add-file LICENSE.txt LICENSE.txt 192 180 \
|
||||||
|
--codesign $(APPLE_SIG) \
|
||||||
|
--notarize AC_PASSWORD \
|
||||||
|
dist/$(APP_NAME)\ $(APP_VERSION).dmg \
|
||||||
|
dist/dmg
|
||||||
|
|
||||||
.PHONY: installer_mac installer_win
|
.PHONY: installer_mac installer_mac_dmg
|
||||||
|
|
||||||
## Clean
|
## Clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf build dist src/*.egg-info *.spec
|
rm -rf build dist src/*.egg-info *.spec
|
||||||
|
|
||||||
.PHONY: clean
|
clean-all: clean
|
||||||
|
rm -R venv
|
||||||
|
|
||||||
|
.PHONY: clean clean-all
|
||||||
|
|||||||
BIN
data/dmg_background.png
Normal file
BIN
data/dmg_background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 172 KiB |
@@ -1,3 +1,9 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
# Used to call the entry point, if packed with pybuild as application.
|
||||||
|
# PYBUILD_INSTALL_ARGS=--install-lib=/usr/share/revpicommander/ \
|
||||||
|
# --install-scripts=/usr/share/revpicommander/
|
||||||
|
#
|
||||||
|
# In that case the entry point will not find the revpicommander module in
|
||||||
|
# the python lib.
|
||||||
|
|
||||||
exec "/usr/share/revpicommander/revpicommander.py" "$@"
|
exec "/usr/share/revpicommander/revpicommander-gui" "$@"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=RevPi PLC Commander
|
Name=RevPi Commander
|
||||||
Comment=Controls the Python PLC program on your Revolution PI
|
Comment=Controls the Python PLC program on your Revolution PI
|
||||||
Comment[de]=Kontrolliert das Python PLC Programm auf dem Revolution PI
|
Comment[de]=Kontrolliert das Python PLC Programm auf dem Revolution PI
|
||||||
Exec=/usr/bin/revpicommander
|
Exec=/usr/bin/revpicommander
|
||||||
@@ -7,4 +7,3 @@ Icon=revpicommander
|
|||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=Application;
|
Categories=Application;
|
||||||
#StartupNotify=true
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 5.3 KiB |
39
make.bat
Normal file
39
make.bat
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
@echo off
|
||||||
|
set PACKAGE=revpicommander
|
||||||
|
set APP_NAME=RevPi Commander
|
||||||
|
|
||||||
|
if "%1" == "venv" goto venv
|
||||||
|
if "%1" == "installer" goto installer
|
||||||
|
if "%1" == "clean" goto clean
|
||||||
|
|
||||||
|
echo Make script for "%APP_NAME%" on Windows
|
||||||
|
echo.
|
||||||
|
echo Need action:
|
||||||
|
echo venv Create / update your virtual environment for build process
|
||||||
|
echo installer Build this application with PyInstaller
|
||||||
|
echo clean Clean up your environment after build process
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:venv
|
||||||
|
python -m venv venv
|
||||||
|
venv\\Scripts\\pip.exe install --upgrade -r requirements.txt
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:installer
|
||||||
|
venv\\Scripts\\pyinstaller -n "%APP_NAME%" ^
|
||||||
|
--add-data="src\%PACKAGE%\locale;.\%PACKAGE%\locale" ^
|
||||||
|
--add-data="data\%PACKAGE%.ico;." ^
|
||||||
|
--icon=data\\%PACKAGE%.ico ^
|
||||||
|
--noconfirm ^
|
||||||
|
--clean ^
|
||||||
|
--onedir ^
|
||||||
|
--windowed ^
|
||||||
|
src\\%PACKAGE%\\__main__.py
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:clean
|
||||||
|
rmdir /S /Q build dist
|
||||||
|
rmdir /S /Q src\%PACKAGE%.egg-info
|
||||||
|
del *.spec
|
||||||
|
|
||||||
|
:end
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
@echo off
|
|
||||||
set PACKAGE=revpicommander
|
|
||||||
|
|
||||||
rem python -m venv venv
|
|
||||||
rem venv\\Scripts\\activate.bat
|
|
||||||
rem pip install -r requirements.txt
|
|
||||||
|
|
||||||
pyinstaller -n "RevPi Commander" ^
|
|
||||||
--add-data="src\%PACKAGE%\locale;.\revpicommander\locale" ^
|
|
||||||
--add-data="data\%PACKAGE%.ico;." ^
|
|
||||||
--icon=data\\%PACKAGE%.ico ^
|
|
||||||
--noconfirm ^
|
|
||||||
--clean ^
|
|
||||||
--onedir ^
|
|
||||||
--windowed ^
|
|
||||||
src\\%PACKAGE%\\__main__.py
|
|
||||||
|
|
||||||
rem deactivate
|
|
||||||
3
setup.iss
Executable file → Normal file
3
setup.iss
Executable file → Normal file
@@ -2,12 +2,13 @@
|
|||||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||||
|
|
||||||
#define MyAppName "RevPi Commander"
|
#define MyAppName "RevPi Commander"
|
||||||
#define MyAppVersion "0.9.10rc2"
|
#define MyAppVersion "0.9.10rc4"
|
||||||
#define MyAppPublisher "Sven Sager"
|
#define MyAppPublisher "Sven Sager"
|
||||||
#define MyAppURL "https://revpimodio.org/"
|
#define MyAppURL "https://revpimodio.org/"
|
||||||
#define MyAppICO "data\revpicommander.ico"
|
#define MyAppICO "data\revpicommander.ico"
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
|
SignTool=kSign
|
||||||
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
|
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
|
||||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||||
AppId={{21E8D429-0C18-462F-AFC0-56EA664DE629}
|
AppId={{21E8D429-0C18-462F-AFC0-56EA664DE629}
|
||||||
|
|||||||
6
setup.py
6
setup.py
@@ -6,9 +6,11 @@ __license__ = "GPLv3"
|
|||||||
|
|
||||||
from setuptools import find_namespace_packages, setup
|
from setuptools import find_namespace_packages, setup
|
||||||
|
|
||||||
|
from src.revpicommander import __version__
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="revpicommander",
|
name="revpicommander",
|
||||||
version="0.9.10rc2",
|
version=__version__,
|
||||||
|
|
||||||
packages=find_namespace_packages("src"),
|
packages=find_namespace_packages("src"),
|
||||||
package_dir={'': 'src'},
|
package_dir={'': 'src'},
|
||||||
@@ -35,7 +37,7 @@ setup(
|
|||||||
maintainer="Sven Sager",
|
maintainer="Sven Sager",
|
||||||
maintainer_email="akira@revpimodio.org",
|
maintainer_email="akira@revpimodio.org",
|
||||||
description="GUI for Revolution Pi to upload programs and do IO-Checks",
|
description="GUI for Revolution Pi to upload programs and do IO-Checks",
|
||||||
long_description="The RevPiCommander is a GUI tool to manage your revolution Pi over the\n"
|
long_description="The RevPiCommander is a GUI tool to manage your Revolution Pi over the\n"
|
||||||
"network. You can search for RevPis in your network, manage the settings\n"
|
"network. You can search for RevPis in your network, manage the settings\n"
|
||||||
"of RevPiPyLoad and do IO checks on your local machine. Developing your\n"
|
"of RevPiPyLoad and do IO checks on your local machine. Developing your\n"
|
||||||
"control program is very easy with the developer, upload and debug it\n"
|
"control program is very easy with the developer, upload and debug it\n"
|
||||||
|
|||||||
@@ -3,3 +3,4 @@
|
|||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "GPLv3"
|
__license__ = "GPLv3"
|
||||||
|
__version__ = "0.9.10rc4"
|
||||||
|
|||||||
@@ -16,6 +16,14 @@ if __package__ == "":
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
if len(sys.argv) == 2 and "--version" in sys.argv:
|
||||||
|
# Catch --version, if this is the only argument (sys.argv[0] is always the script name)
|
||||||
|
from revpicommander import __version__
|
||||||
|
print(__version__)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
else:
|
||||||
from revpicommander.revpicommander import main
|
from revpicommander.revpicommander import main
|
||||||
|
|
||||||
# Run the main application of this package
|
# Run the main application of this package
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ class BackgroundWorker(QtCore.QThread):
|
|||||||
steps_done = QtCore.pyqtSignal(int)
|
steps_done = QtCore.pyqtSignal(int)
|
||||||
status_message = QtCore.pyqtSignal(str)
|
status_message = QtCore.pyqtSignal(str)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None, interruption_text: str = None):
|
||||||
|
self._interruption_text = interruption_text or self.tr("User requested cancellation...")
|
||||||
super(BackgroundWorker, self).__init__(parent)
|
super(BackgroundWorker, self).__init__(parent)
|
||||||
|
|
||||||
def check_cancel(self) -> bool:
|
def check_cancel(self) -> bool:
|
||||||
@@ -28,33 +29,67 @@ class BackgroundWorker(QtCore.QThread):
|
|||||||
:return: True, if interruption was requested
|
:return: True, if interruption was requested
|
||||||
"""
|
"""
|
||||||
if self.isInterruptionRequested():
|
if self.isInterruptionRequested():
|
||||||
self.status_message.emit(self.tr("User requested cancellation..."))
|
self.status_message.emit(self._interruption_text)
|
||||||
self.msleep(750)
|
self.msleep(750)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def exec_dialog(self) -> int:
|
def exec_dialog(self, window_title="", can_cancel=True) -> int:
|
||||||
|
"""
|
||||||
|
Show dialog with progress bar.
|
||||||
|
|
||||||
|
:param window_title: Title of Dialog window
|
||||||
|
:param can_cancel: If False, the cancel button is deactivated
|
||||||
|
:return: Dialog result
|
||||||
|
"""
|
||||||
diag = WorkerDialog(self, self.parent())
|
diag = WorkerDialog(self, self.parent())
|
||||||
|
diag.setWindowTitle(window_title)
|
||||||
|
diag.btn_box.setEnabled(can_cancel)
|
||||||
rc = diag.exec()
|
rc = diag.exec()
|
||||||
diag.deleteLater()
|
diag.deleteLater()
|
||||||
return rc
|
return rc
|
||||||
|
|
||||||
def wait_interruptable(self, seconds=-1) -> None:
|
def wait_interruptable(self, seconds=-1) -> bool:
|
||||||
"""Save function to wait and get the cancel buttons."""
|
"""
|
||||||
|
Save function to wait and get the cancel buttons.
|
||||||
|
|
||||||
|
:param seconds: Wait this amount of seconds
|
||||||
|
:return: True, if interruption was requested
|
||||||
|
"""
|
||||||
counter = seconds * 4
|
counter = seconds * 4
|
||||||
while counter != 0:
|
while counter != 0:
|
||||||
counter -= 1
|
counter -= 1
|
||||||
self.msleep(250)
|
self.msleep(250)
|
||||||
if self.check_cancel():
|
if self.check_cancel():
|
||||||
break
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
"""Worker thread to import pictures from camera."""
|
"""Override this function with your logic."""
|
||||||
log.debug("BackgroundWorker.run")
|
raise NotImplementedError()
|
||||||
self.status_message.emit("Started dummy thread...")
|
|
||||||
self.wait_interruptable(5)
|
|
||||||
self.status_message.emit("Completed dummy thread.")
|
class BackgroundWaiter(BackgroundWorker):
|
||||||
self.wait_interruptable(2)
|
"""Just wait an amount of time and show progress bar."""
|
||||||
|
|
||||||
|
def __init__(self, seconds: int, status_message: str, parent=None, interruption_text: str = None):
|
||||||
|
self._status_message = status_message
|
||||||
|
self._wait_steps = seconds * 4
|
||||||
|
super().__init__(parent, interruption_text)
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
log.debug("BackgroundWaiter.run")
|
||||||
|
self.steps_todo.emit(self._wait_steps)
|
||||||
|
self.status_message.emit(self._status_message)
|
||||||
|
counter = 0
|
||||||
|
while counter <= self._wait_steps:
|
||||||
|
counter += 1
|
||||||
|
self.msleep(250)
|
||||||
|
if self.isInterruptionRequested():
|
||||||
|
self.steps_done.emit(self._wait_steps)
|
||||||
|
if self.check_cancel():
|
||||||
|
return
|
||||||
|
self.steps_done.emit(counter)
|
||||||
|
|
||||||
|
|
||||||
class WorkerDialog(QtWidgets.QDialog, Ui_diag_backgroundworker):
|
class WorkerDialog(QtWidgets.QDialog, Ui_diag_backgroundworker):
|
||||||
|
|||||||
@@ -15,20 +15,25 @@ from threading import Lock
|
|||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from xmlrpc.client import Binary, ServerProxy
|
from xmlrpc.client import Binary, ServerProxy
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtWidgets
|
from PyQt5 import QtCore
|
||||||
from paramiko.ssh_exception import AuthenticationException
|
from paramiko.ssh_exception import AuthenticationException
|
||||||
|
|
||||||
from . import proginit as pi
|
from . import proginit as pi
|
||||||
from .ssh_tunneling.server import SSHLocalTunnel
|
from .ssh_tunneling.server import SSHLocalTunnel
|
||||||
from .sshauth import SSHAuth
|
|
||||||
|
|
||||||
settings = QtCore.QSettings("revpimodio.org", "RevPiCommander")
|
settings = QtCore.QSettings("revpimodio.org", "revpicommander")
|
||||||
"""Global application settings."""
|
"""Global application settings."""
|
||||||
|
|
||||||
homedir = environ.get("HOME", "") or environ.get("APPDATA", "")
|
homedir = environ.get("HOME", "") or environ.get("APPDATA", "")
|
||||||
"""Home dir of user."""
|
"""Home dir of user."""
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectionFail(IntEnum):
|
||||||
|
NO_XML_RPC = 1
|
||||||
|
SSH_CONNECT = 2
|
||||||
|
SSH_AUTH = 4
|
||||||
|
|
||||||
|
|
||||||
class WidgetData(IntEnum):
|
class WidgetData(IntEnum):
|
||||||
address = 260
|
address = 260
|
||||||
acl_level = 262
|
acl_level = 262
|
||||||
@@ -194,6 +199,8 @@ class RevPiSettings:
|
|||||||
class ConnectionManager(QtCore.QThread):
|
class ConnectionManager(QtCore.QThread):
|
||||||
"""Check connection and status for PLC program on Revolution Pi."""
|
"""Check connection and status for PLC program on Revolution Pi."""
|
||||||
|
|
||||||
|
connect_error = QtCore.pyqtSignal(str, str, ConnectionFail, RevPiSettings)
|
||||||
|
"""Error header, message and reason (ConnectionFail) of a new connection after pyload_connect call."""
|
||||||
connection_established = QtCore.pyqtSignal()
|
connection_established = QtCore.pyqtSignal()
|
||||||
"""New connection established successfully with <class 'ServerProxy'>."""
|
"""New connection established successfully with <class 'ServerProxy'>."""
|
||||||
connection_disconnected = QtCore.pyqtSignal()
|
connection_disconnected = QtCore.pyqtSignal()
|
||||||
@@ -311,12 +318,12 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
self.xml_funcs.clear()
|
self.xml_funcs.clear()
|
||||||
self.xml_mode = -1
|
self.xml_mode = -1
|
||||||
|
|
||||||
def pyload_connect(self, revpi_settings: RevPiSettings, parent=None) -> bool:
|
def pyload_connect(self, revpi_settings: RevPiSettings, ssh_pass="") -> bool:
|
||||||
"""
|
"""
|
||||||
Create a new connection from settings object.
|
Create a new connection from settings object.
|
||||||
|
|
||||||
:param revpi_settings: Revolution Pi saved connection settings
|
:param revpi_settings: Revolution Pi saved connection settings
|
||||||
:param parent: Qt parent window for dialog positioning
|
:param ssh_pass: Use this ssh password, if revpi_settings.ssh_use_tunnel is true
|
||||||
:return: True, if the connection was successfully established
|
:return: True, if the connection was successfully established
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -325,50 +332,36 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
|
|
||||||
ssh_tunnel_server = None
|
ssh_tunnel_server = None
|
||||||
ssh_tunnel_port = 0
|
ssh_tunnel_port = 0
|
||||||
ssh_pass = ""
|
|
||||||
|
|
||||||
socket.setdefaulttimeout(2)
|
socket.setdefaulttimeout(revpi_settings.timeout)
|
||||||
|
|
||||||
if revpi_settings.ssh_use_tunnel:
|
if revpi_settings.ssh_use_tunnel:
|
||||||
while True:
|
|
||||||
diag_ssh_auth = SSHAuth(
|
|
||||||
revpi_settings.ssh_user,
|
|
||||||
"{0}.{1}_{2}".format(
|
|
||||||
settings.applicationName(),
|
|
||||||
settings.organizationName(),
|
|
||||||
revpi_settings.internal_id),
|
|
||||||
parent,
|
|
||||||
)
|
|
||||||
if not diag_ssh_auth.exec() == QtWidgets.QDialog.Accepted:
|
|
||||||
self._clear_settings()
|
|
||||||
return False
|
|
||||||
|
|
||||||
ssh_user = diag_ssh_auth.username
|
|
||||||
ssh_pass = diag_ssh_auth.password
|
|
||||||
ssh_tunnel_server = SSHLocalTunnel(
|
ssh_tunnel_server = SSHLocalTunnel(
|
||||||
revpi_settings.port,
|
revpi_settings.port,
|
||||||
revpi_settings.address,
|
revpi_settings.address,
|
||||||
revpi_settings.ssh_port
|
revpi_settings.ssh_port
|
||||||
)
|
)
|
||||||
revpi_settings.ssh_saved_password = diag_ssh_auth.in_keyring
|
|
||||||
try:
|
try:
|
||||||
ssh_tunnel_port = ssh_tunnel_server.connect_by_credentials(ssh_user, ssh_pass)
|
ssh_tunnel_port = ssh_tunnel_server.connect_by_credentials(revpi_settings.ssh_user, ssh_pass)
|
||||||
break
|
|
||||||
except AuthenticationException:
|
except AuthenticationException:
|
||||||
diag_ssh_auth.remove_saved_password()
|
self.connect_error.emit(
|
||||||
QtWidgets.QMessageBox.critical(
|
self.tr("Error"), self.tr(
|
||||||
parent, self.tr("Error"), self.tr(
|
|
||||||
"The combination of username and password was rejected from the SSH server.\n\n"
|
"The combination of username and password was rejected from the SSH server.\n\n"
|
||||||
"Try again."
|
"Try again."
|
||||||
|
),
|
||||||
|
ConnectionFail.SSH_AUTH,
|
||||||
|
revpi_settings,
|
||||||
)
|
)
|
||||||
)
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# todo: Check some more kinds of exceptions and nice user info
|
# todo: Check some more kinds of exceptions and nice user info
|
||||||
self._clear_settings()
|
self._clear_settings()
|
||||||
QtWidgets.QMessageBox.critical(
|
self.connect_error.emit(
|
||||||
parent, self.tr("Error"), self.tr(
|
self.tr("Error"), self.tr(
|
||||||
"Could not establish a SSH connection to server:\n\n{0}"
|
"Could not establish a SSH connection to server:\n\n{0}"
|
||||||
).format(str(e))
|
).format(str(e)),
|
||||||
|
ConnectionFail.SSH_CONNECT,
|
||||||
|
revpi_settings,
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -386,17 +379,30 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
pi.logger.exception(e)
|
pi.logger.exception(e)
|
||||||
self.connection_error_observed.emit(str(e))
|
self.connection_error_observed.emit(str(e))
|
||||||
|
|
||||||
if not revpi_settings.ssh_use_tunnel:
|
if revpi_settings.ssh_use_tunnel:
|
||||||
|
self.connect_error.emit(
|
||||||
|
self.tr("Error"), self.tr(
|
||||||
|
"Can not connect to RevPi XML-RPC Service through SSH tunnel! \n\n"
|
||||||
|
"This could have the following reasons: The XML-RPC service is not "
|
||||||
|
"running / not bind to localhost or the ACL permission is not set for "
|
||||||
|
"127.0.0.1!!!"
|
||||||
|
),
|
||||||
|
ConnectionFail.NO_XML_RPC,
|
||||||
|
revpi_settings,
|
||||||
|
)
|
||||||
|
else:
|
||||||
# todo: Change message, that user can use ssh
|
# todo: Change message, that user can use ssh
|
||||||
QtWidgets.QMessageBox.critical(
|
self.connect_error.emit(
|
||||||
parent, self.tr("Error"), self.tr(
|
self.tr("Error"), self.tr(
|
||||||
"Can not connect to RevPi XML-RPC Service! \n\n"
|
"Can not connect to RevPi XML-RPC Service! \n\n"
|
||||||
"This could have the following reasons: The RevPi is not "
|
"This could have the following reasons: The RevPi is not "
|
||||||
"online, the XML-RPC service is not running / bind to "
|
"online, the XML-RPC service is not running / bind to "
|
||||||
"localhost or the ACL permission is not set for your "
|
"localhost or the ACL permission is not set for your "
|
||||||
"IP!!!\n\nRun 'sudo revpipyload_secure_installation' on "
|
"IP!!!\n\nRun 'sudo revpipyload_secure_installation' on "
|
||||||
"Revolution Pi to setup this function!"
|
"Revolution Pi to setup this function!"
|
||||||
)
|
),
|
||||||
|
ConnectionFail.NO_XML_RPC,
|
||||||
|
revpi_settings,
|
||||||
)
|
)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
@@ -408,7 +414,6 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
self.xml_mode = xml_mode
|
self.xml_mode = xml_mode
|
||||||
|
|
||||||
with self._lck_cli:
|
with self._lck_cli:
|
||||||
socket.setdefaulttimeout(revpi_settings.timeout)
|
|
||||||
self.ssh_tunnel_server = ssh_tunnel_server
|
self.ssh_tunnel_server = ssh_tunnel_server
|
||||||
self._cli = sp
|
self._cli = sp
|
||||||
self._cli_connect.put_nowait((
|
self._cli_connect.put_nowait((
|
||||||
@@ -686,7 +691,8 @@ def import_old_settings():
|
|||||||
revpi_setting = RevPiSettings(i, settings_storage=old_settings)
|
revpi_setting = RevPiSettings(i, settings_storage=old_settings)
|
||||||
revpi_setting._settings = settings
|
revpi_setting._settings = settings
|
||||||
revpi_setting.save_settings()
|
revpi_setting.save_settings()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
pi.logger.warning("Could not import saved connection {0}".format(i))
|
pi.logger.warning("Could not import saved connection {0}".format(i))
|
||||||
|
|
||||||
|
|
||||||
import_old_settings()
|
import_old_settings()
|
||||||
|
|||||||
Binary file not shown.
@@ -93,70 +93,198 @@ Nicht gespeicherte Änderunen gehen verloren</translation>
|
|||||||
<translation type="obsolete">Der ausgewählte RevPi ist schon in der Verbindungsliste als '{0}'.</translation>
|
<translation type="obsolete">Der ausgewählte RevPi ist schon in der Verbindungsliste als '{0}'.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../avahisearch.py" line="283"/>
|
<location filename="../avahisearch.py" line="285"/>
|
||||||
<source> over SSH</source>
|
<source> over SSH</source>
|
||||||
<translation> über SSH</translation>
|
<translation> über SSH</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>ConnectingPyload</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="299"/>
|
||||||
|
<source>Simulator started...</source>
|
||||||
|
<translation type="obsolete">Simulator gestartet...</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="299"/>
|
||||||
|
<source>The simulator is running!
|
||||||
|
|
||||||
|
You can work with this simulator if your call RevPiModIO with this additional parameters:
|
||||||
|
procimg={0}
|
||||||
|
configrsc={1}
|
||||||
|
|
||||||
|
You can copy that from header textbox.</source>
|
||||||
|
<translation type="obsolete">Der Simulator läuft!
|
||||||
|
|
||||||
|
Du kannst mit der Simulation arbeiten, wenn du RevPiModIO mit diesen zusätzlichen Parametern instantiierst:
|
||||||
|
procimg={0}
|
||||||
|
configrsc={1}
|
||||||
|
|
||||||
|
Dies kann aus der Textbox oben kopiert werden.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="308"/>
|
||||||
|
<source>Can not start...</source>
|
||||||
|
<translation type="obsolete">Kann nicht gestartet werden...</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="308"/>
|
||||||
|
<source>Can not start the simulator! Maybe the piCtory file is corrupt or you have no write permissions for '{0}'.</source>
|
||||||
|
<translation type="obsolete">Kann Simulator nicht starten! Vielleicht ist die piCtory Datei defekt oder es gibt keine Schreibberechtigung für '{0}'.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="501"/>
|
||||||
|
<source>Warning</source>
|
||||||
|
<translation type="obsolete">Warnung</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="324"/>
|
||||||
|
<source>This version of Logviewer ist not supported in version {0} of RevPiPyLoad on your RevPi! You need at least version 0.4.1.</source>
|
||||||
|
<translation type="obsolete">Diese Version vom Logbetrachter wird in RevPiPyLoad Version {0} nicht unterstützt! Es wird mindestens Version 0.4.1 benötigt.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="374"/>
|
||||||
|
<source>XML-RPC access mode in the RevPiPyLoad configuration is too small to access this dialog!</source>
|
||||||
|
<translation type="obsolete">XML-RPC Zugriffsberechtigung in der RevPiPyLoad Konfiguraiton ist zu klein für diese Einstellungen!</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="528"/>
|
||||||
|
<source>Error</source>
|
||||||
|
<translation type="obsolete">Fehler</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="354"/>
|
||||||
|
<source>The Version of RevPiPyLoad on your Revolution Pi ({0}) is to old. This Version of RevPiCommander require at least version 0.6.0 of RevPiPyLoad. Please update your Revolution Pi!</source>
|
||||||
|
<translation type="obsolete">Die Version von RevPiPyLoad ({0}) auf dem Revolution Pi ist zu alt. Diese Version vom RevPiCommander braucht mindestens Version 0.6.0. Bitte aktualisiere deinen Revolution Pi!</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="407"/>
|
||||||
|
<source>Question</source>
|
||||||
|
<translation type="obsolete">Frage</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="407"/>
|
||||||
|
<source>Are you sure to reset piControl?
|
||||||
|
The pictory configuration will be reloaded. During that time the process image will be interrupted and could rise errors on running control programs!</source>
|
||||||
|
<translation type="obsolete">Soll piControl wirklich zurückgesetzt werden?
|
||||||
|
Die piCtory Konfiguration wird neu geladen. Das Prozessabbild wird in dieser Zeit nicht verfügbar sein und es könnten Fehler in Steuerungsprogrammen ausgelöst werden!</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="420"/>
|
||||||
|
<source>Success</source>
|
||||||
|
<translation type="obsolete">Erfolgreich</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="420"/>
|
||||||
|
<source>piControl reset executed successfully</source>
|
||||||
|
<translation type="obsolete">piControl wurde erfolgreich zurückgesetzt</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="427"/>
|
||||||
|
<source>piControl reset could not be executed successfully</source>
|
||||||
|
<translation type="obsolete">piControl konnte nicht zurückgesetzt werden</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="475"/>
|
||||||
|
<source>Reset to piCtory defaults...</source>
|
||||||
|
<translation type="obsolete">Standardwerte von piCtory laden...</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="475"/>
|
||||||
|
<source>Do you want to reset your process image to {0} values?
|
||||||
|
You have to stop other RevPiModIO programs before doing that, because they could reset the outputs.</source>
|
||||||
|
<translation type="obsolete">Soll das virtuelle Prozessabbild auf {0} zurückgesetzt werden?
|
||||||
|
Es sollten alle RevPiModIO Programme vorher beendet werden, da diese ihre IO Werte sofort wieder schreiben würden.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="475"/>
|
||||||
|
<source>zero</source>
|
||||||
|
<translation type="obsolete">null</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="475"/>
|
||||||
|
<source>piCtory default</source>
|
||||||
|
<translation type="obsolete">piCtory Standardwerte</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="501"/>
|
||||||
|
<source>The watch mode ist not supported in version {0} of RevPiPyLoad on your RevPi! You need at least version 0.5.3! Maybe the python3-revpimodio2 module is not installed on your RevPi at least version 2.0.0.</source>
|
||||||
|
<translation type="obsolete">Der SPS Betrachter ist in Version {0} von RevPiPyLoad auf dem Rev Pi nicht unterstützt! Es muss mindestens Version 0.5.3 installiert sein! Vielleicht fehlt auch das python3-revpimodio2 Modul, welches mindestens Version 2.0.0 haben muss.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="513"/>
|
||||||
|
<source>Can not load this function, because your ACL level is to low!
|
||||||
|
You need at least level 1 to read or level 3 to write.</source>
|
||||||
|
<translation type="obsolete">Für diese Funktion ist das Berechtigungslevel zu gering!
|
||||||
|
Es muss mindestens Level 1 zum Lesen oder Level 3 zu Schreiben sein.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="528"/>
|
||||||
|
<source>Can not load piCtory configuration.
|
||||||
|
Did you create a hardware configuration? Please check this in piCtory!</source>
|
||||||
|
<translation type="obsolete">Kann piCtory Konfiguration nicht laden.
|
||||||
|
Wurde eine Hardwarekonfiguration in piCtory erzeugt?</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ConnectionManager</name>
|
<name>ConnectionManager</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="512"/>
|
<location filename="../helper.py" line="524"/>
|
||||||
<source>SIMULATING</source>
|
<source>SIMULATING</source>
|
||||||
<translation>SIMULATION</translation>
|
<translation>SIMULATION</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="515"/>
|
<location filename="../helper.py" line="527"/>
|
||||||
<source>NOT CONNECTED</source>
|
<source>NOT CONNECTED</source>
|
||||||
<translation>NICHT VERBUNDEN</translation>
|
<translation>NICHT VERBUNDEN</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="532"/>
|
<location filename="../helper.py" line="544"/>
|
||||||
<source>SERVER ERROR</source>
|
<source>SERVER ERROR</source>
|
||||||
<translation>SERVER FEHLER</translation>
|
<translation>SERVER FEHLER</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="557"/>
|
<location filename="../helper.py" line="569"/>
|
||||||
<source>RUNNING</source>
|
<source>RUNNING</source>
|
||||||
<translation>LÄUFT</translation>
|
<translation>LÄUFT</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="559"/>
|
<location filename="../helper.py" line="571"/>
|
||||||
<source>PLC FILE NOT FOUND</source>
|
<source>PLC FILE NOT FOUND</source>
|
||||||
<translation>SPS PROGRAMM NICHT GEFUNDEN</translation>
|
<translation>SPS PROGRAMM NICHT GEFUNDEN</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="561"/>
|
<location filename="../helper.py" line="573"/>
|
||||||
<source>NOT RUNNING (NO STATUS)</source>
|
<source>NOT RUNNING (NO STATUS)</source>
|
||||||
<translation>LÄUFT NICHT (KEIN STATUS)</translation>
|
<translation>LÄUFT NICHT (KEIN STATUS)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="563"/>
|
<location filename="../helper.py" line="575"/>
|
||||||
<source>PROGRAM KILLED</source>
|
<source>PROGRAM KILLED</source>
|
||||||
<translation>PROGRAMM GETÖTET</translation>
|
<translation>PROGRAMM GETÖTET</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="565"/>
|
<location filename="../helper.py" line="577"/>
|
||||||
<source>PROGRAM TERMED</source>
|
<source>PROGRAM TERMED</source>
|
||||||
<translation>PROGRAMM BEENDET</translation>
|
<translation>PROGRAMM BEENDET</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="567"/>
|
<location filename="../helper.py" line="579"/>
|
||||||
<source>NOT RUNNING</source>
|
<source>NOT RUNNING</source>
|
||||||
<translation>LÄUFT NICHT</translation>
|
<translation>LÄUFT NICHT</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="569"/>
|
<location filename="../helper.py" line="581"/>
|
||||||
<source>FINISHED WITH CODE {0}</source>
|
<source>FINISHED WITH CODE {0}</source>
|
||||||
<translation>BEENDET MIT CODE {0}</translation>
|
<translation>BEENDET MIT CODE {0}</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="384"/>
|
<location filename="../helper.py" line="395"/>
|
||||||
<source>Error</source>
|
<source>Error</source>
|
||||||
<translation>Fehler</translation>
|
<translation>Fehler</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="352"/>
|
<location filename="../helper.py" line="347"/>
|
||||||
<source>The combination of username and password was rejected from the SSH server.
|
<source>The combination of username and password was rejected from the SSH server.
|
||||||
|
|
||||||
Try again.</source>
|
Try again.</source>
|
||||||
@@ -165,7 +293,7 @@ Try again.</source>
|
|||||||
Bitte erneut versuchen.</translation>
|
Bitte erneut versuchen.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="361"/>
|
<location filename="../helper.py" line="359"/>
|
||||||
<source>Could not establish a SSH connection to server:
|
<source>Could not establish a SSH connection to server:
|
||||||
|
|
||||||
{0}</source>
|
{0}</source>
|
||||||
@@ -174,7 +302,7 @@ Bitte erneut versuchen.</translation>
|
|||||||
{0}</translation>
|
{0}</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="384"/>
|
<location filename="../helper.py" line="395"/>
|
||||||
<source>Can not connect to RevPi XML-RPC Service!
|
<source>Can not connect to RevPi XML-RPC Service!
|
||||||
|
|
||||||
This could have the following reasons: The RevPi is not online, the XML-RPC service is not running / bind to localhost or the ACL permission is not set for your IP!!!
|
This could have the following reasons: The RevPi is not online, the XML-RPC service is not running / bind to localhost or the ACL permission is not set for your IP!!!
|
||||||
@@ -186,6 +314,24 @@ Das kann eine der folgenden Ursachen haben: Der Rev Pi ist nicht online, der XML
|
|||||||
|
|
||||||
Führe 'sudo revpipyload_secure_installation' auf dem Revolution Pi aus um diese Funktion zu konfigurieren!</translation>
|
Führe 'sudo revpipyload_secure_installation' auf dem Revolution Pi aus um diese Funktion zu konfigurieren!</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../helper.py" line="383"/>
|
||||||
|
<source>Can not connect to RevPi XML-RPC Service through SSH tunnel!
|
||||||
|
|
||||||
|
This could have the following reasons: The XML-RPC service is not running / bind to localhost or the ACL permission is not set for 127.0.0.1!!!</source>
|
||||||
|
<translation type="obsolete">Kann keine Verbindung zum RevPi XML-RPC Dienst herstellen!
|
||||||
|
|
||||||
|
Das kann eine der folgenden Ursachen haben: Der XML-RPC Dienst läuft nicht / ist nicht an localhost gebunden order die Berechtigungen sind nicht für 127.0.0.1 gesetzt!!!</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../helper.py" line="383"/>
|
||||||
|
<source>Can not connect to RevPi XML-RPC Service through SSH tunnel!
|
||||||
|
|
||||||
|
This could have the following reasons: The XML-RPC service is not running / not bind to localhost or the ACL permission is not set for 127.0.0.1!!!</source>
|
||||||
|
<translation>Kann keine Verbindung zum RevPi XML-RPC Dienst über SSH herstellen!
|
||||||
|
|
||||||
|
Das kann eine der folgenden Ursachen haben: Der XML-RPC Dienst läuft nicht / ist nicht an localhost gebunden order die Berechtigungen sind nicht für 127.0.0.1 gesetzt!!!</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>DebugControl</name>
|
<name>DebugControl</name>
|
||||||
@@ -283,90 +429,90 @@ Ungesicherte Änderungen gehen verloren.</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>RevPiCommander</name>
|
<name>RevPiCommander</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="222"/>
|
<location filename="../revpicommander.py" line="306"/>
|
||||||
<source>Simulator started...</source>
|
<source>Simulator started...</source>
|
||||||
<translation>Simulator gestartet...</translation>
|
<translation>Simulator gestartet...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="231"/>
|
<location filename="../revpicommander.py" line="315"/>
|
||||||
<source>Can not start...</source>
|
<source>Can not start...</source>
|
||||||
<translation>Kann nicht gestartet werden...</translation>
|
<translation>Kann nicht gestartet werden...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="424"/>
|
<location filename="../revpicommander.py" line="508"/>
|
||||||
<source>Warning</source>
|
<source>Warning</source>
|
||||||
<translation>Warnung</translation>
|
<translation>Warnung</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="247"/>
|
<location filename="../revpicommander.py" line="331"/>
|
||||||
<source>This version of Logviewer ist not supported in version {0} of RevPiPyLoad on your RevPi! You need at least version 0.4.1.</source>
|
<source>This version of Logviewer ist not supported in version {0} of RevPiPyLoad on your RevPi! You need at least version 0.4.1.</source>
|
||||||
<translation>Diese Version vom Logbetrachter wird in RevPiPyLoad Version {0} nicht unterstützt! Es wird mindestens Version 0.4.1 benötigt.</translation>
|
<translation>Diese Version vom Logbetrachter wird in RevPiPyLoad Version {0} nicht unterstützt! Es wird mindestens Version 0.4.1 benötigt.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="297"/>
|
<location filename="../revpicommander.py" line="381"/>
|
||||||
<source>XML-RPC access mode in the RevPiPyLoad configuration is too small to access this dialog!</source>
|
<source>XML-RPC access mode in the RevPiPyLoad configuration is too small to access this dialog!</source>
|
||||||
<translation>XML-RPC Zugriffsberechtigung in der RevPiPyLoad Konfiguraiton ist zu klein für diese Einstellungen!</translation>
|
<translation>XML-RPC Zugriffsberechtigung in der RevPiPyLoad Konfiguraiton ist zu klein für diese Einstellungen!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="451"/>
|
<location filename="../revpicommander.py" line="535"/>
|
||||||
<source>Error</source>
|
<source>Error</source>
|
||||||
<translation>Fehler</translation>
|
<translation>Fehler</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="277"/>
|
<location filename="../revpicommander.py" line="361"/>
|
||||||
<source>The Version of RevPiPyLoad on your Revolution Pi ({0}) is to old. This Version of RevPiCommander require at least version 0.6.0 of RevPiPyLoad. Please update your Revolution Pi!</source>
|
<source>The Version of RevPiPyLoad on your Revolution Pi ({0}) is to old. This Version of RevPiCommander require at least version 0.6.0 of RevPiPyLoad. Please update your Revolution Pi!</source>
|
||||||
<translation>Die Version von RevPiPyLoad ({0}) auf dem Revolution Pi ist zu alt. Diese Version vom RevPiCommander braucht mindestens Version 0.6.0. Bitte aktualisiere deinen Revolution Pi!</translation>
|
<translation>Die Version von RevPiPyLoad ({0}) auf dem Revolution Pi ist zu alt. Diese Version vom RevPiCommander braucht mindestens Version 0.6.0. Bitte aktualisiere deinen Revolution Pi!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="330"/>
|
<location filename="../revpicommander.py" line="414"/>
|
||||||
<source>Question</source>
|
<source>Question</source>
|
||||||
<translation>Frage</translation>
|
<translation>Frage</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="330"/>
|
<location filename="../revpicommander.py" line="414"/>
|
||||||
<source>Are you sure to reset piControl?
|
<source>Are you sure to reset piControl?
|
||||||
The pictory configuration will be reloaded. During that time the process image will be interrupted and could rise errors on running control programs!</source>
|
The pictory configuration will be reloaded. During that time the process image will be interrupted and could rise errors on running control programs!</source>
|
||||||
<translation>Soll piControl wirklich zurückgesetzt werden?
|
<translation>Soll piControl wirklich zurückgesetzt werden?
|
||||||
Die piCtory Konfiguration wird neu geladen. Das Prozessabbild wird in dieser Zeit nicht verfügbar sein und es könnten Fehler in Steuerungsprogrammen ausgelöst werden!</translation>
|
Die piCtory Konfiguration wird neu geladen. Das Prozessabbild wird in dieser Zeit nicht verfügbar sein und es könnten Fehler in Steuerungsprogrammen ausgelöst werden!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="343"/>
|
<location filename="../revpicommander.py" line="427"/>
|
||||||
<source>Success</source>
|
<source>Success</source>
|
||||||
<translation>Erfolgreich</translation>
|
<translation>Erfolgreich</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="343"/>
|
<location filename="../revpicommander.py" line="427"/>
|
||||||
<source>piControl reset executed successfully</source>
|
<source>piControl reset executed successfully</source>
|
||||||
<translation>piControl wurde erfolgreich zurückgesetzt</translation>
|
<translation>piControl wurde erfolgreich zurückgesetzt</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="350"/>
|
<location filename="../revpicommander.py" line="434"/>
|
||||||
<source>piControl reset could not be executed successfully</source>
|
<source>piControl reset could not be executed successfully</source>
|
||||||
<translation>piControl konnte nicht zurückgesetzt werden</translation>
|
<translation>piControl konnte nicht zurückgesetzt werden</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="398"/>
|
<location filename="../revpicommander.py" line="482"/>
|
||||||
<source>Reset to piCtory defaults...</source>
|
<source>Reset to piCtory defaults...</source>
|
||||||
<translation>Standardwerte von piCtory laden...</translation>
|
<translation>Standardwerte von piCtory laden...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="424"/>
|
<location filename="../revpicommander.py" line="508"/>
|
||||||
<source>The watch mode ist not supported in version {0} of RevPiPyLoad on your RevPi! You need at least version 0.5.3! Maybe the python3-revpimodio2 module is not installed on your RevPi at least version 2.0.0.</source>
|
<source>The watch mode ist not supported in version {0} of RevPiPyLoad on your RevPi! You need at least version 0.5.3! Maybe the python3-revpimodio2 module is not installed on your RevPi at least version 2.0.0.</source>
|
||||||
<translation>Der SPS Betrachter ist in Version {0} von RevPiPyLoad auf dem Rev Pi nicht unterstützt! Es muss mindestens Version 0.5.3 installiert sein! Vielleicht fehlt auch das python3-revpimodio2 Modul, welches mindestens Version 2.0.0 haben muss.</translation>
|
<translation>Der SPS Betrachter ist in Version {0} von RevPiPyLoad auf dem Rev Pi nicht unterstützt! Es muss mindestens Version 0.5.3 installiert sein! Vielleicht fehlt auch das python3-revpimodio2 Modul, welches mindestens Version 2.0.0 haben muss.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="436"/>
|
<location filename="../revpicommander.py" line="520"/>
|
||||||
<source>Can not load this function, because your ACL level is to low!
|
<source>Can not load this function, because your ACL level is to low!
|
||||||
You need at least level 1 to read or level 3 to write.</source>
|
You need at least level 1 to read or level 3 to write.</source>
|
||||||
<translation>Für diese Funktion ist das Berechtigungslevel zu gering!
|
<translation>Für diese Funktion ist das Berechtigungslevel zu gering!
|
||||||
Es muss mindestens Level 1 zum Lesen oder Level 3 zu Schreiben sein.</translation>
|
Es muss mindestens Level 1 zum Lesen oder Level 3 zu Schreiben sein.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="451"/>
|
<location filename="../revpicommander.py" line="535"/>
|
||||||
<source>Can not load piCtory configuration.
|
<source>Can not load piCtory configuration.
|
||||||
Did you create a hardware configuration? Please check this in piCtory!</source>
|
Did you create a hardware configuration? Please check this in piCtory!</source>
|
||||||
<translation>Kann piCtory Konfiguration nicht laden.
|
<translation>Kann piCtory Konfiguration nicht laden.
|
||||||
Wurde eine Hardwarekonfiguration in piCtory erzeugt?</translation>
|
Wurde eine Hardwarekonfiguration in piCtory erzeugt? Bitte prüfe dies in piCtory!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="101"/>
|
<location filename="../revpicommander.py" line="101"/>
|
||||||
@@ -382,7 +528,7 @@ Das kann eine der folgenden Ursachen haben: Der Rev Pi ist nicht online, der XML
|
|||||||
Führe 'sudo revpipyload_secure_installation' auf dem Revolution Pi aus um diese Funktion zu konfigurieren!</translation>
|
Führe 'sudo revpipyload_secure_installation' auf dem Revolution Pi aus um diese Funktion zu konfigurieren!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="222"/>
|
<location filename="../revpicommander.py" line="306"/>
|
||||||
<source>The simulator is running!
|
<source>The simulator is running!
|
||||||
|
|
||||||
You can work with this simulator if your call RevPiModIO with this additional parameters:
|
You can work with this simulator if your call RevPiModIO with this additional parameters:
|
||||||
@@ -399,27 +545,42 @@ configrsc={1}
|
|||||||
Dies kann aus der Textbox oben kopiert werden.</translation>
|
Dies kann aus der Textbox oben kopiert werden.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="231"/>
|
<location filename="../revpicommander.py" line="315"/>
|
||||||
<source>Can not start the simulator! Maybe the piCtory file is corrupt or you have no write permissions for '{0}'.</source>
|
<source>Can not start the simulator! Maybe the piCtory file is corrupt or you have no write permissions for '{0}'.</source>
|
||||||
<translation>Kann Simulator nicht starten! Vielleicht ist die piCtory Datei defekt oder es gibt keine Schreibberechtigung für '{0}'.</translation>
|
<translation>Kann Simulator nicht starten! Vielleicht ist die piCtory Datei defekt oder es gibt keine Schreibberechtigung für '{0}'.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="398"/>
|
<location filename="../revpicommander.py" line="482"/>
|
||||||
<source>Do you want to reset your process image to {0} values?
|
<source>Do you want to reset your process image to {0} values?
|
||||||
You have to stop other RevPiModIO programs before doing that, because they could reset the outputs.</source>
|
You have to stop other RevPiModIO programs before doing that, because they could reset the outputs.</source>
|
||||||
<translation>Soll das virtuelle Prozessabbild auf {0} zurückgesetzt werden?
|
<translation>Soll das virtuelle Prozessabbild auf {0} zurückgesetzt werden?
|
||||||
Es sollten alle RevPiModIO Programme vorher beendet werden, da diese ihre IO Werte sofort wieder schreiben würden.</translation>
|
Es sollten alle RevPiModIO Programme vorher beendet werden, da diese ihre IO Werte sofort wieder schreiben würden.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="398"/>
|
<location filename="../revpicommander.py" line="482"/>
|
||||||
<source>zero</source>
|
<source>zero</source>
|
||||||
<translation>null</translation>
|
<translation>null</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="398"/>
|
<location filename="../revpicommander.py" line="482"/>
|
||||||
<source>piCtory default</source>
|
<source>piCtory default</source>
|
||||||
<translation>piCtory Standardwerte</translation>
|
<translation>piCtory Standardwerte</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="236"/>
|
||||||
|
<source>Revolution Pi connected!</source>
|
||||||
|
<translation>Revolution Pi verbunden!</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="273"/>
|
||||||
|
<source>Connecting...</source>
|
||||||
|
<translation>Verbinde...</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpicommander.py" line="236"/>
|
||||||
|
<source>Establish a connection to the Revolution Pi...</source>
|
||||||
|
<translation>Baue eine Verbindung zum Revolution Pi auf...</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>RevPiFiles</name>
|
<name>RevPiFiles</name>
|
||||||
@@ -547,6 +708,11 @@ Wählen Sie 'Ja' zum Überschreiben, 'Nein' um nur fehlende
|
|||||||
<source>Choose a local directory first.</source>
|
<source>Choose a local directory first.</source>
|
||||||
<translation>Lokales Verzeichnis wählen.</translation>
|
<translation>Lokales Verzeichnis wählen.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpifiles.py" line="127"/>
|
||||||
|
<source>File transfer...</source>
|
||||||
|
<translation>Dateiübertragung...</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>RevPiInfo</name>
|
<name>RevPiInfo</name>
|
||||||
@@ -668,17 +834,31 @@ Ungesicherte Änderungen gehen verloren.</translation>
|
|||||||
<translation type="obsolete">Neue Verbindung</translation>
|
<translation type="obsolete">Neue Verbindung</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpiplclist.py" line="102"/>
|
<location filename="../revpiplclist.py" line="282"/>
|
||||||
<source>Question</source>
|
<source>Question</source>
|
||||||
<translation>Frage</translation>
|
<translation>Frage</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpiplclist.py" line="102"/>
|
<location filename="../revpiplclist.py" line="121"/>
|
||||||
<source>Do you really want to quit?
|
<source>Do you really want to quit?
|
||||||
Unsaved changes will be lost.</source>
|
Unsaved changes will be lost.</source>
|
||||||
<translation>Soll das Fenster wirklich geschlossen werden?
|
<translation>Soll das Fenster wirklich geschlossen werden?
|
||||||
Ungesicherte Änderungen gehen verloren.</translation>
|
Ungesicherte Änderungen gehen verloren.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpiplclist.py" line="282"/>
|
||||||
|
<source>If you remote this folder, all containing elements will be removed, too.
|
||||||
|
|
||||||
|
Do you want to delete folder and all elements?</source>
|
||||||
|
<translation>Wird dieser Ordner gelöscht, betrifft dies auch alle Elemente im Ordner.
|
||||||
|
|
||||||
|
Wollen sie den Ordner und alle Elemente löschen?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../revpiplclist.py" line="324"/>
|
||||||
|
<source>New folder</source>
|
||||||
|
<translation>Neuer Ordner</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>RevPiProgram</name>
|
<name>RevPiProgram</name>
|
||||||
@@ -955,12 +1135,12 @@ Dies ist kein Fehler, wenn das SPS Startprogramm bereits auf dem Rev Pi ist. Pr
|
|||||||
<context>
|
<context>
|
||||||
<name>SSHAuth</name>
|
<name>SSHAuth</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../sshauth.py" line="49"/>
|
<location filename="../sshauth.py" line="51"/>
|
||||||
<source>Could not save password</source>
|
<source>Could not save password</source>
|
||||||
<translation>Konnte Kennwort nicht speichern</translation>
|
<translation>Konnte Kennwort nicht speichern</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../sshauth.py" line="49"/>
|
<location filename="../sshauth.py" line="51"/>
|
||||||
<source>Could not save password to operating systems password save.
|
<source>Could not save password to operating systems password save.
|
||||||
|
|
||||||
Maybe your operating system does not support saving passwords. This could be due to missing libraries or programs.
|
Maybe your operating system does not support saving passwords. This could be due to missing libraries or programs.
|
||||||
@@ -1049,7 +1229,7 @@ Dies ist kein Fehler von RevPi Commander.</translation>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../../ui_dev/backgroundworker.ui" line="14"/>
|
<location filename="../../../ui_dev/backgroundworker.ui" line="14"/>
|
||||||
<source>File transfer...</source>
|
<source>File transfer...</source>
|
||||||
<translation>Dateiübertragung...</translation>
|
<translation type="obsolete">Dateiübertragung...</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -1684,25 +1864,30 @@ applicable law.
|
|||||||
<translation>SSH Authentifizierung</translation>
|
<translation>SSH Authentifizierung</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../../ui_dev/sshauth.ui" line="26"/>
|
<location filename="../../../ui_dev/sshauth.ui" line="29"/>
|
||||||
<source>SSH username:</source>
|
<source>SSH username:</source>
|
||||||
<translation>SSH Benutzername:</translation>
|
<translation>SSH Benutzername:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../../ui_dev/sshauth.ui" line="33"/>
|
<location filename="../../../ui_dev/sshauth.ui" line="36"/>
|
||||||
<source>SSH password:</source>
|
<source>SSH password:</source>
|
||||||
<translation>SSH Passwort:</translation>
|
<translation>SSH Passwort:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../../ui_dev/sshauth.ui" line="53"/>
|
<location filename="../../../ui_dev/sshauth.ui" line="56"/>
|
||||||
<source>Username and password will be saved in secured operating systems's password storage.</source>
|
<source>Username and password will be saved in secured operating systems's password storage.</source>
|
||||||
<translation>Benutzername und Kennwort werden im Passwortspeicher vom Betriebssystem gesichert.</translation>
|
<translation>Benutzername und Kennwort werden im Passwortspeicher vom Betriebssystem gesichert.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../../ui_dev/sshauth.ui" line="56"/>
|
<location filename="../../../ui_dev/sshauth.ui" line="59"/>
|
||||||
<source>Save username and password</source>
|
<source>Save username and password</source>
|
||||||
<translation>Benutzername und Kennwort merken</translation>
|
<translation>Benutzername und Kennwort merken</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../../../ui_dev/sshauth.ui" line="82"/>
|
||||||
|
<source>Note: The default user for SSH is "pi" which differs from the web configuration. You can find the password on the sticker on the device.</source>
|
||||||
|
<translation>Hinweis: Der Standardbenutzer für SSH ist "pi" dies weicht von der Web-Konfiguration ab. Das Kennwort finden sie auf dem Aufkleber am Gerät.</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>wid_debugcontrol</name>
|
<name>wid_debugcontrol</name>
|
||||||
|
|||||||
@@ -89,11 +89,12 @@ parser.add_argument(
|
|||||||
"-f", "--logfile", dest="logfile",
|
"-f", "--logfile", dest="logfile",
|
||||||
help="Save log entries to this file"
|
help="Save log entries to this file"
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-v", "--verbose", action="count", dest="verbose", default=0,
|
"-v", "--verbose", action="count", dest="verbose", default=0,
|
||||||
help="Switch on verbose logging"
|
help="Switch on verbose logging"
|
||||||
)
|
)
|
||||||
|
# The __main__ script will process the version number argument
|
||||||
|
parser.add_argument("--version", action="store_true", help="Print version number of program and exit")
|
||||||
pargs = parser.parse_args()
|
pargs = parser.parse_args()
|
||||||
|
|
||||||
# Check important objects and set to default if they do not exists
|
# Check important objects and set to default if they do not exists
|
||||||
|
|||||||
@@ -5,28 +5,48 @@
|
|||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2018 Sven Sager"
|
__copyright__ = "Copyright (C) 2018 Sven Sager"
|
||||||
__license__ = "GPLv3"
|
__license__ = "GPLv3"
|
||||||
__version__ = "0.9.10rc2"
|
|
||||||
|
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from os.path import dirname, join
|
from os.path import dirname, join
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
from revpicommander.backgroundworker import BackgroundWaiter
|
||||||
|
from . import __version__
|
||||||
from . import helper
|
from . import helper
|
||||||
from . import proginit as pi
|
from . import proginit as pi
|
||||||
from . import revpilogfile
|
from . import revpilogfile
|
||||||
from .avahisearch import AvahiSearch
|
from .avahisearch import AvahiSearch
|
||||||
from .debugcontrol import DebugControl
|
from .debugcontrol import DebugControl
|
||||||
from .helper import RevPiSettings
|
from .helper import ConnectionFail, RevPiSettings
|
||||||
from .revpifiles import RevPiFiles
|
from .revpifiles import RevPiFiles
|
||||||
from .revpiinfo import RevPiInfo
|
from .revpiinfo import RevPiInfo
|
||||||
from .revpioption import RevPiOption
|
from .revpioption import RevPiOption
|
||||||
from .revpiplclist import RevPiPlcList
|
from .revpiplclist import RevPiPlcList
|
||||||
from .revpiprogram import RevPiProgram
|
from .revpiprogram import RevPiProgram
|
||||||
from .simulator import Simulator
|
from .simulator import Simulator
|
||||||
|
from .sshauth import SSHAuth
|
||||||
from .ui.revpicommander_ui import Ui_win_revpicommander
|
from .ui.revpicommander_ui import Ui_win_revpicommander
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectingPyload(QtCore.QThread):
|
||||||
|
"""
|
||||||
|
Try to establish a connection in background.
|
||||||
|
|
||||||
|
The pyload_connect function will emit signals for error or successful connect. This
|
||||||
|
signals will be used to show error messages and return to this function, if the
|
||||||
|
authentication failed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, revpi_settings: RevPiSettings, ssh_password="", parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self._revpi_settings = revpi_settings
|
||||||
|
self._ssh_password = ssh_password
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
helper.cm.pyload_connect(self._revpi_settings, self._ssh_password)
|
||||||
|
|
||||||
|
|
||||||
class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
|
class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
|
||||||
"""Main application of RevPiCommander."""
|
"""Main application of RevPiCommander."""
|
||||||
|
|
||||||
@@ -56,6 +76,7 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
|
|||||||
|
|
||||||
self.btn_plc_logs.clicked.connect(self.on_act_logs_triggered)
|
self.btn_plc_logs.clicked.connect(self.on_act_logs_triggered)
|
||||||
|
|
||||||
|
helper.cm.connect_error.connect(self.on_cm_connect_error)
|
||||||
helper.cm.connection_disconnected.connect(self.on_cm_connection_disconnected)
|
helper.cm.connection_disconnected.connect(self.on_cm_connection_disconnected)
|
||||||
helper.cm.connection_disconnecting.connect(self.on_cm_connection_disconnecting)
|
helper.cm.connection_disconnecting.connect(self.on_cm_connection_disconnecting)
|
||||||
helper.cm.connection_established.connect(self.on_cm_connection_established)
|
helper.cm.connection_established.connect(self.on_cm_connection_established)
|
||||||
@@ -97,6 +118,21 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
|
|||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# region # REGION: Connection management
|
# region # REGION: Connection management
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(str, str, ConnectionFail, RevPiSettings)
|
||||||
|
def on_cm_connect_error(self, title: str, text: str, fail_code: ConnectionFail, revpi_settings: RevPiSettings):
|
||||||
|
"""
|
||||||
|
Slot to get information of pyload_connect connection errors.
|
||||||
|
|
||||||
|
:param title: Title of error message
|
||||||
|
:param text: Text of error message
|
||||||
|
:param fail_code: Type of error
|
||||||
|
:param revpi_settings: Settings of the revpi with the error
|
||||||
|
"""
|
||||||
|
QtWidgets.QMessageBox.critical(self, title, text)
|
||||||
|
if fail_code is ConnectionFail.SSH_AUTH:
|
||||||
|
# On failed credentials, we try to connect again and remove password form keychain, if exists
|
||||||
|
self._pyload_connect(revpi_settings, True)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(str)
|
@QtCore.pyqtSlot(str)
|
||||||
def on_cm_connection_error_observed(self, message: str):
|
def on_cm_connection_error_observed(self, message: str):
|
||||||
"""
|
"""
|
||||||
@@ -188,6 +224,54 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
|
|||||||
act.setToolTip("{0}:{1}".format(settings.address, settings.port))
|
act.setToolTip("{0}:{1}".format(settings.address, settings.port))
|
||||||
parent_menu.addAction(act)
|
parent_menu.addAction(act)
|
||||||
|
|
||||||
|
def _pyload_connect(self, revpi_settings: RevPiSettings, remove_saved_ssh_password=False):
|
||||||
|
"""
|
||||||
|
Try to async establish a connection to Revolution Pi.
|
||||||
|
|
||||||
|
:param revpi_settings: RevPi settings object
|
||||||
|
:param remove_saved_ssh_password: Remove password from keychain
|
||||||
|
"""
|
||||||
|
ssh_password = ""
|
||||||
|
|
||||||
|
diag_connecting = BackgroundWaiter(
|
||||||
|
revpi_settings.timeout,
|
||||||
|
self.tr("Establish a connection to the Revolution Pi..."),
|
||||||
|
self,
|
||||||
|
self.tr("Revolution Pi connected!"),
|
||||||
|
)
|
||||||
|
helper.cm.connection_established.connect(diag_connecting.requestInterruption)
|
||||||
|
|
||||||
|
if revpi_settings.ssh_use_tunnel:
|
||||||
|
diag_ssh_auth = SSHAuth(
|
||||||
|
revpi_settings.ssh_user,
|
||||||
|
"{0}.{1}_{2}".format(
|
||||||
|
helper.settings.applicationName(),
|
||||||
|
helper.settings.organizationName(),
|
||||||
|
revpi_settings.internal_id),
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
|
||||||
|
if remove_saved_ssh_password and revpi_settings.ssh_saved_password:
|
||||||
|
diag_ssh_auth.remove_saved_password()
|
||||||
|
revpi_settings.ssh_saved_password = False
|
||||||
|
|
||||||
|
# Doesn't matter what user selects, we have to save settings to sync keychain and values
|
||||||
|
if diag_ssh_auth.exec() != QtWidgets.QDialog.Accepted:
|
||||||
|
revpi_settings.save_settings()
|
||||||
|
return
|
||||||
|
|
||||||
|
revpi_settings.ssh_saved_password = diag_ssh_auth.in_keyring
|
||||||
|
revpi_settings.ssh_user = diag_ssh_auth.username
|
||||||
|
ssh_password = diag_ssh_auth.password
|
||||||
|
revpi_settings.save_settings()
|
||||||
|
|
||||||
|
# Connect in background and show the connecting dialog to user
|
||||||
|
th_connecting = ConnectingPyload(revpi_settings, ssh_password, self)
|
||||||
|
th_connecting.finished.connect(diag_connecting.requestInterruption)
|
||||||
|
th_connecting.start()
|
||||||
|
|
||||||
|
diag_connecting.exec_dialog(self.tr("Connecting..."), False)
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def on_act_connections_triggered(self):
|
def on_act_connections_triggered(self):
|
||||||
"""Edit saved connections to Revolution Pi devices."""
|
"""Edit saved connections to Revolution Pi devices."""
|
||||||
@@ -202,7 +286,7 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
|
|||||||
if self.diag_search.just_save:
|
if self.diag_search.just_save:
|
||||||
self.diag_connections.exec_with_presets(self.diag_search.connect_settings)
|
self.diag_connections.exec_with_presets(self.diag_search.connect_settings)
|
||||||
else:
|
else:
|
||||||
helper.cm.pyload_connect(self.diag_search.connect_settings, self)
|
self._pyload_connect(self.diag_search.connect_settings)
|
||||||
|
|
||||||
self._load_men_connections()
|
self._load_men_connections()
|
||||||
|
|
||||||
@@ -361,7 +445,7 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
|
|||||||
@QtCore.pyqtSlot(QtWidgets.QAction)
|
@QtCore.pyqtSlot(QtWidgets.QAction)
|
||||||
def on_men_connections_triggered(self, action: QtWidgets.QAction):
|
def on_men_connections_triggered(self, action: QtWidgets.QAction):
|
||||||
"""A connection is selected in the men_connections menu."""
|
"""A connection is selected in the men_connections menu."""
|
||||||
helper.cm.pyload_connect(action.data(), self)
|
self._pyload_connect(action.data())
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def on_act_webpage_triggered(self):
|
def on_act_webpage_triggered(self):
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ class RevPiFiles(QtWidgets.QMainWindow, Ui_win_files):
|
|||||||
return
|
return
|
||||||
|
|
||||||
uploader = UploadFiles(self.file_list_local(), self)
|
uploader = UploadFiles(self.file_list_local(), self)
|
||||||
if uploader.exec_dialog() == QtWidgets.QDialog.Rejected:
|
if uploader.exec_dialog(self.tr("File transfer...")) == QtWidgets.QDialog.Rejected:
|
||||||
return
|
return
|
||||||
|
|
||||||
if uploader.ec == 0:
|
if uploader.ec == 0:
|
||||||
|
|||||||
@@ -37,13 +37,30 @@ class RevPiPlcList(QtWidgets.QDialog, Ui_diag_connections):
|
|||||||
self.lbl_port.setText(self.lbl_port.text().format(self.__default_port))
|
self.lbl_port.setText(self.lbl_port.text().format(self.__default_port))
|
||||||
self.sbx_port.setValue(self.__default_port)
|
self.sbx_port.setValue(self.__default_port)
|
||||||
|
|
||||||
|
# Dirty workaround to remove default button to prevent action on ENTER key, while user edit texts
|
||||||
|
self.__btn_dummy = QtWidgets.QPushButton(self)
|
||||||
|
self.__btn_dummy.setVisible(False)
|
||||||
|
self.__btn_dummy.setDefault(True)
|
||||||
|
|
||||||
|
def _load_cbb_folder(self):
|
||||||
|
"""Clean up all entries and reload existing ones from treeview."""
|
||||||
|
self.cbb_folder.blockSignals(True)
|
||||||
|
|
||||||
|
self.cbb_folder.clear()
|
||||||
|
self.cbb_folder.addItem("")
|
||||||
|
for i in range(self.tre_connections.topLevelItemCount()):
|
||||||
|
item = self.tre_connections.topLevelItem(i)
|
||||||
|
if item.type() != NodeType.DIR:
|
||||||
|
continue
|
||||||
|
self.cbb_folder.addItem(item.text(0))
|
||||||
|
|
||||||
|
self.cbb_folder.blockSignals(False)
|
||||||
|
|
||||||
def _load_settings(self):
|
def _load_settings(self):
|
||||||
"""Load values to GUI widgets."""
|
"""Load values to GUI widgets."""
|
||||||
pi.logger.debug("RevPiPlcList._load_settings")
|
pi.logger.debug("RevPiPlcList._load_settings")
|
||||||
|
|
||||||
self.tre_connections.clear()
|
self.tre_connections.clear()
|
||||||
self.cbb_folder.clear()
|
|
||||||
self.cbb_folder.addItem("")
|
|
||||||
|
|
||||||
# Get length of array and close it, the RevPiSettings-class need it
|
# Get length of array and close it, the RevPiSettings-class need it
|
||||||
count_settings = helper.settings.beginReadArray("connections")
|
count_settings = helper.settings.beginReadArray("connections")
|
||||||
@@ -67,7 +84,6 @@ class RevPiPlcList(QtWidgets.QDialog, Ui_diag_connections):
|
|||||||
sub_folder.setIcon(0, QtGui.QIcon(":/main/ico/folder.ico"))
|
sub_folder.setIcon(0, QtGui.QIcon(":/main/ico/folder.ico"))
|
||||||
sub_folder.setText(0, folder)
|
sub_folder.setText(0, folder)
|
||||||
self.tre_connections.addTopLevelItem(sub_folder)
|
self.tre_connections.addTopLevelItem(sub_folder)
|
||||||
self.cbb_folder.addItem(folder)
|
|
||||||
|
|
||||||
sub_folder.addChild(con_item)
|
sub_folder.addChild(con_item)
|
||||||
else:
|
else:
|
||||||
@@ -76,7 +92,6 @@ class RevPiPlcList(QtWidgets.QDialog, Ui_diag_connections):
|
|||||||
self.tre_connections.expandAll()
|
self.tre_connections.expandAll()
|
||||||
self.changes = False
|
self.changes = False
|
||||||
|
|
||||||
if self.tre_connections.topLevelItemCount() == 0:
|
|
||||||
self._edit_state()
|
self._edit_state()
|
||||||
|
|
||||||
def accept(self) -> None:
|
def accept(self) -> None:
|
||||||
@@ -150,6 +165,8 @@ class RevPiPlcList(QtWidgets.QDialog, Ui_diag_connections):
|
|||||||
|
|
||||||
def _edit_state(self):
|
def _edit_state(self):
|
||||||
"""Set enabled status of all controls, depending on selected item."""
|
"""Set enabled status of all controls, depending on selected item."""
|
||||||
|
pi.logger.debug("RevPiPlcList._edit_state")
|
||||||
|
|
||||||
item = self.tre_connections.currentItem()
|
item = self.tre_connections.currentItem()
|
||||||
if item is None:
|
if item is None:
|
||||||
up_ok = False
|
up_ok = False
|
||||||
@@ -171,12 +188,16 @@ class RevPiPlcList(QtWidgets.QDialog, Ui_diag_connections):
|
|||||||
|
|
||||||
self.btn_up.setEnabled(up_ok)
|
self.btn_up.setEnabled(up_ok)
|
||||||
self.btn_down.setEnabled(down_ok)
|
self.btn_down.setEnabled(down_ok)
|
||||||
self.btn_delete.setEnabled(con_item)
|
self.btn_delete.setEnabled(con_item or dir_item)
|
||||||
self.txt_name.setEnabled(con_item)
|
self.txt_name.setEnabled(con_item)
|
||||||
self.txt_address.setEnabled(con_item)
|
self.txt_address.setEnabled(con_item)
|
||||||
self.sbx_port.setEnabled(con_item)
|
self.sbx_port.setEnabled(con_item)
|
||||||
self.sbx_timeout.setEnabled(con_item)
|
self.sbx_timeout.setEnabled(con_item)
|
||||||
self.cbb_folder.setEnabled(con_item or dir_item)
|
self.cbb_folder.setEnabled(con_item or dir_item)
|
||||||
|
self.cbb_folder.setEditable(dir_item)
|
||||||
|
if self.cbb_folder.isEditable():
|
||||||
|
# Disable auto complete, this would override a new typed name with existing one
|
||||||
|
self.cbb_folder.setCompleter(None)
|
||||||
|
|
||||||
self.cbx_ssh_use_tunnel.setEnabled(con_item)
|
self.cbx_ssh_use_tunnel.setEnabled(con_item)
|
||||||
self.sbx_ssh_port.setEnabled(con_item)
|
self.sbx_ssh_port.setEnabled(con_item)
|
||||||
@@ -203,22 +224,25 @@ class RevPiPlcList(QtWidgets.QDialog, Ui_diag_connections):
|
|||||||
if 0 <= new_index < dir_item.childCount():
|
if 0 <= new_index < dir_item.childCount():
|
||||||
item = dir_item.takeChild(index)
|
item = dir_item.takeChild(index)
|
||||||
dir_item.insertChild(new_index, item)
|
dir_item.insertChild(new_index, item)
|
||||||
self.tre_connections.expandItem(dir_item)
|
|
||||||
else:
|
else:
|
||||||
index = self.tre_connections.indexOfTopLevelItem(item)
|
index = self.tre_connections.indexOfTopLevelItem(item)
|
||||||
new_index = index + count
|
new_index = index + count
|
||||||
if 0 <= index < self.tre_connections.topLevelItemCount():
|
if 0 <= index < self.tre_connections.topLevelItemCount():
|
||||||
item = self.tre_connections.takeTopLevelItem(index)
|
item = self.tre_connections.takeTopLevelItem(index)
|
||||||
self.tre_connections.insertTopLevelItem(new_index, item)
|
self.tre_connections.insertTopLevelItem(new_index, item)
|
||||||
|
if item.type() == NodeType.DIR:
|
||||||
|
# Expand a moved dir node, it would be collapsed after move
|
||||||
|
self.tre_connections.expandItem(item)
|
||||||
|
|
||||||
self.tre_connections.setCurrentItem(item)
|
self.tre_connections.setCurrentItem(item)
|
||||||
self._edit_state()
|
|
||||||
|
|
||||||
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem, QtWidgets.QTreeWidgetItem)
|
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem, QtWidgets.QTreeWidgetItem)
|
||||||
def on_tre_connections_currentItemChanged(
|
def on_tre_connections_currentItemChanged(
|
||||||
self, current: QtWidgets.QTreeWidgetItem, previous: QtWidgets.QTreeWidgetItem):
|
self, current: QtWidgets.QTreeWidgetItem, previous: QtWidgets.QTreeWidgetItem):
|
||||||
|
|
||||||
self._edit_state()
|
self._edit_state()
|
||||||
|
self._load_cbb_folder()
|
||||||
|
|
||||||
if current and current.type() == NodeType.CON:
|
if current and current.type() == NodeType.CON:
|
||||||
self.__current_item = current
|
self.__current_item = current
|
||||||
|
|
||||||
@@ -255,9 +279,9 @@ class RevPiPlcList(QtWidgets.QDialog, Ui_diag_connections):
|
|||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def on_btn_delete_clicked(self):
|
def on_btn_delete_clicked(self):
|
||||||
"""Remove selected entry."""
|
"""Remove selected entry."""
|
||||||
item = self.tre_connections.currentItem()
|
|
||||||
if item and item.type() == NodeType.CON:
|
|
||||||
|
|
||||||
|
def remove_item(item: QtWidgets.QTreeWidgetItem):
|
||||||
|
"""Remove CON item and save keyring actions for save action."""
|
||||||
revpi_settings = item.data(0, WidgetData.revpi_settings) # type: RevPiSettings
|
revpi_settings = item.data(0, WidgetData.revpi_settings) # type: RevPiSettings
|
||||||
if revpi_settings.ssh_saved_password:
|
if revpi_settings.ssh_saved_password:
|
||||||
# Cleans up keyring in save function
|
# Cleans up keyring in save function
|
||||||
@@ -270,7 +294,27 @@ class RevPiPlcList(QtWidgets.QDialog, Ui_diag_connections):
|
|||||||
index = self.tre_connections.indexOfTopLevelItem(item)
|
index = self.tre_connections.indexOfTopLevelItem(item)
|
||||||
self.tre_connections.takeTopLevelItem(index)
|
self.tre_connections.takeTopLevelItem(index)
|
||||||
|
|
||||||
self._edit_state()
|
item_to_remove = self.tre_connections.currentItem()
|
||||||
|
|
||||||
|
if item_to_remove and item_to_remove.type() == NodeType.DIR:
|
||||||
|
if item_to_remove.childCount():
|
||||||
|
rc = QtWidgets.QMessageBox.question(
|
||||||
|
self, self.tr("Question"), self.tr(
|
||||||
|
"If you remote this folder, all containing elements will be removed, too. \n\n"
|
||||||
|
"Do you want to delete folder and all elements?"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if rc != QtWidgets.QMessageBox.Yes:
|
||||||
|
return
|
||||||
|
|
||||||
|
while item_to_remove.childCount() > 0:
|
||||||
|
remove_item(item_to_remove.child(0))
|
||||||
|
|
||||||
|
item_index = self.tre_connections.indexOfTopLevelItem(item_to_remove)
|
||||||
|
self.tre_connections.takeTopLevelItem(item_index)
|
||||||
|
|
||||||
|
elif item_to_remove and item_to_remove.type() == NodeType.CON:
|
||||||
|
remove_item(item_to_remove)
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def on_btn_add_clicked(self, settings_preset: RevPiSettings = None):
|
def on_btn_add_clicked(self, settings_preset: RevPiSettings = None):
|
||||||
@@ -291,6 +335,20 @@ class RevPiPlcList(QtWidgets.QDialog, Ui_diag_connections):
|
|||||||
self.txt_name.setFocus()
|
self.txt_name.setFocus()
|
||||||
self.txt_name.selectAll()
|
self.txt_name.selectAll()
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot()
|
||||||
|
def on_btn_add_dir_clicked(self):
|
||||||
|
"""Add a new folder."""
|
||||||
|
folder_text = self.tr("New folder")
|
||||||
|
sub_folder = QtWidgets.QTreeWidgetItem(NodeType.DIR)
|
||||||
|
sub_folder.setIcon(0, QtGui.QIcon(":/main/ico/folder.ico"))
|
||||||
|
sub_folder.setText(0, folder_text)
|
||||||
|
|
||||||
|
self.tre_connections.addTopLevelItem(sub_folder)
|
||||||
|
self.tre_connections.setCurrentItem(sub_folder)
|
||||||
|
self.cbb_folder.setFocus()
|
||||||
|
|
||||||
|
self.changes = True
|
||||||
|
|
||||||
@QtCore.pyqtSlot(str)
|
@QtCore.pyqtSlot(str)
|
||||||
def on_txt_name_textEdited(self, text):
|
def on_txt_name_textEdited(self, text):
|
||||||
if self.__current_item.type() != NodeType.CON:
|
if self.__current_item.type() != NodeType.CON:
|
||||||
@@ -349,65 +407,47 @@ class RevPiPlcList(QtWidgets.QDialog, Ui_diag_connections):
|
|||||||
settings.ssh_user = text
|
settings.ssh_user = text
|
||||||
self.changes = True
|
self.changes = True
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(str)
|
||||||
|
def on_cbb_folder_currentIndexChanged(self, text: str):
|
||||||
|
pi.logger.debug("RevPiPlcList.on_cbb_folder_currentIndexChanged({0})".format(text))
|
||||||
|
|
||||||
|
if self.__current_item.type() == NodeType.CON:
|
||||||
|
new_dir_node = self._get_folder_item(text)
|
||||||
|
current_dir_node = self.__current_item.parent()
|
||||||
|
if current_dir_node == new_dir_node:
|
||||||
|
# No change required, both nodes are the same
|
||||||
|
return
|
||||||
|
|
||||||
|
change_item = self.__current_item
|
||||||
|
self.tre_connections.blockSignals(True)
|
||||||
|
self.changes = True
|
||||||
|
|
||||||
|
if current_dir_node:
|
||||||
|
# Move an element to other folder or root
|
||||||
|
index = current_dir_node.indexOfChild(change_item)
|
||||||
|
change_item = current_dir_node.takeChild(index)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Move a root element to a folder
|
||||||
|
index = self.tre_connections.indexOfTopLevelItem(change_item)
|
||||||
|
change_item = self.tre_connections.takeTopLevelItem(index)
|
||||||
|
|
||||||
|
if text == "":
|
||||||
|
self.tre_connections.addTopLevelItem(change_item)
|
||||||
|
|
||||||
|
else:
|
||||||
|
new_dir_node.addChild(change_item)
|
||||||
|
|
||||||
|
self.tre_connections.blockSignals(False)
|
||||||
|
self.tre_connections.setCurrentItem(change_item)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(str)
|
@QtCore.pyqtSlot(str)
|
||||||
def on_cbb_folder_editTextChanged(self, text: str):
|
def on_cbb_folder_editTextChanged(self, text: str):
|
||||||
pi.logger.debug("RevPiPlcList.on_cbb_folder_editTextChanged({0})".format(text))
|
pi.logger.debug("RevPiPlcList.on_cbb_folder_editTextChanged({0})".format(text))
|
||||||
|
|
||||||
if self.__current_item.type() == NodeType.DIR:
|
if self.__current_item.type() == NodeType.DIR and self.__current_item.text(0) != text:
|
||||||
# We just have to rename the dir node
|
# We just have to rename the dir node
|
||||||
self.__current_item.setText(0, text)
|
self.__current_item.setText(0, text)
|
||||||
|
self.changes = True
|
||||||
elif self.__current_item.type() == NodeType.CON:
|
|
||||||
sub_folder = self._get_folder_item(text)
|
|
||||||
dir_node = self.__current_item.parent()
|
|
||||||
if dir_node:
|
|
||||||
if dir_node.text(0) == text:
|
|
||||||
# It is the same folder
|
|
||||||
return
|
|
||||||
|
|
||||||
if text != "" and dir_node.childCount() == 1 and not sub_folder:
|
|
||||||
# The folder hold just one item, so we can rename that
|
|
||||||
for i in range(self.cbb_folder.count()):
|
|
||||||
if self.cbb_folder.itemText(i) == dir_node.text(0):
|
|
||||||
self.cbb_folder.setItemText(i, text)
|
|
||||||
break
|
|
||||||
dir_node.setText(0, text)
|
|
||||||
return
|
|
||||||
|
|
||||||
index = dir_node.indexOfChild(self.__current_item)
|
|
||||||
self.__current_item = dir_node.takeChild(index)
|
|
||||||
|
|
||||||
elif text != "":
|
|
||||||
# Move root to folder
|
|
||||||
index = self.tre_connections.indexOfTopLevelItem(self.__current_item)
|
|
||||||
self.__current_item = self.tre_connections.takeTopLevelItem(index)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Root stays root
|
|
||||||
return
|
|
||||||
|
|
||||||
if text == "":
|
|
||||||
self.tre_connections.addTopLevelItem(self.__current_item)
|
|
||||||
|
|
||||||
else:
|
|
||||||
if sub_folder is None:
|
|
||||||
sub_folder = QtWidgets.QTreeWidgetItem(NodeType.DIR)
|
|
||||||
sub_folder.setIcon(0, QtGui.QIcon(":/main/ico/folder.ico"))
|
|
||||||
sub_folder.setText(0, text)
|
|
||||||
self.tre_connections.addTopLevelItem(sub_folder)
|
|
||||||
self.cbb_folder.addItem(text)
|
|
||||||
sub_folder.addChild(self.__current_item)
|
|
||||||
|
|
||||||
if dir_node and dir_node.childCount() == 0:
|
|
||||||
# Remove empty folders
|
|
||||||
for i in range(self.cbb_folder.count()):
|
|
||||||
if self.cbb_folder.itemText(i) == dir_node.text(0):
|
|
||||||
self.cbb_folder.removeItem(i)
|
|
||||||
break
|
|
||||||
index = self.tre_connections.indexOfTopLevelItem(dir_node)
|
|
||||||
self.tre_connections.takeTopLevelItem(index)
|
|
||||||
|
|
||||||
self.tre_connections.setCurrentItem(self.__current_item)
|
|
||||||
self.cbb_folder.setFocus()
|
|
||||||
|
|
||||||
# endregion # # # # #
|
# endregion # # # # #
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||||||
class Ui_diag_backgroundworker(object):
|
class Ui_diag_backgroundworker(object):
|
||||||
def setupUi(self, diag_backgroundworker):
|
def setupUi(self, diag_backgroundworker):
|
||||||
diag_backgroundworker.setObjectName("diag_backgroundworker")
|
diag_backgroundworker.setObjectName("diag_backgroundworker")
|
||||||
diag_backgroundworker.resize(418, 97)
|
diag_backgroundworker.resize(424, 104)
|
||||||
diag_backgroundworker.setModal(True)
|
diag_backgroundworker.setModal(True)
|
||||||
self.verticalLayout = QtWidgets.QVBoxLayout(diag_backgroundworker)
|
self.verticalLayout = QtWidgets.QVBoxLayout(diag_backgroundworker)
|
||||||
self.verticalLayout.setObjectName("verticalLayout")
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
@@ -37,8 +37,7 @@ class Ui_diag_backgroundworker(object):
|
|||||||
QtCore.QMetaObject.connectSlotsByName(diag_backgroundworker)
|
QtCore.QMetaObject.connectSlotsByName(diag_backgroundworker)
|
||||||
|
|
||||||
def retranslateUi(self, diag_backgroundworker):
|
def retranslateUi(self, diag_backgroundworker):
|
||||||
_translate = QtCore.QCoreApplication.translate
|
pass
|
||||||
diag_backgroundworker.setWindowTitle(_translate("diag_backgroundworker", "File transfer..."))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -67,6 +67,7 @@ class Ui_diag_connections(object):
|
|||||||
self.formLayout_2.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.lbl_folder)
|
self.formLayout_2.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.lbl_folder)
|
||||||
self.cbb_folder = QtWidgets.QComboBox(self.tab_connection)
|
self.cbb_folder = QtWidgets.QComboBox(self.tab_connection)
|
||||||
self.cbb_folder.setEditable(True)
|
self.cbb_folder.setEditable(True)
|
||||||
|
self.cbb_folder.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
|
||||||
self.cbb_folder.setObjectName("cbb_folder")
|
self.cbb_folder.setObjectName("cbb_folder")
|
||||||
self.cbb_folder.addItem("")
|
self.cbb_folder.addItem("")
|
||||||
self.cbb_folder.setItemText(0, "")
|
self.cbb_folder.setItemText(0, "")
|
||||||
@@ -115,39 +116,41 @@ class Ui_diag_connections(object):
|
|||||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
self.vl_edit.addItem(spacerItem)
|
self.vl_edit.addItem(spacerItem)
|
||||||
self.btn_up = QtWidgets.QPushButton(diag_connections)
|
self.btn_up = QtWidgets.QPushButton(diag_connections)
|
||||||
self.btn_up.setText("")
|
|
||||||
icon = QtGui.QIcon()
|
icon = QtGui.QIcon()
|
||||||
icon.addPixmap(QtGui.QPixmap(":/action/ico/arrow-up.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
icon.addPixmap(QtGui.QPixmap(":/action/ico/arrow-up.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
self.btn_up.setIcon(icon)
|
self.btn_up.setIcon(icon)
|
||||||
self.btn_up.setObjectName("btn_up")
|
self.btn_up.setObjectName("btn_up")
|
||||||
self.vl_edit.addWidget(self.btn_up)
|
self.vl_edit.addWidget(self.btn_up)
|
||||||
self.btn_down = QtWidgets.QPushButton(diag_connections)
|
self.btn_down = QtWidgets.QPushButton(diag_connections)
|
||||||
self.btn_down.setText("")
|
|
||||||
icon1 = QtGui.QIcon()
|
icon1 = QtGui.QIcon()
|
||||||
icon1.addPixmap(QtGui.QPixmap(":/action/ico/arrow-down.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
icon1.addPixmap(QtGui.QPixmap(":/action/ico/arrow-down.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
self.btn_down.setIcon(icon1)
|
self.btn_down.setIcon(icon1)
|
||||||
self.btn_down.setObjectName("btn_down")
|
self.btn_down.setObjectName("btn_down")
|
||||||
self.vl_edit.addWidget(self.btn_down)
|
self.vl_edit.addWidget(self.btn_down)
|
||||||
self.btn_delete = QtWidgets.QPushButton(diag_connections)
|
self.btn_delete = QtWidgets.QPushButton(diag_connections)
|
||||||
self.btn_delete.setText("")
|
|
||||||
icon2 = QtGui.QIcon()
|
icon2 = QtGui.QIcon()
|
||||||
icon2.addPixmap(QtGui.QPixmap(":/action/ico/edit-delete.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
icon2.addPixmap(QtGui.QPixmap(":/action/ico/edit-delete-6.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
self.btn_delete.setIcon(icon2)
|
self.btn_delete.setIcon(icon2)
|
||||||
self.btn_delete.setObjectName("btn_delete")
|
self.btn_delete.setObjectName("btn_delete")
|
||||||
self.vl_edit.addWidget(self.btn_delete)
|
self.vl_edit.addWidget(self.btn_delete)
|
||||||
self.btn_add = QtWidgets.QPushButton(diag_connections)
|
self.btn_add_dir = QtWidgets.QPushButton(diag_connections)
|
||||||
self.btn_add.setText("")
|
|
||||||
icon3 = QtGui.QIcon()
|
icon3 = QtGui.QIcon()
|
||||||
icon3.addPixmap(QtGui.QPixmap(":/action/ico/edit-add.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
icon3.addPixmap(QtGui.QPixmap(":/action/ico/folder-open.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
self.btn_add.setIcon(icon3)
|
self.btn_add_dir.setIcon(icon3)
|
||||||
|
self.btn_add_dir.setObjectName("btn_add_dir")
|
||||||
|
self.vl_edit.addWidget(self.btn_add_dir)
|
||||||
|
self.btn_add = QtWidgets.QPushButton(diag_connections)
|
||||||
|
icon4 = QtGui.QIcon()
|
||||||
|
icon4.addPixmap(QtGui.QPixmap(":/action/ico/edit-add.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.btn_add.setIcon(icon4)
|
||||||
self.btn_add.setObjectName("btn_add")
|
self.btn_add.setObjectName("btn_add")
|
||||||
self.vl_edit.addWidget(self.btn_add)
|
self.vl_edit.addWidget(self.btn_add)
|
||||||
self.gridLayout.addLayout(self.vl_edit, 0, 1, 1, 1)
|
self.gridLayout.addLayout(self.vl_edit, 0, 1, 1, 1)
|
||||||
|
|
||||||
self.retranslateUi(diag_connections)
|
self.retranslateUi(diag_connections)
|
||||||
self.tab_properties.setCurrentIndex(0)
|
self.tab_properties.setCurrentIndex(0)
|
||||||
self.btn_box.accepted.connect(diag_connections.accept) # type: ignore
|
|
||||||
self.btn_box.rejected.connect(diag_connections.reject) # type: ignore
|
self.btn_box.rejected.connect(diag_connections.reject) # type: ignore
|
||||||
|
self.btn_box.accepted.connect(diag_connections.accept) # type: ignore
|
||||||
QtCore.QMetaObject.connectSlotsByName(diag_connections)
|
QtCore.QMetaObject.connectSlotsByName(diag_connections)
|
||||||
|
|
||||||
def retranslateUi(self, diag_connections):
|
def retranslateUi(self, diag_connections):
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ class Ui_diag_sshauth(object):
|
|||||||
def setupUi(self, diag_sshauth):
|
def setupUi(self, diag_sshauth):
|
||||||
diag_sshauth.setObjectName("diag_sshauth")
|
diag_sshauth.setObjectName("diag_sshauth")
|
||||||
diag_sshauth.setWindowModality(QtCore.Qt.ApplicationModal)
|
diag_sshauth.setWindowModality(QtCore.Qt.ApplicationModal)
|
||||||
diag_sshauth.resize(363, 163)
|
diag_sshauth.resize(331, 225)
|
||||||
self.verticalLayout = QtWidgets.QVBoxLayout(diag_sshauth)
|
self.verticalLayout = QtWidgets.QVBoxLayout(diag_sshauth)
|
||||||
|
self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
|
||||||
self.verticalLayout.setObjectName("verticalLayout")
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
self.wid_password = QtWidgets.QWidget(diag_sshauth)
|
self.wid_password = QtWidgets.QWidget(diag_sshauth)
|
||||||
self.wid_password.setObjectName("wid_password")
|
self.wid_password.setObjectName("wid_password")
|
||||||
@@ -44,6 +45,16 @@ class Ui_diag_sshauth(object):
|
|||||||
self.btn_box.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
self.btn_box.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||||
self.btn_box.setObjectName("btn_box")
|
self.btn_box.setObjectName("btn_box")
|
||||||
self.verticalLayout.addWidget(self.btn_box)
|
self.verticalLayout.addWidget(self.btn_box)
|
||||||
|
self.lbl_info = QtWidgets.QLabel(diag_sshauth)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.lbl_info.sizePolicy().hasHeightForWidth())
|
||||||
|
self.lbl_info.setSizePolicy(sizePolicy)
|
||||||
|
self.lbl_info.setWordWrap(True)
|
||||||
|
self.lbl_info.setObjectName("lbl_info")
|
||||||
|
self.verticalLayout.addWidget(self.lbl_info)
|
||||||
|
self.verticalLayout.setStretch(3, 1)
|
||||||
|
|
||||||
self.retranslateUi(diag_sshauth)
|
self.retranslateUi(diag_sshauth)
|
||||||
self.btn_box.accepted.connect(diag_sshauth.accept) # type: ignore
|
self.btn_box.accepted.connect(diag_sshauth.accept) # type: ignore
|
||||||
@@ -57,6 +68,7 @@ class Ui_diag_sshauth(object):
|
|||||||
self.lbl_password.setText(_translate("diag_sshauth", "SSH password:"))
|
self.lbl_password.setText(_translate("diag_sshauth", "SSH password:"))
|
||||||
self.cbx_save_password.setToolTip(_translate("diag_sshauth", "Username and password will be saved in secured operating systems\'s password storage."))
|
self.cbx_save_password.setToolTip(_translate("diag_sshauth", "Username and password will be saved in secured operating systems\'s password storage."))
|
||||||
self.cbx_save_password.setText(_translate("diag_sshauth", "Save username and password"))
|
self.cbx_save_password.setText(_translate("diag_sshauth", "Save username and password"))
|
||||||
|
self.lbl_info.setText(_translate("diag_sshauth", "Note: The default user for SSH is \"pi\" which differs from the web configuration. You can find the password on the sticker on the device."))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -6,13 +6,10 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>418</width>
|
<width>424</width>
|
||||||
<height>97</height>
|
<height>104</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
|
||||||
<string>File transfer...</string>
|
|
||||||
</property>
|
|
||||||
<property name="modal">
|
<property name="modal">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
BIN
ui_dev/ico/edit-delete-6.ico
Normal file
BIN
ui_dev/ico/edit-delete-6.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
BIN
ui_dev/ico/process-stop.ico
Executable file → Normal file
BIN
ui_dev/ico/process-stop.ico
Executable file → Normal file
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -9,6 +9,7 @@
|
|||||||
<file>ico/file-python.ico</file>
|
<file>ico/file-python.ico</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="action">
|
<qresource prefix="action">
|
||||||
|
<file>ico/edit-delete-6.ico</file>
|
||||||
<file>ico/applications-utilities.ico</file>
|
<file>ico/applications-utilities.ico</file>
|
||||||
<file>ico/edit-find.ico</file>
|
<file>ico/edit-find.ico</file>
|
||||||
<file>ico/process-stop.ico</file>
|
<file>ico/process-stop.ico</file>
|
||||||
|
|||||||
@@ -108,6 +108,9 @@
|
|||||||
<property name="editable">
|
<property name="editable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
@@ -218,9 +221,6 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btn_up">
|
<widget class="QPushButton" name="btn_up">
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="ressources.qrc">
|
<iconset resource="ressources.qrc">
|
||||||
<normaloff>:/action/ico/arrow-up.ico</normaloff>:/action/ico/arrow-up.ico</iconset>
|
<normaloff>:/action/ico/arrow-up.ico</normaloff>:/action/ico/arrow-up.ico</iconset>
|
||||||
@@ -229,9 +229,6 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btn_down">
|
<widget class="QPushButton" name="btn_down">
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="ressources.qrc">
|
<iconset resource="ressources.qrc">
|
||||||
<normaloff>:/action/ico/arrow-down.ico</normaloff>:/action/ico/arrow-down.ico</iconset>
|
<normaloff>:/action/ico/arrow-down.ico</normaloff>:/action/ico/arrow-down.ico</iconset>
|
||||||
@@ -240,20 +237,22 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btn_delete">
|
<widget class="QPushButton" name="btn_delete">
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="ressources.qrc">
|
<iconset resource="ressources.qrc">
|
||||||
<normaloff>:/action/ico/edit-delete.ico</normaloff>:/action/ico/edit-delete.ico</iconset>
|
<normaloff>:/action/ico/edit-delete-6.ico</normaloff>:/action/ico/edit-delete-6.ico</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_add_dir">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="ressources.qrc">
|
||||||
|
<normaloff>:/action/ico/folder-open.ico</normaloff>:/action/ico/folder-open.ico</iconset>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btn_add">
|
<widget class="QPushButton" name="btn_add">
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="ressources.qrc">
|
<iconset resource="ressources.qrc">
|
||||||
<normaloff>:/action/ico/edit-add.ico</normaloff>:/action/ico/edit-add.ico</iconset>
|
<normaloff>:/action/ico/edit-add.ico</normaloff>:/action/ico/edit-add.ico</iconset>
|
||||||
@@ -268,22 +267,6 @@
|
|||||||
<include location="ressources.qrc"/>
|
<include location="ressources.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
|
||||||
<sender>btn_box</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>diag_connections</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
<connection>
|
||||||
<sender>btn_box</sender>
|
<sender>btn_box</sender>
|
||||||
<signal>rejected()</signal>
|
<signal>rejected()</signal>
|
||||||
@@ -291,8 +274,8 @@
|
|||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>316</x>
|
<x>322</x>
|
||||||
<y>260</y>
|
<y>564</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>286</x>
|
<x>286</x>
|
||||||
@@ -300,5 +283,21 @@
|
|||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>btn_box</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>diag_connections</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>254</x>
|
||||||
|
<y>564</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
</connections>
|
</connections>
|
||||||
</ui>
|
</ui>
|
||||||
|
|||||||
@@ -9,14 +9,17 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>363</width>
|
<width>331</width>
|
||||||
<height>163</height>
|
<height>225</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>SSH authentication</string>
|
<string>SSH authentication</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,1">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetFixedSize</enum>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="wid_password" native="true">
|
<widget class="QWidget" name="wid_password" native="true">
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<layout class="QFormLayout" name="formLayout">
|
||||||
@@ -67,6 +70,22 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lbl_info">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Note: The default user for SSH is "pi" which differs from the web configuration. You can find the password on the sticker on the device.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|||||||
Reference in New Issue
Block a user