Skip to content

Commit 50bb42d

Browse files
author
mcagriaksoy
committed
UI
1 parent 807f2d7 commit 50bb42d

File tree

10 files changed

+1017
-161
lines changed

10 files changed

+1017
-161
lines changed

main.spec

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
# -*- mode: python ; coding: utf-8 -*-
22

33

4-
block_cipher = None
5-
6-
74
a = Analysis(
85
['main.py'],
96
pathex=[],
@@ -14,18 +11,15 @@ a = Analysis(
1411
hooksconfig={},
1512
runtime_hooks=[],
1613
excludes=[],
17-
win_no_prefer_redirects=False,
18-
win_private_assemblies=False,
19-
cipher=block_cipher,
2014
noarchive=False,
15+
optimize=0,
2116
)
22-
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
17+
pyz = PYZ(a.pure)
2318

2419
exe = EXE(
2520
pyz,
2621
a.scripts,
2722
a.binaries,
28-
a.zipfiles,
2923
a.datas,
3024
[],
3125
name='main',
@@ -41,5 +35,4 @@ exe = EXE(
4135
target_arch=None,
4236
codesign_identity=None,
4337
entitlements_file=None,
44-
icon=['ui\\icon.ico'],
4538
)

src/action_ui.py

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
@brief Action UI for the application.
55
@details This module provides the Action UI for the application, allowing users to interact with the system.
66
"""
7+
# Runtime Type Checking
8+
PROGRAM_TYPE_DEBUG = True
9+
PROGRAM_TYPE_RELEASE = False
710
try:
811
from PySide6.QtUiTools import QUiLoader
912
from PySide6.QtWidgets import QDialog, QFileDialog, QMessageBox
1013
from PySide6.QtCore import QFile
14+
from ui.settings import Ui_Dialog
15+
from ui.help import Ui_HelpDialog
1116
except ImportError:
1217
print("PySide6 is not installed. Please install it to use this module.")
1318

14-
1519
def action_save_as(ui):
1620
"""
1721
Save the current state of the application as a new file.
@@ -85,47 +89,61 @@ def show_about_dialog(ui):
8589

8690
def show_help_dialog(ui):
8791
""" Show the help dialog """
88-
# Load the help.ui file
89-
file_path = "ui/help.ui" # Adjust the path if necessary
90-
ui_file = QFile(file_path)
91-
if not ui_file.exists():
92-
QMessageBox.critical(None, "Error", f"Help UI file not found: {file_path}")
93-
return
94-
95-
ui_file.open(QFile.ReadOnly)
96-
loader = QUiLoader()
97-
help_dialog = loader.load(ui_file)
98-
ui_file.close()
99-
100-
if help_dialog:
101-
# Show the help dialog as a modal dialog
102-
help_dialog.setWindowTitle("Help")
103-
help_dialog.setModal(True)
104-
help_dialog.exec()
92+
if PROGRAM_TYPE_DEBUG:
93+
file_path = "ui/help.ui" # Adjust the path if necessary
94+
ui_file = QFile(file_path)
95+
if not ui_file.exists():
96+
QMessageBox.critical(None, "Error", f"Help UI file not found: {file_path}")
97+
return
98+
99+
ui_file.open(QFile.ReadOnly)
100+
loader = QUiLoader()
101+
help_dialog = loader.load(ui_file)
102+
ui_file.close()
103+
if help_dialog:
104+
help_dialog.setWindowTitle("Help")
105+
help_dialog.setModal(True)
106+
help_dialog.exec()
107+
else:
108+
QMessageBox.critical(None, "Error", "Failed to load the help UI.")
105109
else:
106-
QMessageBox.critical(None, "Error", "Failed to load the help UI.")
110+
try:
111+
dialog = QDialog() # Create a QDialog instance
112+
help_dialog = Ui_HelpDialog() # Initialize the UI class
113+
help_dialog.setupUi(dialog) # Set up the UI on the dialog
114+
dialog.setWindowTitle("Help") # Set the dialog title
115+
dialog.exec() # Show the dialog modally
116+
except Exception as e:
117+
print(f"Error in show_help_dialog: {e}")
107118

108119
def show_settings_dialog(ui):
109120
""" Show the settings dialog """
110-
# Load the settings.ui file
111-
file_path = "ui/settings.ui" # Adjust the path if necessary
112-
ui_file = QFile(file_path)
113-
if not ui_file.exists():
114-
QMessageBox.critical(None, "Error", f"Settings UI file not found: {file_path}")
115-
return
116-
117-
ui_file.open(QFile.ReadOnly)
118-
loader = QUiLoader()
119-
settings_dialog = loader.load(ui_file)
120-
ui_file.close()
121-
122-
if settings_dialog:
123-
# Show the settings dialog as a modal dialog
124-
settings_dialog.setWindowTitle("Settings")
125-
settings_dialog.setModal(True)
126-
settings_dialog.exec()
121+
if PROGRAM_TYPE_DEBUG:
122+
file_path = "ui/settings.ui" # Adjust the path if necessary
123+
ui_file = QFile(file_path)
124+
if not ui_file.exists():
125+
QMessageBox.critical(None, "Error", f"Settings UI file not found: {file_path}")
126+
return
127+
128+
ui_file.open(QFile.ReadOnly)
129+
loader = QUiLoader()
130+
settings_dialog = loader.load(ui_file)
131+
ui_file.close()
132+
if settings_dialog:
133+
settings_dialog.setWindowTitle("Settings")
134+
settings_dialog.setModal(True)
135+
settings_dialog.exec()
136+
else:
137+
QMessageBox.critical(None, "Error", "Failed to load the settings UI.")
127138
else:
128-
QMessageBox.critical(None, "Error", "Failed to load the settings UI.")
139+
try:
140+
dialog = QDialog() # Create a QDialog instance
141+
settings_dialog = Ui_Dialog() # Initialize the UI class
142+
settings_dialog.setupUi(dialog) # Set up the UI on the dialog
143+
dialog.setWindowTitle("Settings") # Set the dialog title
144+
dialog.exec() # Show the dialog modally
145+
except Exception as e:
146+
print(f"Error in show_settings_dialog: {e}")
129147

130148
def check_for_updates(ui):
131149
""" Check for updates """

src/ui_main.py

Lines changed: 72 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from os import path, system
1515
from sys import platform, exit, argv
1616
from glob import glob
17-
1817
from src import action_ui
1918
# Runtime Type Checking
2019
PROGRAM_TYPE_DEBUG = True
@@ -28,13 +27,12 @@
2827
#system("python -m pip install pyserial")
2928

3029
try:
31-
from PySide6.QtCore import QObject, QThread, Signal, QFile, Qt
30+
from PySide6.QtCore import QObject, QThread, Signal, QFile, Qt, QEvent, QTimer
3231
from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox, QInputDialog
33-
32+
from ui.main_window import Ui_main_window
3433
if (PROGRAM_TYPE_DEBUG):
3534
from PySide6.QtUiTools import QUiLoader
36-
else: # PROGRAM_TYPE_RELEASE
37-
from ui.ui_main_window import Ui_main_window
35+
3836
except ImportError as e:
3937
print("Import Error! I am installing the required libraries: " + str(e))
4038
#system("pip install {0}".format(str(e).split(" ")[-1]))
@@ -129,7 +127,7 @@ def __init__(self):
129127
self.ui.show()
130128
else: # PROGRAM_TYPE_RELEASE
131129
print("UI File Found!")
132-
self.ui= Ui_main_window()
130+
self.ui = Ui_main_window()
133131
self.ui.setupUi(self)
134132

135133
if (is_windows_dark_mode(self)):
@@ -141,7 +139,7 @@ def __init__(self):
141139
self.thread = None
142140
self.worker = None
143141

144-
self.ui.start_button.clicked.connect(self.start_loop)
142+
self.ui.start_button.clicked.connect(self.on_start_button_clicked)
145143
self.ui.refresh_button.clicked.connect(self.refresh_port)
146144
'''
147145
self.ui.command_edit_1.clicked.connect(self.command1)
@@ -166,6 +164,9 @@ def __init__(self):
166164
self.ui.port_comboBox.addItems(PORTS)
167165
self.ui.send_button.clicked.connect(self.on_send_data_button_clicked)
168166

167+
# when Enter is pressed in send_data_text
168+
self.ui.send_data_text.installEventFilter(self)
169+
169170
self.ui.actionExit.triggered.connect(lambda: exit(0))
170171
self.ui.actionAbout.triggered.connect(action_ui.show_about_dialog)
171172
self.ui.actionCheck_for_updates.triggered.connect(action_ui.check_for_updates)
@@ -224,6 +225,14 @@ def move_command4_to_text(self):
224225
self.ui.send_data_text.setText(self.ui.saved_command_4.text())
225226
self.on_send_data_button_clicked()
226227
'''
228+
def eventFilter(self, obj, event):
229+
# Check if the event is for send_data_text and Enter is pressed
230+
if obj == self.ui.send_data_text and event.type() == QEvent.KeyPress:
231+
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
232+
self.on_send_data_button_clicked()
233+
return True # Prevents QTextEdit from adding a new line
234+
return super().eventFilter(obj, event)
235+
227236
def refresh_port(self):
228237
""" Refresh the serial port list """
229238
PORTS = get_serial_port()
@@ -294,9 +303,20 @@ def establish_serial_communication(self):
294303
if SERIAL_DEVICE.isOpen() == False:
295304
SERIAL_DEVICE.open()
296305

297-
def start_loop(self):
306+
def on_start_button_clicked(self):
298307
""" Start the loop """
299-
self.ui.port_comboBox.setStyleSheet('background-color: white')
308+
# Check if the port_comboBox style is red, if so, set it to system default
309+
if self.ui.port_comboBox.styleSheet() == 'background-color: red':
310+
self.ui.port_comboBox.setStyleSheet('')
311+
312+
global is_serial_port_established
313+
314+
if is_serial_port_established:
315+
is_serial_port_established = False
316+
self.ui.start_button.setText("START")
317+
self.ui.start_button.setStyleSheet('color: green;')
318+
self.on_stop_button_clicked()
319+
return
300320

301321
# If the serial port is not selected, print a message
302322
if self.ui.port_comboBox.currentText() == "":
@@ -311,18 +331,11 @@ def start_loop(self):
311331
self.print_message_on_screen(
312332
"Exception occured while trying establish serial communication!")
313333
return
314-
315-
global is_serial_port_established
316-
317-
if (is_serial_port_established == True):
318-
is_serial_port_established = False
319-
self.on_end_button_clicked()
320-
self.ui.start_button.setText("START")
321-
return
322-
323334
is_serial_port_established = True
324335
# change start_button to stop button
336+
self.ui.options_textEdit.setText('Disconnected!')
325337
self.ui.start_button.setText("STOP")
338+
self.ui.start_button.setStyleSheet('color: red;')
326339

327340
try:
328341
self.worker = Worker() # a new worker to perform those tasks
@@ -332,27 +345,50 @@ def start_loop(self):
332345
# begin our worker object's loop when the thread starts running
333346
self.thread.started.connect(self.worker.work)
334347
self.worker.serial_data.connect(self.read_data_from_thread)
335-
# stop the loop on the stop button click
336-
self.ui.end_button.clicked.connect(self.stop_loop)
337348
# tell the thread it's time to stop running
338349
self.worker.finished.connect(self.thread.quit)
339350
# have worker mark itself for deletion
340351
self.worker.finished.connect(self.worker.deleteLater)
341352
# have thread mark itself for deletion
342353
self.thread.finished.connect(self.thread.deleteLater)
354+
355+
self.enable_configuration(False)
356+
self.ui.options_textEdit.setText('RX/TX Connected!')
357+
self.ui.status_label.setText("CONNECTED!")
358+
self.ui.status_label.setStyleSheet('color: green')
343359
# start the thread
344360
self.thread.start()
345-
346-
347361
except RuntimeError:
348362
self.print_message_on_screen("Exception in Worker Thread!")
349363

350-
def stop_loop(self):
364+
def on_stop_button_clicked(self):
351365
""" Stop the loop """
352-
self.worker.working = False
353366
self.ui.options_textEdit.setText('Stopped!')
354-
# Disconnect the serial port and close it
355-
SERIAL_DEVICE.close()
367+
self.ui.status_label.setText("DISCONNECTED!")
368+
self.ui.status_label.setStyleSheet('color: red')
369+
self.enable_configuration(True)
370+
371+
# Safely stop the worker thread
372+
if hasattr(self, 'worker') and self.worker is not None:
373+
self.worker.working = False
374+
375+
# Safely close the serial device
376+
global SERIAL_DEVICE
377+
try:
378+
if SERIAL_DEVICE.is_open:
379+
SERIAL_DEVICE.close()
380+
except Exception as e:
381+
print(f"Error closing serial port: {e}")
382+
383+
def enable_configuration(self, state):
384+
""" enable/disable the configuration """
385+
self.ui.timeout_comboBox.setEnabled(state)
386+
self.ui.baudrate_comboBox.setEnabled(state)
387+
self.ui.len_comboBox.setEnabled(state)
388+
self.ui.port_comboBox.setEnabled(state)
389+
self.ui.parity_comboBox.setEnabled(state)
390+
self.ui.bit_comboBox.setEnabled(state)
391+
self.ui.flow_comboBox.setEnabled(state)
356392

357393
def read_data_from_thread(self, serial_data):
358394
""" Write the result to the text edit box"""
@@ -361,49 +397,23 @@ def read_data_from_thread(self, serial_data):
361397
self.print_message_on_screen(
362398
"Serial Port Exception! Please check the serial port"
363399
" Possibly it is not connected or the port is not available!")
364-
self.ui.status_label.setText("NOT CONNECTED!")
365-
self.ui.status_label.setStyleSheet('color: red')
400+
self.on_stop_button_clicked()
366401
else:
367-
self.ui.timeout_comboBox.setEnabled(False)
368-
self.ui.baudrate_comboBox.setEnabled(False)
369-
self.ui.len_comboBox.setEnabled(False)
370-
self.ui.port_comboBox.setEnabled(False)
371-
self.ui.parity_comboBox.setEnabled(False)
372-
self.ui.bit_comboBox.setEnabled(False)
373-
self.ui.flow_comboBox.setEnabled(False)
374-
self.ui.start_button.setEnabled(False)
375-
376-
self.ui.options_textEdit.setText('Data Gathering...')
377-
self.ui.status_label.setText("CONNECTED!")
378-
self.ui.status_label.setStyleSheet('color: green')
379402
serial_data = serial_data.replace('\n', '')
380403
self.ui.data_textEdit.insertPlainText("{}".format(serial_data))
381404
self.ui.data_textEdit.verticalScrollBar().setValue(
382405
self.ui.data_textEdit.verticalScrollBar().maximum())
383406

384-
def on_end_button_clicked(self):
385-
""" Stop the process """
386-
global is_serial_port_established
387-
is_serial_port_established = False
388-
self.ui.options_textEdit.setText('Stopped!')
389-
self.ui.status_label.setText("DISCONNECTED!")
390-
self.ui.status_label.setStyleSheet('color: red')
391-
self.ui.timeout_comboBox.setEnabled(True)
392-
self.ui.baudrate_comboBox.setEnabled(True)
393-
self.ui.len_comboBox.setEnabled(True)
394-
self.ui.port_comboBox.setEnabled(True)
395-
self.ui.parity_comboBox.setEnabled(True)
396-
self.ui.bit_comboBox.setEnabled(True)
397-
self.ui.flow_comboBox.setEnabled(True)
398-
self.ui.start_button.setEnabled(True)
399-
400407
def on_send_data_button_clicked(self):
401408
""" Send data to serial port """
402-
if (is_serial_port_established):
409+
if is_serial_port_established:
410+
self.ui.indicate_button.setChecked(True)
403411
mytext = self.ui.send_data_text.toPlainText().encode('utf-8')
404-
#SERIAL_DEVICE.flushInput()
405-
#SERIAL_DEVICE.flushOutput()
406-
SERIAL_DEVICE.write(mytext + b'\r')
412+
SERIAL_DEVICE.flushOutput() # Flush output buffer
413+
SERIAL_DEVICE.write(mytext + b'\r\n')
414+
415+
# Uncheck after 5 seconds without blocking the UI
416+
QTimer.singleShot(500, lambda: self.ui.indicate_button.setChecked(False))
407417
else:
408418
self.print_message_on_screen(
409419
"Serial Port is not established yet! Please establish the serial port first!")
@@ -413,4 +423,6 @@ def start_ui_design():
413423
""" Start the UI Design """
414424
app = QApplication(argv) # Create an instance
415425
window_object = MainWindow() # Create an instance of our class
426+
if PROGRAM_TYPE_RELEASE:
427+
window_object.show()
416428
exit(app.exec())

ui/Convert.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Please use:
2+
3+
pyside6-uic main_window.ui -o main_window.py

0 commit comments

Comments
 (0)