Exemplo n.º 1
0
class ProcessManager:

    configuration = Configuration()
    utility: Utility = Utility()

    def start(self, path: str) -> Tuple[ActionResult, Optional[Popen]]:
        """
        Open file path using ahk executable path

        Args:
            path (str): file path

        Returns:
            Tuple[ActionResult,  Optional[Popen]]:
                ActionResult: return error
                    if failed to start script
                 Optional[Popen]: launched ahk process
        """

        result = ActionResult()

        if not self.utility.is_file(path):
            result.add_error(
                ErrorMessages.script_path_not_valid.format(path))
            return result, None

        ahk_path = ProcessManager.configuration.utility.ahk_executable
        if not ahk_path:
            result.add_error(
                ErrorMessages.autohotkey_path_is_not_valid.format(ahk_path))
            return result, None

        try:
            process = subprocess.Popen([ahk_path, path], shell=False)
            return result, process
        except Exception:
            result.add_error(
                ErrorMessages.could_not_start_script.format(path))
            return result, None

    def open_explorer(self, path: str) -> ActionResult:
        """
        Open path in file explorer for windows only

        Args:
            path (str): file path

        Returns:
            ActionResult: return error
                if for some reason failed to open path
        """

        result = ActionResult()

        try:
            subprocess.Popen('explorer /select,{}'.format(path))
        except Exception:
            result.add_error(ErrorMessages.could_not_open_path.format(path))

        return result
Exemplo n.º 2
0
    def error(self, msg):
        from src.core.utility.configuration import Configuration
        configuration = Configuration()
        if configuration.utility.log_level > self._log_level['error']:
            return

        msg = self._format_message('ERROR', msg)
        if configuration.utility.enable_logging:
            self.logger.error(msg)

        if configuration.utility.enable_debugging:
            print(msg)
Exemplo n.º 3
0
    def critical(self, msg):
        from src.core.utility.configuration import Configuration
        configuration = Configuration()
        if configuration.utility.log_level > self._log_level['critical']:
            return

        msg = self._format_message('CRITICAL', msg)
        if configuration.utility.enable_logging:
            self.logger.critical(msg)

        if configuration.utility.enable_debugging:
            print(msg)
Exemplo n.º 4
0
    def log(self, msg):
        from src.core.utility.configuration import Configuration
        configuration = Configuration()
        if int(configuration.utility.log_level) > int(self._log_level['log']):
            return

        msg = self._format_message('', msg)
        if configuration.utility.enable_logging:
            self.logger.debug(msg)

        if configuration.utility.enable_debugging:
            print(msg)
Exemplo n.º 5
0
    def warning(self, msg):
        from src.core.utility.configuration import Configuration
        configuration = Configuration()
        if configuration.utility.log_level > self._log_level['warning']:
            return

        msg = self._format_message('Warning', msg)
        if configuration.utility.enable_logging:
            self.logger.warning(msg)

        if configuration.utility.enable_debugging:
            print(msg)
Exemplo n.º 6
0
class Application(QApplication):

    app_service = AppService()
    configuration = Configuration()

    def __init__(self):
        QApplication.__init__(self, sys.argv)

        self.app_service.app_model.application = self

        self.setStyle(QtWidgets.QStyleFactory.create('Fusion'))
        self.setWindowIcon(
            QtGui.QIcon(self.configuration.main_window.icon_path))
        self.setQuitOnLastWindowClosed(False)

        self.windows = []
        # create main window
        self.windows.append(MainWindow())
Exemplo n.º 7
0
class AppService:

    configuration: Configuration = Configuration()

    app_model: AppModel = AppModel()
    profile_selected_events: List[Callable] = []
    library_selected_events: List[Callable] = []

    # region public methods

    def get_library_list(self) -> List[Library]:
        return library_service.repository.library_list

    def get_profile_list(self) -> List[Profile]:
        return profile_service.repository.profile_list

    def get_selected_library_scripts(self) -> List[Script]:
        if not self.app_model.selected_library_id:
            return []

        library = library_service.find(self.app_model.selected_library_id)
        return library.script_list if library else []

    def get_selected_profile_scripts(self) -> List[Library]:
        if not self.app_model.selected_profile_id:
            return []

        return profile_service.get_profile_scripts(
            self.app_model.selected_profile_id)

    def refresh(self):
        self.app_model.main_window.refresh()

    def save_configuration(self):
        self.configuration.save(profile_service.repository,
                                library_service.repository)

    # endregion public methods

    # region events

    def on_profile_selected(self, identifier: str):
        profile = profile_service.find(identifier)
        if not profile:
            self.app_model.selected_profile_id = None
        else:
            self.app_model.selected_profile_id = identifier

        self._exec_events(self.profile_selected_events)

    def on_library_selected(self, identifier: str):
        library = library_service.find(identifier)
        if not library:
            self.app_model.selected_library_id = None
        else:
            self.app_model.selected_library_id = identifier

        self._exec_events(self.library_selected_events)

    # endregion events

    # region private methods

    def _exec_events(self, events):
        for method in events:
            try:
                method()
            except Exception as error:
                print(error)
