From 270d9f9c96d554af7038e99f67053157705a74a5 Mon Sep 17 00:00:00 2001 From: Mehmet Aksoy Date: Tue, 15 Apr 2025 11:21:44 +0200 Subject: [PATCH 1/3] [WIP] Updates project to use PySide6 and QtDesigner Migrates the project from PyQt6 to PySide6. Updates the UI loading mechanism to use QUiLoader when in debug mode. Adds a resources file for storing images used in the UI. Fixes issue where ui file path was not correctly defined. Changes start and end button styles. --- Serial-Communication-GUI-Program.pyproject | 1 + ...l-Communication-GUI-Program.pyproject.user | 38 +- src/ui_main.py | 22 +- ui/main_window.ui | 4 +- ui/resource/play.svg | 1 + ui/resources.qrc | 5 + ui/ui_main_window.py | 724 ++++++++++-------- 7 files changed, 463 insertions(+), 332 deletions(-) create mode 100644 ui/resource/play.svg create mode 100644 ui/resources.qrc diff --git a/Serial-Communication-GUI-Program.pyproject b/Serial-Communication-GUI-Program.pyproject index f1430bb..591dbb2 100644 --- a/Serial-Communication-GUI-Program.pyproject +++ b/Serial-Communication-GUI-Program.pyproject @@ -4,6 +4,7 @@ "src/ui_main.py", "ui/icon.ico", "ui/main_window.ui", + "ui/resources.qrc", "ui/ui_main_window.py" ] } diff --git a/Serial-Communication-GUI-Program.pyproject.user b/Serial-Communication-GUI-Program.pyproject.user index 8a3adae..4824242 100644 --- a/Serial-Communication-GUI-Program.pyproject.user +++ b/Serial-Communication-GUI-Program.pyproject.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -13,8 +13,8 @@ ProjectExplorer.Project.EditorSettings + true true - false true Cpp @@ -33,6 +33,7 @@ false 4 false + 0 80 true true @@ -151,7 +152,7 @@ false -e cpu-cycles --call-graph "dwarf,4096" -F 250 mainwindow.py - PythonEditor.RunConfiguration.C:/Projects/Qt_playground/Serial-Communication-GUI-Program/mainwindow.py + PythonEditor.RunConfiguration. C:/Projects/Qt_playground/Serial-Communication-GUI-Program/mainwindow.py true true @@ -168,7 +169,7 @@ false -e cpu-cycles --call-graph "dwarf,4096" -F 250 src\ui_config.py - PythonEditor.RunConfiguration.C:/Projects/Qt_playground/Serial-Communication-GUI-Program/src/ui_config.py + PythonEditor.RunConfiguration. C:/Projects/Qt_playground/Serial-Communication-GUI-Program/src/ui_config.py true true @@ -185,13 +186,11 @@ false -e cpu-cycles --call-graph "dwarf,4096" -F 250 src\ui_main.py - PythonEditor.RunConfiguration.C:/Projects/Qt_playground/Serial-Communication-GUI-Program/src/ui_main.py + PythonEditor.RunConfiguration. C:/Projects/Qt_playground/Serial-Communication-GUI-Program/src/ui_main.py true - C:\Projects\Qt_playground\Serial-Communication-GUI-Program\src\ui_main.py true true - C:/Projects/Qt_playground/Serial-Communication-GUI-Program/src true @@ -204,15 +203,32 @@ false -e cpu-cycles --call-graph "dwarf,4096" -F 250 main.py - PythonEditor.RunConfiguration.C:/Projects/Qt_playground/Serial-Communication-GUI-Program/main.py + PythonEditor.RunConfiguration. C:/Projects/Qt_playground/Serial-Communication-GUI-Program/main.py true - C:\Projects\Qt_playground\Serial-Communication-GUI-Program\main.py true true - C:/Projects/Qt_playground/Serial-Communication-GUI-Program - 4 + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph "dwarf,4096" -F 250 + main.py2 + PythonEditor.RunConfiguration. + C:/Users/aksoym/Desktop/Serial-Communication-GUI-Program/main.py + true + C:\Users\aksoym\Desktop\Serial-Communication-GUI-Program\main.py + true + true + C:/Users/aksoym/Desktop/Serial-Communication-GUI-Program + + 5 diff --git a/src/ui_main.py b/src/ui_main.py index 9f14f23..4735478 100644 --- a/src/ui_main.py +++ b/src/ui_main.py @@ -16,8 +16,8 @@ from glob import glob # Runtime Type Checking -PROGRAM_TYPE_DEBUG = False -PROGRAM_TYPE_RELEASE = True +PROGRAM_TYPE_DEBUG = True +PROGRAM_TYPE_RELEASE = False try: import serial.tools.list_ports @@ -27,11 +27,11 @@ #system("python -m pip install pyserial") try: - from PyQt6.QtCore import QObject, QThread, pyqtSignal - from PyQt6.QtWidgets import QApplication, QMainWindow, QMessageBox, QInputDialog, QFileDialog + from PySide6.QtCore import QObject, QThread, Signal, QFile + from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox, QInputDialog, QFileDialog if (PROGRAM_TYPE_DEBUG): - from PyQt6.uic import loadUi + from PySide6.QtUiTools import QUiLoader else: # PROGRAM_TYPE_RELEASE from ui.ui_main_window import Ui_main_window except ImportError as e: @@ -75,8 +75,8 @@ def get_serial_port(): # MULTI-THREADING class Worker(QObject): """ Worker Thread """ - finished = pyqtSignal() - serial_data = pyqtSignal(str) + finished = Signal() + serial_data = Signal(str) def __init__(self): super(Worker, self).__init__() @@ -103,12 +103,16 @@ def __init__(self): """ Initialize Main Window """ super(MainWindow, self).__init__() if PROGRAM_TYPE_DEBUG: + file_path = path.join("ui/main_window.ui") if not path.exists(file_path): print("UI File Not Found!") exit(1) - loadUi(file_path, self.ui) # Load the .ui file - self.ui.show() # Show the GUI + ui_file = QFile(file_path) + ui_file.open(QFile.ReadOnly) + loader = QUiLoader() + self.ui = loader.load(ui_file) + self.ui.show() else: # PROGRAM_TYPE_RELEASE print("UI File Found!") self.ui= Ui_main_window() diff --git a/ui/main_window.ui b/ui/main_window.ui index ac3de7e..68146c8 100644 --- a/ui/main_window.ui +++ b/ui/main_window.ui @@ -270,7 +270,7 @@ false - background-color:qlineargradient(spread:pad, x1:0.409, y1:0, x2:0.430448, y2:1, stop:0 rgba(255, 0, 0, 255), stop:1 rgba(255, 255, 255, 255)) + @@ -292,7 +292,7 @@ false - background-color:qlineargradient(spread:pad, x1:0.556, y1:0, x2:0.550444, y2:1, stop:0 rgba(0, 146, 0, 255), stop:1 rgba(255, 255, 255, 255)) + START diff --git a/ui/resource/play.svg b/ui/resource/play.svg new file mode 100644 index 0000000..f9e2f8b --- /dev/null +++ b/ui/resource/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/resources.qrc b/ui/resources.qrc new file mode 100644 index 0000000..43e9019 --- /dev/null +++ b/ui/resources.qrc @@ -0,0 +1,5 @@ + + + resource/play.svg + + diff --git a/ui/ui_main_window.py b/ui/ui_main_window.py index 6578bb8..0d8c927 100644 --- a/ui/ui_main_window.py +++ b/ui/ui_main_window.py @@ -1,183 +1,226 @@ -# Form implementation generated from reading ui file 'main_window.ui' -# -# Created by: PyQt6 UI code generator 6.4.2 -# -# WARNING: Any manual changes made to this file will be lost when pyuic6 is -# run again. Do not edit this file unless you know what you are doing. +# -*- coding: utf-8 -*- +################################################################################ +## Form generated from reading UI file 'main_window.ui' +## +## Created by: Qt User Interface Compiler version 6.7.2 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ -from PyQt6 import QtCore, QtGui, QtWidgets - +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient, + QCursor, QFont, QFontDatabase, QGradient, + QIcon, QImage, QKeySequence, QLinearGradient, + QPainter, QPalette, QPixmap, QRadialGradient, + QTransform) +from PySide6.QtWidgets import (QApplication, QComboBox, QFormLayout, QFrame, + QGridLayout, QHBoxLayout, QLabel, QLayout, + QMainWindow, QPushButton, QSizePolicy, QTabWidget, + QTextEdit, QVBoxLayout, QWidget) class Ui_main_window(object): def setupUi(self, main_window): - main_window.setObjectName("main_window") + if not main_window.objectName(): + main_window.setObjectName(u"main_window") main_window.resize(929, 579) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed) + sizePolicy = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(main_window.sizePolicy().hasHeightForWidth()) main_window.setSizePolicy(sizePolicy) - main_window.setMinimumSize(QtCore.QSize(600, 579)) - main_window.setMaximumSize(QtCore.QSize(929, 579)) - main_window.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.ArrowCursor)) - icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap("icon.ico"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) + main_window.setMinimumSize(QSize(600, 579)) + main_window.setMaximumSize(QSize(929, 579)) + main_window.setCursor(QCursor(Qt.CursorShape.ArrowCursor)) + icon = QIcon() + icon.addFile(u"icon.ico", QSize(), QIcon.Mode.Normal, QIcon.State.Off) main_window.setWindowIcon(icon) - main_window.setWindowOpacity(1.0) - self.centralwidget = QtWidgets.QWidget(parent=main_window) - self.centralwidget.setObjectName("centralwidget") - self.tabWidget = QtWidgets.QTabWidget(parent=self.centralwidget) - self.tabWidget.setGeometry(QtCore.QRect(0, 0, 931, 581)) - self.tabWidget.setTabPosition(QtWidgets.QTabWidget.TabPosition.North) - self.tabWidget.setObjectName("tabWidget") - self.tab = QtWidgets.QWidget() - self.tab.setObjectName("tab") - self.gridLayoutWidget_2 = QtWidgets.QWidget(parent=self.tab) - self.gridLayoutWidget_2.setGeometry(QtCore.QRect(0, 0, 721, 511)) - self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2") - self.gridLayout_2 = QtWidgets.QGridLayout(self.gridLayoutWidget_2) + main_window.setWindowOpacity(1.000000000000000) + self.actionAna_Ekran = QAction(main_window) + self.actionAna_Ekran.setObjectName(u"actionAna_Ekran") + self.actionHelp = QAction(main_window) + self.actionHelp.setObjectName(u"actionHelp") + self.centralwidget = QWidget(main_window) + self.centralwidget.setObjectName(u"centralwidget") + self.tabWidget = QTabWidget(self.centralwidget) + self.tabWidget.setObjectName(u"tabWidget") + self.tabWidget.setGeometry(QRect(0, 0, 931, 581)) + self.tabWidget.setTabPosition(QTabWidget.TabPosition.North) + self.tab = QWidget() + self.tab.setObjectName(u"tab") + self.gridLayoutWidget_2 = QWidget(self.tab) + self.gridLayoutWidget_2.setObjectName(u"gridLayoutWidget_2") + self.gridLayoutWidget_2.setGeometry(QRect(0, 0, 721, 511)) + self.gridLayout_2 = QGridLayout(self.gridLayoutWidget_2) + self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setContentsMargins(0, 0, 0, 0) - self.gridLayout_2.setObjectName("gridLayout_2") - self.label_23 = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) - self.label_23.setObjectName("label_23") + self.label_23 = QLabel(self.gridLayoutWidget_2) + self.label_23.setObjectName(u"label_23") + self.gridLayout_2.addWidget(self.label_23, 1, 0, 1, 1) - self.data_textEdit = QtWidgets.QTextEdit(parent=self.gridLayoutWidget_2) + + self.data_textEdit = QTextEdit(self.gridLayoutWidget_2) + self.data_textEdit.setObjectName(u"data_textEdit") self.data_textEdit.setAutoFillBackground(False) - self.data_textEdit.setFrameShape(QtWidgets.QFrame.Shape.Box) - self.data_textEdit.setFrameShadow(QtWidgets.QFrame.Shadow.Raised) - self.data_textEdit.setAutoFormatting(QtWidgets.QTextEdit.AutoFormattingFlag.AutoAll) + self.data_textEdit.setFrameShape(QFrame.Shape.Box) + self.data_textEdit.setFrameShadow(QFrame.Shadow.Raised) + self.data_textEdit.setAutoFormatting(QTextEdit.AutoFormattingFlag.AutoAll) self.data_textEdit.setReadOnly(True) - self.data_textEdit.setObjectName("data_textEdit") + self.gridLayout_2.addWidget(self.data_textEdit, 2, 0, 1, 1) - self.verticalLayoutWidget_5 = QtWidgets.QWidget(parent=self.tab) - self.verticalLayoutWidget_5.setGeometry(QtCore.QRect(900, 390, 21, 132)) - self.verticalLayoutWidget_5.setObjectName("verticalLayoutWidget_5") - self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_5) - self.verticalLayout_5.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetMaximumSize) + + self.verticalLayoutWidget_5 = QWidget(self.tab) + self.verticalLayoutWidget_5.setObjectName(u"verticalLayoutWidget_5") + self.verticalLayoutWidget_5.setGeometry(QRect(900, 390, 21, 132)) + self.verticalLayout_5 = QVBoxLayout(self.verticalLayoutWidget_5) + self.verticalLayout_5.setObjectName(u"verticalLayout_5") + self.verticalLayout_5.setSizeConstraint(QLayout.SizeConstraint.SetMaximumSize) self.verticalLayout_5.setContentsMargins(0, 0, 0, 0) - self.verticalLayout_5.setObjectName("verticalLayout_5") - self.command_edit_1 = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_5) - self.command_edit_1.setMinimumSize(QtCore.QSize(19, 28)) - font = QtGui.QFont() + self.command_edit_1 = QPushButton(self.verticalLayoutWidget_5) + self.command_edit_1.setObjectName(u"command_edit_1") + self.command_edit_1.setMinimumSize(QSize(19, 28)) + font = QFont() font.setPointSize(8) self.command_edit_1.setFont(font) - self.command_edit_1.setObjectName("command_edit_1") + self.verticalLayout_5.addWidget(self.command_edit_1) - self.command_edit_2 = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_5) - self.command_edit_2.setMinimumSize(QtCore.QSize(19, 28)) - font = QtGui.QFont() - font.setPointSize(8) + + self.command_edit_2 = QPushButton(self.verticalLayoutWidget_5) + self.command_edit_2.setObjectName(u"command_edit_2") + self.command_edit_2.setMinimumSize(QSize(19, 28)) self.command_edit_2.setFont(font) - self.command_edit_2.setObjectName("command_edit_2") + self.verticalLayout_5.addWidget(self.command_edit_2) - self.command_edit_3 = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_5) - self.command_edit_3.setMinimumSize(QtCore.QSize(19, 28)) - font = QtGui.QFont() - font.setPointSize(8) + + self.command_edit_3 = QPushButton(self.verticalLayoutWidget_5) + self.command_edit_3.setObjectName(u"command_edit_3") + self.command_edit_3.setMinimumSize(QSize(19, 28)) self.command_edit_3.setFont(font) - self.command_edit_3.setObjectName("command_edit_3") + self.verticalLayout_5.addWidget(self.command_edit_3) - self.command_edit_4 = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_5) - self.command_edit_4.setMinimumSize(QtCore.QSize(19, 28)) - font = QtGui.QFont() - font.setPointSize(8) + + self.command_edit_4 = QPushButton(self.verticalLayoutWidget_5) + self.command_edit_4.setObjectName(u"command_edit_4") + self.command_edit_4.setMinimumSize(QSize(19, 28)) self.command_edit_4.setFont(font) - self.command_edit_4.setObjectName("command_edit_4") + self.verticalLayout_5.addWidget(self.command_edit_4) - self.verticalLayoutWidget_6 = QtWidgets.QWidget(parent=self.tab) - self.verticalLayoutWidget_6.setGeometry(QtCore.QRect(730, 390, 171, 121)) - self.verticalLayoutWidget_6.setObjectName("verticalLayoutWidget_6") - self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_6) + + self.verticalLayoutWidget_6 = QWidget(self.tab) + self.verticalLayoutWidget_6.setObjectName(u"verticalLayoutWidget_6") + self.verticalLayoutWidget_6.setGeometry(QRect(730, 390, 171, 121)) + self.verticalLayout_6 = QVBoxLayout(self.verticalLayoutWidget_6) + self.verticalLayout_6.setObjectName(u"verticalLayout_6") self.verticalLayout_6.setContentsMargins(0, 0, 0, 0) - self.verticalLayout_6.setObjectName("verticalLayout_6") - self.saved_command_1 = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_6) - self.saved_command_1.setObjectName("saved_command_1") + self.saved_command_1 = QPushButton(self.verticalLayoutWidget_6) + self.saved_command_1.setObjectName(u"saved_command_1") + self.verticalLayout_6.addWidget(self.saved_command_1) - self.saved_command_2 = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_6) - self.saved_command_2.setObjectName("saved_command_2") + + self.saved_command_2 = QPushButton(self.verticalLayoutWidget_6) + self.saved_command_2.setObjectName(u"saved_command_2") + self.verticalLayout_6.addWidget(self.saved_command_2) - self.saved_command_3 = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_6) - self.saved_command_3.setObjectName("saved_command_3") + + self.saved_command_3 = QPushButton(self.verticalLayoutWidget_6) + self.saved_command_3.setObjectName(u"saved_command_3") + self.verticalLayout_6.addWidget(self.saved_command_3) - self.saved_command_4 = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_6) - self.saved_command_4.setObjectName("saved_command_4") + + self.saved_command_4 = QPushButton(self.verticalLayoutWidget_6) + self.saved_command_4.setObjectName(u"saved_command_4") + self.verticalLayout_6.addWidget(self.saved_command_4) - self.verticalLayoutWidget_4 = QtWidgets.QWidget(parent=self.tab) - self.verticalLayoutWidget_4.setGeometry(QtCore.QRect(730, 260, 191, 131)) - self.verticalLayoutWidget_4.setObjectName("verticalLayoutWidget_4") - self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_4) + + self.verticalLayoutWidget_4 = QWidget(self.tab) + self.verticalLayoutWidget_4.setObjectName(u"verticalLayoutWidget_4") + self.verticalLayoutWidget_4.setGeometry(QRect(730, 260, 191, 131)) + self.verticalLayout_4 = QVBoxLayout(self.verticalLayoutWidget_4) + self.verticalLayout_4.setObjectName(u"verticalLayout_4") self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) - self.verticalLayout_4.setObjectName("verticalLayout_4") - self.label_11 = QtWidgets.QLabel(parent=self.verticalLayoutWidget_4) - self.label_11.setObjectName("label_11") + self.label_11 = QLabel(self.verticalLayoutWidget_4) + self.label_11.setObjectName(u"label_11") + self.verticalLayout_4.addWidget(self.label_11) - self.options_textEdit = QtWidgets.QTextEdit(parent=self.verticalLayoutWidget_4) - self.options_textEdit.setFrameShape(QtWidgets.QFrame.Shape.Box) - self.options_textEdit.setObjectName("options_textEdit") + + self.options_textEdit = QTextEdit(self.verticalLayoutWidget_4) + self.options_textEdit.setObjectName(u"options_textEdit") + self.options_textEdit.setFrameShape(QFrame.Shape.Box) + self.verticalLayout_4.addWidget(self.options_textEdit) - self.horizontalLayout_3 = QtWidgets.QHBoxLayout() - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.end_button = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_4) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - self.end_button.setFont(font) + + self.horizontalLayout_3 = QHBoxLayout() + self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") + self.end_button = QPushButton(self.verticalLayoutWidget_4) + self.end_button.setObjectName(u"end_button") + font1 = QFont() + font1.setPointSize(9) + font1.setBold(True) + self.end_button.setFont(font1) self.end_button.setAutoFillBackground(False) - self.end_button.setStyleSheet("background-color:qlineargradient(spread:pad, x1:0.409, y1:0, x2:0.430448, y2:1, stop:0 rgba(255, 0, 0, 255), stop:1 rgba(255, 255, 255, 255))") - self.end_button.setLocale(QtCore.QLocale(QtCore.QLocale.Language.English, QtCore.QLocale.Country.UnitedStates)) - self.end_button.setObjectName("end_button") + self.end_button.setStyleSheet(u"") + self.end_button.setLocale(QLocale(QLocale.English, QLocale.UnitedStates)) + self.horizontalLayout_3.addWidget(self.end_button) - self.start_button = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_4) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - self.start_button.setFont(font) + + self.start_button = QPushButton(self.verticalLayoutWidget_4) + self.start_button.setObjectName(u"start_button") + self.start_button.setFont(font1) self.start_button.setAutoFillBackground(False) - self.start_button.setStyleSheet("background-color:qlineargradient(spread:pad, x1:0.556, y1:0, x2:0.550444, y2:1, stop:0 rgba(0, 146, 0, 255), stop:1 rgba(255, 255, 255, 255))") - self.start_button.setObjectName("start_button") + self.start_button.setStyleSheet(u"") + self.horizontalLayout_3.addWidget(self.start_button) + + self.verticalLayout_4.addLayout(self.horizontalLayout_3) - self.formLayoutWidget_3 = QtWidgets.QWidget(parent=self.tab) - self.formLayoutWidget_3.setGeometry(QtCore.QRect(730, 230, 191, 21)) - self.formLayoutWidget_3.setObjectName("formLayoutWidget_3") - self.formLayout_3 = QtWidgets.QFormLayout(self.formLayoutWidget_3) + + self.formLayoutWidget_3 = QWidget(self.tab) + self.formLayoutWidget_3.setObjectName(u"formLayoutWidget_3") + self.formLayoutWidget_3.setGeometry(QRect(730, 230, 191, 21)) + self.formLayout_3 = QFormLayout(self.formLayoutWidget_3) + self.formLayout_3.setObjectName(u"formLayout_3") self.formLayout_3.setContentsMargins(0, 0, 0, 0) - self.formLayout_3.setObjectName("formLayout_3") - self.label_8 = QtWidgets.QLabel(parent=self.formLayoutWidget_3) - font = QtGui.QFont() - font.setFamily("Arial") - font.setPointSize(9) - font.setBold(False) - self.label_8.setFont(font) - self.label_8.setObjectName("label_8") - self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_8) - self.status_label = QtWidgets.QLabel(parent=self.formLayoutWidget_3) - font = QtGui.QFont() - font.setFamily("Arial") - font.setPointSize(9) - font.setBold(False) - self.status_label.setFont(font) - self.status_label.setStyleSheet("") - self.status_label.setObjectName("status_label") - self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.status_label) - self.formLayoutWidget_4 = QtWidgets.QWidget(parent=self.tab) - self.formLayoutWidget_4.setGeometry(QtCore.QRect(732, 28, 191, 231)) - self.formLayoutWidget_4.setObjectName("formLayoutWidget_4") - self.formLayout_4 = QtWidgets.QFormLayout(self.formLayoutWidget_4) + self.label_8 = QLabel(self.formLayoutWidget_3) + self.label_8.setObjectName(u"label_8") + font2 = QFont() + font2.setFamilies([u"Arial"]) + font2.setPointSize(9) + font2.setBold(False) + self.label_8.setFont(font2) + + self.formLayout_3.setWidget(0, QFormLayout.LabelRole, self.label_8) + + self.status_label = QLabel(self.formLayoutWidget_3) + self.status_label.setObjectName(u"status_label") + self.status_label.setFont(font2) + self.status_label.setStyleSheet(u"") + + self.formLayout_3.setWidget(0, QFormLayout.FieldRole, self.status_label) + + self.formLayoutWidget_4 = QWidget(self.tab) + self.formLayoutWidget_4.setObjectName(u"formLayoutWidget_4") + self.formLayoutWidget_4.setGeometry(QRect(732, 28, 191, 231)) + self.formLayout_4 = QFormLayout(self.formLayoutWidget_4) + self.formLayout_4.setObjectName(u"formLayout_4") self.formLayout_4.setContentsMargins(0, 0, 0, 0) - self.formLayout_4.setObjectName("formLayout_4") - self.label_16 = QtWidgets.QLabel(parent=self.formLayoutWidget_4) - self.label_16.setObjectName("label_16") - self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_16) - self.port_comboBox = QtWidgets.QComboBox(parent=self.formLayoutWidget_4) - self.port_comboBox.setObjectName("port_comboBox") - self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.port_comboBox) - self.label_17 = QtWidgets.QLabel(parent=self.formLayoutWidget_4) - self.label_17.setObjectName("label_17") - self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_17) - self.baudrate_comboBox = QtWidgets.QComboBox(parent=self.formLayoutWidget_4) - self.baudrate_comboBox.setObjectName("baudrate_comboBox") + self.label_16 = QLabel(self.formLayoutWidget_4) + self.label_16.setObjectName(u"label_16") + + self.formLayout_4.setWidget(0, QFormLayout.LabelRole, self.label_16) + + self.port_comboBox = QComboBox(self.formLayoutWidget_4) + self.port_comboBox.setObjectName(u"port_comboBox") + + self.formLayout_4.setWidget(0, QFormLayout.FieldRole, self.port_comboBox) + + self.label_17 = QLabel(self.formLayoutWidget_4) + self.label_17.setObjectName(u"label_17") + + self.formLayout_4.setWidget(1, QFormLayout.LabelRole, self.label_17) + + self.baudrate_comboBox = QComboBox(self.formLayoutWidget_4) self.baudrate_comboBox.addItem("") self.baudrate_comboBox.addItem("") self.baudrate_comboBox.addItem("") @@ -188,22 +231,30 @@ def setupUi(self, main_window): self.baudrate_comboBox.addItem("") self.baudrate_comboBox.addItem("") self.baudrate_comboBox.addItem("") - self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.baudrate_comboBox) - self.label_18 = QtWidgets.QLabel(parent=self.formLayoutWidget_4) - self.label_18.setObjectName("label_18") - self.formLayout_4.setWidget(2, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_18) - self.len_comboBox = QtWidgets.QComboBox(parent=self.formLayoutWidget_4) - self.len_comboBox.setObjectName("len_comboBox") + self.baudrate_comboBox.setObjectName(u"baudrate_comboBox") + + self.formLayout_4.setWidget(1, QFormLayout.FieldRole, self.baudrate_comboBox) + + self.label_18 = QLabel(self.formLayoutWidget_4) + self.label_18.setObjectName(u"label_18") + + self.formLayout_4.setWidget(2, QFormLayout.LabelRole, self.label_18) + + self.len_comboBox = QComboBox(self.formLayoutWidget_4) self.len_comboBox.addItem("") self.len_comboBox.addItem("") self.len_comboBox.addItem("") self.len_comboBox.addItem("") - self.formLayout_4.setWidget(2, QtWidgets.QFormLayout.ItemRole.FieldRole, self.len_comboBox) - self.label_19 = QtWidgets.QLabel(parent=self.formLayoutWidget_4) - self.label_19.setObjectName("label_19") - self.formLayout_4.setWidget(3, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_19) - self.timeout_comboBox = QtWidgets.QComboBox(parent=self.formLayoutWidget_4) - self.timeout_comboBox.setObjectName("timeout_comboBox") + self.len_comboBox.setObjectName(u"len_comboBox") + + self.formLayout_4.setWidget(2, QFormLayout.FieldRole, self.len_comboBox) + + self.label_19 = QLabel(self.formLayoutWidget_4) + self.label_19.setObjectName(u"label_19") + + self.formLayout_4.setWidget(3, QFormLayout.LabelRole, self.label_19) + + self.timeout_comboBox = QComboBox(self.formLayoutWidget_4) self.timeout_comboBox.addItem("") self.timeout_comboBox.addItem("") self.timeout_comboBox.addItem("") @@ -212,209 +263,262 @@ def setupUi(self, main_window): self.timeout_comboBox.addItem("") self.timeout_comboBox.addItem("") self.timeout_comboBox.addItem("") - self.formLayout_4.setWidget(3, QtWidgets.QFormLayout.ItemRole.FieldRole, self.timeout_comboBox) - self.label_20 = QtWidgets.QLabel(parent=self.formLayoutWidget_4) - self.label_20.setObjectName("label_20") - self.formLayout_4.setWidget(4, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_20) - self.parity_comboBox = QtWidgets.QComboBox(parent=self.formLayoutWidget_4) - self.parity_comboBox.setObjectName("parity_comboBox") + self.timeout_comboBox.setObjectName(u"timeout_comboBox") + + self.formLayout_4.setWidget(3, QFormLayout.FieldRole, self.timeout_comboBox) + + self.label_20 = QLabel(self.formLayoutWidget_4) + self.label_20.setObjectName(u"label_20") + + self.formLayout_4.setWidget(4, QFormLayout.LabelRole, self.label_20) + + self.parity_comboBox = QComboBox(self.formLayoutWidget_4) self.parity_comboBox.addItem("") self.parity_comboBox.addItem("") self.parity_comboBox.addItem("") self.parity_comboBox.addItem("") self.parity_comboBox.addItem("") - self.formLayout_4.setWidget(4, QtWidgets.QFormLayout.ItemRole.FieldRole, self.parity_comboBox) - self.label_21 = QtWidgets.QLabel(parent=self.formLayoutWidget_4) - self.label_21.setObjectName("label_21") - self.formLayout_4.setWidget(5, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_21) - self.bit_comboBox = QtWidgets.QComboBox(parent=self.formLayoutWidget_4) - self.bit_comboBox.setObjectName("bit_comboBox") + self.parity_comboBox.setObjectName(u"parity_comboBox") + + self.formLayout_4.setWidget(4, QFormLayout.FieldRole, self.parity_comboBox) + + self.label_21 = QLabel(self.formLayoutWidget_4) + self.label_21.setObjectName(u"label_21") + + self.formLayout_4.setWidget(5, QFormLayout.LabelRole, self.label_21) + + self.bit_comboBox = QComboBox(self.formLayoutWidget_4) self.bit_comboBox.addItem("") self.bit_comboBox.addItem("") self.bit_comboBox.addItem("") - self.formLayout_4.setWidget(5, QtWidgets.QFormLayout.ItemRole.FieldRole, self.bit_comboBox) - self.label_24 = QtWidgets.QLabel(parent=self.formLayoutWidget_4) - self.label_24.setObjectName("label_24") - self.formLayout_4.setWidget(6, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_24) - self.flow_comboBox = QtWidgets.QComboBox(parent=self.formLayoutWidget_4) - self.flow_comboBox.setObjectName("flow_comboBox") + self.bit_comboBox.setObjectName(u"bit_comboBox") + + self.formLayout_4.setWidget(5, QFormLayout.FieldRole, self.bit_comboBox) + + self.label_24 = QLabel(self.formLayoutWidget_4) + self.label_24.setObjectName(u"label_24") + + self.formLayout_4.setWidget(6, QFormLayout.LabelRole, self.label_24) + + self.flow_comboBox = QComboBox(self.formLayoutWidget_4) self.flow_comboBox.addItem("") self.flow_comboBox.addItem("") self.flow_comboBox.addItem("") self.flow_comboBox.addItem("") - self.formLayout_4.setWidget(6, QtWidgets.QFormLayout.ItemRole.FieldRole, self.flow_comboBox) - self.label_46 = QtWidgets.QLabel(parent=self.tab) - self.label_46.setGeometry(QtCore.QRect(740, 10, 151, 16)) - self.label_46.setObjectName("label_46") - self.refresh_button = QtWidgets.QPushButton(parent=self.tab) - self.refresh_button.setGeometry(QtCore.QRect(890, 0, 31, 28)) - self.refresh_button.setObjectName("refresh_button") - self.horizontalLayoutWidget = QtWidgets.QWidget(parent=self.tab) - self.horizontalLayoutWidget.setGeometry(QtCore.QRect(0, 520, 901, 31)) - self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") - self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget) - self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetNoConstraint) - self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.flow_comboBox.setObjectName(u"flow_comboBox") + + self.formLayout_4.setWidget(6, QFormLayout.FieldRole, self.flow_comboBox) + + self.label_46 = QLabel(self.tab) + self.label_46.setObjectName(u"label_46") + self.label_46.setGeometry(QRect(740, 10, 151, 16)) + self.refresh_button = QPushButton(self.tab) + self.refresh_button.setObjectName(u"refresh_button") + self.refresh_button.setGeometry(QRect(890, 0, 31, 28)) + self.horizontalLayoutWidget = QWidget(self.tab) + self.horizontalLayoutWidget.setObjectName(u"horizontalLayoutWidget") + self.horizontalLayoutWidget.setGeometry(QRect(0, 520, 901, 31)) + self.horizontalLayout = QHBoxLayout(self.horizontalLayoutWidget) self.horizontalLayout.setSpacing(1) - self.horizontalLayout.setObjectName("horizontalLayout") - self.send_data_text = QtWidgets.QTextEdit(parent=self.horizontalLayoutWidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum) - sizePolicy.setHorizontalStretch(5) - sizePolicy.setVerticalStretch(5) - sizePolicy.setHeightForWidth(self.send_data_text.sizePolicy().hasHeightForWidth()) - self.send_data_text.setSizePolicy(sizePolicy) - self.send_data_text.setMaximumSize(QtCore.QSize(465, 28)) - self.send_data_text.setFrameShape(QtWidgets.QFrame.Shape.Box) - self.send_data_text.setFrameShadow(QtWidgets.QFrame.Shadow.Plain) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.horizontalLayout.setSizeConstraint(QLayout.SizeConstraint.SetNoConstraint) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.send_data_text = QTextEdit(self.horizontalLayoutWidget) + self.send_data_text.setObjectName(u"send_data_text") + sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) + sizePolicy1.setHorizontalStretch(5) + sizePolicy1.setVerticalStretch(5) + sizePolicy1.setHeightForWidth(self.send_data_text.sizePolicy().hasHeightForWidth()) + self.send_data_text.setSizePolicy(sizePolicy1) + self.send_data_text.setMaximumSize(QSize(465, 28)) + self.send_data_text.setFrameShape(QFrame.Shape.Box) + self.send_data_text.setFrameShadow(QFrame.Shadow.Plain) self.send_data_text.setAcceptRichText(False) - self.send_data_text.setObjectName("send_data_text") + self.horizontalLayout.addWidget(self.send_data_text) - self.send_button = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget) - self.send_button.setObjectName("send_button") + + self.send_button = QPushButton(self.horizontalLayoutWidget) + self.send_button.setObjectName(u"send_button") + self.horizontalLayout.addWidget(self.send_button) - self.save_txt_button = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget) - self.save_txt_button.setObjectName("save_txt_button") + + self.save_txt_button = QPushButton(self.horizontalLayoutWidget) + self.save_txt_button.setObjectName(u"save_txt_button") + self.horizontalLayout.addWidget(self.save_txt_button) - self.view_change = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - self.view_change.setFont(font) - self.view_change.setObjectName("view_change") + + self.view_change = QPushButton(self.horizontalLayoutWidget) + self.view_change.setObjectName(u"view_change") + self.view_change.setFont(font1) + self.horizontalLayout.addWidget(self.view_change) - self.night_mode = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget) - self.night_mode.setObjectName("night_mode") + + self.night_mode = QPushButton(self.horizontalLayoutWidget) + self.night_mode.setObjectName(u"night_mode") + self.horizontalLayout.addWidget(self.night_mode) - self.clear_buffer_button = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget) - self.clear_buffer_button.setObjectName("clear_buffer_button") + + self.clear_buffer_button = QPushButton(self.horizontalLayoutWidget) + self.clear_buffer_button.setObjectName(u"clear_buffer_button") + self.horizontalLayout.addWidget(self.clear_buffer_button) + self.tabWidget.addTab(self.tab, "") - self.tab_2 = QtWidgets.QWidget() - self.tab_2.setObjectName("tab_2") - self.textEdit_3 = QtWidgets.QTextEdit(parent=self.tab_2) - self.textEdit_3.setGeometry(QtCore.QRect(10, 10, 911, 491)) + self.tab_2 = QWidget() + self.tab_2.setObjectName(u"tab_2") + self.textEdit_3 = QTextEdit(self.tab_2) + self.textEdit_3.setObjectName(u"textEdit_3") + self.textEdit_3.setGeometry(QRect(10, 10, 911, 491)) self.textEdit_3.setUndoRedoEnabled(False) self.textEdit_3.setReadOnly(True) self.textEdit_3.setAcceptRichText(False) - self.textEdit_3.setObjectName("textEdit_3") - self.label_3 = QtWidgets.QLabel(parent=self.tab_2) - self.label_3.setGeometry(QtCore.QRect(590, 530, 101, 16)) - self.label_3.setObjectName("label_3") - self.label_2 = QtWidgets.QLabel(parent=self.tab_2) - self.label_2.setGeometry(QtCore.QRect(150, 530, 331, 16)) + self.label_3 = QLabel(self.tab_2) + self.label_3.setObjectName(u"label_3") + self.label_3.setGeometry(QRect(590, 530, 101, 16)) + self.label_2 = QLabel(self.tab_2) + self.label_2.setObjectName(u"label_2") + self.label_2.setGeometry(QRect(150, 530, 331, 16)) self.label_2.setOpenExternalLinks(True) - self.label_2.setObjectName("label_2") self.tabWidget.addTab(self.tab_2, "") main_window.setCentralWidget(self.centralwidget) - self.actionAna_Ekran = QtGui.QAction(parent=main_window) - self.actionAna_Ekran.setObjectName("actionAna_Ekran") - self.actionHelp = QtGui.QAction(parent=main_window) - self.actionHelp.setObjectName("actionHelp") self.retranslateUi(main_window) + self.tabWidget.setCurrentIndex(0) - QtCore.QMetaObject.connectSlotsByName(main_window) + + + QMetaObject.connectSlotsByName(main_window) + # setupUi def retranslateUi(self, main_window): - _translate = QtCore.QCoreApplication.translate - main_window.setWindowTitle(_translate("main_window", "AFCOM Client (A free COM port data transfer client)")) - main_window.setStatusTip(_translate("main_window", "Mehmet Cagri Aksoy")) - main_window.setWhatsThis(_translate("main_window", "Serial Communication Program Mehmet Cagri Aksoy")) - self.label_23.setText(_translate("main_window", "Gathering Data (Rx)")) - self.command_edit_1.setText(_translate("main_window", "...")) - self.command_edit_2.setText(_translate("main_window", "...")) - self.command_edit_3.setText(_translate("main_window", "...")) - self.command_edit_4.setText(_translate("main_window", "...")) - self.saved_command_1.setText(_translate("main_window", "Command 1")) - self.saved_command_2.setText(_translate("main_window", "Command 2")) - self.saved_command_3.setText(_translate("main_window", "Command 3")) - self.saved_command_4.setText(_translate("main_window", "Command 4")) - self.label_11.setText(_translate("main_window", "Connection Options:")) - self.end_button.setText(_translate("main_window", "STOP")) - self.start_button.setText(_translate("main_window", "START")) - self.label_8.setText(_translate("main_window", "Port Status :")) - self.status_label.setText(_translate("main_window", "Not Connected")) - self.label_16.setText(_translate("main_window", "Selected Port:")) - self.label_17.setText(_translate("main_window", "Baud Rate:")) - self.baudrate_comboBox.setItemText(0, _translate("main_window", "9600")) - self.baudrate_comboBox.setItemText(1, _translate("main_window", "57600")) - self.baudrate_comboBox.setItemText(2, _translate("main_window", "115200")) - self.baudrate_comboBox.setItemText(3, _translate("main_window", "110")) - self.baudrate_comboBox.setItemText(4, _translate("main_window", "300")) - self.baudrate_comboBox.setItemText(5, _translate("main_window", "1200")) - self.baudrate_comboBox.setItemText(6, _translate("main_window", "2400")) - self.baudrate_comboBox.setItemText(7, _translate("main_window", "4800")) - self.baudrate_comboBox.setItemText(8, _translate("main_window", "19200")) - self.baudrate_comboBox.setItemText(9, _translate("main_window", "38400")) - self.label_18.setText(_translate("main_window", "Length (B):")) - self.len_comboBox.setItemText(0, _translate("main_window", "8")) - self.len_comboBox.setItemText(1, _translate("main_window", "7")) - self.len_comboBox.setItemText(2, _translate("main_window", "6")) - self.len_comboBox.setItemText(3, _translate("main_window", "5")) - self.label_19.setText(_translate("main_window", "Timeout:")) - self.timeout_comboBox.setItemText(0, _translate("main_window", "2")) - self.timeout_comboBox.setItemText(1, _translate("main_window", "3")) - self.timeout_comboBox.setItemText(2, _translate("main_window", "4")) - self.timeout_comboBox.setItemText(3, _translate("main_window", "5")) - self.timeout_comboBox.setItemText(4, _translate("main_window", "10")) - self.timeout_comboBox.setItemText(5, _translate("main_window", "30")) - self.timeout_comboBox.setItemText(6, _translate("main_window", "50")) - self.timeout_comboBox.setItemText(7, _translate("main_window", "100")) - self.label_20.setText(_translate("main_window", "Parity:")) - self.parity_comboBox.setItemText(0, _translate("main_window", "None")) - self.parity_comboBox.setItemText(1, _translate("main_window", "Even")) - self.parity_comboBox.setItemText(2, _translate("main_window", "Odd")) - self.parity_comboBox.setItemText(3, _translate("main_window", "Mark")) - self.parity_comboBox.setItemText(4, _translate("main_window", "Space")) - self.label_21.setText(_translate("main_window", "StopBits:")) - self.bit_comboBox.setItemText(0, _translate("main_window", "1")) - self.bit_comboBox.setItemText(1, _translate("main_window", "1.5")) - self.bit_comboBox.setItemText(2, _translate("main_window", "2")) - self.label_24.setText(_translate("main_window", "Flow Control:")) - self.flow_comboBox.setItemText(0, _translate("main_window", "None")) - self.flow_comboBox.setItemText(1, _translate("main_window", "Xon/Xoff")) - self.flow_comboBox.setItemText(2, _translate("main_window", "RTS/CTS")) - self.flow_comboBox.setItemText(3, _translate("main_window", "DSR/DTR")) - self.label_46.setText(_translate("main_window", "Settings: Refresh:")) - self.refresh_button.setText(_translate("main_window", "↻")) - self.send_data_text.setPlaceholderText(_translate("main_window", "Please enter the data want to sent...")) - self.send_button.setText(_translate("main_window", "SEND")) - self.save_txt_button.setToolTip(_translate("main_window", "Save the output")) - self.save_txt_button.setStatusTip(_translate("main_window", "Save the output")) - self.save_txt_button.setWhatsThis(_translate("main_window", "Save the output")) - self.save_txt_button.setText(_translate("main_window", "Save as .txt")) - self.view_change.setToolTip(_translate("main_window", "Click Here to go to the Simple View")) - self.view_change.setStatusTip(_translate("main_window", "Click Here to go to the Simple View")) - self.view_change.setWhatsThis(_translate("main_window", "Click Here to go to the Simple View")) - self.view_change.setText(_translate("main_window", "<<")) - self.night_mode.setText(_translate("main_window", "🌘 Night Mode")) - self.clear_buffer_button.setText(_translate("main_window", "Clear Buffer")) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("main_window", "Main Page")) - self.textEdit_3.setHtml(_translate("main_window", "\n" + main_window.setWindowTitle(QCoreApplication.translate("main_window", u"AFCOM Client (A free COM port data transfer client)", None)) +#if QT_CONFIG(statustip) + main_window.setStatusTip(QCoreApplication.translate("main_window", u"Mehmet Cagri Aksoy", None)) +#endif // QT_CONFIG(statustip) +#if QT_CONFIG(whatsthis) + main_window.setWhatsThis(QCoreApplication.translate("main_window", u"Serial Communication Program Mehmet Cagri Aksoy", None)) +#endif // QT_CONFIG(whatsthis) + self.actionAna_Ekran.setText(QCoreApplication.translate("main_window", u"Ana Ekran", None)) + self.actionHelp.setText(QCoreApplication.translate("main_window", u"Help", None)) + self.label_23.setText(QCoreApplication.translate("main_window", u"Gathering Data (Rx)", None)) + self.command_edit_1.setText(QCoreApplication.translate("main_window", u"...", None)) + self.command_edit_2.setText(QCoreApplication.translate("main_window", u"...", None)) + self.command_edit_3.setText(QCoreApplication.translate("main_window", u"...", None)) + self.command_edit_4.setText(QCoreApplication.translate("main_window", u"...", None)) + self.saved_command_1.setText(QCoreApplication.translate("main_window", u"Command 1", None)) + self.saved_command_2.setText(QCoreApplication.translate("main_window", u"Command 2", None)) + self.saved_command_3.setText(QCoreApplication.translate("main_window", u"Command 3", None)) + self.saved_command_4.setText(QCoreApplication.translate("main_window", u"Command 4", None)) + self.label_11.setText(QCoreApplication.translate("main_window", u"Connection Options:", None)) + self.end_button.setText(QCoreApplication.translate("main_window", u"STOP", None)) + self.start_button.setText(QCoreApplication.translate("main_window", u"START", None)) + self.label_8.setText(QCoreApplication.translate("main_window", u"Port Status :", None)) + self.status_label.setText(QCoreApplication.translate("main_window", u"Not Connected", None)) + self.label_16.setText(QCoreApplication.translate("main_window", u"Selected Port:", None)) + self.label_17.setText(QCoreApplication.translate("main_window", u"Baud Rate:", None)) + self.baudrate_comboBox.setItemText(0, QCoreApplication.translate("main_window", u"9600", None)) + self.baudrate_comboBox.setItemText(1, QCoreApplication.translate("main_window", u"57600", None)) + self.baudrate_comboBox.setItemText(2, QCoreApplication.translate("main_window", u"115200", None)) + self.baudrate_comboBox.setItemText(3, QCoreApplication.translate("main_window", u"110", None)) + self.baudrate_comboBox.setItemText(4, QCoreApplication.translate("main_window", u"300", None)) + self.baudrate_comboBox.setItemText(5, QCoreApplication.translate("main_window", u"1200", None)) + self.baudrate_comboBox.setItemText(6, QCoreApplication.translate("main_window", u"2400", None)) + self.baudrate_comboBox.setItemText(7, QCoreApplication.translate("main_window", u"4800", None)) + self.baudrate_comboBox.setItemText(8, QCoreApplication.translate("main_window", u"19200", None)) + self.baudrate_comboBox.setItemText(9, QCoreApplication.translate("main_window", u"38400", None)) + + self.label_18.setText(QCoreApplication.translate("main_window", u"Length (B):", None)) + self.len_comboBox.setItemText(0, QCoreApplication.translate("main_window", u"8", None)) + self.len_comboBox.setItemText(1, QCoreApplication.translate("main_window", u"7", None)) + self.len_comboBox.setItemText(2, QCoreApplication.translate("main_window", u"6", None)) + self.len_comboBox.setItemText(3, QCoreApplication.translate("main_window", u"5", None)) + + self.label_19.setText(QCoreApplication.translate("main_window", u"Timeout:", None)) + self.timeout_comboBox.setItemText(0, QCoreApplication.translate("main_window", u"2", None)) + self.timeout_comboBox.setItemText(1, QCoreApplication.translate("main_window", u"3", None)) + self.timeout_comboBox.setItemText(2, QCoreApplication.translate("main_window", u"4", None)) + self.timeout_comboBox.setItemText(3, QCoreApplication.translate("main_window", u"5", None)) + self.timeout_comboBox.setItemText(4, QCoreApplication.translate("main_window", u"10", None)) + self.timeout_comboBox.setItemText(5, QCoreApplication.translate("main_window", u"30", None)) + self.timeout_comboBox.setItemText(6, QCoreApplication.translate("main_window", u"50", None)) + self.timeout_comboBox.setItemText(7, QCoreApplication.translate("main_window", u"100", None)) + + self.label_20.setText(QCoreApplication.translate("main_window", u"Parity:", None)) + self.parity_comboBox.setItemText(0, QCoreApplication.translate("main_window", u"None", None)) + self.parity_comboBox.setItemText(1, QCoreApplication.translate("main_window", u"Even", None)) + self.parity_comboBox.setItemText(2, QCoreApplication.translate("main_window", u"Odd", None)) + self.parity_comboBox.setItemText(3, QCoreApplication.translate("main_window", u"Mark", None)) + self.parity_comboBox.setItemText(4, QCoreApplication.translate("main_window", u"Space", None)) + + self.label_21.setText(QCoreApplication.translate("main_window", u"StopBits:", None)) + self.bit_comboBox.setItemText(0, QCoreApplication.translate("main_window", u"1", None)) + self.bit_comboBox.setItemText(1, QCoreApplication.translate("main_window", u"1.5", None)) + self.bit_comboBox.setItemText(2, QCoreApplication.translate("main_window", u"2", None)) + + self.label_24.setText(QCoreApplication.translate("main_window", u"Flow Control:", None)) + self.flow_comboBox.setItemText(0, QCoreApplication.translate("main_window", u"None", None)) + self.flow_comboBox.setItemText(1, QCoreApplication.translate("main_window", u"Xon/Xoff", None)) + self.flow_comboBox.setItemText(2, QCoreApplication.translate("main_window", u"RTS/CTS", None)) + self.flow_comboBox.setItemText(3, QCoreApplication.translate("main_window", u"DSR/DTR", None)) + + self.label_46.setText(QCoreApplication.translate("main_window", u"Settings: Refresh:", None)) + self.refresh_button.setText(QCoreApplication.translate("main_window", u"\u21bb", None)) + self.send_data_text.setPlaceholderText(QCoreApplication.translate("main_window", u"Please enter the data want to sent...", None)) + self.send_button.setText(QCoreApplication.translate("main_window", u"SEND", None)) +#if QT_CONFIG(tooltip) + self.save_txt_button.setToolTip(QCoreApplication.translate("main_window", u"Save the output", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(statustip) + self.save_txt_button.setStatusTip(QCoreApplication.translate("main_window", u"Save the output", None)) +#endif // QT_CONFIG(statustip) +#if QT_CONFIG(whatsthis) + self.save_txt_button.setWhatsThis(QCoreApplication.translate("main_window", u"Save the output", None)) +#endif // QT_CONFIG(whatsthis) + self.save_txt_button.setText(QCoreApplication.translate("main_window", u"Save as .txt", None)) +#if QT_CONFIG(tooltip) + self.view_change.setToolTip(QCoreApplication.translate("main_window", u"Click Here to go to the Simple View", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(statustip) + self.view_change.setStatusTip(QCoreApplication.translate("main_window", u"Click Here to go to the Simple View", None)) +#endif // QT_CONFIG(statustip) +#if QT_CONFIG(whatsthis) + self.view_change.setWhatsThis(QCoreApplication.translate("main_window", u"Click Here to go to the Simple View", None)) +#endif // QT_CONFIG(whatsthis) + self.view_change.setText(QCoreApplication.translate("main_window", u"<<", None)) + self.night_mode.setText(QCoreApplication.translate("main_window", u"\ud83c\udf18 Night Mode", None)) + self.clear_buffer_button.setText(QCoreApplication.translate("main_window", u"Clear Buffer", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("main_window", u"Main Page", None)) + self.textEdit_3.setHtml(QCoreApplication.translate("main_window", u"\n" "\n" +"\n" "

