WIP: GUI and base function from revpidevelop

This commit is contained in:
2020-09-11 09:37:46 +02:00
parent 2737e78445
commit 954981fd15
11 changed files with 3076 additions and 1902 deletions

150
include/ui/files_ui.py Normal file
View File

@@ -0,0 +1,150 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'files.ui'
#
# Created by: PyQt5 UI code generator 5.10.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_win_files(object):
def setupUi(self, win_files):
win_files.setObjectName("win_files")
win_files.resize(891, 579)
self.centralwidget = QtWidgets.QWidget(win_files)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.gb_select_local = QtWidgets.QGroupBox(self.centralwidget)
self.gb_select_local.setObjectName("gb_select_local")
self.gridLayout_2 = QtWidgets.QGridLayout(self.gb_select_local)
self.gridLayout_2.setObjectName("gridLayout_2")
self.lbl_select_local = QtWidgets.QLabel(self.gb_select_local)
self.lbl_select_local.setObjectName("lbl_select_local")
self.gridLayout_2.addWidget(self.lbl_select_local, 0, 0, 1, 1)
self.btn_select_local = QtWidgets.QPushButton(self.gb_select_local)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/action/ico/folder-open.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_select_local.setIcon(icon)
self.btn_select_local.setIconSize(QtCore.QSize(24, 24))
self.btn_select_local.setAutoDefault(False)
self.btn_select_local.setObjectName("btn_select_local")
self.gridLayout_2.addWidget(self.btn_select_local, 0, 1, 1, 1)
self.btn_refresh_local = QtWidgets.QPushButton(self.gb_select_local)
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/action/ico/refresh.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_refresh_local.setIcon(icon1)
self.btn_refresh_local.setIconSize(QtCore.QSize(24, 24))
self.btn_refresh_local.setObjectName("btn_refresh_local")
self.gridLayout_2.addWidget(self.btn_refresh_local, 0, 2, 1, 1)
self.lbl_path_local = QtWidgets.QLabel(self.gb_select_local)
self.lbl_path_local.setObjectName("lbl_path_local")
self.gridLayout_2.addWidget(self.lbl_path_local, 1, 0, 1, 3)
self.gridLayout_2.setColumnStretch(0, 1)
self.gridLayout.addWidget(self.gb_select_local, 0, 0, 1, 1)
self.gb_select_revpi = QtWidgets.QGroupBox(self.centralwidget)
self.gb_select_revpi.setObjectName("gb_select_revpi")
self.gridLayout_3 = QtWidgets.QGridLayout(self.gb_select_revpi)
self.gridLayout_3.setObjectName("gridLayout_3")
self.lbl_path_revpi = QtWidgets.QLabel(self.gb_select_revpi)
self.lbl_path_revpi.setObjectName("lbl_path_revpi")
self.gridLayout_3.addWidget(self.lbl_path_revpi, 1, 0, 1, 2)
self.lbl_select_revpi = QtWidgets.QLabel(self.gb_select_revpi)
self.lbl_select_revpi.setObjectName("lbl_select_revpi")
self.gridLayout_3.addWidget(self.lbl_select_revpi, 0, 0, 1, 1)
self.btn_refresh_revpi = QtWidgets.QPushButton(self.gb_select_revpi)
self.btn_refresh_revpi.setIcon(icon1)
self.btn_refresh_revpi.setIconSize(QtCore.QSize(24, 24))
self.btn_refresh_revpi.setObjectName("btn_refresh_revpi")
self.gridLayout_3.addWidget(self.btn_refresh_revpi, 0, 1, 1, 1)
self.gridLayout_3.setColumnStretch(0, 1)
self.gridLayout.addWidget(self.gb_select_revpi, 0, 2, 1, 1)
self.tree_files_local = QtWidgets.QTreeWidget(self.centralwidget)
self.tree_files_local.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.tree_files_local.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
self.tree_files_local.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tree_files_local.setIconSize(QtCore.QSize(24, 24))
self.tree_files_local.setObjectName("tree_files_local")
self.tree_files_local.headerItem().setText(0, "1")
self.tree_files_local.header().setVisible(False)
self.gridLayout.addWidget(self.tree_files_local, 1, 0, 1, 1)
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.btn_to_left = QtWidgets.QPushButton(self.centralwidget)
self.btn_to_left.setText("")
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/action/ico/arrow-left.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_to_left.setIcon(icon2)
self.btn_to_left.setIconSize(QtCore.QSize(24, 24))
self.btn_to_left.setAutoDefault(False)
self.btn_to_left.setObjectName("btn_to_left")
self.verticalLayout_2.addWidget(self.btn_to_left)
self.btn_to_right = QtWidgets.QPushButton(self.centralwidget)
self.btn_to_right.setText("")
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(":/action/ico/arrow-right.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_to_right.setIcon(icon3)
self.btn_to_right.setIconSize(QtCore.QSize(24, 24))
self.btn_to_right.setAutoDefault(False)
self.btn_to_right.setObjectName("btn_to_right")
self.verticalLayout_2.addWidget(self.btn_to_right)
self.btn_delete = QtWidgets.QPushButton(self.centralwidget)
self.btn_delete.setText("")
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(":/action/ico/edit-delete.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_delete.setIcon(icon4)
self.btn_delete.setIconSize(QtCore.QSize(24, 24))
self.btn_delete.setAutoDefault(False)
self.btn_delete.setObjectName("btn_delete")
self.verticalLayout_2.addWidget(self.btn_delete)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_2.addItem(spacerItem)
self.gridLayout.addLayout(self.verticalLayout_2, 1, 1, 1, 1)
self.tree_files_revpi = QtWidgets.QTreeWidget(self.centralwidget)
self.tree_files_revpi.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.tree_files_revpi.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
self.tree_files_revpi.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tree_files_revpi.setIconSize(QtCore.QSize(24, 24))
self.tree_files_revpi.setObjectName("tree_files_revpi")
self.tree_files_revpi.headerItem().setText(0, "1")
self.tree_files_revpi.header().setVisible(False)
self.gridLayout.addWidget(self.tree_files_revpi, 1, 2, 1, 1)
self.btn_all = QtWidgets.QPushButton(self.centralwidget)
self.btn_all.setObjectName("btn_all")
self.gridLayout.addWidget(self.btn_all, 2, 0, 1, 3)
win_files.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(win_files)
self.statusbar.setObjectName("statusbar")
win_files.setStatusBar(self.statusbar)
self.retranslateUi(win_files)
QtCore.QMetaObject.connectSlotsByName(win_files)
def retranslateUi(self, win_files):
_translate = QtCore.QCoreApplication.translate
win_files.setWindowTitle(_translate("win_files", "File manager"))
self.gb_select_local.setTitle(_translate("win_files", "Local computer"))
self.lbl_select_local.setText(_translate("win_files", "Path to development root:"))
self.btn_select_local.setToolTip(_translate("win_files", "Open developer root directory"))
self.btn_refresh_local.setToolTip(_translate("win_files", "Reload file list"))
self.lbl_path_local.setText(_translate("win_files", "/"))
self.gb_select_revpi.setTitle(_translate("win_files", "Revolution Pi"))
self.lbl_path_revpi.setText(_translate("win_files", "/"))
self.lbl_select_revpi.setText(_translate("win_files", "RevPiPyLoad working directory:"))
self.btn_refresh_revpi.setToolTip(_translate("win_files", "Reload file list"))
self.tree_files_local.setSortingEnabled(True)
self.tree_files_revpi.setSortingEnabled(True)
self.btn_all.setText(_translate("win_files", "Stop - Upload - Start"))
from . import ressources_rc
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
win_files = QtWidgets.QMainWindow()
ui = Ui_win_files()
ui.setupUi(win_files)
win_files.show()
sys.exit(app.exec_())

File diff suppressed because it is too large Load Diff

View File

@@ -51,8 +51,6 @@ class Ui_diag_program(object):
self.cbb_format.setObjectName("cbb_format")
self.cbb_format.addItem("")
self.cbb_format.addItem("")
self.cbb_format.addItem("")
self.cbb_format.addItem("")
self.gridLayout_2.addWidget(self.cbb_format, 0, 1, 1, 1)
self.btn_program_upload = QtWidgets.QPushButton(self.cb_transfair)
self.btn_program_upload.setObjectName("btn_program_upload")
@@ -124,10 +122,8 @@ class Ui_diag_program(object):
self.lbl_pythonversion.setText(_translate("diag_program", "Python version:"))
self.lbl_plcarguments.setText(_translate("diag_program", "Program arguments:"))
self.cb_transfair.setTitle(_translate("diag_program", "Transfair PLC program"))
self.cbb_format.setItemText(0, _translate("diag_program", "Files"))
self.cbb_format.setItemText(1, _translate("diag_program", "Folder"))
self.cbb_format.setItemText(2, _translate("diag_program", "ZIP archive"))
self.cbb_format.setItemText(3, _translate("diag_program", "TGZ archive"))
self.cbb_format.setItemText(0, _translate("diag_program", "ZIP archive"))
self.cbb_format.setItemText(1, _translate("diag_program", "TGZ archive"))
self.btn_program_upload.setText(_translate("diag_program", "Upload"))
self.btn_program_download.setText(_translate("diag_program", "Download"))
self.lbl_format.setText(_translate("diag_program", "Transfair format:"))

270
include/ui_dev/files.ui Normal file
View File

@@ -0,0 +1,270 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>win_files</class>
<widget class="QMainWindow" name="win_files">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>891</width>
<height>579</height>
</rect>
</property>
<property name="windowTitle">
<string>File manager</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="gb_select_local">
<property name="title">
<string>Local computer</string>
</property>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,0">
<item row="0" column="0">
<widget class="QLabel" name="lbl_select_local">
<property name="text">
<string>Path to development root:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="btn_select_local">
<property name="toolTip">
<string>Open developer root directory</string>
</property>
<property name="icon">
<iconset resource="ressources.qrc">
<normaloff>:/action/ico/folder-open.ico</normaloff>:/action/ico/folder-open.ico</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="btn_refresh_local">
<property name="toolTip">
<string>Reload file list</string>
</property>
<property name="icon">
<iconset resource="ressources.qrc">
<normaloff>:/action/ico/refresh.ico</normaloff>:/action/ico/refresh.ico</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QLabel" name="lbl_path_local">
<property name="text">
<string>/</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="2">
<widget class="QGroupBox" name="gb_select_revpi">
<property name="title">
<string>Revolution Pi</string>
</property>
<layout class="QGridLayout" name="gridLayout_3" columnstretch="1,0">
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="lbl_path_revpi">
<property name="text">
<string>/</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lbl_select_revpi">
<property name="text">
<string>RevPiPyLoad working directory:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="btn_refresh_revpi">
<property name="toolTip">
<string>Reload file list</string>
</property>
<property name="icon">
<iconset resource="ressources.qrc">
<normaloff>:/action/ico/refresh.ico</normaloff>:/action/ico/refresh.ico</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QTreeWidget" name="tree_files_local">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="btn_to_left">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="ressources.qrc">
<normaloff>:/action/ico/arrow-left.ico</normaloff>:/action/ico/arrow-left.ico</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_to_right">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="ressources.qrc">
<normaloff>:/action/ico/arrow-right.ico</normaloff>:/action/ico/arrow-right.ico</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_delete">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="ressources.qrc">
<normaloff>:/action/ico/edit-delete.ico</normaloff>:/action/ico/edit-delete.ico</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="2">
<widget class="QTreeWidget" name="tree_files_revpi">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QPushButton" name="btn_all">
<property name="text">
<string>Stop - Upload - Start</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources>
<include location="ressources.qrc"/>
</resources>
<connections/>
</ui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -9,6 +9,8 @@
<file>ico/file-python.ico</file>
</qresource>
<qresource prefix="action">
<file>ico/arrow-left.ico</file>
<file>ico/arrow-right.ico</file>
<file>ico/folder-open.ico</file>
<file>ico/refresh.ico</file>
<file>ico/reload.ico</file>

View File

@@ -79,16 +79,6 @@
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QComboBox" name="cbb_format">
<item>
<property name="text">
<string>Files</string>
</property>
</item>
<item>
<property name="text">
<string>Folder</string>
</property>
</item>
<item>
<property name="text">
<string>ZIP archive</string>

View File

@@ -17,7 +17,7 @@ import proginit as pi
import revpilogfile
from avahisearch import AvahiSearch
from debugcontrol import DebugControl
from revpidevelop import RevPiDevelop
from revpifiles import RevPiFiles
from revpiinfo import RevPiInfo
from revpioption import RevPiOption
from revpiplclist import RevPiPlcList
@@ -35,8 +35,6 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
self.wid_debugcontrol = None # type: DebugControl
"""Holds the widget of DebugControl."""
self.wid_develop = None # type: RevPiDevelop
"""Holds the widget of RevPiDevelop."""
self.simulating = False
"""True, if simulation is running."""
self.dict_men_connections_subfolder = {}
@@ -55,6 +53,7 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
self.diag_info = RevPiInfo(__version__, self)
self.diag_options = RevPiOption(self)
self.diag_program = RevPiProgram(self)
self.win_files = RevPiFiles(self)
self.win_log = revpilogfile.RevPiLogfile(self)
self.btn_plc_logs.pressed.connect(self.on_act_logs_triggered)
@@ -121,6 +120,8 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
self.diag_info.reject()
self.diag_options.reject()
self.diag_program.reject()
self.win_files.close()
self.win_files.deleteLater()
self.centralwidget.adjustSize()
self.adjustSize()
@@ -136,6 +137,7 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
helper.cm.address,
helper.cm.port
))
self.win_files = RevPiFiles(self)
@QtCore.pyqtSlot(str, str)
def on_cm_status_changed(self, text: str, color: str):
@@ -313,33 +315,13 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
@QtCore.pyqtSlot(bool)
def on_act_developer_toggled(self, state: bool):
"""Extent developer mode to main window."""
if not (state or self.wid_develop is None):
# Remove widget
self.gl.removeWidget(self.wid_develop)
self.wid_develop.deleteLater()
self.wid_develop = None
self.gl.setColumnStretch(1, 0)
if not helper.cm.connected:
return
elif state and helper.cm.connected:
if helper.cm.xml_mode < 2:
QtWidgets.QMessageBox.warning(
self, self.tr("Warning"), self.tr(
"XML-RPC access mode in the RevPiPyLoad "
"configuration is too small to access this dialog!"
)
)
self.act_developer.setChecked(False)
else:
self.wid_develop = RevPiDevelop(self.centralwidget)
self.gl.addWidget(self.wid_develop, 0, 1, 8, 1)
self.gl.setColumnStretch(1, 1)
elif state:
self.act_developer.setChecked(False)
self.centralwidget.adjustSize()
self.adjustSize()
if self.win_files.isHidden():
self.win_files.show()
else:
self.win_files.activateWindow()
@QtCore.pyqtSlot()
def on_act_pictory_triggered(self):

