4
4
###############################################################################
5
5
# OpenLP - Open Source Lyrics Projection #
6
6
# --------------------------------------------------------------------------- #
7
# Copyright (c) 2008-2018 OpenLP Developers #
7
# Copyright (c) 2008-2019 OpenLP Developers #
8
8
# --------------------------------------------------------------------------- #
9
9
# This program is free software; you can redistribute it and/or modify it #
10
10
# under the terms of the GNU General Public License as published by the Free #
37
36
from openlp.core.common.actions import ActionList, CategoryOrder
38
37
from openlp.core.common.applocation import AppLocation
39
38
from openlp.core.common.i18n import UiStrings, format_time, translate
40
from openlp.core.ui.icons import UiIcons
41
39
from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder
42
40
from openlp.core.common.mixins import LogMixin, RegistryProperties
43
41
from openlp.core.common.path import Path, str_to_path
44
42
from openlp.core.common.registry import Registry, RegistryBase
45
43
from openlp.core.common.settings import Settings
46
from openlp.core.lib import ServiceItem, ItemCapabilities, PluginStatus, build_icon
44
from openlp.core.lib import build_icon
47
45
from openlp.core.lib.exceptions import ValidationError
48
from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box
49
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
46
from openlp.core.lib.plugin import PluginStatus
47
from openlp.core.lib.serviceitem import ItemCapabilities, ServiceItem
48
from openlp.core.lib.ui import create_widget_action, critical_error_message_box, find_and_set_in_combo_box
49
from openlp.core.ui.icons import UiIcons
50
from openlp.core.ui.serviceitemeditform import ServiceItemEditForm
51
from openlp.core.ui.servicenoteform import ServiceNoteForm
52
from openlp.core.ui.starttimeform import StartTimeForm
50
53
from openlp.core.widgets.dialogs import FileDialog
51
54
from openlp.core.widgets.toolbar import OpenLPToolbar
230
233
self.service_manager_list.itemExpanded.connect(self.expanded)
231
234
# Last little bits of setting up
232
235
self.service_theme = Settings().value(self.main_window.service_manager_settings_section + '/service theme')
233
self.service_path = str(AppLocation.get_section_data_path('servicemanager'))
236
self.service_path = AppLocation.get_section_data_path('servicemanager')
234
237
# build the drag and drop context menu
235
238
self.dnd_menu = QtWidgets.QMenu()
236
239
self.new_action = self.dnd_menu.addAction(translate('OpenLP.ServiceManager', '&Add New Item'))
586
589
self.main_window.increment_progress_bar(service_content_size)
587
590
# Finally add all the listed media files.
588
591
for write_path in write_list:
589
zip_file.write(str(write_path), str(write_path))
592
zip_file.write(write_path, write_path)
590
593
self.main_window.increment_progress_bar(write_path.stat().st_size)
591
594
with suppress(FileNotFoundError):
592
595
file_path.unlink()
593
os.link(temp_file.name, str(file_path))
596
os.link(temp_file.name, file_path)
594
597
Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', file_path.parent)
595
598
except (PermissionError, OSError) as error:
596
599
self.log_exception('Failed to save service to disk: {name}'.format(name=file_path))
675
678
service_data = None
676
679
self.application.set_busy_cursor()
678
with zipfile.ZipFile(str(file_path)) as zip_file:
681
with zipfile.ZipFile(file_path) as zip_file:
679
682
compressed_size = 0
680
683
for zip_info in zip_file.infolist():
681
684
compressed_size += zip_info.compress_size
688
691
service_data = json_file.read()
690
693
zip_info.filename = os.path.basename(zip_info.filename)
691
zip_file.extract(zip_info, str(self.service_path))
694
zip_file.extract(zip_info, self.service_path)
692
695
self.main_window.increment_progress_bar(zip_info.compress_size)
694
697
items = json.loads(service_data, cls=OpenLPJsonDecoder)
700
703
Settings().setValue('servicemanager/last file', file_path)
702
705
raise ValidationError(msg='No service data found')
703
except (NameError, OSError, ValidationError, zipfile.BadZipFile) as e:
706
except (NameError, OSError, ValidationError, zipfile.BadZipFile):
707
self.application.set_normal_cursor()
704
708
self.log_exception('Problem loading service file {name}'.format(name=file_path))
705
709
critical_error_message_box(
706
710
message=translate('OpenLP.ServiceManager',
707
'The service file {file_path} could not be loaded because it is either corrupt, or '
708
'not a valid OpenLP 2 or OpenLP 3 service file.'.format(file_path=file_path)))
711
'The service file {file_path} could not be loaded because it is either corrupt, '
712
'inaccessible, or not a valid OpenLP 2 or OpenLP 3 service file.'
713
).format(file_path=file_path))
709
714
self.main_window.finished_progress_bar()
710
715
self.application.set_normal_cursor()
711
716
self.repaint_service_list(-1, -1)
727
732
find_and_set_in_combo_box(self.theme_combo_box, theme, set_missing=False)
728
733
if theme == self.theme_combo_box.currentText():
729
self.renderer.set_service_theme(theme)
734
# TODO: Use a local display widget
735
# self.preview_display.set_theme(get_theme_from_name(theme))
731
738
if self._save_lite:
732
739
service_item.set_from_service(item)
1162
1169
# Repaint the screen
1163
1170
self.service_manager_list.clear()
1164
1171
self.service_manager_list.clearSelection()
1165
for item_count, item in enumerate(self.service_items):
1172
for item_index, item in enumerate(self.service_items):
1166
1173
service_item_from_item = item['service_item']
1167
1174
tree_widget_item = QtWidgets.QTreeWidgetItem(self.service_manager_list)
1168
1175
if service_item_from_item.is_valid:
1211
1218
tree_widget_item.setData(0, QtCore.Qt.UserRole, item['order'])
1212
1219
tree_widget_item.setSelected(item['selected'])
1213
1220
# Add the children to their parent tree_widget_item.
1214
for count, frame in enumerate(service_item_from_item.get_frames()):
1221
for slide_index, slide in enumerate(service_item_from_item.slides):
1215
1222
child = QtWidgets.QTreeWidgetItem(tree_widget_item)
1216
1223
# prefer to use a display_title
1217
1224
if service_item_from_item.is_capable(ItemCapabilities.HasDisplayTitle):
1218
text = frame['display_title'].replace('\n', ' ')
1225
text = slide['display_title'].replace('\n', ' ')
1220
text = frame['title'].replace('\n', ' ')
1227
text = slide['title'].replace('\n', ' ')
1221
1228
child.setText(0, text[:40])
1222
child.setData(0, QtCore.Qt.UserRole, count)
1223
if service_item == item_count:
1224
if item['expanded'] and service_item_child == count:
1229
child.setData(0, QtCore.Qt.UserRole, slide_index)
1230
if service_item == item_index:
1231
if item['expanded'] and service_item_child == slide_index:
1225
1232
self.service_manager_list.setCurrentItem(child)
1226
1233
elif service_item_child == -1:
1227
1234
self.service_manager_list.setCurrentItem(tree_widget_item)
1232
1239
Empties the service_path of temporary files on system exit.
1234
for file_name in os.listdir(self.service_path):
1235
file_path = Path(self.service_path, file_name)
1241
for file_path in self.service_path.iterdir():
1236
1242
delete_file(file_path)
1237
if os.path.exists(os.path.join(self.service_path, 'audio')):
1238
shutil.rmtree(os.path.join(self.service_path, 'audio'), True)
1243
audio_path = self.service_path / 'audio'
1244
if audio_path.exists():
1245
audio_path.rmtree(True)
1240
1247
def on_theme_combo_box_selected(self, current_index):
1244
1251
:param current_index: The combo box index for the selected item
1246
1253
self.service_theme = self.theme_combo_box.currentText()
1247
self.renderer.set_service_theme(self.service_theme)
1254
# TODO: Use a local display widget
1255
# self.preview_display.set_theme(get_theme_from_name(theme))
1248
1256
Settings().setValue(self.main_window.service_manager_settings_section + '/service theme', self.service_theme)
1249
1257
self.regenerate_service_items(True)
1336
1344
self.repaint_service_list(s_item, child)
1337
1345
self.live_controller.replace_service_manager_item(item)
1340
1348
# nothing selected for dnd
1341
1349
if self.drop_position == -1:
1342
1350
if isinstance(item, list):
1585
1593
theme_group.addAction(create_widget_action(self.theme_menu, theme, text=theme, checked=False,
1586
1594
triggers=self.on_theme_change_action))
1587
1595
find_and_set_in_combo_box(self.theme_combo_box, self.service_theme)
1588
self.renderer.set_service_theme(self.service_theme)
1596
# TODO: Sort this out
1597
# self.renderer.set_service_theme(self.service_theme)
1589
1598
self.regenerate_service_items()
1591
1600
def on_theme_change_action(self):