From 39820d768bf8248977887b0e1d3ea52481e70d55 Mon Sep 17 00:00:00 2001 From: Erik Lundin Date: Thu, 20 Sep 2012 23:50:23 +0200 Subject: [PATCH 01/38] Fixed bug #1053654 'Adding verses from multiple chapters fails'. Fixes: https://launchpad.net/bugs/1053654 --- openlp/plugins/bibles/lib/__init__.py | 33 ++---------------- openlp/plugins/bibles/lib/db.py | 48 +++++++++++++++++++++++++++ openlp/plugins/bibles/lib/manager.py | 6 ++-- 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py index 73e5ebe8b..97e4ce72e 100644 --- a/openlp/plugins/bibles/lib/__init__.py +++ b/openlp/plugins/bibles/lib/__init__.py @@ -355,37 +355,8 @@ def parse_reference(reference, bible, language_selection, book_ref_id=False): log.debug(u'Matched reference %s' % reference) book = match.group(u'book') if not book_ref_id: - book_names = BibleStrings().BookNames - # escape reserved characters - book_escaped = book - for character in u'\\.^$*+?{}[]()': - book_escaped = book_escaped.replace( - character, u'\\' + character) - regex_book = re.compile(u'\s*%s\s*' % u'\s*'.join( - book_escaped.split()), re.UNICODE | re.IGNORECASE) - if language_selection == LanguageSelection.Bible: - db_book = bible.get_book(book) - if db_book: - book_ref_id = db_book.book_reference_id - elif language_selection == LanguageSelection.Application: - books = filter(lambda key: - regex_book.match(unicode(book_names[key])), book_names.keys()) - books = filter(None, map(BiblesResourcesDB.get_book, books)) - for value in books: - if bible.get_book_by_book_ref_id(value[u'id']): - book_ref_id = value[u'id'] - break - elif language_selection == LanguageSelection.English: - books = BiblesResourcesDB.get_books_like(book) - if books: - book_list = filter( - lambda value: regex_book.match(value[u'name']), books) - if not book_list: - book_list = books - for value in book_list: - if bible.get_book_by_book_ref_id(value[u'id']): - book_ref_id = value[u'id'] - break + book_ref_id = bible.get_book_ref_id_by_localised_name( + book, language_selection) elif not bible.get_book_by_book_ref_id(book_ref_id): book_ref_id = False ranges = match.group(u'ranges') diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index acf7cf461..86f209dc7 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -29,6 +29,7 @@ import chardet import logging import os +import re import sqlite3 from PyQt4 import QtCore @@ -352,6 +353,53 @@ class BibleDB(QtCore.QObject, Manager): book, book_id, language_id) return book_id + def get_book_ref_id_by_localised_name(self, book, + language_selection): + """ + Return the id of a named book. + + ``book`` + The name of the book, according to the selected language. + + ``language_selection`` + The language selection the user has chosen in the settings + section of the Bible. + """ + log.debug(u'get_book_ref_id_by_localised_name("%s", "%s")', + book, language_selection) + from openlp.plugins.bibles.lib import LanguageSelection, \ + BibleStrings + book_names = BibleStrings().BookNames + # escape reserved characters + book_escaped = book + for character in u'\\.^$*+?{}[]()': + book_escaped = book_escaped.replace( + character, u'\\' + character) + regex_book = re.compile(u'\s*%s\s*' % u'\s*'.join( + book_escaped.split()), re.UNICODE | re.IGNORECASE) + if language_selection == LanguageSelection.Bible: + db_book = self.get_book(book) + if db_book: + return db_book.book_reference_id + elif language_selection == LanguageSelection.Application: + books = filter(lambda key: + regex_book.match(unicode(book_names[key])), book_names.keys()) + books = filter(None, map(BiblesResourcesDB.get_book, books)) + for value in books: + if self.get_book_by_book_ref_id(value[u'id']): + return value[u'id'] + elif language_selection == LanguageSelection.English: + books = BiblesResourcesDB.get_books_like(book) + if books: + book_list = filter( + lambda value: regex_book.match(value[u'name']), books) + if not book_list: + book_list = books + for value in book_list: + if self.get_book_by_book_ref_id(value[u'id']): + return value[u'id'] + return False + def get_verses(self, reference_list, show_error=True): """ This is probably the most used function. It retrieves the list of diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 66e0d93bc..4ca5e8a8c 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -277,8 +277,10 @@ class BibleManager(object): """ log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)', bible, book, chapter) - db_book = self.db_cache[bible].get_book(book) - book_ref_id = db_book.book_reference_id + language_selection = self.get_language_selection(bible) + book_ref_id = self.db_cache[bible]. \ + get_book_ref_id_by_localised_name( + book, language_selection) return self.db_cache[bible].get_verse_count(book_ref_id, chapter) def get_verse_count_by_book_ref_id(self, bible, book_ref_id, chapter): From 93d5785b4c8f569fdbc1a32faa5b3acf020d9610 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Tue, 25 Sep 2012 21:15:56 +0100 Subject: [PATCH 02/38] Fixes: Bug #876211 (OpenLyrics export non-compliant for split verses Edit) Fixes: Bug #904690 (cloning a song does not retain splits Edit) Comment added to claifry line 28 --- openlp/plugins/songs/lib/xml.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 72f0ccd7a..55e9a0706 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -260,7 +260,7 @@ class OpenLyrics(object): IMPLEMENTED_VERSION = u'0.8' START_TAGS_REGEX = re.compile(r'\{(\w+)\}') END_TAGS_REGEX = re.compile(r'\{\/(\w+)\}') - VERSE_NUMBER_REGEX = re.compile(u'[a-zA-Z]*') + VERSE_TAG_SPLITTER = re.compile(u'([a-zA-Z]+)([0-9]*)([a-zA-Z]?)') def __init__(self, manager): self.manager = manager @@ -325,10 +325,22 @@ class OpenLyrics(object): # Process the song's lyrics. lyrics = etree.SubElement(song_xml, u'lyrics') verse_list = sxml.get_verses(song.lyrics) + # Add a suffix letter to each verse + verse_tags = [] for verse in verse_list: verse_tag = verse[0][u'type'][0].lower() verse_number = verse[0][u'label'] verse_def = verse_tag + verse_number + verse_tags.append(verse_def) + # Create the letter from the number of duplicates + verse[0][u'suffix'] = chr(96 + verse_tags.count(verse_def)) + # If the verse tag is a duplicate use the suffix letter + for verse in verse_list: + verse_tag = verse[0][u'type'][0].lower() + verse_number = verse[0][u'label'] + verse_def = verse_tag + verse_number + if verse_tags.count(verse_def) > 1: + verse_def += verse[0][u'suffix'] verse_element = \ self._add_text_to_element(u'verse', lyrics, None, verse_def) if u'lang' in verse[0]: @@ -742,11 +754,10 @@ class OpenLyrics(object): if lines.get(u'break') is not None: text += u'\n[---]' verse_def = verse.get(u'name', u' ').lower() - if verse_def[0] in VerseType.Tags: - verse_tag = verse_def[0] - else: + verse_tag, verse_number, verse_part = \ + OpenLyrics.VERSE_TAG_SPLITTER.search(verse_def).groups() + if verse_tag not in VerseType.Tags: verse_tag = VerseType.Tags[VerseType.Other] - verse_number = OpenLyrics.VERSE_NUMBER_REGEX.sub(u'', verse_def) # OpenLyrics allows e. g. "c", but we need "c1". However, this does # not correct the verse order. if not verse_number: @@ -757,13 +768,13 @@ class OpenLyrics(object): if song_xml.get(u'modifiedIn') in (u'1.9.6', u'OpenLP 1.9.6') and \ song_xml.get(u'version') == u'0.7' and \ (verse_tag, verse_number, lang) in verses: - verses[(verse_tag, verse_number, lang)] += u'\n[---]\n' + text + verses[(verse_tag, verse_number, lang, None)] += u'\n[---]\n' + text # Merge v1a, v1b, .... to v1. - elif (verse_tag, verse_number, lang) in verses: + elif (verse_tag, verse_number, lang, verse_part) in verses: verses[(verse_tag, verse_number, lang)] += u'\n' + text else: - verses[(verse_tag, verse_number, lang)] = text - verse_def_list.append((verse_tag, verse_number, lang)) + verses[(verse_tag, verse_number, lang, verse_part)] = text + verse_def_list.append((verse_tag, verse_number, lang, verse_part)) # We have to use a list to keep the order, as dicts are not sorted. for verse in verse_def_list: sxml.add_verse_to_lyrics( From 0674549168d16c2c127a092a53876bef46bcae73 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Wed, 3 Oct 2012 20:54:00 +0100 Subject: [PATCH 03/38] fixed alert dialog's icon --- openlp/plugins/alerts/forms/alertdialog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py index df4209e9d..09c098cf4 100644 --- a/openlp/plugins/alerts/forms/alertdialog.py +++ b/openlp/plugins/alerts/forms/alertdialog.py @@ -35,7 +35,7 @@ class Ui_AlertDialog(object): def setupUi(self, alertDialog): alertDialog.setObjectName(u'alertDialog') alertDialog.resize(400, 300) - alertDialog.setWindowIcon(build_icon(u':/icon/openlp.org-icon-32.bmp')) + alertDialog.setWindowIcon(build_icon(u':/icon/openlp-logo-16x16.png')) self.alertDialogLayout = QtGui.QGridLayout(alertDialog) self.alertDialogLayout.setObjectName(u'alertDialogLayout') self.alertTextLayout = QtGui.QFormLayout() From 17217062f4c594553e591bd95f7763488e383a6b Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Thu, 4 Oct 2012 19:18:24 +0100 Subject: [PATCH 04/38] Removed openlp.org-icon-32.bmp from resources. Found annother instance of the icon being used and corrected it. --- openlp/plugins/custom/forms/editcustomdialog.py | 2 +- resources/images/openlp.org-icon-32.bmp | Bin 10854 -> 0 bytes 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 resources/images/openlp.org-icon-32.bmp diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py index e29f4431a..fe20108e1 100644 --- a/openlp/plugins/custom/forms/editcustomdialog.py +++ b/openlp/plugins/custom/forms/editcustomdialog.py @@ -36,7 +36,7 @@ class Ui_CustomEditDialog(object): customEditDialog.setObjectName(u'customEditDialog') customEditDialog.resize(450, 350) customEditDialog.setWindowIcon( - build_icon(u':/icon/openlp.org-icon-32.bmp')) + build_icon(u':/icon/openlp-logo-16x16.png')) self.dialogLayout = QtGui.QVBoxLayout(customEditDialog) self.dialogLayout.setObjectName(u'dialogLayout') self.titleLayout = QtGui.QHBoxLayout() diff --git a/resources/images/openlp.org-icon-32.bmp b/resources/images/openlp.org-icon-32.bmp deleted file mode 100644 index be77f45b7508f8f40eeda40cfaa64a150b39c17b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10854 zcmdU#cTkk)zQ@m&`Td^98Fn1f{`gPK z$5(j$5TBcspa1ozWz6?K!=L}}|FECTH}KNi)|?pX{|2QpPnsMaxbe^b{RYKa>(m>~ zTvwRgRxEw3v=>WTN^=`z!q-ZBdH(pw(Cg;*VE>^t@4|=qJ-5h&&Hkp%{$|W8-YlH} z(`F_OfoAE>H^MJ$XR;&w!taX2$AY~6$I~ZI)IMGLdzohmSWCksMilu;gTD!pf?Af!KnHhEv@7=pMH8sV)$2Xrpe~$OT!NDmh zDPv<}J9g~A`&TeCkmfI=&V!t57;jnw&6|QO&@-*{6_A&9fs=RXySZfhSqcOKH8nMm zSXx@HTD5BR>ec4v=J;~UmMz)Y*?3b^Q-g1A+O%oIh7ERhcKD9!p7VqZlKFfvmJN8y z1ev$a3&X6-K6)P5XnteEdp>e`_xwa&-ksxb_3+`tp`oGf?(VnVdTV@q{K10L^ zQ&ZEYpMIK|nF+#u`}R3GIZaPbuUoh7Rm?JmIpAex_D5)CihYTEKC_a1VWliKeVs=R zW>Db+(ym;&QlU`bJ=D$0$^vsjLIS>AyLK%LfA;LzS254_yZ{dk&np)1+kz~V;aD_t zEQKz*^Sk9=UVw*IBenO;B}#iw)RnzC0oIh55VXB~`Eo9o8y6S1Y}vAji3u=o-MSU# zoI7{!#EBC{MMW!CtoVJ*s!d>kUuG7~GQUhaiyC!h4~q&~B>L*!oIoWrup1g0G&MCf zG&CSEzI1hU_3-d8GBN_cHuK@*qWyzXQ*{+h)sr@UbIqF<)fc1R!N9r5rGbJ2#MD{oX@fU z1AAtgw0hYAMgs~NVoejOOjnpqTc~ZOyZ)>OtOE;CDXkJULGN&a-jPIowSwS3kXh8= zZ`$B*)(~LIrV%$cdU;c(2?rlN`)HaGjzxWt1$>UaagfQOm>V>)Y;+FC=^{r2dQ9|> z2=vvEc!Q&VpwFFEh3&$K#pw`o7lqd$!8SIExaflO=72+%jMO>s|E|M_3x@ONM+%+fM4UxCiFTV4)<_VdF zV9n|}Uxuzw8z=!8knS+s?r@r(aJ!B$`%nY*8(;q!(b@19nvHMkZv3n6#<%spS*EvX znf|6_2Alte7;af^wDldt_}dj>#-}XzuD-ebUDF-!neAL@w(}q6-~H19+5NuNp8rFv z_pY|thkRgr;6udjz(@86KWfSss$^!2rFfJuloGxK3C^AfyI!t+Z-jjx*P$!IA=FSE zgi6S7=0mLp;^L@H+8Db77`RW=b1stD@eB*?JjZ(Dv~h2KbIW zJg0EOlMsM$V7bAT<%V0{0WIn^*|x$2-EMyuj~>A0yYTeiXP*8lp4nLkwY6-wXmzew zm!oSL)Xx~s^+5GL`4!@G`fDGJ4J}1tRm>trR9YznP&&Z2%5wl@Ki_eH?=%qUG#KTK z$fI5QqMW(Lr$MNMq^;6QO?LotC95dVtm*^9%f;>QTQ-J1X&V{W=@WpK*m$tVTt6*-+6EXEtNLE_b z0m>PQ#JP{ey5AOf492u0QCf_HU z9_uR4QOV3M1XkVo^+E$=uHM^Vj&mQ4_mm4f_@-yDz7V>*=z_&I_<$}10As$e3XU?X z;MiyGKhPzBZsYB>1I}*&FrI$!#cw$mz74y)BjO6}7Oh6!*aupH;bDQ%k))g7BPnLb z(=61xD{@sb(-EV^(h);`D>hbH?5MyKsAGxV$V8IQ?ZjJA=9*|#SuD2JykemN_A2HJ zn~Je?BSZ~4zct1Adf1iS7%L^D&b~N5L!(zR!cQMo?`Zc(CTD{twyG;hSc%A6wEFc^V}}=RjXvqU{SHeSPdX8 z^)`-jDp3=?$CGYNCi@~&ss4A8{bDT7Lj%O|@EUr4(H%=yfv5U+T0CT&49|sDo2vb6Vqco|EKCr1-bwIM%8=|ck?eCf#qVBPz*L(517XlaT0orjMW7<| zoQ1SlwkN3!SO`G%*W5H~EHwf1g(Z;bZ4__vJ!ny>$oe!)0B5%Ig5O zX3D_44cOG)YrC-)un@%FMhWb2nIF%vIW4k2g?e+GFUnjm6?WAD*54fKm2-L@!!H+V7rzK(cGlLWC zE`yVz;vhTqHBbZ3ZN@Rl&K{cQw?(b%`Qn~kR|gq3MVL2+o3%yRbj8|t$2klnyA3A04X1gHio9<(moM&_G7CJ|DWg8nDZ7Qx zZd3iHQvCpYUl{mM#Ca?Zd7K&YlO+6sID|5*ulG2<9_q5ofv((hTX1sGDZ8=@%NA3H z%>ZEdkZyS*C%`<@P7~c?xQe{47J6PShp|D1HNnQsT+5~ii;ig9Zh>P@ypufD1Gz2q zzLViI+ETHYxvL_-JC)O&8r+*2(wi32n;z1i9*PVI!v;j*gQ9SG23MZR9TM|KviQht zNz_mlKRd)xV0#HkaJZc4pq=D+6{`$McheEN>54q`#omU9)aPc7ziCc@X&%R_OyFA( zVp9@kU&?i;jC85wyVS{=Tq#plI^t8owS86S2J9%Nj-J5Jauw?4Dm zihEWaKhascn7N}!jFpRE*09HzS)<-gXN7^2MSUWRe3l=rD2{tk6idnyW{Tn<0K7#o zXc)H`y#qKJ;_2z2o{poz=5&tp1<+#OmfX6IWeaJmqTOnlLBo{EQ#=Nf-N!Qh?n(pi z!;ZA=nQrGk~Au zMWSBHTpUNr5-GF09`+c5dU0F8RUy&jD6rEkPB2HX1_q6-7Y9U{pKfi4Np*~SeS|p% ztw-QEoaTus8_)8e$_{!U3;Crq64+0x1pt20kWAV$Xu2ed9_eJS3g*tDEUX2(88SGi z7qmY~!;xQdxRh2F`MfaZd10)gSU}1X0Zgh>XUY;YJPi1df!PeW*Z>%`xYFRZAfa3L z0zD=?uiz}J;TQq9m2X`i@7*44H<09tB{nGuoXGNjR1p4CF%KHNs7rcYn?PF9Nr#wp zW|09I&2XV&q-e6gX>re;#aT*kvqFLTvozw@Tt4zNKk7wcENDq-0(>A9Nu(x?RHu=K zjG3A=@h#&x!^3d~hm%czpw}C#lUWX$S@vgTZkON#&Il~A$^Zi#4N$i|%BDZjr6t9` zKiPd;>^GIe0qT!M+^1Cn$e?IUp`4)Yr<`P@h)h(_Ow}mv*G>+!yn^{hFiU8|Gr2tE zX*D*W|v1h??4 zaGdoeIJYGG_a(t$-@DSF=_2mq!U!sGZGr+a02ng#NsELu;~~msnj|=g(=1OQs25iq=4gY! zS1WK9bByXjZ^8#y(Hrk9PjSb@LExUu&`Bxh=Mw&t%2-8XDy_FuOo5^9ol-Jdf?~~ z*k~XaHvpq#EQeBGo!Vey+;DIfV>xui(w#Oc@_`Qz@i|dD>0$qF3>vZ*sU}F>_C;6sYVfqo`1~GKEwolNzR5TCbF}W|NLw z(pyM+3W>aIrl$a>aE{AGx*xo+72mp!{eW(K0@S7Mih#X$>A>5%=yub60wRB z0i8GiSAaQbX`uz^#s zCH(K@20xI6&Xh$Bfw?qV(UeL{#)`ni!3Vk@swwc}Ch}_sdDcU*$sof#tWXRu#SB#C z#DNwiW89F&Op1zh<&my@(pyA^%26`8Q!_JIRvd0m?`B?C*~?^o=uI@t2<(KLB!F?i zu^SlY#Y}lL>>Vu%LWY>!Ap{vyD8?p-yBGJ| zTb50IVC%&yV>U1qxLHC4M&JXi7$_wpRb-@+Ow`W|SC(=eng0RZsNopn{(zfgXRLik zj2(0D^@PJvg4x4#;+|Crpu}i#!gOOQbr>rGN}%CKjns-?+Nlq;UMMj_$ZgOvnNTRk zmt@8Phg79dhijRghP4KVJ7qL|#iYN4$ji|%8LcLF8)rtU%lJ7anlp!qb;?rz&l_OUfP=)Q2CNn4#-oXi+bK;R8#1 zmk=6-Vsc4l_JFGsQHOzzg@!=mz9O383W|-A?>3=i@~C5Gq5;fxAvck>NE=|&hEwU# z!C~gw6AFi6@{77e(ws)`X}#HZD$}MrCDi1*RTLN||Jq51jxGuS!(=dzGuZ!zxuHNJ zFPF&6B=QQWyb{TlSLZU3$!qgy>I-NZ3gu13G%cn5O~uW5sZCk2NNaX{TTVh-ZenL% zGSX9+)?1X`TPz$b%NQulkXK~MtEBR3sk}C~uUgh$n=5b3mp2v2Tk!7`%iBuj?Pc-~ nq=HGMyrYUqwY-B(Rewk0;@_cqQ+~y6{_lOgLCkOB?_T~t4=o)@ From 717cd68998c87c40b283c61d1336db2389f74acc Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 6 Oct 2012 10:21:28 +0100 Subject: [PATCH 05/38] Fix media icons --- openlp/plugins/media/lib/mediaitem.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index fe66b90d8..7e8ec6ff2 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -42,7 +42,7 @@ from openlp.core.ui.media import get_media_players, set_media_players log = logging.getLogger(__name__) -CLAPPERBOARD = QtGui.QImage(u':/media/media_video.png') +CLAPPERBOARD = QtGui.QImage(u':/media/image_clapperboard.png') #TODO: Add an appropriate Icon for DVDs, CDs, ... DVD_ICON = QtGui.QImage(u':/media/media_video.png') @@ -225,7 +225,7 @@ class MediaMediaItem(MediaManagerItem): def initialise(self): self.listView.clear() - self.listView.setIconSize(QtCore.QSize(88, 50)) + self.listView.setIconSize(QtCore.QSize(44, 25)) self.loadList(SettingsManager.load_list(self.settingsSection, u'media')) self.populateDisplayTypes() @@ -290,7 +290,7 @@ class MediaMediaItem(MediaManagerItem): key=lambda filename: os.path.split(unicode(filename))[1].lower()) for track in media: track_info = QtCore.QFileInfo(track) - if not track_info.isFile(): + if track_info.isFile(): filename = os.path.split(unicode(track))[1] item_name = QtGui.QListWidgetItem(filename) item_name.setIcon(build_icon(CLAPPERBOARD)) From 1aa51ad5c44c92e12c9934e28f30db1fa49eece0 Mon Sep 17 00:00:00 2001 From: Erik Lundin Date: Mon, 8 Oct 2012 02:47:10 +0200 Subject: [PATCH 06/38] Fixed bug #1038694 'Change in service order not reflected in stage view' Fixes: https://launchpad.net/bugs/1038694 --- openlp/plugins/remotes/html/stage.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openlp/plugins/remotes/html/stage.js b/openlp/plugins/remotes/html/stage.js index 38bd0fe01..6c5f35e1e 100644 --- a/openlp/plugins/remotes/html/stage.js +++ b/openlp/plugins/remotes/html/stage.js @@ -139,8 +139,10 @@ window.OpenLP = { "/api/poll", function (data, status) { OpenLP.updateClock(data); - if (OpenLP.currentItem != data.results.item) { + if (OpenLP.currentItem != data.results.item || + OpenLP.currentService != data.results.service) { OpenLP.currentItem = data.results.item; + OpenLP.currentService = data.results.service; OpenLP.loadSlides(); } else if (OpenLP.currentSlide != data.results.slide) { From 5d3269e9076b7d3a1b4586abe04ebb543f456ee9 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 8 Oct 2012 16:14:38 +0200 Subject: [PATCH 07/38] fixed bug 1014422 ('X11 Over ride being on by default causes gnome-shell to become unusable') Fixes: https://launchpad.net/bugs/1014422 --- openlp/core/ui/advancedtab.py | 21 +++++++++++++-------- openlp/core/ui/maindisplay.py | 9 ++++++++- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index ab8228658..67b5c1b04 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -29,12 +29,12 @@ The :mod:`advancedtab` provides an advanced settings facility. """ from datetime import datetime, timedelta - -from PyQt4 import QtCore, QtGui - import logging import os import sys + +from PyQt4 import QtCore, QtGui + from openlp.core.lib import SettingsTab, translate, build_icon, Receiver from openlp.core.lib.settings import Settings from openlp.core.lib.ui import UiStrings @@ -432,8 +432,7 @@ class AdvancedTab(SettingsTab): translate('OpenLP.AdvancedTab', 'WARNING: New data directory location contains ' 'OpenLP data files. These files WILL be replaced during a copy.')) - self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab', - 'X11')) + self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab', 'X11')) self.x11BypassCheckBox.setText(translate('OpenLP.AdvancedTab', 'Bypass X11 Window Manager')) # Slide Limits @@ -493,8 +492,14 @@ class AdvancedTab(SettingsTab): QtCore.QVariant(True)).toBool() self.serviceNameCheckBox.setChecked(default_service_enabled) self.serviceNameCheckBoxToggled(default_service_enabled) - self.x11BypassCheckBox.setChecked( - settings.value(u'x11 bypass wm', QtCore.QVariant(True)).toBool()) + # Fix for bug #1014422. + x11_bypass_default = True + if sys.platform.startswith(u'linux'): + # Default to False on Gnome. + x11_bypass_default = bool(not + os.environ.get(u'GNOME_DESKTOP_SESSION_ID')) + self.x11BypassCheckBox.setChecked(settings.value( + u'x11 bypass wm', QtCore.QVariant(x11_bypass_default)).toBool()) self.defaultColor = settings.value(u'default color', QtCore.QVariant(u'#ffffff')).toString() self.defaultFileEdit.setText(settings.value(u'default image', @@ -766,7 +771,7 @@ class AdvancedTab(SettingsTab): self.dataExists = False self.dataDirectoryCopyCheckBox.setChecked(True) self.newDataDirectoryHasFilesLabel.hide() - + def onDataDirectoryCancelButtonClicked(self): """ Cancel the data directory location change diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 306bb7511..a1cc0215d 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -31,6 +31,7 @@ and play multimedia within OpenLP. """ import cgi import logging +import os import sys from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL @@ -135,8 +136,14 @@ class MainDisplay(Display): self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') windowFlags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | \ QtCore.Qt.WindowStaysOnTopHint + # Fix for bug #1014422. + x11_bypass_default = True + if sys.platform.startswith(u'linux'): + # Default to False on Gnome. + x11_bypass_default = bool(not + os.environ.get(u'GNOME_DESKTOP_SESSION_ID')) if Settings().value(u'advanced/x11 bypass wm', - QtCore.QVariant(True)).toBool(): + QtCore.QVariant(x11_bypass_default)).toBool(): windowFlags |= QtCore.Qt.X11BypassWindowManagerHint # TODO: The following combination of windowFlags works correctly # on Mac OS X. For next OpenLP version we should test it on other From ce67e95ff7075738f57dff3d5cf31d56ff149e30 Mon Sep 17 00:00:00 2001 From: Erik Lundin Date: Mon, 8 Oct 2012 22:16:54 +0200 Subject: [PATCH 08/38] Removed unnecessary line break --- openlp/plugins/bibles/lib/manager.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 6f9a6aa07..467f7c90a 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -278,8 +278,7 @@ class BibleManager(object): log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)', bible, book, chapter) language_selection = self.get_language_selection(bible) - book_ref_id = self.db_cache[bible]. \ - get_book_ref_id_by_localised_name( + book_ref_id = self.db_cache[bible].get_book_ref_id_by_localised_name( book, language_selection) return self.db_cache[bible].get_verse_count(book_ref_id, chapter) From 51b7f7f028e0a4384a91836c34625f6ecf686f56 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 9 Oct 2012 18:37:35 +0100 Subject: [PATCH 09/38] Image files --- resources/images/media_audio.png | Bin 0 -> 1763 bytes resources/images/media_video.png | Bin 0 -> 1838 bytes resources/images/openlp-2.qrc | 4 +++- resources/images/slidecontroller_multimedia.png | Bin 0 -> 13217 bytes 4 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 resources/images/media_audio.png create mode 100644 resources/images/media_video.png create mode 100644 resources/images/slidecontroller_multimedia.png diff --git a/resources/images/media_audio.png b/resources/images/media_audio.png new file mode 100644 index 0000000000000000000000000000000000000000..f05a5bf559842cda3f3c39aafab7aa045d25920d GIT binary patch literal 1763 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 media_time.png media_stop.png - image_clapperboard.png + media_audio.png + media_video.png + slidecontroller_multimedia.png messagebox_critical.png diff --git a/resources/images/slidecontroller_multimedia.png b/resources/images/slidecontroller_multimedia.png new file mode 100644 index 0000000000000000000000000000000000000000..55f63d880b96a51cebfd1b7f90a8aba6887584c2 GIT binary patch literal 13217 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

IT%HU|*pE%nGyu%eh_lvA3%} zs%`~SF-g=(TAgXK4j{GgA%wqaT7bdFjufQ?M7RQ}p3pT-0_2)Ukkde2x&hlPKxq?| zvO$>wKcz)dW@y6)QAw7PZvkFFTrYorFQH3@OIzWqRVDbl+gpA;ZHfuYe+AXhF zW59Awjj19RYai7`H7Kjm)Mf!v@|6}4qDdyA?#|R@8c1y8D^~BP%Jd6MGOnAjCozKJ z6|G<;rZZIcu8{pL0Lih_L1Y#HZ5Tmmx9XD}VEHO*M_IM$LX#5!1-_%1q=KEnSD@+8 zIIAsT1d7z_6);est5TjLP!^&=3i37;fW+;WsrmGiQsSK+L?bBza6?8gjqQgOwuf>Ocv#Yq%0L zw>B35C0ndV>QJ>S;mKkhEatz73jk;~@NE_$eMb=C>^43)Qw4x?DcGV>a)BvtT>-2_ zJrvQ_k#z7ZD|OkegVKJ7cK6soQKs9-V*Z<643G_Q1v&&<+fp%r&RIDCk|_YxS?ggv zC&5y#fPhFX3+xWTQ|*P7>N|ujz+23=oBtPo+$4I7v8ANH13DRSdL_1B*5C{c=yMn06k7v4pw)M(9tH3e~ z@Q%JcyY@3TkllSgW6i?_xchz_`kZh8G6}^00_kqR28^8*=uXKRAz`ULzP$lhDP9n> zYOXynv;*(z+r{7P+HcqF^ghhh1vE(u;Hv%dyem=4K%^X#)DKe39R6`47K9+J0Gzd7 znHPW}MNR@>WG zEZrZAlBxs8_negsUrXXCNCb|cd1g}JX{P@BOryXd$*%WZp@ zTbpXPx4Ccs$})aai~$ZG{0!|@yKYQo^3rsVF{sjHHMVVhMQRC2KK(N})hzH7!b;_l zeR6z@Ry%ehlr}8^fB=oyfMfwhmXqCf?N)zrF|N{eJ#*ha)EESBSp>7WV}o%%raaZdNT2ZgrCKh;&WHcbKe zu0$k2W`hgh%m8-*ATq&Y14L=11kzR#$N-Z%{SQ{aZNS?13Rnct0-!Cg&zPfiP;G9J zzeTv3a2`MwmJm##4H31UdFFV&Gx%im?Aa6T+qXfVncd|E4pVOFVos}#a%>{%M1r6I z&r+%ck(l;b>6PbS!nhveuypAcxZr||9l@7ixde#nJ&?upZ`iON9Xob}6P1n6royY_2W@EPE+-OI`EGgr6Jzh6HAz8mrH2TB9pY8{%c1#k}f2-1KfV(;LdJ!N7( z|Ji2?uw~1)=s%!e(gjcz0|4$Z0D*7;nE+%n|8k7fPrwpI6AwD)br#28a{+Jz-yYd3 z3*_wE?QY@pv8ShYO5bwJEud6(l4Gt}vqk}L@&8R(02-YFzU!|0uw%y#aRC~(g|lA( zX5xpL$^uwt8L2Vl0uZqTfmYz%0zzQ{Or%r3nGc=l;&{#4wb{V8=4@RSk}SSko*FlH zEI0`Tc;=bsWFPB3M7sq5nz#j!p4kK9Pj?Q`6p@T|e{p%Go6dWKM|`+nz+l>YUP~qF(thJ((6@NQWUZINJy#9#03=9eif{gqCEE zead$-zr)Gv^(JGEZrySD<(H#>|Ni#XLY5&&P5)WJO8eYRKe5y;YXSmzgPI~3v|L~7 z1y{2GW)JuPiz`r|iSG^i{tf3~UFlk+(^JC1i9n_#9y(9HE-SrShQ#ncJJP;?j1bk z6z&q{B8RtI+(Ppa0J*YvSQ|qJ4LpViLeu495EU#eK;vADWh=J}@RBD@x&mjNJrS!9 zu0}d_HM+vD`-KHqy=HAXnCU>v(q)Zafv-NBEztv9!EZr7_uO+i;HRQ{w;q@{aU!a! zs*-MK$PkPjJ2qqHpr{4z3LZ6TBwl@O1_}!cQg^}%7eH;M&tiV50$9S};`h~ijUI{H zZ@*QznU&?MkWQy`I2D@wBB|cJd*Q6JCQ8h#8gKFQO8%U|R|4Z27=G}KtK~?8OB|G?*c4b9MOSh{#m1=5W!M>SU z0HvX>{KFq!fG3}NOn}e*Ag^C0*8)@?fPq@yz`iW10I>Rh+pM9Wpg`mv=5L&jbUME1 zc=RafAp{^C4rAxeUHJ6VPn}G^s|#SR;KKqw99_hiF(;ydmVCY>i|RDTOrRu>N5|Bu zx8bU*t`zn4>(_I?{1facD@(cnP-OvJ@&JU$r^YfZ!v#RO1jih}nP*H)K4<5YDqt8= zRR3NS`UG7Fz>`lrg(seT$~gg)Y5FbN?QS6?_+l56X&Q*dRh~mI^j)<0-#MQofW} z0I(&292SG3eIn|j?ebt`yOF6aWvkb$QSajlx*dF##&w@EUUSV)@PGezr-=S}29W0f zy5YR@zR#~qiQE`V#Wb+Gy1Lm4fMr9d%Ks@!>d7)wqA z?R((u0wKoFY-iT~mK;F5Llm??C4l^kgBWl{|C9i%TD8ii{qDH{YZ~~F`2z0dE<|o_ zF2;=;Cs>hC2C*ja;fEihk<|S50~~$yfUH3zl{o+^FS_flW2KquqPuB+n)XNfD(%+PW1N;$rzZ|3p+_ur2zubjkZ8NCxLp~BpM^UVey<-~KzCPg&z9{F+`J0$oSo&ENrzKhd5xO->cuZ#558(P9L}{F5xmf<% zj^mwTpm|i(d|&yYZ}X~8=dAVFwcipb+6BbY{;vbSncW!#mgU6+6aa0o0MunafP|b_ zAF8CkWeLFco!iq*uFG9O zb}*To0(G8IA~fINEFbig(eH&BuZVtLpN~h=c_=I@L_tAeYRvUpO4ayK0%e*eUS0n@ zZd-N}PHr<6_fLOJ3XrI_oUF)t=lozJAp{nFP}pFUDfDP+zvVZAnNL(*u8Bps`k{v ztfoK>kUzgL6|oWZo&TxV!{OqHxqtsC>c)qW^IRTCg_a)nNjIW|B`-f8U##AUSTu@b zdUXavqg{ig-O=y=t79(GTP#wG7XS&%;exNOxX^xsN(+EPq=H!{h{P6+%fl$(+2~OqFm+c^ zCh!*Dd)V2)e~HO&v6;Z^#4Ps)I&KJI8BYjz@DSEKfY5y5UTCsa2@P`q-WES(j-_cB zF=C`x!K|&V#WBYmjn%8yVCc{x;$DYk%a);U-@e$pcP|beJjnZwKxt{INHh29)k`e$ z@HX*0gPl8fqDz-9`16|96S zvu)nIdE)D8KK=9`Viqxd`gFdueY;rIyY$k_aLzgB;K?VS6gzxB`sgDJ9y~a4dl&CB z6(^i<0$R0dg*)!J124Sr0!}>fMA5%RS%BU9_GO#zXJqY^KPE!!JG@vRN<(G>sl|If z^TJCFyLv^mUR+#)!onitX_}yv3XbzSH7F2c zFeAKOGK(@G4#41SWCnpC}rcA-orAx*CK700T{P@Q|#>$l|o9nlS zt0(sNo{#og9eU9SdREW%Kd*%tn8`p5@DiX2t|Ooo8fc{k)M{Wg1gPgFOQqw5=GNaF zMt*J{e7YC$sDawDT0{@Vcz*_jfxxFBiI4!+mIIKe*<%4)Tc(*;U_)4zFV~eK8jGS| zw>Gj(`2WPt9Rc_&ue`!Hjh-de?#GN7gZJNmU!3PAUYz5;J+ZMvyk_RinSAg6jo_3x z78YR6oH=|S#9jE+uYUDU=K=m>0zf#8`J|h_y6v`MdR#ljh_jPv6hjg7gv=;~5#bzV z;OAgUW}ImZFl8y*M2UkM=pGNS*8@_agO~)-DfP(VTISI`yq}4>{q=}d#K3A9PzU%I z1?6Xf5(0I?33RE!);9NV^~f(s2*7qkqY?BK0&wU&z+qBzNdze^AHErRoDOf`wwBojAbt z0Csr6s*?KwpqnsbCTN5L5dbmCN^?~-PwZ1b*z5M_-sLM`n4|D8tF>skUmi_3fdQj7 zVbI8+c8!*UOLXSR>*VQ;5X%?HnsJHkhfYSIO3oyu&M}D8O zAlJh<=oBUXHYkhlfv$T*bc}dRXt{6&rYtGv2BGju(`_g-u1Tw))d4ih5G##B%h%F` zAUhC@xeI_h=r%2Pn!>hB0U-AftIHc!mg=mA$zMeQCZz4RJH>F($ z454)aJ(;K}_O`-4vkX3u4}Omy0nUam0E5O5Fg%EwhOj9bQ2+|8<#It_~^yk$tY8R$)-&^ZM~^ zS=jMg!(kuay-ikJ+tm2>HtYER{C)tX@wf+M;0T|K+u|M#Oect&3{;aqLw$=k zh1$!>OVI{hT8EIV6M)4yN2RalOcOt*nU=LvPYsde1iot<9Kct*+ALtG(s_J$@EzN5 z2=HM6--b8)XDk5Y{3g7EhG@5H40pHpchmb84n@ac4|MSKK)zmr5ElRn69zNH2axOU z0xeAk8uD!+8bYmE1&>#QZUDNMbDTia2y_ntHCamgDQBH1;F-ypNEgB6h4%s)FR4$) z4mkj;mB$3Q`KF%%X3BynlOjo(ai=gCu7{p|>?U z`gEC%*aSSu*-$?^AK<5ktFr`3foJ}eN!vt%|*CPn9u#6wT8h}?pAj9DZfTiBD$de8H z|8MVHVkA4VGW?wrac^cl`e`@qwnx^?EWjFx1%eGMMo1t$D;5Z`WPyYbNVA$Co|9M12N%i1oncrK=Ux@41a&o?S@&*suFLA$p4a>eI-dHhuj|Rona0~%5;{+M- zkT6Rm>Cqr0?V$*yi4iYhtqN#q?gY@94V;N|AAwr?u~f*8Kw>hPP$W=UEP~h}{Hl@u zc@RJ)pSv`7AM>ZQ`n4t;b944GVl!}Ioz|T7Pq-3%<6(m*e!~iXzuA{J<^4$-n_0P8eDCGa7^Gm?* zrUYgQbRf#W*e1^Vvnkp%b3<=VDclpu22>RADFf)pd49~O13fExS#6_!Dd${rIb{It zF-;IawAOQ}^NL*8y%1k_3bipLgJ-~)%xfmNw!H!<(f{Yj&F^wU?(rwNq~I|_?gyL& zsx2bIylr{h_Y8W;TFy9aPl-)LQM!DI2P4@?(vg8R7yb!DShJRH5`wPjSxx0Z4Hqiu zTFGa3Tn~Vz*ZU-ldP`Wz4-)zPZ~g)Ec*N1k33qSb<>h<#H@L^?=}p?%3{gRltL^u9 zH1yf;_doUL9~OX6QvXx*{!PB&#+S_@0|Xe-h-%LnPY^Zaa^(JvSI}g*jx2dfV+|T~ zA`7_Wj2y8=vcVTg2&8#PRuRyc8<8PvI{UL<&iOVjM8)FAK{H*;#lw>sq-4Zw{v;k@w<9W z^-6_I9xZdLwO^irQVJde#j*Fae05 z8BELPP~bok$iP#FbRGFGumG5dm~SislyiRNb&_B3Gwy|K1vBsf_=KD(sX@p#aNhN_ zGz1I8CNQw3w>1(=O^$|R&m$EpN4^`7l|E-e2K5LV2m!;%?uccQZNF*BCI*Q~3=zon zQV0jKObglZcdyCcV>4hVfp4)yzW{Ip;VH*Haf4^j0NG1)Re(8p19ceEKoB7z)0b?J z9ajS>k?w+cAfPCM1Vx+3kq3fCGzN%@jgZt?SO;10l%ZkzyaWV8>TUp|j0G&q*5?m^ z^|b)@*c>X8(Kohf0EGt#@1rWrvjYay$j58TNiv8~n=1pi@)j>-ixQ+E=rb=g(hyZ? zwV|h{i48(PiHHOQVH7ZTLTk7QNsNY(o=k5eWT8(P9W$;z2}{6};DaCnc>(smUz5Mz zTByG_9iiAez#BN{ECSrirM|Kg{cd0x#tdpe0#r~5s6&*9iV`=N=_G(QG^hreXKOUv z)|<33f&^3*Qzr+fA2KT&z!I}2qUKm~JPUcWEnE#zwr~M=0TUd7(fjm{{~MWs+P{uK zUoZkjm99XwI=}LoL$w2I`{qua``&ql6=W(>!B{W=9k2oxz&Y>)c*>5&a{A|6IGFG^ zWWF2)hLUOp@It;9QCI?x;9-h(F(G)Ml^IbZN3o>|kr)E=(Bf*$G!iw?%EqHe5J1T0 z^p+tA+A3=w32tB`mYXT^DnN-g zfU-SA9r_XG3goG#M{N<5;DWer$1M$t5{b-dh$u(0@uH|I8Dq4J8;A)h8$p#Oz*r)^ z%RSi>nT+GO33;hlrzHk#=>E>%@+W?QPb)h=gbo;XP6UJscE`JZR}_aMx%#U{^)AVK zkf|7}0QQQYD_9rQObA{}fNV3tc=i)~=cUK|Kr&xwvXHVP0j!o)tZu#T1b z@p~cgSGg12Mssjf9e1`6;rTe*GZ-NYIU71UsWBugG(ygqF|d7(ge}pXCFT-QaS+I2 zTl5T!jEtUGdq+18oOdgRoEgm+7J+mwli~~M7r1yq+VETHQgJupG5CBU zj0_Se-M^CtP&N86(zFd}G&E##no@Q!Ww4BA2Zewz$`p{UPUqwH`7(6`k33D6^l4;m zBdarGTnNK?B(K4;;@P_Ho&5IlE&o27G4?#o)rO}E;Icd$4-tHLZGQ>)wDo@v?7$lP zo*fV!6YQ{&JW6GQO-mKuLw4zVqim3E4VrYS8i#bQ! zVgCBB>DTp!{EoS(v|uXCZf0Z-I(MYmpoJKOFoV$Q#w#%fLZdWoKpNSOLlkra3q}qZ ziIY>)hjUFI`tgLg?K|GY+issEMy zp$H)FCHDW;oWtfdj4-d)z0bs;^GPg-kO#p{w(~G^&kJAmkGL4WH@tW89ed~l zgBc^euW=g+@dd03E~%ui4iKM!&fTvshxZAf-W6B!_xOfm=CtuR+|rkBzTtO{e~O=H z9=>EDzUF~D1i2ATEtKP0$3=3dG$*#U-Y?TqR{6{?$B$X8-|qf(ctj5fBIVG3gG42< z9%!toB3M)BWeZpd-+6Dkj{L&{sEZo|+JeY_1df?8izh77$gSCFIMG`i>xnlq!-)35 z`iC5aQ$2~dnaL5oiTz;s1iV2B7)mw+6eCej!qRT~F1|*2#aNIE`jYN5*Y>{_z^)iV zjs8mf3%ml6lcr%gQsx2#B7p=zEbF1HD`{t6Jt0?AA?%K;uU-CiwEy@7urD(R5GE8+ z)Vc0J*!2ZBWgnuRiI4q1kgzpmryXWFB@EP!(G1q+m`0RfGn-Up+ T2B!7~00000NkvXXu0mjfAmt4? literal 0 HcmV?d00001 From f1e04b6d6253946b736c01fd074038e503411360 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 9 Oct 2012 19:00:33 +0100 Subject: [PATCH 10/38] Adjust output to use new images --- openlp/core/ui/slidecontroller.py | 6 +++++- openlp/plugins/media/lib/mediaitem.py | 11 ++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 2d108e72c..0f0f15a3d 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -855,7 +855,11 @@ class SlideController(Controller): else: label = QtGui.QLabel() label.setMargin(4) - label.setScaledContents(True) + if serviceItem.is_media(): + label.setAlignment(QtCore.Qt.AlignHCenter | + QtCore.Qt.AlignVCenter) + else: + label.setScaledContents(True) if self.serviceItem.is_command(): label.setPixmap(QtGui.QPixmap(frame[u'image'])) else: diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 7e8ec6ff2..bd987e79d 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -42,8 +42,9 @@ from openlp.core.ui.media import get_media_players, set_media_players log = logging.getLogger(__name__) -CLAPPERBOARD = QtGui.QImage(u':/media/image_clapperboard.png') -#TODO: Add an appropriate Icon for DVDs, CDs, ... +CLAPPERBOARD = u':/media/slidecontroller_multimedia.png' +VIDEO = QtGui.QImage(u':/media/media_video.png') +AUDIO = QtGui.QImage(u':/media/media_audio.png') DVD_ICON = QtGui.QImage(u':/media/media_video.png') class MediaMediaItem(MediaManagerItem): @@ -218,14 +219,14 @@ class MediaMediaItem(MediaManagerItem): service_item.add_capability(ItemCapabilities.RequiresMedia) # force a non-existent theme service_item.theme = -1 - frame = u':/media/image_clapperboard.png' + frame = CLAPPERBOARD (path, name) = os.path.split(filename) service_item.add_from_command(path, name, frame) return True def initialise(self): self.listView.clear() - self.listView.setIconSize(QtCore.QSize(44, 25)) + self.listView.setIconSize(QtCore.QSize(88, 50)) self.loadList(SettingsManager.load_list(self.settingsSection, u'media')) self.populateDisplayTypes() @@ -293,7 +294,7 @@ class MediaMediaItem(MediaManagerItem): if track_info.isFile(): filename = os.path.split(unicode(track))[1] item_name = QtGui.QListWidgetItem(filename) - item_name.setIcon(build_icon(CLAPPERBOARD)) + item_name.setIcon(build_icon(VIDEO)) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(track)) else: filename = os.path.split(unicode(track))[1] From 9956e0b0c631663af88b22b985aa17585f3e99d9 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Tue, 9 Oct 2012 21:59:33 +0100 Subject: [PATCH 11/38] fixes bug 1063421 I was iterating over a loop as well as poping items out causing an index error --- openlp/plugins/songs/lib/sundayplusimport.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/songs/lib/sundayplusimport.py b/openlp/plugins/songs/lib/sundayplusimport.py index fcf324d41..11b54bdc8 100644 --- a/openlp/plugins/songs/lib/sundayplusimport.py +++ b/openlp/plugins/songs/lib/sundayplusimport.py @@ -154,18 +154,20 @@ class SundayPlusImport(SongImport): # If any line inside any verse contains CCLI or # only Public Domain, we treat this as special data: # we remove that line and add data to specific field. + processed_lines = [] for i in xrange(len(lines)): - lines[i] = lines[i].strip() - line = lines[i] - if line[:4].lower() == u'ccli': + line = lines[i].strip() + if line[:3].lower() == u'ccl': m = re.search(r'[0-9]+', line) if m: self.ccliNumber = int(m.group(0)) - lines.pop(i) + continue elif line.lower() == u'public domain': self.copyright = u'Public Domain' - lines.pop(i) - self.addVerse('\n'.join(lines).strip(), verse_type) + continue + processed_lines.append(line) + self.addVerse('\n'.join(processed_lines).strip(), + verse_type) if end == -1: break i = end + 1 From 57101afef29c84e98d936985119d2486b6da556f Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 10 Oct 2012 17:33:44 +0200 Subject: [PATCH 12/38] fixed bug #1065106 'Change in mainwindow are not reflected in remote' Fixes: https://launchpad.net/bugs/1065106 --- openlp/plugins/remotes/html/openlp.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/remotes/html/openlp.js b/openlp/plugins/remotes/html/openlp.js index 26c13d2f1..87c82c5b4 100644 --- a/openlp/plugins/remotes/html/openlp.js +++ b/openlp/plugins/remotes/html/openlp.js @@ -55,7 +55,9 @@ window.OpenLP = { ); }, loadService: function (event) { - event.preventDefault(); + if (event) { + event.preventDefault(); + } $.getJSON( "/api/service/list", function (data, status) { @@ -150,6 +152,10 @@ window.OpenLP = { OpenLP.currentSlide = data.results.slide; OpenLP.currentItem = data.results.item; if ($("#service-manager").is(":visible")) { + if (OpenLP.currentService != data.results.service) { + OpenLP.currentService = data.results.service; + OpenLP.loadService(); + } $("#service-manager div[data-role=content] ul[data-role=listview] li").attr("data-theme", "c").removeClass("ui-btn-up-e").addClass("ui-btn-up-c"); $("#service-manager div[data-role=content] ul[data-role=listview] li a").each(function () { var item = $(this); @@ -307,7 +313,7 @@ window.OpenLP = { } ); }, - escapeString: function (string) { + escapeString: function (string) { return string.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") } } From ad7715d4022197e5c3f10d30bec4e1218b5193b4 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Wed, 10 Oct 2012 23:36:42 +0200 Subject: [PATCH 13/38] Made the tabs in the web remote translateable. --- openlp/plugins/remotes/html/index.html | 32 ++++++++++++------------ openlp/plugins/remotes/lib/httpserver.py | 4 ++- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/openlp/plugins/remotes/html/index.html b/openlp/plugins/remotes/html/index.html index dad2f8351..148d444bf 100644 --- a/openlp/plugins/remotes/html/index.html +++ b/openlp/plugins/remotes/html/index.html @@ -66,10 +66,10 @@ ${refresh}