Information

\n" "


\n" -"

The AFCOM (aka Serial communication GUI program) tool is a software application that allows users to send and receive data via the serial port (COM port) of their computer. The tool can be used for various purposes, such as testing, debugging, or communicating with other devices that use the serial protocol.

\n" +"

The AFCOM (aka Serial communication GUI program) tool is a software application that allows users to send and receive data via the serial port (COM port) of their computer. The tool can be used for various purposes, such as testing, debugging, or communicating with other devices that use the serial protocol.

\n" "


\n" "

Features

\n" "


\n" -"

The COM port tool has the following features: It supports multiple COM ports and can detect the available ports automatically. It allows users to configure the parameters of the serial communication, such as baud rate. It provides a user-friendly interface that shows the transmitted and received data in hexadecimal, decimal, ASCII, or binary formats. It allows users to save and load the data to and from files.

\n" +"

The COM port tool has the following features: It supports multiple COM ports and can detect the available ports automatically. It allows users to configure the parameters of the serial communication, such as baud rate. It provides a user-friendly interface that shows the transmitted and received data in hexadecimal, decimal, ASCII, or binary formats. It allows users to save and load the data to and from files.

\n" "


\n" "


\n" -"


\n" +"


\n" "


\n" "

Legal Information

\n" "

This application incorporates Qt for Python (PySide), which is licensed under the GNU Lesser General Public License version 3 (LGPLv3). By using this software, you agree to comply with the terms of the LGPLv3 license. For more information about Qt for Python, visit https://www.qt.io/qt-for-python. A copy of the LGPLv3 license is included with this application.

