Comparar commits
49 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 098b603879 | |||
| 7c3b3d648b | |||
| 778aca386c | |||
| 0758b2cf61 | |||
| d7804d8df3 | |||
| 3d9d106bb1 | |||
| 15dc3408ef | |||
| 928643f597 | |||
| 7110091fdd | |||
| 064c2b678a | |||
| e58739de00 | |||
| 7c2fdee78b | |||
| 7bfe46962f | |||
| 32b3023a8e | |||
| a5df44c757 | |||
| 641125eac1 | |||
| d340017a0a | |||
| a67173610d | |||
| e833d01288 | |||
| 3047682223 | |||
| c91dd94728 | |||
| 52f9f44b51 | |||
| 49748191a9 | |||
| e6b937f508 | |||
| 31c13f74fb | |||
| be466b47b7 | |||
| 11b144957b | |||
| 817e97c148 | |||
| 29932004ae | |||
| 6d83e841a9 | |||
| b43a9421d2 | |||
| e70b78d14b | |||
| 6814342d1f | |||
| 68126dcff6 | |||
| e7f00339e6 | |||
| a36b4ec863 | |||
| 074f8eadb1 | |||
| 6a51ae5b1b | |||
| af5f2d3860 | |||
| 38bad564a0 | |||
| c2fa3fb4c8 | |||
| f7082ee3df | |||
| f7c6efb391 | |||
| 051a348afd | |||
| d0af3ede05 | |||
| 0da2adcbe0 | |||
| 07bdd519e9 | |||
| 0829a94c92 | |||
| ce6a365328 |
@@ -151,6 +151,11 @@ endif()
|
||||
|
||||
find_package(ZLIB)
|
||||
|
||||
find_package(LibsnoreQt5 0.6.0)
|
||||
if(LibsnoreQt5_FOUND)
|
||||
find_package(LibsnoreSettingsQt5)
|
||||
endif()
|
||||
|
||||
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
configure_file(test/test_journal.db "${CMAKE_BINARY_DIR}/test/test_journal.db" COPYONLY)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Patches used
|
||||
|
||||
There are our patches on top of Qt 5.4.0, which we are currently
|
||||
using for our binary packages on Windows and Mac OS. Most of them
|
||||
using for our binary packages on Windows and Mac OS X. Most of them
|
||||
have been sent upstream and are part of newer Qt releases.
|
||||
|
||||
All changes are designed to up upstream, and all those that are
|
||||
@@ -28,18 +28,26 @@ purpose is outlined in each patches' front matter.
|
||||
* 0007-X-Network-Fix-up-previous-corruption-patch.patch
|
||||
* 0008-QNAM-Fix-reply-deadlocks-on-server-closing-connectio.patch
|
||||
* 0014-Fix-SNI-for-TlsV1_0OrLater-TlsV1_1OrLater-and-TlsV1_.patch
|
||||
* 0016-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch
|
||||
* 0011-Make-sure-to-report-correct-NetworkAccessibility.patch
|
||||
|
||||
### Upstreamed but not in any release yet (as of 2015-11-16)
|
||||
### Part of Qt v5.5.2 (UNRELEASED!)
|
||||
* 0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch
|
||||
* 0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch
|
||||
* 0012-Make-sure-networkAccessibilityChanged-is-emitted.patch
|
||||
|
||||
### Part of Qt v5.6 and later
|
||||
* 0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch
|
||||
* 0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch
|
||||
* 0011-Make-sure-to-report-correct-NetworkAccessibility.patch
|
||||
* 0012-Make-sure-networkAccessibilityChanged-is-emitted.patch
|
||||
* 0013-Make-UnknownAccessibility-not-block-requests.patch
|
||||
* 0015-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch
|
||||
* 0016-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch
|
||||
* 0019-Ensure-system-tray-icon-is-prepared-even-when-menu-bar.patch
|
||||
|
||||
### Not submitted to be part of any release:
|
||||
### Part of Qt 5.7 and later
|
||||
* 0015-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch
|
||||
|
||||
### Not submitted upstream to be part of any release:
|
||||
* 0006-Fix-force-debug-info-with-macx-clang_NOUPSTREAM.patch
|
||||
This is only needed if you intent to harvest debugging symbols
|
||||
for breakpad.
|
||||
|
||||
+1
-1
Submodule binary updated: ac42257499...a56480559d
@@ -620,7 +620,6 @@ Section Uninstall
|
||||
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCOverlays_x64.dll"
|
||||
!insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCUtil_x64.dll"
|
||||
!undef LIBRARY_X64
|
||||
${Else}
|
||||
DetailPrint "Uninstalling x86 overlay DLLs"
|
||||
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCContextMenu_x86.dll"
|
||||
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCOverlays_x86.dll"
|
||||
|
||||
@@ -59,14 +59,10 @@ int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags) {
|
||||
#include <shlwapi.h>
|
||||
int csync_fnmatch(const char *pattern, const char *name, int flags) {
|
||||
BOOL match;
|
||||
mbchar_t *mbname = c_utf8_path_to_locale(name);
|
||||
mbchar_t *mbpatt = c_utf8_path_to_locale(pattern);
|
||||
|
||||
(void) flags;
|
||||
|
||||
match = PathMatchSpecW(mbname, mbpatt);
|
||||
c_free_locale_string(mbname);
|
||||
c_free_locale_string(mbpatt);
|
||||
match = PathMatchSpecA(name, pattern);
|
||||
|
||||
if(match)
|
||||
return 0;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
* than fmmatch anyway, which does not care for flags.
|
||||
**/
|
||||
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
|
||||
#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
#endif
|
||||
|
||||
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags);
|
||||
|
||||
@@ -297,7 +297,10 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
// zero size in statedb can happen during migration
|
||||
|| (tmp->size != 0 && fs->size != tmp->size))) {
|
||||
|
||||
if (fs->size == tmp->size && tmp->checksumTypeId) {
|
||||
// Checksum comparison at this stage is only enabled for .eml files,
|
||||
// check #4754 #4755
|
||||
bool isEmlFile = csync_fnmatch("*.eml", file, FNM_CASEFOLD) == 0;
|
||||
if (isEmlFile && fs->size == tmp->size && tmp->checksumTypeId) {
|
||||
if (ctx->callbacks.checksum_hook) {
|
||||
st->checksum = ctx->callbacks.checksum_hook(
|
||||
file, tmp->checksumTypeId,
|
||||
|
||||
@@ -230,8 +230,10 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
ULARGE_INTEGER FileIndex;
|
||||
mbchar_t *wuri = c_utf8_path_to_locale( uri );
|
||||
|
||||
h = CreateFileW( wuri, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL+FILE_FLAG_BACKUP_SEMANTICS+FILE_FLAG_OPEN_REPARSE_POINT, NULL );
|
||||
h = CreateFileW( wuri, 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
NULL );
|
||||
if( h == INVALID_HANDLE_VALUE ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_CRIT, "CreateFileW failed on %s", uri );
|
||||
errno = GetLastError();
|
||||
|
||||
@@ -85,6 +85,16 @@ sub fromFileName($)
|
||||
}
|
||||
}
|
||||
|
||||
sub setCredentials
|
||||
{
|
||||
my ($dav, $user, $passwd) = @_;
|
||||
|
||||
$dav->credentials(-url=> $owncloud, -realm=>"sabre/dav",
|
||||
-user=> $user, -pass=> $passwd);
|
||||
$dav->credentials(-url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $user, -pass=> $passwd);
|
||||
}
|
||||
|
||||
|
||||
sub initTesting(;$)
|
||||
{
|
||||
@@ -127,9 +137,7 @@ sub initTesting(;$)
|
||||
my $ua = HTTP::DAV::UserAgent->new(keep_alive => 1 );
|
||||
$d = HTTP::DAV->new(-useragent => $ua);
|
||||
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $user,
|
||||
-pass=> $passwd );
|
||||
setCredentials($d, $user, $passwd);
|
||||
# $d->DebugLevel(3);
|
||||
$prefix = "t1" unless( defined $prefix );
|
||||
|
||||
@@ -193,9 +201,7 @@ sub removeRemoteDir($;$)
|
||||
|
||||
my $url = testDirUrl() . $dir;
|
||||
if( $optionsRef && $optionsRef->{user} && $optionsRef->{passwd} ) {
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $optionsRef->{user},
|
||||
-pass=> $optionsRef->{passwd} );
|
||||
setCredentials($d, $optionsRef->{user}, $optionsRef->{passwd});
|
||||
if( $optionsRef->{url} ) {
|
||||
$url = $optionsRef->{url} . $dir;
|
||||
}
|
||||
@@ -219,9 +225,7 @@ sub createRemoteDir(;$$)
|
||||
my $url = testDirUrl() . $dir;
|
||||
|
||||
if( $optionsRef && $optionsRef->{user} && $optionsRef->{passwd} ) {
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $optionsRef->{user},
|
||||
-pass=> $optionsRef->{passwd} );
|
||||
setCredentials($d, $optionsRef->{user}, $optionsRef->{passwd});
|
||||
if( $optionsRef->{url} ) {
|
||||
$url = $optionsRef->{url} . $dir;
|
||||
}
|
||||
@@ -396,9 +400,7 @@ sub traverse( $$;$ )
|
||||
my %seen;
|
||||
|
||||
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $user,
|
||||
-pass=> $passwd );
|
||||
setCredentials($d, $user, $passwd);
|
||||
$d->open( $owncloud );
|
||||
|
||||
if( my $r = $d->propfind( -url => $url, -depth => 1 ) ) {
|
||||
@@ -513,9 +515,7 @@ sub put_to_dir( $$;$ )
|
||||
my $targetUrl = testDirUrl();
|
||||
|
||||
if( $optionsRef && $optionsRef->{user} && $optionsRef->{passwd} ) {
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $optionsRef->{user},
|
||||
-pass=> $optionsRef->{passwd} );
|
||||
setCredentials($d, $optionsRef->{user}, $optionsRef->{passwd});
|
||||
if( $optionsRef->{url} ) {
|
||||
$targetUrl = $optionsRef->{url};
|
||||
}
|
||||
@@ -649,9 +649,7 @@ sub moveRemoteFile($$;$)
|
||||
{
|
||||
my ($from, $to, $no_testdir) = @_;
|
||||
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $user,
|
||||
-pass=> $passwd );
|
||||
setCredentials($d, $user, $passwd);
|
||||
|
||||
my $fromUrl = testDirUrl(). $from;
|
||||
my $toUrl = testDirUrl() . $to;
|
||||
@@ -725,9 +723,7 @@ sub createShare($$)
|
||||
|
||||
my $dd = HTTP::DAV->new();
|
||||
|
||||
$dd->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $share_user,
|
||||
-pass=> $share_passwd );
|
||||
setCredentials($dd, $share_user, $share_passwd);
|
||||
$dd->open( $owncloud);
|
||||
|
||||
# create a remote dir
|
||||
@@ -769,9 +765,7 @@ sub removeShare($$)
|
||||
|
||||
my $dd = HTTP::DAV->new();
|
||||
|
||||
$dd->credentials( -url => $owncloud, -realm=>"ownCloud",
|
||||
-user => $share_user,
|
||||
-pass => $share_passwd );
|
||||
setCredentials($dd, $share_user, $share_passwd);
|
||||
$dd->open( $owncloud);
|
||||
|
||||
my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });
|
||||
|
||||
@@ -146,9 +146,9 @@ assertLocalAndRemoteDir( '', 0);
|
||||
|
||||
# create a true conflict.
|
||||
printInfo( "Create a conflict." );
|
||||
system( "echo \"This is more stuff\" >> /tmp/kernelcrash.txt" );
|
||||
system( "echo \"This is more server stuff\" >> /tmp/kernelcrash.txt" );
|
||||
put_to_dir( '/tmp/kernelcrash.txt', 'remoteToLocal1' );
|
||||
system( "sleep 2 && touch " . localDir() . "remoteToLocal1/kernelcrash.txt" );
|
||||
system( "sleep 2 && echo \"This is more client stuff\" >> " . localDir() . "remoteToLocal1/kernelcrash.txt" );
|
||||
csync();
|
||||
assertLocalAndRemoteDir( '', 1);
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ assert($emlpropafter->get_property( "getlastmodified" ) eq
|
||||
$emlpropbefore->get_property( "getlastmodified" ));
|
||||
|
||||
printInfo( "Change content of eml file (but not size)");
|
||||
system( "sed -i -e 's/in/IN/' $locDir/test.eml" );
|
||||
system( "sleep 1 && sed -i -e 's/in/IN/' $locDir/test.eml" );
|
||||
|
||||
csync( );
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ endif()
|
||||
set(OWNCLOUDDOLPHINHELPER ${APPLICATION_EXECUTABLE}dolphinpluginhelper)
|
||||
add_library(${OWNCLOUDDOLPHINHELPER} SHARED ownclouddolphinpluginhelper.cpp)
|
||||
target_link_libraries(${OWNCLOUDDOLPHINHELPER} Qt5::Network)
|
||||
generate_export_header(${OWNCLOUDDOLPHINHELPER})
|
||||
generate_export_header(${OWNCLOUDDOLPHINHELPER} BASE_NAME ownclouddolphinpluginhelper)
|
||||
install(TARGETS ${OWNCLOUDDOLPHINHELPER} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
#---OVERLAY PLUGIN---
|
||||
|
||||
@@ -21,11 +21,15 @@ import socket
|
||||
|
||||
from gi.repository import GObject, Nautilus
|
||||
|
||||
print("Initializing owncloud-client-nautilus extension")
|
||||
|
||||
# Do not touch the following line.
|
||||
# Please do not touch the following line.
|
||||
# The reason is that we use a script to adopt this file for branding
|
||||
# by replacing this line with the branding app name. If the following
|
||||
# line is changed, the script can not match the pattern and fails.
|
||||
appname = 'ownCloud'
|
||||
|
||||
print("Initializing "+appname+"-client-nautilus extension")
|
||||
|
||||
|
||||
def get_local_path(url):
|
||||
if url[0:7] == 'file://':
|
||||
url = url[7:]
|
||||
@@ -181,10 +185,10 @@ class MenuExtension(GObject.GObject, Nautilus.MenuProvider):
|
||||
if not syncedFile:
|
||||
return items
|
||||
|
||||
# Create an menu item
|
||||
# Create a menu item
|
||||
labelStr = "Share with " + appname + "..."
|
||||
item = Nautilus.MenuItem(name='NautilusPython::ShareItem', label=labelStr,
|
||||
tip='Share file %s through ownCloud' % file.get_name())
|
||||
tip='Share file {} through {}'.format(file.get_name(), appname) )
|
||||
item.connect("activate", self.menu_share, file)
|
||||
items.append(item)
|
||||
|
||||
|
||||
@@ -31,12 +31,24 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define BUFSIZE 512
|
||||
|
||||
std::wstring getUserName() {
|
||||
DWORD len = BUFSIZE;
|
||||
TCHAR buf[BUFSIZE];
|
||||
if (GetUserName(buf, &len)) {
|
||||
return std::wstring(&buf[0], len);
|
||||
} else {
|
||||
return std::wstring();
|
||||
}
|
||||
}
|
||||
|
||||
// This code is run in a thread
|
||||
void RemotePathChecker::workerThreadLoop()
|
||||
{
|
||||
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||
pipename += L"ownCloud";
|
||||
pipename += L"ownCloud\\";
|
||||
pipename += getUserName();
|
||||
|
||||
bool connected = false;
|
||||
CommunicationSocket socket;
|
||||
@@ -241,4 +253,4 @@ RemotePathChecker::FileState RemotePathChecker::_StrToFileState(const std::wstri
|
||||
}
|
||||
|
||||
return StateNone;
|
||||
}
|
||||
}
|
||||
|
||||
externo
+46
-31
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
** This file is an amalgamation of many separate C source files from SQLite
|
||||
** version 3.12.1. By combining all the individual C code files into this
|
||||
** version 3.12.2. By combining all the individual C code files into this
|
||||
** single large file, the entire code can be compiled as a single translation
|
||||
** unit. This allows many compilers to do optimizations that would not be
|
||||
** possible if the files were compiled separately. Performance improvements
|
||||
@@ -336,9 +336,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.12.1"
|
||||
#define SQLITE_VERSION_NUMBER 3012001
|
||||
#define SQLITE_SOURCE_ID "2016-04-08 15:09:49 fe7d3b75fe1bde41511b323925af8ae1b910bc4d"
|
||||
#define SQLITE_VERSION "3.12.2"
|
||||
#define SQLITE_VERSION_NUMBER 3012002
|
||||
#define SQLITE_SOURCE_ID "2016-04-18 17:30:31 92dc59fd5ad66f646666042eb04195e3a61a9e8e"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -63941,6 +63941,28 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
|
||||
pPage = pCur->apPage[iCellDepth];
|
||||
pCell = findCell(pPage, iCellIdx);
|
||||
|
||||
/* If the bPreserve flag is set to true, then the cursor position must
|
||||
** be preserved following this delete operation. If the current delete
|
||||
** will cause a b-tree rebalance, then this is done by saving the cursor
|
||||
** key and leaving the cursor in CURSOR_REQUIRESEEK state before
|
||||
** returning.
|
||||
**
|
||||
** Or, if the current delete will not cause a rebalance, then the cursor
|
||||
** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
|
||||
** before or after the deleted entry. In this case set bSkipnext to true. */
|
||||
if( bPreserve ){
|
||||
if( !pPage->leaf
|
||||
|| (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
|
||||
){
|
||||
/* A b-tree rebalance will be required after deleting this entry.
|
||||
** Save the cursor key. */
|
||||
rc = saveCursorKey(pCur);
|
||||
if( rc ) return rc;
|
||||
}else{
|
||||
bSkipnext = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the page containing the entry to delete is not a leaf page, move
|
||||
** the cursor to the largest entry in the tree that is smaller than
|
||||
** the entry being deleted. This cell will replace the cell being deleted
|
||||
@@ -63967,28 +63989,6 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
|
||||
invalidateIncrblobCursors(p, pCur->info.nKey, 0);
|
||||
}
|
||||
|
||||
/* If the bPreserve flag is set to true, then the cursor position must
|
||||
** be preserved following this delete operation. If the current delete
|
||||
** will cause a b-tree rebalance, then this is done by saving the cursor
|
||||
** key and leaving the cursor in CURSOR_REQUIRESEEK state before
|
||||
** returning.
|
||||
**
|
||||
** Or, if the current delete will not cause a rebalance, then the cursor
|
||||
** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
|
||||
** before or after the deleted entry. In this case set bSkipnext to true. */
|
||||
if( bPreserve ){
|
||||
if( !pPage->leaf
|
||||
|| (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
|
||||
){
|
||||
/* A b-tree rebalance will be required after deleting this entry.
|
||||
** Save the cursor key. */
|
||||
rc = saveCursorKey(pCur);
|
||||
if( rc ) return rc;
|
||||
}else{
|
||||
bSkipnext = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the page containing the entry to be deleted writable. Then free any
|
||||
** overflow pages associated with the entry and finally remove the cell
|
||||
** itself from within the page. */
|
||||
@@ -82769,7 +82769,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
|
||||
){
|
||||
int pgsz; /* Page size of main database */
|
||||
int i; /* Used to iterate through aTask[] */
|
||||
int mxCache; /* Cache size */
|
||||
VdbeSorter *pSorter; /* The new sorter */
|
||||
KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */
|
||||
int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */
|
||||
@@ -82826,11 +82825,20 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
|
||||
}
|
||||
|
||||
if( !sqlite3TempInMemory(db) ){
|
||||
i64 mxCache; /* Cache size in bytes*/
|
||||
u32 szPma = sqlite3GlobalConfig.szPma;
|
||||
pSorter->mnPmaSize = szPma * pgsz;
|
||||
|
||||
mxCache = db->aDb[0].pSchema->cache_size;
|
||||
if( mxCache<(int)szPma ) mxCache = (int)szPma;
|
||||
pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ);
|
||||
if( mxCache<0 ){
|
||||
/* A negative cache-size value C indicates that the cache is abs(C)
|
||||
** KiB in size. */
|
||||
mxCache = mxCache * -1024;
|
||||
}else{
|
||||
mxCache = mxCache * pgsz;
|
||||
}
|
||||
mxCache = MIN(mxCache, SQLITE_MAX_PMASZ);
|
||||
pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache);
|
||||
|
||||
/* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
|
||||
** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
|
||||
@@ -95563,6 +95571,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
|
||||
zType = z + sqlite3Strlen30(z) + 1;
|
||||
memcpy(zType, pType->z, pType->n);
|
||||
zType[pType->n] = 0;
|
||||
sqlite3Dequote(zType);
|
||||
pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst);
|
||||
pCol->colFlags |= COLFLAG_HASTYPE;
|
||||
}
|
||||
@@ -121360,7 +121369,13 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
|
||||
/* These registers need to be preserved in case there is an IN operator
|
||||
** loop. So we could deallocate the registers here (and potentially
|
||||
** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems
|
||||
** simpler and safer to simply not reuse the registers.
|
||||
**
|
||||
** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
|
||||
*/
|
||||
sqlite3ExprCachePop(pParse);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
@@ -185458,7 +185473,7 @@ static void fts5SourceIdFunc(
|
||||
){
|
||||
assert( nArg==0 );
|
||||
UNUSED_PARAM2(nArg, apUnused);
|
||||
sqlite3_result_text(pCtx, "fts5: 2016-04-08 15:09:49 fe7d3b75fe1bde41511b323925af8ae1b910bc4d", -1, SQLITE_TRANSIENT);
|
||||
sqlite3_result_text(pCtx, "fts5: 2016-04-18 17:30:31 92dc59fd5ad66f646666042eb04195e3a61a9e8e", -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
static int fts5Init(sqlite3 *db){
|
||||
|
||||
externo
+3
-3
@@ -111,9 +111,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.12.1"
|
||||
#define SQLITE_VERSION_NUMBER 3012001
|
||||
#define SQLITE_SOURCE_ID "2016-04-08 15:09:49 fe7d3b75fe1bde41511b323925af8ae1b910bc4d"
|
||||
#define SQLITE_VERSION "3.12.2"
|
||||
#define SQLITE_VERSION_NUMBER 3012002
|
||||
#define SQLITE_SOURCE_ID "2016-04-18 17:30:31 92dc59fd5ad66f646666042eb04195e3a61a9e8e"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
|
||||
@@ -45,7 +45,7 @@ qt_wrap_ui(client_UI_SRCS ${client_UI})
|
||||
set(client_SRCS
|
||||
accountmanager.cpp
|
||||
accountsettings.cpp
|
||||
application.cpp
|
||||
ocapplication.cpp
|
||||
folder.cpp
|
||||
folderman.cpp
|
||||
folderstatusmodel.cpp
|
||||
@@ -54,6 +54,7 @@ set(client_SRCS
|
||||
folderwizard.cpp
|
||||
generalsettings.cpp
|
||||
ignorelisteditor.cpp
|
||||
lockwatcher.cpp
|
||||
logbrowser.cpp
|
||||
networksettings.cpp
|
||||
ocsjob.cpp
|
||||
@@ -211,6 +212,10 @@ if(QTKEYCHAIN_FOUND OR QT5KEYCHAIN_FOUND)
|
||||
list(APPEND libsync_LINK_TARGETS ${QTKEYCHAIN_LIBRARY})
|
||||
include_directories(${QTKEYCHAIN_INCLUDE_DIR})
|
||||
endif()
|
||||
if(LibsnoreQt5_FOUND)
|
||||
add_definitions(-DHAVE_LIBSNORE)
|
||||
|
||||
endif()
|
||||
|
||||
# add executable icon on windows and osx
|
||||
include( AddAppIconMacro )
|
||||
@@ -288,6 +293,7 @@ target_link_libraries( ${APPLICATION_EXECUTABLE} ${QT_LIBRARIES} )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} ${synclib_NAME} )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} updater )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} ${OS_SPECIFIC_LINK_LIBRARIES} )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} Snore::Libsnore Snore::LibsnoreSettings )
|
||||
|
||||
if(WITH_CRASHREPORTER)
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} crashreporter-handler)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "folderstatusmodel.h"
|
||||
#include "folderstatusdelegate.h"
|
||||
#include "utility.h"
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "configfile.h"
|
||||
#include "account.h"
|
||||
#include "accountstate.h"
|
||||
@@ -197,8 +197,7 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
|
||||
return;
|
||||
}
|
||||
|
||||
QString alias = _model->data( index, FolderStatusDelegate::FolderAliasRole ).toString();
|
||||
if (alias.isEmpty()) {
|
||||
if (_model->classify(index) != FolderStatusModel::RootFolder) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,9 @@ void AccountState::setState(State state)
|
||||
} else if (oldState == SignedOut && _state == Disconnected) {
|
||||
checkConnectivity();
|
||||
}
|
||||
if (oldState == Connected || _state == Connected) {
|
||||
emit isConnectedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// might not have changed but the underlying _connectionErrors might have
|
||||
@@ -149,11 +152,6 @@ bool AccountState::isConnectedOrTemporarilyUnavailable() const
|
||||
return isConnected() || _state == ServiceUnavailable;
|
||||
}
|
||||
|
||||
bool AccountState::canSync() const
|
||||
{
|
||||
return isConnected();
|
||||
}
|
||||
|
||||
void AccountState::tagLastSuccessfullETagRequest()
|
||||
{
|
||||
_timeSinceLastETagCheck.restart();
|
||||
|
||||
@@ -102,9 +102,6 @@ public:
|
||||
bool isConnected() const;
|
||||
bool isConnectedOrTemporarilyUnavailable() const;
|
||||
|
||||
/// Returns whether sync actions are allowed to run.
|
||||
bool canSync() const;
|
||||
|
||||
/// Triggers a ping to the server to update state and
|
||||
/// connection status and errors.
|
||||
void checkConnectivity();
|
||||
@@ -130,6 +127,7 @@ private:
|
||||
|
||||
signals:
|
||||
void stateChanged(int state);
|
||||
void isConnectedChanged();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList& errors);
|
||||
|
||||
@@ -41,7 +41,7 @@ class ActivityListModel;
|
||||
namespace Ui {
|
||||
class ActivityWidget;
|
||||
}
|
||||
class Application;
|
||||
class oCApplication;
|
||||
|
||||
/**
|
||||
* @brief The ActivityWidget class
|
||||
|
||||
@@ -67,8 +67,13 @@ void ShibbolethCredentials::setAccount(Account* account)
|
||||
{
|
||||
AbstractCredentials::setAccount(account);
|
||||
|
||||
// This is for existing saved accounts.
|
||||
if (_user.isEmpty()) {
|
||||
_user = _account->credentialSetting(QLatin1String(userC)).toString();
|
||||
}
|
||||
|
||||
// When constructed with a cookie (by the wizard), we usually don't know the
|
||||
// user name yet. Request it now.
|
||||
// user name yet. Request it now from the server.
|
||||
if (_ready && _user.isEmpty()) {
|
||||
QTimer::singleShot(1234, this, SLOT(slotFetchUser()));
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ Folder::Folder(const FolderDefinition& definition,
|
||||
if (!setIgnoredFiles())
|
||||
qWarning("Could not read system exclude file");
|
||||
|
||||
connect(_accountState.data(), SIGNAL(isConnectedChanged()), this, SIGNAL(canSyncChanged()));
|
||||
connect(_engine.data(), SIGNAL(rootEtag(QString)), this, SLOT(etagRetreivedFromSyncEngine(QString)));
|
||||
connect(_engine.data(), SIGNAL(treeWalkResult(const SyncFileItemVector&)),
|
||||
this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
|
||||
@@ -115,6 +116,7 @@ Folder::Folder(const FolderDefinition& definition,
|
||||
connect(_engine.data(), SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)),
|
||||
this, SLOT(slotItemCompleted(const SyncFileItem &, const PropagatorJob &)));
|
||||
connect(_engine.data(), SIGNAL(newBigFolder(QString)), this, SLOT(slotNewBigFolderDiscovered(QString)));
|
||||
connect(_engine.data(), SIGNAL(seenLockedFile(QString)), FolderMan::instance(), SLOT(slotSyncOnceFileUnlocks(QString)));
|
||||
}
|
||||
|
||||
Folder::~Folder()
|
||||
@@ -229,7 +231,7 @@ bool Folder::syncPaused() const
|
||||
|
||||
bool Folder::canSync() const
|
||||
{
|
||||
return !syncPaused() && accountState()->canSync();
|
||||
return !syncPaused() && accountState()->isConnected();
|
||||
}
|
||||
|
||||
void Folder::setSyncPaused( bool paused )
|
||||
@@ -248,6 +250,7 @@ void Folder::setSyncPaused( bool paused )
|
||||
}
|
||||
emit syncPausedChanged(this, paused);
|
||||
emit syncStateChange();
|
||||
emit canSyncChanged();
|
||||
}
|
||||
|
||||
void Folder::setSyncState(SyncResult::Status state)
|
||||
@@ -578,6 +581,7 @@ void Folder::slotWatchedPathChanged(const QString& path)
|
||||
// When no sync is running or it's in the prepare phase, we can
|
||||
// always schedule a new sync.
|
||||
if (! _engine->isSyncRunning() || _syncResult.status() == SyncResult::SyncPrepare) {
|
||||
emit watchedFileChangedExternally(path);
|
||||
emit scheduleToSync(this);
|
||||
return;
|
||||
}
|
||||
@@ -601,6 +605,7 @@ void Folder::slotWatchedPathChanged(const QString& path)
|
||||
#endif
|
||||
|
||||
if (! ownChange) {
|
||||
emit watchedFileChangedExternally(path);
|
||||
emit scheduleToSync(this);
|
||||
}
|
||||
}
|
||||
@@ -683,7 +688,8 @@ void Folder::wipe()
|
||||
QFile::remove( stateDbFile + "-wal" );
|
||||
QFile::remove( stateDbFile + "-journal" );
|
||||
|
||||
FolderMan::instance()->socketApi()->slotRegisterPath(alias());
|
||||
if (canSync())
|
||||
FolderMan::instance()->socketApi()->slotRegisterPath(alias());
|
||||
}
|
||||
|
||||
bool Folder::setIgnoredFiles()
|
||||
|
||||
+7
-2
@@ -131,8 +131,6 @@ public:
|
||||
|
||||
/**
|
||||
* Returns true when the folder may sync.
|
||||
*
|
||||
* !syncPaused() && accountState->canSync().
|
||||
*/
|
||||
bool canSync() const;
|
||||
|
||||
@@ -203,6 +201,13 @@ signals:
|
||||
void progressInfo(const ProgressInfo& progress);
|
||||
void newBigFolderDiscovered(const QString &); // A new folder bigger than the threshold was discovered
|
||||
void syncPausedChanged(Folder*, bool paused);
|
||||
void canSyncChanged();
|
||||
|
||||
/**
|
||||
* Fires for each change inside this folder that wasn't caused
|
||||
* by sync activity.
|
||||
*/
|
||||
void watchedFileChangedExternally(const QString& path);
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
+37
-2
@@ -22,6 +22,7 @@
|
||||
#include "accountstate.h"
|
||||
#include "accountmanager.h"
|
||||
#include "filesystem.h"
|
||||
#include "lockwatcher.h"
|
||||
#include <syncengine.h>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
@@ -44,6 +45,7 @@ FolderMan::FolderMan(QObject *parent) :
|
||||
QObject(parent),
|
||||
_currentSyncFolder(0),
|
||||
_syncEnabled( true ),
|
||||
_lockWatcher(new LockWatcher),
|
||||
_appRestartRequired(false)
|
||||
{
|
||||
Q_ASSERT(!_instance);
|
||||
@@ -64,6 +66,9 @@ FolderMan::FolderMan(QObject *parent) :
|
||||
|
||||
connect(AccountManager::instance(), SIGNAL(accountRemoved(AccountState*)),
|
||||
SLOT(slotRemoveFoldersForAccount(AccountState*)));
|
||||
|
||||
connect(_lockWatcher.data(), SIGNAL(fileUnlocked(QString)),
|
||||
SLOT(slotScheduleFolderOwningFile(QString)));
|
||||
}
|
||||
|
||||
FolderMan *FolderMan::instance()
|
||||
@@ -107,6 +112,8 @@ void FolderMan::unloadFolder( Folder *f )
|
||||
this, SLOT(slotFolderSyncPaused(Folder*,bool)));
|
||||
disconnect(&f->syncEngine().syncFileStatusTracker(), SIGNAL(fileStatusChanged(const QString &, SyncFileStatus)),
|
||||
_socketApi.data(), SLOT(slotFileStatusChanged(const QString &, SyncFileStatus)));
|
||||
disconnect(f, SIGNAL(watchedFileChangedExternally(QString)),
|
||||
&f->syncEngine().syncFileStatusTracker(), SLOT(slotPathTouched(QString)));
|
||||
}
|
||||
|
||||
int FolderMan::unloadAndDeleteAllFolders()
|
||||
@@ -145,11 +152,13 @@ void FolderMan::registerFolderMonitor( Folder *folder )
|
||||
// to the signal mapper which maps to the folder alias. The changed path
|
||||
// is lost this way, but we do not need it for the current implementation.
|
||||
connect(fw, SIGNAL(pathChanged(QString)), folder, SLOT(slotWatchedPathChanged(QString)));
|
||||
|
||||
_folderWatchers.insert(folder->alias(), fw);
|
||||
}
|
||||
|
||||
// register the folder with the socket API
|
||||
_socketApi->slotRegisterPath(folder->alias());
|
||||
if (folder->canSync())
|
||||
_socketApi->slotRegisterPath(folder->alias());
|
||||
}
|
||||
|
||||
void FolderMan::addMonitorPath( const QString& alias, const QString& path )
|
||||
@@ -419,6 +428,17 @@ void FolderMan::slotFolderSyncPaused( Folder *f, bool paused )
|
||||
}
|
||||
}
|
||||
|
||||
void FolderMan::slotFolderCanSyncChanged()
|
||||
{
|
||||
Folder *f = qobject_cast<Folder*>(sender());
|
||||
Q_ASSERT(f);
|
||||
if (f->canSync()) {
|
||||
_socketApi->slotRegisterPath(f->alias());
|
||||
} else {
|
||||
_socketApi->slotUnregisterPath(f->alias());
|
||||
}
|
||||
}
|
||||
|
||||
// this really terminates the current sync process
|
||||
// ie. no questions, no prisoners
|
||||
// csync still remains in a stable state, regardless of that.
|
||||
@@ -457,6 +477,11 @@ void FolderMan::slotScheduleAppRestart()
|
||||
qDebug() << "## Application restart requested!";
|
||||
}
|
||||
|
||||
void FolderMan::slotSyncOnceFileUnlocks(const QString& path)
|
||||
{
|
||||
_lockWatcher->addFile(path);
|
||||
}
|
||||
|
||||
/*
|
||||
* if a folder wants to be synced, it calls this slot and is added
|
||||
* to the queue. The slot to actually start a sync is called afterwards.
|
||||
@@ -536,7 +561,7 @@ void FolderMan::slotAccountStateChanged()
|
||||
}
|
||||
QString accountName = accountState->account()->displayName();
|
||||
|
||||
if (accountState->canSync()) {
|
||||
if (accountState->isConnected()) {
|
||||
qDebug() << "Account" << accountName << "connected, scheduling its folders";
|
||||
|
||||
foreach (Folder *f, _folderMap.values()) {
|
||||
@@ -741,6 +766,13 @@ void FolderMan::slotServerVersionChanged(Account *account)
|
||||
}
|
||||
}
|
||||
|
||||
void FolderMan::slotScheduleFolderOwningFile(const QString& path)
|
||||
{
|
||||
if (Folder* f = folderForPath(path)) {
|
||||
slotScheduleSync(f);
|
||||
}
|
||||
}
|
||||
|
||||
void FolderMan::slotFolderSyncStarted( )
|
||||
{
|
||||
qDebug() << ">===================================== sync started for " << _currentSyncFolder->remoteUrl().toString();
|
||||
@@ -800,8 +832,11 @@ Folder* FolderMan::addFolderInternal(FolderDefinition folderDefinition, AccountS
|
||||
connect(folder, SIGNAL(syncFinished(SyncResult)), SLOT(slotFolderSyncFinished(SyncResult)));
|
||||
connect(folder, SIGNAL(syncStateChange()), SLOT(slotForwardFolderSyncStateChange()));
|
||||
connect(folder, SIGNAL(syncPausedChanged(Folder*,bool)), SLOT(slotFolderSyncPaused(Folder*,bool)));
|
||||
connect(folder, SIGNAL(canSyncChanged()), SLOT(slotFolderCanSyncChanged()));
|
||||
connect(&folder->syncEngine().syncFileStatusTracker(), SIGNAL(fileStatusChanged(const QString &, SyncFileStatus)),
|
||||
_socketApi.data(), SLOT(slotFileStatusChanged(const QString &, SyncFileStatus)));
|
||||
connect(folder, SIGNAL(watchedFileChangedExternally(QString)),
|
||||
&folder->syncEngine().syncFileStatusTracker(), SLOT(slotPathTouched(QString)));
|
||||
|
||||
registerFolderMonitor(folder);
|
||||
return folder;
|
||||
|
||||
+18
-2
@@ -29,9 +29,10 @@ class TestFolderMan;
|
||||
|
||||
namespace OCC {
|
||||
|
||||
class Application;
|
||||
class oCApplication;
|
||||
class SyncResult;
|
||||
class SocketApi;
|
||||
class LockWatcher;
|
||||
|
||||
/**
|
||||
* @brief The FolderMan class
|
||||
@@ -143,6 +144,7 @@ signals:
|
||||
public slots:
|
||||
void slotRemoveFolder( Folder* );
|
||||
void slotFolderSyncPaused(Folder *, bool paused);
|
||||
void slotFolderCanSyncChanged();
|
||||
|
||||
void slotFolderSyncStarted();
|
||||
void slotFolderSyncFinished( const SyncResult& );
|
||||
@@ -184,6 +186,13 @@ public slots:
|
||||
*/
|
||||
void slotScheduleAppRestart();
|
||||
|
||||
/**
|
||||
* Triggers a sync run once the lock on the given file is removed.
|
||||
*
|
||||
* Automatically detemines the folder that's responsible for the file.
|
||||
*/
|
||||
void slotSyncOnceFileUnlocks(const QString& path);
|
||||
|
||||
private slots:
|
||||
// slot to take the next folder from queue and start syncing.
|
||||
void slotStartScheduledFolderSync();
|
||||
@@ -197,6 +206,12 @@ private slots:
|
||||
|
||||
void slotServerVersionChanged(Account* account);
|
||||
|
||||
/**
|
||||
* Schedules the folder for synchronization that contains
|
||||
* the file with the given path.
|
||||
*/
|
||||
void slotScheduleFolderOwningFile(const QString& path);
|
||||
|
||||
private:
|
||||
/** Adds a new folder, does not add it to the account settings and
|
||||
* does not set an account on the new folder.
|
||||
@@ -227,6 +242,7 @@ private:
|
||||
QPointer<RequestEtagJob> _currentEtagJob; // alias of Folder running the current RequestEtagJob
|
||||
|
||||
QMap<QString, FolderWatcher*> _folderWatchers;
|
||||
QScopedPointer<LockWatcher> _lockWatcher;
|
||||
QScopedPointer<SocketApi> _socketApi;
|
||||
|
||||
/** The aliases of folders that shall be synced. */
|
||||
@@ -239,7 +255,7 @@ private:
|
||||
|
||||
static FolderMan *_instance;
|
||||
explicit FolderMan(QObject *parent = 0);
|
||||
friend class OCC::Application;
|
||||
friend class OCC::oCApplication;
|
||||
friend class ::TestFolderMan;
|
||||
};
|
||||
|
||||
|
||||
@@ -574,9 +574,6 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list)
|
||||
return;
|
||||
}
|
||||
|
||||
QVarLengthArray<int, 10> undecidedIndexes;
|
||||
QVector<SubFolderInfo> newSubs;
|
||||
|
||||
std::set<QString> selectiveSyncUndecidedSet; // not QSet because it's not sorted
|
||||
foreach (const QString &str, selectiveSyncUndecidedList) {
|
||||
if (str.startsWith(parentInfo->_path) || parentInfo->_path == QLatin1String("/")) {
|
||||
@@ -584,10 +581,16 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list)
|
||||
}
|
||||
}
|
||||
|
||||
newSubs.reserve(list.size() - 1);
|
||||
for (int i = 1; // skip the parent item (first in the list)
|
||||
i < list.size(); ++i) {
|
||||
const QString &path = list.at(i);
|
||||
QStringList sortedSubfolders = list;
|
||||
// skip the parent item (first in the list)
|
||||
sortedSubfolders.erase(sortedSubfolders.begin());
|
||||
sortedSubfolders.sort();
|
||||
|
||||
QVarLengthArray<int, 10> undecidedIndexes;
|
||||
|
||||
QVector<SubFolderInfo> newSubs;
|
||||
newSubs.reserve(sortedSubfolders.size());
|
||||
foreach (const QString& path, sortedSubfolders) {
|
||||
auto relativePath = path.mid(pathToRemove.size());
|
||||
if (parentInfo->_folder->isFileExcludedRelative(relativePath)) {
|
||||
continue;
|
||||
|
||||
@@ -306,6 +306,7 @@ bool FolderWizardRemotePath::selectByPath(QString path)
|
||||
}
|
||||
|
||||
_ui.folderTreeWidget->setCurrentItem(it);
|
||||
_ui.folderTreeWidget->scrollToItem(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -321,7 +322,9 @@ void FolderWizardRemotePath::slotUpdateDirectories(const QStringList &list)
|
||||
root->setToolTip(0, tr("Choose this to sync the entire account"));
|
||||
root->setData(0, Qt::UserRole, "/");
|
||||
}
|
||||
foreach (QString path, list) {
|
||||
QStringList sortedList = list;
|
||||
sortedList.sort();
|
||||
foreach (QString path, sortedList) {
|
||||
path.remove(webdavFolder);
|
||||
QStringList paths = path.split('/');
|
||||
if (paths.last().isEmpty()) paths.removeLast();
|
||||
@@ -374,8 +377,11 @@ void FolderWizardRemotePath::slotLsColFolderEntry()
|
||||
path = path.mid(1);
|
||||
|
||||
LsColJob *job = runLsColJob(path);
|
||||
// no error handling, no updating, we do this manually
|
||||
// No error handling, no updating, we do this manually
|
||||
// because of extra logic in the typed-path case.
|
||||
disconnect(job, 0, this, 0);
|
||||
connect(job, SIGNAL(finishedWithError(QNetworkReply*)),
|
||||
SLOT(slotTypedPathError(QNetworkReply*)));
|
||||
connect(job, SIGNAL(directoryListingSubfolders(QStringList)),
|
||||
SLOT(slotTypedPathFound(QStringList)));
|
||||
}
|
||||
@@ -386,6 +392,21 @@ void FolderWizardRemotePath::slotTypedPathFound(const QStringList& subpaths)
|
||||
selectByPath(_ui.folderEntry->text());
|
||||
}
|
||||
|
||||
void FolderWizardRemotePath::slotTypedPathError(QNetworkReply* reply)
|
||||
{
|
||||
// Ignore 404s, otherwise users will get annoyed by error popups
|
||||
// when not typing fast enough. It's still clear that a given path
|
||||
// was not found, because the 'Next' button is disabled and no entry
|
||||
// is selected in the tree view.
|
||||
int httpCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (httpCode == 404) {
|
||||
showWarn(""); // hides the warning pane
|
||||
return;
|
||||
}
|
||||
|
||||
slotHandleLsColNetworkError(reply);
|
||||
}
|
||||
|
||||
LsColJob* FolderWizardRemotePath::runLsColJob(const QString& path)
|
||||
{
|
||||
LsColJob *job = new LsColJob(_account, path, this);
|
||||
|
||||
@@ -98,6 +98,7 @@ protected slots:
|
||||
void slotFolderEntryEdited(const QString& text);
|
||||
void slotLsColFolderEntry();
|
||||
void slotTypedPathFound(const QStringList& subpaths);
|
||||
void slotTypedPathError(QNetworkReply* reply);
|
||||
private:
|
||||
LsColJob* runLsColJob(const QString& path);
|
||||
void recursiveInsert(QTreeWidgetItem *parent, QStringList pathTrail, QString path);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "theme.h"
|
||||
#include "configfile.h"
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "utility.h"
|
||||
#include "configfile.h"
|
||||
#include "owncloudsetupwizard.h"
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) by Christian Kamm <mail@ckamm.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "lockwatcher.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
using namespace OCC;
|
||||
|
||||
static const int check_frequency = 20 * 1000; // ms
|
||||
|
||||
LockWatcher::LockWatcher(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
connect(&_timer, SIGNAL(timeout()),
|
||||
SLOT(checkFiles()));
|
||||
_timer.start(check_frequency);
|
||||
}
|
||||
|
||||
void LockWatcher::addFile(const QString& path)
|
||||
{
|
||||
_watchedPaths.insert(path);
|
||||
}
|
||||
|
||||
void LockWatcher::checkFiles()
|
||||
{
|
||||
QSet<QString> unlocked;
|
||||
|
||||
foreach (const QString& path, _watchedPaths) {
|
||||
if (!FileSystem::isFileLocked(path)) {
|
||||
emit fileUnlocked(path);
|
||||
unlocked.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
// Doing it this way instead of with a QMutableSetIterator
|
||||
// ensures that calling back into addFile from connected
|
||||
// slots isn't a problem.
|
||||
_watchedPaths.subtract(unlocked);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) by Christian Kamm <mail@ckamm.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QSet>
|
||||
#include <QTimer>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
/**
|
||||
* @brief Monitors files that are locked, signaling when they become unlocked
|
||||
*
|
||||
* Only relevant on Windows. Some high-profile applications like Microsoft
|
||||
* Word lock the document that is currently being edited. The synchronization
|
||||
* client will be unable to update them while they are locked.
|
||||
*
|
||||
* In this situation we do want to start a sync run as soon as the file
|
||||
* becomes available again. To do that, we need to regularly check whether
|
||||
* the file is still being locked.
|
||||
*
|
||||
* @ingroup gui
|
||||
*/
|
||||
|
||||
class LockWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LockWatcher(QObject* parent = 0);
|
||||
|
||||
/** Start watching a file.
|
||||
*
|
||||
* If the file is not locked later on, the fileUnlocked signal will be
|
||||
* emitted once.
|
||||
*/
|
||||
void addFile(const QString& path);
|
||||
|
||||
signals:
|
||||
/** Emitted when one of the watched files is no longer
|
||||
* being locked. */
|
||||
void fileUnlocked(const QString& path);
|
||||
|
||||
private slots:
|
||||
void checkFiles();
|
||||
|
||||
private:
|
||||
QSet<QString> _watchedPaths;
|
||||
QTimer _timer;
|
||||
};
|
||||
|
||||
}
|
||||
+13
-3
@@ -21,7 +21,7 @@
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "theme.h"
|
||||
#include "utility.h"
|
||||
#include "cocoainitializer.h"
|
||||
@@ -63,7 +63,7 @@ int main(int argc, char **argv)
|
||||
#ifdef Q_OS_MAC
|
||||
Mac::CocoaInitializer cocoaInit; // RIIA
|
||||
#endif
|
||||
OCC::Application app(argc, argv);
|
||||
OCC::oCApplication app(argc, argv);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// The Windows style still has pixelated elements with Qt 5.6,
|
||||
@@ -127,8 +127,17 @@ int main(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
}
|
||||
#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
|
||||
if (qgetenv("QT_QPA_PLATFORMTHEME") != "appmenu-qt5")
|
||||
// We can't call isSystemTrayAvailable with appmenu-qt5 begause it hides the systemtray
|
||||
// (issue #4693)
|
||||
#endif
|
||||
{
|
||||
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
// If the systemtray is not there, we will wait one second for it to maybe start
|
||||
// (eg boot time) then we show the settings dialog if there is still no systemtray.
|
||||
// On XFCE however, we show a message box with explainaition how to install a systemtray.
|
||||
Utility::sleep(1);
|
||||
auto desktopSession = qgetenv("XDG_CURRENT_DESKTOP").toLower();
|
||||
if (desktopSession.isEmpty()) {
|
||||
@@ -152,6 +161,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "theme.h"
|
||||
#include "configfile.h"
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "utility.h"
|
||||
#include "configfile.h"
|
||||
#include "folderman.h"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -91,7 +91,7 @@ QString applicationTrPath()
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
Application::Application(int &argc, char **argv) :
|
||||
oCApplication::oCApplication(int &argc, char **argv) :
|
||||
SharedTools::QtSingleApplication(Theme::instance()->appName() ,argc, argv),
|
||||
_gui(0),
|
||||
_theme(Theme::instance()),
|
||||
@@ -202,7 +202,7 @@ Application::Application(int &argc, char **argv) :
|
||||
connect (this, SIGNAL(aboutToQuit()), SLOT(slotCleanup()));
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
oCApplication::~oCApplication()
|
||||
{
|
||||
// Make sure all folders are gone, otherwise removing the
|
||||
// accounts will remove the associated folders from the settings.
|
||||
@@ -214,7 +214,7 @@ Application::~Application()
|
||||
AccountManager::instance()->shutdown();
|
||||
}
|
||||
|
||||
void Application::slotAccountStateRemoved(AccountState *accountState)
|
||||
void oCApplication::slotAccountStateRemoved(AccountState *accountState)
|
||||
{
|
||||
if (_gui) {
|
||||
disconnect(accountState, SIGNAL(stateChanged(int)),
|
||||
@@ -237,7 +237,7 @@ void Application::slotAccountStateRemoved(AccountState *accountState)
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotAccountStateAdded(AccountState *accountState)
|
||||
void oCApplication::slotAccountStateAdded(AccountState *accountState)
|
||||
{
|
||||
connect(accountState, SIGNAL(stateChanged(int)),
|
||||
_gui, SLOT(slotAccountStateChanged()));
|
||||
@@ -251,7 +251,7 @@ void Application::slotAccountStateAdded(AccountState *accountState)
|
||||
_gui->slotTrayMessageIfServerUnsupported(accountState->account().data());
|
||||
}
|
||||
|
||||
void Application::slotCleanup()
|
||||
void oCApplication::slotCleanup()
|
||||
{
|
||||
AccountManager::instance()->save();
|
||||
FolderMan::instance()->unloadAndDeleteAllFolders();
|
||||
@@ -263,7 +263,7 @@ void Application::slotCleanup()
|
||||
// FIXME: This is not ideal yet since a ConnectionValidator might already be running and is in
|
||||
// progress of timing out in some seconds.
|
||||
// Maybe we need 2 validators, one triggered by timer, one by network configuration changes?
|
||||
void Application::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf)
|
||||
void oCApplication::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf)
|
||||
{
|
||||
if (cnf.state() & QNetworkConfiguration::Active) {
|
||||
//qDebug() << "Trying fast reconnect";
|
||||
@@ -271,7 +271,7 @@ void Application::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotCheckConnection()
|
||||
void oCApplication::slotCheckConnection()
|
||||
{
|
||||
auto list = AccountManager::instance()->accounts();
|
||||
foreach (const auto &accountState , list) {
|
||||
@@ -293,12 +293,12 @@ void Application::slotCheckConnection()
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotCrash()
|
||||
void oCApplication::slotCrash()
|
||||
{
|
||||
Utility::crash();
|
||||
}
|
||||
|
||||
void Application::slotownCloudWizardDone( int res )
|
||||
void oCApplication::slotownCloudWizardDone( int res )
|
||||
{
|
||||
AccountManager *accountMan = AccountManager::instance();
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
@@ -335,7 +335,7 @@ void Application::slotownCloudWizardDone( int res )
|
||||
}
|
||||
}
|
||||
|
||||
void Application::setupLogging()
|
||||
void oCApplication::setupLogging()
|
||||
{
|
||||
// might be called from second instance
|
||||
Logger::instance()->setLogFile(_logFile);
|
||||
@@ -352,12 +352,12 @@ void Application::setupLogging()
|
||||
|
||||
}
|
||||
|
||||
void Application::slotUseMonoIconsChanged(bool)
|
||||
void oCApplication::slotUseMonoIconsChanged(bool)
|
||||
{
|
||||
_gui->slotComputeOverallSyncStatus();
|
||||
}
|
||||
|
||||
void Application::slotParseMessage(const QString &msg, QObject*)
|
||||
void oCApplication::slotParseMessage(const QString &msg, QObject*)
|
||||
{
|
||||
if (msg.startsWith(QLatin1String("MSG_PARSEOPTIONS:"))) {
|
||||
const int lengthOfMsgPrefix = 17;
|
||||
@@ -375,7 +375,7 @@ void Application::slotParseMessage(const QString &msg, QObject*)
|
||||
}
|
||||
}
|
||||
|
||||
void Application::parseOptions(const QStringList &options)
|
||||
void oCApplication::parseOptions(const QStringList &options)
|
||||
{
|
||||
QStringListIterator it(options);
|
||||
// skip file name;
|
||||
@@ -455,7 +455,7 @@ static void displayHelpText(const QString &t)
|
||||
}
|
||||
#endif
|
||||
|
||||
void Application::showHelp()
|
||||
void oCApplication::showHelp()
|
||||
{
|
||||
setHelp();
|
||||
QString helpText;
|
||||
@@ -473,7 +473,7 @@ void Application::showHelp()
|
||||
displayHelpText(helpText);
|
||||
}
|
||||
|
||||
void Application::showVersion()
|
||||
void oCApplication::showVersion()
|
||||
{
|
||||
QString helpText;
|
||||
QTextStream stream(&helpText);
|
||||
@@ -485,7 +485,7 @@ void Application::showVersion()
|
||||
displayHelpText(helpText);
|
||||
}
|
||||
|
||||
void Application::showHint(std::string errorHint)
|
||||
void oCApplication::showHint(std::string errorHint)
|
||||
{
|
||||
static QString binName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
|
||||
std::cerr << errorHint << std::endl;
|
||||
@@ -493,12 +493,12 @@ void Application::showHint(std::string errorHint)
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
bool Application::debugMode()
|
||||
bool oCApplication::debugMode()
|
||||
{
|
||||
return _debugMode;
|
||||
}
|
||||
|
||||
void Application::setHelp()
|
||||
void oCApplication::setHelp()
|
||||
{
|
||||
_helpOnly = true;
|
||||
}
|
||||
@@ -518,7 +518,7 @@ QString substLang(const QString &lang)
|
||||
return lang;
|
||||
}
|
||||
|
||||
void Application::setupTranslations()
|
||||
void oCApplication::setupTranslations()
|
||||
{
|
||||
QStringList uiLanguages;
|
||||
// uiLanguages crashes on Windows with 4.8.0 release builds
|
||||
@@ -582,21 +582,20 @@ void Application::setupTranslations()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Application::giveHelp()
|
||||
bool oCApplication::giveHelp()
|
||||
{
|
||||
return _helpOnly;
|
||||
}
|
||||
|
||||
bool Application::versionOnly()
|
||||
bool oCApplication::versionOnly()
|
||||
{
|
||||
return _versionOnly;
|
||||
}
|
||||
|
||||
void Application::showSettingsDialog()
|
||||
void oCApplication::showSettingsDialog()
|
||||
{
|
||||
_gui->slotShowSettings();
|
||||
}
|
||||
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef APPLICATION_H
|
||||
#define APPLICATION_H
|
||||
#ifndef OCAPPLICATION_H
|
||||
#define OCAPPLICATION_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPointer>
|
||||
@@ -49,12 +49,12 @@ class SslErrorDialog;
|
||||
* @brief The Application class
|
||||
* @ingroup gui
|
||||
*/
|
||||
class Application : public SharedTools::QtSingleApplication
|
||||
class oCApplication : public SharedTools::QtSingleApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Application(int &argc, char **argv);
|
||||
~Application();
|
||||
explicit oCApplication(int &argc, char **argv);
|
||||
~oCApplication();
|
||||
|
||||
bool giveHelp();
|
||||
void showHelp();
|
||||
+31
-13
@@ -11,7 +11,7 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "owncloudgui.h"
|
||||
#include "theme.h"
|
||||
#include "folderman.h"
|
||||
@@ -47,7 +47,7 @@ namespace OCC {
|
||||
|
||||
const char propertyAccountC[] = "oc_account";
|
||||
|
||||
ownCloudGui::ownCloudGui(Application *parent) :
|
||||
ownCloudGui::ownCloudGui(oCApplication *parent) :
|
||||
QObject(parent),
|
||||
_tray(0),
|
||||
#if defined(Q_OS_MAC)
|
||||
@@ -96,10 +96,10 @@ ownCloudGui::ownCloudGui(Application *parent) :
|
||||
connect( AccountManager::instance(), SIGNAL(accountRemoved(AccountState*)),
|
||||
SLOT(setupContextMenu()));
|
||||
|
||||
connect( Logger::instance(), SIGNAL(guiLog(QString,QString)),
|
||||
SLOT(slotShowTrayMessage(QString,QString)));
|
||||
connect( Logger::instance(), SIGNAL(optionalGuiLog(QString,QString)),
|
||||
SLOT(slotShowOptionalTrayMessage(QString,QString)));
|
||||
connect( Logger::instance(), SIGNAL(guiLog(QString,QString, Logger::NotificationType)),
|
||||
SLOT(slotShowTrayMessage(QString,QString, Logger::NotificationType)));
|
||||
connect( Logger::instance(), SIGNAL(optionalGuiLog(QString,QString, Logger::NotificationType)),
|
||||
SLOT(slotShowOptionalTrayMessage(QString,QString,Logger::NotificationType)));
|
||||
connect( Logger::instance(), SIGNAL(guiMessage(QString,QString)),
|
||||
SLOT(slotShowGuiMessage(QString,QString)));
|
||||
|
||||
@@ -237,7 +237,8 @@ void ownCloudGui::slotTrayMessageIfServerUnsupported(Account* account)
|
||||
tr("The server on account %1 runs an old and unsupported version %2. "
|
||||
"Using this client with unsupported server versions is untested and "
|
||||
"potentially dangerous. Proceed at your own risk.")
|
||||
.arg(account->displayName(), account->serverVersion()));
|
||||
.arg(account->displayName(), account->serverVersion()),
|
||||
Logger::Critical );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,19 +536,36 @@ void ownCloudGui::setupContextMenu()
|
||||
}
|
||||
|
||||
|
||||
void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg)
|
||||
void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type)
|
||||
{
|
||||
if( _tray )
|
||||
_tray->showMessage(title, msg);
|
||||
else
|
||||
if( _tray ) {
|
||||
QSystemTrayIcon::MessageIcon trayIcon = QSystemTrayIcon::NoIcon;
|
||||
switch( type ) {
|
||||
case Logger::NoIcon:
|
||||
break;
|
||||
case Logger::Information:
|
||||
trayIcon = QSystemTrayIcon::Information;
|
||||
break;
|
||||
case Logger::SoftError:
|
||||
trayIcon = QSystemTrayIcon::Warning;
|
||||
break;
|
||||
case Logger::Error:
|
||||
case Logger::Critical:
|
||||
trayIcon = QSystemTrayIcon::Critical;
|
||||
break;
|
||||
}
|
||||
|
||||
_tray->showMessage(title, msg, trayIcon);
|
||||
} else {
|
||||
qDebug() << "Tray not ready: " << msg;
|
||||
}
|
||||
}
|
||||
|
||||
void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QString &msg)
|
||||
void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type)
|
||||
{
|
||||
ConfigFile cfg;
|
||||
if (cfg.optionalDesktopNotifications()) {
|
||||
slotShowTrayMessage(title, msg);
|
||||
slotShowTrayMessage(title, msg, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "systray.h"
|
||||
#include "connectionvalidator.h"
|
||||
#include "progressdispatcher.h"
|
||||
#include "logger.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
@@ -32,7 +33,7 @@ class Folder;
|
||||
class SettingsDialog;
|
||||
class SettingsDialogMac;
|
||||
class ShareDialog;
|
||||
class Application;
|
||||
class oCApplication;
|
||||
class LogBrowser;
|
||||
class AccountState;
|
||||
|
||||
@@ -44,7 +45,7 @@ class ownCloudGui : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ownCloudGui(Application *parent = 0);
|
||||
explicit ownCloudGui(oCApplication *parent = 0);
|
||||
|
||||
bool checkAccountExists(bool openSettings);
|
||||
|
||||
@@ -58,8 +59,8 @@ signals:
|
||||
public slots:
|
||||
void setupContextMenu();
|
||||
void slotComputeOverallSyncStatus();
|
||||
void slotShowTrayMessage(const QString &title, const QString &msg);
|
||||
void slotShowOptionalTrayMessage(const QString &title, const QString &msg);
|
||||
void slotShowTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type);
|
||||
void slotShowOptionalTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type);
|
||||
void slotFolderOpenAction( const QString& alias );
|
||||
void slotRebuildRecentMenus();
|
||||
void slotUpdateProgress(const QString &folder, const ProgressInfo& progress);
|
||||
@@ -122,7 +123,7 @@ private:
|
||||
QSignalMapper *_folderOpenActionMapper;
|
||||
QSignalMapper *_recentItemsMapper;
|
||||
|
||||
Application *_app;
|
||||
oCApplication *_app;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -58,6 +58,9 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
|
||||
header << tr("Size");
|
||||
|
||||
_ui->_treeWidget->setHeaderLabels( header );
|
||||
int timestampColumnWidth =
|
||||
_ui->_treeWidget->fontMetrics().width(timeString(QDateTime::currentDateTime()));
|
||||
_ui->_treeWidget->setColumnWidth(0, timestampColumnWidth);
|
||||
_ui->_treeWidget->setColumnWidth(1, 180);
|
||||
_ui->_treeWidget->setColumnCount(5);
|
||||
_ui->_treeWidget->setRootIsDecorated(false);
|
||||
@@ -79,6 +82,10 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
|
||||
_issueItemView = new QTreeWidget(this);
|
||||
header.removeLast();
|
||||
_issueItemView->setHeaderLabels( header );
|
||||
timestampColumnWidth =
|
||||
ActivityItemDelegate::rowHeight() // icon
|
||||
+ _issueItemView->fontMetrics().width(timeString(QDateTime::currentDateTime()));
|
||||
_issueItemView->setColumnWidth(0, timestampColumnWidth);
|
||||
_issueItemView->setColumnWidth(1, 180);
|
||||
_issueItemView->setColumnCount(4);
|
||||
_issueItemView->setRootIsDecorated(false);
|
||||
|
||||
@@ -31,7 +31,7 @@ class SyncResult;
|
||||
namespace Ui {
|
||||
class ProtocolWidget;
|
||||
}
|
||||
class Application;
|
||||
class oCApplication;
|
||||
|
||||
/**
|
||||
* @brief The ProtocolWidget class
|
||||
|
||||
@@ -222,6 +222,7 @@ void SelectiveSyncTreeView::slotUpdateDirectories(QStringList list)
|
||||
}
|
||||
}
|
||||
|
||||
list.sort();
|
||||
foreach (QString path, list) {
|
||||
auto size = job ? job->_sizes.value(path) : 0;
|
||||
path.remove(pathToRemove);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Ui {
|
||||
class SettingsDialog;
|
||||
}
|
||||
class AccountSettings;
|
||||
class Application;
|
||||
class oCApplication;
|
||||
class FolderMan;
|
||||
class ownCloudGui;
|
||||
class ActivitySettings;
|
||||
|
||||
@@ -98,17 +98,6 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account,
|
||||
return;
|
||||
}
|
||||
|
||||
// error label, red box and stuff
|
||||
_ui->errorLabel->setLineWidth(1);
|
||||
_ui->errorLabel->setFrameStyle(QFrame::Plain);
|
||||
|
||||
QPalette errPalette = _ui->errorLabel->palette();
|
||||
errPalette.setColor(QPalette::Active, QPalette::Base, QColor(0xaa, 0x4d, 0x4d));
|
||||
errPalette.setColor(QPalette::Active, QPalette::WindowText, QColor(0xaa, 0xaa, 0xaa));
|
||||
|
||||
_ui->errorLabel->setPalette(errPalette);
|
||||
_ui->errorLabel->setFrameShape(QFrame::Box);
|
||||
_ui->errorLabel->setContentsMargins(QMargins(12,12,12,12));
|
||||
_ui->errorLabel->hide();
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,43 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>123</red>
|
||||
<green>121</green>
|
||||
<blue>134</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
|
||||
@@ -99,6 +99,9 @@ ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
|
||||
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
|
||||
_ui->errorLabel->hide();
|
||||
|
||||
// Setup the sharee search progress indicator
|
||||
_ui->shareeHorizontalLayout->addWidget(&_pi_sharee);
|
||||
}
|
||||
|
||||
ShareUserGroupWidget::~ShareUserGroupWidget()
|
||||
@@ -147,6 +150,7 @@ void ShareUserGroupWidget::slotLineEditReturn()
|
||||
void ShareUserGroupWidget::searchForSharees()
|
||||
{
|
||||
_completionTimer.stop();
|
||||
_pi_sharee.startAnimation();
|
||||
ShareeModel::ShareeSet blacklist;
|
||||
|
||||
// Add the current user to _sharees since we can't share with ourself
|
||||
@@ -158,7 +162,6 @@ void ShareUserGroupWidget::searchForSharees()
|
||||
}
|
||||
_ui->errorLabel->hide();
|
||||
_completerModel->fetch(_ui->shareeLineEdit->text(), blacklist);
|
||||
|
||||
}
|
||||
|
||||
void ShareUserGroupWidget::getShares()
|
||||
@@ -218,6 +221,7 @@ void ShareUserGroupWidget::slotAdjustScrollWidgetSize()
|
||||
|
||||
void ShareUserGroupWidget::slotShareesReady()
|
||||
{
|
||||
_pi_sharee.stopAnimation();
|
||||
if (_completerModel->rowCount() == 0) {
|
||||
displayError(0, tr("No results for '%1'").arg(_completerModel->currentSearch()));
|
||||
return;
|
||||
@@ -274,6 +278,7 @@ void ShareUserGroupWidget::slotCompleterHighlighted(const QModelIndex & index)
|
||||
|
||||
void ShareUserGroupWidget::displayError(int code, const QString& message)
|
||||
{
|
||||
_pi_sharee.stopAnimation();
|
||||
qDebug() << "Error from server" << code << message;
|
||||
_ui->errorLabel->setText(message);
|
||||
_ui->errorLabel->show();
|
||||
|
||||
@@ -129,6 +129,8 @@ private:
|
||||
bool _isFile;
|
||||
bool _disableCompleterActivated; // in order to avoid that we share the contents twice
|
||||
ShareManager *_manager;
|
||||
|
||||
QProgressIndicator _pi_sharee;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>457</width>
|
||||
<height>188</height>
|
||||
<height>164</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -15,14 +15,55 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="shareeLineEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Share with users or groups ...</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="shareeHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="shareeLineEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Share with users or groups ...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="errorLabel">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>123</red>
|
||||
<green>121</green>
|
||||
<blue>134</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Placeholder for Error text</string>
|
||||
</property>
|
||||
@@ -50,8 +91,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>441</width>
|
||||
<height>98</height>
|
||||
<width>437</width>
|
||||
<height>94</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3"/>
|
||||
|
||||
+20
-14
@@ -67,7 +67,8 @@ SocketApi::SocketApi(QObject* parent)
|
||||
|
||||
if (Utility::isWindows()) {
|
||||
socketPath = QLatin1String("\\\\.\\pipe\\")
|
||||
+ QLatin1String("ownCloud");
|
||||
+ QLatin1String("ownCloud") + '\\'
|
||||
+ QString::fromLocal8Bit(qgetenv("USERNAME"));
|
||||
// TODO: once the windows extension supports multiple
|
||||
// client connections, switch back to the theme name
|
||||
// See issue #2388
|
||||
@@ -140,8 +141,10 @@ void SocketApi::slotNewConnection()
|
||||
_listeners.append(socket);
|
||||
|
||||
foreach( Folder *f, FolderMan::instance()->map() ) {
|
||||
QString message = buildRegisterPathMessage(f->path());
|
||||
sendMessage(socket, message);
|
||||
if (f->canSync()) {
|
||||
QString message = buildRegisterPathMessage(f->path());
|
||||
sendMessage(socket, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,6 +183,10 @@ void SocketApi::slotReadSocket()
|
||||
|
||||
void SocketApi::slotRegisterPath( const QString& alias )
|
||||
{
|
||||
// Make sure not to register twice to each connected client
|
||||
if (_registeredAliases.contains(alias))
|
||||
return;
|
||||
|
||||
Folder *f = FolderMan::instance()->folder(alias);
|
||||
if (f) {
|
||||
QString message = buildRegisterPathMessage(f->path());
|
||||
@@ -187,13 +194,20 @@ void SocketApi::slotRegisterPath( const QString& alias )
|
||||
sendMessage(socket, message);
|
||||
}
|
||||
}
|
||||
|
||||
_registeredAliases.insert(alias);
|
||||
}
|
||||
|
||||
void SocketApi::slotUnregisterPath( const QString& alias )
|
||||
{
|
||||
if (!_registeredAliases.contains(alias))
|
||||
return;
|
||||
|
||||
Folder *f = FolderMan::instance()->folder(alias);
|
||||
if (f)
|
||||
broadcastMessage(QLatin1String("UNREGISTER_PATH"), f->path(), QString::null, true );
|
||||
|
||||
_registeredAliases.remove(alias);
|
||||
}
|
||||
|
||||
void SocketApi::slotUpdateFolderView(Folder *f)
|
||||
@@ -274,8 +288,6 @@ void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, QIODevic
|
||||
|
||||
void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice* socket)
|
||||
{
|
||||
const QString nopString("NOP");
|
||||
|
||||
if( !socket ) {
|
||||
qDebug() << "No valid socket object.";
|
||||
return;
|
||||
@@ -288,18 +300,12 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice*
|
||||
Folder* syncFolder = FolderMan::instance()->folderForPath( argument );
|
||||
if (!syncFolder) {
|
||||
// this can happen in offline mode e.g.: nothing to worry about
|
||||
statusString = nopString;
|
||||
statusString = QLatin1String("NOP");
|
||||
} else {
|
||||
const QString file = QDir::cleanPath(argument).mid(syncFolder->cleanPath().length()+1);
|
||||
SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(file);
|
||||
|
||||
// future: Send more specific states for paused, disconnected etc.
|
||||
if( syncFolder->syncPaused() || !syncFolder->accountState()->isConnected() ) {
|
||||
statusString = nopString;
|
||||
} else {
|
||||
SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(file);
|
||||
|
||||
statusString = fileStatus.toSocketAPIString();
|
||||
}
|
||||
statusString = fileStatus.toSocketAPIString();
|
||||
}
|
||||
|
||||
const QString message = QLatin1String("STATUS:") % statusString % QLatin1Char(':') % QDir::toNativeSeparators(argument);
|
||||
|
||||
@@ -77,6 +77,7 @@ private:
|
||||
Q_INVOKABLE void command_SHARE_MENU_TITLE(const QString& argument, QIODevice* socket);
|
||||
QString buildRegisterPathMessage(const QString& path);
|
||||
|
||||
QSet<QString> _registeredAliases;
|
||||
QList<QIODevice*> _listeners;
|
||||
SocketApiServer _localServer;
|
||||
};
|
||||
|
||||
+53
-1
@@ -12,9 +12,15 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_LIBSNORE
|
||||
#include <libsnore/application.h>
|
||||
#include <libsnore/notification/icon.h>
|
||||
#endif
|
||||
|
||||
#include "systray.h"
|
||||
#include "theme.h"
|
||||
#include <QDebug>
|
||||
#include <QPointer>
|
||||
|
||||
#ifdef USE_FDO_NOTIFICATIONS
|
||||
#include <QDBusConnection>
|
||||
@@ -28,8 +34,54 @@
|
||||
|
||||
namespace OCC {
|
||||
|
||||
void Systray::showMessage(const QString & title, const QString & message, MessageIcon icon, int millisecondsTimeoutHint)
|
||||
Systray::Systray( )
|
||||
{
|
||||
#ifdef HAVE_LIBSNORE
|
||||
Snore::SnoreCore &snore = Snore::SnoreCore::instance();
|
||||
snore.loadPlugins( Snore::SnorePlugin::Backend | Snore::SnorePlugin::SecondaryBackend );
|
||||
snore.setDefaultSettingsValue("Silent", true, Snore::LocalSetting );
|
||||
|
||||
_application = Snore::Application( Theme::instance()->appName(), Theme::instance()->applicationIcon() );
|
||||
_application.hints().setValue( "use-markup", true );
|
||||
_application.hints().setValue( "windows-app-id", Theme::instance()->appName() );
|
||||
_application.hints().setValue( "desktop-entry", Theme::instance()->appNameGUI() );
|
||||
_application.hints().setValue( "tray-icon", qVariantFromValue(QPointer<QSystemTrayIcon>(this)));
|
||||
|
||||
// register the Alerts.
|
||||
Snore::Alert alert( Theme::instance()->appNameGUI(), QIcon() );
|
||||
_alerts.insert( QSystemTrayIcon::NoIcon, alert);
|
||||
_application.addAlert(alert);
|
||||
Snore::Alert alert2( Theme::instance()->appNameGUI(), Theme::instance()->syncStateIcon(SyncResult::Success, false ));
|
||||
_alerts.insert( QSystemTrayIcon::Information, alert2);
|
||||
_application.addAlert(alert2);
|
||||
Snore::Alert alert3( Theme::instance()->appNameGUI(), Theme::instance()->syncStateIcon(SyncResult::Problem, false ));
|
||||
_alerts.insert( QSystemTrayIcon::Warning, alert3);
|
||||
_application.addAlert(alert3);
|
||||
Snore::Alert alert4( Theme::instance()->appNameGUI(), Theme::instance()->syncStateIcon(SyncResult::Error, false ));
|
||||
_alerts.insert( QSystemTrayIcon::Critical, alert4);
|
||||
_application.addAlert(alert4);
|
||||
|
||||
snore.registerApplication( _application );
|
||||
snore.setDefaultApplication( _application );
|
||||
|
||||
// connect( &snore, SIGNAL( actionInvoked( Snore::Notification ) ), this, SLOT( slotActionInvoked( Snore::Notification ) ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Systray::showMessage(const QString & title, const QString & message, MessageIcon icon,
|
||||
int millisecondsTimeoutHint)
|
||||
{
|
||||
#ifdef HAVE_LIBSNORE
|
||||
Snore::Alert a = _alerts[NoIcon];
|
||||
if( _alerts.contains(icon) ) {
|
||||
a = _alerts[icon];
|
||||
}
|
||||
|
||||
Snore::Notification n( _application , a, title, message, a.icon() );
|
||||
Snore::SnoreCore::instance().broadcastNotification( n );
|
||||
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef USE_FDO_NOTIFICATIONS
|
||||
if(QDBusInterface(NOTIFICATIONS_SERVICE, NOTIFICATIONS_PATH, NOTIFICATIONS_IFACE).isValid()) {
|
||||
|
||||
+15
-1
@@ -15,8 +15,13 @@
|
||||
#ifndef SYSTRAY_H
|
||||
#define SYSTRAY_H
|
||||
|
||||
#include "logger.h"
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#ifdef HAVE_LIBSNORE
|
||||
#include <libsnore/snore.h>
|
||||
#endif
|
||||
|
||||
class QIcon;
|
||||
|
||||
namespace OCC {
|
||||
@@ -34,8 +39,17 @@ class Systray : public QSystemTrayIcon
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
void showMessage(const QString & title, const QString & message, MessageIcon icon = Information, int millisecondsTimeoutHint = 10000);
|
||||
explicit Systray();
|
||||
|
||||
void showMessage(const QString & title, const QString & message, MessageIcon icon = Information,
|
||||
int millisecondsTimeoutHint = 10000);
|
||||
void setToolTip(const QString &tip);
|
||||
|
||||
private:
|
||||
#ifdef HAVE_LIBSNORE
|
||||
Snore::Application _application;
|
||||
QHash<QSystemTrayIcon::MessageIcon, Snore::Alert> _alerts;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -219,6 +219,7 @@ void ConnectionValidator::slotAuthSuccess()
|
||||
void ConnectionValidator::checkServerCapabilities()
|
||||
{
|
||||
JsonApiJob *job = new JsonApiJob(_account, QLatin1String("ocs/v1.php/cloud/capabilities"), this);
|
||||
job->setTimeout(timeoutToUseMsec);
|
||||
QObject::connect(job, SIGNAL(jsonReceived(QVariantMap, int)), this, SLOT(slotCapabilitiesRecieved(QVariantMap)));
|
||||
job->start();
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ extern "C" {
|
||||
#include "csync.h"
|
||||
#include "vio/csync_vio_local.h"
|
||||
#include "std/c_path.h"
|
||||
#include "std/c_string.h"
|
||||
}
|
||||
|
||||
namespace OCC {
|
||||
@@ -589,4 +590,38 @@ bool FileSystem::remove(const QString &fileName, QString *errorString)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileSystem::isFileLocked(const QString& fileName)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
mbchar_t *wuri = c_utf8_path_to_locale(fileName.toUtf8());
|
||||
|
||||
// Check if file exists
|
||||
DWORD attr = GetFileAttributesW(wuri);
|
||||
if (attr != INVALID_FILE_ATTRIBUTES) {
|
||||
// Try to open the file with as much access as possible..
|
||||
HANDLE win_h = CreateFileW(
|
||||
wuri,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
|
||||
NULL);
|
||||
|
||||
c_free_locale_string(wuri);
|
||||
if (win_h == INVALID_HANDLE_VALUE) {
|
||||
/* could not be opened, so locked? */
|
||||
/* 32 == ERROR_SHARING_VIOLATION */
|
||||
return true;
|
||||
} else {
|
||||
CloseHandle(win_h);
|
||||
}
|
||||
} else {
|
||||
c_free_locale_string(wuri);
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(fileName);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -182,6 +182,11 @@ QByteArray OWNCLOUDSYNC_EXPORT calcAdler32( const QString& fileName );
|
||||
*/
|
||||
QString OWNCLOUDSYNC_EXPORT makeConflictFileName(const QString &fn, const QDateTime &dt);
|
||||
|
||||
/**
|
||||
* Returns true when a file is locked. (Windows only)
|
||||
*/
|
||||
bool OWNCLOUDSYNC_EXPORT isFileLocked(const QString& fileName);
|
||||
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -74,14 +74,14 @@ Logger::~Logger() {
|
||||
}
|
||||
|
||||
|
||||
void Logger::postGuiLog(const QString &title, const QString &message)
|
||||
void Logger::postGuiLog(const QString &title, const QString &message, NotificationType type )
|
||||
{
|
||||
emit guiLog(title, message);
|
||||
emit guiLog(title, message, type);
|
||||
}
|
||||
|
||||
void Logger::postOptionalGuiLog(const QString &title, const QString &message)
|
||||
void Logger::postOptionalGuiLog(const QString &title, const QString &message, NotificationType type )
|
||||
{
|
||||
emit optionalGuiLog(title, message);
|
||||
emit optionalGuiLog(title, message, type);
|
||||
}
|
||||
|
||||
void Logger::postGuiMessage(const QString &title, const QString &message)
|
||||
|
||||
+12
-4
@@ -45,6 +45,14 @@ class OWNCLOUDSYNC_EXPORT Logger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum NotificationType {
|
||||
NoIcon = 0,
|
||||
Information,
|
||||
SoftError,
|
||||
Error,
|
||||
Critical
|
||||
};
|
||||
|
||||
|
||||
bool isNoop() const;
|
||||
void log(Log log);
|
||||
@@ -57,8 +65,8 @@ public:
|
||||
|
||||
static Logger* instance();
|
||||
|
||||
void postGuiLog(const QString& title, const QString& message);
|
||||
void postOptionalGuiLog(const QString& title, const QString& message);
|
||||
void postGuiLog(const QString& title, const QString& message, NotificationType type = Information);
|
||||
void postOptionalGuiLog(const QString& title, const QString& message, NotificationType type = Information);
|
||||
void postGuiMessage(const QString& title, const QString& message);
|
||||
|
||||
void setLogFile( const QString & name );
|
||||
@@ -68,9 +76,9 @@ public:
|
||||
|
||||
signals:
|
||||
void newLog(const QString&);
|
||||
void guiLog(const QString&, const QString&);
|
||||
void guiLog(const QString&, const QString&, Logger::NotificationType type);
|
||||
void guiMessage(const QString&, const QString&);
|
||||
void optionalGuiLog(const QString&, const QString&);
|
||||
void optionalGuiLog(const QString&, const QString&, Logger::NotificationType type);
|
||||
|
||||
public slots:
|
||||
void enterNextLogFile();
|
||||
|
||||
@@ -369,6 +369,9 @@ signals:
|
||||
void progress(const SyncFileItem&, quint64 bytes);
|
||||
void finished();
|
||||
|
||||
/** Emitted when propagation has problems with a locked file. */
|
||||
void seenLockedFile(const QString &fileName);
|
||||
|
||||
private:
|
||||
|
||||
AccountPtr _account;
|
||||
@@ -376,6 +379,11 @@ private:
|
||||
/** Stores the time since a job touched a file. */
|
||||
QHash<QString, QElapsedTimer> _touchedFiles;
|
||||
mutable QMutex _touchedFilesMutex;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
// access to signals which are protected in Qt4
|
||||
friend class PropagateDownloadFileQNAM;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -546,6 +546,14 @@ void PropagateDownloadFileQNAM::slotGetFinished()
|
||||
return;
|
||||
}
|
||||
|
||||
if (_tmpFile.size() == 0 && _item->_size > 0) {
|
||||
FileSystem::remove(_tmpFile.fileName());
|
||||
done(SyncFileItem::NormalError,
|
||||
tr("The downloaded file is empty despite the server announced it should have been %1.")
|
||||
.arg(Utility::octetsToString(_item->_size)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Do checksum validation for the download. If there is no checksum header, the validator
|
||||
// will also emit the validated() signal to continue the flow in slot transmissionChecksumValidated()
|
||||
// as this is (still) also correct.
|
||||
@@ -696,7 +704,14 @@ void PropagateDownloadFileQNAM::downloadFinished()
|
||||
QString renameError;
|
||||
QString conflictFileName = FileSystem::makeConflictFileName(fn, Utility::qDateTimeFromTime_t(_item->_modtime));
|
||||
if (!FileSystem::rename(fn, conflictFileName, &renameError)) {
|
||||
//If the rename fails, don't replace it.
|
||||
// If the rename fails, don't replace it.
|
||||
|
||||
// If the file is locked, we want to retry this sync when it
|
||||
// becomes available again.
|
||||
if (FileSystem::isFileLocked(fn)) {
|
||||
emit _propagator->seenLockedFile(fn);
|
||||
}
|
||||
|
||||
done(SyncFileItem::SoftError, renameError);
|
||||
return;
|
||||
}
|
||||
@@ -756,7 +771,14 @@ void PropagateDownloadFileQNAM::downloadFinished()
|
||||
_propagator->_journal->commit("download finished");
|
||||
}
|
||||
|
||||
_propagator->_anotherSyncNeeded = true;
|
||||
// If the file is locked, we want to retry this sync when it
|
||||
// becomes available again, otherwise try again directly
|
||||
if (FileSystem::isFileLocked(fn)) {
|
||||
emit _propagator->seenLockedFile(fn);
|
||||
} else {
|
||||
_propagator->_anotherSyncNeeded = true;
|
||||
}
|
||||
|
||||
done(SyncFileItem::SoftError, error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -933,6 +933,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
|
||||
connect(_propagator.data(), SIGNAL(progress(const SyncFileItem &,quint64)),
|
||||
this, SLOT(slotProgress(const SyncFileItem &,quint64)));
|
||||
connect(_propagator.data(), SIGNAL(finished()), this, SLOT(slotFinished()), Qt::QueuedConnection);
|
||||
connect(_propagator.data(), SIGNAL(seenLockedFile(QString)), SIGNAL(seenLockedFile(QString)));
|
||||
|
||||
// apply the network limits to the propagator
|
||||
setNetworkLimits(_uploadLimit, _downloadLimit);
|
||||
@@ -1341,7 +1342,7 @@ SyncFileItem* SyncEngine::findSyncItem(const QString &fileName) const
|
||||
{
|
||||
Q_FOREACH(const SyncFileItemPtr &item, _syncedItems) {
|
||||
// Directories will appear in this list as well, and will get their status set once all children have been propagated
|
||||
if ((item->_file == fileName || item->_renameTarget == fileName))
|
||||
if ((item->_file == fileName || (!item->_renameTarget.isEmpty() && item->_renameTarget == fileName)))
|
||||
return item.data();
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -143,6 +143,12 @@ signals:
|
||||
// A new folder was discovered and was not synced because of the confirmation feature
|
||||
void newBigFolder(const QString &folder);
|
||||
|
||||
/** Emitted when propagation has problems with a locked file.
|
||||
*
|
||||
* Forwarded from OwncloudPropagator::seenLockedFile.
|
||||
*/
|
||||
void seenLockedFile(const QString &fileName);
|
||||
|
||||
private slots:
|
||||
void slotRootEtagReceived(const QString &);
|
||||
void slotItemCompleted(const SyncFileItem& item, const PropagatorJob & job);
|
||||
|
||||
@@ -28,14 +28,15 @@ static SyncFileStatus::SyncFileStatusTag lookupProblem(const QString &pathToMatc
|
||||
// qDebug() << Q_FUNC_INFO << pathToMatch << severity << problemPath;
|
||||
if (problemPath == pathToMatch) {
|
||||
return severity;
|
||||
} else if (severity == SyncFileStatus::StatusError && problemPath.startsWith(pathToMatch) && problemPath.at(pathToMatch.size()) == '/') {
|
||||
Q_ASSERT(!pathToMatch.endsWith('/'));
|
||||
} else if (severity == SyncFileStatus::StatusError
|
||||
&& problemPath.startsWith(pathToMatch)
|
||||
&& (pathToMatch.isEmpty() || problemPath.at(pathToMatch.size()) == '/')) {
|
||||
return SyncFileStatus::StatusWarning;
|
||||
} else if (!problemPath.startsWith(pathToMatch)) {
|
||||
// Starting at lower_bound we get the first path that is not smaller,
|
||||
// since: "/a/" < "/a/aa" < "/a/aa/aaa" < "/a/ab/aba"
|
||||
// If problemMap keys are ["/a/aa/aaa", "/a/ab/aba"] and pathToMatch == "/a/aa",
|
||||
// lower_bound(pathToMatch) will point to "/a/aa/aaa", and the moment that
|
||||
// since: "a/" < "a/aa" < "a/aa/aaa" < "a/ab/aba"
|
||||
// If problemMap keys are ["a/aa/aaa", "a/ab/aba"] and pathToMatch == "a/aa",
|
||||
// lower_bound(pathToMatch) will point to "a/aa/aaa", and the moment that
|
||||
// problemPath.startsWith(pathToMatch) == false, we know that we've looked
|
||||
// at everything that interest us.
|
||||
break;
|
||||
@@ -68,54 +69,27 @@ static inline bool showWarningInSocketApi(const SyncFileItem& item)
|
||||
|| status == SyncFileItem::Restoration;
|
||||
}
|
||||
|
||||
static inline bool showSyncInSocketApi( const SyncFileItem& item)
|
||||
{
|
||||
const auto inst = item._instruction;
|
||||
return inst == CSYNC_INSTRUCTION_NEW;
|
||||
}
|
||||
|
||||
SyncFileStatusTracker::SyncFileStatusTracker(SyncEngine *syncEngine)
|
||||
: _syncEngine(syncEngine)
|
||||
{
|
||||
connect(syncEngine, SIGNAL(aboutToPropagate(SyncFileItemVector&)),
|
||||
this, SLOT(slotAboutToPropagate(SyncFileItemVector&)));
|
||||
SLOT(slotAboutToPropagate(SyncFileItemVector&)));
|
||||
connect(syncEngine, SIGNAL(itemCompleted(const SyncFileItem&, const PropagatorJob&)),
|
||||
this, SLOT(slotItemCompleted(const SyncFileItem&)));
|
||||
SLOT(slotItemCompleted(const SyncFileItem&)));
|
||||
connect(syncEngine, SIGNAL(started()), SLOT(slotClearDirtyPaths()));
|
||||
connect(syncEngine, SIGNAL(started()), SLOT(slotSyncEngineRunningChanged()));
|
||||
connect(syncEngine, SIGNAL(finished(bool)), SLOT(slotSyncEngineRunningChanged()));
|
||||
}
|
||||
|
||||
SyncFileStatus SyncFileStatusTracker::rootStatus()
|
||||
SyncFileItem SyncFileStatusTracker::rootSyncFileItem()
|
||||
{
|
||||
/* Possible values for the status:
|
||||
enum SyncFileStatusTag {
|
||||
StatusNone,
|
||||
StatusSync,
|
||||
StatusWarning,
|
||||
StatusUpToDate,
|
||||
StatusError,
|
||||
};
|
||||
*/
|
||||
SyncFileStatus status = SyncFileStatus::StatusUpToDate;
|
||||
|
||||
if( !_syncEngine ) return SyncFileStatus::StatusNone;
|
||||
|
||||
if( _syncEngine->isSyncRunning() ) {
|
||||
status = SyncFileStatus::StatusSync;
|
||||
} else {
|
||||
// sync is not running. Check dirty list and _syncProblems
|
||||
int errs = 0;
|
||||
for (auto it = _syncProblems.begin(); it != _syncProblems.end(); ++it) {
|
||||
if( it->second == SyncFileStatus::StatusError ) {
|
||||
errs ++;
|
||||
break; // stop if an error found at all.
|
||||
}
|
||||
}
|
||||
if( errs ) {
|
||||
status = SyncFileStatus::StatusWarning; // some files underneath had errors
|
||||
}
|
||||
// Only warnings do not change the root emblem away from ok.
|
||||
}
|
||||
return status;
|
||||
|
||||
SyncFileItem fakeRootItem;
|
||||
// It's is not entirely correct to use the sync's status as we'll show the root folder as
|
||||
// syncing even though no child might end up being propagated, but will give us something
|
||||
// better than always UpToDate for now.
|
||||
fakeRootItem._status = _syncEngine->isSyncRunning() ? SyncFileItem::NoStatus : SyncFileItem::Success;
|
||||
fakeRootItem._isDirectory = true;
|
||||
return fakeRootItem;
|
||||
}
|
||||
|
||||
SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& systemFileName)
|
||||
@@ -127,10 +101,10 @@ SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& systemFileName)
|
||||
}
|
||||
|
||||
if( fileName.isEmpty() ) {
|
||||
// this is the root sync folder.
|
||||
return rootStatus();
|
||||
|
||||
// This is the root sync folder, it doesn't have an entry in the database and won't be walked by csync, so create one manually.
|
||||
return syncFileItemStatus(rootSyncFileItem());
|
||||
}
|
||||
|
||||
// The SyncEngine won't notify us at all for CSYNC_FILE_SILENTLY_EXCLUDED
|
||||
// and CSYNC_FILE_EXCLUDE_AND_REMOVE excludes. Even though it's possible
|
||||
// that the status of CSYNC_FILE_EXCLUDE_LIST excludes will change if the user
|
||||
@@ -143,20 +117,34 @@ SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& systemFileName)
|
||||
return SyncFileStatus(SyncFileStatus::StatusWarning);
|
||||
}
|
||||
|
||||
if ( _dirtyPaths.contains(fileName) )
|
||||
return SyncFileStatus::StatusSync;
|
||||
|
||||
SyncFileItem* item = _syncEngine->findSyncItem(fileName);
|
||||
if (item) {
|
||||
return fileStatus(*item);
|
||||
return syncFileItemStatus(*item);
|
||||
}
|
||||
|
||||
// If we're not currently syncing that file, look it up in the database to know if it's shared
|
||||
SyncJournalFileRecord rec = _syncEngine->journal()->getFileRecord(fileName);
|
||||
if (rec.isValid()) {
|
||||
return fileStatus(rec.toSyncFileItem());
|
||||
return syncFileItemStatus(rec.toSyncFileItem());
|
||||
}
|
||||
// Must be a new file, wait for the filesystem watcher to trigger a sync
|
||||
return SyncFileStatus();
|
||||
}
|
||||
|
||||
void SyncFileStatusTracker::slotPathTouched(const QString& fileName)
|
||||
{
|
||||
QString folderPath = _syncEngine->localPath();
|
||||
Q_ASSERT(fileName.startsWith(folderPath));
|
||||
|
||||
QString localPath = fileName.mid(folderPath.size());
|
||||
_dirtyPaths.insert(localPath);
|
||||
|
||||
emit fileStatusChanged(fileName, SyncFileStatus::StatusSync);
|
||||
}
|
||||
|
||||
void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector& items)
|
||||
{
|
||||
std::map<QString, SyncFileStatus::SyncFileStatusTag> oldProblems;
|
||||
@@ -169,10 +157,8 @@ void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector& items)
|
||||
_syncProblems[item->_file] = SyncFileStatus::StatusError;
|
||||
} else if (showWarningInSocketApi(*item)) {
|
||||
_syncProblems[item->_file] = SyncFileStatus::StatusWarning;
|
||||
} else if( showSyncInSocketApi(*item)) {
|
||||
_syncProblems[item->_file] = SyncFileStatus::StatusSync;
|
||||
}
|
||||
emit fileStatusChanged(getSystemDestination(*item), fileStatus(*item));
|
||||
emit fileStatusChanged(getSystemDestination(*item), syncFileItemStatus(*item));
|
||||
}
|
||||
|
||||
// Make sure to push any status that might have been resolved indirectly since the last sync
|
||||
@@ -197,22 +183,33 @@ void SyncFileStatusTracker::slotItemCompleted(const SyncFileItem &item)
|
||||
invalidateParentPaths(item.destination());
|
||||
} else if (showWarningInSocketApi(item)) {
|
||||
_syncProblems[item._file] = SyncFileStatus::StatusWarning;
|
||||
} else if (showSyncInSocketApi(item)) {
|
||||
// new items that were in state sync can now be erased
|
||||
_syncProblems.erase(item._file);
|
||||
} else {
|
||||
// There is currently no situation where an error status set during discovery/update is fixed by propagation.
|
||||
Q_ASSERT(_syncProblems.find(item._file) == _syncProblems.end());
|
||||
}
|
||||
|
||||
emit fileStatusChanged(getSystemDestination(item), fileStatus(item));
|
||||
emit fileStatusChanged(getSystemDestination(item), syncFileItemStatus(item));
|
||||
}
|
||||
|
||||
SyncFileStatus SyncFileStatusTracker::fileStatus(const SyncFileItem& item)
|
||||
void SyncFileStatusTracker::slotSyncEngineRunningChanged()
|
||||
{
|
||||
emit fileStatusChanged(_syncEngine->localPath(), syncFileItemStatus(rootSyncFileItem()));
|
||||
}
|
||||
|
||||
void SyncFileStatusTracker::slotClearDirtyPaths()
|
||||
{
|
||||
// We just assume that during a sync all dirty statuses will be resolved
|
||||
// one way or the other.
|
||||
_dirtyPaths.clear();
|
||||
}
|
||||
|
||||
SyncFileStatus SyncFileStatusTracker::syncFileItemStatus(const SyncFileItem& item)
|
||||
{
|
||||
// Hack to know if the item was taken from the sync engine (Sync), or from the database (UpToDate)
|
||||
bool waitingForPropagation = item._direction != SyncFileItem::None && item._status == SyncFileItem::NoStatus;
|
||||
|
||||
// Mark any directory in the SyncEngine's items as syncing, this is currently how we mark parent directories
|
||||
// of currently syncing items since the PropagateDirectory job will mark the directorie's SyncFileItem::_status as Success
|
||||
// once all child jobs have been completed.
|
||||
bool waitingForPropagation = (item._isDirectory || item._direction != SyncFileItem::None) && item._status == SyncFileItem::NoStatus;
|
||||
SyncFileStatus status(SyncFileStatus::StatusUpToDate);
|
||||
if (waitingForPropagation) {
|
||||
status.set(SyncFileStatus::StatusSync);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "syncfileitem.h"
|
||||
#include "syncfilestatus.h"
|
||||
#include <map>
|
||||
#include <QSet>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
@@ -36,16 +37,21 @@ public:
|
||||
explicit SyncFileStatusTracker(SyncEngine* syncEngine);
|
||||
SyncFileStatus fileStatus(const QString& systemFileName);
|
||||
|
||||
public slots:
|
||||
void slotPathTouched(const QString& fileName);
|
||||
|
||||
signals:
|
||||
void fileStatusChanged(const QString& systemFileName, SyncFileStatus fileStatus);
|
||||
|
||||
private slots:
|
||||
void slotAboutToPropagate(SyncFileItemVector& items);
|
||||
void slotItemCompleted(const SyncFileItem& item);
|
||||
void slotSyncEngineRunningChanged();
|
||||
void slotClearDirtyPaths();
|
||||
|
||||
private:
|
||||
SyncFileStatus fileStatus(const SyncFileItem& item);
|
||||
SyncFileStatus rootStatus();
|
||||
SyncFileStatus syncFileItemStatus(const SyncFileItem& item);
|
||||
SyncFileItem rootSyncFileItem();
|
||||
|
||||
void invalidateParentPaths(const QString& path);
|
||||
QString getSystemDestination(const SyncFileItem& syncEnginePath);
|
||||
@@ -53,6 +59,7 @@ private:
|
||||
SyncEngine* _syncEngine;
|
||||
|
||||
std::map<QString, SyncFileStatus::SyncFileStatusTag> _syncProblems;
|
||||
QSet<QString> _dirtyPaths;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ list(APPEND FolderMan_SRC ../src/gui/folder.cpp )
|
||||
list(APPEND FolderMan_SRC ../src/gui/socketapi.cpp )
|
||||
list(APPEND FolderMan_SRC ../src/gui/accountstate.cpp )
|
||||
list(APPEND FolderMan_SRC ../src/gui/syncrunfilelog.cpp )
|
||||
list(APPEND FolderMan_SRC ../src/gui/lockwatcher.cpp )
|
||||
list(APPEND FolderMan_SRC ${FolderWatcher_SRC})
|
||||
list(APPEND FolderMan_SRC stub.cpp )
|
||||
#include_directories(${QTKEYCHAIN_INCLUDE_DIR})
|
||||
|
||||
+193
-188
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+178
-173
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+182
-177
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+179
-174
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+199
-194
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+168
-163
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+166
-161
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+178
-173
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+174
-169
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+165
-160
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+168
-163
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
Referência em uma Nova Issue
Bloquear um usuário