← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/ThemeManager into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/ThemeManager into lp:openlp.

Requested reviews:
    openlp.org Core (openlp-core)

Initial version of Theme Manager with Import Functionality.
Updated Renderer to use Qgradient for gradients.

Improvements will continue once new Theme xml schema is confirmed.
-- 
https://code.launchpad.net/~trb143/openlp/ThemeManager/+merge/5014
Your team openlp.org Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py	2009-03-23 20:18:06 +0000
+++ openlp/core/lib/__init__.py	2009-03-28 20:12:22 +0000
@@ -31,7 +31,9 @@
 from toolbar import OpenLPToolbar
 from songxmlhandler import SongXMLBuilder
 from songxmlhandler import SongXMLParser
+from themexmlhandler import ThemeXMLBuilder
+from themexmlhandler import ThemeXMLParser
 
 __all__ = ['PluginConfig', 'Plugin', 'SettingsTab', 'MediaManagerItem', 'Event', 'EventType'
-           'XmlRootClass', 'ServiceItem', 'Receiver', 'OpenLPToolbar', 'SongXMLBuilder', 
-           'SongXMLParser', 'EventManager']
+           'XmlRootClass', 'ServiceItem', 'Receiver', 'OpenLPToolbar', 'SongXMLBuilder',
+           'SongXMLParser', 'EventManager', 'ThemeXMLBuilder', 'ThemeXMLParser']

=== added file 'openlp/core/lib/themexmlhandler.py'
--- openlp/core/lib/themexmlhandler.py	1970-01-01 00:00:00 +0000
+++ openlp/core/lib/themexmlhandler.py	2009-03-28 20:12:22 +0000
@@ -0,0 +1,118 @@
+from xml.dom.minidom import  Document
+from xml.etree.ElementTree import ElementTree, XML, dump
+"""
+<?xml version="1.0" encoding="UTF-8"?>
+<song version="1.0">
+   <lyrics language="en">
+       <verse type="chorus" label="1">
+           <![CDATA[ ... ]]>
+       </verse>
+   </lyrics>
+</song>
+
+"""
+class ThemeXMLBuilder():
+    def __init__(self):
+        # Create the minidom document
+        self.theme_xml = Document()
+
+    def new_document(self, name):
+        # Create the <song> base element
+        self.theme = self.theme_xml.createElement(u'Theme')
+        self.theme_xml.appendChild(self.theme)
+        self.theme.setAttribute(u'version', u'1.0')
+
+        self.name = self.theme_xml.createElement(u'Name')
+        ctn = self.theme_xml.createTextNode(name)
+        self.name.appendChild(ctn)
+        self.theme.appendChild(self.name)
+
+    def add_background_transparent(self):
+        # Create the main <lyrics> element
+        background = self.theme_xml.createElement(u'Background')
+        background.setAttribute(u'mode', u'transparent')
+        self.theme.appendChild(background)
+
+    def add_background_solid(self, bkcolor):
+        background = self.theme_xml.createElement(u'Background')
+        background.setAttribute(u'mode', u'opaque')
+        background.setAttribute(u'type', u'solid')
+        self.theme.appendChild(background)
+
+        color = self.theme_xml.createElement(u'color')
+        bkc = self.theme_xml.createTextNode(bkcolor)
+        color.appendChild(bkc)
+        background.appendChild(color)
+
+    def add_background_gradient(self, startcolor, endcolor):
+        background = self.theme_xml.createElement(u'Background')
+        background.setAttribute(u'mode', u'opaque')
+        background.setAttribute(u'type', u'gradient')
+        self.theme.appendChild(background)
+
+        color = self.theme_xml.createElement(u'startcolor')
+        bkc = self.theme_xml.createTextNode(startcolor)
+        color.appendChild(bkc)
+        background.appendChild(color)
+
+        color = self.theme_xml.createElement(u'endcolor')
+        bkc = self.theme_xml.createTextNode(endcolor)
+        color.appendChild(bkc)
+        background.appendChild(color)
+
+    def add_background_image(self, filename, bordercolor):
+        background = self.theme_xml.createElement(u'Background')
+        background.setAttribute(u'mode', u'opaque')
+        background.setAttribute(u'type', u'image')
+        self.theme.appendChild(background)
+
+        color = self.theme_xml.createElement(u'filename')
+        bkc = self.theme_xml.createCDATASection(filename)
+        color.appendChild(bkc)
+        background.appendChild(color)
+
+        color = self.theme_xml.createElement(u'bordercolor')
+        bkc = self.theme_xml.createTextNode(bordercolor)
+        color.appendChild(bkc)
+        background.appendChild(color)
+
+
+    def add_verse_to_lyrics(self, type, number, content):
+        """
+        type - type of verse (Chorus, Verse , Bridge, Custom etc
+        number - number of item eg verse 1
+        content - the text to be stored
+        """
+        verse = self.theme_xml.createElement(u'verse')
+        verse.setAttribute(u'type', type)
+        verse.setAttribute(u'label', number)
+        self.lyrics.appendChild(verse)
+
+        # add data as a CDATA section
+        cds = self.theme_xml.createCDATASection(content)
+        verse.appendChild(cds)
+
+    def dump_xml(self):
+        # Debugging aid to see what we have
+        print self.theme_xml.toprettyxml(indent="  ")
+
+    def extract_xml(self):
+        # Print our newly created XML
+        return self.theme_xml.toxml()
+
+class ThemeXMLParser():
+    def __init__(self, xml):
+        self.theme_xml = ElementTree(element=XML(xml))
+
+    def get_verses(self):
+        #return a list of verse's and attributes
+        iter=self.theme_xml.getiterator()
+        verse_list = []
+        for element in iter:
+            if element.tag == u'verse':
+                verse_list.append([element.attrib, element.text])
+        return verse_list
+
+    def dump_xml(self):
+        # Debugging aid to see what we have
+        print dump(self.theme_xml)

