Comparar commits

..

49 Commits

Autor SHA1 Mensagem Data
Klaas Freitag 098b603879 TrayNotification: Add Alert classes for error, warning etc.
For that, the logger needs to pass through the notification
type that it wants to display.

The snore notifications show specific icons for each type.
2016-05-06 17:26:40 +02:00
Klaas Freitag 7c3b3d648b Systray: Broadcast notifications using libsnore if available. 2016-05-06 14:50:09 +02:00
Klaas Freitag 778aca386c CMake: Find and use libsnore for cross platform notifications. 2016-05-06 14:50:09 +02:00
Klaas Freitag 0758b2cf61 Application: Renamed to oCApplication to avoid clashes
with other projeccts that define a class Application as well, such
as the snorenotify lib.
2016-05-06 14:50:09 +02:00
Jenkins for ownCloud d7804d8df3 [tx-robot] updated from transifex 2016-05-06 02:19:00 -04:00
Olivier Goffart 3d9d106bb1 Dolphin plugin: fix build with branding
Make sure that the name of the _export.h file is the same no matter the plugin
2016-05-04 14:19:18 +02:00
Jenkins for ownCloud 15dc3408ef [tx-robot] updated from transifex 2016-05-04 02:19:15 -04:00
Markus Goetz 928643f597 NSIS: Properly uninstall both x64 and x86 DLLs #4762
Viel hilft viel ;-)
2016-05-03 18:35:01 +02:00
Markus Goetz 7110091fdd Qt patches: Update with information about Qt 5.6 2016-05-03 15:16:07 +02:00
Jocelyn Turcotte 064c2b678a Merge branch 'overlayIconFixes' into 2.2 (#4765) 2016-05-03 13:04:34 +02:00
Jocelyn Turcotte e58739de00 [osx] Fix missing overlay icons on client startup
Since the statuses are cached and that we can't invalidate the cache,
sending NOP would need to be overwritten by the default OK status
once the client successfully connected. But instead of remembering
which files we NOPed, rather wait until we are ready to sync before
sending the REGISTER_PATH message to the socket API client. It will
also prevent the client from sending unnecessary RETRIEVE_FILE_STATUS
requests.

Also remove AccountState::canSync, since it does the same as
isConnected and syncing is not an account responsibility.
2016-05-03 13:01:51 +02:00
Jocelyn Turcotte 7c2fdee78b Avoid a SyncFileStatusTracker private overload with the same name
Having an overload as a private function in the same class makes the
code harder to follow. Rename the private fileStatus to syncFileItemStatus.
2016-05-03 13:01:51 +02:00
Jocelyn Turcotte 7bfe46962f Simplify the root status logic
Go through fileStatus like other cases to make sure that all use
cases go through the same code path. This also makes sure to use
lookupProblem which will use lower_bound which is more efficient
for larger sets of sync problems.

This also fixes the issue with lookupProblem that prevented it to
properly match an empty pathToMatch, caused by the fact that the
problem map contains relative paths not starting with a slash.
2016-05-03 13:01:51 +02:00
Jocelyn Turcotte 32b3023a8e Fix the root item sync status #4682
Make sure that we push the new status when the status of the SyncEngine
changed. SyncEngine::started comes a bit late, only when the propagation
starts, although it's better in this case since child folders will
only switch to Sync in aboutToPropagate.

Also fix an issue with SyncEngine::findSyncItem when using an empty
fileName; this would match and return the wrong item, even though
not currently happening with the code since fileStatus won't call
it with an empty fileName anymore.
2016-05-03 13:01:51 +02:00
Jocelyn Turcotte a5df44c757 Fix the sync status push for parent directories #4682
As before, we rely on metadata-update SyncFileItem entries for parent
directories to notify us that a directory contains files to propagate,
and to know when all children were propagated through its itemCompleted
signal.

Those metadata SyncFileItems however have a None direction and we need
to add a explicit directory check to show them as Sync.
This fix also handles new files as well as existing ones, so no need
to keep a separate logic for new files.
2016-05-03 13:01:51 +02:00
Klaas Freitag 641125eac1 Fix nautilus and nemo plugin branding strings. (#4780)
* Fix nautilus and nemo plugin branding strings.

Fix for owncloud/enterprise#1314

* nautilus plugin: Add a comment why the line needs to stay unchanged.
2016-05-03 11:36:56 +02:00
Jenkins for ownCloud d340017a0a [tx-robot] updated from transifex 2016-05-03 02:19:16 -04:00
Olivier Goffart a67173610d Propagator: fix qt4 build
propagatedownload.cpp:712:35: error: 'seenLockedFile' is a protected member of 'OCC::OwncloudPropagator'

Signals are protected in Qt4 but public in Qt5, mark the class accessing it
as friend when compiling with Qt4
2016-05-02 17:34:21 +02:00
Daniel Molkentin e833d01288 Re-Apply: Disambiguate socket API pathes on Windows with user name
Addresses #3411
2016-05-02 16:09:48 +02:00
Olivier Goffart 3047682223 ShareDialog: show the error message in red
Do the visual stuff from designer.
The previous code that was ment to change the color in red did not work
and changed it to gray instead.
Also I don't see why there should be a frame.

Issue #4773
2016-05-02 14:12:04 +02:00
Jenkins for ownCloud c91dd94728 [tx-robot] updated from transifex 2016-05-02 02:19:41 -04:00
Jenkins for ownCloud 52f9f44b51 [tx-robot] updated from transifex 2016-05-01 02:19:18 -04:00
Jenkins for ownCloud 49748191a9 [tx-robot] updated from transifex 2016-04-30 02:19:14 -04:00
ckamm e6b937f508 LockWatcher: Keep an eye on Windows file locks (#4758)
When a conflict-rename or a temporary-rename fails, notify the
LockWatcher. It'll regularly check whether the file has become
accesible again. When it has, another sync is triggered.

owncloud/enterprise#1288
2016-04-29 16:14:18 +02:00
Roeland Douma 31c13f74fb Add spinner during sharee search (#4764)
Fixed #4740

When searching for sharees we should display a loading spinner.
2016-04-29 14:11:27 +02:00
Olivier Goffart be466b47b7 Merge remote-tracking branch 'origin/2.1' into 2.2 2016-04-29 08:52:17 +02:00
Olivier Goffart 11b144957b PropagateDownload: Throw an error if the file is empty while it should not have been (#4753)
If the downloaded file is empty but the PROPFIND previously announced it
should not have been empty, this might mean the file was somehow corrupted
because of a bug on the server and that we should therefore not accept
the file.

Normaly we accept a change between the actual size of the file and what we
got during discovery because the file might have been updated to a new version
inbetween. But after this patch we won't accept the file if it was replaced
by an empty file.

Will help for issue #4583
Also requested by IL for issue 548
2016-04-29 08:49:27 +02:00
Jenkins for ownCloud 817e97c148 [tx-robot] updated from transifex 2016-04-29 02:19:14 -04:00
Markus Goetz 29932004ae Shibboleth: Load username from config for UI (#4751)
For https://github.com/owncloud/enterprise/issues/1034
2016-04-28 14:55:29 +02:00
Daniel Molkentin 6d83e841a9 Merge pull request #4756 from owncloud/revert-4738-fix_3411
Revert "Disambiguate socket API pathes on Windows with user name"
2016-04-28 13:53:06 +02:00
Daniel Molkentin b43a9421d2 Revert "Disambiguate socket API pathes on Windows with user name" 2016-04-28 13:52:15 +02:00
Klaas Freitag e70b78d14b Merge pull request #4738 from owncloud/fix_3411
Disambiguate socket API pathes on Windows with user name
2016-04-28 13:46:10 +02:00
Klaas Freitag 6814342d1f Merge pull request #4748 from owncloud/win_stat_revisited
vio for windows: Use more graceful create file params.
2016-04-28 13:45:30 +02:00
Christian Kamm 68126dcff6 Checksums: Skip uploads of .eml files only #4754
This is a workaround. A correct solution would still update file metadata
such as the mtime. See #4755.
2016-04-28 12:59:39 +02:00
Christian Kamm e7f00339e6 Fix perl tests #4722
* The dav auth realm is "sabre/dav" for newer server versions
* Content checksums are enabled generally, so conflict detection
  is smarter
2016-04-28 10:44:37 +02:00
Christian Kamm a36b4ec863 FolderWizard: Sort remote folders #4612 2016-04-28 09:29:07 +02:00
Christian Kamm 074f8eadb1 Selective sync: Sort folders in FolderStatusModel #4612 2016-04-28 09:29:07 +02:00
Jenkins for ownCloud 6a51ae5b1b [tx-robot] updated from transifex 2016-04-28 02:19:20 -04:00
Christian Kamm af5f2d3860 Protocol: Make timestamp column width fit the text #4721 2016-04-28 07:37:42 +02:00
ckamm 38bad564a0 Merge pull request #4739 from ckamm/trackdirty
Overlay icons: Track touched files #4730
2016-04-28 07:17:17 +02:00
Christian Kamm c2fa3fb4c8 Overlay icons: Track touched files #4730
This uses the file watcher to keep track of files that were modified
in order to assign them the blue icon.

This is transient state that's not persisted across restarts.
2016-04-28 07:16:49 +02:00
Markus Goetz f7082ee3df sqlite: Update to version 3.12.2
For OS X and Windows
2016-04-27 12:22:12 +02:00
Markus Goetz f7c6efb391 ConnectionValidator: Also set short timeout for capabilities job
Default timeout was 5 min.
2016-04-27 12:19:49 +02:00
Klaas Freitag 051a348afd Vio for windows: Removed the overlap param again.
After discussion and studying docs again we agreed that
the parameter is not neccessary here as it only affects
the process that opens the handle. And we do not want to
do async stuff.
2016-04-27 11:37:21 +02:00
Olivier Goffart d0af3ede05 AccountSettings: context menu: don't rely on the alias
Don't rely on the alias to know weather we shuld show a context menu or not.
Use the classify function to know if it's a root folder instead
2016-04-27 11:21:58 +02:00
Olivier Goffart 0da2adcbe0 Workaround ubuntu 16.04 systemtray bug (#4693) (#4747) 2016-04-27 11:21:13 +02:00
Klaas Freitag 07bdd519e9 vio for windows: Use more graceful create file params. 2016-04-27 11:17:42 +02:00
Christian Kamm 0829a94c92 Remote folder selection: improve path typing #4745 #4746
* Scroll to the target typed path
* Show non-404 errors that were triggered by typing paths
2016-04-27 10:37:17 +02:00
Daniel Molkentin ce6a365328 Disambiguate socket API pathes on Windows with user name
Addresses #3411
2016-04-26 14:49:45 +02:00
94 arquivos alterados com 6051 adições e 5373 exclusões
+5
Ver Arquivo
@@ -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)
+13 -5
Ver Arquivo
@@ -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
-1
Ver Arquivo
@@ -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"
+1 -5
Ver Arquivo
@@ -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;
+1
Ver Arquivo
@@ -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);
+4 -1
Ver Arquivo
@@ -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,
+4 -2
Ver Arquivo
@@ -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();
+18 -24
Ver Arquivo
@@ -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 });
+2 -2
Ver Arquivo
@@ -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);
+1 -1
Ver Arquivo
@@ -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( );
+1 -1
Ver Arquivo
@@ -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---
+9 -5
Ver Arquivo
@@ -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;
}
}
+46 -31
Ver Arquivo
@@ -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){
+3 -3
Ver Arquivo
@@ -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
+7 -1
Ver Arquivo
@@ -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)
+2 -3
Ver Arquivo
@@ -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;
}
+3 -5
Ver Arquivo
@@ -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();
+1 -3
Ver Arquivo
@@ -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);
+1 -1
Ver Arquivo
@@ -41,7 +41,7 @@ class ActivityListModel;
namespace Ui {
class ActivityWidget;
}
class Application;
class oCApplication;
/**
* @brief The ActivityWidget class
+6 -1
Ver Arquivo
@@ -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()));
}
+8 -2
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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;
};
+10 -7
Ver Arquivo
@@ -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;
+23 -2
Ver Arquivo
@@ -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);
+1
Ver Arquivo
@@ -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);
+1 -1
Ver Arquivo
@@ -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"
+51
Ver Arquivo
@@ -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);
}
+66
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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();
}
+1 -1
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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);
}
}
+6 -5
Ver Arquivo
@@ -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
+7
Ver Arquivo
@@ -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);
+1 -1
Ver Arquivo
@@ -31,7 +31,7 @@ class SyncResult;
namespace Ui {
class ProtocolWidget;
}
class Application;
class oCApplication;
/**
* @brief The ProtocolWidget class
+1
Ver Arquivo
@@ -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);
+1 -1
Ver Arquivo
@@ -33,7 +33,7 @@ namespace Ui {
class SettingsDialog;
}
class AccountSettings;
class Application;
class oCApplication;
class FolderMan;
class ownCloudGui;
class ActivitySettings;
-11
Ver Arquivo
@@ -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();
+37
Ver Arquivo
@@ -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>
+6 -1
Ver Arquivo
@@ -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();
+2
Ver Arquivo
@@ -129,6 +129,8 @@ private:
bool _isFile;
bool _disableCompleterActivated; // in order to avoid that we share the contents twice
ShareManager *_manager;
QProgressIndicator _pi_sharee;
};
}
+49 -8
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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);
+1
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
+1
Ver Arquivo
@@ -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();
}
+35
Ver Arquivo
@@ -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
+5
Ver Arquivo
@@ -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);
}
/** @} */
+4 -4
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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();
+8
Ver Arquivo
@@ -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
};
+24 -2
Ver Arquivo
@@ -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;
}
+2 -1
Ver Arquivo
@@ -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;
+6
Ver Arquivo
@@ -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);
+57 -60
Ver Arquivo
@@ -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);
+9 -2
Ver Arquivo
@@ -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;
};
}
+1
Ver Arquivo
@@ -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})
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff