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
# Mac OS X specific
shell_integration/MacOSX/LiferayNativity.xcworkspace/xcuserdata/
shell_integration/MacOSX/*.xcworkspace/xcuserdata/
**/.DS_Store
# Visual C++ cache files

View file

@ -4,7 +4,7 @@ set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_SOVERSION 0 )
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 )
if( NOT DEFINED MIRALL_VERSION_BUILD )

View file

@ -793,7 +793,7 @@
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Library/ScriptingAdditions/LiferayNativity.osax/Contents</string>
<string>Library/ScriptingAdditions/OwnCloudFinder.osax/Contents</string>
<key>PATH_TYPE</key>
<integer>3</integer>
<key>PERMISSIONS</key>
@ -807,7 +807,7 @@
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>LiferayNativity.osax</string>
<string>OwnCloudFinder.osax</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<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 $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "ÅðéëÝîôå ôçí åðéëïãÞ óõíôÞñçóçò ðïõ èá ðñáãìáôïðïéçèåß."
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_DetailPrint "ÐñïóèÞêç óõíôüìåõóçò ãéá ôçí ${APPLICATION_NAME} óôï Áñ÷éêü Ìåíïý."
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Óõíôüìåõóç åðéöÜíåéáò åñãáóßáò"
@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "ÁõôÞ ç åöáñìïãÞ áðåãêáôÜóôáóçò áðáéôåß ðñüóâáóç äéá÷åéñéóôÞ, äïêéìÜóôå îáíÜ"
StrCpy $INIT_UNINSTALLER_RUNNING "Ç åöáñìïãÞ áðåãêáôÜóôáóçò ëåéôïõñãåß Þäç."
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 $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Wybierz sposób utrzymywania."
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_DetailPrint "Dodaję skrót ${APPLICATION_NAME} w Menu Start."
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 $INIT_UNINSTALLER_RUNNING "Dezinstalator już jest uruchomiony."
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 $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Выберите опцию обслуживания для исполнения."
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_DetailPrint "Добавление ярлыка ${APPLICATION_NAME} в меню Пуск"
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Ярлык на рабочем столе"
@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "Установщик уже запущен."
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Этот деинсталятор требует права администратора, попытайтесь ещё"
StrCpy $INIT_UNINSTALLER_RUNNING "Программа удаления уже выполняется."
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 $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 $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_DetailPrint "Prida<64> zástupcu pre ${APPLICATION_NAME} do menu Štart."
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 $INIT_UNINSTALLER_RUNNING "Odinštalátor je už spustený."
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 $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Välj underhålls alternativ att utföra."
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_DetailPrint "Lägger till genväg för ${APPLICATION_NAME} till Start-menyn."
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 $INIT_UNINSTALLER_RUNNING "Avinstallationsprogrammet körs redan."
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 "Spanish"
!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 FileFunc.nsh ;Used to read out parameters
!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
;-----------------------------------------------------------------------------
@ -277,50 +278,10 @@ FunctionEnd
no_process_${processName}_to_end:
!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
!insertmacro CheckAndConfirmEndProcess "${APPLICATION_EXECUTABLE}"
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
${If} ${RunningX64}
ExecWait '"$OUTDIR\vcredist_x64.exe" /install /quiet'
@ -510,17 +471,19 @@ SectionEnd
SectionIn 1 2
SetDetailsPrint textonly
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_x64.exe"
Call InstallRedistributables
Call RegisterShellExt
!insertMacro StopExplorer
!insertMacro StartExplorer ""
CreateDirectory "$INSTDIR\shellext"
${If} ${RunningX64}
!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}
!endif
@ -673,10 +636,16 @@ Section Uninstall
;Shell extension
!ifdef OPTION_SECTION_SC_SHELL_EXT
!define LIBRARY_COM
!define LIBRARY_SHELL_EXTENSION
${If} ${HasSection} SEC_SHELL_EXT
!insertmacro StopExplorer
Call Un.RegisterShellExt
!insertmacro StartExplorer "Un."
!define LIBRARY_X64
!insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCUtil_x64.dll"
!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

View file

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

View file