=== modified file 'openlp/core/render.py'
--- openlp/core/render.py	2009-03-22 07:13:34 +0000
+++ openlp/core/render.py	2009-03-29 16:51:42 +0000
@@ -17,13 +17,19 @@
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place, Suite 330, Boston, MA 02111-1307 USA
 """
+import logging
 
 import sys
 from PyQt4 import QtGui, QtCore, Qt
 
 from copy import copy
 from interpolate import interpolate
+
 class Renderer:
+
+    global log
+    log=logging.getLogger(u'Renderer')
+    log.info(u'Renderer Loaded')
     """All the functions for rendering a set of words onto a Device Context
 
     How to use:
@@ -44,21 +50,21 @@
         self._theme=None
         self._bg_image_filename=None
         self._paint=None
-        
+
     def set_debug(self, debug):
         self._debug=debug
-        
+
     def set_theme(self, theme):
         self._theme=theme
         if theme.BackgroundType == 2:
             self.set_bg_image(theme.BackgroundParameter1)
 
     def set_bg_image(self, filename):
-        print "set bg image", filename
+        log.debug(u"set bg image %s", filename)
         self._bg_image_filename=filename
         if self._paint is not None:
             self.scale_bg_image()
-            
+
     def scale_bg_image(self):
         assert self._paint
         i=QtGui.QImage(self._bg_image_filename)
@@ -67,7 +73,7 @@
         dcw=self._paint.width()+1;dch=self._paint.height()
         imratio=imw/float(imh)
         dcratio=dcw/float(dch)
-        print "Image scaling params", imw, imh, imratio, dcw, dch, dcratio
+        log.debug(u"Image scaling params %s %s %s %s %s %s", imw, imh, imratio, dcw, dch, dcratio)
         if imratio > dcratio:
             scale=dcw/float(imw)
         elif imratio < dcratio:
@@ -84,9 +90,9 @@
         self._paint=p
         if self._bg_image_filename is not None:
             self.scale_bg_image()
-            
+
     def set_words_openlp(self, words):
-#         print "set words openlp", words
+#         log.debug(u" "set words openlp", words
         verses=[]
         words=words.replace("\r\n", "\n")
         verses_text=words.split('\n\n')
@@ -99,9 +105,9 @@
             verses_text.append('\n'.join(v).lstrip()) # remove first \n
 
         return verses_text
-        
+
     def render_screen(self, screennum):
-        print "render screen\n", screennum, self.words[screennum]
+        log.debug(u"render screen\n %s %s ", screennum, self.words[screennum])
         import time
         t=0.0
         words=self.words[screennum]