Exemplo n.º 8
0
class SettingsDialog(QDialog):

    save_button_size = QSize(60, 30)
    browse_button_size = QSize(30, 20)
    file_type_splitter = ';'
    row_height = 40

    configuration = Configuration()

    def __init__(self, parent):
        QDialog.__init__(self, parent)

        self.path_line_edit = None
        self.file_type_line_edit = None

        self._init()

    def _init(self):
        config = self.configuration.settings_dialog

        # set attribute
        self.setWindowTitle(config.name)
        self.resize(config.width, config.height)

        # setup layout
        layout = QVBoxLayout(self)
        settings_layout = QGridLayout()
        ok_layout = QHBoxLayout()

        layout.addLayout(settings_layout)
        layout.addStretch(1)
        ok_layout.setStretch(0, 0)

        # AHK path
        path_label = QLabel('AutoHotKey executable path:', self)
        settings_layout.addWidget(path_label, 0, 0, 1, 1)

        self.path_line_edit = QLineEdit(self)
        self.path_line_edit.setText(self.configuration.utility.ahk_executable)
        settings_layout.addWidget(self.path_line_edit, 0, 1, 1, 1)

        browse_button = QPushButton('...', self)
        browse_button.setFixedSize(self.browse_button_size)
        settings_layout.addWidget(browse_button, 0, 2, 1, 1)
        browse_button.clicked.connect(self.on_browse_button_clicked)

        # file types
        file_type_label = QLabel('AutoHotKey file type:', self)
        settings_layout.addWidget(file_type_label, 1, 0, 1, 1)

        self.file_type_line_edit = QLineEdit(self)
        self.file_type_line_edit.setText(
            self.file_type_splitter.join(
                self.configuration.utility.file_types))
        settings_layout.addWidget(self.file_type_line_edit, 1, 1, 1, 1)

        # ok and cancel button
        layout.addLayout(ok_layout)

        save_button = QPushButton('Save', self)
        save_button.setFixedSize(self.save_button_size)
        ok_layout.addWidget(save_button)
        save_button.clicked.connect(self.on_save_button_clicked)

        cancel_button = QPushButton('Cancel', self)
        ok_layout.addWidget(cancel_button)
        cancel_button.setFixedSize(self.save_button_size)
        cancel_button.clicked.connect(self.on_cancel_button_clicked)

    # region event

    def on_save_button_clicked(self):
        self.configuration.utility.ahk_executable = self.path_line_edit.text()
        self.configuration.utility.file_types = \
            self.file_type_line_edit.text().split(self.file_type_splitter)
        self.configuration.save_general_configs()
        self.accept()

    def on_cancel_button_clicked(self):
        self.reject()

    def on_browse_button_clicked(self):
        dialog = QFileDialog(self, 'AutoHotKey program')
        dialog.setNameFilters(['Program Files (*.exe)', 'All (*.*)'])
        dialog.selectNameFilter('Program Files (*.exe)')

        if dialog.exec_():
            filenames = dialog.selectedFiles()
            if not filenames:
                return

            self.path_line_edit.setText(filenames[0])

    def closeEvent(self, _):
        self.configuration.settings_dialog.width = self.width()
        self.configuration.settings_dialog.height = self.height()
        self.configuration.save_general_configs()
        self.close()
Exemplo n.º 9
0
import os

from src.core.service.library_service import library_service
from src.core.service.message_service import MessageService
from src.core.service.profile_service import ProfileService
from src.core.utility.configuration import Configuration

path = os.getcwd() + '\\test_data\\AutoHotKey'

