diff --git a/blog/want-openlp-your-language.rst b/blog/want-openlp-your-language.rst new file mode 100644 index 0000000..51cf29f --- /dev/null +++ b/blog/want-openlp-your-language.rst @@ -0,0 +1,100 @@ +.. title: Want OpenLP in Your Language? +.. slug: want-openlp-your-language +.. date: 2015-10-03 01:17:00 UTC +.. tags: +.. category: +.. link: +.. description: +.. type: text +.. previewimage: /cover-images/want-openlp-your-language.jpg + +If you'd like to see OpenLP in your language, now's the time! We are about 2 weeks away from the release of 2.2, and +now is your opportunity to translate OpenLP's interface into your own language. + +In order for your langauge to be included you need to have completed the `translation of OpenLP 2.2`_ (you'll need to be +logged into `Transifex`_ to see this page) **by midnight UTC (GMT) on Saturday the 10th of October 2015**. + +Because we believe strongly in quality over quantity at OpenLP, we will not be including any translations that are +incomplete into the final build. **This means that if you want your language to be part of the final release of version +2.2, you need to make sure it is 100% done by the end of Saturday the 10th of October**. This deadline also gives you +just over a week to complete any outstanding translations. + +Languages Needing Work +^^^^^^^^^^^^^^^^^^^^^^ + +Currently, the following translations are more than 80% complete, but still need some work (ordered from most complete +to least complete). My estimate is that none of these should take longer than about 2 hours to complete. + +* Polish +* French +* Lithuanian +* Russian +* Portuguese (Brazil) +* Bulgarian + +The following translations are between 40% and 80% complete. Unless these are worked on this week, they probably won't +make it into the final release of OpenLP. + +* Thai (Thailand) +* Tamil (Sri-Lanka) +* Greek +* Afrikaans +* Chinese (China) +* Korean + +Lastly, the following translations are less than 40% complete. If any of these translations makes it into the final +release, I will be very surprised. + +* Slovenian +* Italian +* Macedonian +* Ukrainian +* Norweigian Nyorsk +* Papiamento +* Turkish +* Malayalam +* Latvian +* Spanish (Colombia) +* Arabic +* Albanian +* Korean (Korea) +* Ukranian (Ukraine) +* Khmer (Cambodia) +* Russian (Russia) +* Amharic +* English (United States) +* Klingon +* Arabic (Egypt) +* Spanish (Chile) +* Vietnamese (Viet Nam) +* Vietnamese + +Get started `translating OpenLP 2.2`_ (you'll need to be logged into `Transifex`_ to see this page). + +Testing Out Your Translation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To test your translation out, do the following: + +1. Make sure you are running version 2.1.6 +2. Install Qt Linguist +3. Windows and OS X users need to `download Qt Linguist`_ +4. Ubuntu, Fedora, and other Linux and Unix users can install Qt Linguist from their package manager +5. Download the language file from Transifex +6. Open it in Qt Linguist +7. Open the File menu, select "*Release*" and save the resulting release file with only your language code as the file name (see Transifex for your language code) +8. Copy the release file to OpenLP's i18n directory +9. Windows: ``C:\Program Files\OpenLP\i18n or C:\Program Files (x86)\OpenLP\i18n`` +10. Mac OS X: ``/Applications/OpenLP.app/Contents/MacOS/i18n/`` +11. Linux: ``/usr/share/openlp/i18n/`` +12. \*BSD: ``/usr/local/share/openlp/i18n/`` +13. (Re)start Openlp and select your language + +[ Image Credit: `Arddangosfa o gelf Zimbabwe yn newby Hall, Ripon`_ ] + +.. _translation of OpenLP 2.2: https://www.transifex.com/openlp/openlp/openlp-22x/ +.. _Transifex: https://www.transifex.com/ +.. _translating OpenLP 2.2: https://www.transifex.com/openlp/openlp/openlp-22x/ +.. _download Qt Linguist: http://code.google.com/p/qtlinguistdownload/downloads/list +.. _Arddangosfa o gelf Zimbabwe yn newby Hall, Ripon: https://www.flickr.com/photos/benbore/2800370449/ + diff --git a/conf.py b/conf.py index 28c0ff2..5295f93 100644 --- a/conf.py +++ b/conf.py @@ -677,7 +677,8 @@ COPY_SOURCES = False # #""" EXTRA_HEAD_DATA = """ - + + """ # Google Analytics or whatever else you use. Added to the bottom of @@ -691,6 +692,9 @@ EXTRA_HEAD_DATA = """ # # #""" +BODY_END = """ + +""" # The possibility to extract metadata from the filename by using a # regular expression. diff --git a/files/cover-images/want-openlp-in-your-language.jpg b/files/cover-images/want-openlp-your-language.jpg similarity index 100% rename from files/cover-images/want-openlp-in-your-language.jpg rename to files/cover-images/want-openlp-your-language.jpg diff --git a/files/files/ftw/do_not_delete.txt b/files/files/ftw/do_not_delete.txt new file mode 100644 index 0000000..36a413a --- /dev/null +++ b/files/files/ftw/do_not_delete.txt @@ -0,0 +1 @@ +Don't delete this directory! It's used to store the download.cfg file for the First Time Wizard. \ No newline at end of file diff --git a/files/screenshots/configuregeneral.png b/files/screenshots/configuregeneral.png new file mode 100644 index 0000000..aa59d48 Binary files /dev/null and b/files/screenshots/configuregeneral.png differ diff --git a/files/screenshots/mainwindow.png b/files/screenshots/mainwindow.png new file mode 100644 index 0000000..1230670 Binary files /dev/null and b/files/screenshots/mainwindow.png differ diff --git a/files/screenshots/song_edit_verse_in_use.png b/files/screenshots/song_edit_verse_in_use.png new file mode 100644 index 0000000..25cd66f Binary files /dev/null and b/files/screenshots/song_edit_verse_in_use.png differ diff --git a/files/screenshots/songimporterchoices.png b/files/screenshots/songimporterchoices.png new file mode 100644 index 0000000..527ad91 Binary files /dev/null and b/files/screenshots/songimporterchoices.png differ diff --git a/files/screenshots/stage_view_song_w_note.png b/files/screenshots/stage_view_song_w_note.png new file mode 100644 index 0000000..6b577c7 Binary files /dev/null and b/files/screenshots/stage_view_song_w_note.png differ diff --git a/themes/openlp2v2/assets/css/custom.css b/themes/openlp2v2/assets/css/custom.css index a0e08f8..3734f95 100644 --- a/themes/openlp2v2/assets/css/custom.css +++ b/themes/openlp2v2/assets/css/custom.css @@ -318,3 +318,9 @@ article blockquote p:first-child { p.indent { margin-left: 3em; } + +a.screenshot-gallery { + display: block; + border-radius: 6px; + border: 4px solid #efefef; +} diff --git a/themes/openlp2v2/assets/css/ekko-lightbox.css b/themes/openlp2v2/assets/css/ekko-lightbox.css new file mode 100644 index 0000000..ec3432f --- /dev/null +++ b/themes/openlp2v2/assets/css/ekko-lightbox.css @@ -0,0 +1,62 @@ +/*! + * Lightbox for Bootstrap 3 by @ashleydw + * https://github.com/ashleydw/lightbox + * + * License: https://github.com/ashleydw/lightbox/blob/master/LICENSE + */ + +.ekko-lightbox-container { + position: relative; +} + +.ekko-lightbox-nav-overlay { + position: absolute; + top: 0; + left: 0; + z-index: 100; + width: 100%; + height: 100%; +} + +.ekko-lightbox-nav-overlay a { + z-index: 100; + display: block; + width: 49%; + height: 100%; + font-size: 30px; + color: #fff; + text-shadow: 2px 2px 4px #000; + opacity: 0; + filter: dropshadow(color=#000000, offx=2, offy=2); + -webkit-transition: opacity 0.5s; + -moz-transition: opacity 0.5s; + -o-transition: opacity 0.5s; + transition: opacity 0.5s; +} + +.ekko-lightbox-nav-overlay a:empty { + width: 49%; +} + +.ekko-lightbox a:hover { + text-decoration: none; + opacity: 1; +} + +.ekko-lightbox .glyphicon-chevron-left { + left: 0; + float: left; + padding-left: 15px; + text-align: left; +} + +.ekko-lightbox .glyphicon-chevron-right { + right: 0; + float: right; + padding-right: 15px; + text-align: right; +} + +.ekko-lightbox .modal-footer { + text-align: left; +} \ No newline at end of file diff --git a/themes/openlp2v2/assets/js/custom.js b/themes/openlp2v2/assets/js/custom.js index 9b8ab8f..c54638f 100644 --- a/themes/openlp2v2/assets/js/custom.js +++ b/themes/openlp2v2/assets/js/custom.js @@ -33,4 +33,8 @@ $(function(){ $("#error-alert").removeClass("hidden"); } } + $(document).delegate('*[data-toggle="lightbox"]', 'click', function(event) { + event.preventDefault(); + $(this).ekkoLightbox(); + }); }); diff --git a/themes/openlp2v2/assets/js/ekko-lightbox.js b/themes/openlp2v2/assets/js/ekko-lightbox.js new file mode 100644 index 0000000..96e55f9 --- /dev/null +++ b/themes/openlp2v2/assets/js/ekko-lightbox.js @@ -0,0 +1,400 @@ +/* +Lightbox for Bootstrap 3 by @ashleydw +https://github.com/ashleydw/lightbox + +License: https://github.com/ashleydw/lightbox/blob/master/LICENSE +*/ + + +(function() { + "use strict"; + var $, EkkoLightbox; + + $ = jQuery; + + EkkoLightbox = function(element, options) { + var content, footer, header, + _this = this; + this.options = $.extend({ + title: null, + footer: null, + remote: null + }, $.fn.ekkoLightbox.defaults, options || {}); + this.$element = $(element); + content = ''; + this.modal_id = this.options.modal_id ? this.options.modal_id : 'ekkoLightbox-' + Math.floor((Math.random() * 1000) + 1); + header = ''; + footer = ''; + $(document.body).append(''); + this.modal = $('#' + this.modal_id); + this.modal_dialog = this.modal.find('.modal-dialog').first(); + this.modal_content = this.modal.find('.modal-content').first(); + this.modal_body = this.modal.find('.modal-body').first(); + this.lightbox_container = this.modal_body.find('.ekko-lightbox-container').first(); + this.lightbox_body = this.lightbox_container.find('> div:first-child').first(); + this.showLoading(); + this.modal_arrows = null; + this.border = { + top: parseFloat(this.modal_dialog.css('border-top-width')) + parseFloat(this.modal_content.css('border-top-width')) + parseFloat(this.modal_body.css('border-top-width')), + right: parseFloat(this.modal_dialog.css('border-right-width')) + parseFloat(this.modal_content.css('border-right-width')) + parseFloat(this.modal_body.css('border-right-width')), + bottom: parseFloat(this.modal_dialog.css('border-bottom-width')) + parseFloat(this.modal_content.css('border-bottom-width')) + parseFloat(this.modal_body.css('border-bottom-width')), + left: parseFloat(this.modal_dialog.css('border-left-width')) + parseFloat(this.modal_content.css('border-left-width')) + parseFloat(this.modal_body.css('border-left-width')) + }; + this.padding = { + top: parseFloat(this.modal_dialog.css('padding-top')) + parseFloat(this.modal_content.css('padding-top')) + parseFloat(this.modal_body.css('padding-top')), + right: parseFloat(this.modal_dialog.css('padding-right')) + parseFloat(this.modal_content.css('padding-right')) + parseFloat(this.modal_body.css('padding-right')), + bottom: parseFloat(this.modal_dialog.css('padding-bottom')) + parseFloat(this.modal_content.css('padding-bottom')) + parseFloat(this.modal_body.css('padding-bottom')), + left: parseFloat(this.modal_dialog.css('padding-left')) + parseFloat(this.modal_content.css('padding-left')) + parseFloat(this.modal_body.css('padding-left')) + }; + this.modal.on('show.bs.modal', this.options.onShow.bind(this)).on('shown.bs.modal', function() { + _this.modal_shown(); + return _this.options.onShown.call(_this); + }).on('hide.bs.modal', this.options.onHide.bind(this)).on('hidden.bs.modal', function() { + if (_this.gallery) { + $(document).off('keydown.ekkoLightbox'); + } + _this.modal.remove(); + return _this.options.onHidden.call(_this); + }).modal('show', options); + return this.modal; + }; + + EkkoLightbox.prototype = { + modal_shown: function() { + var video_id, + _this = this; + if (!this.options.remote) { + return this.error('No remote target given'); + } else { + this.gallery = this.$element.data('gallery'); + if (this.gallery) { + if (this.options.gallery_parent_selector === 'document.body' || this.options.gallery_parent_selector === '') { + this.gallery_items = $(document.body).find('*[data-toggle="lightbox"][data-gallery="' + this.gallery + '"]'); + } else { + this.gallery_items = this.$element.parents(this.options.gallery_parent_selector).first().find('*[data-toggle="lightbox"][data-gallery="' + this.gallery + '"]'); + } + this.gallery_index = this.gallery_items.index(this.$element); + $(document).on('keydown.ekkoLightbox', this.navigate.bind(this)); + if (this.options.directional_arrows && this.gallery_items.length > 1) { + this.lightbox_container.append('
'); + this.modal_arrows = this.lightbox_container.find('div.ekko-lightbox-nav-overlay').first(); + this.lightbox_container.find('a' + this.strip_spaces(this.options.left_arrow_class)).on('click', function(event) { + event.preventDefault(); + return _this.navigate_left(); + }); + this.lightbox_container.find('a' + this.strip_spaces(this.options.right_arrow_class)).on('click', function(event) { + event.preventDefault(); + return _this.navigate_right(); + }); + } + } + if (this.options.type) { + if (this.options.type === 'image') { + return this.preloadImage(this.options.remote, true); + } else if (this.options.type === 'youtube' && (video_id = this.getYoutubeId(this.options.remote))) { + return this.showYoutubeVideo(video_id); + } else if (this.options.type === 'vimeo') { + return this.showVimeoVideo(this.options.remote); + } else if (this.options.type === 'instagram') { + return this.showInstagramVideo(this.options.remote); + } else if (this.options.type === 'url') { + return this.loadRemoteContent(this.options.remote); + } else if (this.options.type === 'video') { + return this.showVideoIframe(this.options.remote); + } else { + return this.error("Could not detect remote target type. Force the type using data-type=\"image|youtube|vimeo|instagram|url|video\""); + } + } else { + return this.detectRemoteType(this.options.remote); + } + } + }, + strip_stops: function(str) { + return str.replace(/\./g, ''); + }, + strip_spaces: function(str) { + return str.replace(/\s/g, ''); + }, + isImage: function(str) { + return str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i); + }, + isSwf: function(str) { + return str.match(/\.(swf)((\?|#).*)?$/i); + }, + getYoutubeId: function(str) { + var match; + match = str.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/); + if (match && match[2].length === 11) { + return match[2]; + } else { + return false; + } + }, + getVimeoId: function(str) { + if (str.indexOf('vimeo') > 0) { + return str; + } else { + return false; + } + }, + getInstagramId: function(str) { + if (str.indexOf('instagram') > 0) { + return str; + } else { + return false; + } + }, + navigate: function(event) { + event = event || window.event; + if (event.keyCode === 39 || event.keyCode === 37) { + if (event.keyCode === 39) { + return this.navigate_right(); + } else if (event.keyCode === 37) { + return this.navigate_left(); + } + } + }, + navigateTo: function(index) { + var next, src; + if (index < 0 || index > this.gallery_items.length - 1) { + return this; + } + this.showLoading(); + this.gallery_index = index; + this.$element = $(this.gallery_items.get(this.gallery_index)); + this.updateTitleAndFooter(); + src = this.$element.attr('data-remote') || this.$element.attr('href'); + this.detectRemoteType(src, this.$element.attr('data-type') || false); + if (this.gallery_index + 1 < this.gallery_items.length) { + next = $(this.gallery_items.get(this.gallery_index + 1), false); + src = next.attr('data-remote') || next.attr('href'); + if (next.attr('data-type') === 'image' || this.isImage(src)) { + return this.preloadImage(src, false); + } + } + }, + navigate_left: function() { + if (this.gallery_items.length === 1) { + return; + } + if (this.gallery_index === 0) { + this.gallery_index = this.gallery_items.length - 1; + } else { + this.gallery_index--; + } + this.options.onNavigate.call(this, 'left', this.gallery_index); + return this.navigateTo(this.gallery_index); + }, + navigate_right: function() { + if (this.gallery_items.length === 1) { + return; + } + if (this.gallery_index === this.gallery_items.length - 1) { + this.gallery_index = 0; + } else { + this.gallery_index++; + } + this.options.onNavigate.call(this, 'right', this.gallery_index); + return this.navigateTo(this.gallery_index); + }, + detectRemoteType: function(src, type) { + var video_id; + type = type || false; + if (type === 'image' || this.isImage(src)) { + this.options.type = 'image'; + return this.preloadImage(src, true); + } else if (type === 'youtube' || (video_id = this.getYoutubeId(src))) { + this.options.type = 'youtube'; + return this.showYoutubeVideo(video_id); + } else if (type === 'vimeo' || (video_id = this.getVimeoId(src))) { + this.options.type = 'vimeo'; + return this.showVimeoVideo(video_id); + } else if (type === 'instagram' || (video_id = this.getInstagramId(src))) { + this.options.type = 'instagram'; + return this.showInstagramVideo(video_id); + } else if (type === 'video') { + this.options.type = 'video'; + return this.showVideoIframe(video_id); + } else { + this.options.type = 'url'; + return this.loadRemoteContent(src); + } + }, + updateTitleAndFooter: function() { + var caption, footer, header, title; + header = this.modal_content.find('.modal-header'); + footer = this.modal_content.find('.modal-footer'); + title = this.$element.data('title') || ""; + caption = this.$element.data('footer') || ""; + if (title || this.options.always_show_close) { + header.css('display', '').find('.modal-title').html(title || " "); + } else { + header.css('display', 'none'); + } + if (caption) { + footer.css('display', '').html(caption); + } else { + footer.css('display', 'none'); + } + return this; + }, + showLoading: function() { + this.lightbox_body.html(''); + return this; + }, + showYoutubeVideo: function(id) { + var height, width; + width = this.checkDimensions(this.$element.data('width') || 560); + height = width / (560 / 315); + return this.showVideoIframe('//www.youtube.com/embed/' + id + '?badge=0&autoplay=1&html5=1', width, height); + }, + showVimeoVideo: function(id) { + var height, width; + width = this.checkDimensions(this.$element.data('width') || 560); + height = width / (500 / 281); + return this.showVideoIframe(id + '?autoplay=1', width, height); + }, + showInstagramVideo: function(id) { + var height, width; + width = this.checkDimensions(this.$element.data('width') || 612); + this.resize(width); + height = width + 80; + this.lightbox_body.html(''); + this.options.onContentLoaded.call(this); + if (this.modal_arrows) { + return this.modal_arrows.css('display', 'none'); + } + }, + showVideoIframe: function(url, width, height) { + height = height || width; + this.resize(width); + this.lightbox_body.html('
'); + this.options.onContentLoaded.call(this); + if (this.modal_arrows) { + this.modal_arrows.css('display', 'none'); + } + return this; + }, + loadRemoteContent: function(url) { + var disableExternalCheck, width, + _this = this; + width = this.$element.data('width') || 560; + this.resize(width); + disableExternalCheck = this.$element.data('disableExternalCheck') || false; + if (!disableExternalCheck && !this.isExternal(url)) { + this.lightbox_body.load(url, $.proxy(function() { + return _this.$element.trigger('loaded.bs.modal'); + })); + } else { + this.lightbox_body.html(''); + this.options.onContentLoaded.call(this); + } + if (this.modal_arrows) { + this.modal_arrows.css('display', 'none'); + } + return this; + }, + isExternal: function(url) { + var match; + match = url.match(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/); + if (typeof match[1] === "string" && match[1].length > 0 && match[1].toLowerCase() !== location.protocol) { + return true; + } + if (typeof match[2] === "string" && match[2].length > 0 && match[2].replace(new RegExp(":(" + { + "http:": 80, + "https:": 443 + }[location.protocol] + ")?$"), "") !== location.host) { + return true; + } + return false; + }, + error: function(message) { + this.lightbox_body.html(message); + return this; + }, + preloadImage: function(src, onLoadShowImage) { + var img, + _this = this; + img = new Image(); + if ((onLoadShowImage == null) || onLoadShowImage === true) { + img.onload = function() { + var image; + image = $(''); + image.attr('src', img.src); + image.addClass('img-responsive'); + _this.lightbox_body.html(image); + if (_this.modal_arrows) { + _this.modal_arrows.css('display', 'block'); + } + return image.load(function() { + _this.resize(img.width); + return _this.options.onContentLoaded.call(_this); + }); + }; + img.onerror = function() { + return _this.error('Failed to load image: ' + src); + }; + } + img.src = src; + return img; + }, + resize: function(width) { + var width_total; + width_total = width + this.border.left + this.padding.left + this.padding.right + this.border.right; + this.modal_dialog.css('width', 'auto').css('max-width', width_total); + this.lightbox_container.find('a').css('line-height', function() { + return $(this).parent().height() + 'px'; + }); + return this; + }, + checkDimensions: function(width) { + var body_width, width_total; + width_total = width + this.border.left + this.padding.left + this.padding.right + this.border.right; + body_width = document.body.clientWidth; + if (width_total > body_width) { + width = this.modal_body.width(); + } + return width; + }, + close: function() { + return this.modal.modal('hide'); + }, + addTrailingSlash: function(url) { + if (url.substr(-1) !== '/') { + url += '/'; + } + return url; + } + }; + + $.fn.ekkoLightbox = function(options) { + return this.each(function() { + var $this; + $this = $(this); + options = $.extend({ + remote: $this.attr('data-remote') || $this.attr('href'), + gallery_parent_selector: $this.attr('data-parent'), + type: $this.attr('data-type') + }, options, $this.data()); + new EkkoLightbox(this, options); + return this; + }); + }; + + $.fn.ekkoLightbox.defaults = { + gallery_parent_selector: 'document.body', + left_arrow_class: '.glyphicon .glyphicon-chevron-left', + right_arrow_class: '.glyphicon .glyphicon-chevron-right', + directional_arrows: true, + type: null, + always_show_close: true, + loadingMessage: 'Loading...', + onShow: function() {}, + onShown: function() {}, + onHide: function() {}, + onHidden: function() {}, + onNavigate: function() {}, + onContentLoaded: function() {} + }; + +}).call(this); diff --git a/themes/openlp2v2/bundles b/themes/openlp2v2/bundles index adb460b..af9b966 100644 --- a/themes/openlp2v2/bundles +++ b/themes/openlp2v2/bundles @@ -1,4 +1,4 @@ -assets/css/all-nocdn.css=bootstrap.css,font-awesome.css,rst.css,code.css,colorbox.css,theme.css,animate.css,animations.css,style.css,custom.css -assets/css/all.css=font-awesome.css,rst.css,code.css,colorbox.css,theme.css,animate.css,animations.css,style.css,custom.css -assets/js/all-nocdn.js=jquery.min.js,bootstrap.min.js,jquery.colorbox-min.js,jquery.appear.js,jquery.backstretch.js,modernizr.js,isotope.js,template.js,custom.js -assets/js/all.js=jquery.colorbox-min.js,jquery.appear.js,jquery.backstretch.js,modernizr.js,isotope.js,template.js,custom.js +assets/css/all-nocdn.css=bootstrap.css,font-awesome.css,rst.css,code.css,colorbox.css,theme.css,animate.css,animations.css,ekko-lightbox.css,style.css,custom.css +assets/css/all.css=font-awesome.css,rst.css,code.css,colorbox.css,theme.css,animate.css,animations.css,ekko-lightbox.css,style.css,custom.css +assets/js/all-nocdn.js=jquery.min.js,bootstrap.min.js,jquery.colorbox-min.js,jquery.appear.js,jquery.backstretch.js,modernizr.js,isotope.js,ekko-lightbox.js,template.js,custom.js +assets/js/all.js=jquery.colorbox-min.js,jquery.appear.js,jquery.backstretch.js,modernizr.js,isotope.js,ekko-lightbox.js,template.js,custom.js diff --git a/themes/openlp2v2/templates/front_page.html b/themes/openlp2v2/templates/front_page.html index f4a968b..aa7142b 100644 --- a/themes/openlp2v2/templates/front_page.html +++ b/themes/openlp2v2/templates/front_page.html @@ -122,6 +122,27 @@

+
+
+

Screenshots

+
+
+ +
+