@@ -111,51 +117,45 @@
     def set_text_rectangle(self, rect):
         """ Sets the rectangle within which text should be rendered"""
         self._rect=rect
-        
+
     def _render_background(self):
-        # xxx may have to prerender to a memdc when set theme is called for use on slow machines
-        # takes 26ms on mijiti's machine!
         assert(self._theme)
         assert(self._paint)
-        print "render background", self._theme.BackgroundType
+        log.debug(u"render background %s %s", self._theme.BackgroundType)
         p=QtGui.QPainter()
         p.begin(self._paint)
         if self._theme.BackgroundType == 0:
             p.fillRect(self._paint.rect(), self._theme.BackgroundParameter1)
         elif self._theme.BackgroundType == 1: # gradient
-            # xxx Use a QGradient Brush!!!
-            # get colours as tuples
-            c1=self._theme.BackgroundParameter1.getRgb()
-            c2=self._theme.BackgroundParameter2.getRgb()
-            dir=self._theme.BackgroundParameter3
-            w=self._paint.width();h=self._paint.height()
-            lines=[]
-            pens=[]
-            if dir == 0: # vertical
-                for y in range (h):
-                    c=interpolate(c1, c2, y/float(h))
-                    lines.append((0,y,w,y))
-                    pens.append(QtGui.QPen(QtGui.QColor(c[0],c[1],c[2]))) # bleagh
-            else:
-                for x in range (w):
-                    c=interpolate(c1, c2, x/float(w))
-                    lines.append((x,0,x,h))
-                    pens.append(QtGui.QPen(QtGui.QColor(c[0],c[1],c[2]))) # bleagh
-            for i in range(len(pens)):
-                p.setPen(pens[i])
-                l=lines[i]
-                p.drawLine(l[0],l[1],l[2],l[3]) # must be a better way!
+            #TODO Add Theme code and fix direction
+
+            gradient = QtGui.QLinearGradient(0, 0, self._paint.width(), self._paint.height())
+            gradient.setColorAt(0, QtGui.QColor(255, 0, 0))
+            gradient.setColorAt(0.5, QtGui.QColor(0, 255, 0))
+            gradient.setColorAt(1, QtGui.QColor(0, 0, 255))
+            p.setBrush(QtGui.QBrush(gradient))
+            rectPath = QtGui.QPainterPath()
+
+            MAX_X = self._paint.width()
+            MAX_Y = self._paint.height()
+
+            rectPath.moveTo(0, 0)
+            rectPath.lineTo(0, MAX_Y)
+            rectPath.lineTo(MAX_X, MAX_Y)
+            rectPath.lineTo(MAX_X, 0)
+            rectPath.closeSubpath()
+            p.drawPath(rectPath)
 
         elif self._theme.BackgroundType == 2: # image
             r=self._paint.rect()
-            print r.x(), r.y(), r.width(),r.height()
-            print self._theme.BackgroundParameter2
+            log.debug(r.x(), r.y(), r.width(),r.height())
+            log.debug(self._theme.BackgroundParameter2)
             if self._theme.BackgroundParameter2 is not None:
                 p.fillRect(self._paint.rect(), self._theme.BackgroundParameter2)
             p.drawPixmap(self.background_offsetx,self.background_offsety, self.img)
         p.end()
-        print "render background done"
-        
+        log.debug(u"render background done")
+
     def split_set_of_lines(self, lines):
 
         """Given a list of lines, decide how to split them best if they don't all fit on the screen
@@ -166,7 +166,7 @@
 
          Returns a list of [lists of lines], one set for each screenful
          """
-#         print "Split set of lines"
+#         log.debug(u" "Split set of lines"
         # Probably ought to save the rendering results to a pseudoDC for redrawing efficiency.  But let's not optimse prematurely!
 
         bboxes = []
@@ -202,7 +202,7 @@
                     retval.append(thislines)
                     thislines=[]
         else:
-#             print "Just split where you can"
+#             log.debug(u" "Just split where you can"
             retval=[]
             startline=0
             endline=startline+1
@@ -221,9 +221,10 @@
 
     def _render_lines(self, lines):
         """render a set of lines according to the theme, return bounding box"""
-        print "_render_lines", lines
+        log.debug(u"_render_lines %s", lines)
 
         bbox=self._render_lines_unaligned(lines)
+        print bbox
 
         t=self._theme
         x=self._rect.left()
@@ -237,10 +238,10 @@
             assert(0, "Invalid value for theme.VerticalAlign:%d" % t.VerticalAlign)
         self._render_background()
         bbox=self._render_lines_unaligned(lines, (x,y))
-        print "render lines DONE"
+        log.debug(u"render lines DONE")
 
         return bbox
-        
+
     def _render_lines_unaligned(self, lines, tlcorner=(0,0)):
 
         """Given a list of lines to render, render each one in turn
@@ -249,7 +250,7 @@
         than a screenful (eg. by using split_set_of_lines)
 
         Returns the bounding box of the text as QRect"""
-        print "render unaligned", lines
+        log.debug(u"render unaligned %s", lines)
         x,y=tlcorner
         brx=x
         bry=y
@@ -268,7 +269,7 @@
             p.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
             p.drawRect(retval)
             p.end()
-        print "render unaligned DONE"
+        log.debug(u"render unaligned DONE")
 
         return  retval
 
@@ -282,14 +283,14 @@
 
         Returns the bottom-right corner (of what was rendered) as a tuple(x,y).
         """
-        print "Render single line '%s' @ %s "%( line, tlcorner)
+        log.debug(u"Render single line '%s' @ %s "%( line, tlcorner))
         x,y=tlcorner
         # We draw the text to see how big it is and then iterate to make it fit
         # when we line wrap we do in in the "lyrics" style, so the second line is
         # right aligned with a "hanging indent"
 
         # get the words
-#         print "Getting the words split right"
+#         log.debug(u" "Getting the words split right"
         words=line.split(" ")
         thisline=' '.join(words)
         lastword=len(words)
@@ -307,8 +308,8 @@
                 lastword-=1
                 thisline=' '.join(words[:lastword])
 
-#         print "This is how they split", lines
-#         print "Now render them"
+#         log.debug(u" "This is how they split", lines
+#         log.debug(u" "Now render them"
         startx=x
         starty=y
         rightextent=None
@@ -356,7 +357,7 @@
                     self._get_extent_and_render(line, (x-self._outline_offset,y-self._outline_offset), dodraw=True, color = t.OutlineColor)
 
             self._get_extent_and_render(line, tlcorner=(x,y), dodraw=True)
-#             print "Line %2d: Render '%s' at (%d, %d) wh=(%d,%d)"%( linenum, line, x, y,w,h)
+#             log.debug(u" "Line %2d: Render '%s' at (%d, %d) wh=(%d,%d)"%( linenum, line, x, y,w,h)
             y += h
             if linenum == 0:
                 self._first_line_right_extent=rightextent
@@ -372,28 +373,36 @@
         return brcorner
 
     # xxx this is what to override for an SDL version
-    def _get_extent_and_render(self, line, tlcorner=(0,0), dodraw=False, color=None):
+    def _get_extent_and_render(self, line, tlcorner=(0,0), dodraw=False, color=None, footer = False):
         """Find bounding box of text  - as render_single_line.
         If dodraw is set, actually draw the text to the current DC as well
 
         return width and height of text as a tuple (w,h)"""
         # setup defaults
-        print "_get_extent_and_render", [line], tlcorner, dodraw
+        log.debug(u"_get_extent_and_render %s %s %s ", [line], tlcorner, dodraw)
         p=QtGui.QPainter()
         p.begin(self._paint)
         # 'twould be more efficient to set this once when theme changes
         # or p changes
-        font=QtGui.QFont(self._theme.FontName,
-                     self._theme.FontProportion, # size
-                     QtGui.QFont.Normal, # weight
-                     0)# italic
+        if footer :
+           font=QtGui.QFont(self._theme.FontName,
+                         12, # size
+                         QtGui.QFont.Normal, # weight
+                         0)# italic
+        else:
+            font=QtGui.QFont(self._theme.FontName,
+                         self._theme.FontProportion, # size
+                         QtGui.QFont.Normal, # weight
+                         0)# italic
         # to make the unit tests monitor independent, we have to be able to
         # specify whether a font proportion is in pixels or points
         if self._theme.FontUnits.lower() == "pixels":
-            print "pixels"
-            font.setPixelSize(self._theme.FontProportion)
-        print self._theme.FontName, self._theme.FontProportion
-        print font.family(), font.pointSize()
+            log.debug(u"pixels")
+            if footer:
+                font.setPixelSize(12)
+            else:
+                font.setPixelSize(self._theme.FontProportion)
+        log.debug(u'Font details %s %s %s %s', self._theme.FontName, self._theme.FontProportion,  font.family(), font.pointSize())
         p.setFont(font)
         if color == None:
             p.setPen(self._theme.FontColor)

=== modified file 'openlp/core/test/test_render.py'
--- openlp/core/test/test_render.py	2009-03-12 20:19:24 +0000
+++ openlp/core/test/test_render.py	2009-03-29 14:38:23 +0000
@@ -81,6 +81,7 @@
     def teardown_class(self):
         print "class quit", self, self.app
         self.app.quit()
+
     def setup_method(self, method):
         print "SSsetup", method
         if not hasattr(self, "app"):
@@ -157,6 +158,7 @@
         expected_answer=["Verse 1: Line 1\nLine 2","Verse 2: Line 1\nLine 2","Verse 3: Line 1\nLine 2\nLine 3"]
         answer=self.r.set_words_openlp(words)
         assert (answer==expected_answer)
+
     def test_render_screens(self):
         words="""
 Verse 1: Line 1