message_service = MessageService()
profile_service = ProfileService()
configuration = Configuration()
configuration.load()

library_service.add(path)
profile_service.add('programming')
profile_service.add('gaming')
# repo_manager = RepoManager.from_json(configs.load_repository())
library_service.refresh()
script = library_service.find_script(
    os.getcwd() + '\\test_data\\AutoHotKey\\Startup\\Duplicate Line.ahk')
script2 = library_service.find_script(
    os.getcwd() + '\\test_data\\AutoHotKey\\Common\\Select Line.ahk')
profile_service.add_script('programming', script)
profile_service.add_script('gaming', script2)
gaming = profile_service.find('gaming')
programming = profile_service.find('programming')

profile_service.start('gaming')
for msg in message_service.messages:
    print(msg)
Exemplo n.º 10
0
class ScriptManager:

    process_manager = ProcessManager()
    configuration = Configuration()
    utility: Utility = Utility()

    def init_script(self, path: str) -> Tuple[ActionResult, Script]:
        """
        Initialize script

        Args:
            path (str): script path

        Returns:
            Tuple[ActionResult, Script]: return error
                if script path is invalid
        """

        result = ActionResult()

        path = self.utility.format_path(path)
        # check if path not the file type we want
        temp_result = self._is_script_file(path)
        result.merge(temp_result)

        if not temp_result.success():
            return result, None

        script = Script(path)
        return result, script

    # region public methods

    def remove(self, script: Script) -> ActionResult:
        """
        Remove script, trying to stop script first

        Args:
            script (Script):

        Returns:
            ActionResult: return error if script
                not allow state change or not exists
        """

        # for some reason we can not stop the script
        result, script = self.stop(script)

        if not result.success():
            result.add_error(
                ErrorMessages.could_not_remove_script_could_not_stop.format(
                    script.identifier()))

        return result

    def refresh(self, script: Script) -> Tuple[ActionResult, Script]:
        """
        Refresh script, check whether it exists

        Args:
            script (Script):

        Returns:
            Tuple[ActionResult, Script]:
        """

        result = ActionResult()

        # check whether file exists
        if not script.exists():
            result.add_error(
                ErrorMessages.could_not_refresh_script_script_removed.format(
                    script.identifier()))

        return result, script

    # endregion public methods

    # region command

    def start(self, script: Script) -> Tuple[ActionResult, Script]:
        """
        Start script

        Args:
            script (Script):

        Returns:
            Tuple[ActionResult, Script]:
        """

        result = ActionResult()

        # check whether script is locked or not exists
        if not script.allow_state_change and not script.is_running():
            result.add_error(
                ErrorMessages.could_not_start_locked_script.format(
                    script.identifier()))
            return result, script

        if script.is_running():
            return result, script

        return self._start_script(script)

    def stop(self, script: Script) -> Tuple[ActionResult, Script]:
        """
        Stop script

        Args:
            script (Script):

        Returns:
            Tuple[ActionResult, Script]:
        """

        result = ActionResult()

        if not script.is_running():
            return result, script

        # check whether script is locked or not exists
        if not script.allow_state_change():
            result.add_error(
                ErrorMessages.could_not_stop_locked_script.format(
                    script.identifier()))
            return result, script

        # trying to kill the process
        try:
            script.process.kill()
            script.stop()
        except Exception:
            result.add_error(
                ErrorMessages.could_not_stop_script.format(
                    script.identifier()))

        return result, script

    def force_start(self, script: Script) -> Tuple[ActionResult, Script]:
        """
        Force start script, script will be locked after this completed

        Args:
            script (Script):

        Returns:
            Tuple[ActionResult, Script]:
        """

        result = ActionResult()

        temp_result, script = self._start_script(script)
        result.merge(temp_result)

        if temp_result.success():
            script.lock()

        return result, script

    def restart(self, script: Script) -> Tuple[ActionResult, Script]:
        """
        Restart script

        Args:
            script (Script):

        Returns:
            Tuple[ActionResult, Script]:
        """

        result = ActionResult()

        if not script.allow_state_change():
            result.add_error(
                ErrorMessages.could_not_restart_script.format(
                    script.identifier()))
            return result, script

        temp_result, script = self.stop(script)

        if not temp_result.success():
            return temp_result, script

        return self._start_script(script)

    def pause(self, script: Script) -> Tuple[ActionResult, Script]:
        """
        Pause script

        Args:
            script (Script):

        Returns:
            Tuple[ActionResult, Script]: return error when process
                cannot be stopped
        """

        result = ActionResult()

        if not script.is_running():
            return result, script

        # * check whether script is locked or not exists
        if not script.allow_state_change():
            result.add_error(
                ErrorMessages.could_not_stop_locked_script.format(
                    script.identifier()))
            return result, script

        # trying to kill the process
        try:
            script.process.kill()
            script.pause()
        except Exception:
            result.add_error(
                ErrorMessages.could_not_stop_script.format(
                    script.identifier()))

        return result, script

    def resume(self, script: Script) -> Tuple[ActionResult, Script]:
        """
        Resume script if it is being paused

        Args:
            script (Script):

        Returns:
            Tuple[ActionResult, Script]:
                Return error when script cannot start
        """

        if not script.is_paused():
            return ActionResult(), script

        result = ActionResult()

        # check whether script is locked or not exists
        if not script.allow_state_change():
            result.add_error(
                ErrorMessages.could_not_start_locked_script.format(
                    script.identifier()))
            return result, script

        result, script = self._start_script(script)
        if result.success():
            script.resume()

        return result, script

    # endregion command

    def _start_script(self, script: Script) -> Tuple[ActionResult, Script]:
        result = ActionResult()

        temp_result, process = self.process_manager.start(script.path)

        if not temp_result.success() or not process:
            return temp_result, script

        script.start(process)
        return result, script

    def _is_script_file(self, path: str) -> ActionResult:
        result = ActionResult()

        if not self.utility.is_file(path):
            result.add_error(ErrorMessages.path_is_not_file.format(path))
            return result

        is_script_file = self.utility.get_file_extension(path) in \
            ScriptManager.configuration.utility.file_types
        if not is_script_file:
            result.add_error(
                ErrorMessages.path_is_not_script_file.format(path))

        return result
