Merge remote-tracking branch 'origin/master' into move_lib_to_sep_dir

Conflicts:
	src/CMakeLists.txt
	src/gui/accountsettings.cpp
	src/gui/folderwizard.cpp
	src/gui/settingsdialog.cpp
	src/libsync/syncengine.h
This commit is contained in:
Daniel Molkentin 2014-08-26 11:29:42 +02:00
commit 902bb7a198
148 changed files with 8662 additions and 10270 deletions

2
.gitignore vendored
View file

@ -79,7 +79,7 @@ dlldata.c
*.scc *.scc
# Mac OS X specific # Mac OS X specific
shell_integration/MacOSX/LiferayNativity.xcworkspace/xcuserdata/ shell_integration/MacOSX/*.xcworkspace/xcuserdata/
**/.DS_Store **/.DS_Store
# Visual C++ cache files # Visual C++ cache files

View file

@ -4,7 +4,7 @@ set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_SOVERSION 0 ) set( MIRALL_SOVERSION 0 )
if ( NOT DEFINED MIRALL_VERSION_SUFFIX ) if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
set( MIRALL_VERSION_SUFFIX "alpha1") #e.g. beta1, beta2, rc1 set( MIRALL_VERSION_SUFFIX "beta1") #e.g. beta1, beta2, rc1
endif( NOT DEFINED MIRALL_VERSION_SUFFIX ) endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
if( NOT DEFINED MIRALL_VERSION_BUILD ) if( NOT DEFINED MIRALL_VERSION_BUILD )

View file

@ -793,7 +793,7 @@
<key>GID</key> <key>GID</key>
<integer>0</integer> <integer>0</integer>
<key>PATH</key> <key>PATH</key>
<string>Library/ScriptingAdditions/LiferayNativity.osax/Contents</string> <string>Library/ScriptingAdditions/OwnCloudFinder.osax/Contents</string>
<key>PATH_TYPE</key> <key>PATH_TYPE</key>
<integer>3</integer> <integer>3</integer>
<key>PERMISSIONS</key> <key>PERMISSIONS</key>
@ -807,7 +807,7 @@
<key>GID</key> <key>GID</key>
<integer>0</integer> <integer>0</integer>
<key>PATH</key> <key>PATH</key>
<string>LiferayNativity.osax</string> <string>OwnCloudFinder.osax</string>
<key>PATH_TYPE</key> <key>PATH_TYPE</key>
<integer>0</integer> <integer>0</integer>
<key>PERMISSIONS</key> <key>PERMISSIONS</key>

View file

@ -0,0 +1,46 @@
# Auto-generated - do not modify
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "نمایش پادداشت های انتشار نسخه"
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "پردازش برای از بین بردن یافت نشد!"
StrCpy $PageReinstall_NEW_Field_3 "حذف نکن"
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "از قبل نصب شده است"
StrCpy $PageReinstall_SAME_Field_2 "افزودن/نصب مجدد اجزا"
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "میانبر دسکتاپ"
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "ایجاد میانبر دسکتاپ"
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "میانبر بازکردن سریع"
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "بله، این پوشه داده را حذف کن."
StrCpy $UNINSTALLER_FILE_Detail "نوشتن حذف کننده"
StrCpy $UNINSTALLER_FINISHED_Detail "اتمام"
StrCpy $INIT_INSTALLER_RUNNING "نصاب از قبل در حال اجراست."
StrCpy $INIT_UNINSTALLER_RUNNING "حذف کننده از قبل در حال اجراست."
StrCpy $SectionGroup_Shortcuts "میانبرها"
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Killing ${APPLICATION_EXECUTABLE} processes."
StrCpy $PageReinstall_NEW_Field_1 "An older version of ${APPLICATION_NAME} is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue."
StrCpy $PageReinstall_NEW_Field_2 "Uninstall before installing"
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Choose how you want to install ${APPLICATION_NAME}."
StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
StrCpy $PageReinstall_SAME_Field_3 "Uninstall ${APPLICATION_NAME}"
StrCpy $UNINSTALLER_APPDATA_TITLE "Uninstall ${APPLICATION_NAME}"
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choose the maintenance option to perform."
StrCpy $SEC_APPLICATION_DETAILS "Installing ${APPLICATION_NAME} essentials."
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start Menu Program Shortcut"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Adding shortcut for ${APPLICATION_NAME} to the Start Menu."
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creating Quick Launch Shortcut"
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} essentials."
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} shortcut."
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Desktop shortcut for ${APPLICATION_NAME}."
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Quick Launch shortcut for ${APPLICATION_NAME}."
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Remove ${APPLICATION_NAME}'s data folder from your computer."
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Do you want to delete ${APPLICATION_NAME}'s data folder?"
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Leave unchecked to keep the data folder for later use or check to delete the data folder."
StrCpy $UNINSTALLER_REGISTRY_Detail "Writing Installer Registry Keys"
StrCpy $UNINSTALL_MESSAGEBOX "It does not appear that ${APPLICATION_NAME} is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)?"
StrCpy $UNINSTALL_ABORT "Uninstall aborted by user"
StrCpy $INIT_NO_QUICK_LAUNCH "Quick Launch Shortcut (N/A)"
StrCpy $INIT_NO_DESKTOP "Desktop Shortcut (overwrites existing)"
StrCpy $UAC_ERROR_ELEVATE "Unable to elevate, error:"
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "This installer requires admin access, try again"
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "This uninstaller requires admin access, try again"

View file

@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "
StrCpy $UNINSTALLER_APPDATA_TITLE "ÁðåãêáôÜóôáóç ${APPLICATION_NAME}" StrCpy $UNINSTALLER_APPDATA_TITLE "ÁðåãêáôÜóôáóç ${APPLICATION_NAME}"
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "ÅðéëÝîôå ôçí åðéëïãÞ óõíôÞñçóçò ðïõ èá ðñáãìáôïðïéçèåß." StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "ÅðéëÝîôå ôçí åðéëïãÞ óõíôÞñçóçò ðïõ èá ðñáãìáôïðïéçèåß."
StrCpy $SEC_APPLICATION_DETAILS "ÅãêáôÜóôáóç âÜóçò ${APPLICATION_NAME} óå åîÝëéîç." StrCpy $SEC_APPLICATION_DETAILS "ÅãêáôÜóôáóç âÜóçò ${APPLICATION_NAME} óå åîÝëéîç."
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Εικονίδια κατάστασης για την Εξερεύνηση των Windows"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Εγκατάσταση εικονιδίων κατάστασης στην Εξερεύνηση των Windows"
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Óõíôüìåõóç óôï Áñ÷éêü Ìåíïý" StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Óõíôüìåõóç óôï Áñ÷éêü Ìåíïý"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "ÐñïóèÞêç óõíôüìåõóçò ãéá ôçí ${APPLICATION_NAME} óôï Áñ÷éêü Ìåíïý." StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "ÐñïóèÞêç óõíôüìåõóçò ãéá ôçí ${APPLICATION_NAME} óôï Áñ÷éêü Ìåíïý."
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Óõíôüìåõóç åðéöÜíåéáò åñãáóßáò" StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Óõíôüìåõóç åðéöÜíåéáò åñãáóßáò"
@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "ÁõôÞ ç åöáñìïãÞ áðåãêáôÜóôáóçò áðáéôåß ðñüóâáóç äéá÷åéñéóôÞ, äïêéìÜóôå îáíÜ" StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "ÁõôÞ ç åöáñìïãÞ áðåãêáôÜóôáóçò áðáéôåß ðñüóâáóç äéá÷åéñéóôÞ, äïêéìÜóôå îáíÜ"
StrCpy $INIT_UNINSTALLER_RUNNING "Ç åöáñìïãÞ áðåãêáôÜóôáóçò ëåéôïõñãåß Þäç." StrCpy $INIT_UNINSTALLER_RUNNING "Ç åöáñìïãÞ áðåãêáôÜóôáóçò ëåéôïõñãåß Þäç."
StrCpy $SectionGroup_Shortcuts "Óõíôïìåýóåéò" StrCpy $SectionGroup_Shortcuts "Óõíôïìåýóåéò"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"

View file

@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Odinstaluj ${APPLICATION_NAME}"
StrCpy $UNINSTALLER_APPDATA_TITLE "Odinstaluj ${APPLICATION_NAME}" StrCpy $UNINSTALLER_APPDATA_TITLE "Odinstaluj ${APPLICATION_NAME}"
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Wybierz sposób utrzymywania." StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Wybierz sposób utrzymywania."
StrCpy $SEC_APPLICATION_DETAILS "Instaluje niezbędne pliki ${APPLICATION_NAME}." StrCpy $SEC_APPLICATION_DETAILS "Instaluje niezbędne pliki ${APPLICATION_NAME}."
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Ikona statusu dla Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instaluj ikonę statusu dla Windows Explorer"
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Skrót w Menu Start" StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Skrót w Menu Start"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Dodaję skrót ${APPLICATION_NAME} w Menu Start." StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Dodaję skrót ${APPLICATION_NAME} w Menu Start."
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Skrót na Pulpicie" StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Skrót na Pulpicie"
@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "Instalator już jest uruchomiony."
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Ten dezinstalator potrzebuje uprawnień administratora, spróbuj ponownie" StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Ten dezinstalator potrzebuje uprawnień administratora, spróbuj ponownie"
StrCpy $INIT_UNINSTALLER_RUNNING "Dezinstalator już jest uruchomiony." StrCpy $INIT_UNINSTALLER_RUNNING "Dezinstalator już jest uruchomiony."
StrCpy $SectionGroup_Shortcuts "Skróty" StrCpy $SectionGroup_Shortcuts "Skróty"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"

View file

@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Удалить ${APPLICATION_NAME}"
StrCpy $UNINSTALLER_APPDATA_TITLE "Удалить ${APPLICATION_NAME}" StrCpy $UNINSTALLER_APPDATA_TITLE "Удалить ${APPLICATION_NAME}"
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Выберите опцию обслуживания для исполнения." StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Выберите опцию обслуживания для исполнения."
StrCpy $SEC_APPLICATION_DETAILS "Установка зависимостей приложения ${APPLICATION_NAME}" StrCpy $SEC_APPLICATION_DETAILS "Установка зависимостей приложения ${APPLICATION_NAME}"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Значки статуса для проводника Windows"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Установка значков статуса для проводника Windows"
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Ярлык в меню Пуск" StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Ярлык в меню Пуск"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Добавление ярлыка ${APPLICATION_NAME} в меню Пуск" StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Добавление ярлыка ${APPLICATION_NAME} в меню Пуск"
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Ярлык на рабочем столе" StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Ярлык на рабочем столе"
@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "Установщик уже запущен."
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Этот деинсталятор требует права администратора, попытайтесь ещё" StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Этот деинсталятор требует права администратора, попытайтесь ещё"
StrCpy $INIT_UNINSTALLER_RUNNING "Программа удаления уже выполняется." StrCpy $INIT_UNINSTALLER_RUNNING "Программа удаления уже выполняется."
StrCpy $SectionGroup_Shortcuts "Ярлыки" StrCpy $SectionGroup_Shortcuts "Ярлыки"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"

View file

@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Odin
StrCpy $UNINSTALLER_APPDATA_TITLE "Odinštalova<76> ${APPLICATION_NAME}" StrCpy $UNINSTALLER_APPDATA_TITLE "Odinštalova<76> ${APPLICATION_NAME}"
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Vyberte možnos<6F> vykona<6E> údržbu." StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Vyberte možnos<6F> vykona<6E> údržbu."
StrCpy $SEC_APPLICATION_DETAILS "Inštalujú sa náležitosti ${APPLICATION_NAME}." StrCpy $SEC_APPLICATION_DETAILS "Inštalujú sa náležitosti ${APPLICATION_NAME}."
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Stavová ikona pre Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Inštalujem stavovú ikonu pre Windows Explorer"
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Zástupca programu v menu Štart" StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Zástupca programu v menu Štart"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Prida<64> zástupcu pre ${APPLICATION_NAME} do menu Štart." StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Prida<64> zástupcu pre ${APPLICATION_NAME} do menu Štart."
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Zástupca na ploche" StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Zástupca na ploche"
@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "In
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Tento odinštalátor vyžaduje admin prístup, skúste to znova" StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Tento odinštalátor vyžaduje admin prístup, skúste to znova"
StrCpy $INIT_UNINSTALLER_RUNNING "Odinštalátor je už spustený." StrCpy $INIT_UNINSTALLER_RUNNING "Odinštalátor je už spustený."
StrCpy $SectionGroup_Shortcuts "Zástupcovia" StrCpy $SectionGroup_Shortcuts "Zástupcovia"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"

View file

@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Avinstallera ${APPLICATION_NAME}"
StrCpy $UNINSTALLER_APPDATA_TITLE "Avinstallera ${APPLICATION_NAME}" StrCpy $UNINSTALLER_APPDATA_TITLE "Avinstallera ${APPLICATION_NAME}"
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Välj underhålls alternativ att utföra." StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Välj underhålls alternativ att utföra."
StrCpy $SEC_APPLICATION_DETAILS "Installerar ${APPLICATION_NAME} väsentligheter." StrCpy $SEC_APPLICATION_DETAILS "Installerar ${APPLICATION_NAME} väsentligheter."
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Statusikoner för Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installerar statusikoner för Windows Explorer"
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start-meny program genväg" StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start-meny program genväg"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Lägger till genväg för ${APPLICATION_NAME} till Start-menyn." StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Lägger till genväg för ${APPLICATION_NAME} till Start-menyn."
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Skrivbordsgenväg" StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Skrivbordsgenväg"
@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "Installationsprogrammet körs redan."
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Detta avinstallationsprogram kräver administratörs rättigheter, försök igen" StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Detta avinstallationsprogram kräver administratörs rättigheter, försök igen"
StrCpy $INIT_UNINSTALLER_RUNNING "Avinstallationsprogrammet körs redan." StrCpy $INIT_UNINSTALLER_RUNNING "Avinstallationsprogrammet körs redan."
StrCpy $SectionGroup_Shortcuts "Genvägar" StrCpy $SectionGroup_Shortcuts "Genvägar"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"

View file

@ -23,3 +23,4 @@
!insertmacro MUI_LANGUAGE "Slovak" !insertmacro MUI_LANGUAGE "Slovak"
!insertmacro MUI_LANGUAGE "Spanish" !insertmacro MUI_LANGUAGE "Spanish"
!insertmacro MUI_LANGUAGE "Polish" !insertmacro MUI_LANGUAGE "Polish"
!insertmacro MUI_LANGUAGE "Farsi"

2
binary

@ -1 +1 @@
Subproject commit 10a2d688b758c3f83b0d9b331b02fcff063bd843 Subproject commit 82d72bc62d1f036a4d73a8e9375b52db6e0573b3

View file

@ -95,6 +95,7 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
!include WordFunc.nsh ;Used by VersionCompare macro function. !include WordFunc.nsh ;Used by VersionCompare macro function.
!include FileFunc.nsh ;Used to read out parameters !include FileFunc.nsh ;Used to read out parameters
!include UAC.nsh ;Used by the UAC elevation to install as user or admin. !include UAC.nsh ;Used by the UAC elevation to install as user or admin.
!include Library.nsh ;Used by the COM registration for shell extensions
!include x64.nsh ;Used to determine the right arch for the shell extensions !include x64.nsh ;Used to determine the right arch for the shell extensions
;----------------------------------------------------------------------------- ;-----------------------------------------------------------------------------
@ -277,50 +278,10 @@ FunctionEnd
no_process_${processName}_to_end: no_process_${processName}_to_end:
!macroend !macroend
!macro StartExplorerAsUserMacro un
Function ${un}StartExplorerAsUser
Exec "$WINDIR\explorer.exe"
FunctionEnd
!macroend
!insertmacro StartExplorerAsUserMacro ""
!insertmacro StartExplorerAsUserMacro "un."
!macro StartExplorer un
DetailPrint "Starting Explorer..."
${UAC.CallFunctionAsUser} ${un}StartExplorerAsUser
!macroend
!macro StopExplorer
DetailPrint "Terminated Explorer..."
FindWindow $R0 "Shell_TrayWnd"
SendMessage $R0 0x5B4 0 0
#Processes::KillProcess explorer.exe
Sleep 1500
DetailPrint "Continuing..."
!macroend
Function EnsureOwncloudShutdown Function EnsureOwncloudShutdown
!insertmacro CheckAndConfirmEndProcess "${APPLICATION_EXECUTABLE}" !insertmacro CheckAndConfirmEndProcess "${APPLICATION_EXECUTABLE}"
FunctionEnd FunctionEnd
Function RegisterShellExt
SetOutPath "$INSTDIR\shellext"
${If} ${RunningX64}
ExecWait '"$SYSDIR\regsvr32.exe" /s "$OUTDIR\OCOverlays_x64.dll"'
${Else}
ExecWait '"$SYSDIR\regsvr32.exe" /s "$OUTDIR\OCOverlays_x86.dll"'
${EndIf}
FunctionEnd
Function Un.RegisterShellExt
${If} ${RunningX64}
ExecWait '"$SYSDIR\regsvr32.exe" /u /s "$INSTDIR\shellext\OCOverlays_x64.dll"'
${Else}
ExecWait '"$SYSDIR\regsvr32.exe" /u /s "$INSTDIR\shellext\OCOverlays_x86.dll"'
${EndIf}
FunctionEnd
Function InstallRedistributables Function InstallRedistributables
${If} ${RunningX64} ${If} ${RunningX64}
ExecWait '"$OUTDIR\vcredist_x64.exe" /install /quiet' ExecWait '"$OUTDIR\vcredist_x64.exe" /install /quiet'
@ -510,17 +471,19 @@ SectionEnd
SectionIn 1 2 SectionIn 1 2
SetDetailsPrint textonly SetDetailsPrint textonly
DetailPrint $OPTION_SECTION_SC_SHELL_EXT_DetailPrint DetailPrint $OPTION_SECTION_SC_SHELL_EXT_DetailPrint
SetOutPath "$INSTDIR\shellext"
File "${SOURCE_PATH}\binary\shell_integration\windows\Release\x64\OCUtil_x64.dll"
File "${SOURCE_PATH}\binary\shell_integration\windows\Release\x64\OCOverlays_x64.dll"
File "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCUtil_x86.dll"
File "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCOverlays_x86.dll"
File "${BUILD_PATH}\vcredist_x86.exe" File "${BUILD_PATH}\vcredist_x86.exe"
File "${BUILD_PATH}\vcredist_x64.exe" File "${BUILD_PATH}\vcredist_x64.exe"
Call InstallRedistributables Call InstallRedistributables
Call RegisterShellExt CreateDirectory "$INSTDIR\shellext"
!insertMacro StopExplorer ${If} ${RunningX64}
!insertMacro StartExplorer "" !define LIBRARY_X64
!insertmacro InstallLib DLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\x64\OCUtil_x64.dll" "$INSTDIR\shellext\OCUtil_x64.dll" "$INSTDIR\shellext"
!insertmacro InstallLib REGDLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\x64\OCOverlays_x64.dll" "$INSTDIR\shellext\OCOverlays_x64.dll" "$INSTDIR\shellext"
!undef LIBRARY_X64
${Else}
!insertmacro InstallLib DLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCUtil_x86.dll" "$INSTDIR\shellext\OCUtil_x86.dll" "$INSTDIR\shellext"
!insertmacro InstallLib REGDLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCOverlays_x86.dll" "$INSTDIR\shellext\OCOverlays_x86.dll" "$INSTDIR\shellext"
${Endif}
${MementoSectionEnd} ${MementoSectionEnd}
!endif !endif
@ -673,10 +636,16 @@ Section Uninstall
;Shell extension ;Shell extension
!ifdef OPTION_SECTION_SC_SHELL_EXT !ifdef OPTION_SECTION_SC_SHELL_EXT
!define LIBRARY_COM
!define LIBRARY_SHELL_EXTENSION
${If} ${HasSection} SEC_SHELL_EXT ${If} ${HasSection} SEC_SHELL_EXT
!insertmacro StopExplorer !define LIBRARY_X64
Call Un.RegisterShellExt !insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCUtil_x64.dll"
!insertmacro StartExplorer "Un." !insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCOverlays_x64.dll"
!undef LIBRARY_X64
${Else}
!insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCUtil_x86.dll"
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCOverlays_x86.dll"
${EndIf} ${EndIf}
!endif !endif

View file

@ -660,7 +660,7 @@ int csync_add_exclude_list(CSYNC *ctx, const char *path) {
return -1; return -1;
} }
return csync_exclude_load(ctx, path); return csync_exclude_load(path, &ctx->excludes);
} }
void csync_clear_exclude_list(CSYNC *ctx) void csync_clear_exclude_list(CSYNC *ctx)

View file