@@ -177,6 +179,7 @@
             answer=self.r.render_screen(v)
 #             print v, answer.x(), answer.y(), answer.width(), answer.height()
             assert(answer==expected_answer[v])
+
     def split_test(self, number, answer, expected_answers):
         lines=[]
         print "Split test", number, answer

=== modified file 'openlp/core/theme/theme.py'
--- openlp/core/theme/theme.py	2009-03-22 07:13:34 +0000
+++ openlp/core/theme/theme.py	2009-03-29 14:38:23 +0000
@@ -8,6 +8,8 @@
 from PyQt4 import QtGui
 
 DelphiColors={"clRed":0xFF0000,
+                "clBlue":0x0000FF,
+                "clYellow":0x0FFFF00,
                "clBlack":0x000000,
                "clWhite":0xFFFFFF}
 
@@ -16,7 +18,7 @@
 <Theme>
   <Name>BlankStyle</Name>
   <BackgroundMode>1</BackgroundMode>
-  <BackgroundType>0</BackgroundType>  
+  <BackgroundType>0</BackgroundType>
   <BackgroundParameter1>$000000</BackgroundParameter1>
   <BackgroundParameter2/>
   <BackgroundParameter3/>
@@ -37,10 +39,10 @@
         """ stores the info about a theme
         attributes:
           name : theme name
-          
+
            BackgroundMode   : 1 - Transparent
                              1 - Opaque
-                             
+
           BackgroundType   : 0 - solid color
                              1 - gradient color
                              2 - image
@@ -53,7 +55,7 @@
                                  for solid - N/A
           BackgroundParameter3 : for image - N/A
                                  for gradient - 0 -> vertical, 1 -> horizontal
-                             
+
           FontName       : name of font to use
           FontColor      : color for main font
           FontProportion : size of font
@@ -108,7 +110,7 @@
 #                            print "nope",
                             pass
                     elif DelphiColors.has_key(t):
-#                        print "colour", 
+#                        print "colour",
                         val=DelphiColors[t]
                     else:
                         try:
@@ -121,7 +123,7 @@
                     val= QtGui.QColor((val>>16) & 0xFF, (val>>8)&0xFF, val&0xFF)
  #               print [val]
                 setattr(self,element.tag, val)
-        
+
 
     def __str__(self):
         s=""

=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py	2009-03-23 20:18:06 +0000
+++ openlp/core/ui/thememanager.py	2009-03-28 20:12:22 +0000
@@ -17,17 +17,22 @@
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place, Suite 330, Boston, MA 02111-1307 USA
 """
-import os
+import os,os.path
+import sys
+import zipfile
 
 from time import sleep
 from copy import deepcopy
+from xml.etree.ElementTree import ElementTree, XML
 from PyQt4 import *
 from PyQt4 import QtCore, QtGui
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 # from openlp.core.resources import *
 # from openlp.core.ui import AboutForm, AlertForm, SettingsForm, SlideController
+from openlp.core import translate
 from openlp.core.lib import OpenLPToolbar
+from openlp.core.utils import ConfigHelper
 #from openlp.core.lib import ThemeItem
 
 # from openlp.core import PluginManager
@@ -44,53 +49,74 @@
     def __init__(self):
         QAbstractItemModel.__init__(self)
         self.items=[]
+        self.rowheight=50
+        self.maximagewidth=self.rowheight*16/9.0;
         log.info("Starting")
+
+    def clearItems(self):
+        self.items=[]
+
     def columnCount(self, parent):
         return 1; # always only a single column (for now)
+
     def rowCount(self, parent):
         return len(self.items)
-    def insertRow(self, row, Theme_item):
-#         self.beginInsertRows(QModelIndex(),row,row)
-        log.info("insert row %d:%s"%(row,Theme_item))
-        self.items.insert(row, Theme_item)
+
+    def insertRow(self, row, filename):
+        self.beginInsertRows(QModelIndex(),row,row)
+        log.info("insert row %d:%s"%(row,filename))
+        (prefix, shortfilename) = os.path.split(str(filename))
+        log.info("shortfilename=%s"%(shortfilename))
+        # create a preview image
+        if os.path.exists(filename):
+            preview = QPixmap(str(filename))
+            w=self.maximagewidth;h=self.rowheight
+            preview = preview.scaled(w,h, Qt.KeepAspectRatio)
+            realw=preview.width(); realh=preview.height()
+            # and move it to the centre of the preview space
+            p=QPixmap(w,h)
+            p.fill(Qt.transparent)
+            painter=QPainter(p)
+            painter.drawPixmap((w-realw)/2,(h-realh)/2,preview)
+        else:
+            w=self.maximagewidth;h=self.rowheight
+            p=QPixmap(w,h)
+            p.fill(Qt.transparent)
+        # finally create the row
+        self.items.insert(row,(filename, p, shortfilename))
         log.info("Items: %s" % self.items)
-#         self.endInsertRows()
+        self.endInsertRows()
+
     def removeRow(self, row):
         self.beginRemoveRows(QModelIndex(), row,row)
         self.items.pop(row)
         self.endRemoveRows()
+
     def addRow(self, item):
         self.insertRow(len(self.items), item)
-        
+
     def index(self, row, col, parent = QModelIndex()):
         return self.createIndex(row,col)
 
     def parent(self, index=QModelIndex()):
         return QModelIndex() # no children as yet
+
     def data(self, index, role):
-        """
-        Called by the Theme manager to draw us in the Theme window
-        """
         row=index.row()
         if row > len(self.items): # if the last row is selected and deleted, we then get called with an empty row!
             return QVariant()
-        item=self.items[row]
         if role==Qt.DisplayRole:
-            retval= item.pluginname + ":" + item.shortname
+            retval= self.items[row][2]
         elif role == Qt.DecorationRole:
-            retval = item.iconic_representation
-        elif role == Qt.ToolTipRole:
-            retval= None
+            retval= self.items[row][1]
         else:
-            retval= None
-        if retval == None:
-            retval=QVariant()
+            retval= QVariant()
 #         log.info("Returning"+ str(retval))
         if type(retval) is not type(QVariant):
             return QVariant(retval)
         else:
             return retval
-        
+
     def __iter__(self):
         for i in self.items:
             yield i
@@ -99,14 +125,9 @@
         log.info("Get Item:%d -> %s" %(row, str(self.items)))
         return self.items[row]
 
-    
 class ThemeManager(QWidget):