\n" -"


\n" -"


")) - self.label_3.setText(_translate("main_window", "Version 2024.12")) - self.label_2.setToolTip(_translate("main_window", "

Github

")) - self.label_2.setText(_translate("main_window", "

Feel free to ask any questions or bug report on Github

")) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("main_window", "About")) - self.actionAna_Ekran.setText(_translate("main_window", "Ana Ekran")) - self.actionHelp.setText(_translate("main_window", "Help")) +"


\n" +"


", None)) + self.label_3.setText(QCoreApplication.translate("main_window", u"Version 2024.12", None)) +#if QT_CONFIG(tooltip) + self.label_2.setToolTip(QCoreApplication.translate("main_window", u"

Github

", None)) +#endif // QT_CONFIG(tooltip) + self.label_2.setText(QCoreApplication.translate("main_window", u"

Feel free to ask any questions or bug report on Github

", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("main_window", u"About", None)) + # retranslateUi + From 86532a8c344aa2f7b961c33990e51f462e6a2429 Mon Sep 17 00:00:00 2001 From: mcagriaksoy Date: Sat, 19 Apr 2025 12:11:33 +0200 Subject: [PATCH 2/3] v1.4.0 changes, ui updated, new functionality, better theme handling --- README.md | 40 +- img/Screenshot_v2024_07_2.jpg | Bin 130153 -> 0 bytes img/Screenshot_v2025_04.jpg | Bin 0 -> 53920 bytes src/ui_main.py | 117 +-- ui/config.ui | 310 ++++++++ ui/help.ui | 64 ++ ui/main_window.ui | 1371 +++++++++++++++------------------ 7 files changed, 1071 insertions(+), 831 deletions(-) delete mode 100644 img/Screenshot_v2024_07_2.jpg create mode 100644 img/Screenshot_v2025_04.jpg create mode 100644 ui/config.ui create mode 100644 ui/help.ui diff --git a/README.md b/README.md index b86df2d..3004bed 100644 --- a/README.md +++ b/README.md @@ -38,20 +38,13 @@ The COM port tool is compatible with: [![OS - Linux](https://img.shields.io/badge/OS-Linux-blue?logo=linux&logoColor=white)](https://www.linux.org/ "Go to Linux homepage") [![OS - Windows](https://img.shields.io/badge/OS-Windows-blue?logo=windows&logoColor=white)](https://www.microsoft.com/ "Go to Microsoft homepage") -To use the tool, follow these steps: -First of all, please ensure that you installed dependencies already. +1. Run the program. +2. Select a serial port and configure parameters. +3. Start communication using the **Start** button. +4. Send or receive data as needed. +5. Save received data or clear buffers using the respective buttons. -``` -python main.py -``` - -Then the project can be run with: - -``` -pip install -r requirements.txt -``` - -![Project SS](https://github.com/mcagriaksoy/Serial-Communication-GUI-Program/blob/master/img/Screenshot_v2024_07_2.jpg) +![Project SS](https://github.com/mcagriaksoy/Serial-Communication-GUI-Program/blob/master/img/Screenshot_v2025_04.jpg) If you encounter any problems while using the COM port tool, try these solutions: @@ -62,9 +55,9 @@ If you have any questions or feedback, please contact me. ## Dependencies -[![PyQt - >= 6.0](https://img.shields.io/badge/PyQt->_6.0-2ea44f)](https://wiki.python.org/moin/PyQt) -[![PyQt_sip - >= 13.0](https://img.shields.io/badge/PyQt_sip->_13.0-2ea44f)](https://pypi.org/project/PyQt6-sip/) -[![PySerial - >= 3.0](https://img.shields.io/badge/PyQt->_3.0-2ea44f)](https://pypi.org/project/pyserial/) +[![PySide - >= 6.0](https://img.shields.io/badge/PySide->_6.0-2ea44f)](https://wiki.python.org/moin/PySide) +[![PySide_sip - >= 13.0](https://img.shields.io/badge/PySide_sip->_13.0-2ea44f)](https://pypi.org/project/PySide6-sip/) +[![PySerial - >= 3.0](https://img.shields.io/badge/PySide->_3.0-2ea44f)](https://pypi.org/project/pyserial/)