Exemplo n.º 11
0
class MainWindow(QMainWindow):
    configuration = Configuration()
    app_service = AppService()

    def __init__(self):
        QMainWindow.__init__(self)

        self._load_configs()
        self._init()
        self.app_service.app_model.main_window = self

        # create a vertical layout in the window
        # all widget should insert into the layout
        central_widget = QWidget(self)
        vertical_layout = QVBoxLayout(central_widget)
        self.setCentralWidget(central_widget)

        # initialize tab widget
        self.tab_widget = TabWidget(self)
        vertical_layout.addWidget(self.tab_widget)

        # add tray icon
        self.tray_icon = TrayIcon(self)

        self.refresh()
        self.show()

    def _init(self):
        config = self.configuration.main_window

        # set attributes
        self.setWindowTitle(config.name)
        self.resize(config.width, config.height)

        self._create_menus()

    # region events

    def closeEvent(self, event):
        library_service.stop_all()

        # Save configuration when window is closed
        self.configuration.main_window.width = self.width()
        self.configuration.main_window.height = self.height()
        self.app_service.save_configuration()
        self.tray_icon.hide()
        sys.exit()

    def changeEvent(self, event):
        if event.type() == QEvent.WindowStateChange:
            if self.windowState() & Qt.WindowMinimized:
                self.setVisible(False)

    # endregion events

    # region public methods

    def refresh(self):
        self.tab_widget.refresh()

    # endregion public methods

    # region private methods

    def _load_configs(self):
        # load saved settings
        self.configuration.load()
        repo = self.configuration.load_libraries()
        if repo:
            library_service.repository = LibraryRepository.from_json(repo)
        repo = self.configuration.load_profiles()
        if repo:
            profile_service.repository = ProfileRepository.from_json(repo)

    def _create_menus(self):
        main_menu = self.menuBar()

        # setting
        settings_menu = main_menu.addMenu('Settings')

        settings_action = QAction("Settings", self)
        settings_action.triggered.connect(self._show_settings)

        settings_menu.addAction(settings_action)

        # # library
        # libraryMenu = mainMenu.addMenu('Library')
        # libraryMenu.addAction(settingsAction)

        # # profile
        # profileMenu = mainMenu.addMenu('Profile')
        # profileMenu.addAction(settingsAction)

    def _show_settings(self):
        dialog = SettingsDialog(self)
        dialog.exec_()
