Phill has proposed merging lp:~phill-ridout/openlp/bug1012110 into lp:openlp.

Requested reviews:
  Phill (phill-ridout)
  Andreas Preikschat (googol)
  Jonathan Corwin (j-corwin)
  Raoul Snyman (raoul-snyman)
Related bugs:
  Bug #1012110 in OpenLP: "pptviewlib does not accept unicode filename"
  https://bugs.launchpad.net/openlp/+bug/1012110

For more details, see:
https://code.launchpad.net/~phill-ridout/openlp/bug1012110/+merge/205856

The main change here is to get the PPTViewer working with unicode filenames. 
There have also been some other improvments in PPTViewer reliability.

Also fixed logging so that it saves the log in UTF-8 rather than the system 
default (1525) on my Windows VM. This was causing issues with when logging 
unicode. 

Finally removed some str()'s that I came across. Remnants from the Py2 days and 
2to3's conversion of unicode() to str()

One of the tests in test_presentationcontroller is broken, but it is in trunk, 
I've had a look at fixing it, but it a bit to deep for me...
-- 
https://code.launchpad.net/~phill-ridout/openlp/bug1012110/+merge/205856
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file '.bzrignore'
--- .bzrignore	2013-09-14 02:42:12 +0000
+++ .bzrignore	2014-02-11 21:32:24 +0000
@@ -28,3 +28,4 @@
 *.nja
 *.orig
 __pycache__
+*.dll

=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py	2013-12-30 19:50:34 +0000
+++ openlp/core/__init__.py	2014-02-11 21:32:24 +0000
@@ -234,7 +234,7 @@
     """
     check_directory_exists(log_path, True)
     filename = os.path.join(log_path, 'openlp.log')
-    logfile = logging.FileHandler(filename, 'w')
+    logfile = logging.FileHandler(filename, 'w', encoding="UTF-8")
     logfile.setFormatter(logging.Formatter('%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
     log.addHandler(logfile)
     if log.isEnabledFor(logging.DEBUG):

=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py	2014-01-01 09:33:07 +0000
+++ openlp/core/lib/__init__.py	2014-02-11 21:32:24 +0000
@@ -185,9 +185,9 @@
     if not return_icon:
         return
     if os.path.exists(thumb_path):
-        return build_icon(str(thumb_path))
+        return build_icon(thumb_path)
     # Fallback for files with animation support.
-    return build_icon(str(image_path))
+    return build_icon(image_path)
 
 
 def validate_thumb(file_path, thumb_path):

=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py	2013-12-28 21:33:38 +0000
+++ openlp/core/lib/mediamanageritem.py	2014-02-11 21:32:24 +0000
@@ -388,7 +388,7 @@
             if target_group is None:
                 self.list_view.clear()
             self.load_list(full_list, target_group)
-            last_dir = os.path.split(str(files[0]))[0]
+            last_dir = os.path.split(files[0])[0]
             Settings().setValue(self.settings_section + '/last directory', last_dir)
             Settings().setValue('%s/%s files' % (self.settings_section, self.settings_section), self.get_file_list())
         if duplicates_found:

=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py	2013-12-28 21:33:38 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py	2014-02-11 21:32:24 +0000
@@ -166,7 +166,7 @@
                 self.main_window.increment_progress_bar()
             if current_list.count(file) > 0:
                 continue
-            filename = os.path.split(str(file))[1]
+            filename = os.path.split(file)[1]
             if not os.path.exists(file):
                 item_name = QtGui.QListWidgetItem(filename)
                 item_name.setIcon(build_icon(ERROR_IMAGE))
@@ -184,7 +184,7 @@
                 controller_name = self.findControllerByType(filename)
                 if controller_name:
                     controller = self.controllers[controller_name]
-                    doc = controller.add_document(str(file))
+                    doc = controller.add_document(file)
                     thumb = os.path.join(doc.get_thumbnail_folder(), 'icon.png')
                     preview = doc.get_thumbnail_path(1, True)
                     if not preview and not initial_load:

=== modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py'
--- openlp/plugins/presentations/lib/pptviewcontroller.py	2013-12-24 08:56:50 +0000
+++ openlp/plugins/presentations/lib/pptviewcontroller.py	2014-02-11 21:32:24 +0000
@@ -27,8 +27,8 @@
 # Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
 ###############################################################################
 
+import logging
 import os
-import logging
 
 if os.name == 'nt':
     from ctypes import cdll
@@ -121,12 +121,17 @@
         the background PptView task started earlier.
         """
         log.debug('LoadPresentation')
+        temp_folder = self.get_temp_folder()
         size = ScreenList().current['size']
         rect = RECT(size.x(), size.y(), size.right(), size.bottom())
-        filepath = str(self.filepath.replace('/', '\\'))
-        if not os.path.isdir(self.get_temp_folder()):
-            os.makedirs(self.get_temp_folder())
-        self.ppt_id = self.controller.process.OpenPPT(filepath, None, rect, str(self.get_temp_folder()) + '\\slide')
+        file_path = os.path.normpath(self.filepath)
+        preview_path = os.path.join(temp_folder, 'slide')
+        # Ensure that the paths are null terminated
+        file_path = file_path.encode('utf-16-le') + b'\0'
+        preview_path = preview_path.encode('utf-16-le') + b'\0'
+        if not os.path.isdir(temp_folder):
+            os.makedirs(temp_folder)
+        self.ppt_id = self.controller.process.OpenPPT(file_path, None, rect, preview_path)
         if self.ppt_id >= 0:
             self.create_thumbnails()
             self.stop_presentation()

=== modified file 'openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp'
--- openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp	2013-12-24 08:56:50 +0000
+++ openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp	2014-02-11 21:32:24 +0000
@@ -61,18 +61,18 @@
     switch(ulReasonForCall)
     {
         case DLL_PROCESS_ATTACH:
-            DEBUG("PROCESS_ATTACH\n");
+            DEBUG(L"PROCESS_ATTACH\n");
             break;
         case DLL_THREAD_ATTACH:
-            //DEBUG("THREAD_ATTACH\n");
+            //DEBUG(L"THREAD_ATTACH\n");
             break;
         case DLL_THREAD_DETACH:
-            //DEBUG("THREAD_DETACH\n");
+            //DEBUG(L"THREAD_DETACH\n");
             break;
         case DLL_PROCESS_DETACH:
             // Clean up... hopefully there is only the one process attached?
             // We'll find out soon enough during tests!
-            DEBUG("PROCESS_DETACH\n");
+            DEBUG(L"PROCESS_DETACH\n");
             for (int i = 0; i < MAX_PPTS; i++)
                 ClosePPT(i);
             break;
@@ -84,18 +84,18 @@
 {
     printf("SetDebug\n");
     debug = onOff;
-    DEBUG("enabled\n");
+    DEBUG(L"enabled\n");
 }
 
 DllExport BOOL CheckInstalled()
 {
-    char cmdLine[MAX_PATH * 2];
+    wchar_t cmdLine[MAX_PATH * 2];
 
-    DEBUG("CheckInstalled\n");
+    DEBUG(L"CheckInstalled\n");
     BOOL found = GetPPTViewerPath(cmdLine, sizeof(cmdLine));
     if(found)
     {
-        DEBUG("Exe: %s\n", cmdLine);
+        DEBUG(L"Exe: %s\n", cmdLine);
     }
     return found;
 }
@@ -106,20 +106,20 @@
 // "<n>.bmp" will be appended to complete the path. E.g. "c:\temp\slide" would
 // create "c:\temp\slide1.bmp" slide2.bmp, slide3.bmp etc.
 // It will also create a *info.txt containing information about the ppt
-DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect,
-    char *previewPath)
+DllExport int OpenPPT(wchar_t *filename, HWND hParentWnd, RECT rect,
+    wchar_t *previewPath)
 {
     STARTUPINFO si;
     PROCESS_INFORMATION pi;
-    char cmdLine[MAX_PATH * 2];
+    wchar_t cmdLine[MAX_PATH * 2];
     int id;
 
-    DEBUG("OpenPPT start: %s; %s\n", filename, previewPath);
-    DEBUG("OpenPPT start: %u; %i, %i, %i, %i\n", hParentWnd, rect.top,
+    DEBUG(L"OpenPPT start: %s; %s\n", filename, previewPath);
+    DEBUG(L"OpenPPT start: %u; %i, %i, %i, %i\n", hParentWnd, rect.top,
         rect.left, rect.bottom, rect.right);
     if (GetPPTViewerPath(cmdLine, sizeof(cmdLine)) == FALSE)
     {
-        DEBUG("OpenPPT: GetPPTViewerPath failed\n");
+        DEBUG(L"OpenPPT: GetPPTViewerPath failed\n");
         return -1;
     }
     id = -1;
@@ -133,12 +133,12 @@
     }
     if (id < 0)
     {
-        DEBUG("OpenPPT: Too many PPTs\n");
+        DEBUG(L"OpenPPT: Too many PPTs\n");
         return -1;
     }
     memset(&pptView[id], 0, sizeof(PPTVIEW));
-    strcpy_s(pptView[id].filename, MAX_PATH, filename);
-    strcpy_s(pptView[id].previewPath, MAX_PATH, previewPath);
+    wcscpy_s(pptView[id].filename, MAX_PATH, filename);
+    wcscpy_s(pptView[id].previewPath, MAX_PATH, previewPath);
     pptView[id].state = PPT_CLOSED;
     pptView[id].slideCount = 0;
     pptView[id].currentSlide = 0;
@@ -169,9 +169,9 @@
         pptView[id].rect.bottom = rect.bottom;
         pptView[id].rect.right = rect.right;
     }
-    strcat_s(cmdLine, MAX_PATH * 2, " /F /S \"");
-    strcat_s(cmdLine, MAX_PATH * 2, filename);
-    strcat_s(cmdLine, MAX_PATH * 2, "\"");
+    wcscat_s(cmdLine, MAX_PATH * 2, L" /F /S \"");
+    wcscat_s(cmdLine, MAX_PATH * 2, filename);
+    wcscat_s(cmdLine, MAX_PATH * 2, L"\"");
     memset(&si, 0, sizeof(si));
     memset(&pi, 0, sizeof(pi));
     BOOL gotInfo = GetPPTInfo(id);
@@ -190,7 +190,7 @@
     globalHook = SetWindowsHookEx(WH_CBT, CbtProc, hInstance, NULL);
     if (globalHook == 0)
     {
-        DEBUG("OpenPPT: SetWindowsHookEx failed\n");
+        DEBUG(L"OpenPPT: SetWindowsHookEx failed\n");
         ClosePPT(id);
         return -1;
     }
@@ -198,7 +198,7 @@
     Sleep(10);
     if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, 0, NULL, &si, &pi))
     {
-        DEBUG("OpenPPT: CreateProcess failed: %s\n", cmdLine);
+        DEBUG(L"OpenPPT: CreateProcess failed: %s\n", cmdLine);
         ClosePPT(id);
         return -1;
     }
@@ -210,32 +210,32 @@
         Sleep(10);
     if (gotInfo)
     {
-        DEBUG("OpenPPT: Info loaded, no refresh\n");
+        DEBUG(L"OpenPPT: Info loaded, no refresh\n");
         pptView[id].state = PPT_LOADED;
         Resume(id);
     }
     else
     {
-        DEBUG("OpenPPT: Get info\n");
+        DEBUG(L"OpenPPT: Get info\n");
         pptView[id].steps = 0;
         int steps = 0;
         while (pptView[id].state == PPT_OPENED)
         {
             if (steps <= pptView[id].steps)
             {
-                Sleep(20);
-                DEBUG("OpenPPT: Step %d/%d\n", steps, pptView[id].steps);
+                Sleep(100);
+                DEBUG(L"OpenPPT: Step %d/%d\n", steps, pptView[id].steps);
                 steps++;
                 NextStep(id);
             }
             Sleep(10);
         }
-        DEBUG("OpenPPT: Slides %d, Steps %d, first slide steps %d\n",
+        DEBUG(L"OpenPPT: Slides %d, Steps %d, first slide steps %d\n",
             pptView[id].slideCount, pptView[id].steps,
             pptView[id].firstSlideSteps);
         for(int i = 1; i <= pptView[id].slideCount; i++)
         {
-            DEBUG("OpenPPT: Slide %d = %d\n", i, pptView[id].slideNos[i]);
+            DEBUG(L"OpenPPT: Slide %d = %d\n", i, pptView[id].slideNos[i]);
         }
         SavePPTInfo(id);
         if (pptView[id].state == PPT_CLOSING
@@ -257,7 +257,7 @@
         }
         pptView[id].msgHook = NULL;
     }
-    DEBUG("OpenPPT: Exit: id=%i\n", id);
+    DEBUG(L"OpenPPT: Exit: id=%i\n", id);
     return id;
 }
 // Load information about the ppt from an info.txt file.
@@ -270,75 +270,75 @@
 BOOL GetPPTInfo(int id)
 {
     struct _stat fileStats;
-    char info[MAX_PATH];
+    wchar_t info[MAX_PATH];
     FILE* pFile;
-    char buf[100];
+    wchar_t buf[100];
 
-    DEBUG("GetPPTInfo: start\n");
-    if (_stat(pptView[id].filename, &fileStats) != 0)
+    DEBUG(L"GetPPTInfo: start\n");
+    if (_wstat(pptView[id].filename, &fileStats) != 0)
     {
         return FALSE;
     }
-    sprintf_s(info, MAX_PATH, "%sinfo.txt", pptView[id].previewPath);
-    int err = fopen_s(&pFile, info, "r");
+    swprintf_s(info, MAX_PATH, L"%sinfo.txt", pptView[id].previewPath);
+    int err = _wfopen_s(&pFile, info, L"r");
     if (err != 0)
     {
-        DEBUG("GetPPTInfo: file open failed - %d\n", err);
-        return FALSE;
-    }
-    fgets(buf, 100, pFile); // version == 1
-    fgets(buf, 100, pFile);
-    if (fileStats.st_mtime != atoi(buf))
-    {
-        DEBUG("GetPPTInfo: date changed\n");
-        fclose (pFile);
-        return FALSE;
-    }
-    fgets(buf, 100, pFile);
-    if (fileStats.st_size != atoi(buf))
-    {
-        DEBUG("GetPPTInfo: size changed\n");
-        fclose (pFile);
-        return FALSE;
-    }
-    fgets(buf, 100, pFile); // slidecount
-    int slideCount = atoi(buf);
-    fgets(buf, 100, pFile); // first slide steps
-    int firstSlideSteps = atoi(buf);
+        DEBUG(L"GetPPTInfo: file open failed - %d\n", err);
+        return FALSE;
+    }
+    fgetws(buf, 100, pFile); // version == 1
+    fgetws(buf, 100, pFile);
+    if (fileStats.st_mtime != _wtoi(buf))
+    {
+        DEBUG(L"GetPPTInfo: date changed\n");
+        fclose (pFile);
+        return FALSE;
+    }
+    fgetws(buf, 100, pFile);
+    if (fileStats.st_size != _wtoi(buf))
+    {
+        DEBUG(L"GetPPTInfo: size changed\n");
+        fclose (pFile);
+        return FALSE;
+    }
+    fgetws(buf, 100, pFile); // slidecount
+    int slideCount = _wtoi(buf);
+    fgetws(buf, 100, pFile); // first slide steps
+    int firstSlideSteps = _wtoi(buf);
     // check all the preview images still exist
     for (int i = 1; i <= slideCount; i++)
     {
-        sprintf_s(info, MAX_PATH, "%s%i.bmp", pptView[id].previewPath, i);
+        swprintf_s(info, MAX_PATH, L"%s%i.bmp", pptView[id].previewPath, i);
         if (GetFileAttributes(info) == INVALID_FILE_ATTRIBUTES)
         {
-            DEBUG("GetPPTInfo: bmp not found\n");
+            DEBUG(L"GetPPTInfo: bmp not found\n");
             return FALSE;
         }
     }
     fclose(pFile);
     pptView[id].slideCount = slideCount;
     pptView[id].firstSlideSteps = firstSlideSteps;
-    DEBUG("GetPPTInfo: exit ok\n");
+    DEBUG(L"GetPPTInfo: exit ok\n");
     return TRUE;
 }
 
 BOOL SavePPTInfo(int id)
 {
     struct _stat fileStats;
-    char info[MAX_PATH];
+    wchar_t info[MAX_PATH];
     FILE* pFile;
 
-    DEBUG("SavePPTInfo: start\n");
-    if (_stat(pptView[id].filename, &fileStats) != 0)
+    DEBUG(L"SavePPTInfo: start\n");
+    if (_wstat(pptView[id].filename, &fileStats) != 0)
     {
-        DEBUG("SavePPTInfo: stat of %s failed\n", pptView[id].filename);
+        DEBUG(L"SavePPTInfo: stat of %s failed\n", pptView[id].filename);
         return FALSE;
     }
-    sprintf_s(info, MAX_PATH, "%sinfo.txt", pptView[id].previewPath);
-    int err = fopen_s(&pFile, info, "w");
+    swprintf_s(info, MAX_PATH, L"%sinfo.txt", pptView[id].previewPath);
+    int err = _wfopen_s(&pFile, info, L"w");
     if (err != 0)
     {
-        DEBUG("SavePPTInfo: fopen of %s failed%i\n", info, err);
+        DEBUG(L"SavePPTInfo: fopen of %s failed%i\n", info, err);
         return FALSE;
     }
     fprintf(pFile, "1\n");
@@ -347,21 +347,21 @@
     fprintf(pFile, "%u\n", pptView[id].slideCount);
     fprintf(pFile, "%u\n", pptView[id].firstSlideSteps);
     fclose(pFile);
-    DEBUG("SavePPTInfo: exit ok\n");
+    DEBUG(L"SavePPTInfo: exit ok\n");
     return TRUE;
 }
 
 // Get the path of the PowerPoint viewer from the registry
-BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize)
+BOOL GetPPTViewerPath(wchar_t *pptViewerPath, int stringSize)
 {
-    char cwd[MAX_PATH];
+    wchar_t cwd[MAX_PATH];
 
-    DEBUG("GetPPTViewerPath: start\n");
+    DEBUG(L"GetPPTViewerPath: start\n");
     if(GetPPTViewerPathFromReg(pptViewerPath, stringSize))
     {
-        if(_access(pptViewerPath, 0) != -1)
+        if(_waccess(pptViewerPath, 0) != -1)
         {
-            DEBUG("GetPPTViewerPath: exit registry\n");
+            DEBUG(L"GetPPTViewerPath: exit registry\n");
             return TRUE;
         }
     }
@@ -370,37 +370,37 @@
     // upset those who like to put things somewhere else
 
     // Viewer 2007 in 64bit Windows:
-    if(_access("C:\\Program Files (x86)\\Microsoft Office\\Office12\\PPTVIEW.EXE",
+    if(_waccess(L"C:\\Program Files (x86)\\Microsoft Office\\Office12\\PPTVIEW.EXE",
         0) != -1)
     {
-        strcpy_s(
-            "C:\\Program Files (x86)\\Microsoft Office\\Office12\\PPTVIEW.EXE",
+        wcscpy_s(
+            L"C:\\Program Files (x86)\\Microsoft Office\\Office12\\PPTVIEW.EXE",
             stringSize, pptViewerPath);
-        DEBUG("GetPPTViewerPath: exit 64bit 2007\n");
+        DEBUG(L"GetPPTViewerPath: exit 64bit 2007\n");
         return TRUE;
     }
     // Viewer 2007 in 32bit Windows:
-    if(_access("C:\\Program Files\\Microsoft Office\\Office12\\PPTVIEW.EXE", 0)
+    if(_waccess(L"C:\\Program Files\\Microsoft Office\\Office12\\PPTVIEW.EXE", 0)
         != -1)
     {
-        strcpy_s("C:\\Program Files\\Microsoft Office\\Office12\\PPTVIEW.EXE",
+        wcscpy_s(L"C:\\Program Files\\Microsoft Office\\Office12\\PPTVIEW.EXE",
             stringSize, pptViewerPath);
-        DEBUG("GetPPTViewerPath: exit 32bit 2007\n");
+        DEBUG(L"GetPPTViewerPath: exit 32bit 2007\n");
         return TRUE;
     }
     // Give them the opportunity to place it in the same folder as the app
-    _getcwd(cwd, MAX_PATH);
-    strcat_s(cwd, MAX_PATH, "\\PPTVIEW.EXE");
-    if(_access(cwd, 0) != -1)
+    _wgetcwd(cwd, MAX_PATH);
+    wcscat_s(cwd, MAX_PATH, L"\\PPTVIEW.EXE");
+    if(_waccess(cwd, 0) != -1)
     {
-        strcpy_s(pptViewerPath, stringSize, cwd);
-        DEBUG("GetPPTViewerPath: exit local\n");
+        wcscpy_s(pptViewerPath, stringSize, cwd);
+        DEBUG(L"GetPPTViewerPath: exit local\n");
         return TRUE;
     }
-    DEBUG("GetPPTViewerPath: exit fail\n");
+    DEBUG(L"GetPPTViewerPath: exit fail\n");
     return FALSE;
 }
-BOOL GetPPTViewerPathFromReg(char *pptViewerPath, int stringSize)
+BOOL GetPPTViewerPathFromReg(wchar_t *pptViewerPath, int stringSize)
 {
     HKEY hKey;
     DWORD dwType, dwSize;
@@ -411,17 +411,17 @@
     // PPT Viewer 2003 (recent versions)
     // PPT Viewer 2003 (older versions) 
     // PPT Viewer 97
-    if ((RegOpenKeyEx(HKEY_CLASSES_ROOT,
-        "PowerPointViewer.Show.12\\shell\\Show\\command", 0, KEY_READ, &hKey)
-        != ERROR_SUCCESS)
-        && (RegOpenKeyEx(HKEY_CLASSES_ROOT,
-        "PowerPointViewer.Show.11\\shell\\Show\\command", 0, KEY_READ, &hKey)
-        != ERROR_SUCCESS)
-        && (RegOpenKeyEx(HKEY_CLASSES_ROOT,
-        "Applications\\PPTVIEW.EXE\\shell\\open\\command", 0, KEY_READ, &hKey)
-        != ERROR_SUCCESS)
-        && (RegOpenKeyEx(HKEY_CLASSES_ROOT,
-        "Applications\\PPTVIEW.EXE\\shell\\Show\\command", 0, KEY_READ, &hKey)
+    if ((RegOpenKeyExW(HKEY_CLASSES_ROOT,
+        L"PowerPointViewer.Show.12\\shell\\Show\\command", 0, KEY_READ, &hKey)
+        != ERROR_SUCCESS)
+        && (RegOpenKeyExW(HKEY_CLASSES_ROOT,
+        L"PowerPointViewer.Show.11\\shell\\Show\\command", 0, KEY_READ, &hKey)
+        != ERROR_SUCCESS)
+        && (RegOpenKeyExW(HKEY_CLASSES_ROOT,
+        L"Applications\\PPTVIEW.EXE\\shell\\open\\command", 0, KEY_READ, &hKey)
+        != ERROR_SUCCESS)
+        && (RegOpenKeyExW(HKEY_CLASSES_ROOT,
+        L"Applications\\PPTVIEW.EXE\\shell\\Show\\command", 0, KEY_READ, &hKey)
         != ERROR_SUCCESS))
     {
         return FALSE;
@@ -436,14 +436,14 @@
         return FALSE;
     }
     // remove "%1" from end of key value
-    pptViewerPath[strlen(pptViewerPath) - 4] = '\0';
+    pptViewerPath[wcslen(pptViewerPath) - 4] = '\0';
     return TRUE;
 }
 
 // Unhook the Windows hook
 void Unhook(int id)
 {
-    DEBUG("Unhook: start %d\n", id);
+    DEBUG(L"Unhook: start %d\n", id);
     if (pptView[id].hook != NULL)
     {
         UnhookWindowsHookEx(pptView[id].hook);
@@ -454,13 +454,13 @@
     }
     pptView[id].hook = NULL;
     pptView[id].msgHook = NULL;
-    DEBUG("Unhook: exit ok\n");
+    DEBUG(L"Unhook: exit ok\n");
 }
 
 // Close the PowerPoint viewer, release resources
 DllExport void ClosePPT(int id)
 {
-    DEBUG("ClosePPT: start%d\n", id);
+    DEBUG(L"ClosePPT: start%d\n", id);
     pptView[id].state = PPT_CLOSED;
     Unhook(id);
     if (pptView[id].hWnd == 0)
@@ -474,13 +474,13 @@
     CloseHandle(pptView[id].hThread);
     CloseHandle(pptView[id].hProcess);
     memset(&pptView[id], 0, sizeof(PPTVIEW));
-    DEBUG("ClosePPT: exit ok\n");
+    DEBUG(L"ClosePPT: exit ok\n");
     return;
 }
 // Moves the show back onto the display
 DllExport void Resume(int id)
 {
-    DEBUG("Resume: %d\n", id);
+    DEBUG(L"Resume: %d\n", id);
     MoveWindow(pptView[id].hWnd, pptView[id].rect.left,
         pptView[id].rect.top,
         pptView[id].rect.right - pptView[id].rect.left,
@@ -490,7 +490,7 @@
 // Moves the show off the screen so it can't be seen
 DllExport void Stop(int id)
 {
-    DEBUG("Stop:%d\n", id);
+    DEBUG(L"Stop:%d\n", id);
     MoveWindow(pptView[id].hWnd, -32000, -32000,
         pptView[id].rect.right - pptView[id].rect.left,
         pptView[id].rect.bottom - pptView[id].rect.top, TRUE);
@@ -499,7 +499,7 @@
 // Return the total number of slides
 DllExport int GetSlideCount(int id)
 {
-    DEBUG("GetSlideCount:%d\n", id);
+    DEBUG(L"GetSlideCount:%d\n", id);
     if (pptView[id].state == 0)
     {
         return -1;
@@ -513,7 +513,7 @@
 // Return the number of the slide currently viewing
 DllExport int GetCurrentSlide(int id)
 {
-    DEBUG("GetCurrentSlide:%d\n", id);
+    DEBUG(L"GetCurrentSlide:%d\n", id);
     if (pptView[id].state == 0)
     {
         return -1;
@@ -527,7 +527,7 @@
 // Take a step forwards through the show
 DllExport void NextStep(int id)
 {
-    DEBUG("NextStep:%d (%d)\n", id, pptView[id].currentSlide);
+    DEBUG(L"NextStep:%d (%d)\n", id, pptView[id].currentSlide);
     if (pptView[id].currentSlide > pptView[id].slideCount) return;
     if (pptView[id].currentSlide < pptView[id].slideCount)
     {
@@ -540,7 +540,7 @@
 // Take a step backwards through the show
 DllExport void PrevStep(int id)
 {
-    DEBUG("PrevStep:%d (%d)\n", id, pptView[id].currentSlide);
+    DEBUG(L"PrevStep:%d (%d)\n", id, pptView[id].currentSlide);
     if (pptView[id].currentSlide > 1)
     {
         pptView[id].guess = pptView[id].currentSlide - 1;
@@ -556,7 +556,7 @@
     // So send random unmapped letter first (say 'A'), then we can
     // better guarantee B will blank instead of trying to guess
     // whether it was already blank or not.
-    DEBUG("Blank:%d\n", id);
+    DEBUG(L"Blank:%d\n", id);
     HWND h1 = GetForegroundWindow();
     HWND h2 = GetFocus();
     SetForegroundWindow(pptView[id].hWnd);
@@ -573,7 +573,7 @@
 // Unblank the show
 DllExport void Unblank(int id)
 {
-    DEBUG("Unblank:%d\n", id);
+    DEBUG(L"Unblank:%d\n", id);
     // Pressing any key resumes.
     // For some reason SendMessage works for unblanking, but not blanking.
     SendMessage(pptView[id].hWnd2, WM_CHAR, 'A', 0);
@@ -582,7 +582,7 @@
 // Go directly to a slide
 DllExport void GotoSlide(int id, int slideNo)
 {
-    DEBUG("GotoSlide %i %i:\n", id, slideNo);
+    DEBUG(L"GotoSlide %i %i:\n", id, slideNo);
     // Did try WM_KEYDOWN/WM_CHAR/WM_KEYUP with SendMessage but didn't work
     // perhaps I was sending to the wrong window? No idea.
     // Anyway fall back to keybd_event, which is OK as long we makesure
@@ -619,7 +619,7 @@
     // Only way I've found to get around this is to step backwards all the way
     // through. Lets move the window out of the way first so the audience
     // doesn't see this.
-    DEBUG("RestartShow:%d\n", id);
+    DEBUG(L"RestartShow:%d\n", id);
     Stop(id);
     GotoSlide(id, pptView[id].slideCount);
     for (int i=0; i <= pptView[id].steps - pptView[id].lastSlideSteps; i++)
@@ -644,12 +644,12 @@
     HHOOK hook = globalHook;
     if (nCode == HCBT_CREATEWND)
     {
-        char csClassName[16];
+        wchar_t csClassName[32];
         HWND hCurrWnd = (HWND)wParam;
         DWORD retProcId = NULL;
         GetClassName(hCurrWnd, csClassName, sizeof(csClassName));
-        if ((strcmp(csClassName, "paneClassDC") == 0)
-          ||(strcmp(csClassName, "screenClass") == 0))
+        if ((wcscmp(csClassName, L"paneClassDC") == 0)
+          ||(wcscmp(csClassName, L"screenClass") == 0))
         {
             int id = -1;
             DWORD windowThread = GetWindowThreadProcessId(hCurrWnd, NULL);
@@ -663,7 +663,7 @@
             }
             if (id >= 0)
             {
-                if (strcmp(csClassName, "paneClassDC") == 0)
+                if (wcscmp(csClassName, L"paneClassDC") == 0)
                 {
                     pptView[id].hWnd2 = hCurrWnd;
                 }
@@ -737,7 +737,7 @@
     CWPSTRUCT *cwp;
     cwp = (CWPSTRUCT *)lParam;
     HHOOK hook = NULL;
-    char filename[MAX_PATH];
+    wchar_t filename[MAX_PATH];
 
     DWORD windowThread = GetWindowThreadProcessId(cwp->hwnd, NULL);
     int id = -1;
@@ -758,9 +758,9 @@
             {
                 if ((pptView[id].currentSlide > 0)
                     && (pptView[id].previewPath != NULL
-                    && strlen(pptView[id].previewPath) > 0))
+                    && wcslen(pptView[id].previewPath) > 0))
                 {
-                    sprintf_s(filename, MAX_PATH, "%s%i.bmp",
+                    swprintf_s(filename, MAX_PATH, L"%s%i.bmp",
                         pptView[id].previewPath,
                         pptView[id].currentSlide);
                     CaptureAndSaveWindow(cwp->hwnd, filename);
@@ -820,7 +820,7 @@
     return CallNextHookEx(hook, nCode, wParam, lParam);
 }
 
-VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename)
+VOID CaptureAndSaveWindow(HWND hWnd, wchar_t* filename)
 {
     HBITMAP hBmp;
     if ((hBmp = CaptureWindow(hWnd)) == NULL)
@@ -863,7 +863,7 @@
 
         // Writing:
         FILE* pFile;
-        int err = fopen_s(&pFile, filename, "wb");
+        int err = _wfopen_s(&pFile, filename, L"wb");
         if (err == 0)
         {
             fwrite(&bmf, sizeof(bmf), 1, pFile);
@@ -893,7 +893,7 @@
         if ((hMemDC = CreateCompatibleDC(hDC)) != NULL)
         {
             hDCBmp = (HBITMAP)SelectObject(hMemDC, hImage);
-            HMODULE hLib = LoadLibrary("User32");
+			HMODULE hLib = LoadLibrary(L"User32");
             // PrintWindow works for windows outside displayable area
             // but was only introduced in WinXP. BitBlt requires the window to
             // be topmost and within the viewable area of the display

=== modified file 'openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h'
--- openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h	2013-12-24 08:56:50 +0000
+++ openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h	2014-02-11 21:32:24 +0000
@@ -26,13 +26,13 @@
 
 #define DllExport extern "C"  __declspec( dllexport )
 
-#define DEBUG(...)  if (debug) printf(__VA_ARGS__)
+#define DEBUG(...)  if (debug) wprintf(__VA_ARGS__)
 
 enum PPTVIEWSTATE {PPT_CLOSED, PPT_STARTED, PPT_OPENED, PPT_LOADED,
     PPT_CLOSING};
 
-DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect,
-    char *previewPath);
+DllExport int OpenPPT(wchar_t *filename, HWND hParentWnd, RECT rect,
+    wchar_t *previewPath);
 DllExport BOOL CheckInstalled();
 DllExport void ClosePPT(int id);
 DllExport int GetCurrentSlide(int id);
@@ -50,11 +50,11 @@
 LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam);
 LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam);
 LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);
-BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize);
-BOOL GetPPTViewerPathFromReg(char *pptViewerPath, int stringSize);
+BOOL GetPPTViewerPath(wchar_t *pptViewerPath, int stringSize);
+BOOL GetPPTViewerPathFromReg(wchar_t *pptViewerPath, int stringSize);
 HBITMAP CaptureWindow(HWND hWnd);
-VOID SaveBitmap(CHAR* filename, HBITMAP hBmp) ;
-VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename);
+VOID SaveBitmap(wchar_t* filename, HBITMAP hBmp) ;
+VOID CaptureAndSaveWindow(HWND hWnd, wchar_t* filename);
 BOOL GetPPTInfo(int id);
 BOOL SavePPTInfo(int id);
 void Unhook(int id);
@@ -80,8 +80,8 @@
     int lastSlideSteps;
     int steps;
     int guess;
-    char filename[MAX_PATH];
-    char previewPath[MAX_PATH];
+    wchar_t filename[MAX_PATH];
+    wchar_t previewPath[MAX_PATH];
     int slideNos[MAX_SLIDES];
     PPTVIEWSTATE state;
 };

=== modified file 'openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj'
--- openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj	2010-09-14 18:18:47 +0000
+++ openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj	2014-02-11 21:32:24 +0000
@@ -21,7 +21,7 @@
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="2"
-			CharacterSet="2"
+			CharacterSet="1"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -93,7 +93,7 @@
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="2"
-			CharacterSet="2"
+			CharacterSet="1"
 			WholeProgramOptimization="1"
 			>
 			<Tool

=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
--- openlp/plugins/presentations/lib/presentationcontroller.py	2013-12-28 21:33:38 +0000
+++ openlp/plugins/presentations/lib/presentationcontroller.py	2014-02-11 21:32:24 +0000
@@ -96,8 +96,14 @@
         """
         Constructor for the PresentationController class
         """
+        self.controller = controller
+        self._setup(name)
+
+    def _setup(self, name):
+        """
+        Run some initial setup. This method is separate from __init__ in order to mock it out in tests.
+        """
         self.slidenumber = 0
-        self.controller = controller
         self.filepath = name
         check_directory_exists(self.get_thumbnail_folder())
 

=== added file 'tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py'
--- tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py	1970-01-01 00:00:00 +0000
+++ tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py	2014-02-11 21:32:24 +0000
@@ -0,0 +1,143 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2013 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer.   #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru,          #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,             #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock,              #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann                         #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+"""
+This module contains tests for the pptviewcontroller module of the Presentations plugin.
+"""
+
+from unittest import TestCase
+
+from tests.functional import MagicMock, patch
+
+from openlp.plugins.presentations.lib.pptviewcontroller import PptviewDocument
+
+#TODO: Items left to test
+#   PptviewController
+#       __init__
+#       check_availablecheck_installed
+#       start_process(self)
+#       kill
+
+class TestPptviewDocument(TestCase):
+    """
+    Test the PptviewDocument Class
+    """
+    #TODO: Items left to test
+    #   PptviewDocument
+    #       __init__
+    #       create_thumbnails
+    #       close_presentation
+    #       is_loaded
+    #       is_active
+    #       blank_screen
+    #       unblank_screen
+    #       is_blank
+    #       stop_presentation
+    #       start_presentation
+    #       get_slide_number
+    #       get_slide_count
+    #       goto_slide
+    #       next_step
+    #       previous_step
+
+    def setUp(self):
+        """
+        Set up the patches and mocks need for all tests.
+        """
+        self.os_patcher = patch('openlp.plugins.presentations.lib.pptviewcontroller.os')
+        self.pptview_document_create_thumbnails_patcher = patch(
+            'openlp.plugins.presentations.lib.pptviewcontroller.PptviewDocument.create_thumbnails')
+        self.pptview_document_stop_presentation_patcher = patch(
+            'openlp.plugins.presentations.lib.pptviewcontroller.PptviewDocument.stop_presentation')
+        self.presentation_document_get_temp_folder_patcher = patch(
+            'openlp.plugins.presentations.lib.pptviewcontroller.PresentationDocument.get_temp_folder')
+        self.presentation_document_setup_patcher = patch(
+            'openlp.plugins.presentations.lib.pptviewcontroller.PresentationDocument._setup')
+        self.rect_patcher = patch('openlp.plugins.presentations.lib.pptviewcontroller.RECT')
+        self.screen_list_patcher = patch('openlp.plugins.presentations.lib.pptviewcontroller.ScreenList')
+
+        self.mock_os = self.os_patcher.start()
+        self.mock_pptview_document_create_thumbnails = self.pptview_document_create_thumbnails_patcher.start()
+        self.mock_pptview_document_stop_presentation = self.pptview_document_stop_presentation_patcher.start()
+        self.mock_presentation_document_get_temp_folder = self.presentation_document_get_temp_folder_patcher.start()
+        self.mock_presentation_document_setup = self.presentation_document_setup_patcher.start()
+        self.mock_rect = self.rect_patcher.start()
+        self.mock_screen_list = self.screen_list_patcher.start()
+
+        self.mock_controller = MagicMock()
+        self.mock_presentation = MagicMock()
+
+        self.mock_presentation_document_get_temp_folder.return_value = 'temp folder'
+
+    def tearDown(self):
+        """
+        Stop the patches
+        """
+        self.os_patcher.stop()
+        self.pptview_document_create_thumbnails_patcher.stop()
+        self.pptview_document_stop_presentation_patcher.stop()
+        self.presentation_document_get_temp_folder_patcher.stop()
+        self.presentation_document_setup_patcher.stop()
+        self.rect_patcher.stop()
+        self.screen_list_patcher.stop()
+
+    def load_presentation_succesfull_test(self):
+        """
+        Test the PptviewDocument.load_presentation() method when the PPT is successfully opened
+        """
+        # GIVEN: A reset mocked_os
+        self.mock_os.reset()
+
+        # WHEN: The temporary directory exists and OpenPPT returns successfully (not -1)
+        self.mock_os.path.isdir.return_value = True
+        self.mock_controller.process.OpenPPT.return_value = 0
+        instance = PptviewDocument(self.mock_controller, self.mock_presentation)
+        instance.filepath = 'test\path.ppt'
+        result = instance.load_presentation()
+
+        # THEN: PptviewDocument.load_presentation should return True
+        self.assertTrue(result)
+
+    def load_presentation_unsuccesfull_test(self):
+        """
+        Test the PptviewDocument.load_presentation() method when the temporary directory does not exist and the PPT is
+        not successfully opened
+        """
+        # GIVEN: A reset mocked_os
+        self.mock_os.reset()
+
+        # WHEN: The temporary directory does not exist and OpenPPT returns unsuccessfully (-1)
+        self.mock_os.path.isdir.return_value = False
+        self.mock_controller.process.OpenPPT.return_value = -1
+        instance = PptviewDocument(self.mock_controller, self.mock_presentation)
+        instance.filepath = 'test\path.ppt'
+        result = instance.load_presentation()
+
+        # THEN: The temporary directory should be created and PptviewDocument.load_presentation should return False
+        self.mock_os.makedirs.assert_called_once_with('temp folder')
+        self.assertFalse(result)

=== modified file 'tests/functional/openlp_plugins/presentations/test_presentationcontroller.py'
--- tests/functional/openlp_plugins/presentations/test_presentationcontroller.py	2013-12-24 08:56:50 +0000
+++ tests/functional/openlp_plugins/presentations/test_presentationcontroller.py	2014-02-11 21:32:24 +0000
@@ -1,53 +1,154 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection                                      #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2014 Raoul Snyman                                        #
-# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan      #
-# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
-# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer.   #
-# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru,          #
-# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,             #
-# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock,              #
-# Frode Woldsund, Martin Zibricky, Patrick Zimmermann                         #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it     #
-# under the terms of the GNU General Public License as published by the Free  #
-# Software Foundation; version 2 of the License.                              #
-#                                                                             #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
-# more details.                                                               #
-#                                                                             #
-# You should have received a copy of the GNU General Public License along     #
-# with this program; if not, write to the Free Software Foundation, Inc., 59  #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
-###############################################################################
-"""
-This module contains tests for the Presentation Controller.
-"""
-from unittest import TestCase
-
-from openlp.plugins.presentations.lib.presentationcontroller import PresentationController
-from tests.functional import MagicMock
-
-class TestPresentationController(TestCase):
-    """
-    Test the PresentationController.
-    """
-    def constructor_test(self):
-        """
-        Test the Constructor
-        """
-        # GIVEN: No presentation controller
-        controller = None
-
-        # WHEN: The presentation controller object is created
-        controller = PresentationController(plugin=MagicMock())
-
-        # THEN: The name of the presentation controller should be correct
-        self.assertEqual('PresentationController', controller.name,
-                         'The name of the presentation controller should be correct')
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2014 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer.   #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru,          #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,             #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock,              #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann                         #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+"""
+This module contains tests for the Presentation Controller.
+"""
+from unittest import TestCase
+
+from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
+from tests.functional import MagicMock, patch
+
+class TestPresentationController(TestCase):
+    """
+    Test the PresentationController.
+    """
+    # TODO: Items left to test
+    #   PresentationController
+    #       __init__
+    #       enabled
+    #       is_available
+    #       check_available
+    #       start_process
+    #       kill
+    #       add_document
+    #       remove_doc
+    #       close_presentation
+    #       _get_plugin_manager
+
+    def constructor_test(self):
+        """
+        Test the Constructor
+        """
+        # GIVEN: No presentation controller
+        controller = None
+
+        # WHEN: The presentation controller object is created
+        controller = PresentationController(plugin=MagicMock())
+
+        # THEN: The name of the presentation controller should be correct
+        self.assertEqual('PresentationController', controller.name,
+                         'The name of the presentation controller should be correct')
+
+class TestPresentationDocument(TestCase):
+    """
+    Test the PresentationDocument Class
+    """
+    # TODO: Items left to test
+    #   PresentationDocument
+    #       __init__
+    #       load_presentation
+    #       presentation_deleted
+    #       get_file_name
+    #       get_thumbnail_folder
+    #       get_temp_folder
+    #       check_thumbnails
+    #       close_presentation
+    #       is_active
+    #       is_loaded
+    #       blank_screen
+    #       unblank_screen
+    #       is_blank
+    #       stop_presentation
+    #       start_presentation
+    #       get_slide_number
+    #       get_slide_count
+    #       goto_slide
+    #       next_step
+    #       previous_step
+    #       convert_thumbnail
+    #       get_thumbnail_path
+    #       poll_slidenumber
+    #       get_slide_text
+    #       get_slide_notes
+
+    def setUp(self):
+        """
+        Set up the patches and mocks need for all tests.
+        """
+        self.check_directory_exists_patcher = patch(
+            'openlp.plugins.presentations.lib.presentationcontroller.check_directory_exists')
+        self.get_thumbnail_folder_patcher = patch(
+            'openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder')
+        self._setup_patcher = patch(
+            'openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument._setup')
+
+        self.mock_check_directory_exists = self.check_directory_exists_patcher.start()
+        self.mock_get_thumbnail_folder = self.get_thumbnail_folder_patcher.start()
+        self.mock_setup = self._setup_patcher.start()
+
+        self.mock_controller = MagicMock()
+
+        self.mock_get_thumbnail_folder.return_value = 'returned/path/'
+
+    def tearDown(self):
+        """
+        Stop the patches
+        """
+        self.check_directory_exists_patcher.stop()
+        self.get_thumbnail_folder_patcher.stop()
+        self._setup_patcher.stop()
+
+    def initalise_presentation_document_test(self):
+        """
+        Test the PresentationDocument __init__ method when initalising the PresentationDocument Class
+        """
+        # GIVEN: A reset mock_setup and mocked controller
+        self.mock_setup.reset()
+
+        # WHEN: Creating an instance of PresentationDocument
+        instance = PresentationDocument(self.mock_controller, 'Name')
+
+        # THEN: PresentationDocument.__init__ should have been called with the correct arguments
+        self.mock_setup.assert_called_once_with('Name')
+
+    def presentation_document_setup_test(self):
+        """
+        Test the PresentationDocument _setup method when initalising the PresentationDocument Class
+        """
+        self._setup_patcher.stop()
+
+        # GIVEN: A  mocked controller, patched check_directory_exists_patcher and patched get_thumbnail_folder method
+
+        # WHEN: Creating an instance of PresentationDocument
+        instance = PresentationDocument(self.mock_controller, 'Name')
+
+        # THEN: check_directory_exists should have been called with the correct arguments
+        self.mock_check_directory_exists.assert_called_once_with('returned/path/')
+
+        self._setup_patcher.start()

_______________________________________________
Mailing list: https://launchpad.net/~openlp-core
Post to     : openlp-core@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openlp-core
More help   : https://help.launchpad.net/ListHelp

Reply via email to