@ -134,23 +134,6 @@ enum csync_ftw_type_e {
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.
@ -203,6 +186,9 @@ typedef void (*csync_log_callback) (int verbosity,
const char *buffer,
void *userdata);
typedef void (*csync_update_callback) (bool local,
const char *dirUrl,
void *userdata);
/**
* @brief Allocate a csync context.

View file

@ -40,28 +40,28 @@
#define CSYNC_LOG_CATEGORY_NAME "csync.exclude"
#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;
if (ctx->excludes == NULL) {
ctx->excludes = c_strlist_new(32);
if (ctx->excludes == NULL) {
if (*inList == NULL) {
*inList = c_strlist_new(32);
if (*inList == NULL) {
return -1;
}
}
if (ctx->excludes->count == ctx->excludes->size) {
list = c_strlist_expand(ctx->excludes, 2 * ctx->excludes->size);
if ((*inList)->count == (*inList)->size) {
list = c_strlist_expand(*inList, 2 * (*inList)->size);
if (list == NULL) {
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 i = 0;
int rc = -1;
@ -70,7 +70,7 @@ int csync_exclude_load(CSYNC *ctx, const char *fname) {
char *entry = NULL;
mbchar_t *w_fname;
if (ctx == NULL || fname == NULL) {
if (fname == NULL) {
return -1;
}
@ -119,7 +119,7 @@ int csync_exclude_load(CSYNC *ctx, const char *fname) {
buf[i] = '\0';
if (*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) {
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 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;
const char *p = 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(dname);
if (ctx == NULL || ctx->excludes == NULL) {
if( ! excludes ) {
goto out;
}
/* 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;
char *pattern_stored = c_strdup(ctx->excludes->vector[i]);
char *pattern_stored = c_strdup(excludes->vector[i]);
char* pattern = pattern_stored;
type = CSYNC_FILE_EXCLUDE_LIST;
@ -313,6 +328,7 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
SAFE_FREE(dname);
}
out:
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.
*/
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.
@ -65,6 +65,14 @@ void csync_exclude_destroy(CSYNC *ctx);
*/
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 */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

View file

@ -24,6 +24,8 @@
#include <inttypes.h>
#include "csync_private.h"
/*
* 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);
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",
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 ));
if (!fetchCtx) {
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);
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 */
fetchCtx = c_malloc( sizeof( struct listdir_context ));
@ -141,6 +144,14 @@ static void propfind_results_recursive_callback(void *userdata,
element->parent = NULL;
c_rbtree_insert(ctx->propfind_recursive_cache, element);
/* 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;
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 */
hdl = ne_propfind_create(ctx->dav_session.ctx, curi, depth);

View file

@ -87,6 +87,8 @@ struct csync_s {
struct {
csync_auth_callback auth_function;
void *userdata;
csync_update_callback update_callback;
void *update_callback_userdata;
} callbacks;
c_strlist_t *excludes;
@ -144,6 +146,10 @@ struct csync_s {
int read_from_db_disabled;
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;");
c_strlist_destroy(result);
/* set a busy handler with 5 seconds timeout */
sqlite3_busy_timeout(db, 5000);
#ifndef NDEBUG
sqlite3_profile(db, sqlite_profile, 0 );
#endif
@ -319,6 +322,10 @@ static int _csync_file_stat_from_metadata_table( csync_file_stat_t **st, sqlite3
REMOTE_PERM_BUF_SIZE);
}
}
} else {
if( rc != SQLITE_DONE ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "WARN: Query results in %d", 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);
if( _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_hash_stmt) < 0 ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata!");
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_hash_stmt);
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);
@ -387,8 +395,9 @@ csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx,
/* bind the query value */
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 ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata!");
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_fileid_stmt);
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.
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);
if( _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_inode_stmt) < 0 ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata by inode!");
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_inode_stmt);
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);
@ -457,7 +467,7 @@ char *csync_statedb_get_etag( CSYNC *ctx, uint64_t jHash ) {
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 rc;
@ -465,6 +475,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
int64_t cnt = 0;
char *likepath;
int asp;
int min_path_len;
if( !path ) {
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);
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;
}
@ -490,7 +501,9 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
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;

View file

@ -342,6 +342,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
}
}
} else {
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Unable to open statedb, setting inst to 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);
break;
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);
break;
default:

View file