Documentation

@@ -79,6 +72,21 @@ pyinstaller --noconfirm --onefile --windowed --icon "ui/icon.ico" "src/main.py" ``` +## Changes + +### V1.4.0 - 2025 Update + +Feature: Added basic_view_enabled and advanced_view_enabled methods to toggle UI layouts visibility. +Implemented start_loop and stop_loop for managing serial communication with threading. +Added on_save_txt_button_clicked to save received data to a .txt file. + +Improvement: Enhanced error handling for serial communication and worker threads. +Added visual feedback for serial port selection and connection status. + +Bug Fix: Fixed UI responsiveness during active serial communication. + +Refactor: Organized serial communication logic into reusable methods. +

License

Released under GNU General Public License v3.0 by @mcagriaksoy. diff --git a/img/Screenshot_v2024_07_2.jpg b/img/Screenshot_v2024_07_2.jpg deleted file mode 100644 index 2d69dd359d1a38f6963fc90cf2a3fc422740c565..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130153 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 diff --git a/img/Screenshot_v2025_04.jpg b/img/Screenshot_v2025_04.jpg new file mode 100644 index 0000000000000000000000000000000000000000..61fd922618ca66568b8158069da4cdc7d596afdb GIT binary patch literal 53920 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 literal 0 HcmV?d00001 diff --git a/src/ui_main.py b/src/ui_main.py index 4735478..5d4ff2c 100644 --- a/src/ui_main.py +++ b/src/ui_main.py @@ -6,9 +6,9 @@ __author__ = 'Mehmet Cagri Aksoy - github.com/mcagriaksoy' __annotations__ = 'AFCOM - Serial Communication GUI Program' -__version__ = '2024.12' +__version__ = '2025 - 1.4.0.0' __license__ = 'JGPLv3' -__status__ = 'Research' +__status__ = 'Development' # IMPORTS from os import path, system @@ -42,8 +42,20 @@ SERIAL_DEVICE = Serial() PORTS = [] is_serial_port_established = False -nightModeEnabled = False -simpleViewEnabled = False + +from winreg import OpenKey, HKEY_CURRENT_USER, QueryValueEx, ConnectRegistry, KEY_READ, KEY_WOW64_64KEY + +def is_windows_dark_mode(self): + try: + registry = ConnectRegistry(None, HKEY_CURRENT_USER) + registry_key = OpenKey(registry, r'Software\Microsoft\Windows\CurrentVersion\Themes\Personalize') + value, _ = QueryValueEx(registry_key, 'AppsUseLightTheme') + return value == 0 # 0 means dark mode is enabled + except WindowsError: + return False + +# simpleViewEnabled = False + def get_serial_port(): """ Lists serial port names @@ -102,6 +114,7 @@ class MainWindow(QMainWindow): def __init__(self): """ Initialize Main Window """ super(MainWindow, self).__init__() + if PROGRAM_TYPE_DEBUG: file_path = path.join("ui/main_window.ui") @@ -117,6 +130,10 @@ def __init__(self): print("UI File Found!") self.ui= Ui_main_window() self.ui.setupUi(self) + + if (is_windows_dark_mode(self)): + print("Windows Dark Mode is enabled!") + # todo add dark mode support for the UI PORTS = get_serial_port() @@ -125,7 +142,7 @@ def __init__(self): self.ui.start_button.clicked.connect(self.start_loop) self.ui.refresh_button.clicked.connect(self.refresh_port) - + ''' self.ui.command_edit_1.clicked.connect(self.command1) self.ui.command_edit_2.clicked.connect(self.command2) self.ui.command_edit_3.clicked.connect(self.command3) @@ -135,49 +152,50 @@ def __init__(self): self.ui.saved_command_2.clicked.connect(self.move_command2_to_text) self.ui.saved_command_3.clicked.connect(self.move_command3_to_text) self.ui.saved_command_4.clicked.connect(self.move_command4_to_text) + ''' - self.ui.clear_buffer_button.clicked.connect(self.clear_buffer) + # When actionClear_Cache is triggered, clear the buffer + self.ui.actionClear_Cache.triggered.connect(self.clear_buffer) - self.ui.night_mode.clicked.connect(self.night_mode_clicked) - self.ui.view_change.clicked.connect(self.view_changes) + self.ui.actionBasic_View.triggered.connect(self.basic_view_enabled) + self.ui.actionAdvanced_View.triggered.connect(self.advanced_view_enabled) + #self.ui.clear_buffer_button.clicked.connect(self.clear_buffer) - self.ui.port_comboBox.addItems(PORTS) + # self.ui.view_change.clicked.connect(self.view_changes) + self.ui.port_comboBox.addItems(PORTS) self.ui.send_button.clicked.connect(self.on_send_data_button_clicked) - self.ui.end_button.clicked.connect(self.on_end_button_clicked) + def basic_view_enabled(self): + """ Hide specific layouts in the UI for basic view """ + # Hide all widgets in the verticalLayout_config + for i in range(self.ui.verticalLayout_config.count()): + widget = self.ui.verticalLayout_config.itemAt(i).widget() + if widget: + widget.setVisible(False) + + # Optionally, hide all widgets in the formLayout_config + for i in range(self.ui.formLayout_config.count()): + widget = self.ui.formLayout_config.itemAt(i).widget() + if widget: + widget.setVisible(False) - def view_changes(self): - """ Change the window size """ - global simpleViewEnabled - # Change the window size - if simpleViewEnabled == False: - self.resize(726, 580) - self.ui.view_change.setText(">>") - simpleViewEnabled = True - else: - self.resize(929, 580) - self.ui.view_change.setText("<<") - simpleViewEnabled = False - - def night_mode_clicked(self): - """ Night Mode """ - #define static variable - global nightModeEnabled - - # Invert all colors - if nightModeEnabled == False: - self.setStyleSheet("background-color: #2C2F33; color: #FFFFFF;") - self.ui.night_mode.setText("🌘 Day Mode") - self.ui.tabWidget.setStyleSheet("QWidget { background-color: #2C2F33; color: #FFFFFF; } QTabBar::tab { background: #2C2F33; color: #FFFFFF; }") - nightModeEnabled = True - else: - self.setStyleSheet("background-color: #FFFFFF; color: #000000;") - self.ui.night_mode.setText("🌘 Night Mode") - self.ui.tabWidget.setStyleSheet("QWidget { background-color: #FFFFFF; color: #000000; } QTabBar::tab { background: #FFFFFF; color: #000000; }") - nightModeEnabled = False - + def advanced_view_enabled(self): + """ Show specific layouts in the UI for advanced view """ + # Show all widgets in the verticalLayout_config + for i in range(self.ui.verticalLayout_config.count()): + widget = self.ui.verticalLayout_config.itemAt(i).widget() + if widget: + widget.setVisible(True) + + # Optionally, show all widgets in the formLayout_config + for i in range(self.ui.formLayout_config.count()): + widget = self.ui.formLayout_config.itemAt(i).widget() + if widget: + widget.setVisible(True) + + ''' def command1(self): """ Open the text input popup to save command for button 1 """ self.command_edit(1) @@ -228,7 +246,7 @@ def move_command4_to_text(self): """ Move the saved command to the text box """ self.ui.send_data_text.setText(self.ui.saved_command_4.text()) self.on_send_data_button_clicked() - + ''' def refresh_port(self): """ Refresh the serial port list """ PORTS = get_serial_port() @@ -318,10 +336,20 @@ def start_loop(self): return global is_serial_port_established + + if (is_serial_port_established == True): + is_serial_port_established = False + self.on_end_button_clicked() + self.ui.start_button.setText("START") + return + is_serial_port_established = True + # change start_button to stop button + self.ui.start_button.setText("STOP") + try: self.worker = Worker() # a new worker to perform those tasks - self.thread = QThread() # a new thread to run our background tasks in + self.thread = QThread() # a new thread to run our background tasks in # move the worker into the thread, do this first before connecting the signals self.worker.moveToThread(self.thread) # begin our worker object's loop when the thread starts running @@ -337,6 +365,8 @@ def start_loop(self): self.thread.finished.connect(self.thread.deleteLater) # start the thread self.thread.start() + + except RuntimeError: self.print_message_on_screen("Exception in Worker Thread!") @@ -347,12 +377,12 @@ def stop_loop(self): # Disconnect the serial port and close it SERIAL_DEVICE.close() - def clear_buffer(self): """ Clear the buffer """ self.ui.data_textEdit.clear() self.ui.send_data_text.clear() + def read_data_from_thread(self, serial_data): """ Write the result to the text edit box""" # self.ui.data_textEdit.append("{}".format(i)) @@ -423,5 +453,4 @@ def start_ui_design(): """ Start the UI Design """ app = QApplication(argv) # Create an instance window_object = MainWindow() # Create an instance of our class - window_object.show() exit(app.exec()) diff --git a/ui/config.ui b/ui/config.ui new file mode 100644 index 0000000..6a22fbe --- /dev/null +++ b/ui/config.ui @@ -0,0 +1,310 @@ + + + Form + + + + 0 + 0 + 206 + 280 + + + + Form + + + + + 18 + 12 + 151 + 16 + + + + Settings: Refresh: + + + + + + 168 + 2 + 31 + 28 + + + + + + + + + + 10 + 40 + 191 + 231 + + + + + + + Selected Port: + + + + + + + + + + Baud Rate: + + + + + + + + 9600 + + + + + 57600 + + + + + 115200 + + + + + 110 + + + + + 300 + + + + + 1200 + + + + + 2400 + + + + + 4800 + + + + + 19200 + + + + + 38400 + + + + + + + + Length (B): + + + + + + + + 8 + + + + + 7 + + + + + 6 + + + + + 5 + + + + + + + + Timeout: + + + + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 10 + + + + + 30 + + + + + 50 + + + + + 100 + + + + + + + + Parity: + + + + + + + + None + + + + + Even + + + + + Odd + + + + + Mark + + + + + Space + + + + + + + + StopBits: + + + + + + + + 1 + + + + + 1.5 + + + + + 2 + + + + + + + + Flow Control: + + + + + + + + None + + + + + Xon/Xoff + + + + + RTS/CTS + + + + + DSR/DTR + + + + + + + + Save All + + + + + + + + + diff --git a/ui/help.ui b/ui/help.ui new file mode 100644 index 0000000..bf20954 --- /dev/null +++ b/ui/help.ui @@ -0,0 +1,64 @@ + + + Dialog + + + + 0 + 0 + 765 + 397 + + + + Dialog + + + + + 10 + 10 + 751 + 341 + + + + false + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:12pt; font-weight:696;">Information</span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:12pt;">The AFCOM (also known as Serial communication GUI program) tool is a software application that allows users to send and receive data via the serial port (COM port) of their computer. The tool can be used for various purposes, such as testing, debugging, or communicating with other devices that use the serial protocol. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:12pt; font-weight:696;">Features</span><span style=" font-family:'Segoe UI'; font-size:12pt;"> </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:12pt;">The COM port tool has the following features: It supports multiple COM ports and can detect the available ports automatically. It allows users to configure the parameters of the serial communication, such as baud rate. It provides a user-friendly interface that shows the transmitted and received data in hexadecimal, decimal, ASCII, or binary formats. It allows users to save and load the data to and from files.</span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:12pt; font-weight:696;">Legal Information</span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:12pt;">This application incorporates Qt for Python (PySide), which is licensed under the GNU Lesser General Public License version 3 (LGPLv3). By using this software, you agree to comply with the terms of the LGPLv3 license. For more information about Qt for Python, visit https://www.qt.io/qt-for-python. A copy of the LGPLv3 license is included with this application.</span></p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p></body></html> + + + false + + + + + + 150 + 360 + 491 + 16 + + + + AFCOM Client v1.4.0.0 (C) 2020 - 2025 Author: Mehmet Cagri Aksoy github.com/mcagriaksoy + + + + + + diff --git a/ui/main_window.ui b/ui/main_window.ui index 68146c8..33968c0 100644 --- a/ui/main_window.ui +++ b/ui/main_window.ui @@ -6,8 +6,8 @@ 0 0 - 929 - 579 + 1127 + 633 @@ -18,14 +18,14 @@ - 600 - 579 + 0 + 0 - 929 - 579 + 9290 + 4095 @@ -48,775 +48,564 @@ Serial Communication Program Mehmet Cagri Aksoy - - - - 0 - 0 - 931 - 581 - + + + + + + + + 5 + 5 + + + + + 5000 + 28 + + + + QFrame::Box + + + QFrame::Sunken + + + false + + + Please enter the data want to sent... + + + + + + + 1 + + + QLayout::SetDefaultConstraint + + + + + + 250 + 16777215 + + + + Push Data + + + + + + + + + 6 + + + QLayout::SetDefaultConstraint + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + Qt::AlignJustify|Qt::AlignVCenter + + + 4 + + + 2 + + + + + Refresh Port(s): + + + + + + + + 120 + 16777215 + + + + + + + + + + + Selected Port: + + + + + + + + 120 + 16777215 + + + + + + + + Baud Rate: + + + + + + + + 120 + 16777215 + + + + + 9600 + + + + + 57600 + + + + + 115200 + + + + + 110 + + + + + 300 + + + + + 1200 + + + + + 2400 + + + + + 4800 + + + + + 19200 + + + + + 38400 + + + + + + + + Length (B): + + + + + + + + 120 + 16777215 + + + + + 8 + + + + + 7 + + + + + 6 + + + + + 5 + + + + + + + + Timeout: + + + + + + + + 120 + 16777215 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 10 + + + + + 30 + + + + + 50 + + + + + 100 + + + + + + + + Parity: + + + + + + + + 120 + 16777215 + + + + + None + + + + + Even + + + + + Odd + + + + + Mark + + + + + Space + + + + + + + + StopBits: + + + + + + + + 120 + 16777215 + + + + + 1 + + + + + 1.5 + + + + + 2 + + + + + + + + Flow Control: + + + + + + + + 120 + 16777215 + + + + + None + + + + + Xon/Xoff + + + + + RTS/CTS + + + + + DSR/DTR + + + + + + + + + + Connection Options: + + + + + + + + 205 + 16777215 + + + + QFrame::NoFrame + + + + + + + + + + Arial + 9 + 50 + false + + + + Status : + + + + + + + + Arial + 9 + 50 + false + + + + + + + Not Connected + + + + + + + + + 4 + + + + + + 250 + 16777215 + + + + + 9 + 75 + true + + + + false + + + + + + CONNECT + + + + + + + + + + + false + + + QFrame::Box + + + QFrame::Sunken + + + QTextEdit::AutoNone + + + true + + + + + + + + + + + 0 + 0 + 1127 + 21 + + + + + File - - QTabWidget::TabPosition::North + + + + + + + + Edit - - 0 + + + + Setup - - - Main Page - - - - - 0 - 0 - 721 - 511 - - - - - - - Gathering Data (Rx) - - - - - - - false - - - QFrame::Shape::Box - - - QFrame::Shadow::Raised - - - QTextEdit::AutoFormattingFlag::AutoAll - - - true - - - - - - - - - 900 - 390 - 21 - 132 - - - - - QLayout::SizeConstraint::SetMaximumSize - - - - - - 19 - 28 - - - - - 8 - - - - ... - - - - - - - - 19 - 28 - - - - - 8 - - - - ... - - - - - - - - 19 - 28 - - - - - 8 - - - - ... - - - - - - - - 19 - 28 - - - - - 8 - - - - ... - - - - - - - - - 730 - 390 - 171 - 121 - - - - - - - Command 1 - - - - - - - Command 2 - - - - - - - Command 3 - - - - - - - Command 4 - - - - - - - - - 730 - 260 - 191 - 131 - - - - - - - Connection Options: - - - - - - - QFrame::Shape::Box - - - - - - - - - - 9 - true - - - - false - - - - - - - - - STOP - - - - - - - - 9 - true - - - - false - - - - - - START - - - - - - - - - - - 730 - 230 - 191 - 21 - - - - - - - - Arial - 9 - false - - - - Port Status : - - - - - - - - Arial - 9 - false - - - - - - - Not Connected - - - - - - - - - 732 - 28 - 191 - 231 - - - - - - - Selected Port: - - - - - - - - - - Baud Rate: - - - - - - - - 9600 - - - - - 57600 - - - - - 115200 - - - - - 110 - - - - - 300 - - - - - 1200 - - - - - 2400 - - - - - 4800 - - - - - 19200 - - - - - 38400 - - - - - - - - Length (B): - - - - - - - - 8 - - - - - 7 - - - - - 6 - - - - - 5 - - - - - - - - Timeout: - - - - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 10 - - - - - 30 - - - - - 50 - - - - - 100 - - - - - - - - Parity: - - - - - - - - None - - - - - Even - - - - - Odd - - - - - Mark - - - - - Space - - - - - - - - StopBits: - - - - - - - - 1 - - - - - 1.5 - - - - - 2 - - - - - - - - Flow Control: - - - - - - - - None - - - - - Xon/Xoff - - - - - RTS/CTS - - - - - DSR/DTR - - - - - - - - - - 740 - 10 - 151 - 16 - - - - Settings: Refresh: - - - - - - 890 - 0 - 31 - 28 - - - - - - - - - - 0 - 520 - 901 - 31 - - - - - 1 - - - QLayout::SizeConstraint::SetNoConstraint - - - - - - 5 - 5 - - - - - 465 - 28 - - - - QFrame::Shape::Box - - - QFrame::Shadow::Plain - - - false - - - Please enter the data want to sent... - - - - - - - SEND - - - - - - - Save the output - - - Save the output - - - Save the output - - - Save as .txt - - - - - - - - 9 - true - - - - Click Here to go to the Simple View - - - Click Here to go to the Simple View - - - Click Here to go to the Simple View - - - << - - - - - - - 🌘 Night Mode - - - - - - - Clear Buffer - - - - - - - - - About - - - - - 10 - 10 - 911 - 491 - - - - false - - - true - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> -p, li { white-space: pre-wrap; } -hr { height: 1px; border-width: 0; } -li.unchecked::marker { content: "\2610"; } -li.checked::marker { content: "\2612"; } -</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:700;">Information</span></p> -<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"><br /></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The AFCOM (aka Serial communication GUI program) tool is a software application that allows users to send and receive data via the serial port (COM port) of their computer. The tool can be used for various purposes, such as testing, debugging, or communicating with other devices that use the serial protocol. </span></p> -<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"><br /></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:700;">Features</span><span style=" font-size:12pt;"> </span></p> -<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"><br /></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The COM port tool has the following features: It supports multiple COM ports and can detect the available ports automatically. It allows users to configure the parameters of the serial communication, such as baud rate. It provides a user-friendly interface that shows the transmitted and received data in hexadecimal, decimal, ASCII, or binary formats. It allows users to save and load the data to and from files.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:700;">Legal Information</span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This application incorporates Qt for Python (PySide), which is licensed under the GNU Lesser General Public License version 3 (LGPLv3). By using this software, you agree to comply with the terms of the LGPLv3 license. For more information about Qt for Python, visit https://www.qt.io/qt-for-python. A copy of the LGPLv3 license is included with this application.</span></p> -<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - false - - - - - - 590 - 530 - 101 - 16 - - - - Version 2024.12 - - - - - - 150 - 530 - 331 - 16 - - - - <html><head/><body><p><a href="https://github.com/mcagriaksoy/Serial-Communication-GUI-Program"><span style=" text-decoration: underline; color:#0000ff;">Github</span></a></p></body></html> - - - <html><head/><body><p>Feel free to ask any questions or bug report on <a href="https://github.com/mcagriaksoy/Serial-Communication-GUI-Program"><span style=" text-decoration: underline; color:#0000ff;">Github</span></a></p></body></html> - - - true - - - + + + Control + + + + + + + Help + + + + + + + + Window + + + + + + + + + + @@ -828,6 +617,46 @@ li.checked::marker { content: "\2612"; } Help + + + About + + + + + Check for Updates + + + + + Reset terminal + + + + + Clear Cache + + + + + Exit + + + + + New.. + + + + + Basic View + + + + + Advanced View + + From 86347fc9a65ef6f113cd6a4f78b7dcf7f615ec6d Mon Sep 17 00:00:00 2001 From: mcagriaksoy Date: Sun, 20 Apr 2025 11:48:38 +0200 Subject: [PATCH 3/3] More UI changes in case of seperated actions --- src/action_ui.py | 137 +++++++++++++ src/help.py | 0 src/ui_main.py | 66 ++---- ui/main_window.ui | 47 ++++- ui/resources.qrc | 6 +- ui/settings.ui | 496 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 691 insertions(+), 61 deletions(-) create mode 100644 src/action_ui.py create mode 100644 src/help.py create mode 100644 ui/settings.ui diff --git a/src/action_ui.py b/src/action_ui.py new file mode 100644 index 0000000..e0d1af0 --- /dev/null +++ b/src/action_ui.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +""" +@file action_ui.py +@brief Action UI for the application. +@details This module provides the Action UI for the application, allowing users to interact with the system. +""" +try: + from PySide6.QtUiTools import QUiLoader + from PySide6.QtWidgets import QDialog, QFileDialog, QMessageBox + from PySide6.QtCore import QFile +except ImportError: + print("PySide6 is not installed. Please install it to use this module.") + + +def action_save_as(ui): + """ + Save the current state of the application as a new file. + """ + # Open the file dialog to select the save location and file name + file_name, _ = QFileDialog.getSaveFileName( + None, 'Save File', '', 'Text Files (*.txt)') + if file_name: + with open(file_name, 'w') as file: + text = ui.data_textEdit.toPlainText() # Access the textEdit element + file.write(text) + +def action_save(ui): + """ + Save the current state of the application to the existing file. + """ + # Check if a file is already open + if hasattr(ui, 'current_file'): + # Save the current state to the existing file + with open(ui.current_file, 'w') as file: + file.write(ui.data_textEdit.toPlainText()) + else: + # If no file is open, call action_save_as to prompt for a file name + action_save_as(ui) + +def basic_view_enabled(ui): + """ Hide specific layouts in the UI for basic view """ + # Hide all widgets in the verticalLayout_config + for i in range(ui.verticalLayout_config.count()): + widget = ui.verticalLayout_config.itemAt(i).widget() + if widget: + widget.setVisible(False) + + # Optionally, hide all widgets in the formLayout_config + for i in range(ui.formLayout_config.count()): + widget = ui.formLayout_config.itemAt(i).widget() + if widget: + widget.setVisible(False) + +def advanced_view_enabled(ui): + """ Show specific layouts in the UI for advanced view """ + # Show all widgets in the verticalLayout_config + for i in range(ui.verticalLayout_config.count()): + widget = ui.verticalLayout_config.itemAt(i).widget() + if widget: + widget.setVisible(True) + + # Optionally, show all widgets in the formLayout_config + for i in range(ui.formLayout_config.count()): + widget = ui.formLayout_config.itemAt(i).widget() + if widget: + widget.setVisible(True) + +def clear_buffer(ui): + """ Clear the buffer """ + ui.data_textEdit.clear() + ui.send_data_text.clear() + +def show_about_dialog(ui): + """ Show the about dialog """ + # Crete a message box to display the about information + msg_box = QMessageBox() + msg_box.setWindowTitle("About") + msg_box.setText("AFCOM Client v1.4.0.0 (C) 2020 - 2025 \r\n\r\nAuthor: Mehmet Cagri Aksoy \r\ngithub.com/mcagriaksoy") + msg_box.setIcon(QMessageBox.Information) + msg_box.setStandardButtons(QMessageBox.Ok) + msg_box.setDefaultButton(QMessageBox.Ok) + msg_box.setModal(True) + msg_box.exec() # Show the message box modally + + +def show_help_dialog(ui): + """ Show the help dialog """ + # Load the help.ui file + file_path = "ui/help.ui" # Adjust the path if necessary + ui_file = QFile(file_path) + if not ui_file.exists(): + QMessageBox.critical(None, "Error", f"Help UI file not found: {file_path}") + return + + ui_file.open(QFile.ReadOnly) + loader = QUiLoader() + help_dialog = loader.load(ui_file) + ui_file.close() + + if help_dialog: + # Show the help dialog as a modal dialog + help_dialog.setWindowTitle("Help") + help_dialog.setModal(True) + help_dialog.exec() + else: + QMessageBox.critical(None, "Error", "Failed to load the help UI.") + +def show_settings_dialog(ui): + """ Show the settings dialog """ + # Load the settings.ui file + file_path = "ui/settings.ui" # Adjust the path if necessary + ui_file = QFile(file_path) + if not ui_file.exists(): + QMessageBox.critical(None, "Error", f"Settings UI file not found: {file_path}") + return + + ui_file.open(QFile.ReadOnly) + loader = QUiLoader() + settings_dialog = loader.load(ui_file) + ui_file.close() + + if settings_dialog: + # Show the settings dialog as a modal dialog + settings_dialog.setWindowTitle("Settings") + settings_dialog.setModal(True) + settings_dialog.exec() + else: + QMessageBox.critical(None, "Error", "Failed to load the settings UI.") + +def check_for_updates(ui): + """ Check for updates """ + # Placeholder function for checking updates + # You can implement the actual update check logic here + QMessageBox.information(ui, "Check for Updates", "No updates available at this time.") + + + diff --git a/src/help.py b/src/help.py new file mode 100644 index 0000000..e69de29 diff --git a/src/ui_main.py b/src/ui_main.py index 5d4ff2c..8b2c9e3 100644 --- a/src/ui_main.py +++ b/src/ui_main.py @@ -15,6 +15,7 @@ from sys import platform, exit, argv from glob import glob +from src import action_ui # Runtime Type Checking PROGRAM_TYPE_DEBUG = True PROGRAM_TYPE_RELEASE = False @@ -27,8 +28,8 @@ #system("python -m pip install pyserial") try: - from PySide6.QtCore import QObject, QThread, Signal, QFile - from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox, QInputDialog, QFileDialog + from PySide6.QtCore import QObject, QThread, Signal, QFile, Qt + from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox, QInputDialog if (PROGRAM_TYPE_DEBUG): from PySide6.QtUiTools import QUiLoader @@ -154,47 +155,23 @@ def __init__(self): self.ui.saved_command_4.clicked.connect(self.move_command4_to_text) ''' - # When actionClear_Cache is triggered, clear the buffer - self.ui.actionClear_Cache.triggered.connect(self.clear_buffer) + self.ui.actionClear_Cache.triggered.connect(action_ui.clear_buffer) - self.ui.actionBasic_View.triggered.connect(self.basic_view_enabled) - self.ui.actionAdvanced_View.triggered.connect(self.advanced_view_enabled) - #self.ui.clear_buffer_button.clicked.connect(self.clear_buffer) + self.ui.actionBasic_View.triggered.connect(lambda: action_ui.basic_view_enabled(self.ui)) + self.ui.actionAdvanced_View.triggered.connect(lambda: action_ui.advanced_view_enabled(self.ui)) - # self.ui.view_change.clicked.connect(self.view_changes) + self.ui.actionSave.triggered.connect(action_ui.action_save) + self.ui.actionSave_As.triggered.connect(action_ui.action_save_as) self.ui.port_comboBox.addItems(PORTS) self.ui.send_button.clicked.connect(self.on_send_data_button_clicked) - def basic_view_enabled(self): - """ Hide specific layouts in the UI for basic view """ - # Hide all widgets in the verticalLayout_config - for i in range(self.ui.verticalLayout_config.count()): - widget = self.ui.verticalLayout_config.itemAt(i).widget() - if widget: - widget.setVisible(False) - - # Optionally, hide all widgets in the formLayout_config - for i in range(self.ui.formLayout_config.count()): - widget = self.ui.formLayout_config.itemAt(i).widget() - if widget: - widget.setVisible(False) - - def advanced_view_enabled(self): - """ Show specific layouts in the UI for advanced view """ - # Show all widgets in the verticalLayout_config - for i in range(self.ui.verticalLayout_config.count()): - widget = self.ui.verticalLayout_config.itemAt(i).widget() - if widget: - widget.setVisible(True) - - # Optionally, show all widgets in the formLayout_config - for i in range(self.ui.formLayout_config.count()): - widget = self.ui.formLayout_config.itemAt(i).widget() - if widget: - widget.setVisible(True) + self.ui.actionExit.triggered.connect(lambda: exit(0)) + self.ui.actionAbout.triggered.connect(action_ui.show_about_dialog) + self.ui.actionCheck_for_updates.triggered.connect(action_ui.check_for_updates) + self.ui.actionHelp_2.triggered.connect(action_ui.show_help_dialog) + self.ui.actionPreferences.triggered.connect(action_ui.show_settings_dialog) - ''' def command1(self): """ Open the text input popup to save command for button 1 """ @@ -377,12 +354,6 @@ def stop_loop(self): # Disconnect the serial port and close it SERIAL_DEVICE.close() - def clear_buffer(self): - """ Clear the buffer """ - self.ui.data_textEdit.clear() - self.ui.send_data_text.clear() - - def read_data_from_thread(self, serial_data): """ Write the result to the text edit box""" # self.ui.data_textEdit.append("{}".format(i)) @@ -410,17 +381,6 @@ def read_data_from_thread(self, serial_data): self.ui.data_textEdit.verticalScrollBar().setValue( self.ui.data_textEdit.verticalScrollBar().maximum()) - def on_save_txt_button_clicked(self): - """ Save the values to the TXT file""" - # Open file dialog to create new .txt file - file_name, _ = QFileDialog.getSaveFileName( - self, 'Save File', '', 'Text Files (*.txt)') - if file_name: - with open(file_name, 'w') as file: - text = self.ui.data_textEdit.toPlainText() - file.write(text) - file.close() - def on_end_button_clicked(self): """ Stop the process """ global is_serial_port_established diff --git a/ui/main_window.ui b/ui/main_window.ui index 33968c0..1b949fc 100644 --- a/ui/main_window.ui +++ b/ui/main_window.ui @@ -35,8 +35,8 @@ AFCOM Client (A free COM port data transfer client) - - icon.icoicon.ico + + :/res/icon.ico:/res/icon.ico 1.000000000000000 @@ -127,7 +127,7 @@ - Refresh Port(s): + Refresh Port(s): @@ -565,6 +565,8 @@ + + @@ -575,8 +577,9 @@ - Setup + Settings + @@ -589,6 +592,7 @@ Help + @@ -599,6 +603,7 @@ + @@ -657,7 +662,39 @@ Advanced View + + + Preferences.. + + + + + Minimize + + + + + Full Screen + + + + + Help + + + + + Save As.. + + + + + Save + + - + + + diff --git a/ui/resources.qrc b/ui/resources.qrc index 43e9019..b205054 100644 --- a/ui/resources.qrc +++ b/ui/resources.qrc @@ -1,5 +1,5 @@ - - resource/play.svg - + + icon.ico + diff --git a/ui/settings.ui b/ui/settings.ui new file mode 100644 index 0000000..3338a08 --- /dev/null +++ b/ui/settings.ui @@ -0,0 +1,496 @@ + + + Dialog + + + + 0 + 0 + 251 + 386 + + + + Dialog + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close|QDialogButtonBox::SaveAll + + + + + + + Settings + + + + + 10 + 20 + 221 + 311 + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + Qt::AlignJustify|Qt::AlignVCenter + + + 4 + + + 2 + + + + + Refresh Port(s): + + + + + + + + 120 + 16777215 + + + + + + + + + + + Selected Port: + + + + + + + + 120 + 16777215 + + + + + + + + Baud Rate: + + + + + + + + 120 + 16777215 + + + + + 9600 + + + + + 57600 + + + + + 115200 + + + + + 110 + + + + + 300 + + + + + 1200 + + + + + 2400 + + + + + 4800 + + + + + 19200 + + + + + 38400 + + + + + + + + Length (B): + + + + + + + + 120 + 16777215 + + + + + 8 + + + + + 7 + + + + + 6 + + + + + 5 + + + + + + + + Timeout: + + + + + + + + 120 + 16777215 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 10 + + + + + 30 + + + + + 50 + + + + + 100 + + + + + + + + Parity: + + + + + + + + 120 + 16777215 + + + + + None + + + + + Even + + + + + Odd + + + + + Mark + + + + + Space + + + + + + + + StopBits: + + + + + + + + 120 + 16777215 + + + + + 1 + + + + + 1.5 + + + + + 2 + + + + + + + + Flow Control: + + + + + + + + 120 + 16777215 + + + + + None + + + + + Xon/Xoff + + + + + RTS/CTS + + + + + DSR/DTR + + + + + + + + UI Language: + + + + + + + + 120 + 16777215 + + + + + English + + + + + Türkçe + + + + + + + + + 120 + 16777215 + + + + + + + + Terminal Font: + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + 120 + 16777215 + + + + + Defult (System) + + + + + Dark + + + + + Light + + + + + + + + Theme: + + + + + + + + + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +