From 051fa9db8fd4a3fbb213f0b60c8c39dff946f3ad Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Sun, 20 Oct 2013 21:34:46 +0100 Subject: [PATCH 01/41] Changed logging to UTF-8 --- openlp/core/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index f86f9036f..f3edf476e 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -230,7 +230,7 @@ def set_up_logging(log_path): """ 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): From f6c3881d03c2b81ec170d1892bbe21a288ae322d Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Sun, 20 Oct 2013 21:42:40 +0100 Subject: [PATCH 02/41] Unicodified C Library --- .../lib/pptviewlib/pptviewlib.cpp | 218 +++++++++--------- .../presentations/lib/pptviewlib/pptviewlib.h | 18 +- .../lib/pptviewlib/pptviewlib.vcproj | 6 +- 3 files changed, 121 insertions(+), 121 deletions(-) diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp index b9ed433ca..a4ee5053c 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp @@ -61,18 +61,18 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReasonForCall, 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 @@ DllExport void SetDebug(BOOL onOff) { 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 @@ DllExport BOOL CheckInstalled() // ".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 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, } 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 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, 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 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, 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 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, 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,13 +210,13 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, 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) @@ -224,18 +224,18 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, if (steps <= pptView[id].steps) { Sleep(20); - DEBUG("OpenPPT: Step %d/%d\n", steps, pptView[id].steps); + 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 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, } 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 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, 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); + DEBUG(L"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)) + fgetws(buf, 100, pFile); // version == 1 + fgetws(buf, 100, pFile); + if (fileStats.st_mtime != _wtoi(buf)) { - DEBUG("GetPPTInfo: date changed\n"); + DEBUG(L"GetPPTInfo: date changed\n"); fclose (pFile); return FALSE; } - fgets(buf, 100, pFile); - if (fileStats.st_size != atoi(buf)) + fgetws(buf, 100, pFile); + if (fileStats.st_size != _wtoi(buf)) { - DEBUG("GetPPTInfo: size changed\n"); + DEBUG(L"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); + 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 @@ BOOL SavePPTInfo(int id) 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 @@ BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize) // 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 @@ BOOL GetPPTViewerPathFromReg(char *pptViewerPath, int stringSize) // 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) + if ((RegOpenKeyExW(HKEY_CLASSES_ROOT, + L"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) + && (RegOpenKeyExW(HKEY_CLASSES_ROOT, + L"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) + && (RegOpenKeyExW(HKEY_CLASSES_ROOT, + L"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) + && (RegOpenKeyExW(HKEY_CLASSES_ROOT, + L"Applications\\PPTVIEW.EXE\\shell\\Show\\command", 0, KEY_READ, &hKey) != ERROR_SUCCESS)) { return FALSE; @@ -436,14 +436,14 @@ BOOL GetPPTViewerPathFromReg(char *pptViewerPath, int stringSize) 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 @@ void Unhook(int id) } 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 @@ DllExport void ClosePPT(int id) 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 @@ DllExport void Resume(int id) // 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 @@ DllExport void Stop(int id) // 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 @@ DllExport int GetSlideCount(int id) // 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 @@ DllExport int GetCurrentSlide(int id) // 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 @@ DllExport void NextStep(int id) // 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 @@ DllExport void Blank(int id) // 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 @@ DllExport void Blank(int id) // 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 @@ DllExport void Unblank(int id) // 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 @@ DllExport void RestartShow(int id) // 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 @@ LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam) 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 @@ LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam) } if (id >= 0) { - if (strcmp(csClassName, "paneClassDC") == 0) + if (wcscmp(csClassName, L"paneClassDC") == 0) { pptView[id].hWnd2 = hCurrWnd; } @@ -737,7 +737,7 @@ LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam){ 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 @@ LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam){ { 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 @@ LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam){ 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 @@ VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename) // 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 @@ HBITMAP CaptureWindow(HWND hWnd) 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 diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h index 65f3b9b69..ce7e4e4dc 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h @@ -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 @@ DllExport void SetDebug(BOOL onOff); 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 @@ struct PPTVIEW 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; }; diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj index f20db6c8f..dd1b0b505 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj @@ -18,10 +18,10 @@ Date: Sun, 20 Oct 2013 21:49:39 +0100 Subject: [PATCH 03/41] Fixed up pptviewcontroller to work with the unicode changes to the c library --- openlp/plugins/presentations/lib/pptviewcontroller.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index 34f5129b8..9f39419e4 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -27,8 +27,8 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import os import logging +import os if os.name == 'nt': from ctypes import cdll @@ -123,10 +123,14 @@ class PptviewDocument(PresentationDocument): log.debug('LoadPresentation') size = ScreenList().current['size'] rect = RECT(size.x(), size.y(), size.right(), size.bottom()) - filepath = str(self.filepath.replace('/', '\\')) + file_path = os.path.normpath(self.filepath) + preview_path = os.path.join(self.get_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(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') + self.ppt_id = self.controller.process.OpenPPT(file_path, None, rect, preview_path) if self.ppt_id >= 0: self.create_thumbnails() self.stop_presentation() From f374c58d390c77864125bf86677a53b5d60ad493 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Mon, 28 Oct 2013 21:15:16 +0000 Subject: [PATCH 04/41] Tidying up some uneeded str() --- openlp/plugins/presentations/lib/mediaitem.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index f1d0f1110..e669e17b0 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -161,7 +161,7 @@ class PresentationMediaItem(MediaManagerItem): 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)) @@ -179,7 +179,7 @@ class PresentationMediaItem(MediaManagerItem): 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: From a69b2d86ef4de193091d1bab6bcb0eb970aa0366 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Mon, 28 Oct 2013 21:23:17 +0000 Subject: [PATCH 05/41] More uneeded str's --- openlp/core/lib/__init__.py | 4 ++-- openlp/core/lib/mediamanageritem.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index bc427830e..1bec55743 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -217,9 +217,9 @@ def create_thumb(image_path, thumb_path, return_icon=True, size=None): 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): diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 9e7eb8d73..c086c7494 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -372,7 +372,7 @@ class MediaManagerItem(QtGui.QWidget): 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: From 4345608759b628dd3d6f65dce59fbe43497c9760 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Fri, 1 Nov 2013 19:30:26 +0000 Subject: [PATCH 06/41] fixed issue with not all PPTS not loading correctly using PPTViewer --- openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp index a4ee5053c..ac51f1155 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp @@ -223,7 +223,7 @@ DllExport int OpenPPT(wchar_t *filename, HWND hParentWnd, RECT rect, { if (steps <= pptView[id].steps) { - Sleep(20); + Sleep(100); DEBUG(L"OpenPPT: Step %d/%d\n", steps, pptView[id].steps); steps++; NextStep(id); From 2535bda1bb4d44b74399d75a807a7e6cdb69db90 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Thu, 7 Nov 2013 20:33:55 +0000 Subject: [PATCH 07/41] Added tests for load presentation --- .../presentations/test_pptviewcontroller.py | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py diff --git a/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py b/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py new file mode 100644 index 000000000..2492488e5 --- /dev/null +++ b/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py @@ -0,0 +1,141 @@ +# -*- 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 mock 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 oload_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 = 'xyc' + 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) From 61da0e8ad956708c5c89b1a8fc082a7f3d7613f7 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Thu, 7 Nov 2013 20:35:02 +0000 Subject: [PATCH 08/41] Some refactoring --- .bzrignore | 1 + openlp/plugins/presentations/lib/pptviewcontroller.py | 7 ++++--- .../plugins/presentations/lib/pptviewlib/pptviewlib.cpp | 4 ++-- .../plugins/presentations/lib/presentationcontroller.py | 8 +++++++- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.bzrignore b/.bzrignore index d87c55a61..f149d97a7 100644 --- a/.bzrignore +++ b/.bzrignore @@ -28,3 +28,4 @@ tests.kdev4 *.nja *.orig __pycache__ +*.dll diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index 9f39419e4..9c9f81028 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -121,15 +121,16 @@ class PptviewDocument(PresentationDocument): 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()) file_path = os.path.normpath(self.filepath) - preview_path = os.path.join(self.get_temp_folder(), 'slide') + 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(self.get_temp_folder()): - os.makedirs(self.get_temp_folder()) + 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() diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp index ac51f1155..8b0df45ec 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp @@ -223,12 +223,12 @@ DllExport int OpenPPT(wchar_t *filename, HWND hParentWnd, RECT rect, { if (steps <= pptView[id].steps) { - Sleep(100); + Sleep(25); DEBUG(L"OpenPPT: Step %d/%d\n", steps, pptView[id].steps); steps++; NextStep(id); } - Sleep(10); + Sleep(75); } DEBUG(L"OpenPPT: Slides %d, Steps %d, first slide steps %d\n", pptView[id].slideCount, pptView[id].steps, diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index 17911606c..03efa989f 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -96,8 +96,14 @@ class PresentationDocument(object): """ Constructor for the PresentationController class """ - self.slidenumber = 0 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.filepath = name check_directory_exists(self.get_thumbnail_folder()) From 47292d3ec78839b36874b060851192dee02f03d1 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Thu, 7 Nov 2013 20:42:21 +0000 Subject: [PATCH 09/41] Changed test path --- .../openlp_plugins/presentations/test_pptviewcontroller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py b/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py index 2492488e5..338f7825c 100644 --- a/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py @@ -133,7 +133,7 @@ class TestPptviewDocument(TestCase): 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 = 'xyc' + instance.filepath = 'test\path.ppt' result = instance.load_presentation() # THEN: The temporary directory should be created and PptviewDocument.load_presentation should return False From cc3cdf71269a20ed1e2418af1829002d76a31d30 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Sat, 16 Nov 2013 10:05:41 +0000 Subject: [PATCH 10/41] added some tests for PresentationController --- .../lib/pptviewlib/pptviewlib.cpp | 4 +- .../presentations/test_pptviewcontroller.py | 4 +- .../test_presentationcontroller.py | 138 ++++++++++++++++++ 3 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 tests/functional/openlp_plugins/presentations/test_presentationcontroller.py diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp index 8b0df45ec..ac51f1155 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp @@ -223,12 +223,12 @@ DllExport int OpenPPT(wchar_t *filename, HWND hParentWnd, RECT rect, { if (steps <= pptView[id].steps) { - Sleep(25); + Sleep(100); DEBUG(L"OpenPPT: Step %d/%d\n", steps, pptView[id].steps); steps++; NextStep(id); } - Sleep(75); + Sleep(10); } DEBUG(L"OpenPPT: Slides %d, Steps %d, first slide steps %d\n", pptView[id].slideCount, pptView[id].steps, diff --git a/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py b/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py index 338f7825c..d2d8bb5bd 100644 --- a/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py @@ -29,8 +29,8 @@ """ This module contains tests for the pptviewcontroller module of the Presentations plugin. """ -from unittest import TestCase from mock import MagicMock, patch +from unittest import TestCase from openlp.plugins.presentations.lib.pptviewcontroller import PptviewDocument @@ -104,7 +104,7 @@ class TestPptviewDocument(TestCase): self.rect_patcher.stop() self.screen_list_patcher.stop() - def oload_presentation_succesfull_test(self): + def load_presentation_succesfull_test(self): """ Test the PptviewDocument.load_presentation() method when the PPT is successfully opened """ diff --git a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py new file mode 100644 index 000000000..8ebf52c09 --- /dev/null +++ b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py @@ -0,0 +1,138 @@ +# -*- 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 mock import MagicMock, patch +from unittest import TestCase + +from openlp.plugins.presentations.lib.presentationcontroller import PresentationDocument + +# TODO: Items left to test +# PresentationController +# __init__ +# enabled +# is_available +# check_available +# start_process +# kill +# add_document +# remove_doc +# close_presentation +# _get_plugin_manager + + +class TestPptviewDocument(TestCase): + """ + Test the PptviewDocument 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() From 20ae5d13b008c004e550a8aefd26ae0b54fad8f0 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Sat, 16 Nov 2013 10:16:06 +0000 Subject: [PATCH 11/41] some final cleanups --- .../plugins/presentations/lib/pptviewlib/pptviewlib.vcproj | 2 +- .../openlp_plugins/presentations/test_pptviewcontroller.py | 4 +++- .../presentations/test_presentationcontroller.py | 7 ++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj index dd1b0b505..d2843e510 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.vcproj @@ -18,7 +18,7 @@ Date: Sat, 16 Nov 2013 10:54:24 +0000 Subject: [PATCH 12/41] Fix doc strings --- .../presentations/test_presentationcontroller.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py index 3ea949b80..e836bd756 100644 --- a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py @@ -50,9 +50,9 @@ from openlp.plugins.presentations.lib.presentationcontroller import Presentation # _get_plugin_manager -class TestPptviewDocument(TestCase): +class TestPresentationDocument(TestCase): """ - Test the PptviewDocument Class + Test the PresentationDocument Class """ # TODO: Items left to test # PresentationDocument From c8a3b330442d6596788b057d6308a9014834b1c3 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Mon, 30 Dec 2013 19:50:34 +0000 Subject: [PATCH 13/41] Start to fix ServiceManager and extent tests --- openlp/core/__init__.py | 1 + openlp/core/common/openlpmixin.py | 10 +- openlp/core/common/registry.py | 8 +- openlp/core/common/registrymixin.py | 4 +- openlp/core/ui/servicemanager.py | 116 +++++---- openlp/core/ui/thememanager.py | 18 +- .../openlp_core_common/test_init.py | 4 +- .../openlp_core_ui/test_servicemanager.py | 230 +++++++++++++++++- 8 files changed, 317 insertions(+), 74 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index e9e899b26..b5a922617 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -137,6 +137,7 @@ class OpenLP(QtGui.QApplication): self.main_window = MainWindow() Registry().execute('bootstrap_initialise') Registry().execute('bootstrap_post_set_up') + Registry().initialise = False self.main_window.show() if show_splash: # now kill the splashscreen diff --git a/openlp/core/common/openlpmixin.py b/openlp/core/common/openlpmixin.py index 400f7e4a8..dda448cc2 100644 --- a/openlp/core/common/openlpmixin.py +++ b/openlp/core/common/openlpmixin.py @@ -4,8 +4,8 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2013 Raoul Snyman # -# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan # +# 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, # @@ -33,7 +33,7 @@ import logging import inspect from openlp.core.common import trace_error_handler -DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent'] +DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent', 'drag_enter_event', 'drop_event'] class OpenLPMixin(object): @@ -68,13 +68,13 @@ class OpenLPMixin(object): def log_debug(self, message): """ - Common log debug handler which prints the calling path + Common log debug handler """ self.logger.debug(message) def log_info(self, message): """ - Common log info handler which prints the calling path + Common log info handler """ self.logger.info(message) diff --git a/openlp/core/common/registry.py b/openlp/core/common/registry.py index f0c508da4..5bbb698d5 100644 --- a/openlp/core/common/registry.py +++ b/openlp/core/common/registry.py @@ -63,6 +63,7 @@ class Registry(object): registry.service_list = {} registry.functions_list = {} registry.running_under_test = False + registry.initialising = True # Allow the tests to remove Registry entries but not the live system if 'nose' in sys.argv[0]: registry.running_under_test = True @@ -78,9 +79,10 @@ class Registry(object): if key in self.service_list: return self.service_list[key] else: - trace_error_handler(log) - log.error('Service %s not found in list' % key) - #raise KeyError('Service %s not found in list' % key) + if not self.initialising: + trace_error_handler(log) + log.error('Service %s not found in list' % key) + raise KeyError('Service %s not found in list' % key) def register(self, key, reference): """ diff --git a/openlp/core/common/registrymixin.py b/openlp/core/common/registrymixin.py index a474084b0..e7bcc24d7 100644 --- a/openlp/core/common/registrymixin.py +++ b/openlp/core/common/registrymixin.py @@ -4,8 +4,8 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2013 Raoul Snyman # -# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan # +# 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, # diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 431fb010b..7324d0fbe 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -4,8 +4,8 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2013 Raoul Snyman # -# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan # +# 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, # @@ -42,7 +42,8 @@ log = logging.getLogger(__name__) from PyQt4 import QtCore, QtGui -from openlp.core.common import Registry, AppLocation, Settings, ThemeLevel, check_directory_exists, UiStrings, translate +from openlp.core.common import Registry, AppLocation, Settings, ThemeLevel, OpenLPMixin, RegistryMixin, \ + check_directory_exists, UiStrings, translate from openlp.core.lib import OpenLPToolbar, ServiceItem, ItemCapabilities, PluginStatus, build_icon from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm @@ -75,7 +76,7 @@ class ServiceManagerList(QtGui.QTreeWidget): self.service_manager.on_move_selection_down() event.accept() elif event.key() == QtCore.Qt.Key_Delete: - self.service_manager.onDeleteFromService() + self.service_manager.on_delete_from_service() event.accept() event.ignore() else: @@ -99,7 +100,7 @@ class ServiceManagerList(QtGui.QTreeWidget): drag.start(QtCore.Qt.CopyAction) -class ServiceManagerDialog(object): +class Ui_ServiceManager(object): """ UI part of the Service Manager """ @@ -107,6 +108,10 @@ class ServiceManagerDialog(object): """ Define the UI """ + # start with the layout + self.layout = QtGui.QVBoxLayout(self) + self.layout.setSpacing(0) + self.layout.setMargin(0) # Create the top toolbar self.toolbar = OpenLPToolbar(self) self.toolbar.add_toolbar_action('newService', text=UiStrings().NewService, icon=':/general/general_new.png', @@ -154,48 +159,58 @@ class ServiceManagerDialog(object): self.order_toolbar = OpenLPToolbar(self) action_list = ActionList.get_instance() action_list.add_category(UiStrings().Service, CategoryOrder.standard_toolbar) - self.service_manager_list.move_top = self.order_toolbar.add_toolbar_action('moveTop', + self.service_manager_list.move_top = self.order_toolbar.add_toolbar_action( + 'moveTop', text=translate('OpenLP.ServiceManager', 'Move to &top'), icon=':/services/service_top.png', tooltip=translate('OpenLP.ServiceManager', 'Move item to the top of the service.'), - can_shortcuts=True, category=UiStrings().Service, triggers=self.onServiceTop) - self.service_manager_list.move_up = self.order_toolbar.add_toolbar_action('moveUp', + can_shortcuts=True, category=UiStrings().Service, triggers=self.on_service_top) + self.service_manager_list.move_up = self.order_toolbar.add_toolbar_action( + 'moveUp', text=translate('OpenLP.ServiceManager', 'Move &up'), icon=':/services/service_up.png', tooltip=translate('OpenLP.ServiceManager', 'Move item up one position in the service.'), - can_shortcuts=True, category=UiStrings().Service, triggers=self.onServiceUp) - self.service_manager_list.move_down = self.order_toolbar.add_toolbar_action('moveDown', + can_shortcuts=True, category=UiStrings().Service, triggers=self.on_service_up) + self.service_manager_list.move_down = self.order_toolbar.add_toolbar_action( + 'moveDown', text=translate('OpenLP.ServiceManager', 'Move &down'), icon=':/services/service_down.png', tooltip=translate('OpenLP.ServiceManager', 'Move item down one position in the service.'), - can_shortcuts=True, category=UiStrings().Service, triggers=self.onServiceDown) - self.service_manager_list.move_bottom = self.order_toolbar.add_toolbar_action('moveBottom', + can_shortcuts=True, category=UiStrings().Service, triggers=self.on_service_down) + self.service_manager_list.move_bottom = self.order_toolbar.add_toolbar_action( + 'moveBottom', text=translate('OpenLP.ServiceManager', 'Move to &bottom'), icon=':/services/service_bottom.png', tooltip=translate('OpenLP.ServiceManager', 'Move item to the end of the service.'), - can_shortcuts=True, category=UiStrings().Service, triggers=self.onServiceEnd) - self.service_manager_list.down = self.order_toolbar.add_toolbar_action('down', + can_shortcuts=True, category=UiStrings().Service, triggers=self.on_service_end) + self.service_manager_list.down = self.order_toolbar.add_toolbar_action( + 'down', text=translate('OpenLP.ServiceManager', 'Move &down'), can_shortcuts=True, tooltip=translate('OpenLP.ServiceManager', 'Moves the selection down the window.'), visible=False, triggers=self.on_move_selection_down) action_list.add_action(self.service_manager_list.down) - self.service_manager_list.up = self.order_toolbar.add_toolbar_action('up', + self.service_manager_list.up = self.order_toolbar.add_toolbar_action( + 'up', text=translate('OpenLP.ServiceManager', 'Move up'), can_shortcuts=True, tooltip=translate('OpenLP.ServiceManager', 'Moves the selection up the window.'), visible=False, triggers=self.on_move_selection_up) action_list.add_action(self.service_manager_list.up) self.order_toolbar.addSeparator() - self.service_manager_list.delete = self.order_toolbar.add_toolbar_action('delete', can_shortcuts=True, + self.service_manager_list.delete = self.order_toolbar.add_toolbar_action( + 'delete', can_shortcuts=True, text=translate('OpenLP.ServiceManager', '&Delete From Service'), icon=':/general/general_delete.png', tooltip=translate('OpenLP.ServiceManager', 'Delete the selected item from the service.'), - triggers=self.onDeleteFromService) + triggers=self.on_delete_from_service) self.order_toolbar.addSeparator() - self.service_manager_list.expand = self.order_toolbar.add_toolbar_action('expand', can_shortcuts=True, + self.service_manager_list.expand = self.order_toolbar.add_toolbar_action( + 'expand', can_shortcuts=True, text=translate('OpenLP.ServiceManager', '&Expand all'), icon=':/services/service_expand_all.png', tooltip=translate('OpenLP.ServiceManager', 'Expand all the service items.'), category=UiStrings().Service, triggers=self.on_expand_all) - self.service_manager_list.collapse = self.order_toolbar.add_toolbar_action('collapse', can_shortcuts=True, + self.service_manager_list.collapse = self.order_toolbar.add_toolbar_action( + 'collapse', can_shortcuts=True, text=translate('OpenLP.ServiceManager', '&Collapse all'), icon=':/services/service_collapse_all.png', tooltip=translate('OpenLP.ServiceManager', 'Collapse all the service items.'), category=UiStrings().Service, triggers=self.on_collapse_all) self.order_toolbar.addSeparator() - self.service_manager_list.make_live = self.order_toolbar.add_toolbar_action('make_live', can_shortcuts=True, + self.service_manager_list.make_live = self.order_toolbar.add_toolbar_action( + 'make_live', can_shortcuts=True, text=translate('OpenLP.ServiceManager', 'Go Live'), icon=':/general/general_live.png', tooltip=translate('OpenLP.ServiceManager', 'Send the selected item to Live.'), category=UiStrings().Service, @@ -287,12 +302,12 @@ class ServiceManagerDialog(object): Accept Drag events ``event`` - Handle of the event pint passed + Handle of the event passed """ event.accept() -class ServiceManager(QtGui.QWidget, ServiceManagerDialog): +class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManager): """ Manages the services. This involves taking text strings from plugins and adding them to the service. This service can then be zipped up with all the resources used into one OSZ or oszl file for use on any OpenLP v2 installation. @@ -305,7 +320,6 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): super(ServiceManager, self).__init__(parent) self.active = build_icon(':/media/auto-start_active.png') self.inactive = build_icon(':/media/auto-start_inactive.png') - Registry().register('service_manager', self) self.service_items = [] self.suffixes = [] self.drop_position = 0 @@ -314,17 +328,21 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): self._modified = False self._file_name = '' self.service_has_all_original_files = True - self.service_note_form = ServiceNoteForm() - self.service_item_edit_form = ServiceItemEditForm() - self.start_time_form = StartTimeForm() - # start with the layout - self.layout = QtGui.QVBoxLayout(self) - self.layout.setSpacing(0) - self.layout.setMargin(0) + + def bootstrap_initialise(self): + print(self) self.setup_ui(self) # Need to use event as called across threads and UI is updated QtCore.QObject.connect(self, QtCore.SIGNAL('servicemanager_set_item'), self.on_set_item) + def bootstrap_post_set_up(self): + """ + Can be set up as a late setup + """ + self.service_note_form = ServiceNoteForm() + self.service_item_edit_form = ServiceItemEditForm() + self.start_time_form = StartTimeForm() + def set_modified(self, modified=True): """ Setter for property "modified". Sets whether or not the current service has been modified. @@ -432,7 +450,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save) - def on_recent_service_clicked(self): + def on_recent_service_clicked(self, field=None): """ Load a recent file as the service triggered by mainwindow recent service list. """ @@ -656,8 +674,8 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): '(*.oszl)')) else: file_name = QtGui.QFileDialog.getSaveFileName(self.main_window, UiStrings().SaveService, path, - translate('OpenLP.ServiceManager', 'OpenLP Service Files (*' - '.osz);;')) + translate('OpenLP.ServiceManager', + 'OpenLP Service Files (*.osz);;')) if not file_name: return False if os.path.splitext(file_name)[1] == '': @@ -1016,7 +1034,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): """ Makes a specific item in the service live. """ - if index >= 0 and index < self.service_manager_list.topLevelItemCount(): + if 0 >= index < self.service_manager_list.topLevelItemCount(): item = self.service_manager_list.topLevelItem(index) self.service_manager_list.setCurrentItem(item) self.make_live() @@ -1071,7 +1089,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): pos = item.data(0, QtCore.Qt.UserRole) self.service_items[pos - 1]['expanded'] = True - def onServiceTop(self): + def on_service_top(self): """ Move the current ServiceItem to the top of the list. """ @@ -1083,7 +1101,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): self.repaint_service_list(0, child) self.set_modified() - def onServiceUp(self): + def on_service_up(self): """ Move the current ServiceItem one position up in the list. """ @@ -1095,7 +1113,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): self.repaint_service_list(item - 1, child) self.set_modified() - def onServiceDown(self): + def on_service_down(self): """ Move the current ServiceItem one position down in the list. """ @@ -1107,7 +1125,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): self.repaint_service_list(item + 1, child) self.set_modified() - def onServiceEnd(self): + def on_service_end(self): """ Move the current ServiceItem to the bottom of the list. """ @@ -1119,7 +1137,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): self.repaint_service_list(len(self.service_items) - 1, child) self.set_modified() - def onDeleteFromService(self): + def on_delete_from_service(self): """ Remove the current ServiceItem from the list. """ @@ -1218,7 +1236,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): if os.path.exists(os.path.join(self.service_path, 'audio')): shutil.rmtree(os.path.join(self.service_path, 'audio'), True) - def on_theme_combo_box_selected(self, currentIndex): + def on_theme_combo_box_selected(self, current_index): """ Set the theme for the current service. """ @@ -1274,17 +1292,17 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): self.repaint_service_list(-1, -1) self.application.set_normal_cursor() - def replace_service_item(self, newItem): + def replace_service_item(self, new_item): """ Using the service item passed replace the one with the same edit id if found. """ for item_count, item in enumerate(self.service_items): - if item['service_item'].edit_id == newItem.edit_id and item['service_item'].name == newItem.name: - newItem.render() - newItem.merge(item['service_item']) - item['service_item'] = newItem + if item['service_item'].edit_id == new_item.edit_id and item['service_item'].name == new_item.name: + new_item.render() + new_item.merge(item['service_item']) + item['service_item'] = new_item self.repaint_service_list(item_count + 1, 0) - self.live_controller.replace_service_manager_item(newItem) + self.live_controller.replace_service_manager_item(new_item) self.set_modified() def add_service_item(self, item, rebuild=False, expand=None, replace=False, repaint=True, selected=False): @@ -1324,8 +1342,8 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): self.repaint_service_list(len(self.service_items) - 1, -1) else: self.service_items.insert(self.drop_position, - {'service_item': item, 'order': self.drop_position, - 'expanded': expand, 'selected': selected}) + {'service_item': item, 'order': self.drop_position, + 'expanded': expand, 'selected': selected}) self.repaint_service_list(self.drop_position, -1) # if rebuilding list make sure live is fixed. if rebuild: @@ -1357,7 +1375,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): else: return self.service_items[item]['service_item'] - def on_make_live(self): + def on_make_live(self, field=None): """ Send the current item to the Live slide controller but triggered by a tablewidget click event. """ diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 82473ec86..9eb24d564 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -304,8 +304,8 @@ class ThemeManager(RegistryMixin, OpenLPMixin, QtGui.QWidget, ThemeManagerHelper Delete a theme """ if self._validate_theme_action(translate('OpenLP.ThemeManager', 'You must select a theme to delete.'), - translate('OpenLP.ThemeManager', 'Delete Confirmation'), - translate('OpenLP.ThemeManager', 'Delete %s theme?')): + translate('OpenLP.ThemeManager', 'Delete Confirmation'), + translate('OpenLP.ThemeManager', 'Delete %s theme?')): item = self.theme_list_widget.currentItem() theme = item.text() row = self.theme_list_widget.row(item) @@ -472,7 +472,7 @@ class ThemeManager(RegistryMixin, OpenLPMixin, QtGui.QWidget, ThemeManagerHelper self.log_debug('No theme data - using default theme') return ThemeXML() else: - return self._create_theme_from_Xml(xml, self.path) + return self._create_theme_from_xml(xml, self.path) def over_write_message_box(self, theme_name): """ @@ -548,8 +548,8 @@ class ThemeManager(RegistryMixin, OpenLPMixin, QtGui.QWidget, ThemeManagerHelper if not abort_import: # As all files are closed, we can create the Theme. if file_xml: - theme = self._create_theme_from_Xml(file_xml, self.path) - self.generate_and_save_image(directory, theme_name, theme) + theme = self._create_theme_from_xml(file_xml, self.path) + self.generate_and_save_image(theme_name, theme) # Only show the error message, when IOError was not raised (in # this case the error message has already been shown). elif theme_zip is not None: @@ -611,9 +611,9 @@ class ThemeManager(RegistryMixin, OpenLPMixin, QtGui.QWidget, ThemeManagerHelper except IOError as xxx_todo_changeme: shutil.Error = xxx_todo_changeme self.log_exception('Failed to save theme image') - self.generate_and_save_image(self.path, name, theme) + self.generate_and_save_image(name, theme) - def generate_and_save_image(self, directory, name, theme): + def generate_and_save_image(self, name, theme): """ Generate and save a preview image """ @@ -632,7 +632,7 @@ class ThemeManager(RegistryMixin, OpenLPMixin, QtGui.QWidget, ThemeManagerHelper self.main_window.display_progress_bar(len(self.theme_list)) for theme in self.theme_list: self.main_window.increment_progress_bar() - self.generate_and_save_image(self.path, theme, self.get_theme_data(theme)) + self.generate_and_save_image(theme, self.get_theme_data(theme)) self.main_window.finished_progress_bar() self.load_themes() @@ -657,7 +657,7 @@ class ThemeManager(RegistryMixin, OpenLPMixin, QtGui.QWidget, ThemeManagerHelper """ return os.path.join(self.path, theme + '.png') - def _create_theme_from_Xml(self, theme_xml, path): + def _create_theme_from_xml(self, theme_xml, path): """ Return a theme object using information parsed from XML diff --git a/tests/functional/openlp_core_common/test_init.py b/tests/functional/openlp_core_common/test_init.py index 50a2578ae..dcc4fe32a 100644 --- a/tests/functional/openlp_core_common/test_init.py +++ b/tests/functional/openlp_core_common/test_init.py @@ -4,8 +4,8 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2013 Raoul Snyman # -# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan # +# 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, # diff --git a/tests/interfaces/openlp_core_ui/test_servicemanager.py b/tests/interfaces/openlp_core_ui/test_servicemanager.py index 391c90b3e..8cde77dcd 100644 --- a/tests/interfaces/openlp_core_ui/test_servicemanager.py +++ b/tests/interfaces/openlp_core_ui/test_servicemanager.py @@ -7,7 +7,7 @@ from unittest import TestCase from PyQt4 import QtGui from openlp.core.common import Registry -from openlp.core.lib import ScreenList, ServiceItem +from openlp.core.lib import ScreenList, ServiceItem, ItemCapabilities from openlp.core.ui.mainwindow import MainWindow from tests.interfaces import MagicMock, patch @@ -39,16 +39,18 @@ class TestServiceManager(TestCase): """ # GIVEN: A New Service Manager instance - # WHEN I have an empty display + # WHEN I have set up the display + self.service_manager.setup_ui(self.service_manager) # THEN the count of items should be zero self.assertEqual(self.service_manager.service_manager_list.topLevelItemCount(), 0, 'The service manager list should be empty ') - def context_menu_test(self): + def default_context_menu_test(self): """ - Test the context_menu() method. + Test the context_menu() method with a default service item """ # GIVEN: A service item added + self.service_manager.setup_ui(self.service_manager) with patch('PyQt4.QtGui.QTreeWidget.itemAt') as mocked_item_at_method, \ patch('PyQt4.QtGui.QWidget.mapToGlobal'), \ patch('PyQt4.QtGui.QMenu.exec_'): @@ -84,3 +86,223 @@ class TestServiceManager(TestCase): 'The action should be set invisible.' self.service_manager.auto_start_action.setVisible.assert_called_once_with(False), \ 'The action should be set invisible.' + + + def edit_context_menu_test(self): + """ + Test the context_menu() method with a edit service item + """ + # GIVEN: A service item added + self.service_manager.setup_ui(self.service_manager) + with patch('PyQt4.QtGui.QTreeWidget.itemAt') as mocked_item_at_method, \ + patch('PyQt4.QtGui.QWidget.mapToGlobal'), \ + patch('PyQt4.QtGui.QMenu.exec_'): + mocked_item = MagicMock() + mocked_item.parent.return_value = None + mocked_item_at_method.return_value = mocked_item + # We want 1 to be returned for the position + mocked_item.data.return_value = 1 + # A service item without capabilities. + service_item = ServiceItem() + service_item.add_capability(ItemCapabilities.CanEdit) + service_item.edit_id = 1 + self.service_manager.service_items = [{'service_item': service_item}] + q_point = None + # Mocked actions. + self.service_manager.edit_action.setVisible = MagicMock() + self.service_manager.create_custom_action.setVisible = MagicMock() + self.service_manager.maintain_action.setVisible = MagicMock() + self.service_manager.notes_action.setVisible = MagicMock() + self.service_manager.time_action.setVisible = MagicMock() + self.service_manager.auto_start_action.setVisible = MagicMock() + + # WHEN: Show the context menu. + self.service_manager.context_menu(q_point) + + # THEN: The following actions should be not visible. + self.service_manager.edit_action.setVisible.assert_called_with(True), \ + 'The action should be set visible.' + self.service_manager.create_custom_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.maintain_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.notes_action.setVisible.assert_called_with(True), 'The action should be set visible.' + self.service_manager.time_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.auto_start_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + + def maintain_context_menu_test(self): + """ + Test the context_menu() method with a maintain + """ + # GIVEN: A service item added + self.service_manager.setup_ui(self.service_manager) + with patch('PyQt4.QtGui.QTreeWidget.itemAt') as mocked_item_at_method, \ + patch('PyQt4.QtGui.QWidget.mapToGlobal'), \ + patch('PyQt4.QtGui.QMenu.exec_'): + mocked_item = MagicMock() + mocked_item.parent.return_value = None + mocked_item_at_method.return_value = mocked_item + # We want 1 to be returned for the position + mocked_item.data.return_value = 1 + # A service item without capabilities. + service_item = ServiceItem() + service_item.add_capability(ItemCapabilities.CanMaintain) + self.service_manager.service_items = [{'service_item': service_item}] + q_point = None + # Mocked actions. + self.service_manager.edit_action.setVisible = MagicMock() + self.service_manager.create_custom_action.setVisible = MagicMock() + self.service_manager.maintain_action.setVisible = MagicMock() + self.service_manager.notes_action.setVisible = MagicMock() + self.service_manager.time_action.setVisible = MagicMock() + self.service_manager.auto_start_action.setVisible = MagicMock() + + # WHEN: Show the context menu. + self.service_manager.context_menu(q_point) + + # THEN: The following actions should be not visible. + self.service_manager.edit_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.create_custom_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.maintain_action.setVisible.assert_called_with(True), \ + 'The action should be set visible.' + self.service_manager.notes_action.setVisible.assert_called_with(True), 'The action should be set visible.' + self.service_manager.time_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.auto_start_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + + def loopy_context_menu_test(self): + """ + Test the context_menu() method with a loop + """ + # GIVEN: A service item added + self.service_manager.setup_ui(self.service_manager) + with patch('PyQt4.QtGui.QTreeWidget.itemAt') as mocked_item_at_method, \ + patch('PyQt4.QtGui.QWidget.mapToGlobal'), \ + patch('PyQt4.QtGui.QMenu.exec_'): + mocked_item = MagicMock() + mocked_item.parent.return_value = None + mocked_item_at_method.return_value = mocked_item + # We want 1 to be returned for the position + mocked_item.data.return_value = 1 + # A service item without capabilities. + service_item = ServiceItem() + service_item.add_capability(ItemCapabilities.CanLoop) + service_item._raw_frames.append("One") + service_item._raw_frames.append("Two") + self.service_manager.service_items = [{'service_item': service_item}] + q_point = None + # Mocked actions. + self.service_manager.edit_action.setVisible = MagicMock() + self.service_manager.create_custom_action.setVisible = MagicMock() + self.service_manager.maintain_action.setVisible = MagicMock() + self.service_manager.notes_action.setVisible = MagicMock() + self.service_manager.time_action.setVisible = MagicMock() + self.service_manager.auto_start_action.setVisible = MagicMock() + + # WHEN: Show the context menu. + self.service_manager.context_menu(q_point) + + # THEN: The following actions should be not visible. + self.service_manager.edit_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.create_custom_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.maintain_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.notes_action.setVisible.assert_called_with(True), 'The action should be set visible.' + self.service_manager.time_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.auto_start_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + + def start_time_context_menu_test(self): + """ + Test the context_menu() method with a start time + """ + # GIVEN: A service item added + self.service_manager.setup_ui(self.service_manager) + with patch('PyQt4.QtGui.QTreeWidget.itemAt') as mocked_item_at_method, \ + patch('PyQt4.QtGui.QWidget.mapToGlobal'), \ + patch('PyQt4.QtGui.QMenu.exec_'): + mocked_item = MagicMock() + mocked_item.parent.return_value = None + mocked_item_at_method.return_value = mocked_item + # We want 1 to be returned for the position + mocked_item.data.return_value = 1 + # A service item without capabilities. + service_item = ServiceItem() + service_item.add_capability(ItemCapabilities.HasVariableStartTime) + self.service_manager.service_items = [{'service_item': service_item}] + q_point = None + # Mocked actions. + self.service_manager.edit_action.setVisible = MagicMock() + self.service_manager.create_custom_action.setVisible = MagicMock() + self.service_manager.maintain_action.setVisible = MagicMock() + self.service_manager.notes_action.setVisible = MagicMock() + self.service_manager.time_action.setVisible = MagicMock() + self.service_manager.auto_start_action.setVisible = MagicMock() + + # WHEN: Show the context menu. + self.service_manager.context_menu(q_point) + + # THEN: The following actions should be not visible. + self.service_manager.edit_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.create_custom_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.maintain_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.notes_action.setVisible.assert_called_with(True), 'The action should be set visible.' + self.service_manager.time_action.setVisible.assert_called_with(True), \ + 'The action should be set visible.' + self.service_manager.auto_start_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + + def auto_start_context_menu_test(self): + """ + Test the context_menu() method with can auto start + """ + # GIVEN: A service item added + self.service_manager.setup_ui(self.service_manager) + with patch('PyQt4.QtGui.QTreeWidget.itemAt') as mocked_item_at_method, \ + patch('PyQt4.QtGui.QWidget.mapToGlobal'), \ + patch('PyQt4.QtGui.QMenu.exec_'): + mocked_item = MagicMock() + mocked_item.parent.return_value = None + mocked_item_at_method.return_value = mocked_item + # We want 1 to be returned for the position + mocked_item.data.return_value = 1 + # A service item without capabilities. + service_item = ServiceItem() + service_item.add_capability(ItemCapabilities.CanAutoStartForLive) + self.service_manager.service_items = [{'service_item': service_item}] + q_point = None + # Mocked actions. + self.service_manager.edit_action.setVisible = MagicMock() + self.service_manager.create_custom_action.setVisible = MagicMock() + self.service_manager.maintain_action.setVisible = MagicMock() + self.service_manager.notes_action.setVisible = MagicMock() + self.service_manager.time_action.setVisible = MagicMock() + self.service_manager.auto_start_action.setVisible = MagicMock() + + # WHEN: Show the context menu. + self.service_manager.context_menu(q_point) + + # THEN: The following actions should be not visible. + self.service_manager.edit_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.create_custom_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.maintain_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.notes_action.setVisible.assert_called_with(True), 'The action should be set visible.' + self.service_manager.time_action.setVisible.assert_called_once_with(False), \ + 'The action should be set invisible.' + self.service_manager.auto_start_action.setVisible.assert_called_with(True), \ + 'The action should be set visible.' + From e49beeb2c47e7cd19da985b3cc132c2c03789f30 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 31 Dec 2013 07:27:07 +0000 Subject: [PATCH 14/41] More tests --- openlp/core/ui/servicemanager.py | 14 +++--- .../openlp_core_lib/test_pluginmanager.py | 20 ++++----- .../functional/openlp_core_lib/test_screen.py | 2 +- .../openlp_core_lib/test_serviceitem.py | 44 +++++++++---------- .../openlp_core_ui/test_servicemanager.py | 36 +++++++++++++-- 5 files changed, 73 insertions(+), 43 deletions(-) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 7324d0fbe..0f66e1533 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -397,7 +397,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage if not suffix in self.suffixes: self.suffixes.append(suffix) - def on_new_service_clicked(self): + def on_new_service_clicked(self, field=None): """ Create a new service. """ @@ -861,7 +861,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage theme_action.setChecked(True) self.menu.exec_(self.service_manager_list.mapToGlobal(point)) - def on_service_item_note_form(self): + def on_service_item_note_form(self, field=None): """ Allow the service note to be edited """ @@ -872,7 +872,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.repaint_service_list(item, -1) self.set_modified() - def on_start_time_form(self): + def on_start_time_form(self, field=None): """ Opens a dialog to type in service item notes. """ @@ -911,7 +911,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.main_window.general_settings_section + '/loop delay') self.set_modified() - def on_timed_slide_interval(self): + def on_timed_slide_interval(self, field=None): """ Shows input dialog for enter interval in seconds for delay """ @@ -944,7 +944,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.service_items[item]['service_item'].will_auto_start = \ not self.service_items[item]['service_item'].will_auto_start - def on_service_item_edit_form(self): + def on_service_item_edit_form(self, field=None): """ Opens a dialog to edit the service item and update the service display if changes are saved. """ @@ -1024,7 +1024,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage prev_item_last_slide = service_iterator.value() service_iterator += 1 - def on_set_item(self, message): + def on_set_item(self, message, field=None): """ Called by a signal to select a specific item and make it live usually from remote. """ @@ -1137,7 +1137,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.repaint_service_list(len(self.service_items) - 1, child) self.set_modified() - def on_delete_from_service(self): + def on_delete_from_service(self, field=None): """ Remove the current ServiceItem from the list. """ diff --git a/tests/functional/openlp_core_lib/test_pluginmanager.py b/tests/functional/openlp_core_lib/test_pluginmanager.py index 66383548a..ce5c240b2 100644 --- a/tests/functional/openlp_core_lib/test_pluginmanager.py +++ b/tests/functional/openlp_core_lib/test_pluginmanager.py @@ -71,7 +71,7 @@ class TestPluginManager(TestCase): # THEN: The create_media_manager_item() method should have been called self.assertEqual(0, mocked_plugin.create_media_manager_item.call_count, - 'The create_media_manager_item() method should not have been called.') + 'The create_media_manager_item() method should not have been called.') def hook_media_manager_with_active_plugin_test(self): """ @@ -104,7 +104,7 @@ class TestPluginManager(TestCase): # THEN: The hook_settings_tabs() method should have been called self.assertEqual(0, mocked_plugin.create_media_manager_item.call_count, - 'The create_media_manager_item() method should not have been called.') + 'The create_media_manager_item() method should not have been called.') def hook_settings_tabs_with_disabled_plugin_and_mocked_form_test(self): """ @@ -124,9 +124,9 @@ class TestPluginManager(TestCase): # THEN: The create_settings_tab() method should not have been called, but the plugins lists should be the same self.assertEqual(0, mocked_plugin.create_settings_tab.call_count, - 'The create_media_manager_item() method should not have been called.') + 'The create_media_manager_item() method should not have been called.') self.assertEqual(mocked_settings_form.plugin_manager.plugins, plugin_manager.plugins, - 'The plugins on the settings form should be the same as the plugins in the plugin manager') + 'The plugins on the settings form should be the same as the plugins in the plugin manager') def hook_settings_tabs_with_active_plugin_and_mocked_form_test(self): """ @@ -146,9 +146,9 @@ class TestPluginManager(TestCase): # THEN: The create_media_manager_item() method should have been called with the mocked settings form self.assertEqual(1, mocked_plugin.create_settings_tab.call_count, - 'The create_media_manager_item() method should have been called once.') + 'The create_media_manager_item() method should have been called once.') self.assertEqual(plugin_manager.plugins, mocked_settings_form.plugin_manager.plugins, - 'The plugins on the settings form should be the same as the plugins in the plugin manager') + 'The plugins on the settings form should be the same as the plugins in the plugin manager') def hook_settings_tabs_with_active_plugin_and_no_form_test(self): """ @@ -181,7 +181,7 @@ class TestPluginManager(TestCase): # THEN: The create_media_manager_item() method should have been called self.assertEqual(0, mocked_plugin.add_import_menu_item.call_count, - 'The add_import_menu_item() method should not have been called.') + 'The add_import_menu_item() method should not have been called.') def hook_import_menu_with_active_plugin_test(self): """ @@ -214,7 +214,7 @@ class TestPluginManager(TestCase): # THEN: The add_export_menu_Item() method should not have been called self.assertEqual(0, mocked_plugin.add_export_menu_Item.call_count, - 'The add_export_menu_Item() method should not have been called.') + 'The add_export_menu_Item() method should not have been called.') def hook_export_menu_with_active_plugin_test(self): """ @@ -248,7 +248,7 @@ class TestPluginManager(TestCase): # THEN: The upgrade_settings() method should not have been called self.assertEqual(0, mocked_plugin.upgrade_settings.call_count, - 'The upgrade_settings() method should not have been called.') + 'The upgrade_settings() method should not have been called.') def hook_upgrade_plugin_settings_with_active_plugin_test(self): """ @@ -282,7 +282,7 @@ class TestPluginManager(TestCase): # THEN: The add_tools_menu_item() method should have been called self.assertEqual(0, mocked_plugin.add_tools_menu_item.call_count, - 'The add_tools_menu_item() method should not have been called.') + 'The add_tools_menu_item() method should not have been called.') def hook_tools_menu_with_active_plugin_test(self): """ diff --git a/tests/functional/openlp_core_lib/test_screen.py b/tests/functional/openlp_core_lib/test_screen.py index b9e7fb5e0..bf4bf7263 100644 --- a/tests/functional/openlp_core_lib/test_screen.py +++ b/tests/functional/openlp_core_lib/test_screen.py @@ -84,4 +84,4 @@ class TestScreenList(TestCase): new_screen_count = len(self.screens.screen_list) self.assertEqual(old_screen_count + 1, new_screen_count, 'The new_screens list should be bigger') self.assertEqual(SCREEN, self.screens.screen_list.pop(), - 'The 2nd screen should be identical to the first screen') + 'The 2nd screen should be identical to the first screen') diff --git a/tests/functional/openlp_core_lib/test_serviceitem.py b/tests/functional/openlp_core_lib/test_serviceitem.py index 3c53c8179..15da3b738 100644 --- a/tests/functional/openlp_core_lib/test_serviceitem.py +++ b/tests/functional/openlp_core_lib/test_serviceitem.py @@ -99,9 +99,9 @@ class TestServiceItem(TestCase): # THEN: The frames should also be valid self.assertEqual('Test Custom', service_item.get_display_title(), 'The title should be "Test Custom"') self.assertEqual(VERSE[:-1], service_item.get_frames()[0]['text'], - 'The returned text matches the input, except the last line feed') + 'The returned text matches the input, except the last line feed') self.assertEqual(VERSE.split('\n', 1)[0], service_item.get_rendered_frame(1), - 'The first line has been returned') + 'The first line has been returned') self.assertEqual('Slide 1', service_item.get_frame_title(0), '"Slide 1" has been returned as the title') self.assertEqual('Slide 2', service_item.get_frame_title(1), '"Slide 2" has been returned as the title') self.assertEqual('', service_item.get_frame_title(2), 'Blank has been returned as the title of slide 3') @@ -127,24 +127,24 @@ class TestServiceItem(TestCase): # THEN: We should get back a valid service item self.assertTrue(service_item.is_valid, 'The new service item should be valid') self.assertEqual(test_file, service_item.get_rendered_frame(0), - 'The first frame should match the path to the image') + 'The first frame should match the path to the image') self.assertEqual(frame_array, service_item.get_frames()[0], - 'The return should match frame array1') + 'The return should match frame array1') self.assertEqual(test_file, service_item.get_frame_path(0), - 'The frame path should match the full path to the image') + 'The frame path should match the full path to the image') self.assertEqual(image_name, service_item.get_frame_title(0), - 'The frame title should match the image name') + 'The frame title should match the image name') self.assertEqual(image_name, service_item.get_display_title(), - 'The display title should match the first image name') + 'The display title should match the first image name') self.assertTrue(service_item.is_image(), 'This service item should be of an "image" type') self.assertTrue(service_item.is_capable(ItemCapabilities.CanMaintain), - 'This service item should be able to be Maintained') + 'This service item should be able to be Maintained') self.assertTrue(service_item.is_capable(ItemCapabilities.CanPreview), - 'This service item should be able to be be Previewed') + 'This service item should be able to be be Previewed') self.assertTrue(service_item.is_capable(ItemCapabilities.CanLoop), - 'This service item should be able to be run in a can be made to Loop') + 'This service item should be able to be run in a can be made to Loop') self.assertTrue(service_item.is_capable(ItemCapabilities.CanAppend), - 'This service item should be able to have new items added to it') + 'This service item should be able to have new items added to it') def service_item_load_image_from_local_service_test(self): """ @@ -180,27 +180,27 @@ class TestServiceItem(TestCase): self.assertTrue(service_item.is_valid, 'The first service item should be valid') self.assertTrue(service_item2.is_valid, 'The second service item should be valid') self.assertEqual(test_file1, service_item.get_rendered_frame(0), - 'The first frame should match the path to the image') + 'The first frame should match the path to the image') self.assertEqual(test_file2, service_item2.get_rendered_frame(0), - 'The Second frame should match the path to the image') + 'The Second frame should match the path to the image') self.assertEqual(frame_array1, service_item.get_frames()[0], 'The return should match the frame array1') self.assertEqual(frame_array2, service_item2.get_frames()[0], 'The return should match the frame array2') self.assertEqual(test_file1, service_item.get_frame_path(0), - 'The frame path should match the full path to the image') + 'The frame path should match the full path to the image') self.assertEqual(test_file2, service_item2.get_frame_path(0), - 'The frame path should match the full path to the image') + 'The frame path should match the full path to the image') self.assertEqual(image_name1, service_item.get_frame_title(0), - 'The 1st frame title should match the image name') + 'The 1st frame title should match the image name') self.assertEqual(image_name2, service_item2.get_frame_title(0), - 'The 2nd frame title should match the image name') + 'The 2nd frame title should match the image name') self.assertEqual(service_item.name, service_item.title.lower(), - 'The plugin name should match the display title, as there are > 1 Images') + 'The plugin name should match the display title, as there are > 1 Images') self.assertTrue(service_item.is_image(), 'This service item should be of an "image" type') self.assertTrue(service_item.is_capable(ItemCapabilities.CanMaintain), - 'This service item should be able to be Maintained') + 'This service item should be able to be Maintained') self.assertTrue(service_item.is_capable(ItemCapabilities.CanPreview), - 'This service item should be able to be be Previewed') + 'This service item should be able to be be Previewed') self.assertTrue(service_item.is_capable(ItemCapabilities.CanLoop), - 'This service item should be able to be run in a can be made to Loop') + 'This service item should be able to be run in a can be made to Loop') self.assertTrue(service_item.is_capable(ItemCapabilities.CanAppend), - 'This service item should be able to have new items added to it') + 'This service item should be able to have new items added to it') diff --git a/tests/interfaces/openlp_core_ui/test_servicemanager.py b/tests/interfaces/openlp_core_ui/test_servicemanager.py index 8cde77dcd..c42d41dfe 100644 --- a/tests/interfaces/openlp_core_ui/test_servicemanager.py +++ b/tests/interfaces/openlp_core_ui/test_servicemanager.py @@ -4,7 +4,7 @@ from unittest import TestCase -from PyQt4 import QtGui +from PyQt4 import QtGui, QtTest, QtCore from openlp.core.common import Registry from openlp.core.lib import ScreenList, ServiceItem, ItemCapabilities @@ -25,6 +25,7 @@ class TestServiceManager(TestCase): with patch('openlp.core.lib.PluginManager'): self.main_window = MainWindow() self.service_manager = Registry().get('service_manager') + self.event_was_called = False def tearDown(self): """ @@ -35,7 +36,7 @@ class TestServiceManager(TestCase): def basic_service_manager_test(self): """ - Test the Service Manager display functionality + Test the Service Manager UI Functionality """ # GIVEN: A New Service Manager instance @@ -87,7 +88,6 @@ class TestServiceManager(TestCase): self.service_manager.auto_start_action.setVisible.assert_called_once_with(False), \ 'The action should be set invisible.' - def edit_context_menu_test(self): """ Test the context_menu() method with a edit service item @@ -306,3 +306,33 @@ class TestServiceManager(TestCase): self.service_manager.auto_start_action.setVisible.assert_called_with(True), \ 'The action should be set visible.' + def click_on_new_service_test1(self): + """ + Test the on_new_service event handler + """ + # GIVEN: An initial form + self.service_manager.setup_ui(self.service_manager) + + # WHEN displaying the UI and pressing cancel + new_service = self.service_manager.toolbar.actions['newService'] + self.service_manager.on_new_service_clicked = self.dummy_event() + new_service.trigger() + assert self.event_was_called is True, 'The on_new_service_clicked method should have been called' + + def click_on_new_service_test2(self): + """ + Test the on_new_service event handler + """ + # GIVEN: An initial form + self.service_manager.setup_ui(self.service_manager) + + # WHEN displaying the UI and pressing cancel + new_service = self.service_manager.toolbar.actions['newService'] + mocked_event = MagicMock() + self.service_manager.on_new_service_clicked = mocked_event + new_service.trigger() + print(mocked_event.call_count) + assert self.event_was_called == 1, 'The on_new_service_clicked method should have been called' + + def dummy_event(self): + self.event_was_called = True \ No newline at end of file From 51178b2ede307b0fcb9759e6659a14db39bff184 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 31 Dec 2013 20:29:03 +0000 Subject: [PATCH 15/41] Fix tests --- openlp/core/common/registry.py | 2 +- openlp/core/ui/__init__.py | 3 +- openlp/core/ui/media/mediacontroller.py | 50 ++++++------ openlp/core/ui/media/mediaplayer.py | 3 +- openlp/core/ui/media/phononplayer.py | 29 ++++--- openlp/core/ui/media/playertab.py | 18 ++--- openlp/core/ui/media/vlcplayer.py | 76 +++++++++---------- openlp/core/ui/media/webkitplayer.py | 16 ++-- openlp/core/ui/servicemanager.py | 73 ++++++++---------- openlp/core/ui/settingsform.py | 4 +- openlp/core/ui/thememanager.py | 43 ++++++++--- openlp/core/ui/thememanagerhelper.py | 50 ------------ openlp/plugins/media/lib/mediaitem.py | 73 +++++++++--------- .../openlp_core_ui/test_servicemanager.py | 33 ++------ ...emanagerhelper.py => test_thememanager.py} | 49 ++++++------ 15 files changed, 239 insertions(+), 283 deletions(-) delete mode 100644 openlp/core/ui/thememanagerhelper.py rename tests/interfaces/openlp_core_ui/{test_thememanagerhelper.py => test_thememanager.py} (73%) diff --git a/openlp/core/common/registry.py b/openlp/core/common/registry.py index 5bbb698d5..4d43a738e 100644 --- a/openlp/core/common/registry.py +++ b/openlp/core/common/registry.py @@ -172,5 +172,5 @@ class Registry(object): log.exception('Exception for function %s', function) else: trace_error_handler(log) - log.error("Event %s not called by not registered" % event) + log.error("Event %s called but not registered" % event) return results diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index 677c65ab1..dee413ef0 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -99,11 +99,10 @@ from .formattingtagcontroller import FormattingTagController from .shortcutlistform import ShortcutListForm from .mediadockmanager import MediaDockManager from .servicemanager import ServiceManager -from .thememanagerhelper import ThemeManagerHelper from .thememanager import ThemeManager __all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeManager', 'MediaDockManager', 'ServiceItemEditForm', 'FirstTimeForm', 'FirstTimeLanguageForm', 'ThemeForm', 'ThemeLayoutForm', 'FileRenameForm', 'StartTimeForm', 'MainDisplay', 'Display', 'ServiceNoteForm', 'SlideController', 'DisplayController', 'GeneralTab', 'ThemesTab', 'AdvancedTab', 'PluginForm', - 'FormattingTagForm', 'ShortcutListForm', 'FormattingTagController', 'ThemeManagerHelper'] + 'FormattingTagForm', 'ShortcutListForm', 'FormattingTagController'] diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index 50db35602..ac52700a1 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -35,7 +35,7 @@ import os import datetime from PyQt4 import QtCore, QtGui -from openlp.core.common import Registry, Settings, UiStrings, translate +from openlp.core.common import Registry, RegistryMixin, Settings, UiStrings, translate from openlp.core.lib import OpenLPToolbar from openlp.core.lib.ui import critical_error_message_box from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players @@ -99,7 +99,7 @@ class MediaController(object): Constructor """ Registry().register('media_controller', self) - Registry().register_function('bootstrap_initialise', self.check_available_media_players) + Registry().register_function('bootstrap_initialise', self.bootstrap_initialise) self.media_players = {} self.display_controllers = {} self.current_media_players = {} @@ -134,20 +134,22 @@ class MediaController(object): """ Set the active players and available media files """ + suffix_list = [] self.audio_extensions_list = [] for player in list(self.media_players.values()): if player.is_active: for item in player.audio_extensions_list: if not item in self.audio_extensions_list: self.audio_extensions_list.append(item) - self.service_manager.supported_suffixes(item[2:]) + suffix_list.append(item[2:]) self.video_extensions_list = [] for player in list(self.media_players.values()): if player.is_active: for item in player.video_extensions_list: if item not in self.video_extensions_list: self.video_extensions_list.extend(item) - self.service_manager.supported_suffixes(item[2:]) + suffix_list.append(item[2:]) + self.service_manager.supported_suffixes(suffix_list) def register_players(self, player): """ @@ -159,7 +161,7 @@ class MediaController(object): """ self.media_players[player.name] = player - def check_available_media_players(self): + def bootstrap_initialise(self): """ Check to see if we have any media Player's available. """ @@ -169,27 +171,28 @@ class MediaController(object): if filename.endswith('player.py') and not filename == 'mediaplayer.py': path = os.path.join(controller_dir, filename) if os.path.isfile(path): - modulename = 'openlp.core.ui.media.' + os.path.splitext(filename)[0] - log.debug('Importing controller %s', modulename) + module_name = 'openlp.core.ui.media.' + os.path.splitext(filename)[0] + log.debug('Importing controller %s', module_name) try: - __import__(modulename, globals(), locals(), []) + __import__(module_name, globals(), locals(), []) # On some platforms importing vlc.py might cause # also OSError exceptions. (e.g. Mac OS X) except (ImportError, OSError): - log.warn('Failed to import %s on path %s', modulename, path) + log.warn('Failed to import %s on path %s', module_name, path) player_classes = MediaPlayer.__subclasses__() for player_class in player_classes: player = player_class(self) self.register_players(player) if not self.media_players: return False - savedPlayers, overriddenPlayer = get_media_players() - invalid_media_players = [mediaPlayer for mediaPlayer in savedPlayers - if not mediaPlayer in self.media_players or not self.media_players[mediaPlayer].check_available()] + saved_players, overridden_player = get_media_players() + invalid_media_players = \ + [mediaPlayer for mediaPlayer in saved_players if not mediaPlayer in self.media_players or + not self.media_players[mediaPlayer].check_available()] if invalid_media_players: for invalidPlayer in invalid_media_players: - savedPlayers.remove(invalidPlayer) - set_media_players(savedPlayers, overriddenPlayer) + saved_players.remove(invalidPlayer) + set_media_players(saved_players, overridden_player) self._set_active_players() self._generate_extensions_lists() return True @@ -270,14 +273,17 @@ class MediaController(object): # Build a Media ToolBar controller.mediabar = OpenLPToolbar(controller) controller.mediabar.add_toolbar_action('playbackPlay', text='media_playback_play', - icon=':/slides/media_playback_start.png', - tooltip=translate('OpenLP.SlideController', 'Start playing media.'), triggers=controller.send_to_plugins) + icon=':/slides/media_playback_start.png', + tooltip=translate('OpenLP.SlideController', 'Start playing media.'), + triggers=controller.send_to_plugins) controller.mediabar.add_toolbar_action('playbackPause', text='media_playback_pause', - icon=':/slides/media_playback_pause.png', - tooltip=translate('OpenLP.SlideController', 'Pause playing media.'), triggers=controller.send_to_plugins) + icon=':/slides/media_playback_pause.png', + tooltip=translate('OpenLP.SlideController', 'Pause playing media.'), + triggers=controller.send_to_plugins) controller.mediabar.add_toolbar_action('playbackStop', text='media_playback_stop', - icon=':/slides/media_playback_stop.png', - tooltip=translate('OpenLP.SlideController', 'Stop playing media.'), triggers=controller.send_to_plugins) + icon=':/slides/media_playback_stop.png', + tooltip=translate('OpenLP.SlideController', 'Stop playing media.'), + triggers=controller.send_to_plugins) # Build the seek_slider. controller.seek_slider = MediaSlider(QtCore.Qt.Horizontal, self, controller) controller.seek_slider.setMaximum(1000) @@ -445,11 +451,11 @@ class MediaController(object): if not self._check_file_type(controller, display, service_item): # Media could not be loaded correctly critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'), - translate('MediaPlugin.MediaItem', 'Unsupported File')) + translate('MediaPlugin.MediaItem', 'Unsupported File')) return False if not self.media_play(controller): critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'), - translate('MediaPlugin.MediaItem', 'Unsupported File')) + translate('MediaPlugin.MediaItem', 'Unsupported File')) return False service_item.set_media_length(controller.media_info.length) self.media_stop(controller) diff --git a/openlp/core/ui/media/mediaplayer.py b/openlp/core/ui/media/mediaplayer.py index e3173c053..3aa0c1fbf 100644 --- a/openlp/core/ui/media/mediaplayer.py +++ b/openlp/core/ui/media/mediaplayer.py @@ -37,8 +37,7 @@ from openlp.core.ui.media import MediaState class MediaPlayer(object): """ - This is the base class media Player class to provide OpenLP with a - pluggable media display framework. + This is the base class media Player class to provide OpenLP with a pluggable media display framework. """ def __init__(self, parent, name='media_player'): diff --git a/openlp/core/ui/media/phononplayer.py b/openlp/core/ui/media/phononplayer.py index f5790f08f..5a2d29223 100644 --- a/openlp/core/ui/media/phononplayer.py +++ b/openlp/core/ui/media/phononplayer.py @@ -80,12 +80,12 @@ class PhononPlayer(MediaPlayer): self.parent = parent self.additional_extensions = ADDITIONAL_EXT mimetypes.init() - for mimetype in Phonon.BackendCapabilities.availableMimeTypes(): - mimetype = str(mimetype) - if mimetype.startswith('audio/'): - self._addToList(self.audio_extensions_list, mimetype) - elif mimetype.startswith('video/'): - self._addToList(self.video_extensions_list, mimetype) + for mime_type in Phonon.BackendCapabilities.availableMimeTypes(): + mime_type = str(mime_type) + if mime_type.startswith('audio/'): + self._addToList(self.audio_extensions_list, mime_type) + elif mime_type.startswith('video/'): + self._addToList(self.video_extensions_list, mime_type) def _addToList(self, mimetype_list, mimetype): """ @@ -144,14 +144,14 @@ class PhononPlayer(MediaPlayer): self.volume(display, volume) return True - def media_state_wait(self, display, mediaState): + def media_state_wait(self, display, media_state): """ Wait for the video to change its state Wait no longer than 5 seconds. """ start = datetime.now() current_state = display.media_object.state() - while current_state != mediaState: + while current_state != media_state: current_state = display.media_object.state() if current_state == Phonon.ErrorState: return False @@ -172,8 +172,7 @@ class PhononPlayer(MediaPlayer): """ controller = display.controller start_time = 0 - if display.media_object.state() != Phonon.PausedState and \ - controller.media_info.start_time > 0: + if display.media_object.state() != Phonon.PausedState and controller.media_info.start_time > 0: start_time = controller.media_info.start_time display.media_object.play() if not self.media_state_wait(display, Phonon.PlayingState): @@ -262,8 +261,8 @@ class PhononPlayer(MediaPlayer): Return some info about this player """ return(translate('Media.player', 'Phonon is a media player which ' - 'interacts with the operating system to provide media capabilities.') + - '
' + translate('Media.player', 'Audio') + - '
' + str(self.audio_extensions_list) + - '
' + translate('Media.player', 'Video') + - '
' + str(self.video_extensions_list) + '
') + 'interacts with the operating system to provide media capabilities.') + + '
' + translate('Media.player', 'Audio') + + '
' + str(self.audio_extensions_list) + + '
' + translate('Media.player', 'Video') + + '
' + str(self.video_extensions_list) + '
') diff --git a/openlp/core/ui/media/playertab.py b/openlp/core/ui/media/playertab.py index 58b56426a..566071f30 100644 --- a/openlp/core/ui/media/playertab.py +++ b/openlp/core/ui/media/playertab.py @@ -39,13 +39,13 @@ from openlp.core.ui.media import get_media_players, set_media_players class MediaQCheckBox(QtGui.QCheckBox): """ - MediaQCheckBox adds an extra property, playerName to the QCheckBox class. + MediaQCheckBox adds an extra property, player_name to the QCheckBox class. """ def set_player_name(self, name): """ Set the player name """ - self.playerName = name + self.player_name = name class PlayerTab(SettingsTab): @@ -113,9 +113,9 @@ class PlayerTab(SettingsTab): self.ordering_button_layout.setObjectName('ordering_button_layout') self.ordering_button_layout.addStretch(1) self.ordering_up_button = create_button(self, 'ordering_up_button', role='up', - click=self.on_up_button_clicked) + click=self.on_up_button_clicked) self.ordering_down_button = create_button(self, 'ordering_down_button', role='down', - click=self.on_down_button_clicked) + click=self.on_down_button_clicked) self.ordering_button_layout.addWidget(self.ordering_up_button) self.ordering_button_layout.addWidget(self.ordering_down_button) self.ordering_button_layout.addStretch(1) @@ -135,8 +135,8 @@ class PlayerTab(SettingsTab): self.background_color_group_box.setTitle(UiStrings().BackgroundColor) self.background_color_label.setText(UiStrings().DefaultColor) self.information_label.setText(translate('OpenLP.PlayerTab', - 'Visible background for videos with aspect ratio different to screen.')) - self.retranslatePlayers() + 'Visible background for videos with aspect ratio different to screen.')) + self.retranslate_players() def on_background_color_button_clicked(self): """ @@ -151,7 +151,7 @@ class PlayerTab(SettingsTab): """ Add or remove players depending on their status """ - player = self.sender().playerName + player = self.sender().player_name if check_state == QtCore.Qt.Checked: if player not in self.used_players: self.used_players.append(player) @@ -249,9 +249,9 @@ class PlayerTab(SettingsTab): else: checkbox.setChecked(False) self.update_player_list() - self.retranslatePlayers() + self.retranslate_players() - def retranslatePlayers(self): + def retranslate_players(self): """ Translations for players is dependent on their setup as well """ diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py index bf6374473..7c892a87c 100644 --- a/openlp/core/ui/media/vlcplayer.py +++ b/openlp/core/ui/media/vlcplayer.py @@ -118,35 +118,35 @@ class VlcPlayer(MediaPlayer): """ Set up the media player """ - display.vlcWidget = QtGui.QFrame(display) - display.vlcWidget.setFrameStyle(QtGui.QFrame.NoFrame) + display.vlc_widget = QtGui.QFrame(display) + display.vlc_widget.setFrameStyle(QtGui.QFrame.NoFrame) # creating a basic vlc instance command_line_options = '--no-video-title-show' if not display.has_audio: command_line_options += ' --no-audio --no-video-title-show' if Settings().value('advanced/hide mouse') and display.controller.is_live: command_line_options += ' --mouse-hide-timeout=0' - display.vlcInstance = vlc.Instance(command_line_options) + display.vlc_instance = vlc.Instance(command_line_options) # creating an empty vlc media player - display.vlcMediaPlayer = display.vlcInstance.media_player_new() - display.vlcWidget.resize(display.size()) - display.vlcWidget.raise_() - display.vlcWidget.hide() + display.vlc_media_player = display.vlc_instance.media_player_new() + display.vlc_widget.resize(display.size()) + display.vlc_widget.raise_() + display.vlc_widget.hide() # The media player has to be 'connected' to the QFrame. # (otherwise a video would be displayed in it's own window) # This is platform specific! # You have to give the id of the QFrame (or similar object) # to vlc, different platforms have different functions for this. - win_id = int(display.vlcWidget.winId()) + win_id = int(display.vlc_widget.winId()) if sys.platform == "win32": - display.vlcMediaPlayer.set_hwnd(win_id) + display.vlc_media_player.set_hwnd(win_id) elif sys.platform == "darwin": # We have to use 'set_nsobject' since Qt4 on OSX uses Cocoa # framework and not the old Carbon. - display.vlcMediaPlayer.set_nsobject(win_id) + display.vlc_media_player.set_nsobject(win_id) else: # for Linux using the X Server - display.vlcMediaPlayer.set_xwindow(win_id) + display.vlc_media_player.set_xwindow(win_id) self.has_own_widget = True def check_available(self): @@ -165,18 +165,18 @@ class VlcPlayer(MediaPlayer): file_path = str(controller.media_info.file_info.absoluteFilePath()) path = os.path.normcase(file_path) # create the media - display.vlcMedia = display.vlcInstance.media_new_path(path) + display.vlc_media = display.vlc_instance.media_new_path(path) # put the media in the media player - display.vlcMediaPlayer.set_media(display.vlcMedia) + display.vlc_media_player.set_media(display.vlc_media) # parse the metadata of the file - display.vlcMedia.parse() + display.vlc_media.parse() self.volume(display, volume) # We need to set media_info.length during load because we want # to avoid start and stop the video twice. Once for real playback # and once to just get media length. # # Media plugin depends on knowing media length before playback. - controller.media_info.length = int(display.vlcMediaPlayer.get_media().get_duration() / 1000) + controller.media_info.length = int(display.vlc_media_player.get_media().get_duration() / 1000) return True def media_state_wait(self, display, media_state): @@ -185,8 +185,8 @@ class VlcPlayer(MediaPlayer): Wait no longer than 60 seconds. (loading an iso file needs a long time) """ start = datetime.now() - while not media_state == display.vlcMedia.get_state(): - if display.vlcMedia.get_state() == vlc.State.Error: + while not media_state == display.vlc_media.get_state(): + if display.vlc_media.get_state() == vlc.State.Error: return False self.application.process_events() if (datetime.now() - start).seconds > 60: @@ -197,7 +197,7 @@ class VlcPlayer(MediaPlayer): """ Resize the player """ - display.vlcWidget.resize(display.size()) + display.vlc_widget.resize(display.size()) def play(self, display): """ @@ -207,25 +207,25 @@ class VlcPlayer(MediaPlayer): start_time = 0 if self.state != MediaState.Paused and controller.media_info.start_time > 0: start_time = controller.media_info.start_time - display.vlcMediaPlayer.play() + display.vlc_media_player.play() if not self.media_state_wait(display, vlc.State.Playing): return False self.volume(display, controller.media_info.volume) if start_time > 0: self.seek(display, controller.media_info.start_time * 1000) - controller.media_info.length = int(display.vlcMediaPlayer.get_media().get_duration() / 1000) + controller.media_info.length = int(display.vlc_media_player.get_media().get_duration() / 1000) controller.seek_slider.setMaximum(controller.media_info.length * 1000) self.state = MediaState.Playing - display.vlcWidget.raise_() + display.vlc_widget.raise_() return True def pause(self, display): """ Pause the current item """ - if display.vlcMedia.get_state() != vlc.State.Playing: + if display.vlc_media.get_state() != vlc.State.Playing: return - display.vlcMediaPlayer.pause() + display.vlc_media_player.pause() if self.media_state_wait(display, vlc.State.Paused): self.state = MediaState.Paused @@ -233,7 +233,7 @@ class VlcPlayer(MediaPlayer): """ Stop the current item """ - display.vlcMediaPlayer.stop() + display.vlc_media_player.stop() self.state = MediaState.Stopped def volume(self, display, vol): @@ -241,21 +241,21 @@ class VlcPlayer(MediaPlayer): Set the volume """ if display.has_audio: - display.vlcMediaPlayer.audio_set_volume(vol) + display.vlc_media_player.audio_set_volume(vol) def seek(self, display, seek_value): """ Go to a particular position """ - if display.vlcMediaPlayer.is_seekable(): - display.vlcMediaPlayer.set_time(seek_value) + if display.vlc_media_player.is_seekable(): + display.vlc_media_player.set_time(seek_value) def reset(self, display): """ Reset the player """ - display.vlcMediaPlayer.stop() - display.vlcWidget.setVisible(False) + display.vlc_media_player.stop() + display.vlc_widget.setVisible(False) self.state = MediaState.Off def set_visible(self, display, status): @@ -263,23 +263,23 @@ class VlcPlayer(MediaPlayer): Set the visibility """ if self.has_own_widget: - display.vlcWidget.setVisible(status) + display.vlc_widget.setVisible(status) def update_ui(self, display): """ Update the UI """ # Stop video if playback is finished. - if display.vlcMedia.get_state() == vlc.State.Ended: + if display.vlc_media.get_state() == vlc.State.Ended: self.stop(display) controller = display.controller if controller.media_info.end_time > 0: - if display.vlcMediaPlayer.get_time() > controller.media_info.end_time * 1000: + if display.vlc_media_player.get_time() > controller.media_info.end_time * 1000: self.stop(display) self.set_visible(display, False) if not controller.seek_slider.isSliderDown(): controller.seek_slider.blockSignals(True) - controller.seek_slider.setSliderPosition(display.vlcMediaPlayer.get_time()) + controller.seek_slider.setSliderPosition(display.vlc_media_player.get_time()) controller.seek_slider.blockSignals(False) def get_info(self): @@ -287,8 +287,8 @@ class VlcPlayer(MediaPlayer): Return some information about this player """ return(translate('Media.player', 'VLC is an external player which ' - 'supports a number of different formats.') + - '
' + translate('Media.player', 'Audio') + - '
' + str(AUDIO_EXT) + '
' + - translate('Media.player', 'Video') + '
' + - str(VIDEO_EXT) + '
') + 'supports a number of different formats.') + + '
' + translate('Media.player', 'Audio') + + '
' + str(AUDIO_EXT) + '
' + + translate('Media.player', 'Video') + '
' + + str(VIDEO_EXT) + '
') \ No newline at end of file diff --git a/openlp/core/ui/media/webkitplayer.py b/openlp/core/ui/media/webkitplayer.py index a7aac96eb..e3a522140 100644 --- a/openlp/core/ui/media/webkitplayer.py +++ b/openlp/core/ui/media/webkitplayer.py @@ -376,9 +376,9 @@ class WebkitPlayer(MediaPlayer): else: is_visible = "hidden" if controller.media_info.is_flash: - display.frame.evaluateJavaScript('show_flash("setVisible", null, null, "%s");' % (is_visible)) + display.frame.evaluateJavaScript('show_flash("setVisible", null, null, "%s");' % is_visible) else: - display.frame.evaluateJavaScript('show_video("setVisible", null, null, null, "%s");' % (is_visible)) + display.frame.evaluateJavaScript('show_video("setVisible", null, null, null, "%s");' % is_visible) def update_ui(self, display): """ @@ -412,9 +412,9 @@ class WebkitPlayer(MediaPlayer): Return some information about this player """ return(translate('Media.player', 'Webkit is a media player which runs ' - 'inside a web browser. This player allows text over video to be ' - 'rendered.') + - '
' + translate('Media.player', 'Audio') + - '
' + str(AUDIO_EXT) + '
' + - translate('Media.player', 'Video') + '
' + - str(VIDEO_EXT) + '
') + 'inside a web browser. This player allows text over video to be ' + 'rendered.') + + '
' + translate('Media.player', 'Audio') + + '
' + str(AUDIO_EXT) + '
' + + translate('Media.player', 'Video') + '
' + + str(VIDEO_EXT) + '
') diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 0f66e1533..d492355e9 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -30,7 +30,6 @@ The service manager sets up, loads, saves and manages services. """ import html -import logging import os import shutil import zipfile @@ -38,8 +37,6 @@ import json from tempfile import mkstemp from datetime import datetime, timedelta -log = logging.getLogger(__name__) - from PyQt4 import QtCore, QtGui from openlp.core.common import Registry, AppLocation, Settings, ThemeLevel, OpenLPMixin, RegistryMixin, \ @@ -291,7 +288,7 @@ class Ui_ServiceManager(object): self.service_manager_list.down, self.service_manager_list.expand, self.service_manager_list.collapse - ]) + ]) Registry().register_function('theme_update_list', self.update_theme_list) Registry().register_function('config_screen_changed', self.regenerate_service_items) Registry().register_function('theme_update_global', self.theme_change) @@ -330,7 +327,6 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.service_has_all_original_files = True def bootstrap_initialise(self): - print(self) self.setup_ui(self) # Need to use event as called across threads and UI is updated QtCore.QObject.connect(self, QtCore.SIGNAL('servicemanager_set_item'), self.on_set_item) @@ -387,15 +383,16 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ self.suffixes = [] - def supported_suffixes(self, suffix): + def supported_suffixes(self, suffix_list): """ Adds Suffixes supported to the master list. Called from Plugins. - ``suffix`` - New Suffix to be supported + ``suffix_list`` + New Suffix's to be supported """ - if not suffix in self.suffixes: - self.suffixes.append(suffix) + for suffix in suffix_list: + if not suffix in self.suffixes: + self.suffixes.append(suffix) def on_new_service_clicked(self, field=None): """ @@ -482,12 +479,12 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage temp_file, temp_file_name = mkstemp('.osz', 'openlp_') # We don't need the file handle. os.close(temp_file) - log.debug(temp_file_name) + self.log_debug(temp_file_name) path_file_name = str(self.file_name()) path, file_name = os.path.split(path_file_name) base_name = os.path.splitext(file_name)[0] service_file_name = '%s.osj' % base_name - log.debug('ServiceManager.save_file - %s', path_file_name) + self.log_debug('ServiceManager.save_file - %s', path_file_name) Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', path) service = [] write_list = [] @@ -540,11 +537,11 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage for file_item in write_list: file_size = os.path.getsize(file_item) total_size += file_size - log.debug('ServiceManager.save_file - ZIP contents size is %i bytes' % total_size) + self.log_debug('ServiceManager.save_file - ZIP contents size is %i bytes' % total_size) service_content = json.dumps(service) # Usual Zip file cannot exceed 2GiB, file with Zip64 cannot be extracted using unzip in UNIX. allow_zip_64 = (total_size > 2147483648 + len(service_content)) - log.debug('ServiceManager.save_file - allowZip64 is %s' % allow_zip_64) + self.log_debug('ServiceManager.save_file - allowZip64 is %s' % allow_zip_64) zip_file = None success = True self.main_window.increment_progress_bar() @@ -567,7 +564,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage shutil.copy(audio_from, save_file) zip_file.write(audio_from, audio_to) except IOError: - log.exception('Failed to save service to disk: %s', temp_file_name) + self.log_exception('Failed to save service to disk: %s', temp_file_name) self.main_window.error_message(translate('OpenLP.ServiceManager', 'Error Saving File'), translate('OpenLP.ServiceManager', 'There was an error saving your file.')) success = False @@ -596,12 +593,12 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage temp_file, temp_file_name = mkstemp('.oszl', 'openlp_') # We don't need the file handle. os.close(temp_file) - log.debug(temp_file_name) + self.log_debug(temp_file_name) path_file_name = str(self.file_name()) path, file_name = os.path.split(path_file_name) base_name = os.path.splitext(file_name)[0] service_file_name = '%s.osj' % base_name - log.debug('ServiceManager.save_file - %s', path_file_name) + self.log_debug('ServiceManager.save_file - %s', path_file_name) Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', path) service = [] self.application.set_busy_cursor() @@ -622,7 +619,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage # First we add service contents. zip_file.writestr(service_file_name, service_content) except IOError: - log.exception('Failed to save service to disk: %s', temp_file_name) + self.log_exception('Failed to save service to disk: %s', temp_file_name) self.main_window.error_message(translate('OpenLP.ServiceManager', 'Error Saving File'), translate('OpenLP.ServiceManager', 'There was an error saving your file.')) success = False @@ -686,7 +683,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.set_file_name(file_name) self.decide_save_method() - def decide_save_method(self): + def decide_save_method(self, field=None): """ Determine which type of save method to use. """ @@ -715,14 +712,14 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage try: ucs_file = zip_info.filename except UnicodeDecodeError: - log.exception('file_name "%s" is not valid UTF-8' % zip_info.file_name) + self.log_exception('file_name "%s" is not valid UTF-8' % zip_info.file_name) critical_error_message_box(message=translate('OpenLP.ServiceManager', 'File is not a valid service.\n The content encoding is not UTF-8.')) continue os_file = ucs_file.replace('/', os.path.sep) if not os_file.startswith('audio'): os_file = os.path.split(os_file)[1] - log.debug('Extract file: %s', os_file) + self.log_debug('Extract file: %s', os_file) zip_info.filename = os_file zip_file.extract(zip_info, self.service_path) if os_file.endswith('osj') or os_file.endswith('osd'): @@ -759,19 +756,19 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage Settings().setValue('servicemanager/last file', file_name) else: critical_error_message_box(message=translate('OpenLP.ServiceManager', 'File is not a valid service.')) - log.error('File contains no service data') + self.log_error('File contains no service data') except (IOError, NameError, zipfile.BadZipfile): - log.exception('Problem loading service file %s' % file_name) + self.log_exception('Problem loading service file %s' % file_name) critical_error_message_box(message=translate('OpenLP.ServiceManager', 'File could not be opened because it is corrupt.')) except zipfile.BadZipfile: if os.path.getsize(file_name) == 0: - log.exception('Service file is zero sized: %s' % file_name) + self.log_exception('Service file is zero sized: %s' % file_name) QtGui.QMessageBox.information(self, translate('OpenLP.ServiceManager', 'Empty File'), translate('OpenLP.ServiceManager', 'This service file does not contain ' 'any data.')) else: - log.exception('Service file is cannot be extracted as zip: %s' % file_name) + self.log_exception('Service file is cannot be extracted as zip: %s' % file_name) QtGui.QMessageBox.information(self, translate('OpenLP.ServiceManager', 'Corrupt File'), translate('OpenLP.ServiceManager', 'This file is either corrupt or it is not an OpenLP 2 service file.')) @@ -881,7 +878,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage if self.start_time_form.exec_(): self.repaint_service_list(item, -1) - def toggle_auto_play_slides_once(self): + def toggle_auto_play_slides_once(self, field=None): """ Toggle Auto play slide once. Inverts auto play once option for the item """ @@ -896,7 +893,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.main_window.general_settings_section + '/loop delay') self.set_modified() - def toggle_auto_play_slides_loop(self): + def toggle_auto_play_slides_loop(self, field=None): """ Toggle Auto play slide loop. """ @@ -1059,7 +1056,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage return self.service_manager_list.setCurrentItem(item_after) - def on_collapse_all(self): + def on_collapse_all(self, field=None): """ Collapse all the service items. """ @@ -1074,7 +1071,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage pos = item.data(0, QtCore.Qt.UserRole) self.service_items[pos - 1]['expanded'] = False - def on_expand_all(self): + def on_expand_all(self, field=None): """ Collapse all the service items. """ @@ -1089,7 +1086,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage pos = item.data(0, QtCore.Qt.UserRole) self.service_items[pos - 1]['expanded'] = True - def on_service_top(self): + def on_service_top(self, field=None): """ Move the current ServiceItem to the top of the list. """ @@ -1101,7 +1098,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.repaint_service_list(0, child) self.set_modified() - def on_service_up(self): + def on_service_up(self, field=None): """ Move the current ServiceItem one position up in the list. """ @@ -1113,7 +1110,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.repaint_service_list(item - 1, child) self.set_modified() - def on_service_down(self): + def on_service_down(self, field=None): """ Move the current ServiceItem one position down in the list. """ @@ -1125,7 +1122,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.repaint_service_list(item + 1, child) self.set_modified() - def on_service_end(self): + def on_service_end(self, field=None): """ Move the current ServiceItem to the bottom of the list. """ @@ -1229,7 +1226,6 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Empties the service_path of temporary files on system exit. """ - log.debug('Cleaning up service_path') for file_name in os.listdir(self.service_path): file_path = os.path.join(self.service_path, file_name) delete_file(file_path) @@ -1240,7 +1236,6 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Set the theme for the current service. """ - log.debug('on_theme_combo_box_selected') self.service_theme = self.theme_combo_box.currentText() self.renderer.set_service_theme(self.service_theme) Settings().setValue(self.main_window.service_manager_settings_section + '/service theme', self.service_theme) @@ -1250,7 +1245,6 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ The theme may have changed in the settings dialog so make sure the theme combo box is in the correct state. """ - log.debug('theme_change') visible = self.renderer.theme_level == ThemeLevel.Global self.theme_label.setVisible(visible) self.theme_combo_box.setVisible(visible) @@ -1260,7 +1254,6 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage Rebuild the service list as things have changed and a repaint is the easiest way to do this. """ self.application.set_busy_cursor() - log.debug('regenerate_service_items') # force reset of renderer as theme data has changed self.service_has_all_original_files = True if self.service_items: @@ -1412,7 +1405,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage 'is missing or inactive')) self.application.set_normal_cursor() - def remote_edit(self): + def remote_edit(self, field=None): """ Triggers a remote edit to a plugin to allow item to be edited. """ @@ -1423,7 +1416,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage if new_item: self.add_service_item(new_item, replace=True) - def create_custom(self): + def create_custom(self, field=None): """ Saves the current text item as a custom slide """ @@ -1543,7 +1536,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.renderer.set_service_theme(self.service_theme) self.regenerate_service_items() - def on_theme_change_action(self): + def on_theme_change_action(self, field=None): """ Handles theme change events """ diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index cdd763ee9..d220fb70d 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -51,7 +51,7 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): Initialise the settings form """ Registry().register('settings_form', self) - Registry().register_function('bootstrap_post_set_up', self.post_set_up) + Registry().register_function('bootstrap_post_set_up', self.bootstrap_post_set_up) super(SettingsForm, self).__init__(parent) self.processes = [] self.setupUi(self) @@ -117,7 +117,7 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): self.stacked_layout.widget(tabIndex).cancel() return QtGui.QDialog.reject(self) - def post_set_up(self): + def bootstrap_post_set_up(self): """ Run any post-setup code for the tabs on the form """ diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 9eb24d564..fc38228ef 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -42,22 +42,19 @@ from openlp.core.lib import FileDialog, ImageSource, OpenLPToolbar, get_text_fil check_item_selected, create_thumb, validate_thumb from openlp.core.lib.theme import ThemeXML, BackgroundType from openlp.core.lib.ui import critical_error_message_box, create_widget_action -from openlp.core.ui import FileRenameForm, ThemeForm, ThemeManagerHelper +from openlp.core.ui import FileRenameForm, ThemeForm from openlp.core.utils import delete_file, get_locale_key, get_filesystem_encoding -class ThemeManager(RegistryMixin, OpenLPMixin, QtGui.QWidget, ThemeManagerHelper): +class Ui_ThemeManager(object): """ - Manages the orders of Theme. + UI part of the Theme Manager """ - def __init__(self, parent=None): + def setup_ui(self, widget): """ - Constructor + Define the UI """ - super(ThemeManager, self).__init__(parent) - self.settings_section = 'themes' - self.theme_form = ThemeForm(self) - self.file_rename_form = FileRenameForm() + # start with the layout self.layout = QtGui.QVBoxLayout(self) self.layout.setSpacing(0) @@ -128,7 +125,18 @@ class ThemeManager(RegistryMixin, OpenLPMixin, QtGui.QWidget, ThemeManagerHelper # Signals self.theme_list_widget.doubleClicked.connect(self.change_global_from_screen) self.theme_list_widget.currentItemChanged.connect(self.check_list_state) - Registry().register_function('theme_update_global', self.change_global_from_tab) + + +class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): + """ + Manages the orders of Theme. + """ + def __init__(self, parent=None): + """ + Constructor + """ + super(ThemeManager, self).__init__(parent) + self.settings_section = 'themes' # Variables self.theme_list = [] self.old_background_image = None @@ -137,7 +145,7 @@ class ThemeManager(RegistryMixin, OpenLPMixin, QtGui.QWidget, ThemeManagerHelper """ process the bootstrap initialise setup request """ - self.log_debug('initialise called') + self.setup_ui(self) self.global_theme = Settings().value(self.settings_section + '/global theme') self.build_theme_path() self.load_first_time_themes() @@ -146,8 +154,21 @@ class ThemeManager(RegistryMixin, OpenLPMixin, QtGui.QWidget, ThemeManagerHelper """ process the bootstrap post setup request """ + self.theme_form = ThemeForm(self) + self.theme_form.path = self.path + self.file_rename_form = FileRenameForm() + Registry().register_function('theme_update_global', self.change_global_from_tab) self._push_themes() + def build_theme_path(self): + """ + Set up the theme path variables + """ + self.path = AppLocation.get_section_data_path(self.settings_section) + check_directory_exists(self.path) + self.thumb_path = os.path.join(self.path, 'thumbnails') + check_directory_exists(self.thumb_path) + def check_list_state(self, item, field=None): """ If Default theme selected remove delete button. diff --git a/openlp/core/ui/thememanagerhelper.py b/openlp/core/ui/thememanagerhelper.py deleted file mode 100644 index 641cf949f..000000000 --- a/openlp/core/ui/thememanagerhelper.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- 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 # -############################################################################### -""" -The Theme Controller helps manages adding, deleteing and modifying of themes. -""" -import os - -from openlp.core.common import AppLocation, check_directory_exists - - -class ThemeManagerHelper(object): - """ - Manages the non ui theme functions. - """ - def build_theme_path(self): - """ - Set up the theme path variables - """ - self.log_debug('build theme path called') - self.path = AppLocation.get_section_data_path(self.settings_section) - check_directory_exists(self.path) - self.thumb_path = os.path.join(self.path, 'thumbnails') - check_directory_exists(self.thumb_path) - self.theme_form.path = self.path \ No newline at end of file diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index c9ba6a47d..4dbe4c636 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -94,7 +94,7 @@ class MediaMediaItem(MediaManagerItem): self.reset_action.setToolTip(UiStrings().ResetLiveBG) self.automatic = UiStrings().Automatic self.display_type_label.setText(translate('MediaPlugin.MediaItem', 'Use Player:')) - self.rebuild_players() + #self.rebuild_players() def required_icons(self): """ @@ -112,9 +112,9 @@ class MediaMediaItem(MediaManagerItem): def add_end_header_bar(self): # Replace backgrounds do not work at present so remove functionality. self.replace_action = self.toolbar.add_toolbar_action('replace_action', icon=':/slides/slide_blank.png', - triggers=self.onReplaceClick) + triggers=self.on_replace_click) self.reset_action = self.toolbar.add_toolbar_action('reset_action', icon=':/system/system_close.png', - visible=False, triggers=self.onResetClick) + visible=False, triggers=self.on_reset_click) self.media_widget = QtGui.QWidget(self) self.media_widget.setObjectName('media_widget') self.display_layout = QtGui.QFormLayout(self.media_widget) @@ -128,16 +128,16 @@ class MediaMediaItem(MediaManagerItem): self.display_layout.addRow(self.display_type_label, self.display_type_combo_box) # Add the Media widget to the page layout. self.page_layout.addWidget(self.media_widget) - self.display_type_combo_box.currentIndexChanged.connect(self.overridePlayerChanged) + self.display_type_combo_box.currentIndexChanged.connect(self.override_player_changed) - def overridePlayerChanged(self, index): + def override_player_changed(self, index): player = get_media_players()[0] if index == 0: set_media_players(player) else: set_media_players(player, player[index-1]) - def onResetClick(self): + def on_reset_click(self): """ Called to reset the Live background with the media selected, """ @@ -150,12 +150,13 @@ class MediaMediaItem(MediaManagerItem): """ self.reset_action.setVisible(False) - def onReplaceClick(self): + def on_replace_click(self): """ Called to replace Live background with the media selected. """ if check_item_selected(self.list_view, - translate('MediaPlugin.MediaItem', 'You must select a media file to replace the background with.')): + translate('MediaPlugin.MediaItem', + 'You must select a media file to replace the background with.')): item = self.list_view.currentItem() filename = item.data(QtCore.Qt.UserRole) if os.path.exists(filename): @@ -168,14 +169,16 @@ class MediaMediaItem(MediaManagerItem): self.reset_action.setVisible(True) else: critical_error_message_box(UiStrings().LiveBGError, - translate('MediaPlugin.MediaItem', 'There was no display item to amend.')) + translate('MediaPlugin.MediaItem', + 'There was no display item to amend.')) else: critical_error_message_box(UiStrings().LiveBGError, - translate('MediaPlugin.MediaItem', - 'There was a problem replacing your background, the media file "%s" no longer exists.') % filename) + translate('MediaPlugin.MediaItem', + 'There was a problem replacing your background, ' + 'the media file "%s" no longer exists.') % filename) def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, - context=ServiceItemContext.Live): + context=ServiceItemContext.Live): """ Generate the slide data. Needs to be implemented by the plugin. """ @@ -211,16 +214,16 @@ class MediaMediaItem(MediaManagerItem): def initialise(self): self.list_view.clear() self.list_view.setIconSize(QtCore.QSize(88, 50)) - self.servicePath = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails') - check_directory_exists(self.servicePath) + self.service_path = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails') + check_directory_exists(self.service_path) self.load_list(Settings().value(self.settings_section + '/media files')) - self.populateDisplayTypes() + self.populate_display_types() def rebuild_players(self): """ Rebuild the tab in the media manager when changes are made in the settings. """ - self.populateDisplayTypes() + self.populate_display_types() self.on_new_file_masks = translate('MediaPlugin.MediaItem', 'Videos (%s);;Audio (%s);;%s (*)') % ( ' '.join(self.media_controller.video_extensions_list), ' '.join(self.media_controller.audio_extensions_list), UiStrings().AllFiles) @@ -228,25 +231,25 @@ class MediaMediaItem(MediaManagerItem): def display_setup(self): self.media_controller.setup_display(self.display_controller.preview_display, False) - def populateDisplayTypes(self): + def populate_display_types(self): """ Load the combobox with the enabled media players, allowing user to select a specific player if settings allow. """ - # block signals to avoid unnecessary overridePlayerChanged Signals while combo box creation + # block signals to avoid unnecessary override_player_changed Signals while combo box creation self.display_type_combo_box.blockSignals(True) self.display_type_combo_box.clear() - usedPlayers, overridePlayer = get_media_players() + used_players, override_player = get_media_players() media_players = self.media_controller.media_players - currentIndex = 0 - for player in usedPlayers: + current_index = 0 + for player in used_players: # load the drop down selection self.display_type_combo_box.addItem(media_players[player].original_name) - if overridePlayer == player: - currentIndex = len(self.display_type_combo_box) + if override_player == player: + current_index = len(self.display_type_combo_box) if self.display_type_combo_box.count() > 1: self.display_type_combo_box.insertItem(0, self.automatic) - self.display_type_combo_box.setCurrentIndex(currentIndex) - if overridePlayer: + self.display_type_combo_box.setCurrentIndex(current_index) + if override_player: self.media_widget.show() else: self.media_widget.hide() @@ -257,7 +260,7 @@ class MediaMediaItem(MediaManagerItem): Remove a media item from the list. """ if check_item_selected(self.list_view, - translate('MediaPlugin.MediaItem', 'You must select a media file to delete.')): + translate('MediaPlugin.MediaItem', 'You must select a media file to delete.')): row_list = [item.row() for item in self.list_view.selectedIndexes()] row_list.sort(reverse=True) for row in row_list: @@ -266,25 +269,25 @@ class MediaMediaItem(MediaManagerItem): def load_list(self, media, target_group=None): # Sort the media by its filename considering language specific characters. - media.sort(key=lambda filename: get_locale_key(os.path.split(str(filename))[1])) + media.sort(key=lambda file_name: get_locale_key(os.path.split(str(file_name))[1])) for track in media: track_info = QtCore.QFileInfo(track) if not os.path.exists(track): - filename = os.path.split(str(track))[1] - item_name = QtGui.QListWidgetItem(filename) + file_name = os.path.split(str(track))[1] + item_name = QtGui.QListWidgetItem(file_name) item_name.setIcon(ERROR_ICON) item_name.setData(QtCore.Qt.UserRole, track) elif track_info.isFile(): - filename = os.path.split(str(track))[1] - item_name = QtGui.QListWidgetItem(filename) - if '*.%s' % (filename.split('.')[-1].lower()) in self.media_controller.audio_extensions_list: + file_name = os.path.split(str(track))[1] + item_name = QtGui.QListWidgetItem(file_name) + if '*.%s' % (file_name.split('.')[-1].lower()) in self.media_controller.audio_extensions_list: item_name.setIcon(AUDIO_ICON) else: item_name.setIcon(VIDEO_ICON) item_name.setData(QtCore.Qt.UserRole, track) else: - filename = os.path.split(str(track))[1] - item_name = QtGui.QListWidgetItem(filename) + file_name = os.path.split(str(track))[1] + item_name = QtGui.QListWidgetItem(file_name) item_name.setIcon(build_icon(DVD_ICON)) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track) @@ -302,7 +305,7 @@ class MediaMediaItem(MediaManagerItem): media = [x for x in media if os.path.splitext(x)[1] in extension] return media - def search(self, string, showError): + def search(self, string, show_error): files = Settings().value(self.settings_section + '/media files') results = [] string = string.lower() diff --git a/tests/interfaces/openlp_core_ui/test_servicemanager.py b/tests/interfaces/openlp_core_ui/test_servicemanager.py index c42d41dfe..5e4d5dead 100644 --- a/tests/interfaces/openlp_core_ui/test_servicemanager.py +++ b/tests/interfaces/openlp_core_ui/test_servicemanager.py @@ -25,7 +25,6 @@ class TestServiceManager(TestCase): with patch('openlp.core.lib.PluginManager'): self.main_window = MainWindow() self.service_manager = Registry().get('service_manager') - self.event_was_called = False def tearDown(self): """ @@ -306,33 +305,17 @@ class TestServiceManager(TestCase): self.service_manager.auto_start_action.setVisible.assert_called_with(True), \ 'The action should be set visible.' - def click_on_new_service_test1(self): + def click_on_new_service_test(self): """ - Test the on_new_service event handler + Test the on_new_service event handler is called by the UI """ # GIVEN: An initial form - self.service_manager.setup_ui(self.service_manager) - - # WHEN displaying the UI and pressing cancel - new_service = self.service_manager.toolbar.actions['newService'] - self.service_manager.on_new_service_clicked = self.dummy_event() - new_service.trigger() - assert self.event_was_called is True, 'The on_new_service_clicked method should have been called' - - def click_on_new_service_test2(self): - """ - Test the on_new_service event handler - """ - # GIVEN: An initial form - self.service_manager.setup_ui(self.service_manager) - - # WHEN displaying the UI and pressing cancel - new_service = self.service_manager.toolbar.actions['newService'] mocked_event = MagicMock() self.service_manager.on_new_service_clicked = mocked_event - new_service.trigger() - print(mocked_event.call_count) - assert self.event_was_called == 1, 'The on_new_service_clicked method should have been called' + self.service_manager.setup_ui(self.service_manager) - def dummy_event(self): - self.event_was_called = True \ No newline at end of file + # WHEN displaying the UI and pressing cancel + new_service = self.service_manager.toolbar.actions['newService'] + new_service.trigger() + + assert mocked_event.call_count == 1, 'The on_new_service_clicked method should have been called once' diff --git a/tests/interfaces/openlp_core_ui/test_thememanagerhelper.py b/tests/interfaces/openlp_core_ui/test_thememanager.py similarity index 73% rename from tests/interfaces/openlp_core_ui/test_thememanagerhelper.py rename to tests/interfaces/openlp_core_ui/test_thememanager.py index d0456edc2..441159363 100644 --- a/tests/interfaces/openlp_core_ui/test_thememanagerhelper.py +++ b/tests/interfaces/openlp_core_ui/test_thememanager.py @@ -27,20 +27,23 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -Interface tests to test the thememanagerhelper class and related methods. +Interface tests to test the themeManager class and related methods. """ import os from unittest import TestCase from tempfile import mkstemp -from openlp.core.common import Settings -from openlp.core.ui import ThemeManagerHelper +from PyQt4 import QtGui, QtTest, QtCore + +from openlp.core.common import Registry, Settings +from openlp.core.lib import ScreenList +from openlp.core.ui import ThemeManager from tests.functional import patch, MagicMock -class TestThemeManagerHelper(TestCase): +class TestThemeManager(TestCase): """ - Test the functions in the ThemeManagerHelp[er module + Test the functions in the ThemeManager module """ def setUp(self): """ @@ -48,8 +51,8 @@ class TestThemeManagerHelper(TestCase): """ fd, self.ini_file = mkstemp('.ini') Settings().set_filename(self.ini_file) - self.helper = ThemeManagerHelper() - self.helper.settings_section = "themes" + Registry.create() + self.theme_manager = ThemeManager() def tearDown(self): """ @@ -58,29 +61,29 @@ class TestThemeManagerHelper(TestCase): os.unlink(self.ini_file) os.unlink(Settings().fileName()) - def test_initialise(self): + def initialise_test(self): """ - Test the thememanagerhelper initialise - basic test + Test the thememanager initialise - basic test """ # GIVEN: A new a call to initialise + self.theme_manager.build_theme_path = MagicMock() + self.theme_manager.load_first_time_themes = MagicMock() Settings().setValue('themes/global theme', 'my_theme') - self.helper.build_theme_path = MagicMock() - self.helper.load_first_time_themes = MagicMock() # WHEN: the initialistion is run - self.helper.initialise() + self.theme_manager.bootstrap_initialise() # THEN: - self.assertEqual(1, self.helper.build_theme_path.call_count, + self.assertEqual(1, self.theme_manager.build_theme_path.call_count, 'The function build_theme_path should have been called') - self.assertEqual(1, self.helper.load_first_time_themes.call_count, + self.assertEqual(1, self.theme_manager.load_first_time_themes.call_count, 'The function load_first_time_themes should have been called only once') - self.assertEqual(self.helper.global_theme, 'my_theme', + self.assertEqual(self.theme_manager.global_theme, 'my_theme', 'The global theme should have been set to my_theme') - def test_build_theme_path(self): + def build_theme_path_test(self): """ - Test the thememanagerhelper build_theme_path - basic test + Test the thememanager build_theme_path - basic test """ # GIVEN: A new a call to initialise with patch('openlp.core.common.applocation.check_directory_exists') as mocked_check_directory_exists: @@ -88,12 +91,12 @@ class TestThemeManagerHelper(TestCase): mocked_check_directory_exists.return_value = True Settings().setValue('themes/global theme', 'my_theme') - self.helper.theme_form = MagicMock() - #self.helper.load_first_time_themes = MagicMock() + self.theme_manager.theme_form = MagicMock() + self.theme_manager.load_first_time_themes = MagicMock() # WHEN: the build_theme_path is run - self.helper.build_theme_path() + self.theme_manager.build_theme_path() - # THEN: - self.assertEqual(self.helper.path, self.helper.theme_form.path, - 'The theme path and the main path should be the same value') \ No newline at end of file + # THEN: + self.assertEqual(self.theme_manager.path, self.theme_manager.theme_form.path, + 'The theme path and the main path should be the same value') From 259b2b074f6f0a5d0c1c2f43b3d920709018814c Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 31 Dec 2013 21:02:35 +0000 Subject: [PATCH 16/41] Fix widget --- openlp/core/ui/servicemanager.py | 10 ++++---- openlp/core/ui/thememanager.py | 6 ++--- .../openlp_core_ui/test_thememanager.py | 23 +++++++++++++++---- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index d492355e9..64184f225 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -106,11 +106,11 @@ class Ui_ServiceManager(object): Define the UI """ # start with the layout - self.layout = QtGui.QVBoxLayout(self) + self.layout = QtGui.QVBoxLayout(widget) self.layout.setSpacing(0) self.layout.setMargin(0) # Create the top toolbar - self.toolbar = OpenLPToolbar(self) + self.toolbar = OpenLPToolbar(widget) self.toolbar.add_toolbar_action('newService', text=UiStrings().NewService, icon=':/general/general_new.png', tooltip=UiStrings().CreateService, triggers=self.on_new_service_clicked) self.toolbar.add_toolbar_action('openService', text=UiStrings().OpenService, @@ -122,7 +122,7 @@ class Ui_ServiceManager(object): tooltip=translate('OpenLP.ServiceManager', 'Save this service.'), triggers=self.decide_save_method) self.toolbar.addSeparator() - self.theme_label = QtGui.QLabel('%s:' % UiStrings().Theme, self) + self.theme_label = QtGui.QLabel('%s:' % UiStrings().Theme, widget) self.theme_label.setMargin(3) self.theme_label.setObjectName('theme_label') self.toolbar.add_toolbar_widget(self.theme_label) @@ -135,7 +135,7 @@ class Ui_ServiceManager(object): self.toolbar.setObjectName('toolbar') self.layout.addWidget(self.toolbar) # Create the service manager list - self.service_manager_list = ServiceManagerList(self) + self.service_manager_list = ServiceManagerList(widget) self.service_manager_list.setEditTriggers( QtGui.QAbstractItemView.CurrentChanged | QtGui.QAbstractItemView.DoubleClicked | @@ -153,7 +153,7 @@ class Ui_ServiceManager(object): self.service_manager_list.__class__.dropEvent = self.drop_event self.layout.addWidget(self.service_manager_list) # Add the bottom toolbar - self.order_toolbar = OpenLPToolbar(self) + self.order_toolbar = OpenLPToolbar(widget) action_list = ActionList.get_instance() action_list.add_category(UiStrings().Service, CategoryOrder.standard_toolbar) self.service_manager_list.move_top = self.order_toolbar.add_toolbar_action( diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index fc38228ef..845f8f7e9 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -56,11 +56,11 @@ class Ui_ThemeManager(object): """ # start with the layout - self.layout = QtGui.QVBoxLayout(self) + self.layout = QtGui.QVBoxLayout(widget) self.layout.setSpacing(0) self.layout.setMargin(0) self.layout.setObjectName('layout') - self.toolbar = OpenLPToolbar(self) + self.toolbar = OpenLPToolbar(widget) self.toolbar.setObjectName('toolbar') self.toolbar.add_toolbar_action('newTheme', text=UiStrings().NewTheme, icon=':/themes/theme_new.png', @@ -93,7 +93,7 @@ class Ui_ThemeManager(object): self.theme_widget = QtGui.QWidgetAction(self.toolbar) self.theme_widget.setObjectName('theme_widget') # create theme manager list - self.theme_list_widget = QtGui.QListWidget(self) + self.theme_list_widget = QtGui.QListWidget(widget) self.theme_list_widget.setAlternatingRowColors(True) self.theme_list_widget.setIconSize(QtCore.QSize(88, 50)) self.theme_list_widget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) diff --git a/tests/interfaces/openlp_core_ui/test_thememanager.py b/tests/interfaces/openlp_core_ui/test_thememanager.py index 441159363..8b4b8be74 100644 --- a/tests/interfaces/openlp_core_ui/test_thememanager.py +++ b/tests/interfaces/openlp_core_ui/test_thememanager.py @@ -33,10 +33,7 @@ import os from unittest import TestCase from tempfile import mkstemp -from PyQt4 import QtGui, QtTest, QtCore - from openlp.core.common import Registry, Settings -from openlp.core.lib import ScreenList from openlp.core.ui import ThemeManager from tests.functional import patch, MagicMock @@ -98,5 +95,21 @@ class TestThemeManager(TestCase): self.theme_manager.build_theme_path() # THEN: - self.assertEqual(self.theme_manager.path, self.theme_manager.theme_form.path, - 'The theme path and the main path should be the same value') + assert self.theme_manager.thumb_path.startswith(self.theme_manager.path) is True, \ + 'The thumb path and the main path should start with the same value' + + def click_on_new_theme_test(self): + """ + Test the on_add_theme event handler is called by the UI + """ + # GIVEN: An initial form + Settings().setValue('themes/global theme', 'my_theme') + mocked_event = MagicMock() + self.theme_manager.on_add_theme = mocked_event + self.theme_manager.setup_ui(self.theme_manager) + + # WHEN displaying the UI and pressing cancel + new_theme = self.theme_manager.toolbar.actions['newTheme'] + new_theme.trigger() + + assert mocked_event.call_count == 1, 'The on_add_theme method should have been called once' From 2755aad4c65f609b70d1cfe52d4b3c8b76806279 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 1 Jan 2014 09:33:07 +0000 Subject: [PATCH 17/41] More PEP 8 changes --- openlp/core/lib/__init__.py | 72 ++++++------- openlp/core/ui/servicemanager.py | 116 ++++++++++++++------- openlp/core/ui/thememanager.py | 92 ++++++++++------ openlp/plugins/alerts/alertsplugin.py | 37 +++++-- openlp/plugins/alerts/forms/alertdialog.py | 15 ++- openlp/plugins/alerts/forms/alertform.py | 46 ++++---- openlp/plugins/alerts/lib/alertsmanager.py | 6 +- openlp/plugins/alerts/lib/alertstab.py | 25 +++++ openlp/plugins/alerts/lib/db.py | 6 +- 9 files changed, 266 insertions(+), 149 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index b5f2b1cee..549f0879c 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -89,8 +89,8 @@ def get_text_file_string(text_file): returns False. If there is an error loading the file or the content can't be decoded then the function will return None. - ``textfile`` - The name of the file. + :param text_file: The name of the file. + :return The file as a single string """ if not os.path.isfile(text_file): return False @@ -114,8 +114,8 @@ def str_to_bool(string_value): """ Convert a string version of a boolean into a real boolean. - ``string_value`` - The string value to examine and convert to a boolean type. + :param string_value: The string value to examine and convert to a boolean type. + :return The correct boolean value """ if isinstance(string_value, bool): return string_value @@ -127,9 +127,10 @@ def build_icon(icon): Build a QIcon instance from an existing QIcon, a resource location, or a physical file location. If the icon is a QIcon instance, that icon is simply returned. If not, it builds a QIcon instance from the resource or file name. - ``icon`` + :param icon: The icon to build. This can be a QIcon, a resource string in the form ``:/resource/file.png``, or a file location like ``/path/to/file.png``. However, the **recommended** way is to specify a resource string. + :return The build icon. """ button_icon = QtGui.QIcon() if isinstance(icon, QtGui.QIcon): @@ -148,8 +149,7 @@ def image_to_byte(image): """ Resize an image to fit on the current screen for the web and returns it as a byte stream. - ``image`` - The image to converted. + :param image: The image to converted. """ log.debug('image_to_byte - start') byte_array = QtCore.QByteArray() @@ -166,18 +166,12 @@ def create_thumb(image_path, thumb_path, return_icon=True, size=None): """ Create a thumbnail from the given image path and depending on ``return_icon`` it returns an icon from this thumb. - ``image_path`` - The image file to create the icon from. - - ``thumb_path`` - The filename to save the thumbnail to. - - ``return_icon`` - States if an icon should be build and returned from the thumb. Defaults to ``True``. - - ``size`` - Allows to state a own size (QtCore.QSize) to use. Defaults to ``None``, which means that a default height of 88 - is used. + :param image_path: The image file to create the icon from. + :param thumb_path: The filename to save the thumbnail to. + :param return_icon: States if an icon should be build and returned from the thumb. Defaults to ``True``. + :param size: Allows to state a own size (QtCore.QSize) to use. Defaults to ``None``, which means that a default + height of 88 is used. + :return The final icon. """ ext = os.path.splitext(thumb_path)[1].lower() reader = QtGui.QImageReader(image_path) @@ -201,11 +195,9 @@ def validate_thumb(file_path, thumb_path): Validates whether an file's thumb still exists and if is up to date. **Note**, you must **not** call this function, before checking the existence of the file. - ``file_path`` - The path to the file. The file **must** exist! - - ``thumb_path`` - The path to the thumb. + :param file_path: The path to the file. The file **must** exist! + :param thumb_path: The path to the thumb. + :return True, False if the image has changed since the thumb was created. """ if not os.path.exists(thumb_path): return False @@ -218,19 +210,12 @@ def resize_image(image_path, width, height, background='#000000'): """ Resize an image to fit on the current screen. - ``image_path`` - The path to the image to resize. - - ``width`` - The new image width. - - ``height`` - The new image height. - - ``background`` - The background colour. Defaults to black. - DO NOT REMOVE THE DEFAULT BACKGROUND VALUE! + + :param image_path: The path to the image to resize. + :param width: The new image width. + :param height: The new image height. + :param background: The background colour. Defaults to black. """ log.debug('resize_image - start') reader = QtGui.QImageReader(image_path) @@ -265,11 +250,8 @@ def check_item_selected(list_widget, message): """ Check if a list item is selected so an action may be performed on it - ``list_widget`` - The list to check for selected items - - ``message`` - The message to give the user if no item is selected + :param list_widget: The list to check for selected items + :param message: The message to give the user if no item is selected """ if not list_widget.selectedIndexes(): QtGui.QMessageBox.information(list_widget.parent(), @@ -281,6 +263,8 @@ def check_item_selected(list_widget, message): def clean_tags(text): """ Remove Tags from text for display + + :param text: Text to be cleaned """ text = text.replace('
', '\n') text = text.replace('{br}', '\n') @@ -294,6 +278,8 @@ def clean_tags(text): def expand_tags(text): """ Expand tags HTML for display + + :param text: The text to be expanded. """ for tag in FormattingTags.get_html_tags(): text = text.replace(tag['start tag'], tag['start html']) @@ -304,11 +290,11 @@ def expand_tags(text): def create_separated_list(string_list): """ Returns a string that represents a join of a list of strings with a localized separator. This function corresponds + to QLocale::createSeparatedList which was introduced in Qt 4.8 and implements the algorithm from http://www.unicode.org/reports/tr35/#ListPatterns - ``string_list`` - List of unicode strings + :param string_list: List of unicode strings """ if LooseVersion(Qt.PYQT_VERSION_STR) >= LooseVersion('4.9') and \ LooseVersion(Qt.qVersion()) >= LooseVersion('4.8'): diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 64184f225..f131a20c7 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -63,6 +63,7 @@ class ServiceManagerList(QtGui.QTreeWidget): def keyPressEvent(self, event): """ Capture Key press and respond accordingly. + :param event: """ if isinstance(event, QtGui.QKeyEvent): # here accept the event and do something @@ -83,6 +84,7 @@ class ServiceManagerList(QtGui.QTreeWidget): """ Drag and drop event does not care what data is selected as the recipient will use events to request the data move just tell it what plugin to call + :param event: """ if event.buttons() != QtCore.Qt.LeftButton: event.ignore() @@ -104,6 +106,7 @@ class Ui_ServiceManager(object): def setup_ui(self, widget): """ Define the UI + :param widget: """ # start with the layout self.layout = QtGui.QVBoxLayout(widget) @@ -298,8 +301,7 @@ class Ui_ServiceManager(object): """ Accept Drag events - ``event`` - Handle of the event passed + :param event: Handle of the event passed """ event.accept() @@ -327,6 +329,9 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.service_has_all_original_files = True def bootstrap_initialise(self): + """ + To be called as part of initialisation + """ self.setup_ui(self) # Need to use event as called across threads and UI is updated QtCore.QObject.connect(self, QtCore.SIGNAL('servicemanager_set_item'), self.on_set_item) @@ -342,6 +347,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def set_modified(self, modified=True): """ Setter for property "modified". Sets whether or not the current service has been modified. + + :param modified: Indicates if the service has new or removed items. Used to trigger a remote update. """ if modified: self.service_id += 1 @@ -358,6 +365,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def set_file_name(self, file_name): """ Setter for service file. + + :param file_name: The service file name """ self._file_name = str(file_name) self.main_window.set_service_modified(self.is_modified(), self.short_file_name()) @@ -387,8 +396,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Adds Suffixes supported to the master list. Called from Plugins. - ``suffix_list`` - New Suffix's to be supported + :param suffix_list: New Suffix's to be supported """ for suffix in suffix_list: if not suffix in self.suffixes: @@ -397,6 +405,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_new_service_clicked(self, field=None): """ Create a new service. + :param field: """ if self.is_modified(): result = self.save_modified_service() @@ -411,8 +420,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Loads the service file and saves the existing one it there is one unchanged. - ``load_file`` - The service file to the loaded. Will be None is from menu so selection will be required. + :param load_file: The service file to the loaded. Will be None is from menu so selection will be required. """ if self.is_modified(): result = self.save_modified_service() @@ -450,6 +458,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_recent_service_clicked(self, field=None): """ Load a recent file as the service triggered by mainwindow recent service list. + :param field: """ sender = self.sender() self.load_file(sender.data()) @@ -484,7 +493,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage path, file_name = os.path.split(path_file_name) base_name = os.path.splitext(file_name)[0] service_file_name = '%s.osj' % base_name - self.log_debug('ServiceManager.save_file - %s', path_file_name) + self.log_debug('ServiceManager.save_file - %s' % path_file_name) Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', path) service = [] write_list = [] @@ -564,7 +573,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage shutil.copy(audio_from, save_file) zip_file.write(audio_from, audio_to) except IOError: - self.log_exception('Failed to save service to disk: %s', temp_file_name) + self.log_exception('Failed to save service to disk: %s' % temp_file_name) self.main_window.error_message(translate('OpenLP.ServiceManager', 'Error Saving File'), translate('OpenLP.ServiceManager', 'There was an error saving your file.')) success = False @@ -686,6 +695,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def decide_save_method(self, field=None): """ Determine which type of save method to use. + :param field: """ if not self.file_name(): return self.save_file_as() @@ -697,6 +707,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def load_file(self, file_name): """ Load an existing service file + :param file_name: """ if not file_name: return False @@ -719,7 +730,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage os_file = ucs_file.replace('/', os.path.sep) if not os_file.startswith('audio'): os_file = os.path.split(os_file)[1] - self.log_debug('Extract file: %s', os_file) + self.log_debug('Extract file: %s' % os_file) zip_info.filename = os_file zip_file.extract(zip_info, self.service_path) if os_file.endswith('osj') or os_file.endswith('osd'): @@ -795,6 +806,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def context_menu(self, point): """ The Right click context menu from the Serviceitem list + + :param point: The location of the cursor. """ item = self.service_manager_list.itemAt(point) if item is None: @@ -861,6 +874,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_service_item_note_form(self, field=None): """ Allow the service note to be edited + :param field: """ item = self.find_service_item()[0] self.service_note_form.text_edit.setPlainText(self.service_items[item]['service_item'].notes) @@ -872,6 +886,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_start_time_form(self, field=None): """ Opens a dialog to type in service item notes. + :param field: """ item = self.find_service_item()[0] self.start_time_form.item = self.service_items[item] @@ -881,6 +896,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def toggle_auto_play_slides_once(self, field=None): """ Toggle Auto play slide once. Inverts auto play once option for the item + :param field: """ item = self.find_service_item()[0] service_item = self.service_items[item]['service_item'] @@ -896,6 +912,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def toggle_auto_play_slides_loop(self, field=None): """ Toggle Auto play slide loop. + :param field: """ item = self.find_service_item()[0] service_item = self.service_items[item]['service_item'] @@ -911,6 +928,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_timed_slide_interval(self, field=None): """ Shows input dialog for enter interval in seconds for delay + :param field: """ item = self.find_service_item()[0] service_item = self.service_items[item]['service_item'] @@ -944,6 +962,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_service_item_edit_form(self, field=None): """ Opens a dialog to edit the service item and update the service display if changes are saved. + :param field: """ item = self.find_service_item()[0] self.service_item_edit_form.set_service_item(self.service_items[item]['service_item']) @@ -956,11 +975,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage Called by the SlideController to request a preview item be made live and allows the next preview to be updated if relevant. - ``unique_identifier`` - Reference to the service_item - - ``row`` - individual row number + :param unique_identifier: Reference to the service_item + :param row: individual row number """ for sitem in self.service_items: if sitem['service_item'].unique_identifier == unique_identifier: @@ -991,9 +1007,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Called by the SlideController to select the previous service item. - ``last_slide`` - Is this the last slide in the service_item - + :param last_slide: Is this the last slide in the service_item. """ if not self.service_manager_list.selected_items(): return @@ -1024,12 +1038,17 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_set_item(self, message, field=None): """ Called by a signal to select a specific item and make it live usually from remote. + + :param field: + :param message: The data passed in from a remove message """ self.set_item(int(message)) def set_item(self, index): """ Makes a specific item in the service live. + + :param index: The index of the service item list to be actioned. """ if 0 >= index < self.service_manager_list.topLevelItemCount(): item = self.service_manager_list.topLevelItem(index) @@ -1059,6 +1078,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_collapse_all(self, field=None): """ Collapse all the service items. + :param field: """ for item in self.service_items: item['expanded'] = False @@ -1067,6 +1087,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def collapsed(self, item): """ Record if an item is collapsed. Used when repainting the list to get the correct state. + + :param item: The service item to be checked """ pos = item.data(0, QtCore.Qt.UserRole) self.service_items[pos - 1]['expanded'] = False @@ -1074,6 +1096,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_expand_all(self, field=None): """ Collapse all the service items. + :param field: """ for item in self.service_items: item['expanded'] = True @@ -1082,6 +1105,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def expanded(self, item): """ Record if an item is collapsed. Used when repainting the list to get the correct state. + + :param item: The service item to be checked """ pos = item.data(0, QtCore.Qt.UserRole) self.service_items[pos - 1]['expanded'] = True @@ -1089,6 +1114,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_service_top(self, field=None): """ Move the current ServiceItem to the top of the list. + :param field: """ item, child = self.find_service_item() if item < len(self.service_items) and item != -1: @@ -1101,6 +1127,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_service_up(self, field=None): """ Move the current ServiceItem one position up in the list. + :param field: """ item, child = self.find_service_item() if item > 0: @@ -1113,6 +1140,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_service_down(self, field=None): """ Move the current ServiceItem one position down in the list. + :param field: """ item, child = self.find_service_item() if item < len(self.service_items) and item != -1: @@ -1125,6 +1153,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_service_end(self, field=None): """ Move the current ServiceItem to the bottom of the list. + :param field: """ item, child = self.find_service_item() if item < len(self.service_items) and item != -1: @@ -1137,6 +1166,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_delete_from_service(self, field=None): """ Remove the current ServiceItem from the list. + :param field: """ item = self.find_service_item()[0] if item != -1: @@ -1149,11 +1179,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage Clear the existing service list and prepaint all the items. This is used when moving items as the move takes place in a supporting list, and when regenerating all the items due to theme changes. - ``service_item`` - The item which changed. (int) - - ``service_item_child`` - The child of the ``service_item``, which will be selected. (int) + :param service_item: The item which changed. (int) + :param service_item_child: The child of the ``service_item``, which will be selected. (int) """ # Correct order of items in array count = 1 @@ -1235,6 +1262,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_theme_combo_box_selected(self, current_index): """ Set the theme for the current service. + + :param current_index: The combo box index for the selected item """ self.service_theme = self.theme_combo_box.currentText() self.renderer.set_service_theme(self.service_theme) @@ -1252,6 +1281,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def regenerate_service_items(self, changed=False): """ Rebuild the service list as things have changed and a repaint is the easiest way to do this. + + :param changed: True if the list has changed for new / removed items. False for a theme change. """ self.application.set_busy_cursor() # force reset of renderer as theme data has changed @@ -1288,6 +1319,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def replace_service_item(self, new_item): """ Using the service item passed replace the one with the same edit id if found. + + :param new_item: a new service item to up date an existing one. """ for item_count, item in enumerate(self.service_items): if item['service_item'].edit_id == new_item.edit_id and item['service_item'].name == new_item.name: @@ -1302,29 +1335,30 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Add a Service item to the list - ``item`` - Service Item to be added - - ``expand`` - Override the default expand settings. (Tristate) + :param item: Service Item to be added + :param rebuild: Do we need to rebuild the live display (Default False) + :param expand: Override the default expand settings. (Tristate) + :param replace: Is the service item a replacement (Default False) + :param repaint: Do we need to repaint the service item list (Default True) + :param selected: Has the item been selected (Default False) """ # if not passed set to config value if expand is None: expand = Settings().value('advanced/expand service item') item.from_service = True if replace: - sitem, child = self.find_service_item() - item.merge(self.service_items[sitem]['service_item']) - self.service_items[sitem]['service_item'] = item - self.repaint_service_list(sitem, child) + s_item, child = self.find_service_item() + item.merge(self.service_items[s_item]['service_item']) + self.service_items[s_item]['service_item'] = item + self.repaint_service_list(s_item, child) self.live_controller.replace_service_manager_item(item) else: item.render() # nothing selected for dnd if self.drop_position == 0: if isinstance(item, list): - for inditem in item: - self.service_items.append({'service_item': inditem, + for ind_item in item: + self.service_items.append({'service_item': ind_item, 'order': len(self.service_items) + 1, 'expanded': expand, 'selected': selected}) else: @@ -1371,6 +1405,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_make_live(self, field=None): """ Send the current item to the Live slide controller but triggered by a tablewidget click event. + :param field: """ self.make_live() @@ -1378,8 +1413,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Send the current item to the Live slide controller - ``row`` - Row number to be displayed if from preview. -1 is passed if the value is not set + :param row: Row number to be displayed if from preview. -1 is passed if the value is not set """ item, child = self.find_service_item() # No items in service @@ -1408,6 +1442,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def remote_edit(self, field=None): """ Triggers a remote edit to a plugin to allow item to be edited. + :param field: """ item = self.find_service_item()[0] if self.service_items[item]['service_item'].is_capable(ItemCapabilities.CanEdit): @@ -1419,6 +1454,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def create_custom(self, field=None): """ Saves the current text item as a custom slide + :param field: """ item = self.find_service_item()[0] Registry().execute('custom_create_from_service', self.service_items[item]['service_item']) @@ -1452,8 +1488,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage Receive drop event and trigger an internal event to get the plugins to build and push the correct service item. The drag event payload carries the plugin name - ``event`` - Handle of the event pint passed + :param event: Handle of the event passed """ link = event.mimeData() if link.hasUrls(): @@ -1512,8 +1547,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Called from ThemeManager when the Themes have changed - ``theme_list`` - A list of current themes to be displayed + :param theme_list: A list of current themes to be displayed """ self.theme_combo_box.clear() self.theme_menu.clear() @@ -1539,6 +1573,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def on_theme_change_action(self, field=None): """ Handles theme change events + + :param field: """ theme = self.sender().objectName() # No object name means that the "Default" theme is supposed to be used. @@ -1551,6 +1587,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def _get_parent_item_data(self, item): """ Finds and returns the parent item for any item + + :param item: The service item list item to be checked. """ parent_item = item.parent() if parent_item is None: diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 845f8f7e9..d9d798b67 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -53,8 +53,8 @@ class Ui_ThemeManager(object): def setup_ui(self, widget): """ Define the UI + :param widget: The screen object the the dialog is to be attached to. """ - # start with the layout self.layout = QtGui.QVBoxLayout(widget) self.layout.setSpacing(0) @@ -173,6 +173,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ If Default theme selected remove delete button. Note for some reason a dummy field is required. Nothing is passed! + + :param field: + :param item: Service Item to process """ if item is None: return @@ -186,8 +189,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def context_menu(self, point): """ - Build the Right Click Context menu and set state depending on - the type of theme. + Build the Right Click Context menu and set state depending on the type of theme. + + :param point: The position of the mouse so the correct item can be found. """ item = self.theme_list_widget.itemAt(point) if item is None: @@ -221,8 +225,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def change_global_from_screen(self, index=-1): """ - Change the global theme when a theme is double clicked upon in the - Theme Manager list + Change the global theme when a theme is double clicked upon in the Theme Manager list. + + :param index: """ selected_row = self.theme_list_widget.currentRow() for count in range(0, self.theme_list_widget.count()): @@ -242,8 +247,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def on_add_theme(self, field=None): """ - Loads a new theme with the default settings and then launches the theme - editing form for the user to make their customisations. + Loads a new theme with the default settings and then launches the theme editing form for the user to make + their customisations. + :param field: """ theme = ThemeXML() theme.set_default_header_footer() @@ -254,6 +260,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def on_rename_theme(self, field=None): """ Renames an existing theme to a new name + :param field: """ if self._validate_theme_action(translate('OpenLP.ThemeManager', 'You must select a theme to rename.'), translate('OpenLP.ThemeManager', 'Rename Confirmation'), @@ -278,6 +285,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def on_copy_theme(self, field=None): """ Copies an existing theme to a new name + :param field: """ item = self.theme_list_widget.currentItem() old_theme_name = item.data(QtCore.Qt.UserRole) @@ -292,6 +300,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def clone_theme_data(self, theme_data, new_theme_name): """ Takes a theme and makes a new copy of it as well as saving it. + + :param theme_data: The theme to be used + :param new_theme_name: The new theme name to save the data to """ save_to = None save_from = None @@ -307,6 +318,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ Loads the settings for the theme that is to be edited and launches the theme editing form so the user can make their changes. + :param field: """ if check_item_selected(self.theme_list_widget, translate('OpenLP.ThemeManager', 'You must select a theme to edit.')): @@ -322,7 +334,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def on_delete_theme(self, field=None): """ - Delete a theme + Delete a theme triggered by the UI. + :param field: """ if self._validate_theme_action(translate('OpenLP.ThemeManager', 'You must select a theme to delete.'), translate('OpenLP.ThemeManager', 'Delete Confirmation'), @@ -341,8 +354,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ Delete a theme. - ``theme`` - The theme to delete. + :param theme: The theme to delete. """ self.theme_list.remove(theme) thumb = '%s.png' % theme @@ -358,6 +370,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def on_export_theme(self, field=None): """ Export the theme in a zip file + :param field: """ item = self.theme_list_widget.currentItem() if item is None: @@ -399,6 +412,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ Opens a file dialog to select the theme file(s) to import before attempting to extract OpenLP themes from those files. This process will load both OpenLP version 1 and version 2 themes. + :param field: """ files = FileDialog.getOpenFileNames(self, translate('OpenLP.ThemeManager', 'Select Theme Import File'), @@ -483,8 +497,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ Returns a theme object from an XML file - ``theme_name`` - Name of the theme to load from file + :param theme_name: Name of the theme to load from file + :return The theme object. """ self.log_debug('get theme data for theme %s' % theme_name) xml_file = os.path.join(self.path, str(theme_name), str(theme_name) + '.xml') @@ -498,6 +512,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def over_write_message_box(self, theme_name): """ Display a warning box to the user that a theme already exists + :param theme_name: Name of the theme. + :return Confirm if the theme is to be overeritten. """ ret = QtGui.QMessageBox.question(self, translate('OpenLP.ThemeManager', 'Theme Already Exists'), translate('OpenLP.ThemeManager', @@ -510,11 +526,12 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def unzip_theme(self, file_name, directory): """ - Unzip the theme, remove the preview file if stored - Generate a new preview file. Check the XML theme version and upgrade if - necessary. + Unzip the theme, remove the preview file if stored. Generate a new preview file. Check the XML theme version + and upgrade if necessary. + :param file_name: + :param directory: """ - self.log_debug('Unzipping theme %s', file_name) + self.log_debug('Unzipping theme %s' % file_name) file_name = str(file_name) theme_zip = None out_file = None @@ -583,8 +600,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ Check if theme already exists and displays error message - ``theme_name`` - Name of the Theme to test + :param theme_name: Name of the Theme to test + :return True or False if theme exists """ theme_dir = os.path.join(self.path, theme_name) if os.path.exists(theme_dir): @@ -596,7 +613,11 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def save_theme(self, theme, image_from, image_to): """ - Called by thememaintenance Dialog to save the theme and to trigger the reload of the theme list + Called by theme maintenance Dialog to save the theme and to trigger the reload of the theme list + + :param theme: The theme data object. + :param image_from: Where the theme image is currently located. + :param image_to: Where the Theme Image is to be saved to """ self._write_theme(theme, image_from, image_to) if theme.background_type == BackgroundType.to_string(BackgroundType.Image): @@ -608,6 +629,10 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def _write_theme(self, theme, image_from, image_to): """ Writes the theme to the disk and handles the background image if necessary + + :param theme: The theme data object. + :param image_from: Where the theme image is currently located. + :param image_to: Where the Theme Image is to be saved to """ name = theme.theme_name theme_pretty_xml = theme.extract_formatted_xml() @@ -637,6 +662,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def generate_and_save_image(self, name, theme): """ Generate and save a preview image + + :param name: The name of the theme. + :param theme: The theme data object. """ frame = self.generate_image(theme) sample_path_name = os.path.join(self.path, name + '.png') @@ -661,11 +689,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ Call the renderer to build a Sample Image - ``theme_data`` - The theme to generated a preview for. - - ``force_page`` - Flag to tell message lines per page need to be generated. + :param theme_data: The theme to generated a preview for. + :param force_page: Flag to tell message lines per page need to be generated. """ return self.renderer.generate_preview(theme_data, force_page) @@ -673,26 +698,33 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ Return an image representing the look of the theme - ``theme`` - The theme to return the image for + :param theme: The theme to return the image for. """ return os.path.join(self.path, theme + '.png') - def _create_theme_from_xml(self, theme_xml, path): + def _create_theme_from_xml(self, theme_xml, image_path): """ Return a theme object using information parsed from XML - ``theme_xml`` - The XML data to load into the theme + :param theme_xml: The Theme data object. + :param image_path: Where the theme image is stored + :return Theme data. """ theme = ThemeXML() theme.parse(theme_xml) - theme.extend_image_filename(path) + theme.extend_image_filename(image_path) return theme def _validate_theme_action(self, select_text, confirm_title, confirm_text, test_plugin=True, confirm=True): """ Check to see if theme has been selected and the destructive action is allowed. + + :param select_text: Text for message box if no item selected. + :param confirm_title: Confirm message title to be displayed. + :param confirm_text: Confirm message text to be displayed. + :param test_plugin: Do we check the plugins for theme usage. + :param confirm: Do we display a confirm box before run checks. + :return True or False depending on the validity. """ self.global_theme = Settings().value(self.settings_section + '/global theme') if check_item_selected(self.theme_list_widget, select_text): diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 8e80871b9..97ca0f60b 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -127,9 +127,15 @@ __default_settings__ = { class AlertsPlugin(Plugin): + """ + The Alerts Plugin Class + """ log.info('Alerts Plugin loaded') def __init__(self): + """ + Class __init__ method + """ super(AlertsPlugin, self).__init__('alerts', __default_settings__, settings_tab_class=AlertsTab) self.weight = -3 self.icon_path = ':/plugins/plugin_alerts.png' @@ -142,17 +148,21 @@ class AlertsPlugin(Plugin): """ Give the alerts plugin the opportunity to add items to the **Tools** menu. - ``tools_menu`` + :param tools_menu: The actual **Tools** menu item, so that your actions can use it as their parent. """ log.info('add tools menu') self.tools_alert_item = create_action(tools_menu, 'toolsAlertItem', - text=translate('AlertsPlugin', '&Alert'), icon=':/plugins/plugin_alerts.png', - statustip=translate('AlertsPlugin', 'Show an alert message.'), - visible=False, can_shortcuts=True, triggers=self.on_alerts_trigger) + text=translate('AlertsPlugin', '&Alert'), + icon=':/plugins/plugin_alerts.png', + statustip=translate('AlertsPlugin', 'Show an alert message.'), + visible=False, can_shortcuts=True, triggers=self.on_alerts_trigger) self.main_window.tools_menu.addAction(self.tools_alert_item) def initialise(self): + """ + Initialise plugin + """ log.info('Alerts Initialising') super(AlertsPlugin, self).initialise() self.tools_alert_item.setVisible(True) @@ -171,16 +181,27 @@ class AlertsPlugin(Plugin): action_list.remove_action(self.tools_alert_item, 'Tools') def toggle_alerts_state(self): + """ + Switch the alerts state + """ self.alerts_active = not self.alerts_active Settings().setValue(self.settings_section + '/active', self.alerts_active) def on_alerts_trigger(self): + """ + Start of the Alerts dialog triggered from the main menu. + """ self.alert_form.load_list() self.alert_form.exec_() def about(self): + """ + Plugin Alerts about method + + :return: text + """ about_text = translate('AlertsPlugin', 'Alerts Plugin' - '
The alert plugin controls the displaying of nursery alerts on the display screen.') + '
The alert plugin controls the displaying of alerts on the display screen.') return about_text def set_plugin_text_strings(self): @@ -209,7 +230,7 @@ class AlertsPlugin(Plugin): """ align = VerticalType.Names[self.settings_tab.location] return CSS % (align, self.settings_tab.font_face, self.settings_tab.font_size, self.settings_tab.font_color, - self.settings_tab.background_color) + self.settings_tab.background_color) def get_display_html(self): """ @@ -226,5 +247,5 @@ class AlertsPlugin(Plugin): """ align = VerticalType.Names[self.settings_tab.location] frame.evaluateJavaScript('update_css("%s", "%s", "%s", "%s", "%s")' % - (align, self.settings_tab.font_face, self.settings_tab.font_size, - self.settings_tab.font_color, self.settings_tab.background_color)) + (align, self.settings_tab.font_face, self.settings_tab.font_size, + self.settings_tab.font_color, self.settings_tab.background_color)) diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py index e5d1cddab..a4596d9ea 100644 --- a/openlp/plugins/alerts/forms/alertdialog.py +++ b/openlp/plugins/alerts/forms/alertdialog.py @@ -36,6 +36,11 @@ from openlp.core.lib.ui import create_button, create_button_box class Ui_AlertDialog(object): def setupUi(self, alert_dialog): + """ + Setup the Alert UI dialog + + :param alert_dialog: + """ alert_dialog.setObjectName('alert_dialog') alert_dialog.resize(400, 300) alert_dialog.setWindowIcon(build_icon(':/icon/openlp-logo-16x16.png')) @@ -72,20 +77,24 @@ class Ui_AlertDialog(object): self.save_button.setObjectName('save_button') self.manage_button_layout.addWidget(self.save_button) self.delete_button = create_button(alert_dialog, 'delete_button', role='delete', enabled=False, - click=alert_dialog.on_delete_button_clicked) + click=alert_dialog.on_delete_button_clicked) self.manage_button_layout.addWidget(self.delete_button) self.manage_button_layout.addStretch() self.alert_dialog_layout.addLayout(self.manage_button_layout, 1, 1) display_icon = build_icon(':/general/general_live.png') self.display_button = create_button(alert_dialog, 'display_button', icon=display_icon, enabled=False) self.display_close_button = create_button(alert_dialog, 'display_close_button', icon=display_icon, - enabled=False) + enabled=False) self.button_box = create_button_box(alert_dialog, 'button_box', ['close'], - [self.display_button, self.display_close_button]) + [self.display_button, self.display_close_button]) self.alert_dialog_layout.addWidget(self.button_box, 2, 0, 1, 2) self.retranslateUi(alert_dialog) def retranslateUi(self, alert_dialog): + """ + Retranslate the UI strings + :param alert_dialog: + """ alert_dialog.setWindowTitle(translate('AlertsPlugin.AlertForm', 'Alert Message')) self.alert_entry_label.setText(translate('AlertsPlugin.AlertForm', 'Alert &text:')) self.alert_parameter.setText(translate('AlertsPlugin.AlertForm', '&Parameter:')) diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 144d1f249..80bd0cffa 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -113,9 +113,10 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): """ if not self.alert_text_edit.text(): QtGui.QMessageBox.information(self, - translate('AlertsPlugin.AlertForm', 'New Alert'), - translate('AlertsPlugin.AlertForm', 'You haven\'t specified any text for your alert. \n' - 'Please type in some text before clicking New.')) + translate('AlertsPlugin.AlertForm', 'New Alert'), + translate('AlertsPlugin.AlertForm', + 'You haven\'t specified any text for your alert. \n' + 'Please type in some text before clicking New.')) else: alert = AlertItem() alert.text = self.alert_text_edit.text() @@ -153,10 +154,10 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): List item has been double clicked to display it. """ item = self.alert_list_widget.selectedIndexes()[0] - bitem = self.alert_list_widget.item(item.row()) - self.trigger_alert(bitem.text()) - self.alert_text_edit.setText(bitem.text()) - self.item_id = bitem.data(QtCore.Qt.UserRole) + list_item = self.alert_list_widget.item(item.row()) + self.trigger_alert(list_item.text()) + self.alert_text_edit.setText(list_item.text()) + self.item_id = list_item.data(QtCore.Qt.UserRole) self.save_button.setEnabled(False) def on_single_click(self): @@ -164,9 +165,9 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): List item has been single clicked to add it to the edit field so it can be changed. """ item = self.alert_list_widget.selectedIndexes()[0] - bitem = self.alert_list_widget.item(item.row()) - self.alert_text_edit.setText(bitem.text()) - self.item_id = bitem.data(QtCore.Qt.UserRole) + list_item = self.alert_list_widget.item(item.row()) + self.alert_text_edit.setText(list_item.text()) + self.item_id = list_item.data(QtCore.Qt.UserRole) # If the alert does not contain '<>' we clear the ParameterEdit field. if self.alert_text_edit.text().find('<>') == -1: self.parameter_edit.setText('') @@ -182,20 +183,25 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): if not text: return False # We found '<>' in the alert text, but the ParameterEdit field is empty. - if text.find('<>') != -1 and not self.parameter_edit.text() and QtGui.QMessageBox.question(self, - translate('AlertsPlugin.AlertForm', 'No Parameter Found'), - translate('AlertsPlugin.AlertForm', 'You have not entered a parameter to be replaced.\n' - 'Do you want to continue anyway?'), - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No: + if text.find('<>') != -1 and not self.parameter_edit.text() and \ + QtGui.QMessageBox.question(self, + translate('AlertsPlugin.AlertForm', 'No Parameter Found'), + translate('AlertsPlugin.AlertForm', + 'You have not entered a parameter to be replaced.\n' + 'Do you want to continue anyway?'), + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No: self.parameter_edit.setFocus() return False # The ParameterEdit field is not empty, but we have not found '<>' # in the alert text. - elif text.find('<>') == -1 and self.parameter_edit.text() and QtGui.QMessageBox.question(self, - translate('AlertsPlugin.AlertForm', 'No Placeholder Found'), - translate('AlertsPlugin.AlertForm', 'The alert text does not contain \'<>\'.\n' - 'Do you want to continue anyway?'), - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No: + elif text.find('<>') == -1 and self.parameter_edit.text() and \ + QtGui.QMessageBox.question(self, + translate('AlertsPlugin.AlertForm', 'No Placeholder Found'), + translate('AlertsPlugin.AlertForm', 'The alert text does not contain \'<>\'.\n' + 'Do you want to continue anyway?'), + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No: self.parameter_edit.setFocus() return False text = text.replace('<>', self.parameter_edit.text()) diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index 6d1357aaf..26461f9ee 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -67,8 +67,8 @@ class AlertsManager(QtCore.QObject): """ Called from the Alert Tab to display an alert. - ``text`` - display text + :param text: + The text to display """ log.debug('display alert called %s' % text) if text: @@ -98,7 +98,7 @@ class AlertsManager(QtCore.QObject): """ Time has finished so if our time then request the next Alert if there is one and reset the timer. - ``event`` + :param event: the QT event that has been triggered. """ log.debug('timer event') diff --git a/openlp/plugins/alerts/lib/alertstab.py b/openlp/plugins/alerts/lib/alertstab.py index 4d09fcdb3..7ac5db672 100644 --- a/openlp/plugins/alerts/lib/alertstab.py +++ b/openlp/plugins/alerts/lib/alertstab.py @@ -114,6 +114,9 @@ class AlertsTab(SettingsTab): self.font_preview.setText(UiStrings().OLPV2x) def on_background_color_button_clicked(self): + """ + The background color has been changed. + """ new_color = QtGui.QColorDialog.getColor(QtGui.QColor(self.background_color), self) if new_color.isValid(): self.background_color = new_color.name() @@ -121,9 +124,15 @@ class AlertsTab(SettingsTab): self.update_display() def on_font_combo_box_clicked(self): + """ + The Font Combo was changed. + """ self.update_display() def on_font_color_button_clicked(self): + """ + The Font Color button has clicked. + """ new_color = QtGui.QColorDialog.getColor(QtGui.QColor(self.font_color), self) if new_color.isValid(): self.font_color = new_color.name() @@ -131,14 +140,24 @@ class AlertsTab(SettingsTab): self.update_display() def on_timeout_spin_box_changed(self): + """ + The Time out spin box has changed. + + """ self.timeout = self.timeout_spin_box.value() self.changed = True def on_font_size_spin_box_changed(self): + """ + The font size spin box has changed. + """ self.font_size = self.font_size_spin_box.value() self.update_display() def load(self): + """ + Load the settings into the UI. + """ settings = Settings() settings.beginGroup(self.settings_section) self.timeout = settings.value('timeout') @@ -160,6 +179,9 @@ class AlertsTab(SettingsTab): self.changed = False def save(self): + """ + Save the changes on exit of the Settings dialog. + """ settings = Settings() settings.beginGroup(self.settings_section) # Check value has changed as no event handles this field @@ -179,6 +201,9 @@ class AlertsTab(SettingsTab): self.changed = False def update_display(self): + """ + Update the preview display after changes have been made, + """ font = QtGui.QFont() font.setFamily(self.font_combo_box.currentFont().family()) font.setBold(True) diff --git a/openlp/plugins/alerts/lib/db.py b/openlp/plugins/alerts/lib/db.py index bd333241c..436f0314b 100644 --- a/openlp/plugins/alerts/lib/db.py +++ b/openlp/plugins/alerts/lib/db.py @@ -47,14 +47,14 @@ def init_schema(url): """ Setup the alerts database connection and initialise the database schema - ``url`` + :param url: The database to setup """ session, metadata = init_db(url) alerts_table = Table('alerts', metadata, - Column('id', types.Integer(), primary_key=True), - Column('text', types.UnicodeText, nullable=False)) + Column('id', types.Integer(), primary_key=True), + Column('text', types.UnicodeText, nullable=False)) mapper(AlertItem, alerts_table) From db6ba7c780f506153593bcd373eb0485bea599d1 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 1 Jan 2014 09:57:06 +0000 Subject: [PATCH 18/41] fix alerts more --- openlp/core/ui/servicemanager.py | 2 +- openlp/plugins/alerts/alertsplugin.py | 8 +++----- openlp/plugins/alerts/forms/alertdialog.py | 5 +++-- openlp/plugins/alerts/forms/alertform.py | 6 ++---- openlp/plugins/alerts/lib/alertsmanager.py | 8 ++++---- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index f131a20c7..e1aa1537f 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -365,7 +365,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def set_file_name(self, file_name): """ Setter for service file. - + :param file_name: The service file name """ self._file_name = str(file_name) diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 97ca0f60b..e41c413bc 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -148,8 +148,7 @@ class AlertsPlugin(Plugin): """ Give the alerts plugin the opportunity to add items to the **Tools** menu. - :param tools_menu: - The actual **Tools** menu item, so that your actions can use it as their parent. + :param tools_menu: The actual **Tools** menu item, so that your actions can use it as their parent. """ log.info('add tools menu') self.tools_alert_item = create_action(tools_menu, 'toolsAlertItem', @@ -240,10 +239,9 @@ class AlertsPlugin(Plugin): def refresh_css(self, frame): """ - Trigger an update of the CSS in the maindisplay. + Trigger an update of the CSS in the main display. - ``frame`` - The Web frame holding the page. + :param frame: The Web frame holding the page. """ align = VerticalType.Names[self.settings_tab.location] frame.evaluateJavaScript('update_css("%s", "%s", "%s", "%s", "%s")' % diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py index a4596d9ea..eead213fa 100644 --- a/openlp/plugins/alerts/forms/alertdialog.py +++ b/openlp/plugins/alerts/forms/alertdialog.py @@ -39,7 +39,7 @@ class Ui_AlertDialog(object): """ Setup the Alert UI dialog - :param alert_dialog: + :param alert_dialog: The dialog """ alert_dialog.setObjectName('alert_dialog') alert_dialog.resize(400, 300) @@ -93,7 +93,8 @@ class Ui_AlertDialog(object): def retranslateUi(self, alert_dialog): """ Retranslate the UI strings - :param alert_dialog: + + :param alert_dialog: The dialog """ alert_dialog.setWindowTitle(translate('AlertsPlugin.AlertForm', 'Alert Message')) self.alert_entry_label.setText(translate('AlertsPlugin.AlertForm', 'Alert &text:')) diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 80bd0cffa..4e3bedcd5 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -177,8 +177,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): """ Prepares the alert text for displaying. - ``text`` - The alert text (unicode). + :param text: The alert text. """ if not text: return False @@ -213,8 +212,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): Called when the *alert_list_widget*'s current row has been changed. This enables or disables buttons which require an item to act on. - ``row`` - The row (int). If there is no current row, the value is -1. + :param row: The row (int). If there is no current row, the value is -1. """ if row == -1: self.display_button.setEnabled(False) diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index 26461f9ee..b1d453fb2 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -59,6 +59,8 @@ class AlertsManager(QtCore.QObject): def alert_text(self, message): """ Called via a alerts_text event. Message is single element array containing text. + + :param message: The message text to be displayed """ if message: self.display_alert(message[0]) @@ -67,8 +69,7 @@ class AlertsManager(QtCore.QObject): """ Called from the Alert Tab to display an alert. - :param text: - The text to display + :param text: The text to display """ log.debug('display alert called %s' % text) if text: @@ -98,8 +99,7 @@ class AlertsManager(QtCore.QObject): """ Time has finished so if our time then request the next Alert if there is one and reset the timer. - :param event: - the QT event that has been triggered. + :param event: the QT event that has been triggered. """ log.debug('timer event') if event.timerId() == self.timer_id: From 8c71c9622256789198edde3b4d0c0b23d82d2c4b Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 1 Jan 2014 10:56:23 +0000 Subject: [PATCH 19/41] Fixes for Custom --- .../plugins/custom/forms/editcustomdialog.py | 6 ++- openlp/plugins/custom/forms/editcustomform.py | 21 +++------- .../custom/forms/editcustomslideform.py | 7 ++-- openlp/plugins/custom/lib/customtab.py | 14 +++++++ openlp/plugins/custom/lib/customxmlhandler.py | 13 +++---- openlp/plugins/custom/lib/db.py | 2 +- openlp/plugins/custom/lib/mediaitem.py | 38 +++++++++++++++++++ 7 files changed, 73 insertions(+), 28 deletions(-) diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py index 2ac24949a..22a33d921 100644 --- a/openlp/plugins/custom/forms/editcustomdialog.py +++ b/openlp/plugins/custom/forms/editcustomdialog.py @@ -36,6 +36,10 @@ from openlp.core.lib.ui import create_button_box, create_button class Ui_CustomEditDialog(object): def setupUi(self, custom_edit_dialog): + """ + Build the Edit Dialog UI + :param custom_edit_dialog: The Dialog + """ custom_edit_dialog.setObjectName('custom_edit_dialog') custom_edit_dialog.resize(450, 350) custom_edit_dialog.setWindowIcon(build_icon(':/icon/openlp-logo-16x16.png')) @@ -100,7 +104,7 @@ class Ui_CustomEditDialog(object): self.dialog_layout.addLayout(self.bottom_form_layout) self.preview_button = QtGui.QPushButton() self.button_box = create_button_box(custom_edit_dialog, 'button_box', ['cancel', 'save'], - [self.preview_button]) + [self.preview_button]) self.dialog_layout.addWidget(self.button_box) self.retranslateUi(custom_edit_dialog) diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index a10d16059..010f7d1bc 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -70,8 +70,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): """ Load a list of themes into the themes combo box. - ``theme_list`` - The list of themes to load. + :param theme_list: The list of themes to load. """ self.theme_combo_box.clear() self.theme_combo_box.addItem('') @@ -81,12 +80,8 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): """ Called when editing or creating a new custom. - ``id`` - The custom's id. If zero, then a new custom is created. - - ``preview`` - States whether the custom is edited while being previewed in the - preview panel. + :param id: The custom's id. If zero, then a new custom is created. + :param preview: States whether the custom is edited while being previewed in the preview panel. """ self.slide_list_view.clear() if id == 0: @@ -195,11 +190,8 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): """ Updates the slide list after editing slides. - ``slides`` - A list of all slides which have been edited. - - ``edit_all`` - Indicates if all slides or only one slide has been edited. + :param slides: A list of all slides which have been edited. + :param edit_all: Indicates if all slides or only one slide has been edited. """ if edit_all: self.slide_list_view.clear() @@ -229,8 +221,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): Called when the *slide_list_view*'s current row has been changed. This enables or disables buttons which require an slide to act on. - ``row`` - The row (int). If there is no current row, the value is -1. + :param row: The row (int). If there is no current row, the value is -1. """ if row == -1: self.delete_button.setEnabled(False) diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py index 0672a7258..afce4887b 100644 --- a/openlp/plugins/custom/forms/editcustomslideform.py +++ b/openlp/plugins/custom/forms/editcustomslideform.py @@ -57,8 +57,7 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): """ Set the text for slide_text_edit. - ``text`` - The text (unicode). + :param text: The text (unicode). """ self.slide_text_edit.clear() if text: @@ -87,7 +86,9 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): def insert_single_line_text_at_cursor(self, text): """ - Adds ``text`` in a single line at the cursor position. + Adds a single line at the cursor position. + + :param text: The text to be inserted """ full_text = self.slide_text_edit.toPlainText() position = self.slide_text_edit.textCursor().position() diff --git a/openlp/plugins/custom/lib/customtab.py b/openlp/plugins/custom/lib/customtab.py index 6e0137aa7..fae5bedba 100644 --- a/openlp/plugins/custom/lib/customtab.py +++ b/openlp/plugins/custom/lib/customtab.py @@ -72,6 +72,8 @@ class CustomTab(SettingsTab): def on_display_footer_check_box_changed(self, check_state): """ Toggle the setting for displaying the footer. + + :param check_state: The current check box state """ self.display_footer = False # we have a set value convert to True/False @@ -79,9 +81,18 @@ class CustomTab(SettingsTab): self.display_footer = True def on_add_from_service_check_box_changed(self, check_state): + """ + Allows service items to create Custom items. + + :param check_state: The current check box state + """ self.update_load = (check_state == QtCore.Qt.Checked) def load(self): + """ + + Load the settings into the dialog + """ settings = Settings() settings.beginGroup(self.settings_section) self.display_footer = settings.value('display footer') @@ -91,6 +102,9 @@ class CustomTab(SettingsTab): settings.endGroup() def save(self): + """ + Save the Dialog settings + """ settings = Settings() settings.beginGroup(self.settings_section) settings.setValue('display footer', self.display_footer) diff --git a/openlp/plugins/custom/lib/customxmlhandler.py b/openlp/plugins/custom/lib/customxmlhandler.py index cef195c06..c0f02942f 100644 --- a/openlp/plugins/custom/lib/customxmlhandler.py +++ b/openlp/plugins/custom/lib/customxmlhandler.py @@ -50,6 +50,7 @@ from lxml import etree, objectify log = logging.getLogger(__name__) + #TODO: These classes need to be refactored into a single class. class CustomXMLBuilder(object): """ @@ -89,15 +90,11 @@ class CustomXMLBuilder(object): """ Add a verse to the ```` tag. - ``verse_type`` - A string denoting the type of verse. Possible values are "Chorus", - "Verse", "Bridge", and "Custom". + :param verse_type: A string denoting the type of verse. Possible values are "Chorus", "Verse", "Bridge", + and "Custom". + :param number: An integer denoting the number of the item, for example: verse 1. + :param content: The actual text of the verse to be stored. - ``number`` - An integer denoting the number of the item, for example: verse 1. - - ``content`` - The actual text of the verse to be stored. """ verse = self.custom_xml.createElement('verse') verse.setAttribute('type', verse_type) diff --git a/openlp/plugins/custom/lib/db.py b/openlp/plugins/custom/lib/db.py index f05e1c1ff..44287b543 100644 --- a/openlp/plugins/custom/lib/db.py +++ b/openlp/plugins/custom/lib/db.py @@ -71,7 +71,7 @@ def init_schema(url): Column('text', types.UnicodeText, nullable=False), Column('credits', types.UnicodeText), Column('theme_name', types.Unicode(128)) - ) + ) mapper(CustomSlide, custom_slide_table) diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index e888b7b95..cfea319e6 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -73,6 +73,9 @@ class CustomMediaItem(MediaManagerItem): self.remote_custom = -1 def add_end_header_bar(self): + """ + Add the Custom End Head bar and register events and functions + """ self.toolbar.addSeparator() self.add_search_to_toolbar() # Signals and slots @@ -91,10 +94,17 @@ class CustomMediaItem(MediaManagerItem): self.add_custom_from_service = Settings().value(self.settings_section + '/add custom from service') def retranslateUi(self): + """ + + + """ self.search_text_label.setText('%s:' % UiStrings().Search) self.search_text_button.setText(UiStrings().Search) def initialise(self): + """ + Initialise the UI so it can provide Searches + """ self.search_text_edit.set_search_types([(CustomSearch.Titles, ':/songs/song_search_title.png', translate('SongsPlugin.MediaItem', 'Titles'), translate('SongsPlugin.MediaItem', 'Search Titles...')), @@ -107,6 +117,11 @@ class CustomMediaItem(MediaManagerItem): def load_list(self, custom_slides, target_group=None): # Sort out what custom we want to select after loading the list. + """ + + :param custom_slides: + :param target_group: + """ self.save_auto_select_id() self.list_view.clear() custom_slides.sort() @@ -123,6 +138,9 @@ class CustomMediaItem(MediaManagerItem): # active trigger it and clean up so it will not update again. def on_new_click(self): + """ + Handle the New item event + """ self.edit_custom_form.load_custom(0) self.edit_custom_form.exec_() self.on_clear_text_button_click() @@ -132,6 +150,9 @@ class CustomMediaItem(MediaManagerItem): """ Called by ServiceManager or SlideController by event passing the custom Id in the payload along with an indicator to say which type of display is required. + + :param custom_id: The id of the item to be edited + :param preview: Do we need to update the Preview after the edit. (Default False) """ custom_id = int(custom_id) valid = self.plugin.db_manager.get_object(CustomSlide, custom_id) @@ -184,12 +205,20 @@ class CustomMediaItem(MediaManagerItem): self.on_search_text_button_clicked() def on_focus(self): + """ + Set the focus + """ self.search_text_edit.setFocus() def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, context=ServiceItemContext.Service): """ Generate the slide data. Needs to be implemented by the plugin. + :param service_item: To be updated + :param item: The custom database item to be used + :param xml_version: No used + :param remote: Is this triggered by the Preview Controller or Service Manager. + :param context: Why is this item required to be build (Default Service). """ item_id = self._get_id_of_item_to_generate(item, self.remote_custom) service_item.add_capability(ItemCapabilities.CanEdit) @@ -243,6 +272,8 @@ class CustomMediaItem(MediaManagerItem): """ If search as type enabled invoke the search on each key press. If the Title is being searched do not start until 2 characters have been entered. + + :param text: The search text """ search_length = 2 if len(text) > search_length: @@ -253,6 +284,8 @@ class CustomMediaItem(MediaManagerItem): def service_load(self, item): """ Triggered by a custom item being loaded by the service manager. + + :param item: The service Item from the service to load found in the database. """ log.debug('service_load') if self.plugin.status != PluginStatus.Active: @@ -271,6 +304,8 @@ class CustomMediaItem(MediaManagerItem): def create_from_service_item(self, item): """ Create a custom slide from a text service item + + :param item: the service item to be converted to a Custom item """ custom = CustomSlide() custom.title = item.title @@ -303,6 +338,9 @@ class CustomMediaItem(MediaManagerItem): def search(self, string, show_error): """ Search the database for a given item. + + :param string: The search string + :param show_error: The error string to be show. """ search = '%' + string.lower() + '%' search_results = self.plugin.db_manager.get_all_objects(CustomSlide, From 85182074170fae356f121f5a03ca745b6be33de7 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 1 Jan 2014 14:59:57 +0000 Subject: [PATCH 20/41] Fix up test failures --- openlp/core/common/registry.py | 2 +- .../openlp_core_common/test_registry.py | 14 ++--- .../openlp_core_ui/test_listpreviewwidget.py | 4 +- .../openlp_core_ui/test_mainwindow.py | 7 ++- .../openlp_core_ui/test_starttimedialog.py | 60 +++++++++---------- .../openlp_core_ui/test_thememanagerhelper.py | 21 +------ 6 files changed, 43 insertions(+), 65 deletions(-) diff --git a/openlp/core/common/registry.py b/openlp/core/common/registry.py index f0c508da4..5bcf01d0f 100644 --- a/openlp/core/common/registry.py +++ b/openlp/core/common/registry.py @@ -80,7 +80,7 @@ class Registry(object): else: trace_error_handler(log) log.error('Service %s not found in list' % key) - #raise KeyError('Service %s not found in list' % key) + return None def register(self, key, reference): """ diff --git a/tests/functional/openlp_core_common/test_registry.py b/tests/functional/openlp_core_common/test_registry.py index ee236035d..84813195e 100644 --- a/tests/functional/openlp_core_common/test_registry.py +++ b/tests/functional/openlp_core_common/test_registry.py @@ -59,22 +59,18 @@ class TestRegistry(TestCase): with self.assertRaises(KeyError) as context: Registry().register('test1', mock_1) self.assertEqual(context.exception.args[0], 'Duplicate service exception test1', - 'KeyError exception should have been thrown for duplicate service') + 'KeyError exception should have been thrown for duplicate service') # WHEN I try to get back a non existent component # THEN I will get an exception - with self.assertRaises(KeyError) as context: - temp = Registry().get('test2') - self.assertEqual(context.exception.args[0], 'Service test2 not found in list', - 'KeyError exception should have been thrown for missing service') + temp = Registry().get('test2') + self.assertEqual(temp, None, 'KeyError error None should not have been returned for missing service') # WHEN I try to replace a component I should be allowed (testing only) Registry().remove('test1') # THEN I will get an exception - with self.assertRaises(KeyError) as context: - temp = Registry().get('test1') - self.assertEqual(context.exception.args[0], 'Service test1 not found in list', - 'KeyError exception should have been thrown for deleted service') + temp = Registry().get('test1') + self.assertEqual(temp, None, 'KeyError error None should have been returned for deleted service') def registry_function_test(self): """ diff --git a/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py b/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py index f11ad6939..6d638cdd1 100644 --- a/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py +++ b/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py @@ -38,7 +38,7 @@ class TestListPreviewWidget(TestCase): def initial_slide_count_test(self): """ - Test the inital slide count. + Test the initial slide count . """ # GIVEN: A new ListPreviewWidget instance. # WHEN: No SlideItem has been added yet. @@ -47,7 +47,7 @@ class TestListPreviewWidget(TestCase): def initial_slide_number_test(self): """ - Test the inital slide number. + Test the initial current slide number. """ # GIVEN: A new ListPreviewWidget instance. # WHEN: No SlideItem has been added yet. diff --git a/tests/interfaces/openlp_core_ui/test_mainwindow.py b/tests/interfaces/openlp_core_ui/test_mainwindow.py index b073b2219..279fe15db 100644 --- a/tests/interfaces/openlp_core_ui/test_mainwindow.py +++ b/tests/interfaces/openlp_core_ui/test_mainwindow.py @@ -22,12 +22,13 @@ class TestMainWindow(TestCase): # Mock cursor busy/normal methods. self.app.set_busy_cursor = MagicMock() self.app.set_normal_cursor = MagicMock() - self.app.args =[] + self.app.args = [] Registry().register('application', self.app) # Mock classes and methods used by mainwindow. with patch('openlp.core.ui.mainwindow.SettingsForm') as mocked_settings_form, \ patch('openlp.core.ui.mainwindow.ImageManager') as mocked_image_manager, \ - patch('openlp.core.ui.mainwindow.SlideController') as mocked_slide_controller, \ + patch('openlp.core.ui.mainwindow.LiveController') as mocked_live_controller, \ + patch('openlp.core.ui.mainwindow.PreviewController') as mocked_preview_controller, \ patch('openlp.core.ui.mainwindow.OpenLPDockWidget') as mocked_dock_widget, \ patch('openlp.core.ui.mainwindow.QtGui.QToolBox') as mocked_q_tool_box_class, \ patch('openlp.core.ui.mainwindow.QtGui.QMainWindow.addDockWidget') as mocked_add_dock_method, \ @@ -53,7 +54,7 @@ class TestMainWindow(TestCase): mocked_value.side_effect = [True, 2] # WHEN: Call the restore method. - Registry().execute('bootstrap_post_set_up') + self.main_window.restore_current_media_manager_item() # THEN: The current widget should have been set. self.main_window.media_tool_box.setCurrentIndex.assert_called_with(2) diff --git a/tests/interfaces/openlp_core_ui/test_starttimedialog.py b/tests/interfaces/openlp_core_ui/test_starttimedialog.py index 211bd2219..709a5d68f 100644 --- a/tests/interfaces/openlp_core_ui/test_starttimedialog.py +++ b/tests/interfaces/openlp_core_ui/test_starttimedialog.py @@ -34,28 +34,28 @@ class TestStartTimeDialog(TestCase): """ Test StartTimeDialog are defaults correct """ - self.assertEqual(self.form.hourSpinBox.minimum(), 0, 'The minimum hour should stay the same as the dialog') - self.assertEqual(self.form.hourSpinBox.maximum(), 4, 'The maximum hour should stay the same as the dialog') - self.assertEqual(self.form.minuteSpinBox.minimum(), 0, - 'The minimum minute should stay the same as the dialog') - self.assertEqual(self.form.minuteSpinBox.maximum(), 59, - 'The maximum minute should stay the same as the dialog') - self.assertEqual(self.form.secondSpinBox.minimum(), 0, - 'The minimum second should stay the same as the dialog') - self.assertEqual(self.form.secondSpinBox.maximum(), 59, - 'The maximum second should stay the same as the dialog') - self.assertEqual(self.form.hourFinishSpinBox.minimum(), 0, - 'The minimum finish hour should stay the same as the dialog') - self.assertEqual(self.form.hourFinishSpinBox.maximum(), 4, - 'The maximum finish hour should stay the same as the dialog') - self.assertEqual(self.form.minuteFinishSpinBox.minimum(), 0, - 'The minimum finish minute should stay the same as the dialog') - self.assertEqual(self.form.minuteFinishSpinBox.maximum(), 59, - 'The maximum finish minute should stay the same as the dialog') - self.assertEqual(self.form.secondFinishSpinBox.minimum(), 0, - 'The minimum finish second should stay the same as the dialog') - self.assertEqual(self.form.secondFinishSpinBox.maximum(), 59, - 'The maximum finish second should stay the same as the dialog') + self.assertEqual(self.form.hour_spin_box.minimum(), 0, 'The minimum hour should stay the same as the dialog') + self.assertEqual(self.form.hour_spin_box.maximum(), 4, 'The maximum hour should stay the same as the dialog') + self.assertEqual(self.form.minute_spin_box.minimum(), 0, + 'The minimum minute should stay the same as the dialog') + self.assertEqual(self.form.minute_spin_box.maximum(), 59, + 'The maximum minute should stay the same as the dialog') + self.assertEqual(self.form.second_spin_box.minimum(), 0, + 'The minimum second should stay the same as the dialog') + self.assertEqual(self.form.second_spin_box.maximum(), 59, + 'The maximum second should stay the same as the dialog') + self.assertEqual(self.form.hour_finish_spin_box.minimum(), 0, + 'The minimum finish hour should stay the same as the dialog') + self.assertEqual(self.form.hour_finish_spin_box.maximum(), 4, + 'The maximum finish hour should stay the same as the dialog') + self.assertEqual(self.form.minute_finish_spin_box.minimum(), 0, + 'The minimum finish minute should stay the same as the dialog') + self.assertEqual(self.form.minute_finish_spin_box.maximum(), 59, + 'The maximum finish minute should stay the same as the dialog') + self.assertEqual(self.form.second_finish_spin_box.minimum(), 0, + 'The minimum finish second should stay the same as the dialog') + self.assertEqual(self.form.second_finish_spin_box.maximum(), 59, + 'The maximum finish second should stay the same as the dialog') def time_display_test(self): """ @@ -75,22 +75,22 @@ class TestStartTimeDialog(TestCase): QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) # THEN the following input values are returned - self.assertEqual(self.form.hourSpinBox.value(), 0) - self.assertEqual(self.form.minuteSpinBox.value(), 1) - self.assertEqual(self.form.secondSpinBox.value(), 1) + self.assertEqual(self.form.hour_spin_box.value(), 0) + self.assertEqual(self.form.minute_spin_box.value(), 1) + self.assertEqual(self.form.second_spin_box.value(), 1) self.assertEqual(self.form.item['service_item'].start_time, 61, 'The start time should stay the same') # WHEN displaying the UI, changing the time to 2min 3secs and pressing enter self.form.item = {'service_item': mocked_serviceitem} with patch('PyQt4.QtGui.QDialog.exec_'): self.form.exec_() - self.form.minuteSpinBox.setValue(2) - self.form.secondSpinBox.setValue(3) + self.form.minute_spin_box.setValue(2) + self.form.second_spin_box.setValue(3) ok_widget = self.form.button_box.button(self.form.button_box.Ok) QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) # THEN the following values are returned - self.assertEqual(self.form.hourSpinBox.value(), 0) - self.assertEqual(self.form.minuteSpinBox.value(), 2) - self.assertEqual(self.form.secondSpinBox.value(), 3) + self.assertEqual(self.form.hour_spin_box.value(), 0) + self.assertEqual(self.form.minute_spin_box.value(), 2) + self.assertEqual(self.form.second_spin_box.value(), 3) self.assertEqual(self.form.item['service_item'].start_time, 123, 'The start time should have changed') diff --git a/tests/interfaces/openlp_core_ui/test_thememanagerhelper.py b/tests/interfaces/openlp_core_ui/test_thememanagerhelper.py index d0456edc2..b4757fef7 100644 --- a/tests/interfaces/openlp_core_ui/test_thememanagerhelper.py +++ b/tests/interfaces/openlp_core_ui/test_thememanagerhelper.py @@ -50,6 +50,7 @@ class TestThemeManagerHelper(TestCase): Settings().set_filename(self.ini_file) self.helper = ThemeManagerHelper() self.helper.settings_section = "themes" + self.helper.log_debug = MagicMock() def tearDown(self): """ @@ -58,26 +59,6 @@ class TestThemeManagerHelper(TestCase): os.unlink(self.ini_file) os.unlink(Settings().fileName()) - def test_initialise(self): - """ - Test the thememanagerhelper initialise - basic test - """ - # GIVEN: A new a call to initialise - Settings().setValue('themes/global theme', 'my_theme') - self.helper.build_theme_path = MagicMock() - self.helper.load_first_time_themes = MagicMock() - - # WHEN: the initialistion is run - self.helper.initialise() - - # THEN: - self.assertEqual(1, self.helper.build_theme_path.call_count, - 'The function build_theme_path should have been called') - self.assertEqual(1, self.helper.load_first_time_themes.call_count, - 'The function load_first_time_themes should have been called only once') - self.assertEqual(self.helper.global_theme, 'my_theme', - 'The global theme should have been set to my_theme') - def test_build_theme_path(self): """ Test the thememanagerhelper build_theme_path - basic test From d6aa4e2299d49b90ec54f38d70766984b2d0701c Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Fri, 3 Jan 2014 21:33:40 +0000 Subject: [PATCH 21/41] Fix message text --- tests/functional/openlp_core_common/test_registry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/functional/openlp_core_common/test_registry.py b/tests/functional/openlp_core_common/test_registry.py index 84813195e..a57d7ea85 100644 --- a/tests/functional/openlp_core_common/test_registry.py +++ b/tests/functional/openlp_core_common/test_registry.py @@ -64,13 +64,13 @@ class TestRegistry(TestCase): # WHEN I try to get back a non existent component # THEN I will get an exception temp = Registry().get('test2') - self.assertEqual(temp, None, 'KeyError error None should not have been returned for missing service') + self.assertEqual(temp, None, 'None should have been returned for missing service') # WHEN I try to replace a component I should be allowed (testing only) Registry().remove('test1') # THEN I will get an exception temp = Registry().get('test1') - self.assertEqual(temp, None, 'KeyError error None should have been returned for deleted service') + self.assertEqual(temp, None, 'None should have been returned for deleted service') def registry_function_test(self): """ From 4c7fa599c6fbd8f57ecb2b13d0c69f881d3a1058 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 4 Jan 2014 08:28:45 +0000 Subject: [PATCH 22/41] Add app to test --- tests/interfaces/openlp_core_ui/test_thememanager.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/interfaces/openlp_core_ui/test_thememanager.py b/tests/interfaces/openlp_core_ui/test_thememanager.py index 73e5b63fa..17a22f215 100644 --- a/tests/interfaces/openlp_core_ui/test_thememanager.py +++ b/tests/interfaces/openlp_core_ui/test_thememanager.py @@ -33,6 +33,8 @@ import os from unittest import TestCase from tempfile import mkstemp +from PyQt4 import QtGui + from openlp.core.common import Registry, Settings from openlp.core.ui import ThemeManager from tests.functional import patch, MagicMock @@ -48,16 +50,17 @@ class TestThemeManager(TestCase): """ fd, self.ini_file = mkstemp('.ini') Settings().set_filename(self.ini_file) + self.app = QtGui.QApplication([]) Registry.create() self.theme_manager = ThemeManager() - def tearDown(self): """ Delete all the C++ objects at the end so that we don't have a segfault """ os.unlink(self.ini_file) os.unlink(Settings().fileName()) + del self.app def initialise_test(self): """ From 5eba575618e0bdd3d5dcaaf823562e2f8f643aa2 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 4 Jan 2014 11:50:27 +0000 Subject: [PATCH 23/41] Add tests for new function --- openlp/core/ui/slidecontroller.py | 37 ++++++++- ...er.py => test_formattingtagscontroller.py} | 0 ...tagsform.py => test_formattingtagsform.py} | 0 .../openlp_core_ui/test_slidecontroller.py | 78 +++++++++++++++++++ 4 files changed, 113 insertions(+), 2 deletions(-) rename tests/functional/openlp_core_ui/{tests_formattingtagscontroller.py => test_formattingtagscontroller.py} (100%) rename tests/functional/openlp_core_ui/{tests_formattingtagsform.py => test_formattingtagsform.py} (100%) create mode 100644 tests/functional/openlp_core_ui/test_slidecontroller.py diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 8f61df6c9..31779a0e9 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -72,6 +72,11 @@ WIDE_MENU = [ 'desktop_screen_button' ] +NON_TEXT_MENU = [ + 'blank_screen_button', + 'desktop_screen_button' +] + class DisplayController(QtGui.QWidget): """ @@ -116,6 +121,9 @@ class SlideController(DisplayController): self.screen_size_changed() def initialise(self): + """ + Initialise the UI elements of the controller + """ self.screens = ScreenList() try: self.ratio = self.screens.current['size'].width() / self.screens.current['size'].height() @@ -442,6 +450,8 @@ class SlideController(DisplayController): def set_live_hot_keys(self, parent=None): """ Set the live hotkeys + + :param parent: The parent UI object for actions to be added to. """ self.previous_service = create_action(parent, 'previousService', text=translate('OpenLP.SlideController', 'Previous Service'), @@ -469,6 +479,8 @@ class SlideController(DisplayController): def toggle_display(self, action): """ Toggle the display settings triggered from remote messages. + + :param action: The blank action to be processed. """ if action == 'blank' or action == 'hide': self.on_blank_display(True) @@ -544,6 +556,8 @@ class SlideController(DisplayController): def __add_actions_to_widget(self, widget): """ Add actions to the widget specified by `widget` + + :param widget: The UI widget for the actions """ widget.addActions([ self.previous_item, self.next_item, @@ -574,6 +588,8 @@ class SlideController(DisplayController): def on_controller_size_changed(self, width): """ Change layout of display control buttons on controller size change + + :param width: the new width of the display """ if self.is_live: # Space used by the toolbar. @@ -581,12 +597,24 @@ class SlideController(DisplayController): # Add the threshold to prevent flickering. if width > used_space + HIDE_MENU_THRESHOLD and self.hide_menu.isVisible(): self.toolbar.set_widget_visible(NARROW_MENU, False) - self.toolbar.set_widget_visible(WIDE_MENU) + self.set_blank_menu() # Take away a threshold to prevent flickering. elif width < used_space - HIDE_MENU_THRESHOLD and not self.hide_menu.isVisible(): - self.toolbar.set_widget_visible(WIDE_MENU, False) + self.set_blank_menu(False) self.toolbar.set_widget_visible(NARROW_MENU) + def set_blank_menu(self, visible=True): + """ + Set the correct menu type dependent on the service item type + + :param visible: Do I need to hide the menu? + """ + self.toolbar.set_widget_visible(WIDE_MENU, False) + if self.service_item and self.service_item.is_text(): + self.toolbar.set_widget_visible(WIDE_MENU, visible) + else: + self.toolbar.set_widget_visible(NON_TEXT_MENU, visible) + def on_song_bar_handler(self): """ Some song handler @@ -612,6 +640,8 @@ class SlideController(DisplayController): def enable_tool_bar(self, item): """ Allows the toolbars to be reconfigured based on Controller Type and ServiceItem Type + + :param item: current service item being processed """ if self.is_live: self.enable_live_tool_bar(item) @@ -621,6 +651,8 @@ class SlideController(DisplayController): def enable_live_tool_bar(self, item): """ Allows the live toolbar to be customised + + :param item: The current service item """ # Work-around for OS X, hide and then show the toolbar # See bug #791050 @@ -643,6 +675,7 @@ class SlideController(DisplayController): self.mediabar.show() self.previous_item.setVisible(not item.is_media()) self.next_item.setVisible(not item.is_media()) + self.set_blank_menu() # Work-around for OS X, hide and then show the toolbar # See bug #791050 self.toolbar.show() diff --git a/tests/functional/openlp_core_ui/tests_formattingtagscontroller.py b/tests/functional/openlp_core_ui/test_formattingtagscontroller.py similarity index 100% rename from tests/functional/openlp_core_ui/tests_formattingtagscontroller.py rename to tests/functional/openlp_core_ui/test_formattingtagscontroller.py diff --git a/tests/functional/openlp_core_ui/tests_formattingtagsform.py b/tests/functional/openlp_core_ui/test_formattingtagsform.py similarity index 100% rename from tests/functional/openlp_core_ui/tests_formattingtagsform.py rename to tests/functional/openlp_core_ui/test_formattingtagsform.py diff --git a/tests/functional/openlp_core_ui/test_slidecontroller.py b/tests/functional/openlp_core_ui/test_slidecontroller.py new file mode 100644 index 000000000..3198340f0 --- /dev/null +++ b/tests/functional/openlp_core_ui/test_slidecontroller.py @@ -0,0 +1,78 @@ +# -*- 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 # +############################################################################### +""" +Package to test the openlp.core.ui.slidecontroller package. +""" +from unittest import TestCase + +from openlp.core.ui import SlideController + +from tests.interfaces import MagicMock, patch + + +class TestSlideController(TestCase): + + def initial_slide_controller_test(self): + """ + Test the initial slide controller state . + """ + # GIVEN: A new slideController instance. + slide_controller = SlideController(None) + # WHEN: No SlideItem has been added yet. + # THEN: The count of items should be zero. + self.assertEqual(slide_controller.is_live, False, 'The base slide controller should not be a live controller') + + def toggle_blank_test(self): + """ + Test the setting of the display blank icons by display type. + """ + # GIVEN: A new slideController instance. + slide_controller = SlideController(None) + service_item = MagicMock() + toolbar = MagicMock() + toolbar.set_widget_visible = self.dummy_widget_visible + slide_controller.toolbar = toolbar + slide_controller.service_item = service_item + + # WHEN a text based service item is used + slide_controller.service_item.is_text = MagicMock(return_value=True) + slide_controller.set_blank_menu() + + # THEN: then call set up the toolbar to blank the display screen. + self.assertEqual(len(self.test_widget), 3, 'There should be three icons to display on the screen') + + # WHEN a non text based service item is used + slide_controller.service_item.is_text = MagicMock(return_value=False) + slide_controller.set_blank_menu() + + # THEN: then call set up the toolbar to blank the display screen. + self.assertEqual(len(self.test_widget), 2, 'There should be only two icons to display on the screen') + + def dummy_widget_visible(self, widget, visible=True): + self.test_widget = widget From 0da7475748fe27f0410c151bd9e26ad1ed98cf91 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 4 Jan 2014 12:06:48 +0000 Subject: [PATCH 24/41] Fix up comments --- tests/functional/openlp_core_ui/test_slidecontroller.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/functional/openlp_core_ui/test_slidecontroller.py b/tests/functional/openlp_core_ui/test_slidecontroller.py index 3198340f0..2f94c4ec6 100644 --- a/tests/functional/openlp_core_ui/test_slidecontroller.py +++ b/tests/functional/openlp_core_ui/test_slidecontroller.py @@ -44,8 +44,8 @@ class TestSlideController(TestCase): """ # GIVEN: A new slideController instance. slide_controller = SlideController(None) - # WHEN: No SlideItem has been added yet. - # THEN: The count of items should be zero. + # WHEN: the default controller is built. + # THEN: The the controller should not be a live controller. self.assertEqual(slide_controller.is_live, False, 'The base slide controller should not be a live controller') def toggle_blank_test(self): @@ -64,14 +64,14 @@ class TestSlideController(TestCase): slide_controller.service_item.is_text = MagicMock(return_value=True) slide_controller.set_blank_menu() - # THEN: then call set up the toolbar to blank the display screen. + # THEN: then call set up the toolbar to blank the display screen. self.assertEqual(len(self.test_widget), 3, 'There should be three icons to display on the screen') # WHEN a non text based service item is used slide_controller.service_item.is_text = MagicMock(return_value=False) slide_controller.set_blank_menu() - # THEN: then call set up the toolbar to blank the display screen. + # THEN: then call set up the toolbar to blank the display screen. self.assertEqual(len(self.test_widget), 2, 'There should be only two icons to display on the screen') def dummy_widget_visible(self, widget, visible=True): From 2dd4a9c54257ab8daa9254beb9f22a43d2df2b52 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 4 Jan 2014 16:33:20 +0000 Subject: [PATCH 25/41] Add config to service file --- openlp/core/lib/ui.py | 12 +++--- openlp/core/ui/servicemanager.py | 65 +++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py index cf37748b9..68fe2f7f9 100644 --- a/openlp/core/lib/ui.py +++ b/openlp/core/lib/ui.py @@ -342,18 +342,16 @@ def create_valign_selection_widgets(parent): return label, combo_box -def find_and_set_in_combo_box(combo_box, value_to_find): +def find_and_set_in_combo_box(combo_box, value_to_find, set_missing=True): """ Find a string in a combo box and set it as the selected item if present - ``combo_box`` - The combo box to check for selected items - - ``value_to_find`` - The value to find + :param combo_box: The combo box to check for selected items + :param value_to_find: The value to find + :param set_missing: if not found leave value as current """ index = combo_box.findText(value_to_find, QtCore.Qt.MatchExactly) if index == -1: # Not Found. - index = 0 + index = 0 if set_missing else combo_box.currentIndex() combo_box.setCurrentIndex(index) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index e1aa1537f..0d0007549 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -475,6 +475,19 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage Settings().setValue('servicemanager/last file', '') self.plugin_manager.new_service_created() + def create_basic_service(self): + """ + Create the initial service array with the base items to be saved. + + :return service array + """ + service = [] + core = {'lite-service': self._save_lite, + 'service-theme': self.service_theme + } + service.append({'openlp_core': core}) + return service + def save_file(self): """ Save the current service file. @@ -495,7 +508,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage service_file_name = '%s.osj' % base_name self.log_debug('ServiceManager.save_file - %s' % path_file_name) Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', path) - service = [] + service = self.create_basic_service() write_list = [] missing_list = [] audio_files = [] @@ -607,9 +620,9 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage path, file_name = os.path.split(path_file_name) base_name = os.path.splitext(file_name)[0] service_file_name = '%s.osj' % base_name - self.log_debug('ServiceManager.save_file - %s', path_file_name) + self.log_debug('ServiceManager.save_file - %s' % path_file_name) Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', path) - service = [] + service = self.create_basic_service() self.application.set_busy_cursor() # Number of items + 1 to zip it self.main_window.display_progress_bar(len(self.service_items) + 1) @@ -647,7 +660,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage delete_file(temp_file_name) return success - def save_file_as(self): + def save_file_as(self, field=None): """ Get a file name and then call :func:`ServiceManager.save_file` to save the file. """ @@ -748,19 +761,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.new_file() self.set_file_name(file_name) self.main_window.display_progress_bar(len(items)) - for item in items: - self.main_window.increment_progress_bar() - service_item = ServiceItem() - if self._save_lite: - service_item.set_from_service(item) - else: - service_item.set_from_service(item, self.service_path) - service_item.validate_item(self.suffixes) - if service_item.is_capable(ItemCapabilities.OnLoadUpdate): - new_item = Registry().get(service_item.name).service_load(service_item) - if new_item: - service_item = new_item - self.add_service_item(service_item, repaint=False) + self.process_service_items(items) delete_file(p_file) self.main_window.add_recent_file(file_name) self.set_modified(False) @@ -794,6 +795,34 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage self.application.set_normal_cursor() self.repaint_service_list(-1, -1) + def process_service_items(self, service_items): + """ + Process all the array of service items loaded from the saved service + + :param service_items: list of service_items + """ + for item in service_items: + self.main_window.increment_progress_bar() + service_item = ServiceItem() + if 'openlp_core' in item: + item = item.get('openlp_core') + theme = item.get('service-theme', None) + if theme: + find_and_set_in_combo_box(self.theme_combo_box, theme, set_missing=False) + if theme == self.theme_combo_box.currentText(): + self.renderer.set_service_theme(theme) + else: + if self._save_lite: + service_item.set_from_service(item) + else: + service_item.set_from_service(item, self.service_path) + service_item.validate_item(self.suffixes) + if service_item.is_capable(ItemCapabilities.OnLoadUpdate): + new_item = Registry().get(service_item.name).service_load(service_item) + if new_item: + service_item = new_item + self.add_service_item(service_item, repaint=False) + def load_last_file(self): """ Load the last service item from the service manager when the service was last closed. Can be blank if there was @@ -896,6 +925,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def toggle_auto_play_slides_once(self, field=None): """ Toggle Auto play slide once. Inverts auto play once option for the item + :param field: """ item = self.find_service_item()[0] @@ -912,6 +942,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage def toggle_auto_play_slides_loop(self, field=None): """ Toggle Auto play slide loop. + :param field: """ item = self.find_service_item()[0] From 5b6663b578ebf5b6c7e09063ee03322c001461ea Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 4 Jan 2014 17:19:30 +0000 Subject: [PATCH 26/41] basic tests --- .../openlp_core_ui/test_servicemanager.py | 85 +++++++++++++++++++ .../openlp_core_ui/test_slidecontroller.py | 2 +- 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 tests/functional/openlp_core_ui/test_servicemanager.py diff --git a/tests/functional/openlp_core_ui/test_servicemanager.py b/tests/functional/openlp_core_ui/test_servicemanager.py new file mode 100644 index 000000000..583a8c09e --- /dev/null +++ b/tests/functional/openlp_core_ui/test_servicemanager.py @@ -0,0 +1,85 @@ +# -*- 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 # +############################################################################### +""" +Package to test the openlp.core.ui.slidecontroller package. +""" +from unittest import TestCase + +from openlp.core.common import Registry +from openlp.core.ui import ServiceManager + +from tests.interfaces import MagicMock, patch + + +class TestServiceManager(TestCase): + + def setUp(self): + """ + Create the UI + """ + Registry.create() + #self.app = QtGui.QApplication([]) + #ScreenList.create(self.app.desktop()) + #Registry().register('application', MagicMock()) + #with patch('openlp.core.lib.PluginManager'): + # self.main_window = MainWindow() + #self.service_manager = Registry().get('service_manager') + + def tearDown(self): + """ + Delete all the C++ objects at the end so that we don't have a segfault + """ + #del self.main_window + #del self.app + pass + + def initial_service_manager_test(self): + """ + Test the initial of service manager. + """ + # GIVEN: A new service manager instance. + ServiceManager(None) + # WHEN: the default service manager is built. + # THEN: The the controller should be registered in the registry. + self.assertNotEqual(Registry().get('service_manager'), None, 'The base service manager should be registered') + + def create_basic_service_test(self): + """ + Test the create basic service array + """ + # GIVEN: A new service manager instance. + service_manager = ServiceManager(None) + # WHEN: when the basic service array is created. + service_manager._save_lite = False + service_manager.service_theme = 'test_theme' + service = service_manager.create_basic_service()[0] + # THEN: The the controller should be registered in the registry. + self.assertNotEqual(service, None, 'The base service should be created') + self.assertEqual(service['openlp_core']['service-theme'], 'test_theme', 'The test theme should be saved') + self.assertEqual(service['openlp_core']['lite-service'], False, 'The lite service should be saved') \ No newline at end of file diff --git a/tests/functional/openlp_core_ui/test_slidecontroller.py b/tests/functional/openlp_core_ui/test_slidecontroller.py index 2f94c4ec6..56d87c511 100644 --- a/tests/functional/openlp_core_ui/test_slidecontroller.py +++ b/tests/functional/openlp_core_ui/test_slidecontroller.py @@ -45,7 +45,7 @@ class TestSlideController(TestCase): # GIVEN: A new slideController instance. slide_controller = SlideController(None) # WHEN: the default controller is built. - # THEN: The the controller should not be a live controller. + # THEN: The controller should not be a live controller. self.assertEqual(slide_controller.is_live, False, 'The base slide controller should not be a live controller') def toggle_blank_test(self): From 60d4009261468f6f3e4d3dd9e277a08528c813b5 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 4 Jan 2014 20:58:18 +0000 Subject: [PATCH 27/41] start off --- openlp/core/lib/renderer.py | 14 +++++++------- openlp/core/ui/maindisplay.py | 8 +++----- openlp/core/ui/thememanager.py | 3 +-- openlp/core/ui/themestab.py | 3 ++- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 4ef3b7a63..6eeccfc2a 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -31,7 +31,7 @@ import logging from PyQt4 import QtGui, QtCore, QtWebKit -from openlp.core.common import Registry, Settings +from openlp.core.common import Registry, OpenLPMixin, RegistryMixin, Settings from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, ScreenList, ServiceItem, expand_tags, \ build_lyrics_format_css, build_lyrics_outline_css from openlp.core.common import ThemeLevel @@ -50,12 +50,11 @@ VERSE_FOR_LINE_COUNT = '\n'.join(map(str, range(100))) FOOTER = ['Arky Arky (Unknown)', 'Public Domain', 'CCLI 123456'] -class Renderer(object): +class Renderer(OpenLPMixin, RegistryMixin): """ Class to pull all Renderer interactions into one place. The plugins will call helper methods to do the rendering but this class will provide display defense code. """ - log.info('Renderer Loaded') def __init__(self): """ @@ -63,20 +62,21 @@ class Renderer(object): """ log.debug('Initialisation started') self.screens = ScreenList() - Registry().register('renderer', self) self.theme_level = ThemeLevel.Global self.global_theme_name = '' self.service_theme_name = '' self.item_theme_name = '' self.force_page = False - self.display = MainDisplay(None, False, self) - self.display.setup() self._theme_dimensions = {} self._calculate_default() - Registry().register_function('theme_update_global', self.set_global_theme) self.web = QtWebKit.QWebView() self.web.setVisible(False) self.web_frame = self.web.page().mainFrame() + Registry().register_function('theme_update_global', self.set_global_theme) + + def bootstrap_initialise(self): + self.display = MainDisplay(None, False, self) + self.display.setup() def update_display(self): """ diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 60c0a7f4f..ecaeb0299 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -56,9 +56,8 @@ log = logging.getLogger(__name__) class Display(QtGui.QGraphicsView): """ - This is a general display screen class. Here the general display settings - will done. It will be used as specialized classes by Main Display and - Preview display. + This is a general display screen class. Here the general display settings will done. It will be used as + specialized classes by Main Display and Preview display. """ def __init__(self, parent, live, controller): """ @@ -521,8 +520,7 @@ class MainDisplay(Display): class AudioPlayer(QtCore.QObject): """ - This Class will play audio only allowing components to work with a - soundtrack independent of the user interface. + This Class will play audio only allowing components to work with a soundtrack independent of the user interface. """ log.info('AudioPlayer Loaded') diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index d9d798b67..2f5e3b47a 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -158,7 +158,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): self.theme_form.path = self.path self.file_rename_form = FileRenameForm() Registry().register_function('theme_update_global', self.change_global_from_tab) - self._push_themes() + self.load_themes() def build_theme_path(self): """ @@ -446,7 +446,6 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): self._write_theme(theme, None, None) Settings().setValue(self.settings_section + '/global theme', theme.theme_name) self.application.set_normal_cursor() - self.load_themes() def load_themes(self): """ diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index da2cb0f87..b5033e452 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -160,7 +160,8 @@ class ThemesTab(SettingsTab): """ After setting things up... """ - Registry().execute('theme_update_global') + #Registry().execute('theme_update_global') + pass def on_song_level_button_clicked(self): """ From 360d9883b49978313673e2f4f02e0ce0b11cfcb8 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 5 Jan 2014 17:09:51 +0000 Subject: [PATCH 28/41] Migrate renderer --- openlp/core/common/registrymixin.py | 2 + openlp/core/lib/renderer.py | 153 +++++++++++----------------- openlp/core/ui/maindisplay.py | 4 + openlp/core/ui/mainwindow.py | 3 + openlp/core/ui/servicemanager.py | 5 + openlp/core/ui/thememanager.py | 4 + 6 files changed, 78 insertions(+), 93 deletions(-) diff --git a/openlp/core/common/registrymixin.py b/openlp/core/common/registrymixin.py index e7bcc24d7..7a7876311 100644 --- a/openlp/core/common/registrymixin.py +++ b/openlp/core/common/registrymixin.py @@ -40,10 +40,12 @@ class RegistryMixin(object): """ Register the class and bootstrap hooks. """ + print("RegistryMixin - before super ", self.__class__.__name__) try: super(RegistryMixin, self).__init__(parent) except TypeError: super(RegistryMixin, self).__init__() + print("RegistryMixin - after super") Registry().register(de_hump(self.__class__.__name__), self) Registry().register_function('bootstrap_initialise', self.bootstrap_initialise) Registry().register_function('bootstrap_post_set_up', self.bootstrap_post_set_up) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 6eeccfc2a..c4bccf904 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -27,7 +27,6 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import logging from PyQt4 import QtGui, QtCore, QtWebKit @@ -37,8 +36,6 @@ from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, Scree from openlp.core.common import ThemeLevel from openlp.core.ui import MainDisplay -log = logging.getLogger(__name__) - VERSE = 'The Lord said to {r}Noah{/r}: \n' \ 'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n' \ 'The Lord said to {g}Noah{/g}:\n' \ @@ -60,7 +57,9 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Initialise the renderer. """ - log.debug('Initialisation started') + print("Renderer - before super") + super(Renderer, self).__init__(None) + print("Renderer - after super") self.screens = ScreenList() self.theme_level = ThemeLevel.Global self.global_theme_name = '' @@ -75,6 +74,10 @@ class Renderer(OpenLPMixin, RegistryMixin): Registry().register_function('theme_update_global', self.set_global_theme) def bootstrap_initialise(self): + """ + + + """ self.display = MainDisplay(None, False, self) self.display.setup() @@ -82,7 +85,7 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Updates the renderer's information about the current screen. """ - log.debug('Update Display') + self.log_debug('Update Display') self._calculate_default() if self.display: self.display.close() @@ -94,15 +97,11 @@ class Renderer(OpenLPMixin, RegistryMixin): """ This method updates the theme in ``_theme_dimensions`` when a theme has been edited or renamed. - ``theme_name`` - The current theme name. - - ``old_theme_name`` - The old theme name. Has only to be passed, when the theme has been renamed. Defaults to *None*. - - ``only_delete`` - Only remove the given ``theme_name`` from the ``_theme_dimensions`` list. This can be used when a theme is - permanently deleted. + :param theme_name: The current theme name. + :param old_theme_name: The old theme name. Has only to be passed, when the theme has been renamed. + Defaults to *None*. + :param only_delete: Only remove the given ``theme_name`` from the ``_theme_dimensions`` list. This can be + used when a theme is permanently deleted. """ if old_theme_name is not None and old_theme_name in self._theme_dimensions: del self._theme_dimensions[old_theme_name] @@ -115,8 +114,7 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Helper method to save theme names and theme data. - ``theme_name`` - The theme name. + :param theme_name: The theme name """ if theme_name not in self._theme_dimensions: theme_data = self.theme_manager.get_theme_data(theme_name) @@ -134,10 +132,9 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Set up the theme to be used before rendering an item. - ``override_theme_data`` - The theme data should be passed, when we want to use our own theme data, regardless of the theme level. This - should for example be used in the theme manager. **Note**, this is **not** to be mixed up with the - ``set_item_theme`` method. + :param override_theme_data: The theme data should be passed, when we want to use our own theme data, regardless + of the theme level. This should for example be used in the theme manager. **Note**, this is **not** to + be mixed up with the ``set_item_theme`` method. """ # Just assume we use the global theme. theme_to_use = self.global_theme_name @@ -167,8 +164,7 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Sets the theme level. - ``theme_level`` - The theme level to be used. + :param theme_level: The theme level to be used. """ self.theme_level = theme_level @@ -187,8 +183,7 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Set the service-level theme. - ``service_theme_name`` - The service level theme's name. + :param service_theme_name: The service level theme's name. """ self._set_theme(service_theme_name) self.service_theme_name = service_theme_name @@ -197,8 +192,7 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Set the item-level theme. **Note**, this has to be done for each item we are rendering. - ``item_theme_name`` - The item theme's name. + :param item_theme_name: The item theme's name. """ self._set_theme(item_theme_name) self.item_theme_name = item_theme_name @@ -207,13 +201,10 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Generate a preview of a theme. - ``theme_data`` - The theme to generated a preview for. - - ``force_page`` - Flag to tell message lines per page need to be generated. + :param theme_data: The theme to generated a preview for. + :param force_page: Flag to tell message lines per page need to be generated. """ - log.debug('generate preview') + self.log_debug('generate preview') # save value for use in format_slide self.force_page = force_page # build a service item to generate preview @@ -245,13 +236,11 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Calculate how much text can fit on a slide. - ``text`` - The words to go on the slides. + :param text: The words to go on the slides. + :param item: The :class:`~openlp.core.lib.serviceitem.ServiceItem` item object. - ``item`` - The :class:`~openlp.core.lib.serviceitem.ServiceItem` item object. """ - log.debug('format slide') + self.log_debug('format slide') # Add line endings after each line of text used for bibles. line_end = '
' if item.is_capable(ItemCapabilities.NoLineBreaks): @@ -329,7 +318,7 @@ class Renderer(OpenLPMixin, RegistryMixin): self.width = screen_size.width() self.height = screen_size.height() self.screen_ratio = self.height / self.width - log.debug('_calculate default %s, %f' % (screen_size, self.screen_ratio)) + self.log_debug('_calculate default %s, %f' % (screen_size, self.screen_ratio)) # 90% is start of footer self.footer_start = int(self.height * 0.90) @@ -337,8 +326,7 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Calculates the placement and size of the main rectangle. - ``theme_data`` - The theme information + :param theme_data: The theme information """ if not theme_data.font_main_override: return QtCore.QRect(10, 0, self.width - 20, self.footer_start) @@ -350,8 +338,7 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Calculates the placement and size of the footer rectangle. - ``theme_data`` - The theme data. + :param theme_data: The theme data. """ if not theme_data.font_footer_override: return QtCore.QRect(10, self.footer_start, self.width - 20, self.height - self.footer_start) @@ -364,16 +351,11 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Sets the rectangle within which text should be rendered. - ``theme_data`` - The theme data. - - ``rect_main`` - The main text block. - - ``rect_footer`` - The footer text block. + :param theme_data: The theme data. + :param rect_main: The main text block. + :param rect_footer: The footer text block. """ - log.debug('_set_text_rectangle %s , %s' % (rect_main, rect_footer)) + self.log_debug('_set_text_rectangle %s , %s' % (rect_main, rect_footer)) self._rect = rect_main self._rect_footer = rect_footer self.page_width = self._rect.width() @@ -409,16 +391,13 @@ class Renderer(OpenLPMixin, RegistryMixin): def _paginate_slide(self, lines, line_end): """ Figure out how much text can appear on a slide, using the current theme settings. + **Note:** The smallest possible "unit" of text for a slide is one line. If the line is too long it will be cut off when displayed. - ``lines`` - The text to be fitted on the slide split into lines. - - ``line_end`` - The text added after each line. Either ``u' '`` or ``u'
``. + :param lines: The text to be fitted on the slide split into lines. + :param line_end: The text added after each line. Either ``u' '`` or ``u'
``. """ - log.debug('_paginate_slide - Start') formatted = [] previous_html = '' previous_raw = '' @@ -431,22 +410,19 @@ class Renderer(OpenLPMixin, RegistryMixin): else: previous_raw = separator.join(lines) formatted.append(previous_raw) - log.debug('_paginate_slide - End') + self.log_debug('_paginate_slide - End') return formatted def _paginate_slide_words(self, lines, line_end): """ Figure out how much text can appear on a slide, using the current theme settings. + **Note:** The smallest possible "unit" of text for a slide is one word. If one line is too long it will be processed word by word. This is sometimes need for **bible** verses. - ``lines`` - The text to be fitted on the slide split into lines. - - ``line_end`` - The text added after each line. Either ``u' '`` or ``u'
``. This is needed for **bibles**. + :param lines: The text to be fitted on the slide split into lines. + :param line_end: The text added after each line. Either ``u' '`` or ``u'
``. This is needed for **bibles**. """ - log.debug('_paginate_slide_words - Start') formatted = [] previous_html = '' previous_raw = '' @@ -476,7 +452,7 @@ class Renderer(OpenLPMixin, RegistryMixin): previous_html += html_line + line_end previous_raw += line + line_end formatted.append(previous_raw) - log.debug('_paginate_slide_words - End') + self.log_debug('_paginate_slide_words - End') return formatted def _get_start_tags(self, raw_text): @@ -488,8 +464,8 @@ class Renderer(OpenLPMixin, RegistryMixin): The first unicode string is the text, with correct closing tags. The second unicode string are OpenLP's opening formatting tags and the third unicode string the html opening formatting tags. - ``raw_text`` - The text to test. The text must **not** contain html tags, only OpenLP formatting tags are allowed:: + :param raw_text: The text to test. The text must **not** contain html tags, only OpenLP formatting tags + are allowed:: {st}{r}Text text text """ @@ -522,29 +498,18 @@ class Renderer(OpenLPMixin, RegistryMixin): and word based (word by word). It is assumed that this method is **only** called, when the lines/words to be rendered do **not** fit as a whole. - ``formatted`` - The list to append any slides. - - ``previous_html`` - The html text which is know to fit on a slide, but is not yet added to the list of slides. (unicode string) - - ``previous_raw`` - The raw text (with formatting tags) which is know to fit on a slide, but is not yet added to the list of - slides. (unicode string) - - ``html_list`` - The elements which do not fit on a slide and needs to be processed using the binary chop. The text contains - html. - - ``raw_list`` - The elements which do not fit on a slide and needs to be processed using the binary chop. The elements can - contain formatting tags. - - ``separator`` - The separator for the elements. For lines this is ``u'
'`` and for words this is ``u' '``. - - ``line_end`` - The text added after each "element line". Either ``u' '`` or ``u'
``. This is needed for bibles. + :param formatted: The list to append any slides. + :param previous_html: The html text which is know to fit on a slide, but is not yet added to the list of + slides. (unicode string) + :param previous_raw: The raw text (with formatting tags) which is know to fit on a slide, but is not yet added + to the list of slides. (unicode string) + :param html_list: The elements which do not fit on a slide and needs to be processed using the binary chop. + The text contains html. + :param raw_list: The elements which do not fit on a slide and needs to be processed using the binary chop. + The elements can contain formatting tags. + :param separator: The separator for the elements. For lines this is ``u'
'`` and for words this is ``u' '``. + :param line_end: The text added after each "element line". Either ``u' '`` or ``u'
``. This is needed for + bibles. """ smallest_index = 0 highest_index = len(html_list) - 1 @@ -591,8 +556,7 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Checks if the given ``text`` fits on a slide. If it does ``True`` is returned, otherwise ``False``. - ``text`` - The text to check. It may contain HTML tags. + :param text: The text to check. It may contain HTML tags. """ self.web_frame.evaluateJavaScript('show_text("%s")' % text.replace('\\', '\\\\').replace('\"', '\\\"')) return self.web_frame.contentsSize().height() <= self.empty_height @@ -600,6 +564,8 @@ class Renderer(OpenLPMixin, RegistryMixin): def _words_split(self, line): """ Split the slide up by word so can wrap better + + :param line: Line to be split """ # this parse we are to be wordy line = line.replace('\n', ' ') @@ -619,7 +585,8 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Adds the theme manager to the class dynamically """ - if not hasattr(self, '_theme_manager'): + print("renderer _get_theme_manager") + if not hasattr(self, '_theme_manager') or not self._theme_manager : self._theme_manager = Registry().get('theme_manager') return self._theme_manager diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index ecaeb0299..ba0c91390 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -63,12 +63,14 @@ class Display(QtGui.QGraphicsView): """ Constructor """ + print("Display - before super") if live: super(Display, self).__init__() # Overwrite the parent() method. self.parent = lambda: parent else: super(Display, self).__init__(parent) + print("Display - after super") self.is_live = live self.controller = controller self.screen = {} @@ -125,7 +127,9 @@ class MainDisplay(Display): """ Constructor """ + print("MainDisplay - before super") super(MainDisplay, self).__init__(parent, live, controller) + print("MainDisplay - after super") self.screens = ScreenList() self.rebuild_css = False self.hide_mode = None diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 46c318061..53feb24b5 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -468,7 +468,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ This constructor sets up the interface, the various managers, and the plugins. """ + print("Mainwindow - before super") super(MainWindow, self).__init__() + print("Mainwindow - after super") Registry().register('main_window', self) self.clipboard = self.application.clipboard() self.arguments = self.application.args @@ -541,6 +543,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ process the bootstrap post setup request """ + print("Mainwindow - bs post") self.preview_controller.panel.setVisible(Settings().value('user interface/preview panel')) self.live_controller.panel.setVisible(Settings().value('user interface/live panel')) self.load_settings() diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 0d0007549..0ea9e6833 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -316,7 +316,9 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Sets up the service manager, toolbars, list view, et al. """ + print("ServiceManager - before super") super(ServiceManager, self).__init__(parent) + print("ServiceManager - after super") self.active = build_icon(':/media/auto-start_active.png') self.inactive = build_icon(':/media/auto-start_inactive.png') self.service_items = [] @@ -332,6 +334,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ To be called as part of initialisation """ + print("ServiceManager - bs i") self.setup_ui(self) # Need to use event as called across threads and UI is updated QtCore.QObject.connect(self, QtCore.SIGNAL('servicemanager_set_item'), self.on_set_item) @@ -340,6 +343,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Can be set up as a late setup """ + print("ServiceManager - bs psu") self.service_note_form = ServiceNoteForm() self.service_item_edit_form = ServiceItemEditForm() self.start_time_form = StartTimeForm() @@ -1638,6 +1642,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Adds the Renderer to the class dynamically """ + print("serviceManager _get_renderer") if not hasattr(self, '_renderer'): self._renderer = Registry().get('renderer') return self._renderer diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 2f5e3b47a..a5f8f7712 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -135,7 +135,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ Constructor """ + print("ThemeManager - before super") super(ThemeManager, self).__init__(parent) + print("ThemeManager - after super") self.settings_section = 'themes' # Variables self.theme_list = [] @@ -145,6 +147,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ process the bootstrap initialise setup request """ + print("ThemeManager - bs i") self.setup_ui(self) self.global_theme = Settings().value(self.settings_section + '/global theme') self.build_theme_path() @@ -154,6 +157,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ process the bootstrap post setup request """ + print("ThemeManager - bs psu") self.theme_form = ThemeForm(self) self.theme_form.path = self.path self.file_rename_form = FileRenameForm() From 3a5c15a29ae0b917efa26263639ce91c7be53304 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 5 Jan 2014 17:12:42 +0000 Subject: [PATCH 29/41] Migrate renderer - cleanup --- openlp/core/lib/renderer.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index c4bccf904..7a566256d 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -75,8 +75,7 @@ class Renderer(OpenLPMixin, RegistryMixin): def bootstrap_initialise(self): """ - - + Initialise functions """ self.display = MainDisplay(None, False, self) self.display.setup() @@ -85,7 +84,6 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Updates the renderer's information about the current screen. """ - self.log_debug('Update Display') self._calculate_default() if self.display: self.display.close() @@ -126,7 +124,7 @@ class Renderer(OpenLPMixin, RegistryMixin): # if No file do not update cache if theme_data.background_filename: self.image_manager.add_image(theme_data.background_filename, - ImageSource.Theme, QtGui.QColor(theme_data.background_border_color)) + ImageSource.Theme, QtGui.QColor(theme_data.background_border_color)) def pre_render(self, override_theme_data=None): """ @@ -410,7 +408,6 @@ class Renderer(OpenLPMixin, RegistryMixin): else: previous_raw = separator.join(lines) formatted.append(previous_raw) - self.log_debug('_paginate_slide - End') return formatted def _paginate_slide_words(self, lines, line_end): @@ -452,7 +449,6 @@ class Renderer(OpenLPMixin, RegistryMixin): previous_html += html_line + line_end previous_raw += line + line_end formatted.append(previous_raw) - self.log_debug('_paginate_slide_words - End') return formatted def _get_start_tags(self, raw_text): @@ -466,7 +462,6 @@ class Renderer(OpenLPMixin, RegistryMixin): :param raw_text: The text to test. The text must **not** contain html tags, only OpenLP formatting tags are allowed:: - {st}{r}Text text text """ raw_tags = [] From 7fe95731f9e54a62c9b563ece2246eec1361568f Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 11 Jan 2014 17:52:01 +0000 Subject: [PATCH 30/41] Fix up Main display --- openlp/core/common/openlpmixin.py | 3 +- openlp/core/lib/renderer.py | 12 +-- openlp/core/lib/serviceitem.py | 11 ++- openlp/core/ui/maindisplay.py | 110 ++++++++++++-------------- openlp/core/ui/mainwindow.py | 3 +- openlp/core/ui/servicemanager.py | 8 +- openlp/core/ui/slidecontroller.py | 93 +++++++++++++++------- openlp/core/ui/thememanager.py | 3 +- openlp/plugins/media/lib/mediaitem.py | 2 +- 9 files changed, 139 insertions(+), 106 deletions(-) diff --git a/openlp/core/common/openlpmixin.py b/openlp/core/common/openlpmixin.py index dda448cc2..9e7b43539 100644 --- a/openlp/core/common/openlpmixin.py +++ b/openlp/core/common/openlpmixin.py @@ -33,7 +33,8 @@ import logging import inspect from openlp.core.common import trace_error_handler -DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent', 'drag_enter_event', 'drop_event'] +DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent', 'drag_enter_event', 'drop_event', 'on_controller_size_changed', + 'preview_size_changed', 'resizeEvent'] class OpenLPMixin(object): diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 7a566256d..415c5dfab 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -60,6 +60,8 @@ class Renderer(OpenLPMixin, RegistryMixin): print("Renderer - before super") super(Renderer, self).__init__(None) print("Renderer - after super") + # Need live behaviour if this is also working as a pseudo MainDisplay. + self.is_live = True self.screens = ScreenList() self.theme_level = ThemeLevel.Global self.global_theme_name = '' @@ -77,7 +79,7 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Initialise functions """ - self.display = MainDisplay(None, False, self) + self.display = MainDisplay(self) self.display.setup() def update_display(self): @@ -87,7 +89,7 @@ class Renderer(OpenLPMixin, RegistryMixin): self._calculate_default() if self.display: self.display.close() - self.display = MainDisplay(None, False, self) + self.display = MainDisplay(self) self.display.setup() self._theme_dimensions = {} @@ -114,6 +116,7 @@ class Renderer(OpenLPMixin, RegistryMixin): :param theme_name: The theme name """ + self.log_debug("_set_theme with theme %s" % theme_name) if theme_name not in self._theme_dimensions: theme_data = self.theme_manager.get_theme_data(theme_name) main_rect = self.get_main_rectangle(theme_data) @@ -169,9 +172,6 @@ class Renderer(OpenLPMixin, RegistryMixin): def set_global_theme(self): """ Set the global-level theme name. - - ``global_theme_name`` - The global-level theme's name. """ global_theme_name = Settings().value('themes/global theme') self._set_theme(global_theme_name) @@ -192,6 +192,7 @@ class Renderer(OpenLPMixin, RegistryMixin): :param item_theme_name: The item theme's name. """ + self.log_debug("set_item_theme with theme %s" % item_theme_name) self._set_theme(item_theme_name) self.item_theme_name = item_theme_name @@ -202,7 +203,6 @@ class Renderer(OpenLPMixin, RegistryMixin): :param theme_data: The theme to generated a preview for. :param force_page: Flag to tell message lines per page need to be generated. """ - self.log_debug('generate preview') # save value for use in format_slide self.force_page = force_page # build a service item to generate preview diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 738e23464..6bd764fed 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -31,8 +31,8 @@ The :mod:`serviceitem` provides the service item functionality including the type and capability of an item. """ -import cgi import datetime +import html import logging import os import uuid @@ -241,9 +241,8 @@ class ServiceItem(object): self.theme_data, self.main, self.footer = self.renderer.pre_render() if self.service_item_type == ServiceItemType.Text: log.debug('Formatting slides: %s' % self.title) - # Save rendered pages to this dict. In the case that a slide is used - # twice we can use the pages saved to the dict instead of rendering - # them again. + # Save rendered pages to this dict. In the case that a slide is used twice we can use the pages saved to + # the dict instead of rendering them again. previous_pages = {} for slide in self._raw_frames: verse_tag = slide['verseTag'] @@ -254,11 +253,11 @@ class ServiceItem(object): previous_pages[verse_tag] = (slide['raw_slide'], pages) for page in pages: page = page.replace('
', '{br}') - html = expand_tags(cgi.escape(page.rstrip())) + html_data = expand_tags(html.escape(page.rstrip())) self._display_frames.append({ 'title': clean_tags(page), 'text': clean_tags(page.rstrip()), - 'html': html.replace('&nbsp;', ' '), + 'html': html_data.replace('&nbsp;', ' '), 'verseTag': verse_tag }) elif self.service_item_type == ServiceItemType.Image or self.service_item_type == ServiceItemType.Command: diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index ba0c91390..3eb3179ff 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -44,7 +44,7 @@ import sys from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL from PyQt4.phonon import Phonon -from openlp.core.common import Registry, Settings, translate +from openlp.core.common import Registry, OpenLPMixin, Settings, translate from openlp.core.lib import ServiceItem, ImageSource, build_html, expand_tags, image_to_byte from openlp.core.lib.theme import BackgroundType @@ -59,20 +59,22 @@ class Display(QtGui.QGraphicsView): This is a general display screen class. Here the general display settings will done. It will be used as specialized classes by Main Display and Preview display. """ - def __init__(self, parent, live, controller): + def __init__(self, parent): """ Constructor """ - print("Display - before super") - if live: + print("Display - before super", parent, type(parent)) + self.is_live = False + if hasattr(parent, 'is_live') and parent.is_live: + self.is_live = True + if self.is_live: super(Display, self).__init__() # Overwrite the parent() method. self.parent = lambda: parent else: super(Display, self).__init__(parent) print("Display - after super") - self.is_live = live - self.controller = controller + self.controller = parent self.screen = {} # FIXME: On Mac OS X (tested on 10.7) the display screen is corrupt with # OpenGL. Only white blank screen is shown on the 2nd monitor all the @@ -85,9 +87,7 @@ class Display(QtGui.QGraphicsView): """ Set up and build the screen base """ - log.debug('Start Display base setup (live = %s)' % self.is_live) self.setGeometry(self.screen['size']) - log.debug('Setup webView') self.web_view = QtWebKit.QWebView(self) self.web_view.setGeometry(0, 0, self.screen['size'].width(), self.screen['size'].height()) self.web_view.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled, True) @@ -108,27 +108,28 @@ class Display(QtGui.QGraphicsView): def resizeEvent(self, event): """ React to resizing of this display + + :param event: The event to be handled """ self.web_view.setGeometry(0, 0, self.width(), self.height()) - def is_web_loaded(self): + def is_web_loaded(self, field=None): """ Called by webView event to show display is fully loaded """ - log.debug('is web loaded') self.web_loaded = True -class MainDisplay(Display): +class MainDisplay(OpenLPMixin, Display): """ This is the display screen as a specialized class from the Display class """ - def __init__(self, parent, live, controller): + def __init__(self, parent): """ Constructor """ print("MainDisplay - before super") - super(MainDisplay, self).__init__(parent, live, controller) + super(MainDisplay, self).__init__(parent) print("MainDisplay - after super") self.screens = ScreenList() self.rebuild_css = False @@ -136,7 +137,7 @@ class MainDisplay(Display): self.override = {} self.retranslateUi() self.media_object = None - if live: + if self.is_live: self.audio_player = AudioPlayer(self) else: self.audio_player = None @@ -167,6 +168,8 @@ class MainDisplay(Display): def set_transparency(self, enabled): """ Set the transparency of the window + + :param enabled: Is transparency enabled """ if enabled: self.setAutoFillBackground(False) @@ -192,7 +195,7 @@ class MainDisplay(Display): """ Set up and build the output screen """ - log.debug('Start MainDisplay setup (live = %s)' % self.is_live) + self.log_debug('Start MainDisplay setup (live = %s)' % self.is_live) self.screen = self.screens.current self.setVisible(False) Display.setup(self) @@ -219,20 +222,15 @@ class MainDisplay(Display): service_item.bg_image_bytes = image_to_byte(self.initial_fame) self.web_view.setHtml(build_html(service_item, self.screen, self.is_live, None, plugins=self.plugin_manager.plugins)) - self.__hideMouse() - log.debug('Finished MainDisplay setup') + self._hide_mouse() def text(self, slide, animate=True): """ Add the slide text from slideController - ``slide`` - The slide text to be displayed - - ``animate`` - Perform transitions if applicable when setting the text + :param slide: The slide text to be displayed + :param animate: Perform transitions if applicable when setting the text """ - log.debug('text to display') # Wait for the webview to update before displaying text. while not self.web_loaded: self.application.process_events() @@ -251,10 +249,9 @@ class MainDisplay(Display): """ Display an alert. - ``text`` - The text to be displayed. + :param text: The text to be displayed. + :param location: Where on the screen is the text to be displayed """ - log.debug('alert to display') # First we convert <>& marks to html variants, then apply # formattingtags, finally we double all backslashes for JavaScript. text_prepared = expand_tags(cgi.escape(text)).replace('\\', '\\\\').replace('\"', '\\\"') @@ -281,6 +278,9 @@ class MainDisplay(Display): def direct_image(self, path, background): """ API for replacement backgrounds so Images are added directly to cache. + + :param path: Path to Image + :param background: The background color """ self.image_manager.add_image(path, ImageSource.ImagePlugin, background) if not hasattr(self, 'service_item'): @@ -298,12 +298,9 @@ class MainDisplay(Display): Add an image as the background. The image has already been added to the cache. - ``path`` - The path to the image to be displayed. **Note**, the path is only - passed to identify the image. If the image has changed it has to be - re-added to the image manager. + :param path: The path to the image to be displayed. **Note**, the path is only passed to identify the image. + If the image has changed it has to be re-added to the image manager. """ - log.debug('image to display') image = self.image_manager.get_image_bytes(path, ImageSource.ImagePlugin) self.controller.media_controller.media_reset(self.controller) self.display_image(image) @@ -311,6 +308,8 @@ class MainDisplay(Display): def display_image(self, image): """ Display an image, as is. + + :param image: The image to be displayed """ self.setGeometry(self.screen['size']) if image: @@ -321,10 +320,8 @@ class MainDisplay(Display): def reset_image(self): """ - Reset the background image to the service item image. Used after the - image plugin has changed the background. + Reset the background image to the service item image. Used after the image plugin has changed the background. """ - log.debug('reset_image') if hasattr(self, 'service_item'): self.display_image(self.service_item.bg_image_bytes) else: @@ -339,7 +336,6 @@ class MainDisplay(Display): """ Generates a preview of the image displayed. """ - log.debug('preview for %s', self.is_live) was_visible = self.isVisible() self.application.process_events() # We must have a service item to preview. @@ -371,10 +367,11 @@ class MainDisplay(Display): def build_html(self, service_item, image_path=''): """ - Store the service_item and build the new HTML from it. Add the - HTML to the display + Store the service_item and build the new HTML from it. Add the HTML to the display + + :param service_item: The Service item to be used + :param image_path: Where the image resides. """ - log.debug('build_html') self.web_loaded = False self.initial_fame = None self.service_item = service_item @@ -396,17 +393,14 @@ class MainDisplay(Display): BackgroundType.to_string(BackgroundType.Transparent)) if self.service_item.theme_data.background_filename: self.service_item.bg_image_bytes = self.image_manager.get_image_bytes( - self.service_item.theme_data.background_filename, ImageSource.Theme - ) + self.service_item.theme_data.background_filename, ImageSource.Theme) if image_path: image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin) else: image_bytes = None html = build_html(self.service_item, self.screen, self.is_live, background, image_bytes, plugins=self.plugin_manager.plugins) - log.debug('buildHtml - pre setHtml') self.web_view.setHtml(html) - log.debug('buildHtml - post setHtml') if service_item.foot_text: self.footer(service_item.foot_text) # if was hidden keep it hidden @@ -415,22 +409,24 @@ class MainDisplay(Display): Registry().execute('slidecontroller_live_unblank') else: self.hide_display(self.hide_mode) - self.__hideMouse() + self._hide_mouse() def footer(self, text): """ Display the Footer + + :param text: footer text to be displayed """ - log.debug('footer') js = 'show_footer(\'' + text.replace('\\', '\\\\').replace('\'', '\\\'') + '\')' self.frame.evaluateJavaScript(js) def hide_display(self, mode=HideMode.Screen): """ - Hide the display by making all layers transparent - Store the images so they can be replaced when required + Hide the display by making all layers transparent Store the images so they can be replaced when required + + :param mode: How the screen is to be hidden """ - log.debug('hide_display mode = %d', mode) + self.log_debug('hide_display mode = %d' % mode) if self.screens.display_count == 1: # Only make visible if setting enabled. if not Settings().value('core/display on monitor'): @@ -453,7 +449,6 @@ class MainDisplay(Display): Show the stored layers so the screen reappears as it was originally. Make the stored images None to release memory. """ - log.debug('show_display') if self.screens.display_count == 1: # Only make visible if setting enabled. if not Settings().value('core/display on monitor'): @@ -466,7 +461,7 @@ class MainDisplay(Display): if self.is_live: Registry().execute('live_display_active') - def __hideMouse(self): + def _hide_mouse(self): """ Hide mouse cursor when moved over display. """ @@ -522,11 +517,10 @@ class MainDisplay(Display): live_controller = property(_get_live_controller) -class AudioPlayer(QtCore.QObject): +class AudioPlayer(OpenLPMixin, QtCore.QObject): """ This Class will play audio only allowing components to work with a soundtrack independent of the user interface. """ - log.info('AudioPlayer Loaded') def __init__(self, parent): """ @@ -535,7 +529,6 @@ class AudioPlayer(QtCore.QObject): ``parent`` The parent widget. """ - log.debug('AudioPlayer Initialisation started') super(AudioPlayer, self).__init__(parent) self.current_index = -1 self.playlist = [] @@ -569,7 +562,7 @@ class AudioPlayer(QtCore.QObject): When the audio track finishes. """ if self.repeat: - log.debug('Repeat is enabled... here we go again!') + self.log_debug('Repeat is enabled... here we go again!') self.media_object.clearQueue() self.media_object.clear() self.current_index = -1 @@ -594,7 +587,6 @@ class AudioPlayer(QtCore.QObject): """ We want to play the file so start it """ - log.debug('AudioPlayer.play() called') if self.current_index == -1: self.on_about_to_finish() self.media_object.play() @@ -603,22 +595,19 @@ class AudioPlayer(QtCore.QObject): """ Pause the Audio """ - log.debug('AudioPlayer.pause() called') self.media_object.pause() def stop(self): """ Stop the Audio and clean up """ - log.debug('AudioPlayer.stop() called') self.media_object.stop() def add_to_playlist(self, file_names): """ Add another file to the playlist. - ``file_names`` - A list with files to be added to the playlist. + :param file_names: A list with files to be added to the playlist. """ if not isinstance(file_names, list): file_names = [file_names] @@ -643,6 +632,8 @@ class AudioPlayer(QtCore.QObject): def go_to(self, index): """ Go to a particular track in the list + + :param index: The track to go to """ is_playing = self.media_object.state() == Phonon.PlayingState self.media_object.clearQueue() @@ -655,6 +646,9 @@ class AudioPlayer(QtCore.QObject): def connectSlot(self, signal, slot): """ Connect a slot to a signal on the media object. Used by slidecontroller to connect to audio object. + + :param slot: The slot the signal is attached to. + :param signal: The signal to be fired """ QtCore.QObject.connect(self.media_object, signal, slot) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 53feb24b5..de13c0301 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -548,6 +548,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.live_controller.panel.setVisible(Settings().value('user interface/live panel')) self.load_settings() self.restore_current_media_manager_item() + Registry().execute('theme_update_global') def restore_current_media_manager_item(self): """ @@ -676,7 +677,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): else: self.active_plugin.toggle_status(PluginStatus.Inactive) # Set global theme and - Registry().execute('theme_update_global', self.theme_manager_contents.global_theme) + Registry().execute('theme_update_global') self.theme_manager_contents.load_first_time_themes() # Check if any Bibles downloaded. If there are, they will be processed. Registry().execute('bibles_load_list', True) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 0ea9e6833..c43b9853b 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -1024,9 +1024,9 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Called by the SlideController to select the next service item. """ - if not self.service_manager_list.selected_items(): + if not self.service_manager_list.selectedItems(): return - selected = self.service_manager_list.selected_items()[0] + selected = self.service_manager_list.selectedItems()[0] look_for = 0 service_iterator = QtGui.QTreeWidgetItemIterator(self.service_manager_list) while service_iterator.value(): @@ -1044,9 +1044,9 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage :param last_slide: Is this the last slide in the service_item. """ - if not self.service_manager_list.selected_items(): + if not self.service_manager_list.selectedItems(): return - selected = self.service_manager_list.selected_items()[0] + selected = self.service_manager_list.selectedItems()[0] prev_item = None prev_item_last_slide = None service_iterator = QtGui.QTreeWidgetItemIterator(self.service_manager_list) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 31779a0e9..956eedf6a 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -93,8 +93,7 @@ class DisplayController(QtGui.QWidget): def send_to_plugins(self, *args): """ - This is the generic function to send signal for control widgets, - created from within other plugins + This is the generic function to send signal for control widgets, created from within other plugins This function is needed to catch the current controller """ sender = self.sender().objectName() if self.sender().objectName() else self.sender().text() @@ -277,7 +276,8 @@ class SlideController(DisplayController): self.toolbar.add_toolbar_widget(self.song_menu) # Stuff for items with background audio. # FIXME: object name should be changed. But this requires that we migrate the shortcut. - self.audio_pause_item = self.toolbar.add_toolbar_action('audioPauseItem', + self.audio_pause_item = self.toolbar.add_toolbar_action( + 'audioPauseItem', icon=':/slides/media_playback_pause.png', text=translate('OpenLP.SlideController', 'Pause Audio'), tooltip=translate('OpenLP.SlideController', 'Pause audio.'), checked=False, visible=False, category=self.category, context=QtCore.Qt.WindowShortcut, @@ -318,7 +318,7 @@ class SlideController(DisplayController): self.slide_layout.setSpacing(0) self.slide_layout.setMargin(0) self.slide_layout.setObjectName('SlideLayout') - self.preview_display = Display(self, self.is_live, self) + self.preview_display = Display(self) self.preview_display.setGeometry(QtCore.QRect(0, 0, 300, 300)) self.preview_display.screen = {'size': self.preview_display.geometry()} self.preview_display.setup() @@ -532,7 +532,7 @@ class SlideController(DisplayController): # rebuild display as screen size changed if self.display: self.display.close() - self.display = MainDisplay(self, self.is_live, self) + self.display = MainDisplay(self) self.display.setup() if self.is_live: self.__add_actions_to_widget(self.display) @@ -566,17 +566,15 @@ class SlideController(DisplayController): def preview_size_changed(self): """ - Takes care of the SlidePreview's size. Is called when one of the the - splitters is moved or when the screen size is changed. Note, that this - method is (also) called frequently from the mainwindow *paintEvent*. + Takes care of the SlidePreview's size. Is called when one of the the splitters is moved or when the screen + size is changed. Note, that this method is (also) called frequently from the mainwindow *paintEvent*. """ if self.ratio < self.preview_frame.width() / self.preview_frame.height(): # We have to take the height as limit. max_height = self.preview_frame.height() - self.grid.margin() * 2 self.slide_preview.setFixedSize(QtCore.QSize(max_height * self.ratio, max_height)) self.preview_display.setFixedSize(QtCore.QSize(max_height * self.ratio, max_height)) - self.preview_display.screen = { - 'size': self.preview_display.geometry()} + self.preview_display.screen = {'size': self.preview_display.geometry()} else: # We have to take the width as limit. max_width = self.preview_frame.width() - self.grid.margin() * 2 @@ -683,6 +681,8 @@ class SlideController(DisplayController): def enable_preview_tool_bar(self, item): """ Allows the Preview toolbar to be customised + + :param item: The current service item """ # Work-around for OS X, hide and then show the toolbar # See bug #791050 @@ -712,6 +712,8 @@ class SlideController(DisplayController): """ Method to install the service item into the controller Called by plugins + + :param item: The current service item """ item.render() slide_no = 0 @@ -723,6 +725,8 @@ class SlideController(DisplayController): def replace_service_manager_item(self, item): """ Replacement item following a remote edit + + :param item: The current service item """ if item == self.service_item: self._process_item(item, self.preview_widget.current_slide_number()) @@ -731,6 +735,9 @@ class SlideController(DisplayController): """ Method to install the service item into the controller and request the correct toolbar for the plugin. Called by :class:`~openlp.core.ui.ServiceManager` + + :param item: The current service item + :param slide_no: The slide number to select """ # If no valid slide number is specified we take the first one, but we remember the initial value to see if we # should reload the song or not @@ -755,6 +762,9 @@ class SlideController(DisplayController): def _process_item(self, service_item, slide_no): """ Loads a ServiceItem into the system from ServiceManager. Display the slide number passed. + + :param service_item: The current service item + :param slide_no: The slide number to select """ self.on_stop_loop() old_item = self.service_item @@ -762,8 +772,9 @@ class SlideController(DisplayController): self.service_item = copy.copy(service_item) if old_item and self.is_live and old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay): self._reset_blank() - Registry().execute( - '%s_start' % service_item.name.lower(), [service_item, self.is_live, self.hide_mode(), slide_no]) + if service_item.is_command(): + Registry().execute( + '%s_start' % service_item.name.lower(), [service_item, self.is_live, self.hide_mode(), slide_no]) self.slide_list = {} if self.is_live: self.song_menu.menu().clear() @@ -789,7 +800,7 @@ class SlideController(DisplayController): self.set_audio_items_visibility(True) row = 0 width = self.main_window.control_splitter.sizes()[self.split] - for framenumber, frame in enumerate(self.service_item.get_frames()): + for frame_number, frame in enumerate(self.service_item.get_frames()): if self.service_item.is_text(): if frame['verseTag']: # These tags are already translated. @@ -798,7 +809,7 @@ class SlideController(DisplayController): two_line_def = '%s\n%s' % (verse_def[0], verse_def[1:]) row = two_line_def if verse_def not in self.slide_list: - self.slide_list[verse_def] = framenumber + self.slide_list[verse_def] = frame_number if self.is_live: self.song_menu.menu().addAction(verse_def, self.on_song_bar_handler) else: @@ -808,7 +819,7 @@ class SlideController(DisplayController): row += 1 self.slide_list[str(row)] = row - 1 # If current slide set background to image - if not self.service_item.is_command() and framenumber == slide_no: + if not self.service_item.is_command() and frame_number == slide_no: self.service_item.bg_image_bytes = \ self.image_manager.get_image_bytes(frame['path'], ImageSource.ImagePlugin) self.preview_widget.replace_service_item(self.service_item, width, slide_no) @@ -832,10 +843,11 @@ class SlideController(DisplayController): self.on_media_close() Registry().execute('slidecontroller_%s_started' % self.type_prefix, [service_item]) - # Screen event methods def on_slide_selected_index(self, message): """ Go to the requested slide + + :param message: remote message to be processed. """ index = int(message[0]) if not self.service_item: @@ -880,6 +892,8 @@ class SlideController(DisplayController): def on_blank_display(self, checked=None): """ Handle the blank screen button actions + + :param checked: the new state of the of the widget """ if checked is None: checked = self.blank_screen.isChecked() @@ -899,6 +913,8 @@ class SlideController(DisplayController): def on_theme_display(self, checked=None): """ Handle the Theme screen button + + :param checked: the new state of the of the widget """ if checked is None: checked = self.theme_screen.isChecked() @@ -918,6 +934,8 @@ class SlideController(DisplayController): def on_hide_display(self, checked=None): """ Handle the Hide screen button + + :param checked: the new state of the of the widget """ if checked is None: checked = self.desktop_screen.isChecked() @@ -984,8 +1002,9 @@ class SlideController(DisplayController): def slide_selected(self, start=False): """ - Generate the preview when you click on a slide. - if this is the Live Controller also display on the screen + Generate the preview when you click on a slide. If this is the Live Controller also display on the screen + + :param start: """ row = self.preview_widget.current_slide_number() self.selected_row = 0 @@ -1008,12 +1027,13 @@ class SlideController(DisplayController): self.update_preview() self.selected_row = row self.preview_widget.change_slide(row) - Registry().execute('slidecontroller_%s_changed' % self.type_prefix, row) self.display.setFocus() def on_slide_change(self, row): """ The slide has been changed. Update the slidecontroller accordingly + + :param row: Row to be selected """ self.preview_widget.change_slide(row) self.update_preview() @@ -1046,20 +1066,24 @@ class SlideController(DisplayController): def on_slide_selected_next_action(self, checked): """ - Wrapper function from create_action so we can throw away the - incorrect parameter + Wrapper function from create_action so we can throw away the incorrect parameter + + :param checked: the new state of the of the widget """ self.on_slide_selected_next() def on_slide_selected_next(self, wrap=None): """ Go to the next slide. + + :param wrap: Are we wrapping round the service item """ if not self.service_item: return - Registry().execute('%s_next' % self.service_item.name.lower(), [self.service_item, self.is_live]) - if self.service_item.is_command() and self.is_live: - self.update_preview() + if self.service_item.is_command(): + Registry().execute('%s_next' % self.service_item.name.lower(), [self.service_item, self.is_live]) + if self.is_live: + self.update_preview() else: row = self.preview_widget.current_slide_number() + 1 if row == self.preview_widget.slide_count(): @@ -1084,9 +1108,10 @@ class SlideController(DisplayController): """ if not self.service_item: return - Registry().execute('%s_previous' % self.service_item.name.lower(), [self.service_item, self.is_live]) - if self.service_item.is_command() and self.is_live: - self.update_preview() + if self.service_item.is_command(): + Registry().execute('%s_previous' % self.service_item.name.lower(), [self.service_item, self.is_live]) + if self.is_live: + self.update_preview() else: row = self.preview_widget.current_slide_number() - 1 if row == -1: @@ -1129,6 +1154,8 @@ class SlideController(DisplayController): def on_play_slides_loop(self, checked=None): """ Start or stop 'Play Slides in Loop' + + :param checked: is the check box checked. """ if checked is None: checked = self.play_slides_loop.isChecked() @@ -1150,6 +1177,8 @@ class SlideController(DisplayController): def on_play_slides_once(self, checked=None): """ Start or stop 'Play Slides to End' + + :param checked: is the check box checked. """ if checked is None: checked = self.play_slides_once.isChecked() @@ -1177,6 +1206,8 @@ class SlideController(DisplayController): def set_audio_pause_clicked(self, checked): """ Pause the audio player + + :param checked: is the check box checked. """ if not self.audio_pause_item.isVisible(): return @@ -1188,6 +1219,8 @@ class SlideController(DisplayController): def timerEvent(self, event): """ If the timer event is for this window select next slide + + :param event: The triggered event """ if event.timerId() == self.timer_id: self.on_slide_selected_next(self.play_slides_loop.isChecked()) @@ -1235,6 +1268,8 @@ class SlideController(DisplayController): def on_media_start(self, item): """ Respond to the arrival of a media service item + + :param item: The service item to be processed """ self.media_controller.video(self.controller_type, item, self.hide_mode()) if not self.is_live: @@ -1288,6 +1323,8 @@ class SlideController(DisplayController): def on_audio_time_remaining(self, time): """ Update how much time is remaining + + :param time: the time remainings """ seconds = self.display.audio_player.media_object.remainingTime() // 1000 minutes = seconds // 60 @@ -1335,7 +1372,7 @@ class SlideController(DisplayController): """ Adds the service manager to the class dynamically """ - if not hasattr(self, '_service_manager'): + if not hasattr(self, '_service_manager') or not self._service_manager: self._service_manager = Registry().get('service_manager') return self._service_manager diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index a5f8f7712..2632477eb 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -515,8 +515,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): def over_write_message_box(self, theme_name): """ Display a warning box to the user that a theme already exists + :param theme_name: Name of the theme. - :return Confirm if the theme is to be overeritten. + :return Confirm if the theme is to be overwritten. """ ret = QtGui.QMessageBox.question(self, translate('OpenLP.ThemeManager', 'Theme Already Exists'), translate('OpenLP.ThemeManager', diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 4dbe4c636..644b573b9 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -74,7 +74,7 @@ class MediaMediaItem(MediaManagerItem): self.display_controller.controller_layout = QtGui.QVBoxLayout() self.media_controller.register_controller(self.display_controller) self.media_controller.set_controls_visible(self.display_controller, False) - self.display_controller.preview_display = Display(self.display_controller, False, self.display_controller) + self.display_controller.preview_display = Display(self.display_controller) self.display_controller.preview_display.hide() self.display_controller.preview_display.setGeometry(QtCore.QRect(0, 0, 300, 300)) self.display_controller.preview_display.screen = {'size': self.display_controller.preview_display.geometry()} From 75b27422ad514843a71d14df6a8c4c427888eac1 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 11 Jan 2014 19:31:06 +0000 Subject: [PATCH 31/41] Add renderer tests --- .../openlp_core_lib/test_renderer.py | 89 +++++++++++++++++++ .../openlp_core_ui/test_servicemanager.py | 8 -- 2 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 tests/functional/openlp_core_lib/test_renderer.py diff --git a/tests/functional/openlp_core_lib/test_renderer.py b/tests/functional/openlp_core_lib/test_renderer.py new file mode 100644 index 000000000..d0aa82b74 --- /dev/null +++ b/tests/functional/openlp_core_lib/test_renderer.py @@ -0,0 +1,89 @@ +# -*- 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 # +############################################################################### +""" +Package to test the openlp.core.ui.renderer package. +""" +from unittest import TestCase + +from PyQt4 import QtCore + +from openlp.core.common import Registry +from openlp.core.lib import Renderer, ScreenList + +from tests.interfaces import MagicMock + +SCREEN = { + 'primary': False, + 'number': 1, + 'size': QtCore.QRect(0, 0, 1024, 768) +} + + +class TestRenderer(TestCase): + + def setUp(self): + """ + Set up the components need for all tests. + """ + # Mocked out desktop object + self.desktop = MagicMock() + self.desktop.primaryScreen.return_value = SCREEN['primary'] + self.desktop.screenCount.return_value = SCREEN['number'] + self.desktop.screenGeometry.return_value = SCREEN['size'] + self.screens = ScreenList.create(self.desktop) + Registry.create() + + def tearDown(self): + """ + Delete QApplication. + """ + del self.screens + + def initial_renderer_test(self): + """ + Test the initial renderer state . + """ + # GIVEN: A new renderer instance. + renderer = Renderer() + # WHEN: the default renderer is built. + # THEN: The renderer should be a live controller. + self.assertEqual(renderer.is_live, True, 'The base renderer should be a live controller') + + def default_screen_layout_test(self): + """ + Test the default layout calculations. + """ + # GIVEN: A new renderer instance. + renderer = Renderer() + # WHEN: given the default screen size has been created. + # THEN: The renderer have created a default screen. + self.assertEqual(renderer.width, 1024, 'The base renderer should be a live controller') + self.assertEqual(renderer.height, 768, 'The base renderer should be a live controller') + self.assertEqual(renderer.screen_ratio, 0.75, 'The base renderer should be a live controller') + self.assertEqual(renderer.footer_start, 691, 'The base renderer should be a live controller') \ No newline at end of file diff --git a/tests/functional/openlp_core_ui/test_servicemanager.py b/tests/functional/openlp_core_ui/test_servicemanager.py index 583a8c09e..3de560786 100644 --- a/tests/functional/openlp_core_ui/test_servicemanager.py +++ b/tests/functional/openlp_core_ui/test_servicemanager.py @@ -44,19 +44,11 @@ class TestServiceManager(TestCase): Create the UI """ Registry.create() - #self.app = QtGui.QApplication([]) - #ScreenList.create(self.app.desktop()) - #Registry().register('application', MagicMock()) - #with patch('openlp.core.lib.PluginManager'): - # self.main_window = MainWindow() - #self.service_manager = Registry().get('service_manager') def tearDown(self): """ Delete all the C++ objects at the end so that we don't have a segfault """ - #del self.main_window - #del self.app pass def initial_service_manager_test(self): From 9fc4f0c3397eaacce382354376493c01d3771481 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 11 Jan 2014 19:46:31 +0000 Subject: [PATCH 32/41] Add Main display tests --- .../openlp_core_ui/test_maindisplay.py | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 tests/functional/openlp_core_ui/test_maindisplay.py diff --git a/tests/functional/openlp_core_ui/test_maindisplay.py b/tests/functional/openlp_core_ui/test_maindisplay.py new file mode 100644 index 000000000..dffc6ec16 --- /dev/null +++ b/tests/functional/openlp_core_ui/test_maindisplay.py @@ -0,0 +1,81 @@ +# -*- 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 # +############################################################################### +""" +Package to test the openlp.core.ui.slidecontroller package. +""" +from unittest import TestCase + +from PyQt4 import QtCore + +from openlp.core.common import Registry +from openlp.core.lib import ScreenList +from openlp.core.ui import MainDisplay + +from tests.interfaces import MagicMock, patch + +SCREEN = { + 'primary': False, + 'number': 1, + 'size': QtCore.QRect(0, 0, 1024, 768) +} + + +class TestMainDisplay(TestCase): + + def setUp(self): + """ + Set up the components need for all tests. + """ + # Mocked out desktop object + self.desktop = MagicMock() + self.desktop.primaryScreen.return_value = SCREEN['primary'] + self.desktop.screenCount.return_value = SCREEN['number'] + self.desktop.screenGeometry.return_value = SCREEN['size'] + self.screens = ScreenList.create(self.desktop) + Registry.create() + + def tearDown(self): + """ + Delete QApplication. + """ + del self.screens + + def initial_main_display_test(self): + """ + Test the initial Main Display state . + """ + # GIVEN: A new slideController instance. + display = MagicMock() + display.is_live = True + + # WHEN: the default controller is built. + main_display = MainDisplay(display) + + # THEN: The controller should not be a live controller. + self.assertEqual(main_display.is_live, True, 'The main display should be a live controller') From 743ad7b44aaa34df82c981545fc9fb0656542780 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 11 Jan 2014 21:29:01 +0000 Subject: [PATCH 33/41] Clean up inits --- openlp/core/__init__.py | 32 ++++++++------- openlp/core/common/__init__.py | 2 +- openlp/core/lib/__init__.py | 2 +- openlp/core/lib/mediamanageritem.py | 61 ++++++++++++++++++----------- openlp/core/ui/media/__init__.py | 2 +- openlp/core/utils/__init__.py | 3 +- 6 files changed, 61 insertions(+), 41 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index b5a922617..948525839 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -43,7 +43,7 @@ from traceback import format_exception from PyQt4 import QtCore, QtGui -from openlp.core.common import Registry, AppLocation, Settings, UiStrings, check_directory_exists +from openlp.core.common import Registry, OpenLPMixin, AppLocation, Settings, UiStrings, check_directory_exists from openlp.core.lib import ScreenList from openlp.core.resources import qInitResources from openlp.core.ui.mainwindow import MainWindow @@ -58,6 +58,7 @@ __all__ = ['OpenLP', 'main'] log = logging.getLogger() + NT_REPAIR_STYLESHEET = """ QMainWindow::separator { @@ -81,7 +82,7 @@ QToolBar """ -class OpenLP(QtGui.QApplication): +class OpenLP(OpenLPMixin, QtGui.QApplication): """ The core application class. This class inherits from Qt's QApplication class in order to provide the core of the application. @@ -101,6 +102,8 @@ class OpenLP(QtGui.QApplication): def run(self, args): """ Run the OpenLP application. + + :param args: Some Args """ self.is_event_loop_active = False # On Windows, the args passed into the constructor are ignored. Not very handy, so set the ones we want to use. @@ -172,25 +175,20 @@ class OpenLP(QtGui.QApplication): self.shared_memory.create(1) return False - def hook_exception(self, exctype, value, traceback): + def hook_exception(self, exc_type, value, traceback): """ Add an exception hook so that any uncaught exceptions are displayed in this window rather than somewhere where users cannot see it and cannot report when we encounter these problems. - ``exctype`` - The class of exception. - - ``value`` - The actual exception object. - - ``traceback`` - A traceback object with the details of where the exception occurred. + :param exc_type: The class of exception. + :param value: The actual exception object. + :param traceback: A traceback object with the details of where the exception occurred. """ # We can't log.exception here because the last exception no longer exists, we're actually busy handling it. - log.critical(''.join(format_exception(exctype, value, traceback))) + log.critical(''.join(format_exception(exc_type, value, traceback))) if not hasattr(self, 'exception_form'): self.exception_form = ExceptionForm() - self.exception_form.exception_text_edit.setPlainText(''.join(format_exception(exctype, value, traceback))) + self.exception_form.exception_text_edit.setPlainText(''.join(format_exception(exc_type, value, traceback))) self.set_normal_cursor() self.exception_form.exec_() @@ -198,7 +196,6 @@ class OpenLP(QtGui.QApplication): """ Wrapper to make ProcessEvents visible and named correctly """ - log.debug('processing event flush') self.processEvents() def set_busy_cursor(self): @@ -218,6 +215,8 @@ class OpenLP(QtGui.QApplication): def event(self, event): """ Enables direct file opening on OS X + + :param event: The event """ if event.type() == QtCore.QEvent.FileOpen: file_name = event.file() @@ -231,6 +230,8 @@ class OpenLP(QtGui.QApplication): def set_up_logging(log_path): """ Setup our logging using log_path + + :param log_path: the path """ check_directory_exists(log_path, True) filename = os.path.join(log_path, 'openlp.log') @@ -244,7 +245,8 @@ def set_up_logging(log_path): def main(args=None): """ The main function which parses command line options and then runs - the PyQt4 Application. + + :param args: Some args """ # Set up command line options. usage = 'Usage: %prog [options] [qt-options]' diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py index 11e9d82b2..8963213d3 100644 --- a/openlp/core/common/__init__.py +++ b/openlp/core/common/__init__.py @@ -38,7 +38,7 @@ import traceback from PyQt4 import QtCore -log = logging.getLogger(__name__) +log = logging.getLogger(__name__+'.__init__') FIRST_CAMEL_REGEX = re.compile('(.)([A-Z][a-z]+)') diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 549f0879c..d747cb5ba 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -39,7 +39,7 @@ from PyQt4 import QtCore, QtGui, Qt from openlp.core.common import translate -log = logging.getLogger(__name__) +log = logging.getLogger(__name__+'.__init__') class ServiceItemContext(object): diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 34b24e0c2..c45a963d4 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -332,8 +332,7 @@ class MediaManagerItem(QtGui.QWidget): """ Turn file from Drag and Drop into an array so the Validate code can run it. - ``data`` - A dictionary containing the list of files to be loaded and the target + :param data: A dictionary containing the list of files to be loaded and the target """ new_files = [] error_shown = False @@ -353,9 +352,8 @@ class MediaManagerItem(QtGui.QWidget): def dnd_move_internal(self, target): """ Handle internal moving of media manager items - - ``target`` - The target of the DnD action +s + :param target: The target of the DnD action """ pass @@ -364,11 +362,8 @@ class MediaManagerItem(QtGui.QWidget): Process a list for files either from the File Dialog or from Drag and Drop - ``files`` - The files to be loaded. - - ``target_group`` - The QTreeWidgetItem of the group that will be the parent of the added files + :param files: The files to be loaded. + :param target_group: The QTreeWidgetItem of the group that will be the parent of the added files """ names = [] full_list = [] @@ -399,6 +394,8 @@ class MediaManagerItem(QtGui.QWidget): def context_menu(self, point): """ Display a context menu + + :param point: The point the cursor was at """ item = self.list_view.itemAt(point) # Decide if we have to show the context menu or not. @@ -422,6 +419,9 @@ class MediaManagerItem(QtGui.QWidget): def load_list(self, load_list, target_group): """ Load a list. Needs to be implemented by the plugin. + + :param load_list: List object to load + :param target_group: Group to load """ raise NotImplementedError('MediaManagerItem.loadList needs to be defined by the plugin') @@ -454,6 +454,11 @@ class MediaManagerItem(QtGui.QWidget): context=ServiceItemContext.Live): """ Generate the slide data. Needs to be implemented by the plugin. + :param service_item: The service Item to be processed + :param item: The database item to be used to build the service item + :param xml_version: + :param remote: Was this remote triggered (False) + :param context: The service context """ raise NotImplementedError('MediaManagerItem.generate_slide_data needs to be defined by the plugin') @@ -471,12 +476,14 @@ class MediaManagerItem(QtGui.QWidget): Allows the change of current item in the list to be actioned """ if Settings().value('advanced/single click preview') and self.quick_preview_allowed \ - and self.list_view.selectedIndexes() and self.auto_select_id == -1: + and self.list_view.selectedIndexes() and self.auto_select_id == -1: self.on_preview_click(True) def on_preview_click(self, keep_focus=False): """ Preview an item by building a service item then adding that service item to the preview slide controller. + + :param keep_focus: Do we keep focus (False) """ if not self.list_view.selectedIndexes() and not self.remote_triggered: QtGui.QMessageBox.information(self, UiStrings().NISp, @@ -506,14 +513,16 @@ class MediaManagerItem(QtGui.QWidget): """ Remote Call wrapper - ``message`` - The passed data item_id:Remote. + :param message: The passed data item_id:Remote. """ self.go_live(message[0], remote=message[1]) def go_live(self, item_id=None, remote=False): """ Make the currently selected item go live. + + :param item_id: item to make live + :param remote: From Remote """ log.debug('%s Live requested', self.plugin.name) item = None @@ -530,6 +539,8 @@ class MediaManagerItem(QtGui.QWidget): def create_item_from_id(self, item_id): """ Create a media item from an item id. + + :param item_id: Id to make live """ item = QtGui.QListWidgetItem() item.setData(QtCore.Qt.UserRole, item_id) @@ -558,14 +569,17 @@ class MediaManagerItem(QtGui.QWidget): """ Remote Call wrapper - ``message`` - The passed data item:Remote. + :param message: The passed data item:Remote. """ self.add_to_service(message[0], remote=message[1]) def add_to_service(self, item=None, replace=None, remote=False): """ Add this item to the current service. + + :param item: Item to be processed + :param replace: Replace the existing item + :param remote: Triggered from remote """ service_item = self.build_service_item(item, True, remote=remote, context=ServiceItemContext.Service) if service_item: @@ -598,6 +612,10 @@ class MediaManagerItem(QtGui.QWidget): def build_service_item(self, item=None, xml_version=False, remote=False, context=ServiceItemContext.Live): """ Common method for generating a service item + :param item: Service Item to be built. + :param xml_version: version of XML (False) + :param remote: Remote triggered (False) + :param context: The context on which this is called """ service_item = ServiceItem(self.plugin) service_item.add_icon(self.plugin.icon_path) @@ -611,8 +629,7 @@ class MediaManagerItem(QtGui.QWidget): Method to add processing when a service has been loaded and individual service items need to be processed by the plugins. - ``item`` - The item to be processed and returned. + :param item: The item to be processed and returned. """ return item @@ -634,11 +651,8 @@ class MediaManagerItem(QtGui.QWidget): """ Utility method to check items being submitted for slide generation. - ``item`` - The item to check. - - ``remote_item`` - The id to assign if the slide generation was remotely triggered. + :param item: The item to check. + :param remote_item: The id to assign if the slide generation was remotely triggered. """ if item is None: if self.remote_triggered is None: @@ -665,6 +679,9 @@ class MediaManagerItem(QtGui.QWidget): def search(self, string, show_error=True): """ Performs a plugin specific search for items containing ``string`` + + :param string: String to be displayed + :param show_error: Should the error be shown (True) """ raise NotImplementedError('Plugin.search needs to be defined by the plugin') diff --git a/openlp/core/ui/media/__init__.py b/openlp/core/ui/media/__init__.py index 31a27b620..b915e8beb 100644 --- a/openlp/core/ui/media/__init__.py +++ b/openlp/core/ui/media/__init__.py @@ -35,7 +35,7 @@ from openlp.core.common import Settings from PyQt4 import QtCore -log = logging.getLogger(__name__) +log = logging.getLogger(__name__+'.__init__') class MediaState(object): diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 8b63a251f..426606987 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -56,7 +56,8 @@ if sys.platform != 'win32' and sys.platform != 'darwin': from openlp.core.common import translate -log = logging.getLogger(__name__) +log = logging.getLogger(__name__+'.__init__') + APPLICATION_VERSION = {} IMAGES_FILTER = None ICU_COLLATOR = None From 68d8f58b5c2b13f7e91f90ac1bfd6224f352cc1a Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 11 Jan 2014 21:46:20 +0000 Subject: [PATCH 34/41] Clean up Alerts --- openlp/plugins/alerts/forms/alertdialog.py | 3 +++ openlp/plugins/alerts/forms/alertform.py | 5 ++--- openlp/plugins/alerts/lib/alertsmanager.py | 20 +++++--------------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py index eead213fa..e4fd29a39 100644 --- a/openlp/plugins/alerts/forms/alertdialog.py +++ b/openlp/plugins/alerts/forms/alertdialog.py @@ -35,6 +35,9 @@ from openlp.core.lib.ui import create_button, create_button_box class Ui_AlertDialog(object): + """ + Alert UI Class + """ def setupUi(self, alert_dialog): """ Setup the Alert UI dialog diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 4e3bedcd5..f5e5ee31a 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -29,7 +29,7 @@ from PyQt4 import QtGui, QtCore -from openlp.core.common import translate +from openlp.core.common import Registry, translate from openlp.plugins.alerts.lib.db import AlertItem from .alertdialog import Ui_AlertDialog @@ -46,8 +46,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): self.manager = plugin.manager self.plugin = plugin self.item_id = None - # TODO: Use Registry() - super(AlertForm, self).__init__(self.plugin.main_window) + super(AlertForm, self).__init__( Registry().get('main_window')) self.setupUi(self) self.display_button.clicked.connect(self.on_display_clicked) self.display_close_button.clicked.connect(self.on_display_close_clicked) diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index b1d453fb2..4b0832537 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -31,25 +31,17 @@ The :mod:`~openlp.plugins.alerts.lib.alertsmanager` module contains the part of displaying of alerts. """ -import logging - from PyQt4 import QtCore -from openlp.core.common import Registry, translate +from openlp.core.common import OpenLPMixin, RegistryMixin, Registry, translate -log = logging.getLogger(__name__) - - -class AlertsManager(QtCore.QObject): +class AlertsManager(OpenLPMixin, RegistryMixin, QtCore.QObject): """ AlertsManager manages the settings of Alerts. """ - log.info('Alert Manager loaded') - def __init__(self, parent): super(AlertsManager, self).__init__(parent) - Registry().register('alerts_manager', self) self.timer_id = 0 self.alert_list = [] Registry().register_function('live_display_active', self.generate_alert) @@ -71,7 +63,7 @@ class AlertsManager(QtCore.QObject): :param text: The text to display """ - log.debug('display alert called %s' % text) + self.log_debug('display alert called %s' % text) if text: self.alert_list.append(text) if self.timer_id != 0: @@ -85,7 +77,6 @@ class AlertsManager(QtCore.QObject): """ Format and request the Alert and start the timer. """ - log.debug('Generate Alert called') if not self.alert_list: return text = self.alert_list.pop(0) @@ -101,10 +92,9 @@ class AlertsManager(QtCore.QObject): :param event: the QT event that has been triggered. """ - log.debug('timer event') if event.timerId() == self.timer_id: - alertTab = self.parent().settings_tab - self.live_controller.display.alert('', alertTab.location) + alert_tab = self.parent().settings_tab + self.live_controller.display.alert('', alert_tab.location) self.killTimer(self.timer_id) self.timer_id = 0 self.generate_alert() From b5c26595068a7c271ced9cf68a03854e1e0a6c24 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 11 Jan 2014 22:01:41 +0000 Subject: [PATCH 35/41] Clean up Song Usage --- .../songusage/forms/songusagedeletedialog.py | 14 +++++- .../songusage/forms/songusagedeleteform.py | 14 ++++-- .../songusage/forms/songusagedetaildialog.py | 13 ++++++ .../songusage/forms/songusagedetailform.py | 10 ++--- openlp/plugins/songusage/lib/db.py | 21 +++++---- openlp/plugins/songusage/songusageplugin.py | 43 ++++++++++++++----- 6 files changed, 83 insertions(+), 32 deletions(-) diff --git a/openlp/plugins/songusage/forms/songusagedeletedialog.py b/openlp/plugins/songusage/forms/songusagedeletedialog.py index bf7e4ded5..01597a790 100644 --- a/openlp/plugins/songusage/forms/songusagedeletedialog.py +++ b/openlp/plugins/songusage/forms/songusagedeletedialog.py @@ -34,7 +34,15 @@ from openlp.core.lib.ui import create_button_box class Ui_SongUsageDeleteDialog(object): + """ + The Song Usage delete dialog + """ def setupUi(self, song_usage_delete_dialog): + """ + Setup the UI + + :param song_usage_delete_dialog: + """ song_usage_delete_dialog.setObjectName('song_usage_delete_dialog') song_usage_delete_dialog.resize(291, 243) self.vertical_layout = QtGui.QVBoxLayout(song_usage_delete_dialog) @@ -55,8 +63,12 @@ class Ui_SongUsageDeleteDialog(object): self.retranslateUi(song_usage_delete_dialog) def retranslateUi(self, song_usage_delete_dialog): + """ + Retranslate the strings + :param song_usage_delete_dialog: + """ song_usage_delete_dialog.setWindowTitle( translate('SongUsagePlugin.SongUsageDeleteForm', 'Delete Song Usage Data')) self.delete_label.setText( translate('SongUsagePlugin.SongUsageDeleteForm', 'Select the date up to which the song usage data ' - 'should be deleted. All data recorded before this date will be permanently deleted.')) + 'should be deleted. \nAll data recorded before this date will be permanently deleted.')) diff --git a/openlp/plugins/songusage/forms/songusagedeleteform.py b/openlp/plugins/songusage/forms/songusagedeleteform.py index 19d137e1c..c3446cdd3 100644 --- a/openlp/plugins/songusage/forms/songusagedeleteform.py +++ b/openlp/plugins/songusage/forms/songusagedeleteform.py @@ -48,19 +48,25 @@ class SongUsageDeleteForm(QtGui.QDialog, Ui_SongUsageDeleteDialog): self.button_box.clicked.connect(self.on_button_box_clicked) def on_button_box_clicked(self, button): + """ + The button event has been triggered + + :param button: The button pressed + """ if self.button_box.standardButton(button) == QtGui.QDialogButtonBox.Ok: - ret = QtGui.QMessageBox.question(self, + ret = QtGui.QMessageBox.question( + self, translate('SongUsagePlugin.SongUsageDeleteForm', 'Delete Selected Song Usage Events?'), translate('SongUsagePlugin.SongUsageDeleteForm', - 'Are you sure you want to delete selected Song Usage data?'), + 'Are you sure you want to delete selected Song Usage data?'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), QtGui.QMessageBox.No) if ret == QtGui.QMessageBox.Yes: delete_date = self.delete_calendar.selectedDate().toPyDate() self.manager.delete_all_objects(SongUsageItem, SongUsageItem.usagedate <= delete_date) self.main_window.information_message( translate('SongUsagePlugin.SongUsageDeleteForm', 'Deletion Successful'), - translate( - 'SongUsagePlugin.SongUsageDeleteForm', 'All requested data has been deleted successfully.') + translate('SongUsagePlugin.SongUsageDeleteForm', + 'All requested data has been deleted successfully.') ) self.accept() else: diff --git a/openlp/plugins/songusage/forms/songusagedetaildialog.py b/openlp/plugins/songusage/forms/songusagedetaildialog.py index 2f92000f0..ede5075a0 100644 --- a/openlp/plugins/songusage/forms/songusagedetaildialog.py +++ b/openlp/plugins/songusage/forms/songusagedetaildialog.py @@ -35,7 +35,15 @@ from openlp.core.lib.ui import create_button_box class Ui_SongUsageDetailDialog(object): + """ + The Song Usage report details + """ def setupUi(self, song_usage_detail_dialog): + """ + Set up the UI + + :param song_usage_detail_dialog: + """ song_usage_detail_dialog.setObjectName('song_usage_detail_dialog') song_usage_detail_dialog.resize(609, 413) self.vertical_layout = QtGui.QVBoxLayout(song_usage_detail_dialog) @@ -82,6 +90,11 @@ class Ui_SongUsageDetailDialog(object): self.save_file_push_button.clicked.connect(song_usage_detail_dialog.define_output_location) def retranslateUi(self, song_usage_detail_dialog): + """ + Retranslate the UI + + :param song_usage_detail_dialog: + """ song_usage_detail_dialog.setWindowTitle( translate('SongUsagePlugin.SongUsageDetailForm', 'Song Usage Extraction')) self.date_range_group_box.setTitle(translate('SongUsagePlugin.SongUsageDetailForm', 'Select Date Range')) diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index dcbf0bae8..2e96a4eb6 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -66,8 +66,8 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): """ Triggered when the Directory selection button is clicked """ - path = QtGui.QFileDialog.getExistingDirectory(self, - translate('SongUsagePlugin.SongUsageDetailForm', 'Output File Location'), + path = QtGui.QFileDialog.getExistingDirectory( + self, translate('SongUsagePlugin.SongUsageDetailForm', 'Output File Location'), Settings().value(self.plugin.settings_section + '/last directory export')) if path: Settings().setValue(self.plugin.settings_section + '/last directory export', path) @@ -83,7 +83,7 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): self.main_window.error_message( translate('SongUsagePlugin.SongUsageDetailForm', 'Output Path Not Selected'), translate('SongUsagePlugin.SongUsageDetailForm', 'You have not set a valid output location for your' - ' song usage report. Please select an existing path on your computer.') + ' song usage report. \nPlease select an existing path on your computer.') ) return check_directory_exists(path) @@ -109,8 +109,8 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): file_handle.write(record.encode('utf-8')) self.main_window.information_message( translate('SongUsagePlugin.SongUsageDetailForm', 'Report Creation'), - translate('SongUsagePlugin.SongUsageDetailForm', 'Report \n%s \n' - 'has been successfully created. ') % report_file_name + translate('SongUsagePlugin.SongUsageDetailForm', + 'Report \n%s \nhas been successfully created. ') % report_file_name ) except IOError: log.exception('Failed to write out song usage records') diff --git a/openlp/plugins/songusage/lib/db.py b/openlp/plugins/songusage/lib/db.py index 816d06f2c..b7b9c6801 100644 --- a/openlp/plugins/songusage/lib/db.py +++ b/openlp/plugins/songusage/lib/db.py @@ -48,21 +48,20 @@ def init_schema(url): """ Setup the songusage database connection and initialise the database schema - ``url`` - The database to setup + :param url: The database to setup """ session, metadata = init_db(url) songusage_table = Table('songusage_data', metadata, - Column('id', types.Integer(), primary_key=True), - Column('usagedate', types.Date, index=True, nullable=False), - Column('usagetime', types.Time, index=True, nullable=False), - Column('title', types.Unicode(255), nullable=False), - Column('authors', types.Unicode(255), nullable=False), - Column('copyright', types.Unicode(255)), - Column('ccl_number', types.Unicode(65)), - Column('plugin_name', types.Unicode(20)), - Column('source', types.Unicode(10)) + Column('id', types.Integer(), primary_key=True), + Column('usagedate', types.Date, index=True, nullable=False), + Column('usagetime', types.Time, index=True, nullable=False), + Column('title', types.Unicode(255), nullable=False), + Column('authors', types.Unicode(255), nullable=False), + Column('copyright', types.Unicode(255)), + Column('ccl_number', types.Unicode(65)), + Column('plugin_name', types.Unicode(20)), + Column('source', types.Unicode(10)) ) mapper(SongUsageItem, songusage_table) diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 491e97b64..4d38de6dd 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -58,6 +58,9 @@ __default_settings__ = { class SongUsagePlugin(Plugin): + """ + Song Usage Plugin class + """ log.info('SongUsage Plugin loaded') def __init__(self): @@ -79,31 +82,33 @@ class SongUsagePlugin(Plugin): """ Give the SongUsage plugin the opportunity to add items to the **Tools** menu. - ``tools_menu`` - The actual **Tools** menu item, so that your actions can use it as their parent. + :param tools_menu: The actual **Tools** menu item, so that your actions can use it as their parent. """ log.info('add tools menu') - self.toolsMenu = tools_menu + self.tools_menu = tools_menu self.song_usage_menu = QtGui.QMenu(tools_menu) self.song_usage_menu.setObjectName('song_usage_menu') self.song_usage_menu.setTitle(translate('SongUsagePlugin', '&Song Usage Tracking')) # SongUsage Delete - self.song_usage_delete = create_action(tools_menu, 'songUsageDelete', + self.song_usage_delete = create_action( + tools_menu, 'songUsageDelete', text=translate('SongUsagePlugin', '&Delete Tracking Data'), statustip=translate('SongUsagePlugin', 'Delete song usage data up to a specified date.'), triggers=self.on_song_usage_delete) # SongUsage Report - self.song_usage_report = create_action(tools_menu, 'songUsageReport', + self.song_usage_report = create_action( + tools_menu, 'songUsageReport', text=translate('SongUsagePlugin', '&Extract Tracking Data'), statustip=translate('SongUsagePlugin', 'Generate a report on song usage.'), triggers=self.on_song_usage_report) # SongUsage activation - self.song_usage_status = create_action(tools_menu, 'songUsageStatus', + self.song_usage_status = create_action( + tools_menu, 'songUsageStatus', text=translate('SongUsagePlugin', 'Toggle Tracking'), statustip=translate('SongUsagePlugin', 'Toggle the tracking of song usage.'), checked=False, can_shortcuts=True, triggers=self.toggle_song_usage_state) # Add Menus together - self.toolsMenu.addAction(self.song_usage_menu.menuAction()) + self.tools_menu.addAction(self.song_usage_menu.menuAction()) self.song_usage_menu.addAction(self.song_usage_status) self.song_usage_menu.addSeparator() self.song_usage_menu.addAction(self.song_usage_report) @@ -117,7 +122,7 @@ class SongUsagePlugin(Plugin): self.song_usage_active_button.hide() # Signals and slots QtCore.QObject.connect(self.song_usage_status, QtCore.SIGNAL('visibilityChanged(bool)'), - self.song_usage_status.setChecked) + self.song_usage_status.setChecked) self.song_usage_active_button.toggled.connect(self.toggle_song_usage_state) self.song_usage_menu.menuAction().setVisible(False) @@ -165,8 +170,7 @@ class SongUsagePlugin(Plugin): def set_button_state(self): """ - Keep buttons inline. Turn of signals to stop dead loop but we need the - button and check box set correctly. + Keep buttons inline. Turn of signals to stop dead loop but we need the button and check box set correctly. """ self.song_usage_active_button.blockSignals(True) self.song_usage_status.blockSignals(True) @@ -186,12 +190,16 @@ class SongUsagePlugin(Plugin): def display_song_usage(self, item): """ Song Usage for which has been displayed + + :param item: Item displayed """ self._add_song_usage(translate('SongUsagePlugin', 'display'), item) def print_song_usage(self, item): """ Song Usage for which has been printed + + :param item: Item printed """ self._add_song_usage(translate('SongUsagePlugin', 'printed'), item) @@ -210,15 +218,28 @@ class SongUsagePlugin(Plugin): self.manager.save_object(song_usage_item) def on_song_usage_delete(self): + """ + Request the delete form to be displayed + """ self.song_usage_delete_form.exec_() def on_song_usage_report(self): + """ + Display the song usage report generator screen + + """ self.song_usage_detail_form.initialise() self.song_usage_detail_form.exec_() def about(self): + """ + The plugin about text + + :return: the text to be displayed + """ about_text = translate('SongUsagePlugin', - 'SongUsage Plugin
This plugin tracks the usage of songs in services.') + 'SongUsage Plugin
' + 'This plugin tracks the usage of songs in services.') return about_text def set_plugin_text_strings(self): From 5d740a770687bae496cdf56feb8138362760b58d Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 11 Jan 2014 22:05:38 +0000 Subject: [PATCH 36/41] Removep bzr commit -mRemovep --- openlp/core/common/registrymixin.py | 2 -- openlp/core/lib/renderer.py | 3 --- openlp/core/ui/maindisplay.py | 4 ---- openlp/core/ui/mainwindow.py | 3 --- openlp/core/ui/servicemanager.py | 5 ----- openlp/core/ui/thememanager.py | 4 ---- tests/functional/openlp_plugins/remotes/test_router.py | 1 - 7 files changed, 22 deletions(-) diff --git a/openlp/core/common/registrymixin.py b/openlp/core/common/registrymixin.py index 7a7876311..e7bcc24d7 100644 --- a/openlp/core/common/registrymixin.py +++ b/openlp/core/common/registrymixin.py @@ -40,12 +40,10 @@ class RegistryMixin(object): """ Register the class and bootstrap hooks. """ - print("RegistryMixin - before super ", self.__class__.__name__) try: super(RegistryMixin, self).__init__(parent) except TypeError: super(RegistryMixin, self).__init__() - print("RegistryMixin - after super") Registry().register(de_hump(self.__class__.__name__), self) Registry().register_function('bootstrap_initialise', self.bootstrap_initialise) Registry().register_function('bootstrap_post_set_up', self.bootstrap_post_set_up) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 415c5dfab..49407a78d 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -57,9 +57,7 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Initialise the renderer. """ - print("Renderer - before super") super(Renderer, self).__init__(None) - print("Renderer - after super") # Need live behaviour if this is also working as a pseudo MainDisplay. self.is_live = True self.screens = ScreenList() @@ -580,7 +578,6 @@ class Renderer(OpenLPMixin, RegistryMixin): """ Adds the theme manager to the class dynamically """ - print("renderer _get_theme_manager") if not hasattr(self, '_theme_manager') or not self._theme_manager : self._theme_manager = Registry().get('theme_manager') return self._theme_manager diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 3eb3179ff..13277f6e7 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -63,7 +63,6 @@ class Display(QtGui.QGraphicsView): """ Constructor """ - print("Display - before super", parent, type(parent)) self.is_live = False if hasattr(parent, 'is_live') and parent.is_live: self.is_live = True @@ -73,7 +72,6 @@ class Display(QtGui.QGraphicsView): self.parent = lambda: parent else: super(Display, self).__init__(parent) - print("Display - after super") self.controller = parent self.screen = {} # FIXME: On Mac OS X (tested on 10.7) the display screen is corrupt with @@ -128,9 +126,7 @@ class MainDisplay(OpenLPMixin, Display): """ Constructor """ - print("MainDisplay - before super") super(MainDisplay, self).__init__(parent) - print("MainDisplay - after super") self.screens = ScreenList() self.rebuild_css = False self.hide_mode = None diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index de13c0301..0261903fc 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -468,9 +468,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ This constructor sets up the interface, the various managers, and the plugins. """ - print("Mainwindow - before super") super(MainWindow, self).__init__() - print("Mainwindow - after super") Registry().register('main_window', self) self.clipboard = self.application.clipboard() self.arguments = self.application.args @@ -543,7 +541,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ process the bootstrap post setup request """ - print("Mainwindow - bs post") self.preview_controller.panel.setVisible(Settings().value('user interface/preview panel')) self.live_controller.panel.setVisible(Settings().value('user interface/live panel')) self.load_settings() diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index c43b9853b..ce941688d 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -316,9 +316,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Sets up the service manager, toolbars, list view, et al. """ - print("ServiceManager - before super") super(ServiceManager, self).__init__(parent) - print("ServiceManager - after super") self.active = build_icon(':/media/auto-start_active.png') self.inactive = build_icon(':/media/auto-start_inactive.png') self.service_items = [] @@ -334,7 +332,6 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ To be called as part of initialisation """ - print("ServiceManager - bs i") self.setup_ui(self) # Need to use event as called across threads and UI is updated QtCore.QObject.connect(self, QtCore.SIGNAL('servicemanager_set_item'), self.on_set_item) @@ -343,7 +340,6 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Can be set up as a late setup """ - print("ServiceManager - bs psu") self.service_note_form = ServiceNoteForm() self.service_item_edit_form = ServiceItemEditForm() self.start_time_form = StartTimeForm() @@ -1642,7 +1638,6 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage """ Adds the Renderer to the class dynamically """ - print("serviceManager _get_renderer") if not hasattr(self, '_renderer'): self._renderer = Registry().get('renderer') return self._renderer diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 2632477eb..777a3e014 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -135,9 +135,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ Constructor """ - print("ThemeManager - before super") super(ThemeManager, self).__init__(parent) - print("ThemeManager - after super") self.settings_section = 'themes' # Variables self.theme_list = [] @@ -147,7 +145,6 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ process the bootstrap initialise setup request """ - print("ThemeManager - bs i") self.setup_ui(self) self.global_theme = Settings().value(self.settings_section + '/global theme') self.build_theme_path() @@ -157,7 +154,6 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager): """ process the bootstrap post setup request """ - print("ThemeManager - bs psu") self.theme_form = ThemeForm(self) self.theme_form.path = self.path self.file_rename_form = FileRenameForm() diff --git a/tests/functional/openlp_plugins/remotes/test_router.py b/tests/functional/openlp_plugins/remotes/test_router.py index 5cd2147ce..7f42a8cad 100644 --- a/tests/functional/openlp_plugins/remotes/test_router.py +++ b/tests/functional/openlp_plugins/remotes/test_router.py @@ -87,7 +87,6 @@ class TestRouter(TestCase): router = HttpRouter() router.initialise() test_value = 'b3BlbmxwOnBhc3N3b3Jk' - print(router.auth) # THEN: the function should return the correct password self.assertEqual(router.auth, test_value, From ca47293345869da4503f98948ca2aed94016cf92 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Mon, 13 Jan 2014 17:29:31 +0000 Subject: [PATCH 37/41] Fix up help link --- openlp/core/ui/mainwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 0261903fc..c8dd5e045 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -291,7 +291,7 @@ class Ui_MainWindow(object): self.about_item.setMenuRole(QtGui.QAction.AboutRole) if os.name == 'nt': self.local_help_file = os.path.join(AppLocation.get_directory(AppLocation.AppDir), 'OpenLP.chm') - self.offline_help_item = create_action(main_window, 'offline_help_item', + self.offline_help_item = create_action(main_window, 'offlineHelpItem', icon=':/system/system_help_contents.png', can_shortcuts=True, category=UiStrings().Help, triggers=self.on_offline_help_clicked) From bc3081fd18478e4b6b61aae515cecc16e53d032a Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Mon, 13 Jan 2014 17:31:46 +0000 Subject: [PATCH 38/41] Remove redundent method --- openlp/core/ui/themestab.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index b5033e452..f754d626c 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -156,13 +156,6 @@ class ThemesTab(SettingsTab): self.settings_form.register_post_process('theme_update_global') self.tab_visited = False - def post_set_up(self): - """ - After setting things up... - """ - #Registry().execute('theme_update_global') - pass - def on_song_level_button_clicked(self): """ Set the theme level From 83e20b79b63da0d3eebd61377697531063424f20 Mon Sep 17 00:00:00 2001 From: Rafael Lerm Date: Thu, 16 Jan 2014 18:34:37 -0200 Subject: [PATCH 39/41] Changed string that caused crash on startup. Corrected bug 1269929 --- openlp/core/ui/mainwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 46c318061..7864120a9 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -291,7 +291,7 @@ class Ui_MainWindow(object): self.about_item.setMenuRole(QtGui.QAction.AboutRole) if os.name == 'nt': self.local_help_file = os.path.join(AppLocation.get_directory(AppLocation.AppDir), 'OpenLP.chm') - self.offline_help_item = create_action(main_window, 'offline_help_item', + self.offline_help_item = create_action(main_window, 'offlineHelpItem', icon=':/system/system_help_contents.png', can_shortcuts=True, category=UiStrings().Help, triggers=self.on_offline_help_clicked) From b718b76c8c0e7d42a3e184abab1e71ecf30f8567 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Tue, 11 Feb 2014 21:07:06 +0000 Subject: [PATCH 40/41] HEAD --- .../openlp_plugins/presentations/test_presentationcontroller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py index 1feb0c473..151fc5495 100644 --- a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py @@ -51,7 +51,7 @@ class TestPresentationController(TestCase): # close_presentation # _get_plugin_manager - def constructor_tvest(self): + def constructor_test(self): """ Test the Constructor """ From 7f58348c8c9debe8b03e77608672a13c4fda7edf Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 23 Feb 2014 15:41:09 +0000 Subject: [PATCH 41/41] fix up pintservice form --- openlp/core/ui/mainwindow.py | 4 ++-- openlp/core/ui/printserviceform.py | 9 +++++---- openlp/core/ui/servicemanager.py | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index c8dd5e045..296809128 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -311,8 +311,8 @@ class Ui_MainWindow(object): self.export_language_item)) add_actions(self.file_menu, (self.file_new_item, self.file_open_item, self.file_save_item, self.file_save_as_item, self.recent_files_menu.menuAction(), None, - self.file_import_menu.menuAction(), self.file_export_menu.menuAction(), None, self.print_service_order_item, - self.file_exit_item)) + self.file_import_menu.menuAction(), self.file_export_menu.menuAction(), None, + self.print_service_order_item, self.file_exit_item)) add_actions(self.view_mode_menu, (self.mode_default_item, self.mode_setup_item, self.mode_live_item)) add_actions(self.view_menu, (self.view_mode_menu.menuAction(), None, self.view_media_manager_item, self.view_service_manager_item, self.view_theme_manager_item, None, self.view_preview_panel, diff --git a/openlp/core/ui/printserviceform.py b/openlp/core/ui/printserviceform.py index 1adb3290c..3a6fbe8c1 100644 --- a/openlp/core/ui/printserviceform.py +++ b/openlp/core/ui/printserviceform.py @@ -31,9 +31,10 @@ The actual print service dialog """ import datetime import os +import html +import lxml.html from PyQt4 import QtCore, QtGui -from lxml import html from openlp.core.common import Registry, Settings, UiStrings, translate from openlp.core.lib import get_text_file_string @@ -183,7 +184,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): self._add_element( 'span', translate('OpenLP.ServiceManager', 'Custom Service Notes: '), div, classId='customNotesTitle') self._add_element('span', html.escape(self.footer_text_edit.toPlainText()), div, classId='customNotesText') - self.document.setHtml(html.tostring(html_data).decode()) + self.document.setHtml(lxml.html.tostring(html_data).decode()) self.preview_widget.updatePreview() def _add_preview_item(self, body, item, index): @@ -257,9 +258,9 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): Tuple name/value pair to add as an optional attribute """ if text is not None: - element = html.fragment_fromstring(str(text), create_parent=tag) + element = lxml.html.fragment_fromstring(str(text), create_parent=tag) else: - element = html.Element(tag) + element = lxml.html.Element(tag) if parent is not None: parent.append(element) if classId is not None: diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index ce941688d..8a1989881 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -1627,7 +1627,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage else: return parent_item.data(0, QtCore.Qt.UserRole) - def print_service_order(self): + def print_service_order(self, field=None): """ Print a Service Order Sheet. """