Merge fixes

This commit is contained in:
Philip Ridout 2017-08-07 21:50:01 +01:00
parent 11a9f58cb6
commit e6faf233ed
13 changed files with 55 additions and 461 deletions

View File

@ -644,7 +644,6 @@ def replace_params(args, kwargs, params):
from .exceptions import ValidationError
from .filedialog import FileDialog
from .screen import ScreenList
from .formattingtags import FormattingTags
from .plugin import PluginStatus, StringContent, Plugin

View File

@ -1,58 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2017 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; version 2 of the License. #
# #
# 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, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
Provide a work around for a bug in QFileDialog <https://bugs.launchpad.net/openlp/+bug/1209515>
"""
import logging
import os
from urllib import parse
from PyQt5 import QtWidgets
from openlp.core.common import UiStrings
log = logging.getLogger(__name__)
class FileDialog(QtWidgets.QFileDialog):
"""
Subclass QFileDialog to work round a bug
"""
@staticmethod
def getOpenFileNames(parent, *args, **kwargs):
"""
Reimplement getOpenFileNames to fix the way it returns some file names that url encoded when selecting multiple
files
"""
files, filter_used = QtWidgets.QFileDialog.getOpenFileNames(parent, *args, **kwargs)
file_list = []
for file in files:
if not os.path.exists(file):
log.info('File not found. Attempting to unquote.')
file = parse.unquote(file)
if not os.path.exists(file):
log.error('File {text} not found.'.format(text=file))
QtWidgets.QMessageBox.information(parent, UiStrings().FileNotFound,
UiStrings().FileNotFoundMessage.format(name=file))
continue
file_list.append(file)
return file_list

View File

@ -26,12 +26,14 @@ import logging
import os
import re
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtCore, QtWidgets
from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings, translate
from openlp.core.lib import FileDialog, ServiceItem, StringContent, ServiceItemContext
from openlp.core.common.path import 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
from openlp.core.ui.lib.filedialog import FileDialog
from openlp.core.ui.lib.listwidgetwithdnd import ListWidgetWithDnD
from openlp.core.ui.lib.toolbar import OpenLPToolbar
@ -309,13 +311,14 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties):
"""
Add a file to the list widget to make it available for showing
"""
files = FileDialog.getOpenFileNames(self, self.on_new_prompt,
Settings().value(self.settings_section + '/last directory'),
self.on_new_file_masks)
log.info('New files(s) {files}'.format(files=files))
if files:
file_paths, selected_filter = FileDialog.getOpenFileNames(
self, self.on_new_prompt,
str_to_path(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:
self.application.set_busy_cursor()
self.validate_and_load(files)
self.validate_and_load([path_to_str(path) for path in file_paths])
self.application.set_normal_cursor()
def load_file(self, data):

View File

@ -1,118 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2017 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; version 2 of the License. #
# #
# 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, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
""" Patch the QFileDialog so it accepts and returns Path objects"""
from functools import wraps
from pathlib import Path
from PyQt5 import QtWidgets
from openlp.core.common.path import path_to_str, str_to_path
from openlp.core.lib import replace_params
class PQFileDialog(QtWidgets.QFileDialog):
@classmethod
@wraps(QtWidgets.QFileDialog.getExistingDirectory)
def getExistingDirectory(cls, *args, **kwargs):
"""
Reimplement `getExistingDirectory` so that it can be called with, and return Path objects
:type parent: QtWidgets.QWidget or None
:type caption: str
:type directory: pathlib.Path
:type options: QtWidgets.QFileDialog.Options
:rtype: tuple[Path, str]
"""
args, kwargs = replace_params(args, kwargs, ((2, 'directory', path_to_str),))
return_value = super().getExistingDirectory(*args, **kwargs)
# getExistingDirectory returns a str that represents the path. The string is empty if the user cancels the
# dialog.
return str_to_path(return_value)
@classmethod
@wraps(QtWidgets.QFileDialog.getOpenFileName)
def getOpenFileName(cls, *args, **kwargs):
"""
Reimplement `getOpenFileName` so that it can be called with, and return Path objects
:type parent: QtWidgets.QWidget or None
:type caption: str
:type directory: pathlib.Path
:type filter: str
:type initialFilter: str
:type options: QtWidgets.QFileDialog.Options
:rtype: tuple[Path, str]
"""
args, kwargs = replace_params(args, kwargs, ((2, 'directory', path_to_str),))
return_value = super().getOpenFileName(*args, **kwargs)
# getOpenFileName returns a tuple. The first item is a of str's that represents the path. The string is empty if
# the user cancels the dialog.
return str_to_path(return_value[0]), return_value[1]
@classmethod
def getOpenFileNames(cls, *args, **kwargs):
"""
Reimplement `getOpenFileNames` so that it can be called with, and return Path objects
:type parent: QtWidgets.QWidget or None
:type caption: str
:type directory: pathlib.Path
:type filter: str
:type initialFilter: str
:type options: QtWidgets.QFileDialog.Options
:rtype: tuple[list[Path], str]
"""
args, kwargs = replace_params(args, kwargs, ((2, 'directory', path_to_str),))
return_value = super().getOpenFileNames(*args, **kwargs)
# getSaveFileName returns a tuple. The first item is a list of str's that represents the path. The list is
# empty if the user cancels the dialog.
paths = [str_to_path(path) for path in return_value[0]]
return paths, return_value[1]
@classmethod
def getSaveFileName(cls, *args, **kwargs):
"""
Reimplement `getSaveFileName` so that it can be called with, and return Path objects
:type parent: QtWidgets.QWidget or None
:type caption: str
:type directory: pathlib.Path
:type filter: str
:type initialFilter: str
:type options: QtWidgets.QFileDialog.Options
:rtype: tuple[Path or None, str]
"""
args, kwargs = replace_params(args, kwargs, ((2, 'directory', path_to_str),))
return_value = super().getSaveFileName(*args, **kwargs)
# getSaveFileName returns a tuple. The first item represents the path as a str. The string is empty if the user
# cancels the dialog.
return str_to_path(return_value[0]), return_value[1]

View File

@ -27,7 +27,7 @@ from PyQt5 import QtCore, QtWidgets
from openlp.core.common import UiStrings, translate
from openlp.core.common.path import path_to_str, str_to_path
from openlp.core.lib import build_icon
from openlp.core.ui.lib.filedialogpatches import PQFileDialog
from openlp.core.ui.lib.filedialog import FileDialog
class PathType(Enum):
@ -40,7 +40,6 @@ class PathEdit(QtWidgets.QWidget):
The :class:`~openlp.core.ui.lib.pathedit.PathEdit` class subclasses QWidget to create a custom widget for use when
a file or directory needs to be selected.
"""
pathChanged = QtCore.pyqtSignal(Path)
def __init__(self, parent=None, path_type=PathType.Files, default_path=None, dialog_caption=None, show_revert=True):
@ -176,11 +175,11 @@ class PathEdit(QtWidgets.QWidget):
if self._path_type == PathType.Directories:
if not caption:
caption = translate('OpenLP.PathEdit', 'Select Directory')
path = PQFileDialog.getExistingDirectory(self, caption, self._path, PQFileDialog.ShowDirsOnly)
path = FileDialog.getExistingDirectory(self, caption, self._path, FileDialog.ShowDirsOnly)
elif self._path_type == PathType.Files:
if not caption:
caption = self.dialog_caption = translate('OpenLP.PathEdit', 'Select File')
path, filter_used = PQFileDialog.getOpenFileName(self, caption, self._path, self.filters)
path, filter_used = FileDialog.getOpenFileName(self, caption, self._path, self.filters)
if path:
self.on_new_path(path)

