forked from openlp/openlp
1392 lines
77 KiB
Python
1392 lines
77 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
##########################################################################
|
|
# OpenLP - Open Source Lyrics Projection #
|
|
# ---------------------------------------------------------------------- #
|
|
# Copyright (c) 2008-2021 OpenLP Developers #
|
|
# ---------------------------------------------------------------------- #
|
|
# This program is free software: you can redistribute it and/or modify #
|
|
# it under the terms of the GNU General Public License as published by #
|
|
# the Free Software Foundation, either version 3 of the License, or #
|
|
# (at your option) any later version. #
|
|
# #
|
|
# This program is distributed in the hope that it will be useful, #
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
# GNU General Public License for more details. #
|
|
# #
|
|
# You should have received a copy of the GNU General Public License #
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
|
##########################################################################
|
|
"""
|
|
This is the main window, where all the action happens.
|
|
"""
|
|
import os
|
|
import shutil
|
|
from datetime import datetime, date
|
|
from pathlib import Path
|
|
from tempfile import gettempdir
|
|
|
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
|
|
|
from openlp.core.state import State
|
|
from openlp.core.api.websockets import WebSocketServer
|
|
from openlp.core.api.http.server import HttpServer
|
|
from openlp.core.api.zeroconf import start_zeroconf
|
|
from openlp.core.common import add_actions, is_macosx, is_win
|
|
from openlp.core.common.actions import ActionList, CategoryOrder
|
|
from openlp.core.common.applocation import AppLocation
|
|
from openlp.core.common.i18n import LanguageManager, UiStrings, translate
|
|
from openlp.core.common.mixins import LogMixin, RegistryProperties
|
|
from openlp.core.common.path import create_paths
|
|
from openlp.core.common.registry import Registry
|
|
from openlp.core.common.settings import Settings
|
|
from openlp.core.display.screens import ScreenList
|
|
from openlp.core.lib.plugin import PluginStatus
|
|
from openlp.core.lib.ui import create_action
|
|
from openlp.core.projectors.manager import ProjectorManager
|
|
from openlp.core.ui.aboutform import AboutForm
|
|
from openlp.core.ui.firsttimeform import FirstTimeForm
|
|
from openlp.core.ui.formattingtagform import FormattingTagForm
|
|
from openlp.core.ui.icons import UiIcons
|
|
from openlp.core.ui.pluginform import PluginForm
|
|
from openlp.core.ui.printserviceform import PrintServiceForm
|
|
from openlp.core.ui.servicemanager import ServiceManager
|
|
from openlp.core.ui.settingsform import SettingsForm
|
|
from openlp.core.ui.shortcutlistform import ShortcutListForm
|
|
from openlp.core.ui.style import PROGRESSBAR_STYLE, get_library_stylesheet
|
|
from openlp.core.ui.thememanager import ThemeManager
|
|
from openlp.core.version import get_version
|
|
from openlp.core.widgets.dialogs import FileDialog
|
|
from openlp.core.widgets.docks import MediaDockManager, OpenLPDockWidget
|
|
|
|
|
|
class Ui_MainWindow(object):
|
|
"""
|
|
This is the UI part of the main window.
|
|
"""
|
|
def setup_ui(self, main_window):
|
|
"""
|
|
Set up the user interface
|
|
"""
|
|
main_window.setObjectName('MainWindow')
|
|
main_window.setWindowIcon(UiIcons().main_icon)
|
|
main_window.setDockNestingEnabled(True)
|
|
if is_macosx():
|
|
main_window.setDocumentMode(True)
|
|
# Set up the main container, which contains all the other form widgets.
|
|
self.main_content = QtWidgets.QWidget(main_window)
|
|
self.main_content.setObjectName('main_content')
|
|
self.main_content_layout = QtWidgets.QHBoxLayout(self.main_content)
|
|
self.main_content_layout.setSpacing(0)
|
|
self.main_content_layout.setContentsMargins(0, 0, 0, 0)
|
|
self.main_content_layout.setObjectName('main_content_layout')
|
|
main_window.setCentralWidget(self.main_content)
|
|
self.control_splitter = QtWidgets.QSplitter(self.main_content)
|
|
self.control_splitter.setOrientation(QtCore.Qt.Horizontal)
|
|
self.control_splitter.setObjectName('control_splitter')
|
|
self.main_content_layout.addWidget(self.control_splitter)
|
|
preview_visible = self.settings.value('user interface/preview panel')
|
|
live_visible = self.settings.value('user interface/live panel')
|
|
panel_locked = self.settings.value('user interface/lock panel')
|
|
# Create menu
|
|
self.menu_bar = QtWidgets.QMenuBar(main_window)
|
|
self.menu_bar.setObjectName('menu_bar')
|
|
self.file_menu = QtWidgets.QMenu(self.menu_bar)
|
|
self.file_menu.setObjectName('fileMenu')
|
|
self.recent_files_menu = QtWidgets.QMenu(self.file_menu)
|
|
self.recent_files_menu.setObjectName('recentFilesMenu')
|
|
self.file_import_menu = QtWidgets.QMenu(self.file_menu)
|
|
if not is_macosx():
|
|
self.file_import_menu.setIcon(UiIcons().download)
|
|
self.file_import_menu.setObjectName('file_import_menu')
|
|
self.file_export_menu = QtWidgets.QMenu(self.file_menu)
|
|
if not is_macosx():
|
|
self.file_export_menu.setIcon(UiIcons().upload)
|
|
self.file_export_menu.setObjectName('file_export_menu')
|
|
# View Menu
|
|
self.view_menu = QtWidgets.QMenu(self.menu_bar)
|
|
self.view_menu.setObjectName('viewMenu')
|
|
self.view_mode_menu = QtWidgets.QMenu(self.view_menu)
|
|
self.view_mode_menu.setObjectName('viewModeMenu')
|
|
# Tools Menu
|
|
self.tools_menu = QtWidgets.QMenu(self.menu_bar)
|
|
self.tools_menu.setObjectName('tools_menu')
|
|
# Settings Menu
|
|
self.settings_menu = QtWidgets.QMenu(self.menu_bar)
|
|
self.settings_menu.setObjectName('settingsMenu')
|
|
self.settings_language_menu = QtWidgets.QMenu(self.settings_menu)
|
|
self.settings_language_menu.setObjectName('settingsLanguageMenu')
|
|
# Help Menu
|
|
self.help_menu = QtWidgets.QMenu(self.menu_bar)
|
|
self.help_menu.setObjectName('helpMenu')
|
|
main_window.setMenuBar(self.menu_bar)
|
|
self.status_bar = QtWidgets.QStatusBar(main_window)
|
|
self.status_bar.setObjectName('status_bar')
|
|
main_window.setStatusBar(self.status_bar)
|
|
self.load_progress_bar = QtWidgets.QProgressBar(self.status_bar)
|
|
self.load_progress_bar.setObjectName('load_progress_bar')
|
|
self.status_bar.addPermanentWidget(self.load_progress_bar)
|
|
self.load_progress_bar.hide()
|
|
self.load_progress_bar.setValue(0)
|
|
self.load_progress_bar.setStyleSheet(PROGRESSBAR_STYLE)
|
|
self.default_theme_label = QtWidgets.QLabel(self.status_bar)
|
|
self.default_theme_label.setObjectName('default_theme_label')
|
|
self.status_bar.addPermanentWidget(self.default_theme_label)
|
|
# Create the MediaManager
|
|
self.media_manager_dock = OpenLPDockWidget(main_window, 'media_manager_dock',
|
|
UiIcons().box)
|
|
self.media_manager_dock.setStyleSheet(get_library_stylesheet())
|
|
# Create the media toolbox
|
|
self.media_tool_box = QtWidgets.QToolBox(self.media_manager_dock)
|
|
self.media_tool_box.setObjectName('media_tool_box')
|
|
self.media_manager_dock.setWidget(self.media_tool_box)
|
|
main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.media_manager_dock)
|
|
# Create the service manager
|
|
self.service_manager_dock = OpenLPDockWidget(main_window, 'service_manager_dock',
|
|
UiIcons().live)
|
|
self.service_manager_contents = ServiceManager(self.service_manager_dock)
|
|
self.service_manager_dock.setWidget(self.service_manager_contents)
|
|
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.service_manager_dock)
|
|
# Create the theme manager
|
|
self.theme_manager_dock = OpenLPDockWidget(main_window, 'theme_manager_dock',
|
|
UiIcons().theme)
|
|
self.theme_manager_contents = ThemeManager(self.theme_manager_dock)
|
|
self.theme_manager_contents.setObjectName('theme_manager_contents')
|
|
self.theme_manager_dock.setWidget(self.theme_manager_contents)
|
|
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.theme_manager_dock)
|
|
# Create the projector manager
|
|
self.projector_manager_dock = OpenLPDockWidget(parent=main_window,
|
|
name='projector_manager_dock',
|
|
icon=UiIcons().projector)
|
|
self.projector_manager_contents = ProjectorManager(self.projector_manager_dock)
|
|
self.projector_manager_contents.setObjectName('projector_manager_contents')
|
|
self.projector_manager_dock.setWidget(self.projector_manager_contents)
|
|
self.projector_manager_dock.setVisible(False)
|
|
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.projector_manager_dock)
|
|
# Create the menu items
|
|
action_list = ActionList.get_instance()
|
|
action_list.add_category(UiStrings().File, CategoryOrder.standard_menu)
|
|
self.file_new_item = create_action(main_window, 'fileNewItem', icon=UiIcons().new,
|
|
can_shortcuts=True, category=UiStrings().File,
|
|
triggers=self.service_manager_contents.on_new_service_clicked)
|
|
self.file_open_item = create_action(main_window, 'fileOpenItem', icon=UiIcons().open,
|
|
can_shortcuts=True, category=UiStrings().File,
|
|
triggers=self.service_manager_contents.on_load_service_clicked)
|
|
self.file_save_item = create_action(main_window, 'fileSaveItem', icon=UiIcons().save,
|
|
can_shortcuts=True, category=UiStrings().File,
|
|
triggers=self.service_manager_contents.decide_save_method)
|
|
self.file_save_as_item = create_action(main_window, 'fileSaveAsItem', can_shortcuts=True,
|
|
category=UiStrings().File,
|
|
triggers=self.service_manager_contents.save_file_as)
|
|
self.print_service_order_item = create_action(main_window, 'printServiceItem', can_shortcuts=True,
|
|
category=UiStrings().File,
|
|
triggers=lambda x: PrintServiceForm().exec())
|
|
self.file_exit_item = create_action(main_window, 'fileExitItem', icon=UiIcons().exit,
|
|
can_shortcuts=True,
|
|
category=UiStrings().File, triggers=main_window.close)
|
|
# Give QT Extra Hint that this is the Exit Menu Item
|
|
self.file_exit_item.setMenuRole(QtWidgets.QAction.QuitRole)
|
|
action_list.add_category(UiStrings().Import, CategoryOrder.standard_menu)
|
|
self.import_theme_item = create_action(main_window, 'importThemeItem', category=UiStrings().Import,
|
|
can_shortcuts=True)
|
|
self.import_language_item = create_action(main_window, 'importLanguageItem')
|
|
action_list.add_category(UiStrings().Export, CategoryOrder.standard_menu)
|
|
self.export_theme_item = create_action(main_window, 'exportThemeItem', category=UiStrings().Export,
|
|
can_shortcuts=True)
|
|
self.export_language_item = create_action(main_window, 'exportLanguageItem')
|
|
action_list.add_category(UiStrings().View, CategoryOrder.standard_menu)
|
|
# Projector items
|
|
self.import_projector_item = create_action(main_window, 'importProjectorItem', category=UiStrings().Import,
|
|
can_shortcuts=False)
|
|
action_list.add_category(UiStrings().Import, CategoryOrder.standard_menu)
|
|
self.view_projector_manager_item = create_action(main_window, 'viewProjectorManagerItem',
|
|
icon=UiIcons().projector,
|
|
checked=self.projector_manager_dock.isVisible(),
|
|
can_shortcuts=True,
|
|
category=UiStrings().View,
|
|
triggers=self.toggle_projector_manager)
|
|
self.view_media_manager_item = create_action(main_window, 'viewMediaManagerItem',
|
|
icon=UiIcons().box,
|
|
checked=self.media_manager_dock.isVisible(),
|
|
can_shortcuts=True,
|
|
category=UiStrings().View, triggers=self.toggle_media_manager)
|
|
self.view_theme_manager_item = create_action(main_window, 'viewThemeManagerItem', can_shortcuts=True,
|
|
icon=UiIcons().theme,
|
|
checked=self.theme_manager_dock.isVisible(),
|
|
category=UiStrings().View, triggers=self.toggle_theme_manager)
|
|
self.view_service_manager_item = create_action(main_window, 'viewServiceManagerItem', can_shortcuts=True,
|
|
icon=UiIcons().live,
|
|
checked=self.service_manager_dock.isVisible(),
|
|
category=UiStrings().View, triggers=self.toggle_service_manager)
|
|
self.view_preview_panel = create_action(main_window, 'viewPreviewPanel', can_shortcuts=True,
|
|
checked=preview_visible, category=UiStrings().View,
|
|
triggers=self.set_preview_panel_visibility)
|
|
self.view_live_panel = create_action(main_window, 'viewLivePanel', can_shortcuts=True, checked=live_visible,
|
|
category=UiStrings().View, triggers=self.set_live_panel_visibility)
|
|
self.lock_panel = create_action(main_window, 'lockPanel', can_shortcuts=True, checked=panel_locked,
|
|
category=UiStrings().View, triggers=self.set_lock_panel)
|
|
action_list.add_category(UiStrings().ViewMode, CategoryOrder.standard_menu)
|
|
self.mode_default_item = create_action(
|
|
main_window, 'modeDefaultItem', checked=False, category=UiStrings().ViewMode, can_shortcuts=True)
|
|
self.mode_setup_item = create_action(main_window, 'modeSetupItem', checked=False, category=UiStrings().ViewMode,
|
|
can_shortcuts=True)
|
|
self.mode_live_item = create_action(main_window, 'modeLiveItem', checked=True, category=UiStrings().ViewMode,
|
|
can_shortcuts=True)
|
|
self.mode_group = QtWidgets.QActionGroup(main_window)
|
|
self.mode_group.addAction(self.mode_default_item)
|
|
self.mode_group.addAction(self.mode_setup_item)
|
|
self.mode_group.addAction(self.mode_live_item)
|
|
self.mode_default_item.setChecked(True)
|
|
action_list.add_category(UiStrings().Tools, CategoryOrder.standard_menu)
|
|
self.tools_add_tool_item = create_action(main_window,
|
|
'toolsAddToolItem', icon=UiIcons().add,
|
|
category=UiStrings().Tools, can_shortcuts=True)
|
|
self.tools_open_data_folder = create_action(main_window,
|
|
'toolsOpenDataFolder', icon=UiIcons().open,
|
|
category=UiStrings().Tools, can_shortcuts=True)
|
|
self.tools_first_time_wizard = create_action(main_window,
|
|
'toolsFirstTimeWizard', icon=UiIcons().undo,
|
|
category=UiStrings().Tools, can_shortcuts=True)
|
|
self.update_theme_images = create_action(main_window,
|
|
'updateThemeImages', category=UiStrings().Tools, can_shortcuts=True)
|
|
action_list.add_category(UiStrings().Settings, CategoryOrder.standard_menu)
|
|
self.settings_plugin_list_item = create_action(main_window,
|
|
'settingsPluginListItem',
|
|
icon=UiIcons().plugin_list,
|
|
can_shortcuts=True,
|
|
category=UiStrings().Settings,
|
|
triggers=self.on_plugin_item_clicked)
|
|
# i18n Language Items
|
|
self.auto_language_item = create_action(main_window, 'autoLanguageItem', checked=LanguageManager.auto_language)
|
|
self.language_group = QtWidgets.QActionGroup(main_window)
|
|
self.language_group.setExclusive(True)
|
|
self.language_group.setObjectName('languageGroup')
|
|
add_actions(self.language_group, [self.auto_language_item])
|
|
qm_list = LanguageManager.get_qm_list()
|
|
saved_language = LanguageManager.get_language()
|
|
for key in sorted(qm_list.keys()):
|
|
language_item = create_action(main_window, key, checked=qm_list[key] == saved_language)
|
|
add_actions(self.language_group, [language_item])
|
|
self.settings_shortcuts_item = create_action(main_window, 'settingsShortcutsItem',
|
|
icon=UiIcons().shortcuts,
|
|
category=UiStrings().Settings, can_shortcuts=True)
|
|
# Formatting Tags were also known as display tags.
|
|
self.formatting_tag_item = create_action(main_window, 'displayTagItem',
|
|
icon=UiIcons().edit, category=UiStrings().Settings,
|
|
can_shortcuts=True)
|
|
self.settings_configure_item = create_action(main_window, 'settingsConfigureItem',
|
|
icon=UiIcons().settings, can_shortcuts=True,
|
|
category=UiStrings().Settings)
|
|
# Give QT Extra Hint that this is the Preferences Menu Item
|
|
self.settings_configure_item.setMenuRole(QtWidgets.QAction.PreferencesRole)
|
|
self.settings_import_item = create_action(main_window, 'settingsImportItem',
|
|
category=UiStrings().Import, can_shortcuts=True)
|
|
self.settings_export_item = create_action(main_window, 'settingsExportItem',
|
|
category=UiStrings().Export, can_shortcuts=True)
|
|
action_list.add_category(UiStrings().Help, CategoryOrder.standard_menu)
|
|
self.about_item = create_action(main_window, 'aboutItem', icon=UiIcons().info,
|
|
can_shortcuts=True, category=UiStrings().Help,
|
|
triggers=self.on_about_item_clicked)
|
|
# Give QT Extra Hint that this is an About Menu Item
|
|
self.about_item.setMenuRole(QtWidgets.QAction.AboutRole)
|
|
if is_win():
|
|
self.local_help_file = AppLocation.get_directory(AppLocation.AppDir) / 'OpenLP.chm'
|
|
elif is_macosx():
|
|
self.local_help_file = AppLocation.get_directory(AppLocation.AppDir) / '..' / 'Resources' / 'OpenLP.help'
|
|
self.user_manual_item = create_action(main_window, 'userManualItem', icon=UiIcons().manual,
|
|
can_shortcuts=True, category=UiStrings().Help,
|
|
triggers=self.on_help_clicked)
|
|
self.web_site_item = create_action(main_window, 'webSiteItem', can_shortcuts=True, category=UiStrings().Help)
|
|
# Shortcuts not connected to buttons or menu entries.
|
|
self.search_shortcut_action = create_action(main_window,
|
|
'searchShortcut', can_shortcuts=True,
|
|
category=translate('OpenLP.MainWindow', 'General'),
|
|
triggers=self.on_search_shortcut_triggered)
|
|
'''
|
|
Leave until the import projector options are finished
|
|
add_actions(self.file_import_menu, (self.settings_import_item, self.import_theme_item,
|
|
self.import_projector_item, self.import_language_item, None))
|
|
'''
|
|
add_actions(self.file_import_menu, (self.settings_import_item, self.import_theme_item,
|
|
self.import_language_item, None))
|
|
add_actions(self.file_export_menu, (self.settings_export_item, self.export_theme_item,
|
|
self.export_language_item, None))
|
|
add_actions(self.file_menu, (self.file_new_item, self.file_open_item,
|
|
self.file_save_item, self.file_save_as_item, self.recent_files_menu.menuAction(), None,
|
|
self.file_import_menu.menuAction(), self.file_export_menu.menuAction(), None,
|
|
self.print_service_order_item, self.file_exit_item))
|
|
add_actions(self.view_mode_menu, (self.mode_default_item, self.mode_setup_item, self.mode_live_item))
|
|
add_actions(self.view_menu, (self.view_mode_menu.menuAction(), None, self.view_media_manager_item,
|
|
self.view_projector_manager_item, self.view_service_manager_item, self.view_theme_manager_item,
|
|
None, self.view_preview_panel, self.view_live_panel, None, self.lock_panel))
|
|
# i18n add Language Actions
|
|
add_actions(self.settings_language_menu, (self.auto_language_item, None))
|
|
add_actions(self.settings_language_menu, self.language_group.actions())
|
|
# Qt on OS X looks for keywords in the menu items title to determine which menu items get added to the main
|
|
# menu. If we are running on Mac OS X the menu items whose title contains those keywords but don't belong in the
|
|
# main menu need to be marked as such with QAction.NoRole.
|
|
if is_macosx():
|
|
self.settings_shortcuts_item.setMenuRole(QtWidgets.QAction.NoRole)
|
|
self.formatting_tag_item.setMenuRole(QtWidgets.QAction.NoRole)
|
|
add_actions(self.settings_menu, (self.settings_plugin_list_item, self.settings_language_menu.menuAction(),
|
|
None, self.formatting_tag_item, self.settings_shortcuts_item, self.settings_configure_item))
|
|
add_actions(self.tools_menu, (self.tools_add_tool_item, None))
|
|
add_actions(self.tools_menu, (self.tools_open_data_folder, None))
|
|
add_actions(self.tools_menu, (self.tools_first_time_wizard, None))
|
|
add_actions(self.tools_menu, [self.update_theme_images])
|
|
add_actions(self.help_menu, (self.user_manual_item, None, self.web_site_item, self.about_item))
|
|
add_actions(self.menu_bar, (self.file_menu.menuAction(), self.view_menu.menuAction(),
|
|
self.tools_menu.menuAction(), self.settings_menu.menuAction(), self.help_menu.menuAction()))
|
|
add_actions(self, [self.search_shortcut_action])
|
|
# Initialise the translation
|
|
self.retranslate_ui(main_window)
|
|
self.media_tool_box.setCurrentIndex(0)
|
|
# Connect up some signals and slots
|
|
self.file_menu.aboutToShow.connect(self.update_recent_files_menu)
|
|
# Hide the entry, as it does not have any functionality yet.
|
|
self.tools_add_tool_item.setVisible(False)
|
|
self.import_language_item.setVisible(False)
|
|
self.export_language_item.setVisible(False)
|
|
self.set_lock_panel(panel_locked)
|
|
self.settings_imported = False
|
|
|
|
def retranslate_ui(self, main_window):
|
|
"""
|
|
Set up the translation system
|
|
"""
|
|
main_window.setWindowTitle(UiStrings().OpenLP)
|
|
self.file_menu.setTitle(translate('OpenLP.MainWindow', '&File'))
|
|
self.file_import_menu.setTitle(translate('OpenLP.MainWindow', '&Import'))
|
|
self.file_export_menu.setTitle(translate('OpenLP.MainWindow', '&Export'))
|
|
self.recent_files_menu.setTitle(translate('OpenLP.MainWindow', '&Recent Services'))
|
|
self.view_menu.setTitle(translate('OpenLP.MainWindow', '&View'))
|
|
self.view_mode_menu.setTitle(translate('OpenLP.MainWindow', '&Layout Presets'))
|
|
self.tools_menu.setTitle(translate('OpenLP.MainWindow', '&Tools'))
|
|
self.settings_menu.setTitle(translate('OpenLP.MainWindow', '&Settings'))
|
|
self.settings_language_menu.setTitle(translate('OpenLP.MainWindow', '&Language'))
|
|
self.help_menu.setTitle(translate('OpenLP.MainWindow', '&Help'))
|
|
self.media_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Library'))
|
|
self.service_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Service'))
|
|
self.theme_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Themes'))
|
|
self.projector_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Projector Controller'))
|
|
self.file_new_item.setText(translate('OpenLP.MainWindow', '&New Service'))
|
|
self.file_new_item.setToolTip(UiStrings().NewService)
|
|
self.file_new_item.setStatusTip(UiStrings().CreateService)
|
|
self.file_open_item.setText(translate('OpenLP.MainWindow', '&Open Service'))
|
|
self.file_open_item.setToolTip(UiStrings().OpenService)
|
|
self.file_open_item.setStatusTip(translate('OpenLP.MainWindow', 'Open an existing service.'))
|
|
self.file_save_item.setText(translate('OpenLP.MainWindow', '&Save Service'))
|
|
self.file_save_item.setToolTip(UiStrings().SaveService)
|
|
self.file_save_item.setStatusTip(translate('OpenLP.MainWindow', 'Save the current service to disk.'))
|
|
self.file_save_as_item.setText(translate('OpenLP.MainWindow', 'Save Service &As...'))
|
|
self.file_save_as_item.setToolTip(translate('OpenLP.MainWindow', 'Save Service As'))
|
|
self.file_save_as_item.setStatusTip(translate('OpenLP.MainWindow',
|
|
'Save the current service under a new name.'))
|
|
self.print_service_order_item.setText(UiStrings().PrintService)
|
|
self.print_service_order_item.setStatusTip(translate('OpenLP.MainWindow', 'Print the current service.'))
|
|
self.file_exit_item.setText(translate('OpenLP.MainWindow', 'E&xit'))
|
|
self.file_exit_item.setStatusTip(translate('OpenLP.MainWindow', 'Close OpenLP - Shut down the program.'))
|
|
self.import_theme_item.setText(translate('OpenLP.MainWindow', '&Theme'))
|
|
self.import_language_item.setText(translate('OpenLP.MainWindow', '&Language'))
|
|
self.export_theme_item.setText(translate('OpenLP.MainWindow', '&Theme'))
|
|
self.export_language_item.setText(translate('OpenLP.MainWindow', '&Language'))
|
|
self.settings_shortcuts_item.setText(translate('OpenLP.MainWindow', 'Configure &Shortcuts...'))
|
|
self.formatting_tag_item.setText(translate('OpenLP.MainWindow', 'Configure &Formatting Tags...'))
|
|
self.settings_configure_item.setText(translate('OpenLP.MainWindow', '&Configure OpenLP...'))
|
|
self.settings_export_item.setStatusTip(
|
|
translate('OpenLP.MainWindow', 'Export settings to a *.config file.'))
|
|
self.settings_export_item.setText(translate('OpenLP.MainWindow', 'Settings'))
|
|
self.settings_import_item.setStatusTip(
|
|
translate('OpenLP.MainWindow', 'Import settings from a *.config file previously exported from '
|
|
'this or another machine.'))
|
|
self.settings_import_item.setText(translate('OpenLP.MainWindow', 'Settings'))
|
|
self.view_projector_manager_item.setText(translate('OpenLP.MainWindow', '&Projector Controller'))
|
|
self.view_projector_manager_item.setToolTip(translate('OpenLP.MainWindow', 'Hide or show Projectors.'))
|
|
self.view_projector_manager_item.setStatusTip(translate('OpenLP.MainWindow',
|
|
'Toggle visibility of the Projectors.'))
|
|
self.view_media_manager_item.setText(translate('OpenLP.MainWindow', 'L&ibrary'))
|
|
self.view_media_manager_item.setToolTip(translate('OpenLP.MainWindow', 'Hide or show the Library.'))
|
|
self.view_media_manager_item.setStatusTip(translate('OpenLP.MainWindow',
|
|
'Toggle the visibility of the Library.'))
|
|
self.view_theme_manager_item.setText(translate('OpenLP.MainWindow', '&Themes'))
|
|
self.view_theme_manager_item.setToolTip(translate('OpenLP.MainWindow', 'Hide or show themes'))
|
|
self.view_theme_manager_item.setStatusTip(translate('OpenLP.MainWindow',
|
|
'Toggle visibility of the Themes.'))
|
|
self.view_service_manager_item.setText(translate('OpenLP.MainWindow', '&Service'))
|
|
self.view_service_manager_item.setToolTip(translate('OpenLP.MainWindow', 'Hide or show Service.'))
|
|
self.view_service_manager_item.setStatusTip(translate('OpenLP.MainWindow',
|
|
'Toggle visibility of the Service.'))
|
|
self.view_preview_panel.setText(translate('OpenLP.MainWindow', '&Preview'))
|
|
self.view_preview_panel.setToolTip(translate('OpenLP.MainWindow', 'Hide or show Preview.'))
|
|
self.view_preview_panel.setStatusTip(
|
|
translate('OpenLP.MainWindow', 'Toggle visibility of the Preview.'))
|
|
self.view_live_panel.setText(translate('OpenLP.MainWindow', 'Li&ve'))
|
|
self.view_live_panel.setToolTip(translate('OpenLP.MainWindow', 'Hide or show Live'))
|
|
self.lock_panel.setText(translate('OpenLP.MainWindow', 'L&ock visibility of the panels'))
|
|
self.lock_panel.setStatusTip(translate('OpenLP.MainWindow', 'Lock visibility of the panels.'))
|
|
self.view_live_panel.setStatusTip(translate('OpenLP.MainWindow', 'Toggle visibility of the Live.'))
|
|
self.settings_plugin_list_item.setText(translate('OpenLP.MainWindow', '&Manage Plugins'))
|
|
self.settings_plugin_list_item.setStatusTip(translate('OpenLP.MainWindow', 'You can enable and disable plugins '
|
|
'from here.'))
|
|
self.about_item.setText(translate('OpenLP.MainWindow', '&About'))
|
|
self.about_item.setStatusTip(translate('OpenLP.MainWindow', 'More information about OpenLP.'))
|
|
self.user_manual_item.setText(translate('OpenLP.MainWindow', '&User Manual'))
|
|
self.search_shortcut_action.setText(UiStrings().Search)
|
|
self.search_shortcut_action.setToolTip(
|
|
translate('OpenLP.MainWindow', 'Jump to the search box of the current active plugin.'))
|
|
self.web_site_item.setText(translate('OpenLP.MainWindow', '&Web Site'))
|
|
for item in self.language_group.actions():
|
|
item.setText(item.objectName())
|
|
item.setStatusTip(translate('OpenLP.MainWindow',
|
|
'Set the interface language to {name}').format(name=item.objectName()))
|
|
self.auto_language_item.setText(translate('OpenLP.MainWindow', '&Autodetect'))
|
|
self.auto_language_item.setStatusTip(translate('OpenLP.MainWindow', 'Use the system language, if available.'))
|
|
self.tools_add_tool_item.setText(translate('OpenLP.MainWindow', 'Add &Tool...'))
|
|
self.tools_add_tool_item.setStatusTip(translate('OpenLP.MainWindow',
|
|
'Add an application to the list of tools.'))
|
|
self.tools_open_data_folder.setText(translate('OpenLP.MainWindow', 'Open &Data Folder...'))
|
|
self.tools_open_data_folder.setStatusTip(translate('OpenLP.MainWindow',
|
|
'Open the folder where songs, bibles and other data resides.'))
|
|
self.tools_first_time_wizard.setText(translate('OpenLP.MainWindow', 'Re-run First Time Wizard'))
|
|
self.tools_first_time_wizard.setStatusTip(translate('OpenLP.MainWindow',
|
|
'Re-run the First Time Wizard, importing songs, Bibles and themes.'))
|
|
self.update_theme_images.setText(translate('OpenLP.MainWindow', 'Update Theme Images'))
|
|
self.update_theme_images.setStatusTip(translate('OpenLP.MainWindow',
|
|
'Update the preview images for all themes.'))
|
|
self.mode_default_item.setText(translate('OpenLP.MainWindow', '&Show all'))
|
|
self.mode_default_item.setStatusTip(translate('OpenLP.MainWindow', 'Reset the interface back to the '
|
|
'default layout and show all the panels.'))
|
|
self.mode_setup_item.setText(translate('OpenLP.MainWindow', '&Setup'))
|
|
self.mode_setup_item.setStatusTip(translate('OpenLP.MainWindow', 'Use layout that focuses on setting'
|
|
' up the Service.'))
|
|
self.mode_live_item.setText(translate('OpenLP.MainWindow', '&Live'))
|
|
self.mode_live_item.setStatusTip(translate('OpenLP.MainWindow', 'Use layout that focuses on Live.'))
|
|
|
|
|
|
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryProperties):
|
|
"""
|
|
The main window.
|
|
"""
|
|
def __init__(self):
|
|
"""
|
|
This constructor sets up the interface, the various managers, and the plugins.
|
|
"""
|
|
super(MainWindow, self).__init__()
|
|
Registry().register('main_window', self)
|
|
self.clipboard = QtWidgets.QApplication.clipboard()
|
|
self.recent_files = []
|
|
self.timer_id = 0
|
|
self.new_data_path = None
|
|
self.copy_data = False
|
|
self.settings.set_up_default_values()
|
|
self.about_form = AboutForm(self)
|
|
self.ws_server = WebSocketServer()
|
|
self.http_server = HttpServer(self)
|
|
start_zeroconf()
|
|
SettingsForm(self)
|
|
self.formatting_tag_form = FormattingTagForm(self)
|
|
self.shortcut_form = ShortcutListForm(self)
|
|
# Set up the interface
|
|
self.setup_ui(self)
|
|
# Define the media Dock Manager
|
|
self.media_dock_manager = MediaDockManager(self.media_tool_box)
|
|
# Load settings after setup_ui so default UI sizes are overwritten
|
|
# Once settings are loaded update the menu with the recent files.
|
|
self.update_recent_files_menu()
|
|
self.plugin_form = PluginForm(self)
|
|
# Set up signals and slots
|
|
self.media_manager_dock.visibilityChanged.connect(self.view_media_manager_item.setChecked)
|
|
self.service_manager_dock.visibilityChanged.connect(self.view_service_manager_item.setChecked)
|
|
self.theme_manager_dock.visibilityChanged.connect(self.view_theme_manager_item.setChecked)
|
|
self.projector_manager_dock.visibilityChanged.connect(self.view_projector_manager_item.setChecked)
|
|
self.import_theme_item.triggered.connect(self.theme_manager_contents.on_import_theme)
|
|
self.export_theme_item.triggered.connect(self.theme_manager_contents.on_export_theme)
|
|
self.web_site_item.triggered.connect(self.on_help_web_site_clicked)
|
|
self.tools_open_data_folder.triggered.connect(self.on_tools_open_data_folder_clicked)
|
|
self.tools_first_time_wizard.triggered.connect(self.on_first_time_wizard_clicked)
|
|
self.update_theme_images.triggered.connect(self.on_update_theme_images)
|
|
self.formatting_tag_item.triggered.connect(self.on_formatting_tag_item_clicked)
|
|
self.settings_configure_item.triggered.connect(self.on_settings_configure_item_clicked)
|
|
self.settings_shortcuts_item.triggered.connect(self.on_settings_shortcuts_item_clicked)
|
|
self.settings_import_item.triggered.connect(self.on_settings_import_item_clicked)
|
|
self.settings_export_item.triggered.connect(self.on_settings_export_item_clicked)
|
|
# i18n set signals for languages
|
|
self.language_group.triggered.connect(LanguageManager.set_language)
|
|
self.mode_default_item.triggered.connect(self.on_mode_default_item_clicked)
|
|
self.mode_setup_item.triggered.connect(self.on_mode_setup_item_clicked)
|
|
self.mode_live_item.triggered.connect(self.on_mode_live_item_clicked)
|
|
# Media Manager
|
|
self.media_tool_box.currentChanged.connect(self.on_media_tool_box_changed)
|
|
self.application.set_busy_cursor()
|
|
# Timestamp for latest screen-change-popup. Used to prevent spamming the user with popups
|
|
self.screen_change_timestamp = None
|
|
# Simple message boxes
|
|
Registry().register_function('theme_update_global', self.default_theme_changed)
|
|
Registry().register_function('config_screen_changed', self.screen_changed)
|
|
Registry().register_function('bootstrap_post_set_up', self.bootstrap_post_set_up)
|
|
# Reset the cursor
|
|
self.application.set_normal_cursor()
|
|
|
|
def _wait_for_threads(self):
|
|
"""
|
|
Wait for the threads
|
|
"""
|
|
# Sometimes the threads haven't finished, let's wait for them
|
|
wait_dialog = QtWidgets.QProgressDialog(translate('OpenLP.MainWindow', 'Waiting for some things to finish...'),
|
|
'', 0, 0, self)
|
|
wait_dialog.setWindowTitle(translate('OpenLP.MainWindow', 'Please Wait'))
|
|
for window_flag in [QtCore.Qt.WindowContextHelpButtonHint]:
|
|
wait_dialog.setWindowFlag(window_flag, False)
|
|
wait_dialog.setWindowModality(QtCore.Qt.WindowModal)
|
|
wait_dialog.setAutoClose(False)
|
|
wait_dialog.setCancelButton(None)
|
|
wait_dialog.show()
|
|
thread_names = list(self.application.worker_threads.keys())
|
|
for thread_name in thread_names:
|
|
if thread_name not in self.application.worker_threads.keys():
|
|
continue
|
|
self.log_debug('Waiting for thread %s' % thread_name)
|
|
QtWidgets.QApplication.processEvents()
|
|
thread = self.application.worker_threads[thread_name]['thread']
|
|
worker = self.application.worker_threads[thread_name]['worker']
|
|
try:
|
|
if worker and hasattr(worker, 'stop'):
|
|
# If the worker has a stop method, run it
|
|
worker.stop()
|
|
if thread and thread.isRunning():
|
|
# If the thread is running, let's wait 5 seconds for it
|
|
retry = 0
|
|
while thread.isRunning() and retry < 50:
|
|
# Make the GUI responsive while we wait
|
|
QtWidgets.QApplication.processEvents()
|
|
thread.wait(100)
|
|
retry += 1
|
|
if thread.isRunning():
|
|
# If the thread is still running after 5 seconds, kill it
|
|
thread.terminate()
|
|
except RuntimeError:
|
|
# Ignore the RuntimeError that is thrown when Qt has already deleted the C++ thread object
|
|
pass
|
|
wait_dialog.close()
|
|
|
|
def bootstrap_post_set_up(self):
|
|
"""
|
|
process the bootstrap post setup request
|
|
"""
|
|
self.load_settings()
|
|
self.restore_current_media_manager_item()
|
|
Registry().execute('theme_update_global')
|
|
|
|
def restore_current_media_manager_item(self):
|
|
"""
|
|
Called on start up to restore the last active media plugin.
|
|
"""
|
|
self.log_info('Load data from Settings')
|
|
if self.settings.value('advanced/save current plugin'):
|
|
saved_plugin_id = self.settings.value('advanced/current media plugin')
|
|
if saved_plugin_id != -1:
|
|
self.media_tool_box.setCurrentIndex(saved_plugin_id)
|
|
|
|
def on_search_shortcut_triggered(self):
|
|
"""
|
|
Called when the search shortcut has been pressed.
|
|
"""
|
|
# Make sure the media_dock is visible.
|
|
if not self.media_manager_dock.isVisible():
|
|
self.media_manager_dock.setVisible(True)
|
|
widget = self.media_tool_box.currentWidget()
|
|
if widget:
|
|
widget.on_focus()
|
|
|
|
def on_media_tool_box_changed(self, index):
|
|
"""
|
|
Focus a widget when the media toolbox changes.
|
|
"""
|
|
widget = self.media_tool_box.widget(index)
|
|
if widget:
|
|
widget.on_focus()
|
|
|
|
def on_new_version(self, version):
|
|
"""
|
|
Notifies the user that a newer version of OpenLP is available. Triggered by delay thread and cannot display
|
|
popup.
|
|
|
|
:param version: The Version to be displayed.
|
|
"""
|
|
version_text = translate('OpenLP.MainWindow', 'Version {new} of OpenLP is now available for download (you are '
|
|
'currently running version {current}). \n\nYou can download the latest version from '
|
|
'https://openlp.org/.').format(new=version, current=get_version()[u'full'])
|
|
QtWidgets.QMessageBox.question(self, translate('OpenLP.MainWindow', 'OpenLP Version Updated'), version_text)
|
|
|
|
def on_new_remote_version(self, version):
|
|
"""
|
|
Notifies the user that a newer version of the web remote is available. Triggered by delay thread and cannot
|
|
display popup.
|
|
|
|
:param version: The Version to be displayed.
|
|
"""
|
|
Registry().get('settings').setValue('api/last version test', date.today().strftime('%Y-%m-%d'))
|
|
Registry().get('settings_form').api_tab.master_version = version
|
|
version_text = translate('OpenLP.MainWindow', 'Version {version} of the web remote is now available for '
|
|
'download.\nTo download this version, go to the Remote settings and click the Upgrade '
|
|
'button.').format(version=version)
|
|
self.information_message(translate('OpenLP.MainWindow', 'New Web Remote Version Available'), version_text)
|
|
|
|
def show(self):
|
|
"""
|
|
Show the main form, as well as the display form
|
|
"""
|
|
QtWidgets.QWidget.show(self)
|
|
self.activateWindow()
|
|
# We have -disable-web-security added by our code.
|
|
# If a file is passed in we will have that as well so count of 2
|
|
# If not we need to see if we want to use the previous file.so count of 1
|
|
if self.application.args and len(self.application.args) > 1:
|
|
self.open_cmd_line_files(self.application.args)
|
|
elif self.settings.value('core/auto open'):
|
|
self.service_manager_contents.load_last_file()
|
|
# This will store currently used layout preset so it remains enabled on next startup.
|
|
# If any panel is enabled/disabled after preset is set, this setting is not saved.
|
|
view_mode = self.settings.value('core/view mode')
|
|
if view_mode == 'default' and self.settings.value('user interface/is preset layout'):
|
|
self.mode_default_item.setChecked(True)
|
|
elif view_mode == 'setup' and self.settings.value('user interface/is preset layout'):
|
|
self.set_view_mode(True, True, False, True, False, True)
|
|
self.mode_setup_item.setChecked(True)
|
|
elif view_mode == 'live' and self.settings.value('user interface/is preset layout'):
|
|
self.set_view_mode(False, True, False, False, True, True)
|
|
self.mode_live_item.setChecked(True)
|
|
|
|
def first_time(self):
|
|
"""
|
|
Import themes if first time
|
|
"""
|
|
self.application.process_events()
|
|
for plugin in State().list_plugins():
|
|
if hasattr(plugin, 'first_time'):
|
|
self.application.process_events()
|
|
plugin.first_time()
|
|
self.application.process_events()
|
|
# Load the themes from files
|
|
self.theme_manager_contents.load_first_time_themes()
|
|
# Update the theme widget
|
|
self.theme_manager_contents.load_themes()
|
|
temp_path = Path(gettempdir(), 'openlp')
|
|
shutil.rmtree(temp_path, True)
|
|
|
|
def on_first_time_wizard_clicked(self):
|
|
"""
|
|
Re-run the first time wizard. Prompts the user for run confirmation.If wizard is run, songs, bibles and
|
|
themes are imported. The default theme is changed (if necessary). The plugins in pluginmanager are
|
|
set active/in-active to match the selection in the wizard.
|
|
"""
|
|
answer = QtWidgets.QMessageBox.warning(self,
|
|
translate('OpenLP.MainWindow', 'Re-run First Time Wizard?'),
|
|
translate('OpenLP.MainWindow',
|
|
'Are you sure you want to re-run the First '
|
|
'Time Wizard?\n\nRe-running this wizard may make changes to '
|
|
'your current OpenLP configuration and possibly add songs to '
|
|
'your existing songs list and change your default theme.'),
|
|
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
|
|
QtWidgets.QMessageBox.No),
|
|
QtWidgets.QMessageBox.No)
|
|
if answer == QtWidgets.QMessageBox.No:
|
|
return
|
|
first_run_wizard = FirstTimeForm(self)
|
|
first_run_wizard.initialize(ScreenList())
|
|
if first_run_wizard.exec() == QtWidgets.QDialog.Rejected:
|
|
return
|
|
self.application.set_busy_cursor()
|
|
self.first_time()
|
|
# Check if Projectors panel should be visible or not after wizard.
|
|
if self.settings.value('projector/show after wizard'):
|
|
self.projector_manager_dock.setVisible(True)
|
|
else:
|
|
self.projector_manager_dock.setVisible(False)
|
|
for plugin in State().list_plugins():
|
|
self.active_plugin = plugin
|
|
old_status = self.active_plugin.status
|
|
self.active_plugin.set_status()
|
|
if old_status != self.active_plugin.status:
|
|
if self.active_plugin.status == PluginStatus.Active:
|
|
self.active_plugin.toggle_status(PluginStatus.Active)
|
|
self.active_plugin.app_startup()
|
|
else:
|
|
self.active_plugin.toggle_status(PluginStatus.Inactive)
|
|
# Set global theme and
|
|
Registry().execute('theme_update_global')
|
|
# Check if any Bibles downloaded. If there are, they will be processed.
|
|
Registry().execute('bibles_load_list')
|
|
self.application.set_normal_cursor()
|
|
|
|
def is_display_blank(self):
|
|
"""
|
|
Check and display message if screen blank on setup.
|
|
"""
|
|
if self.settings.value('core/screen blank'):
|
|
if self.settings.value('core/blank warning'):
|
|
QtWidgets.QMessageBox.question(self, translate('OpenLP.MainWindow', 'OpenLP Main Display Blanked'),
|
|
translate('OpenLP.MainWindow', 'The Main Display has been blanked out'))
|
|
|
|
def error_message(self, title, message):
|
|
"""
|
|
Display an error message
|
|
|
|
:param title: The title of the warning box.
|
|
:param message: The message to be displayed.
|
|
"""
|
|
if hasattr(self.application, 'splash'):
|
|
self.application.splash.close()
|
|
QtWidgets.QMessageBox.critical(self, title, message)
|
|
|
|
def warning_message(self, title, message):
|
|
"""
|
|
Display a warning message
|
|
|
|
:param title: The title of the warning box.
|
|
:param message: The message to be displayed.
|
|
"""
|
|
if hasattr(self.application, 'splash'):
|
|
self.application.splash.close()
|
|
QtWidgets.QMessageBox.warning(self, title, message)
|
|
|
|
def information_message(self, title, message):
|
|
"""
|
|
Display an informational message
|
|
|
|
:param title: The title of the warning box.
|
|
:param message: The message to be displayed.
|
|
"""
|
|
if hasattr(self.application, 'splash'):
|
|
self.application.splash.close()
|
|
QtWidgets.QMessageBox.information(self, title, message)
|
|
|
|
@staticmethod
|
|
def on_help_web_site_clicked():
|
|
"""
|
|
Load the OpenLP website
|
|
"""
|
|
import webbrowser
|
|
webbrowser.open_new('https://openlp.org/')
|
|
|
|
def on_help_clicked(self):
|
|
"""
|
|
If is_macosx or is_win, open the local OpenLP help file.
|
|
Use the Online manual in other cases. (Linux)
|
|
"""
|
|
if is_macosx() or is_win():
|
|
QtGui.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(str(self.local_help_file)))
|
|
else:
|
|
import webbrowser
|
|
webbrowser.open_new('https://manual.openlp.org/')
|
|
|
|
def on_about_item_clicked(self):
|
|
"""
|
|
Show the About form
|
|
"""
|
|
self.about_form.exec()
|
|
|
|
def on_plugin_item_clicked(self):
|
|
"""
|
|
Show the Plugin form
|
|
"""
|
|
self.plugin_form.load()
|
|
self.plugin_form.exec()
|
|
|
|
@staticmethod
|
|
def on_tools_open_data_folder_clicked():
|
|
"""
|
|
Open data folder
|
|
"""
|
|
path = str(AppLocation.get_data_path())
|
|
QtGui.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(path))
|
|
|
|
def on_update_theme_images(self):
|
|
"""
|
|
Updates the new theme preview images.
|
|
"""
|
|
self.theme_manager_contents.update_preview_images()
|
|
|
|
def on_formatting_tag_item_clicked(self):
|
|
"""
|
|
Show the Settings dialog
|
|
"""
|
|
self.formatting_tag_form.exec()
|
|
|
|
def on_settings_configure_item_clicked(self):
|
|
"""
|
|
Show the Settings dialog
|
|
"""
|
|
self.settings_form.exec()
|
|
|
|
def on_settings_shortcuts_item_clicked(self):
|
|
"""
|
|
Show the shortcuts dialog
|
|
"""
|
|
if self.shortcut_form.exec():
|
|
self.shortcut_form.save()
|
|
|
|
def on_settings_import_item_clicked(self):
|
|
"""
|
|
Import settings from an export INI file
|
|
"""
|
|
answer = QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Import settings?'),
|
|
translate('OpenLP.MainWindow', 'Are you sure you want to import '
|
|
'settings?\n\n Importing settings will '
|
|
'make permanent changes to your current '
|
|
'OpenLP configuration.\n\n Importing '
|
|
'incorrect settings may cause erratic '
|
|
'behaviour or OpenLP to terminate '
|
|
'abnormally.'),
|
|
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
|
|
QtWidgets.QMessageBox.No),
|
|
QtWidgets.QMessageBox.No)
|
|
if answer == QtWidgets.QMessageBox.No:
|
|
return
|
|
import_file_path, filter_used = FileDialog.getOpenFileName(
|
|
self,
|
|
translate('OpenLP.MainWindow', 'Import settings'),
|
|
None,
|
|
translate('OpenLP.MainWindow', 'OpenLP Settings (*.conf)'))
|
|
if import_file_path is None:
|
|
return
|
|
setting_sections = []
|
|
# Add main sections.
|
|
setting_sections.extend(['core'])
|
|
setting_sections.extend(['advanced'])
|
|
setting_sections.extend(['user interface'])
|
|
setting_sections.extend(['shortcuts'])
|
|
setting_sections.extend(['servicemanager'])
|
|
setting_sections.extend(['themes'])
|
|
setting_sections.extend(['projector'])
|
|
setting_sections.extend(['players'])
|
|
setting_sections.extend(['displayTags'])
|
|
setting_sections.extend(['SettingsImport'])
|
|
setting_sections.extend(['crashreport'])
|
|
# Add plugin sections.
|
|
setting_sections.extend([plugin.name for plugin in State().list_plugins()])
|
|
# Copy the settings file to the tmp dir, because we do not want to change the original one.
|
|
temp_dir_path = Path(gettempdir(), 'openlp')
|
|
create_paths(temp_dir_path)
|
|
temp_config_path = temp_dir_path / import_file_path.name
|
|
shutil.copyfile(import_file_path, temp_config_path)
|
|
import_settings = Settings(str(temp_config_path), QtCore.QSettings.IniFormat)
|
|
|
|
self.log_info('hook upgrade_plugin_settings')
|
|
self.plugin_manager.hook_upgrade_plugin_settings(import_settings)
|
|
# Upgrade settings to prepare the import.
|
|
if import_settings.can_upgrade():
|
|
import_settings.upgrade_settings()
|
|
# Lets do a basic sanity check. If it contains this string we can assume it was created by OpenLP and so we'll
|
|
# load what we can from it, and just silently ignore anything we don't recognise.
|
|
if import_settings.value('SettingsImport/type') != 'OpenLP_settings_export':
|
|
QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Import settings'),
|
|
translate('OpenLP.MainWindow', 'The file you have selected does not appear '
|
|
'to be a valid OpenLP settings file.\n\n'
|
|
'Processing has terminated and '
|
|
'no changes have been made.'),
|
|
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
|
|
return
|
|
import_keys = import_settings.allKeys()
|
|
for section_key in import_keys:
|
|
# We need to handle the really bad files.
|
|
try:
|
|
section, key = section_key.split('/')
|
|
except ValueError:
|
|
section = 'unknown'
|
|
key = ''
|
|
# Switch General back to lowercase.
|
|
if section == 'General' or section == '%General':
|
|
section = 'general'
|
|
section_key = section + "/" + key
|
|
# Make sure it's a valid section for us.
|
|
if section not in setting_sections:
|
|
continue
|
|
# We have a good file, import it.
|
|
for section_key in import_keys:
|
|
if 'eneral' in section_key:
|
|
section_key = section_key.lower()
|
|
try:
|
|
value = import_settings.value(section_key)
|
|
except KeyError:
|
|
value = None
|
|
self.log_warning('The key "{key}" does not exist (anymore), so it will be skipped.'.
|
|
format(key=section_key))
|
|
if value is not None:
|
|
self.settings.setValue('{key}'.format(key=section_key), value)
|
|
now = datetime.now()
|
|
self.settings.setValue('SettingsImport/file_imported', import_file_path)
|
|
self.settings.setValue('SettingsImport/file_date_imported', now.strftime("%Y-%m-%d %H:%M"))
|
|
self.settings.sync()
|
|
# We must do an immediate restart or current configuration will overwrite what was just imported when
|
|
# application terminates normally. We need to exit without saving configuration.
|
|
QtWidgets.QMessageBox.information(self, translate('OpenLP.MainWindow', 'Import settings'),
|
|
translate('OpenLP.MainWindow',
|
|
'OpenLP will now close. Imported settings will '
|
|
'be applied the next time you start OpenLP.'))
|
|
self.settings_imported = True
|
|
self.clean_up()
|
|
QtCore.QCoreApplication.exit()
|
|
|
|
def on_settings_export_item_clicked(self):
|
|
"""
|
|
Export settings to a .conf file in INI format
|
|
"""
|
|
export_file_path, filter_used = FileDialog.getSaveFileName(
|
|
self,
|
|
translate('OpenLP.MainWindow', 'Export Settings File'),
|
|
None,
|
|
translate('OpenLP.MainWindow', 'OpenLP Settings (*.conf)'))
|
|
if not export_file_path:
|
|
return
|
|
# Make sure it's a .conf file.
|
|
export_file_path = export_file_path.with_suffix('.conf')
|
|
self.save_settings()
|
|
try:
|
|
self.settings.export(export_file_path)
|
|
except OSError as ose:
|
|
QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Export setting error'),
|
|
translate('OpenLP.MainWindow',
|
|
'An error occurred while exporting the settings: {err}'
|
|
).format(err=ose.strerror),
|
|
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
|
|
|
|
def on_mode_default_item_clicked(self):
|
|
"""
|
|
Put OpenLP into "Default" view mode.
|
|
"""
|
|
self.set_view_mode(True, True, True, True, True, True, 'default')
|
|
self.settings.setValue('user interface/is preset layout', True)
|
|
self.settings.setValue('projector/show after wizard', True)
|
|
|
|
def on_mode_setup_item_clicked(self):
|
|
"""
|
|
Put OpenLP into "Setup" view mode.
|
|
"""
|
|
self.set_view_mode(True, True, False, True, False, True, 'setup')
|
|
self.settings.setValue('user interface/is preset layout', True)
|
|
self.settings.setValue('projector/show after wizard', True)
|
|
|
|
def on_mode_live_item_clicked(self):
|
|
"""
|
|
Put OpenLP into "Live" view mode.
|
|
"""
|
|
self.set_view_mode(False, True, False, False, True, True, 'live')
|
|
self.settings.setValue('user interface/is preset layout', True)
|
|
self.settings.setValue('projector/show after wizard', True)
|
|
|
|
def set_view_mode(self, media=True, service=True, theme=True, preview=True, live=True, projector=True, mode=''):
|
|
"""
|
|
Set OpenLP to a different view mode.
|
|
"""
|
|
if mode:
|
|
self.settings.setValue('core/view mode', mode)
|
|
self.media_manager_dock.setVisible(media)
|
|
self.service_manager_dock.setVisible(service)
|
|
self.theme_manager_dock.setVisible(theme)
|
|
self.projector_manager_dock.setVisible(projector)
|
|
self.set_preview_panel_visibility(preview)
|
|
self.set_live_panel_visibility(live)
|
|
|
|
def screen_changed(self):
|
|
"""
|
|
The screen has changed so we have to update components such as the renderer.
|
|
"""
|
|
self.application.set_busy_cursor()
|
|
self.renderer.resize(self.live_controller.screens.current.display_geometry.size())
|
|
self.preview_controller.screen_size_changed()
|
|
self.live_controller.setup_displays()
|
|
self.live_controller.screen_size_changed()
|
|
self.setFocus()
|
|
self.activateWindow()
|
|
self.application.set_normal_cursor()
|
|
# if a warning has been shown within the last 5 seconds, skip showing again to avoid spamming user,
|
|
# also do not show if the settings window is visible
|
|
if not self.settings_form.isVisible() and not self.screen_change_timestamp or \
|
|
self.screen_change_timestamp and (datetime.now() - self.screen_change_timestamp).seconds > 5:
|
|
QtWidgets.QMessageBox.warning(self, translate('OpenLP.MainWindow', 'Screen setup has changed'),
|
|
translate('OpenLP.MainWindow',
|
|
'The screen setup has changed. '
|
|
'OpenLP will try to automatically select a display screen, but '
|
|
'you should consider updating the screen settings.'),
|
|
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
|
|
self.screen_change_timestamp = datetime.now()
|
|
|
|
def closeEvent(self, event):
|
|
"""
|
|
Hook to close the main window and display windows on exit
|
|
"""
|
|
# The MainApplication did not even enter the event loop (this happens
|
|
# when OpenLP is not fully loaded). Just ignore the event.
|
|
if not self.application.is_event_loop_active:
|
|
event.ignore()
|
|
return
|
|
if self.service_manager_contents.is_modified():
|
|
ret = self.service_manager_contents.save_modified_service()
|
|
if ret == QtWidgets.QMessageBox.Save:
|
|
if self.service_manager_contents.decide_save_method():
|
|
event.accept()
|
|
else:
|
|
event.ignore()
|
|
elif ret == QtWidgets.QMessageBox.Discard:
|
|
event.accept()
|
|
else:
|
|
event.ignore()
|
|
else:
|
|
if self.settings.value('advanced/enable exit confirmation'):
|
|
msg_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Question,
|
|
translate('OpenLP.MainWindow', 'Exit OpenLP'),
|
|
translate('OpenLP.MainWindow', 'Are you sure you want to exit OpenLP?'),
|
|
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Close |
|
|
QtWidgets.QMessageBox.Cancel),
|
|
self)
|
|
close_button = msg_box.button(QtWidgets.QMessageBox.Close)
|
|
close_button.setText(translate('OpenLP.MainWindow', '&Exit OpenLP'))
|
|
msg_box.setDefaultButton(QtWidgets.QMessageBox.Close)
|
|
if msg_box.exec() == QtWidgets.QMessageBox.Close:
|
|
event.accept()
|
|
else:
|
|
event.ignore()
|
|
else:
|
|
event.accept()
|
|
if event.isAccepted():
|
|
# Wait for all the threads to complete
|
|
self._wait_for_threads()
|
|
# If we just did a settings import, close without saving changes.
|
|
self.clean_up(save_settings=not self.settings_imported)
|
|
|
|
def eventFilter(self, obj, event):
|
|
if event.type() == QtCore.QEvent.FileOpen:
|
|
file_name = event.file()
|
|
self.log_debug('Got open file event for {name}!'.format(name=file_name))
|
|
self.application.args.insert(0, file_name)
|
|
return True
|
|
# Mac OS X should restore app window when user clicked on the OpenLP icon
|
|
# in the Dock bar. However, OpenLP consists of multiple windows and this
|
|
# does not work. This workaround fixes that.
|
|
# The main OpenLP window is restored when it was previously minimized.
|
|
elif event.type() == QtCore.QEvent.ApplicationActivate:
|
|
if is_macosx() and hasattr(self, 'main_window'):
|
|
if self.main_window.isMinimized():
|
|
# Copied from QWidget.setWindowState() docs on how to restore and activate a minimized window
|
|
# while preserving its maximized and/or full-screen state.
|
|
self.main_window.setWindowState(self.main_window.windowState() & ~QtCore.Qt.WindowMinimized |
|
|
QtCore.Qt.WindowActive)
|
|
return True
|
|
|
|
return super(MainWindow, self).eventFilter(obj, event)
|
|
|
|
def clean_up(self, save_settings=True):
|
|
"""
|
|
Runs all the cleanup code before OpenLP shuts down.
|
|
|
|
:param save_settings: Switch to prevent saving settings. Defaults to **True**.
|
|
"""
|
|
if save_settings:
|
|
if self.settings.value('advanced/save current plugin'):
|
|
self.settings.setValue('advanced/current media plugin', self.media_tool_box.currentIndex())
|
|
# Call the cleanup method to shutdown plugins.
|
|
self.log_info('cleanup plugins')
|
|
self.plugin_manager.finalise_plugins()
|
|
if save_settings:
|
|
# Save settings
|
|
self.save_settings()
|
|
# Check if we need to change the data directory
|
|
if self.new_data_path:
|
|
self.change_data_directory()
|
|
# Close down the display
|
|
if self.live_controller.display:
|
|
self.live_controller.display.close()
|
|
# self.live_controller.display = None
|
|
# Clean temporary files used by services
|
|
self.service_manager_contents.clean_up()
|
|
if is_win():
|
|
# Needed for Windows to stop crashes on exit
|
|
Registry().remove('application')
|
|
|
|
def set_service_modified(self, modified, file_name):
|
|
"""
|
|
This method is called from the ServiceManager to set the title of the main window.
|
|
|
|
:param modified: Whether or not this service has been modified.
|
|
:param file_name: The file name of the service file.
|
|
"""
|
|
if modified:
|
|
title = '{title} - {name}*'.format(title=UiStrings().OpenLP, name=file_name)
|
|
else:
|
|
title = '{title} - {name}'.format(title=UiStrings().OpenLP, name=file_name)
|
|
self.setWindowTitle(title)
|
|
|
|
def show_status_message(self, message):
|
|
"""
|
|
Show a message in the status bar
|
|
"""
|
|
self.status_bar.showMessage(message)
|
|
|
|
def default_theme_changed(self):
|
|
"""
|
|
Update the default theme indicator in the status bar
|
|
"""
|
|
theme_name = self.settings.value('themes/global theme')
|
|
self.default_theme_label.setText(translate('OpenLP.MainWindow',
|
|
'Default Theme: {theme}').format(theme=theme_name))
|
|
|
|
def toggle_media_manager(self):
|
|
"""
|
|
Toggle the visibility of the media manager
|
|
"""
|
|
self.media_manager_dock.setVisible(not self.media_manager_dock.isVisible())
|
|
self.settings.setValue('user interface/is preset layout', False)
|
|
|
|
def toggle_projector_manager(self):
|
|
"""
|
|
Toggle visibility of the projector manager
|
|
"""
|
|
self.projector_manager_dock.setVisible(not self.projector_manager_dock.isVisible())
|
|
self.settings.setValue('user interface/is preset layout', False)
|
|
# Check/uncheck checkbox on First time wizard based on visibility of this panel.
|
|
if not self.settings.value('projector/show after wizard'):
|
|
self.settings.setValue('projector/show after wizard', True)
|
|
else:
|
|
self.settings.setValue('projector/show after wizard', False)
|
|
|
|
def toggle_service_manager(self):
|
|
"""
|
|
Toggle the visibility of the service manager
|
|
"""
|
|
self.service_manager_dock.setVisible(not self.service_manager_dock.isVisible())
|
|
self.settings.setValue('user interface/is preset layout', False)
|
|
|
|
def toggle_theme_manager(self):
|
|
"""
|
|
Toggle the visibility of the theme manager
|
|
"""
|
|
self.theme_manager_dock.setVisible(not self.theme_manager_dock.isVisible())
|
|
self.settings.setValue('user interface/is preset layout', False)
|
|
|
|
def set_preview_panel_visibility(self, visible):
|
|
"""
|
|
Sets the visibility of the preview panel including saving the setting and updating the menu.
|
|
|
|
:param visible: A bool giving the state to set the panel to
|
|
True - Visible
|
|
False - Hidden
|
|
|
|
"""
|
|
self.preview_controller.panel.setVisible(visible)
|
|
self.settings.setValue('user interface/preview panel', visible)
|
|
self.view_preview_panel.setChecked(visible)
|
|
self.settings.setValue('user interface/is preset layout', False)
|
|
|
|
def set_lock_panel(self, lock):
|
|
"""
|
|
Sets the ability to stop the toolbars being changed.
|
|
"""
|
|
if lock:
|
|
self.theme_manager_dock.setFeatures(QtWidgets.QDockWidget.NoDockWidgetFeatures)
|
|
self.service_manager_dock.setFeatures(QtWidgets.QDockWidget.NoDockWidgetFeatures)
|
|
self.media_manager_dock.setFeatures(QtWidgets.QDockWidget.NoDockWidgetFeatures)
|
|
self.projector_manager_dock.setFeatures(QtWidgets.QDockWidget.NoDockWidgetFeatures)
|
|
self.view_mode_menu.setEnabled(False)
|
|
self.view_media_manager_item.setEnabled(False)
|
|
self.view_service_manager_item.setEnabled(False)
|
|
self.view_theme_manager_item.setEnabled(False)
|
|
self.view_projector_manager_item.setEnabled(False)
|
|
self.view_preview_panel.setEnabled(False)
|
|
self.view_live_panel.setEnabled(False)
|
|
else:
|
|
self.theme_manager_dock.setFeatures(QtWidgets.QDockWidget.AllDockWidgetFeatures)
|
|
self.service_manager_dock.setFeatures(QtWidgets.QDockWidget.AllDockWidgetFeatures)
|
|
self.media_manager_dock.setFeatures(QtWidgets.QDockWidget.AllDockWidgetFeatures)
|
|
self.projector_manager_dock.setFeatures(QtWidgets.QDockWidget.AllDockWidgetFeatures)
|
|
self.view_mode_menu.setEnabled(True)
|
|
self.view_media_manager_item.setEnabled(True)
|
|
self.view_service_manager_item.setEnabled(True)
|
|
self.view_theme_manager_item.setEnabled(True)
|
|
self.view_projector_manager_item.setEnabled(True)
|
|
self.view_preview_panel.setEnabled(True)
|
|
self.view_live_panel.setEnabled(True)
|
|
self.settings.setValue('user interface/lock panel', lock)
|
|
|
|
def set_live_panel_visibility(self, visible):
|
|
"""
|
|
Sets the visibility of the live panel including saving the setting and updating the menu.
|
|
|
|
|
|
:param visible: A bool giving the state to set the panel to
|
|
True - Visible
|
|
False - Hidden
|
|
"""
|
|
self.live_controller.panel.setVisible(visible)
|
|
self.settings.setValue('user interface/live panel', visible)
|
|
self.view_live_panel.setChecked(visible)
|
|
self.settings.setValue('user interface/is preset layout', False)
|
|
|
|
def load_settings(self):
|
|
"""
|
|
Load the main window settings.
|
|
"""
|
|
# Remove obsolete entries.
|
|
self.settings.remove('custom slide')
|
|
self.settings.remove('service')
|
|
self.recent_files = self.settings.value('core/recent files')
|
|
self.move(self.settings.value('user interface/main window position'))
|
|
self.restoreGeometry(self.settings.value('user interface/main window geometry'))
|
|
self.restoreState(self.settings.value('user interface/main window state'))
|
|
self.live_controller.splitter.restoreState(self.settings.value('user interface/live splitter geometry'))
|
|
self.preview_controller.splitter.restoreState(self.settings.value('user interface/preview splitter geometry'))
|
|
self.control_splitter.restoreState(self.settings.value('user interface/main window splitter geometry'))
|
|
# This needs to be called after restoreState(), because saveState() also saves the "Collapsible" property
|
|
# which was True (by default) < OpenLP 2.1.
|
|
self.control_splitter.setChildrenCollapsible(False)
|
|
|
|
def save_settings(self):
|
|
"""
|
|
Save the main window settings.
|
|
"""
|
|
# Exit if we just did a settings import.
|
|
if self.settings_imported:
|
|
return
|
|
self.settings.setValue('core/recent files', self.recent_files)
|
|
self.settings.setValue('user interface/main window position', self.pos())
|
|
self.settings.setValue('user interface/main window state', self.saveState())
|
|
self.settings.setValue('user interface/main window geometry', self.saveGeometry())
|
|
self.settings.setValue('user interface/live splitter geometry', self.live_controller.splitter.saveState())
|
|
self.settings.setValue('user interface/preview splitter geometry', self.preview_controller.splitter.saveState())
|
|
self.settings.setValue('user interface/main window splitter geometry', self.control_splitter.saveState())
|
|
|
|
def update_recent_files_menu(self):
|
|
"""
|
|
Updates the recent file menu with the latest list of service files accessed.
|
|
"""
|
|
recent_file_count = self.settings.value('advanced/recent file count')
|
|
self.recent_files_menu.clear()
|
|
count = 0
|
|
for recent_path in self.recent_files:
|
|
if not recent_path.is_file():
|
|
continue
|
|
count += 1
|
|
self.log_debug('Recent file name: {name}'.format(name=recent_path))
|
|
action = create_action(self, '',
|
|
text='&{n} {name}'.format(n=count, name=recent_path.name),
|
|
data=recent_path, triggers=self.service_manager_contents.on_recent_service_clicked)
|
|
self.recent_files_menu.addAction(action)
|
|
if count == recent_file_count:
|
|
break
|
|
clear_recent_files_action = \
|
|
create_action(self, '', text=translate('OpenLP.MainWindow', 'Clear List', 'Clear List of recent files'),
|
|
statustip=translate('OpenLP.MainWindow', 'Clear the list of recent files.'),
|
|
enabled=bool(self.recent_files), triggers=self.clear_recent_file_menu)
|
|
add_actions(self.recent_files_menu, (None, clear_recent_files_action))
|
|
|
|
def add_recent_file(self, filename):
|
|
"""
|
|
Adds a service to the list of recently used files.
|
|
|
|
:param filename: The service filename to add
|
|
"""
|
|
# The max_recent_files value does not have an interface and so never gets
|
|
# actually stored in the settings therefore the default value of 20 will
|
|
# always be used.
|
|
max_recent_files = self.settings.value('advanced/max recent files')
|
|
file_path = Path(filename)
|
|
# Some cleanup to reduce duplication in the recent file list
|
|
file_path = file_path.resolve()
|
|
if file_path in self.recent_files:
|
|
self.recent_files.remove(file_path)
|
|
self.recent_files.insert(0, file_path)
|
|
self.recent_files = self.recent_files[:max_recent_files]
|
|
|
|
def clear_recent_file_menu(self):
|
|
"""
|
|
Clears the recent files.
|
|
"""
|
|
self.recent_files = []
|
|
|
|
def display_progress_bar(self, size):
|
|
"""
|
|
Make Progress bar visible and set size
|
|
"""
|
|
self.load_progress_bar.show()
|
|
self.load_progress_bar.setMaximum(size)
|
|
self.load_progress_bar.setValue(0)
|
|
self.application.process_events()
|
|
|
|
def increment_progress_bar(self, increment=1):
|
|
"""
|
|
Increase the Progress Bar by the value in increment.
|
|
|
|
:param int increment: The value you to increase the progress bar by.
|
|
"""
|
|
self.load_progress_bar.setValue(self.load_progress_bar.value() + increment)
|
|
self.application.process_events()
|
|
|
|
def finished_progress_bar(self):
|
|
"""
|
|
Trigger it's removal after 2.5 second
|
|
"""
|
|
self.timer_id = self.startTimer(2500)
|
|
|
|
def timerEvent(self, event):
|
|
"""
|
|
Remove the Progress bar from view.
|
|
"""
|
|
if event.timerId() == self.timer_id:
|
|
self.timer_id = 0
|
|
self.load_progress_bar.hide()
|
|
# Sometimes the timer goes off as OpenLP is shutting down, and the application has already been deleted
|
|
if self.application:
|
|
self.application.process_events()
|
|
|
|
def set_copy_data(self, copy_data):
|
|
"""
|
|
Set the flag to copy the data
|
|
"""
|
|
self.copy_data = copy_data
|
|
|
|
def change_data_directory(self):
|
|
"""
|
|
Change the data directory.
|
|
"""
|
|
self.log_info('Changing data path to {newpath}'.format(newpath=self.new_data_path))
|
|
old_data_path = AppLocation.get_data_path()
|
|
# Copy OpenLP data to new location if requested.
|
|
self.application.set_busy_cursor()
|
|
if self.copy_data:
|
|
self.log_info('Copying data to new path')
|
|
try:
|
|
self.show_status_message(
|
|
translate('OpenLP.MainWindow', 'Copying OpenLP data to new data directory location - {path} '
|
|
'- Please wait for copy to finish').format(path=self.new_data_path))
|
|
shutil.copytree(str(old_data_path), str(self.new_data_path))
|
|
self.log_info('Copy successful')
|
|
except (OSError, shutil.Error) as why:
|
|
self.application.set_normal_cursor()
|
|
self.log_exception('Data copy failed {err}'.format(err=str(why)))
|
|
err_text = translate('OpenLP.MainWindow',
|
|
'OpenLP Data directory copy failed\n\n{err}').format(err=str(why))
|
|
QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'New Data Directory Error'),
|
|
err_text,
|
|
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
|
|
return False
|
|
else:
|
|
self.log_info('No data copy requested')
|
|
# Change the location of data directory in config file.
|
|
self.settings.setValue('advanced/data path', self.new_data_path)
|
|
# Check if the new data path is our default.
|
|
if self.new_data_path == AppLocation.get_directory(AppLocation.DataDir):
|
|
self.settings.remove('advanced/data path')
|
|
self.application.set_normal_cursor()
|
|
|
|
def open_cmd_line_files(self, args):
|
|
"""
|
|
Open files passed in through command line arguments
|
|
|
|
:param list[str] args: List of remaining positionall arguments
|
|
"""
|
|
for arg in args:
|
|
file_name = os.path.expanduser(arg)
|
|
if os.path.isfile(file_name):
|
|
self.service_manager_contents.load_file(Path(file_name))
|