View File

@@ -0,0 +1,299 @@
# -*- coding: utf-8 -*-
"""File manager for up und download PLC program."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2020 Sven Sager"
__license__ = "GPLv3"
import gzip
import os
from enum import IntEnum
from os import DirEntry, scandir
from xmlrpc.client import Binary
from PyQt5 import QtCore, QtGui, QtWidgets
import helper
import proginit as pi
from helper import WidgetData
from ui.files_ui import Ui_win_files
class NodeType(IntEnum):
FILE = 1000
DIR = 1001
class RevPiFiles(QtWidgets.QMainWindow, Ui_win_files):
def __init__(self, parent=None):
super(RevPiFiles, self).__init__(parent)
self.setupUi(self)
self.tree_files_counter = 0
self.tree_files_counter_max = 10000
self.lbl_path_local.setText(helper.cm.develop_watch_path or self.tr("Please select..."))
self.btn_all.setEnabled(False)
self.btn_to_left.setEnabled(False)
self.btn_to_right.setEnabled(False)
self.btn_delete.setEnabled(False)
if helper.cm.develop_watch_path:
self._load_path_files(True)
def __del__(self):
pi.logger.debug("RevPiFiles.__del__")
def _do_my_job(self, stop_restart=True):
"""
Upload the selected files and do a optionally restart.
:param stop_restart: True will restart program
"""
if not helper.cm.connected:
return
if stop_restart and helper.cm.call_remote_function("plcstop") is None:
QtWidgets.QMessageBox.critical(
self, self.tr("Error"), self.tr(
"Can not stop plc program on Revolution Pi."
)
)
return
# Get config to find actual auto start program for warnings
opt_program = helper.cm.call_remote_function("get_config", default_value={})
opt_program = opt_program.get("plcprogram", "none.py")
uploaded = True # Will be False, when opt_program was found in files
ec = 0
for file_name in self.file_list():
# todo: Check exception of local file
with open(file_name, "rb") as fh:
# Remove base dir of file to set relative for PyLoad
send_name = file_name.replace(helper.cm.develop_watch_path, "")[1:]
# Check whether this is the auto start program
if send_name == opt_program:
uploaded = False
# Transfer file
try:
upload_status = helper.cm.call_remote_function(
"plcupload", Binary(gzip.compress(fh.read())), send_name,
default_value=False
)
except Exception as e:
pi.logger.error(e)
ec = -2
break
if not upload_status:
ec = -1
break
if ec == 0:
# Tell user, we did not find the auto start program in files
if uploaded:
QtWidgets.QMessageBox.information(
self, self.tr("Information..."), self.tr(
"A PLC program has been uploaded. Please check the "
"PLC options to see if the correct program is "
"specified as the start program."
)
)
elif ec == -1:
QtWidgets.QMessageBox.critical(
self, self.tr("Error"), self.tr(
"The Revolution Pi could not process some parts of the "
"transmission."
)
)
elif ec == -2:
QtWidgets.QMessageBox.critical(
self, self.tr("Error"),
self.tr("Errors occurred during transmission")
)
if stop_restart and helper.cm.call_remote_function("plcstart", default_value=1) != 0:
QtWidgets.QMessageBox.warning(
self, self.tr("Warning"), self.tr(
"Could not start the plc program on Revolution Pi."
)
)
def _set_gui_control_states(self):
"""Setup states of actions and buttons."""
state = len(self.tree_files_local.selectedItems()) > 0
self.btn_all.setEnabled(state)
self.btn_to_left.setEnabled(state)
self.btn_to_right.setEnabled(state)
self.btn_delete.setEnabled(state)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# region # REGION: Tree management
def __insert_files(self, base_dir: str, child=None):
"""
Recursively add files to tree view.
:param base_dir: Directory to scan for files
:param child: Child widget to add new widgets
"""
for de in os.scandir(base_dir): # type: DirEntry
if self.tree_files_counter > self.tree_files_counter_max:
return
if de.is_dir(follow_symlinks=False):
item = QtWidgets.QTreeWidgetItem(NodeType.DIR)
item.setText(0, de.name)
item.setIcon(0, QtGui.QIcon(":/main/ico/folder.ico"))
if child:
child.addChild(item)
else:
self.tree_files_local.addTopLevelItem(item)
self.__insert_files(de.path, item)
elif de.is_file(follow_symlinks=False):
self.tree_files_counter += 1
item = QtWidgets.QTreeWidgetItem(NodeType.FILE)
item.setText(0, de.name)
item.setData(0, WidgetData.file_name, de.path)
item.setIcon(0, QtGui.QIcon(
":/file/ico/file-else.ico" if de.name.find(".py") == -1 else
":/file/ico/file-python.ico"
))
if child:
child.addChild(item)
else:
self.tree_files_local.addTopLevelItem(item)
item.setSelected(de.path in helper.cm.develop_watch_files)
self._parent_selected(item)
def __select_children(self, top_item: QtWidgets.QTreeWidgetItem, value: bool):
"""Recursive select files from directory."""
pi.logger.debug("RevPiFiles.__select_children")
for i in range(top_item.childCount()):
item = top_item.child(i)
if item.type() == NodeType.DIR:
self.__select_children(item, value)
elif item.type() == NodeType.FILE:
item.setSelected(value)
def _load_path_files(self, silent=False):
"""
Refresh the file list.
:param silent: Do not show message boxes
"""
pi.logger.debug("RevPiFiles._load_path_files")
self.tree_files_counter = 0
self.tree_files_local.blockSignals(True)
self.tree_files_local.clear()
self.tree_files_local.blockSignals(False)
self.__insert_files(helper.cm.develop_watch_path)
self.tree_files_local.sortItems(0, QtCore.Qt.AscendingOrder)
if not silent and self.tree_files_counter > self.tree_files_counter_max:
QtWidgets.QMessageBox.critical(
self, self.tr("Error"), self.tr(
"Stop scanning for files, because we found more than {0} files."
).format(self.tree_files_counter_max)
)
self._set_gui_control_states()
def _parent_selected(self, item: QtWidgets.QTreeWidgetItem):
"""Check all children of a parent are selected."""
if item.parent():
all_selected = True
for i in range(item.parent().childCount()):
if not item.parent().child(i).isSelected():
all_selected = False
break
item.parent().setSelected(all_selected)
def file_list(self):
"""Generate a file list with full path of selected entries."""
pi.logger.debug("RevPiFiles.file_list")
lst = []
for item in self.tree_files_local.selectedItems():
if item.type() == NodeType.DIR:
continue
lst.append(item.data(0, WidgetData.file_name))
return lst
@QtCore.pyqtSlot()
def on_tree_files_local_itemSelectionChanged(self):
item = self.tree_files_local.currentItem()
if item is None:
return
pi.logger.debug("RevPiFiles.on_tree_files_itemSelectionChanged")
# Block while preselect other entries
self.tree_files_local.blockSignals(True)
if item.type() == NodeType.DIR:
self.__select_children(item, item.isSelected())
elif item.type() == NodeType.FILE:
self._parent_selected(item)
self.tree_files_local.blockSignals(False)
self._set_gui_control_states()
helper.cm.develop_watch_files = self.file_list()
# endregion # # # # #
@QtCore.pyqtSlot()
def on_btn_all_pressed(self):
pi.logger.debug("RevPiDevelop.on_btn_all_pressed")
self._do_my_job(True)
@QtCore.pyqtSlot()
def on_btn_select_local_pressed(self):
pi.logger.debug("RevPiFiles.on_btn_select_pressed")
diag_folder = QtWidgets.QFileDialog(
self, self.tr("Select folder..."),
helper.cm.develop_watch_path,
)
diag_folder.setFileMode(QtWidgets.QFileDialog.DirectoryOnly)
if diag_folder.exec() != QtWidgets.QFileDialog.Accepted:
return
selected_dir = diag_folder.selectedFiles()[0]
if not os.access(selected_dir, os.R_OK):
QtWidgets.QMessageBox.critical(
self, self.tr("Error"), self.tr(
"Can not access the folder '{0}' to read files."
)
)
helper.cm.develop_watch_files = []
helper.cm.develop_watch_path = ""
return
self.lbl_path_local.setText(selected_dir)
helper.cm.develop_watch_path = selected_dir
helper.cm.develop_watch_files = []
self._load_path_files(False)
@QtCore.pyqtSlot()
def on_btn_refresh_local_pressed(self):
pi.logger.debug("RevPiDevelop.on_btn_refresh_pressed")
self._load_path_files(False)

View File

@@ -313,8 +313,7 @@ class RevPiProgram(QtWidgets.QDialog, Ui_diag_program):
@QtCore.pyqtSlot(int)
def on_cbb_format_currentIndexChanged(self, index: int):
helper.settings.setValue("program/cbb_format_index", index)
self.cbx_pictory.setEnabled(index >= 2)
self.btn_program_download.setEnabled(index != 1)
self.cbx_pictory.setEnabled(index >= 1)
@QtCore.pyqtSlot()
def on_btn_program_download_pressed(self):
@@ -325,23 +324,6 @@ class RevPiProgram(QtWidgets.QDialog, Ui_diag_program):
selected_dir = ""
if self.cbb_format.currentIndex() == 0:
# Save files to selected directory
diag_folder = QtWidgets.QFileDialog(
self, self.tr("Select folder..."),
helper.cm.program_last_dir_selected,
)
diag_folder.setFileMode(QtWidgets.QFileDialog.DirectoryOnly)
self.rejected.connect(diag_folder.reject)
if diag_folder.exec() != QtWidgets.QFileDialog.Accepted:
return
selected_dir = diag_folder.selectedFiles()[0]
fh = open(mkstemp()[1], "wb")
helper.cm.program_last_dir_selected = selected_dir
elif self.cbb_format.currentIndex() == 2:
# Save files as zip archive
diag_save = QtWidgets.QFileDialog(
self, self.tr("Save ZIP archive..."),
@@ -362,7 +344,7 @@ class RevPiProgram(QtWidgets.QDialog, Ui_diag_program):
helper.cm.program_last_zip_file = filename
elif self.cbb_format.currentIndex() == 3:
elif self.cbb_format.currentIndex() == 1:
# Save files as TarGz archive
diag_save = QtWidgets.QFileDialog(
self, self.tr("Save TGZ archive..."),
@@ -389,7 +371,7 @@ class RevPiProgram(QtWidgets.QDialog, Ui_diag_program):
plcfile = helper.cm.call_remote_function(
"plcdownload",
"zip" if self.cbb_format.currentIndex() == 2 else "tar",
"zip" if self.cbb_format.currentIndex() == 0 else "tar",
self.cbx_pictory.isChecked()
)
@@ -405,20 +387,6 @@ class RevPiProgram(QtWidgets.QDialog, Ui_diag_program):
fh.write(plcfile.data)
fh.close()
if self.cbb_format.currentIndex() == 0:
# Extract archive to selected directory
os.makedirs(selected_dir, exist_ok=True)
fh_pack = tarfile.open(fh.name)
for tar_item in fh_pack.getmembers():
if tar_item.name == "revpipyload":
# Ignore root folder in Tar file
continue
tar_item.name = tar_item.name.replace("revpipyload/", "")
fh_pack.extract(tar_item, selected_dir)
fh_pack.close()
except Exception as e:
pi.logger.error(e)
QtWidgets.QMessageBox.critical(
@@ -452,43 +420,6 @@ class RevPiProgram(QtWidgets.QDialog, Ui_diag_program):
rscfile = None
if self.cbb_format.currentIndex() == 0:
# Upload files
diag_open = QtWidgets.QFileDialog(
self,
self.tr("Upload plc files..."),
helper.cm.program_last_dir_upload,
self.tr("Python file (*.py);;Config file (*.conf);;;JSON file (*.json);;All files (*.*)")
)
diag_open.setAcceptMode(QtWidgets.QFileDialog.AcceptOpen)
diag_open.setFileMode(QtWidgets.QFileDialog.ExistingFiles)
self.rejected.connect(diag_open.reject)
if diag_open.exec() != QtWidgets.QFileDialog.AcceptSave or len(diag_open.selectedFiles()) != 1:
return
lst_files = diag_open.selectedFiles()
if len(lst_files) > 0:
helper.cm.program_last_dir_upload = os.path.dirname(lst_files[0])
elif self.cbb_format.currentIndex() == 1:
# Select folder to upload
diag_folder = QtWidgets.QFileDialog(
self, self.tr("Select folder to upload..."),
helper.cm.program_last_dir_upload,
)
diag_folder.setFileMode(QtWidgets.QFileDialog.DirectoryOnly)
self.rejected.connect(diag_folder.reject)
if diag_folder.exec() != QtWidgets.QFileDialog.Accepted:
return
selected_dir = diag_folder.selectedFiles()[0]
helper.cm.program_last_dir_upload = selected_dir
folder_name = os.path.basename(selected_dir)
lst_files = self.create_filelist(selected_dir)
elif self.cbb_format.currentIndex() == 2:
# Upload zip archive content
diag_open = QtWidgets.QFileDialog(
self, self.tr("Upload content of ZIP archive..."),
@@ -522,7 +453,7 @@ class RevPiProgram(QtWidgets.QDialog, Ui_diag_program):
)
return
elif self.cbb_format.currentIndex() == 3:
elif self.cbb_format.currentIndex() == 1:
# Upload TarGz content
diag_open = QtWidgets.QFileDialog(
self, self.tr("Upload content of TAR archive..."),