Exemplo n.º 12
0
class AddScriptToProfileDialog(QDialog):

    add_button_size = QSize(50, 40)
    ok_button_size = QSize(100, 60)

    app_service: AppService = AppService()
    configuration: Configuration = Configuration()

    def __init__(self, parent):
        QDialog.__init__(self, parent)

        self.available_scripts: List[Script] = []
        self.selected_scripts: List[Script] = []
        self.available_script_table: TableWidget = None
        self.selected_script_table: TableWidget = None

        self._init_available_scripts()
        self._init()
        self.show()

    def _init(self):
        config = self.configuration.add_script_dialog

        # set attributes
        self.setWindowTitle(config.name)
        self.resize(config.width, config.height)

        # setup layouts
        layout = QVBoxLayout(self)
        script_table_layout = QHBoxLayout()
        ok_layout = QHBoxLayout()
        available_layout = QVBoxLayout()
        button_layout = QVBoxLayout()
        selected_layout = QVBoxLayout()

        layout.addLayout(script_table_layout)
        layout.addLayout(ok_layout)

        script_table_layout.addLayout(available_layout)
        script_table_layout.addLayout(button_layout)
        script_table_layout.addLayout(selected_layout)

        # initialize available script table
        self.available_script_table = AddScriptDialogTableWidget(
            self, self.available_scripts)
        self.available_script_table.itemDoubleClicked.connect(
            self.on_available_script_table_item_double_clicked)
        available_layout.addWidget(self.available_script_table)
        self.available_script_table.refresh()

        # initialize selected script table
        self.selected_script_table = AddScriptDialogTableWidget(
            self, self.selected_scripts)
        self.selected_script_table.itemDoubleClicked.connect(
            self.on_selected_script_table_item_double_clicked)
        selected_layout.addWidget(self.selected_script_table)
        self.available_script_table.refresh()

        # add and remove button
        button_layout.addStretch(1)
        add_button = QPushButton('>', self)
        add_button.setFixedSize(self.add_button_size)
        button_layout.addWidget(add_button)
        add_button.clicked.connect(self.on_add_button_clicked)

        add_all_button = QPushButton('>>>', self)
        add_all_button.setFixedSize(self.add_button_size)
        button_layout.addWidget(add_all_button)
        add_all_button.clicked.connect(self.on_add_all_button_clicked)
        button_layout.addStretch(1)

        remove_button = QPushButton('<', self)
        button_layout.addWidget(remove_button)
        remove_button.setFixedSize(self.add_button_size)
        remove_button.clicked.connect(self.on_remove_button_clicked)

        remove_all_button = QPushButton('<<<', self)
        button_layout.addWidget(remove_all_button)
        remove_all_button.setFixedSize(self.add_button_size)
        remove_all_button.clicked.connect(self.on_remove_all_button_clicked)
        button_layout.addStretch(1)

        # ok and cancel button
        ok_button = QPushButton('Ok', self)
        ok_button.setFixedSize(self.ok_button_size)
        ok_layout.addWidget(ok_button)
        ok_button.clicked.connect(self.on_ok_button_clicked)

        cancel_button = QPushButton('Cancel', self)
        ok_layout.addWidget(cancel_button)
        cancel_button.setFixedSize(self.ok_button_size)
        cancel_button.clicked.connect(self.on_cancel_button_clicked)

    def get_selected_scripts(self) -> List[Script]:
        return self.selected_script_table.scripts

    # region events

    def on_ok_button_clicked(self):
        self.accept()

    def on_cancel_button_clicked(self):
        self.reject()

    def on_add_button_clicked(self):
        # get selected table items
        selected_items = self.available_script_table.selectedItems()
        if not selected_items:
            return

        # each row has x number of columns
        step = len(self.available_script_table.columns)
        i = 0
        while i < len(selected_items):
            item = selected_items[i]
            self._select_script(item.script_id)
            i += step

    def on_add_all_button_clicked(self):
        # reset the scripts
        # now you will have everything available in avaliable_script list
        self._init_available_scripts()

        # set selected as available scripts
        self.selected_scripts = self.available_scripts
        self.available_scripts = []

        # set the table scripts
        self.selected_script_table.scripts = self.selected_scripts
        self.available_script_table.scripts = self.available_scripts

        # refresh tables
        self.available_script_table.refresh()
        self.selected_script_table.refresh()

    def on_remove_all_button_clicked(self):
        # reset all data
        self._init_available_scripts()
        self.selected_script_table.scripts = self.selected_scripts
        self.available_script_table.scripts = self.available_scripts
        self.available_script_table.refresh()
        self.selected_script_table.refresh()

    def on_remove_button_clicked(self):
        selected_items = self.selected_script_table.selectedItems()
        if not selected_items:
            return

        # each row has x number of columns
        step = len(self.selected_script_table.columns)
        i = 0
        while i < len(selected_items):
            item = selected_items[i]
            self._unselect_script(item.script_id)
            i += step

    def on_available_script_table_item_double_clicked(self, item):
        self._select_script(item.script_id)

    def on_selected_script_table_item_double_clicked(self, item):
        self._unselect_script(item.script_id)

    def closeEvent(self, _):
        self.configuration.add_script_dialog.width = self.width()
        self.configuration.add_script_dialog.height = self.height()
        self.configuration.save_general_configs()
        self.close()

    # endregion events

    def _init_available_scripts(self):
        profile = profile_service.find(
            self.app_service.app_model.selected_profile_id)
        if not profile:
            return

        self.available_scripts = []
        self.selected_scripts = []
        scripts = library_service.get_all_scripts()

        for script_id in profile.script_id_list:
            found = next((x for x in scripts if x.has_id(script_id)), None)
            if not found:
                continue

            scripts.remove(found)

        self.available_scripts = scripts

    def _select_script(self, script_id):
        script = next(
            (x for x in self.available_scripts if x.has_id(script_id)), None)
        if not script:
            return

        self.selected_scripts.append(script)
        self.available_scripts.remove(script)
        self.selected_script_table.refresh()
        self.available_script_table.refresh()

    def _unselect_script(self, script_id):
        script = next(
            (x for x in self.selected_scripts if x.has_id(script_id)), None)
        if not script:
            return

        self.available_scripts.append(script)
        self.selected_scripts.remove(script)
        self.available_script_table.refresh()
        self.selected_script_table.refresh()