-
-    """Manages the orders of Theme.  Currently this involves taking
-    text strings from plugins and adding them to an OOS file. In
-    future, it will also handle zipping up all the resources used into
-    one lump.
-    Also handles the UI tasks of moving things up and down etc.
+    """
+    Manages the orders of Theme.  C
     """
     global log
     log=logging.getLogger(u'ThemeManager')
@@ -122,19 +143,26 @@
         self.Toolbar.addToolbarButton("Edit Theme", ":/themes/theme_edit.png")
         self.Toolbar.addToolbarButton("Delete Theme", ":/themes/theme_delete.png")
         self.Toolbar.addSeparator()
-        self.Toolbar.addToolbarButton("Import Theme", ":/themes/theme_import.png")
-        self.Toolbar.addToolbarButton("Export Theme", ":/themes/theme_export.png")        
+        self.Toolbar.addToolbarButton("Import Theme", ":/themes/theme_import.png",
+            u'Allows Themes to be imported', self.onImportTheme)
+        self.Toolbar.addToolbarButton("Export Theme", ":/themes/theme_export.png")
         self.ThemeWidget = QtGui.QWidgetAction(self.Toolbar)
         self.Toolbar.addAction(self.ThemeWidget)
 
         self.Layout.addWidget(self.Toolbar)
 
-        self.TreeView = QtGui.QTreeView(self)
+        self.ThemeListView = QtGui.QListView(self)
         self.Theme_data=ThemeData()
-        self.TreeView.setModel(self.Theme_data)
-        self.Layout.addWidget(self.TreeView)
+        self.ThemeListView.setModel(self.Theme_data)
+        self.ThemeListView.setAlternatingRowColors(True)
+        self.Layout.addWidget(self.ThemeListView)
+        self.ThemeListView.setAlternatingRowColors(True)
+
         self.themelist= []
-        
+        self.path = os.path.join(ConfigHelper.get_data_path(), u'themes')
+        self.checkThemesExists(self.path)
+        self.loadThemes() # load the themes
+
 #    def addThemeItem(self, item):
 #        """Adds Theme item"""
 #        log.info("addThemeItem")
@@ -158,7 +186,7 @@
 #                self.Theme_data.addRow(item)
 #            else:
 #                self.Theme_data.insertRow(row+1, item)
-#                
+#
 #    def removeThemeItem(self):
 #        """Remove currently selected item"""
 #        pass
@@ -182,10 +210,55 @@
 #        oosfile.write(self.oos_as_text)
 #        oosfile.write("# END OOS\n")
 #        oosfile.close()
-        
-    def load(self):
-        log.debug(u'Load')        
-        self.themelist = [u'African Sunset', u'Snowy Mountains', u'Wilderness', u'Wet and Windy London']
-        
+
+    def onImportTheme(self):
+        files = QtGui.QFileDialog.getOpenFileNames(None,
+            translate('ThemeManager', u'Select Import File'),
+            self.path,
+            u'Theme (*.theme)')
+        log.info(u'New Themes) %s', str(files))
+        if len(files) > 0:
+            for file in files:
+                self.unzipTheme(file, self.path)
+        self.Theme_data.clearItems()
+        self.loadThemes()
+
+    def loadThemes(self):
+        log.debug(u'Load themes from dir')
+#        self.themelist = [u'African Sunset', u'Snowy Mountains', u'Wilderness', u'Wet and Windy London']
+        for root, dirs, files in os.walk(self.path):
+            for name in files:
+                if name.endswith(u'.bmp'):
+                    self.Theme_data.addRow(os.path.join(self.path, name))
+
     def getThemes(self):
         return self.themelist
+
+    def checkThemesExists(self, dir):
+        log.debug(u'check themes')
+        if os.path.exists(dir) == False:
+            os.mkdir(dir)
+
+    def unzipTheme(self, filename, dir):
+        log.debug(u'Unzipping theme %s', filename)
+        zip = zipfile.ZipFile(str(filename))
+        for file in zip.namelist():
+            if file.endswith('/'):
+                theme_dir = os.path.join(dir, file)
+                if os.path.exists(theme_dir) == False:
+                    os.mkdir(os.path.join(dir, file))
+            else:
+                fullpath = os.path.join(dir, file)
+                if file.endswith(u'.xml'):
+                    self.checkVersion1(fullpath)
+                outfile = open(fullpath, 'w')
+                outfile.write(zip.read(file))
+                outfile.close()
+
+    def checkVersion1(self, xmlfile):
+        file=open(xmlfile)
+        t=''.join(file.readlines()) # read the file and change list to a string
+        tree = ElementTree(element=XML(t)).getroot()
+        print "AA"
+        print tree.find('BackgroundType')
+        print "AAA"


Follow ups