From 7badfb650fa018591903cfd49f598d2e9faaeeb6 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 7 Mar 2009 09:20:26 +0000 Subject: [PATCH] Initial Release of Custom plugin. All bits present but does not work! bzr-revno: 389 --- openlp/plugins/custom/__init__.py | 17 ++ openlp/plugins/custom/customplugin.py | 56 +++++ openlp/plugins/custom/forms/__init__.py | 23 ++ .../plugins/custom/forms/editcustomdialog.py | 106 +++++++++ openlp/plugins/custom/forms/editcustomform.py | 156 +++++++++++++ openlp/plugins/custom/lib/__init__.py | 26 +++ openlp/plugins/custom/lib/classes.py | 40 ++++ openlp/plugins/custom/lib/custommediaitem.py | 206 ++++++++++++++++++ openlp/plugins/custom/lib/manager.py | 144 ++++++++++++ openlp/plugins/custom/lib/meta.py | 33 +++ openlp/plugins/custom/lib/models.py | 33 +++ openlp/plugins/custom/lib/tables.py | 31 +++ resources/forms/editcustomdialog.ui | 166 ++++++++++++++ 13 files changed, 1037 insertions(+) create mode 100644 openlp/plugins/custom/__init__.py create mode 100644 openlp/plugins/custom/customplugin.py create mode 100644 openlp/plugins/custom/forms/__init__.py create mode 100644 openlp/plugins/custom/forms/editcustomdialog.py create mode 100644 openlp/plugins/custom/forms/editcustomform.py create mode 100644 openlp/plugins/custom/lib/__init__.py create mode 100644 openlp/plugins/custom/lib/classes.py create mode 100644 openlp/plugins/custom/lib/custommediaitem.py create mode 100644 openlp/plugins/custom/lib/manager.py create mode 100644 openlp/plugins/custom/lib/meta.py create mode 100644 openlp/plugins/custom/lib/models.py create mode 100644 openlp/plugins/custom/lib/tables.py create mode 100644 resources/forms/editcustomdialog.ui diff --git a/openlp/plugins/custom/__init__.py b/openlp/plugins/custom/__init__.py new file mode 100644 index 000000000..5bab2c955 --- /dev/null +++ b/openlp/plugins/custom/__init__.py @@ -0,0 +1,17 @@ +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley, Carsten Tinggaard + +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 +""" diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py new file mode 100644 index 000000000..b2ae40213 --- /dev/null +++ b/openlp/plugins/custom/customplugin.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008 Martin Thompson, Tim Bentley, + +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 +""" +import logging + +from PyQt4 import QtCore, QtGui + +from openlp.core.resources import * +from openlp.core.lib import Plugin, PluginUtils, MediaManagerItem +from forms import EditCustomForm +from openlp.plugins.custom.lib import CustomManager, CustomTab, CustomMediaItem + +class CustomPlugin(Plugin, PluginUtils): + + global log + log=logging.getLogger("CustomPlugin") + log.info("Custom Plugin loaded") + + def __init__(self): + # Call the parent constructor + Plugin.__init__(self, 'Custom', '1.9.0') + self.weight = -5 + self.custommanager = CustomManager(self.config) + self.edit_custom_form = EditCustomForm(self.custommanager) + # Create the plugin icon + self.icon = QtGui.QIcon() + self.icon.addPixmap(QtGui.QPixmap(':/media/media_custom.png'), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + + def get_media_manager_item(self): + # Create the MediaManagerItem object + self.media_item = CustomMediaItem(self, self.icon, 'Custom Slides') + return self.media_item + + def get_settings_tab(self): + pass + + def initialise(self): + pass + diff --git a/openlp/plugins/custom/forms/__init__.py b/openlp/plugins/custom/forms/__init__.py new file mode 100644 index 000000000..bff19d91b --- /dev/null +++ b/openlp/plugins/custom/forms/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley, + +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 editcustomform import EditCustomForm + +__all__ = ['EditCustomForm'] diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py new file mode 100644 index 000000000..6fb1ae6aa --- /dev/null +++ b/openlp/plugins/custom/forms/editcustomdialog.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'editcustomdialog.ui' +# +# Created: Sat Mar 7 09:01:43 2009 +# by: PyQt4 UI code generator 4.4.4 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +class Ui_customEditDialog(object): + def setupUi(self, customEditDialog): + customEditDialog.setObjectName("customEditDialog") + customEditDialog.resize(590, 541) + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(":/icon/openlp.org-icon-32.bmp"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + customEditDialog.setWindowIcon(icon) + self.verticalLayout = QtGui.QVBoxLayout(customEditDialog) + self.verticalLayout.setObjectName("verticalLayout") + self.horizontalLayout = QtGui.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.TitleLabel = QtGui.QLabel(customEditDialog) + self.TitleLabel.setObjectName("TitleLabel") + self.horizontalLayout.addWidget(self.TitleLabel) + self.TitleEdit = QtGui.QLineEdit(customEditDialog) + self.TitleEdit.setObjectName("TitleEdit") + self.horizontalLayout.addWidget(self.TitleEdit) + self.verticalLayout.addLayout(self.horizontalLayout) + self.VerseListView = QtGui.QListWidget(customEditDialog) + self.VerseListView.setObjectName("VerseListView") + self.verticalLayout.addWidget(self.VerseListView) + self.EditWidget = QtGui.QWidget(customEditDialog) + self.EditWidget.setObjectName("EditWidget") + self.EditLayout_3 = QtGui.QHBoxLayout(self.EditWidget) + self.EditLayout_3.setSpacing(8) + self.EditLayout_3.setMargin(0) + self.EditLayout_3.setObjectName("EditLayout_3") + self.VerseTextEdit_3 = QtGui.QTextEdit(self.EditWidget) + self.VerseTextEdit_3.setObjectName("VerseTextEdit_3") + self.EditLayout_3.addWidget(self.VerseTextEdit_3) + self.ButtonWidge = QtGui.QWidget(self.EditWidget) + self.ButtonWidge.setObjectName("ButtonWidge") + self.ButtonLayout_3 = QtGui.QVBoxLayout(self.ButtonWidge) + self.ButtonLayout_3.setSpacing(8) + self.ButtonLayout_3.setMargin(0) + self.ButtonLayout_3.setObjectName("ButtonLayout_3") + self.AddButton_3 = QtGui.QPushButton(self.ButtonWidge) + self.AddButton_3.setObjectName("AddButton_3") + self.ButtonLayout_3.addWidget(self.AddButton_3) + self.EditButton_3 = QtGui.QPushButton(self.ButtonWidge) + self.EditButton_3.setObjectName("EditButton_3") + self.ButtonLayout_3.addWidget(self.EditButton_3) + self.SaveButton_3 = QtGui.QPushButton(self.ButtonWidge) + self.SaveButton_3.setObjectName("SaveButton_3") + self.ButtonLayout_3.addWidget(self.SaveButton_3) + self.DeleteButton = QtGui.QPushButton(self.ButtonWidge) + self.DeleteButton.setObjectName("DeleteButton") + self.ButtonLayout_3.addWidget(self.DeleteButton) + spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.ButtonLayout_3.addItem(spacerItem) + self.EditLayout_3.addWidget(self.ButtonWidge) + self.verticalLayout.addWidget(self.EditWidget) + self.horizontalLayout_3 = QtGui.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.ThemeLabel = QtGui.QLabel(customEditDialog) + self.ThemeLabel.setObjectName("ThemeLabel") + self.horizontalLayout_3.addWidget(self.ThemeLabel) + self.ThemecomboBox = QtGui.QComboBox(customEditDialog) + self.ThemecomboBox.setObjectName("ThemecomboBox") + self.horizontalLayout_3.addWidget(self.ThemecomboBox) + self.verticalLayout.addLayout(self.horizontalLayout_3) + self.horizontalLayout_2 = QtGui.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.CreditLabel = QtGui.QLabel(customEditDialog) + self.CreditLabel.setObjectName("CreditLabel") + self.horizontalLayout_2.addWidget(self.CreditLabel) + self.CreditEdit = QtGui.QLineEdit(customEditDialog) + self.CreditEdit.setObjectName("CreditEdit") + self.horizontalLayout_2.addWidget(self.CreditEdit) + self.verticalLayout.addLayout(self.horizontalLayout_2) + self.buttonBox = QtGui.QDialogButtonBox(customEditDialog) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) + self.buttonBox.setObjectName("buttonBox") + self.verticalLayout.addWidget(self.buttonBox) + + self.retranslateUi(customEditDialog) + QtCore.QMetaObject.connectSlotsByName(customEditDialog) + customEditDialog.setTabOrder(self.TitleEdit, self.VerseTextEdit_3) + customEditDialog.setTabOrder(self.VerseTextEdit_3, self.EditButton_3) + customEditDialog.setTabOrder(self.EditButton_3, self.SaveButton_3) + customEditDialog.setTabOrder(self.SaveButton_3, self.CreditEdit) + customEditDialog.setTabOrder(self.CreditEdit, self.VerseListView) + customEditDialog.setTabOrder(self.VerseListView, self.AddButton_3) + customEditDialog.setTabOrder(self.AddButton_3, self.DeleteButton) + customEditDialog.setTabOrder(self.DeleteButton, self.buttonBox) + + def retranslateUi(self, customEditDialog): + customEditDialog.setWindowTitle(QtGui.QApplication.translate("customEditDialog", "Edit Custom Slides", None, QtGui.QApplication.UnicodeUTF8)) + self.TitleLabel.setText(QtGui.QApplication.translate("customEditDialog", "Title:", None, QtGui.QApplication.UnicodeUTF8)) + self.AddButton_3.setText(QtGui.QApplication.translate("customEditDialog", "Add", None, QtGui.QApplication.UnicodeUTF8)) + self.EditButton_3.setText(QtGui.QApplication.translate("customEditDialog", "Edit", None, QtGui.QApplication.UnicodeUTF8)) + self.SaveButton_3.setText(QtGui.QApplication.translate("customEditDialog", "Save", None, QtGui.QApplication.UnicodeUTF8)) + self.DeleteButton.setText(QtGui.QApplication.translate("customEditDialog", "Delete", None, QtGui.QApplication.UnicodeUTF8)) + self.ThemeLabel.setText(QtGui.QApplication.translate("customEditDialog", "Theme:", None, QtGui.QApplication.UnicodeUTF8)) + self.CreditLabel.setText(QtGui.QApplication.translate("customEditDialog", "Credits:", None, QtGui.QApplication.UnicodeUTF8)) diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py new file mode 100644 index 000000000..111c914ef --- /dev/null +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley, + +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 Qt, QtCore, QtGui + +from editcustomdialog import Ui_customEditDialog + +class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): + """ + Class documentation goes here. + """ + def __init__(self, custommanager, parent = None): + """ + Constructor + """ + QtGui.QDialog.__init__(self, parent) + self.setupUi(self) + # Connecting signals and slots + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.rejected) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), self.accept) + QtCore.QObject.connect(self.AddButton_3, QtCore.SIGNAL("pressed()"), self.onAddButtonPressed) + QtCore.QObject.connect(self.EditButton_3, QtCore.SIGNAL("pressed()"), self.onEditButtonPressed) + QtCore.QObject.connect(self.SaveButton_3, QtCore.SIGNAL("pressed()"), self.onSaveButtonPressed) + QtCore.QObject.connect(self.DeleteButton, QtCore.SIGNAL("pressed()"), self.onDeleteButtonPressed) + # Create other objects and forms + self.custommanager = custommanager + self.initialise() + + #self.savebutton = self.ButtonBox.button(QtGui.QDialogButtonBox.Save) + + def accept(self): + pass + + def rejected(self): + self.close() + + def onAddButtonPressed(self): + pass + + def onEditButtonPressed(self): + pass + + def onSaveButtonPressed(self): + pass + + def onDeleteButtonPressed(self): + pass + + def initialise(self): + pass +# list = self.songmanager.get_authors() +# self.AuthorsSelectionComboItem.clear() +# for i in list: +# self.AuthorsSelectionComboItem.addItem( i.display_name) + + def loadSong(self, id): + pass +# self.song = self.songmanager.get_song(id) +# self.TitleEditItem.setText(self.song.title) +# self.LyricsTextEdit.setText(self.song.lyrics) +# self.CopyrightEditItem.setText(self.song.copyright) +# +# self.AuthorsListView.clear() # clear the results +# self.AuthorsListView.setHorizontalHeaderLabels(QtCore.QStringList(['', u'Author'])) +# self.AuthorsListView.setVerticalHeaderLabels(QtCore.QStringList([''])) +# self.AuthorsListView.horizontalHeader().setVisible(False) +# self.AuthorsListView.verticalHeader().setVisible(False) +# self.AuthorsListView.setRowCount(0) +# for author in self.song.authors: +# row_count = self.AuthorsListView.rowCount() +# self.AuthorsListView.setRowCount(row_count + 1) +# author_id = QtGui.QTableWidgetItem(str(author.id)) +# self.AuthorsListView.setItem(row_count, 0, author_id) +# author_name = QtGui.QTableWidgetItem(str(author.display_name)) +# self.AuthorsListView.setItem(row_count, 1, author_name) +# self.AuthorsListView.setRowHeight(row_count, 20) +# self._validate_song() + + def onAddAuthorsButtonClicked(self): + """ + Slot documentation goes here. + """ + self.authors_form.load_form() + self.authors_form.exec_() + + def onAddTopicButtonClicked(self): + """ + Slot documentation goes here. + """ + self.topics_form.load_form() + self.topics_form.exec_() + + def onAddSongBookButtonClicked(self): + """ + Slot documentation goes here. + """ + self.song_book_form.load_form() + self.song_book_form.exec_() + + def _validate_song(self): + """ + Check the validity of the form. Only display the 'save' if the data can be saved. + """ + valid = True # Lets be nice and assume the data is correct. + if len(self.TitleEditItem.displayText()) == 0: #Song title missing + valid = False + #self._color_widget(self.TitleEditItem, True) + #else: + #self._color_widget(self.TitleEditItem, False) + if len(self.CopyrightEditItem.displayText()) == 0: #Song title missing + valid = False + #self._color_widget(self.CopyrightEditItem, True) + #else: + #self._color_widget(self.CopyrightEditItem, False) + + if valid: + self.ButtonBox.addButton(self.savebutton, QtGui.QDialogButtonBox.AcceptRole) # hide the save button tile screen is valid + else: + self.ButtonBox.removeButton(self.savebutton) # hide the save button tile screen is valid + + def _color_widget(self, slot, invalid): + r = Qt.QPalette(slot.palette()) + if invalid == True: + r.setColor(Qt.QPalette.Base, Qt.QColor('darkRed')) + else: + r.setColor(Qt.QPalette.Base, Qt.QColor('white')) + slot.setPalette(r) + slot.setAutoFillBackground(True) + + def on_TitleEditItem_lostFocus(self): + #self._validate_song() + pass + + def onCopyrightInsertItemTriggered(self): + text = self.CopyrightEditItem.displayText() + pos = self.CopyrightEditItem.cursorPosition() + text = text[:pos] + u'©' + text[pos:] + self.CopyrightEditItem.setText(text) + self.CopyrightEditItem.setFocus() + self.CopyrightEditItem.setCursorPosition(pos + 1) diff --git a/openlp/plugins/custom/lib/__init__.py b/openlp/plugins/custom/lib/__init__.py new file mode 100644 index 000000000..62be8eefa --- /dev/null +++ b/openlp/plugins/custom/lib/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008 Martin Thompson, Tim Bentley + +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 manager import CustomManager +from customtab import CustomTab +from custommediaitem import CustomMediaItem + +__all__ = ['CustomManager', 'CustomTab', 'CustomMediaItem'] + diff --git a/openlp/plugins/custom/lib/classes.py b/openlp/plugins/custom/lib/classes.py new file mode 100644 index 000000000..afeac94a1 --- /dev/null +++ b/openlp/plugins/custom/lib/classes.py @@ -0,0 +1,40 @@ +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008 Martin Thompson, Tim Bentley, + +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 +""" + +class BaseModel(object): + """ + BaseModel provides a base object with a set of generic functions + """ + + @classmethod + def populate(cls, **kwargs): + """ + Creates an instance of a class and populates it, returning the instance + """ + me = cls() + keys = kwargs.keys() + for key in keys: + me.__setattr__(key, kwargs[key]) + return me + +class CustomSlide(BaseModel): + """ + Author model + """ + pass diff --git a/openlp/plugins/custom/lib/custommediaitem.py b/openlp/plugins/custom/lib/custommediaitem.py new file mode 100644 index 000000000..4454ed692 --- /dev/null +++ b/openlp/plugins/custom/lib/custommediaitem.py @@ -0,0 +1,206 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley + +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 +""" +import logging + +from PyQt4 import QtCore, QtGui + +from openlp.core import translate +from openlp.core.lib import MediaManagerItem +from openlp.core.resources import * + +from openlp.plugins.custom.lib import CustomTab + +class CustomMediaItem(MediaManagerItem): + """ + This is the custom media manager item for Custom Slides. + """ + global log + log=logging.getLogger("CustomMediaItem") + log.info("Custom Media Item loaded") + + def __init__(self, parent, icon, title): + MediaManagerItem.__init__(self, parent, icon, title) + + + def setupUi(self): + # Add a toolbar + self.addToolbar() + # Create buttons for the toolbar + ## New Custom Button ## + self.addToolbarButton('New Custom', 'Add a new Custom Item', + ':/custom/custom_new.png', self.onCustomNewClick, 'CustomNewItem') + ## Edit Custom Button ## + self.addToolbarButton('Edit Custom', 'Edit the selected Custom Item', + ':/custom/custom_edit.png', self.onCustomEditClick, 'CustomEditItem') + ## Delete Custom Button ## + self.addToolbarButton('Delete Custom', 'Delete the selected Custom Item', + ':/custom/custom_delete.png', self.onCustomDeleteClick, 'CustomDeleteItem') + ## Separator Line ## + self.addToolbarSeparator() + ## Preview Custom Button ## + self.addToolbarButton('Preview Custom', 'Preview the selected Custom', + ':/system/system_preview.png', self.onCustomPreviewClick, 'CustomPreviewItem') + ## Live Custom Button ## + self.addToolbarButton('Go Live', 'Send the selected Custom live', + ':/system/system_live.png', self.onCustomLiveClick, 'CustomLiveItem') + ## Add Custom Button ## + self.addToolbarButton('Add Custom To Service', + 'Add the selected Custom(s) to the service', ':/system/system_add.png', + self.onCustomAddClick, 'CustomAddItem') + ## Add the Customlist widget ## + # Create the tab widget + self.CustomWidget = QtGui.QWidget(self) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.CustomWidget.sizePolicy().hasHeightForWidth()) + self.CustomWidget.setSizePolicy(sizePolicy) + self.CustomWidget.setObjectName('CustomWidget') + self.SearchLayout = QtGui.QGridLayout(self.CustomWidget) + self.SearchLayout.setObjectName('SearchLayout') + self.SearchTypeComboBox = QtGui.QComboBox(self.CustomWidget) + self.SearchTypeComboBox.setObjectName('SearchTypeComboBox') + self.SearchLayout.addWidget(self.SearchTypeComboBox, 0, 1, 1, 2) + self.SearchTypeLabel = QtGui.QLabel(self.CustomWidget) + self.SearchTypeLabel.setObjectName('SearchTypeLabel') + self.SearchTypeLabel.setText('Search Type:') + self.SearchLayout.addWidget(self.SearchTypeLabel, 0, 0, 1, 1) + self.SearchTextLabel = QtGui.QLabel(self.CustomWidget) + self.SearchTextLabel.setObjectName('SearchTextLabel') + self.SearchTextLabel.setText('Search Text:') + self.SearchLayout.addWidget(self.SearchTextLabel, 2, 0, 1, 1) + self.SearchTextEdit = QtGui.QLineEdit(self.CustomWidget) + self.SearchTextEdit.setObjectName('SearchTextEdit') + self.SearchLayout.addWidget(self.SearchTextEdit, 2, 1, 1, 2) + self.ClearTextButton = QtGui.QPushButton(self.CustomWidget) + self.ClearTextButton.setObjectName('ClearTextButton') + self.ClearTextButton.setText('Clear') + self.SearchLayout.addWidget(self.ClearTextButton, 3, 1, 1, 1) + self.SearchTextButton = QtGui.QPushButton(self.CustomWidget) + self.SearchTextButton.setObjectName('SearchTextButton') + self.SearchTextButton.setText('Search') + self.SearchLayout.addWidget(self.SearchTextButton, 3, 2, 1, 1) + # Add the Custom widget to the page layout + self.PageLayout.addWidget(self.CustomWidget) + self.CustomListView = QtGui.QTableWidget() + self.CustomListView.setColumnCount(2) + self.CustomListView.setColumnHidden(0, True) + self.CustomListView.setColumnWidth(1, 240) + #self.CustomListView.setColumnWidth(2, 80) + self.CustomListView.setShowGrid(False) + self.CustomListView.setSortingEnabled(False) + self.CustomListView.setAlternatingRowColors(True) + self.CustomListView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.CustomListView.setHorizontalHeaderLabels(QtCore.QStringList(['', u'Custom Name'])) + self.CustomListView.horizontalHeader().setVisible(False) + self.CustomListView.verticalHeader().setVisible(False) + self.CustomListView.setGeometry(QtCore.QRect(10, 100, 256, 591)) + self.CustomListView.setObjectName('listView') + self.PageLayout.addWidget(self.CustomListView) + + QtCore.QObject.connect(self.SearchTextButton, QtCore.SIGNAL("pressed()"), self.onSearchTextButtonClick) + QtCore.QObject.connect(self.ClearTextButton, QtCore.SIGNAL("pressed()"), self.onClearTextButtonClick) + QtCore.QObject.connect(self.SearchTextEdit, QtCore.SIGNAL("textChanged(const QString&)"), self.onSearchTextEditChanged) + + QtCore.QObject.connect(self.CustomListView, QtCore.SIGNAL("itemPressed(QTableWidgetItem * item)"), self.onCustomSelected) + + +# #define and add the context menu +# self.CustomListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) +# +# self.CustomListView.addAction(self.add_to_context_menu(self.CustomListView, ':/Customs/Custom_new.png', "&Edit Custom", self.onCustomEditClick)) +# self.CustomListView.addAction(self.add_to_context_separator(self.CustomListView)) +# self.CustomListView.addAction(self.add_to_context_menu(self.CustomListView, ':/system/system_preview.png', "&Preview Custom", self.onCustomPreviewClick)) +# self.CustomListView.addAction(self.add_to_context_menu(self.CustomListView, ':/system/system_live.png', "&Show Live", self.onCustomLiveClick)) +# self.CustomListView.addAction(self.add_to_context_menu(self.CustomListView, ':/system/system_add.png', "&Add to Service", self.onCustomEditClick)) + + + def onClearTextButtonClick(self): + """ + Clear the search text. + """ + self.SearchTextEdit.clear() + + def onSearchTextEditChanged(self, text): + sl = 3 + if self.SearchTypeComboBox.currentText() == u'Lyrics': + sl = 7 + if len(text) > sl: # only search if > 3 characters + self.onSearchTextButtonClick() + + def onSearchTextButtonClick(self): + search_keywords = str(self.SearchTextEdit.displayText()) + search_results = [] + search_type = self.SearchTypeComboBox.currentText() + if search_type == u'Titles': + log.debug("Titles Search") + search_results = self.Custommanager.search_Custom_title(search_keywords) + elif search_type == u'Lyrics': + log.debug("Lyrics Search") + search_results = self.Custommanager.search_Custom_lyrics(search_keywords) + elif search_type == u'Authors': + log.debug("Authors Search") + #searchresults = self.Custommanager.get_Custom_from_author(searchtext) + self._display_results(search_results) + + def onCustomSelected(self, item): + print item + + def onCustomNewClick(self): + self.parent.edit_custom_form.exec_() + + def onCustomEditClick(self): + current_row = self.CustomListView.currentRow() + id = int(self.CustomListView.item(current_row, 0).text()) + self.edit_Custom_form.loadCustom(id) + self.edit_Custom_form.exec_() + + def onCustomDeleteClick(self): + pass + + def onCustomPreviewClick(self): + pass + + def onCustomLiveClick(self): + pass + + def onCustomAddClick(self): + pass + + def _display_results(self, searchresults): + log.debug("_search results") + self.CustomListView.clear() # clear the results + self.CustomListView.setHorizontalHeaderLabels(QtCore.QStringList(['', u'Custom Name'])) + self.CustomListView.horizontalHeader().setVisible(False) + self.CustomListView.verticalHeader().setVisible(False) + self.CustomListView.setRowCount(0) + #log.debug("Records returned from search %s", len(searchresults)) + for Custom in searchresults: + for author in Custom.authors: + c = self.CustomListView.rowCount() + self.CustomListView.setRowCount(c + 1) + Custom_index = QtGui.QTableWidgetItem(str(Custom.id)) + self.CustomListView.setItem(c , 0, Custom_index) + Custom_detail = QtGui.QTableWidgetItem(u'%s (%s)' % (str(Custom.title), str(author.display_name))) + self.CustomListView.setItem(c , 1, Custom_detail) + #twi = QtGui.QTableWidgetItem() + #self.CustomListView.setItem(c , 2, twi) + self.CustomListView.setRowHeight(c, 20) + diff --git a/openlp/plugins/custom/lib/manager.py b/openlp/plugins/custom/lib/manager.py new file mode 100644 index 000000000..0c318740c --- /dev/null +++ b/openlp/plugins/custom/lib/manager.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008 Martin Thompson, Tim Bentley + +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 +""" + +import os, os.path +import sys + +from sqlalchemy import asc, desc +from openlp.plugins.custom.lib.models import init_models, metadata, session, \ + engine, CustomSlide, custom_slide_table + +import logging + +class CustomManager(): + """ + The Song Manager provides a central location for all database code. This + class takes care of connecting to the database and running all the queries. + """ + + global log + log=logging.getLogger('CustomManager') + log.info('Custom manager loaded') + + def __init__(self, config): + """ + Creates the connection to the database, and creates the tables if they + don't exist. + """ + self.config = config + log.debug('Custom Initialising') + self.db_url = u'' + db_type = self.config.get_config(u'db type') + if db_type == u'sqlite': + self.db_url = u'sqlite:///' + self.config.get_data_path() + \ + u'/custom.sqlite' + else: + self.db_url = db_type + 'u://' + \ + self.config.get_config(u'db username') + u':' + \ + self.config.get_config(u'db password') + u'@' + \ + self.config.get_config(u'db hostname') + u'/' + \ + self.config.get_config(u'db database') + self.session = init_models(self.db_url) + if not custom_slide_table.exists(): + metadata.create_all() + log.debug('Custom Initialised') +# +# def process_dialog(self, dialogobject): +# self.dialogobject = dialogobject +# +# def get_songs(self): +# """ +# Returns the details of a song +# """ +# return self.session.query(Song).order_by(title).all() +# +# def search_song_title(self, keywords): +# """ +# Searches the song title for keywords. +# """ +# return self.session.query(Song).filter(Song.search_title.like(u'%' + keywords + u'%')).order_by(Song.search_title.asc()).all() +# +# def search_song_lyrics(self, keywords): +# """ +# Searches the song lyrics for keywords. +# """ +# return self.session.query(Song).filter(Song.search_lyrics.like(u'%' + keywords + u'%')).order_by(Song.search_lyrics.asc()).all() +# +# def get_song(self, id=None): +# """ +# Returns the details of a song +# """ +# if id is None: +# return Song() +# else: +# return self.session.query(Song).get(id) +# +# def save_song(self, song): +# """ +# Saves a song to the database +# """ +# try: +# self.session.add(song) +# self.session.commit() +# return True +# except: +# return False +# +# def delete_song(self, song): +# try: +# self.session.delete(song) +# self.session.commit() +# return True +# except: +# return False +# +# def get_authors(self): +# """ +# Returns a list of all the authors +# """ +# return self.session.query(Author).order_by(Author.display_name).all() +# +# def get_author(self, id): +# """ +# Details of the Author +# """ +# return self.session.query(Author).get(id) +# +# def save_author(self, author): +# """ +# Save the Author and refresh the cache +# """ +# try: +# self.session.add(author) +# self.session.commit() +# return True +# except: +# return False +# +# def delete_author(self, authorid): +# """ +# Delete the author and refresh the author cache +# """ +# try: +# self.session.delete(author) +# self.session.commit() +# return True +# except: +# return False diff --git a/openlp/plugins/custom/lib/meta.py b/openlp/plugins/custom/lib/meta.py new file mode 100644 index 000000000..b3f02791b --- /dev/null +++ b/openlp/plugins/custom/lib/meta.py @@ -0,0 +1,33 @@ +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008 Martin Thompson, Tim Bentley, + +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 sqlalchemy import MetaData +from sqlalchemy.orm import scoped_session, sessionmaker + +__all__ = ['session', 'metadata', 'engine'] + +# SQLAlchemy database engine. Updated by model.init_model() +engine = None + +# SQLAlchemy session manager. Updated by model.init_model() +session = None + +# Global metadata. If you have multiple databases with overlapping table +# names, you'll need a metadata for each database +metadata = MetaData() diff --git a/openlp/plugins/custom/lib/models.py b/openlp/plugins/custom/lib/models.py new file mode 100644 index 000000000..a167a0839 --- /dev/null +++ b/openlp/plugins/custom/lib/models.py @@ -0,0 +1,33 @@ +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008 Martin Thompson, Tim Bentley, + +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 sqlalchemy import create_engine +from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation + +from openlp.plugins.custom.lib.meta import session, metadata, engine +from openlp.plugins.custom.lib.tables import * +from openlp.plugins.custom.lib.classes import * + +def init_models(url): + engine = create_engine(url) + metadata.bind = engine + session = scoped_session(sessionmaker(autoflush=True, autocommit=False, + bind=engine)) + mapper(CustomSlide, custom_slide_table) + return session diff --git a/openlp/plugins/custom/lib/tables.py b/openlp/plugins/custom/lib/tables.py new file mode 100644 index 000000000..1ff4cd76f --- /dev/null +++ b/openlp/plugins/custom/lib/tables.py @@ -0,0 +1,31 @@ +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008 Martin Thompson, Tim Bentley, + +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 sqlalchemy import Column, Table, ForeignKey, types + +from openlp.plugins.custom.lib.meta import metadata + +# Definition of the "songs" table +custom_slide_table = Table('custom_slide', metadata, + Column('id', types.Integer(), primary_key=True), + Column('title', types.Unicode(255), nullable=False), + Column('text', types.UnicodeText, nullable=False), + Column('credits', types.UnicodeText), + Column('theme_name', types.Unicode(128)) +) diff --git a/resources/forms/editcustomdialog.ui b/resources/forms/editcustomdialog.ui new file mode 100644 index 000000000..2bfabd56b --- /dev/null +++ b/resources/forms/editcustomdialog.ui @@ -0,0 +1,166 @@ + + + customEditDialog + + + + 0 + 0 + 590 + 541 + + + + Edit Custom Slides + + + + :/icon/openlp.org-icon-32.bmp:/icon/openlp.org-icon-32.bmp + + + + + + + + Title: + + + + + + + + + + + + + + + + 8 + + + 0 + + + + + + + + + 8 + + + 0 + + + + + Add + + + + + + + Edit + + + + + + + Save + + + + + + + Delete + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + Theme: + + + + + + + + + + + + + + Credits: + + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + TitleEdit + VerseTextEdit_3 + EditButton_3 + SaveButton_3 + CreditEdit + VerseListView + AddButton_3 + DeleteButton + buttonBox + + + + + + + accept() + rejected() + onAddButtonPressed() + onDeleteButtonPressed() + onSaveButtonPressed() + onEditButtonPressed() + +