← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~j-corwin/openlp/general into lp:openlp

 

Jonathan Corwin has proposed merging lp:~j-corwin/openlp/general into lp:openlp.

Requested reviews:
  Tim Bentley (trb143)
  Raoul Snyman (raoul-snyman)
Related bugs:
  Bug #634771 in OpenLP: "OpenLP 1.9.2+bzr1016-0ubuntu1~lucid1 does not start"
  https://bugs.launchpad.net/openlp/+bug/634771
  Bug #646718 in OpenLP: "Songbook, Number will not loaded, Title will not be saved"
  https://bugs.launchpad.net/openlp/+bug/646718
  Bug #696013 in OpenLP: "song import from powerpoint crashes every second time"
  https://bugs.launchpad.net/openlp/+bug/696013
  Bug #696021 in OpenLP: "presentation loader does not work fine in Windows using Powerpoint Viewer 2007"
  https://bugs.launchpad.net/openlp/+bug/696021
  Bug #696637 in OpenLP: "Alert not positioned correctly in single screen"
  https://bugs.launchpad.net/openlp/+bug/696637
  Bug #727732 in OpenLP: "Openlp 1.9.?? crashes on start"
  https://bugs.launchpad.net/openlp/+bug/727732
  Bug #735039 in OpenLP: "Cannot import PowerPoint Presentations with PowerPoint 2010"
  https://bugs.launchpad.net/openlp/+bug/735039

For more details, see:
https://code.launchpad.net/~j-corwin/openlp/general/+merge/60292

Attempt at implementing a remote "Stage" view
Fix remote browser so it highlights correct item if an item is in the service twice
Remove a redundant method

 - Removed link from remote page, now accessed via /stage
 - Put back stuff I inadvertently removed!
 - Added a couple of labels to the remote settings tab with the links to the remote pages
-- 
https://code.launchpad.net/~j-corwin/openlp/general/+merge/60292
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/eventreceiver.py'
--- openlp/core/lib/eventreceiver.py	2011-03-25 17:49:53 +0000
+++ openlp/core/lib/eventreceiver.py	2011-05-07 22:28:26 +0000
@@ -111,10 +111,6 @@
     ``servicemanager_set_item``
         Go live on a specific item, by index
 
-    ``servicemanager_list_request``
-        Request the service list. Responds with servicemanager_list_response
-        containing a array of dictionaries
-
     ``maindisplay_blank``
         Blank the maindisplay window
 

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2011-05-06 05:17:13 +0000
+++ openlp/core/ui/servicemanager.py	2011-05-07 22:28:26 +0000
@@ -275,8 +275,6 @@
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'servicemanager_set_item'), self.onSetItem)
         QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'servicemanager_list_request'), self.listRequest)
-        QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'config_updated'), self.configUpdated)
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'config_screen_changed'),
@@ -1307,23 +1305,6 @@
         else:
             return parentitem.data(0, QtCore.Qt.UserRole).toInt()[0]
 
