Commit [b05607] Maximize Restore History

[plugin.image.mypicsdb] updated to version 1.3.4

beenje beenje 2013-02-06

1 2 > >> (Page 1 of 2)
removed plugin.image.mypicsdb/resources/lib/Viewer.py
removed plugin.image.mypicsdb/resources/skins/Default/720p/FilterWizard.xml
changed plugin.image.mypicsdb/resources/language/Danish/strings.xml
changed plugin.image.mypicsdb/resources/language/Dutch/strings.xml
changed plugin.image.mypicsdb/resources/language/English/strings.xml
changed plugin.image.mypicsdb/resources/language/French/strings.xml
changed plugin.image.mypicsdb/resources/language/German/strings.xml
changed plugin.image.mypicsdb/resources/lib/EXIF.py
changed plugin.image.mypicsdb/resources/lib/MypicsDB.py
changed plugin.image.mypicsdb/resources/lib/XMP.py
changed plugin.image.mypicsdb/resources/lib/__init__.py
copied plugin.image.mypicsdb/resources/language/PLEASE_translation.txt -> plugin.image.mypicsdb/resources/lib/viewer.py
copied plugin.image.mypicsdb/resources/lib/CharsetDecoder.py -> plugin.image.mypicsdb/resources/lib/translationeditor.py
copied plugin.image.mypicsdb/resources/lib/EXIF_changes.txt -> plugin.image.mypicsdb/resources/lib/common.py
copied plugin.image.mypicsdb/resources/lib/FilterWizard.py -> plugin.image.mypicsdb/resources/lib/filterwizard.py
copied plugin.image.mypicsdb/resources/lib/TranslationEditor.py -> plugin.image.mypicsdb/resources/lib/pathscanner.py
copied plugin.image.mypicsdb/resources/lib/vfs.py -> plugin.image.mypicsdb/resources/lib/dbabstractionlayer.py
copied plugin.image.mypicsdb/resources/skins/Default/1080i/FilterWizard.xml -> plugin.image.mypicsdb/resources/skins/Default/1080i/filterwizard.xml
plugin.image.mypicsdb/resources/language/Danish/strings.xml Diff Switch to side-by-side view
Loading...
plugin.image.mypicsdb/resources/language/Dutch/strings.xml Diff Switch to side-by-side view
Loading...
plugin.image.mypicsdb/resources/language/English/strings.xml Diff Switch to side-by-side view
Loading...
plugin.image.mypicsdb/resources/language/French/strings.xml Diff Switch to side-by-side view
Loading...
plugin.image.mypicsdb/resources/language/German/strings.xml Diff Switch to side-by-side view
Loading...
plugin.image.mypicsdb/resources/lib/EXIF.py Diff Switch to side-by-side view
Loading...
plugin.image.mypicsdb/resources/lib/MypicsDB.py Diff Switch to side-by-side view
Loading...
plugin.image.mypicsdb/resources/lib/XMP.py Diff Switch to side-by-side view
Loading...
plugin.image.mypicsdb/resources/lib/__init__.py Diff Switch to side-by-side view
Loading...
plugin.image.mypicsdb/resources/language/PLEASE_translation.txt to plugin.image.mypicsdb/resources/lib/viewer.py
--- a/plugin.image.mypicsdb/resources/language/PLEASE_translation.txt
+++ b/plugin.image.mypicsdb/resources/lib/viewer.py
@@ -1,19 +1,48 @@
-Hello
+# from frost
 
-If you read this, it may be because you decided to translate the plugin for your
-language. If you do so, please contact me on the official forum :
-http://forum.xbmc.org/showthread.php?t=80845
-and send me your file to include in the plugin.
+# Modules general
+import os
 
-Thank you
+# Modules XBMC
+import xbmc
+import xbmcgui
+from traceback import print_exc
+import common
 
-----------
-Bonjour
+# constants
+ADDON_NAME = common.getaddon_name()
+ADDON_DIR  = common.getaddon_path()
 
-Si vous lisez ceci, c'est peut ętre parce que vous avez décidé de traduire le 
-plugin dans votre langue. Si vous le faites, merci de me contacter sur le forum officiel XBMC :
-http://forum.xbmc.org/showthread.php?t=80845
-et envoyez moi votre fichier pour l'inclure dans le plugin.
 
-Merci
+class Viewer:
+    # constants
+    WINDOW = 10147
+    CONTROL_LABEL = 1
+    CONTROL_TEXTBOX = 5
 
+    def __init__( self, *args, **kwargs ):
+        # activate the text viewer window
+        xbmc.executebuiltin( "ActivateWindow(%d)" % ( self.WINDOW, ) )
+        # get window
+        self.window = xbmcgui.Window( self.WINDOW )
+        # give window time to initialize
+        xbmc.sleep( 100 )
+        # set controls
+        self.setControls()
+
+    def setControls( self ):
+        #get header, text
+        heading, text = self.getText()
+        # set heading
+        self.window.getControl( self.CONTROL_LABEL ).setLabel( "%s - %s" % ( heading, ADDON_NAME, ) )
+        # set text
+        self.window.getControl( self.CONTROL_TEXTBOX ).setText( text )
+
+    def getText( self ):
+        try:
+            txt = open( os.path.join( ADDON_DIR, "Readme.txt" ) ).read()
+            return "Readme", txt
+        except:
+            print_exc()
+        return "", ""
+
plugin.image.mypicsdb/resources/lib/CharsetDecoder.py to plugin.image.mypicsdb/resources/lib/translationeditor.py
--- a/plugin.image.mypicsdb/resources/lib/CharsetDecoder.py
+++ b/plugin.image.mypicsdb/resources/lib/translationeditor.py
@@ -1,52 +1,94 @@
 #!/usr/bin/python
 # -*- coding: utf8 -*-
 