@ -134,23 +134,6 @@ enum csync_ftw_type_e {
CSYNC_FTW_TYPE_SKIP CSYNC_FTW_TYPE_SKIP
}; };
enum csync_notify_type_e {
CSYNC_NOTIFY_INVALID,
CSYNC_NOTIFY_START_SYNC_SEQUENCE,
CSYNC_NOTIFY_START_DOWNLOAD,
CSYNC_NOTIFY_START_UPLOAD,
CSYNC_NOTIFY_PROGRESS,
CSYNC_NOTIFY_FINISHED_DOWNLOAD,
CSYNC_NOTIFY_FINISHED_UPLOAD,
CSYNC_NOTIFY_FINISHED_SYNC_SEQUENCE,
CSYNC_NOTIFY_START_DELETE,
CSYNC_NOTIFY_END_DELETE,
CSYNC_NOTIFY_ERROR,
CSYNC_NOTIFY_START_LOCAL_UPDATE,
CSYNC_NOTIFY_FINISHED_LOCAL_UPDATE,
CSYNC_NOTIFY_START_REMOTE_UPDATE,
CSYNC_NOTIFY_FINISHED_REMOTE_UPDATE
};
/** /**
* CSync File Traversal structure. * CSync File Traversal structure.
@ -203,6 +186,9 @@ typedef void (*csync_log_callback) (int verbosity,
const char *buffer, const char *buffer,
void *userdata); void *userdata);
typedef void (*csync_update_callback) (bool local,
const char *dirUrl,
void *userdata);
/** /**
* @brief Allocate a csync context. * @brief Allocate a csync context.

View file

@ -40,28 +40,28 @@
#define CSYNC_LOG_CATEGORY_NAME "csync.exclude" #define CSYNC_LOG_CATEGORY_NAME "csync.exclude"
#include "csync_log.h" #include "csync_log.h"
static int _csync_exclude_add(CSYNC *ctx, const char *string) { static int _csync_exclude_add(c_strlist_t **inList, const char *string) {
c_strlist_t *list; c_strlist_t *list;
if (ctx->excludes == NULL) { if (*inList == NULL) {
ctx->excludes = c_strlist_new(32); *inList = c_strlist_new(32);
if (ctx->excludes == NULL) { if (*inList == NULL) {
return -1; return -1;
} }
} }
if (ctx->excludes->count == ctx->excludes->size) { if ((*inList)->count == (*inList)->size) {
list = c_strlist_expand(ctx->excludes, 2 * ctx->excludes->size); list = c_strlist_expand(*inList, 2 * (*inList)->size);
if (list == NULL) { if (list == NULL) {
return -1; return -1;
} }
ctx->excludes = list; *inList = list;
} }
return c_strlist_add(ctx->excludes, string); return c_strlist_add(*inList, string);
} }
int csync_exclude_load(CSYNC *ctx, const char *fname) { int csync_exclude_load(const char *fname, c_strlist_t **list) {
int fd = -1; int fd = -1;
int i = 0; int i = 0;
int rc = -1; int rc = -1;
@ -70,7 +70,7 @@ int csync_exclude_load(CSYNC *ctx, const char *fname) {
char *entry = NULL; char *entry = NULL;
mbchar_t *w_fname; mbchar_t *w_fname;
if (ctx == NULL || fname == NULL) { if (fname == NULL) {
return -1; return -1;
} }
@ -119,7 +119,7 @@ int csync_exclude_load(CSYNC *ctx, const char *fname) {
buf[i] = '\0'; buf[i] = '\0';
if (*entry != '#') { if (*entry != '#') {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", entry); CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", entry);
rc = _csync_exclude_add(ctx, entry); rc = _csync_exclude_add(list, entry);
if (rc < 0) { if (rc < 0) {
goto out; goto out;
} }
@ -145,6 +145,21 @@ void csync_exclude_destroy(CSYNC *ctx) {
} }
CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) { CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
CSYNC_EXCLUDE_TYPE match = CSYNC_NOT_EXCLUDED;
match = csync_excluded_no_ctx( ctx->excludes, path, filetype );
if (match == CSYNC_NOT_EXCLUDED && ctx->checkBlackListHook) {
if (ctx->checkBlackListHook(ctx->checkBlackListData, path)) {
match = CSYNC_FILE_EXCLUDE_LIST;
}
}
return match;
}
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype) {
size_t i = 0; size_t i = 0;
const char *p = NULL; const char *p = NULL;
char *bname = NULL; char *bname = NULL;
@ -226,14 +241,14 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
SAFE_FREE(bname); SAFE_FREE(bname);
SAFE_FREE(dname); SAFE_FREE(dname);
if (ctx == NULL || ctx->excludes == NULL) { if( ! excludes ) {
goto out; goto out;
} }
/* Loop over all exclude patterns and evaluate the given path */ /* Loop over all exclude patterns and evaluate the given path */
for (i = 0; match == CSYNC_NOT_EXCLUDED && i < ctx->excludes->count; i++) { for (i = 0; match == CSYNC_NOT_EXCLUDED && i < excludes->count; i++) {
bool match_dirs_only = false; bool match_dirs_only = false;
char *pattern_stored = c_strdup(ctx->excludes->vector[i]); char *pattern_stored = c_strdup(excludes->vector[i]);
char* pattern = pattern_stored; char* pattern = pattern_stored;
type = CSYNC_FILE_EXCLUDE_LIST; type = CSYNC_FILE_EXCLUDE_LIST;
@ -313,6 +328,7 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
SAFE_FREE(dname); SAFE_FREE(dname);
} }
out: out:
return match; return match;

View file

@ -37,7 +37,7 @@ typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
* *
* @return 0 on success, -1 if an error occured with errno set. * @return 0 on success, -1 if an error occured with errno set.
*/ */
int csync_exclude_load(CSYNC *ctx, const char *fname); int csync_exclude_load(const char *fname, c_strlist_t **list);
/** /**
* @brief Clear the exclude list in memory. * @brief Clear the exclude list in memory.
@ -65,6 +65,14 @@ void csync_exclude_destroy(CSYNC *ctx);
*/ */
CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype); CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype);
/**
* @brief csync_excluded_no_ctx
* @param excludes
* @param path
* @param filetype
* @return
*/
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype);
#endif /* _CSYNC_EXCLUDE_H */ #endif /* _CSYNC_EXCLUDE_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */ /* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

View file

@ -24,6 +24,8 @@
#include <inttypes.h> #include <inttypes.h>
#include "csync_private.h"
/* /*
* helper method to build up a user text for SSL problems, called from the * helper method to build up a user text for SSL problems, called from the
@ -430,6 +432,8 @@ static int dav_connect(csync_owncloud_ctx_t *ctx, const char *base_url) {
ne_set_read_timeout(ctx->dav_session.ctx, ctx->dav_session.read_timeout); ne_set_read_timeout(ctx->dav_session.ctx, ctx->dav_session.read_timeout);
DEBUG_WEBDAV("Timeout set to %u seconds", ctx->dav_session.read_timeout ); DEBUG_WEBDAV("Timeout set to %u seconds", ctx->dav_session.read_timeout );
} }
// Should never take more than some seconds, 30 is really a max.
ne_set_connect_timeout(ctx->dav_session.ctx, 30);
snprintf( uaBuf, sizeof(uaBuf), "Mozilla/5.0 (%s) csyncoC/%s", snprintf( uaBuf, sizeof(uaBuf), "Mozilla/5.0 (%s) csyncoC/%s",
csync_owncloud_get_platform(), CSYNC_STRINGIFY( LIBCSYNC_VERSION )); csync_owncloud_get_platform(), CSYNC_STRINGIFY( LIBCSYNC_VERSION ));
@ -537,6 +541,11 @@ static struct listdir_context *fetch_resource_list(csync_owncloud_ctx_t *ctx, co
} }
} }
if( ctx->csync_ctx->callbacks.update_callback ) {
ctx->csync_ctx->callbacks.update_callback(false, curi,
ctx->csync_ctx->callbacks.update_callback_userdata);
}
fetchCtx = c_malloc( sizeof( struct listdir_context )); fetchCtx = c_malloc( sizeof( struct listdir_context ));
if (!fetchCtx) { if (!fetchCtx) {
errno = ENOMEM; errno = ENOMEM;

View file

@ -54,6 +54,9 @@ struct listdir_context *get_listdir_context_from_recursive_cache(csync_owncloud_
DEBUG_WEBDAV("get_listdir_context_from_recursive_cache No element %s in cache found", curi); DEBUG_WEBDAV("get_listdir_context_from_recursive_cache No element %s in cache found", curi);
return NULL; return NULL;
} }
if( ctx->csync_ctx->callbacks.update_callback ) {
ctx->csync_ctx->callbacks.update_callback(false, curi, ctx->csync_ctx->callbacks.update_callback_userdata);
}
/* Out of the element, create a listdir_context.. if we could be sure that it is immutable, we could ref instead.. need to investigate */ /* Out of the element, create a listdir_context.. if we could be sure that it is immutable, we could ref instead.. need to investigate */
fetchCtx = c_malloc( sizeof( struct listdir_context )); fetchCtx = c_malloc( sizeof( struct listdir_context ));
@ -141,6 +144,14 @@ static void propfind_results_recursive_callback(void *userdata,
element->parent = NULL; element->parent = NULL;
c_rbtree_insert(ctx->propfind_recursive_cache, element); c_rbtree_insert(ctx->propfind_recursive_cache, element);
/* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */ /* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */
// We do this here and in get_listdir_context_from_recursive_cache because
// a recursive PROPFIND might take some time but we still want to
// be informed. Later when get_listdir_context_from_recursive_cache is
// called the DB queries might be the problem causing slowness, so do it again there then.
if( ctx->csync_ctx->callbacks.update_callback ) {
ctx->csync_ctx->callbacks.update_callback(false, path, ctx->csync_ctx->callbacks.update_callback_userdata);
}
} }
} }
@ -189,6 +200,9 @@ void fetch_resource_list_recursive(csync_owncloud_ctx_t *ctx, const char *uri, c
int depth = NE_DEPTH_INFINITE; int depth = NE_DEPTH_INFINITE;
DEBUG_WEBDAV("fetch_resource_list_recursive Starting recursive propfind %s %s", uri, curi); DEBUG_WEBDAV("fetch_resource_list_recursive Starting recursive propfind %s %s", uri, curi);
if( ctx->csync_ctx->callbacks.update_callback ) {
ctx->csync_ctx->callbacks.update_callback(false, curi, ctx->csync_ctx->callbacks.update_callback_userdata);
}
/* do a propfind request and parse the results in the results function, set as callback */ /* do a propfind request and parse the results in the results function, set as callback */
hdl = ne_propfind_create(ctx->dav_session.ctx, curi, depth); hdl = ne_propfind_create(ctx->dav_session.ctx, curi, depth);

View file

@ -87,6 +87,8 @@ struct csync_s {
struct { struct {
csync_auth_callback auth_function; csync_auth_callback auth_function;
void *userdata; void *userdata;
csync_update_callback update_callback;
void *update_callback_userdata;
} callbacks; } callbacks;
c_strlist_t *excludes; c_strlist_t *excludes;
@ -144,6 +146,10 @@ struct csync_s {
int read_from_db_disabled; int read_from_db_disabled;
struct csync_owncloud_ctx_s *owncloud_context; struct csync_owncloud_ctx_s *owncloud_context;
/* hooks for checking the white list */
void *checkBlackListData;
int (*checkBlackListHook)(void*, const char*);
}; };

View file

@ -222,6 +222,9 @@ int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
result = csync_statedb_query(db, "PRAGMA case_sensitive_like = ON;"); result = csync_statedb_query(db, "PRAGMA case_sensitive_like = ON;");
c_strlist_destroy(result); c_strlist_destroy(result);
/* set a busy handler with 5 seconds timeout */
sqlite3_busy_timeout(db, 5000);
#ifndef NDEBUG #ifndef NDEBUG
sqlite3_profile(db, sqlite_profile, 0 ); sqlite3_profile(db, sqlite_profile, 0 );
#endif #endif
@ -319,6 +322,10 @@ static int _csync_file_stat_from_metadata_table( csync_file_stat_t **st, sqlite3
REMOTE_PERM_BUF_SIZE); REMOTE_PERM_BUF_SIZE);
} }
} }
} else {
if( rc != SQLITE_DONE ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "WARN: Query results in %d", rc);
}
} }
return rc; return rc;
} }
@ -350,8 +357,9 @@ csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx,
sqlite3_bind_int64(ctx->statedb.by_hash_stmt, 1, (long long signed int)phash); sqlite3_bind_int64(ctx->statedb.by_hash_stmt, 1, (long long signed int)phash);
if( _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_hash_stmt) < 0 ) { rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_hash_stmt);
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata!"); if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
} }
sqlite3_reset(ctx->statedb.by_hash_stmt); sqlite3_reset(ctx->statedb.by_hash_stmt);
@ -387,8 +395,9 @@ csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx,
/* bind the query value */ /* bind the query value */
sqlite3_bind_text(ctx->statedb.by_fileid_stmt, 1, file_id, -1, SQLITE_STATIC); sqlite3_bind_text(ctx->statedb.by_fileid_stmt, 1, file_id, -1, SQLITE_STATIC);
if( _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_fileid_stmt) < 0 ) { rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_fileid_stmt);
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata!"); if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
} }
// clear the resources used by the statement. // clear the resources used by the statement.
sqlite3_reset(ctx->statedb.by_fileid_stmt); sqlite3_reset(ctx->statedb.by_fileid_stmt);
@ -427,8 +436,9 @@ csync_file_stat_t *csync_statedb_get_stat_by_inode(CSYNC *ctx,
sqlite3_bind_int64(ctx->statedb.by_inode_stmt, 1, (long long signed int)inode); sqlite3_bind_int64(ctx->statedb.by_inode_stmt, 1, (long long signed int)inode);
if( _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_inode_stmt) < 0 ) { rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_inode_stmt);
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata by inode!"); if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata by inode: %d!", rc);
} }
sqlite3_reset(ctx->statedb.by_inode_stmt); sqlite3_reset(ctx->statedb.by_inode_stmt);
@ -457,7 +467,7 @@ char *csync_statedb_get_etag( CSYNC *ctx, uint64_t jHash ) {
return ret; return ret;
} }
#define BELOW_PATH_QUERY "SELECT phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm FROM metadata WHERE path LIKE(?)" #define BELOW_PATH_QUERY "SELECT phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm FROM metadata WHERE pathlen>? AND path LIKE(?)"
int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) { int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
int rc; int rc;
@ -465,6 +475,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
int64_t cnt = 0; int64_t cnt = 0;
char *likepath; char *likepath;
int asp; int asp;
int min_path_len;
if( !path ) { if( !path ) {
return -1; return -1;
@ -476,7 +487,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
rc = sqlite3_prepare_v2(ctx->statedb.db, BELOW_PATH_QUERY, -1, &stmt, NULL); rc = sqlite3_prepare_v2(ctx->statedb.db, BELOW_PATH_QUERY, -1, &stmt, NULL);
if( rc != SQLITE_OK ) { if( rc != SQLITE_OK ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for hash query."); CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for below path query.");
return -1; return -1;
} }
@ -490,7 +501,9 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
return -1; return -1;
} }
sqlite3_bind_text(stmt, 1, likepath, -1, SQLITE_STATIC); min_path_len = strlen(path);
sqlite3_bind_int(stmt, 1, min_path_len);
sqlite3_bind_text(stmt, 2, likepath, -1, SQLITE_STATIC);
cnt = 0; cnt = 0;

View file

@ -342,6 +342,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
} }
} }
} else { } else {
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Unable to open statedb, setting inst to NEW" );
st->instruction = CSYNC_INSTRUCTION_NEW; st->instruction = CSYNC_INSTRUCTION_NEW;
} }

View file

@ -48,6 +48,9 @@ csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name) {
return owncloud_opendir(ctx, name); return owncloud_opendir(ctx, name);
break; break;
case LOCAL_REPLICA: case LOCAL_REPLICA:
if( ctx->callbacks.update_callback ) {
ctx->callbacks.update_callback(ctx->replica, name, ctx->callbacks.update_callback_userdata);
}
return csync_vio_local_opendir(name); return csync_vio_local_opendir(name);
break; break;
default: default:

View file

@ -25,6 +25,8 @@
#define CSYNC_TEST 1 #define CSYNC_TEST 1
#include "csync_exclude.c" #include "csync_exclude.c"
#define EXCLUDE_LIST_FILE SOURCEDIR"/../sync-exclude.lst"
static void setup(void **state) { static void setup(void **state) {
CSYNC *csync; CSYNC *csync;
int rc; int rc;
@ -42,7 +44,7 @@ static void setup_init(void **state) {
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2"); rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
assert_int_equal(rc, 0); assert_int_equal(rc, 0);
rc = csync_exclude_load(csync, SOURCEDIR "/../sync-exclude.lst"); rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes));
assert_int_equal(rc, 0); assert_int_equal(rc, 0);
*state = csync; *state = csync;
@ -66,7 +68,7 @@ static void teardown(void **state) {
static void check_csync_exclude_add(void **state) static void check_csync_exclude_add(void **state)
{ {
CSYNC *csync = *state; CSYNC *csync = *state;
_csync_exclude_add(csync, (const char *) "/tmp/check_csync1/*"); _csync_exclude_add(&(csync->excludes), "/tmp/check_csync1/*");
assert_string_equal(csync->excludes->vector[0], "/tmp/check_csync1/*"); assert_string_equal(csync->excludes->vector[0], "/tmp/check_csync1/*");
} }
@ -75,10 +77,11 @@ static void check_csync_exclude_load(void **state)
CSYNC *csync = *state; CSYNC *csync = *state;
int rc; int rc;
rc = csync_exclude_load(csync, SOURCEDIR "/../sync-exclude.lst"); rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes) );
assert_int_equal(rc, 0); assert_int_equal(rc, 0);
assert_string_equal(csync->excludes->vector[0], "*.filepart"); assert_string_equal(csync->excludes->vector[0], "*.filepart");
assert_int_not_equal(csync->excludes->count, 0);
} }
static void check_csync_excluded(void **state) static void check_csync_excluded(void **state)
@ -106,15 +109,9 @@ static void check_csync_excluded(void **state)
rc = csync_excluded(csync, "foo/bar/.apdisk", CSYNC_FTW_TYPE_DIR); rc = csync_excluded(csync, "foo/bar/.apdisk", CSYNC_FTW_TYPE_DIR);
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
/*
* Pattern: .java/
* A file wont be excluded but a directory .java will be.
*/
/* rc = csync_excluded(csync, ".java", CSYNC_FTW_TYPE_DIR);
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
rc = csync_excluded(csync, ".java", CSYNC_FTW_TYPE_FILE); rc = csync_excluded(csync, ".java", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_NOT_EXCLUDED); assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
*/
/* Files in the ignored dir .java will also be ignored. */ /* Files in the ignored dir .java will also be ignored. */
rc = csync_excluded(csync, ".apdisk/totally_amazing.jar", CSYNC_FTW_TYPE_FILE); rc = csync_excluded(csync, ".apdisk/totally_amazing.jar", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
@ -141,20 +138,6 @@ static void check_csync_excluded(void **state)
/* Not excluded because the pattern .netscape/cache requires directory. */ /* Not excluded because the pattern .netscape/cache requires directory. */
rc = csync_excluded(csync, ".netscape/cache", CSYNC_FTW_TYPE_FILE); rc = csync_excluded(csync, ".netscape/cache", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_NOT_EXCLUDED); assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
/*
rc = csync_excluded(csync, ".netscape/cache", CSYNC_FTW_TYPE_DIR);
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);*/
/* Excluded because the parent dir .netscape/cache is ingored. */
/* rc = csync_excluded(csync, ".netscape/cache/foo", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
rc = csync_excluded(csync, ".netscape/cache/bar.txt", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
rc = csync_excluded(csync, ".netscape/cache/longrun", CSYNC_FTW_TYPE_DIR);
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
*/
} }

View file

@ -13,7 +13,6 @@
<file>resources/settings.png</file> <file>resources/settings.png</file>
<file>resources/activity.png</file> <file>resources/activity.png</file>
<file>resources/network.png</file> <file>resources/network.png</file>
<file>resources/owncloud_logo_blue.png</file>
<file>resources/lock-http.png</file> <file>resources/lock-http.png</file>
<file>resources/lock-https.png</file> <file>resources/lock-https.png</file>
</qresource> </qresource>

View file

@ -1,11 +1,11 @@
if(APPLE) if(APPLE)
add_custom_target( mac_overlayplugin ALL add_custom_target( mac_overlayplugin ALL
xcodebuild -workspace ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/LiferayNativity.xcworkspace xcodebuild -workspace ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloud.xcworkspace
-scheme LiferayNativity.osax SYMROOT=${CMAKE_CURRENT_BINARY_DIR} archive -scheme OwnCloudFinder.osax SYMROOT=${CMAKE_CURRENT_BINARY_DIR} archive
COMMENT building Mac Overlay iccons) COMMENT building Mac Overlay iccons)
INSTALL( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/LiferayNativity.osax/Contents INSTALL( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/OwnCloudFinder.osax/Contents
DESTINATION ${CMAKE_INSTALL_PREFIX}/Library/ScriptingAdditions/LiferayNativity.osax/ ) DESTINATION ${CMAKE_INSTALL_PREFIX}/Library/ScriptingAdditions/OwnCloudFinder.osax/ )
endif(APPLE) endif(APPLE)

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:LiferayNativityFinder/LiferayNativityFinder.xcodeproj">
</FileRef>
<FileRef
location = "group:LiferayNativityInjector/LiferayNativityInjector.xcodeproj">
</FileRef>
</Workspace>

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
type = "0"
version = "1.0">
<FileBreakpoints>
<FileBreakpoint
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "LiferayNativityFinder/ContentManager.m"
timestampString = "426161859.780288"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "90"
endingLineNumber = "90"
landmarkName = "-setResultForPath:result:"
landmarkType = "5">
</FileBreakpoint>
</FileBreakpoints>
</Bucket>

View file

@ -1,28 +0,0 @@
/**
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*/
#import <Foundation/Foundation.h>
@interface NSObject (ContextMenuHandlers)
struct TFENodeVector;
+ (void)ContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 view:(id)arg4 browserController:(id)arg5 addPlugIns:(BOOL)arg6;
+ (void)ContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 view:(id)arg4 windowController:(id)arg5 addPlugIns:(BOOL)arg6;
+ (void)ContextMenuHandlers_addViewSpecificStuffToMenu:(id)arg1 browserViewController:(id)arg2 context:(unsigned int)arg3;
- (void)ContextMenuHandlers_configureWithNodes:(const struct TFENodeVector*)arg1 browserController:(id)arg2 container:(BOOL)arg3;
- (void)ContextMenuHandlers_configureWithNodes:(const struct TFENodeVector*)arg1 windowController:(id)arg2 container:(BOOL)arg3;
@end

View file

