From 685a8efa013d5a9d285f7d2a638f0c06b3eff037 Mon Sep 17 00:00:00 2001 From: bert003 Date: Sat, 29 Apr 2023 17:23:04 +0200 Subject: [PATCH 1/4] Update Date and Time Implemented auto update of Date and Time and Time Zone including visible spinner --- Preferences/Date and Time.app/Date and Time | 125 ++++++++++++++------ 1 file changed, 92 insertions(+), 33 deletions(-) diff --git a/Preferences/Date and Time.app/Date and Time b/Preferences/Date and Time.app/Date and Time index 1c18175e..2daf1279 100755 --- a/Preferences/Date and Time.app/Date and Time +++ b/Preferences/Date and Time.app/Date and Time @@ -11,10 +11,25 @@ import time from PyQt5.QtCore import Qt, QDateTime, QTimer from PyQt5.QtWidgets import (QApplication, QDateTimeEdit, QGridLayout, QGroupBox, QLabel, QMainWindow, QMessageBox, - QPushButton, QTabWidget, QVBoxLayout, QWidget) + QPushButton, QTabWidget, QVBoxLayout, QWidget, QSizePolicy) from PyQt5.QtGui import QMovie, QKeyEvent, QPixmap -from PyQt5.QtCore import QEvent +from PyQt5.QtCore import QEvent, QObject, QThread, pyqtSignal +class SetDateTimeAutoWorker(QObject): + finished = pyqtSignal() + returncode = pyqtSignal(object) + def run(self): + try: + time.sleep(1) + # Set the date and time automatically using NTP + subprocess.run(["sudo", "ntpdate", "-v", "-b", + "-u", "pool.ntp.org"], check=True) + self.returncode.emit("OK") + self.finished.emit() + return + except subprocess.CalledProcessError as e: + self.returncode.emit(e.stderr) + self.finished.emit() class DateTimeWindow(QMainWindow): def __init__(self): @@ -75,7 +90,7 @@ class DateTimeWindow(QMainWindow): self.edit_menu.addAction("Set Date and Time automatically", self.set_date_time_auto) - self.edit_menu.addAction("Set time zone automatically", + self.edit_menu.addAction("Set Time Zone automatically", self.set_time_zone_auto) # Help menu @@ -86,16 +101,16 @@ class DateTimeWindow(QMainWindow): # Create spinner self.spinner = QLabel(self) # Generated using http://ajaxload.info/ + self.spinner.setFixedSize(400, 250) self.spinner.setMovie( QMovie(os.path.dirname(__file__) + "/Resources/spinner.gif")) self.spinner.movie().start() - self.spinner.hide() self.spinner.setAlignment(Qt.AlignCenter) - # self.spinner.setFixedSize(16, 16) - self.spinner.move(0, self.height() - self.spinner.height()) + self.spinner.move(0, 0) + self.spinner.hide() # Connect to the resizeEvent of the window to update the position of the spinner self.resizeEvent = lambda event: self.spinner.move( - -20, self.height() - self.spinner.height() - 10) + (self.width()//2)-200, (self.height()//2)-125) def send_shortcut(self, key_code, modifier): # Send shortcut to currently focused widget like Ctrl+C, Ctrl+V, etc. @@ -127,7 +142,7 @@ class DateTimeWindow(QMainWindow): self.grp_set_date_time.setLayout(self.vbox_set_date_time) self.btn_set_date_time_auto = QPushButton( - "Set Date and Time automatically", self) + "Set Date and Time Automatically", self) self.grp_set_date_time_auto = QGroupBox("Date and Time options", self) self.vbox_set_date_time_auto = QVBoxLayout() @@ -155,9 +170,9 @@ class DateTimeWindow(QMainWindow): def create_time_zone_tab(self): # Create widgets self.btn_set_time_zone_auto = QPushButton( - "Set time zone automatically", self) + "Set Time Zone Automatically", self) - self.grp_set_time_zone = QGroupBox("Set time zone", self) + self.grp_set_time_zone = QGroupBox("Set Time Zone", self) self.vbox_set_time_zone = QVBoxLayout() self.vbox_set_time_zone.addWidget(self.btn_set_time_zone_auto) self.grp_set_time_zone.setLayout(self.vbox_set_time_zone) @@ -181,7 +196,7 @@ class DateTimeWindow(QMainWindow): capture_output=True, text=True, check=True) return QDateTime.fromString(result.stdout.strip(), "yyyy-MM-dd hh:mm:ss") except subprocess.CalledProcessError as e: - self.show_error_dialog("Error getting current Date and Time", + self.show_error_dialog("Error getting current Date and Time!", f"An error occurred while getting the current Date and Time: {e.stderr}") return QDateTime.currentDateTime() @@ -197,36 +212,80 @@ class DateTimeWindow(QMainWindow): self.dt_set_date_time_manual.setDateTime( self.get_current_datetime()) except subprocess.CalledProcessError as e: - self.show_error_dialog("Error setting Date and Time", + self.show_error_dialog("Error setting Date and Time!", f"An error occurred while setting the Date and Time: {e.stderr}") self.spinner.hide() - def set_date_time_auto(self): + # show spinner wrapper + def show_spinner(self): self.spinner.show() - # Wait one second before setting the date and time automatically - time.sleep(1) - try: - # Set the date and time automatically using NTP - subprocess.run(["sudo", "ntpdate", "-v", "-b", - "-u", "pool.ntp.org"], check=True) - self.dt_set_date_time_manual.setDateTime( - self.get_current_datetime()) - except subprocess.CalledProcessError as e: - self.show_error_dialog("Error setting Date and Time automatically", - f"An error occurred while setting the Date and Time automatically: {e.stderr}") + + # hide spinner wrapper + def hide_spinner(self): + self.spinner.hide() + + # enable all widgets + def enable_window_widgets(self): + self.setEnabled(True) + + # disable all widgets + def disable_window_widgets(self): + self.setEnabled(False) + + def check_date_time_auto_result(self, ret_code): + if ret_code == "OK": + self.dt_set_date_time_manual.setDateTime(self.get_current_datetime()) + else: + self.show_error_dialog("Error setting Date and Time automatically!", + f"An error occurred while setting the Date and Time automatically: {ret_code}") # Restart the timer if it is not running if not self.timer.isActive(): self.timer.start() - self.spinner.hide() + def check_time_zone_auto_result(self, ret_code): + if ret_code != "OK": + self.show_error_dialog("Error setting Time Zone automatically!", + f"An error occurred while setting the Time Zone automatically: {ret_code}") + + def set_date_time_auto(self): + # create a QThread object + self.thread = QThread(parent=self) + # create a worker object + self.worker = SetDateTimeAutoWorker() + # move worker to the thread + self.worker.moveToThread(self.thread) + # connect signals and slots + self.thread.started.connect(self.worker.run) + self.worker.finished.connect(self.thread.quit) + # set actions to execute when thread is done + self.worker.returncode.connect(self.hide_spinner) + self.worker.returncode.connect(self.enable_window_widgets) + self.worker.returncode.connect(self.check_date_time_auto_result) + # disable button and show spinner + self.disable_window_widgets() + self.show_spinner() + # start the thread + self.thread.start() + def set_time_zone_auto(self): - try: - # Set the time zone automatically using NTP - subprocess.run(["sudo", "ntpdate", "-v", "-b", - "-u", "pool.ntp.org"], check=True) - except subprocess.CalledProcessError as e: - self.show_error_dialog("Error setting time zone automatically", - f"An error occurred while setting the time zone automatically: {e.stderr}") + # create a QThread object + self.thread = QThread(parent=self) + # create a worker object + self.worker = SetDateTimeAutoWorker() + # move worker to the thread + self.worker.moveToThread(self.thread) + # connect signals and slots + self.thread.started.connect(self.worker.run) + self.worker.finished.connect(self.thread.quit) + # set actions to execute when thread is done + self.worker.returncode.connect(self.hide_spinner) + self.worker.returncode.connect(self.enable_window_widgets) + self.worker.returncode.connect(self.check_time_zone_auto_result) + # disable button and show spinner + self.disable_window_widgets() + self.show_spinner() + # start the thread + self.thread.start() def show_error_dialog(self, title, message): msg_box = QMessageBox() @@ -249,7 +308,7 @@ class DateTimeWindow(QMainWindow): msg.setDetailedText(data) msg.setText("

Date and Time

") msg.setInformativeText( - "A simple preferences application to set date and time using ntpdate and date

https://github.com/helloSystem/Utilities") + "A simple preferences application to set date and time usig ntpdate and date

https://github.com/helloSystem/Utilities") msg.exec() From 361c3fcd1a6e0591f27ccd622ef5c356bae42cff Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 29 Apr 2023 18:37:09 +0200 Subject: [PATCH 2/4] Fix typo --- Preferences/Date and Time.app/Date and Time | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Preferences/Date and Time.app/Date and Time b/Preferences/Date and Time.app/Date and Time index 2daf1279..fc7df2fd 100755 --- a/Preferences/Date and Time.app/Date and Time +++ b/Preferences/Date and Time.app/Date and Time @@ -308,7 +308,7 @@ class DateTimeWindow(QMainWindow): msg.setDetailedText(data) msg.setText("

Date and Time

") msg.setInformativeText( - "A simple preferences application to set date and time usig ntpdate and date

https://github.com/helloSystem/Utilities") + "A simple preferences application to set date and time using ntpdate and date

https://github.com/helloSystem/Utilities") msg.exec() From da269c7fa0adc4f9b40650efa7cbff8c38ed3c90 Mon Sep 17 00:00:00 2001 From: bert003 Date: Sun, 30 Apr 2023 16:16:56 +0200 Subject: [PATCH 3/4] Update Date and Time - Made room for spinner under bottom-most buttons in each tab - Converted Main Window to fixed size since, as I see it, resizing will compromise its aesthetics --- Preferences/Date and Time.app/Date and Time | 79 +++++++++++++-------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/Preferences/Date and Time.app/Date and Time b/Preferences/Date and Time.app/Date and Time index 2daf1279..a3ecbaee 100755 --- a/Preferences/Date and Time.app/Date and Time +++ b/Preferences/Date and Time.app/Date and Time @@ -35,6 +35,20 @@ class DateTimeWindow(QMainWindow): def __init__(self): super().__init__() + # Create Date Time spinner + self.dt_spinner = QLabel() + self.dt_spinner.setMovie(QMovie(os.path.dirname(__file__) + "/Resources/spinner.gif")) + self.dt_spinner.movie().start() + self.dt_spinner.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + self.dt_spinner.hide() + + # Create Time Zone spinner + self.tz_spinner = QLabel() + self.tz_spinner.setMovie(QMovie(os.path.dirname(__file__) + "/Resources/spinner.gif")) + self.tz_spinner.movie().start() + self.tz_spinner.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + self.tz_spinner.hide() + # Create tab widget self.tabs = QTabWidget() @@ -53,7 +67,8 @@ class DateTimeWindow(QMainWindow): # Set window properties self.setWindowTitle("Date and Time") - self.setMinimumSize(400, 250) + #self.setMinimumSize(400, 320) + self.setFixedSize(400, 320) # File menu self.file_menu = self.menuBar().addMenu("File") @@ -98,20 +113,6 @@ class DateTimeWindow(QMainWindow): about_action = self.help_menu.addAction("About", self.show_about) about_action.setShortcut("Ctrl+?") - # Create spinner - self.spinner = QLabel(self) - # Generated using http://ajaxload.info/ - self.spinner.setFixedSize(400, 250) - self.spinner.setMovie( - QMovie(os.path.dirname(__file__) + "/Resources/spinner.gif")) - self.spinner.movie().start() - self.spinner.setAlignment(Qt.AlignCenter) - self.spinner.move(0, 0) - self.spinner.hide() - # Connect to the resizeEvent of the window to update the position of the spinner - self.resizeEvent = lambda event: self.spinner.move( - (self.width()//2)-200, (self.height()//2)-125) - def send_shortcut(self, key_code, modifier): # Send shortcut to currently focused widget like Ctrl+C, Ctrl+V, etc. widget = self.focusWidget() @@ -148,6 +149,12 @@ class DateTimeWindow(QMainWindow): self.vbox_set_date_time_auto = QVBoxLayout() self.vbox_set_date_time_auto.addWidget(self.btn_set_date_time_auto) self.grp_set_date_time_auto.setLayout(self.vbox_set_date_time_auto) + + self.grp_dt_spinner = QGroupBox("", self) + self.grp_dt_spinner.setStyleSheet("border : 0;") + self.vbox_dt_spinner = QVBoxLayout() + self.vbox_dt_spinner.addWidget(self.dt_spinner) + self.grp_dt_spinner.setLayout(self.vbox_dt_spinner) # Connect signals to slots self.btn_set_date_time_manual.clicked.connect( @@ -157,10 +164,9 @@ class DateTimeWindow(QMainWindow): # Create grid layout for date/time tab self.grid_layout_date_time = QGridLayout() - self.grid_layout_date_time.addWidget( - self.grp_set_date_time, 2, 0, 1, 2) - self.grid_layout_date_time.addWidget( - self.grp_set_date_time_auto, 3, 0, 1, 2) + self.grid_layout_date_time.addWidget(self.grp_set_date_time, 2, 0, 1, 2) + self.grid_layout_date_time.addWidget(self.grp_set_date_time_auto, 3, 0, 1, 2) + self.grid_layout_date_time.addWidget(self.grp_dt_spinner, 4, 0, 1, 2) self.grid_layout_date_time.setRowStretch(4, 1) # Create date/time tab and set layout @@ -177,12 +183,19 @@ class DateTimeWindow(QMainWindow): self.vbox_set_time_zone.addWidget(self.btn_set_time_zone_auto) self.grp_set_time_zone.setLayout(self.vbox_set_time_zone) + self.grp_tz_spinner = QGroupBox("", self) + self.grp_tz_spinner.setStyleSheet("border : 0;") + self.vbox_tz_spinner = QVBoxLayout() + self.vbox_tz_spinner.addWidget(self.tz_spinner) + self.grp_tz_spinner.setLayout(self.vbox_tz_spinner) + # Connect signals to slots self.btn_set_time_zone_auto.clicked.connect(self.set_time_zone_auto) # Create grid layout for time zone tab self.grid_layout_time_zone = QGridLayout() self.grid_layout_time_zone.addWidget(self.grp_set_time_zone, 1, 0) + self.grid_layout_time_zone.addWidget(self.grp_tz_spinner, 2, 0) self.grid_layout_time_zone.setRowStretch(2, 1) # Create time zone tab and set layout @@ -216,13 +229,21 @@ class DateTimeWindow(QMainWindow): f"An error occurred while setting the Date and Time: {e.stderr}") self.spinner.hide() - # show spinner wrapper - def show_spinner(self): - self.spinner.show() + # show date time spinner wrapper + def show_dt_spinner(self): + self.dt_spinner.show() - # hide spinner wrapper - def hide_spinner(self): - self.spinner.hide() + # show time zone spinner wrapper + def show_tz_spinner(self): + self.tz_spinner.show() + + # hide date time spinner wrapper + def hide_dt_spinner(self): + self.dt_spinner.hide() + + # hide date time spinner wrapper + def hide_tz_spinner(self): + self.tz_spinner.hide() # enable all widgets def enable_window_widgets(self): @@ -258,12 +279,12 @@ class DateTimeWindow(QMainWindow): self.thread.started.connect(self.worker.run) self.worker.finished.connect(self.thread.quit) # set actions to execute when thread is done - self.worker.returncode.connect(self.hide_spinner) + self.worker.returncode.connect(self.hide_dt_spinner) self.worker.returncode.connect(self.enable_window_widgets) self.worker.returncode.connect(self.check_date_time_auto_result) # disable button and show spinner self.disable_window_widgets() - self.show_spinner() + self.show_dt_spinner() # start the thread self.thread.start() @@ -278,12 +299,12 @@ class DateTimeWindow(QMainWindow): self.thread.started.connect(self.worker.run) self.worker.finished.connect(self.thread.quit) # set actions to execute when thread is done - self.worker.returncode.connect(self.hide_spinner) + self.worker.returncode.connect(self.hide_tz_spinner) self.worker.returncode.connect(self.enable_window_widgets) self.worker.returncode.connect(self.check_time_zone_auto_result) # disable button and show spinner self.disable_window_widgets() - self.show_spinner() + self.show_tz_spinner() # start the thread self.thread.start() From b1b5c20320237704d737c168cee494d7f715d3a1 Mon Sep 17 00:00:00 2001 From: bert003 Date: Sun, 30 Apr 2023 16:20:34 +0200 Subject: [PATCH 4/4] Revert "Update Date and Time" This reverts commit da269c7fa0adc4f9b40650efa7cbff8c38ed3c90. --- Preferences/Date and Time.app/Date and Time | 79 ++++++++------------- 1 file changed, 29 insertions(+), 50 deletions(-) diff --git a/Preferences/Date and Time.app/Date and Time b/Preferences/Date and Time.app/Date and Time index b6c4cc2a..fc7df2fd 100755 --- a/Preferences/Date and Time.app/Date and Time +++ b/Preferences/Date and Time.app/Date and Time @@ -35,20 +35,6 @@ class DateTimeWindow(QMainWindow): def __init__(self): super().__init__() - # Create Date Time spinner - self.dt_spinner = QLabel() - self.dt_spinner.setMovie(QMovie(os.path.dirname(__file__) + "/Resources/spinner.gif")) - self.dt_spinner.movie().start() - self.dt_spinner.setAlignment(Qt.AlignHCenter | Qt.AlignTop) - self.dt_spinner.hide() - - # Create Time Zone spinner - self.tz_spinner = QLabel() - self.tz_spinner.setMovie(QMovie(os.path.dirname(__file__) + "/Resources/spinner.gif")) - self.tz_spinner.movie().start() - self.tz_spinner.setAlignment(Qt.AlignHCenter | Qt.AlignTop) - self.tz_spinner.hide() - # Create tab widget self.tabs = QTabWidget() @@ -67,8 +53,7 @@ class DateTimeWindow(QMainWindow): # Set window properties self.setWindowTitle("Date and Time") - #self.setMinimumSize(400, 320) - self.setFixedSize(400, 320) + self.setMinimumSize(400, 250) # File menu self.file_menu = self.menuBar().addMenu("File") @@ -113,6 +98,20 @@ class DateTimeWindow(QMainWindow): about_action = self.help_menu.addAction("About", self.show_about) about_action.setShortcut("Ctrl+?") + # Create spinner + self.spinner = QLabel(self) + # Generated using http://ajaxload.info/ + self.spinner.setFixedSize(400, 250) + self.spinner.setMovie( + QMovie(os.path.dirname(__file__) + "/Resources/spinner.gif")) + self.spinner.movie().start() + self.spinner.setAlignment(Qt.AlignCenter) + self.spinner.move(0, 0) + self.spinner.hide() + # Connect to the resizeEvent of the window to update the position of the spinner + self.resizeEvent = lambda event: self.spinner.move( + (self.width()//2)-200, (self.height()//2)-125) + def send_shortcut(self, key_code, modifier): # Send shortcut to currently focused widget like Ctrl+C, Ctrl+V, etc. widget = self.focusWidget() @@ -149,12 +148,6 @@ class DateTimeWindow(QMainWindow): self.vbox_set_date_time_auto = QVBoxLayout() self.vbox_set_date_time_auto.addWidget(self.btn_set_date_time_auto) self.grp_set_date_time_auto.setLayout(self.vbox_set_date_time_auto) - - self.grp_dt_spinner = QGroupBox("", self) - self.grp_dt_spinner.setStyleSheet("border : 0;") - self.vbox_dt_spinner = QVBoxLayout() - self.vbox_dt_spinner.addWidget(self.dt_spinner) - self.grp_dt_spinner.setLayout(self.vbox_dt_spinner) # Connect signals to slots self.btn_set_date_time_manual.clicked.connect( @@ -164,9 +157,10 @@ class DateTimeWindow(QMainWindow): # Create grid layout for date/time tab self.grid_layout_date_time = QGridLayout() - self.grid_layout_date_time.addWidget(self.grp_set_date_time, 2, 0, 1, 2) - self.grid_layout_date_time.addWidget(self.grp_set_date_time_auto, 3, 0, 1, 2) - self.grid_layout_date_time.addWidget(self.grp_dt_spinner, 4, 0, 1, 2) + self.grid_layout_date_time.addWidget( + self.grp_set_date_time, 2, 0, 1, 2) + self.grid_layout_date_time.addWidget( + self.grp_set_date_time_auto, 3, 0, 1, 2) self.grid_layout_date_time.setRowStretch(4, 1) # Create date/time tab and set layout @@ -183,19 +177,12 @@ class DateTimeWindow(QMainWindow): self.vbox_set_time_zone.addWidget(self.btn_set_time_zone_auto) self.grp_set_time_zone.setLayout(self.vbox_set_time_zone) - self.grp_tz_spinner = QGroupBox("", self) - self.grp_tz_spinner.setStyleSheet("border : 0;") - self.vbox_tz_spinner = QVBoxLayout() - self.vbox_tz_spinner.addWidget(self.tz_spinner) - self.grp_tz_spinner.setLayout(self.vbox_tz_spinner) - # Connect signals to slots self.btn_set_time_zone_auto.clicked.connect(self.set_time_zone_auto) # Create grid layout for time zone tab self.grid_layout_time_zone = QGridLayout() self.grid_layout_time_zone.addWidget(self.grp_set_time_zone, 1, 0) - self.grid_layout_time_zone.addWidget(self.grp_tz_spinner, 2, 0) self.grid_layout_time_zone.setRowStretch(2, 1) # Create time zone tab and set layout @@ -229,21 +216,13 @@ class DateTimeWindow(QMainWindow): f"An error occurred while setting the Date and Time: {e.stderr}") self.spinner.hide() - # show date time spinner wrapper - def show_dt_spinner(self): - self.dt_spinner.show() - - # show time zone spinner wrapper - def show_tz_spinner(self): - self.tz_spinner.show() - - # hide date time spinner wrapper - def hide_dt_spinner(self): - self.dt_spinner.hide() + # show spinner wrapper + def show_spinner(self): + self.spinner.show() - # hide date time spinner wrapper - def hide_tz_spinner(self): - self.tz_spinner.hide() + # hide spinner wrapper + def hide_spinner(self): + self.spinner.hide() # enable all widgets def enable_window_widgets(self): @@ -279,12 +258,12 @@ class DateTimeWindow(QMainWindow): self.thread.started.connect(self.worker.run) self.worker.finished.connect(self.thread.quit) # set actions to execute when thread is done - self.worker.returncode.connect(self.hide_dt_spinner) + self.worker.returncode.connect(self.hide_spinner) self.worker.returncode.connect(self.enable_window_widgets) self.worker.returncode.connect(self.check_date_time_auto_result) # disable button and show spinner self.disable_window_widgets() - self.show_dt_spinner() + self.show_spinner() # start the thread self.thread.start() @@ -299,12 +278,12 @@ class DateTimeWindow(QMainWindow): self.thread.started.connect(self.worker.run) self.worker.finished.connect(self.thread.quit) # set actions to execute when thread is done - self.worker.returncode.connect(self.hide_tz_spinner) + self.worker.returncode.connect(self.hide_spinner) self.worker.returncode.connect(self.enable_window_widgets) self.worker.returncode.connect(self.check_time_zone_auto_result) # disable button and show spinner self.disable_window_widgets() - self.show_tz_spinner() + self.show_spinner() # start the thread self.thread.start()