@ -25,6 +25,8 @@
#define CSYNC_TEST 1
#include "csync_exclude.c"
#define EXCLUDE_LIST_FILE SOURCEDIR"/../sync-exclude.lst"
static void setup(void **state) {
CSYNC *csync;
int rc;
@ -42,7 +44,7 @@ static void setup_init(void **state) {
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
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);
*state = csync;
@ -66,7 +68,7 @@ static void teardown(void **state) {
static void check_csync_exclude_add(void **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/*");
}
@ -75,10 +77,11 @@ static void check_csync_exclude_load(void **state)
CSYNC *csync = *state;
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_string_equal(csync->excludes->vector[0], "*.filepart");
assert_int_not_equal(csync->excludes->count, 0);
}
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);
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);
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
*/
/* Files in the ignored dir .java will also be ignored. */
rc = csync_excluded(csync, ".apdisk/totally_amazing.jar", CSYNC_FTW_TYPE_FILE);
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. */
rc = csync_excluded(csync, ".netscape/cache", CSYNC_FTW_TYPE_FILE);
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/activity.png</file>
<file>resources/network.png</file>
<file>resources/owncloud_logo_blue.png</file>
<file>resources/lock-http.png</file>
<file>resources/lock-https.png</file>
</qresource>

View file

@ -1,11 +1,11 @@
if(APPLE)
add_custom_target( mac_overlayplugin ALL
xcodebuild -workspace ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/LiferayNativity.xcworkspace
-scheme LiferayNativity.osax SYMROOT=${CMAKE_CURRENT_BINARY_DIR} archive
xcodebuild -workspace ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloud.xcworkspace
-scheme OwnCloudFinder.osax SYMROOT=${CMAKE_CURRENT_BINARY_DIR} archive
COMMENT building Mac Overlay iccons)
INSTALL( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/LiferayNativity.osax/Contents
DESTINATION ${CMAKE_INSTALL_PREFIX}/Library/ScriptingAdditions/LiferayNativity.osax/ )
INSTALL( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/OwnCloudFinder.osax/Contents
DESTINATION ${CMAKE_INSTALL_PREFIX}/Library/ScriptingAdditions/OwnCloudFinder.osax/ )
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
{
NSLog(@"LiferayNativityFinder: refreshing icon badges failed");
NSLog(@"OwnCloudFinder: refreshing icon badges failed");
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)
+ (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];
@ -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];

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)
- (void)IconOverlayHandlers_drawIconWithFrame:(struct CGRect)arg1;
- (void)IconOverlayHandlers_drawImage:(id)arg1;
- (void)IconOverlayHandlers_drawRect:(struct CGRect)arg1;
- (void)OCIconOverlayHandlers_drawIconWithFrame:(struct CGRect)arg1;
- (void)OCIconOverlayHandlers_drawImage:(id)arg1;
- (void)OCIconOverlayHandlers_drawRect:(struct CGRect)arg1;
@end

View file

@ -22,7 +22,7 @@
- (void)IconOverlayHandlers_drawIconWithFrame:(struct CGRect)arg1
{
[self IconOverlayHandlers_drawIconWithFrame:arg1];
[self OCIconOverlayHandlers_drawIconWithFrame:arg1];
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;
FINode* node = (FINode*)[realSelf representedItem];
@ -91,14 +91,18 @@
if (iconimage != nil)
{
CGImageSourceRef source;
NSData* data = [iconimage TIFFRepresentation];
CGRect destRect = CGRectMake(0, 0, [icon size].width, [icon size].height);
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];
@ -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];

View file

@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrincipalClass</key>
<string>FinderHook</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
@ -11,7 +9,7 @@
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.liferay.nativity</string>
<string>com.owncloud.finder</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@ -42,5 +40,7 @@
</dict>
<key>CFPlugInUnloadFunction</key>
<string></string>
<key>NSPrincipalClass</key>
<string>FinderHook</string>
</dict>
</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; };
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>"; };
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>"; };
/* End PBXFileReference section */
@ -67,7 +67,7 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
089C166AFE841209C02AAC07 /* LiferayNativityFinder */ = {
089C166AFE841209C02AAC07 /* OwnCloudFinder */ = {
isa = PBXGroup;
children = (
08FB77AFFE84173DC02AAC07 /* Source */,
@ -75,7 +75,7 @@
089C1671FE841209C02AAC07 /* External Frameworks and Libraries */,
19C28FB6FE9D52B211CA2CBB /* Products */,
);
name = LiferayNativityFinder;
name = OwnCloudFinder;
sourceTree = "<group>";
usesTabs = 1;
};
@ -152,7 +152,7 @@
19C28FB6FE9D52B211CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
8D576316048677EA00EA77CD /* LiferayNativityFinder.bundle */,
8D576316048677EA00EA77CD /* OwnCloudFinder.bundle */,
);
name = Products;
sourceTree = "<group>";
@ -160,9 +160,9 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
8D57630D048677EA00EA77CD /* LiferayNativityFinder */ = {
8D57630D048677EA00EA77CD /* OwnCloudFinder */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "LiferayNativityFinder" */;
buildConfigurationList = 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "OwnCloudFinder" */;
buildPhases = (
8D57630F048677EA00EA77CD /* Resources */,
8D576311048677EA00EA77CD /* Sources */,
@ -172,10 +172,10 @@
);
dependencies = (
);
name = LiferayNativityFinder;
name = OwnCloudFinder;
productInstallPath = "$(HOME)/Library/Bundles";
productName = LiferayNativityFinder;
productReference = 8D576316048677EA00EA77CD /* LiferayNativityFinder.bundle */;
productName = OwnCloudFinder;
productReference = 8D576316048677EA00EA77CD /* OwnCloudFinder.bundle */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
@ -186,7 +186,7 @@
attributes = {
LastUpgradeCheck = 0460;
};
buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "LiferayNativityFinder" */;
buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "OwnCloudFinder" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
@ -196,11 +196,11 @@
French,
German,
);
mainGroup = 089C166AFE841209C02AAC07 /* LiferayNativityFinder */;
mainGroup = 089C166AFE841209C02AAC07 /* OwnCloudFinder */;
projectDirPath = "";
projectRoot = "";
targets = (
8D57630D048677EA00EA77CD /* LiferayNativityFinder */,
8D57630D048677EA00EA77CD /* OwnCloudFinder */,
);
};
/* End PBXProject section */
@ -260,7 +260,7 @@
GCC_OPTIMIZATION_LEVEL = 0;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles";
PRODUCT_NAME = LiferayNativityFinder;
PRODUCT_NAME = OwnCloudFinder;
WRAPPER_EXTENSION = bundle;
};
name = Debug;
@ -277,7 +277,7 @@
GCC_MODEL_TUNING = G5;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles";
PRODUCT_NAME = LiferayNativityFinder;
PRODUCT_NAME = OwnCloudFinder;
WRAPPER_EXTENSION = bundle;
};
name = Release;
@ -315,7 +315,7 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "LiferayNativityFinder" */ = {
1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "OwnCloudFinder" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB911B08733D790010E9CD /* Debug */,
@ -324,7 +324,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "LiferayNativityFinder" */ = {
1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "OwnCloudFinder" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB911F08733D790010E9CD /* Debug */,

View file

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

View file

@ -217,7 +217,7 @@ static RequestManager* sharedInstance = nil;
{
NSLog(@"Connect Socket!");
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"
NSLog(@"I goofed: %@", err);

View file

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

View file

@ -7,27 +7,27 @@
#define WAIT_FOR_APPLE_EVENT_TO_ENTER_HANDLER_IN_SECONDS 1.0
#define FINDER_MIN_TESTED_VERSION @"10.7"
#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);
static NSString* globalLock = @"I'm the global lock to prevent concruent handler executions";
// SIMBL-compatible interface
@interface LiferayNativityShell : NSObject { }
@interface OwnCloudShell : NSObject { }
-(void) install;
-(void) uninstall;
@end
// just a dummy class for locating our bundle
@interface LiferayNativityInjector : NSObject { }
@interface OwnCloudInjector : NSObject { }
@end
@implementation LiferayNativityInjector { }
@implementation OwnCloudInjector { }
@end
static bool liferayNativityLoaded = false;
static NSString* liferayNativityBundleName = @"LiferayNativityFinder";
static NSString* liferayNativityBundleName = @"OwnCloudFinder";
typedef struct {
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"];
NSBundle* pluginBundle = [NSBundle bundleWithPath:liferayNativityLocation];
if (!pluginBundle) {
@ -182,11 +182,11 @@ static LNBundleType mainBundleType(AppleEvent* reply) {
EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refcon) {
@synchronized(globalLock) {
@autoreleasepool {
NSBundle* injectorBundle = [NSBundle bundleForClass:[LiferayNativityInjector class]];
NSBundle* injectorBundle = [NSBundle bundleForClass:[OwnCloudInjector class]];
NSString* injectorVersion = [injectorBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
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;
}
@ -206,7 +206,7 @@ EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refco
return noErr;
} @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;
@ -232,13 +232,13 @@ EXPORT OSErr HandleUnloadEvent(const AppleEvent* ev, AppleEvent* reply, long ref
@autoreleasepool {
@try {
if (!liferayNativityLoaded) {
NSLog(@"LiferayNativityInjector: not loaded.");
NSLog(@"OwnCloudInjector: not loaded.");
return noErr;
}
NSString* bundleName = liferayNativityBundleName;
NSBundle* liferayNativityInjectorBundle = [NSBundle bundleForClass:[LiferayNativityInjector class]];
NSBundle* liferayNativityInjectorBundle = [NSBundle bundleForClass:[OwnCloudInjector class]];
NSString* liferayNativityLocation = [liferayNativityInjectorBundle pathForResource:bundleName ofType:@"bundle"];
NSBundle* pluginBundle = [NSBundle bundleWithPath:liferayNativityLocation];
if (!pluginBundle) {
@ -261,7 +261,7 @@ EXPORT OSErr HandleUnloadEvent(const AppleEvent* ev, AppleEvent* reply, long ref
return noErr;
} @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;

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

View file

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

View file

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

View file

@ -1,8 +1,14 @@
#!/bin/sh
# osascript $HOME/owncloud.com/mirall/shell_integration/MacOSX/unload.scpt
sudo rm -rf /Library/ScriptingAdditions/LiferayNativity.osax
sudo cp -r $HOME/Library/Developer/Xcode/DerivedData/LiferayNativity-gvtginoclfyisuagangtxsfbuztw/Build/Products/Debug/LiferayNativity.osax /Library/ScriptingAdditions/
sudo rm -rf /Library/ScriptingAdditions/OwnCloudFinder.osax
# 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
sleep 1

View file

@ -11,26 +11,47 @@ class ownCloudExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoP
nautilusVFSFile_table = {}
registered_paths = {}
remainder = ''
connected = False
watch_id = 0
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect(("localhost", 33001))
self.sock.settimeout(5)
GObject.io_add_watch(self.sock, GObject.IO_IN, self.handle_notify)
self.connectToOwnCloud
if not self.connected:
# try again in 5 seconds - attention, logic inverted!
GObject.timeout_add(5000, self.connectToOwnCloud)
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):
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 ):
if path in self.nautilusVFSFile_table:
return self.nautilusVFSFile_table[path]
else:
return None
def callback_update_file( self, path ):
print "Got an update callback for " + path
def askForOverlay(self, file):
if os.path.isdir(file):
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):
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
def handle_server_response(self, l):
Emblems = { 'OK' : 'oC_ok',
@ -66,16 +98,27 @@ class ownCloudExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoP
item = self.find_item_for_file(parts[2])
if item:
item.add_emblem(emblem)
elif action == 'UPDATE_VIEW':
# Search all items underneath this path and invalidate them
if parts[1] in self.registered_paths:
for p in self.nautilusVFSFile_table:
if p.startswith( parts[1] ):
item = self.nautilusVFSFile_table[p]
item.invalidate_extension_info()
self.update_file_info(item)
self.invalidate_items_underneath( parts[1] )
elif action == 'REGISTER_PATH':
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:
# print "We got unknown action " + action
1
@ -106,8 +149,6 @@ class ownCloudExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoP
def get_local_path(self, path):
return path.replace("file://", "")
def update_file_info(self, item):
if item.get_uri_scheme() != 'file':
return

View file

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

View file

@ -24,7 +24,8 @@ HRESULT OCOverlayRegistrationHandler::MakeRegistryEntries(const CLSID& clsid, PC
{
HRESULT hResult;
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)) {
hResult = RegCreateKey(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, &shellOverlayKey);
if(!SUCCEEDED(hResult)) {
@ -69,7 +70,7 @@ HRESULT OCOverlayRegistrationHandler::RemoveRegistryEntries(PCWSTR friendlyName)
return hResult;
}
HRESULT OCOverlayRegistrationHandler::RegisterCOMObject(PCWSTR modulePath, const CLSID& clsid)
HRESULT OCOverlayRegistrationHandler::RegisterCOMObject(PCWSTR modulePath, PCWSTR friendlyName, const CLSID& clsid)
{
if (modulePath == NULL) {
return E_FAIL;
@ -91,14 +92,15 @@ HRESULT OCOverlayRegistrationHandler::RegisterCOMObject(PCWSTR modulePath, const
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegSetValue(clsidKey, NULL, REG_SZ, friendlyName, (DWORD) wcslen(friendlyName)));
HKEY 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)) {
return hResult;
}
DWORD cbData = lstrlen(modulePath) * sizeof(*modulePath);
hResult = HRESULT_FROM_WIN32(RegSetValue(inprocessKey, NULL, REG_SZ, modulePath, cbData));
hResult = HRESULT_FROM_WIN32(RegSetValue(inprocessKey, NULL, REG_SZ, modulePath, (DWORD) wcslen(modulePath)));
if(!SUCCEEDED(hResult)) {
return hResult;

View file

@ -23,7 +23,7 @@ class __declspec(dllexport) OCOverlayRegistrationHandler
{
public:
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 UnregisterCOMObject(const CLSID& clsid);
};

View file

@ -22,14 +22,17 @@
#define OVERLAY_GUID_WARNING L"{0960F096-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_WARNING_SHARED L"{0960F097-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_NAME_ERROR L"OCError"
#define OVERLAY_NAME_ERROR_SHARED L"OCErrorShared"
#define OVERLAY_NAME_OK L"OCOK"
#define OVERLAY_NAME_OK_SHARED L"OCOKShared"
#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 OVERLAY_GENERIC_NAME L"OC Overlay Handler"
// two spaces to put us a head of the competition :/
#define OVERLAY_NAME_ERROR L" OCError"
#define OVERLAY_NAME_ERROR_SHARED L" OCErrorShared"
#define OVERLAY_NAME_OK L" OCOK"
#define OVERLAY_NAME_OK_SHARED L" OCOKShared"
#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_CLSID L"CLSID"
@ -44,4 +47,4 @@
#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
mirall/discoveryphase.cpp
mirall/selectivesyncdialog.cpp
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)

View file

@ -26,6 +26,7 @@
#include "ignorelisteditor.h"
#include "account.h"
#include "quotainfo.h"
#include "selectivesyncdialog.h"
#include "creds/abstractcredentials.h"
#include <math.h>
@ -77,6 +78,7 @@ AccountSettings::AccountSettings(QWidget *parent) :
ui->_buttonRemove->setEnabled(false);
ui->_buttonEnable->setEnabled(false);
ui->_buttonSelectiveSync->setEnabled(false);
ui->_buttonAdd->setEnabled(true);
QAction *resetFolderAction = new QAction(this);
@ -92,6 +94,7 @@ AccountSettings::AccountSettings(QWidget *parent) :
connect(ui->_buttonRemove, SIGNAL(clicked()), this, SLOT(slotRemoveCurrentFolder()));
connect(ui->_buttonEnable, SIGNAL(clicked()), this, SLOT(slotEnableCurrentFolder()));
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->ignoredFilesButton, SIGNAL(clicked()), SLOT(slotIgnoreFilesEditor()));;
@ -111,9 +114,13 @@ AccountSettings::AccountSettings(QWidget *parent) :
this, SLOT(slotAccountChanged(Account*,Account*)));
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)));
setFolderList(FolderMan::instance()->map());
slotSyncStateChange();
}
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->quotaInfo(), SIGNAL(quotaUpdated(qint64,qint64)),
this, SLOT(slotUpdateQuota(qint64,qint64)));
disconnect(oldAccount, SIGNAL(stateChanged(int)), this, SLOT(slotAccountStateChanged(int)));
}
_account = newAccount;
@ -150,12 +158,14 @@ void AccountSettings::slotFolderActivated( const QModelIndex& indx )
} else {
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->_buttonSelectiveSync->setEnabled(isConnected && isValid);
if ( isValid ) {
bool folderEnabled = _model->data( indx, FolderStatusDelegate::FolderSyncEnabled).toBool();
if ( folderEnabled ) {
bool folderPaused = _model->data( indx, FolderStatusDelegate::FolderSyncPaused).toBool();
if ( !folderPaused) {
ui->_buttonEnable->setText( tr( "Pause" ) );
} else {
ui->_buttonEnable->setText( tr( "Resume" ) );
@ -189,10 +199,13 @@ void AccountSettings::slotFolderWizardAccepted()
QString alias = folderWizard->field(QLatin1String("alias")).toString();
QString sourceFolder = folderWizard->field(QLatin1String("sourceFolder")).toString();
QString targetPath = folderWizard->property("targetPath").toString();
QStringList selectiveSyncBlackList
= folderWizard->property("selectiveSyncBlackList").toStringList();
if (!FolderMan::ensureJournalGone( sourceFolder ))
return;
folderMan->addFolderDefinition(alias, sourceFolder, targetPath );
folderMan->addFolderDefinition(alias, sourceFolder, targetPath, selectiveSyncBlackList );
Folder *f = folderMan->setupFolderFromConfigFile( alias );
slotAddFolder( f );
folderMan->setSyncEnabled(true);
@ -222,7 +235,11 @@ void AccountSettings::slotAddFolder( Folder *folder )
if( ! folder || folder->alias().isEmpty() ) return;
QStandardItem *item = new QStandardItem();
folderToModelItem( item, folder );
bool isConnected = false;
if (_account) {
isConnected = (_account->state() == Account::Connected);
}
folderToModelItem( item, folder, isConnected);
_model->appendRow( item );
// in order to update the enabled state of the "Sync now" button
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;
item->setData( f->nativePath(), FolderStatusDelegate::FolderPathRole );
item->setData( f->remotePath(), FolderStatusDelegate::FolderSecondPathRole );
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::Status status = res.status();
@ -260,35 +277,39 @@ void AccountSettings::folderToModelItem( QStandardItem *item, Folder *f )
Theme *theme = Theme::instance();
item->setData( theme->statusHeaderText( status ), Qt::ToolTipRole );
if( f->syncEnabled() ) {
if( status == SyncResult::SyncPrepare ) {
if( _wasDisabledBefore ) {
// 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 );
if ( accountConnected ) {
if( f->syncPaused() ) {
item->setData( theme->folderDisabledIcon( ), FolderStatusDelegate::FolderStatusIconRole ); // size 48 before
_wasDisabledBefore = false;
} else {
// kepp the previous icon for the prepare phase.
if( status == SyncResult::Problem) {
item->setData( theme->syncStateIcon( SyncResult::Success), FolderStatusDelegate::FolderStatusIconRole );
if( status == SyncResult::SyncPrepare ) {
if( _wasDisabledBefore ) {
// 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 {
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 {
item->setData( theme->folderDisabledIcon( ), FolderStatusDelegate::FolderStatusIconRole ); // size 48 before
_wasDisabledBefore = false;
item->setData( theme->folderOfflineIcon(), FolderStatusDelegate::FolderStatusIconRole);
}
item->setData( theme->statusHeaderText( status ), FolderStatusDelegate::FolderStatus );
if( errorList.isEmpty() ) {
if( (status == SyncResult::Error ||
status == SyncResult::SetupError ||
status == SyncResult::SyncAbortRequested ||
status == SyncResult::Unavailable)) {
status == SyncResult::SyncAbortRequested )) {
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 )
{
if( ! indx.isValid() ) return;
@ -422,57 +457,60 @@ void AccountSettings::slotEnableCurrentFolder()
if( selected.isValid() ) {
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;
bool terminate = false;
// 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 );
if( alias.isEmpty() ) {
qDebug() << "Empty alias to enable.";
return;
}
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 ) {
folderToModelItem( item, folder );
folderToModelItem( item, folder, _account->state() == Account::Connected );
} else {
// the dialog is not visible.
}
@ -564,6 +602,14 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
QStandardItem *item = itemForFolder( folder );
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()
&& Progress::isWarningKind(progress._lastCompletedItem._status)) {
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 kindString = Progress::asActionString(curItem);
// switch on extra space.
item->setData( QVariant(true), FolderStatusDelegate::AddProgressSpace );
QString fileProgressString;
if (Progress::isSizeDependent(curItem._instruction)) {
@ -730,6 +775,11 @@ void AccountSettings::slotAccountStateChanged(int state)
QUrl safeUrl(_account->url());
safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI
slotButtonsSetEnabled();
FolderMan *folderMan = FolderMan::instance();
foreach (Folder *folder, folderMan->map().values()) {
slotUpdateFolderState(folder);
}
slotSyncStateChange();
if (state == Account::Connected) {
QString user;
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()
{
delete ui;

View file

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

View file

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

View file

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

View file

@ -54,7 +54,7 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP
, _path(path)
, _remotePath(secondPath)
, _alias(alias)
, _enabled(true)
, _paused(false)
, _csyncError(false)
, _csyncUnavail(false)
, _wipeDb(false)
@ -215,14 +215,14 @@ QString Folder::nativePath() const
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 ) {
// qDebug() << "Syncing enabled on folder " << name();
@ -260,6 +260,7 @@ void Folder::slotPollTimerTimeout()
qDebug() << "** Force Sync now, state is " << _syncResult.statusString();
emit scheduleToSync(alias());
} else {
// do the ordinary etag chech for the root folder.
RequestEtagJob* job = new RequestEtagJob(AccountManager::instance()->account(), remotePath(), this);
// check if the etag is different
QObject::connect(job, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
@ -287,7 +288,6 @@ void Folder::slotNetworkUnavailable()
if (account && account->state() == Account::Connected) {
account->setState(Account::Disconnected);
}
_syncResult.setStatus(SyncResult::Unavailable);
emit syncStateChange();
}
@ -483,7 +483,7 @@ void Folder::slotTerminateSync()
// Do not display an error message, user knows his own actions.
// _errors.append( tr("The CSync thread terminated.") );
// _csyncError = true;
setSyncEnabled(false);
FolderMan::instance()->slotSetFolderPaused(alias(), true);
setSyncState(SyncResult::SyncAbortRequested);
return;
}
@ -592,10 +592,12 @@ void Folder::startSync(const QStringList &pathList)
//direct connection so the message box is blocking the sync.
connect(_engine.data(), SIGNAL(aboutToRemoveAllFiles(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(jobCompleted(SyncFileItem)), this, SLOT(slotJobCompleted(SyncFileItem)));
setDirtyNetworkLimits();
_engine->setSelectiveSyncBlackList(selectiveSyncBlackList());
QMetaObject::invokeMethod(_engine.data(), "startSync", Qt::QueuedConnection);
@ -662,7 +664,8 @@ void Folder::slotSyncFinished()
_syncResult.setErrorStrings( _errors );
qDebug() << " * owncloud csync thread finished with error";
} else if (_csyncUnavail) {
_syncResult.setStatus(SyncResult::Unavailable);
_syncResult.setStatus(SyncResult::Error);
qDebug() << " ** csync not available.";
} else if( _syncResult.warnCount() > 0 ) {
// there have been warnings on the way.
_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
// 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
* be called.
*/
void setSyncEnabled( bool );
void setSyncPaused( bool );
bool syncEnabled() const;
bool syncPaused() const;
void prepareToSync();
@ -121,6 +121,10 @@ public:
SyncJournalDb *journalDb() { return &_journal; }
CSYNC *csyncContext() { return _csync_ctx; }
QStringList selectiveSyncBlackList() { return _selectiveSyncBlackList; }
void setSelectiveSyncBlackList(const QStringList &blackList)
{ _selectiveSyncBlackList = blackList; }
signals:
void syncStateChange();
@ -157,6 +161,7 @@ private slots:
void slotCsyncUnavailable();
void slotSyncFinished();
void slotFolderDiscovered(bool local, QString folderName);
void slotTransmissionProgress(const Progress::Info& pi);
void slotJobCompleted(const SyncFileItem&);
@ -184,10 +189,11 @@ private:
QString _remotePath;
QString _alias;
QString _configFile;
bool _enabled;
bool _paused;
SyncResult _syncResult;
QScopedPointer<SyncEngine> _engine;
QStringList _errors;
QStringList _selectiveSyncBlackList;
bool _csyncError;
bool _csyncUnavail;
bool _wipeDb;

View file

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

View file

@ -50,7 +50,8 @@ public:
* QString sourceFolder on local machine
* 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 */
Folder* folderForPath(const QString& path);
@ -77,17 +78,23 @@ public:
/** Creates a new and empty local directory. */
bool startFromScratch( const QString& );
QString statusToString( SyncResult, bool enabled ) const;
QString statusToString(SyncResult, bool paused ) const;
static SyncResult accountStatus( const QList<Folder*> &folders );
void removeMonitorPath( 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:
/**
* 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.
*
* Attention: The alias string may be zero. Do a general update of the state than.
*/
void folderSyncStateChange( const QString & );
@ -95,7 +102,7 @@ signals:
public slots:
void slotRemoveFolder( const QString& );
void slotEnableFolder( const QString&, bool );
void slotSetFolderPaused(const QString&, bool paused);
void slotFolderSyncStarted();
void slotFolderSyncFinished( const SyncResult& );
@ -131,9 +138,6 @@ private:
QString getBackupName( const QString& ) const;
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;
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));
int warningCount = qvariant_cast<int>(index.data(WarningCount));
bool syncOngoing = qvariant_cast<bool>(index.data(SyncRunning));
// 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" );
QRect iconRect = option.rect;
@ -246,7 +247,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
h += aliasMargin;
// 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 barHeight = qMax(fileNameTextHeight, aliasFm.height()+4); ;
int overallWidth = option.rect.width()-2*aliasMargin;

View file

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

View file

@ -18,6 +18,7 @@
#include "theme.h"
#include "networkjobs.h"
#include "account.h"
#include "selectivesyncdialog.h"
#include <QDebug>
#include <QDesktopServices>
@ -30,6 +31,7 @@
#include <QValidator>
#include <QWizardPage>
#include <QTreeWidget>
#include <QVBoxLayout>
#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
*/
@ -431,7 +477,8 @@ void FolderWizardRemotePath::showWarn( const QString& msg ) const
FolderWizard::FolderWizard( QWidget *parent )
: QWizard(parent),
_folderWizardSourcePage(new FolderWizardLocalPath),
_folderWizardTargetPage(0)
_folderWizardTargetPage(0),
_folderWizardSelectiveSyncPage(new FolderWizardSelectiveSync)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setPage(Page_Source, _folderWizardSourcePage );
@ -439,6 +486,7 @@ FolderWizard::FolderWizard( QWidget *parent )
_folderWizardTargetPage = new FolderWizardRemotePath();
setPage(Page_Target, _folderWizardTargetPage );
}
setPage(Page_SelectiveSync, _folderWizardSelectiveSyncPage);
setWindowTitle( tr("Add Folder") );
setOptions(QWizard::CancelButtonOnLeft);

View file

@ -26,6 +26,8 @@
namespace Mirall {
class SelectiveSyncTreeView;
class ownCloudInfo;
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 {
Page_Source,
Page_Target
Page_Target,
Page_SelectiveSync
};
FolderWizard(QWidget *parent = 0);
@ -110,6 +132,7 @@ private:
FolderWizardLocalPath *_folderWizardSourcePage;
FolderWizardRemotePath *_folderWizardTargetPage;
FolderWizardSelectiveSync *_folderWizardSelectiveSyncPage;
};

View file

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

View file

@ -54,7 +54,9 @@ ownCloudGui::ownCloudGui(Application *parent) :
{
_tray = new Systray();
_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)),
SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason)));
@ -97,7 +99,7 @@ ownCloudGui::ownCloudGui(Application *parent) :
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"
" try\n"
" «event NVTYload»\n"
@ -164,12 +166,12 @@ void ownCloudGui::slotSyncStateChange( const QString& alias )
slotComputeOverallSyncStatus();
if( alias.isEmpty() ) {
return; // Valid, just a general GUI redraw was needed.
}
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) {
Logger::instance()->enterNextLogFile();
}
@ -199,25 +201,28 @@ void ownCloudGui::startupConnected( bool connected, const QStringList& fails )
if( connected ) {
qDebug() << "######## connected to ownCloud Server!";
folderMan->setSyncEnabled(true);
_tray->setIcon( Theme::instance()->syncStateIcon( SyncResult::NotYetStarted, true ) );
_tray->show();
// _tray->setIcon( Theme::instance()->syncStateIcon( SyncResult::NotYetStarted, true ) );
// _tray->show();
}
_startupFails = fails; // store that for the settings dialog once it appears.
if( !_settingsDialog.isNull() )
if( !_settingsDialog.isNull() ) {
_settingsDialog->setGeneralErrors( _startupFails );
}
slotComputeOverallSyncStatus();
}
void ownCloudGui::slotComputeOverallSyncStatus()
{
if (Account *a = AccountManager::instance()->account()) {
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"));
return;
}
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"));
return;
}
@ -249,7 +254,7 @@ void ownCloudGui::slotComputeOverallSyncStatus()
QStringList allStatusStrings;
foreach(Folder* folder, map.values()) {
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);
}
@ -261,6 +266,16 @@ void ownCloudGui::slotComputeOverallSyncStatus()
QIcon statusIcon = Theme::instance()->syncStateIcon( overallResult.status(), true);
_tray->setIcon( statusIcon );
_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);
QString totalSizeStr = Utility::octetsToString( progress._totalSize );
if(progress._totalSize == 0 ) {
if (!progress._currentDiscoveredFolder.isEmpty()) {
_actionStatus->setText( tr("Discovering %1")
.arg( progress._currentDiscoveredFolder ));
} else if (progress._totalSize == 0 ) {
quint64 currentFile = progress._completedFileCount + progress._currentItems.count();
_actionStatus->setText( tr("Syncing %1 of %2 (%3 left)")
.arg( currentFile ).arg( progress._totalFileCount )
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) );
} else {
QString totalSizeStr = Utility::octetsToString( progress._totalSize );
_actionStatus->setText( tr("Syncing %1 (%2 left)")
.arg( totalSizeStr )
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) );
@ -491,7 +509,8 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const Progress::Info
slotRebuildRecentMenus();
}
if (progress._completedFileCount == progress._totalFileCount) {
if (progress._completedFileCount == progress._totalFileCount
&& progress._currentDiscoveredFolder.isEmpty()) {
QTimer::singleShot(2000, this, SLOT(slotDisplayIdle()));
}
}

View file

@ -74,11 +74,8 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent) :
NetworkSettings *networkSettings = new 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(accountIconChanged(QIcon)), SLOT(slotUpdateAccountIcon(QIcon)));
connect( _accountSettings, SIGNAL(openFolderAlias(const QString&)),
gui, SLOT(slotFolderOpenAction(QString)));
@ -130,22 +127,7 @@ void SettingsDialog::addAccount(const QString &title, QWidget *widget)
_accountItem->setSizeHint(QSize(0, 32));
_ui->labelWidget->addItem(_accountItem);
_ui->stack->addWidget(widget);
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);
}
}
_accountSettings->slotSyncStateChange();
}
void SettingsDialog::setGeneralErrors(const QStringList &errors)
@ -168,6 +150,11 @@ void SettingsDialog::accept() {
QDialog::accept();
}
void SettingsDialog::slotUpdateAccountIcon(const QIcon &icon)
{
_accountItem->setIcon(icon);
}
void SettingsDialog::showActivityPage()
{
_ui->labelWidget->setCurrentRow(_protocolIdx);

View file

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

View file

@ -43,12 +43,12 @@ enum csync_exclude_type_e {
};
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 {
const int PORT = 33001;
const int PORT = 34001;
}
namespace Mirall {
@ -57,7 +57,7 @@ namespace Mirall {
namespace SocketApiHelper {
SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName );
SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName, c_strlist_t *excludes );
/**
* @brief recursiveFolderStatus
@ -70,7 +70,7 @@ SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName );
*/
// compute the file status of a directory recursively. It returns either
// "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);
@ -84,14 +84,14 @@ SyncFileStatus recursiveFolderStatus(Folder *folder, const QString& fileName )
SyncFileStatus sfs;
if( fi.isDir() ) {
sfs = recursiveFolderStatus(folder, normalizedFile );
sfs = recursiveFolderStatus(folder, normalizedFile, excludes );
} else {
QString fs( normalizedFile );
if( fileName.isEmpty() ) {
// toplevel, no slash etc. needed.
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 ) {
@ -106,7 +106,7 @@ SyncFileStatus recursiveFolderStatus(Folder *folder, const QString& fileName )
/**
* 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
@ -142,7 +142,8 @@ SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName )
// '\' is ignored, so convert to unix path before passing the path in.
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 ) {
return SyncFileStatus(SyncFileStatus::STATUS_IGNORE);
}
@ -157,7 +158,7 @@ SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName )
SyncFileStatus status(SyncFileStatus::STATUS_NONE);
if( type == CSYNC_FTW_TYPE_DIR ) {
// compute recursive status of the directory
status = recursiveFolderStatus( folder, fileName );
status = recursiveFolderStatus( folder, fileName, excludes );
} else if(fi.lastModified() != rec._modtime ) {
// file was locally modified.
status.set(SyncFileStatus::STATUS_EVAL);
@ -179,6 +180,7 @@ SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName )
SocketApi::SocketApi(QObject* parent)
: QObject(parent)
, _localServer(new QTcpServer(this))
, _excludes(0)
{
// setup socket
DEBUG << "Establishing SocketAPI server at" << PORT;
@ -197,6 +199,28 @@ SocketApi::~SocketApi()
{
DEBUG << "dtor";
_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()
@ -261,7 +285,7 @@ void SocketApi::slotUnregisterPath( const QString& alias )
{
Folder *f = FolderMan::instance()->folder(alias);
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;
QString localMessage = message;
@ -312,13 +336,16 @@ void SocketApi::sendMessage(QTcpSocket *socket, const QString& message)
localMessage.append(QLatin1Char('\n'));
}
qint64 sent = socket->write(localMessage.toUtf8());
if( doWait ) {
socket->waitForBytesWritten(1000);
}
if( sent != localMessage.toUtf8().length() ) {
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);
@ -333,7 +360,7 @@ void SocketApi::broadcastMessage( const QString& verb, const QString& path, cons
DEBUG << "Broadcasting to" << _listeners.count() << "listeners: " << msg;
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");
} else {
const QString file = argument.mid(syncFolder->path().length());
SyncFileStatus fileStatus = SocketApiHelper::fileStatus(syncFolder, file);
SyncFileStatus fileStatus = SocketApiHelper::fileStatus(syncFolder, file, _excludes);
statusString = fileStatus.toSocketAPIString();
}

View file

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

View file

@ -53,6 +53,14 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr
} else {
_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;
// Blacklisting

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