View File

@ -35,7 +35,6 @@ from openlp.core.ui import ThemeLayoutForm
from openlp.core.ui.media.webkitplayer import VIDEO_EXT
from .themewizard import Ui_ThemeWizard
log = logging.getLogger(__name__)

View File

@ -22,7 +22,6 @@
"""
The Theme Manager manages adding, deleteing and modifying of themes.
"""
import json
import os
import zipfile
import shutil
@ -32,12 +31,14 @@ from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, OpenLPMixin, RegistryMixin, \
UiStrings, check_directory_exists, translate, is_win, get_filesystem_encoding, delete_file
from openlp.core.lib import FileDialog, ImageSource, ValidationError, get_text_file_string, build_icon, \
from openlp.core.common.path import path_to_str, str_to_path
from openlp.core.lib import ImageSource, ValidationError, get_text_file_string, build_icon, \
check_item_selected, create_thumb, validate_thumb
from openlp.core.lib.theme import Theme, BackgroundType
from openlp.core.lib.ui import critical_error_message_box, create_widget_action
from openlp.core.ui import FileRenameForm, ThemeForm
from openlp.core.ui.lib import OpenLPToolbar
from openlp.core.ui.lib.filedialog import FileDialog
from openlp.core.common.languagemanager import get_locale_key
@ -424,15 +425,17 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
those files. This process will only load version 2 themes.
:param field:
"""
files = FileDialog.getOpenFileNames(self,
translate('OpenLP.ThemeManager', 'Select Theme Import File'),
Settings().value(self.settings_section + '/last directory import'),
translate('OpenLP.ThemeManager', 'OpenLP Themes (*.otz)'))
self.log_info('New Themes {name}'.format(name=str(files)))
if not files:
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')),
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_name in files:
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.load_themes()

View File

@ -22,6 +22,8 @@
"""
The Create/Edit theme wizard
"""
from pathlib import Path
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import UiStrings, translate, is_macosx
@ -30,8 +32,6 @@ from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGrad
from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets
from openlp.core.ui.lib import ColorButton, PathEdit
from pathlib import Path
class Ui_ThemeWizard(object):
"""

