Implemented adding image groups

This commit is contained in:
Arjan Schrijver 2013-01-25 15:06:49 +01:00
parent 9b707d2351
commit a770f90320
9 changed files with 379 additions and 19 deletions

View File

@ -46,6 +46,7 @@ class TreeWidgetWithDnD(QtGui.QTreeWidget):
QtGui.QTreeWidget.__init__(self, parent)
self.mimeDataText = name
self.header().close()
self.defaultIndentation = self.indentation()
self.setIndentation(0)
assert(self.mimeDataText)

View File

@ -58,6 +58,7 @@ class UiStrings(object):
"""
self.About = translate('OpenLP.Ui', 'About')
self.Add = translate('OpenLP.Ui', '&Add')
self.AddGroup = translate('OpenLP.Ui', 'Add group')
self.Advanced = translate('OpenLP.Ui', 'Advanced')
self.AllFiles = translate('OpenLP.Ui', 'All Files')
self.Automatic = translate('OpenLP.Ui', 'Automatic')

View File

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2013 Raoul Snyman #
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
"""
Forms in OpenLP are made up of two classes. One class holds all the graphical
elements, like buttons and lists, and the other class holds all the functional
code, like slots and loading and saving.
The first class, commonly known as the **Dialog** class, is typically named
``Ui_<name>Dialog``. It is a slightly modified version of the class that the
``pyuic4`` command produces from Qt4's .ui file. Typical modifications will be
converting most strings from "" to u'' and using OpenLP's ``translate()``
function for translating strings.
The second class, commonly known as the **Form** class, is typically named
``<name>Form``. This class is the one which is instantiated and used. It uses
dual inheritance to inherit from (usually) QtGui.QDialog and the Ui class
mentioned above, like so::
class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
This allows OpenLP to use ``self.object`` for all the GUI elements while keeping
them separate from the functionality, so that it is easier to recreate the GUI
from the .ui files later if necessary.
"""
from addgroupform import AddGroupForm

View File

@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2013 Raoul Snyman #
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
from PyQt4 import QtGui
from openlp.core.lib import translate
from openlp.core.lib.ui import create_button_box
class Ui_AddGroupDialog(object):
def setupUi(self, addGroupDialog):
addGroupDialog.setObjectName(u'addGroupDialog')
addGroupDialog.resize(300, 10)
self.dialogLayout = QtGui.QVBoxLayout(addGroupDialog)
self.dialogLayout.setObjectName(u'dialogLayout')
self.nameLayout = QtGui.QFormLayout()
self.nameLayout.setObjectName(u'nameLayout')
self.parentGroupLabel = QtGui.QLabel(addGroupDialog)
self.parentGroupLabel.setObjectName(u'parentGroupLabel')
self.parentGroupComboBox = QtGui.QComboBox(addGroupDialog)
self.parentGroupComboBox.setObjectName(u'parentGroupComboBox')
self.nameLayout.addRow(self.parentGroupLabel, self.parentGroupComboBox)
self.nameLabel = QtGui.QLabel(addGroupDialog)
self.nameLabel.setObjectName(u'nameLabel')
self.nameEdit = QtGui.QLineEdit(addGroupDialog)
self.nameEdit.setObjectName(u'nameEdit')
self.nameLabel.setBuddy(self.nameEdit)
self.nameLayout.addRow(self.nameLabel, self.nameEdit)
self.dialogLayout.addLayout(self.nameLayout)
self.buttonBox = create_button_box(addGroupDialog, u'buttonBox', [u'cancel', u'save'])
self.dialogLayout.addWidget(self.buttonBox)
self.retranslateUi(addGroupDialog)
addGroupDialog.setMaximumHeight(addGroupDialog.sizeHint().height())
def retranslateUi(self, addGroupDialog):
addGroupDialog.setWindowTitle(translate('ImagePlugin.AddGroupForm', 'Add group'))
self.parentGroupLabel.setText(translate('ImagePlugin.AddGroupForm', 'Parent group:'))
self.nameLabel.setText(translate('ImagePlugin.AddGroupForm', 'Group name:'))

View File

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2013 Raoul Snyman #
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
from PyQt4 import QtGui
from openlp.core.lib import translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.images.forms.addgroupdialog import Ui_AddGroupDialog
class AddGroupForm(QtGui.QDialog, Ui_AddGroupDialog):
"""
Class documentation goes here.
"""
def __init__(self, parent=None):
"""
Constructor
"""
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
def exec_(self, clear=True):
if clear:
self.nameEdit.clear()
self.nameEdit.setFocus()
return QtGui.QDialog.exec_(self)
def accept(self):
if not self.nameEdit.text():
critical_error_message_box(message=translate('ImagePlugin.AddGroupForm',
'You need to type in a group name.'))
self.nameEdit.setFocus()
return False
else:
return QtGui.QDialog.accept(self)

View File

@ -37,7 +37,8 @@ from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, Sett
UiStrings
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation, delete_file, locale_compare, get_images_filter
from openlp.plugins.images.lib.db import ImageFilenames
from openlp.plugins.images.forms import AddGroupForm
from openlp.plugins.images.lib.db import ImageFilenames, ImageGroups
log = logging.getLogger(__name__)
@ -53,6 +54,8 @@ class ImageMediaItem(MediaManagerItem):
self.quickPreviewAllowed = True
self.hasSearch = True
self.manager = plugin.manager
self.addgroupform = AddGroupForm(self)
self.fillGroupsComboBox()
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged)
# Allow DnD from the desktop
self.listView.activateDnD()
@ -62,6 +65,8 @@ class ImageMediaItem(MediaManagerItem):
'Select Image(s)')
file_formats = get_images_filter()
self.onNewFileMasks = u'%s;;%s (*.*) (*)' % (file_formats, UiStrings().AllFiles)
self.addGroupAction.setText(UiStrings().AddGroup)
self.addGroupAction.setToolTip(UiStrings().AddGroup)
self.replaceAction.setText(UiStrings().ReplaceBG)
self.replaceAction.setToolTip(UiStrings().ReplaceLiveBG)
self.resetAction.setText(UiStrings().ResetBG)
@ -78,6 +83,7 @@ class ImageMediaItem(MediaManagerItem):
log.debug(u'initialise')
self.listView.clear()
self.listView.setIconSize(QtCore.QSize(88, 50))
self.listView.setIndentation(self.listView.defaultIndentation)
self.servicePath = os.path.join(AppLocation.get_section_data_path(self.settingsSection), u'thumbnails')
check_directory_exists(self.servicePath)
# Import old images list
@ -92,12 +98,16 @@ class ImageMediaItem(MediaManagerItem):
Settings().remove(self.settingsSection + u'/images files')
Settings().remove(self.settingsSection + u'/images count')
# Load images from the database
self.loadList(self.manager.get_all_objects(ImageFilenames, order_by_ref=ImageFilenames.filename))
self.loadFullList(self.manager.get_all_objects(ImageFilenames, order_by_ref=ImageFilenames.filename), True)
def addListViewToToolBar(self):
MediaManagerItem.addListViewToToolBar(self)
self.listView.addAction(self.replaceAction)
def addStartHeaderBar(self):
self.addGroupAction = self.toolbar.addToolbarAction(u'addGroupAction',
icon=u':/images/image_new_group.png', triggers=self.onAddGroupClick)
def addEndHeaderBar(self):
self.replaceAction = self.toolbar.addToolbarAction(u'replaceAction',
icon=u':/slides/slide_blank.png', triggers=self.onReplaceClick)
@ -111,15 +121,15 @@ class ImageMediaItem(MediaManagerItem):
# Turn off auto preview triggers.
self.listView.blockSignals(True)
if check_item_selected(self.listView, translate('ImagePlugin.MediaItem','You must select an image to delete.')):
row_list = [item.row() for item in self.listView.selectedIndexes()]
row_list.sort(reverse=True)
item_list = self.listView.selectedItems()
Receiver.send_message(u'cursor_busy')
self.main_window.displayProgressBar(len(row_list))
for row in row_list:
self.plugin.formParent.displayProgressBar(len(item_list))
for row_item in item_list:
row_item = self.listView.topLevelItem(row)
if row_item:
delete_file(os.path.join(self.servicePath, row_item.text(0)))
self.listView.takeTopLevelItem(row)
row_item.parent().removeChild(row_item)
self.main_window.incrementProgressBar()
self.manager.delete_object(ImageFilenames, row_item.data(0, QtCore.Qt.UserRole).id)
SettingsManager.setValue(self.settingsSection + u'/images files', self.getFileList())
@ -127,20 +137,51 @@ class ImageMediaItem(MediaManagerItem):
Receiver.send_message(u'cursor_normal')
self.listView.blockSignals(False)
def loadList(self, images, initialLoad=False):
def addSubGroups(self, groupList, parentGroupId):
"""
Recursively add subgroups to the given parent group
"""
image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == parentGroupId)
image_groups.sort(cmp=locale_compare, key=lambda group_object: group_object.group_name)
for image_group in image_groups:
group = QtGui.QTreeWidgetItem()
group.setText(0, image_group.group_name)
if parentGroupId is 0:
self.listView.addTopLevelItem(group)
else:
groupList[parentGroupId].addChild(group)
groupList[image_group.id] = group
self.addSubGroups(groupList, image_group.id)
def fillGroupsComboBox(self, parentGroupId=0, prefix=''):
"""
Recursively add groups to the combobox in the 'Add group' dialog
"""
if parentGroupId is 0:
self.addgroupform.parentGroupComboBox.clear()
self.addgroupform.parentGroupComboBox.addItem(translate('ImagePlugin.MediaItem', '-- Top-level group --'), 0)
image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == parentGroupId)
image_groups.sort(cmp=locale_compare, key=lambda group_object: group_object.group_name)
for image_group in image_groups:
self.addgroupform.parentGroupComboBox.addItem(prefix+image_group.group_name, image_group.id)
self.fillGroupsComboBox(image_group.id, prefix+' ')
def loadFullList(self, images, initialLoad=False):
"""
Replace the list of images and groups in the interface.
"""
if not initialLoad:
Receiver.send_message(u'cursor_busy')
self.main_window.displayProgressBar(len(images))
self.listView.clear()
# Load the list of groups and add them to the treeView
group_items = {}
self.addSubGroups(group_items, 0)
# Sort the images by its filename considering language specific
# characters.
images.sort(cmp=locale_compare, key=lambda filename: os.path.split(unicode(filename))[1])
images.sort(cmp=locale_compare, key=lambda image_object: os.path.split(unicode(image_object.filename))[1])
for imageFile in images:
if type(imageFile) is str or type(imageFile) is unicode:
filename = imageFile
imageFile = ImageFilenames()
imageFile.group_id = 0
imageFile.filename = unicode(filename)
success = self.manager.save_object(imageFile)
log.debug(u'Loading image: %s', imageFile.filename)
filename = os.path.split(imageFile.filename)[1]
thumb = os.path.join(self.servicePath, filename)
if not os.path.exists(imageFile.filename):
@ -150,19 +191,40 @@ class ImageMediaItem(MediaManagerItem):
icon = build_icon(thumb)
else:
icon = create_thumb(imageFile.filename, thumb)
log.debug(u'Loading image: %s', imageFile.filename)
item_name = QtGui.QTreeWidgetItem(filename)
item_name.setText(0, filename)
item_name.setIcon(0, icon)
item_name.setToolTip(0, imageFile.filename)
item_name.setData(0, QtCore.Qt.UserRole, imageFile)
self.listView.addTopLevelItem(item_name)
if imageFile.group_id is 0:
if 0 not in group_items:
# The 'Imported' group is only displayed when there are files that were imported from the
# configuration file
imported_group = QtGui.QTreeWidgetItem()
imported_group.setText(0, translate('ImagePlugin.MediaItem', 'Imported'))
self.listView.insertTopLevelItem(0, imported_group)
group_items[0] = imported_group
group_items[imageFile.group_id].addChild(item_name)
if not initialLoad:
self.main_window.incrementProgressBar()
if not initialLoad:
self.main_window.finishedProgressBar()
Receiver.send_message(u'cursor_normal')
def loadList(self, images, initialLoad=False):
"""
Add new images to the database. This method is called when adding images using the Add button or DnD.
"""
for filename in images:
if filename is None:
continue
imageFile = ImageFilenames()
imageFile.group_id = 0
imageFile.filename = unicode(filename)
success = self.manager.save_object(imageFile)
self.loadFullList(self.manager.get_all_objects(ImageFilenames, order_by_ref=ImageFilenames.filename),
initialLoad)
def generateSlideData(self, service_item, item=None, xmlVersion=False,
remote=False, context=ServiceItemContext.Service):
background = QtGui.QColor(Settings().value(self.settingsSection + u'/background color'))
@ -182,6 +244,9 @@ class ImageMediaItem(MediaManagerItem):
missing_items = []
missing_items_filenames = []
for bitem in items:
if bitem.data(0, QtCore.Qt.UserRole) is None:
# Ignore double-clicked groups
continue
filename = bitem.data(0, QtCore.Qt.UserRole).filename
if not os.path.exists(filename):
missing_items.append(bitem)
@ -205,11 +270,60 @@ class ImageMediaItem(MediaManagerItem):
return False
# Continue with the existing images.
for bitem in items:
if bitem.data(0, QtCore.Qt.UserRole) is None:
# Ignore double-clicked groups
continue
filename = bitem.data(0, QtCore.Qt.UserRole).filename
name = os.path.split(filename)[1]
service_item.add_from_image(filename, name, background)
return True
def __checkObject(self, objects, newObject, edit):
"""
Utility method to check for an existing object.
``edit``
If we edit an item, this should be *True*.
"""
if objects:
# If we edit an existing object, we need to make sure that we do
# not return False when nothing has changed.
if edit:
for object in objects:
if object.id != newObject.id:
return False
return True
else:
return False
else:
return True
def checkGroupName(self, newGroup, edit=False):
"""
Returns *False* if the given Group already exists, otherwise *True*.
"""
groups = self.manager.get_all_objects(ImageGroups, ImageGroups.group_name == newGroup.group_name)
return self.__checkObject(groups, newGroup, edit)
def onAddGroupClick(self):
"""
Called to add a new group
"""
if self.addgroupform.exec_():
new_group = ImageGroups.populate(parent_id=self.addgroupform.parentGroupComboBox.itemData(
self.addgroupform.parentGroupComboBox.currentIndex(), QtCore.Qt.UserRole),
group_name=self.addgroupform.nameEdit.text())
if self.checkGroupName(new_group):
if self.manager.save_object(new_group):
self.loadList([])
self.fillGroupsComboBox()
else:
critical_error_message_box(
message=translate('ImagePlugin.AddGroupForm', 'Could not add the new group.'))
else:
critical_error_message_box(
message=translate('ImagePlugin.AddGroupForm', 'This group already exists.'))
def onResetClick(self):
"""
Called to reset the Live backgound with the image selected,
@ -230,9 +344,8 @@ class ImageMediaItem(MediaManagerItem):
if check_item_selected(self.listView,
translate('ImagePlugin.MediaItem', 'You must select an image to replace the background with.')):
background = QtGui.QColor(Settings().value(self.settingsSection + u'/background color'))
item = self.listView.selectedIndexes()[0]
bitem = self.listView.topLevelItem(item.row())
filename = bitem.data(QtCore.Qt.UserRole).filename
bitem = self.listView.selectedItems()[0]
filename = bitem.data(0, QtCore.Qt.UserRole).filename
if os.path.exists(filename):
if self.plugin.liveController.display.directImage(filename, background):
self.resetAction.setVisible(True)

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddGroupDialog</class>
<widget class="QDialog" name="AddGroupDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>365</width>
<height>119</height>
</rect>
</property>
<property name="windowTitle">
<string>Add group</string>
</property>
<layout class="QFormLayout" name="AddGroupLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="horizontalSpacing">
<number>8</number>
</property>
<property name="verticalSpacing">
<number>8</number>
</property>
<property name="margin">
<number>8</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="ParentGroupLabel">
<property name="text">
<string>Parent group:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="ParentGroupComboBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="GroupNameLabel">
<property name="text">
<string>Group name:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="GroupNameEdit"/>
</item>
<item row="3" column="1">
<widget class="QDialogButtonBox" name="GroupButtonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../images/openlp-2.qrc"/>
</resources>
<connections/>
</ui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

View File

@ -21,6 +21,9 @@
<file>song_topic_edit.png</file>
<file>song_book_edit.png</file>
</qresource>
<qresource prefix="images">
<file>image_new_group.png</file>
</qresource>
<qresource prefix="bibles">
<file>bibles_search_text.png</file>
<file>bibles_search_reference.png</file>