@@ -97,10 +97,10 @@ ${refresh} @@ -127,10 +127,10 @@

${alerts}

@@ -148,10 +148,10 @@

${search}

diff --git a/openlp/plugins/remotes/lib/httpserver.py b/openlp/plugins/remotes/lib/httpserver.py index cd2802542..8a66b919a 100644 --- a/openlp/plugins/remotes/lib/httpserver.py +++ b/openlp/plugins/remotes/lib/httpserver.py @@ -308,7 +308,9 @@ class HttpConnection(object): 'add_and_go_to_service': translate('RemotePlugin.Mobile', 'Add & Go to Service'), 'no_results': translate('RemotePlugin.Mobile', 'No Results'), - 'options': translate('RemotePlugin.Mobile', 'Options') + 'options': translate('RemotePlugin.Mobile', 'Options'), + 'service': translate('RemotePlugin.Mobile', 'Service'), + 'slides': translate('RemotePlugin.Mobile', 'Slides') } def ready_read(self): From e55bc7f35d8b527116f32658ec73c9535039c2e6 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Wed, 10 Oct 2012 22:58:21 +0100 Subject: [PATCH 14/38] Fixes: 1065216 Alert display - Text dissapers of the edge of the screen Fixes: 1065149 Clicking new or save disables buttons to display alert Long words now wrap rather than dissapearing off of the edge. When creating a new item or editing one, the text is left in the text box, the item in the list stays selected and the display buttons enabled so the user does not have to find and click on the alert they just created. --- openlp/plugins/alerts/alertsplugin.py | 1 + openlp/plugins/alerts/forms/alertform.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 2d7fd8296..1720fa382 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -105,6 +105,7 @@ CSS = """ font-size: %spt; color: %s; background-color: %s; + word-wrap: break-word; } """ diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index ab4b6583e..7832f0c7d 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -80,6 +80,10 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): item_name = QtGui.QListWidgetItem(alert.text) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(alert.id)) self.alertListWidget.addItem(item_name) + if alert.text == unicode(self.alertTextEdit.text()): + self.item_id = alert.id + self.alertListWidget.setCurrentRow( + self.alertListWidget.row(item_name)) def onDisplayClicked(self): self.triggerAlert(unicode(self.alertTextEdit.text())) @@ -112,7 +116,6 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): alert = AlertItem() alert.text = unicode(self.alertTextEdit.text()) self.manager.save_object(alert) - self.alertTextEdit.setText(u'') self.loadList() def onSaveClick(self): @@ -125,6 +128,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): self.manager.save_object(alert) self.item_id = None self.loadList() + self.saveButton.setEnabled(False) def onTextChanged(self): """ From 017366c4849206f9a3f24735efb3d49e3d676488 Mon Sep 17 00:00:00 2001 From: Erik Lundin Date: Thu, 11 Oct 2012 21:25:50 +0200 Subject: [PATCH 15/38] Made literal string to constant. --- openlp/plugins/bibles/lib/db.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 86f209dc7..d4fd930ed 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -45,6 +45,8 @@ import upgrade log = logging.getLogger(__name__) +RESERVED_CHARACTERS = u'\\.^$*+?{}[]()' + class BibleMeta(BaseModel): """ Bible Meta Data @@ -372,7 +374,7 @@ class BibleDB(QtCore.QObject, Manager): book_names = BibleStrings().BookNames # escape reserved characters book_escaped = book - for character in u'\\.^$*+?{}[]()': + for character in RESERVED_CHARACTERS: book_escaped = book_escaped.replace( character, u'\\' + character) regex_book = re.compile(u'\s*%s\s*' % u'\s*'.join( From 24041c7f17a7b772a30ac91744ccf33e850aabbf Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Thu, 11 Oct 2012 23:03:54 +0100 Subject: [PATCH 16/38] Presentation error traps --- .../presentations/lib/impresscontroller.py | 4 ++ .../presentations/lib/messagelistener.py | 50 ++++++++++++++++--- .../presentations/lib/powerpointcontroller.py | 6 ++- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index a85f43592..ceb793cb2 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -155,6 +155,8 @@ class ImpressController(PresentationController): desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop') except AttributeError: log.warn(u'Failure to find desktop - Impress may have closed') + except pywintypes.com_error: + log.warn(u'Failure to find desktop - Impress may have closed') return desktop if desktop else None def get_com_servicemanager(self): @@ -284,6 +286,8 @@ class ImpressDocument(PresentationDocument): props = tuple(props) doc = self.document pages = doc.getDrawPages() + if not pages: + return if not os.path.isdir(self.get_temp_folder()): os.makedirs(self.get_temp_folder()) for idx in range(pages.getCount()): diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index cb8f7b7b8..dc8ac79d1 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -88,29 +88,40 @@ class Controller(object): Use the last slide number. """ log.debug(u'Live = %s, activate' % self.is_live) + if not self.doc: + return False if self.doc.is_active(): - return + return True if not self.doc.is_loaded(): if not self.doc.load_presentation(): - return + log.warn(u'Failed to activate %s' % self.doc.filepath) + return False if self.is_live: self.doc.start_presentation() if self.doc.slidenumber > 1: if self.doc.slidenumber > self.doc.get_slide_count(): self.doc.slidenumber = self.doc.get_slide_count() self.doc.goto_slide(self.doc.slidenumber) + if self.doc.is_active(): + return True + else: + log.warn(u'Failed to activate %s' % self.doc.filepath) + return False def slide(self, slide): """ Go to a specific slide """ log.debug(u'Live = %s, slide' % self.is_live) + if not self.doc: + return if not self.is_live: return if self.doc.is_blank(): self.doc.slidenumber = int(slide) + 1 return - self.activate() + if not self.activate(): + return self.doc.goto_slide(int(slide) + 1) self.doc.poll_slidenumber(self.is_live) @@ -119,12 +130,15 @@ class Controller(object): Based on the handler passed at startup triggers the first slide """ log.debug(u'Live = %s, first' % self.is_live) + if not self.doc: + return if not self.is_live: return if self.doc.is_blank(): self.doc.slidenumber = 1 return - self.activate() + if not self.activate(): + return self.doc.start_presentation() self.doc.poll_slidenumber(self.is_live) @@ -133,12 +147,15 @@ class Controller(object): Based on the handler passed at startup triggers the last slide """ log.debug(u'Live = %s, last' % self.is_live) + if not self.doc: + return if not self.is_live: return if self.doc.is_blank(): self.doc.slidenumber = self.doc.get_slide_count() return - self.activate() + if not self.activate(): + return self.doc.goto_slide(self.doc.get_slide_count()) self.doc.poll_slidenumber(self.is_live) @@ -147,6 +164,8 @@ class Controller(object): Based on the handler passed at startup triggers the next slide event """ log.debug(u'Live = %s, next' % self.is_live) + if not self.doc: + return if not self.is_live: return if self.doc.is_blank(): @@ -158,7 +177,8 @@ class Controller(object): # contain animations that need to be stepped through. if self.doc.slidenumber > self.doc.get_slide_count(): return - self.activate() + if not self.activate(): + return self.doc.next_step() self.doc.poll_slidenumber(self.is_live) @@ -167,13 +187,16 @@ class Controller(object): Based on the handler passed at startup triggers the previous slide event """ log.debug(u'Live = %s, previous' % self.is_live) + if not self.doc: + return if not self.is_live: return if self.doc.is_blank(): if self.doc.slidenumber > 1: self.doc.slidenumber = self.doc.slidenumber - 1 return - self.activate() + if not self.activate(): + return self.doc.previous_step() self.doc.poll_slidenumber(self.is_live) @@ -182,6 +205,8 @@ class Controller(object): Based on the handler passed at startup triggers slide show to shut down """ log.debug(u'Live = %s, shutdown' % self.is_live) + if not self.doc: + return self.doc.close_presentation() self.doc = None @@ -190,6 +215,8 @@ class Controller(object): Instruct the controller to blank the presentation """ log.debug(u'Live = %s, blank' % self.is_live) + if not self.doc: + return if not self.is_live: return if not self.doc.is_loaded(): @@ -205,6 +232,8 @@ class Controller(object): Instruct the controller to stop and hide the presentation """ log.debug(u'Live = %s, stop' % self.is_live) + if not self.doc: + return if not self.is_live: return if not self.doc.is_loaded(): @@ -218,9 +247,12 @@ class Controller(object): Instruct the controller to unblank the presentation """ log.debug(u'Live = %s, unblank' % self.is_live) + if not self.doc: + return if not self.is_live: return - self.activate() + if not self.activate(): + return if self.doc.slidenumber and \ self.doc.slidenumber != self.doc.get_slide_number(): self.doc.goto_slide(self.doc.slidenumber) @@ -228,6 +260,8 @@ class Controller(object): Receiver.send_message(u'live_display_hide', HideMode.Screen) def poll(self): + if not self.doc: + return self.doc.poll_slidenumber(self.is_live) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 54b9c2144..63183e7b5 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -94,9 +94,9 @@ class PowerpointController(PresentationController): self.docs[0].close_presentation() if self.process is None: return - if self.process.Presentations.Count > 0: - return try: + if self.process.Presentations.Count > 0: + return self.process.Quit() except pywintypes.com_error: pass @@ -253,6 +253,8 @@ class PowerpointDocument(PresentationDocument): renderer = self.controller.plugin.renderer rect = renderer.screens.current[u'size'] ppt_window = self.presentation.SlideShowSettings.Run() + if not ppt_window: + return ppt_window.Top = rect.y() * 72 / dpi ppt_window.Height = rect.height() * 72 / dpi ppt_window.Left = rect.x() * 72 / dpi From 0836306f1bd3b03ab3e4b48805dcbe16aa998781 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 12 Oct 2012 00:55:21 +0200 Subject: [PATCH 17/38] Bug 687638: add function locale_compare. --- openlp/core/utils/__init__.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 41a097a15..957fde829 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -488,10 +488,24 @@ def format_time(text, local_time): return re.sub('\%[a-zA-Z]', match_formatting, text) +def locale_compare(string1, string2): + """ + Compares two strings according to the current QLocale settings. + + As any other compare function, returns a negative, or a positive value, + or 0, depending on whether string1 collates before or after string2 or + is equal to it. + """ + # Function locale.strcol() from standard Python library does not work + # properly on Windows and probably somewhere else. + return int(QtCore.QString.localeAwareCompare( + QtCore.QString(string1).toLower(), QtCore.QString(string2).toLower())) + + from languagemanager import LanguageManager from actions import ActionList __all__ = [u'AppLocation', u'get_application_version', u'check_latest_version', u'add_actions', u'get_filesystem_encoding', u'LanguageManager', u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance', - u'delete_file', u'clean_filename', u'format_time'] + u'delete_file', u'clean_filename', u'format_time', u'locale_compare'] From 7b608a948ad473b9f514dc10cc6a85f40b6a6683 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 12 Oct 2012 02:03:37 +0200 Subject: [PATCH 18/38] Bug 687638: use locale aware comparison for song list. --- openlp/plugins/songs/lib/mediaitem.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 88999dce4..e338a11d9 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -27,7 +27,6 @@ ############################################################################### import logging -import locale import re import os import shutil @@ -40,7 +39,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_directory_exists from openlp.core.lib.ui import UiStrings, create_widget_action from openlp.core.lib.settings import Settings -from openlp.core.utils import AppLocation +from openlp.core.utils import AppLocation, locale_compare from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ SongImportForm, SongExportForm from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \ @@ -263,7 +262,7 @@ class SongMediaItem(MediaManagerItem): # Sort the songs by its title considering language specific characters. # lower() is needed for windows! searchresults.sort( - cmp=locale.strcoll, key=lambda song: song.title.lower()) + cmp=locale_compare, key=lambda song: song.title) for song in searchresults: # Do not display temporary songs if song.temporary: From 2cc18a8fb448f62adc1be25270141bff00475b33 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 12 Oct 2012 13:55:06 +0200 Subject: [PATCH 19/38] Bug #687638: use locale aware comparison for songs by default. --- openlp/core/utils/__init__.py | 4 ++-- openlp/plugins/songs/forms/songexportform.py | 3 +-- openlp/plugins/songs/lib/db.py | 10 +++++++++- openlp/plugins/songs/lib/mediaitem.py | 7 ++----- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 957fde829..764cab06a 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -490,11 +490,11 @@ def format_time(text, local_time): def locale_compare(string1, string2): """ - Compares two strings according to the current QLocale settings. + Compares two strings according to the current locale settings. As any other compare function, returns a negative, or a positive value, or 0, depending on whether string1 collates before or after string2 or - is equal to it. + is equal to it. Comparison is case insensitive. """ # Function locale.strcol() from standard Python library does not work # properly on Windows and probably somewhere else. diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py index c483c91b6..15239f9c2 100644 --- a/openlp/plugins/songs/forms/songexportform.py +++ b/openlp/plugins/songs/forms/songexportform.py @@ -29,7 +29,6 @@ The :mod:`songexportform` module provides the wizard for exporting songs to the OpenLyrics format. """ -import locale import logging from PyQt4 import QtCore, QtGui @@ -252,7 +251,7 @@ class SongExportForm(OpenLPWizard): # Load the list of songs. Receiver.send_message(u'cursor_busy') songs = self.plugin.manager.get_all_objects(Song) - songs.sort(cmp=locale.strcoll, key=lambda song: song.title.lower()) + songs.sort() for song in songs: # No need to export temporary songs. if song.temporary: diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index d79d177fd..0d404a235 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -35,6 +35,7 @@ from sqlalchemy.orm import mapper, relation from sqlalchemy.sql.expression import func from openlp.core.lib.db import BaseModel, init_db +from openlp.core.utils import locale_compare class Author(BaseModel): """ @@ -63,7 +64,14 @@ class Song(BaseModel): """ Song model """ - pass + # By default sort the songs by its title considering language specific + # characters. + def __lt__(self, other): + r = locale_compare(self.title, other.title) + return True if r < 0 else False + + def __eq__(self, other): + return 0 == locale_compare(self.title, other.title) class Topic(BaseModel): diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index e338a11d9..0808bcba0 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -39,7 +39,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_directory_exists from openlp.core.lib.ui import UiStrings, create_widget_action from openlp.core.lib.settings import Settings -from openlp.core.utils import AppLocation, locale_compare +from openlp.core.utils import AppLocation from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ SongImportForm, SongExportForm from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \ @@ -259,10 +259,7 @@ class SongMediaItem(MediaManagerItem): log.debug(u'display results Song') self.saveAutoSelectId() self.listView.clear() - # Sort the songs by its title considering language specific characters. - # lower() is needed for windows! - searchresults.sort( - cmp=locale_compare, key=lambda song: song.title) + searchresults.sort() for song in searchresults: # Do not display temporary songs if song.temporary: From 4427d4168ed2bb2a08b322f97ab81f8f7d06fdf4 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 12 Oct 2012 15:00:56 +0200 Subject: [PATCH 20/38] Bug #687638: use locale aware comparison in other places too. --- openlp/core/ui/thememanager.py | 9 ++++----- openlp/plugins/bibles/forms/bibleimportform.py | 5 ++--- openlp/plugins/bibles/lib/mediaitem.py | 6 +++--- openlp/plugins/custom/lib/db.py | 11 ++++++++++- openlp/plugins/custom/lib/mediaitem.py | 6 +++--- openlp/plugins/images/lib/mediaitem.py | 12 ++++++------ openlp/plugins/media/lib/mediaitem.py | 14 +++++++------- openlp/plugins/presentations/lib/mediaitem.py | 10 +++++----- openlp/plugins/songs/lib/db.py | 2 +- 9 files changed, 41 insertions(+), 34 deletions(-) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 844ffec8c..a5293e3a8 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -30,7 +30,6 @@ import os import zipfile import shutil import logging -import locale import re from xml.etree.ElementTree import ElementTree, XML @@ -46,7 +45,8 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ create_widget_action from openlp.core.theme import Theme from openlp.core.ui import FileRenameForm, ThemeForm -from openlp.core.utils import AppLocation, delete_file, get_filesystem_encoding +from openlp.core.utils import AppLocation, delete_file, locale_compare, \ + get_filesystem_encoding log = logging.getLogger(__name__) @@ -457,9 +457,8 @@ class ThemeManager(QtGui.QWidget): self.configUpdated() files = SettingsManager.get_files(self.settingsSection, u'.png') # Sort the themes by its name considering language specific characters. - # lower() is needed for windows! - files.sort(key=lambda file_name: unicode(file_name).lower(), - cmp=locale.strcoll) + files.sort(key=lambda file_name: unicode(file_name), + cmp=locale_compare) # now process the file list of png files for name in files: # check to see file is in theme root directory diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index 0a1d4cc23..d805ba34f 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -30,7 +30,6 @@ The bible import functions for OpenLP """ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -39,7 +38,7 @@ from openlp.core.lib.db import delete_database from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.settings import Settings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings -from openlp.core.utils import AppLocation +from openlp.core.utils import AppLocation, locale_compare from openlp.plugins.bibles.lib.manager import BibleFormat from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename @@ -523,7 +522,7 @@ class BibleImportForm(OpenLPWizard): """ self.webTranslationComboBox.clear() bibles = self.web_bible_list[index].keys() - bibles.sort(cmp=locale.strcoll) + bibles.sort(cmp=locale_compare) self.webTranslationComboBox.addItems(bibles) def onOsisBrowseButtonClicked(self): diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 5176e7d47..0647076c8 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -27,7 +27,6 @@ ############################################################################### import logging -import locale from PyQt4 import QtCore, QtGui @@ -38,6 +37,7 @@ from openlp.core.lib.settings import Settings from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \ create_horizontal_adjusting_combo_box, critical_error_message_box, \ find_and_set_in_combo_box, build_icon +from openlp.core.utils import locale_compare from openlp.plugins.bibles.forms import BibleImportForm, EditBibleForm from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \ VerseReferenceList, get_reference_separator, LanguageSelection, \ @@ -381,7 +381,7 @@ class BibleMediaItem(MediaManagerItem): # Get all bibles and sort the list. bibles = self.plugin.manager.get_bibles().keys() bibles = filter(None, bibles) - bibles.sort(cmp=locale.strcoll) + bibles.sort(cmp=locale_compare) # Load the bibles into the combo boxes. self.quickVersionComboBox.addItems(bibles) self.quickSecondComboBox.addItems(bibles) @@ -538,7 +538,7 @@ class BibleMediaItem(MediaManagerItem): data = BiblesResourcesDB.get_book_by_id( book.book_reference_id) books.append(data[u'name'] + u' ') - books.sort(cmp=locale.strcoll) + books.sort(cmp=locale_compare) set_case_insensitive_completer(books, self.quickSearchEdit) def onImportClick(self): diff --git a/openlp/plugins/custom/lib/db.py b/openlp/plugins/custom/lib/db.py index 6f3155f48..c885562f2 100644 --- a/openlp/plugins/custom/lib/db.py +++ b/openlp/plugins/custom/lib/db.py @@ -34,12 +34,21 @@ from sqlalchemy import Column, Table, types from sqlalchemy.orm import mapper from openlp.core.lib.db import BaseModel, init_db +from openlp.core.utils import locale_compare class CustomSlide(BaseModel): """ CustomSlide model """ - pass + # By default sort the customs by its title considering language specific + # characters. + def __lt__(self, other): + r = locale_compare(self.title, other.title) + return True if r < 0 else False + + def __eq__(self, other): + return 0 == locale_compare(self.title, other.title) + def init_schema(url): """ diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 663c5489d..01053549f 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -27,7 +27,6 @@ ############################################################################### import logging -import locale from PyQt4 import QtCore, QtGui from sqlalchemy.sql import or_, func @@ -36,6 +35,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_item_selected, translate from openlp.core.lib.ui import UiStrings from openlp.core.lib.settings import Settings +from openlp.core.utils import locale_compare from openlp.plugins.custom.forms import EditCustomForm from openlp.plugins.custom.lib import CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide @@ -110,9 +110,9 @@ class CustomMediaItem(MediaManagerItem): self.saveAutoSelectId() self.listView.clear() # Sort the customs by its title considering language specific - # characters. lower() is needed for windows! + # characters. custom_slides.sort( - cmp=locale.strcoll, key=lambda custom: custom.title.lower()) + cmp=locale_compare, key=lambda custom: custom.title) for custom_slide in custom_slides: custom_name = QtGui.QListWidgetItem(custom_slide.title) custom_name.setData( diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 0fdb1537c..9239f8d72 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -28,7 +28,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -37,7 +36,8 @@ from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \ Receiver, create_thumb, validate_thumb from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.settings import Settings -from openlp.core.utils import AppLocation, delete_file, get_images_filter +from openlp.core.utils import AppLocation, delete_file, locale_compare, \ + get_images_filter log = logging.getLogger(__name__) @@ -126,10 +126,10 @@ class ImageMediaItem(MediaManagerItem): if not initialLoad: Receiver.send_message(u'cursor_busy') self.plugin.formParent.displayProgressBar(len(images)) - # Sort the themes by its filename considering language specific - # characters. lower() is needed for windows! - images.sort(cmp=locale.strcoll, - key=lambda filename: os.path.split(unicode(filename))[1].lower()) + # Sort the images by its filename considering language specific + # characters. + images.sort(cmp=locale_compare, + key=lambda filename: os.path.split(unicode(filename))[1]) for imageFile in images: filename = os.path.split(unicode(imageFile))[1] thumb = os.path.join(self.servicePath, filename) diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index bd987e79d..9f661149b 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -28,7 +28,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -39,6 +38,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ create_horizontal_adjusting_combo_box from openlp.core.ui import Controller, Display from openlp.core.ui.media import get_media_players, set_media_players +from openlp.core.utils import locale_compare log = logging.getLogger(__name__) @@ -285,10 +285,10 @@ class MediaMediaItem(MediaManagerItem): u'media', self.getFileList()) def loadList(self, media): - # Sort the themes by its filename considering language specific - # characters. lower() is needed for windows! - media.sort(cmp=locale.strcoll, - key=lambda filename: os.path.split(unicode(filename))[1].lower()) + # Sort the media by its filename considering language specific + # characters. + media.sort(cmp=locale_compare, + key=lambda filename: os.path.split(unicode(filename))[1]) for track in media: track_info = QtCore.QFileInfo(track) if track_info.isFile(): @@ -307,8 +307,8 @@ class MediaMediaItem(MediaManagerItem): def getList(self, type=MediaType.Audio): media = SettingsManager.load_list(self.settingsSection, u'media') - media.sort(cmp=locale.strcoll, - key=lambda filename: os.path.split(unicode(filename))[1].lower()) + media.sort(cmp=locale_compare, + key=lambda filename: os.path.split(unicode(filename))[1]) ext = [] if type == MediaType.Audio: ext = self.plugin.audio_extensions_list diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 290882e26..9cfed177c 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -28,7 +28,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -38,6 +37,7 @@ from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ create_horizontal_adjusting_combo_box from openlp.core.lib.settings import Settings +from openlp.core.utils import locale_compare from openlp.plugins.presentations.lib import MessageListener log = logging.getLogger(__name__) @@ -169,10 +169,10 @@ class PresentationMediaItem(MediaManagerItem): if not initialLoad: Receiver.send_message(u'cursor_busy') self.plugin.formParent.displayProgressBar(len(files)) - # Sort the themes by its filename considering language specific - # characters. lower() is needed for windows! - files.sort(cmp=locale.strcoll, - key=lambda filename: os.path.split(unicode(filename))[1].lower()) + # Sort the presentations by its filename considering language specific + # characters. + files.sort(cmp=locale_compare, + key=lambda filename: os.path.split(unicode(filename))[1]) for file in files: if not initialLoad: self.plugin.formParent.incrementProgressBar() diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index 0d404a235..36b6d53ad 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -69,7 +69,7 @@ class Song(BaseModel): def __lt__(self, other): r = locale_compare(self.title, other.title) return True if r < 0 else False - + def __eq__(self, other): return 0 == locale_compare(self.title, other.title) From 83de6bb99f23e97ccfbfd549f08c5b1c07b9b980 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Fri, 12 Oct 2012 20:51:47 +0200 Subject: [PATCH 21/38] Fixed bug #851706: The song import dialog now shows individual songs being imported. Also tried to make the progress page of the FTW work better, pity it is only slightly... Fixes: https://launchpad.net/bugs/851706 --- openlp/core/ui/firsttimeform.py | 14 +++++++++++- openlp/plugins/songs/lib/olpimport.py | 15 +++++++++--- openlp/plugins/songs/songsplugin.py | 33 +++++++++++++++++++++------ 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py index 1bd746759..0461e49d1 100644 --- a/openlp/core/ui/firsttimeform.py +++ b/openlp/core/ui/firsttimeform.py @@ -177,8 +177,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): return FirstTimePage.Progress elif self.currentId() == FirstTimePage.Themes: Receiver.send_message(u'cursor_busy') + Receiver.send_message(u'openlp_process_events') while not self.themeScreenshotThread.isFinished(): time.sleep(0.1) + Receiver.send_message(u'openlp_process_events') # Build the screenshot icons, as this can not be done in the thread. self._buildThemeScreenshots() Receiver.send_message(u'cursor_normal') @@ -188,10 +190,11 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): def onCurrentIdChanged(self, pageId): """ - Detects Page changes and updates as approprate. + Detects Page changes and updates as appropriate. """ # Keep track of the page we are at. Triggering "Cancel" causes pageId # to be a -1. + Receiver.send_message(u'openlp_process_events') if pageId != -1: self.lastId = pageId if pageId == FirstTimePage.Plugins: @@ -227,6 +230,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): self.cancelButton.setVisible(False) elif pageId == FirstTimePage.Progress: Receiver.send_message(u'cursor_busy') + self.update() + Receiver.send_message(u'openlp_process_events') + time.sleep(0.5) + Receiver.send_message(u'openlp_process_events') self._preWizard() Receiver.send_message(u'openlp_process_events') self._performWizard() @@ -342,8 +349,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): self.max_progress = 0 self.finishButton.setVisible(False) Receiver.send_message(u'openlp_process_events') + time.sleep(0.1) # Loop through the songs list and increase for each selected item for i in xrange(self.songsListWidget.count()): + Receiver.send_message(u'openlp_process_events') item = self.songsListWidget.item(i) if item.checkState() == QtCore.Qt.Checked: filename = item.data(QtCore.Qt.UserRole).toString() @@ -352,6 +361,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): # Loop through the Bibles list and increase for each selected item iterator = QtGui.QTreeWidgetItemIterator(self.biblesTreeWidget) while iterator.value(): + Receiver.send_message(u'openlp_process_events') item = iterator.value() if item.parent() and item.checkState(0) == QtCore.Qt.Checked: filename = item.data(0, QtCore.Qt.UserRole).toString() @@ -360,6 +370,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): iterator += 1 # Loop through the themes list and increase for each selected item for i in xrange(self.themesListWidget.count()): + Receiver.send_message(u'openlp_process_events') item = self.themesListWidget.item(i) if item.checkState() == QtCore.Qt.Checked: filename = item.data(QtCore.Qt.UserRole).toString() @@ -381,6 +392,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): self.progressPage.setTitle(translate('OpenLP.FirstTimeWizard', 'Setting Up')) self.progressPage.setSubTitle(u'Setup complete.') + Receiver.send_message(u'openlp_process_events') def _postWizard(self): """ diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py index 7a9d98c98..4b97fdafe 100644 --- a/openlp/plugins/songs/lib/olpimport.py +++ b/openlp/plugins/songs/lib/olpimport.py @@ -63,10 +63,14 @@ class OpenLPSongImport(SongImport): SongImport.__init__(self, manager, **kwargs) self.sourceSession = None - def doImport(self): + def doImport(self, progressDialog=None): """ Run the import for an OpenLP version 2 song database. + + ``progressDialog`` + The QProgressDialog used when importing songs from the FRW. """ + class OldAuthor(BaseModel): """ Author model @@ -101,13 +105,14 @@ class OpenLPSongImport(SongImport): """ pass - + # Check the file type if not self.importSource.endswith(u'.sqlite'): self.logError(self.importSource, translate('SongsPlugin.OpenLPSongImport', 'Not a valid OpenLP 2.0 song database.')) return self.importSource = u'sqlite:///%s' % self.importSource + # Load the db file engine = create_engine(self.importSource) source_meta = MetaData() source_meta.reflect(engine) @@ -224,7 +229,11 @@ class OpenLPSongImport(SongImport): file_name=media_file.file_name)) clean_song(self.manager, new_song) self.manager.save_object(new_song) - if self.importWizard: + if progressDialog: + progressDialog.setValue(progressDialog.value() + 1) + progressDialog.setLabelText( + WizardStrings.ImportingType % new_song.title) + else: self.importWizard.incrementProgressBar( WizardStrings.ImportingType % new_song.title) if self.stopImportFlag: diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 8b7bd36e8..46506a478 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -29,6 +29,7 @@ import logging import os from tempfile import gettempdir +import sqlite3 from PyQt4 import QtCore, QtGui @@ -82,7 +83,7 @@ class SongsPlugin(Plugin): unicode(UiStrings().Tools)) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'servicemanager_new_service'), - self.clearTemporarySongs) + self.clearTemporarySongs) def addImportMenuItem(self, import_menu): @@ -235,31 +236,37 @@ class SongsPlugin(Plugin): If the first time wizard has run, this function is run to import all the new songs into the database. """ + Receiver.send_message(u'openlp_process_events') self.onToolsReindexItemTriggered() + Receiver.send_message(u'openlp_process_events') db_dir = unicode(os.path.join( unicode(gettempdir(), get_filesystem_encoding()), u'openlp')) if not os.path.exists(db_dir): return song_dbs = [] + song_count = 0 for sfile in os.listdir(db_dir): if sfile.startswith(u'songs_') and sfile.endswith(u'.sqlite'): + Receiver.send_message(u'openlp_process_events') song_dbs.append(os.path.join(db_dir, sfile)) + song_count += self._countSongs(os.path.join(db_dir, sfile)) if not song_dbs: return + Receiver.send_message(u'openlp_process_events') progress = QtGui.QProgressDialog(self.formParent) progress.setWindowModality(QtCore.Qt.WindowModal) progress.setWindowTitle(translate('OpenLP.Ui', 'Importing Songs')) progress.setLabelText(translate('OpenLP.Ui', 'Starting import...')) progress.setCancelButton(None) - progress.setRange(0, len(song_dbs)) + progress.setRange(0, song_count) progress.setMinimumDuration(0) progress.forceShow() - for idx, db in enumerate(song_dbs): - progress.setValue(idx) - Receiver.send_message(u'openlp_process_events') + Receiver.send_message(u'openlp_process_events') + for db in song_dbs: importer = OpenLPSongImport(self.manager, filename=db) - importer.doImport() - progress.setValue(len(song_dbs)) + importer.doImport(progress) + Receiver.send_message(u'openlp_process_events') + progress.setValue(song_count) self.mediaItem.onSearchTextButtonClicked() def finalise(self): @@ -287,3 +294,15 @@ class SongsPlugin(Plugin): songs = self.manager.get_all_objects(Song, Song.temporary == True) for song in songs: self.manager.delete_object(Song, song.id) + + def _countSongs(self, db_file): + connection = sqlite3.connect(db_file) + cursor = connection.cursor() + cursor.execute(u'SELECT COUNT(id) AS song_count FROM songs') + song_count = cursor.fetchone()[0] + connection.close() + try: + song_count = int(song_count) + except (TypeError, ValueError): + song_count = 0 + return song_count From efef105c3facf0e02bb39202a846581b08321eb1 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Fri, 12 Oct 2012 20:15:36 +0100 Subject: [PATCH 22/38] ppt problems --- openlp/plugins/presentations/lib/powerpointcontroller.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 63183e7b5..c00c6d559 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -210,6 +210,13 @@ class PowerpointDocument(PresentationDocument): self.presentation.SlideShowSettings.Run() self.presentation.SlideShowWindow.View.State = 1 self.presentation.SlideShowWindow.Activate() + if self.presentation.Application.Version == u'14.0': + # Unblanking is broken in PowerPoint 2010, need to redisplay + slide = self.presentation.SlideShowWindow.View.CurrentShowPosition + click = self.presentation.SlideShowWindow.View.GetClickIndex() + self.presentation.SlideShowWindow.View.GotoSlide(slide) + if click: + self.presentation.SlideShowWindow.View.GotoClick(click) def blank_screen(self): """ From e26cd9ca6bc63b31cbe75b5660f81a8b52cd538a Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 12 Oct 2012 21:40:15 +0200 Subject: [PATCH 23/38] Bug #687638: for customs cmp method in sort not necessary. --- openlp/plugins/custom/lib/mediaitem.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 01053549f..10a3ec056 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -35,7 +35,6 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_item_selected, translate from openlp.core.lib.ui import UiStrings from openlp.core.lib.settings import Settings -from openlp.core.utils import locale_compare from openlp.plugins.custom.forms import EditCustomForm from openlp.plugins.custom.lib import CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide @@ -109,10 +108,7 @@ class CustomMediaItem(MediaManagerItem): # Sort out what custom we want to select after loading the list. self.saveAutoSelectId() self.listView.clear() - # Sort the customs by its title considering language specific - # characters. - custom_slides.sort( - cmp=locale_compare, key=lambda custom: custom.title) + custom_slides.sort() for custom_slide in custom_slides: custom_name = QtGui.QListWidgetItem(custom_slide.title) custom_name.setData( From c7e555e0e8660d71ae1edece85f981f9c807c32f Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Fri, 12 Oct 2012 22:33:10 +0100 Subject: [PATCH 24/38] Various end of show issues --- openlp/plugins/presentations/lib/impresscontroller.py | 10 ++++++++-- .../plugins/presentations/lib/powerpointcontroller.py | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index ceb793cb2..b1c0bcc82 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -363,7 +363,9 @@ class ImpressDocument(PresentationDocument): log.debug(u'is active OpenOffice') if not self.is_loaded(): return False - return self.control is not None + if not self.control: + return False + return self.control.isRunning() def unblank_screen(self): """ @@ -384,7 +386,7 @@ class ImpressDocument(PresentationDocument): Returns true if screen is blank """ log.debug(u'is blank OpenOffice') - if self.control: + if self.control and self.control.isRunning(): return self.control.isPaused() else: return False @@ -440,7 +442,11 @@ class ImpressDocument(PresentationDocument): """ Triggers the next effect of slide on the running presentation """ + is_paused = self.control.isPaused() self.control.gotoNextEffect() + time.sleep(0.1) + if not is_paused and self.control.isPaused(): + self.control.gotoPreviousEffect() def previous_step(self): """ diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index c00c6d559..7da9a95d7 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -295,6 +295,8 @@ class PowerpointDocument(PresentationDocument): """ log.debug(u'next_step') self.presentation.SlideShowWindow.View.Next() + if self.get_slide_number() > self.get_slide_count(): + self.previous_step() def previous_step(self): """ From 0ddeef9d8ff19218e27b9d111918b9622819cea6 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Fri, 12 Oct 2012 23:13:58 +0100 Subject: [PATCH 25/38] Blank desktop issues --- .../presentations/lib/messagelistener.py | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index dc8ac79d1..fdceda4ab 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -49,6 +49,7 @@ class Controller(object): """ self.is_live = live self.doc = None + self.hide_mode = None log.info(u'%s controller loaded' % live) def add_handler(self, controller, file, hide_mode, slide_no): @@ -67,6 +68,7 @@ class Controller(object): # Inform slidecontroller that the action failed? return self.doc.slidenumber = slide_no + self.hide_mode = hide_mode if self.is_live: if hide_mode == HideMode.Screen: Receiver.send_message(u'live_display_hide', HideMode.Screen) @@ -117,7 +119,7 @@ class Controller(object): return if not self.is_live: return - if self.doc.is_blank(): + if self.hide_mode: self.doc.slidenumber = int(slide) + 1 return if not self.activate(): @@ -134,7 +136,7 @@ class Controller(object): return if not self.is_live: return - if self.doc.is_blank(): + if self.hide_mode: self.doc.slidenumber = 1 return if not self.activate(): @@ -151,7 +153,7 @@ class Controller(object): return if not self.is_live: return - if self.doc.is_blank(): + if self.hide_mode: self.doc.slidenumber = self.doc.get_slide_count() return if not self.activate(): @@ -168,7 +170,7 @@ class Controller(object): return if not self.is_live: return - if self.doc.is_blank(): + if self.hide_mode: if self.doc.slidenumber < self.doc.get_slide_count(): self.doc.slidenumber = self.doc.slidenumber + 1 return @@ -191,7 +193,7 @@ class Controller(object): return if not self.is_live: return - if self.doc.is_blank(): + if self.hide_mode: if self.doc.slidenumber > 1: self.doc.slidenumber = self.doc.slidenumber - 1 return @@ -215,23 +217,28 @@ class Controller(object): Instruct the controller to blank the presentation """ log.debug(u'Live = %s, blank' % self.is_live) + self.hide_mode = hide_mode if not self.doc: return if not self.is_live: return - if not self.doc.is_loaded(): - return - if not self.doc.is_active(): - return if hide_mode == HideMode.Theme: + if not self.doc.is_loaded(): + return + if not self.doc.is_active(): + return Receiver.send_message(u'live_display_hide', HideMode.Theme) - self.doc.blank_screen() + elif hide_mode == HideMode.Blank: + if not self.activate(): + return + self.doc.blank_screen() def stop(self): """ Instruct the controller to stop and hide the presentation """ log.debug(u'Live = %s, stop' % self.is_live) + self.hide_mode = HideMode.Screen if not self.doc: return if not self.is_live: @@ -247,6 +254,7 @@ class Controller(object): Instruct the controller to unblank the presentation """ log.debug(u'Live = %s, unblank' % self.is_live) + self.hide_mode = None if not self.doc: return if not self.is_live: From ba57e335c0a450643db744a844a0a057518d6234 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 13 Oct 2012 08:34:15 +0100 Subject: [PATCH 26/38] Stop blank alerts being displayed --- openlp/plugins/alerts/lib/alertsmanager.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index 018b38af2..7b43c202a 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -57,8 +57,6 @@ class AlertsManager(QtCore.QObject): """ if message: self.displayAlert(message[0]) - else: - self.displayAlert(u'') def displayAlert(self, text=u''): """ @@ -68,14 +66,15 @@ class AlertsManager(QtCore.QObject): display text """ log.debug(u'display alert called %s' % text) - self.alertList.append(text) - if self.timer_id != 0: - Receiver.send_message(u'mainwindow_status_text', - translate('AlertsPlugin.AlertsManager', - 'Alert message created and displayed.')) - return - Receiver.send_message(u'mainwindow_status_text', u'') - self.generateAlert() + if text: + self.alertList.append(text) + if self.timer_id != 0: + Receiver.send_message(u'mainwindow_status_text', + translate('AlertsPlugin.AlertsManager', + 'Alert message created and displayed.')) + return + Receiver.send_message(u'mainwindow_status_text', u'') + self.generateAlert() def generateAlert(self): """ From 43e41b2688d63926479164c8b60078fcf2c1d310 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sat, 13 Oct 2012 19:05:55 +0200 Subject: [PATCH 27/38] Try to lessen the number of superfluous process events signals --- openlp/core/ui/firsttimeform.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py index 0461e49d1..14f1299de 100644 --- a/openlp/core/ui/firsttimeform.py +++ b/openlp/core/ui/firsttimeform.py @@ -230,14 +230,12 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): self.cancelButton.setVisible(False) elif pageId == FirstTimePage.Progress: Receiver.send_message(u'cursor_busy') - self.update() - Receiver.send_message(u'openlp_process_events') - time.sleep(0.5) + self.repaint() Receiver.send_message(u'openlp_process_events') + # Try to give the wizard a chance to redraw itself + time.sleep(0.2) self._preWizard() - Receiver.send_message(u'openlp_process_events') self._performWizard() - Receiver.send_message(u'openlp_process_events') self._postWizard() Receiver.send_message(u'cursor_normal') Receiver.send_message(u'openlp_process_events') @@ -270,8 +268,8 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): """ Receiver.send_message(u'cursor_busy') self._performWizard() - Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'cursor_normal') + Receiver.send_message(u'openlp_process_events') Settings().setValue(u'general/has run wizard', QtCore.QVariant(True)) self.close() @@ -349,7 +347,6 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): self.max_progress = 0 self.finishButton.setVisible(False) Receiver.send_message(u'openlp_process_events') - time.sleep(0.1) # Loop through the songs list and increase for each selected item for i in xrange(self.songsListWidget.count()): Receiver.send_message(u'openlp_process_events') @@ -392,7 +389,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): self.progressPage.setTitle(translate('OpenLP.FirstTimeWizard', 'Setting Up')) self.progressPage.setSubTitle(u'Setup complete.') + self.repaint() Receiver.send_message(u'openlp_process_events') + # Try to give the wizard a chance to repaint itself + time.sleep(0.1) def _postWizard(self): """ From 4c1fe14fd2f018292eb15e2eff05c96fb94a86e6 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Sat, 13 Oct 2012 19:32:32 +0100 Subject: [PATCH 28/38] Raoul's kicks --- openlp/plugins/presentations/lib/impresscontroller.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index b1c0bcc82..3d78f7bdb 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -153,9 +153,7 @@ class ImpressController(PresentationController): desktop = None try: desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop') - except AttributeError: - log.warn(u'Failure to find desktop - Impress may have closed') - except pywintypes.com_error: + except (AttributeError, pywintypes.com_error): log.warn(u'Failure to find desktop - Impress may have closed') return desktop if desktop else None @@ -363,9 +361,7 @@ class ImpressDocument(PresentationDocument): log.debug(u'is active OpenOffice') if not self.is_loaded(): return False - if not self.control: - return False - return self.control.isRunning() + return self.control.isRunning() if self.control else False def unblank_screen(self): """ From 9f5ed9589bdd08ab4361f540275ba1901f028441 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Sat, 13 Oct 2012 20:07:30 +0100 Subject: [PATCH 29/38] Slide counts can only be got if active --- openlp/plugins/presentations/lib/messagelistener.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index fdceda4ab..bf46191ac 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -171,16 +171,18 @@ class Controller(object): if not self.is_live: return if self.hide_mode: + if not self.doc.is_active(): + return if self.doc.slidenumber < self.doc.get_slide_count(): self.doc.slidenumber = self.doc.slidenumber + 1 return + if not self.activate(): + return # The "End of slideshow" screen is after the last slide # Note, we can't just stop on the last slide, since it may # contain animations that need to be stepped through. if self.doc.slidenumber > self.doc.get_slide_count(): return - if not self.activate(): - return self.doc.next_step() self.doc.poll_slidenumber(self.is_live) @@ -194,6 +196,8 @@ class Controller(object): if not self.is_live: return if self.hide_mode: + if not self.doc.is_active(): + return if self.doc.slidenumber > 1: self.doc.slidenumber = self.doc.slidenumber - 1 return From bbbf426cf2a9c19a5d6632f259bf40acfd8c69ae Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Sat, 13 Oct 2012 20:48:58 +0100 Subject: [PATCH 30/38] If change slides whilst blank, update slidecontroller --- .../presentations/lib/messagelistener.py | 19 ++++++++++++------- .../lib/presentationcontroller.py | 11 ++++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index bf46191ac..7cc12c7f9 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -80,7 +80,7 @@ class Controller(object): else: self.doc.start_presentation() Receiver.send_message(u'live_display_hide', HideMode.Screen) - self.doc.slidenumber = 0 + self.doc.slidenumber = 1 if slide_no > 1: self.slide(slide_no) @@ -121,11 +121,12 @@ class Controller(object): return if self.hide_mode: self.doc.slidenumber = int(slide) + 1 + self.poll() return if not self.activate(): return self.doc.goto_slide(int(slide) + 1) - self.doc.poll_slidenumber(self.is_live) + self.poll() def first(self): """ @@ -138,11 +139,12 @@ class Controller(object): return if self.hide_mode: self.doc.slidenumber = 1 + self.poll() return if not self.activate(): return self.doc.start_presentation() - self.doc.poll_slidenumber(self.is_live) + self.poll() def last(self): """ @@ -155,11 +157,12 @@ class Controller(object): return if self.hide_mode: self.doc.slidenumber = self.doc.get_slide_count() + self.poll() return if not self.activate(): return self.doc.goto_slide(self.doc.get_slide_count()) - self.doc.poll_slidenumber(self.is_live) + self.poll() def next(self): """ @@ -175,6 +178,7 @@ class Controller(object): return if self.doc.slidenumber < self.doc.get_slide_count(): self.doc.slidenumber = self.doc.slidenumber + 1 + self.poll() return if not self.activate(): return @@ -184,7 +188,7 @@ class Controller(object): if self.doc.slidenumber > self.doc.get_slide_count(): return self.doc.next_step() - self.doc.poll_slidenumber(self.is_live) + self.poll() def previous(self): """ @@ -200,11 +204,12 @@ class Controller(object): return if self.doc.slidenumber > 1: self.doc.slidenumber = self.doc.slidenumber - 1 + self.poll() return if not self.activate(): return self.doc.previous_step() - self.doc.poll_slidenumber(self.is_live) + self.poll() def shutdown(self): """ @@ -274,7 +279,7 @@ class Controller(object): def poll(self): if not self.doc: return - self.doc.poll_slidenumber(self.is_live) + self.doc.poll_slidenumber(self.is_live, self.hide_mode) class MessageListener(object): diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index b72e1e9d4..4006cbc3e 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -260,16 +260,17 @@ class PresentationDocument(object): else: return None - def poll_slidenumber(self, is_live): + def poll_slidenumber(self, is_live, hide_mode): """ Check the current slide number """ if not self.is_active(): return - current = self.get_slide_number() - if current == self.slidenumber: - return - self.slidenumber = current + if not hide_mode: + current = self.get_slide_number() + if current == self.slidenumber: + return + self.slidenumber = current if is_live: prefix = u'live' else: From 0f18ec43a060b7f4f7bfe99ddee2bf5d2a4eb583 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Sun, 14 Oct 2012 13:11:48 +0200 Subject: [PATCH 31/38] Bug #687638: improved performance of local aware sorting. --- openlp/core/utils/__init__.py | 12 ++++++--- openlp/plugins/songs/forms/songexportform.py | 4 ++- openlp/plugins/songs/lib/db.py | 26 +++++++++++++------- openlp/plugins/songs/lib/mediaitem.py | 5 ++-- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 764cab06a..742b1e4bc 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -498,8 +498,13 @@ def locale_compare(string1, string2): """ # Function locale.strcol() from standard Python library does not work # properly on Windows and probably somewhere else. - return int(QtCore.QString.localeAwareCompare( - QtCore.QString(string1).toLower(), QtCore.QString(string2).toLower())) + return QtCore.QString.localeAwareCompare(string1.lower(), string2.lower()) + + +# For performance reasons provide direct reference to compare function +# without wrapping it in another function making te string lowercase. +# This is needed for sorting songs. +locale_direct_compare = QtCore.QString.localeAwareCompare from languagemanager import LanguageManager @@ -508,4 +513,5 @@ from actions import ActionList __all__ = [u'AppLocation', u'get_application_version', u'check_latest_version', u'add_actions', u'get_filesystem_encoding', u'LanguageManager', u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance', - u'delete_file', u'clean_filename', u'format_time', u'locale_compare'] + u'delete_file', u'clean_filename', u'format_time', u'locale_compare', + u'locale_direct_compare'] diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py index 15239f9c2..1f2988568 100644 --- a/openlp/plugins/songs/forms/songexportform.py +++ b/openlp/plugins/songs/forms/songexportform.py @@ -37,6 +37,7 @@ from openlp.core.lib import build_icon, Receiver, SettingsManager, translate, \ create_separated_list from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings +from openlp.core.utils import locale_direct_compare from openlp.plugins.songs.lib.db import Song from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport @@ -251,7 +252,8 @@ class SongExportForm(OpenLPWizard): # Load the list of songs. Receiver.send_message(u'cursor_busy') songs = self.plugin.manager.get_all_objects(Song) - songs.sort() + songs.sort( + cmp=locale_direct_compare, key=lambda song: song.sort_string) for song in songs: # No need to export temporary songs. if song.temporary: diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index 36b6d53ad..122d29859 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -31,11 +31,11 @@ the Songs plugin """ from sqlalchemy import Column, ForeignKey, Table, types -from sqlalchemy.orm import mapper, relation +from sqlalchemy.orm import mapper, relation, reconstructor from sqlalchemy.sql.expression import func +from PyQt4 import QtCore from openlp.core.lib.db import BaseModel, init_db -from openlp.core.utils import locale_compare class Author(BaseModel): """ @@ -64,14 +64,22 @@ class Song(BaseModel): """ Song model """ - # By default sort the songs by its title considering language specific - # characters. - def __lt__(self, other): - r = locale_compare(self.title, other.title) - return True if r < 0 else False + def __init__(self): + self.sort_string = '' - def __eq__(self, other): - return 0 == locale_compare(self.title, other.title) + # This decorator tells sqlalchemy to call this method everytime + # any data on this object are updated. + @reconstructor + def init_on_load(self): + """ + Precompute string to be used for sorting. + + Song sorting is performance sensitive operation. + To get maximum speed lets precompute the string + used for comparison. + """ + # Avoid the overhead of converting string to lowercase and to QString + self.sort_string = QtCore.QString(self.title.lower()) class Topic(BaseModel): diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 0808bcba0..05da69f61 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -39,7 +39,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_directory_exists from openlp.core.lib.ui import UiStrings, create_widget_action from openlp.core.lib.settings import Settings -from openlp.core.utils import AppLocation +from openlp.core.utils import AppLocation, locale_direct_compare from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ SongImportForm, SongExportForm from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \ @@ -259,7 +259,8 @@ class SongMediaItem(MediaManagerItem): log.debug(u'display results Song') self.saveAutoSelectId() self.listView.clear() - searchresults.sort() + searchresults.sort( + cmp=locale_direct_compare, key=lambda song: song.sort_string) for song in searchresults: # Do not display temporary songs if song.temporary: From 7321f5fb2d7cc1c061b3062a2962c9b00c0236ed Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Sun, 14 Oct 2012 20:42:20 +0200 Subject: [PATCH 32/38] Bug #1002038: Disable and hide presentation plugin on osx. --- openlp/core/lib/pluginmanager.py | 8 ++++++++ openlp/core/ui/firsttimewizard.py | 20 +++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index 8899f5846..b90375506 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -85,6 +85,14 @@ class PluginManager(object): log.debug(u'finding plugins in %s at depth %d', unicode(plugin_dir), startdepth) for root, dirs, files in os.walk(plugin_dir): + # TODO Presentation plugin is not yet working on Mac OS X. + # For now just ignore it. The following code will hide it + # in settings dialog. + if sys.platform == 'darwin': + present_plugin_dir = os.path.join(plugin_dir, 'presentations') + # Ignore files from the presentation plugin directory. + if root.startswith(present_plugin_dir): + continue for name in files: if name.endswith(u'.py') and not name.startswith(u'__'): path = os.path.abspath(os.path.join(root, name)) diff --git a/openlp/core/ui/firsttimewizard.py b/openlp/core/ui/firsttimewizard.py index 1ce523cbc..92204a583 100644 --- a/openlp/core/ui/firsttimewizard.py +++ b/openlp/core/ui/firsttimewizard.py @@ -82,13 +82,13 @@ class Ui_FirstTimeWizard(object): self.imageCheckBox.setChecked(True) self.imageCheckBox.setObjectName(u'imageCheckBox') self.pluginLayout.addWidget(self.imageCheckBox) - self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage) - if sys.platform == "darwin": - self.presentationCheckBox.setChecked(False) - else: + # TODO Presentation plugin is not yet working on Mac OS X. + # For now just ignore it. + if sys.platform != 'darwin': + self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage) self.presentationCheckBox.setChecked(True) - self.presentationCheckBox.setObjectName(u'presentationCheckBox') - self.pluginLayout.addWidget(self.presentationCheckBox) + self.presentationCheckBox.setObjectName(u'presentationCheckBox') + self.pluginLayout.addWidget(self.presentationCheckBox) self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage) self.mediaCheckBox.setChecked(True) self.mediaCheckBox.setObjectName(u'mediaCheckBox') @@ -214,9 +214,11 @@ class Ui_FirstTimeWizard(object): self.bibleCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Bible')) self.imageCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Images')) - self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard', - 'Presentations')) - if sys.platform == "darwin": + # TODO Presentation plugin is not yet working on Mac OS X. + # For now just ignore it. + if sys.platform != 'darwin': + self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard', + 'Presentations')) self.presentationCheckBox.setEnabled(False) self.mediaCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Media (Audio and Video)')) From 16c0ec482e5db0fbe0335ec09c9041e60d9b6e88 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Mon, 15 Oct 2012 10:25:42 +0200 Subject: [PATCH 33/38] Bug #1002038: Fix enabling presentation plugin if no osx os. --- openlp/core/ui/firsttimewizard.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openlp/core/ui/firsttimewizard.py b/openlp/core/ui/firsttimewizard.py index 92204a583..4477dd4cb 100644 --- a/openlp/core/ui/firsttimewizard.py +++ b/openlp/core/ui/firsttimewizard.py @@ -219,7 +219,6 @@ class Ui_FirstTimeWizard(object): if sys.platform != 'darwin': self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Presentations')) - self.presentationCheckBox.setEnabled(False) self.mediaCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Media (Audio and Video)')) self.remoteCheckBox.setText(translate('OpenLP.FirstTimeWizard', From f84c0899389cb8444f7615306012935e928af61c Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 16 Oct 2012 10:25:54 +0200 Subject: [PATCH 34/38] fixed bug #1066296 (Renaming theme keeps old/new theme in Theme manager) Fixes: https://launchpad.net/bugs/1066296 --- openlp/core/ui/thememanager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index a5293e3a8..70bf78b29 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -284,6 +284,7 @@ class ThemeManager(QtGui.QWidget): plugin.renameTheme(old_theme_name, new_theme_name) self.mainwindow.renderer.update_theme( new_theme_name, old_theme_name) + self.loadThemes() def onCopyTheme(self): """ From bb9113ccdf4e5a810ccea8f10c3e9ade7832187e Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Tue, 16 Oct 2012 18:26:23 +0100 Subject: [PATCH 35/38] Fixed bug1067247 In the process uncovered a bug with transliteration, so fixed that also --- openlp/plugins/songs/lib/xml.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 55e9a0706..5fe6068df 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -763,18 +763,19 @@ class OpenLyrics(object): if not verse_number: verse_number = u'1' lang = verse.get(u'lang') + translit = verse.get(u'translit') # In OpenLP 1.9.6 we used v1a, v1b ... to represent visual slide # breaks. In OpenLyrics 0.7 an attribute has been added. if song_xml.get(u'modifiedIn') in (u'1.9.6', u'OpenLP 1.9.6') and \ song_xml.get(u'version') == u'0.7' and \ - (verse_tag, verse_number, lang) in verses: + (verse_tag, verse_number, translit, lang) in verses: verses[(verse_tag, verse_number, lang, None)] += u'\n[---]\n' + text # Merge v1a, v1b, .... to v1. - elif (verse_tag, verse_number, lang, verse_part) in verses: - verses[(verse_tag, verse_number, lang)] += u'\n' + text + elif (verse_tag, verse_number, lang, translit, verse_part) in verses: + verses[(verse_tag, verse_number, lang, translit, verse_part)] += u'\n' + text else: - verses[(verse_tag, verse_number, lang, verse_part)] = text - verse_def_list.append((verse_tag, verse_number, lang, verse_part)) + verses[(verse_tag, verse_number, lang, translit, verse_part)] = text + verse_def_list.append((verse_tag, verse_number, lang, translit, verse_part)) # We have to use a list to keep the order, as dicts are not sorted. for verse in verse_def_list: sxml.add_verse_to_lyrics( From 540fe6fd1bc71202a2dc5c57bea33669273570f3 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 16 Oct 2012 19:21:32 +0100 Subject: [PATCH 36/38] Slow down the Impress start up loop --- openlp/plugins/songs/lib/oooimport.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openlp/plugins/songs/lib/oooimport.py b/openlp/plugins/songs/lib/oooimport.py index 49e6c2a70..da96dc936 100644 --- a/openlp/plugins/songs/lib/oooimport.py +++ b/openlp/plugins/songs/lib/oooimport.py @@ -27,6 +27,7 @@ ############################################################################### import logging import os +import time from PyQt4 import QtCore @@ -123,6 +124,7 @@ class OooImport(SongImport): try: uno_instance = get_uno_instance(resolver) except NoConnectException: + time.sleep(0.1) log.exception("Failed to resolve uno connection") self.startOooProcess() loop += 1 From bd9a1e550b902e173c5ce83be45958b7b44e1af2 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Thu, 18 Oct 2012 00:00:44 +0200 Subject: [PATCH 37/38] Bug #1067703 fixed. --- openlp/core/ui/firsttimeform.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py index 14f1299de..6a18b2011 100644 --- a/openlp/core/ui/firsttimeform.py +++ b/openlp/core/ui/firsttimeform.py @@ -430,8 +430,11 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): 'Enabling selected plugins...')) self._setPluginStatus(self.songsCheckBox, u'songs/status') self._setPluginStatus(self.bibleCheckBox, u'bibles/status') - self._setPluginStatus(self.presentationCheckBox, - u'presentations/status') + # TODO Presentation plugin is not yet working on Mac OS X. + # For now just ignore it. + if sys.platform != 'darwin': + self._setPluginStatus(self.presentationCheckBox, + u'presentations/status') self._setPluginStatus(self.imageCheckBox, u'images/status') self._setPluginStatus(self.mediaCheckBox, u'media/status') self._setPluginStatus(self.remoteCheckBox, u'remotes/status') From e997d098f490f7540bb581588729460bebd0df7c Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Thu, 18 Oct 2012 21:22:48 +0100 Subject: [PATCH 38/38] spotted a couple mistakes --- openlp/plugins/songs/lib/xml.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 5fe6068df..407971ae0 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -768,8 +768,8 @@ class OpenLyrics(object): # breaks. In OpenLyrics 0.7 an attribute has been added. if song_xml.get(u'modifiedIn') in (u'1.9.6', u'OpenLP 1.9.6') and \ song_xml.get(u'version') == u'0.7' and \ - (verse_tag, verse_number, translit, lang) in verses: - verses[(verse_tag, verse_number, lang, None)] += u'\n[---]\n' + text + (verse_tag, verse_number, lang, translit) in verses: + verses[(verse_tag, verse_number, lang, translit, None)] += u'\n[---]\n' + text # Merge v1a, v1b, .... to v1. elif (verse_tag, verse_number, lang, translit, verse_part) in verses: verses[(verse_tag, verse_number, lang, translit, verse_part)] += u'\n' + text