diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index ebb2d6c22..3a203c2c4 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -405,7 +405,7 @@ def main(args=None): # Set our data path log.info('Data path: {name}'.format(name=data_path)) # Point to our data path - portable_settings.setValue('advanced/data path', str(data_path)) + portable_settings.setValue('advanced/data path', data_path) portable_settings.setValue('advanced/is portable', True) portable_settings.sync() else: @@ -422,8 +422,8 @@ def main(args=None): if application.is_data_path_missing(): application.shared_memory.detach() sys.exit() - # Remove/convert obsolete settings. - Settings().remove_obsolete_settings() + # Upgrade settings. + Settings().upgrade_settings() # First time checks in settings if not Settings().value('core/has run wizard'): if not FirstTimeLanguageForm().exec(): diff --git a/openlp/core/api/endpoint/controller.py b/openlp/core/api/endpoint/controller.py index 85e9623f9..c3f5fd89f 100644 --- a/openlp/core/api/endpoint/controller.py +++ b/openlp/core/api/endpoint/controller.py @@ -79,8 +79,7 @@ def controller_text(request): item['title'] = str(frame['display_title']) if current_item.is_capable(ItemCapabilities.HasNotes): item['slide_notes'] = str(frame['notes']) - if current_item.is_capable(ItemCapabilities.HasThumbnails) and \ - Settings().value('api/thumbnails'): + if current_item.is_capable(ItemCapabilities.HasThumbnails) and Settings().value('api/thumbnails'): # If the file is under our app directory tree send the portion after the match data_path = str(AppLocation.get_data_path()) if frame['image'][0:len(data_path)] == data_path: diff --git a/openlp/core/common/applocation.py b/openlp/core/common/applocation.py index 29ca6fb3e..87ef7e6c1 100644 --- a/openlp/core/common/applocation.py +++ b/openlp/core/common/applocation.py @@ -86,7 +86,7 @@ class AppLocation(object): """ # Check if we have a different data location. if Settings().contains('advanced/data path'): - path = Path(Settings().value('advanced/data path')) + path = Settings().value('advanced/data path') else: path = AppLocation.get_directory(AppLocation.DataDir) check_directory_exists(path) @@ -118,7 +118,7 @@ class AppLocation(object): """ Return the path a particular module stores its data under. - :type section: str + :param str section: :rtype: openlp.core.common.path.Path """ path = AppLocation.get_data_path() / section diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index 8d12a69e5..1e6a120fa 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -24,15 +24,18 @@ This class contains the core default settings. """ import datetime import logging +import json import os from PyQt5 import QtCore, QtGui -from openlp.core.common import ThemeLevel, SlideLimits, UiStrings, is_win, is_linux - +from openlp.core.common import SlideLimits, ThemeLevel, UiStrings, is_linux, is_win +from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder +from openlp.core.common.path import Path, path_to_str, str_to_path log = logging.getLogger(__name__) +__version__ = 2 # Fix for bug #1014422. X11_BYPASS_DEFAULT = True @@ -44,21 +47,6 @@ if is_linux(): X11_BYPASS_DEFAULT = False -def recent_files_conv(value): - """ - If the value is not a list convert it to a list - :param value: Value to convert - :return: value as a List - """ - if isinstance(value, list): - return value - elif isinstance(value, str): - return [value] - elif isinstance(value, bytes): - return [value.decode()] - return [] - - def media_players_conv(string): """ If phonon is in the setting string replace it with system @@ -73,14 +61,24 @@ def media_players_conv(string): return string +def file_names_conv(file_names): + """ + Convert a list of file names in to a list of file paths. + + :param list[str] file_names: The list of file names to convert. + :return: The list converted to file paths + :rtype: openlp.core.common.path.Path + """ + return [str_to_path(file_name) for file_name in file_names] + + class Settings(QtCore.QSettings): """ Class to wrap QSettings. * Exposes all the methods of QSettings. - * Adds functionality for OpenLP Portable. If the ``defaultFormat`` is set to - ``IniFormat``, and the path to the Ini file is set using ``set_filename``, - then the Settings constructor (without any arguments) will create a Settings + * Adds functionality for OpenLP Portable. If the ``defaultFormat`` is set to ``IniFormat``, and the path to the Ini + file is set using ``set_filename``, then the Settings constructor (without any arguments) will create a Settings object for accessing settings stored in that Ini file. ``__default_settings__`` @@ -91,7 +89,7 @@ class Settings(QtCore.QSettings): ('general/enable slide loop', 'advanced/slide limits', [(SlideLimits.Wrap, True), (SlideLimits.End, False)]) - The first entry is the *old key*; it will be removed. + The first entry is the *old key*; if it is different from the *new key* it will be removed. The second entry is the *new key*; we will add it to the config. If this is just an empty string, we just remove the old key. The last entry is a list containing two-pair tuples. If the list is empty, no conversion is made. @@ -105,11 +103,12 @@ class Settings(QtCore.QSettings): So, if the type of the old value is bool, then there must be two rules. """ __default_settings__ = { + 'settings/version': 0, 'advanced/add page break': False, 'advanced/alternate rows': not is_win(), 'advanced/autoscrolling': {'dist': 1, 'pos': 0}, 'advanced/current media plugin': -1, - 'advanced/data path': '', + 'advanced/data path': None, # 7 stands for now, 0 to 6 is Monday to Sunday. 'advanced/default service day': 7, 'advanced/default service enabled': True, @@ -143,7 +142,7 @@ class Settings(QtCore.QSettings): 'api/authentication enabled': False, 'api/ip address': '0.0.0.0', 'api/thumbnails': True, - 'crashreport/last directory': '', + 'crashreport/last directory': None, 'formattingTags/html_tags': '', 'core/audio repeat list': False, 'core/auto open': False, @@ -162,7 +161,7 @@ class Settings(QtCore.QSettings): 'core/screen blank': False, 'core/show splash': True, 'core/logo background color': '#ffffff', - 'core/logo file': ':/graphics/openlp-splash-screen.png', + 'core/logo file': Path(':/graphics/openlp-splash-screen.png'), 'core/logo hide on startup': False, 'core/songselect password': '', 'core/songselect username': '', @@ -177,17 +176,17 @@ class Settings(QtCore.QSettings): 'media/players': 'system,webkit', 'media/override player': QtCore.Qt.Unchecked, 'players/background color': '#000000', - 'servicemanager/last directory': '', - 'servicemanager/last file': '', - 'servicemanager/service theme': '', + 'servicemanager/last directory': None, + 'servicemanager/last file': None, + 'servicemanager/service theme': None, 'SettingsImport/file_date_created': datetime.datetime.now().strftime("%Y-%m-%d %H:%M"), 'SettingsImport/Make_Changes': 'At_Own_RISK', 'SettingsImport/type': 'OpenLP_settings_export', 'SettingsImport/version': '', 'themes/global theme': '', - 'themes/last directory': '', - 'themes/last directory export': '', - 'themes/last directory import': '', + 'themes/last directory': None, + 'themes/last directory export': None, + 'themes/last directory import': None, 'themes/theme level': ThemeLevel.Song, 'themes/wrap footer': False, 'user interface/live panel': True, @@ -208,22 +207,20 @@ class Settings(QtCore.QSettings): 'projector/db database': '', 'projector/enable': True, 'projector/connect on start': False, - 'projector/last directory import': '', - 'projector/last directory export': '', + 'projector/last directory import': None, + 'projector/last directory export': None, 'projector/poll time': 20, # PJLink timeout is 30 seconds 'projector/socket timeout': 5, # 5 second socket timeout 'projector/source dialog type': 0 # Source select dialog box type } __file_path__ = '' - __obsolete_settings__ = [ + __setting_upgrade_1__ = [ # Changed during 2.2.x development. - # ('advanced/stylesheet fix', '', []), - # ('general/recent files', 'core/recent files', [(recent_files_conv, None)]), ('songs/search as type', 'advanced/search as type', []), ('media/players', 'media/players_temp', [(media_players_conv, None)]), # Convert phonon to system ('media/players_temp', 'media/players', []), # Move temp setting from above to correct setting ('advanced/default color', 'core/logo background color', []), # Default image renamed + moved to general > 2.4. - ('advanced/default image', '/core/logo file', []), # Default image renamed + moved to general after 2.4. + ('advanced/default image', 'core/logo file', []), # Default image renamed + moved to general after 2.4. ('remotes/https enabled', '', []), ('remotes/https port', '', []), ('remotes/twelve hour', 'api/twelve hour', []), @@ -234,7 +231,6 @@ class Settings(QtCore.QSettings): ('remotes/authentication enabled', 'api/authentication enabled', []), ('remotes/ip address', 'api/ip address', []), ('remotes/thumbnails', 'api/thumbnails', []), - ('advanced/default image', 'core/logo file', []), # Default image renamed + moved to general after 2.4. ('shortcuts/escapeItem', 'shortcuts/desktopScreenEnable', []), # Escape item was removed in 2.6. ('shortcuts/offlineHelpItem', 'shortcuts/userManualItem', []), # Online and Offline help were combined in 2.6. ('shortcuts/onlineHelpItem', 'shortcuts/userManualItem', []), # Online and Offline help were combined in 2.6. @@ -243,7 +239,28 @@ class Settings(QtCore.QSettings): # Last search type was renamed to last used search type in 2.6 since Bible search value type changed in 2.6. ('songs/last search type', 'songs/last used search type', []), ('bibles/last search type', '', []), - ('custom/last search type', 'custom/last used search type', []) + ('custom/last search type', 'custom/last used search type', [])] + + __setting_upgrade_2__ = [ + # The following changes are being made for the conversion to using Path objects made in 2.6 development + ('advanced/data path', 'advanced/data path', [(str_to_path, None)]), + ('crashreport/last directory', 'crashreport/last directory', [(str_to_path, None)]), + ('servicemanager/last directory', 'servicemanager/last directory', [(str_to_path, None)]), + ('servicemanager/last file', 'servicemanager/last file', [(str_to_path, None)]), + ('themes/last directory', 'themes/last directory', [(str_to_path, None)]), + ('themes/last directory export', 'themes/last directory export', [(str_to_path, None)]), + ('themes/last directory import', 'themes/last directory import', [(str_to_path, None)]), + ('projector/last directory import', 'projector/last directory import', [(str_to_path, None)]), + ('projector/last directory export', 'projector/last directory export', [(str_to_path, None)]), + ('bibles/last directory import', 'bibles/last directory import', [(str_to_path, None)]), + ('presentations/pdf_program', 'presentations/pdf_program', [(str_to_path, None)]), + ('songs/last directory import', 'songs/last directory import', [(str_to_path, None)]), + ('songs/last directory export', 'songs/last directory export', [(str_to_path, None)]), + ('songusage/last directory export', 'songusage/last directory export', [(str_to_path, None)]), + ('core/recent files', 'core/recent files', [(file_names_conv, None)]), + ('media/media files', 'media/media files', [(file_names_conv, None)]), + ('presentations/presentations files', 'presentations/presentations files', [(file_names_conv, None)]), + ('core/logo file', 'core/logo file', [(str_to_path, None)]) ] @staticmethod @@ -256,13 +273,16 @@ class Settings(QtCore.QSettings): Settings.__default_settings__.update(default_values) @staticmethod - def set_filename(ini_file): + def set_filename(ini_path): """ Sets the complete path to an Ini file to be used by Settings objects. Does not affect existing Settings objects. + + :param openlp.core.common.path.Path ini_path: ini file path + :rtype: None """ - Settings.__file_path__ = ini_file + Settings.__file_path__ = str(ini_path) @staticmethod def set_up_default_values(): @@ -431,14 +451,22 @@ class Settings(QtCore.QSettings): key = self.group() + '/' + key return Settings.__default_settings__[key] - def remove_obsolete_settings(self): + def upgrade_settings(self): """ This method is only called to clean up the config. It removes old settings and it renames settings. See ``__obsolete_settings__`` for more details. """ - for old_key, new_key, rules in Settings.__obsolete_settings__: - # Once removed we don't have to do this again. - if self.contains(old_key): + current_version = self.value('settings/version') + if __version__ == current_version: + return + for version in range(current_version, __version__): + version += 1 + upgrade_list = getattr(self, '__setting_upgrade_{version}__'.format(version=version)) + for old_key, new_key, rules in upgrade_list: + # Once removed we don't have to do this again. - Can be removed once fully switched to the versioning + # system. + if not self.contains(old_key): + continue if new_key: # Get the value of the old_key. old_value = super(Settings, self).value(old_key) @@ -457,14 +485,17 @@ class Settings(QtCore.QSettings): old_value = new break self.setValue(new_key, old_value) - self.remove(old_key) + if new_key != old_key: + self.remove(old_key) + self.setValue('settings/version', version) def value(self, key): """ Returns the value for the given ``key``. The returned ``value`` is of the same type as the default value in the *Settings.__default_settings__* dict. - :param key: The key to return the value from. + :param str key: The key to return the value from. + :return: The value stored by the setting. """ # if group() is not empty the group has not been specified together with the key. if self.group(): @@ -474,6 +505,18 @@ class Settings(QtCore.QSettings): setting = super(Settings, self).value(key, default_value) return self._convert_value(setting, default_value) + def setValue(self, key, value): + """ + Reimplement the setValue method to handle Path objects. + + :param str key: The key of the setting to save + :param value: The value to save + :rtype: None + """ + if isinstance(value, Path) or (isinstance(value, list) and value and isinstance(value[0], Path)): + value = json.dumps(value, cls=OpenLPJsonEncoder) + super().setValue(key, value) + def _convert_value(self, setting, default_value): """ This converts the given ``setting`` to the type of the given ``default_value``. @@ -491,8 +534,11 @@ class Settings(QtCore.QSettings): if isinstance(default_value, str): return '' # An empty list saved to the settings results in a None type being returned. - else: + elif isinstance(default_value, list): return [] + elif isinstance(setting, str): + if '__Path__' in setting: + return json.loads(setting, cls=OpenLPJsonDecoder) # Convert the setting to the correct type. if isinstance(default_value, bool): if isinstance(setting, bool): diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 6b04d076b..59a0e4e33 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -29,7 +29,7 @@ import re from PyQt5 import QtCore, QtWidgets from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings, translate -from openlp.core.common.path import path_to_str, str_to_path +from openlp.core.common.path import Path, path_to_str, str_to_path from openlp.core.lib import ServiceItem, StringContent, ServiceItemContext from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.ui import create_widget_action, critical_error_message_box @@ -313,7 +313,7 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): """ file_paths, selected_filter = FileDialog.getOpenFileNames( self, self.on_new_prompt, - str_to_path(Settings().value(self.settings_section + '/last directory')), + Settings().value(self.settings_section + '/last directory'), self.on_new_file_masks) log.info('New files(s) {file_paths}'.format(file_paths=file_paths)) if file_paths: @@ -377,9 +377,8 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): self.list_view.clear() self.load_list(full_list, target_group) last_dir = os.path.split(files[0])[0] - Settings().setValue(self.settings_section + '/last directory', last_dir) - Settings().setValue('{section}/{section} files'.format(section=self.settings_section), - self.get_file_list()) + Settings().setValue(self.settings_section + '/last directory', Path(last_dir)) + Settings().setValue('{section}/{section} files'.format(section=self.settings_section), self.get_file_list()) if duplicates_found: critical_error_message_box(UiStrings().Duplicate, translate('OpenLP.MediaManagerItem', @@ -400,13 +399,15 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): def get_file_list(self): """ Return the current list of files + + :rtype: list[openlp.core.common.path.Path] """ - file_list = [] + file_paths = [] for index in range(self.list_view.count()): list_item = self.list_view.item(index) filename = list_item.data(QtCore.Qt.UserRole) - file_list.append(filename) - return file_list + file_paths.append(str_to_path(filename)) + return file_paths def load_list(self, load_list, target_group): """ diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index b06e0fbd4..1b1cddfea 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -150,7 +150,7 @@ class Plugin(QtCore.QObject, RegistryProperties): self.status = PluginStatus.Inactive # Add the default status to the default settings. default_settings[name + '/status'] = PluginStatus.Inactive - default_settings[name + '/last directory'] = '' + default_settings[name + '/last directory'] = None # Append a setting for files in the mediamanager (note not all plugins # which have a mediamanager need this). if media_item_class is not None: diff --git a/openlp/core/ui/exceptionform.py b/openlp/core/ui/exceptionform.py index 349352d92..00a7c89e2 100644 --- a/openlp/core/ui/exceptionform.py +++ b/openlp/core/ui/exceptionform.py @@ -70,9 +70,9 @@ try: except ImportError: VLC_VERSION = '-' -from openlp.core.common import Settings, UiStrings, translate +from openlp.core.common import RegistryProperties, Settings, UiStrings, is_linux, translate from openlp.core.common.versionchecker import get_application_version -from openlp.core.common import RegistryProperties, is_linux +from openlp.core.ui.lib.filedialog import FileDialog from .exceptiondialog import Ui_ExceptionDialog @@ -139,17 +139,17 @@ class ExceptionForm(QtWidgets.QDialog, Ui_ExceptionDialog, RegistryProperties): """ Saving exception log and system information to a file. """ - filename = QtWidgets.QFileDialog.getSaveFileName( + file_path, filter_used = FileDialog.getSaveFileName( self, translate('OpenLP.ExceptionForm', 'Save Crash Report'), Settings().value(self.settings_section + '/last directory'), - translate('OpenLP.ExceptionForm', 'Text files (*.txt *.log *.text)'))[0] - if filename: - filename = str(filename).replace('/', os.path.sep) - Settings().setValue(self.settings_section + '/last directory', os.path.dirname(filename)) + translate('OpenLP.ExceptionForm', 'Text files (*.txt *.log *.text)')) + if file_path: + Settings().setValue(self.settings_section + '/last directory', file_path.parent) opts = self._create_report() report_text = self.report_text.format(version=opts['version'], description=opts['description'], traceback=opts['traceback'], libs=opts['libs'], system=opts['system']) + filename = str(file_path) try: report_file = open(filename, 'w') try: @@ -212,17 +212,16 @@ class ExceptionForm(QtWidgets.QDialog, Ui_ExceptionDialog, RegistryProperties): def on_attach_file_button_clicked(self): """ - Attache files to the bug report e-mail. + Attach files to the bug report e-mail. """ - files, filter_used = QtWidgets.QFileDialog.getOpenFileName(self, - translate('ImagePlugin.ExceptionDialog', - 'Select Attachment'), - Settings().value(self.settings_section + - '/last directory'), - '{text} (*)'.format(text=UiStrings().AllFiles)) - log.info('New files(s) {files}'.format(files=str(files))) - if files: - self.file_attachment = str(files) + file_path, filter_used = \ + FileDialog.getOpenFileName(self, + translate('ImagePlugin.ExceptionDialog', 'Select Attachment'), + Settings().value(self.settings_section + '/last directory'), + '{text} (*)'.format(text=UiStrings().AllFiles)) + log.info('New file {file}'.format(file=file_path)) + if file_path: + self.file_attachment = str(file_path) def __button_state(self, state): """ diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 6160aa622..70a7ddf5f 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -293,7 +293,7 @@ class GeneralTab(SettingsTab): self.auto_open_check_box.setChecked(settings.value('auto open')) self.show_splash_check_box.setChecked(settings.value('show splash')) self.logo_background_color = settings.value('logo background color') - self.logo_file_path_edit.path = str_to_path(settings.value('logo file')) + self.logo_file_path_edit.path = settings.value('logo file') self.logo_hide_on_startup_check_box.setChecked(settings.value('logo hide on startup')) self.logo_color_button.color = self.logo_background_color self.check_for_updates_check_box.setChecked(settings.value('update check')) @@ -327,7 +327,7 @@ class GeneralTab(SettingsTab): settings.setValue('auto open', self.auto_open_check_box.isChecked()) settings.setValue('show splash', self.show_splash_check_box.isChecked()) settings.setValue('logo background color', self.logo_background_color) - settings.setValue('logo file', path_to_str(self.logo_file_path_edit.path)) + settings.setValue('logo file', self.logo_file_path_edit.path) settings.setValue('logo hide on startup', self.logo_hide_on_startup_check_box.isChecked()) settings.setValue('update check', self.check_for_updates_check_box.isChecked()) settings.setValue('save prompt', self.save_check_service_check_box.isChecked()) diff --git a/openlp/core/ui/lib/wizard.py b/openlp/core/ui/lib/wizard.py index 936682585..8f3093fef 100644 --- a/openlp/core/ui/lib/wizard.py +++ b/openlp/core/ui/lib/wizard.py @@ -30,6 +30,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings, translate, is_macosx from openlp.core.lib import build_icon from openlp.core.lib.ui import add_welcome_page +from openlp.core.ui.lib.filedialog import FileDialog log = logging.getLogger(__name__) @@ -278,37 +279,38 @@ class OpenLPWizard(QtWidgets.QWizard, RegistryProperties): def get_file_name(self, title, editbox, setting_name, filters=''): """ - Opens a QFileDialog and saves the filename to the given editbox. + Opens a FileDialog and saves the filename to the given editbox. - :param title: The title of the dialog (unicode). - :param editbox: An editbox (QLineEdit). - :param setting_name: The place where to save the last opened directory. - :param filters: The file extension filters. It should contain the file description + :param str title: The title of the dialog. + :param QtWidgets.QLineEdit editbox: An QLineEdit. + :param str setting_name: The place where to save the last opened directory. + :param str filters: The file extension filters. It should contain the file description as well as the file extension. For example:: 'OpenLP 2 Databases (*.sqlite)' + :rtype: None """ if filters: filters += ';;' filters += '%s (*)' % UiStrings().AllFiles - filename, filter_used = QtWidgets.QFileDialog.getOpenFileName( - self, title, os.path.dirname(Settings().value(self.plugin.settings_section + '/' + setting_name)), - filters) - if filename: - editbox.setText(filename) - Settings().setValue(self.plugin.settings_section + '/' + setting_name, filename) + file_path, filter_used = FileDialog.getOpenFileName( + self, title, Settings().value(self.plugin.settings_section + '/' + setting_name), filters) + if file_path: + editbox.setText(str(file_path)) + Settings().setValue(self.plugin.settings_section + '/' + setting_name, file_path.parent) def get_folder(self, title, editbox, setting_name): """ - Opens a QFileDialog and saves the selected folder to the given editbox. + Opens a FileDialog and saves the selected folder to the given editbox. - :param title: The title of the dialog (unicode). - :param editbox: An editbox (QLineEdit). - :param setting_name: The place where to save the last opened directory. + :param str title: The title of the dialog. + :param QtWidgets.QLineEdit editbox: An QLineEditbox. + :param str setting_name: The place where to save the last opened directory. + :rtype: None """ - folder = QtWidgets.QFileDialog.getExistingDirectory( + folder_path = FileDialog.getExistingDirectory( self, title, Settings().value(self.plugin.settings_section + '/' + setting_name), QtWidgets.QFileDialog.ShowDirsOnly) - if folder: - editbox.setText(folder) - Settings().setValue(self.plugin.settings_section + '/' + setting_name, folder) + if folder_path: + editbox.setText(str(folder_path)) + Settings().setValue(self.plugin.settings_section + '/' + setting_name, folder_path) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index e846898b5..7b0caaa98 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -37,6 +37,7 @@ from PyQt5 import QtCore, QtWidgets, QtWebKit, QtWebKitWidgets, QtGui, QtMultime from openlp.core.common import AppLocation, Registry, RegistryProperties, OpenLPMixin, Settings, translate,\ is_macosx, is_win +from openlp.core.common.path import path_to_str from openlp.core.lib import ServiceItem, ImageSource, ScreenList, build_html, expand_tags, image_to_byte from openlp.core.lib.theme import BackgroundType from openlp.core.ui import HideMode, AlertLocation, DisplayControllerType @@ -259,7 +260,7 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties): background_color.setNamedColor(Settings().value('core/logo background color')) if not background_color.isValid(): background_color = QtCore.Qt.white - image_file = Settings().value('core/logo file') + image_file = path_to_str(Settings().value('core/logo file')) splash_image = QtGui.QImage(image_file) self.initial_fame = QtGui.QImage( self.screen['size'].width(), diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 9e9edde33..023d1799d 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -39,7 +39,7 @@ from openlp.core.api.http import server from openlp.core.common import Registry, RegistryProperties, AppLocation, LanguageManager, Settings, UiStrings, \ check_directory_exists, translate, is_win, is_macosx, add_actions from openlp.core.common.actions import ActionList, CategoryOrder -from openlp.core.common.path import Path +from openlp.core.common.path import Path, path_to_str, str_to_path from openlp.core.common.versionchecker import get_application_version from openlp.core.lib import Renderer, PluginManager, ImageManager, PluginStatus, ScreenList, build_icon from openlp.core.lib.ui import create_action @@ -879,8 +879,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): # Convert image files log.info('hook upgrade_plugin_settings') self.plugin_manager.hook_upgrade_plugin_settings(import_settings) - # Remove/rename old settings to prepare the import. - import_settings.remove_obsolete_settings() + # Upgrade settings to prepare the import. + 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': @@ -1277,7 +1277,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): settings.remove('custom slide') settings.remove('service') settings.beginGroup(self.general_settings_section) - self.recent_files = settings.value('recent files') + self.recent_files = [path_to_str(file_path) for file_path in settings.value('recent files')] settings.endGroup() settings.beginGroup(self.ui_settings_section) self.move(settings.value('main window position')) @@ -1301,7 +1301,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): log.debug('Saving QSettings') settings = Settings() settings.beginGroup(self.general_settings_section) - settings.setValue('recent files', self.recent_files) + settings.setValue('recent files', [str_to_path(file) for file in self.recent_files]) settings.endGroup() settings.beginGroup(self.ui_settings_section) settings.setValue('main window position', self.pos()) @@ -1443,7 +1443,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): log.info('No data copy requested') # Change the location of data directory in config file. settings = QtCore.QSettings() - settings.setValue('advanced/data path', self.new_data_path) + settings.setValue('advanced/data path', Path(self.new_data_path)) # Check if the new data path is our default. if self.new_data_path == str(AppLocation.get_directory(AppLocation.DataDir)): settings.remove('advanced/data path') diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 519378e75..5051e43c1 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -35,12 +35,13 @@ from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, ThemeLevel, OpenLPMixin, \ RegistryMixin, check_directory_exists, UiStrings, translate, split_filename, delete_file from openlp.core.common.actions import ActionList, CategoryOrder -from openlp.core.common.path import Path +from openlp.core.common.languagemanager import format_time +from openlp.core.common.path import Path, path_to_str, str_to_path from openlp.core.lib import ServiceItem, ItemCapabilities, PluginStatus, build_icon from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm from openlp.core.ui.lib import OpenLPToolbar -from openlp.core.common.languagemanager import format_time +from openlp.core.ui.lib.filedialog import FileDialog class ServiceManagerList(QtWidgets.QTreeWidget): @@ -373,7 +374,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa """ self._file_name = str(file_name) self.main_window.set_service_modified(self.is_modified(), self.short_file_name()) - Settings().setValue('servicemanager/last file', file_name) + Settings().setValue('servicemanager/last file', Path(file_name)) self._save_lite = self._file_name.endswith('.oszl') def file_name(self): @@ -435,18 +436,17 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa elif result == QtWidgets.QMessageBox.Save: self.decide_save_method() if not load_file: - file_name, filter_used = QtWidgets.QFileDialog.getOpenFileName( + file_path, filter_used = FileDialog.getOpenFileName( self.main_window, translate('OpenLP.ServiceManager', 'Open File'), Settings().value(self.main_window.service_manager_settings_section + '/last directory'), translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz *.oszl)')) - if not file_name: + if not file_path: return False else: - file_name = load_file - Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', - split_filename(file_name)[0]) - self.load_file(file_name) + file_path = str_to_path(load_file) + Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', file_path.parent) + self.load_file(str(file_path)) def save_modified_service(self): """ @@ -477,7 +477,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa self.set_file_name('') self.service_id += 1 self.set_modified(False) - Settings().setValue('servicemanager/last file', '') + Settings().setValue('servicemanager/last file', None) self.plugin_manager.new_service_created() def create_basic_service(self): @@ -513,7 +513,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa base_name = os.path.splitext(file_name)[0] service_file_name = '{name}.osj'.format(name=base_name) self.log_debug('ServiceManager.save_file - {name}'.format(name=path_file_name)) - Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', path) + Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', Path(path)) service = self.create_basic_service() write_list = [] missing_list = [] @@ -634,7 +634,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa base_name = os.path.splitext(file_name)[0] service_file_name = '{name}.osj'.format(name=base_name) self.log_debug('ServiceManager.save_file - {name}'.format(name=path_file_name)) - Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', path) + Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', Path(path)) service = self.create_basic_service() self.application.set_busy_cursor() # Number of items + 1 to zip it @@ -695,7 +695,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa default_file_name = format_time(default_pattern, local_time) else: default_file_name = '' - directory = Settings().value(self.main_window.service_manager_settings_section + '/last directory') + directory = path_to_str(Settings().value(self.main_window.service_manager_settings_section + '/last directory')) path = os.path.join(directory, default_file_name) # SaveAs from osz to oszl is not valid as the files will be deleted on exit which is not sensible or usable in # the long term. @@ -778,7 +778,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa delete_file(Path(p_file)) self.main_window.add_recent_file(file_name) self.set_modified(False) - Settings().setValue('servicemanager/last file', file_name) + Settings().setValue('servicemanager/last file', Path(file_name)) else: critical_error_message_box(message=translate('OpenLP.ServiceManager', 'File is not a valid service.')) self.log_error('File contains no service data') @@ -843,7 +843,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa Load the last service item from the service manager when the service was last closed. Can be blank if there was no service present. """ - file_name = Settings().value('servicemanager/last file') + file_name = str_to_path(Settings().value('servicemanager/last file')) if file_name: self.load_file(file_name) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 776926b7a..f32118f95 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -378,16 +378,16 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage critical_error_message_box(message=translate('OpenLP.ThemeManager', 'You have not selected a theme.')) return theme = item.data(QtCore.Qt.UserRole) - path, filter_used = \ - QtWidgets.QFileDialog.getSaveFileName(self.main_window, - translate('OpenLP.ThemeManager', 'Save Theme - ({name})'). - format(name=theme), - Settings().value(self.settings_section + '/last directory export'), - translate('OpenLP.ThemeManager', 'OpenLP Themes (*.otz)')) + export_path, filter_used = \ + FileDialog.getSaveFileName(self.main_window, + translate('OpenLP.ThemeManager', 'Save Theme - ({name})'). + format(name=theme), + Settings().value(self.settings_section + '/last directory export'), + translate('OpenLP.ThemeManager', 'OpenLP Themes (*.otz)')) self.application.set_busy_cursor() - if path: - Settings().setValue(self.settings_section + '/last directory export', path) - if self._export_theme(path, theme): + if export_path: + Settings().setValue(self.settings_section + '/last directory export', export_path.parent) + if self._export_theme(str(export_path, theme)): QtWidgets.QMessageBox.information(self, translate('OpenLP.ThemeManager', 'Theme Exported'), translate('OpenLP.ThemeManager', @@ -428,16 +428,15 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage file_paths, selected_filter = FileDialog.getOpenFileNames( self, translate('OpenLP.ThemeManager', 'Select Theme Import File'), - str_to_path(Settings().value(self.settings_section + '/last directory import')), + Settings().value(self.settings_section + '/last directory import'), translate('OpenLP.ThemeManager', 'OpenLP Themes (*.otz)')) self.log_info('New Themes {file_paths}'.format(file_paths=file_paths)) if not file_paths: return self.application.set_busy_cursor() for file_path in file_paths: - file_name = path_to_str(file_path) - Settings().setValue(self.settings_section + '/last directory import', str(file_name)) - self.unzip_theme(file_name, self.path) + self.unzip_theme(path_to_str(file_path), self.path) + Settings().setValue(self.settings_section + '/last directory import', file_path) self.load_themes() self.application.set_normal_cursor() diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index bcc81f9cb..4829ff234 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -59,7 +59,7 @@ __default_settings__ = { 'bibles/range separator': '', 'bibles/list separator': '', 'bibles/end separator': '', - 'bibles/last directory import': '', + 'bibles/last directory import': None, 'bibles/hide combined quick error': False, 'bibles/is search while typing enabled': True } diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 9c69c8ac5..bcf222eb0 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -390,7 +390,7 @@ class ImageMediaItem(MediaManagerItem): self.application.set_normal_cursor() self.load_list(files, target_group) last_dir = os.path.split(files[0])[0] - Settings().setValue(self.settings_section + '/last directory', last_dir) + Settings().setValue(self.settings_section + '/last directory', Path(last_dir)) def load_list(self, images, target_group=None, initial_load=False): """ diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index f004b27a1..154d033c1 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -27,7 +27,7 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, check_directory_exists, UiStrings,\ translate -from openlp.core.common.path import Path +from openlp.core.common.path import Path, path_to_str, str_to_path from openlp.core.lib import ItemCapabilities, MediaManagerItem, MediaType, ServiceItem, ServiceItemContext, \ build_icon, check_item_selected from openlp.core.lib.ui import create_widget_action, critical_error_message_box, create_horizontal_adjusting_combo_box @@ -303,7 +303,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties): self.list_view.clear() self.service_path = os.path.join(str(AppLocation.get_section_data_path(self.settings_section)), 'thumbnails') check_directory_exists(Path(self.service_path)) - self.load_list(Settings().value(self.settings_section + '/media files')) + self.load_list([path_to_str(file) for file in Settings().value(self.settings_section + '/media files')]) self.rebuild_players() def rebuild_players(self): @@ -401,14 +401,14 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties): :param media_type: Type to get, defaults to audio. :return: The media list """ - media = Settings().value(self.settings_section + '/media files') - media.sort(key=lambda filename: get_locale_key(os.path.split(str(filename))[1])) + media_file_paths = Settings().value(self.settings_section + '/media files') + media_file_paths.sort(key=lambda file_path: get_locale_key(file_path.name)) if media_type == MediaType.Audio: extension = self.media_controller.audio_extensions_list else: extension = self.media_controller.video_extensions_list extension = [x[1:] for x in extension] - media = [x for x in media if os.path.splitext(x)[1] in extension] + media = [x for x in media_file_paths if x.suffix in extension] return media def search(self, string, show_error): @@ -419,13 +419,12 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties): :param show_error: Should the error be shown (True) :return: The search result. """ - files = Settings().value(self.settings_section + '/media files') results = [] string = string.lower() - for file in files: - filename = os.path.split(str(file))[1] - if filename.lower().find(string) > -1: - results.append([file, filename]) + for file_path in Settings().value(self.settings_section + '/media files'): + file_name = file_path.name + if file_name.lower().find(string) > -1: + results.append([str(file_path), file_name]) return results def on_load_optical(self): @@ -446,13 +445,13 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties): :param optical: The clip to add. """ - full_list = self.get_file_list() + file_paths = self.get_file_list() # If the clip already is in the media list it isn't added and an error message is displayed. - if optical in full_list: + if optical in file_paths: critical_error_message_box(translate('MediaPlugin.MediaItem', 'Mediaclip already saved'), translate('MediaPlugin.MediaItem', 'This mediaclip has already been saved')) return # Append the optical string to the media list - full_list.append(optical) + file_paths.append(optical) self.load_list([optical]) - Settings().setValue(self.settings_section + '/media files', self.get_file_list()) + Settings().setValue(self.settings_section + '/media files', file_paths) diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 9e2921667..99c937eb0 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -26,10 +26,11 @@ import os from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common import Registry, Settings, UiStrings, translate +from openlp.core.common.languagemanager import get_locale_key +from openlp.core.common.path import path_to_str from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemContext,\ build_icon, check_item_selected, create_thumb, validate_thumb from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box -from openlp.core.common.languagemanager import get_locale_key from openlp.plugins.presentations.lib import MessageListener from openlp.plugins.presentations.lib.pdfcontroller import PDF_CONTROLLER_FILETYPES @@ -126,8 +127,8 @@ class PresentationMediaItem(MediaManagerItem): Populate the media manager tab """ self.list_view.setIconSize(QtCore.QSize(88, 50)) - files = Settings().value(self.settings_section + '/presentations files') - self.load_list(files, initial_load=True) + file_paths = Settings().value(self.settings_section + '/presentations files') + self.load_list([path_to_str(file) for file in file_paths], initial_load=True) self.populate_display_types() def populate_display_types(self): @@ -157,7 +158,7 @@ class PresentationMediaItem(MediaManagerItem): existing files, and when the user adds new files via the media manager. """ current_list = self.get_file_list() - titles = [os.path.split(file)[1] for file in current_list] + titles = [file_path.name for file_path in current_list] self.application.set_busy_cursor() if not initial_load: self.main_window.display_progress_bar(len(files)) @@ -410,11 +411,11 @@ class PresentationMediaItem(MediaManagerItem): :param show_error: not used :return: """ - files = Settings().value(self.settings_section + '/presentations files') + file_paths = Settings().value(self.settings_section + '/presentations files') results = [] string = string.lower() - for file in files: - filename = os.path.split(str(file))[1] - if filename.lower().find(string) > -1: - results.append([file, filename]) + for file_path in file_paths: + file_name = file_path.name + if file_name.lower().find(string) > -1: + results.append([path_to_str(file_path), file_name]) return results diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py index bd8e48da3..f4a091551 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -28,7 +28,7 @@ from subprocess import check_output, CalledProcessError from openlp.core.common import AppLocation, check_binary_exists from openlp.core.common import Settings, is_win -from openlp.core.common.path import Path +from openlp.core.common.path import Path, path_to_str from openlp.core.lib import ScreenList from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument @@ -113,7 +113,7 @@ class PdfController(PresentationController): self.also_supports = [] # Use the user defined program if given if Settings().value('presentations/enable_pdf_program'): - pdf_program = Settings().value('presentations/pdf_program') + pdf_program = path_to_str(Settings().value('presentations/pdf_program')) program_type = self.process_check_binary(pdf_program) if program_type == 'gs': self.gsbin = pdf_program diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index fa804f2d3..3e92827c8 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -155,9 +155,7 @@ class PresentationTab(SettingsTab): enable_pdf_program = Settings().value(self.settings_section + '/enable_pdf_program') self.pdf_program_check_box.setChecked(enable_pdf_program) self.program_path_edit.setEnabled(enable_pdf_program) - pdf_program = Settings().value(self.settings_section + '/pdf_program') - if pdf_program: - self.program_path_edit.path = str_to_path(pdf_program) + self.program_path_edit.path = Settings().value(self.settings_section + '/pdf_program') def save(self): """ @@ -193,13 +191,13 @@ class PresentationTab(SettingsTab): Settings().setValue(setting_key, self.ppt_window_check_box.checkState()) changed = True # Save pdf-settings - pdf_program = path_to_str(self.program_path_edit.path) + pdf_program_path = self.program_path_edit.path enable_pdf_program = self.pdf_program_check_box.checkState() # If the given program is blank disable using the program - if pdf_program == '': + if not pdf_program_path: enable_pdf_program = 0 - if pdf_program != Settings().value(self.settings_section + '/pdf_program'): - Settings().setValue(self.settings_section + '/pdf_program', pdf_program) + if pdf_program_path != Settings().value(self.settings_section + '/pdf_program'): + Settings().setValue(self.settings_section + '/pdf_program', pdf_program_path) changed = True if enable_pdf_program != Settings().value(self.settings_section + '/enable_pdf_program'): Settings().setValue(self.settings_section + '/enable_pdf_program', enable_pdf_program) diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index a91f78794..6f9989565 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -39,7 +39,7 @@ log = logging.getLogger(__name__) __default_settings__ = {'presentations/override app': QtCore.Qt.Unchecked, 'presentations/enable_pdf_program': QtCore.Qt.Unchecked, - 'presentations/pdf_program': '', + 'presentations/pdf_program': None, 'presentations/Impress': QtCore.Qt.Checked, 'presentations/Powerpoint': QtCore.Qt.Checked, 'presentations/Powerpoint Viewer': QtCore.Qt.Checked, diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index e3c0eb620..502d40126 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -239,13 +239,11 @@ class SongImportForm(OpenLPWizard, RegistryProperties): filters += ';;' filters += '{text} (*)'.format(text=UiStrings().AllFiles) file_paths, selected_filter = FileDialog.getOpenFileNames( - self, title, - str_to_path(Settings().value(self.plugin.settings_section + '/last directory import')), filters) + self, title, Settings().value(self.plugin.settings_section + '/last directory import'), filters) if file_paths: file_names = [path_to_str(file_path) for file_path in file_paths] listbox.addItems(file_names) - Settings().setValue(self.plugin.settings_section + '/last directory import', - os.path.split(str(file_names[0]))[0]) + Settings().setValue(self.plugin.settings_section + '/last directory import', file_paths[0].parent) def get_list_of_files(self, list_box): """ @@ -363,14 +361,15 @@ class SongImportForm(OpenLPWizard, RegistryProperties): def on_error_save_to_button_clicked(self): """ Save the error report to a file. + + :rtype: None """ - filename, filter_used = QtWidgets.QFileDialog.getSaveFileName( + file_path, filter_used = FileDialog.getSaveFileName( self, Settings().value(self.plugin.settings_section + '/last directory import')) - if not filename: + if not file_path: return - report_file = codecs.open(filename, 'w', 'utf-8') - report_file.write(self.error_report_text_edit.toPlainText()) - report_file.close() + with file_path.open('w', encoding='utf-8') as report_file: + report_file.write(self.error_report_text_edit.toPlainText()) def add_file_select_item(self): """ diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index f156f3ee3..1edb999dc 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -66,8 +66,8 @@ __default_settings__ = { 'songs/display songbook': False, 'songs/display written by': True, 'songs/display copyright symbol': False, - 'songs/last directory import': '', - 'songs/last directory export': '', + 'songs/last directory import': None, + 'songs/last directory export': None, 'songs/songselect username': '', 'songs/songselect password': '', 'songs/songselect searches': '', diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index b69b04c7a..7aa636635 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -56,14 +56,16 @@ class SongUsageDetailForm(QtWidgets.QDialog, Ui_SongUsageDetailDialog, RegistryP """ self.from_date_calendar.setSelectedDate(Settings().value(self.plugin.settings_section + '/from date')) self.to_date_calendar.setSelectedDate(Settings().value(self.plugin.settings_section + '/to date')) - self.report_path_edit.path = str_to_path( - Settings().value(self.plugin.settings_section + '/last directory export')) + self.report_path_edit.path = Settings().value(self.plugin.settings_section + '/last directory export') def on_report_path_edit_path_changed(self, file_path): """ - Triggered when the Directory selection button is clicked + Called when the path in the `PathEdit` has changed + + :param openlp.core.common.path.Path file_path: The new path. + :rtype: None """ - Settings().setValue(self.plugin.settings_section + '/last directory export', path_to_str(file_path)) + Settings().setValue(self.plugin.settings_section + '/last directory export', file_path) def accept(self): """ diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 705d86f5d..d0c2f7fe7 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -50,7 +50,7 @@ __default_settings__ = { 'songusage/active': False, 'songusage/to date': QtCore.QDate(YEAR, 8, 31), 'songusage/from date': QtCore.QDate(YEAR - 1, 9, 1), - 'songusage/last directory export': '' + 'songusage/last directory export': None } diff --git a/tests/functional/openlp_core_common/test_applocation.py b/tests/functional/openlp_core_common/test_applocation.py index c8fcc151d..7dff1a073 100644 --- a/tests/functional/openlp_core_common/test_applocation.py +++ b/tests/functional/openlp_core_common/test_applocation.py @@ -42,12 +42,14 @@ class TestAppLocation(TestCase): """ with patch('openlp.core.common.applocation.Settings') as mocked_class, \ patch('openlp.core.common.AppLocation.get_directory') as mocked_get_directory, \ - patch('openlp.core.common.applocation.check_directory_exists') as mocked_check_directory_exists: + patch('openlp.core.common.applocation.check_directory_exists') as mocked_check_directory_exists, \ + patch('openlp.core.common.applocation.os') as mocked_os: # GIVEN: A mocked out Settings class and a mocked out AppLocation.get_directory() mocked_settings = mocked_class.return_value mocked_settings.contains.return_value = False - mocked_get_directory.return_value = Path('test', 'dir') + mocked_get_directory.return_value = os.path.join('test', 'dir') mocked_check_directory_exists.return_value = True + mocked_os.path.normpath.return_value = os.path.join('test', 'dir') # WHEN: we call AppLocation.get_data_path() data_path = AppLocation.get_data_path() @@ -55,8 +57,8 @@ class TestAppLocation(TestCase): # THEN: check that all the correct methods were called, and the result is correct mocked_settings.contains.assert_called_with('advanced/data path') mocked_get_directory.assert_called_with(AppLocation.DataDir) - mocked_check_directory_exists.assert_called_with(Path('test', 'dir')) - self.assertEqual(Path('test', 'dir'), data_path, 'Result should be "test/dir"') + mocked_check_directory_exists.assert_called_with(os.path.join('test', 'dir')) + self.assertEqual(os.path.join('test', 'dir'), data_path, 'Result should be "test/dir"') def test_get_data_path_with_custom_location(self): """ diff --git a/tests/functional/openlp_core_common/test_settings.py b/tests/functional/openlp_core_common/test_settings.py index 6b30d0218..fe6e68604 100644 --- a/tests/functional/openlp_core_common/test_settings.py +++ b/tests/functional/openlp_core_common/test_settings.py @@ -26,7 +26,6 @@ from unittest import TestCase from unittest.mock import patch from openlp.core.common import Settings -from openlp.core.common.settings import recent_files_conv from tests.helpers.testmixin import TestMixin @@ -48,25 +47,6 @@ class TestSettings(TestCase, TestMixin): """ self.destroy_settings() - def test_recent_files_conv(self): - """ - Test that recent_files_conv, converts various possible types of values correctly. - """ - # GIVEN: A list of possible value types and the expected results - possible_values = [(['multiple', 'values'], ['multiple', 'values']), - (['single value'], ['single value']), - ('string value', ['string value']), - (b'bytes value', ['bytes value']), - ([], []), - (None, [])] - - # WHEN: Calling recent_files_conv with the possible values - for value, expected_result in possible_values: - actual_result = recent_files_conv(value) - - # THEN: The actual result should be the same as the expected result - self.assertEqual(actual_result, expected_result) - def test_settings_basic(self): """ Test the Settings creation and its default usage diff --git a/tests/functional/openlp_core_ui/test_exceptionform.py b/tests/functional/openlp_core_ui/test_exceptionform.py index f205a4ce2..37a040aa6 100644 --- a/tests/functional/openlp_core_ui/test_exceptionform.py +++ b/tests/functional/openlp_core_ui/test_exceptionform.py @@ -29,6 +29,7 @@ from unittest import TestCase from unittest.mock import mock_open, patch from openlp.core.common import Registry +from openlp.core.common.path import Path from openlp.core.ui import exceptionform from tests.helpers.testmixin import TestMixin @@ -154,7 +155,7 @@ class TestExceptionForm(TestMixin, TestCase): # THEN: Verify strings were formatted properly mocked_add_query_item.assert_called_with('body', MAIL_ITEM_TEXT) - @patch("openlp.core.ui.exceptionform.QtWidgets.QFileDialog.getSaveFileName") + @patch("openlp.core.ui.exceptionform.FileDialog.getSaveFileName") @patch("openlp.core.ui.exceptionform.Qt") def test_on_save_report_button_clicked(self, mocked_qt, @@ -181,7 +182,7 @@ class TestExceptionForm(TestMixin, TestCase): mocked_qt.PYQT_VERSION_STR = 'PyQt5 Test' mocked_is_linux.return_value = False mocked_application_version.return_value = 'Trunk Test' - mocked_save_filename.return_value = ['testfile.txt', ] + mocked_save_filename.return_value = (Path('testfile.txt'), 'filter') test_form = exceptionform.ExceptionForm() test_form.file_attachment = None diff --git a/tests/functional/openlp_plugins/images/test_lib.py b/tests/functional/openlp_plugins/images/test_lib.py index f00463d67..821a64bb0 100644 --- a/tests/functional/openlp_plugins/images/test_lib.py +++ b/tests/functional/openlp_plugins/images/test_lib.py @@ -28,6 +28,7 @@ from unittest.mock import ANY, MagicMock, patch from PyQt5 import QtCore, QtWidgets from openlp.core.common import Registry +from openlp.core.common.path import Path from openlp.plugins.images.lib.db import ImageFilenames, ImageGroups from openlp.plugins.images.lib.mediaitem import ImageMediaItem @@ -65,7 +66,7 @@ class TestImageMediaItem(TestCase): # THEN: load_list should have been called with the file list and None, # the directory should have been saved to the settings mocked_load_list.assert_called_once_with(file_list, None) - mocked_settings().setValue.assert_called_once_with(ANY, '/path1') + mocked_settings().setValue.assert_called_once_with(ANY, Path('/', 'path1')) @patch('openlp.plugins.images.lib.mediaitem.ImageMediaItem.load_list') @patch('openlp.plugins.images.lib.mediaitem.Settings') @@ -82,7 +83,7 @@ class TestImageMediaItem(TestCase): # THEN: load_list should have been called with the file list and the group name, # the directory should have been saved to the settings mocked_load_list.assert_called_once_with(file_list, 'group') - mocked_settings().setValue.assert_called_once_with(ANY, '/path1') + mocked_settings().setValue.assert_called_once_with(ANY, Path('/', 'path1')) @patch('openlp.plugins.images.lib.mediaitem.ImageMediaItem.load_full_list') def test_save_new_images_list_empty_list(self, mocked_load_full_list): diff --git a/tests/functional/openlp_plugins/media/test_mediaitem.py b/tests/functional/openlp_plugins/media/test_mediaitem.py index 80d21da91..d0ed7499f 100644 --- a/tests/functional/openlp_plugins/media/test_mediaitem.py +++ b/tests/functional/openlp_plugins/media/test_mediaitem.py @@ -28,6 +28,7 @@ from unittest.mock import MagicMock, patch from PyQt5 import QtCore from openlp.core import Settings +from openlp.core.common.path import Path from openlp.plugins.media.lib.mediaitem import MediaMediaItem from tests.helpers.testmixin import TestMixin @@ -66,7 +67,7 @@ class MediaItemTest(TestCase, TestMixin): Media Remote Search Successful find """ # GIVEN: The Mediaitem set up a list of media - Settings().setValue(self.media_item.settings_section + '/media files', ['test.mp3', 'test.mp4']) + Settings().setValue(self.media_item.settings_section + '/media files', [Path('test.mp3'), Path('test.mp4')]) # WHEN: Retrieving the test file result = self.media_item.search('test.mp4', False) # THEN: a file should be found @@ -77,7 +78,7 @@ class MediaItemTest(TestCase, TestMixin): Media Remote Search not find """ # GIVEN: The Mediaitem set up a list of media - Settings().setValue(self.media_item.settings_section + '/media files', ['test.mp3', 'test.mp4']) + Settings().setValue(self.media_item.settings_section + '/media files', [Path('test.mp3'), Path('test.mp4')]) # WHEN: Retrieving the test file result = self.media_item.search('test.mpx', False) # THEN: a file should be found diff --git a/tests/interfaces/openlp_core_lib/test_pluginmanager.py b/tests/interfaces/openlp_core_lib/test_pluginmanager.py index 39e964143..2e9e8342f 100644 --- a/tests/interfaces/openlp_core_lib/test_pluginmanager.py +++ b/tests/interfaces/openlp_core_lib/test_pluginmanager.py @@ -32,6 +32,7 @@ from unittest.mock import MagicMock, patch from PyQt5 import QtWidgets from openlp.core.common import Registry, Settings +from openlp.core.common.path import Path from openlp.core.lib.pluginmanager import PluginManager from tests.helpers.testmixin import TestMixin @@ -48,7 +49,7 @@ class TestPluginManager(TestCase, TestMixin): """ self.setup_application() self.build_settings() - self.temp_dir = mkdtemp('openlp') + self.temp_dir = Path(mkdtemp('openlp')) Settings().setValue('advanced/data path', self.temp_dir) Registry.create() Registry().register('service_list', MagicMock()) @@ -62,7 +63,7 @@ class TestPluginManager(TestCase, TestMixin): # On windows we need to manually garbage collect to close sqlalchemy files # to avoid errors when temporary files are deleted. gc.collect() - shutil.rmtree(self.temp_dir) + shutil.rmtree(str(self.temp_dir)) @patch('openlp.plugins.songusage.lib.db.init_schema') @patch('openlp.plugins.songs.lib.db.init_schema')