Exemplo n.º 13
0
class TrayIcon(QSystemTrayIcon):

    configuration: Configuration = Configuration()
    app_service: AppService = AppService()

    def __init__(self, parent=None):
        QSystemTrayIcon.__init__(self, parent)

        # set tray icon
        self.setIcon(QtGui.QIcon(self.configuration.main_window.icon_path))

        # double click event
        self.activated.connect(self.on_activated)

        # add right click menu
        menu = QMenu(parent)

        pause_action = menu.addAction(button_text_pause)
        pause_action.triggered.connect(self.on_pause_triggered)

        resume_action = menu.addAction(button_text_resume)
        resume_action.triggered.connect(self.on_resume_triggered)

        stop_all_action = menu.addAction(button_text_stop)
        stop_all_action.triggered.connect(self.on_stop_triggered)

        menu.addSeparator()

        show_action = menu.addAction(button_text_show)
        show_action.triggered.connect(self.show_triggered)

        exit_action = menu.addAction(button_text_exit)
        exit_action.triggered.connect(self.on_exit_triggered)

        self.setContextMenu(menu)
        self.show()

    def on_activated(self, reason):
        if reason == QSystemTrayIcon.DoubleClick:
            self.show_triggered()

    def show_triggered(self):
        self.app_service.app_model.main_window.setVisible(True)
        self.app_service.app_model.main_window.setWindowState(Qt.WindowActive)

    def on_exit_triggered(self):
        self.app_service.app_model.main_window.closeEvent(QCloseEvent())

    def on_stop_triggered(self):
        library_service.stop_all()
        profile_service.stop_all()

        self._refresh_main_window()
        self._show_message_box(dialog_message_stop)

    def on_pause_triggered(self):
        library_service.pause_all()
        self._refresh_main_window()
        self._show_message_box(dialog_message_pause)

    def on_resume_triggered(self):
        library_service.resume_all()
        self._refresh_main_window()
        self._show_message_box(dialog_message_resume)

    # region private methods

    def _show_message_box(self, message: str):
        # * Show notification box
        message_box = QMessageBox(None)
        message_box.setIcon(QMessageBox.Information)
        message_box.setText(message)
        message_box.setWindowTitle(dialog_title)
        message_box.exec_()

    def _refresh_main_window(self):
        # * Refresh UI
        self.app_service.app_model.main_window.refresh()