@ -1,125 +0,0 @@
/**
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*/
#import "ContentManager.h"
#import "FinderHook.h"
#import "IconCache.h"
#import "objc/objc-class.h"
#import "RequestManager.h"
static BOOL installed = NO;
@implementation FinderHook
+ (void)hookClassMethod:(SEL)oldSelector inClass:(NSString*)className toCallToTheNewMethod:(SEL)newSelector
{
Class hookedClass = NSClassFromString(className);
Method oldMethod = class_getClassMethod(hookedClass, oldSelector);
Method newMethod = class_getClassMethod(hookedClass, newSelector);
method_exchangeImplementations(newMethod, oldMethod);
}
+ (void)hookMethod:(SEL)oldSelector inClass:(NSString*)className toCallToTheNewMethod:(SEL)newSelector
{
Class hookedClass = NSClassFromString(className);
Method oldMethod = class_getInstanceMethod(hookedClass, oldSelector);
Method newMethod = class_getInstanceMethod(hookedClass, newSelector);
method_exchangeImplementations(newMethod, oldMethod);
}
+ (void)install
{
if (installed)
{
NSLog(@"LiferayNativityFinder: already installed");
return;
}
NSLog(@"LiferayNativityFinder: installing ownCloud Shell extension");
[RequestManager sharedInstance];
// Icons
[self hookMethod:@selector(drawImage:) inClass:@"IKImageBrowserCell" toCallToTheNewMethod:@selector(IconOverlayHandlers_IKImageBrowserCell_drawImage:)]; // 10.7 & 10.8 & 10.9 (Icon View arrange by name)
[self hookMethod:@selector(drawImage:) inClass:@"IKFinderReflectiveIconCell" toCallToTheNewMethod:@selector(IconOverlayHandlers_IKFinderReflectiveIconCell_drawImage:)]; // 10.7 & 10.8 & 10.9 (Icon View arrange by everything else)
[self hookMethod:@selector(drawIconWithFrame:) inClass:@"TListViewIconAndTextCell" toCallToTheNewMethod:@selector(IconOverlayHandlers_drawIconWithFrame:)]; // 10.7 & 10.8 & 10.9 Column View
[self hookMethod:@selector(drawRect:) inClass:@"TDimmableIconImageView" toCallToTheNewMethod:@selector(IconOverlayHandlers_drawRect:)]; // 10.9 (List and Coverflow Views)
// Context Menus
[self hookClassMethod:@selector(addViewSpecificStuffToMenu:browserViewController:context:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(ContextMenuHandlers_addViewSpecificStuffToMenu:browserViewController:context:)]; // 10.7 & 10.8
[self hookClassMethod:@selector(addViewSpecificStuffToMenu:clickedView:browserViewController:context:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(ContextMenuHandlers_addViewSpecificStuffToMenu:clickedView:browserViewController:context:)]; // 10.9
[self hookClassMethod:@selector(handleContextMenuCommon:nodes:event:view:windowController:addPlugIns:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(ContextMenuHandlers_handleContextMenuCommon:nodes:event:view:windowController:addPlugIns:)]; // 10.7
[self hookClassMethod:@selector(handleContextMenuCommon:nodes:event:view:browserController:addPlugIns:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(ContextMenuHandlers_handleContextMenuCommon:nodes:event:view:browserController:addPlugIns:)]; // 10.8
[self hookClassMethod:@selector(handleContextMenuCommon:nodes:event:clickedView:browserViewController:addPlugIns:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(ContextMenuHandlers_handleContextMenuCommon:nodes:event:clickedView:browserViewController:addPlugIns:)]; // 10.9
[self hookMethod:@selector(configureWithNodes:windowController:container:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(ContextMenuHandlers_configureWithNodes:windowController:container:)]; // 10.7
[self hookMethod:@selector(configureWithNodes:browserController:container:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(ContextMenuHandlers_configureWithNodes:browserController:container:)]; // 10.8
[self hookMethod:@selector(configureFromMenuNeedsUpdate:clickedView:container:event:selectedNodes:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(ContextMenuHandlers_configureFromMenuNeedsUpdate:clickedView:container:event:selectedNodes:)]; // 10.9
installed = YES;
NSLog(@"LiferayNativityFinder: installed");
}
+ (void)uninstall
{
if (!installed)
{
NSLog(@"LiferayNativityFinder: not installed");
return;
}
NSLog(@"LiferayNativityFinder: uninstalling");
[[ContentManager sharedInstance] dealloc];
[[IconCache sharedInstance] dealloc];
[[RequestManager sharedInstance] dealloc];
// Icons
[self hookMethod:@selector(IconOverlayHandlers_drawImage:) inClass:@"TIconViewCell" toCallToTheNewMethod:@selector(drawImage:)]; // 10.7 & 10.8 & 10.9
[self hookMethod:@selector(IconOverlayHandlers_drawIconWithFrame:) inClass:@"TListViewIconAndTextCell" toCallToTheNewMethod:@selector(drawIconWithFrame:)]; // 10.7 & 10.8 & 10.9
// Context Menus
[self hookClassMethod:@selector(ContextMenuHandlers_addViewSpecificStuffToMenu:browserViewController:context:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(addViewSpecificStuffToMenu:browserViewController:context:)]; // 10.7 & 10.8
[self hookClassMethod:@selector(ContextMenuHandlers_handleContextMenuCommon:nodes:event:view:windowController:addPlugIns:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(handleContextMenuCommon:nodes:event:view:windowController:addPlugIns:)]; // 10.7
[self hookMethod:@selector(ContextMenuHandlers_configureWithNodes:windowController:container:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(configureWithNodes:windowController:container:)]; // 10.7
[self hookClassMethod:@selector(ContextMenuHandlers_handleContextMenuCommon:nodes:event:view:browserController:addPlugIns:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(handleContextMenuCommon:nodes:event:view:browserController:addPlugIns:)]; // 10.8
[self hookMethod:@selector(ContextMenuHandlers_configureWithNodes:browserController:container:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(configureWithNodes:browserController:container:)]; // 10.8
installed = NO;
NSLog(@"LiferayNativityFinder: uninstalled");
}
@end

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary title="LiferayNativityInjector Terminology">
<suite name="LiferayNativityInjector Suite" code="NVTY" description="LiferayNativity Injector commands">
<command name="install LiferayNativity" code="NVTYload" description="Loads LiferayNativity into the Finder process"/>
<command name="uninstall LiferayNativity" code="NVTYunld" description="Unloads LiferayNativity from the Finder process"/>
<command name="check LiferayNativity" code="NVTYlded" description="Checks if LiferayNativity is loaded in Finder process"/>
</suite>
</dictionary>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:OwnCloudFinder/OwnCloudFinder.xcodeproj">
</FileRef>
<FileRef
location = "group:OwnCloudInjector/OwnCloudInjector.xcodeproj">
</FileRef>
</Workspace>

View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
<false/>
<key>IDESourceControlProjectIdentifier</key>
<string>5264E8F5-AB49-45F3-868F-647EEFAB70E0</string>
<key>IDESourceControlProjectName</key>
<string>OwnCloud</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>09EE94AA-F410-4594-AB26-5A0220DEAEC7</key>
<string>ssh://github.com/owncloud/mirall.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>shell_integration/MacOSX/OwnCloud.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>09EE94AA-F410-4594-AB26-5A0220DEAEC7</key>
<string>../../..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>ssh://github.com/owncloud/mirall.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>110</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>09EE94AA-F410-4594-AB26-5A0220DEAEC7</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>09EE94AA-F410-4594-AB26-5A0220DEAEC7</string>
<key>IDESourceControlWCCName</key>
<string>mirall</string>
</dict>
</array>
</dict>
</plist>

View file

@ -237,7 +237,7 @@ static ContentManager* sharedInstance = nil;
} }
else else
{ {
NSLog(@"LiferayNativityFinder: refreshing icon badges failed"); NSLog(@"OwnCloudFinder: refreshing icon badges failed");
return; return;
} }

View file

@ -0,0 +1,28 @@
/**
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*/
#import <Foundation/Foundation.h>
@interface NSObject (ContextMenuHandlers)
struct TFENodeVector;
+ (void)OCContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 view:(id)arg4 browserController:(id)arg5 addPlugIns:(BOOL)arg6;
+ (void)OCContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 view:(id)arg4 windowController:(id)arg5 addPlugIns:(BOOL)arg6;
+ (void)OCContextMenuHandlers_addViewSpecificStuffToMenu:(id)arg1 browserViewController:(id)arg2 context:(unsigned int)arg3;
- (void)OCContextMenuHandlers_configureWithNodes:(const struct TFENodeVector*)arg1 browserController:(id)arg2 container:(BOOL)arg3;
- (void)OCContextMenuHandlers_configureWithNodes:(const struct TFENodeVector*)arg1 windowController:(id)arg2 container:(BOOL)arg3;
@end

View file

@ -17,9 +17,9 @@
@implementation NSObject (ContextMenuHandlers) @implementation NSObject (ContextMenuHandlers)
+ (void)ContextMenuHandlers_addViewSpecificStuffToMenu:(id)arg1 browserViewController:(id)arg2 context:(unsigned int)arg3 // 10.7 & 10.8 + (void)OCContextMenuHandlers_addViewSpecificStuffToMenu:(id)arg1 browserViewController:(id)arg2 context:(unsigned int)arg3 // 10.7 & 10.8
{ {
[self ContextMenuHandlers_addViewSpecificStuffToMenu:arg1 browserViewController:arg2 context:arg3]; [self OCContextMenuHandlers_addViewSpecificStuffToMenu:arg1 browserViewController:arg2 context:arg3];
MenuManager* menuManager = [MenuManager sharedInstance]; MenuManager* menuManager = [MenuManager sharedInstance];
@ -30,9 +30,9 @@
} }
} }
+ (void)ContextMenuHandlers_addViewSpecificStuffToMenu:(id)arg1 clickedView:(id)arg2 browserViewController:(id)arg3 context:(unsigned int)arg4 // 10.9 + (void)OCContextMenuHandlers_addViewSpecificStuffToMenu:(id)arg1 clickedView:(id)arg2 browserViewController:(id)arg3 context:(unsigned int)arg4 // 10.9
{ {
[self ContextMenuHandlers_addViewSpecificStuffToMenu:arg1 clickedView:arg2 browserViewController:arg3 context:arg4]; [self OCContextMenuHandlers_addViewSpecificStuffToMenu:arg1 clickedView:arg2 browserViewController:arg3 context:arg4];
MenuManager* menuManager = [MenuManager sharedInstance]; MenuManager* menuManager = [MenuManager sharedInstance];

View file

@ -0,0 +1,125 @@
/**
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*/
#import "ContentManager.h"
#import "FinderHook.h"
#import "IconCache.h"
#import "objc/objc-class.h"
#import "RequestManager.h"
static BOOL installed = NO;
@implementation FinderHook
+ (void)hookClassMethod:(SEL)oldSelector inClass:(NSString*)className toCallToTheNewMethod:(SEL)newSelector
{
Class hookedClass = NSClassFromString(className);
Method oldMethod = class_getClassMethod(hookedClass, oldSelector);
Method newMethod = class_getClassMethod(hookedClass, newSelector);
method_exchangeImplementations(newMethod, oldMethod);
}
+ (void)hookMethod:(SEL)oldSelector inClass:(NSString*)className toCallToTheNewMethod:(SEL)newSelector
{
Class hookedClass = NSClassFromString(className);
Method oldMethod = class_getInstanceMethod(hookedClass, oldSelector);
Method newMethod = class_getInstanceMethod(hookedClass, newSelector);
method_exchangeImplementations(newMethod, oldMethod);
}
+ (void)install
{
if (installed)
{
NSLog(@"OwnCloudFinder: already installed");
return;
}
NSLog(@"OwnCloudFinder: installing ownCloud Shell extension");
[RequestManager sharedInstance];
// Icons
[self hookMethod:@selector(drawImage:) inClass:@"IKImageBrowserCell" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_IKImageBrowserCell_drawImage:)]; // 10.7 & 10.8 & 10.9 (Icon View arrange by name)
[self hookMethod:@selector(drawImage:) inClass:@"IKFinderReflectiveIconCell" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_IKFinderReflectiveIconCell_drawImage:)]; // 10.7 & 10.8 & 10.9 (Icon View arrange by everything else)
[self hookMethod:@selector(drawIconWithFrame:) inClass:@"TListViewIconAndTextCell" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_drawIconWithFrame:)]; // 10.7 & 10.8 & 10.9 Column View
[self hookMethod:@selector(drawRect:) inClass:@"TDimmableIconImageView" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_drawRect:)]; // 10.9 (List and Coverflow Views)
// Context Menus
[self hookClassMethod:@selector(addViewSpecificStuffToMenu:browserViewController:context:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(OCContextMenuHandlers_addViewSpecificStuffToMenu:browserViewController:context:)]; // 10.7 & 10.8
[self hookClassMethod:@selector(addViewSpecificStuffToMenu:clickedView:browserViewController:context:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(OCContextMenuHandlers_addViewSpecificStuffToMenu:clickedView:browserViewController:context:)]; // 10.9
[self hookClassMethod:@selector(handleContextMenuCommon:nodes:event:view:windowController:addPlugIns:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(OCContextMenuHandlers_handleContextMenuCommon:nodes:event:view:windowController:addPlugIns:)]; // 10.7
[self hookClassMethod:@selector(handleContextMenuCommon:nodes:event:view:browserController:addPlugIns:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(OCContextMenuHandlers_handleContextMenuCommon:nodes:event:view:browserController:addPlugIns:)]; // 10.8
[self hookClassMethod:@selector(handleContextMenuCommon:nodes:event:clickedView:browserViewController:addPlugIns:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(OCContextMenuHandlers_handleContextMenuCommon:nodes:event:clickedView:browserViewController:addPlugIns:)]; // 10.9
[self hookMethod:@selector(configureWithNodes:windowController:container:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(OCContextMenuHandlers_configureWithNodes:windowController:container:)]; // 10.7
[self hookMethod:@selector(configureWithNodes:browserController:container:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(OCContextMenuHandlers_configureWithNodes:browserController:container:)]; // 10.8
[self hookMethod:@selector(configureFromMenuNeedsUpdate:clickedView:container:event:selectedNodes:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(OCContextMenuHandlers_configureFromMenuNeedsUpdate:clickedView:container:event:selectedNodes:)]; // 10.9
installed = YES;
NSLog(@"OwnCloudFinder: installed");
}
+ (void)uninstall
{
if (!installed)
{
NSLog(@"OwnCloudFinder: not installed");
return;
}
NSLog(@"OwnCloudFinder: uninstalling");
[[ContentManager sharedInstance] dealloc];
[[IconCache sharedInstance] dealloc];
[[RequestManager sharedInstance] dealloc];
// Icons
[self hookMethod:@selector(OCIconOverlayHandlers_drawImage:) inClass:@"TIconViewCell" toCallToTheNewMethod:@selector(drawImage:)]; // 10.7 & 10.8 & 10.9
[self hookMethod:@selector(OCIconOverlayHandlers_drawIconWithFrame:) inClass:@"TListViewIconAndTextCell" toCallToTheNewMethod:@selector(drawIconWithFrame:)]; // 10.7 & 10.8 & 10.9
// Context Menus
[self hookClassMethod:@selector(OCContextMenuHandlers_addViewSpecificStuffToMenu:browserViewController:context:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(addViewSpecificStuffToMenu:browserViewController:context:)]; // 10.7 & 10.8
[self hookClassMethod:@selector(OCContextMenuHandlers_handleContextMenuCommon:nodes:event:view:windowController:addPlugIns:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(handleContextMenuCommon:nodes:event:view:windowController:addPlugIns:)]; // 10.7
[self hookMethod:@selector(OCContextMenuHandlers_configureWithNodes:windowController:container:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(configureWithNodes:windowController:container:)]; // 10.7
[self hookClassMethod:@selector(OCContextMenuHandlers_handleContextMenuCommon:nodes:event:view:browserController:addPlugIns:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(handleContextMenuCommon:nodes:event:view:browserController:addPlugIns:)]; // 10.8
[self hookMethod:@selector(OCContextMenuHandlers_configureWithNodes:browserController:container:) inClass:@"TContextMenu" toCallToTheNewMethod:@selector(configureWithNodes:browserController:container:)]; // 10.8
installed = NO;
NSLog(@"OwnCloudFinder: uninstalled");
}
@end

View file

@ -16,8 +16,8 @@
@interface NSObject (IconOverlayHandlers) @interface NSObject (IconOverlayHandlers)
- (void)IconOverlayHandlers_drawIconWithFrame:(struct CGRect)arg1; - (void)OCIconOverlayHandlers_drawIconWithFrame:(struct CGRect)arg1;
- (void)IconOverlayHandlers_drawImage:(id)arg1; - (void)OCIconOverlayHandlers_drawImage:(id)arg1;
- (void)IconOverlayHandlers_drawRect:(struct CGRect)arg1; - (void)OCIconOverlayHandlers_drawRect:(struct CGRect)arg1;
@end @end

View file

@ -22,7 +22,7 @@
- (void)IconOverlayHandlers_drawIconWithFrame:(struct CGRect)arg1 - (void)IconOverlayHandlers_drawIconWithFrame:(struct CGRect)arg1
{ {
[self IconOverlayHandlers_drawIconWithFrame:arg1]; [self OCIconOverlayHandlers_drawIconWithFrame:arg1];
NSURL* url = [[NSClassFromString(@"FINode") nodeFromNodeRef:[(TIconAndTextCell*)self node]->fNodeRef] previewItemURL]; NSURL* url = [[NSClassFromString(@"FINode") nodeFromNodeRef:[(TIconAndTextCell*)self node]->fNodeRef] previewItemURL];
@ -48,21 +48,21 @@
} }
} }
- (void)IconOverlayHandlers_IKImageBrowserCell_drawImage:(id)arg1 - (void)OCIconOverlayHandlers_IKImageBrowserCell_drawImage:(id)arg1
{ {
IKImageWrapper*imageWrapper = [self IconOverlayHandlers_imageWrapper:arg1]; IKImageWrapper*imageWrapper = [self OCIconOverlayHandlers_imageWrapper:arg1];
[self IconOverlayHandlers_IKImageBrowserCell_drawImage:imageWrapper]; [self OCIconOverlayHandlers_IKImageBrowserCell_drawImage:imageWrapper];
} }
- (void)IconOverlayHandlers_IKFinderReflectiveIconCell_drawImage:(id)arg1 - (void)OCIconOverlayHandlers_IKFinderReflectiveIconCell_drawImage:(id)arg1
{ {
IKImageWrapper*imageWrapper = [self IconOverlayHandlers_imageWrapper:arg1]; IKImageWrapper*imageWrapper = [self OCIconOverlayHandlers_imageWrapper:arg1];
[self IconOverlayHandlers_IKFinderReflectiveIconCell_drawImage:imageWrapper]; [self OCIconOverlayHandlers_IKFinderReflectiveIconCell_drawImage:imageWrapper];
} }
- (IKImageWrapper*)IconOverlayHandlers_imageWrapper:(id)arg1 - (IKImageWrapper*)OCIconOverlayHandlers_imageWrapper:(id)arg1
{ {
TIconViewCell* realSelf = (TIconViewCell*)self; TIconViewCell* realSelf = (TIconViewCell*)self;
FINode* node = (FINode*)[realSelf representedItem]; FINode* node = (FINode*)[realSelf representedItem];
@ -91,14 +91,18 @@
if (iconimage != nil) if (iconimage != nil)
{ {
CGImageSourceRef source; CGRect destRect = CGRectMake(0, 0, [icon size].width, [icon size].height);
NSData* data = [iconimage TIFFRepresentation]; CGImageRef cgImage = [iconimage CGImageForProposedRect:&destRect
context:[NSGraphicsContext currentContext]
hints:nil];
if (cgImage) {
CGContextDrawImage(myContext, destRect, cgImage);
//CGImageRelease(cgImage); // leak here? if we leave this code in, Finder crashes
// But actually i'm not seeing a leak in Activity Monitor.. maybe it is not really leaking?
} else {
NSLog(@"No image given!!!!!11 %@", [url path]);
}
source = CGImageSourceCreateWithData((CFDataRef)data, NULL);
CGImageRef maskRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
CGContextDrawImage(myContext, CGRectMake(0, 0, [icon size].width, [icon size].height), maskRef);
CFRelease(source);
CFRelease(maskRef);
} }
[icon unlockFocus]; [icon unlockFocus];
@ -111,9 +115,9 @@
} }
} }
- (void)IconOverlayHandlers_drawRect:(struct CGRect)arg1 - (void)OCIconOverlayHandlers_drawRect:(struct CGRect)arg1
{ {
[self IconOverlayHandlers_drawRect:arg1]; [self OCIconOverlayHandlers_drawRect:arg1];
NSView* supersuperview = [[(NSView*)self superview] superview]; NSView* supersuperview = [[(NSView*)self superview] superview];

View file

@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>NSPrincipalClass</key>
<string>FinderHook</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>English</string> <string>English</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
@ -11,7 +9,7 @@
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string></string> <string></string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.liferay.nativity</string> <string>com.owncloud.finder</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
@ -42,5 +40,7 @@
</dict> </dict>
<key>CFPlugInUnloadFunction</key> <key>CFPlugInUnloadFunction</key>
<string></string> <string></string>
<key>NSPrincipalClass</key>
<string>FinderHook</string>
</dict> </dict>
</plist> </plist>

View file

@ -48,7 +48,7 @@
8C37DDB9161594B400016A95 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; }; 8C37DDB9161594B400016A95 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; };
8C99F6921622D145002D2135 /* IconCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconCache.h; sourceTree = "<group>"; }; 8C99F6921622D145002D2135 /* IconCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconCache.h; sourceTree = "<group>"; };
8C99F6931622D145002D2135 /* IconCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IconCache.m; sourceTree = "<group>"; }; 8C99F6931622D145002D2135 /* IconCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IconCache.m; sourceTree = "<group>"; };
8D576316048677EA00EA77CD /* LiferayNativityFinder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LiferayNativityFinder.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 8D576316048677EA00EA77CD /* OwnCloudFinder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OwnCloudFinder.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -67,7 +67,7 @@
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
089C166AFE841209C02AAC07 /* LiferayNativityFinder */ = { 089C166AFE841209C02AAC07 /* OwnCloudFinder */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
08FB77AFFE84173DC02AAC07 /* Source */, 08FB77AFFE84173DC02AAC07 /* Source */,
@ -75,7 +75,7 @@
089C1671FE841209C02AAC07 /* External Frameworks and Libraries */, 089C1671FE841209C02AAC07 /* External Frameworks and Libraries */,
19C28FB6FE9D52B211CA2CBB /* Products */, 19C28FB6FE9D52B211CA2CBB /* Products */,
); );
name = LiferayNativityFinder; name = OwnCloudFinder;
sourceTree = "<group>"; sourceTree = "<group>";
usesTabs = 1; usesTabs = 1;
}; };
@ -152,7 +152,7 @@
19C28FB6FE9D52B211CA2CBB /* Products */ = { 19C28FB6FE9D52B211CA2CBB /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
8D576316048677EA00EA77CD /* LiferayNativityFinder.bundle */, 8D576316048677EA00EA77CD /* OwnCloudFinder.bundle */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -160,9 +160,9 @@
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
8D57630D048677EA00EA77CD /* LiferayNativityFinder */ = { 8D57630D048677EA00EA77CD /* OwnCloudFinder */ = {
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "LiferayNativityFinder" */; buildConfigurationList = 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "OwnCloudFinder" */;
buildPhases = ( buildPhases = (
8D57630F048677EA00EA77CD /* Resources */, 8D57630F048677EA00EA77CD /* Resources */,
8D576311048677EA00EA77CD /* Sources */, 8D576311048677EA00EA77CD /* Sources */,
@ -172,10 +172,10 @@
); );
dependencies = ( dependencies = (
); );
name = LiferayNativityFinder; name = OwnCloudFinder;
productInstallPath = "$(HOME)/Library/Bundles"; productInstallPath = "$(HOME)/Library/Bundles";
productName = LiferayNativityFinder; productName = OwnCloudFinder;
productReference = 8D576316048677EA00EA77CD /* LiferayNativityFinder.bundle */; productReference = 8D576316048677EA00EA77CD /* OwnCloudFinder.bundle */;
productType = "com.apple.product-type.bundle"; productType = "com.apple.product-type.bundle";
}; };
/* End PBXNativeTarget section */ /* End PBXNativeTarget section */
@ -186,7 +186,7 @@
attributes = { attributes = {
LastUpgradeCheck = 0460; LastUpgradeCheck = 0460;
}; };
buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "LiferayNativityFinder" */; buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "OwnCloudFinder" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.2";
developmentRegion = English; developmentRegion = English;
hasScannedForEncodings = 1; hasScannedForEncodings = 1;
@ -196,11 +196,11 @@
French, French,
German, German,
); );
mainGroup = 089C166AFE841209C02AAC07 /* LiferayNativityFinder */; mainGroup = 089C166AFE841209C02AAC07 /* OwnCloudFinder */;
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
targets = ( targets = (
8D57630D048677EA00EA77CD /* LiferayNativityFinder */, 8D57630D048677EA00EA77CD /* OwnCloudFinder */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
@ -260,7 +260,7 @@
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;
INFOPLIST_FILE = Info.plist; INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles"; INSTALL_PATH = "$(HOME)/Library/Bundles";
PRODUCT_NAME = LiferayNativityFinder; PRODUCT_NAME = OwnCloudFinder;
WRAPPER_EXTENSION = bundle; WRAPPER_EXTENSION = bundle;
}; };
name = Debug; name = Debug;
@ -277,7 +277,7 @@
GCC_MODEL_TUNING = G5; GCC_MODEL_TUNING = G5;
INFOPLIST_FILE = Info.plist; INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles"; INSTALL_PATH = "$(HOME)/Library/Bundles";
PRODUCT_NAME = LiferayNativityFinder; PRODUCT_NAME = OwnCloudFinder;
WRAPPER_EXTENSION = bundle; WRAPPER_EXTENSION = bundle;
}; };
name = Release; name = Release;
@ -315,7 +315,7 @@
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "LiferayNativityFinder" */ = { 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "OwnCloudFinder" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
1DEB911B08733D790010E9CD /* Debug */, 1DEB911B08733D790010E9CD /* Debug */,
@ -324,7 +324,7 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "LiferayNativityFinder" */ = { 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "OwnCloudFinder" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
1DEB911F08733D790010E9CD /* Debug */, 1DEB911F08733D790010E9CD /* Debug */,

View file

@ -2,6 +2,6 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "self:LiferayNativityFinder.xcodeproj"> location = "self:OwnCloudFinder.xcodeproj">
</FileRef> </FileRef>
</Workspace> </Workspace>

View file

@ -217,7 +217,7 @@ static RequestManager* sharedInstance = nil;
{ {
NSLog(@"Connect Socket!"); NSLog(@"Connect Socket!");
NSError *err = nil; NSError *err = nil;
if (![_socket connectToHost:@"localhost" onPort:33001 withTimeout:5 error:&err]) // Asynchronous! if (![_socket connectToHost:@"localhost" onPort:34001 withTimeout:5 error:&err]) // Asynchronous!
{ {
// If there was an error, it's likely something like "already connected" or "no delegate set" // If there was an error, it's likely something like "already connected" or "no delegate set"
NSLog(@"I goofed: %@", err); NSLog(@"I goofed: %@", err);

View file

@ -7,51 +7,51 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.liferay.nativity</string> <string>com.owncloud.injector</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>LiferayNativityInjector</string> <string>OwnCloudInjector</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>osax</string> <string>osax</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0.2</string> <string>1.0.2</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>NVTY</string> <string>OWNC</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0.2</string> <string>1.0.2</string>
<key>OSAScriptingDefinition</key> <key>OSAScriptingDefinition</key>
<string>LiferayNativityInjector.sdef</string> <string>OwnCloudInjector.sdef</string>
<key>OSAXHandlers</key> <key>OSAXHandlers</key>
<dict> <dict>
<key>Events</key> <key>Events</key>
<dict> <dict>
<key>NVTYload</key>
<dict>
<key>Handler</key>
<string>HandleLoadEvent</string>
<key>ThreadSafe</key>
<false/>
<key>Context</key>
<string>Process</string>
</dict>
<key>NVTYunld</key>
<dict>
<key>Handler</key>
<string>HandleUnloadEvent</string>
<key>ThreadSafe</key>
<false/>
<key>Context</key>
<string>Process</string>
</dict>
<key>NVTYlded</key> <key>NVTYlded</key>
<dict> <dict>
<key>Context</key>
<string>Process</string>
<key>Handler</key> <key>Handler</key>
<string>HandleLoadedEvent</string> <string>HandleLoadedEvent</string>
<key>ThreadSafe</key> <key>ThreadSafe</key>
<false/> <false/>
</dict>
<key>NVTYload</key>
<dict>
<key>Context</key> <key>Context</key>
<string>Process</string> <string>Process</string>
<key>Handler</key>
<string>HandleLoadEvent</string>
<key>ThreadSafe</key>
<false/>
</dict>
<key>NVTYunld</key>
<dict>
<key>Context</key>
<string>Process</string>
<key>Handler</key>
<string>HandleUnloadEvent</string>
<key>ThreadSafe</key>
<false/>
</dict> </dict>
</dict> </dict>
</dict> </dict>

View file

@ -7,27 +7,27 @@
#define WAIT_FOR_APPLE_EVENT_TO_ENTER_HANDLER_IN_SECONDS 1.0 #define WAIT_FOR_APPLE_EVENT_TO_ENTER_HANDLER_IN_SECONDS 1.0
#define FINDER_MIN_TESTED_VERSION @"10.7" #define FINDER_MIN_TESTED_VERSION @"10.7"
#define FINDER_MAX_TESTED_VERSION @"10.8.5" #define FINDER_MAX_TESTED_VERSION @"10.8.5"
#define LIFERAYNATIVITY_INJECTED_NOTIFICATION @"LiferayNativityInjectedNotification" #define LIFERAYNATIVITY_INJECTED_NOTIFICATION @"OwnCloudInjectedNotification"
EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refcon); EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refcon);
static NSString* globalLock = @"I'm the global lock to prevent concruent handler executions"; static NSString* globalLock = @"I'm the global lock to prevent concruent handler executions";
// SIMBL-compatible interface // SIMBL-compatible interface
@interface LiferayNativityShell : NSObject { } @interface OwnCloudShell : NSObject { }
-(void) install; -(void) install;
-(void) uninstall; -(void) uninstall;
@end @end
// just a dummy class for locating our bundle // just a dummy class for locating our bundle
@interface LiferayNativityInjector : NSObject { } @interface OwnCloudInjector : NSObject { }
@end @end
@implementation LiferayNativityInjector { } @implementation OwnCloudInjector { }
@end @end
static bool liferayNativityLoaded = false; static bool liferayNativityLoaded = false;
static NSString* liferayNativityBundleName = @"LiferayNativityFinder"; static NSString* liferayNativityBundleName = @"OwnCloudFinder";
typedef struct { typedef struct {
NSString* location; NSString* location;
@ -128,7 +128,7 @@ static OSErr loadBundle(LNBundleType type, AppleEvent* reply, long refcon) {
} }
} }
NSBundle* liferayNativityInjectorBundle = [NSBundle bundleForClass:[LiferayNativityInjector class]]; NSBundle* liferayNativityInjectorBundle = [NSBundle bundleForClass:[OwnCloudInjector class]];
NSString* liferayNativityLocation = [liferayNativityInjectorBundle pathForResource:bundleName ofType:@"bundle"]; NSString* liferayNativityLocation = [liferayNativityInjectorBundle pathForResource:bundleName ofType:@"bundle"];
NSBundle* pluginBundle = [NSBundle bundleWithPath:liferayNativityLocation]; NSBundle* pluginBundle = [NSBundle bundleWithPath:liferayNativityLocation];
if (!pluginBundle) { if (!pluginBundle) {
@ -182,11 +182,11 @@ static LNBundleType mainBundleType(AppleEvent* reply) {
EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refcon) { EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refcon) {
@synchronized(globalLock) { @synchronized(globalLock) {
@autoreleasepool { @autoreleasepool {
NSBundle* injectorBundle = [NSBundle bundleForClass:[LiferayNativityInjector class]]; NSBundle* injectorBundle = [NSBundle bundleForClass:[OwnCloudInjector class]];
NSString* injectorVersion = [injectorBundle objectForInfoDictionaryKey:@"CFBundleVersion"]; NSString* injectorVersion = [injectorBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
if (!injectorVersion || ![injectorVersion isKindOfClass:[NSString class]]) { if (!injectorVersion || ![injectorVersion isKindOfClass:[NSString class]]) {
reportError(reply, [NSString stringWithFormat:@"Unable to determine LiferayNativityInjector version!"]); reportError(reply, [NSString stringWithFormat:@"Unable to determine OwnCloudInjector version!"]);
return 7; return 7;
} }
@ -206,7 +206,7 @@ EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refco
return noErr; return noErr;
} @catch (NSException* exception) { } @catch (NSException* exception) {
reportError(reply, [NSString stringWithFormat:@"Failed to load LiferayNativity with exception: %@", exception]); reportError(reply, [NSString stringWithFormat:@"Failed to load OwnCloudFinder with exception: %@", exception]);
} }
return 1; return 1;
@ -232,13 +232,13 @@ EXPORT OSErr HandleUnloadEvent(const AppleEvent* ev, AppleEvent* reply, long ref
@autoreleasepool { @autoreleasepool {
@try { @try {
if (!liferayNativityLoaded) { if (!liferayNativityLoaded) {
NSLog(@"LiferayNativityInjector: not loaded."); NSLog(@"OwnCloudInjector: not loaded.");
return noErr; return noErr;
} }
NSString* bundleName = liferayNativityBundleName; NSString* bundleName = liferayNativityBundleName;
NSBundle* liferayNativityInjectorBundle = [NSBundle bundleForClass:[LiferayNativityInjector class]]; NSBundle* liferayNativityInjectorBundle = [NSBundle bundleForClass:[OwnCloudInjector class]];
NSString* liferayNativityLocation = [liferayNativityInjectorBundle pathForResource:bundleName ofType:@"bundle"]; NSString* liferayNativityLocation = [liferayNativityInjectorBundle pathForResource:bundleName ofType:@"bundle"];
NSBundle* pluginBundle = [NSBundle bundleWithPath:liferayNativityLocation]; NSBundle* pluginBundle = [NSBundle bundleWithPath:liferayNativityLocation];
if (!pluginBundle) { if (!pluginBundle) {
@ -261,7 +261,7 @@ EXPORT OSErr HandleUnloadEvent(const AppleEvent* ev, AppleEvent* reply, long ref
return noErr; return noErr;
} @catch (NSException* exception) { } @catch (NSException* exception) {
reportError(reply, [NSString stringWithFormat:@"Failed to unload LiferayNativity with exception: %@", exception]); reportError(reply, [NSString stringWithFormat:@"Failed to unload OwnCloudFinder with exception: %@", exception]);
} }
return 1; return 1;

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary title="OwnCloudInjector Terminology">
<suite name="OwnCloudInjector Suite" code="OWNC" description="OwnCloud Injector commands">
<command name="install OwnCloud" code="OWNCload" description="Loads OwnCloud into the Finder process"/>
<command name="uninstall OwnCloud" code="OWNCunld" description="Unloads OwnCloud from the Finder process"/>
<command name="check OwnCloud" code="OWNClded" description="Checks if OwnCloud is loaded in Finder process"/>
</suite>
</dictionary>

View file

@ -7,27 +7,27 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
0B36CB92182461A10039B237 /* LiferayNativityFinder.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 0B36CB91182461A10039B237 /* LiferayNativityFinder.bundle */; }; 0B36CB92182461A10039B237 /* OwnCloudFinder.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 0B36CB91182461A10039B237 /* OwnCloudFinder.bundle */; };
0BD9C38E1778EF450094CF5D /* license.txt in Resources */ = {isa = PBXBuildFile; fileRef = 0BD9C38D1778EF450094CF5D /* license.txt */; }; 0BD9C38E1778EF450094CF5D /* license.txt in Resources */ = {isa = PBXBuildFile; fileRef = 0BD9C38D1778EF450094CF5D /* license.txt */; };
8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */; }; 8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */; };
8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D5B49A704867FD3000E48DA /* InfoPlist.strings */; }; 8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D5B49A704867FD3000E48DA /* InfoPlist.strings */; };
D6ACBEA2117B7D5600F6691C /* LiferayNativityInjector.m in Sources */ = {isa = PBXBuildFile; fileRef = D6ACBE9E117B7D5600F6691C /* LiferayNativityInjector.m */; }; D6ACBEA2117B7D5600F6691C /* OwnCloudInjector.m in Sources */ = {isa = PBXBuildFile; fileRef = D6ACBE9E117B7D5600F6691C /* OwnCloudInjector.m */; };
D6ACBEA3117B7D5600F6691C /* LNStandardVersionComparator.m in Sources */ = {isa = PBXBuildFile; fileRef = D6ACBEA0117B7D5600F6691C /* LNStandardVersionComparator.m */; }; D6ACBEA3117B7D5600F6691C /* LNStandardVersionComparator.m in Sources */ = {isa = PBXBuildFile; fileRef = D6ACBEA0117B7D5600F6691C /* LNStandardVersionComparator.m */; };
D6ACBEA5117B7D6100F6691C /* LiferayNativityInjector.sdef in Resources */ = {isa = PBXBuildFile; fileRef = D6ACBEA4117B7D6100F6691C /* LiferayNativityInjector.sdef */; }; D6ACBEA5117B7D6100F6691C /* OwnCloudInjector.sdef in Resources */ = {isa = PBXBuildFile; fileRef = D6ACBEA4117B7D6100F6691C /* OwnCloudInjector.sdef */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; }; 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
0B36CB91182461A10039B237 /* LiferayNativityFinder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; path = LiferayNativityFinder.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 0B36CB91182461A10039B237 /* OwnCloudFinder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; path = OwnCloudFinder.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
0BD9C38D1778EF450094CF5D /* license.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = license.txt; sourceTree = "<group>"; }; 0BD9C38D1778EF450094CF5D /* license.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = license.txt; sourceTree = "<group>"; };
8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D60A992314CE37030061AD6D /* LiferayNativity.osax */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LiferayNativity.osax; sourceTree = BUILT_PRODUCTS_DIR; }; D60A992314CE37030061AD6D /* OwnCloudFinder.osax */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OwnCloudFinder.osax; sourceTree = BUILT_PRODUCTS_DIR; };
D6ACBE9E117B7D5600F6691C /* LiferayNativityInjector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LiferayNativityInjector.m; sourceTree = "<group>"; }; D6ACBE9E117B7D5600F6691C /* OwnCloudInjector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OwnCloudInjector.m; sourceTree = "<group>"; };
D6ACBE9F117B7D5600F6691C /* LNVersionComparisonProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNVersionComparisonProtocol.h; sourceTree = "<group>"; }; D6ACBE9F117B7D5600F6691C /* LNVersionComparisonProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNVersionComparisonProtocol.h; sourceTree = "<group>"; };
D6ACBEA0117B7D5600F6691C /* LNStandardVersionComparator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNStandardVersionComparator.m; sourceTree = "<group>"; }; D6ACBEA0117B7D5600F6691C /* LNStandardVersionComparator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNStandardVersionComparator.m; sourceTree = "<group>"; };
D6ACBEA1117B7D5600F6691C /* LNStandardVersionComparator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNStandardVersionComparator.h; sourceTree = "<group>"; }; D6ACBEA1117B7D5600F6691C /* LNStandardVersionComparator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNStandardVersionComparator.h; sourceTree = "<group>"; };
D6ACBEA4117B7D6100F6691C /* LiferayNativityInjector.sdef */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = LiferayNativityInjector.sdef; sourceTree = "<group>"; }; D6ACBEA4117B7D6100F6691C /* OwnCloudInjector.sdef */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = OwnCloudInjector.sdef; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -67,8 +67,8 @@
089C167CFE841241C02AAC07 /* Resources */ = { 089C167CFE841241C02AAC07 /* Resources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0B36CB91182461A10039B237 /* LiferayNativityFinder.bundle */, 0B36CB91182461A10039B237 /* OwnCloudFinder.bundle */,
D6ACBEA4117B7D6100F6691C /* LiferayNativityInjector.sdef */, D6ACBEA4117B7D6100F6691C /* OwnCloudInjector.sdef */,
8D576317048677EA00EA77CD /* Info.plist */, 8D576317048677EA00EA77CD /* Info.plist */,
8D5B49A704867FD3000E48DA /* InfoPlist.strings */, 8D5B49A704867FD3000E48DA /* InfoPlist.strings */,
0BD9C38D1778EF450094CF5D /* license.txt */, 0BD9C38D1778EF450094CF5D /* license.txt */,
@ -79,7 +79,7 @@
08FB77AFFE84173DC02AAC07 /* Source */ = { 08FB77AFFE84173DC02AAC07 /* Source */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D6ACBE9E117B7D5600F6691C /* LiferayNativityInjector.m */, D6ACBE9E117B7D5600F6691C /* OwnCloudInjector.m */,
D6ACBE9F117B7D5600F6691C /* LNVersionComparisonProtocol.h */, D6ACBE9F117B7D5600F6691C /* LNVersionComparisonProtocol.h */,
D6ACBEA0117B7D5600F6691C /* LNStandardVersionComparator.m */, D6ACBEA0117B7D5600F6691C /* LNStandardVersionComparator.m */,
D6ACBEA1117B7D5600F6691C /* LNStandardVersionComparator.h */, D6ACBEA1117B7D5600F6691C /* LNStandardVersionComparator.h */,
@ -90,7 +90,7 @@
D60A992414CE37030061AD6D /* Products */ = { D60A992414CE37030061AD6D /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D60A992314CE37030061AD6D /* LiferayNativity.osax */, D60A992314CE37030061AD6D /* OwnCloudFinder.osax */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -98,9 +98,9 @@
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
8D57630D048677EA00EA77CD /* LiferayNativity.osax */ = { 8D57630D048677EA00EA77CD /* OwnCloudFinder.osax */ = {
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "LiferayNativity.osax" */; buildConfigurationList = 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "OwnCloudFinder.osax" */;
buildPhases = ( buildPhases = (
8D57630F048677EA00EA77CD /* Resources */, 8D57630F048677EA00EA77CD /* Resources */,
8D576311048677EA00EA77CD /* Sources */, 8D576311048677EA00EA77CD /* Sources */,
@ -110,10 +110,10 @@
); );
dependencies = ( dependencies = (
); );
name = LiferayNativity.osax; name = OwnCloudFinder.osax;
productInstallPath = "$(HOME)/Library/Bundles"; productInstallPath = "$(HOME)/Library/Bundles";
productName = "TotalFinder-osax"; productName = "TotalFinder-osax";
productReference = D60A992314CE37030061AD6D /* LiferayNativity.osax */; productReference = D60A992314CE37030061AD6D /* OwnCloudFinder.osax */;
productType = "com.apple.product-type.bundle"; productType = "com.apple.product-type.bundle";
}; };
/* End PBXNativeTarget section */ /* End PBXNativeTarget section */
@ -126,7 +126,7 @@
LastUpgradeCheck = 0460; LastUpgradeCheck = 0460;
ORGANIZATIONNAME = BinaryAge; ORGANIZATIONNAME = BinaryAge;
}; };
buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "LiferayNativityInjector" */; buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "OwnCloudInjector" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.2";
developmentRegion = English; developmentRegion = English;
hasScannedForEncodings = 1; hasScannedForEncodings = 1;
@ -139,7 +139,7 @@
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
targets = ( targets = (
8D57630D048677EA00EA77CD /* LiferayNativity.osax */, 8D57630D048677EA00EA77CD /* OwnCloudFinder.osax */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
@ -149,9 +149,9 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0B36CB92182461A10039B237 /* LiferayNativityFinder.bundle in Resources */, 0B36CB92182461A10039B237 /* OwnCloudFinder.bundle in Resources */,
8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */, 8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */,
D6ACBEA5117B7D6100F6691C /* LiferayNativityInjector.sdef in Resources */, D6ACBEA5117B7D6100F6691C /* OwnCloudInjector.sdef in Resources */,
0BD9C38E1778EF450094CF5D /* license.txt in Resources */, 0BD9C38E1778EF450094CF5D /* license.txt in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -163,7 +163,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D6ACBEA2117B7D5600F6691C /* LiferayNativityInjector.m in Sources */, D6ACBEA2117B7D5600F6691C /* OwnCloudInjector.m in Sources */,
D6ACBEA3117B7D5600F6691C /* LNStandardVersionComparator.m in Sources */, D6ACBEA3117B7D5600F6691C /* LNStandardVersionComparator.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -195,7 +195,7 @@
"-framework", "-framework",
AppKit, AppKit,
); );
PRODUCT_NAME = LiferayNativity; PRODUCT_NAME = OwnCloudFinder;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
WRAPPER_EXTENSION = osax; WRAPPER_EXTENSION = osax;
}; };
@ -214,7 +214,7 @@
"-framework", "-framework",
AppKit, AppKit,
); );
PRODUCT_NAME = LiferayNativity; PRODUCT_NAME = OwnCloudFinder;
WRAPPER_EXTENSION = osax; WRAPPER_EXTENSION = osax;
}; };
name = Release; name = Release;
@ -245,7 +245,7 @@
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "LiferayNativity.osax" */ = { 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "OwnCloudFinder.osax" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
1DEB911B08733D790010E9CD /* Debug */, 1DEB911B08733D790010E9CD /* Debug */,
@ -254,7 +254,7 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "LiferayNativityInjector" */ = { 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "OwnCloudInjector" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
1DEB911F08733D790010E9CD /* Debug */, 1DEB911F08733D790010E9CD /* Debug */,

View file

@ -2,6 +2,6 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "self:LiferayNativityInjector.xcodeproj"> location = "self:OwnCloudFinder.xcodeproj">
</FileRef> </FileRef>
</Workspace> </Workspace>

View file

@ -15,9 +15,9 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "8D57630D048677EA00EA77CD" BlueprintIdentifier = "8D57630D048677EA00EA77CD"
BuildableName = "LiferayNativityFinder.bundle" BuildableName = "OwnCloudFinder.bundle"
BlueprintName = "LiferayNativityFinder" BlueprintName = "OwnCloudFinder"
ReferencedContainer = "container:../LiferayNativityFinder/LiferayNativityFinder.xcodeproj"> ReferencedContainer = "container:../OwnCloudFinder/OwnCloudFinder.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildActionEntry> </BuildActionEntry>
<BuildActionEntry <BuildActionEntry
@ -29,9 +29,9 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "8D57630D048677EA00EA77CD" BlueprintIdentifier = "8D57630D048677EA00EA77CD"
BuildableName = "LiferayNativity.osax" BuildableName = "OwnCloudFinder.osax"
BlueprintName = "LiferayNativity.osax" BlueprintName = "OwnCloudFinder.osax"
ReferencedContainer = "container:LiferayNativityInjector.xcodeproj"> ReferencedContainer = "container:OwnCloudInjector.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildActionEntry> </BuildActionEntry>
</BuildActionEntries> </BuildActionEntries>

View file

@ -1,8 +1,14 @@
#!/bin/sh #!/bin/sh
# osascript $HOME/owncloud.com/mirall/shell_integration/MacOSX/unload.scpt # osascript $HOME/owncloud.com/mirall/shell_integration/MacOSX/unload.scpt
sudo rm -rf /Library/ScriptingAdditions/LiferayNativity.osax sudo rm -rf /Library/ScriptingAdditions/OwnCloudFinder.osax
sudo cp -r $HOME/Library/Developer/Xcode/DerivedData/LiferayNativity-gvtginoclfyisuagangtxsfbuztw/Build/Products/Debug/LiferayNativity.osax /Library/ScriptingAdditions/ # Klaas' machine
OSAXDIR=$HOME/Library/Developer/Xcode/DerivedData/OwnCloud-*/Build/Products/Debug/OwnCloudFinder.osax
[ -d $OSAXDIR ] ||OSAXDIR=$HOME/Library/Developer/Xcode/DerivedData/OwnCloud-*/Build/Intermediates/ArchiveIntermediates/OwnCloudFinder.osax/IntermediateBuildFilesPath/UninstalledProducts/OwnCloudFinder.osax
# Markus' machine
[ -d $OSAXDIR ] || echo "OSAX does not exist"
[ -d $OSAXDIR ] && sudo cp -rv $OSAXDIR /Library/ScriptingAdditions/
sudo killall Finder sudo killall Finder
sleep 1 sleep 1

View file

@ -11,26 +11,47 @@ class ownCloudExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoP
nautilusVFSFile_table = {} nautilusVFSFile_table = {}
registered_paths = {} registered_paths = {}
remainder = '' remainder = ''
connected = False
watch_id = 0
def __init__(self): def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.connectToOwnCloud
self.sock.connect(("localhost", 33001)) if not self.connected:
self.sock.settimeout(5) # try again in 5 seconds - attention, logic inverted!
GObject.timeout_add(5000, self.connectToOwnCloud)
GObject.io_add_watch(self.sock, GObject.IO_IN, self.handle_notify)
def port(self):
return 34001 # Fixme, read from config file.
def connectToOwnCloud(self):
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect(("localhost", self.port()))
self.sock.settimeout(5)
self.connected = True
self.watch_id = GObject.io_add_watch(self.sock, GObject.IO_IN, self.handle_notify)
except:
print "Connect could not be established, try again later!"
self.sock.close()
return not self.connected
def sendCommand(self, cmd): def sendCommand(self, cmd):
self.sock.send(cmd) if self.connected:
try:
self.sock.send(cmd)
except:
print "Sending failed."
GObject.source_remove( self.watch_id )
self.connected = False
GObject.timeout_add(5000, self.connectToOwnCloud)
def find_item_for_file( self, path ): def find_item_for_file( self, path ):
if path in self.nautilusVFSFile_table: if path in self.nautilusVFSFile_table:
return self.nautilusVFSFile_table[path] return self.nautilusVFSFile_table[path]
else: else:
return None return None
def callback_update_file( self, path ):
print "Got an update callback for " + path
def askForOverlay(self, file): def askForOverlay(self, file):
if os.path.isdir(file): if os.path.isdir(file):
folderStatus = self.sendCommand("RETRIEVE_FOLDER_STATUS:"+file+"\n"); folderStatus = self.sendCommand("RETRIEVE_FOLDER_STATUS:"+file+"\n");
@ -38,6 +59,17 @@ class ownCloudExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoP
if os.path.isfile(file): if os.path.isfile(file):
fileStatus = self.sendCommand("RETRIEVE_FILE_STATUS:"+file+"\n"); fileStatus = self.sendCommand("RETRIEVE_FILE_STATUS:"+file+"\n");
def invalidate_items_underneath( self, path ):
update_items = []
for p in self.nautilusVFSFile_table:
if p == path or p.startswith( path ):
item = self.nautilusVFSFile_table[p]
update_items.append(item)
for item in update_items:
item.invalidate_extension_info()
# self.update_file_info(item)
# Handles a single line of server respoonse and sets the emblem # Handles a single line of server respoonse and sets the emblem
def handle_server_response(self, l): def handle_server_response(self, l):
Emblems = { 'OK' : 'oC_ok', Emblems = { 'OK' : 'oC_ok',
@ -66,16 +98,27 @@ class ownCloudExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoP
item = self.find_item_for_file(parts[2]) item = self.find_item_for_file(parts[2])
if item: if item:
item.add_emblem(emblem) item.add_emblem(emblem)
elif action == 'UPDATE_VIEW': elif action == 'UPDATE_VIEW':
# Search all items underneath this path and invalidate them
if parts[1] in self.registered_paths: if parts[1] in self.registered_paths:
for p in self.nautilusVFSFile_table: self.invalidate_items_underneath( parts[1] )
if p.startswith( parts[1] ):
item = self.nautilusVFSFile_table[p]
item.invalidate_extension_info()
self.update_file_info(item)
elif action == 'REGISTER_PATH': elif action == 'REGISTER_PATH':
self.registered_paths[parts[1]] = 1 self.registered_paths[parts[1]] = 1
self.invalidate_items_underneath( parts[1] )
elif action == 'UNREGISTER_PATH':
del self.registered_paths[parts[1]]
self.invalidate_items_underneath( parts[1] )
# check if there are non pathes any more, if so, its usual
# that mirall went away. Try reconnect.
if not self.registered_paths:
self.sock.close()
self.connected = False
GObject.source_remove( self.watch_id )
GObject.timeout_add(5000, self.connectToOwnCloud)
else: else:
# print "We got unknown action " + action # print "We got unknown action " + action
1 1
@ -106,8 +149,6 @@ class ownCloudExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoP
def get_local_path(self, path): def get_local_path(self, path):
return path.replace("file://", "") return path.replace("file://", "")
def update_file_info(self, item): def update_file_info(self, item):
if item.get_uri_scheme() != 'file': if item.get_uri_scheme() != 'file':
return return

View file

@ -108,7 +108,7 @@ HRESULT RegisterCLSID(LPCOLESTR guidStr, PCWSTR overlayStr, PCWSTR szModule)
return hResult; return hResult;
} }
hResult = OCOverlayRegistrationHandler::RegisterCOMObject(szModule, guid); hResult = OCOverlayRegistrationHandler::RegisterCOMObject(szModule, OVERLAY_GENERIC_NAME, guid);
if (!SUCCEEDED(hResult)) { if (!SUCCEEDED(hResult)) {
return hResult; return hResult;

View file

@ -24,7 +24,8 @@ HRESULT OCOverlayRegistrationHandler::MakeRegistryEntries(const CLSID& clsid, PC
{ {
HRESULT hResult; HRESULT hResult;
HKEY shellOverlayKey = NULL; HKEY shellOverlayKey = NULL;
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, 0, KEY_WRITE, &shellOverlayKey)); // the key may not exist yet
hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &shellOverlayKey, NULL));
if (!SUCCEEDED(hResult)) { if (!SUCCEEDED(hResult)) {
hResult = RegCreateKey(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, &shellOverlayKey); hResult = RegCreateKey(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, &shellOverlayKey);
if(!SUCCEEDED(hResult)) { if(!SUCCEEDED(hResult)) {
@ -69,7 +70,7 @@ HRESULT OCOverlayRegistrationHandler::RemoveRegistryEntries(PCWSTR friendlyName)
return hResult; return hResult;
} }
HRESULT OCOverlayRegistrationHandler::RegisterCOMObject(PCWSTR modulePath, const CLSID& clsid) HRESULT OCOverlayRegistrationHandler::RegisterCOMObject(PCWSTR modulePath, PCWSTR friendlyName, const CLSID& clsid)
{ {
if (modulePath == NULL) { if (modulePath == NULL) {
return E_FAIL; return E_FAIL;
@ -91,14 +92,15 @@ HRESULT OCOverlayRegistrationHandler::RegisterCOMObject(PCWSTR modulePath, const
return hResult; return hResult;
} }
hResult = HRESULT_FROM_WIN32(RegSetValue(clsidKey, NULL, REG_SZ, friendlyName, (DWORD) wcslen(friendlyName)));
HKEY inprocessKey = NULL; HKEY inprocessKey = NULL;
hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(clsidKey, REGISTRY_IN_PROCESS, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &inprocessKey, NULL)); hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(clsidKey, REGISTRY_IN_PROCESS, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &inprocessKey, NULL));
if(!SUCCEEDED(hResult)) { if(!SUCCEEDED(hResult)) {
return hResult; return hResult;
} }
DWORD cbData = lstrlen(modulePath) * sizeof(*modulePath); hResult = HRESULT_FROM_WIN32(RegSetValue(inprocessKey, NULL, REG_SZ, modulePath, (DWORD) wcslen(modulePath)));
hResult = HRESULT_FROM_WIN32(RegSetValue(inprocessKey, NULL, REG_SZ, modulePath, cbData));
if(!SUCCEEDED(hResult)) { if(!SUCCEEDED(hResult)) {
return hResult; return hResult;

View file

@ -23,7 +23,7 @@ class __declspec(dllexport) OCOverlayRegistrationHandler
{ {
public: public:
static HRESULT MakeRegistryEntries(const CLSID& clsid, PCWSTR fileType); static HRESULT MakeRegistryEntries(const CLSID& clsid, PCWSTR fileType);
static HRESULT RegisterCOMObject(PCWSTR modulePath, const CLSID& clsid); static HRESULT RegisterCOMObject(PCWSTR modulePath, PCWSTR friendlyName, const CLSID& clsid);
static HRESULT RemoveRegistryEntries(PCWSTR friendlyName); static HRESULT RemoveRegistryEntries(PCWSTR friendlyName);
static HRESULT UnregisterCOMObject(const CLSID& clsid); static HRESULT UnregisterCOMObject(const CLSID& clsid);
}; };

View file

@ -22,14 +22,17 @@
#define OVERLAY_GUID_WARNING L"{0960F096-F328-48A3-B746-276B1E3C3722}" #define OVERLAY_GUID_WARNING L"{0960F096-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_WARNING_SHARED L"{0960F097-F328-48A3-B746-276B1E3C3722}" #define OVERLAY_GUID_WARNING_SHARED L"{0960F097-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_NAME_ERROR L"OCError" #define OVERLAY_GENERIC_NAME L"OC Overlay Handler"
#define OVERLAY_NAME_ERROR_SHARED L"OCErrorShared"
#define OVERLAY_NAME_OK L"OCOK" // two spaces to put us a head of the competition :/
#define OVERLAY_NAME_OK_SHARED L"OCOKShared" #define OVERLAY_NAME_ERROR L" OCError"
#define OVERLAY_NAME_SYNC L"OCSync" #define OVERLAY_NAME_ERROR_SHARED L" OCErrorShared"
#define OVERLAY_NAME_SYNC_SHARED L"OCSyncShared" #define OVERLAY_NAME_OK L" OCOK"
#define OVERLAY_NAME_WARNING L"OCWarning" #define OVERLAY_NAME_OK_SHARED L" OCOKShared"
#define OVERLAY_NAME_WARNING_SHARED L"OCWarningShared" #define OVERLAY_NAME_SYNC L" OCSync"
#define OVERLAY_NAME_SYNC_SHARED L" OCSyncShared"
#define OVERLAY_NAME_WARNING L" OCWarning"
#define OVERLAY_NAME_WARNING_SHARED L" OCWarningShared"
#define REGISTRY_OVERLAY_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers" #define REGISTRY_OVERLAY_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers"
#define REGISTRY_CLSID L"CLSID" #define REGISTRY_CLSID L"CLSID"
@ -44,4 +47,4 @@
#define GET_FILE_OVERLAY_ID L"getFileIconId" #define GET_FILE_OVERLAY_ID L"getFileIconId"
#define PORT 33001 #define PORT 34001

View file

@ -1,4 +1,6 @@
# TODO: OSX and LIB_ONLY seem to require this to go to binary dir only # TODO: OSX and LIB_ONLY seem to require this to go to binary dir only
mirall/discoveryphase.cpp
mirall/selectivesyncdialog.cpp
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync) set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)

View file

@ -26,6 +26,7 @@
#include "ignorelisteditor.h" #include "ignorelisteditor.h"
#include "account.h" #include "account.h"
#include "quotainfo.h" #include "quotainfo.h"
#include "selectivesyncdialog.h"
#include "creds/abstractcredentials.h" #include "creds/abstractcredentials.h"
#include <math.h> #include <math.h>
@ -77,6 +78,7 @@ AccountSettings::AccountSettings(QWidget *parent) :
ui->_buttonRemove->setEnabled(false); ui->_buttonRemove->setEnabled(false);
ui->_buttonEnable->setEnabled(false); ui->_buttonEnable->setEnabled(false);
ui->_buttonSelectiveSync->setEnabled(false);
ui->_buttonAdd->setEnabled(true); ui->_buttonAdd->setEnabled(true);
QAction *resetFolderAction = new QAction(this); QAction *resetFolderAction = new QAction(this);
@ -92,6 +94,7 @@ AccountSettings::AccountSettings(QWidget *parent) :
connect(ui->_buttonRemove, SIGNAL(clicked()), this, SLOT(slotRemoveCurrentFolder())); connect(ui->_buttonRemove, SIGNAL(clicked()), this, SLOT(slotRemoveCurrentFolder()));
connect(ui->_buttonEnable, SIGNAL(clicked()), this, SLOT(slotEnableCurrentFolder())); connect(ui->_buttonEnable, SIGNAL(clicked()), this, SLOT(slotEnableCurrentFolder()));
connect(ui->_buttonAdd, SIGNAL(clicked()), this, SLOT(slotAddFolder())); connect(ui->_buttonAdd, SIGNAL(clicked()), this, SLOT(slotAddFolder()));
connect(ui->_buttonSelectiveSync, SIGNAL(clicked()), this, SLOT(slotSelectiveSync()));
connect(ui->modifyAccountButton, SIGNAL(clicked()), SLOT(slotOpenAccountWizard())); connect(ui->modifyAccountButton, SIGNAL(clicked()), SLOT(slotOpenAccountWizard()));
connect(ui->ignoredFilesButton, SIGNAL(clicked()), SLOT(slotIgnoreFilesEditor()));; connect(ui->ignoredFilesButton, SIGNAL(clicked()), SLOT(slotIgnoreFilesEditor()));;
@ -111,9 +114,13 @@ AccountSettings::AccountSettings(QWidget *parent) :
this, SLOT(slotAccountChanged(Account*,Account*))); this, SLOT(slotAccountChanged(Account*,Account*)));
slotAccountChanged(AccountManager::instance()->account(), 0); slotAccountChanged(AccountManager::instance()->account(), 0);
connect(FolderMan::instance(), SIGNAL(folderListLoaded(Folder::Map)), FolderMan *folderMan = FolderMan::instance();
connect(folderMan, SIGNAL(folderSyncStateChange(QString)),
this, SLOT(slotSyncStateChange(QString)));
connect(folderMan, SIGNAL(folderListLoaded(Folder::Map)),
this, SLOT(setFolderList(Folder::Map))); this, SLOT(setFolderList(Folder::Map)));
setFolderList(FolderMan::instance()->map()); setFolderList(FolderMan::instance()->map());
slotSyncStateChange();
} }
void AccountSettings::slotAccountChanged(Account *newAccount, Account *oldAccount) void AccountSettings::slotAccountChanged(Account *newAccount, Account *oldAccount)
@ -122,6 +129,7 @@ void AccountSettings::slotAccountChanged(Account *newAccount, Account *oldAccoun
disconnect(oldAccount, SIGNAL(stateChanged(int)), this, SLOT(slotAccountStateChanged(int))); disconnect(oldAccount, SIGNAL(stateChanged(int)), this, SLOT(slotAccountStateChanged(int)));
disconnect(oldAccount->quotaInfo(), SIGNAL(quotaUpdated(qint64,qint64)), disconnect(oldAccount->quotaInfo(), SIGNAL(quotaUpdated(qint64,qint64)),
this, SLOT(slotUpdateQuota(qint64,qint64))); this, SLOT(slotUpdateQuota(qint64,qint64)));
disconnect(oldAccount, SIGNAL(stateChanged(int)), this, SLOT(slotAccountStateChanged(int)));
} }
_account = newAccount; _account = newAccount;
@ -150,12 +158,14 @@ void AccountSettings::slotFolderActivated( const QModelIndex& indx )
} else { } else {
ui->_buttonAdd->setVisible(true); ui->_buttonAdd->setVisible(true);
} }
ui->_buttonAdd->setEnabled(_account && _account->state() == Account::Connected); bool isConnected = _account && _account->state() == Account::Connected;
ui->_buttonAdd->setEnabled(isConnected);
ui->_buttonEnable->setEnabled( isValid ); ui->_buttonEnable->setEnabled( isValid );
ui->_buttonSelectiveSync->setEnabled(isConnected && isValid);
if ( isValid ) { if ( isValid ) {
bool folderEnabled = _model->data( indx, FolderStatusDelegate::FolderSyncEnabled).toBool(); bool folderPaused = _model->data( indx, FolderStatusDelegate::FolderSyncPaused).toBool();
if ( folderEnabled ) { if ( !folderPaused) {
ui->_buttonEnable->setText( tr( "Pause" ) ); ui->_buttonEnable->setText( tr( "Pause" ) );
} else { } else {
ui->_buttonEnable->setText( tr( "Resume" ) ); ui->_buttonEnable->setText( tr( "Resume" ) );
@ -189,10 +199,13 @@ void AccountSettings::slotFolderWizardAccepted()
QString alias = folderWizard->field(QLatin1String("alias")).toString(); QString alias = folderWizard->field(QLatin1String("alias")).toString();
QString sourceFolder = folderWizard->field(QLatin1String("sourceFolder")).toString(); QString sourceFolder = folderWizard->field(QLatin1String("sourceFolder")).toString();
QString targetPath = folderWizard->property("targetPath").toString(); QString targetPath = folderWizard->property("targetPath").toString();
QStringList selectiveSyncBlackList
= folderWizard->property("selectiveSyncBlackList").toStringList();
if (!FolderMan::ensureJournalGone( sourceFolder )) if (!FolderMan::ensureJournalGone( sourceFolder ))
return; return;
folderMan->addFolderDefinition(alias, sourceFolder, targetPath );
folderMan->addFolderDefinition(alias, sourceFolder, targetPath, selectiveSyncBlackList );
Folder *f = folderMan->setupFolderFromConfigFile( alias ); Folder *f = folderMan->setupFolderFromConfigFile( alias );
slotAddFolder( f ); slotAddFolder( f );
folderMan->setSyncEnabled(true); folderMan->setSyncEnabled(true);
@ -222,7 +235,11 @@ void AccountSettings::slotAddFolder( Folder *folder )
if( ! folder || folder->alias().isEmpty() ) return; if( ! folder || folder->alias().isEmpty() ) return;
QStandardItem *item = new QStandardItem(); QStandardItem *item = new QStandardItem();
folderToModelItem( item, folder ); bool isConnected = false;
if (_account) {
isConnected = (_account->state() == Account::Connected);
}
folderToModelItem( item, folder, isConnected);
_model->appendRow( item ); _model->appendRow( item );
// in order to update the enabled state of the "Sync now" button // in order to update the enabled state of the "Sync now" button
connect(folder, SIGNAL(syncStateChange()), this, SLOT(slotFolderSyncStateChange()), Qt::UniqueConnection); connect(folder, SIGNAL(syncStateChange()), this, SLOT(slotFolderSyncStateChange()), Qt::UniqueConnection);
@ -244,15 +261,15 @@ void AccountSettings::setGeneralErrors( const QStringList& errors )
} }
} }
void AccountSettings::folderToModelItem( QStandardItem *item, Folder *f ) void AccountSettings::folderToModelItem( QStandardItem *item, Folder *f, bool accountConnected )
{ {
if( ! item || !f ) return; if( ! item || !f ) return;
item->setData( f->nativePath(), FolderStatusDelegate::FolderPathRole ); item->setData( f->nativePath(), FolderStatusDelegate::FolderPathRole );
item->setData( f->remotePath(), FolderStatusDelegate::FolderSecondPathRole ); item->setData( f->remotePath(), FolderStatusDelegate::FolderSecondPathRole );
item->setData( f->alias(), FolderStatusDelegate::FolderAliasRole ); item->setData( f->alias(), FolderStatusDelegate::FolderAliasRole );
item->setData( f->syncEnabled(), FolderStatusDelegate::FolderSyncEnabled ); item->setData( f->syncPaused(), FolderStatusDelegate::FolderSyncPaused );
item->setData( accountConnected, FolderStatusDelegate::FolderAccountConnected );
SyncResult res = f->syncResult(); SyncResult res = f->syncResult();
SyncResult::Status status = res.status(); SyncResult::Status status = res.status();
@ -260,35 +277,39 @@ void AccountSettings::folderToModelItem( QStandardItem *item, Folder *f )
Theme *theme = Theme::instance(); Theme *theme = Theme::instance();
item->setData( theme->statusHeaderText( status ), Qt::ToolTipRole ); item->setData( theme->statusHeaderText( status ), Qt::ToolTipRole );
if( f->syncEnabled() ) { if ( accountConnected ) {
if( status == SyncResult::SyncPrepare ) { if( f->syncPaused() ) {
if( _wasDisabledBefore ) { item->setData( theme->folderDisabledIcon( ), FolderStatusDelegate::FolderStatusIconRole ); // size 48 before
// if the folder was disabled before, set the sync icon _wasDisabledBefore = false;
item->setData( theme->syncStateIcon( SyncResult::SyncRunning), FolderStatusDelegate::FolderStatusIconRole );
} // we keep the previous icon for the SyncPrepare state.
} else if( status == SyncResult::Undefined ) {
// startup, the sync was never done.
qDebug() << "XXX FIRST time sync, setting icon to sync running!";
item->setData( theme->syncStateIcon( SyncResult::SyncRunning), FolderStatusDelegate::FolderStatusIconRole );
} else { } else {
// kepp the previous icon for the prepare phase. if( status == SyncResult::SyncPrepare ) {
if( status == SyncResult::Problem) { if( _wasDisabledBefore ) {
item->setData( theme->syncStateIcon( SyncResult::Success), FolderStatusDelegate::FolderStatusIconRole ); // if the folder was disabled before, set the sync icon
item->setData( theme->syncStateIcon( SyncResult::SyncRunning), FolderStatusDelegate::FolderStatusIconRole );
} // we keep the previous icon for the SyncPrepare state.
} else if( status == SyncResult::Undefined ) {
// startup, the sync was never done.
qDebug() << "XXX FIRST time sync, setting icon to sync running!";
item->setData( theme->syncStateIcon( SyncResult::SyncRunning), FolderStatusDelegate::FolderStatusIconRole );
} else { } else {
item->setData( theme->syncStateIcon( status ), FolderStatusDelegate::FolderStatusIconRole ); // kepp the previous icon for the prepare phase.
if( status == SyncResult::Problem) {
item->setData( theme->syncStateIcon( SyncResult::Success), FolderStatusDelegate::FolderStatusIconRole );
} else {
item->setData( theme->syncStateIcon( status ), FolderStatusDelegate::FolderStatusIconRole );
}
} }
} }
} else { } else {
item->setData( theme->folderDisabledIcon( ), FolderStatusDelegate::FolderStatusIconRole ); // size 48 before item->setData( theme->folderOfflineIcon(), FolderStatusDelegate::FolderStatusIconRole);
_wasDisabledBefore = false;
} }
item->setData( theme->statusHeaderText( status ), FolderStatusDelegate::FolderStatus ); item->setData( theme->statusHeaderText( status ), FolderStatusDelegate::FolderStatus );
if( errorList.isEmpty() ) { if( errorList.isEmpty() ) {
if( (status == SyncResult::Error || if( (status == SyncResult::Error ||
status == SyncResult::SetupError || status == SyncResult::SetupError ||
status == SyncResult::SyncAbortRequested || status == SyncResult::SyncAbortRequested )) {
status == SyncResult::Unavailable)) {
errorList << theme->statusHeaderText(status); errorList << theme->statusHeaderText(status);
} }
} }
@ -369,6 +390,20 @@ void AccountSettings::slotResetCurrentFolder()
} }
} }
void AccountSettings::slotSelectiveSync()
{
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
if( selected.isValid() ) {
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
FolderMan *folderMan = FolderMan::instance();
Folder *f = folderMan->folder(alias);
if (f) {
(new SelectiveSyncDialog(f, this))->open();
}
}
}
void AccountSettings::slotDoubleClicked( const QModelIndex& indx ) void AccountSettings::slotDoubleClicked( const QModelIndex& indx )
{ {
if( ! indx.isValid() ) return; if( ! indx.isValid() ) return;
@ -422,57 +457,60 @@ void AccountSettings::slotEnableCurrentFolder()
if( selected.isValid() ) { if( selected.isValid() ) {
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString(); QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
bool folderEnabled = _model->data( selected, FolderStatusDelegate::FolderSyncEnabled).toBool();
qDebug() << "Toggle enabled/disabled Folder alias " << alias << " - current state: " << folderEnabled;
if( !alias.isEmpty() ) {
FolderMan *folderMan = FolderMan::instance();
qDebug() << "Application: enable folder with alias " << alias; if( alias.isEmpty() ) {
bool terminate = false; qDebug() << "Empty alias to enable.";
return;
// this sets the folder status to disabled but does not interrupt it.
Folder *f = folderMan->folder( alias );
if (!f) {
return;
}
if( folderEnabled ) {
// check if a sync is still running and if so, ask if we should terminate.
if( f->isBusy() ) { // its still running
#if defined(Q_OS_MAC)
QWidget *parent = this;
Qt::WindowFlags flags = Qt::Sheet;
#else
QWidget *parent = 0;
Qt::WindowFlags flags = Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint; // default flags
#endif
QMessageBox msgbox(QMessageBox::Question, tr("Sync Running"),
tr("The syncing operation is running.<br/>Do you want to terminate it?"),
QMessageBox::Yes | QMessageBox::No, parent, flags);
msgbox.setDefaultButton(QMessageBox::Yes);
int reply = msgbox.exec();
if ( reply == QMessageBox::Yes )
terminate = true;
else
return; // do nothing
}
}
// message box can return at any time while the thread keeps running,
// so better check again after the user has responded.
if ( f->isBusy() && terminate ) {
f->slotTerminateSync();
}
folderMan->slotEnableFolder( alias, !folderEnabled );
// keep state for the icon setting.
if( !folderEnabled ) _wasDisabledBefore = true;
slotUpdateFolderState (f);
// set the button text accordingly.
slotFolderActivated( selected );
} }
FolderMan *folderMan = FolderMan::instance();
qDebug() << "Application: enable folder with alias " << alias;
bool terminate = false;
bool currentlyPaused = false;
// this sets the folder status to disabled but does not interrupt it.
Folder *f = folderMan->folder( alias );
if (!f) {
return;
}
currentlyPaused = f->syncPaused();
if( ! currentlyPaused ) {
// check if a sync is still running and if so, ask if we should terminate.
if( f->isBusy() ) { // its still running
#if defined(Q_OS_MAC)
QWidget *parent = this;
Qt::WindowFlags flags = Qt::Sheet;
#else
QWidget *parent = 0;
Qt::WindowFlags flags = Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint; // default flags
#endif
QMessageBox msgbox(QMessageBox::Question, tr("Sync Running"),
tr("The syncing operation is running.<br/>Do you want to terminate it?"),
QMessageBox::Yes | QMessageBox::No, parent, flags);
msgbox.setDefaultButton(QMessageBox::Yes);
int reply = msgbox.exec();
if ( reply == QMessageBox::Yes )
terminate = true;
else
return; // do nothing
}
}
// message box can return at any time while the thread keeps running,
// so better check again after the user has responded.
if ( f->isBusy() && terminate ) {
f->slotTerminateSync();
}
f->setSyncPaused(!currentlyPaused); // toggle the pause setting
folderMan->slotSetFolderPaused( alias, !currentlyPaused );
// keep state for the icon setting.
if( currentlyPaused ) _wasDisabledBefore = true;
slotUpdateFolderState (f);
// set the button text accordingly.
slotFolderActivated( selected );
} }
} }
@ -505,7 +543,7 @@ void AccountSettings::slotUpdateFolderState( Folder *folder )
} }
if( item ) { if( item ) {
folderToModelItem( item, folder ); folderToModelItem( item, folder, _account->state() == Account::Connected );
} else { } else {
// the dialog is not visible. // the dialog is not visible.
} }
@ -564,6 +602,14 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
QStandardItem *item = itemForFolder( folder ); QStandardItem *item = itemForFolder( folder );
if( !item ) return; if( !item ) return;
// switch on extra space.
item->setData( QVariant(true), FolderStatusDelegate::AddProgressSpace );
if (!progress._currentDiscoveredFolder.isEmpty()) {
item->setData( tr("Discovering %1").arg(progress._currentDiscoveredFolder) , FolderStatusDelegate::SyncProgressItemString );
return;
}
if(!progress._lastCompletedItem.isEmpty() if(!progress._lastCompletedItem.isEmpty()
&& Progress::isWarningKind(progress._lastCompletedItem._status)) { && Progress::isWarningKind(progress._lastCompletedItem._status)) {
int warnCount = item->data(FolderStatusDelegate::WarningCount).toInt(); int warnCount = item->data(FolderStatusDelegate::WarningCount).toInt();
@ -591,8 +637,7 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
QString itemFileName = shortenFilename(folder, curItem._file); QString itemFileName = shortenFilename(folder, curItem._file);
QString kindString = Progress::asActionString(curItem); QString kindString = Progress::asActionString(curItem);
// switch on extra space.
item->setData( QVariant(true), FolderStatusDelegate::AddProgressSpace );
QString fileProgressString; QString fileProgressString;
if (Progress::isSizeDependent(curItem._instruction)) { if (Progress::isSizeDependent(curItem._instruction)) {
@ -730,6 +775,11 @@ void AccountSettings::slotAccountStateChanged(int state)
QUrl safeUrl(_account->url()); QUrl safeUrl(_account->url());
safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI
slotButtonsSetEnabled(); slotButtonsSetEnabled();
FolderMan *folderMan = FolderMan::instance();
foreach (Folder *folder, folderMan->map().values()) {
slotUpdateFolderState(folder);
}
slotSyncStateChange();
if (state == Account::Connected) { if (state == Account::Connected) {
QString user; QString user;
if (AbstractCredentials *cred = _account->credentials()) { if (AbstractCredentials *cred = _account->credentials()) {
@ -755,6 +805,21 @@ void AccountSettings::slotAccountStateChanged(int state)
} }
} }
void AccountSettings::slotSyncStateChange(const QString& alias)
{
Q_UNUSED(alias);
QIcon icon;
if (_account && _account->state() == Account::Connected) {
FolderMan *folderMan = FolderMan::instance();
SyncResult state = folderMan->accountStatus(folderMan->map().values());
icon = Theme::instance()->syncStateIcon(state.status());
} else {
icon = Theme::instance()->folderOfflineIcon();
}
emit accountIconChanged(icon);
}
AccountSettings::~AccountSettings() AccountSettings::~AccountSettings()
{ {
delete ui; delete ui;

View file

@ -54,6 +54,7 @@ signals:
void openProtocol(); void openProtocol();
void openFolderAlias( const QString& ); void openFolderAlias( const QString& );
void infoFolderAlias( const QString& ); void infoFolderAlias( const QString& );
void accountIconChanged( const QIcon& );
public slots: public slots:
void slotFolderActivated( const QModelIndex& ); void slotFolderActivated( const QModelIndex& );
@ -62,6 +63,7 @@ public slots:
void slotDoubleClicked( const QModelIndex& ); void slotDoubleClicked( const QModelIndex& );
void slotSetProgress(const QString& folder, const Progress::Info& progress); void slotSetProgress(const QString& folder, const Progress::Info& progress);
void slotButtonsSetEnabled(); void slotButtonsSetEnabled();
void slotSyncStateChange(const QString& alias = QString());
void slotUpdateQuota( qint64,qint64 ); void slotUpdateQuota( qint64,qint64 );
void slotIgnoreFilesEditor(); void slotIgnoreFilesEditor();
@ -81,10 +83,11 @@ protected slots:
void slotFolderWizardRejected(); void slotFolderWizardRejected();
void slotOpenAccountWizard(); void slotOpenAccountWizard();
void slotHideProgress(); void slotHideProgress();
void slotSelectiveSync();
private: private:
QString shortenFilename( const QString& folder, const QString& file ) const; QString shortenFilename( const QString& folder, const QString& file ) const;
void folderToModelItem( QStandardItem *, Folder * ); void folderToModelItem(QStandardItem *, Folder * , bool accountConnected);
QStandardItem* itemForFolder(const QString& ); QStandardItem* itemForFolder(const QString& );
void showConnectionLabel( const QString& message, const QString& tooltip = QString() ); void showConnectionLabel( const QString& message, const QString& tooltip = QString() );

View file

@ -70,6 +70,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="_buttonSelectiveSync">
<property name="text">
<string>Selective Sync...</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer_3"> <spacer name="verticalSpacer_3">
<property name="orientation"> <property name="orientation">

View file

@ -179,7 +179,6 @@ void Application::slotLogout()
FolderMan *folderMan = FolderMan::instance(); FolderMan *folderMan = FolderMan::instance();
folderMan->setSyncEnabled(false); folderMan->setSyncEnabled(false);
folderMan->terminateSyncProcess(); folderMan->terminateSyncProcess();
folderMan->unloadAllFolders();
a->setState(Account::SignedOut); a->setState(Account::SignedOut);
// show result // show result
_gui->slotComputeOverallSyncStatus(); _gui->slotComputeOverallSyncStatus();
@ -209,6 +208,8 @@ void Application::slotCleanup()
if (account) { if (account) {
account->save(); account->save();
} }
FolderMan::instance()->unloadAllFolders();
_gui->slotShutdown(); _gui->slotShutdown();
_gui->deleteLater(); _gui->deleteLater();
} }

View file

@ -54,7 +54,7 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP
, _path(path) , _path(path)
, _remotePath(secondPath) , _remotePath(secondPath)
, _alias(alias) , _alias(alias)
, _enabled(true) , _paused(false)
, _csyncError(false) , _csyncError(false)
, _csyncUnavail(false) , _csyncUnavail(false)
, _wipeDb(false) , _wipeDb(false)
@ -215,14 +215,14 @@ QString Folder::nativePath() const
return QDir::toNativeSeparators(_path); return QDir::toNativeSeparators(_path);
} }
bool Folder::syncEnabled() const bool Folder::syncPaused() const
{ {
return _enabled; return _paused;
} }
void Folder::setSyncEnabled( bool doit ) void Folder::setSyncPaused( bool doit )
{ {
_enabled = doit; _paused = doit;
if( doit ) { if( doit ) {
// qDebug() << "Syncing enabled on folder " << name(); // qDebug() << "Syncing enabled on folder " << name();
@ -260,6 +260,7 @@ void Folder::slotPollTimerTimeout()
qDebug() << "** Force Sync now, state is " << _syncResult.statusString(); qDebug() << "** Force Sync now, state is " << _syncResult.statusString();
emit scheduleToSync(alias()); emit scheduleToSync(alias());
} else { } else {
// do the ordinary etag chech for the root folder.
RequestEtagJob* job = new RequestEtagJob(AccountManager::instance()->account(), remotePath(), this); RequestEtagJob* job = new RequestEtagJob(AccountManager::instance()->account(), remotePath(), this);
// check if the etag is different // check if the etag is different
QObject::connect(job, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString))); QObject::connect(job, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
@ -287,7 +288,6 @@ void Folder::slotNetworkUnavailable()
if (account && account->state() == Account::Connected) { if (account && account->state() == Account::Connected) {
account->setState(Account::Disconnected); account->setState(Account::Disconnected);
} }
_syncResult.setStatus(SyncResult::Unavailable);
emit syncStateChange(); emit syncStateChange();
} }
@ -483,7 +483,7 @@ void Folder::slotTerminateSync()
// Do not display an error message, user knows his own actions. // Do not display an error message, user knows his own actions.
// _errors.append( tr("The CSync thread terminated.") ); // _errors.append( tr("The CSync thread terminated.") );
// _csyncError = true; // _csyncError = true;
setSyncEnabled(false); FolderMan::instance()->slotSetFolderPaused(alias(), true);
setSyncState(SyncResult::SyncAbortRequested); setSyncState(SyncResult::SyncAbortRequested);
return; return;
} }
@ -592,10 +592,12 @@ void Folder::startSync(const QStringList &pathList)
//direct connection so the message box is blocking the sync. //direct connection so the message box is blocking the sync.
connect(_engine.data(), SIGNAL(aboutToRemoveAllFiles(SyncFileItem::Direction,bool*)), connect(_engine.data(), SIGNAL(aboutToRemoveAllFiles(SyncFileItem::Direction,bool*)),
SLOT(slotAboutToRemoveAllFiles(SyncFileItem::Direction,bool*))); SLOT(slotAboutToRemoveAllFiles(SyncFileItem::Direction,bool*)));
connect(_engine.data(), SIGNAL(folderDiscovered(bool,QString)), this, SLOT(slotFolderDiscovered(bool,QString)));
connect(_engine.data(), SIGNAL(transmissionProgress(Progress::Info)), this, SLOT(slotTransmissionProgress(Progress::Info))); connect(_engine.data(), SIGNAL(transmissionProgress(Progress::Info)), this, SLOT(slotTransmissionProgress(Progress::Info)));
connect(_engine.data(), SIGNAL(jobCompleted(SyncFileItem)), this, SLOT(slotJobCompleted(SyncFileItem))); connect(_engine.data(), SIGNAL(jobCompleted(SyncFileItem)), this, SLOT(slotJobCompleted(SyncFileItem)));
setDirtyNetworkLimits(); setDirtyNetworkLimits();
_engine->setSelectiveSyncBlackList(selectiveSyncBlackList());
QMetaObject::invokeMethod(_engine.data(), "startSync", Qt::QueuedConnection); QMetaObject::invokeMethod(_engine.data(), "startSync", Qt::QueuedConnection);
@ -662,7 +664,8 @@ void Folder::slotSyncFinished()
_syncResult.setErrorStrings( _errors ); _syncResult.setErrorStrings( _errors );
qDebug() << " * owncloud csync thread finished with error"; qDebug() << " * owncloud csync thread finished with error";
} else if (_csyncUnavail) { } else if (_csyncUnavail) {
_syncResult.setStatus(SyncResult::Unavailable); _syncResult.setStatus(SyncResult::Error);
qDebug() << " ** csync not available.";
} else if( _syncResult.warnCount() > 0 ) { } else if( _syncResult.warnCount() > 0 ) {
// there have been warnings on the way. // there have been warnings on the way.
_syncResult.setStatus(SyncResult::Problem); _syncResult.setStatus(SyncResult::Problem);
@ -688,6 +691,13 @@ void Folder::slotEmitFinishedDelayed()
} }
void Folder::slotFolderDiscovered(bool, QString folderName)
{
Progress::Info pi;
pi._currentDiscoveredFolder = folderName;
ProgressDispatcher::instance()->setProgressInfo(alias(), pi);
}
// the progress comes without a folder and the valid path set. Add that here // the progress comes without a folder and the valid path set. Add that here
// and hand the result over to the progress dispatcher. // and hand the result over to the progress dispatcher.

View file

@ -85,9 +85,9 @@ public:
* If the sync is switched off, the startSync method is not going to * If the sync is switched off, the startSync method is not going to
* be called. * be called.
*/ */
void setSyncEnabled( bool ); void setSyncPaused( bool );
bool syncEnabled() const; bool syncPaused() const;
void prepareToSync(); void prepareToSync();
@ -121,6 +121,10 @@ public:
SyncJournalDb *journalDb() { return &_journal; } SyncJournalDb *journalDb() { return &_journal; }
CSYNC *csyncContext() { return _csync_ctx; } CSYNC *csyncContext() { return _csync_ctx; }
QStringList selectiveSyncBlackList() { return _selectiveSyncBlackList; }
void setSelectiveSyncBlackList(const QStringList &blackList)
{ _selectiveSyncBlackList = blackList; }
signals: signals:
void syncStateChange(); void syncStateChange();
@ -157,6 +161,7 @@ private slots:
void slotCsyncUnavailable(); void slotCsyncUnavailable();
void slotSyncFinished(); void slotSyncFinished();
void slotFolderDiscovered(bool local, QString folderName);
void slotTransmissionProgress(const Progress::Info& pi); void slotTransmissionProgress(const Progress::Info& pi);
void slotJobCompleted(const SyncFileItem&); void slotJobCompleted(const SyncFileItem&);
@ -184,10 +189,11 @@ private:
QString _remotePath; QString _remotePath;
QString _alias; QString _alias;
QString _configFile; QString _configFile;
bool _enabled; bool _paused;
SyncResult _syncResult; SyncResult _syncResult;
QScopedPointer<SyncEngine> _engine; QScopedPointer<SyncEngine> _engine;
QStringList _errors; QStringList _errors;
QStringList _selectiveSyncBlackList;
bool _csyncError; bool _csyncError;
bool _csyncUnavail; bool _csyncUnavail;
bool _wipeDb; bool _wipeDb;

View file

@ -53,6 +53,7 @@ FolderMan::FolderMan(QObject *parent) :
_instance = this; _instance = this;
_socketApi = new SocketApi(this); _socketApi = new SocketApi(this);
_socketApi->slotReadExcludes();
} }
FolderMan *FolderMan::instance() FolderMan *FolderMan::instance()
@ -234,7 +235,7 @@ void FolderMan::terminateCurrentSync()
#define PAR_O_TAG QLatin1String("__PAR_OPEN__") #define PAR_O_TAG QLatin1String("__PAR_OPEN__")
#define PAR_C_TAG QLatin1String("__PAR_CLOSE__") #define PAR_C_TAG QLatin1String("__PAR_CLOSE__")
QString FolderMan::escapeAlias( const QString& alias ) const QString FolderMan::escapeAlias( const QString& alias )
{ {
QString a(alias); QString a(alias);
@ -312,6 +313,7 @@ Folder* FolderMan::setupFolderFromConfigFile(const QString &file) {
QString backend = settings.value(QLatin1String("backend")).toString(); QString backend = settings.value(QLatin1String("backend")).toString();
QString targetPath = settings.value( QLatin1String("targetPath")).toString(); QString targetPath = settings.value( QLatin1String("targetPath")).toString();
bool paused = settings.value( QLatin1String("paused"), false).toBool(); bool paused = settings.value( QLatin1String("paused"), false).toBool();
QStringList blackList = settings.value( QLatin1String("blackList")).toStringList();
// QString connection = settings.value( QLatin1String("connection") ).toString(); // QString connection = settings.value( QLatin1String("connection") ).toString();
QString alias = unescapeAlias( escapedAlias ); QString alias = unescapeAlias( escapedAlias );
@ -326,11 +328,12 @@ Folder* FolderMan::setupFolderFromConfigFile(const QString &file) {
} }
folder = new Folder( alias, path, targetPath, this ); folder = new Folder( alias, path, targetPath, this );
folder->setConfigFile(file); folder->setConfigFile(cfgFile.absoluteFilePath());
folder->setSelectiveSyncBlackList(blackList);
qDebug() << "Adding folder to Folder Map " << folder; qDebug() << "Adding folder to Folder Map " << folder;
_folderMap[alias] = folder; _folderMap[alias] = folder;
if (paused) { if (paused) {
folder->setSyncEnabled(!paused); folder->setSyncPaused(paused);
_disabledFolders.insert(folder); _disabledFolders.insert(folder);
} }
@ -346,7 +349,7 @@ Folder* FolderMan::setupFolderFromConfigFile(const QString &file) {
return folder; return folder;
} }
void FolderMan::slotEnableFolder( const QString& alias, bool enable ) void FolderMan::slotSetFolderPaused( const QString& alias, bool paused )
{ {
if( ! _folderMap.contains( alias ) ) { if( ! _folderMap.contains( alias ) ) {
qDebug() << "!! Can not enable alias " << alias << ", can not be found in folderMap."; qDebug() << "!! Can not enable alias " << alias << ", can not be found in folderMap.";
@ -355,13 +358,12 @@ void FolderMan::slotEnableFolder( const QString& alias, bool enable )
Folder *f = _folderMap[alias]; Folder *f = _folderMap[alias];
if( f ) { if( f ) {
f->setSyncEnabled(enable);
slotScheduleSync(alias); slotScheduleSync(alias);
// FIXME: Use MirallConfigFile // FIXME: Use MirallConfigFile
QSettings settings(_folderConfigPath + QLatin1Char('/') + f->configFile(), QSettings::IniFormat); QSettings settings(f->configFile(), QSettings::IniFormat);
settings.beginGroup(escapeAlias(f->alias())); settings.beginGroup(escapeAlias(f->alias()));
if (enable) { if (!paused) {
settings.remove("paused"); settings.remove("paused");
_disabledFolders.remove(f); _disabledFolders.remove(f);
} else { } else {
@ -410,7 +412,7 @@ SyncResult FolderMan::syncResult( const QString& alias )
void FolderMan::slotScheduleAllFolders() void FolderMan::slotScheduleAllFolders()
{ {
foreach( Folder *f, _folderMap.values() ) { foreach( Folder *f, _folderMap.values() ) {
if (f && f->syncEnabled()) { if (f && ! f->syncPaused()) {
slotScheduleSync( f->alias() ); slotScheduleSync( f->alias() );
} }
} }
@ -433,7 +435,7 @@ void FolderMan::slotScheduleSync( const QString& alias )
if( ! _scheduleQueue.contains(alias ) && _folderMap.contains(alias) ) { if( ! _scheduleQueue.contains(alias ) && _folderMap.contains(alias) ) {
Folder *f = _folderMap[alias]; Folder *f = _folderMap[alias];
if( f ) { if( f ) {
if( f->syncEnabled() ) { if( !f->syncPaused() ) {
f->prepareToSync(); f->prepareToSync();
} else { } else {
qDebug() << "Folder is not enabled, not scheduled!"; qDebug() << "Folder is not enabled, not scheduled!";
@ -442,7 +444,6 @@ void FolderMan::slotScheduleSync( const QString& alias )
} }
} }
_scheduleQueue.enqueue(alias); _scheduleQueue.enqueue(alias);
} else { } else {
qDebug() << " II> Sync for folder " << alias << " already scheduled, do not enqueue!"; qDebug() << " II> Sync for folder " << alias << " already scheduled, do not enqueue!";
} }
@ -450,6 +451,8 @@ void FolderMan::slotScheduleSync( const QString& alias )
QTimer::singleShot(500, this, SLOT(slotScheduleFolderSync())); QTimer::singleShot(500, this, SLOT(slotScheduleFolderSync()));
} }
// only enable or disable foldermans will to schedule and do syncs.
// this is not the same as Pause and Resume of folders.
void FolderMan::setSyncEnabled( bool enabled ) void FolderMan::setSyncEnabled( bool enabled )
{ {
if (!_syncEnabled && enabled && !_scheduleQueue.isEmpty()) { if (!_syncEnabled && enabled && !_scheduleQueue.isEmpty()) {
@ -457,12 +460,8 @@ void FolderMan::setSyncEnabled( bool enabled )
QTimer::singleShot(200, this, SLOT(slotScheduleFolderSync())); QTimer::singleShot(200, this, SLOT(slotScheduleFolderSync()));
} }
_syncEnabled = enabled; _syncEnabled = enabled;
// force a redraw in case the network connect status changed
foreach( Folder *f, _folderMap.values() ) { emit( folderSyncStateChange(QString::null) );
if(f) { // check for f != 0. That can happen, do not remove the check!
f->setSyncEnabled(enabled && !_disabledFolders.contains(f));
}
}
} }
/* /*
@ -487,10 +486,15 @@ void FolderMan::slotScheduleFolderSync()
const QString alias = _scheduleQueue.dequeue(); const QString alias = _scheduleQueue.dequeue();
if( _folderMap.contains( alias ) ) { if( _folderMap.contains( alias ) ) {
Folder *f = _folderMap[alias]; Folder *f = _folderMap[alias];
if( f && f->syncEnabled() ) { if( f && !f->syncPaused() ) {
_currentSyncFolder = alias; _currentSyncFolder = alias;
f->startSync( QStringList() ); f->startSync( QStringList() );
// reread the excludes of the socket api
// FIXME: the excludes need rework.
_socketApi->slotClearExcludesList();
_socketApi->slotReadExcludes();
} }
} }
} }
@ -514,7 +518,8 @@ void FolderMan::slotFolderSyncFinished( const SyncResult& )
QTimer::singleShot(200, this, SLOT(slotScheduleFolderSync())); QTimer::singleShot(200, this, SLOT(slotScheduleFolderSync()));
} }
void FolderMan::addFolderDefinition(const QString& alias, const QString& sourceFolder, const QString& targetPath ) void FolderMan::addFolderDefinition(const QString& alias, const QString& sourceFolder,
const QString& targetPath, const QStringList &selectiveSyncBlackList )
{ {
QString escapedAlias = escapeAlias(alias); QString escapedAlias = escapeAlias(alias);
// Create a settings file named after the alias // Create a settings file named after the alias
@ -525,6 +530,7 @@ void FolderMan::addFolderDefinition(const QString& alias, const QString& sourceF
// for compat reasons // for compat reasons
settings.setValue(QLatin1String("backend"), "owncloud" ); settings.setValue(QLatin1String("backend"), "owncloud" );
settings.setValue(QLatin1String("connection"), Theme::instance()->appName()); settings.setValue(QLatin1String("connection"), Theme::instance()->appName());
settings.setValue(QLatin1String("blackList"), selectiveSyncBlackList);
settings.sync(); settings.sync();
} }
@ -576,7 +582,7 @@ void FolderMan::removeFolder( const QString& alias )
if( _folderMap.contains( alias )) { if( _folderMap.contains( alias )) {
qDebug() << "Removing " << alias; qDebug() << "Removing " << alias;
f = _folderMap.take( alias ); f = _folderMap[alias]; // do not remove from the map, that is done in unloadFolder.
} else { } else {
qDebug() << "!! Can not remove " << alias << ", not in folderMap."; qDebug() << "!! Can not remove " << alias << ", not in folderMap.";
} }
@ -585,10 +591,10 @@ void FolderMan::removeFolder( const QString& alias )
f->wipe(); f->wipe();
// can be removed if we are able to delete the folder object. // can be removed if we are able to delete the folder object.
f->setSyncEnabled(false); f->setSyncPaused(true);
// remove the folder configuration // remove the folder configuration
QFile file( _folderConfigPath + QLatin1Char('/') + f->configFile() ); QFile file(f->configFile() );
if( file.exists() ) { if( file.exists() ) {
qDebug() << "Remove folder config file " << file.fileName(); qDebug() << "Remove folder config file " << file.fileName();
file.remove(); file.remove();
@ -680,42 +686,44 @@ SyncResult FolderMan::accountStatus(const QList<Folder*> &folders)
if( cnt == 1 ) { if( cnt == 1 ) {
Folder *folder = folders.at(0); Folder *folder = folders.at(0);
if( folder ) { if( folder ) {
SyncResult::Status syncStatus = folder->syncResult().status(); if( folder->syncPaused() ) {
overallResult.setStatus(SyncResult::Paused);
} else {
SyncResult::Status syncStatus = folder->syncResult().status();
switch( syncStatus ) {
case SyncResult::Undefined: switch( syncStatus ) {
overallResult.setStatus(SyncResult::Error); case SyncResult::Undefined:
break; overallResult.setStatus(SyncResult::Error);
case SyncResult::NotYetStarted: break;
overallResult.setStatus( SyncResult::NotYetStarted ); case SyncResult::NotYetStarted:
break; overallResult.setStatus( SyncResult::NotYetStarted );
case SyncResult::SyncPrepare: break;
overallResult.setStatus( SyncResult::SyncPrepare ); case SyncResult::SyncPrepare:
break; overallResult.setStatus( SyncResult::SyncPrepare );
case SyncResult::SyncRunning: break;
overallResult.setStatus( SyncResult::SyncRunning ); case SyncResult::SyncRunning:
break; overallResult.setStatus( SyncResult::SyncRunning );
case SyncResult::Unavailable: break;
overallResult.setStatus( SyncResult::Unavailable ); case SyncResult::Problem: // don't show the problem icon in tray.
break; case SyncResult::Success:
case SyncResult::Problem: // don't show the problem icon in tray. if( overallResult.status() == SyncResult::Undefined )
case SyncResult::Success: overallResult.setStatus( SyncResult::Success );
if( overallResult.status() == SyncResult::Undefined ) break;
overallResult.setStatus( SyncResult::Success ); case SyncResult::Error:
break; overallResult.setStatus( SyncResult::Error );
case SyncResult::Error: break;
overallResult.setStatus( SyncResult::Error ); case SyncResult::SetupError:
break; if ( overallResult.status() != SyncResult::Error )
case SyncResult::SetupError: overallResult.setStatus( SyncResult::SetupError );
if ( overallResult.status() != SyncResult::Error ) break;
overallResult.setStatus( SyncResult::SetupError ); case SyncResult::SyncAbortRequested:
break; overallResult.setStatus( SyncResult::SyncAbortRequested);
case SyncResult::SyncAbortRequested: break;
overallResult.setStatus( SyncResult::SyncAbortRequested); case SyncResult::Paused:
break; overallResult.setStatus( SyncResult::Paused);
case SyncResult::Paused: break;
overallResult.setStatus( SyncResult::Paused); }
break;
} }
} }
} else { } else {
@ -724,36 +732,36 @@ SyncResult FolderMan::accountStatus(const QList<Folder*> &folders)
int abortSeen = 0; int abortSeen = 0;
int runSeen = 0; int runSeen = 0;
int various = 0; int various = 0;
int unavail = 0;
foreach ( Folder *folder, folders ) { foreach ( Folder *folder, folders ) {
SyncResult folderResult = folder->syncResult(); if( folder->syncPaused() ) {
SyncResult::Status syncStatus = folderResult.status();
switch( syncStatus ) {
case SyncResult::Undefined:
case SyncResult::NotYetStarted:
case SyncResult::SyncPrepare:
various++;
break;
case SyncResult::SyncRunning:
runSeen++;
break;
case SyncResult::Unavailable:
unavail++;
break;
case SyncResult::Problem: // don't show the problem icon in tray.
case SyncResult::Success:
goodSeen++;
break;
case SyncResult::Error:
case SyncResult::SetupError:
errorsSeen++;
break;
case SyncResult::SyncAbortRequested:
case SyncResult::Paused:
abortSeen++; abortSeen++;
// no default case on purpose, check compiler warnings } else {
SyncResult folderResult = folder->syncResult();
SyncResult::Status syncStatus = folderResult.status();
switch( syncStatus ) {
case SyncResult::Undefined:
case SyncResult::NotYetStarted:
case SyncResult::SyncPrepare:
various++;
break;
case SyncResult::SyncRunning:
runSeen++;
break;
case SyncResult::Problem: // don't show the problem icon in tray.
case SyncResult::Success:
goodSeen++;
break;
case SyncResult::Error:
case SyncResult::SetupError:
errorsSeen++;
break;
case SyncResult::SyncAbortRequested:
case SyncResult::Paused:
abortSeen++;
// no default case on purpose, check compiler warnings
}
} }
} }
bool set = false; bool set = false;
@ -779,7 +787,7 @@ SyncResult FolderMan::accountStatus(const QList<Folder*> &folders)
return overallResult; return overallResult;
} }
QString FolderMan::statusToString( SyncResult syncStatus, bool enabled ) const QString FolderMan::statusToString( SyncResult syncStatus, bool paused ) const
{ {
QString folderMessage; QString folderMessage;
switch( syncStatus.status() ) { switch( syncStatus.status() ) {
@ -795,9 +803,6 @@ QString FolderMan::statusToString( SyncResult syncStatus, bool enabled ) const
case SyncResult::SyncRunning: case SyncResult::SyncRunning:
folderMessage = tr( "Sync is running." ); folderMessage = tr( "Sync is running." );
break; break;
case SyncResult::Unavailable:
folderMessage = tr( "Server is currently not available." );
break;
case SyncResult::Success: case SyncResult::Success:
folderMessage = tr( "Last Sync was successful." ); folderMessage = tr( "Last Sync was successful." );
break; break;
@ -817,7 +822,7 @@ QString FolderMan::statusToString( SyncResult syncStatus, bool enabled ) const
break; break;
// no default case on purpose, check compiler warnings // no default case on purpose, check compiler warnings
} }
if( !enabled ) { if( paused ) {
// sync is disabled. // sync is disabled.
folderMessage = tr( "%1 (Sync is paused)" ).arg(folderMessage); folderMessage = tr( "%1 (Sync is paused)" ).arg(folderMessage);
} }

View file

@ -50,7 +50,8 @@ public:
* QString sourceFolder on local machine * QString sourceFolder on local machine
* QString targetPath on remote * QString targetPath on remote
*/ */
void addFolderDefinition(const QString&, const QString&, const QString& ); void addFolderDefinition(const QString&, const QString&, const QString& ,
const QStringList &selectiveSyncBlacklist = QStringList() );
/** Returns the folder which the file or directory stored in path is in */ /** Returns the folder which the file or directory stored in path is in */
Folder* folderForPath(const QString& path); Folder* folderForPath(const QString& path);
@ -77,17 +78,23 @@ public:
/** Creates a new and empty local directory. */ /** Creates a new and empty local directory. */
bool startFromScratch( const QString& ); bool startFromScratch( const QString& );
QString statusToString( SyncResult, bool enabled ) const; QString statusToString(SyncResult, bool paused ) const;
static SyncResult accountStatus( const QList<Folder*> &folders ); static SyncResult accountStatus( const QList<Folder*> &folders );
void removeMonitorPath( const QString& alias, const QString& path ); void removeMonitorPath( const QString& alias, const QString& path );
void addMonitorPath( const QString& alias, const QString& path ); void addMonitorPath( const QString& alias, const QString& path );
// Escaping of the alias which is used in QSettings AND the file
// system, thus need to be escaped.
static QString escapeAlias( const QString& );
signals: signals:
/** /**
* signal to indicate a folder named by alias has changed its sync state. * signal to indicate a folder named by alias has changed its sync state.
* Get the state via the Folder Map or the syncResult and syncState methods. * Get the state via the Folder Map or the syncResult and syncState methods.
*
* Attention: The alias string may be zero. Do a general update of the state than.
*/ */
void folderSyncStateChange( const QString & ); void folderSyncStateChange( const QString & );
@ -95,7 +102,7 @@ signals:
public slots: public slots:
void slotRemoveFolder( const QString& ); void slotRemoveFolder( const QString& );
void slotEnableFolder( const QString&, bool ); void slotSetFolderPaused(const QString&, bool paused);
void slotFolderSyncStarted(); void slotFolderSyncStarted();
void slotFolderSyncFinished( const SyncResult& ); void slotFolderSyncFinished( const SyncResult& );
@ -131,9 +138,6 @@ private:
QString getBackupName( const QString& ) const; QString getBackupName( const QString& ) const;
void registerFolderMonitor( Folder *folder ); void registerFolderMonitor( Folder *folder );
// Escaping of the alias which is used in QSettings AND the file
// system, thus need to be escaped.
QString escapeAlias( const QString& ) const;
QString unescapeAlias( const QString& ) const; QString unescapeAlias( const QString& ) const;
void removeFolder( const QString& ); void removeFolder( const QString& );

View file

@ -133,8 +133,9 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
QString itemString = qvariant_cast<QString>(index.data(SyncProgressItemString)); QString itemString = qvariant_cast<QString>(index.data(SyncProgressItemString));
int warningCount = qvariant_cast<int>(index.data(WarningCount)); int warningCount = qvariant_cast<int>(index.data(WarningCount));
bool syncOngoing = qvariant_cast<bool>(index.data(SyncRunning)); bool syncOngoing = qvariant_cast<bool>(index.data(SyncRunning));
// QString statusText = qvariant_cast<QString>(index.data(FolderStatus)); // QString statusText = qvariant_cast<QString>(index.data(FolderStatus));
bool syncEnabled = index.data(FolderSyncEnabled).toBool(); bool syncEnabled = index.data(FolderAccountConnected).toBool();
// QString syncStatus = syncEnabled? tr( "Enabled" ) : tr( "Disabled" ); // QString syncStatus = syncEnabled? tr( "Enabled" ) : tr( "Disabled" );
QRect iconRect = option.rect; QRect iconRect = option.rect;
@ -246,7 +247,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
h += aliasMargin; h += aliasMargin;
// Sync File Progress Bar: Show it if syncFile is not empty. // Sync File Progress Bar: Show it if syncFile is not empty.
if( !overallString.isEmpty()) { if( !overallString.isEmpty() || !itemString.isEmpty()) {
int fileNameTextHeight = subFm.boundingRect(tr("File")).height(); int fileNameTextHeight = subFm.boundingRect(tr("File")).height();
int barHeight = qMax(fileNameTextHeight, aliasFm.height()+4); ; int barHeight = qMax(fileNameTextHeight, aliasFm.height()+4); ;
int overallWidth = option.rect.width()-2*aliasMargin; int overallWidth = option.rect.width()-2*aliasMargin;

View file

@ -42,8 +42,9 @@ class FolderStatusDelegate : public QStyledItemDelegate
FolderRemotePath, FolderRemotePath,
FolderStatus, FolderStatus,
FolderErrorMsg, FolderErrorMsg,
FolderSyncEnabled, FolderSyncPaused,
FolderStatusIconRole, FolderStatusIconRole,
FolderAccountConnected,
SyncProgressOverallPercent, SyncProgressOverallPercent,
SyncProgressOverallString, SyncProgressOverallString,

View file

@ -18,6 +18,7 @@
#include "theme.h" #include "theme.h"
#include "networkjobs.h" #include "networkjobs.h"
#include "account.h" #include "account.h"
#include "selectivesyncdialog.h"
#include <QDebug> #include <QDebug>
#include <QDesktopServices> #include <QDesktopServices>
@ -30,6 +31,7 @@
#include <QValidator> #include <QValidator>
#include <QWizardPage> #include <QWizardPage>
#include <QTreeWidget> #include <QTreeWidget>
#include <QVBoxLayout>
#include <stdlib.h> #include <stdlib.h>
@ -424,6 +426,50 @@ void FolderWizardRemotePath::showWarn( const QString& msg ) const
// ==================================================================================== // ====================================================================================
FolderWizardSelectiveSync::FolderWizardSelectiveSync()
{
QVBoxLayout *layout = new QVBoxLayout(this);
_treeView = new SelectiveSyncTreeView(this);
layout->addWidget(new QLabel(tr("Selective Sync: You can optionally deselect subfolders you do not wish to synchronize.")));
layout->addWidget(_treeView);
}
FolderWizardSelectiveSync::~FolderWizardSelectiveSync()
{
}
void FolderWizardSelectiveSync::initializePage()
{
QString alias = wizard()->field(QLatin1String("alias")).toString();
QString targetPath = wizard()->property("targetPath").toString();
if (targetPath.startsWith('/')) {
targetPath = targetPath.mid(1);
}
_treeView->setFolderInfo(targetPath, alias);
QWizardPage::initializePage();
}
bool FolderWizardSelectiveSync::validatePage()
{
wizard()->setProperty("selectiveSyncBlackList", QVariant(_treeView->createBlackList()));
return true;
}
void FolderWizardSelectiveSync::cleanupPage()
{
QString alias = wizard()->field(QLatin1String("alias")).toString();
QString targetPath = wizard()->property("targetPath").toString();
_treeView->setFolderInfo(targetPath, alias);
QWizardPage::cleanupPage();
}
// ====================================================================================
/** /**
* Folder wizard itself * Folder wizard itself
*/ */
@ -431,7 +477,8 @@ void FolderWizardRemotePath::showWarn( const QString& msg ) const
FolderWizard::FolderWizard( QWidget *parent ) FolderWizard::FolderWizard( QWidget *parent )
: QWizard(parent), : QWizard(parent),
_folderWizardSourcePage(new FolderWizardLocalPath), _folderWizardSourcePage(new FolderWizardLocalPath),
_folderWizardTargetPage(0) _folderWizardTargetPage(0),
_folderWizardSelectiveSyncPage(new FolderWizardSelectiveSync)
{ {
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setPage(Page_Source, _folderWizardSourcePage ); setPage(Page_Source, _folderWizardSourcePage );
@ -439,6 +486,7 @@ FolderWizard::FolderWizard( QWidget *parent )
_folderWizardTargetPage = new FolderWizardRemotePath(); _folderWizardTargetPage = new FolderWizardRemotePath();
setPage(Page_Target, _folderWizardTargetPage ); setPage(Page_Target, _folderWizardTargetPage );
} }
setPage(Page_SelectiveSync, _folderWizardSelectiveSyncPage);
setWindowTitle( tr("Add Folder") ); setWindowTitle( tr("Add Folder") );
setOptions(QWizard::CancelButtonOnLeft); setOptions(QWizard::CancelButtonOnLeft);

View file

@ -26,6 +26,8 @@
namespace Mirall { namespace Mirall {
class SelectiveSyncTreeView;
class ownCloudInfo; class ownCloudInfo;
class FormatWarningsWizardPage : public QWizardPage { class FormatWarningsWizardPage : public QWizardPage {
@ -90,6 +92,25 @@ private:
}; };
class FolderWizardSelectiveSync : public QWizardPage
{
Q_OBJECT
public:
FolderWizardSelectiveSync();
~FolderWizardSelectiveSync();
virtual bool validatePage() Q_DECL_OVERRIDE;
virtual void initializePage() Q_DECL_OVERRIDE;
virtual void cleanupPage() Q_DECL_OVERRIDE;
private:
SelectiveSyncTreeView *_treeView;
};
/** /**
* *
*/ */
@ -100,7 +121,8 @@ public:
enum { enum {
Page_Source, Page_Source,
Page_Target Page_Target,
Page_SelectiveSync
}; };
FolderWizard(QWidget *parent = 0); FolderWizard(QWidget *parent = 0);
@ -110,6 +132,7 @@ private:
FolderWizardLocalPath *_folderWizardSourcePage; FolderWizardLocalPath *_folderWizardSourcePage;
FolderWizardRemotePath *_folderWizardTargetPage; FolderWizardRemotePath *_folderWizardTargetPage;
FolderWizardSelectiveSync *_folderWizardSelectiveSyncPage;
}; };

View file

@ -46,6 +46,7 @@ GeneralSettings::GeneralSettings(QWidget *parent) :
_ui->aboutGroupBox->hide(); _ui->aboutGroupBox->hide();
} else { } else {
_ui->aboutLabel->setText(about); _ui->aboutLabel->setText(about);
_ui->aboutLabel->setWordWrap(true);
_ui->aboutLabel->setOpenExternalLinks(true); _ui->aboutLabel->setOpenExternalLinks(true);
} }

View file

@ -54,7 +54,9 @@ ownCloudGui::ownCloudGui(Application *parent) :
{ {
_tray = new Systray(); _tray = new Systray();
_tray->setParent(this); _tray->setParent(this);
_tray->setIcon( Theme::instance()->syncStateIcon( SyncResult::NotYetStarted, true ) );
// for the beginning, set the offline icon until the account was verified
_tray->setIcon( Theme::instance()->folderOfflineIcon(true));
connect(_tray.data(), SIGNAL(activated(QSystemTrayIcon::ActivationReason)), connect(_tray.data(), SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason))); SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason)));
@ -97,7 +99,7 @@ ownCloudGui::ownCloudGui(Application *parent) :
void ownCloudGui::setupOverlayIcons() void ownCloudGui::setupOverlayIcons()
{ {
if( Utility::isMac() && QFile::exists("/Library/ScriptingAdditions/LiferayNativity.osax") ) { if( Utility::isMac() && QFile::exists("/Library/ScriptingAdditions/OwnCloudFinder.osax") ) {
QString aScript = QString::fromUtf8("tell application \"Finder\"\n" QString aScript = QString::fromUtf8("tell application \"Finder\"\n"
" try\n" " try\n"
" «event NVTYload»\n" " «event NVTYload»\n"
@ -164,12 +166,12 @@ void ownCloudGui::slotSyncStateChange( const QString& alias )
slotComputeOverallSyncStatus(); slotComputeOverallSyncStatus();
if( alias.isEmpty() ) {
return; // Valid, just a general GUI redraw was needed.
}
qDebug() << "Sync state changed for folder " << alias << ": " << result.statusString(); qDebug() << "Sync state changed for folder " << alias << ": " << result.statusString();
// Promote sync result to settings-dialog for sync protocol?
// if( _progressDialog ) {
// _progressDialog->setSyncResult(result);
// }
if (result.status() == SyncResult::Success || result.status() == SyncResult::Error) { if (result.status() == SyncResult::Success || result.status() == SyncResult::Error) {
Logger::instance()->enterNextLogFile(); Logger::instance()->enterNextLogFile();
} }
@ -199,25 +201,28 @@ void ownCloudGui::startupConnected( bool connected, const QStringList& fails )
if( connected ) { if( connected ) {
qDebug() << "######## connected to ownCloud Server!"; qDebug() << "######## connected to ownCloud Server!";
folderMan->setSyncEnabled(true); folderMan->setSyncEnabled(true);
_tray->setIcon( Theme::instance()->syncStateIcon( SyncResult::NotYetStarted, true ) ); // _tray->setIcon( Theme::instance()->syncStateIcon( SyncResult::NotYetStarted, true ) );
_tray->show(); // _tray->show();
} }
_startupFails = fails; // store that for the settings dialog once it appears. _startupFails = fails; // store that for the settings dialog once it appears.
if( !_settingsDialog.isNull() ) if( !_settingsDialog.isNull() ) {
_settingsDialog->setGeneralErrors( _startupFails ); _settingsDialog->setGeneralErrors( _startupFails );
}
slotComputeOverallSyncStatus();
} }
void ownCloudGui::slotComputeOverallSyncStatus() void ownCloudGui::slotComputeOverallSyncStatus()
{ {
if (Account *a = AccountManager::instance()->account()) { if (Account *a = AccountManager::instance()->account()) {
if (a->state() == Account::SignedOut) { if (a->state() == Account::SignedOut) {
_tray->setIcon(Theme::instance()->syncStateIcon( SyncResult::Unavailable, true)); _tray->setIcon(Theme::instance()->folderOfflineIcon(true));
_tray->setToolTip(tr("Please sign in")); _tray->setToolTip(tr("Please sign in"));
return; return;
} }
if (a->state() == Account::Disconnected) { if (a->state() == Account::Disconnected) {
_tray->setIcon(Theme::instance()->syncStateIcon( SyncResult::Unavailable, true)); _tray->setIcon(Theme::instance()->folderOfflineIcon(true));
_tray->setToolTip(tr("Disconnected from server")); _tray->setToolTip(tr("Disconnected from server"));
return; return;
} }
@ -249,7 +254,7 @@ void ownCloudGui::slotComputeOverallSyncStatus()
QStringList allStatusStrings; QStringList allStatusStrings;
foreach(Folder* folder, map.values()) { foreach(Folder* folder, map.values()) {
qDebug() << "Folder in overallStatus Message: " << folder << " with name " << folder->alias(); qDebug() << "Folder in overallStatus Message: " << folder << " with name " << folder->alias();
QString folderMessage = folderMan->statusToString(folder->syncResult().status(), folder->syncEnabled()); QString folderMessage = folderMan->statusToString(folder->syncResult().status(), folder->syncPaused());
allStatusStrings += tr("Folder %1: %2").arg(folder->alias(), folderMessage); allStatusStrings += tr("Folder %1: %2").arg(folder->alias(), folderMessage);
} }
@ -261,6 +266,16 @@ void ownCloudGui::slotComputeOverallSyncStatus()
QIcon statusIcon = Theme::instance()->syncStateIcon( overallResult.status(), true); QIcon statusIcon = Theme::instance()->syncStateIcon( overallResult.status(), true);
_tray->setIcon( statusIcon ); _tray->setIcon( statusIcon );
_tray->setToolTip(trayMessage); _tray->setToolTip(trayMessage);
} else {
// undefined because there are no folders.
QIcon icon = Theme::instance()->syncStateIcon(SyncResult::Problem);
_tray->setIcon( icon );
_tray->setToolTip(tr("There are no sync folders configured."));
#if !defined Q_OS_MAC
if( _settingsDialog ) {
_settingsDialog->slotUpdateAccountIcon(icon);
}
#endif
} }
} }
} }
@ -444,13 +459,16 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const Progress::Info
{ {
Q_UNUSED(folder); Q_UNUSED(folder);
QString totalSizeStr = Utility::octetsToString( progress._totalSize ); if (!progress._currentDiscoveredFolder.isEmpty()) {
if(progress._totalSize == 0 ) { _actionStatus->setText( tr("Discovering %1")
.arg( progress._currentDiscoveredFolder ));
} else if (progress._totalSize == 0 ) {
quint64 currentFile = progress._completedFileCount + progress._currentItems.count(); quint64 currentFile = progress._completedFileCount + progress._currentItems.count();
_actionStatus->setText( tr("Syncing %1 of %2 (%3 left)") _actionStatus->setText( tr("Syncing %1 of %2 (%3 left)")
.arg( currentFile ).arg( progress._totalFileCount ) .arg( currentFile ).arg( progress._totalFileCount )
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) ); .arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) );
} else { } else {
QString totalSizeStr = Utility::octetsToString( progress._totalSize );
_actionStatus->setText( tr("Syncing %1 (%2 left)") _actionStatus->setText( tr("Syncing %1 (%2 left)")
.arg( totalSizeStr ) .arg( totalSizeStr )
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) ); .arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) );
@ -491,7 +509,8 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const Progress::Info
slotRebuildRecentMenus(); slotRebuildRecentMenus();
} }
if (progress._completedFileCount == progress._totalFileCount) { if (progress._completedFileCount == progress._totalFileCount
&& progress._currentDiscoveredFolder.isEmpty()) {
QTimer::singleShot(2000, this, SLOT(slotDisplayIdle())); QTimer::singleShot(2000, this, SLOT(slotDisplayIdle()));
} }
} }

View file

@ -74,11 +74,8 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent) :
NetworkSettings *networkSettings = new NetworkSettings; NetworkSettings *networkSettings = new NetworkSettings;
_ui->stack->addWidget(networkSettings); _ui->stack->addWidget(networkSettings);
FolderMan *folderMan = FolderMan::instance();
connect( folderMan, SIGNAL(folderSyncStateChange(QString)),
this, SLOT(slotSyncStateChange(QString)));
connect( _accountSettings, SIGNAL(folderChanged()), gui, SLOT(slotFoldersChanged())); connect( _accountSettings, SIGNAL(folderChanged()), gui, SLOT(slotFoldersChanged()));
connect( _accountSettings, SIGNAL(accountIconChanged(QIcon)), SLOT(slotUpdateAccountIcon(QIcon)));
connect( _accountSettings, SIGNAL(openFolderAlias(const QString&)), connect( _accountSettings, SIGNAL(openFolderAlias(const QString&)),
gui, SLOT(slotFolderOpenAction(QString))); gui, SLOT(slotFolderOpenAction(QString)));
@ -130,22 +127,7 @@ void SettingsDialog::addAccount(const QString &title, QWidget *widget)
_accountItem->setSizeHint(QSize(0, 32)); _accountItem->setSizeHint(QSize(0, 32));
_ui->labelWidget->addItem(_accountItem); _ui->labelWidget->addItem(_accountItem);
_ui->stack->addWidget(widget); _ui->stack->addWidget(widget);
slotSyncStateChange(); _accountSettings->slotSyncStateChange();
}
void SettingsDialog::slotSyncStateChange(const QString& alias)
{
FolderMan *folderMan = FolderMan::instance();
SyncResult state = folderMan->accountStatus(folderMan->map().values());
_accountItem->setIcon(Theme::instance()->syncStateIcon(state.status()));
if (!alias.isEmpty()) {
Folder *folder = folderMan->folder(alias);
if( folder ) {
_accountSettings->slotUpdateFolderState(folder);
}
}
} }
void SettingsDialog::setGeneralErrors(const QStringList &errors) void SettingsDialog::setGeneralErrors(const QStringList &errors)
@ -168,6 +150,11 @@ void SettingsDialog::accept() {
QDialog::accept(); QDialog::accept();
} }
void SettingsDialog::slotUpdateAccountIcon(const QIcon &icon)
{
_accountItem->setIcon(icon);
}
void SettingsDialog::showActivityPage() void SettingsDialog::showActivityPage()
{ {
_ui->labelWidget->setCurrentRow(_protocolIdx); _ui->labelWidget->setCurrentRow(_protocolIdx);

View file

@ -45,13 +45,15 @@ public:
void setGeneralErrors( const QStringList& errors ); void setGeneralErrors( const QStringList& errors );
public slots: public slots:
void slotSyncStateChange(const QString& alias = QString());
void showActivityPage(); void showActivityPage();
void slotUpdateAccountIcon(const QIcon& icon);
protected: protected:
void reject() Q_DECL_OVERRIDE; void reject() Q_DECL_OVERRIDE;
void accept() Q_DECL_OVERRIDE; void accept() Q_DECL_OVERRIDE;
private slots:
private: private:
Ui::SettingsDialog *_ui; Ui::SettingsDialog *_ui;
AccountSettings *_accountSettings; AccountSettings *_accountSettings;

View file

@ -43,12 +43,12 @@ enum csync_exclude_type_e {
}; };
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE; typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype); CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype);
int csync_exclude_load(const char *fname, c_strlist_t **list);
} }
namespace { namespace {
const int PORT = 33001; const int PORT = 34001;
} }
namespace Mirall { namespace Mirall {
@ -57,7 +57,7 @@ namespace Mirall {
namespace SocketApiHelper { namespace SocketApiHelper {
SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName ); SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName, c_strlist_t *excludes );
/** /**
* @brief recursiveFolderStatus * @brief recursiveFolderStatus
@ -70,7 +70,7 @@ SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName );
*/ */
// compute the file status of a directory recursively. It returns either // compute the file status of a directory recursively. It returns either
// "all in sync" or "needs update" or "error", no more details. // "all in sync" or "needs update" or "error", no more details.
SyncFileStatus recursiveFolderStatus(Folder *folder, const QString& fileName ) SyncFileStatus recursiveFolderStatus(Folder *folder, const QString& fileName, c_strlist_t *excludes )
{ {
QDir dir(folder->path() + fileName); QDir dir(folder->path() + fileName);
@ -84,14 +84,14 @@ SyncFileStatus recursiveFolderStatus(Folder *folder, const QString& fileName )
SyncFileStatus sfs; SyncFileStatus sfs;
if( fi.isDir() ) { if( fi.isDir() ) {
sfs = recursiveFolderStatus(folder, normalizedFile ); sfs = recursiveFolderStatus(folder, normalizedFile, excludes );
} else { } else {
QString fs( normalizedFile ); QString fs( normalizedFile );
if( fileName.isEmpty() ) { if( fileName.isEmpty() ) {
// toplevel, no slash etc. needed. // toplevel, no slash etc. needed.
fs = entry.normalized(QString::NormalizationForm_C); fs = entry.normalized(QString::NormalizationForm_C);
} }
sfs = fileStatus(folder, fs ); sfs = fileStatus(folder, fs, excludes);
} }
if( sfs.tag() == SyncFileStatus::STATUS_STAT_ERROR || sfs.tag() == SyncFileStatus::STATUS_ERROR ) { if( sfs.tag() == SyncFileStatus::STATUS_STAT_ERROR || sfs.tag() == SyncFileStatus::STATUS_ERROR ) {
@ -106,7 +106,7 @@ SyncFileStatus recursiveFolderStatus(Folder *folder, const QString& fileName )
/** /**
* Get status about a single file. * Get status about a single file.
*/ */
SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName ) SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName, c_strlist_t *excludes )
{ {
// FIXME: Find a way for STATUS_ERROR // FIXME: Find a way for STATUS_ERROR
@ -142,7 +142,8 @@ SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName )
// '\' is ignored, so convert to unix path before passing the path in. // '\' is ignored, so convert to unix path before passing the path in.
QString unixFileName = QDir::fromNativeSeparators(fileName); QString unixFileName = QDir::fromNativeSeparators(fileName);
CSYNC_EXCLUDE_TYPE excl = csync_excluded(folder->csyncContext(), unixFileName.toUtf8(), type);
CSYNC_EXCLUDE_TYPE excl = csync_excluded_no_ctx(excludes, unixFileName.toUtf8(), type);
if( excl != CSYNC_NOT_EXCLUDED ) { if( excl != CSYNC_NOT_EXCLUDED ) {
return SyncFileStatus(SyncFileStatus::STATUS_IGNORE); return SyncFileStatus(SyncFileStatus::STATUS_IGNORE);
} }
@ -157,7 +158,7 @@ SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName )
SyncFileStatus status(SyncFileStatus::STATUS_NONE); SyncFileStatus status(SyncFileStatus::STATUS_NONE);
if( type == CSYNC_FTW_TYPE_DIR ) { if( type == CSYNC_FTW_TYPE_DIR ) {
// compute recursive status of the directory // compute recursive status of the directory
status = recursiveFolderStatus( folder, fileName ); status = recursiveFolderStatus( folder, fileName, excludes );
} else if(fi.lastModified() != rec._modtime ) { } else if(fi.lastModified() != rec._modtime ) {
// file was locally modified. // file was locally modified.
status.set(SyncFileStatus::STATUS_EVAL); status.set(SyncFileStatus::STATUS_EVAL);
@ -179,6 +180,7 @@ SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName )
SocketApi::SocketApi(QObject* parent) SocketApi::SocketApi(QObject* parent)
: QObject(parent) : QObject(parent)
, _localServer(new QTcpServer(this)) , _localServer(new QTcpServer(this))
, _excludes(0)
{ {
// setup socket // setup socket
DEBUG << "Establishing SocketAPI server at" << PORT; DEBUG << "Establishing SocketAPI server at" << PORT;
@ -197,6 +199,28 @@ SocketApi::~SocketApi()
{ {
DEBUG << "dtor"; DEBUG << "dtor";
_localServer->close(); _localServer->close();
slotClearExcludesList();
}
void SocketApi::slotClearExcludesList()
{
c_strlist_clear(_excludes);
}
void SocketApi::slotReadExcludes()
{
MirallConfigFile cfgFile;
slotClearExcludesList();
QString excludeList = cfgFile.excludeFile( MirallConfigFile::SystemScope );
if( !excludeList.isEmpty() ) {
qDebug() << "==== added system ignore list to socketapi:" << excludeList.toUtf8();
csync_exclude_load(excludeList.toUtf8(), &_excludes);
}
excludeList = cfgFile.excludeFile( MirallConfigFile::UserScope );
if( !excludeList.isEmpty() ) {
qDebug() << "==== added user defined ignore list to csync:" << excludeList.toUtf8();
csync_exclude_load(excludeList.toUtf8(), &_excludes);
}
} }
void SocketApi::slotNewConnection() void SocketApi::slotNewConnection()
@ -261,7 +285,7 @@ void SocketApi::slotUnregisterPath( const QString& alias )
{ {
Folder *f = FolderMan::instance()->folder(alias); Folder *f = FolderMan::instance()->folder(alias);
if (f) { if (f) {
broadcastMessage(QLatin1String("UNREGISTER_PATH"), f->path() ); broadcastMessage(QLatin1String("UNREGISTER_PATH"), f->path(), QString::null, true );
} }
} }
@ -304,7 +328,7 @@ void SocketApi::slotJobCompleted(const QString &folder, const SyncFileItem &item
void SocketApi::sendMessage(QTcpSocket *socket, const QString& message) void SocketApi::sendMessage(QTcpSocket *socket, const QString& message, bool doWait)
{ {
DEBUG << "Sending message: " << message; DEBUG << "Sending message: " << message;
QString localMessage = message; QString localMessage = message;
@ -312,13 +336,16 @@ void SocketApi::sendMessage(QTcpSocket *socket, const QString& message)
localMessage.append(QLatin1Char('\n')); localMessage.append(QLatin1Char('\n'));
} }
qint64 sent = socket->write(localMessage.toUtf8()); qint64 sent = socket->write(localMessage.toUtf8());
if( doWait ) {
socket->waitForBytesWritten(1000);
}
if( sent != localMessage.toUtf8().length() ) { if( sent != localMessage.toUtf8().length() ) {
qDebug() << "WARN: Could not send all data on socket for " << localMessage; qDebug() << "WARN: Could not send all data on socket for " << localMessage;
} }
} }
void SocketApi::broadcastMessage( const QString& verb, const QString& path, const QString& status ) void SocketApi::broadcastMessage( const QString& verb, const QString& path, const QString& status, bool doWait )
{ {
QString msg(verb); QString msg(verb);
@ -333,7 +360,7 @@ void SocketApi::broadcastMessage( const QString& verb, const QString& path, cons
DEBUG << "Broadcasting to" << _listeners.count() << "listeners: " << msg; DEBUG << "Broadcasting to" << _listeners.count() << "listeners: " << msg;
foreach(QTcpSocket *socket, _listeners) { foreach(QTcpSocket *socket, _listeners) {
sendMessage(socket, msg); sendMessage(socket, msg, doWait);
} }
} }
@ -363,7 +390,7 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QTcpSocket
statusString = QLatin1String("NOP"); statusString = QLatin1String("NOP");
} else { } else {
const QString file = argument.mid(syncFolder->path().length()); const QString file = argument.mid(syncFolder->path().length());
SyncFileStatus fileStatus = SocketApiHelper::fileStatus(syncFolder, file); SyncFileStatus fileStatus = SocketApiHelper::fileStatus(syncFolder, file, _excludes);
statusString = fileStatus.toSocketAPIString(); statusString = fileStatus.toSocketAPIString();
} }

View file

@ -16,6 +16,10 @@
#ifndef SOCKETAPI_H #ifndef SOCKETAPI_H
#define SOCKETAPI_H #define SOCKETAPI_H
extern "C" {
#include <std/c_string.h>
}
#include <QWeakPointer> #include <QWeakPointer>
#include <QTcpSocket> #include <QTcpSocket>
#include <QTcpServer> #include <QTcpServer>
@ -40,7 +44,8 @@ public slots:
void slotUpdateFolderView(const QString&); void slotUpdateFolderView(const QString&);
void slotUnregisterPath( const QString& alias ); void slotUnregisterPath( const QString& alias );
void slotRegisterPath( const QString& alias ); void slotRegisterPath( const QString& alias );
void slotReadExcludes();
void slotClearExcludesList();
private slots: private slots:
void slotNewConnection(); void slotNewConnection();
void onLostConnection(); void onLostConnection();
@ -48,8 +53,8 @@ private slots:
void slotJobCompleted(const QString &, const SyncFileItem &); void slotJobCompleted(const QString &, const SyncFileItem &);
private: private:
void sendMessage(QTcpSocket* socket, const QString& message); void sendMessage(QTcpSocket* socket, const QString& message, bool doWait = false);
void broadcastMessage(const QString& verb, const QString &path, const QString &status = QString::null); void broadcastMessage(const QString& verb, const QString &path, const QString &status = QString::null, bool doWait = false);
Q_INVOKABLE void command_RETRIEVE_FOLDER_STATUS(const QString& argument, QTcpSocket* socket); Q_INVOKABLE void command_RETRIEVE_FOLDER_STATUS(const QString& argument, QTcpSocket* socket);
Q_INVOKABLE void command_RETRIEVE_FILE_STATUS(const QString& argument, QTcpSocket* socket); Q_INVOKABLE void command_RETRIEVE_FILE_STATUS(const QString& argument, QTcpSocket* socket);
@ -57,6 +62,7 @@ private:
private: private:
QTcpServer *_localServer; QTcpServer *_localServer;
QList<QTcpSocket*> _listeners; QList<QTcpSocket*> _listeners;
c_strlist_t *_excludes;
}; };
} }

View file

@ -53,6 +53,14 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr
} else { } else {
_item._errorString = errorString; _item._errorString = errorString;
} }
if( _propagator->_abortRequested.fetchAndAddRelaxed(0) ) {
// an abort request is ongoing. Change the status to Soft-Error
status = SyncFileItem::SoftError;
_item._errorString = tr("Operation was canceled by user interaction.");
}
_item._status = status; _item._status = status;
// Blacklisting // Blacklisting

Some files were not shown because too many files have changed in this diff Show more