-from urllib import quote_plus,unquote_plus
+""" 
+Copyright (C) 2012 Xycl
 
-def smart_unicode(s):
-    """credit : sfaxman"""
-    if not s:
-        return ''
-    try:
-        if not isinstance(s, basestring):
-            if hasattr(s, '__unicode__'):
-                s = unicode(s)
-            else:
-                s = unicode(str(s), 'UTF-8')
-        elif not isinstance(s, unicode):
-            s = unicode(s, 'UTF-8')
-    except:
-        if not isinstance(s, basestring):
-            if hasattr(s, '__unicode__'):
-                s = unicode(s)
-            else:
-                s = unicode(str(s), 'ISO-8859-1')
-        elif not isinstance(s, unicode):
-            s = unicode(s, 'ISO-8859-1')
-    return s
+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, either version 3 of the License, or
+(at your option) any later version.
+
+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, see <http://www.gnu.org/licenses/>.
+"""
+
+import xbmc
+import xbmcgui
+import MypicsDB as MPDB
+import common
+
+#_ = sys.modules[ "__main__" ].__language__
+
+
+STATUS_LABEL    = 100
+STATUS_LABEL2   = 101
+BUTTON_OK       = 102
+BUTTON_CANCEL   = 103
+TAGS_LIST       = 120
+CANCEL_DIALOG   = ( 9, 10, 92, 216, 247, 257, 275, 61467, 61448, )
+ACTION_SELECT_ITEM = 7
+ACTION_MOUSE_START = 100
+ACTION_TAB         = 18
+SELECT_ITEM = (ACTION_SELECT_ITEM, ACTION_MOUSE_START)
+
+class TranslationEditor( xbmcgui.WindowXMLDialog ):
     
-def smart_utf8(s):
-    return smart_unicode(s).encode('utf-8')
+    def __init__( self, xml, cwd, default):
+        xbmcgui.WindowXMLDialog.__init__(self)
     
-def get_crc32( parm ):
-    parm = parm.lower()        
-    bytes = bytearray(parm.encode())
-    crc = 0xffffffff;
-    for b in bytes:
-        crc = crc ^ (b << 24)          
-        for i in range(8):
-            if (crc & 0x80000000 ):                 
-                crc = (crc << 1) ^ 0x04C11DB7                
-            else:
-                crc = crc << 1;                        
-        crc = crc & 0xFFFFFFFF
+    def onInit( self ):  
+        self.setup_all()
+
+    def setup_all( self ):
+
+        self.getControl( STATUS_LABEL ).setLabel( common.getstring(30620) )
+        self.getControl( STATUS_LABEL2 ).setLabel( common.getstring(30622) )
+        self.getControl( BUTTON_OK ).setLabel( common.getstring(30621) )
+        self.getControl( TAGS_LIST ).reset()
         
-    return '%08x' % crc    
+        TagTypesAndTranslation =  MPDB.getTagTypesForTranslation()
+
+        for TagTypeAndTranslation in TagTypesAndTranslation:
+            listitem = xbmcgui.ListItem( label=TagTypeAndTranslation[0], label2=TagTypeAndTranslation[1]) 
+            self.getControl( TAGS_LIST ).addItem( listitem )
+
+        self.setFocus( self.getControl( TAGS_LIST ) )
+        self.getControl( TAGS_LIST ).selectItem( 0 )
+
+     
     
-def quote_param(parm):
-    #parm = smart_utf8( parm.replace ("'", "\\'").replace ('"', '\\"') )
-    parm = smart_utf8( parm.replace("\\", "\\\\\\\\").replace ("'", "\\'").replace ('"', '\\"') )
-    #parm = smart_utf8( parm.replace ("'", "\\'") )
-    parm = quote_plus(parm)
-    
-    return parm+    def onClick( self, controlId ):
+        pass    
+
+    def onFocus( self, controlId ):
+        self.controlId = controlId
+
+    def onAction( self, action ):
+        #try:
+            # Cancel
+            if ( action.getId() in CANCEL_DIALOG or self.getFocusId() == BUTTON_CANCEL and action.getId() in SELECT_ITEM ):
+                self.close()
+            # Okay
+            if ( self.getFocusId() == BUTTON_OK and action.getId() in SELECT_ITEM ):
+                self.close()
+            
+            # Select or deselect item in list
+            if ( action.getId() in SELECT_ITEM and self.getFocusId() == TAGS_LIST ):
+                item = self.getControl( TAGS_LIST ).getSelectedItem()
+                #pos  = self.getControl( TAGS_LIST ).getSelectedPosition()
+                
+                kb = xbmc.Keyboard(item.getLabel2(),  common.getstring(30623)%( common.smart_utf8(item.getLabel())), False)
+                kb.doModal()
+                if (kb.isConfirmed()):
+                    item.setLabel2(kb.getText())
+                    MPDB.setTranslatedTagType(common.smart_unicode(item.getLabel()), common.smart_unicode(item.getLabel2()))
+                    self.getControl( TAGS_LIST ).setVisible(False)
+                    self.getControl( TAGS_LIST ).setVisible(True)
+
+                    
plugin.image.mypicsdb/resources/lib/EXIF_changes.txt to plugin.image.mypicsdb/resources/lib/common.py
--- a/plugin.image.mypicsdb/resources/lib/EXIF_changes.txt
+++ b/plugin.image.mypicsdb/resources/lib/common.py
@@ -1,121 +1,186 @@
-~ EXIF.py Changelog ~
+#!/usr/bin/python
+# -*- coding: utf8 -*-
 