-    def listRequest(self, message=None):
-        data = []
-        item = self.findServiceItem()[0]
-        if item >= 0 and item < len(self.serviceItems):
-            curitem = self.serviceItems[item]
-        else:
-            curitem = None
-        for item in self.serviceItems:
-            service_item = item[u'service_item']
-            data_item = {}
-            data_item[u'title'] = unicode(service_item.get_display_title())
-            data_item[u'plugin'] = unicode(service_item.name)
-            data_item[u'notes'] = unicode(service_item.notes)
-            data_item[u'selected'] = (item == curitem)
-            data.append(data_item)
-        Receiver.send_message(u'servicemanager_list_response', data)
-
     def printServiceOrder(self):
         """
         Print a Service Order Sheet.

=== modified file 'openlp/plugins/remotes/html/openlp.js'
--- openlp/plugins/remotes/html/openlp.js	2011-05-05 18:48:11 +0000
+++ openlp/plugins/remotes/html/openlp.js	2011-05-07 22:28:26 +0000
@@ -48,6 +48,7 @@
         $.each(data.results.items, function (idx, value) {
           var li = $("<li data-icon=\"false\">").append(
             $("<a href=\"#\">").attr("value", parseInt(idx, 10)).text(value["title"]));
+          li.attr("uuid", value["id"])
           li.children("a").click(OpenLP.setItem);
           ul.append(li);
         });
@@ -119,10 +120,10 @@
           $("#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);
-            if (item.text() == OpenLP.currentItem) {
-              while (item[0].tagName != "LI") {
-                item = item.parent();
-              }
+            while (item[0].tagName != "LI") {
+              item = item.parent();
+            }
+            if (item.attr("uuid") == OpenLP.currentItem) {
               item.attr("data-theme", "e").removeClass("ui-btn-up-c").addClass("ui-btn-up-e");
               return false;
             }

=== added file 'openlp/plugins/remotes/html/stage.css'
--- openlp/plugins/remotes/html/stage.css	1970-01-01 00:00:00 +0000
+++ openlp/plugins/remotes/html/stage.css	2011-05-07 22:28:26 +0000
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ * OpenLP - Open Source Lyrics Projection                                    *
+ * ------------------------------------------------------------------------- *
+ * Copyright (c) 2008-2010 Raoul Snyman                                      *
+ * Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael    *
+ * Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler,      *
+ * Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,    *
+ * Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund           *
+ * ------------------------------------------------------------------------- *
+ * This program is free software; you can redistribute it and/or modify it   *
+ * under the terms of the GNU General Public License as published by the     *
+ * Free Software Foundation; version 2 of the License.                       *
+ *                                                                           *
+ * This program is distributed in the hope that it will be useful, but       *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of                *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General  *
+ * Public License for more details.                                          *
+ *                                                                           *
+ * You should have received a copy of the GNU General Public License along   *
+ * with this program; if not, write to the Free Software Foundation, Inc.,   *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     *
+ *****************************************************************************/
+ 
+body {
+  background-color: black;
+  font-family: sans-serif;
+  overflow: hidden;
+}
+
+#currentslide {
+  font-size: 40pt;
+  color: white;
+}
+
+#nextslide {
+  font-size: 30pt;
+  color: grey;
+  padding-top: 25px;
+}
+
+#right {
+  float: right;
+}
+
+#clock {
+  font-size: 40pt;
+  color: yellow;
+  text-align: right;
+}
+
+#notes {
+  font-size: 36pt;
+  color: salmon;
+  text-align: right;
+}
+
+#verseorder {
+  font-size: 30pt;
+  color: green;
+  text-align: left;
+}
+
+.currenttag {
+   color: lightgreen;
+   font-weight: bold;
+}

=== added file 'openlp/plugins/remotes/html/stage.html'
--- openlp/plugins/remotes/html/stage.html	1970-01-01 00:00:00 +0000
+++ openlp/plugins/remotes/html/stage.html	2011-05-07 22:28:26 +0000
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<!--
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      #
+# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler,        #
+# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,      #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund             #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+-->
+<head>
+  <meta charset="utf-8" />
+  <title>OpenLP 2.0 Remote</title>
+  <link rel="stylesheet" href="/files/stage.css" />
+  <script type="text/javascript" src="/files/jquery.js"></script>
+  <script type="text/javascript" src="/files/stage.js"></script>
+</head>
+<body>
+<div id="right">
+  <div id="clock"></div>
+  <div id="notes"></div>
+</div>
+<div id="verseorder"></div>
+<div id="currentslide"></div>
+<div id="nextslide"></div>
+</body>
+</html>

=== added file 'openlp/plugins/remotes/html/stage.js'
--- openlp/plugins/remotes/html/stage.js	1970-01-01 00:00:00 +0000
+++ openlp/plugins/remotes/html/stage.js	2011-05-07 22:28:26 +0000
@@ -0,0 +1,104 @@
+/*****************************************************************************
+ * OpenLP - Open Source Lyrics Projection                                    *
+ * ------------------------------------------------------------------------- *
+ * Copyright (c) 2008-2010 Raoul Snyman                                      *
+ * Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael    *
+ * Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler,      *
+ * Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,    *
+ * Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund           *
+ * ------------------------------------------------------------------------- *
+ * This program is free software; you can redistribute it and/or modify it   *
+ * under the terms of the GNU General Public License as published by the     *
+ * Free Software Foundation; version 2 of the License.                       *
+ *                                                                           *
+ * This program is distributed in the hope that it will be useful, but       *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of                *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General  *
+ * Public License for more details.                                          *
+ *                                                                           *
+ * You should have received a copy of the GNU General Public License along   *
+ * with this program; if not, write to the Free Software Foundation, Inc.,   *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     *
+ *****************************************************************************/
+window.OpenLP = {
+  loadService: function (event) {
+    $.getJSON(
+      "/api/service/list",
+      function (data, status) {
+        OpenLP.nextSong = "";
+        $("#notes").html("");
+        for (idx in data.results.items) {
+          idx = parseInt(idx, 10);
+          if ((data.results.items[idx]["selected"]) && 
+            (data.results.items.length > idx + 1)) {
+            $("#notes").html(data.results.items[idx]["notes"]);
+            OpenLP.nextSong = data.results.items[idx + 1]["title"];
+            break;
+          }
+        }
+        OpenLP.updateSlide();
+      }
+    );
+  },
+  loadSlides: function (event) {
+    $.getJSON(
+      "/api/controller/live/text",
+      function (data, status) {
+        OpenLP.currentSlides = data.results.slides;
+        OpenLP.currentSlide = 0;
+        var div = $("#verseorder");
+        div.html("");
+        for (idx in data.results.slides) {
+          idx = parseInt(idx, 10);
+          div.append("&nbsp;<span>");
+          var tag = data.results.slides[idx]["tag"];
+          if (tag == 'None')
+            tag = idx;
+          $("#verseorder span").last().attr("id", "tag" + idx).text(tag);
+          if (data.results.slides[idx]["selected"]) 
+            OpenLP.currentSlide = idx;
+        }
+        OpenLP.loadService();
+      }
+    );
+  },
+  updateSlide: function() {
+    $("#verseorder span").removeClass("currenttag");
+    $("#tag" + OpenLP.currentSlide).addClass("currenttag");
+    $("#currentslide").html(OpenLP.currentSlides[OpenLP.currentSlide]["text"]);
+    if (OpenLP.currentSlide < OpenLP.currentSlides.length - 1) 
+      $("#nextslide").html(OpenLP.currentSlides[OpenLP.currentSlide + 1]["text"]);
+    else 
+      $("#nextslide").html("Next: " + OpenLP.nextSong);
+  },
+  updateClock: function() {
+    var div = $("#clock");
+    var t = new Date(); 
+    var h = t.getHours();
+    if (h > 12) 
+      h = h - 12;
+    var m = t.getMinutes();
+    if (m < 10)
+      m = '0' + m + '';
+    div.html(h + ":" + m);
+  },
+  pollServer: function () {
+    $.getJSON(
+      "/api/poll",
+      function (data, status) {
+        OpenLP.updateClock();
+        if (OpenLP.currentItem != data.results.item) {
+          OpenLP.currentItem = data.results.item;
+          OpenLP.loadSlides();
+        } 
+        else if (OpenLP.currentSlide != data.results.slide) {
+          OpenLP.currentSlide = parseInt(data.results.slide, 10);
+          OpenLP.updateSlide();
+        }
+      }
+    );
+  }
+}
+$.ajaxSetup({ cache: false });
+setInterval("OpenLP.pollServer();", 500);
+OpenLP.pollServer();

=== modified file 'openlp/plugins/remotes/lib/httpserver.py'
--- openlp/plugins/remotes/lib/httpserver.py	2011-03-24 19:04:02 +0000
+++ openlp/plugins/remotes/lib/httpserver.py	2011-05-07 22:28:26 +0000
@@ -34,6 +34,9 @@
 ``/``
     Go to the web interface.
 
+``/stage``
+    Show the stage view.
+
 ``/files/{filename}``
     Serve a static file.
 
@@ -241,6 +244,7 @@
         self.parent = parent
         self.routes = [
             (u'^/$', self.serve_file),
+            (u'^/(stage)$', self.serve_file),
             (r'^/files/(.*)$', self.serve_file),
             (r'^/api/poll$', self.poll),
             (r'^/api/controller/(live|preview)/(.*)$', self.controller),
@@ -256,18 +260,18 @@
     def _get_service_items(self):
         service_items = []
         service_manager = self.parent.parent.serviceManager
-        item = service_manager.findServiceItem()[0]
-        if item >= 0 and item < len(service_manager.serviceItems):
-            curitem = service_manager.serviceItems[item]
+        if self.parent.current_item:
+            cur_uuid = self.parent.current_item._uuid
         else:
-            curitem = None
+            cur_uuid = None
         for item in service_manager.serviceItems:
             service_item = item[u'service_item']
             service_items.append({
+                u'id': unicode(service_item._uuid),
                 u'title': unicode(service_item.get_display_title()),
                 u'plugin': unicode(service_item.name),
                 u'notes': unicode(service_item.notes),
-                u'selected': (item == curitem)
+                u'selected': (service_item._uuid == cur_uuid)
             })
         return service_items
 
@@ -312,6 +316,8 @@
         log.debug(u'serve file request %s' % filename)
         if not filename:
             filename = u'index.html'
+        elif filename == u'stage':
+            filename = u'stage.html'
         path = os.path.normpath(os.path.join(self.parent.html_dir, filename))
         if not path.startswith(self.parent.html_dir):
             return HttpResponse(code=u'404 Not Found')
@@ -349,7 +355,7 @@
         """
         result = {
             u'slide': self.parent.current_slide or 0,
-            u'item': self.parent.current_item.title \
+            u'item': self.parent.current_item._uuid \
                 if self.parent.current_item else u''
         }
         return HttpResponse(json.dumps({u'results': result}),

=== modified file 'openlp/plugins/remotes/lib/remotetab.py'
--- openlp/plugins/remotes/lib/remotetab.py	2011-04-13 19:12:47 +0000
+++ openlp/plugins/remotes/lib/remotetab.py	2011-05-07 22:28:26 +0000
@@ -24,10 +24,12 @@
 # Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
 ###############################################################################
 
-from PyQt4 import QtCore, QtGui
+from PyQt4 import QtCore, QtGui, QtNetwork
 
 from openlp.core.lib import SettingsTab, translate
 
+ZERO_URL = u'0.0.0.0'
+
 class RemoteTab(SettingsTab):
     """
     RemoteTab is the Remotes settings tab in the settings dialog.
@@ -51,13 +53,29 @@
         self.addressEdit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(
             u'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'), self))
         self.addressEdit.setObjectName(u'addressEdit')
+        QtCore.QObject.connect(self.addressEdit,
+            QtCore.SIGNAL(u'textChanged(const QString&)'), self.setUrls)
         self.serverSettingsLayout.addRow(self.addressLabel, self.addressEdit)
         self.portLabel = QtGui.QLabel(self.serverSettingsGroupBox)
         self.portLabel.setObjectName(u'portLabel')
         self.portSpinBox = QtGui.QSpinBox(self.serverSettingsGroupBox)
         self.portSpinBox.setMaximum(32767)
         self.portSpinBox.setObjectName(u'portSpinBox')
+        QtCore.QObject.connect(self.portSpinBox,
+            QtCore.SIGNAL(u'valueChanged(int)'), self.setUrls)
         self.serverSettingsLayout.addRow(self.portLabel, self.portSpinBox)
+        self.remoteUrlLabel = QtGui.QLabel(self.serverSettingsGroupBox)
+        self.remoteUrlLabel.setObjectName(u'remoteUrlLabel')
+        self.remoteUrl = QtGui.QLabel(self.serverSettingsGroupBox)
+        self.remoteUrl.setObjectName(u'remoteUrl')
+        self.remoteUrl.setOpenExternalLinks(True)
+        self.serverSettingsLayout.addRow(self.remoteUrlLabel, self.remoteUrl)
+        self.stageUrlLabel = QtGui.QLabel(self.serverSettingsGroupBox)
+        self.stageUrlLabel.setObjectName(u'stageUrlLabel')
+        self.stageUrl = QtGui.QLabel(self.serverSettingsGroupBox)
+        self.stageUrl.setObjectName(u'stageUrl')
+        self.stageUrl.setOpenExternalLinks(True)
+        self.serverSettingsLayout.addRow(self.stageUrlLabel, self.stageUrl)
         self.leftLayout.addWidget(self.serverSettingsGroupBox)
         self.leftLayout.addStretch()
         self.rightLayout.addStretch()
@@ -69,6 +87,34 @@
             'Serve on IP address:'))
         self.portLabel.setText(translate('RemotePlugin.RemoteTab',
             'Port number:'))
+        self.remoteUrlLabel.setText(translate('RemotePlugin.RemoteTab',
+            'Remote URL:'))
+        self.stageUrlLabel.setText(translate('RemotePlugin.RemoteTab',
+            'Stage view URL:'))
+
+    def setUrls(self):
+        ipAddress = None
+        if self.addressEdit.text() == ZERO_URL:
+            for ip in QtNetwork.QNetworkInterface.allAddresses():
+                if ip.protocol() == 0 and ip != QtNetwork.QHostAddress.LocalHost:
+                    ipAddress = ip.toString()
+                    break
+        else:
+            ipAddress = self.addressEdit.text()
+        if not ipAddress:
+            self.remoteUrlLabel.setVisible(False)
+            self.remoteUrl.setVisible(False)
+            self.stageUrlLabel.setVisible(False)
+            self.stageUrl.setVisible(False)
+            return
+        self.remoteUrlLabel.setVisible(True)
+        self.remoteUrl.setVisible(True)
+        self.stageUrlLabel.setVisible(True)
+        self.stageUrl.setVisible(True)
+        url = u'http://%s:%s/' % (ipAddress, self.portSpinBox.value())
+        self.remoteUrl.setText(u'<a href="%s">%s</a>' % (url, url))
+        url = url + u'stage'
+        self.stageUrl.setText(u'<a href="%s">%s</a>' % (url, url))
 
     def load(self):
         self.portSpinBox.setValue(
@@ -76,7 +122,8 @@
                 QtCore.QVariant(4316)).toInt()[0])
         self.addressEdit.setText(
             QtCore.QSettings().value(self.settingsSection + u'/ip address',
-                QtCore.QVariant(u'0.0.0.0')).toString())
+                QtCore.QVariant(ZERO_URL)).toString())
+        self.setUrls()
 
     def save(self):
         QtCore.QSettings().setValue(self.settingsSection + u'/port',


Follow ups