View File

@ -28,12 +28,15 @@ import logging
import re
import os
import shutil
from pathlib import Path
from PyQt5 import QtCore, QtWidgets
from openlp.core.common import Registry, RegistryProperties, AppLocation, UiStrings, check_directory_exists, translate
from openlp.core.lib import FileDialog, PluginStatus, MediaType, create_separated_list
from openlp.core.common.path import path_to_str
from openlp.core.lib import PluginStatus, MediaType, create_separated_list
from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, find_and_set_in_combo_box
from openlp.core.ui.lib.filedialog import FileDialog
from openlp.core.common.languagemanager import get_natural_key
from openlp.plugins.songs.lib import VerseType, clean_song
from openlp.plugins.songs.lib.db import Book, Song, Author, AuthorType, Topic, MediaFile, SongBookEntry
@ -925,9 +928,10 @@ class EditSongForm(QtWidgets.QDialog, Ui_EditSongDialog, RegistryProperties):
Loads file(s) from the filesystem.
"""
filters = '{text} (*)'.format(text=UiStrings().AllFiles)
file_names = FileDialog.getOpenFileNames(self, translate('SongsPlugin.EditSongForm', 'Open File(s)'), '',
filters)
for filename in file_names:
file_paths, selected_filter = FileDialog.getOpenFileNames(
self, translate('SongsPlugin.EditSongForm', 'Open File(s)'), Path(), filters)
for file_path in file_paths:
filename = path_to_str(file_path)
item = QtWidgets.QListWidgetItem(os.path.split(str(filename))[1])
item.setData(QtCore.Qt.UserRole, filename)
self.audio_list_widget.addItem(item)

View File

@ -29,8 +29,9 @@ import os
from PyQt5 import QtCore, QtWidgets
from openlp.core.common import RegistryProperties, Settings, UiStrings, translate
from openlp.core.lib import FileDialog
from openlp.core.common.path import path_to_str, str_to_path
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.lib.filedialog import FileDialog
from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings
from openlp.plugins.songs.lib.importer import SongFormat, SongFormatSelect
@ -237,10 +238,11 @@ class SongImportForm(OpenLPWizard, RegistryProperties):
if filters:
filters += ';;'
filters += '{text} (*)'.format(text=UiStrings().AllFiles)
file_names = FileDialog.getOpenFileNames(
file_paths, selected_filter = FileDialog.getOpenFileNames(
self, title,
Settings().value(self.plugin.settings_section + '/last directory import'), filters)
if file_names:
str_to_path(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])

View File

@ -25,7 +25,6 @@ Package to test the openlp.core.lib.filedialog package.
from unittest import TestCase
from unittest.mock import MagicMock, call, patch
from openlp.core.lib.filedialog import FileDialog
class TestFileDialog(TestCase):
@ -45,52 +44,3 @@ class TestFileDialog(TestCase):
self.os_patcher.stop()
self.qt_gui_patcher.stop()
self.ui_strings_patcher.stop()
def test_get_open_file_names_canceled(self):
"""
Test that FileDialog.getOpenFileNames() returns and empty QStringList when QFileDialog is canceled
(returns an empty QStringList)
"""
self.mocked_os.reset_mock()
# GIVEN: An empty QStringList as a return value from QFileDialog.getOpenFileNames
self.mocked_qt_gui.QFileDialog.getOpenFileNames.return_value = ([], [])
# WHEN: FileDialog.getOpenFileNames is called
result = FileDialog.getOpenFileNames(self.mocked_parent)
# THEN: The returned value should be an empty QStringList and os.path.exists should not have been called
assert not self.mocked_os.path.exists.called
self.assertEqual(result, [],
'FileDialog.getOpenFileNames should return and empty list when QFileDialog.getOpenFileNames '
'is canceled')
def test_returned_file_list(self):
"""
Test that FileDialog.getOpenFileNames handles a list of files properly when QFileList.getOpenFileNames
returns a good file name, a url encoded file name and a non-existing file
"""
self.mocked_os.rest_mock()
self.mocked_qt_gui.reset_mock()
# GIVEN: A List of known values as a return value from QFileDialog.getOpenFileNames and a list of valid file
# names.
self.mocked_qt_gui.QFileDialog.getOpenFileNames.return_value = ([
'/Valid File', '/url%20encoded%20file%20%231', '/non-existing'], [])
self.mocked_os.path.exists.side_effect = lambda file_name: file_name in [
'/Valid File', '/url encoded file #1']
self.mocked_ui_strings().FileNotFound = 'File Not Found'
self.mocked_ui_strings().FileNotFoundMessage = 'File {name} not found.\nPlease try selecting it individually.'
# WHEN: FileDialog.getOpenFileNames is called
result = FileDialog.getOpenFileNames(self.mocked_parent)
# THEN: os.path.exists should have been called with known args. QmessageBox.information should have been
# called. The returned result should correlate with the input.
call_list = [call('/Valid File'), call('/url%20encoded%20file%20%231'), call('/url encoded file #1'),
call('/non-existing'), call('/non-existing')]
self.mocked_os.path.exists.assert_has_calls(call_list)
self.mocked_qt_gui.QMessageBox.information.assert_called_with(
self.mocked_parent, 'File Not Found',
'File /non-existing not found.\nPlease try selecting it individually.')
self.assertEqual(result, ['/Valid File', '/url encoded file #1'], 'The returned file list is incorrect')

View File

@ -1,189 +0,0 @@
import os
import sys
from unittest import TestCase
from unittest.mock import patch
from pathlib import Path
from PyQt5 import QtWidgets
from openlp.core.ui.lib.filedialogpatches import PQFileDialog
class TestFileDialogPatches(TestCase):
"""
Tests for the :mod:`openlp.core.ui.lib.filedialogpatches` module
"""
def test_pq_file_dialog(self):
"""
Test that the :class:`PQFileDialog` instantiates correctly
"""
# GIVEN: The PQFileDialog class
# WHEN: Creating an instance
instance = PQFileDialog()
# THEN: The instance should be an instance of QFileDialog
self.assertIsInstance(instance, QtWidgets.QFileDialog)
def test_get_existing_directory_user_abort(self):
"""
Test that `getExistingDirectory` handles the case when the user cancels the dialog
"""
# GIVEN: PQFileDialog with a mocked QDialog.getExistingDirectory method
# WHEN: Calling PQFileDialog.getExistingDirectory and the user cancels the dialog returns a empty string
with patch('PyQt5.QtWidgets.QFileDialog.getExistingDirectory', return_value=''):
result = PQFileDialog.getExistingDirectory()
# THEN: The result should be None
self.assertEqual(result, None)
def test_get_existing_directory_user_accepts(self):
"""
Test that `getExistingDirectory` handles the case when the user accepts the dialog
"""
# GIVEN: PQFileDialog with a mocked QDialog.getExistingDirectory method
# WHEN: Calling PQFileDialog.getExistingDirectory, the user chooses a file and accepts the dialog (it returns a
# string pointing to the directory)
with patch('PyQt5.QtWidgets.QFileDialog.getExistingDirectory', return_value=os.path.join('test', 'dir')):
result = PQFileDialog.getExistingDirectory()
# THEN: getExistingDirectory() should return a Path object pointing to the chosen file
self.assertEqual(result, Path('test', 'dir'))
def test_get_existing_directory_param_order(self):
"""
Test that `getExistingDirectory` passes the parameters to `QFileDialog.getExistingDirectory` in the correct
order
"""
# GIVEN: PQFileDialog
with patch('openlp.core.ui.lib.filedialogpatches.QtWidgets.QFileDialog.getExistingDirectory', return_value='') \
as mocked_get_existing_directory:
# WHEN: Calling the getExistingDirectory method with all parameters set
PQFileDialog.getExistingDirectory('Parent', 'Caption', Path('test', 'dir'), 'Options')
# THEN: The `QFileDialog.getExistingDirectory` should have been called with the parameters in the correct
# order
mocked_get_existing_directory.assert_called_once_with('Parent', 'Caption', os.path.join('test', 'dir'),
'Options')
def test_get_open_file_name_user_abort(self):
"""
Test that `getOpenFileName` handles the case when the user cancels the dialog
"""
# GIVEN: PQFileDialog with a mocked QDialog.getOpenFileName method
# WHEN: Calling PQFileDialog.getOpenFileName and the user cancels the dialog (it returns a tuple with the first
# value set as an empty string)
with patch('PyQt5.QtWidgets.QFileDialog.getOpenFileName', return_value=('', '')):
result = PQFileDialog.getOpenFileName()
# THEN: First value should be None
self.assertEqual(result[0], None)
def test_get_open_file_name_user_accepts(self):
"""
Test that `getOpenFileName` handles the case when the user accepts the dialog
"""
# GIVEN: PQFileDialog with a mocked QDialog.getOpenFileName method
# WHEN: Calling PQFileDialog.getOpenFileName, the user chooses a file and accepts the dialog (it returns a
# tuple with the first value set as an string pointing to the file)
with patch('PyQt5.QtWidgets.QFileDialog.getOpenFileName',
return_value=(os.path.join('test', 'chosen.file'), '')):
result = PQFileDialog.getOpenFileName()
# THEN: getOpenFileName() should return a tuple with the first value set to a Path object pointing to the
# chosen file
self.assertEqual(result[0], Path('test', 'chosen.file'))
def test_get_open_file_name_selected_filter(self):
"""
Test that `getOpenFileName` does not modify the selectedFilter as returned by `QFileDialog.getOpenFileName`
"""
# GIVEN: PQFileDialog with a mocked QDialog.get_save_file_name method
# WHEN: Calling PQFileDialog.getOpenFileName, and `QFileDialog.getOpenFileName` returns a known `selectedFilter`
with patch('PyQt5.QtWidgets.QFileDialog.getOpenFileName', return_value=('', 'selected filter')):
result = PQFileDialog.getOpenFileName()
# THEN: getOpenFileName() should return a tuple with the second value set to a the selected filter
self.assertEqual(result[1], 'selected filter')
def test_get_open_file_names_user_abort(self):
"""
Test that `getOpenFileNames` handles the case when the user cancels the dialog
"""
# GIVEN: PQFileDialog with a mocked QDialog.getOpenFileNames method
# WHEN: Calling PQFileDialog.getOpenFileNames and the user cancels the dialog (it returns a tuple with the first
# value set as an empty list)
with patch('PyQt5.QtWidgets.QFileDialog.getOpenFileNames', return_value=([], '')):
result = PQFileDialog.getOpenFileNames()
# THEN: First value should be an empty list
self.assertEqual(result[0], [])
def test_get_open_file_names_user_accepts(self):
"""
Test that `getOpenFileNames` handles the case when the user accepts the dialog
"""
# GIVEN: PQFileDialog with a mocked QDialog.getOpenFileNames method
# WHEN: Calling PQFileDialog.getOpenFileNames, the user chooses some files and accepts the dialog (it returns a
# tuple with the first value set as a list of strings pointing to the file)
with patch('PyQt5.QtWidgets.QFileDialog.getOpenFileNames',
return_value=([os.path.join('test', 'chosen.file1'), os.path.join('test', 'chosen.file2')], '')):
result = PQFileDialog.getOpenFileNames()
# THEN: getOpenFileNames() should return a tuple with the first value set to a list of Path objects pointing
# to the chosen file
self.assertEqual(result[0], [Path('test', 'chosen.file1'), Path('test', 'chosen.file2')])
def test_get_open_file_names_selected_filter(self):
"""
Test that `getOpenFileNames` does not modify the selectedFilter as returned by `QFileDialog.getOpenFileNames`
"""
# GIVEN: PQFileDialog with a mocked QDialog.getOpenFileNames method
# WHEN: Calling PQFileDialog.getOpenFileNames, and `QFileDialog.getOpenFileNames` returns a known
# `selectedFilter`
with patch('PyQt5.QtWidgets.QFileDialog.getOpenFileNames', return_value=([], 'selected filter')):
result = PQFileDialog.getOpenFileNames()
# THEN: getOpenFileNames() should return a tuple with the second value set to a the selected filter
self.assertEqual(result[1], 'selected filter')
def test_get_save_file_name_user_abort(self):
"""
Test that `getSaveFileName` handles the case when the user cancels the dialog
"""
# GIVEN: PQFileDialog with a mocked QDialog.get_save_file_name method
# WHEN: Calling PQFileDialog.getSaveFileName and the user cancels the dialog (it returns a tuple with the first
# value set as an empty string)
with patch('PyQt5.QtWidgets.QFileDialog.getSaveFileName', return_value=('', '')):
result = PQFileDialog.getSaveFileName()
# THEN: First value should be None
self.assertEqual(result[0], None)
def test_get_save_file_name_user_accepts(self):
"""
Test that `getSaveFileName` handles the case when the user accepts the dialog
"""
# GIVEN: PQFileDialog with a mocked QDialog.getSaveFileName method
# WHEN: Calling PQFileDialog.getSaveFileName, the user chooses a file and accepts the dialog (it returns a
# tuple with the first value set as an string pointing to the file)
with patch('PyQt5.QtWidgets.QFileDialog.getSaveFileName',
return_value=(os.path.join('test', 'chosen.file'), '')):
result = PQFileDialog.getSaveFileName()
# THEN: getSaveFileName() should return a tuple with the first value set to a Path object pointing to the
# chosen file
self.assertEqual(result[0], Path('test', 'chosen.file'))
def test_get_save_file_name_selected_filter(self):
"""
Test that `getSaveFileName` does not modify the selectedFilter as returned by `QFileDialog.getSaveFileName`
"""
# GIVEN: PQFileDialog with a mocked QDialog.get_save_file_name method
# WHEN: Calling PQFileDialog.getSaveFileName, and `QFileDialog.getSaveFileName` returns a known `selectedFilter`
with patch('PyQt5.QtWidgets.QFileDialog.getSaveFileName', return_value=('', 'selected filter')):
result = PQFileDialog.getSaveFileName()
# THEN: getSaveFileName() should return a tuple with the second value set to a the selected filter
self.assertEqual(result[1], 'selected filter')

View File

@ -28,7 +28,7 @@ from unittest import TestCase
from unittest.mock import MagicMock, PropertyMock, patch
from openlp.core.ui.lib import PathEdit, PathType
from openlp.core.ui.lib.filedialogpatches import PQFileDialog
from openlp.core.ui.lib.filedialog import FileDialog
class TestPathEdit(TestCase):
@ -126,9 +126,9 @@ class TestPathEdit(TestCase):
"""
# GIVEN: An instance of PathEdit with the `path_type` set to `Directories` and a mocked
# QFileDialog.getExistingDirectory
with patch('openlp.core.ui.lib.pathedit.PQFileDialog.getExistingDirectory', return_value=None) as \
with patch('openlp.core.ui.lib.pathedit.FileDialog.getExistingDirectory', return_value=None) as \
mocked_get_existing_directory, \
patch('openlp.core.ui.lib.pathedit.PQFileDialog.getOpenFileName') as mocked_get_open_file_name:
patch('openlp.core.ui.lib.pathedit.FileDialog.getOpenFileName') as mocked_get_open_file_name:
self.widget._path_type = PathType.Directories
self.widget._path = Path('test', 'path')
@ -138,7 +138,7 @@ class TestPathEdit(TestCase):
# THEN: The FileDialog.getExistingDirectory should have been called with the default caption
mocked_get_existing_directory.assert_called_once_with(self.widget, 'Select Directory',
Path('test', 'path'),
PQFileDialog.ShowDirsOnly)
FileDialog.ShowDirsOnly)
self.assertFalse(mocked_get_open_file_name.called)
def test_on_browse_button_clicked_directory_custom_caption(self):
@ -148,9 +148,9 @@ class TestPathEdit(TestCase):
"""
# GIVEN: An instance of PathEdit with the `path_type` set to `Directories` and a mocked
# QFileDialog.getExistingDirectory with `default_caption` set.
with patch('openlp.core.ui.lib.pathedit.PQFileDialog.getExistingDirectory', return_value=None) as \
with patch('openlp.core.ui.lib.pathedit.FileDialog.getExistingDirectory', return_value=None) as \
mocked_get_existing_directory, \
patch('openlp.core.ui.lib.pathedit.PQFileDialog.getOpenFileName') as mocked_get_open_file_name:
patch('openlp.core.ui.lib.pathedit.FileDialog.getOpenFileName') as mocked_get_open_file_name:
self.widget._path_type = PathType.Directories
self.widget._path = Path('test', 'path')
self.widget.dialog_caption = 'Directory Caption'
@ -161,7 +161,7 @@ class TestPathEdit(TestCase):
# THEN: The FileDialog.getExistingDirectory should have been called with the custom caption
mocked_get_existing_directory.assert_called_once_with(self.widget, 'Directory Caption',
Path('test', 'path'),
PQFileDialog.ShowDirsOnly)
FileDialog.ShowDirsOnly)
self.assertFalse(mocked_get_open_file_name.called)
def test_on_browse_button_clicked_file(self):
@ -169,8 +169,8 @@ class TestPathEdit(TestCase):
Test the `browse_button` `clicked` handler on_browse_button_clicked when the `path_type` is set to Files.
"""
# GIVEN: An instance of PathEdit with the `path_type` set to `Files` and a mocked QFileDialog.getOpenFileName
with patch('openlp.core.ui.lib.pathedit.PQFileDialog.getExistingDirectory') as mocked_get_existing_directory, \
patch('openlp.core.ui.lib.pathedit.PQFileDialog.getOpenFileName', return_value=(None, '')) as \
with patch('openlp.core.ui.lib.pathedit.FileDialog.getExistingDirectory') as mocked_get_existing_directory, \
patch('openlp.core.ui.lib.pathedit.FileDialog.getOpenFileName', return_value=(None, '')) as \
mocked_get_open_file_name:
self.widget._path_type = PathType.Files
self.widget._path = Path('test', 'pat.h')
@ -190,8 +190,8 @@ class TestPathEdit(TestCase):
"""
# GIVEN: An instance of PathEdit with the `path_type` set to `Files` and a mocked QFileDialog.getOpenFileName
# with `default_caption` set.
with patch('openlp.core.ui.lib.pathedit.PQFileDialog.getExistingDirectory') as mocked_get_existing_directory, \
patch('openlp.core.ui.lib.pathedit.PQFileDialog.getOpenFileName', return_value=(None, '')) as \
with patch('openlp.core.ui.lib.pathedit.FileDialog.getExistingDirectory') as mocked_get_existing_directory, \
patch('openlp.core.ui.lib.pathedit.FileDialog.getOpenFileName', return_value=(None, '')) as \
mocked_get_open_file_name:
self.widget._path_type = PathType.Files
self.widget._path = Path('test', 'pat.h')
@ -212,7 +212,7 @@ class TestPathEdit(TestCase):
"""
# GIVEN: An instance of PathEdit with a mocked QFileDialog.getOpenFileName which returns an empty str for the
# file path.
with patch('openlp.core.ui.lib.pathedit.PQFileDialog.getOpenFileName', return_value=(None, '')) as \
with patch('openlp.core.ui.lib.pathedit.FileDialog.getOpenFileName', return_value=(None, '')) as \
mocked_get_open_file_name:
# WHEN: Calling on_browse_button_clicked
@ -228,7 +228,7 @@ class TestPathEdit(TestCase):
"""
# GIVEN: An instance of PathEdit with a mocked QFileDialog.getOpenFileName which returns a str for the file
# path.
with patch('openlp.core.ui.lib.pathedit.PQFileDialog.getOpenFileName',
with patch('openlp.core.ui.lib.pathedit.FileDialog.getOpenFileName',
return_value=(Path('test', 'pat.h'), '')) as mocked_get_open_file_name, \
patch.object(self.widget, 'on_new_path'):