-2012-06-13 - Ianaré Sévi
-Merge patches:
-  Support malformed last IFD by fhats
-  Light source, Flash and Metering mode dictionaries update by gryfik
+""" 
+Common functions.
+Copyright (C) 2012 Xycl
 
-2008-07-31 - Ianaré Sévi
-Wikipedia Commons hunt for suitable test case images,
-testing new code additions.
+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, either version 3 of the License, or
+(at your option) any later version.
 
-2008-07-09 - Stephen H. Olson
-Fix a problem with reading MakerNotes out of NEF files.
-Add some more Nikon MakerNote tags.
+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.
 
-2008-07-08 - Stephen H. Olson
-An error check for large tags totally borked MakerNotes.
-  With Nikon anyway, valid MakerNotes can be pretty big.
-Add error check for a crash caused by nikon_ev_bias being 
-  called with the wrong args.
-Drop any garbage after a null character in string
-  (patch from Andrew McNabb <amcnabb@google.com>).
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
 
-2008-02-12 - Ianaré Sévi
-Fix crash on invalid MakerNote
-Fix crash on huge Makernote (temp fix)
-Add printIM tag 0xC4A5, needs decoding info
-Add 0x9C9B-F range of tags
-Add a bunch of tag definitions from:
- http://owl.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
-Add 'strict' variable and command line option
 
-2008-01-18 - Gunter Ohrner
-Add 'GPSDate' tag
+import sys, os, urllib
+import xbmc, xbmcaddon
 
-2007-12-12 - Ianaré Sévi
-Fix quick option on certain image types
-Add note on tag naming in documentation
+__addonname__    = sys.modules[ "__main__" ].__addonname__
+__settings__ = xbmcaddon.Addon(id=__addonname__)
+__language__ = __settings__.getLocalizedString
+__homepath__ = __settings__.getAddonInfo('path').decode('utf-8')
+__sys_file_encoding__ = sys.getfilesystemencoding()
 
-2007-11-30 - Ianaré Sévi
-Changed -s option to -t
-Put changelog into separate file
 
-2007-10-28 - Ianaré Sévi
-Merged changes from MoinMoin:ReimarBauer
-Added command line option for debug, stop
-processing on tag.
+def getaddon_path():
+    return __homepath__
 
-2007-09-27 - Ianaré Sévi
-Add some Olympus Makernote tags.
 
-2007-09-26 - Stephen H. Olson
-Don't error out on invalid Olympus 'SpecialMode'.
-Add a few more Olympus/Minolta tags.
+def getaddon_name():
+    __settings__.getAddonInfo('name')
 
-2007-09-22 - Stephen H. Olson
-Don't error on invalid string
-Improved Nikon MakerNote support
+    
+def getaddon_info(parm):
+    # author, changelog, description, disclaimer, fanart. icon, id, name, path, profile, stars, summary, type, version
+    return __settings__.getAddonInfo(parm)
 
-2007-05-03 - Martin Stone <mj_stone@users.sourceforge.net>
-Fix for inverted detailed flag and Photoshop header
 
-2007-03-24 - Ianaré Sévi
-Can now ignore MakerNotes Tags for faster processing.
+def getstring(num):
+    return __language__(num)
 
-2007-01-18 - Ianaré Sévi <ianare@gmail.com>
-Fixed a couple errors and assuming maintenance of the library.
 
-2006-08-04 MoinMoin:ReimarBauer
-Added an optional parameter name to process_file and dump_IFD. Using this parameter the
-loop is breaked after that tag_name is processed.
-some PEP8 changes
+# taken from: http://wiki.xbmc.org/index.php?title=Xbmcaddon_module
+def openaddon_settings():
+    __settings__.openSettings()
 
----------------------------- original notices -------------------------
 
-Contains code from "exifdump.py" originally written by Thierry Bousch
-<bousch@topo.math.u-psud.fr> and released into the public domain.
+def getxbmc_version():    
+    xbmc.getInfoLabel('System.BuildVersion')
 
-Updated and turned into general-purpose library by Gene Cash
 
-Patch Contributors:
-* Simon J. Gerraty <sjg@crufty.net>
-s2n fix & orientation decode
-* John T. Riedl <riedl@cs.umn.edu>
-Added support for newer Nikon type 3 Makernote format for D70 and some
-other Nikon cameras.
-* Joerg Schaefer <schaeferj@gmx.net>
-Fixed subtle bug when faking an EXIF header, which affected maker notes
-using relative offsets, and a fix for Nikon D100.
+def getaddon_setting(name):
+    return __settings__.getSetting(name)
 
-1999-08-21 TB  Last update by Thierry Bousch to his code.
 
-2002-01-17 CEC Discovered code on web.
-            Commented everything.
-            Made small code improvements.
-            Reformatted for readability.
+def setaddon_setting(name, value):
+    __settings__.setSetting(id=name, value=value)
+
+
+# helpers
+def show_notification(title, message, timeout=2000, image=""):
+    if image == "":
+        command = 'Notification(%s,%s,%s)' % (smart_utf8(title), smart_utf8(message), timeout)
+    else:
+        command = 'Notification(%s,%s,%s,%s)' % (smart_utf8(title), smart_utf8(message), timeout, smart_utf8(image))
+    xbmc.executebuiltin(command)
+
+
+def run_plugin(plugin, params=""):
+    if params != "":
+        quoted_params = [ name+"="+quote_param(value)+"&" for (name, value) in params][:-1]
+        xbmc.executebuiltin('XBMC.RunPlugin(%s?%s)'%(smart_utf8(plugin), smart_utf8(quoted_params)))
+    else:
+        xbmc.executebuiltin('XBMC.RunPlugin(%s)'%smart_utf8(plugin))
+
+
+def run_script(script):
+    xbmc.executebuiltin('XBMC.RunScript(%s)'%smart_utf8(script))
+
+
+def smart_unicode(s):
+    """credit : sfaxman"""
+    if not s:
+        return ''
+    try:
+        if not isinstance(s, basestring):
+            if hasattr(s, '__unicode__'):
+                s = unicode(s)
+            else:
+                s = unicode(str(s), 'UTF-8')
+        elif not isinstance(s, unicode):
+            s = unicode(s, 'UTF-8')
+    except:
+        if not isinstance(s, basestring):
+            if hasattr(s, '__unicode__'):
+                s = unicode(s)
+            else:
+                s = unicode(str(s), 'ISO-8859-1')
+        elif not isinstance(s, unicode):
+            s = unicode(s, 'ISO-8859-1')
+    return s
+
+
+def smart_utf8(s):
+    return smart_unicode(s).encode('utf-8')
+
+
+def get_crc32( parm ):
+    parm = parm.lower()        
+    byte = bytearray(parm.encode())
+    crc = 0xffffffff;
+    for b in byte:
+        crc = crc ^ (b << 24)          
+        for _ in range(8):
+            if (crc & 0x80000000 ):                 
+                crc = (crc << 1) ^ 0x04C11DB7                
+            else:
+                crc = crc << 1;                        
+        crc = crc & 0xFFFFFFFF
+
+    return '%08x' % crc    
+
+
+def quote_param(parm):
+    parm = smart_utf8( parm.replace("\\", "\\\\\\\\").replace ("'", "\\'").replace ('"', '\\"') )
+    parm = urllib.quote_plus(parm)
+
+    return parm
+
+
+def unquote_param(parm):
+    parm = urllib.unquote_plus(parm)
+    parm = smart_unicode( parm.replace ('\\"', '"').replace ("\\'", "'").replace("\\\\\\\\", "\\") )
+
+    return parm
+
+
+def log(module, msg, level=xbmc.LOGDEBUG):
+    if type(module).__name__=='unicode':
+        module = module.encode('utf-8')
+
+    if type(msg).__name__=='unicode':
+        msg = msg.encode('utf-8')
+        
+    if getaddon_setting("debugging") == "true" and xbmc.LOGERROR != level:
+        level = xbmc.LOGNOTICE
+
+    filename = smart_utf8(os.path.basename(sys._getframe(1).f_code.co_filename))
+    lineno  = str(sys._getframe(1).f_lineno)
+
+    if len(module.strip()) == 0:
+        try:
+            module = "function " + sys._getframe(1).f_code.co_name
+        except:
+            module = " "
+            pass
+    else:
+        module = 'object ' + module
+    xbmc.log(str("[%s] line %5d in %s %s >> %s"%(__addonname__, int(lineno), filename, module, msg.__str__())), level)    
+
+
+# version is a string like 'x.y.z'
+# if first version is greater then -1 is returned. if equal then 0 is returned.
+def check_version(first, second):
+    a = first.split('.')
+    b = second.split('.')
+    
+    for i in range(len(a)):
+        # if we're here and there is no element left in b then a is greater than b
+        if len(b)<i:
+            return -1
+        
+        if int(a[i]) != int(b[i]):
+            return int(b[i]) - int(a[i])
+    # if we're here and a was equal to b, but b is longer than a then b must be greater  
+    if len(b)>len(a):
+        return 1
             
-2002-01-19 CEC Added ability to read TIFFs and JFIF-format JPEGs.
-            Added ability to extract JPEG formatted thumbnail.
-            Added ability to read GPS IFD (not tested).
-            Converted IFD data structure to dictionaries indexed by
-            tag name.
-            Factored into library returning dictionary of IFDs plus
-            thumbnail, if any.
-            
-2002-01-20 CEC Added MakerNote processing logic.
-            Added Olympus MakerNote.
-            Converted data structure to single-level dictionary, avoiding
-            tag name collisions by prefixing with IFD name.  This makes
-            it much easier to use.
-2002-01-23 CEC Trimmed nulls from end of string values.
-
-2002-01-25 CEC Discovered JPEG thumbnail in Olympus TIFF MakerNote.
-
-2002-01-26 CEC Added ability to extract TIFF thumbnails.
-            Added Nikon, Fujifilm, Casio MakerNotes.
-            
-2003-11-30 CEC Fixed problem with canon_decode_tag() not creating an
-            IFD_Tag() object.
-            
-2004-02-15 CEC Finally fixed bit shift warning by converting Y to 0L.
+    return 0
plugin.image.mypicsdb/resources/lib/FilterWizard.py to plugin.image.mypicsdb/resources/lib/filterwizard.py
--- a/plugin.image.mypicsdb/resources/lib/FilterWizard.py
+++ b/plugin.image.mypicsdb/resources/lib/filterwizard.py
@@ -1,15 +1,26 @@
 #!/usr/bin/python
 # -*- coding: utf8 -*-
 
-import sys
-import os
-import xbmc
+""" 
+Copyright (C) 2012 Xycl
+
+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, either version 3 of the License, or
+(at your option) any later version.
+
+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, see <http://www.gnu.org/licenses/>.
+"""
+
 import xbmcgui
-import urllib
 import MypicsDB as MPDB
-import CharsetDecoder as decoder
-
-_ = sys.modules[ "__main__" ].__language__
+import common
 
 
 STATUS_LABEL       = 100
@@ -33,19 +44,19 @@
     def __init__( self, xml, cwd, default):
         xbmcgui.WindowXMLDialog.__init__(self)
         
-    def setDelegate(self, filter):
-        self.filter = filter
+    def setDelegate(self, filterfunc):
+        self.filter = filterfunc
         
     def onInit( self ):  
         self.setup_all()
 
     def setup_all( self ):
-        self.getControl( STATUS_LABEL ).setLabel( _(30610) )
-        self.getControl( TAGS_COLUMN ).setLabel(  _(30601) )        
-        self.getControl( CONTENT_COLUMN ).setLabel( _(30602) )        
-        self.getControl( BUTTON_OK ).setLabel( _(30613) )
-        self.getControl( BUTTON_CANCEL ).setLabel( _(30614) )
-        self.getControl( BUTTON_MATCHALL ).setLabel( _(30615) )
+        self.getControl( STATUS_LABEL ).setLabel( common.getstring(30610) )
+        self.getControl( TAGS_COLUMN ).setLabel(  common.getstring(30601) )        
+        self.getControl( CONTENT_COLUMN ).setLabel( common.getstring(30602) )        
+        self.getControl( BUTTON_OK ).setLabel( common.getstring(30613) )
+        self.getControl( BUTTON_CANCEL ).setLabel( common.getstring(30614) )
+        self.getControl( BUTTON_MATCHALL ).setLabel( common.getstring(30615) )
         self.getControl( TAGS_LIST ).reset()
 
         
@@ -56,12 +67,11 @@
         self.CheckTagNames = {}
         
         if self.checkedTags == 1:
-            self.getControl( CHECKED_LABEL ).setLabel(  _(30611) )
+            self.getControl( CHECKED_LABEL ).setLabel(  common.getstring(30611) )
         else:
-            self.getControl( CHECKED_LABEL ).setLabel(  _(30612)% (self.checkedTags) )
-        
-        
-        TotalTagTypes = len(self.TagTypes)
+            self.getControl( CHECKED_LABEL ).setLabel(  common.getstring(30612)% (self.checkedTags) )
+        
+
         i = 0
         for TagType in self.TagTypes:
             TagTypeItem = xbmcgui.ListItem( label=TagType)   
@@ -78,7 +88,7 @@
 
      
     def isContentChecked(self, tagType, tagContent):
-        key = decoder.smart_unicode(tagType) + '||' + decoder.smart_unicode(tagContent)
+        key = common.smart_unicode(tagType) + '||' + common.smart_unicode(tagContent)
         if key in self.CheckTagNames :
             checked = self.CheckTagNames[ key ]    
         else :
@@ -90,7 +100,7 @@
     
         self.getControl( TAGS_CONTENT_LIST ).reset()
         TagContents = [u"%s"%k  for k in MPDB.list_Tags(tagType)]
-        TotalTagContents = len(TagContents)
+
         self.CurrentlySelectedTagType = tagType
         
         for TagContent in TagContents:
@@ -106,10 +116,10 @@
             self.getControl( TAGS_CONTENT_LIST ).addItem( TagContentItem )
             
     def onClick( self, controlId ):
-      pass    
+        pass    
 
     def onFocus( self, controlId ):
-      self.controlId = controlId
+        self.controlId = controlId
 
     def checkGUITagContent(self, item, checked):
         
@@ -171,7 +181,7 @@
                 pos  = self.getControl( TAGS_CONTENT_LIST ).getSelectedPosition()
                 if pos != -1 and item != None:
                     checked = item.getProperty("checked")
-                    key = decoder.smart_unicode(self.CurrentlySelectedTagType) + '||' + decoder.smart_unicode(item.getLabel2())
+                    key = common.smart_unicode(self.CurrentlySelectedTagType) + '||' + common.smart_unicode(item.getLabel2())
                     
                     if checked == "checkbutton.png":
                         self.checkGUITagContent(item, -1)
@@ -186,9 +196,9 @@
                     
 
                     if self.checkedTags == 1:
-                        self.getControl( CHECKED_LABEL ).setLabel(  _(30611) )
+                        self.getControl( CHECKED_LABEL ).setLabel(  common.getstring(30611) )
                     else:
-                        self.getControl( CHECKED_LABEL ).setLabel(  _(30612)% (self.checkedTags) )
+                        self.getControl( CHECKED_LABEL ).setLabel(  common.getstring(30612)% (self.checkedTags) )
                     self.getControl( CHECKED_LABEL ).setVisible(False)
                     self.getControl( CHECKED_LABEL ).setVisible(True)
 
plugin.image.mypicsdb/resources/lib/TranslationEditor.py to plugin.image.mypicsdb/resources/lib/pathscanner.py
--- a/plugin.image.mypicsdb/resources/lib/TranslationEditor.py
+++ b/plugin.image.mypicsdb/resources/lib/pathscanner.py
@@ -1,79 +1,147 @@
-import sys
-import os
-import xbmc
-import xbmcgui
-import urllib
-import MypicsDB as MPDB
-import CharsetDecoder as decoder
+#!/usr/bin/python
+# -*- coding: utf8 -*-
 
-_ = sys.modules[ "__main__" ].__language__
+""" 
+Copyright (C) 2012 Xycl
+
+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, either version 3 of the License, or
+(at your option) any later version.
+
+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, see <http://www.gnu.org/licenses/>.
+
+"""
+
+import os, urllib, re
+import xbmc, xbmcvfs
+import common
+import json
+
+class Scanner(object):
+
+    def walk(self, path, recursive = False, types = None):
+        filenames = []
+        dirnames  = []
+        files_to_return = []
+        dirs_to_return = []
+
+        if type(path).__name__=='unicode':
+            path = path.encode('utf-8')
+            
+        if path.startswith('multipath://'):
+            common.log("Scanner.walk", 'multipath "%s"'%path)
+            dirs = path[12:-1].split('/')
+            for item in dirs:
+                dirnames1, filenames1 = self._walk(urllib.unquote_plus(item), recursive, types)
+
+                for dirname in dirnames1:
+                    dirnames.append(dirname)
+                for filename in filenames1:
+                    filenames.append(filename)               
+               
+        else:
+            common.log("Scanner.walk", 'path "%s"'%path)
+            dirnames, filenames = self._walk(path, recursive, types)
+
+        # Make sure everything is a unicode
+        for filename in filenames:
+            files_to_return.append(common.smart_unicode(filename))
+        for dirname in dirnames:
+            dirs_to_return.append(common.smart_unicode(dirname))
+
+        return dirs_to_return, files_to_return
 
 
-STATUS_LABEL    = 100
-STATUS_LABEL2   = 101
-BUTTON_OK       = 102
-BUTTON_CANCEL   = 103
-TAGS_LIST       = 120
-CANCEL_DIALOG   = ( 9, 10, 92, 216, 247, 257, 275, 61467, 61448, )
-ACTION_SELECT_ITEM = 7
-ACTION_MOUSE_START = 100
-ACTION_TAB         = 18
-SELECT_ITEM = (ACTION_SELECT_ITEM, ACTION_MOUSE_START)
+    def _walk(self, path, recursive, types):
+        filenames = []
+        dirnames   = []
+        files     = []
 
-class TranslationEditor( xbmcgui.WindowXMLDialog ):
-    
-    def __init__( self, xml, cwd, default):
-        xbmcgui.WindowXMLDialog.__init__(self)
-    
-    def onInit( self ):  
-        self.setup_all()
+        path = xbmc.translatePath(path)
+        common.log("Scanner._walk",'"%s"'%path)
+        #if xbmcvfs.exists(xbmc.translatePath(path)) or re.match(r"[a-zA-Z]:\\", path) is not None:
+        subdirs, files = self._listdir(path)
+        for subdir in subdirs:
+            dirnames.append(os.path.join(path, subdir))
 
-    def setup_all( self ):
+        for filename in files:
+            if types is not None:
+                if os.path.splitext(filename)[1].upper() in types or os.path.splitext(filename)[1].lower() in types :
+                    filenames.append(os.path.join(path, filename))
+                else:
+                    common.log("Scanner:_walk", 'Found file "%s" is excluded'%os.path.join(path, filename))
+            else:              
+                filenames.append(os.path.join(path, filename))
 
-        self.getControl( STATUS_LABEL ).setLabel( _(30620) )
-        self.getControl( STATUS_LABEL2 ).setLabel( _(30622) )
-        self.getControl( BUTTON_OK ).setLabel( _(30621) )
-        self.getControl( TAGS_LIST ).reset()
+
+        if recursive:
+            for item in subdirs:
+                dirnames1, filenames1 = self._walk(os.path.join(path, item), recursive, types)
+                for item in dirnames1:
+                    dirnames.append(item)
+                for item in filenames1:
+                    filenames.append(item)
         
-        TagTypesAndTranslation =  MPDB.getTagTypesForTranslation()
-        TotalTagTypes = len(TagTypesAndTranslation)
-        i=0
-        for TagTypeAndTranslation in TagTypesAndTranslation:
-            listitem = xbmcgui.ListItem( label=TagTypeAndTranslation[0], label2=TagTypeAndTranslation[1]) 
-            self.getControl( TAGS_LIST ).addItem( listitem )
+        return dirnames, filenames
 
-        self.setFocus( self.getControl( TAGS_LIST ) )
-        self.getControl( TAGS_LIST ).selectItem( 0 )
 
-     
-    
-    def onClick( self, controlId ):
-      pass    
+    def getname(self, filename):
+        filename = common.smart_unicode(filename)
+        return os.path.basename(filename)
 
-    def onFocus( self, controlId ):
-      self.controlId = controlId
+    def delete(self, filename):
+        xbmcvfs.delete(filename)
+        
+    def getlocalfile(self, filename):
+        
+        filename = common.smart_unicode(filename)
+        
+        # Windows NEEDS unicode but OpenElec utf-8
+        try:
+            exists = os.path.exists(filename)
+        except:
+            exists = os.path.exists(common.smart_utf8(filename))
+        if exists:
+            return filename, False
+        else:
+            tempdir     = xbmc.translatePath('special://temp').decode('utf-8')
+            basefilename    = self.getname(filename)
+            destination = os.path.join(tempdir, basefilename)
+            xbmcvfs.copy(filename, destination)
 
-    def onAction( self, action ):
-        #try:
-            # Cancel
-            if ( action.getId() in CANCEL_DIALOG or self.getFocusId() == BUTTON_CANCEL and action.getId() in SELECT_ITEM ):
-                array = []
-                self.close()
-            # Okay
-            if ( self.getFocusId() == BUTTON_OK and action.getId() in SELECT_ITEM ):
-                self.close()
+            return common.smart_unicode(destination), True
+
             
-            # Select or deselect item in list
-            if ( action.getId() in SELECT_ITEM and self.getFocusId() == TAGS_LIST ):
-                item = self.getControl( TAGS_LIST ).getSelectedItem()
-                pos  = self.getControl( TAGS_LIST ).getSelectedPosition()
+    def _listdir(self, path):
+
+        try:
+            return xbmcvfs.listdir(path)
+        except:
+            file_list = []
+            dir_list  = []
+            json_response = xbmc.executeJSONRPC('{ "jsonrpc" : "2.0" , "method" : "Files.GetDirectory" , "params" : { "directory" : "%s" , "sort" : { "method" : "file" } } , "id" : 1 }' % common.smart_utf8(path.replace('\\', '\\\\')))
+            jsonobject = json.loads(json_response)
+
+            try:
+                if jsonobject['result']['files']:
+
+                    for item in jsonobject['result']['files']:
+
+                        filename = common.smart_utf8(item['label'])
+                        if item['filetype'] == 'directory':
+                            dir_list.append(filename)
+                        else:
+                            file_list.append(filename)
+                            
+            except Exception,msg:
+                common.log("Scanner.listdir", 'Path "%s"'%path, xbmc.LOGERROR )
+                common.log("Scanner.listdir", "%s - %s"%(Exception,msg), xbmc.LOGERROR )
                 
-                kb = xbmc.Keyboard(item.getLabel2(),  _(30623)%( decoder.smart_utf8(item.getLabel())), False)
-                kb.doModal()
-                if (kb.isConfirmed()):
-                    item.setLabel2(kb.getText())
-                    MPDB.setTranslatedTagType(decoder.smart_unicode(item.getLabel()), decoder.smart_unicode(item.getLabel2()))
-                    self.getControl( TAGS_LIST ).setVisible(False)
-                    self.getControl( TAGS_LIST ).setVisible(True)
-
-                    
+            return dir_list, file_list
plugin.image.mypicsdb/resources/lib/vfs.py to plugin.image.mypicsdb/resources/lib/dbabstractionlayer.py
--- a/plugin.image.mypicsdb/resources/lib/vfs.py
+++ b/plugin.image.mypicsdb/resources/lib/dbabstractionlayer.py
@@ -1,252 +1,289 @@
-'''
-    Convenience wrappers  and extensions for some commonly used VFS functions
-    in XBMC addons.  This module exposes all the functionality of xbmcvfs plus
-    some extra functions.
-
-    Copyright (C) 2012 Patrick Carey
-
-    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, either version 3 of the License, or
-    (at your option) any later version.
-
-    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, see <http://www.gnu.org/licenses/>.
-'''
-
-import json
-import os
-import xbmc
-import xbmcvfs
-
-
-def walk(path):
-
-    '''
-        Reimplementation of os.walk using XBMC's jsonrpc API.
-
-        This has the nice added benefits of being able to walk remote
-        directories and inside compressed files such as rars/zips.
-    '''
-
-    dir_tree = [[path]]
-
-    current_depth = 0
-
-    while True:
-
-        if current_depth > -1:
-
+#!/usr/bin/python
+# -*- coding: utf8 -*-
+
+""" 
+Database abstraction layer for Sqlite and MySql
+Copyright (C) 2012 Xycl
+
+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, either version 3 of the License, or
+(at your option) any later version.
+
+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, see <http://www.gnu.org/licenses/>.
+
+ATTENTION:
+Needs the following entries in addon.xml
+  <requires>
+    .......
+    <import addon="script.module.myconnpy" version="0.3.2"/>
+  </requires>
+
+Usage:
+-----------------------------------------------------------------------------------
+Get a database class :
+
+db = DBFactory('mysql', db_name, db_user, db_pass, db_address='127.0.0.1', port=3306)
+or
+db = DBFactory('sqlite', db_name)
+
+1) The database class automatically connects to the DB within __init__()
+2) Supported methods:
+a) connect() and disconnect(). That means you can disconnect and later reconnect using connect() method as long as the DB class instance exists.
+b) cursor(). Creates a cursor object and returns it.
+c) commit()
+-----------------------------------------------------------------------------------
+Get a Cursor
+cursor = db.cursor()
+
+Supported methods:
+1) close() which closes the cursor.
+2) execute(statement, bind_variables). To use bind variables use the ? as placeholder. Example: "select * from table where column = ?".
+3) fetchone(). Fetches one row. Return None in case of end of fetch.
+4) fetchall(). Fetches all rows.
+5) request(). Does an execute() and fetchall() without the possiblity to use bind variables.
+6) request_with_binds(). Does an execute() and fetchall() with bind variables.
+
+
+Example
+
+db_type  = 'mysql' if common.getaddon_setting('mysql')=='true' else 'sqlite'
+db_name  = 'Pictures.db' if len(common.getaddon_setting('db_name')) == 0 else common.getaddon_setting('db_name')
+if db_type == 'sqlite':
+    db_user    = ''
+    db_pass    = ''
+    db_address = ''
+    db_port    = ''
+else:
+    db_user    = common.getaddon_setting('db_user')
+    db_pass    = common.getaddon_setting('db_pass')
+    db_address = common.getaddon_setting('db_address')
+    db_port    = common.getaddon_setting('db_port')
+
+"""
+
+
+import xbmc, sys
+import common
+
+AddonName = ( sys.modules[ "__main__" ].AddonName )
+
+database=''
+
+def DBFactory(backend, db_name, *args):
+    global database
+    
+    backends = {'mysql':MysqlConnection, 'sqlite':SqliteConnection}
+
+    if backend.lower() == 'mysql':
+        print "mysql"
+        import mysql.connector as database
+            
+    # default is to use Sqlite
+    else:
+        print "Sqlite"
+        try:
+            from sqlite3 import dbapi2 as database
+        except:
+            from pysqlite2 import dbapi2 as database        
+                
+    return backends[backend](db_name, *args)
+    
+
+
+class BaseConnection(object):
+
+    def connect(self):
+        raise NotImplementedError( "Database:connect() not implemented" )
+
+
+    def cursor(self):        
+        raise NotImplementedError( "Database:cursor() not implemented" )
+
+
+    def disconnect(self):
+        self.connection.close()
+
+
+    def commit(self):
+        self.connection.commit()
+
+
+
+class MysqlConnection(BaseConnection):
+
+    def __init__(self, *args):
+        self.connect(*args)
+
+
+    def connect( self, db_name, db_user, db_pass, db_address='127.0.0.1', db_port=3306):
+        self.db_name  = db_name
+        self.db_user = db_user
+        self.db_pass = db_pass
+        if db_port != 3306: 
+            self.db_address = '%s:%s' %(db_address,db_port)
+        else:
+            self.db_address = db_address
+
+        self.connection = database.connect(db_address, db_user, db_pass, db_name)
+        self.connection.set_charset('utf-8')
+        self.connection.set_unicode(True)
+
+
+    def cursor(self):        
+        return MysqlCursor(self.connection.cursor())
+
+
+
+class SqliteConnection(BaseConnection):
+
+    def __init__(self, *args):
+        self.connect(*args)
+
+
+    def connect(self, db_name):
+        self.db_name = db_name
+        self.connection = database.connect(db_name)
+        self.connection.text_factory = unicode
+
+
+    def cursor(self):        
+        return SqliteCursor(self.connection.cursor())
+
+
+
+class BaseCursor(object):
+
+    DEBUGGING = True
+
+    def __init__(self, cursor):
+        self.cursor = cursor
+
+
+    def close(self):
+        self.cursor.close()
+
+
+    def execute(self, sql, bindvariables=None):
+        if bindvariables is not None and isinstance(self, MysqlCursor) == True:
+            sql = sql.replace('?', '%s')
+        if bindvariables is not None:
+            self.cursor.execute(sql, bindvariables)
+        else:
+            self.cursor.execute(sql)
+
+
+    def fetchone(self):
+        row_object = self.cursor.fetchone()
+        if row_object is not None:
+            return [column for column in row_object]
+        else:
+            return None
+
+
+    def fetchall(self):
+        return [row for row in self.cursor.fetchall()]
+
+
+    def request(self, statement):
+        try:
+            self.execute( statement )
+            retour = self.fetchall()
+            self.commit()
+        except Exception,msg:
+            common.log("Database abstraction layer",  "The request failed :", xbmc.LOGERROR )
+            common.log("Database abstraction layer",  "%s - %s"%(Exception,msg), xbmc.LOGERROR )
+            common.log("Database abstraction layer",  "SQL Request> %s"%statement, xbmc.LOGERROR)
+            common.log("Database abstraction layer",  "---", xbmc.LOGERROR )
+            retour= []
+
+        return retour
+
+
+    def request_with_binds(self, statement, bindvariables):
+
+        binds = []
+        for value in bindvariables:
+            if type(value).__name__ == 'str':
+                binds.append(common.smart_unicode(value))
+            else:
+                binds.append(value)
+        try:
+            self.execute( statement, binds )
+            retour = self.fetchall()
+            self.commit()
+
+        except Exception,msg:
             try:
-
-                current_path = dir_tree[current_depth].pop(0)
-                current_dirs, current_files = [], []
-
-                for x in listdir(current_path, extra_metadata=True):
-
-                    if x['filetype'] == 'directory':
-
-                        current_dirs.append(x['file'])
-
-                    else:
-
-                        current_files.append(x['file'])
-
-            except IndexError:
-
-                current_depth -= 1
-
-                dir_tree.pop()
-
-            else:
-
-                yield (current_path, current_dirs, current_files)
-
-                if current_dirs:
-
-                    current_depth += 1
-
-                    dir_tree.append(current_dirs)
-
-        else:
-
-            break
-
-
-def listdir(path, extra_metadata=False):
-
-    '''
-        Reimplementation of os.listdir using XBMC's jsonrpc API.
-
-        Returns a list of file/directory names from the specified path
-
-        Accepts an optional boolean 'extra_metadata' as the second argument
-        which will cause the function to instead return a list of dictionaries
-        containing all of the metadata about each file that was retrieved from
-        XBMC.
-    '''
-
-    fileList = []
-
-    json_response = xbmc.executeJSONRPC('{ "jsonrpc" : "2.0" , "method" : "Files.GetDirectory" , "params" : { "directory" : "%s" , "sort" : { "method" : "file" } } , "id" : 1 }' % path.encode('utf-8').replace('\\', '\\\\'))
-
-    jsonobject = json.loads(json_response)
-
-    if jsonobject['result']['files']:
-
-        for item in jsonobject['result']['files']:
-
-            if extra_metadata:
-
-                fileList.append(item)
-
-            else:
-
-                fileList.append(item['file'])
-
-    return fileList
-
-
-def copy(source, destination):
-
-    """
-    copy(source, destination) -- Copy file to destination, returns true/false.
-
-    source          : file to copy.
-    destination     : destination file
-
-    example:
-     - success = vfs.copy(source, destination)
-    """
-
-    return xbmcvfs.copy(source, destination)
-
-
-def delete(path):
-
-    """
-    delete(file) -- Delete file
-
-    file        : file to delete
-
-    example:
-     - vfs.delete(file)
-    """
-
-    return xbmcvfs.delete(path)
-
-
-def exists(path):
-
-    """
-    exists(path) -- Check if file exists, returns true/false.
-
-    path        : file or folder
-
-    example:
-     - success = vfs.exists(path)
-    """
-
-    return xbmcvfs.exists(path)
-
-
-def mkdir(path):
-
-    """
-    mkdir(path) -- Create a folder.
-
-    path        : folder
-
-    example:
-     - success = vfs.mkdir(path)
-    """
-
-    return xbmcvfs.mkdir(path)
-
-
-def rename(source, target):
-
-    """
-    rename(file, newFileName) -- Rename file, returns true/false.
-
-    file        : file to reaname
-    newFileName : new filename, including the full path
-
-    example:
-     - success = vfs.rename(file, newFileName)
-    """
-
-    return xbmcvfs.rename(source, target)
-
-
-def rmdir(path):
-
-    """
-    rmdir(path) -- Remove a folder.
-
-    path        : folder
-
-    example:
-     - success = vfs.rmdir(path)
-    """
-
-    return xbmcvfs.rmdir(path)
-
-
-def comparepathlists(list1, list2, fullpath=False):
-
-    """
-        comparepathlists(list1, list2) -- Compare two lists of paths
-
-        list1 : list, contains paths (local or remote, absolute or relative)
-        list2 : list, contains paths (local or remote, absolute or relative)
-        fullpath : boolean, set True to compare perform straight comparison of lists
-                            set False (default) to compare on filename portions of each list
-
-        returns: dictionary:
-            common_items: list, contains paths of items common to both lists
-            list1_items: list, contains paths of items found only in list1
-            list2_items: list, contains paths of items found only in list2
-
-        example:
-         - compare = comparepathlists(list1, list2)
-    """
-
-    # initialise dict to store results and temp data
-    results = {}
-    temp_data = {}
-
-    if fullpath:
-
-        temp_path = lambda x: x
-
-    else:
-
-        temp_path = lambda x: os.path.split(x)[1]
-
-    for path in list1:
-
-        temp_data['list1'].append(temp_path(path))
-
-    for path in list2:
-
-        temp_data['list2'].append(temp_path(path))
-
-    # get items not in list 2
-    results['list1_items'] = []
-    gen = (i for i, x in enumerate(temp_data['list1']) if not x in temp_data['list2'])
-    for i in gen:
-        results['list1_items'].append(list1[i])
-
-    # get items not in list 1
-    results['list2_items'] = []
-    gen = (i for i, x in enumerate(temp_data['list2']) if not x in temp_data['list1'])
-    for i in gen:
-        results['list2_items'].append(list2[i])
-
-    return results
+                common.log("Database abstraction layer",  "The request failed :", xbmc.LOGERROR )
+                common.log("Database abstraction layer",  "%s - %s"%(Exception,msg), xbmc.LOGERROR )
+            except:
+                pass
+            try:
+                common.log("Database abstraction layer",  "SQL RequestWithBinds > %s"%statement, xbmc.LOGERROR)
+            except:
+                pass
+            try:
+                i = 1
+                for var in binds:
+                    common.log ("SQL RequestWithBinds %d> %s"%(i,var), xbmc.LOGERROR)
+                    i=i+1
+                common.log("Database abstraction layer",  "---", xbmc.LOGERROR )
+            except:
+                pass
+            retour= []
+
+        return retour
+
+
+
+class MysqlCursor(BaseCursor):
+    pass
+"""
+    def __init__(self, cursor)
+        self.cursor = cursor
+
+
+    def execute(self, sql, bindvariables=None):
+        if bindvariables is not None and isinstance(self, MysqlCursor) == True
+            sql = sql.replace('?', '%s')
+        self.cursor.execute(sql, bindvariables)
+
+
+    def fetchone(self):
+        row_object = self.cursor.fetchone():
+        return [column for column in row_object]
+
+
+    def fetchall(self):
+        return [row for row in self.cursor.fetchall()]
+"""
+
+
+
+class SqliteCursor(BaseCursor):
+    pass
+"""
+    def __init__(self, cursor)
+        self.cursor = cursor
+
+
+    def execute(self, sql, bindvariables=None):
+        self.cursor.execute(sql, bindvariables)
+
+
+    def fetchone(self):
+        row_object = self.cursor.fetchone():
+        return [column for column in row_object]
+
+
+    def fetchall(self):
+        return [row for row in self.cursor]
+"""
+
1 2 > >> (Page 1 of 2)