1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2026-04-03 09:11:33 +02:00

Compare commits

...

645 Commits

Author SHA1 Message Date
Michael Schuster
03cddabfd0 Tray menu: Only show time ago (view too noisy)
Don't show date and time for now, rather as a tool tip later.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-19 19:12:34 +01:00
Michael Schuster
8c2d77c68f Merge pull request #1699 from Milokita/test-file-fix
apply http2 qt resend patch from owncloud
2020-01-19 18:11:36 +01:00
Dominique Fuchs
d3cd422b46 Fix crash on start without any accounts
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
(cherry picked from commit 9935606c87ec4818f04c7d7c63d2f4b61187eead)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-19 14:14:23 +01:00
István Váradi
482ab9ad14 Merge pull request #1738 from ivaradi/qt5.5-compat
Qt 5.5 compatibility ifdef
2020-01-19 13:42:31 +01:00
István Váradi
835cd2ac80 Qt 5.5 compatibility ifdef
Signed-off-by: István Váradi <ivaradi@varadiistvan.hu>
2020-01-19 13:16:17 +01:00
Michael Schuster
36e2813169 Merge pull request #1737 from nextcloud/appimage-qmlfix
Testing fix for qmldir import with linuxdeployqt AppImage
2020-01-19 12:43:32 +01:00
Dominique Fuchs
35f8103b40 Testing fix for qmldir import with linuxdeployqt AppImage by correcting source path
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-19 09:10:59 +01:00
Nextcloud bot
f4febe04bc [tx-robot] updated from transifex 2020-01-19 03:25:56 +00:00
Michael Schuster
c2f5f156f0 Bump version year to 2020
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-18 17:11:44 +01:00
Michael Schuster
7136d92011 Linux AppImage build script: Add QML dir for new 2.7 Tray menu
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-18 16:31:48 +01:00
Michael Schuster
a35aa58943 Linux AppImage build script: Use QtKeyChain master
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-18 16:31:22 +01:00
Michael Schuster
e7f7ad7eb3 Merge pull request #1735 from nextcloud/feature/context-menu-direct-edit
Add direct editing to the file manager extension
2020-01-18 15:45:49 +01:00
Michael Schuster
c0863ede02 Share context menu: Use directEditing capability in SocketApi
- Allow direct editing "Edit" when an editor is available for the mime type
- Show "Open in browser" if editing is unavailable (as previously)
  (now on top of the menu list)
- Rename the menu title to the app name, "Nextcloud" instead of "Share via ..."

Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-18 15:12:16 +01:00
Michael Schuster
45b39cdbc1 Add support for the directEditing capability
- Fetch in ConnectionValidator::slotCapabilitiesRecieved
- Add editors to a list made of the new DirectEditor class

TODO:
- Add support for re-fetch and continously check for changes (ETag)

Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-18 15:07:51 +01:00
Michael Schuster
9447a10716 JsonApiJob: Add method usePOST to allow anonymous POST requests
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-18 15:03:21 +01:00
Michael Schuster
2039872ee5 Merge pull request #1565 from nextcloud/qml-tray-menu
New tray window
2020-01-18 13:18:45 +01:00
Michael Schuster
016a90d7b0 More code maintenance
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-18 12:56:26 +01:00
Dominique Fuchs
9b5bb1365c Code maintenance - correct some syntax, fix some warnings.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-18 10:30:34 +01:00
Nextcloud bot
b0dfdca76f [tx-robot] updated from transifex 2020-01-18 03:28:30 +00:00
Michael Schuster
de74057cc8 Add grey hint Activity entry if limit is reached
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-17 20:26:48 +01:00
Michael Schuster
e2188b109a Limit fetching Activities to 100 or max. 30 days old
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-17 20:25:41 +01:00
Michael Schuster
3ae55c2555 AccountState: Add helper to find navigation App
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-17 20:21:42 +01:00
Michael Schuster
b47adb7aeb Notifications bug fix: Don't init ETag response header with *
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-17 20:20:37 +01:00
Michael Schuster
889cb636d3 Add Activity date and time
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-17 20:16:20 +01:00
Dominique Fuchs
c9719f44dc Fix hover property wrongly placed in button, not MouseArea
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-17 16:30:27 +01:00
Dominique Fuchs
599dae0486 Inclusion of possible 'notification' type descriptions in activity
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-17 14:50:05 +01:00
Dominique Fuchs
1c5cdc4d36 Adapted currentId logic for activity fetching to new API (should fix endless fetch bug)
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-17 14:29:54 +01:00
Dominique Fuchs
0156edf320 Removed visibility workaround
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-17 11:21:43 +01:00
Dominique Fuchs
f425dfdfea Set sourceSize to prevent blurry rerendering of svg source in activityIcon
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-17 10:38:21 +01:00
Dominique Fuchs
7ea2f3fa59 Refresh visibility of ListView based on presence of items on showWindow
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-17 09:09:42 +01:00
Dominique Fuchs
1c22070a74 Refresh immediately on showWindow, regardless of the timer
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-17 09:04:24 +01:00
Nextcloud bot
21f3cb8f7d [tx-robot] updated from transifex 2020-01-17 03:26:44 +00:00
Michael Schuster
9abc1eb921 Add initial support for Apps menu icon display (show remote SVGs)
Caching and showing them from local data-URLs leaded to blurry rendering in Qt.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-16 18:43:48 +01:00
Dominique Fuchs
94325359d7 Fixed bug regarding additional but empty delegate at end of activitylist
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 18:01:18 +01:00
Dominique Fuchs
585094a719 Minor property hierarchy fix
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 17:40:47 +01:00
Dominique Fuchs
4b79c597dc Disabled animations until population glitches are fixed
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 17:11:08 +01:00
Dominique Fuchs
1bc8ec59aa Streamlining local sync notification/activity icons with server ones. Added fileAction logic for local sync activities
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 17:09:34 +01:00
Dominique Fuchs
b9a350e201 Minor layout adjustments
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 15:19:17 +01:00
Dominique Fuchs
cd80c749d6 Retreive and svg data from icon property url for activity entries
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 14:01:54 +01:00
Dominique Fuchs
06fdde8f1e Upgrade of NC server API usage + corresponding activity queries and properties including icon ref
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 12:43:04 +01:00
Dominique Fuchs
9f259bda27 Add check if applist rowCount() already empty to prevent assert exception
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 11:30:51 +01:00
Dominique Fuchs
d7a9940973 Fix failing of several tests by including ocsjob source (after its inclusion in accountstate in a previous commit)
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 10:53:43 +01:00
Dominique Fuchs
db92d5bfff append the correct folderwatcher (platform specific)
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 10:39:56 +01:00
Dominique Fuchs
246f7e9395 1px border #0082c9 around tray window
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-16 08:01:09 +01:00
Nextcloud bot
b5549bf00c [tx-robot] updated from transifex 2020-01-16 03:28:16 +00:00
Michael Schuster
7fe138330e Double the width of the Apps menu (x starts at the Talk button)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-16 00:57:49 +01:00
Michael Schuster
3488fd7c7f Fix font sizes for "Log out" and "Remove account" and the Apps menu
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-16 00:45:31 +01:00
Roeland Jago Douma
a3aab00ca9 Windows 7 is out of support
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
2020-01-16 00:07:10 +01:00
Brandon
d10bc1bb14 Correct wrong variable
Signed-off-by: Brandon <brandon.yeow@websparks.sg>
2020-01-15 23:07:14 +01:00
Brandon
18a88fcecf Correct wrong variable
Signed-off-by: Brandon <me@branbit.com>
Signed-off-by: Brandon <brandon.yeow@websparks.sg>
2020-01-15 23:07:14 +01:00
ritsute
c92f520423 Handle broken shared file error gracefully
Signed-off-by: Brandon <me@branbit.com>
Signed-off-by: Brandon <brandon.yeow@websparks.sg>
2020-01-15 23:07:14 +01:00
Dominique Fuchs
00d73a9389 Add visual separation between accountStateIndicator and avatar
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-15 20:11:50 +01:00
Dominique Fuchs
ddf67ff948 Preserve a 2px distance from tray border (streamlining with acount menu)
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-15 19:28:40 +01:00
Dominique Fuchs
9b32ebdae4 Allow text to expand further if one or both buttons aren't visible
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-15 19:15:25 +01:00
Dominique Fuchs
0ec2291bd7 Layout adjustments & also show remote path in activitylist
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-15 18:44:33 +01:00
Michael Schuster
026bf02c85 App menu: Filter out Talk because we have a dedicated button for it
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-15 18:14:20 +01:00
Michael Schuster
42ebc7e995 Remove debug output
Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-15 18:09:33 +01:00
Michael Schuster
b4b6366ba8 Add App list menu to Tray UI
- Modify Window.qml and Systray to show the App menu upon clicking the App button
  on the top-right. Fall back to opening the general URL in case no apps are found.

- Introduce a new UserAppsModel in UserModel.cpp to access the fetched server Apps
  from AccountState (propagated down from the User class).

Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-15 16:42:06 +01:00
Michael Schuster
7b740f5e9a Remove setTalkCapability() from AccountState and filter for Talk upon App list building
Since the per Account App list is now being built in AccountState's slotNavigationAppsFetched
it's easy to filter for the availability of the Talk app on the server by its ID property
upon App list building, thus eliminating the need for an extra fetch job.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-15 16:30:05 +01:00
Michael Schuster
cb328d6cea Fetch server Apps in AccountState (moved from ownCloudGui)
- Add a new class AccountApp to keep them in an AccountAppList
  and also save properties like ID and Icon URL.

- Clear the app list upon re-fetch to avoid endlessly growing lists
  like in the previous implementation in ownCloudGui.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-15 16:23:46 +01:00
Dominique Fuchs
b57b8cfb66 Resized add account icon, adapted layout for new size
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-15 08:01:54 +01:00
Nextcloud bot
cb1c68a36e [tx-robot] updated from transifex 2020-01-15 03:24:58 +00:00
Dominique Fuchs
29138cc533 Font and icon size improvements, svg transfer to new folder
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-14 19:48:21 +01:00
Dominique Fuchs
c09dd9287c Fix missing trayScreen init in non-OSX clause
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-14 08:55:39 +01:00
Dominique Fuchs
65b47d4613 Make qml UI strings translatable
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-14 07:59:28 +01:00
Nextcloud bot
aab2d01a7c [tx-robot] updated from transifex 2020-01-14 03:25:33 +00:00
Dominique Fuchs
f748a4bb50 Made tray window positioning HighDPI aware
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-13 22:11:57 +01:00
Dominique Fuchs
e4b19d0cb5 Activity refresh in background
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-13 14:35:58 +01:00
Dominique Fuchs
eeefbe57af Added progressInfo / cleanup to acitivtymodel
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-13 13:10:32 +01:00
Dominique Fuchs
84066634e7 Integrated local error messages in activitymodel
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-13 12:54:38 +01:00
Dominique Fuchs
9e82ba60b4 Integrated local sync activities in activitymodel
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-13 12:20:41 +01:00
Dominique Fuchs
96a74d9ef0 Minor improvements
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-13 11:46:49 +01:00
Dominique Fuchs
1ebcd3a0fb Icon selection, svg path transfers, scrollbar
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-13 09:59:34 +01:00
JanDragon
7565c547ae Welcome to 2020 2020-01-13 09:28:51 +01:00
Michael Schuster
8f9101773c Fix Explorer integration on Windows and the crash on other systems
- Ensure that the folder integration stays persistent in Explorer,
  the uninstaller removes the folder upon updating the client.
  Recreate all entries upon start. This has the benefit of removing
  old remains of non-working, outdated entries.

- Don't crash on the other systems when the user clicks the option
  button "Show sync folders in Explorer's Navigation Pane".
  Even though the option currently doesn't work on the other platforms,
  crashing is never good...

Signed-off-by: Michael Schuster <michael@schuster.ms>
2020-01-13 09:25:01 +01:00
Dominique Fuchs
17fcfd4e41 Show ListView delegate only when model is populated (prevent dummy delegate)
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-13 09:12:44 +01:00
Dominique Fuchs
9e6df7a4dc Add populate transition
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-13 08:43:51 +01:00
Dominique Fuchs
9319210c4c Fix local folder not opening on windows, add extra slash
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-13 08:33:10 +01:00
Nextcloud bot
43fa27887d [tx-robot] updated from transifex 2020-01-13 03:24:43 +00:00
Dominique Fuchs
58f1c3234d Temperarily disabling animations due to lags - FIXME
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-12 21:37:08 +01:00
Dominique Fuchs
715924cac6 Show activitylist on initial tray opening when logged in
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-12 21:19:18 +01:00
Dominique Fuchs
163ca3b58a Removed old account toolbox
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-12 19:53:02 +01:00
Dominique Fuchs
1c2916052d Bunch of fixes and optimizations for activityList
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-12 17:52:51 +01:00
Dominique Fuchs
b76da25ef1 Model/View improvements, also fixes crash on account removal
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-12 16:16:24 +01:00
Dominique Fuchs
7f35178c70 More fixes to login/logout logic
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-12 11:06:48 +01:00
Dominique Fuchs
212e1f80f5 emit signal for current user GUI refresh on login/logout
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-12 10:46:14 +01:00
Dominique Fuchs
a2c9e369c3 call resetRejectedCertificates on fresh login
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-12 10:42:40 +01:00
Dominique Fuchs
78f12de997 Merge branch 'master' into qml-tray-menu 2020-01-12 09:12:16 +01:00
Dominique Fuchs
8ec7cfa700 Connection status indicators as avatar overlay
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-12 09:10:06 +01:00
Dominique Fuchs
bc8f64bb98 Generalized connection check, now working for every user in account menu
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-12 08:50:13 +01:00
Nextcloud bot
c7cc716e57 [tx-robot] updated from transifex 2020-01-12 03:25:48 +00:00
Dominique Fuchs
578a3b4ef4 Streamlined 'Add account' button with account entries
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-11 20:28:00 +01:00
Dominique Fuchs
cc671dfad3 Fix local folder URL
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-11 19:56:56 +01:00
Dominique Fuchs
86b915d42e Systray now a singleton with instance(), show tray on finished wizard
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-11 17:34:56 +01:00
Dominique Fuchs
738127525f Fix comment
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-11 17:14:44 +01:00
Dominique Fuchs
6485ef480b Added confirmation dialog for account removal
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-11 17:06:42 +01:00
Dominique Fuchs
9af7d4ad06 Fix crash on startup when no users configured
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-11 16:41:20 +01:00
Dominique Fuchs
32741162d9 Detect newly added user and rebuild account menu automatically
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-11 15:47:36 +01:00
Dominique Fuchs
3da982f073 Implemented account removal
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-11 15:32:59 +01:00
Dominique Fuchs
a021f62e96 Tray creation timing, account menu reinstantiating on visible change
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-11 15:05:37 +01:00
Dominique Fuchs
80e21560eb More UserLine, avatar fixes
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-11 14:57:22 +01:00
Nextcloud bot
e38b98c81a [tx-robot] updated from transifex 2020-01-11 03:25:40 +00:00
Dominique Fuchs
9c0221a0fa UserLine drafting, bugfixes, restuctures
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-10 16:28:53 +01:00
Nextcloud bot
afbed7dbd7 [tx-robot] updated from transifex 2020-01-10 03:27:02 +00:00
Roeland Jago Douma
05083e32c9 Ask for password on password protected link shares
Fixes #1485

This was missed when creating the new share dialog.
Now it pops up with a nice share password dialog to enter for your link
share.

Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
2020-01-09 18:20:32 +01:00
Nextcloud bot
c6bd8c1221 [tx-robot] updated from transifex 2020-01-09 04:16:12 +00:00
Nextcloud bot
63c7844a27 [tx-robot] updated from transifex 2020-01-08 04:16:49 +00:00
Nextcloud bot
762032ebbc [tx-robot] updated from transifex 2020-01-07 04:17:27 +00:00
JanDragon
4a64e8da83 Updated year in legalnotice.cpp 2020-01-06 09:08:22 +01:00
Nextcloud bot
5c6af99f11 [tx-robot] updated from transifex 2020-01-06 04:16:30 +00:00
Dominique Fuchs
6ac1a4a353 Preps for UserLine submenu
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-05 21:31:09 +01:00
Dominique Fuchs
330ff96ee2 Code cleanup regarding context menu. Pause/resume logic implemented. Halfway through remodeling account menu.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-05 21:06:42 +01:00
Dominique Fuchs
a90995cf15 Focus and popup improvements for macOS
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-05 16:25:32 +01:00
Nextcloud bot
84693b95ec [tx-robot] updated from transifex 2020-01-05 04:28:46 +00:00
Dominique Fuchs
aa9921c6f5 Quit/settings button in tray menu, disable context menu, font size fixes
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-04 17:22:56 +01:00
Dominique Fuchs
d653618b0a Fix blurry caret svg due to https://bugreports.qt.io/browse/QTBUG-44863
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-04 12:18:06 +01:00
Dominique Fuchs
dc9744448c Fix wrong macro clause
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-04 12:15:01 +01:00
Dominique Fuchs
ed9c06583a Fix macOS popup y position, neglecting unneccesary calculations
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-04 12:08:30 +01:00
Dominique Fuchs
ff92adf3e0 Tray account menu wording/positioning
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-04 10:09:01 +01:00
Nextcloud bot
bf95c03847 [tx-robot] updated from transifex 2020-01-04 04:17:33 +00:00
Dominique Fuchs
e0641df727 First real activity connection
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-03 16:15:15 +01:00
Dominique Fuchs
f01c47e0ec Fix server adress retreival in tray window buttons
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-03 14:00:07 +01:00
Dominique Fuchs
faf46fcf60 More typo fix
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-03 13:42:07 +01:00
Dominique Fuchs
687a99279d Has function for ActivityModel, typos
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-03 13:39:10 +01:00
Dominique Fuchs
25e09815be Fixed client.qrc
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-03 13:17:01 +01:00
Dominique Fuchs
02cb43180c Fix git not recognizing case sensitive changes
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-03 13:12:04 +01:00
Dominique Fuchs
b32310b8a6 Gigantic ton of changes and deletions: ActivityListModel, tray GUI, Account logic.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-03 13:09:29 +01:00
Dominique Fuchs
556a1a5ef2 Added ActivityModel in new tray backend, implemented as delegate in UI
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-02 10:39:53 +01:00
Dominique Fuchs
36467c1e3a Added folder search for User instance, added open folder button connection
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-02 09:55:37 +01:00
Dominique Fuchs
d4b334636e Fall back to primary screen on QT version < 5.10 instead of icon position detection
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-02 08:56:07 +01:00
Dominique Fuchs
7653c5fa60 Fix merge conflict
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2020-01-02 08:43:34 +01:00
Nextcloud bot
bd61cd3142 [tx-robot] updated from transifex 2020-01-02 04:14:47 +00:00
Nextcloud bot
1a0f7221d9 [tx-robot] updated from transifex 2020-01-01 04:14:20 +00:00
Nextcloud bot
7303c726f9 [tx-robot] updated from transifex 2019-12-31 04:15:07 +00:00
Dominique Fuchs
44bfc79caa Implemented platform agnostic tray window positioning logic
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-30 14:14:28 +01:00
Dominique Fuchs
6f8ffc0357 Backend code separation & structure cleanup
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-30 11:52:07 +01:00
Dominique Fuchs
bb45a5f67e Added popup show/hide logic
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-30 11:39:21 +01:00
Nextcloud bot
baa0a5b8af [tx-robot] updated from transifex 2019-12-30 04:12:51 +00:00
Nextcloud bot
9081556e1d [tx-robot] updated from transifex 2019-12-29 04:14:53 +00:00
Nextcloud bot
1b14f55c3c [tx-robot] updated from transifex 2019-12-28 04:13:31 +00:00
Nextcloud bot
89a5e34414 [tx-robot] updated from transifex 2019-12-27 04:13:27 +00:00
Nextcloud bot
e2bc7d1307 [tx-robot] updated from transifex 2019-12-26 04:11:34 +00:00
XNG
768cf7e1ae apply http2 qt resend patch from owncloud
Signed-off-by: XNG <Milokita@users.noreply.github.com>
2019-12-25 14:36:25 +08:00
XNG
d87a88e39f apply http2 qt resend patch from owncloud
Signed-off-by: XNG <Milokita@users.noreply.github.com>
2019-12-25 14:13:03 +08:00
XNG
314c00a8b7 apply http2 qt resend patch from owncloud
Signed-off-by: XNG <Milokita@users.noreply.github.com>
2019-12-25 13:59:15 +08:00
Nextcloud bot
16ed62d548 [tx-robot] updated from transifex 2019-12-25 04:13:59 +00:00
Michael Schuster
2b2810511d KeychainChunk: Fix error handling in ReadJob::slotReadJobDone
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 12:17:43 +01:00
Michael Schuster
e07859fb3c Fix date in ActivityWidget and remove unnecessary string conversion
The local date and time value was converted into a string, just to be converted
into another string, to be converted to a value once again, returning zero as
the result. This caused the widget to always display "now".

Looks like this was a simply copy and paste mistake from this line in
ActivityListModel::slotActivitiesReceived:

a._dateTime = QDateTime::fromString(json.value("date").toString(), Qt::ISODate);

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 08:53:14 +01:00
Michael Schuster
9b034a2eb0 Heavy refactoring: Windows workaround for >= 4k (4096 bit) client-cert SSL keys and large certs
With QtKeychain on Windows, storing larger keys or certs in one keychain entry causes the
following error due to limits in the Windows APIs:
    Error: "Credential size exceeds maximum size of 2560"

This fix implements the new wrapper class KeychainChunk with wrapper jobs ReadJob and WriteJob
to encapsulate the QKeychain handling of ReadPasswordJob and WritePasswordJob with binaryData
but split every supplied keychain entry's data into 2048 byte chunks, on Windows only.

The wrapper is used for all keychain operations in WebFlowCredentials, except for the server password.

All finished keychain jobs now get deleted properly, to avoid memory leaks.

For reference also see previous fixes:
- https://github.com/nextcloud/desktop/pull/1389
- https://github.com/nextcloud/desktop/pull/1394

This should finally fix the re-opened issue:
- https://github.com/nextcloud/desktop/issues/863

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:47:35 +01:00
Michael Schuster
bd9652b24c Flow2AuthWidget: Minor fixes and improvements
- Improve status messages

- Add a counter to make sure that "Link copied to clipboard." is visible for
  three seconds and to not enable the buttons too early

- Add more space between buttons and status

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
8b5f09305c Flow2: Refactor UI into Flow2AuthWidget only and improve Flow2Auth
- Flow2AuthCredsPage:
  - Remove .ui file and embed Flow2AuthWidget into layout

- Flow2AuthWidget:
  - Make use generic for Flow2AuthCredsPage and WebFlowCredentialsDialog
  - Fix _errorLabel to render HTML tags instead of dumping them as plain text

- Flow2Auth:
  - Explicitly start auth with startAuth(account) instead of using constructor
  - Take control of copying the auth link to clipboard
  - Request a new auth link on copying, to avoid expiry invalidation
  - Use signals statusChanged() and result() to be more verbose (status, errors)
  - Change timer invocation and add safety bool's to avoid weird behaviour when
    the user triggers multiple link-copy calls (fetchNewToken)

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
6d033f2964 Add new HeaderBanner class for WebFlowCredentialsDialog
New widget on top of the layout, based on Qt's own modern wizard header banner.

This should improve the user's perception of the dialog.

Encapsulate the existing layout into a container layout to allow the banner taking
the full width of the dialog.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
0bcac1882a Make WebFlowCredentialsDialog cancellation- and deletion-safe
- Add new signal to let WebFlowCredentials know and emit asked() to also
  tell AccountState that the user won't authenticate, and triggering
  log-out state in the settings window.

- Use deleteLater() to safely delete WebFlowCredentialsDialog, so
  that Qt can free it at the right time and without crashes.
  Do the same with it's _webView and _flow2AuthWidget on closeEvent().

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
b6b04aeff8 WebFlowCredentialsDialog: Bring re-auth dialog to top (raise) on error
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
a69aed80e6 Flow2: Make ProgressIndicator's background-aware (Dark-/Light-Mode switching)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
e81f972270 Flow2: Add poll status text, ProgressIndicator and countdown timer
Also enable / disable buttons during polling.

This aims to make the authentication status more transparent and should avoid the
impression that the client is perhaps doing nothing.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
542590db7c Small fixes and code cleanup
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
e04aae94bc Flow2: Poll for re-auth result upon WebFlowCredentialsDialog window activation
Since the default remote poll interval has been re-raised recently to 30 seconds,
the delay between clicking "Grant access" in the browser and fetch and showing success
in the dialog may seem erroneous to the users and tempt them to click "Re-open browser"
again, causing the whole login process to restart.

This commit implements an event handler to pass the dialog's window activation
event down to the Login Flow v2 widget, in order to allow it to poll earlier.

See previous commits for dependent implementation details.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
aa18667905 WebFlowCredentialsDialog: Bring re-auth dialog to top (raise) upon showing SettingsDialog
Purpose: The floating re-auth windows of the WebFlowCredentialsDialog often get hidden behind
the SettingsDialog, and the users have to minimize a lot of other windows to find them again.

See previous commit for dependent implementation details.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
addb27a085 Add helper slots and signals to catch SettingsDialog's window activation events
Signal the SettingsDialog's window activation event down to ownCloudGui and Application,
so that other classes can hook in to get notified when the SettingsDialog is being shown
again.

This approach has been chosen because we otherwise would have to deal with new instance
pointers of the current SettingsWindow - but Application is already there ;-)

Purpose: The floating re-auth windows of the WebFlowCredentialsDialog often get hidden
behind the SettingsDialog, and the users have to minimize a lot of other windows to find
them again. This commit implements the preparation for the upcoming fix commit.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
be10d5200f Flow2: Use ownCloudGui::raiseDialog to bring account setup wizard to top (raise) on auth result
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
e8348612b4 Flow2: Poll for auth result upon account setup wizard window activation
Since the default remote poll interval has been re-raised recently to 30 seconds,
the delay between clicking "Grant access" in the browser and fetch and showing success
in the wizard may seem erroneous to the users and tempt them to click "Re-open browser"
again, causing the whole login process to restart.

This commit implements an event handler to pass the wizard's window activation
event down to the Login Flow v2 page, in order to allow it to poll earlier.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
3a160a4dce Flow2: Bring account setup wizard to top (raise) on auth result
Show and raise the wizard on success / error in the Login Flow v2 auth.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00
Michael Schuster
ccd20f0172 Fix issue #1237: White text on almost-white background
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:44:18 +01:00
Michael Schuster
c03bc8540c Fix folder opening in ActivityListModel
After fixing the crash in the previous commit, double-clicking on Activity list rows still didn't work.

This fix partly reverts commit 8546d53b05 in ActivityItemDelegate::PathRole
of ActivityListModel::data, but adds a new check for relPath's existence in line 74.

I'm assuming the previous change there has been done to shorten the code and avoid opening the user's home
folder upon clicking entries which file value is "App Password". The new path-check takes care of that too now.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:42:01 +01:00
Michael Schuster
003acb7254 Fix crash in ActivityListModel (fixes #1693)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:42:01 +01:00
Michael Schuster
b961b683d6 Show date and time in activity log (fixes issue #1683)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:40:42 +01:00
Nextcloud bot
f82ef95866 [tx-robot] updated from transifex 2019-12-24 04:15:27 +00:00
Nextcloud bot
ed9000bb07 [tx-robot] updated from transifex 2019-12-23 04:17:38 +00:00
Nextcloud bot
6afe2b124d [tx-robot] updated from transifex 2019-12-22 04:20:47 +00:00
Nextcloud bot
629d23d832 [tx-robot] updated from transifex 2019-12-21 03:50:38 +00:00
Nextcloud bot
d837feca71 [tx-robot] updated from transifex 2019-12-20 03:50:25 +00:00
Michael Schuster
a7dade979c Fix build (missing refactoring)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
3a2caf61e5 Mac and high-dpi displays: Add workaround in ActivityItemDelegate to show full uncropped activity's actionText and timeText
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
b5ed16088a Make all ProgressIndicator's background-aware (Dark-/Light-Mode switching)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
e4a20b9e72 Make OwncloudWizard and its pages background-aware (Dark-/Light-Mode switching)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
37e5fe786f Remove unnecessary string translation and copy in ActivityItemDelegate
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
643995528b Remove unnecessary breaks in ActivityListModel
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
ecd17f2ea2 Make ActivityItemDelegate background- and selection-aware (Dark-/Light-Mode switching)
Also implement cached member icons in ActivityListModel and return their enums to
ActivityItemDelegate instead of always recreating them for each call to paint().

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
bf0bf2c1b6 Refactor ActivitySettings: Rename member variable ui to _ui
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
acedf362b6 Make AccountSettings and ActivitySettings background-aware (Dark-/Light-Mode switching)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
3b580eeca7 Change error link colour in AccountSettings::showConnectionLabel
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
6adfff1f13 Add new Theme helper method to custom-colourize links
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Michael Schuster
7d542d7989 Change Dark Mode link colour
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-19 22:07:30 +01:00
Nextcloud bot
b6a8195cb0 [tx-robot] updated from transifex 2019-12-19 03:51:44 +00:00
Michael Schuster
cc21d175f1 Fix Activity List: Add check to avoid first empty entry
Add checks to ActivityListModel::combineActivityLists in order to avoid adding
empty Activity entries to the _finalList.

The previous implementation always added an empty entry to the top of the list because
_notificationIgnoredFiles was appended without checking (_listOfIgnoredFiles.size() > 0).

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-18 03:29:54 +01:00
Nextcloud bot
ade4b198cf [tx-robot] updated from transifex 2019-12-17 03:51:18 +00:00
Nextcloud bot
32b65f576f [tx-robot] updated from transifex 2019-12-15 03:50:26 +00:00
Nextcloud bot
f2bbb90d52 [tx-robot] updated from transifex 2019-12-14 03:50:17 +00:00
Nextcloud bot
ffbf06755f [tx-robot] updated from transifex 2019-12-13 03:50:26 +00:00
Nextcloud bot
58716bb406 [tx-robot] updated from transifex 2019-12-12 03:50:18 +00:00
Nextcloud bot
782d68afa8 [tx-robot] updated from transifex 2019-12-11 03:10:56 +00:00
Nextcloud bot
1c1f291778 [tx-robot] updated from transifex 2019-12-10 03:14:17 +00:00
Michael Schuster
b754eacd74 macOS: Rename 'Explorer' appropriately on non-Windows
- Rename it to 'Finder' on macOS.
- This way we also avoid having the whole string re-translated on Transifex.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-09 21:37:21 +01:00
Michael Schuster
7ce8a6a201 Make the ShareDialog background-aware (Dark-/Light-Mode switching)
Use customizeStyle() to change link colours, icons and pixmaps in the ShareDialog and notify
it's widgets via slots.

TODO - known issue (macOS):
- The background and font colours in the ShareUserLine widget still stay the same.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-09 21:37:21 +01:00
Michael Schuster
789a2a7ae3 Make SettingsDialog background-aware (Dark-/Light-Mode switching)
Use customizeStyle() to change link colours in the SettingsDialog and notify it's widgets via slots.

Also modify the background colour of the errors messages in AccountSettings::showConnectionLabel
to always use an appropiate colour for it's custom-defined background.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-09 21:37:21 +01:00
Michael Schuster
be4fc6b887 Implement and move some colour-aware helper methods into the Theme class
This introduces a new method to change the colours in the links in QLabel's.
Utilizes a custom crafted RegEx function to replace already-coloured links.

Moved code is based on stuff from the SettingsDialog class.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-09 21:37:21 +01:00
Michael Schuster
2dae31486a Pick from upstream: Fix too low contrast when tab is selected
The low contrast is also a problem with the Dark Mode on macOS.

For reference please see:
- Commit: 413ef5e96d
- Issue: https://github.com/owncloud/client/issues/7512

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-09 21:37:21 +01:00
Michael Schuster
71f66c6229 Fix SSL-button's info background color for Dark Mode
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-09 21:37:21 +01:00
Michael Schuster
b4f926ded7 Remove submodule qtmacgoodies and the MacSettingsDialog class
Reverts back to the SettingsDialog class because of bugs and glitches with
more recent Qt versions (Qt 5.12) and with the macOS Dark Mode.

See upstream: https://github.com/owncloud/client/pull/7492

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-09 21:37:21 +01:00
Dominique Fuchs
438a445353 Merge remote-tracking branch 'origin/master' into qml-tray-menu 2019-12-09 06:52:52 +01:00
Dominique Fuchs
6a04fe8ab6 Remove init.qml from CMakeLists and resource file
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-09 06:43:20 +01:00
Nextcloud bot
ca7bdf245e [tx-robot] updated from transifex 2019-12-09 03:11:08 +00:00
Dominique Fuchs
c45d2212a5 Removal of init.qml plus minor fixes
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-08 20:18:03 +01:00
Dominique Fuchs
66bfccc738 Replaced .engine() by pointer access b/c of backward compatibility
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-08 13:18:46 +01:00
Dominique Fuchs
ae7eddf7c9 Fixed inconsistent module import versions (based on Qt 5.9)
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-08 11:32:22 +01:00
Nextcloud bot
36a59f09ac [tx-robot] updated from transifex 2019-12-08 03:12:35 +00:00
Michael Schuster
5869b93acb Fix deleteKeychainEntries: Stay consistent with job->setInsecureFallback(false)
We never fall back to the insecure variant in the whole codebase, so don't do it here.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-08 02:47:22 +01:00
Michael Schuster
b15eb27aa9 Fix Windows key-chunk deletion (too paranoid)
Clear the key chunk buffer, but don't set _clientSslKeyChunkCount to zero because we need it later for deleteKeychainEntries

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-08 02:47:22 +01:00
Michael Schuster
336b64a569 Fix member variable name from last refactoring (Windows code)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-08 02:47:22 +01:00
Michael Schuster
6a49e787bb Fix Remote Wipe keychain storage
In certain cases don't write the app password in Account::writeAppPasswordOnce:
- id() is empty: This always happend once the Account Wizard showed the folder selection
- appPassword is empty: Caused by Logout -> Relaunch, preventing remote wipe on relaunch

Implement some logging to ease debugging in the future.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-08 02:47:22 +01:00
Michael Schuster
0c5f4a1525 Remote Wipe: Implement hack to allow deleting all keychain entries (SSL certs & keys)
Client SSL certificates and keys cannot be deleted at this time because there is
no UI for selecting them on re-login.

We introduce this dirty hack here, to allow deleting them upon Remote Wipe.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-08 02:47:22 +01:00
Michael Schuster
6ef9f3cc26 Refactoring: Windows workaround for >= 4k (4096 bit) client-cert SSL keys
WebFlowCredentials:
- Remove _clientSslCaKeyWriteQueue and simply use _clientSslKeyChunkBufferPEM
- Store key's sub-chunks in slots with "." (dot) suffix
- Implement deletion of the key chunks in WebFlowCredentials::deleteKeychainEntries
- Remove spaces in log messages
- Improve code readability

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-08 02:47:22 +01:00
Michael Schuster
72be80cbd9 Windows: Workaround for storing >= 4k (4096 bit) client-cert SSL keys
With QtKeychain on Windows, storing larger keys in one keychain entry causes the
following error due to limits in the Windows APIs:
  Error: "Credential size exceeds maximum size of 2560"

To avoid overhead on the other platforms and balance code duplication, this
approach puts some read- and write-parts into Windows-only defines.

For reference also see previous fixes:
- https://github.com/nextcloud/desktop/pull/1389
- https://github.com/nextcloud/desktop/pull/1394

This (again) fixes the re-opened issue:
- https://github.com/nextcloud/desktop/issues/863

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-08 02:47:22 +01:00
Nextcloud bot
99a27d19b9 [tx-robot] updated from transifex 2019-12-07 03:13:09 +00:00
Michael Schuster
877fd7abb9 Fall back to old login flow on GS as this is not yet ready (#2: re-auth)
This commit ensures that the check also occurs on re-authorization in case
the user gets logged out.

See: https://github.com/nextcloud/desktop/pull/1644

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-06 21:03:01 +01:00
Roeland Jago Douma
363e62f8fa Fall back to old login flow on GS as this is not yet ready
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
2019-12-06 21:03:01 +01:00
David Kahles
9a3aa55b29 Compare QDateTime objects more efficient
There is no need to call toMSecsSinceEpoch() as QDateTime implements an
comparison operator itself. This is more efficient, because the
QDateTime comparison operator doesn't call localtime() in all cases. Thus, we
don't read /etc/localtime for every comparison. This improves
performance in some cases.

Signed-off-by: David Kahles <david.kahles96@gmail.com>
2019-12-06 16:17:53 +01:00
Dominique Fuchs
ab9897b397 Added frontend invokation to open local folder
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-06 14:50:34 +01:00
Nextcloud bot
30829d0669 [tx-robot] updated from transifex 2019-12-06 03:13:10 +00:00
Dominique Fuchs
c18611d4af Finished account switch back- and frontend in tray menuwindow
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-05 11:38:29 +01:00
Dominique Fuchs
5eff8608fe Account swtich logic and UI updates
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-05 08:21:19 +01:00
Nextcloud bot
c25a56b2be [tx-robot] updated from transifex 2019-12-05 03:11:15 +00:00
Dominique Fuchs
3a4ca5e190 Working on account switching
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-04 16:19:42 +01:00
Dominique Fuchs
d1d1f9bb58 Connected AccountWizard with new account action in tray menu, minor fixes
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-04 14:19:23 +01:00
Dominique Fuchs
0c81d25e96 Clean up test variable
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-04 13:18:18 +01:00
Dominique Fuchs
90ace3fedc Minor preps for c++ ActivityListModel impl. in QML
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-04 13:10:28 +01:00
Dominique Fuchs
3a0ccf3697 connected UserModel login/logout signals, minor fixes
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-04 13:00:26 +01:00
Nextcloud bot
ea1e42cb83 [tx-robot] updated from transifex 2019-12-04 10:22:14 +00:00
Dominique Fuchs
4e0997dbdf Minor fixes and enhancements
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-04 08:06:56 +01:00
Nextcloud bot
50b4fdc03d [tx-robot] updated from transifex 2019-12-04 03:10:59 +00:00
Dominique Fuchs
57084fbd3e WIP: working UserModel.cpp and account menu
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-03 22:15:25 +01:00
Dominique Fuchs
4478399282 More stuff regarding tray/UserModel.cpp
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-03 18:50:34 +01:00
Dominique Fuchs
53abf5a316 WIP: Building User/MenuModel backend for tray menu
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-03 17:25:11 +01:00
Joas Schilling
9ce2491d67 Use … instead of 3 dots
Signed-off-by: Joas Schilling <coding@schilljs.com>
2019-12-03 09:06:06 +01:00
Joas Schilling
ec637217f2 Fix some translations
Signed-off-by: Joas Schilling <coding@schilljs.com>
2019-12-03 09:06:06 +01:00
Joas Schilling
91a5395e1a Improve the translation of "Share via …"
Signed-off-by: Joas Schilling <coding@schilljs.com>
2019-12-03 09:06:06 +01:00
Dominique Fuchs
dac1c9b413 Avatar, full user name and server address now reflected in QML gui, provided by C++ backend
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-12-03 07:26:59 +01:00
Dominique Fuchs
c21e4f5982 Clean up test variable 2019-12-02 22:48:39 +01:00
Dominique Fuchs
478281d853 Restructures and refactorings: New systray class, handling of current user selection, integration of user information in tray window header 2019-12-02 22:45:14 +01:00
Dominique Fuchs
08d4c56886 WIP: Extending systray class, transitioning towas independent ActivityModel inclusion 2019-12-02 14:10:18 +01:00
Nextcloud bot
4987add452 [tx-robot] updated from transifex 2019-12-02 03:10:52 +00:00
Nextcloud bot
6a9f155856 [tx-robot] updated from transifex 2019-11-30 03:10:58 +00:00
Michael Schuster
407864c40e Fix copyright year in MacOSXBundleInfo.plist.in for 2019
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-29 17:24:25 +01:00
Dominique Fuchs
03c0d8ba5a Minor preps for c++ ActivityListModel impl. in QML 2019-11-29 17:06:35 +01:00
Michael Schuster
76c7ab499f Use ReadPasswordJob::finished for ReadPasswordJob
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-29 13:53:52 +01:00
Michael Schuster
dcc84d3508 Fix remote wipe keychain storage (issue #1592)
The app password for the remote wipe was constantly being written in
WebFlowCredentials::slotFinished to the keychain, leading to unnecessary
write and log overhead on the system.

This fix introduces a check to only store the app password once in
a lifetime of the Account class. Also the method used to store the
password will be renamed from setAppPassword to writeAppPasswordOnce
to be more expressive.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-29 13:53:52 +01:00
Nextcloud bot
8ae18d9935 [tx-robot] updated from transifex 2019-11-29 03:10:32 +00:00
Nextcloud bot
013e08f80a [tx-robot] updated from transifex 2019-11-28 03:12:08 +00:00
Nextcloud bot
33dd60107d [tx-robot] updated from transifex 2019-11-27 03:07:47 +00:00
István Váradi
2fc76c2b24 Build for Debian stable and oldstable
Signed-off-by: István Váradi <ivaradi@varadiistvan.hu>
2019-11-26 16:20:11 +01:00
Christoph Wurst
923abd8d0b Fix legal notice year
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
2019-11-26 12:46:02 +01:00
Nextcloud bot
dc6c638f34 [tx-robot] updated from transifex 2019-11-26 03:07:54 +00:00
Nextcloud bot
2081a265b1 [tx-robot] updated from transifex 2019-11-23 03:09:19 +00:00
Nextcloud bot
a72c3ba8f0 [tx-robot] updated from transifex 2019-11-22 03:09:11 +00:00
Nextcloud bot
363a865263 [tx-robot] updated from transifex 2019-11-21 03:08:55 +00:00
Nextcloud bot
b40e753696 [tx-robot] updated from transifex 2019-11-20 03:09:39 +00:00
Nextcloud bot
58e99184bb [tx-robot] updated from transifex 2019-11-19 03:08:32 +00:00
Nextcloud bot
79ba95ce04 [tx-robot] updated from transifex 2019-11-18 03:06:58 +00:00
Michael Schuster
93319a6a61 Merge pull request #1623 from nextcloud/mac-prepare-notarization
macOS build: Avoid the Get-Task-Allow Entitlement (Notarization)
2019-11-17 21:54:47 +01:00
Michael Schuster
7fb0a82e69 macOS build: Avoid the Get-Task-Allow Entitlement (Notarization)
Setting CODE_SIGN_INJECT_BASE_ENTITLEMENTS to NO is required for macOS
Notarization.

See: https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution/resolving_common_notarization_issues

And upstream: 97f4af32ae

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-17 21:33:04 +01:00
Michael Schuster
e9e6b85bd9 Merge pull request #1621 from nextcloud/mac-sign-timestamp
Add timestamp to Mac installer code signing
2019-11-17 18:12:29 +01:00
Michael Schuster
3b5966bba0 Add timestamp to Mac installer code signing
Use the --timestamp option for 'productsign' to add a secure timestamp.

See: https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution/resolving_common_notarization_issues

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-17 17:50:52 +01:00
Nextcloud bot
7fc592cb22 [tx-robot] updated from transifex 2019-11-17 03:09:30 +00:00
Michael Schuster
c7299dec78 Merge pull request #1619 from nextcloud/bumpQt-5.12.5
Bump Qt 5.12.5 image
2019-11-17 03:19:25 +01:00
Michael Schuster
fce0a50e37 Fix: add /usr/local/lib to LD_LIBRARY_PATH for OpenSSL 1.1.1
Drone pipeline qt-5.12 failed because the unit tests didn't find OpenSSL.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-17 02:56:53 +01:00
Michael Schuster
c047232c3b Fix: escape env vars
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-17 01:59:04 +01:00
Michael Schuster
a846f0276d Bump Qt 5.12.5 image
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-17 01:30:53 +01:00
Michael Schuster
e2cb3aa078 Merge pull request #1617 from nextcloud/appimageQt-5.12.5
Upgrade for Qt 5.12.5 in docker-ci
2019-11-16 22:09:36 +01:00
Michael Schuster
801098f546 Fix dir in upload script
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-16 21:53:25 +01:00
Michael Schuster
4fc8936553 Make AppImage upload optional and add timeout
Moves the upload into a separate Drone command and adds a timeout for curl
to fail after 15 minutes.

Returns zero to keep Drone from failing.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-16 21:36:59 +01:00
Michael Schuster
dd0135ce2e Move .desktop file path to new env var to avoid duplicates
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-16 21:34:13 +01:00
Michael Schuster
d830a1c5f7 Upgrade for Qt 5.12.5 in docker-ci
- Use the new image: nextcloudci/client-5.12:client-5.12-5
- Use it's new QT_BASE_DIR: /opt/qt5.12.5

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-16 21:31:07 +01:00
Nextcloud bot
403df7cebc [tx-robot] updated from transifex 2019-11-16 03:06:41 +00:00
Nextcloud bot
45bc034261 [tx-robot] updated from transifex 2019-11-15 03:07:58 +00:00
Nextcloud bot
bbbead5769 [tx-robot] updated from transifex 2019-11-14 03:07:51 +00:00
Michael Schuster
fca7b32405 Merge pull request #1604 from nextcloud/rakekniven-patch-1
l10n: Remove string from Transifex resource
2019-11-14 03:22:29 +01:00
Michael Schuster
d558af31c9 Merge pull request #1605 from nextcloud/revert-1586-qt5.5-compat
Revert and Fix "Remove HTTP/2 support from Xenial"
2019-11-14 03:19:09 +01:00
Michael Schuster
5131463644 Fix: Apply http2 patch from owncloud #1573 - only with Qt >= 5.8
Drone builds failed with Qt 5.7 and we introduce a new ifdef here
to avoid patching specifically for Ubuntu Xenial only.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-14 02:39:06 +01:00
Michael Schuster
9e8498ad4e Revert "Remove HTTP/2 support from Xenial" 2019-11-14 02:22:01 +01:00
Michael Schuster
3777ae4624 Merge pull request #1586 from ivaradi/qt5.5-compat
Remove HTTP/2 support from Xenial
2019-11-14 01:45:19 +01:00
rakekniven
e896c41ef9 l10n: Remove string from Transifex resource
Fix for #1578 

Signed-off-by: rakekniven <mark.ziegler@rakekniven.de>
2019-11-13 18:03:22 +01:00
Nextcloud bot
9d8b8be8d2 [tx-robot] updated from transifex 2019-11-13 03:07:30 +00:00
Nextcloud bot
1c15b97b11 [tx-robot] updated from transifex 2019-11-12 03:09:20 +00:00
Nextcloud bot
8017ee45f5 [tx-robot] updated from transifex 2019-11-10 03:11:47 +00:00
Nextcloud bot
8c1e3cabe0 [tx-robot] updated from transifex 2019-11-09 03:03:34 +00:00
Michael Schuster
0c6279f86a Merge branch 'master' into qt5.5-compat 2019-11-07 15:49:43 +01:00
Nextcloud bot
1cffa3b731 [tx-robot] updated from transifex 2019-11-07 03:06:07 +00:00
Nextcloud bot
549acb0785 [tx-robot] updated from transifex 2019-11-06 03:08:01 +00:00
István Váradi
a143b42c2a Remove HTTP/2 support from Xenial
Signed-off-by: István Váradi <ivaradi@varadiistvan.hu>
2019-11-05 19:34:32 +01:00
Nextcloud bot
e85ad9de6a [tx-robot] updated from transifex 2019-11-05 03:05:20 +00:00
Camila Ayres
0ab5bbb08e Merge pull request #1522 from adrb/issue_1351
* fix for issue no. 1351
2019-11-04 22:48:20 +01:00
Camila Ayres
4efa282f80 Merge branch 'master' into issue_1351 2019-11-04 22:48:07 +01:00
Camila Ayres
d53cfbd9fb Merge pull request #1573 from Milokita/master
Fix #1182 - upload of files with umlaut.
2019-11-04 20:21:17 +01:00
Camila Ayres
94986877d8 Merge branch 'master' into master 2019-11-04 20:20:32 +01:00
Camila Ayres
f3bc2f5e87 Merge pull request #1579 from nextcloud/fix-remote-wipe-proxy
Fix remote wipe when a proxy is configured.
2019-11-04 20:16:53 +01:00
Camila Ayres
a5365a6cce Merge branch 'master' into master 2019-11-04 20:14:11 +01:00
Michael Schuster
b9ad82ceeb Merge branch 'master' into fix-remote-wipe-proxy 2019-11-04 19:58:56 +01:00
Camila Ayres
fe959fe0d5 Merge pull request #1580 from nextcloud/fix-updater-message
Fix updater message: Download link instead of "use the system's updat…
2019-11-04 19:55:39 +01:00
Michael Schuster
6421397083 Fix updater message: Download link instead of "use the system's update tool"
Provide a download link to the new version instead of the confusing message that
users should use their "system's update tool to install it".

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-11-04 19:19:59 +01:00
Camila San
52ae354ca2 Fix remote wipe when a proxy is configured.
Signed-off-by: Camila San <hello@camila.codes>
2019-11-04 17:52:02 +00:00
Dominique Fuchs
c6ff66be79 Smoother deletions: Added animation for removeDisplaced including sequential opacity change and displacement animation
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-11-04 12:48:07 +01:00
Nextcloud bot
73af9b1cac [tx-robot] updated from transifex 2019-11-04 03:08:04 +00:00
Nextcloud bot
cdaee7b933 [tx-robot] updated from transifex 2019-11-03 03:09:40 +00:00
Nextcloud bot
6adbd9bd50 [tx-robot] updated from transifex 2019-11-02 03:04:09 +00:00
Nextcloud bot
6acf3871e4 [tx-robot] updated from transifex 2019-11-01 02:56:47 +00:00
XNG
ead2131ba2 Merge branch 'master' of https://github.com/Milokita/desktop 2019-11-01 09:35:19 +08:00
XNG
cf1532acf1 Apply http2 patch from owncloud
Signed-off-by: XNG <Milokita@users.noreply.github.com>
2019-11-01 09:35:10 +08:00
XNG
17ca7ab5db Apply http2 patch from owncloud
Signed-off-by: XNG <Milokita@users.noreply.github.com>
2019-11-01 09:22:52 +08:00
XNG
c42332a5ee Merge pull request #1 from nextcloud/master
Just some catch up
2019-11-01 08:48:06 +08:00
Nextcloud bot
c736f48ac9 [tx-robot] updated from transifex 2019-10-31 02:57:51 +00:00
Dominique Fuchs
06b251063e Initial ListView design/modeling for activity list
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-10-30 20:47:21 +01:00
Dominique Fuchs
cb7b2a3dc6 Merge branch 'master' into qml-tray-menu 2019-10-30 17:19:18 +01:00
Nextcloud bot
5ac203ebd8 [tx-robot] updated from transifex 2019-10-30 02:56:18 +00:00
Dominique Fuchs
6135eb26ad Finished (static) header design and hover effects
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-10-29 23:25:00 +01:00
Dominique Fuchs
d18e2ba339 Merge pull request #1429 from nextcloud/recipientnote
Finishing PR #1154
2019-10-29 14:49:36 +01:00
Dominique Fuchs
7ed03f1f29 resolving conflict with current master
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-10-29 14:07:26 +01:00
Dominique Fuchs
5301477747 Merge branch 'master' into recipientnote 2019-10-29 12:58:14 +01:00
Dominique Fuchs
73667a5367 Updated vecto icons and names, disabled init position (breaks on multiple monitors on windows), integrated new icons in qml
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-10-29 08:13:05 +01:00
Nextcloud bot
09c282d9ea [tx-robot] updated from transifex 2019-10-29 03:05:48 +00:00
Dominique Fuchs
f9f1b49298 Added new vector graphics for tray window header icons
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-10-28 10:36:09 +01:00
Nextcloud bot
f5ff69f8b3 [tx-robot] updated from transifex 2019-10-28 03:05:30 +00:00
Camila San
1e43c29484 Add new qml tray icon.
This is a work in progress.

Signed-off-by: Camila San <hello@camila.codes>
2019-10-27 20:02:30 +01:00
Michael Schuster
a15cad0088 Merge pull request #1451 from nextcloud/move-rtfiles
Move journal files away from sync folder to standardized location
2019-10-27 18:03:49 +01:00
Michael Schuster
8e8858178b Merge branch 'master' into move-rtfiles 2019-10-27 17:49:22 +01:00
Michael Schuster
528352ba82 Merge pull request #1449 from nextcloud/lnx-domainname-desktopfiles
Linux/Wayland: Updated .desktop file naming scheme
2019-10-27 17:48:28 +01:00
Michael Schuster
e54f127a06 Merge branch 'master' into lnx-domainname-desktopfiles 2019-10-27 17:30:48 +01:00
Michael Schuster
d9fd9cfef2 Merge pull request #1454 from nextcloud/syncjournal-del-prio
Prioritize DELETE instruction in SyncFileVector (merged trees)
2019-10-27 17:29:03 +01:00
Michael Schuster
9618500975 fix tab spacing
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-10-27 17:25:50 +01:00
Michael Schuster
25076f2ddc tab formatting (just a little more ;p)
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-10-27 17:03:23 +01:00
Dominique Fuchs
66912071a8 Merge branch 'syncjournal-del-prio' of https://github.com/nextcloud/desktop into syncjournal-del-prio 2019-10-27 16:56:07 +01:00
Dominique Fuchs
e9438549f4 tab formatting
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-10-27 16:55:37 +01:00
Dominique Fuchs
eff75a2059 Merge branch 'master' into move-rtfiles 2019-10-27 15:43:41 +01:00
Dominique Fuchs
d001d9d1a3 Merge branch 'master' into syncjournal-del-prio 2019-10-27 15:38:43 +01:00
Dominique Fuchs
5c3f71c097 Merge branch 'master' into qml-tray-menu 2019-10-27 15:38:16 +01:00
Dominique Fuchs
7f764f8108 Added basic UI [WIP] for new tray window
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-10-27 15:19:20 +01:00
Nextcloud bot
2dcf594fc6 [tx-robot] updated from transifex 2019-10-27 03:04:17 +00:00
Nextcloud bot
076469f385 [tx-robot] updated from transifex 2019-10-26 03:05:59 +00:00
Nextcloud bot
e178eeb7f5 [tx-robot] updated from transifex 2019-10-25 03:06:12 +00:00
Nextcloud bot
a8cf6e0443 [tx-robot] updated from transifex 2019-10-24 03:05:27 +00:00
Michael Schuster
725458b63c Merge pull request #1554 from sryze/fix-duplicate-apps
Fix duplicate items in Apps menu (a bug introduced in #1477)
2019-10-23 23:44:54 +02:00
Sergey Zolotarev
9a11bef263 Fix duplicate items in Apps menu (a bug introduced in #1477)
Signed-off-by: Sergey Zolotarev <sryze@protonmail.com>
2019-10-24 02:55:56 +06:00
Michael Schuster
b184cba953 Merge pull request #1553 from nextcloud/jospoortvliet-patch-1
Update ChangeLog
2019-10-23 22:45:55 +02:00
Jos Poortvliet
8b393ce792 Update ChangeLog
Link to https://github.com/nextcloud/desktop/releases as there's no plan to keep the changelog file up to date.
2019-10-23 21:30:40 +02:00
Nextcloud bot
f801ffe4f7 [tx-robot] updated from transifex 2019-10-23 03:05:14 +00:00
Camila Ayres
b293a5b818 Merge pull request #1529 from nextcloud/samu-workopen-patch-2-1
Replace command line Step 5 Install Homebrew
2019-10-22 15:08:11 +02:00
Camila Ayres
beffd726bd Merge branch 'master' into samu-workopen-patch-2-1 2019-10-22 15:08:01 +02:00
Camila Ayres
41f6c9e52d Merge pull request #1530 from nextcloud/samu-workopen-patch-1
Update Installing Mac Step 11
2019-10-22 15:01:58 +02:00
Camila Ayres
ce71673824 Merge branch 'master' into samu-workopen-patch-1 2019-10-22 14:59:45 +02:00
Camila Ayres
e05f187fcf Merge pull request #1544 from asapelkin/address_sanitizer
Enabled address sanitizing for tests
2019-10-22 14:59:33 +02:00
Camila Ayres
04b5754653 Merge branch 'master' into address_sanitizer 2019-10-22 14:43:37 +02:00
Camila Ayres
44bc3692fd Merge pull request #1527 from nextcloud/qt-5.12.5-update-submodules
Update submodules for Qt 5.12.5 (qtmacgoodies)
2019-10-22 14:41:51 +02:00
Camila Ayres
3a310f93e0 Merge branch 'master' into qt-5.12.5-update-submodules 2019-10-22 14:31:27 +02:00
Nextcloud bot
706769026d [tx-robot] updated from transifex 2019-10-22 03:06:06 +00:00
asapelkin
704e34fa99 enabled address sanitizing for tests
Signed-off-by: asapelkin <asapelkin0x01@ya.ru>
2019-10-22 01:13:59 +03:00
Roeland Jago Douma
a6fae36cb2 Merge pull request #1536 from nextcloud/ci/bump5.12image/libsecret
Bump Qt5.12 image
2019-10-21 20:27:53 +02:00
Roeland Jago Douma
4c791abafc Bump Qt5.12 image
Main improvement is that this image contains the libsecret.
So when building qtkeychain that should be used.

Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
2019-10-21 14:50:25 +02:00
István Váradi
11e14f1726 Merge pull request #1531 from ivaradi/debian-dbus
Add libdbus-1-dev to the build dependencies
2019-10-21 14:03:03 +02:00
István Váradi
0273689ca9 Merge branch 'master' into debian-dbus 2019-10-21 11:39:51 +02:00
Nextcloud bot
05a56c2e8e [tx-robot] updated from transifex 2019-10-21 03:06:00 +00:00
Michael Schuster
325dd8732e Merge pull request #1487 from nextcloud/testSyncFileStatusTracker-winPath
Fix tests for Windows platform
2019-10-20 21:48:36 +02:00
Michael Schuster
4d5dd0f49c Merge branch 'master' into testSyncFileStatusTracker-winPath 2019-10-20 21:33:19 +02:00
Michael Schuster
39d85fd008 Merge pull request #1532 from nextcloud/fix-msvc-clang-variadic-macro-warning-fix
MSVC Fix for PR #1526: Fix clang's variadic macro warnings
2019-10-20 13:31:01 +02:00
Michael Schuster
a12164ad53 MSVC Fix for PR #1526: Fix clang's variadic macro warnings
The recently merged #1526 caused the MSVC Builds on Windows to fail.

This patch sets the new CMake flag only if the compiler it not MSVC.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-10-20 12:52:52 +02:00
István Váradi
805b85a4d7 Add libdbus-1-dev to the build dependencies
Signed-off-by: István Váradi <ivaradi@varadiistvan.hu>
2019-10-20 10:23:49 +02:00
Nextcloud bot
cacb300ffd [tx-robot] updated from transifex 2019-10-20 03:08:24 +00:00
samu-workopen
15e36c535f Update Step 11
Step 11 is completely outdated, please replace it with: 
Enable git submodules:
$ cd desktop
$ git submodule init
$ git submodule update
Generate the build files:
$ cd build
$ cmake .. -DCMAKE_INSTALL_PREFIX=~/nextcloud-desktop-client -DCMAKE_BUILD_TYPE=Debug -DNO_SHIBBOLETH=1
2019-10-19 16:11:49 +02:00
Camila Ayres
b5e51c7e34 Merge pull request #1528 from nextcloud/samu-workopen-patch-1
Update building instructions.
2019-10-19 15:14:17 +02:00
samu-workopen
e4482ef675 Replace command line Step 5 Install Homebrew
replace brew install "qt5 --with-qtwebkit" with "install qt5" otherwise it will not work
2019-10-19 15:06:07 +02:00
samu-workopen
09b3be25fc Update building instructions
Added links and a description how to clone the repo
2019-10-19 14:21:04 +02:00
Michael Schuster
7235db2793 Merge branch 'master' into qt-5.12.5-update-submodules 2019-10-19 05:43:23 +02:00
Nextcloud bot
35005e46b4 [tx-robot] updated from transifex 2019-10-19 03:04:56 +00:00
Michael Schuster
abd50022d1 Update submodules for Qt 5.12.5 (qtmacgoodies)
Fetch the new submodule commits to get these fixes:
- Merge upstream: Retrieve the associated NSView more reliably: https://github.com/camilasan/qtmacgoodies/pull/1
- Bugfix for Qt 5.12.5 - Redraw the ToolBar: https://github.com/camilasan/qtmacgoodies/pull/2

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-10-19 05:04:41 +02:00
Michael Schuster
e9c12c32d2 Merge pull request #1526 from JohannesLorenz/clang-variadic-macro-warning-fix
Fix clang's variadic macro warnings
2019-10-19 04:41:54 +02:00
Michael Schuster
8950417d37 Merge branch 'master' into clang-variadic-macro-warning-fix 2019-10-19 04:37:42 +02:00
Michael Schuster
8c6e2f84c1 Merge pull request #1471 from tintou/master
Build with libcloudproviders on debian and in the AppImage

NOTE:
The admin/linux/Dockerfile is outdated and the following repo is currently used for our daily builds:
https://github.com/nextcloud/docker-ci/tree/master/client

This fix will be added there soon too.
2019-10-19 04:36:08 +02:00
Michael Schuster
d0aec7696a Merge branch 'master' into master 2019-10-19 03:50:43 +02:00
Michael Schuster
a9da2a2277 Merge pull request #1456 from andwun/fix/too-low-default-poll-interval
Revert DEFAULT_REMOTE_POLL_INTERVAL back from 5 seconds to 30 seconds
2019-10-19 03:48:39 +02:00
Michael Schuster
4f1e4e149f Merge branch 'master' into fix/too-low-default-poll-interval 2019-10-19 03:40:21 +02:00
Adrian Brzezinski
bd25144390 Merge branch 'issue_1351' of https://github.com/adrb/desktop into issue_1351
Signed-off-by: Adrian Brzezinski <adrian.brzezinski@eo.pl>
2019-10-18 08:30:46 +02:00
Adrian Brzezinski
3d1fc20d01 Merge branch 'issue_1351' of https://github.com/adrb/desktop into issue_1351
Signed-off-by: Adrian Brzezinski <adrian.brzezinski@eo.pl>
2019-10-18 08:24:50 +02:00
adrb
921b144d06 Merge branch 'master' into issue_1351 2019-10-18 08:19:32 +02:00
Adrian Brzezinski
12d306fa85 Merge branch 'issue_1351' of https://github.com/adrb/desktop into issue_1351 2019-10-18 08:18:19 +02:00
Adrian Brzezinski
3b750895b4 * fix for issue no. 1351
Signed-off-by: Adrian Brzezinski <adrian.brzezinski@eo.pl>
2019-10-18 08:16:59 +02:00
Johannes Lorenz
8c334a1f43 Fix clang's variadic macro warnings
Using variadic macros like `qCWarning()` without any parameter for "..."
is a GNU extension, which causes a lot of `clang` warnings:

```
desktop/src/common/ownsql.cpp:74:24: warning: must specify at least one
 argument for '...' parameter of variadic macro
 [-Wgnu-zero-variadic-macro-arguments]
        qCWarning(lcSql) << "Error:" << _error << "for" << filename;
                       ^
/usr/include/qt/QtCore/qloggingcategory.h:140:11: note: macro 'qCWarning'
 defined here
          ^
```

This patch tells `clang` to be silent.

Signed-off-by: Johannes Lorenz <j.git@lorenz-ho.me>
2019-10-18 05:25:05 +02:00
Nextcloud bot
6db3b2fb78 [tx-robot] updated from transifex 2019-10-18 03:04:52 +00:00
Michael Schuster
5775ec1ff1 Merge pull request #1504 from nextcloud/feature/remote-wipe
Remote wipe for RC1.
2019-10-17 22:23:37 +02:00
Michael Schuster
32bb31a417 Merge branch 'master' into feature/remote-wipe 2019-10-17 22:05:20 +02:00
Michael Schuster
87844f5ff4 Merge pull request #1523 from nextcloud/improvement/merge-ignored-files-notification
Merge the list of ignored files/symlinks into one Activity notification.
2019-10-17 22:04:18 +02:00
Camila San
19491ff85f Once client gets 401/403 from the server, check if remote wipe was requested.
- When the the users logs because of 401 or 403 errors, it checks if the
server requested the remote wipe. If yes, locally deletes account and folders
connected to the account and notify the server. If no, proceeds to ask the
user to login again.
- The app password is restored in the keychain.
- WIP: The change also includes a test class for RemoteWipe.

Signed-off-by: Camila San <hello@camila.codes>
2019-10-17 20:11:31 +02:00
Camila San
8546d53b05 Merge the list of ignored files/symlinks into one Activity notification.
Signed-off-by: Camila San <hello@camila.codes>
2019-10-17 18:45:33 +02:00
Adrian Brzezinski
dfb20586ce * fix for issue no. 1351 2019-10-17 14:45:38 +02:00
Camila Ayres
5783c406a2 Merge branch 'master' into master 2019-10-17 13:44:07 +02:00
Camila Ayres
6c56811636 Merge branch 'master' into testSyncFileStatusTracker-winPath 2019-10-17 13:37:01 +02:00
Camila Ayres
08c7be5350 Merge pull request #1520 from nextcloud/fix-mac-crash-qtmacgoodies-pr-1
Pick from upstream: Update qtmacgoodies for an OSX crash fix #6930
2019-10-17 13:35:58 +02:00
Michael Schuster
ade9c6ce72 Merge branch 'master' into fix-mac-crash-qtmacgoodies-pr-1 2019-10-17 05:50:38 +02:00
Nextcloud bot
fdefb19bdb [tx-robot] updated from transifex 2019-10-17 03:05:50 +00:00
Michael Schuster
ade50d0b92 Pick from upstream: Update qtmacgoodies for an OSX crash fix #6930
With Qt 5.12.5 this OC crash also applies to the Nextcloud Desktop Client on macOS.

For reference please see:
- https://github.com/owncloud/client/issues/6930
- 0dc7bc3328

For the required changes in the qtmacgoodies submodule see:
https://github.com/camilasan/qtmacgoodies/pull/1

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-10-17 04:29:33 +02:00
Michael Schuster
09bae4d6e1 Merge pull request #1478 from sryze/quit-wizard-fix
Don't run connection wizard when quitting the application
2019-10-16 14:01:42 +02:00
Michael Schuster
0c30d9cfe8 Merge branch 'master' into quit-wizard-fix 2019-10-16 05:19:21 +02:00
Nextcloud bot
94dae8d535 [tx-robot] updated from transifex 2019-10-16 03:04:57 +00:00
Michael Schuster
e8fc3ecf28 Merge branch 'master' into quit-wizard-fix 2019-10-16 04:43:41 +02:00
Michael Schuster
b3a03e9c58 Merge pull request #1516 from nextcloud/backport/1515/master
[master] Add new "styles" plugin to macOS deployment script for Qt 5.12.5
2019-10-16 01:44:49 +02:00
Michael Schuster
097b923871 Add new "styles" plugin to macOS deployment script for Qt 5.12.5
Qt 5.12 needs this library to use the correct style for Light / Dark Mode:

  styles/libqmacstyle.dylib

The interface looks like from the 1990's without this library ;-)

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-10-15 23:32:04 +00:00
Nextcloud bot
f422a63200 [tx-robot] updated from transifex 2019-10-15 03:04:26 +00:00
Nextcloud bot
eec460a32d [tx-robot] updated from transifex 2019-10-13 03:05:59 +00:00
Nextcloud bot
5ccea62ba6 [tx-robot] updated from transifex 2019-10-12 03:05:06 +00:00
Nextcloud bot
529beb328a [tx-robot] updated from transifex 2019-10-11 03:02:18 +00:00
Michael Schuster
796cc8cd28 Merge pull request #1495 from nextcloud/fix-flow2-content-length
Add a 'Content-Length: 0' header to initial POST requests
2019-10-10 08:08:26 +02:00
Michael Schuster
c8b4145214 Add a 'Content-Length: 0' header to initial POST requests
The webserver lighttpd rejected POST requests without a Content-length
header with "411 Length Required".

See: https://github.com/nextcloud/desktop/issues/1473

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-10-10 05:17:22 +02:00
Michael Schuster
04a9f0313a Merge pull request #1481 from asapelkin/for_loop_optimization
Avoiding copying in range-based loops
2019-10-10 01:30:40 +02:00
Michael Schuster
6166961804 Merge pull request #1441 from nextcloud/trexcl
Fixed missing 'translatable' exclusions, added missing window titles
2019-10-10 01:29:57 +02:00
Michael Schuster
4ddc606361 Merge branch 'master' into for_loop_optimization 2019-10-10 01:12:57 +02:00
Michael Schuster
836c748cd9 Merge branch 'master' into trexcl 2019-10-10 01:12:48 +02:00
Michael Schuster
3bee0bcf04 Merge pull request #1032 from k1l1/master
Changed max GUI bandwidth limits
2019-10-10 01:09:01 +02:00
Michael Schuster
0d349d54b4 Fix outdated link to server admin docs
Sets the target version from "15" to "latest" and removes
"index.html" because this could get obsolete in the future too.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-10-10 01:03:46 +02:00
Michael Schuster
29123f4d9d Merge branch 'master' into master 2019-10-10 00:45:04 +02:00
Michael Schuster
a16c1a8957 Merge branch 'master' into for_loop_optimization 2019-10-10 00:41:46 +02:00
Dominique Fuchs
c1cd308940 Merge branch 'master' into quit-wizard-fix 2019-10-09 09:18:26 +02:00
Sergey Zolotarev
4bba498229 Replace isQuitting flag with disconnect()
Signed-off-by: Sergey Zolotarev <sryze@protonmail.com>
2019-10-09 11:07:00 +06:00
Nextcloud bot
40b2fc8848 [tx-robot] updated from transifex 2019-10-09 03:04:39 +00:00
Dominique Fuchs
6bc13fcab1 Merge branch 'master' into for_loop_optimization 2019-10-08 10:36:25 +02:00
Dominique Fuchs
c3cb7dfadd Merge branch 'testSyncFileStatusTracker-winPath' of https://github.com/nextcloud/desktop into testSyncFileStatusTracker-winPath 2019-10-08 08:44:23 +02:00
Dominique Fuchs
7750d2198d Don't need a second if for non-Windows, using Qt macro for platform check
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-10-08 08:44:08 +02:00
Dominique Fuchs
3ced2a6ea3 Merge branch 'master' into testSyncFileStatusTracker-winPath 2019-10-08 08:37:29 +02:00
Dominique Fuchs
f993e7c555 Fixed typo preventing successful path rename on Win and modified ASSERT for Window path styles
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-10-08 08:31:31 +02:00
Nextcloud bot
35df5691f2 [tx-robot] updated from transifex 2019-10-08 03:03:10 +00:00
asapelkin
6b71e4ec6f Merge branch 'master' into for_loop_optimization 2019-10-07 15:31:01 +03:00
Camila Ayres
9c199cc753 Merge pull request #1477 from sryze/tray-menu-fix
Prevent jumping of tray menu
2019-10-07 12:53:28 +02:00
asapelkin
57f9b8159f Merge branch 'master' into for_loop_optimization 2019-10-07 12:35:18 +03:00
Camila Ayres
a94e116926 Merge branch 'master' into tray-menu-fix 2019-10-07 09:56:40 +02:00
Dominique Fuchs
75444e44b9 Merge branch 'master' into master 2019-10-07 09:45:22 +02:00
Nextcloud bot
dbfa5dc786 [tx-robot] updated from transifex 2019-10-07 03:02:44 +00:00
asapelkin
17f39bd09d little loops optimization
Signed-off-by: asapelkin <asapelkin0x01@ya.ru>
2019-10-07 01:29:55 +03:00
Nextcloud bot
7c8e650c5a [tx-robot] updated from transifex 2019-10-06 03:05:29 +00:00
Sergey Zolotarev
eaddc55267 Don't run connection wizard when quitting the application
Signed-off-by: Sergey Zolotarev <sryze@protonmail.com>
2019-10-05 22:38:47 +06:00
Sergey Zolotarev
f6b6765424 Prevent jumping of tray menu
Instead of adding the "Apps" menu after the apps are fetched, add it
from the start (together with other actions) but in a disabled state,
and enable it after the apps data is ready.

Signed-off-by: Sergey Zolotarev <sryze@protonmail.com>
2019-10-05 22:10:35 +06:00
Dominique Fuchs
f3ab9d5fef Merge branch 'master' into master 2019-10-05 10:35:59 +02:00
Nextcloud bot
998354b5ab [tx-robot] updated from transifex 2019-10-05 03:04:09 +00:00
Michael Schuster
852d39e271 Merge pull request #1465 from nextcloud/show-server-vers
Add server info to menu
2019-10-05 01:50:38 +02:00
Michael Schuster
7deb74cc22 Merge branch 'master' into show-server-vers 2019-10-05 00:44:08 +02:00
Michael Schuster
ba6d1ab886 Merge pull request #1474 from nextcloud/rakekniven-patch-1
Fixed grammar
2019-10-05 00:43:05 +02:00
Michael Schuster
c72aa457b3 Merge branch 'master' into rakekniven-patch-1 2019-10-05 00:04:39 +02:00
István Váradi
6ed6a5e8ea Merge pull request #1467 from ivaradi/fix-eoan-build
Remove kdelibs5-dev from the build dependencies for Eoan
2019-10-04 21:29:51 +02:00
István Váradi
fd7ba861a1 Merge branch 'master' into fix-eoan-build 2019-10-04 20:15:38 +02:00
rakekniven
b25aa99de7 Fixed grammar
Reported at Transifex.
See https://www.transifex.com/nextcloud/nextcloud/translate/#nl/client/182396083

Signed-off-by: rakekniven <mark.ziegler@rakekniven.de>
2019-10-04 08:10:55 +02:00
Nextcloud bot
dddb233f16 [tx-robot] updated from transifex 2019-10-04 03:05:53 +00:00
Corentin Noël
04dd02c295 Build with libcloudproviders on debian and in the AppImage
Signed-off-by: Corentin Noël <corentin.noel@collabora.com>
2019-10-03 10:33:46 +02:00
Nextcloud bot
3f495a30e0 [tx-robot] updated from transifex 2019-10-03 03:03:10 +00:00
István Váradi
37f74291b5 Remove kdelibs5-dev from the build dependencies for Eoan
Signed-off-by: István Váradi <ivaradi@varadiistvan.hu>
2019-10-02 20:04:23 +02:00
Nextcloud bot
361c5a5a54 [tx-robot] updated from transifex 2019-10-02 03:05:56 +00:00
Daniel Kesselberg
4114fe68c9 Add server info to menu
Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
2019-10-01 16:16:20 +02:00
Camila Ayres
4dddf88569 Merge pull request #1459 from tribut/fix-ldap-display-name
Use user-provided username in `displayName()` - Fix #836
2019-10-01 15:06:15 +02:00
Camila Ayres
7f19d5669b Merge branch 'master' into fix-ldap-display-name 2019-10-01 12:34:39 +02:00
Roeland Jago Douma
c6705ecd9c Merge pull request #1462 from tribut/fix-typo-elided
Fix typo
2019-10-01 12:02:36 +02:00
Felix Eckhofer
28da954aad Fix typo
Signed-off-by: Felix Eckhofer <felix@eckhofer.com>
2019-10-01 08:25:24 +02:00
Nextcloud bot
a8fbbc65c1 [tx-robot] updated from transifex 2019-10-01 03:15:23 +00:00
Michael Schuster
47ffcfd561 Merge pull request #1461 from nextcloud/issue/1458
Checks if exclude file is empty before creating the regular expressions.
2019-09-30 21:52:04 +02:00
Camila San
481d8d3a0b Checks if exclude file is empty before creating the regular expressions.
The default file created by the application it is not empty.

Signed-off-by: Camila San <hello@camila.codes>
2019-09-30 20:38:56 +02:00
Felix Eckhofer
ace142bb23 Use user-provided username in displayName()
This replaces `davUser()`, which is replaced by a numeric ID when using
LDAP, by the username that was actually used for logging in.

Fixes #836

Signed-off-by: Felix Eckhofer <felix@eckhofer.com>
2019-09-30 17:56:14 +02:00
Dominique Fuchs
ea14baff6c Merge branch 'lnx-domainname-desktopfiles' of https://github.com/nextcloud/desktop into lnx-domainname-desktopfiles 2019-09-30 11:00:10 +02:00
Dominique Fuchs
0c4c5c5f8b Fixed typo / double suffix
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-30 10:59:59 +02:00
Dominique Fuchs
0a407a39b0 Merge branch 'master' into lnx-domainname-desktopfiles 2019-09-30 09:46:15 +02:00
Dominique Fuchs
3ad1c0e7a8 Created wrapper variable LINUX_APPLICATION_ID to clean up code
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-30 09:45:41 +02:00
Nextcloud bot
a140720901 [tx-robot] updated from transifex 2019-09-30 03:12:41 +00:00
Nextcloud bot
141d31c546 [tx-robot] updated from transifex 2019-09-29 03:15:41 +00:00
Andreas Wunderlich
f293dbfeeb Revert default remote poll interval back from 5 seconds to 30 seconds
Signed-off-by: Andreas Wunderlich <code@andwun.me>
2019-09-29 00:58:35 +02:00
Dominique Fuchs
3f533edba6 Merge branch 'master' into syncjournal-del-prio 2019-09-28 09:29:04 +02:00
Dominique Fuchs
10a5e75cd8 Harmonizing sorting algorithm (again)
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-28 09:17:12 +02:00
Nextcloud bot
58349fae02 [tx-robot] updated from transifex 2019-09-28 03:04:02 +00:00
Dominique Fuchs
3269402f48 Merge branch 'syncjournal-del-prio' of https://github.com/nextcloud/desktop into syncjournal-del-prio 2019-09-27 12:21:06 +02:00
Dominique Fuchs
26f7848821 Fix logic for DELETE prio, now (hopefully) in harmony with destination sorting
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-27 12:21:02 +02:00
Dominique Fuchs
08efb40599 Merge branch 'master' into syncjournal-del-prio 2019-09-27 09:59:32 +02:00
Dominique Fuchs
f81e5be119 Implemented second sorting step for SyncFileVector (merged trees) to prioritize DELETEs
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-27 09:34:49 +02:00
Nextcloud bot
cf4fcebc53 [tx-robot] updated from transifex 2019-09-27 03:04:15 +00:00
Michael Schuster
00db94a73c Revert "Fix White Window issue on Windows after Qt 5.12.4 upgrade"
This reverts commit 8f616969ab.

Turns out that with the upgrade to the new released Qt 5.12.5 the issue
has been solved by the Qt developers, so this fix becomes obsolete.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-09-27 04:58:12 +02:00
Dominique Fuchs
a8ecf486d1 Updated AppImage instructions w/ new desktop file name
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-26 21:01:01 +02:00
Dominique Fuchs
83918619cf Corrected new .desktop file location in forgotten function
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-26 20:56:14 +02:00
Dominique Fuchs
f52c330c22 cleanup and migration for location change
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-26 19:09:40 +02:00
Dominique Fuchs
67ed54671b Adapted for cmd version and added migration step for config file
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-26 17:47:01 +02:00
Dominique Fuchs
fc6b895f52 moved default db sync file to Qt standard path AppDataLocation
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-26 17:09:24 +02:00
Camila Ayres
6f9256f290 Merge branch 'master' into lnx-domainname-desktopfiles 2019-09-26 13:26:22 +02:00
Camila Ayres
f6b03f0186 Merge pull request #1443 from nextcloud/enhancement/change-share-menu-wording
Improve wording of the context menu in the file manager extension.
2019-09-26 13:20:42 +02:00
Dominique Fuchs
555c513acb Merge branch 'master' into lnx-domainname-desktopfiles 2019-09-26 12:51:20 +02:00
Dominique Fuchs
96da4674f9 Updated .desktop file naming scheme
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-26 12:36:05 +02:00
Dominique Fuchs
e5f0ee3b92 Fixed wrongly formatted define statement
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-26 12:35:32 +02:00
Camila Ayres
570041e3b4 Merge branch 'master' into enhancement/change-share-menu-wording 2019-09-26 11:12:43 +02:00
Camila Ayres
c0e7120b12 Merge pull request #1445 from nextcloud/fix-white-window
Fix White Window issue on Windows after Qt 5.12.4 upgrade
2019-09-26 11:04:14 +02:00
Michael Schuster
82a73e443c Merge branch 'master' into fix-white-window 2019-09-26 05:21:42 +02:00
Nextcloud bot
5d3a8e3725 [tx-robot] updated from transifex 2019-09-26 03:03:05 +00:00
Michael Schuster
8f616969ab Fix White Window issue on Windows after Qt 5.12.4 upgrade
Qt 5.12.4 seems to introduce a new bug on Windows, causing the settings window
to not be redrawn when re-opening it, for example by clicking at the tray icon.

As a workaround this fix starts a 100 ms timer to be fired once upon
QDialog::showEvent is called.

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-09-26 04:59:17 +02:00
Michael Schuster
cb60e8aa90 Merge branch 'master' of https://github.com/nextcloud/desktop 2019-09-26 01:41:06 +02:00
Camila San
b9f0e444e8 Improve wording of the context menu in the file manager extension.
'Share...' -> 'Share options'
'private link' -> 'internal link'
Removes 'to clipboard' from 'copy link' options.

Signed-off-by: Camila San <hello@camila.codes>
2019-09-25 19:54:22 +02:00
Dominique Fuchs
cd89efc24b Fixed some missing 'translatable' exclusions, added missing window titles in flow dialogs
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-25 14:02:59 +02:00
Nextcloud bot
8ebacae846 [tx-robot] updated from transifex 2019-09-25 03:04:06 +00:00
Camila Ayres
7a033395f2 Merge pull request #1438 from nextcloud/enhancement/change-share-menu-wording
Changes wording in the share context menu.
2019-09-24 16:52:27 +02:00
Camila San
dd90ed9643 Changes wording in the share context menu.
Instead of only Nextcloud it says "Share via Nextcloud".

Signed-off-by: Camila San <hello@camila.codes>
2019-09-24 16:25:03 +02:00
Camila Ayres
d392843c12 Merge pull request #1434 from nextcloud/ui-msg-delete-all-files
UI improvement: Message box: Delete / Keep all files
2019-09-24 12:24:36 +02:00
Camila Ayres
e944aa6f2d Merge branch 'master' into ui-msg-delete-all-files 2019-09-24 12:06:09 +02:00
Nextcloud bot
08c76f5997 [tx-robot] updated from transifex 2019-09-24 03:07:21 +00:00
Nextcloud bot
4c2895c92f [tx-robot] updated from transifex 2019-09-21 03:02:36 +00:00
Dominique Fuchs
d8dca83dd5 Merge branch 'master' into recipientnote 2019-09-20 19:01:34 +02:00
Dominique Fuchs
0ff91574d2 show only 'shared with you by...' if it's not the current user itself
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-20 18:50:32 +02:00
Michael Schuster
30cff4e4f8 UI improvement: Message box: Delete / Keep all files
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-09-20 16:47:11 +02:00
Nextcloud bot
1138118d8e [tx-robot] updated from transifex 2019-09-20 03:04:15 +00:00
Dominique Fuchs
be2c1fdb89 Merge pull request #1427 from mawasak/master
Fix for #1382 "linux client crashes for no discernable reason"
2019-09-19 19:51:12 +02:00
Dominique Fuchs
030e85c06c Merge branch 'master' into master 2019-09-19 17:05:04 +02:00
Camila Ayres
b493f03d42 Finish adding tags to the the exemptLabels list for the stale bot. 2019-09-19 14:47:40 +02:00
Camila Ayres
4bfd2a5d77 Update exempt labels config for stale bot. 2019-09-19 13:36:44 +02:00
Camila Ayres
4945dd126a Add configuration file for funding.
Bounty source link.
2019-09-19 13:05:14 +02:00
Camila Ayres
8caa997181 Add configuration file for stale bot. 2019-09-19 12:59:21 +02:00
Dominique Fuchs
2b88ea390c Merge branch 'master' into recipientnote 2019-09-19 10:05:06 +02:00
Dominique Fuchs
31f3b322c8 Color corrections and sharer=self case implementation
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-19 10:04:52 +02:00
Nextcloud bot
55ebd5154c [tx-robot] updated from transifex 2019-09-19 03:06:20 +00:00
Mariusz Wasak
dcc33f3417 Fix for #1382 "linux client crashes for no discernable reason"
There in no "return" in
PropagateUploadFileCommon::slotStartUpload in if (prevModtime != _item-
>_modtime) {... }

There is possibility that
PropagateItemJob::done(status, errorString)
maybe called two times from PropagateUploadFileCommon::slotStartUpload
1. in if (prevModtime != _item->_modtime) {... }
2. in if (fileIsStillChanging(*_item)) {..}
if changes in files are frequent the second call is possible.

This two calls has effect in PropagatorCompositeJob::slotSubJobFinished
and job is removed two times in _runningJobs.remove(i);
(the second time with argumetnt -1 (because first call removed job).

This return was removed in commit
efc039863b - by accident I think.

Good simulation is to synchronize firefox profile with frequent page
refresh.

Signed-off-by: Mariusz Wasak <mawasak@gmail.com>
2019-09-18 18:18:12 +02:00
Michael Schuster
eab8c1eb7e Merge branch 'master' into recipientnote 2019-09-18 14:02:47 +02:00
Dominique Fuchs
5a9fc02f07 Correcting autoraise for widget w/ background fill
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-18 13:40:14 +02:00
Dominique Fuchs
9d6780d6c1 Finishing PR #1154 adding note when sharing
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-18 13:37:49 +02:00
Nextcloud bot
811c3c995a [tx-robot] updated from transifex 2019-09-18 03:04:37 +00:00
Michael Schuster
44ed5744f1 Merge branch 'master' of https://github.com/nextcloud/desktop 2019-09-17 17:46:17 +02:00
Nextcloud bot
179bbffd76 [tx-robot] updated from transifex 2019-09-17 02:55:13 +00:00
Michael Schuster
207de071f4 Add warning for failed chown in libsync/propagatedownload.cpp
In addition to PR 1409 generate warnings if chown fails.

See: https://github.com/nextcloud/desktop/pull/1409

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-09-16 20:26:18 +02:00
Michael Schuster
0845f25f70 Merge pull request #1240 from ivan-cukic/ivan/remote-size-retrieved-race-condition
Race condition in the remote size loading logic
2019-09-16 20:08:29 +02:00
Michael Schuster
916d414543 Merge branch 'master' into ivan/remote-size-retrieved-race-condition 2019-09-16 19:17:00 +02:00
Michael Schuster
b93fbddf05 Merge pull request #1409 from DominiqueFuchs/msvc-warn-audit
Review of msvc/gcc warnings -> code cleanup, prevention of implicit casts, variadic macros
2019-09-16 19:08:10 +02:00
Michael Schuster
b40e3e7b4e Merge branch 'master' into msvc-warn-audit 2019-09-16 16:55:42 +02:00
Kilian Pfeiffer
c46ca5c256 Merge branch 'master' into master 2019-09-16 13:41:15 +02:00
Nextcloud bot
44d954ade9 [tx-robot] updated from transifex 2019-09-16 02:55:42 +00:00
Dominique Fuchs
cdc939ae97 Merge pull request #1214 from Thaodan/fix_urlscheme_warning
fix qt warning about registering a URL sheme first.
2019-09-15 19:31:20 +02:00
Dominique Fuchs
a2a753a34b Merge branch 'master' into fix_urlscheme_warning 2019-09-15 19:12:22 +02:00
Camila Ayres
d0e25c230a Merge pull request #1149 from nextcloud/bugfixing-slideshow
slideshow buttons
2019-09-15 18:52:05 +02:00
Camila Ayres
82a67a44c4 Merge branch 'master' into bugfixing-slideshow 2019-09-15 18:18:46 +02:00
Camila Ayres
233a423e8c Merge pull request #1420 from nextcloud/e2e-csr-transmit
Fixing E2E CSR transmission failure for new connections
2019-09-15 17:22:49 +02:00
Dominique Fuchs
5e099adb2f Merge branch 'master' into e2e-csr-transmit 2019-09-15 12:03:16 +02:00
Dominique Fuchs
a35b346e62 Fixed e2e key transmission issue after generation (forgotten content type on sendrequest())
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-15 11:53:57 +02:00
Dominique Fuchs
7d4406254a Merge branch 'master' into fix_urlscheme_warning 2019-09-15 09:56:16 +02:00
Nextcloud bot
70091726c9 [tx-robot] updated from transifex 2019-09-15 02:57:10 +00:00
Nextcloud bot
564088680a [tx-robot] updated from transifex 2019-09-14 02:55:51 +00:00
Dominique Fuchs
1eb61b7949 Fixed unused var
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-13 20:49:59 +02:00
Dominique Fuchs
f6bac6cfdd Merge branch 'bugfixing-slideshow' of https://github.com/nextcloud/desktop into bugfixing-slideshow 2019-09-13 20:38:16 +02:00
Dominique Fuchs
e8c8fe4223 Added slight svg transparency as requested in ref issue, fixed bg detection logic
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-13 20:38:03 +02:00
Dominique Fuchs
3659bca0ec Merge branch 'master' into bugfixing-slideshow 2019-09-13 17:30:25 +02:00
Dominique Fuchs
ace3da841c (Maybe) finished implementation of themed wizard buttons and accessibility refinements and thus implementation of helper fct. to retrieve themed QIcons.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-13 17:26:39 +02:00
Kilian Pfeiffer
457b0c3ab1 Merge branch 'master' into master 2019-09-13 08:57:06 +02:00
Dominique Fuchs
544229d1e8 [WIP] themed button implementation
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-13 08:24:02 +02:00
Dominique Fuchs
af05db895c [WIP] Resource file and include changes as well as new control icons for wizard slide buttons
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-13 08:08:39 +02:00
Nextcloud bot
2958cf2180 [tx-robot] updated from transifex 2019-09-13 02:57:35 +00:00
Michael Schuster
32c114bd17 Merge branch 'master' of https://github.com/nextcloud/desktop 2019-09-13 02:19:22 +02:00
Dominique Fuchs
1d96b102c0 Layout optimizations and tab access for self-hosting link
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-12 22:00:43 +02:00
Michael Schuster
d6fce49162 Merge pull request #1414 from nextcloud/fix-double-slashes
Fix double slashes
2019-09-12 21:25:43 +02:00
Dominique Fuchs
ff5bf8634f fix naming for slide navigation, adapted everywhere to be consistent
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-12 20:59:03 +02:00
Dominique Fuchs
f49cd1850c Restructured layout, as the initial change were too broken (after additions through the last months)
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-12 20:53:40 +02:00
Dominique Fuchs
d420242fcb Merge branch 'bugfixing-slideshow' of https://github.com/nextcloud/desktop into bugfixing-slideshow 2019-09-12 17:56:30 +02:00
Dominique Fuchs
c873da75e4 Fixed wrong resource paths
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-12 17:52:31 +02:00
Dominique Fuchs
9b60573d7e Merge branch 'master' into bugfixing-slideshow 2019-09-12 17:09:26 +02:00
Dominique Fuchs
907f36bfcb Merge branch 'bugfixing-slideshow' of https://github.com/nextcloud/desktop into bugfixing-slideshow 2019-09-12 16:43:54 +02:00
Dominique Fuchs
04fedf83b4 Added newly created next/prev svg's and fixed reduntant layout parts in wizard
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-12 16:43:24 +02:00
Michael Schuster
f3d774e2e5 Merge branch 'master' into fix-double-slashes 2019-09-12 05:09:21 +02:00
Nextcloud bot
8f40161fa2 [tx-robot] updated from transifex 2019-09-12 02:55:19 +00:00
Dominique Fuchs
febc035063 Merge branch 'master' into ivan/remote-size-retrieved-race-condition 2019-09-11 22:56:34 +02:00
Dominique Fuchs
4902751d02 Merge branch 'master' into bugfixing-slideshow 2019-09-11 22:17:57 +02:00
Dominique Fuchs
45bd869a15 Merge branch 'master' into master 2019-09-11 22:06:22 +02:00
Michael Schuster
905c1532fe fix comment typo
Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-09-11 17:31:16 +02:00
Michael Schuster
c3d8657619 Merge branch 'master' of https://github.com/nextcloud/desktop 2019-09-11 17:27:49 +02:00
Nextcloud bot
51ff031de5 [tx-robot] updated from transifex 2019-09-11 03:05:21 +00:00
Dominique Fuchs
6b9395a3c5 Merge pull request #916 from nextcloud/icons
Remove outdated (and unused) icons
2019-09-10 16:15:43 +02:00
Dominique Fuchs
b1db012094 Merge branch 'master' into icons 2019-09-10 14:36:40 +02:00
Dominique Fuchs
556e8d39aa Merge pull request #719 from tuxmaster5000/owncloud
Rename owncloud tests to nextcloud
2019-09-10 14:31:30 +02:00
Dominique Fuchs
cd5ff96904 Merge branch 'master' into owncloud 2019-09-10 13:11:02 +02:00
Dominique Fuchs
24a20ec758 Merge pull request #1039 from javierllorente/master
Add sync date next to "Synchronized with local folder"
2019-09-10 11:38:59 +02:00
Dominique Fuchs
4edab98b58 Merge branch 'master' into owncloud 2019-09-10 11:03:39 +02:00
Dominique Fuchs
dd130ede8f Merge branch 'master' into master 2019-09-10 10:17:37 +02:00
Dominique Fuchs
81bcb46ef2 Merge pull request #1231 from Zottel92/issue1216/IgnoreEmacsRecoveryFiles
issue1216: added sync-exclude entry for emacs recovery files
2019-09-10 09:46:24 +02:00
Dominique Fuchs
37f532c1f0 Merge branch 'master' into issue1216/IgnoreEmacsRecoveryFiles 2019-09-10 09:02:55 +02:00
Nextcloud bot
04f2bd4baa [tx-robot] updated from transifex 2019-09-10 03:06:52 +00:00
Dominique Fuchs
07df659a3f Merge branch 'master' into issue1216/IgnoreEmacsRecoveryFiles 2019-09-09 21:46:39 +02:00
Dominique Fuchs
e89ff9ae61 Merge branch 'master' into msvc-warn-audit 2019-09-09 20:16:52 +02:00
Dominique Fuchs
c662ff1902 fixed wrongly assigned pointer, didn't recognize class
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 20:06:32 +02:00
Dominique Fuchs
a3825080db Use -Wno-gnu-zero-variadic-macro-arguments only for Clang
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 19:35:30 +02:00
Dominique Fuchs
a237493def Q_UNUSED for atm unused parameters
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 19:23:38 +02:00
Dominique Fuchs
3a0cd45782 Declared Q_UNUSED for as-of-now unused parameters.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 19:23:37 +02:00
Dominique Fuchs
f08cc08eb2 Prevented warning regarding operator precedence - enhanced clarity by adding parentheses
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 19:23:36 +02:00
Dominique Fuchs
e3685b951c removed reduntant /* within a comment
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 19:23:35 +02:00
Dominique Fuchs
6b04e2f77b Remove unnecessary argument
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 19:23:34 +02:00
Dominique Fuchs
2e8b7771b0 Prevent use of uninitialized folder pointer.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 19:23:32 +02:00
Dominique Fuchs
26e98d35e6 Added forgotten case when parsing log through gui. LockedFiles were not communicated.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 19:23:31 +02:00
Dominique Fuchs
ab3d0141ec initialize _modtime to prevent undefined usage
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 19:23:30 +02:00
Dominique Fuchs
39df36c247 Use return type to prevent warning and determine chown success. Added TODO
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 18:06:29 +02:00
Dominique Fuchs
7473cdf184 Removed disabling of msvc warning to prevent generating a unknown option for other compilers in turn. Now detect specifically GCC in ifdef
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-09 13:46:46 +02:00
Nextcloud bot
4f7d7e3601 [tx-robot] updated from transifex 2019-09-09 03:06:29 +00:00
Dominique Fuchs
49a6dc311e Merge branch 'master' into msvc-warn-audit 2019-09-08 20:00:48 +02:00
Dominique Fuchs
c585e81530 Moved macro definition due to timing issues while compiling when relying on header inheritance
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 19:46:08 +02:00
Dominique Fuchs
c779098772 Conditional (based on Qt version) use of 'horizontalAdvance' to provide better UI experience. See https://doc.qt.io/qt-5/qfontmetrics-obsolete.html#width
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 19:37:56 +02:00
Dominique Fuchs
cc07ed1ee8 commit 222b2d did the trick. now streamlined use of https://doc.qt.io/qt-5/qtglobal.html#QT_VERSION_CHECK
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 19:22:40 +02:00
Dominique Fuchs
222b2d8645 Further testing of cond. include of Qt library > 5.9. Utilized different macro.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 19:17:00 +02:00
Dominique Fuchs
f41eeaf6ec Fixed another logic error -> logical to bitwise OR for QTLEGACY
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 18:51:54 +02:00
Dominique Fuchs
48097801e8 Fixed logic error in QTLEGACY macro and added forgottin #if clause for header file
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 18:42:40 +02:00
Dominique Fuchs
dca83aad45 Added macro definition and compile-time condition to support Qt < 5.9
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 17:33:34 +02:00
Dominique Fuchs
be7a524557 Indeed, DWORD is a special snowflake - only when on _WIN32
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 16:22:08 +02:00
Dominique Fuchs
0827ff0995 Fixed wrongly formatted args for win32 linker flags resulting in 'unrecognized option' for all of them. Remark: /WL is for VS only, useless (and not necessary for msvc cmd)
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 16:09:58 +02:00
Dominique Fuchs
503b9de2a0 Fixed missing braces
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 15:49:53 +02:00
Dominique Fuchs
a2d47cdec4 Qt: Fixed numerous deprecated calls by adapting newer ones
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 15:40:49 +02:00
Dominique Fuchs
ba74c24d8f Added cmake preprocessor definitions when using msvc regarding the 'safe' versions of CRT functions
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 14:47:35 +02:00
Dominique Fuchs
d60a216982 Use existing fct for RegKeyQuery instead of redundant subroutine
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 13:44:00 +02:00
Dominique Fuchs
d6af025a46 Numoerous safe conversions implemented. Added additional Utility::convertSizeToDWORD for windows builds.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 11:33:20 +02:00
Dominique Fuchs
82fa10c227 Corrected namespace when calling convertSizetoUint
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 10:21:59 +02:00
Nextcloud bot
13b2b5253e [tx-robot] updated from transifex 2019-09-08 03:10:00 +00:00
Dominique Fuchs
46e0a05078 Renamed conversion function to make intention more clear. Also defaulted to 'controlled truncation' to not stupidly crash. TBD/TODO: Better handling for such things.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 02:20:24 +02:00
Dominique Fuchs
8329de4cee Selectively and temporary disabled warning about unknown preprocessor declarative for msvc when using specific GCC instruction.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 02:07:52 +02:00
Dominique Fuchs
b4dee67bf5 Implemented Utility::convert function to convert size_t -> uint safely and on the fly. Often necessary for Qt and WIN32 functions. Using this will not generate compiler warnings of possible truncation. First call implemented in ownsql.cpp
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 02:04:50 +02:00
Dominique Fuchs
5ae3435fe6 Fixed broken overloading mechanism of variadic templates. See code comment for further information.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-08 01:09:22 +02:00
Dominique Fuchs
9a256fcbfe usage of UINT as iterator here because comparing with UINT retval from DragQueryFile
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-07 21:42:10 +02:00
Dominique Fuchs
112d2bfe11 Removed redundant (and wrong in terms of it's value) definitions for WINVER/_WIN32_WINNT
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-07 21:28:12 +02:00
Dominique Fuchs
69a11a7ec1 Removed redundant (and wrong in terms of it's value) definitions for WINVER/_WIN32_WINNT
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-07 21:26:40 +02:00
Dominique Fuchs
3960ffea3f Removed redundant (and wrong in terms of it's value) definitions for WINVER/_WIN32_WINNT
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-07 20:58:20 +02:00
Dominique Fuchs
78543deee4 Updated WINVER/_WIN32_WINNT from 0x0600 to 0x0601 (e.g. Server 2008/Vista to 7) as 7 is reasonable and noted everywhere as requirement
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
2019-09-07 20:55:49 +02:00
Dominique Fuchs
4dd49327e4 Merge remote-tracking branch 'upstream/master' 2019-09-07 19:41:35 +02:00
Nextcloud bot
2121e7116e [tx-robot] updated from transifex 2019-09-07 03:06:08 +00:00
Michael Schuster
67107a4f5d Fix double slashes in WebDAV URLs (account setup wizard)
Sanitize URL paths to elaminate double-slashes in the URL path string,
used for the first connection by the account setup wizard.

Example: https://cloud.example.com/remote.php/webdav//

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-09-07 04:18:07 +02:00
Michael Schuster
0557d53f5f Merge branch 'master' of https://github.com/nextcloud/desktop 2019-09-07 03:30:47 +02:00
Michael Schuster
819a006a17 Replace old NSI Windows setup wizard graphics
New UI resources based on current https://github.com/nextcloud/promo

New:
- Icon based on https://github.com/nextcloud/desktop/pull/1401
- Wizard image & header image (dotted background replaces old cloud background)

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-09-07 02:00:49 +02:00
Dominique Fuchs
65ee5915af Merge remote-tracking branch 'upstream/master' 2019-09-06 21:00:37 +02:00
Dominique Fuchs
8ad3b18932 Merge branch 'master' of https://github.com/DominiqueFuchs/desktop 2019-09-06 20:43:51 +02:00
Camila San
c835c39491 Bump master version to 2.7.
Signed-off-by: Camila San <hello@camila.codes>
2019-09-06 18:20:52 +02:00
Michael Schuster
4cb45d5d6a Merge branch 'master' of https://github.com/nextcloud/desktop 2019-09-06 17:57:52 +02:00
Michael Schuster
b28ae98d58 Merge branch 'master' of https://github.com/nextcloud/desktop 2019-09-06 16:45:17 +02:00
Dominique Fuchs
c389985c2e Merge remote-tracking branch 'upstream/master' 2019-09-03 10:53:43 +02:00
Kilian Pfeiffer
ac24874585 Merge branch 'master' into master 2019-06-12 12:41:09 +02:00
Sebastian Grund
a9bea53c89 issue1216: added sync-exclude entry for emacs recovery files
Signed-off-by: Sebastian Grund <grund92@gmx.de>
2019-05-22 08:52:37 +02:00
Ivan Čukić
0f7c10a2d6 Race condition in the remote size loading logic
The quota retrieval process might not be finished by the time
the used space on the server (`_rSize`) is compared against
the locally available disk space which might end up in
a "There isn't enough free space in the local folder!" message
even if there is enough free space.

This patch updates the status after the quota has been retrieved.

It also initializes `_rSize` to `-1` so that errors like this
are easier to catch in the future.
2019-05-08 23:09:55 +02:00
Corentin Noël
18f51e47d7 Merge branch 'master' into master 2019-05-03 17:04:42 +02:00
Corentin Noël
aba4b722af Merge branch 'master' into fix_urlscheme_warning 2019-05-03 17:03:23 +02:00
Corentin Noël
654049d4fd Merge branch 'master' into icons 2019-05-03 17:02:59 +02:00
Björn Bidar
cea0d519a4 fix qt warning about registering a URL sheme first.
Qt recommends to register a URL scheme before installing it.
I don't know the impact of the not registering before instaling but I
think the change is pretty harmles.

See:
https://doc.qt.io/qt-5/qwebengineurlscheme.html#registerScheme
Signed-off-by: Björn Bidar <theodorstormgrade@gmail.com>
2019-04-22 07:38:38 +02:00
Izabela Bakollari
ff7b0aace9 Modified slideshow buttons and edited "Host your own server" link 2019-03-18 16:31:35 +01:00
Izabela Bakollari
9b476a5caa Add files via upload 2019-03-18 15:58:12 +01:00
Kilian Pfeiffer
2c58bee151 Merge branch 'master' into master 2019-03-09 17:57:11 +01:00
Kilian Pfeiffer
c4ffd844f3 Merge branch 'master' into master 2019-02-12 12:46:19 +01:00
Javier Llorente
cbc19e86fb Add sync date next to "Synchronized with local folder" 2019-01-22 23:16:57 +01:00
kilian.pfeiffer
10073c1f10 changed max GUI bandwith limits 2019-01-18 15:11:52 +01:00
Jan-Christoph Borchardt
8a35bfdc13 Remove outdated icons
Signed-off-by: Jan-Christoph Borchardt <hey@jancborchardt.net>
2019-01-15 19:59:34 +01:00
tuxmaster5000
ddf1ac04e5 Merge branch 'master' into owncloud 2018-10-16 09:35:33 +02:00
Camila Ayres
aa388b86c0 Merge branch 'master' into owncloud 2018-10-14 16:13:01 +02:00
tuxmaster5000
f9c6449c05 Fix include file 2018-10-12 15:56:26 +02:00
tuxmaster5000
3c00c09ea8 Rename owncloud tests to nextcloud 2018-10-12 14:52:18 +02:00
289 changed files with 47363 additions and 43422 deletions

View File

@@ -22,11 +22,11 @@ steps:
source /opt/qt57/bin/qt57-env.sh &&
mkdir build &&
cd build &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 ../ &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 -DSANITIZE_ADDRESS=ON ../ &&
make &&
useradd -m -s /bin/bash test &&
chown -R test:test . &&
su -c 'ctest --output-on-failure' test"
su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test"
trigger:
branch:
- master
@@ -59,11 +59,11 @@ steps:
source /opt/qt58/bin/qt58-env.sh &&
mkdir build &&
cd build &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 ../ &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 -DSANITIZE_ADDRESS=ON ../ &&
make &&
useradd -m -s /bin/bash test &&
chown -R test:test . &&
su -c 'ctest --output-on-failure' test"
su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test"
trigger:
branch:
- master
@@ -96,11 +96,11 @@ steps:
source /opt/qt59/bin/qt59-env.sh &&
mkdir build &&
cd build &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 ../ &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 -DSANITIZE_ADDRESS=ON ../ &&
make &&
useradd -m -s /bin/bash test &&
chown -R test:test . &&
su -c 'ctest --output-on-failure' test"
su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test"
trigger:
branch:
- master
@@ -137,11 +137,11 @@ steps:
source /opt/qt510/bin/qt510-env.sh &&
mkdir build &&
cd build &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 ../ &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 -DSANITIZE_ADDRESS=ON ../ &&
make &&
useradd -m -s /bin/bash test &&
chown -R test:test . &&
su -c 'ctest --output-on-failure' test"
su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test"
trigger:
branch:
- master
@@ -178,11 +178,11 @@ steps:
source /opt/qt511/bin/qt511-env.sh &&
mkdir build &&
cd build &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 ../ &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 -DSANITIZE_ADDRESS=ON ../ &&
make &&
useradd -m -s /bin/bash test &&
chown -R test:test . &&
su -c 'ctest --output-on-failure' test"
su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test"
trigger:
branch:
- master
@@ -219,11 +219,11 @@ steps:
source /opt/qt511/bin/qt511-env.sh &&
mkdir build &&
cd build &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 ../ &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 -DSANITIZE_ADDRESS=ON ../ &&
make &&
useradd -m -s /bin/bash test &&
chown -R test:test . &&
su -c 'ctest --output-on-failure' test"
su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test"
trigger:
branch:
- master
@@ -237,13 +237,17 @@ name: qt-5.12
steps:
- name: build and test
image: nextcloudci/client-5.12:client-5.12-2
image: nextcloudci/client-5.12:client-5.12-5
commands:
# Install QtKeyChain
- /bin/bash -c "
export CC=gcc-7 &&
export CXX=g++-7 &&
source /opt/qt512/bin/qt512-env.sh &&
export QT_BASE_DIR=/opt/qt5.12.5 &&
export QTDIR=\$QT_BASE_DIR &&
export PATH=\$QT_BASE_DIR/bin:\$PATH &&
export LD_LIBRARY_PATH=\$QT_BASE_DIR/lib/x86_64-linux-gnu:\$QT_BASE_DIR/lib:/usr/local/lib:\$LD_LIBRARY_PATH &&
export PKG_CONFIG_PATH=\$QT_BASE_DIR/lib/pkgconfig:\$PKG_CONFIG_PATH &&
cd /tmp &&
git clone https://github.com/frankosterfeld/qtkeychain.git &&
cd qtkeychain &&
@@ -257,14 +261,18 @@ steps:
- /bin/bash -c "
export CC=gcc-7 &&
export CXX=g++-7 &&
source /opt/qt512/bin/qt512-env.sh &&
export QT_BASE_DIR=/opt/qt5.12.5 &&
export QTDIR=\$QT_BASE_DIR &&
export PATH=\$QT_BASE_DIR/bin:\$PATH &&
export LD_LIBRARY_PATH=\$QT_BASE_DIR/lib/x86_64-linux-gnu:\$QT_BASE_DIR/lib:/usr/local/lib:\$LD_LIBRARY_PATH &&
export PKG_CONFIG_PATH=\$QT_BASE_DIR/lib/pkgconfig:\$PKG_CONFIG_PATH &&
mkdir build &&
cd build &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 ../ &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 -DSANITIZE_ADDRESS=ON ../ &&
make &&
useradd -m -s /bin/bash test &&
chown -R test:test . &&
su -c 'ctest --output-on-failure' test"
su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test"
trigger:
branch:
- master
@@ -278,13 +286,17 @@ name: qt-5.12-clang
steps:
- name: build and test
image: nextcloudci/client-5.12:client-5.12-2
image: nextcloudci/client-5.12:client-5.12-5
commands:
# Install QtKeyChain
- /bin/bash -c "
export CC=clang-6.0 &&
export CXX=clang++-6.0 &&
source /opt/qt512/bin/qt512-env.sh &&
export QT_BASE_DIR=/opt/qt5.12.5 &&
export QTDIR=\$QT_BASE_DIR &&
export PATH=\$QT_BASE_DIR/bin:\$PATH &&
export LD_LIBRARY_PATH=\$QT_BASE_DIR/lib/x86_64-linux-gnu:\$QT_BASE_DIR/lib:/usr/local/lib:\$LD_LIBRARY_PATH &&
export PKG_CONFIG_PATH=\$QT_BASE_DIR/lib/pkgconfig:\$PKG_CONFIG_PATH &&
cd /tmp &&
git clone https://github.com/frankosterfeld/qtkeychain.git &&
cd qtkeychain &&
@@ -298,14 +310,18 @@ steps:
- /bin/bash -c "
export CC=clang-6.0 &&
export CXX=clang++-6.0 &&
source /opt/qt512/bin/qt512-env.sh &&
export QT_BASE_DIR=/opt/qt5.12.5 &&
export QTDIR=\$QT_BASE_DIR &&
export PATH=\$QT_BASE_DIR/bin:\$PATH &&
export LD_LIBRARY_PATH=\$QT_BASE_DIR/lib/x86_64-linux-gnu:\$QT_BASE_DIR/lib:/usr/local/lib:\$LD_LIBRARY_PATH &&
export PKG_CONFIG_PATH=\$QT_BASE_DIR/lib/pkgconfig:\$PKG_CONFIG_PATH &&
mkdir build &&
cd build &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 ../ &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 -DSANITIZE_ADDRESS=ON ../ &&
make &&
useradd -m -s /bin/bash test &&
chown -R test:test . &&
su -c 'ctest --output-on-failure' test"
su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test"
trigger:
branch:
- master
@@ -319,9 +335,10 @@ name: AppImage
steps:
- name: build
image: nextcloudci/client-5.12:client-5.12-2
image: nextcloudci/client-5.12:client-5.12-5
commands:
- /bin/bash -c "./admin/linux/build-appimage.sh"
- /bin/bash -c "./admin/linux/upload-appimage.sh"
trigger:
branch:
- master

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# You can add one username per supported platform and one custom link
custom: https://www.bountysource.com/teams/nextcloud/issues?tracker_ids=74294474

67
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,67 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 28
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 14
# Issues with these labels will never be considered stale
exemptLabels:
- 1. to develop
- 2. to review
- 3. to release
- 4. to test
- accessibility
- backport-request
- bug
- design
- enhancement
- epic
- discussion
- documentation
- overview
- good first issue
- feature-request
- feature: :arrows_counterclockwise: sync engine
- feature: :busts_in_silhouette: sharing
- feature: :cloud: system tray
- feature: :gear: settings
- feature: :inbox_tray: install and update
- feature: :key: authentication
- feature: :lock: end to end encryption
- feature: :memo: versions
- feature: :minidisc: external storage
- feature: :minidisc: virtual drive
- feature: :new: versions
- feature: :tongue: language l10n and translations
- feature: :wheelchair: accessibility
- feature: :white_square_button: nextcloudcmd
- feature: :zap: activity and :bell: notification
- good first issue
- help wanted
- high
- integration
- low
- medium
- needs info
- os: :apple: macOS
- os: :door: Windows
- os: :penguin: Linux
- os: :smiling_imp: FreeBSD
- overview
- package: appimage
- package: debian
- package: snap
- papercut
- regression
- security
- server
- spec
- technical debt
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This request did not receive an update in the last 4 weeks.
Please take a look again and update the issue with new details,
otherwise the issue will be automatically closed in 2 weeks. Thank you!
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

3
.gitmodules vendored
View File

@@ -1,6 +1,3 @@
[submodule "src/3rdparty/qtmacgoodies"]
path = src/3rdparty/qtmacgoodies
url = https://github.com/camilasan/qtmacgoodies.git
[submodule "binary"]
path = binary
url = git://github.com/owncloud/owncloud-client-binary.git

View File

@@ -198,7 +198,7 @@ X-GNOME-Autostart-Delay=3
# Translations
Icon[cs_CZ]=@NAZEV_IKONY_APLIKACE@
Icon[cs_CZ]=@APPLICATION_ICON_NAME@
Name[cs_CZ]=@APPLICATION_NAME@ synchronizační klient pro desktop
Comment[cs_CZ]=@APPLICATION_NAME@ synchronizační klient pro desktop
GenericName[cs_CZ]=Synchronizace složek

View File

@@ -0,0 +1,204 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Exec=@APPLICATION_EXECUTABLE@
Name=@APPLICATION_NAME@ desktop sync client
Comment=@APPLICATION_NAME@ desktop synchronization client
GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
Icon[cy_GB]=@APPLICATION_ICON_NAME@
Name[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
Comment[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
GenericName[cy_GB]=Cydweddu Ffolder

View File

@@ -198,7 +198,7 @@ X-GNOME-Autostart-Delay=3
# Translations
Icon[de]=@APPLICATION_ICON_NAME@
Name[de]=@APPLICATION_NAME@ Client zur Desktop-Synchronisation
Comment[de]=@APPLICATION_NAME@ Client zur Desktop-Synchronisation
GenericName[de]=Synchronisationsordner
Icon[de_DE]=@APPLICATION_ICON_NAME@
Name[de_DE]=@APPLICATION_NAME@ Client zur Desktop-Synchronisation
Comment[de_DE]=@APPLICATION_NAME@ Client zur Desktop-Synchronisation
GenericName[de_DE]=Synchronisationsordner

View File

@@ -198,4 +198,7 @@ X-GNOME-Autostart-Delay=3
# Translations
Icon[el]=@APPLICATION_ICON_NAME@
Name[el]=@APPLICATION_NAME@ πρόγραμμα συγχρονισμού
Comment[el]=@APPLICATION_NAME@ πρόγραμμα συγχρονισμού
GenericName[el]=Συγχρονισμός φακέλου

View File

@@ -0,0 +1,204 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Exec=@APPLICATION_EXECUTABLE@
Name=@APPLICATION_NAME@ desktop sync client
Comment=@APPLICATION_NAME@ desktop synchronization client
GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
Icon[es_AR]=@APPLICATION_ICON_NAME@
Name[es_AR]=@APPLICATION_NAME@ cliente de sincronización de escritorio
Comment[es_AR]=@APPLICATION_NAME@ cliente de sincronización de escritorio
GenericName[es_AR]=Sincronización de carpetas

View File

@@ -201,4 +201,4 @@ X-GNOME-Autostart-Delay=3
Icon[ro]=@APPLICATION_ICON_NAME@
Name[ro]=@APPLICATION_NAME@ client de sincronizare pentru desktop
Comment[ro]=@APPLICATION_NAME@ client de sincronizare pentru desktop
GenericName[ro]=Sincronizare dosare
GenericName[ro]=Sincronizare director

View File

@@ -201,4 +201,4 @@ X-GNOME-Autostart-Delay=3
Icon[sk_SK]=@APPLICATION_ICON_NAME@
Name[sk_SK]=@APPLICATION_NAME@ synchronizačný klient pre PC
Comment[sk_SK]=@APPLICATION_NAME@ synchronizačný klient pre PC
GenericName[sk_SK]=Synchnonizácia priečinkov
GenericName[sk_SK]=Synchronizácia priečinkov

View File

@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
# Translations
Icon[sl]=@APPLICATION_ICON_NAME@
Name[sl]=@APPLICATION_NAME@ odjemalec za usklajevanje
Comment[sl]=@APPLICATION_NAME@ odjemalec za usklajevanje
Name[sl]=@APPLICATION_NAME@ program za usklajevanje
Comment[sl]=@APPLICATION_NAME@ program za usklajevanje
GenericName[sl]=Usklajevanje map

View File

@@ -199,4 +199,6 @@ X-GNOME-Autostart-Delay=3
# Translations
Icon[sv]=@APPLICATION_ICON_NAME@
Name[sv]=@APPLICATION_NAME@ desktopssynkklient
Comment[sv]=@APPLICATION_NAME@ desktopssynkroniseringsklient
GenericName[sv]=Mappsynkronisering

View File

@@ -0,0 +1,204 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Exec=@APPLICATION_EXECUTABLE@
Name=@APPLICATION_NAME@ desktop sync client
Comment=@APPLICATION_NAME@ desktop synchronization client
GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
Icon[sw]=@APPLICATION_ICON_NAME@
Name[sw]=Teja ya @APPLICATION_NAME@ ya kufanana faili kwa seva na faili ziko hapa
Comment[sw]=Teja ya @APPLICATION_NAME@ ya kufanana faili kwa seva na faili ziko hapa
GenericName[sw]=Fanana Kabrasha

View File

@@ -203,14 +203,28 @@ if( WIN32 )
add_definitions( -D__USE_MINGW_ANSI_STDIO=1 )
add_definitions( -DNOMINMAX )
# Get APIs from from Vista onwards.
add_definitions( -D_WIN32_WINNT=0x0600)
add_definitions( -DWINVER=0x0600)
add_definitions( -D_WIN32_WINNT=0x0601 )
add_definitions( -DWINVER=0x0601 )
if( MSVC )
# Use automatic overload for suitable CRT safe-functions
# See https://docs.microsoft.com/de-de/cpp/c-runtime-library/security-features-in-the-crt?view=vs-2019
add_definitions( -D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1 )
# Also: Disable compiler warnings because we don't use Windows CRT safe-functions explicitly and don't intend to
# as this is a pure cross-platform source the only alternative would be a ton of ifdefs with calls to the _s version
add_definitions( -D_CRT_SECURE_NO_WARNINGS )
endif( MSVC )
endif( WIN32 )
if (APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif()
option(SANITIZE_ADDRESS "Enable address sanitizer in tests" OFF)
if (SANITIZE_ADDRESS)
include(SanitizerFlags)
enable_sanitizer()
endif ()
# Handle Translations, pick all client_* files from trans directory.
file( GLOB TRANS_FILES ${CMAKE_SOURCE_DIR}/translations/client_*.ts)
set(TRANSLATIONS ${TRANS_FILES})

View File

@@ -1,3 +1,6 @@
Will be tracked going forward here:
https://github.com/nextcloud/desktop/releases
2.5 Series ChangeLog
====================

View File

@@ -7,11 +7,12 @@ set( APPLICATION_UPDATE_URL "https://updates.nextcloud.org/client/" CACHE STRING
set( APPLICATION_HELP_URL "" CACHE STRING "URL for the help menu" )
set( APPLICATION_ICON_NAME "Nextcloud" )
set( APPLICATION_SERVER_URL "" CACHE STRING "URL for the server to use. If entered the server can only connect to this instance" )
set( APPLICATION_REV_DOMAIN "com.nextcloud.desktopclient" )
set( LINUX_PACKAGE_SHORTNAME "nextcloud" )
set( LINUX_APPLICATION_ID "${APPLICATION_REV_DOMAIN}.${LINUX_PACKAGE_SHORTNAME}")
set( THEME_CLASS "NextcloudTheme" )
set( APPLICATION_REV_DOMAIN "com.nextcloud.desktopclient" )
set( WIN_SETUP_BITMAP_PATH "${CMAKE_SOURCE_DIR}/admin/win/nsi" )
set( MAC_INSTALLER_BACKGROUND_FILE "${CMAKE_SOURCE_DIR}/admin/osx/installer-background.png" CACHE STRING "The MacOSX installer background image")

View File

@@ -1,7 +1,7 @@
set( MIRALL_VERSION_MAJOR 2 )
set( MIRALL_VERSION_MINOR 5 )
set( MIRALL_VERSION_PATCH 3 )
set( MIRALL_VERSION_YEAR 2019 )
set( MIRALL_VERSION_MINOR 7 )
set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_VERSION_YEAR 2020 )
set( MIRALL_SOVERSION 0 )
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )

View File

@@ -14,6 +14,7 @@ RUN apt-get update -q && DEBIAN_FRONTEND=noninteractive apt-get install -q -y --
libsqlite3-dev \
libssl-dev \
libcmocka-dev \
libcloudproviders-dev \
qt5-default \
qttools5-dev-tools \
libqt5webkit5-dev \

View File

@@ -6,23 +6,26 @@ mkdir /app
mkdir /build
#Set Qt-5.12
export QT_BASE_DIR=/opt/qt512
export QT_BASE_DIR=/opt/qt5.12.5
export QTDIR=$QT_BASE_DIR
export PATH=$QT_BASE_DIR/bin:$PATH
export LD_LIBRARY_PATH=$QT_BASE_DIR/lib/x86_64-linux-gnu:$QT_BASE_DIR/lib:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=$QT_BASE_DIR/lib/pkgconfig:$PKG_CONFIG_PATH
#Set APPID for .desktop file processing
export LINUX_APPLICATION_ID=com.nextcloud.desktopclient.nextcloud
#set defaults
export SUFFIX=${DRONE_PULL_REQUEST:=master}
if [ $SUFFIX != "master" ]; then
SUFFIX="PR-$SUFFIX"
fi
#QtKeyChain 0.9.1
#QtKeyChain master
cd /build
git clone https://github.com/frankosterfeld/qtkeychain.git
cd qtkeychain
git checkout v0.9.1
git checkout master
mkdir build
cd build
cmake -D CMAKE_INSTALL_PREFIX=/usr ../
@@ -62,11 +65,12 @@ rm -rf ./usr/share/caja-python/
rm -rf ./usr/share/nautilus-python/
rm -rf ./usr/share/nemo-python/
# Move sync exlucde to right location
# Move sync exclude to right location
mv ./etc/Nextcloud/sync-exclude.lst ./usr/bin/
rm -rf ./etc
sed -i -e 's|Icon=nextcloud|Icon=Nextcloud|g' usr/share/applications/nextcloud.desktop # Bug in desktop file?
DESKTOP_FILE=/app/usr/share/applications/${LINUX_APPLICATION_ID}.desktop
sed -i -e 's|Icon=nextcloud|Icon=Nextcloud|g' ${DESKTOP_FILE} # Bug in desktop file?
cp ./usr/share/icons/hicolor/512x512/apps/Nextcloud.png . # Workaround for linuxeployqt bug, FIXME
@@ -87,17 +91,12 @@ chmod a+x linuxdeployqt*.AppImage
rm ./linuxdeployqt-continuous-x86_64.AppImage
unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/app/usr/lib/
./squashfs-root/AppRun /app/usr/share/applications/nextcloud.desktop -bundle-non-qt-libs
./squashfs-root/AppRun ${DESKTOP_FILE} -bundle-non-qt-libs -qmldir=$DRONE_WORKSPACE/src/gui
# Set origin
./squashfs-root/usr/bin/patchelf --set-rpath '$ORIGIN/' /app/usr/lib/libnextcloudsync.so.0
# Build AppImage
./squashfs-root/AppRun /app/usr/share/applications/nextcloud.desktop -appimage
./squashfs-root/AppRun ${DESKTOP_FILE} -appimage
mv Nextcloud*.AppImage Nextcloud-${SUFFIX}-${DRONE_COMMIT}-x86_64.AppImage
curl --upload-file $(readlink -f ./Nextcloud*.AppImage) https://transfer.sh/Nextcloud-${SUFFIX}-${DRONE_COMMIT}-x86_64.AppImage
echo
echo "Get the AppImage at the link above!"

View File

@@ -7,9 +7,10 @@ Build-Depends: cmake,
cdbs,
dh-python,
extra-cmake-modules (>= 5.16),
kdelibs5-dev,
libkf5kio-dev,
libcmocka-dev,
libcloudproviders-dev,
libdbus-1-dev,
libhttp-dav-perl,
libinotify-dev [kfreebsd-any],
libqt5svg5-dev,

View File

@@ -0,0 +1,48 @@
nextcloud-client (2.3.3-1.0~oldstable1) oldstable; urgency=medium
* Debian build support for the forked client.
-- István Váradi <ivaradi@varadiistvan.hu> Mon, 6 Nov 2017 20:20:04 +0100
nextcloud-client (2.3.1-1.0) oldstable; urgency=medium
* New upstream version
-- István Váradi <ivaradi@varadiistvan.hu> Thu, 23 Mar 2017 19:07:36 +0100
nextcloud-client (2.3.0-1.0) oldstable; urgency=medium
* New upstream version
-- István Váradi <ivaradi@varadiistvan.hu> Tue, 21 Mar 2017 19:34:13 +0100
nextcloud-client (2.2.4-1.4) oldstable; urgency=medium
* The locale-specific icon names are correct too
-- István Váradi <ivaradi@varadiistvan.hu> Tue, 7 Feb 2017 19:55:40 +0100
nextcloud-client (2.2.4-1.3) oldstable; urgency=medium
* Caja syncstate plugin is built.
* The syncstate plugin has application-specific name
-- István Váradi <ivaradi@varadiistvan.hu> Fri, 27 Jan 2017 19:34:18 +0100
nextcloud-client (2.2.4-1.2) oldstable; urgency=medium
* Fixed appname in the Nemo syncstate extension.
-- István Váradi <ivaradi@varadiistvan.hu> Thu, 19 Jan 2017 16:46:50 +0100
nextcloud-client (2.2.4-1.1) oldstable; urgency=medium
* Added Nautilus and Nemo syncstate extensions.
-- István Váradi <ivaradi@varadiistvan.hu> Tue, 17 Jan 2017 19:55:32 +0100
nextcloud-client (2.2.4-1.0) oldstable; urgency=medium
* Initial release.
-- István Váradi <ivaradi@varadiistvan.hu> Wed, 14 Dec 2016 20:07:46 +0100

View File

@@ -0,0 +1,84 @@
Source: nextcloud-client
Section: contrib/devel
Priority: optional
Maintainer: István Váradi <ivaradi@varadiistvan.hu>
Build-Depends: cmake,
debhelper,
cdbs,
dh-python,
extra-cmake-modules (>= 5.16),
kdelibs5-dev,
kio-dev,
libcmocka-dev,
libdbus-1-dev,
libhttp-dav-perl,
libinotify-dev [kfreebsd-any],
libqt5webkit5-dev,
libqt5svg5-dev,
libsqlite3-dev,
libssl-dev (>= 1.1.0),
zlib1g-dev,
optipng,
pkg-kde-tools,
python-sphinx | python3-sphinx,
python3-all,
qt5keychain-dev,
qtwebengine5-dev,
qtdeclarative5-dev,
qttools5-dev,
qttools5-dev-tools,
xvfb
Standards-Version: 3.9.8
Homepage: https://github.com/nextcloud/client_theming
#Vcs-Git: git://anonscm.debian.org/collab-maint/nextcloud-client.git
#Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/nextcloud-client.git
Package: nextcloud-client
Architecture: any
Depends: libnextcloudsync0 (=${binary:Version}), ${shlibs:Depends}, ${misc:Depends}, nextcloud-client-l10n
Recommends: libgnome-keyring0
Description: Nextcloud desktop sync client
Use the desktop client to keep your files synchronized
between your Nextcloud server and your desktop. Select
one or more directories on your local machine and always
have access to your latest files wherever you are.
Package: libnextcloudsync0
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Nextcloud sync library
Used by the Nextcloud desktop client as the synchronization engine.
Package: libnextcloudsync-dev
Architecture: any
Section: contrib/libdevel
Depends: libnextcloudsync0 (=${binary:Version}), ${misc:Depends}
Description: Nextcloud sync library development files
The headers and development library for the Nextcloud sync library.
Package: nextcloud-client-l10n
Architecture: all
Depends: ${misc:Depends}
Description: Nextcloud client internatialization files
The translation files.
Package: nextcloud-client-nautilus
Architecture: all
Depends: nextcloud-client (>=${binary:Version}), libnextcloudsync0, python-nautilus, nautilus, ${misc:Depends}
Description: Nautilus plugin for Nextcloud
This package contains a Nautilus plugin to display
synchronization status icons for Nextcloud files.
Package: nextcloud-client-nemo
Architecture: all
Depends: nextcloud-client (>=${binary:Version}), libnextcloudsync0, python-nemo, nemo, ${misc:Depends}
Description: Nemo plugin for Nextcloud
This package contains a Nemo plugin to display
synchronization status icons for Nextcloud files.
Package: nextcloud-client-caja
Architecture: all
Depends: nextcloud-client (>=${binary:Version}), libnextcloudsync0, python-caja, caja, ${misc:Depends}
Description: Caja plugin for Nextcloud
This package contains a Caja plugin to display
synchronization status icons for Nextcloud files.

View File

@@ -9,7 +9,10 @@ Build-Depends: cmake,
extra-cmake-modules (>= 5.16),
kdelibs5-dev,
kio-dev,
libavcodec58,
libcmocka-dev,
libcloudproviders-dev,
libdbus-1-dev,
libhttp-dav-perl,
libinotify-dev [kfreebsd-any],
libqt5webkit5-dev,

View File

@@ -10,6 +10,8 @@ Build-Depends: cmake,
kdelibs5-dev,
libkf5kio-dev,
libcmocka-dev,
libcloudproviders-dev,
libdbus-1-dev,
libhttp-dav-perl,
libinotify-dev [kfreebsd-any],
libqt5svg5-dev,

View File

@@ -51,7 +51,7 @@ if ! wget http://ppa.launchpad.net/${repo}/ubuntu/pool/main/n/nextcloud-client/n
origsourceopt="-sa"
fi
for distribution in xenial bionic disco eoan stable; do
for distribution in xenial bionic disco eoan stable oldstable; do
rm -rf nextcloud-client_${basever}
cp -a ${DRONE_WORKSPACE} nextcloud-client_${basever}
@@ -98,26 +98,46 @@ if test "${pull_request}" = "master"; then
PPA=$PPA_BETA
OBS_PROJECT=$OBS_PROJECT_BETA
fi
OBS_SUBDIR="${OBS_PROJECT}/${OBS_PACKAGE}"
if test -f ~/.has_ppa_keys; then
for changes in nextcloud-client_*~+([a-z])1_source.changes; do
dput $PPA $changes > /dev/null
case "${changes}" in
*oldstable1*)
;;
*)
dput $PPA $changes > /dev/null
;;
esac
done
mkdir osc
cd osc
osc co ${OBS_PROJECT} ${OBS_PACKAGE}
if test "$(ls ${OBS_SUBDIR})"; then
osc delete ${OBS_SUBDIR}/*
fi
cp ../nextcloud-client*.orig.tar.* ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9].dsc ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9].debian.tar* ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9]_source.changes ${OBS_SUBDIR}/
osc add ${OBS_SUBDIR}/*
for distribution in stable oldstable; do
if test "${distribution}" = "oldstable"; then
pkgsuffix=".${distribution}"
pkgvertag="~${distribution}1"
else
pkgsuffix=""
pkgvertag=""
fi
cd ${OBS_SUBDIR}
osc commit -m "Travis update"
package="${OBS_PACKAGE}${pkgsuffix}"
OBS_SUBDIR="${OBS_PROJECT}/${package}"
mkdir -p osc
pushd osc
osc co ${OBS_PROJECT} ${package}
if test "$(ls ${OBS_SUBDIR})"; then
osc delete ${OBS_SUBDIR}/*
fi
cp ../nextcloud-client*.orig.tar.* ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9]${pkgvertag}.dsc ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9]${pkgvertag}.debian.tar* ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9]${pkgvertag}_source.changes ${OBS_SUBDIR}/
osc add ${OBS_SUBDIR}/*
cd ${OBS_SUBDIR}
osc commit -m "Travis update"
popd
done
fi
fi

21
admin/linux/upload-appimage.sh Executable file
View File

@@ -0,0 +1,21 @@
#! /bin/bash
set -xe
cd /build
# Upload AppImage
APPIMAGE=$(readlink -f ./Nextcloud*.AppImage)
BASENAME=$(basename ${APPIMAGE})
if curl --max-time 900 --upload-file ${APPIMAGE} https://transfer.sh/${BASENAME}
then
echo
echo "Get the AppImage at the link above!"
else
echo
echo "Upload failed, however this is an optional step."
fi
# Don't let the Drone build fail
exit 0

View File

@@ -49,7 +49,7 @@ fi
if [ ! -z "$identity" ]; then
echo "Will try to sign the installer"
pushd $install_path
productsign --sign "$identity" "$installer_file" "$installer_file.new"
productsign --timestamp --sign "$identity" "$installer_file" "$installer_file.new"
mv "$installer_file".new "$installer_file"
popd
else

View File

@@ -32,11 +32,12 @@ FRAMEWORK_SEARCH_PATH=[
os.path.join(os.environ['HOME'], 'Library/Frameworks')
]
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/Qt-5.6.2/lib', '.']
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/Qt-5.12.5/lib', '.']
QT_PLUGINS = [
'sqldrivers/libqsqlite.dylib',
'platforms/libqcocoa.dylib',
'styles/libqmacstyle.dylib',
'imageformats/libqgif.dylib',
'imageformats/libqico.dylib',
'imageformats/libqjpeg.dylib',
@@ -46,7 +47,7 @@ QT_PLUGINS = [
QT_PLUGINS_SEARCH_PATH=[
# os.path.join(os.environ['QTDIR'], 'plugins'),
# '/usr/local/Cellar/qt/5.2.1/plugins',
'/usr/local/Qt-5.6.2/plugins',
'/usr/local/Qt-5.12.5/plugins',
]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

2
binary

Submodule binary updated: 3425fab2c6...09f12de312

View File

@@ -1,16 +1,8 @@
<RCC>
<qresource prefix="/client">
<file>resources/dialog-close.png</file>
<file>resources/dialog-ok.png</file>
<file>resources/dialog-cancel.png</file>
<file>resources/folder-sync.png</file>
<file>resources/folder-sync@2x.png</file>
<file>resources/task-ongoing.png</file>
<file>resources/view-refresh.png</file>
<file>resources/warning.png</file>
<file>resources/warning@2x.png</file>
<file>resources/settings.png</file>
<file>resources/settings@2x.png</file>
<file>resources/activity.svg</file>
<file>resources/activity.png</file>
<file>resources/activity@2x.png</file>
<file>resources/network.png</file>
@@ -20,13 +12,13 @@
<file>resources/lock-https.png</file>
<file>resources/lock-https@2x.png</file>
<file>resources/account.png</file>
<file>resources/account.svg</file>
<file>resources/more.svg</file>
<file>resources/delete.png</file>
<file>resources/close.svg</file>
<file>resources/bell.svg</file>
<file>resources/link.svg</file>
<file>resources/files.svg</file>
<file>resources/folder-grey.png</file>
<file>resources/state-error.svg</file>
<file>resources/state-warning.svg</file>
<file>resources/folder.svg</file>
@@ -38,7 +30,14 @@
<file>resources/copy.svg</file>
<file>resources/state-sync.svg</file>
<file>resources/add.png</file>
<file>resources/add-color.svg</file>
<file>resources/state-info.svg</file>
<file>resources/change.svg</file>
<file>resources/delete-color.svg</file>
</qresource>
<qresource prefix="/"/>
<qresource prefix="/qml">
<file>src/gui/tray/Window.qml</file>
<file>src/gui/tray/UserLine.qml</file>
</qresource>
</RCC>

View File

@@ -27,7 +27,7 @@
<key>CFBundleShortVersionString</key>
<string>@MIRALL_VERSION_STRING@</string>
<key>NSHumanReadableCopyright</key>
<string>(C) 2014-2018 @APPLICATION_VENDOR@</string>
<string>(C) 2014-2020 @APPLICATION_VENDOR@</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>SUShowReleaseNotes</key>

View File

@@ -0,0 +1,17 @@
# Enable address sanitizer (gcc/clang only)
macro(ENABLE_SANITIZER)
if (NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
message(FATAL_ERROR "Sanitizer supported only for gcc/clang")
endif()
set(SANITIZER_FLAGS "-fsanitize=address -fsanitize=leak -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZER_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZER_FLAGS}")
set(LINKER_FLAGS "-fsanitize=address,undefined -fuse-ld=gold")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
endmacro()

View File

@@ -3,7 +3,11 @@
# For details see the accompanying COPYING* file.
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long -Wno-gnu-zero-variadic-macro-arguments")
# Use this only for Clang
if (CMAKE_CXX_COMPILER MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long -Wno-gnu-zero-variadic-macro-arguments")
endif()
# Fix sqlite compilation on macOS
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-incompatible-pointer-types-discards-qualifiers")

View File

@@ -8,12 +8,12 @@
#cmakedefine CRASHREPORTER_EXECUTABLE "@CRASHREPORTER_EXECUTABLE@"
#define SOCKETAPI_TEAM_IDENTIFIER_PREFIX "@SOCKETAPI_TEAM_IDENTIFIER_PREFIX@"
#cmakedefine APPLICATION_DOMAIN @APPLICATION_DOMAIN@
#cmakedefine THEME_CLASS @THEME_CLASS@
#cmakedefine THEME_INCLUDE @THEME_INCLUDE@
#cmakedefine APPLICATION_NAME "@APPLICATION_NAME@"
#cmakedefine APPLICATION_VENDOR "@APPLICATION_VENDOR@"
#cmakedefine APPLICATION_DOMAIN "@APPLICATION_DOMAIN@"
#cmakedefine APPLICATION_REV_DOMAIN "@APPLICATION_REV_DOMAIN@"
#cmakedefine APPLICATION_SHORTNAME "@APPLICATION_SHORTNAME@"
#cmakedefine APPLICATION_EXECUTABLE "@APPLICATION_EXECUTABLE@"
@@ -21,6 +21,7 @@
#cmakedefine APPLICATION_HELP_URL "@APPLICATION_HELP_URL@"
#cmakedefine APPLICATION_ICON_NAME "@APPLICATION_ICON_NAME@"
#cmakedefine APPLICATION_SERVER_URL "@APPLICATION_SERVER_URL@"
#cmakedefine LINUX_APPLICATION_ID "@LINUX_APPLICATION_ID@"
#cmakedefine APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR "@APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR@"
#cmakedefine APPLICATION_WIZARD_HEADER_TITLE_COLOR "@APPLICATION_WIZARD_HEADER_TITLE_COLOR@"
#cmakedefine APPLICATION_WIZARD_USE_CUSTOM_LOGO "@APPLICATION_WIZARD_USE_CUSTOM_LOGO@"

View File

@@ -13,11 +13,19 @@ desktop client.
These instructions are updated to work with version |version| of the Nextcloud Client.
Getting Source Code
-------------------
You have two possibilities to clone the repo.
The :ref:`generic-build-instructions` pull the latest code directly from
GitHub, and work on Linux, macOS, and Windows.
First option is As [remote URL](https://help.github.com/en/articles/which-remote-url-should-i-use) you can choose between cloning with HTTPS URL's, which is recommended or cloning with SSH URL's.
[https://github.com/nextcloud/desktop.git](https://github.com/nextcloud/desktop.git)
When you don't have SSH key added to your GitHub account, than use HTTPS.
When you no part of the nextcloud organisation, clone with HTTPS:
```
$ git clone git@github.com:nextcloud/desktop.git
```
macOS
-----
@@ -47,7 +55,7 @@ To set up your build environment for development using HomeBrew_:
5. Install a Qt5 version with qtwebkit support::
brew install qt5 --with-qtwebkit
brew install qt5
6. Install any missing dependencies::
@@ -67,10 +75,23 @@ To set up your build environment for development using HomeBrew_:
10. Install the Packages_ package creation tool.
11. In the build directory, run ``admin/osx/create_mac.sh <build_dir> <install_dir>``.
If you have a developer signing certificate, you can specify
its Common Name as a third parameter (use quotes) to have the package
signed automatically.
11. Enable git submodules:
```
$ cd desktop
$ git submodule init
$ git submodule update
```
12. Generate the build files:
```
$ cd build
$ cmake .. -DCMAKE_INSTALL_PREFIX=~/nextcloud-desktop-client -DCMAKE_BUILD_TYPE=Debug -DNO_SHIBBOLETH=1
```
13. Compile and install:
```
$ make install
```
.. note:: Contrary to earlier versions, Nextcloud 1.7 and later are packaged
as a ``pkg`` installer. Do not call "make package" at any time when

View File

@@ -27,7 +27,7 @@ download page.
System Requirements
----------------------------------
- Windows 7+
- Windows 8.1+
- macOS 10.7+ (**64-bit only**)
- CentOS 6 & 7 (64-bit only)
- Debian 8.0 & 9.0

1
resources/add-color.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewbox="0 0 16 16"><path fill="#00d400" d="M9.02 13.98h-2v-5h-5v-2h5v-5h2v5l5-.028V8.98h-5z"/></svg>

After

Width:  |  Height:  |  Size: 179 B

1
resources/change.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" version="1.1" height="16"><path d="m8 2c-2.142 0-4.125 1.145-5.196 3l1.948 1.125c0.671-1.162 1.906-1.875 3.2476-1.875 1.1906 0 2.297 0.56157 3 1.5l-1.5 1.5h4.5v-4.5l-1.406 1.406c-1.129-1.348-2.802-2.1563-4.594-2.1563z"/><path d="m2 8.75v4.5l1.408-1.41c1.116 1.334 2.817 2.145 4.592 2.16 2.16 0.01827 4.116-1.132 5.196-3.002l-1.948-1.125c-0.677 1.171-1.9005 1.886-3.248 1.875-1.18-0.01-2.3047-0.572-3-1.5l1.5-1.5z"/></svg>

After

Width:  |  Height:  |  Size: 493 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16"><path d="m3.0503 4.4645 3.5355 3.5355-3.5355 3.536 1.4142 1.414 3.5355-3.5358 3.536 3.5358 1.414-1.414-3.5358-3.536 3.5358-3.5355-1.414-1.4142-3.536 3.5355-3.5355-3.5355-1.4142 1.4142z" fill="#d40000"/></svg>

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -467,6 +467,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = FinderSyncExt/FinderSyncExt.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";

View File

@@ -35,11 +35,11 @@ public:
QString contextMenuTitle() const
{
return _strings.value("CONTEXT_MENU_TITLE", "ownCloud");
return _strings.value("CONTEXT_MENU_TITLE", "Nextcloud");
}
QString shareActionTitle() const
{
return _strings.value("SHARE_MENU_TITLE", "Share...");
return _strings.value("SHARE_MENU_TITLE", "Share");
}
QString copyPrivateLinkTitle() const { return _strings["COPY_PRIVATE_LINK_MENU_TITLE"]; }

View File

@@ -89,7 +89,7 @@ IFACEMETHODIMP OCContextMenu::Initialize(
HDROP hDrop = static_cast<HDROP>(GlobalLock(stm.hGlobal));
if (hDrop) {
UINT nFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
for (int i = 0; i < nFiles; ++i) {
for (UINT i = 0; i < nFiles; ++i) {
// Get the path of the file.
wchar_t buffer[MAX_PATH];

View File

@@ -5,6 +5,8 @@
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
// Note: Here was a #define for windows target version
// e.g. WINVER / _WIN32_WINNT, see https://devblogs.microsoft.com/oldnewthing/20070411-00/?p=27283
// Unnecessary because we define both in desktop/CMakeLists.txt
#include <SDKDDKVer.h>

View File

@@ -13,8 +13,10 @@
*/
#define WIN32_LEAN_AND_MEAN
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
// Note: Here was a #define for windows target version
// e.g. WINVER / _WIN32_WINNT, see https://devblogs.microsoft.com/oldnewthing/20070411-00/?p=27283
// Unnecessary because we define both in desktop/CMakeLists.txt
#include "CommunicationSocket.h"
#include "RegistryUtil.h"

View File

@@ -1,7 +1,9 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
// Note: Here was a #define for windows target version
// e.g. WINVER / _WIN32_WINNT, see https://devblogs.microsoft.com/oldnewthing/20070411-00/?p=27283
// Unnecessary because we define both in desktop/CMakeLists.txt
#include <windows.h>

View File

@@ -29,12 +29,17 @@ if(NOT MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORTIFY_SOURCE=2")
endif()
# Calling Qt's qCWarning(category, ...) with no params for "..." is a GNU
# extension (C++11 §16.3/4 forbids them). Silence clang's warnings.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-gnu-zero-variadic-macro-arguments")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments")
endif()
if(WIN32)
# Enable DEP & ASLR
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /nxcompat /dynamicbase")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /nxcompat /dynamicbase")
elseif(UNIX AND NOT APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now")

View File

@@ -499,7 +499,7 @@ restart_sync:
}
Cmd cmd;
QString dbPath = options.source_dir + SyncJournalDb::makeDbName(options.source_dir, credentialFreeUrl, folder, user);
QString dbPath = options.source_dir + SyncJournalDb::makeDbName(credentialFreeUrl, folder, user);
SyncJournalDb db(dbPath);
if (!selectiveSyncList.empty()) {

View File

@@ -11,43 +11,50 @@
// For overloading macros by argument count
// See stackoverflow.com/questions/16683146/can-macros-be-overloaded-by-number-of-arguments
#define OC_ASSERT_CAT(A, B) A##B
#define OC_ASSERT_SELECT(NAME, NUM) OC_ASSERT_CAT(NAME##_, NUM)
#define OC_ASSERT_GET_COUNT(_1, _2, _3, COUNT, ...) COUNT
#define OC_ASSERT_VA_SIZE(...) OC_ASSERT_GET_COUNT(__VA_ARGS__, 3, 2, 1, 0)
// Bugfix 08/09/2019: Broken arg expansion led to always collapsing to 1 arg (XXXX_1 overload result)
// See also: https://stackoverflow.com/questions/9183993/msvc-variadic-macro-expansion
#define OC_ASSERT_GLUE(x, y) x y
#define OC_ASSERT_OVERLOAD(NAME, ...) OC_ASSERT_SELECT(NAME, OC_ASSERT_VA_SIZE(__VA_ARGS__)) \
(__VA_ARGS__)
#define OC_ASSERT_GET_COUNT(_1, _2, _3, COUNT, ...) COUNT
#define OC_ASSERT_EXPAND_ARGS(args) OC_ASSERT_GET_COUNT args
#define OC_ASSERT_VA_SIZE(...) OC_ASSERT_EXPAND_ARGS((__VA_ARGS__, 3, 2, 1, 0))
#define OC_ASSERT_SELECT2(NAME, COUNT) NAME##COUNT
#define OC_ASSERT_SELECT1(NAME, COUNT) OC_ASSERT_SELECT2(NAME, COUNT)
#define OC_ASSERT_SELECT(NAME, COUNT) OC_ASSERT_SELECT1(NAME, COUNT)
#define OC_ASSERT_OVERLOAD(NAME, ...) OC_ASSERT_GLUE(OC_ASSERT_SELECT(NAME, OC_ASSERT_VA_SIZE(__VA_ARGS__)), \
(__VA_ARGS__))
// Default assert: If the condition is false in debug builds, terminate.
//
// Prints a message on failure, even in release builds.
#define ASSERT(...) OC_ASSERT_OVERLOAD(ASSERT, __VA_ARGS__)
#define ASSERT_1(cond) \
#define ASSERT1(cond) \
if (!(cond)) { \
OC_ASSERT_MSG("ASSERT: \"%s\" in file %s, line %d", #cond, __FILE__, __LINE__); \
} else { \
}
#define ASSERT_2(cond, message) \
#define ASSERT2(cond, message) \
if (!(cond)) { \
OC_ASSERT_MSG("ASSERT: \"%s\" in file %s, line %d with message: %s", #cond, __FILE__, __LINE__, message); \
} else { \
}
#define ASSERT(...) OC_ASSERT_OVERLOAD(ASSERT, __VA_ARGS__)
// Enforce condition to be true, even in release builds.
//
// Prints 'message' and aborts execution if 'cond' is false.
#define ENFORCE(...) OC_ASSERT_OVERLOAD(ENFORCE, __VA_ARGS__)
#define ENFORCE_1(cond) \
#define ENFORCE1(cond) \
if (!(cond)) { \
qFatal("ENFORCE: \"%s\" in file %s, line %d", #cond, __FILE__, __LINE__); \
} else { \
}
#define ENFORCE_2(cond, message) \
#define ENFORCE2(cond, message) \
if (!(cond)) { \
qFatal("ENFORCE: \"%s\" in file %s, line %d with message: %s", #cond, __FILE__, __LINE__, message); \
} else { \
}
#define ENFORCE(...) OC_ASSERT_OVERLOAD(ENFORCE, __VA_ARGS__)
// An assert that is only present in debug builds: typically used for
// asserts that are too expensive for release mode.

View File

@@ -207,7 +207,10 @@ static inline uint64_t c_jhash64(const uint8_t *k, uint64_t length, uint64_t int
/* handle the last 23 bytes */
c += length;
switch(len) {
// pragma only for GCC (and clang continues to pretend to be it by defining __GNUC__)
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
case 23: c+=((uint64_t)k[22]<<56);
case 22: c+=((uint64_t)k[21]<<48);
case 21: c+=((uint64_t)k[20]<<40);

View File

@@ -281,8 +281,8 @@ int SqlQuery::prepare(const QByteArray &sql, bool allow_failure)
*/
static bool startsWithInsensitive(const QByteArray &a, const char *b)
{
int len = strlen(b);
return a.size() >= len && qstrnicmp(a.constData(), b, len) == 0;
size_t len = strlen(b);
return a.size() >= len && qstrnicmp(a.constData(), b, Utility::convertSizeToUint(len)) == 0;
}
bool SqlQuery::isSelect()

View File

@@ -23,6 +23,7 @@
#include <QElapsedTimer>
#include <QUrl>
#include <QDir>
#include <QStandardPaths>
#include <sqlite3.h>
#include "common/syncjournaldb.h"
@@ -102,11 +103,15 @@ SyncJournalDb::SyncJournalDb(const QString &dbFilePath, QObject *parent)
}
}
QString SyncJournalDb::makeDbName(const QString &localPath,
const QUrl &remoteUrl,
QString SyncJournalDb::makeDbName(const QUrl &remoteUrl,
const QString &remotePath,
const QString &user)
{
const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
if (!QDir(dbPath).exists()) {
QDir().mkdir(dbPath);
}
QString journalPath = QLatin1String("._sync_");
QString key = QString::fromUtf8("%1@%2:%3").arg(user, remoteUrl.toString(), remotePath);
@@ -115,17 +120,16 @@ QString SyncJournalDb::makeDbName(const QString &localPath,
journalPath.append(ba.left(6).toHex());
journalPath.append(".db");
journalPath = dbPath + QLatin1Char('/') + journalPath;
// If the journal doesn't exist and we can't create a file
// at that location, try again with a journal name that doesn't
// have the ._ prefix.
//
// The disadvantage of that filename is that it will only be ignored
// by client versions >2.3.2.
//
// See #5633: "._*" is often forbidden on samba shared folders.
// If it exists already, the path is clearly usable
QFile file(QDir(localPath).filePath(journalPath));
QFile file(QDir(dbPath).filePath(journalPath));
if (file.exists()) {
return journalPath;
}
@@ -140,7 +144,7 @@ QString SyncJournalDb::makeDbName(const QString &localPath,
// Can we create it if we drop the underscore?
QString alternateJournalPath = journalPath.mid(2).prepend(".");
QFile file2(QDir(localPath).filePath(alternateJournalPath));
QFile file2(QDir(dbPath).filePath(alternateJournalPath));
if (file2.open(QIODevice::ReadWrite)) {
// The alternative worked, use it
qCInfo(lcDb) << "Using alternate database path" << alternateJournalPath;

View File

@@ -46,8 +46,7 @@ public:
virtual ~SyncJournalDb();
/// Create a journal path for a specific configuration
static QString makeDbName(const QString &localPath,
const QUrl &remoteUrl,
static QString makeDbName(const QUrl &remoteUrl,
const QString &remotePath,
const QString &user);
@@ -103,6 +102,7 @@ public:
: _chunk(0)
, _transferid(0)
, _size(0)
, _modtime(0)
, _errorCount(0)
, _valid(false)
{

View File

@@ -255,7 +255,7 @@ void Utility::usleep(int usec)
}
// This can be overriden from the tests
OCSYNC_EXPORT bool fsCasePreserving_override = []()-> bool {
OCSYNC_EXPORT bool fsCasePreserving_override = []() -> bool {
QByteArray env = qgetenv("OWNCLOUD_TEST_CASE_PRESERVING");
if (!env.isEmpty())
return env.toInt();
@@ -362,12 +362,12 @@ QString Utility::fileNameForGuiUse(const QString &fName)
QByteArray Utility::normalizeEtag(QByteArray etag)
{
/* strip "XXXX-gzip" */
if(etag.startsWith('"') && etag.endsWith("-gzip\"")) {
if (etag.startsWith('"') && etag.endsWith("-gzip\"")) {
etag.chop(6);
etag.remove(0, 1);
}
/* strip trailing -gzip */
if(etag.endsWith("-gzip")) {
if (etag.endsWith("-gzip")) {
etag.chop(5);
}
/* strip normal quotes */
@@ -396,6 +396,26 @@ void Utility::crash()
*a = 1;
}
// Use this functions to retrieve uint/int (often required by Qt and WIN32) from size_t
// without compiler warnings about possible truncation
uint Utility::convertSizeToUint(size_t &convertVar)
{
if (convertVar > UINT_MAX) {
//throw std::bad_cast();
convertVar = UINT_MAX; // intentionally default to wrong value here to not crash: exception handling TBD
}
return static_cast<uint>(convertVar);
}
uint Utility::convertSizeToInt(size_t &convertVar)
{
if (convertVar > INT_MAX) {
//throw std::bad_cast();
convertVar = INT_MAX; // intentionally default to wrong value here to not crash: exception handling TBD
}
return static_cast<int>(convertVar);
}
// read the output of the owncloud --version command from the owncloud
// version that is on disk. This works for most versions of the client,
// because clients that do not yet know the --version flag return the
@@ -445,7 +465,7 @@ QString Utility::timeAgoInWords(const QDateTime &dt, const QDateTime &from)
if (floor(secs / 3600.0) > 0) {
int hours = floor(secs / 3600.0);
if(hours == 1){
if (hours == 1) {
return (QObject::tr("%n hour ago", "", hours));
} else {
return (QObject::tr("%n hours ago", "", hours));
@@ -460,7 +480,7 @@ QString Utility::timeAgoInWords(const QDateTime &dt, const QDateTime &from)
return QObject::tr("Less than a minute ago");
}
} else if(minutes == 1){
} else if (minutes == 1) {
return (QObject::tr("%n minute ago", "", minutes));
} else {
return (QObject::tr("%n minutes ago", "", minutes));

View File

@@ -20,6 +20,7 @@
#ifndef UTILITY_H
#define UTILITY_H
#include "ocsynclib.h"
#include <QString>
#include <QByteArray>
@@ -29,6 +30,7 @@
#include <QMap>
#include <QUrl>
#include <QUrlQuery>
#include <QtQuick/QQuickImageProvider>
#include <functional>
#include <memory>
@@ -55,6 +57,12 @@ namespace Utility {
OCSYNC_EXPORT QByteArray userAgentString();
OCSYNC_EXPORT bool hasLaunchOnStartup(const QString &appName);
OCSYNC_EXPORT void setLaunchOnStartup(const QString &appName, const QString &guiName, bool launch);
OCSYNC_EXPORT uint convertSizeToUint(size_t &convertVar);
OCSYNC_EXPORT uint convertSizeToInt(size_t &convertVar);
#ifdef Q_OS_WIN
OCSYNC_EXPORT DWORD convertSizeToDWORD(size_t &convertVar);
#endif
/**
* Return the amount of free space available.

View File

@@ -47,14 +47,18 @@ QString getUserAutostartDir_private()
bool hasLaunchOnStartup_private(const QString &appName)
{
QString desktopFileLocation = getUserAutostartDir_private() + appName + QLatin1String(".desktop");
QString desktopFileLocation = getUserAutostartDir_private()
+ QLatin1String(LINUX_APPLICATION_ID)
+ QLatin1String(".desktop");
return QFile::exists(desktopFileLocation);
}
void setLaunchOnStartup_private(const QString &appName, const QString &guiName, bool enable)
{
QString userAutoStartPath = getUserAutostartDir_private();
QString desktopFileLocation = userAutoStartPath + appName + QLatin1String(".desktop");
QString desktopFileLocation = userAutoStartPath
+ QLatin1String(LINUX_APPLICATION_ID)
+ QLatin1String(".desktop");
if (enable) {
if (!QDir().exists(userAutoStartPath) && !QDir().mkpath(userAutoStartPath)) {
qCWarning(lcUtility) << "Could not create autostart folder" << userAutoStartPath;

View File

@@ -90,32 +90,13 @@ void setLaunchOnStartup_private(const QString &appName, const QString &guiName,
// TODO: Right now only detection on toggle/startup, not when windows theme is switched while nextcloud is running
static inline bool hasDarkSystray_private()
{
bool hasDarkSystray = true;
// Open registry key first, continue only on success (may be legitimately absent in earlier windows versions)
HKEY hKey;
LONG lRes = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey);
// classical windows function - preserve buff size for DWORD, call ExW version, store regkey value in nResult
if (lRes == ERROR_SUCCESS) {
DWORD dwBufferSize(sizeof(DWORD));
DWORD nResult(0);
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexw
LONG nError = ::RegQueryValueExW(hKey,
L"SystemUsesLightTheme",
NULL,
NULL,
reinterpret_cast<LPBYTE>(&nResult),
&dwBufferSize);
// if RegQuery returned no error and light theme was found, change systray return value
if (nError == ERROR_SUCCESS && nResult == 1)
hasDarkSystray = false;
return hasDarkSystray;
} else {
// fallback to true if regkey could not be determined
return hasDarkSystray;
if(Utility::registryGetKeyValue( HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
"SystemUsesLightTheme" ) == 1) {
return false;
}
else {
return true;
}
}
@@ -283,4 +264,13 @@ bool Utility::registryWalkSubKeys(HKEY hRootKey, const QString &subKey, const st
return retCode != ERROR_NO_MORE_ITEMS;
}
DWORD Utility::convertSizeToDWORD(size_t &convertVar)
{
if( convertVar > UINT_MAX ) {
//throw std::bad_cast();
convertVar = UINT_MAX; // intentionally default to wrong value here to not crash: exception handling TBD
}
return static_cast<DWORD>(convertVar);
}
} // namespace OCC

View File

@@ -73,7 +73,7 @@ static void csync_exclude_expand_escapes(QByteArray &input)
line[o++] = line[i];
}
}
input.resize(o);
input.resize(OCC::Utility::convertSizeToUint(o));
}
// See http://support.microsoft.com/kb/74496 and
@@ -288,7 +288,11 @@ void ExcludedFiles::addManualExclude(const QByteArray &expr)
void ExcludedFiles::addManualExclude(const QByteArray &expr, const QByteArray &basePath)
{
#if defined(Q_OS_WIN)
Q_ASSERT(basePath.size() >= 2 && basePath.at(1) == ':');
#else
Q_ASSERT(basePath.startsWith('/'));
#endif
Q_ASSERT(basePath.endsWith('/'));
auto key = basePath;
@@ -322,7 +326,11 @@ bool ExcludedFiles::loadExcludeFile(const QByteArray & basePath, const QString &
csync_exclude_expand_escapes(line);
_allExcludes[basePath].append(line);
}
prepare(basePath);
// nothing to prepare if the user decided to not exclude anything
if(_allExcludes.size())
prepare(basePath);
return true;
}
@@ -338,8 +346,8 @@ bool ExcludedFiles::reloadExcludeFiles()
_fullRegexDir.clear();
bool success = true;
for (auto basePath : _excludeFiles.keys()) {
for (auto file : _excludeFiles.value(basePath)) {
for (const auto& basePath : _excludeFiles.keys()) {
for (const auto& file : _excludeFiles.value(basePath)) {
success = loadExcludeFile(basePath, file);
}
}

View File

@@ -724,7 +724,8 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
if (ctx->current == LOCAL_REPLICA) {
ASSERT(dirent->path.startsWith(ctx->local.uri)); // path is relative to uri
// "len + 1" to include the slash in-between.
dirent->path = dirent->path.mid(strlen(ctx->local.uri) + 1);
size_t uriLength = strlen(ctx->local.uri);
dirent->path = dirent->path.mid(OCC::Utility::convertSizeToInt(uriLength) + 1);
}
previous_fs = ctx->current_fs;

View File

@@ -38,6 +38,7 @@
#include "c_alloc.h"
#include "c_string.h"
#include "common/filesystembase.h"
#include "common/utility.h"
/* Convert a locale String to UTF8 */
QByteArray c_utf8_from_locale(const mbchar_t *wstr)
@@ -52,10 +53,10 @@ QByteArray c_utf8_from_locale(const mbchar_t *wstr)
size_t len;
len = wcslen(wstr);
/* Call once to get the required size. */
size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, OCC::Utility::convertSizeToInt(len), NULL, 0, NULL, NULL);
if (size_needed > 0) {
dst.resize(size_needed);
WideCharToMultiByte(CP_UTF8, 0, wstr, len, dst.data(), size_needed, NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, wstr, OCC::Utility::convertSizeToInt(len), dst.data(), size_needed, NULL, NULL);
}
return dst;
#else
@@ -95,7 +96,7 @@ mbchar_t* c_utf8_string_to_locale(const char *str)
int size_needed;
len = strlen(str);
size_needed = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
size_needed = MultiByteToWideChar(CP_UTF8, 0, str, OCC::Utility::convertSizeToInt(len), NULL, 0);
if (size_needed > 0) {
int size_char = (size_needed + 1) * sizeof(mbchar_t);
dst = (mbchar_t*)c_malloc(size_char);
@@ -114,7 +115,8 @@ mbchar_t* c_utf8_string_to_locale(const char *str)
return NULL;
} else {
#ifdef _WIN32
QByteArray unc_str = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(str, strlen(str)));
size_t strLength = strlen(str);
QByteArray unc_str = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(str, OCC::Utility::convertSizeToInt(strLength)));
mbchar_t *dst = c_utf8_string_to_locale(unc_str);
return dst;
#else

View File

@@ -57,7 +57,7 @@ csync_vio_handle_t *csync_vio_local_opendir(const char *name) {
handle = (dhandle_t*)c_malloc(sizeof(dhandle_t));
// the file wildcard has to be attached
int len_name = strlen(name);
size_t len_name = strlen(name);
if( len_name ) {
char *h = NULL;

View File

@@ -1,5 +1,5 @@
project(gui)
find_package(Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt5 REQUIRED COMPONENTS Widgets Svg)
set(CMAKE_AUTOMOC TRUE)
set(CMAKE_AUTOUIC TRUE)
set(CMAKE_AUTORCC TRUE)
@@ -24,7 +24,6 @@ set(client_UI_SRCS
ignorelisteditor.ui
ignorelisttablewidget.ui
networksettings.ui
activitywidget.ui
synclogdialog.ui
settingsdialog.ui
sharedialog.ui
@@ -35,12 +34,13 @@ set(client_UI_SRCS
addcertificatedialog.ui
proxyauthdialog.ui
mnemonicdialog.ui
tray/Window.qml
tray/UserLine.qml
wizard/flow2authwidget.ui
wizard/owncloudadvancedsetuppage.ui
wizard/owncloudconnectionmethoddialog.ui
wizard/owncloudhttpcredspage.ui
wizard/owncloudoauthcredspage.ui
wizard/flow2authcredspage.ui
wizard/flow2authwidget.ui
wizard/owncloudsetupnocredspage.ui
wizard/owncloudwizardresultpage.ui
wizard/webview.ui
@@ -74,10 +74,6 @@ set(client_SRCS
openfilemanager.cpp
owncloudgui.cpp
owncloudsetupwizard.cpp
activitydata.cpp
activitylistmodel.cpp
activitywidget.cpp
activityitemdelegate.cpp
selectivesyncdialog.cpp
settingsdialog.cpp
sharedialog.cpp
@@ -100,14 +96,20 @@ set(client_SRCS
synclogdialog.cpp
tooltipupdater.cpp
notificationconfirmjob.cpp
servernotificationhandler.cpp
guiutility.cpp
elidedlabel.cpp
headerbanner.cpp
iconjob.cpp
remotewipe.cpp
tray/ActivityData.cpp
tray/ActivityListModel.cpp
tray/UserModel.cpp
tray/NotificationHandler.cpp
creds/credentialsfactory.cpp
creds/httpcredentialsgui.cpp
creds/oauth.cpp
creds/flow2auth.cpp
creds/keychainchunk.cpp
creds/webflowcredentials.cpp
creds/webflowcredentialsdialog.cpp
wizard/postfixlineedit.cpp
@@ -144,8 +146,6 @@ set(updater_SRCS
IF( APPLE )
list(APPEND client_SRCS cocoainitializer_mac.mm)
list(APPEND client_SRCS settingsdialogmac.cpp)
list(REMOVE_ITEM client_SRCS settingsdialog.cpp)
list(APPEND client_SRCS socketapisocket_mac.mm)
list(APPEND client_SRCS systray.mm)
@@ -175,14 +175,6 @@ set(3rdparty_SRC
../3rdparty/kmessagewidget/kmessagewidget.cpp
)
if (APPLE)
list(APPEND 3rdparty_SRC
../3rdparty/qtmacgoodies/src/macpreferenceswindow.mm
../3rdparty/qtmacgoodies/src/macstandardicon.mm
../3rdparty/qtmacgoodies/src/macwindow.mm
)
endif()
if(NOT WIN32)
list(APPEND 3rdparty_SRC ../3rdparty/qtlockedfile/qtlockedfile_unix.cpp)
else()
@@ -306,7 +298,7 @@ else()
endif()
add_library(updater STATIC ${updater_SRCS})
target_link_libraries(updater ${synclib_NAME} Qt5::Widgets Qt5::Network Qt5::Xml Qt5::WebEngineWidgets)
target_link_libraries(updater ${synclib_NAME} Qt5::Widgets Qt5::Svg Qt5::Network Qt5::Xml Qt5::WebEngineWidgets)
target_include_directories(updater PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
@@ -316,7 +308,7 @@ set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/${APPLICATION_EXECUTABLE};${CMAKE_INSTALL_RPATH}" )
target_link_libraries( ${APPLICATION_EXECUTABLE} Qt5::Widgets Qt5::Network Qt5::Xml)
target_link_libraries( ${APPLICATION_EXECUTABLE} Qt5::Widgets Qt5::Svg Qt5::Network Qt5::Xml)
target_link_libraries( ${APPLICATION_EXECUTABLE} ${synclib_NAME} )
target_link_libraries( ${APPLICATION_EXECUTABLE} updater )
target_link_libraries( ${APPLICATION_EXECUTABLE} ${OS_SPECIFIC_LINK_LIBRARIES} )
@@ -338,7 +330,6 @@ ENDIF()
target_include_directories(${APPLICATION_EXECUTABLE} PRIVATE
${CMAKE_SOURCE_DIR}/src/3rdparty/QProgressIndicator
${CMAKE_SOURCE_DIR}/src/3rdparty/qtlockedfile
${CMAKE_SOURCE_DIR}/src/3rdparty/qtmacgoodies/src
${CMAKE_SOURCE_DIR}/src/3rdparty/qtsingleapplication
${CMAKE_SOURCE_DIR}/src/3rdparty/kmessagewidget
${CMAKE_CURRENT_BINARY_DIR}
@@ -397,7 +388,7 @@ endif()
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT WIN32)
configure_file(${CMAKE_SOURCE_DIR}/mirall.desktop.in
${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.desktop)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.desktop DESTINATION ${DATADIR}/applications )
${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop DESTINATION ${DATADIR}/applications )
endif()

View File

@@ -368,6 +368,7 @@ void AccountManager::shutdown()
_accounts.clear();
foreach (const auto &acc, accountsCopy) {
emit accountRemoved(acc.data());
emit removeAccountFolders(acc.data());
}
}

View File

@@ -70,7 +70,6 @@ public:
*/
void deleteAccount(AccountState *account);
/**
* Creates an account and sets up some basic handlers.
* Does *not* add the account to the account manager just yet.
@@ -90,6 +89,9 @@ private:
// Adds an account to the tracked list, emitting accountAdded()
void addAccountState(AccountState *accountState);
AccountManager() {}
QList<AccountStatePtr> _accounts;
public slots:
/// Saves account data, not including the credentials
void saveAccount(Account *a);
@@ -104,9 +106,6 @@ public slots:
Q_SIGNALS:
void accountAdded(AccountState *account);
void accountRemoved(AccountState *account);
private:
AccountManager() {}
QList<AccountStatePtr> _accounts;
void removeAccountFolders(AccountState *account);
};
}

View File

@@ -57,10 +57,6 @@
#include "account.h"
#ifdef Q_OS_MAC
#include "settingsdialogmac.h"
#endif
namespace OCC {
Q_LOGGING_CATEGORY(lcAccountSettings, "nextcloud.gui.account.settings", QtInfoMsg)
@@ -113,13 +109,13 @@ protected:
AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
: QWidget(parent)
, ui(new Ui::AccountSettings)
, _ui(new Ui::AccountSettings)
, _wasDisabledBefore(false)
, _accountState(accountState)
, _quotaInfo(accountState)
, _menuShown(false)
{
ui->setupUi(this);
_ui->setupUi(this);
_model = new FolderStatusModel;
_model->setAccountState(_accountState);
@@ -127,35 +123,37 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
FolderStatusDelegate *delegate = new FolderStatusDelegate;
delegate->setParent(this);
ui->_folderList->header()->hide();
ui->_folderList->setItemDelegate(delegate);
ui->_folderList->setModel(_model);
// Connect styleChanged events to our widgets, so they can adapt (Dark-/Light-Mode switching)
connect(this, &AccountSettings::styleChanged, delegate, &FolderStatusDelegate::slotStyleChanged);
_ui->_folderList->header()->hide();
_ui->_folderList->setItemDelegate(delegate);
_ui->_folderList->setModel(_model);
#if defined(Q_OS_MAC)
ui->_folderList->setMinimumWidth(400);
_ui->_folderList->setMinimumWidth(400);
#else
ui->_folderList->setMinimumWidth(300);
_ui->_folderList->setMinimumWidth(300);
#endif
new ToolTipUpdater(ui->_folderList);
new ToolTipUpdater(_ui->_folderList);
auto mouseCursorChanger = new MouseCursorChanger(this);
mouseCursorChanger->folderList = ui->_folderList;
mouseCursorChanger->folderList = _ui->_folderList;
mouseCursorChanger->model = _model;
ui->_folderList->setMouseTracking(true);
ui->_folderList->setAttribute(Qt::WA_Hover, true);
ui->_folderList->installEventFilter(mouseCursorChanger);
_ui->_folderList->setMouseTracking(true);
_ui->_folderList->setAttribute(Qt::WA_Hover, true);
_ui->_folderList->installEventFilter(mouseCursorChanger);
createAccountToolbox();
connect(AccountManager::instance(), &AccountManager::accountAdded,
this, &AccountSettings::slotAccountAdded);
connect(ui->_folderList, &QWidget::customContextMenuRequested,
connect(this, &AccountSettings::removeAccountFolders,
AccountManager::instance(), &AccountManager::removeAccountFolders);
connect(_ui->_folderList, &QWidget::customContextMenuRequested,
this, &AccountSettings::slotCustomContextMenuRequested);
connect(ui->_folderList, &QAbstractItemView::clicked,
connect(_ui->_folderList, &QAbstractItemView::clicked,
this, &AccountSettings::slotFolderListClicked);
connect(ui->_folderList, &QTreeView::expanded, this, &AccountSettings::refreshSelectiveSyncStatus);
connect(ui->_folderList, &QTreeView::collapsed, this, &AccountSettings::refreshSelectiveSyncStatus);
connect(ui->selectiveSyncNotification, &QLabel::linkActivated,
connect(_ui->_folderList, &QTreeView::expanded, this, &AccountSettings::refreshSelectiveSyncStatus);
connect(_ui->_folderList, &QTreeView::collapsed, this, &AccountSettings::refreshSelectiveSyncStatus);
connect(_ui->selectiveSyncNotification, &QLabel::linkActivated,
this, &AccountSettings::slotLinkActivated);
connect(_model, &FolderStatusModel::suggestExpand, ui->_folderList, &QTreeView::expand);
connect(_model, &FolderStatusModel::suggestExpand, _ui->_folderList, &QTreeView::expand);
connect(_model, &FolderStatusModel::dirtyChanged, this, &AccountSettings::refreshSelectiveSyncStatus);
refreshSelectiveSyncStatus();
connect(_model, &QAbstractItemModel::rowsInserted,
@@ -172,20 +170,21 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
addAction(syncNowWithRemoteDiscovery);
connect(ui->selectiveSyncApply, &QAbstractButton::clicked, _model, &FolderStatusModel::slotApplySelectiveSync);
connect(ui->selectiveSyncCancel, &QAbstractButton::clicked, _model, &FolderStatusModel::resetFolders);
connect(ui->bigFolderApply, &QAbstractButton::clicked, _model, &FolderStatusModel::slotApplySelectiveSync);
connect(ui->bigFolderSyncAll, &QAbstractButton::clicked, _model, &FolderStatusModel::slotSyncAllPendingBigFolders);
connect(ui->bigFolderSyncNone, &QAbstractButton::clicked, _model, &FolderStatusModel::slotSyncNoPendingBigFolders);
connect(_ui->selectiveSyncApply, &QAbstractButton::clicked, _model, &FolderStatusModel::slotApplySelectiveSync);
connect(_ui->selectiveSyncCancel, &QAbstractButton::clicked, _model, &FolderStatusModel::resetFolders);
connect(_ui->bigFolderApply, &QAbstractButton::clicked, _model, &FolderStatusModel::slotApplySelectiveSync);
connect(_ui->bigFolderSyncAll, &QAbstractButton::clicked, _model, &FolderStatusModel::slotSyncAllPendingBigFolders);
connect(_ui->bigFolderSyncNone, &QAbstractButton::clicked, _model, &FolderStatusModel::slotSyncNoPendingBigFolders);
connect(FolderMan::instance(), &FolderMan::folderListChanged, _model, &FolderStatusModel::resetFolders);
connect(this, &AccountSettings::folderChanged, _model, &FolderStatusModel::resetFolders);
QColor color = palette().highlight().color();
ui->quotaProgressBar->setStyleSheet(QString::fromLatin1(progressBarStyleC).arg(color.name()));
// quotaProgressBar style now set in customizeStyle()
/*QColor color = palette().highlight().color();
_ui->quotaProgressBar->setStyleSheet(QString::fromLatin1(progressBarStyleC).arg(color.name()));*/
ui->connectLabel->setText(tr("No account configured."));
_ui->connectLabel->setText(tr("No account configured."));
connect(_accountState, &AccountState::stateChanged, this, &AccountSettings::slotAccountStateChanged);
slotAccountStateChanged();
@@ -202,70 +201,31 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
{
slotNewMnemonicGenerated();
} else {
ui->encryptionMessage->hide();
_ui->encryptionMessage->hide();
}
}
connect(UserModel::instance(), &UserModel::addAccount,
this, &AccountSettings::slotOpenAccountWizard);
void AccountSettings::createAccountToolbox()
{
QMenu *menu = new QMenu();
connect(menu, &QMenu::aboutToShow, this, &AccountSettings::slotMenuBeforeShow);
_addAccountAction = new QAction(tr("Add new"), this);
menu->addAction(_addAccountAction);
connect(_addAccountAction, &QAction::triggered, this, &AccountSettings::slotOpenAccountWizard);
_toggleSignInOutAction = new QAction(tr("Log out"), this);
connect(_toggleSignInOutAction, &QAction::triggered, this, &AccountSettings::slotToggleSignInState);
menu->addAction(_toggleSignInOutAction);
QAction *action = new QAction(tr("Remove"), this);
menu->addAction(action);
connect(action, &QAction::triggered, this, &AccountSettings::slotDeleteAccount);
ui->_accountToolbox->setText(tr("Account") + QLatin1Char(' '));
ui->_accountToolbox->setMenu(menu);
ui->_accountToolbox->setPopupMode(QToolButton::InstantPopup);
slotAccountAdded(_accountState);
customizeStyle();
}
void AccountSettings::slotNewMnemonicGenerated()
{
ui->encryptionMessage->setText(tr("This account supports end-to-end encryption"));
_ui->encryptionMessage->setText(tr("This account supports end-to-end encryption"));
QAction *mnemonic = new QAction(tr("Enable encryption"), this);
connect(mnemonic, &QAction::triggered, this, &AccountSettings::requesetMnemonic);
connect(mnemonic, &QAction::triggered, ui->encryptionMessage, &KMessageWidget::hide);
connect(mnemonic, &QAction::triggered, _ui->encryptionMessage, &KMessageWidget::hide);
ui->encryptionMessage->addAction(mnemonic);
ui->encryptionMessage->show();
_ui->encryptionMessage->addAction(mnemonic);
_ui->encryptionMessage->show();
}
void AccountSettings::slotMenuBeforeShow() {
if (_menuShown) {
return;
}
auto menu = ui->_accountToolbox->menu();
// We can't check this during the initial creation as there is no account yet then
if (_accountState->account()->capabilities().clientSideEncryptionAvaliable()) {
QAction *mnemonic = new QAction(tr("Show E2E mnemonic"), this);
connect(mnemonic, &QAction::triggered, this, &AccountSettings::requesetMnemonic);
menu->addAction(mnemonic);
}
_menuShown = true;
}
QString AccountSettings::selectedFolderAlias() const
{
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
QModelIndex selected = _ui->_folderList->selectionModel()->currentIndex();
if (!selected.isValid())
return "";
return _model->data(selected, FolderStatusDelegate::FolderAliasRole).toString();
@@ -278,16 +238,7 @@ void AccountSettings::slotOpenAccountWizard()
if (qgetenv("QT_QPA_PLATFORMTHEME") == "appmenu-qt5" || QSystemTrayIcon::isSystemTrayAvailable()) {
topLevelWidget()->close();
}
#ifdef Q_OS_MAC
qCDebug(lcAccountSettings) << parent() << topLevelWidget();
SettingsDialogMac *sd = qobject_cast<SettingsDialogMac *>(topLevelWidget());
if (sd) {
sd->showActivityPage();
} else {
qFatal("nope");
}
#endif
OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)), nullptr);
}
@@ -303,7 +254,7 @@ void AccountSettings::slotToggleSignInState()
void AccountSettings::doExpand()
{
ui->_folderList->expandToDepth(0);
_ui->_folderList->expandToDepth(0);
}
void AccountSettings::slotShowMnemonic(const QString &mnemonic) {
@@ -334,9 +285,9 @@ void AccountSettings::slotEncryptionFlagError(const QByteArray& fileId, int http
void AccountSettings::slotLockForEncryptionSuccess(const QByteArray& fileId, const QByteArray &token)
{
accountsState()->account()->e2e()->setTokenForFolder(fileId, token);
accountsState()->account()->e2e()->setTokenForFolder(fileId, token);
FolderMetadata emptyMetadata(accountsState()->account());
FolderMetadata emptyMetadata(accountsState()->account());
auto encryptedMetadata = emptyMetadata.encryptedMetadata();
if (encryptedMetadata.isEmpty()) {
//TODO: Mark the folder as unencrypted as the metadata generation failed.
@@ -348,36 +299,36 @@ void AccountSettings::slotLockForEncryptionSuccess(const QByteArray& fileId, con
return;
}
auto storeMetadataJob = new StoreMetaDataApiJob(accountsState()->account(), fileId, emptyMetadata.encryptedMetadata());
connect(storeMetadataJob, &StoreMetaDataApiJob::success,
this, &AccountSettings::slotUploadMetadataSuccess);
connect(storeMetadataJob, &StoreMetaDataApiJob::error,
this, &AccountSettings::slotUpdateMetadataError);
connect(storeMetadataJob, &StoreMetaDataApiJob::success,
this, &AccountSettings::slotUploadMetadataSuccess);
connect(storeMetadataJob, &StoreMetaDataApiJob::error,
this, &AccountSettings::slotUpdateMetadataError);
storeMetadataJob->start();
storeMetadataJob->start();
}
void AccountSettings::slotUploadMetadataSuccess(const QByteArray& folderId)
{
const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
connect(unlockJob, &UnlockEncryptFolderApiJob::success,
this, &AccountSettings::slotUnlockFolderSuccess);
connect(unlockJob, &UnlockEncryptFolderApiJob::error,
this, &AccountSettings::slotUnlockFolderError);
unlockJob->start();
const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
connect(unlockJob, &UnlockEncryptFolderApiJob::success,
this, &AccountSettings::slotUnlockFolderSuccess);
connect(unlockJob, &UnlockEncryptFolderApiJob::error,
this, &AccountSettings::slotUnlockFolderError);
unlockJob->start();
}
void AccountSettings::slotUpdateMetadataError(const QByteArray& folderId, int httpReturnCode)
{
Q_UNUSED(httpReturnCode);
const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
connect(unlockJob, &UnlockEncryptFolderApiJob::success,
this, &AccountSettings::slotUnlockFolderSuccess);
connect(unlockJob, &UnlockEncryptFolderApiJob::error,
this, &AccountSettings::slotUnlockFolderError);
unlockJob->start();
const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
connect(unlockJob, &UnlockEncryptFolderApiJob::success,
this, &AccountSettings::slotUnlockFolderSuccess);
connect(unlockJob, &UnlockEncryptFolderApiJob::error,
this, &AccountSettings::slotUnlockFolderError);
unlockJob->start();
}
void AccountSettings::slotLockForEncryptionError(const QByteArray& fileId, int httpErrorCode)
@@ -551,7 +502,7 @@ void AccountSettings::slotEditCurrentIgnoredFiles()
void AccountSettings::slotEditCurrentLocalIgnoredFiles()
{
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
QModelIndex selected = _ui->_folderList->selectionModel()->currentIndex();
if (!selected.isValid() || _model->classify(selected) != FolderStatusModel::SubFolder)
return;
QString fileName = _model->data(selected, FolderStatusDelegate::FolderPathRole).toString();
@@ -623,7 +574,7 @@ void AccountSettings::slotSubfolderContextMenuRequested(const QModelIndex& index
void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
{
QTreeView *tv = ui->_folderList;
QTreeView *tv = _ui->_folderList;
QModelIndex index = tv->indexAt(pos);
if (!index.isValid()) {
return;
@@ -654,7 +605,7 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
ac = menu->addAction(tr("Edit Ignored Files"));
connect(ac, &QAction::triggered, this, &AccountSettings::slotEditCurrentIgnoredFiles);
if (!ui->_folderList->isExpanded(index)) {
if (!_ui->_folderList->isExpanded(index)) {
ac = menu->addAction(tr("Choose what to sync"));
ac->setEnabled(folderConnected);
connect(ac, &QAction::triggered, this, &AccountSettings::doExpand);
@@ -693,7 +644,7 @@ void AccountSettings::slotFolderListClicked(const QModelIndex &indx)
}
if (_model->classify(indx) == FolderStatusModel::RootFolder) {
// tries to find if we clicked on the '...' button.
QTreeView *tv = ui->_folderList;
QTreeView *tv = _ui->_folderList;
auto pos = tv->mapFromGlobal(QCursor::pos());
if (FolderStatusDelegate::optionsButtonRect(tv->visualRect(indx), layoutDirection()).contains(pos)) {
slotCustomContextMenuRequested(pos);
@@ -706,8 +657,8 @@ void AccountSettings::slotFolderListClicked(const QModelIndex &indx)
// Expand root items on single click
if (_accountState && _accountState->state() == AccountState::Connected) {
bool expanded = !(ui->_folderList->isExpanded(indx));
ui->_folderList->setExpanded(indx, expanded);
bool expanded = !(_ui->_folderList->isExpanded(indx));
_ui->_folderList->setExpanded(indx, expanded);
}
}
}
@@ -744,7 +695,7 @@ void AccountSettings::slotFolderWizardAccepted()
qCInfo(lcAccountSettings) << "Creating folder" << definition.localPath;
if (!dir.mkpath(".")) {
QMessageBox::warning(this, tr("Folder creation failed"),
tr("<p>Could not create local folder <i>%1</i>.")
tr("<p>Could not create local folder <i>%1</i>.</p>")
.arg(QDir::toNativeSeparators(definition.localPath)));
return;
}
@@ -789,7 +740,7 @@ void AccountSettings::slotRemoveCurrentFolder()
{
FolderMan *folderMan = FolderMan::instance();
auto folder = folderMan->folder(selectedFolderAlias());
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
QModelIndex selected = _ui->_folderList->selectionModel()->currentIndex();
if (selected.isValid() && folder) {
int row = selected.row();
@@ -831,7 +782,7 @@ void AccountSettings::slotOpenCurrentFolder()
void AccountSettings::slotOpenCurrentLocalSubFolder()
{
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
QModelIndex selected = _ui->_folderList->selectionModel()->currentIndex();
if (!selected.isValid() || _model->classify(selected) != FolderStatusModel::SubFolder)
return;
QString fileName = _model->data(selected, FolderStatusDelegate::FolderPathRole).toString();
@@ -845,18 +796,21 @@ void AccountSettings::showConnectionLabel(const QString &message, QStringList er
"border-width: 1px; border-style: solid; border-color: #aaaaaa;"
"border-radius:5px;");
if (errors.isEmpty()) {
ui->connectLabel->setText(message);
ui->connectLabel->setToolTip(QString());
ui->connectLabel->setStyleSheet(QString());
QString msg = message;
Theme::replaceLinkColorStringBackgroundAware(msg);
_ui->connectLabel->setText(msg);
_ui->connectLabel->setToolTip(QString());
_ui->connectLabel->setStyleSheet(QString());
} else {
errors.prepend(message);
const QString msg = errors.join(QLatin1String("\n"));
QString msg = errors.join(QLatin1String("\n"));
qCDebug(lcAccountSettings) << msg;
ui->connectLabel->setText(msg);
ui->connectLabel->setToolTip(QString());
ui->connectLabel->setStyleSheet(errStyle);
Theme::replaceLinkColorString(msg, QColor("#c1c8e6"));
_ui->connectLabel->setText(msg);
_ui->connectLabel->setToolTip(QString());
_ui->connectLabel->setStyleSheet(errStyle);
}
ui->accountStatus->setVisible(!message.isEmpty());
_ui->accountStatus->setVisible(!message.isEmpty());
}
void AccountSettings::slotEnableCurrentFolder()
@@ -954,29 +908,29 @@ void AccountSettings::slotOpenOC()
void AccountSettings::slotUpdateQuota(qint64 total, qint64 used)
{
if (total > 0) {
ui->quotaProgressBar->setVisible(true);
ui->quotaProgressBar->setEnabled(true);
_ui->quotaProgressBar->setVisible(true);
_ui->quotaProgressBar->setEnabled(true);
// workaround the label only accepting ints (which may be only 32 bit wide)
const double percent = used / (double)total * 100;
const int percentInt = qMin(qRound(percent), 100);
ui->quotaProgressBar->setValue(percentInt);
_ui->quotaProgressBar->setValue(percentInt);
QString usedStr = Utility::octetsToString(used);
QString totalStr = Utility::octetsToString(total);
QString percentStr = Utility::compactFormatDouble(percent, 1);
QString toolTip = tr("%1 (%3%) of %2 in use. Some folders, including network mounted or shared folders, might have different limits.").arg(usedStr, totalStr, percentStr);
ui->quotaInfoLabel->setText(tr("%1 of %2 in use").arg(usedStr, totalStr));
ui->quotaInfoLabel->setToolTip(toolTip);
ui->quotaProgressBar->setToolTip(toolTip);
_ui->quotaInfoLabel->setText(tr("%1 of %2 in use").arg(usedStr, totalStr));
_ui->quotaInfoLabel->setToolTip(toolTip);
_ui->quotaProgressBar->setToolTip(toolTip);
} else {
ui->quotaProgressBar->setVisible(false);
ui->quotaInfoLabel->setToolTip(QString());
_ui->quotaProgressBar->setVisible(false);
_ui->quotaInfoLabel->setToolTip(QString());
/* -1 means not computed; -2 means unknown; -3 means unlimited (#3940)*/
if (total == 0 || total == -1) {
ui->quotaInfoLabel->setText(tr("Currently there is no storage usage information available."));
_ui->quotaInfoLabel->setText(tr("Currently there is no storage usage information available."));
} else {
QString usedStr = Utility::octetsToString(used);
ui->quotaInfoLabel->setText(tr("%1 in use").arg(usedStr));
_ui->quotaInfoLabel->setText(tr("%1 in use").arg(usedStr));
}
}
}
@@ -985,7 +939,7 @@ void AccountSettings::slotAccountStateChanged()
{
int state = _accountState ? _accountState->state() : AccountState::Disconnected;
if (_accountState) {
ui->sslButton->updateAccountState(_accountState);
_ui->sslButton->updateAccountState(_accountState);
AccountPtr account = _accountState->account();
QUrl safeUrl(account->url());
safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI
@@ -1030,7 +984,7 @@ void AccountSettings::slotAccountStateChanged()
"<a href='%1'>Click here</a> to re-open the browser.")
.arg(url.toString(QUrl::FullyEncoded)));
} else {
showConnectionLabel(tr("Connecting to %1...").arg(serverWithUser));
showConnectionLabel(tr("Connecting to %1").arg(serverWithUser));
}
} else {
showConnectionLabel(tr("No connection to %1 at %2.")
@@ -1044,14 +998,14 @@ void AccountSettings::slotAccountStateChanged()
}
/* Allow to expand the item if the account is connected. */
ui->_folderList->setItemsExpandable(state == AccountState::Connected);
_ui->_folderList->setItemsExpandable(state == AccountState::Connected);
if (state != AccountState::Connected) {
/* check if there are expanded root items, if so, close them */
int i;
for (i = 0; i < _model->rowCount(); ++i) {
if (ui->_folderList->isExpanded(_model->index(i)))
ui->_folderList->setExpanded(_model->index(i), false);
if (_ui->_folderList->isExpanded(_model->index(i)))
_ui->_folderList->setExpanded(_model->index(i), false);
}
} else if (_model->isDirty()) {
// If we connect and have pending changes, show the list.
@@ -1062,21 +1016,12 @@ void AccountSettings::slotAccountStateChanged()
// sync user interface buttons.
refreshSelectiveSyncStatus();
/* set the correct label for the Account toolbox button */
if (_accountState) {
if (_accountState->isSignedOut()) {
_toggleSignInOutAction->setText(tr("Log in"));
} else {
_toggleSignInOutAction->setText(tr("Log out"));
}
}
if (state == AccountState::State::Connected) {
/* TODO: We should probably do something better here.
* Verify if the user has a private key already uploaded to the server,
* if it has, do not offer to create one.
*/
qCInfo(lcAccountSettings) << "Accout" << accountsState()->account()->displayName()
qCInfo(lcAccountSettings) << "Account" << accountsState()->account()->displayName()
<< "Client Side Encryption" << accountsState()->account()->capabilities().clientSideEncryptionAvaliable();
}
}
@@ -1095,21 +1040,21 @@ void AccountSettings::slotLinkActivated(const QString &link)
// Make sure the folder itself is expanded
Folder *f = FolderMan::instance()->folder(alias);
QModelIndex folderIndx = _model->indexForPath(f, QString());
if (!ui->_folderList->isExpanded(folderIndx)) {
ui->_folderList->setExpanded(folderIndx, true);
if (!_ui->_folderList->isExpanded(folderIndx)) {
_ui->_folderList->setExpanded(folderIndx, true);
}
QModelIndex indx = _model->indexForPath(f, myFolder);
if (indx.isValid()) {
// make sure all the parents are expanded
for (auto i = indx.parent(); i.isValid(); i = i.parent()) {
if (!ui->_folderList->isExpanded(i)) {
ui->_folderList->setExpanded(i, true);
if (!_ui->_folderList->isExpanded(i)) {
_ui->_folderList->setExpanded(i, true);
}
}
ui->_folderList->setSelectionMode(QAbstractItemView::SingleSelection);
ui->_folderList->setCurrentIndex(indx);
ui->_folderList->scrollTo(indx);
_ui->_folderList->setSelectionMode(QAbstractItemView::SingleSelection);
_ui->_folderList->setCurrentIndex(indx);
_ui->_folderList->scrollTo(indx);
} else {
qCWarning(lcAccountSettings) << "Unable to find a valid index for " << myFolder;
}
@@ -1118,7 +1063,7 @@ void AccountSettings::slotLinkActivated(const QString &link)
AccountSettings::~AccountSettings()
{
delete ui;
delete _ui;
}
void AccountSettings::refreshSelectiveSyncStatus()
@@ -1156,8 +1101,8 @@ void AccountSettings::refreshSelectiveSyncStatus()
}
if (msg.isEmpty()) {
ui->selectiveSyncButtons->setVisible(true);
ui->bigFolderUi->setVisible(false);
_ui->selectiveSyncButtons->setVisible(true);
_ui->bigFolderUi->setVisible(false);
} else {
ConfigFile cfg;
QString info = !cfg.confirmExternalStorage()
@@ -1166,44 +1111,32 @@ void AccountSettings::refreshSelectiveSyncStatus()
? tr("There are folders that were not synchronized because they are external storages: ")
: tr("There are folders that were not synchronized because they are too big or external storages: ");
ui->selectiveSyncNotification->setText(info + msg);
ui->selectiveSyncButtons->setVisible(false);
ui->bigFolderUi->setVisible(true);
_ui->selectiveSyncNotification->setText(info + msg);
_ui->selectiveSyncButtons->setVisible(false);
_ui->bigFolderUi->setVisible(true);
shouldBeVisible = true;
}
ui->selectiveSyncApply->setEnabled(_model->isDirty() || !msg.isEmpty());
bool wasVisible = !ui->selectiveSyncStatus->isHidden();
_ui->selectiveSyncApply->setEnabled(_model->isDirty() || !msg.isEmpty());
bool wasVisible = !_ui->selectiveSyncStatus->isHidden();
if (wasVisible != shouldBeVisible) {
QSize hint = ui->selectiveSyncStatus->sizeHint();
QSize hint = _ui->selectiveSyncStatus->sizeHint();
if (shouldBeVisible) {
ui->selectiveSyncStatus->setMaximumHeight(0);
ui->selectiveSyncStatus->setVisible(true);
_ui->selectiveSyncStatus->setMaximumHeight(0);
_ui->selectiveSyncStatus->setVisible(true);
}
auto anim = new QPropertyAnimation(ui->selectiveSyncStatus, "maximumHeight", ui->selectiveSyncStatus);
auto anim = new QPropertyAnimation(_ui->selectiveSyncStatus, "maximumHeight", _ui->selectiveSyncStatus);
anim->setEndValue(shouldBeVisible ? hint.height() : 0);
anim->start(QAbstractAnimation::DeleteWhenStopped);
connect(anim, &QPropertyAnimation::finished, [this, shouldBeVisible]() {
ui->selectiveSyncStatus->setMaximumHeight(QWIDGETSIZE_MAX);
_ui->selectiveSyncStatus->setMaximumHeight(QWIDGETSIZE_MAX);
if (!shouldBeVisible) {
ui->selectiveSyncStatus->hide();
_ui->selectiveSyncStatus->hide();
}
});
}
}
void AccountSettings::slotAccountAdded(AccountState *)
{
// if the theme is limited to single account, the button must hide if
// there is already one account.
int s = AccountManager::instance()->accounts().size();
if (s > 0 && !Theme::instance()->multiAccount()) {
_addAccountAction->setVisible(false);
} else {
_addAccountAction->setVisible(true);
}
}
void AccountSettings::slotDeleteAccount()
{
// Deleting the account potentially deletes 'this', so
@@ -1246,12 +1179,30 @@ bool AccountSettings::event(QEvent *e)
// Expand the folder automatically only if there's only one, see #4283
// The 2 is 1 folder + 1 'add folder' button
if (_model->rowCount() <= 2) {
ui->_folderList->setExpanded(_model->index(0, 0), true);
_ui->_folderList->setExpanded(_model->index(0, 0), true);
}
}
return QWidget::event(e);
}
void AccountSettings::slotStyleChanged()
{
customizeStyle();
// Notify the other widgets (Dark-/Light-Mode switching)
emit styleChanged();
}
void AccountSettings::customizeStyle()
{
QString msg = _ui->connectLabel->text();
Theme::replaceLinkColorStringBackgroundAware(msg);
_ui->connectLabel->setText(msg);
QColor color = palette().highlight().color();
_ui->quotaProgressBar->setStyleSheet(QString::fromLatin1(progressBarStyleC).arg(color.name()));
}
} // namespace OCC
#include "accountsettings.moc"

View File

@@ -63,11 +63,14 @@ signals:
void openFolderAlias(const QString &);
void showIssuesList(AccountState *account);
void requesetMnemonic();
void removeAccountFolders(AccountState *account);
void styleChanged();
public slots:
void slotOpenOC();
void slotUpdateQuota(qint64, qint64);
void slotAccountStateChanged();
void slotStyleChanged();
AccountState *accountsState() { return _accountState; }
@@ -87,7 +90,6 @@ protected slots:
void slotDeleteAccount();
void slotToggleSignInState();
void slotOpenAccountWizard();
void slotAccountAdded(AccountState *);
void refreshSelectiveSyncStatus();
void slotMarkSubfolderEncrypted(const FolderStatusModel::SubFolderInfo* folderInfo);
void slotMarkSubfolderDecrypted(const FolderStatusModel::SubFolderInfo* folderInfo);
@@ -97,8 +99,6 @@ protected slots:
void doExpand();
void slotLinkActivated(const QString &link);
void slotMenuBeforeShow();
// Encryption Related Stuff.
void slotShowMnemonic(const QString &mnemonic);
void slotNewMnemonicGenerated();
@@ -128,11 +128,12 @@ private:
bool event(QEvent *) override;
void createAccountToolbox();
void openIgnoredFilesDialog(const QString & absFolderPath);
void customizeStyle();
/// Returns the alias of the selected folder, empty string if none
QString selectedFolderAlias() const;
Ui::AccountSettings *ui;
Ui::AccountSettings *_ui;
FolderStatusModel *_model;
QUrl _OCUrl;

View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>582</width>
<width>581</width>
<height>557</height>
</rect>
</property>
@@ -184,13 +184,6 @@
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="_accountToolbox">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@@ -14,16 +14,24 @@
#include "accountstate.h"
#include "accountmanager.h"
#include "remotewipe.h"
#include "account.h"
#include "creds/abstractcredentials.h"
#include "creds/httpcredentials.h"
#include "logger.h"
#include "configfile.h"
#include "ocsnavigationappsjob.h"
#include <QSettings>
#include <QTimer>
#include <qfontmetrics.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QNetworkRequest>
#include <QBuffer>
namespace OCC {
Q_LOGGING_CATEGORY(lcAccountState, "nextcloud.gui.account.state", QtInfoMsg)
@@ -34,13 +42,14 @@ AccountState::AccountState(AccountPtr account)
, _state(AccountState::Disconnected)
, _connectionStatus(ConnectionValidator::Undefined)
, _waitingForNewCredentials(false)
, _notificationsEtagResponseHeader("*")
, _maintenanceToConnectedDelay(60000 + (qrand() % (4 * 60000))) // 1-5min delay
, _remoteWipe(new RemoteWipe(_account))
, _hasTalk(false)
{
qRegisterMetaType<AccountState *>("AccountState*");
connect(account.data(), &Account::invalidCredentials,
this, &AccountState::slotInvalidCredentials);
this, &AccountState::slotHandleRemoteWipeCheck);
connect(account.data(), &Account::credentialsFetched,
this, &AccountState::slotCredentialsFetched);
connect(account.data(), &Account::credentialsAsked,
@@ -67,6 +76,11 @@ AccountPtr AccountState::account() const
return _account;
}
bool AccountState::hasTalk() const
{
return _hasTalk;
}
AccountState::ConnectionStatus AccountState::connectionStatus() const
{
return _connectionStatus;
@@ -230,6 +244,9 @@ void AccountState::checkConnectivity()
// Use a small authed propfind as a minimal ping when we're
// already connected.
conValidator->checkAuthentication();
// Get the Apps available on the server.
fetchNavigationApps();
} else {
// Check the server and then the auth.
@@ -260,7 +277,7 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
// Come online gradually from 503 or maintenance mode
if (status == ConnectionValidator::Connected
&& (_connectionStatus == ConnectionValidator::ServiceUnavailable
|| _connectionStatus == ConnectionValidator::MaintenanceMode)) {
|| _connectionStatus == ConnectionValidator::MaintenanceMode)) {
if (!_timeSinceMaintenanceOver.isValid()) {
qCInfo(lcAccountState) << "AccountState reconnection: delaying for"
<< _maintenanceToConnectedDelay << "ms";
@@ -286,6 +303,9 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
case ConnectionValidator::Connected:
if (_state != Connected) {
setState(Connected);
// Get the Apps available on the server.
fetchNavigationApps();
}
break;
case ConnectionValidator::Undefined:
@@ -303,7 +323,7 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
break;
case ConnectionValidator::CredentialsWrong:
case ConnectionValidator::CredentialsNotReady:
slotInvalidCredentials();
handleInvalidCredentials();
break;
case ConnectionValidator::SslError:
setState(SignedOut);
@@ -322,7 +342,20 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
}
}
void AccountState::slotInvalidCredentials()
void AccountState::slotHandleRemoteWipeCheck()
{
// make sure it changes account state and icons
signOutByUi();
qCInfo(lcAccountState) << "Invalid credentials for" << _account->url().toString()
<< "checking for remote wipe request";
_waitingForNewCredentials = false;
setState(SignedOut);
}
void AccountState::handleInvalidCredentials()
{
if (isSignedOut() || _waitingForNewCredentials)
return;
@@ -343,6 +376,7 @@ void AccountState::slotInvalidCredentials()
account()->credentials()->askFromUser();
}
void AccountState::slotCredentialsFetched(AbstractCredentials *)
{
// Make a connection attempt, no matter whether the credentials are
@@ -384,4 +418,110 @@ std::unique_ptr<QSettings> AccountState::settings()
return s;
}
void AccountState::fetchNavigationApps(){
OcsNavigationAppsJob *job = new OcsNavigationAppsJob(_account);
job->addRawHeader("If-None-Match", navigationAppsEtagResponseHeader());
connect(job, &OcsNavigationAppsJob::appsJobFinished, this, &AccountState::slotNavigationAppsFetched);
connect(job, &OcsNavigationAppsJob::etagResponseHeaderReceived, this, &AccountState::slotEtagResponseHeaderReceived);
connect(job, &OcsNavigationAppsJob::ocsError, this, &AccountState::slotOcsError);
job->getNavigationApps();
}
void AccountState::slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode){
if(statusCode == 200){
qCDebug(lcAccountState) << "New navigation apps ETag Response Header received " << value;
setNavigationAppsEtagResponseHeader(value);
}
}
void AccountState::slotOcsError(int statusCode, const QString &message)
{
qCDebug(lcAccountState) << "Error " << statusCode << " while fetching new navigation apps: " << message;
}
void AccountState::slotNavigationAppsFetched(const QJsonDocument &reply, int statusCode)
{
if(_account){
if (statusCode == 304) {
qCWarning(lcAccountState) << "Status code " << statusCode << " Not Modified - No new navigation apps.";
} else {
_apps.clear();
_hasTalk = false;
if(!reply.isEmpty()){
auto element = reply.object().value("ocs").toObject().value("data");
auto navLinks = element.toArray();
if(navLinks.size() > 0){
foreach (const QJsonValue &value, navLinks) {
auto navLink = value.toObject();
AccountApp *app = new AccountApp(navLink.value("name").toString(), QUrl(navLink.value("href").toString()),
navLink.value("id").toString(), QUrl(navLink.value("icon").toString()));
_apps << app;
if(app->id() == QLatin1String("spreed"))
_hasTalk = true;
}
}
}
emit hasFetchedNavigationApps();
}
}
}
AccountAppList AccountState::appList() const
{
return _apps;
}
AccountApp* AccountState::findApp(const QString &appId) const
{
if(!appId.isEmpty()) {
foreach(AccountApp *app, appList()) {
if(app->id() == appId)
return app;
}
}
return nullptr;
}
/*-------------------------------------------------------------------------------------*/
AccountApp::AccountApp(const QString &name, const QUrl &url,
const QString &id, const QUrl &iconUrl,
QObject *parent)
: QObject(parent)
, _name(name)
, _url(url)
, _id(id)
, _iconUrl(iconUrl)
{
}
QString AccountApp::name() const
{
return _name;
}
QUrl AccountApp::url() const
{
return _url;
}
QString AccountApp::id() const
{
return _id;
}
QUrl AccountApp::iconUrl() const
{
return _iconUrl;
}
/*-------------------------------------------------------------------------------------*/
} // namespace OCC

View File

@@ -29,8 +29,11 @@ namespace OCC {
class AccountState;
class Account;
class AccountApp;
class RemoteWipe;
typedef QExplicitlySharedDataPointer<AccountState> AccountStatePtr;
typedef QList<AccountApp*> AccountAppList;
/**
* @brief Extra info about an ownCloud server account.
@@ -100,6 +103,11 @@ public:
bool isSignedOut() const;
bool hasTalk() const;
AccountAppList appList() const;
AccountApp* findApp(const QString &appId) const;
/** A user-triggered sign out which disconnects, stops syncs
* for the account and forgets the password. */
void signOutByUi();
@@ -150,6 +158,9 @@ public:
*/
void setNavigationAppsEtagResponseHeader(const QByteArray &value);
///Asks for user credentials
void handleInvalidCredentials();
public slots:
/// Triggers a ping to the server to update state and
/// connection status and errors.
@@ -157,23 +168,34 @@ public slots:
private:
void setState(State state);
void fetchNavigationApps();
signals:
void stateChanged(int state);
void isConnectedChanged();
void hasFetchedNavigationApps();
protected Q_SLOTS:
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList &errors);
void slotInvalidCredentials();
/// When client gets a 401 or 403 checks if server requested remote wipe
/// before asking for user credentials again
void slotHandleRemoteWipeCheck();
void slotCredentialsFetched(AbstractCredentials *creds);
void slotCredentialsAsked(AbstractCredentials *creds);
void slotNavigationAppsFetched(const QJsonDocument &reply, int statusCode);
void slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode);
void slotOcsError(int statusCode, const QString &message);
private:
AccountPtr _account;
State _state;
ConnectionStatus _connectionStatus;
QStringList _connectionErrors;
bool _waitingForNewCredentials;
bool _hasTalk;
QElapsedTimer _timeSinceLastETagCheck;
QPointer<ConnectionValidator> _connectionValidator;
QByteArray _notificationsEtagResponseHeader;
@@ -190,7 +212,41 @@ private:
* Milliseconds for which to delay reconnection after 503/maintenance.
*/
int _maintenanceToConnectedDelay;
/**
* Connects remote wipe check with the account
* the log out triggers the check (loads app password -> create request)
*/
RemoteWipe *_remoteWipe;
/**
* Holds the App names and URLs available on the server
*/
AccountAppList _apps;
};
class AccountApp : public QObject
{
Q_OBJECT
public:
AccountApp(const QString &name, const QUrl &url,
const QString &id, const QUrl &iconUrl,
QObject* parent = 0);
QString name() const;
QUrl url() const;
QString id() const;
QUrl iconUrl() const;
private:
QString _name;
QUrl _url;
QString _id;
QUrl _iconUrl;
};
}
Q_DECLARE_METATYPE(OCC::AccountState *)

View File

@@ -1,313 +0,0 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Olivier Goffart <ogoffart@woboq.com>
*
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "activityitemdelegate.h"
#include "folderstatusmodel.h"
#include "folderman.h"
#include "accountstate.h"
#include "activitydata.h"
#include <theme.h>
#include <account.h>
#include <QFileIconProvider>
#include <QPainter>
#include <QApplication>
namespace OCC {
int ActivityItemDelegate::_iconHeight = 0;
int ActivityItemDelegate::_margin = 0;
int ActivityItemDelegate::_primaryButtonWidth = 0;
int ActivityItemDelegate::_secondaryButtonWidth = 0;
int ActivityItemDelegate::_spaceBetweenButtons = 0;
int ActivityItemDelegate::_timeWidth = 0;
int ActivityItemDelegate::_buttonHeight = 0;
const QString ActivityItemDelegate::_remote_share("remote_share");
const QString ActivityItemDelegate::_call("call");
int ActivityItemDelegate::iconHeight()
{
if (_iconHeight == 0) {
QStyleOptionViewItem option;
QFont font = option.font;
QFontMetrics fm(font);
_iconHeight = qRound(fm.height() / 5.0 * 8.0);
}
return _iconHeight;
}
int ActivityItemDelegate::rowHeight()
{
if (_margin == 0) {
QStyleOptionViewItem opt;
QFont f = opt.font;
QFontMetrics fm(f);
_margin = fm.height() / 2;
#if defined(Q_OS_WIN)
_margin += 5;
#endif
}
return iconHeight() + 5 * _margin;
}
QSize ActivityItemDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex & /* index */) const
{
QFont font = option.font;
return QSize(0, rowHeight());
}
void ActivityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyledItemDelegate::paint(painter, option, index);
QFont font = option.font;
QFontMetrics fm(font);
int margin = fm.height() / 2.5;
painter->save();
int iconSize = 16;
int iconOffset = qRound(fm.height() / 4.0 * 7.0);
int offset = 4;
// get the data
Activity::Type activityType = qvariant_cast<Activity::Type>(index.data(ActionRole));
QIcon actionIcon = qvariant_cast<QIcon>(index.data(ActionIconRole));
QString objectType = qvariant_cast<QString>(index.data(ObjectTypeRole));
QString actionText = qvariant_cast<QString>(index.data(ActionTextRole));
QString messageText = qvariant_cast<QString>(index.data(MessageRole));
QList<QVariant> customList = index.data(ActionsLinksRole).toList();
QString timeText = qvariant_cast<QString>(index.data(PointInTimeRole));
bool accountOnline = qvariant_cast<bool>(index.data(AccountConnectedRole));
// activity/notification icons
QRect actionIconRect = option.rect;
actionIconRect.setLeft(option.rect.left() + iconOffset/3);
actionIconRect.setRight(option.rect.left() + iconOffset);
actionIconRect.setTop(option.rect.top() + qRound((option.rect.height() - 16)/3.0));
// subject text rect
QRect actionTextBox = actionIconRect;
int actionTextBoxWidth = fm.width(actionText);
actionTextBox.setTop(option.rect.top() + margin + offset/2);
actionTextBox.setHeight(fm.height());
actionTextBox.setLeft(actionIconRect.right() + margin);
actionTextBox.setRight(actionTextBox.left() + actionTextBoxWidth + margin);
// message text rect
QRect messageTextBox = actionTextBox;
int messageTextWidth = fm.width(messageText);
int messageTextTop = option.rect.top() + fm.height() + margin;
if(actionText.isEmpty()) messageTextTop = option.rect.top() + margin + offset/2;
messageTextBox.setTop(messageTextTop);
messageTextBox.setHeight(fm.height());
messageTextBox.setBottom(messageTextBox.top() + fm.height());
messageTextBox.setRight(messageTextBox.left() + messageTextWidth + margin);
if(messageText.isEmpty()){
messageTextBox.setHeight(0);
messageTextBox.setBottom(messageTextBox.top());
}
// time box rect
QRect timeBox = messageTextBox;
QString timeStr = tr("%1").arg(timeText);
int timeTextWidth = fm.width(timeStr);
int timeTop = option.rect.top() + fm.height() + fm.height() + margin + offset/2;
if(messageText.isEmpty() || actionText.isEmpty())
timeTop = option.rect.top() + fm.height() + margin;
timeBox.setTop(timeTop);
timeBox.setHeight(fm.height());
timeBox.setBottom(timeBox.top() + fm.height());
timeBox.setRight(timeBox.left() + timeTextWidth + margin);
// buttons - default values
int rightMargin = margin;
int leftMargin = margin * offset;
int top = option.rect.top() + margin;
int buttonSize = option.rect.height()/2;
int right = option.rect.right() - rightMargin;
int left = right - buttonSize;
QStyleOptionButton secondaryButton;
secondaryButton.rect = option.rect;
secondaryButton.features |= QStyleOptionButton::Flat;
secondaryButton.state |= QStyle::State_None;
secondaryButton.rect.setLeft(left);
secondaryButton.rect.setRight(right);
secondaryButton.rect.setTop(top + margin);
secondaryButton.rect.setHeight(iconSize);
QStyleOptionButton primaryButton;
primaryButton.rect = option.rect;
primaryButton.features |= QStyleOptionButton::DefaultButton;
primaryButton.state |= QStyle::State_Raised;
primaryButton.rect.setTop(top);
primaryButton.rect.setHeight(buttonSize);
right = secondaryButton.rect.left() - rightMargin;
left = secondaryButton.rect.left() - leftMargin;
primaryButton.rect.setRight(right);
if(activityType == Activity::Type::NotificationType){
// Secondary will be 'Dismiss' or '...' multiple options button
secondaryButton.icon = QIcon(QLatin1String(":/client/resources/close.svg"));
if(customList.size() > 1)
secondaryButton.icon = QIcon(QLatin1String(":/client/resources/more.svg"));
secondaryButton.iconSize = QSize(iconSize, iconSize);
// Primary button will be 'More Information' or 'Accept'
primaryButton.text = tr("More information");
if(objectType == _remote_share) primaryButton.text = tr("Accept");
if(objectType == _call) primaryButton.text = tr("Join");
primaryButton.rect.setLeft(left - margin * 2 - fm.width(primaryButton.text));
// save info to be able to filter mouse clicks
_buttonHeight = buttonSize;
_primaryButtonWidth = primaryButton.rect.size().width();
_secondaryButtonWidth = secondaryButton.rect.size().width();
_spaceBetweenButtons = secondaryButton.rect.left() - primaryButton.rect.right();
} else if(activityType == Activity::SyncResultType){
// Secondary will be 'open file manager' with the folder icon
secondaryButton.icon = QIcon(QLatin1String(":/client/resources/folder.svg"));
secondaryButton.iconSize = QSize(iconSize, iconSize);
// Primary button will be 'open browser'
primaryButton.text = tr("Open Browser");
primaryButton.rect.setLeft(left - margin * 2 - fm.width(primaryButton.text));
// save info to be able to filter mouse clicks
_buttonHeight = buttonSize;
_primaryButtonWidth = primaryButton.rect.size().width();
_secondaryButtonWidth = secondaryButton.rect.size().width();
_spaceBetweenButtons = secondaryButton.rect.left() - primaryButton.rect.right();
} else if(activityType == Activity::SyncFileItemType){
// Secondary will be 'open file manager' with the folder icon
secondaryButton.icon = QIcon(QLatin1String(":/client/resources/folder.svg"));
secondaryButton.iconSize = QSize(iconSize, iconSize);
// No primary button on this case
// Whatever error we have at this case it is local, there is no point on opening the browser
_primaryButtonWidth = 0;
_secondaryButtonWidth = secondaryButton.rect.size().width();
_spaceBetweenButtons = secondaryButton.rect.left() - primaryButton.rect.right();
} else {
_spaceBetweenButtons = leftMargin;
_primaryButtonWidth = 0;
_secondaryButtonWidth = 0;
}
// draw the icon
QPixmap pm = actionIcon.pixmap(iconSize, iconSize, QIcon::Normal);
painter->drawPixmap(QPoint(actionIconRect.left(), actionIconRect.top()), pm);
// change pen color if use is not online
QPalette p = option.palette;
if(!accountOnline)
p.setCurrentColorGroup(QPalette::Disabled);
// change pen color if the line is selected
if (option.state & QStyle::State_Selected)
painter->setPen(p.color(QPalette::HighlightedText));
else
painter->setPen(p.color(QPalette::Text));
// calculate space for text - use the max possible before using the elipses
int spaceLeftForText = option.rect.width() - (actionIconRect.width() + margin + rightMargin + leftMargin) -
(_primaryButtonWidth + _secondaryButtonWidth + _spaceBetweenButtons);
// draw the subject
const QString elidedAction = fm.elidedText(actionText, Qt::ElideRight, spaceLeftForText);
painter->drawText(actionTextBox, elidedAction);
// draw the buttons
if(activityType == Activity::Type::NotificationType || activityType == Activity::Type::SyncResultType)
QApplication::style()->drawControl(QStyle::CE_PushButton, &primaryButton, painter);
// Since they are errors on local syncing, there is nothing to do in the server
if(activityType != Activity::Type::ActivityType)
QApplication::style()->drawControl(QStyle::CE_PushButton, &secondaryButton, painter);
// draw the message
// change pen color for the message
if(!messageText.isEmpty()){
const QString elidedMessage = fm.elidedText(messageText, Qt::ElideRight, spaceLeftForText);
painter->drawText(messageTextBox, elidedMessage);
}
// change pen color for the time
if (option.state & QStyle::State_Selected)
painter->setPen(p.color(QPalette::Disabled, QPalette::HighlightedText));
else
painter->setPen(p.color(QPalette::Disabled, QPalette::Text));
// draw the time
const QString elidedTime = fm.elidedText(timeStr, Qt::ElideRight, spaceLeftForText);
painter->drawText(timeBox, elidedTime);
painter->restore();
}
bool ActivityItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
const QStyleOptionViewItem &option, const QModelIndex &index)
{
Activity::Type activityType = qvariant_cast<Activity::Type>(index.data(ActionRole));
if(activityType != Activity::Type::ActivityType){
if (event->type() == QEvent::MouseButtonRelease){
QMouseEvent *mouseEvent = (QMouseEvent*)event;
if(mouseEvent){
int mouseEventX = mouseEvent->x();
int mouseEventY = mouseEvent->y();
int buttonsWidth = _primaryButtonWidth + _spaceBetweenButtons + _secondaryButtonWidth;
int x = option.rect.left() + option.rect.width() - buttonsWidth - _timeWidth;
int y = option.rect.top();
// clickable area for ...
if (mouseEventX > x && mouseEventX < x + buttonsWidth){
if(mouseEventY > y && mouseEventY < y + _buttonHeight){
// ...primary button ('more information' or 'accept' on notifications or 'open browser' on errors)
if (mouseEventX > x && mouseEventX < x + _primaryButtonWidth){
emit primaryButtonClickedOnItemView(index);
// ...secondary button ('dismiss' on notifications or 'open file manager' on errors)
} else {
x += _primaryButtonWidth + _spaceBetweenButtons;
if (mouseEventX > x && mouseEventX < x + _secondaryButtonWidth)
emit secondaryButtonClickedOnItemView(index);
}
}
}
}
}
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
} // namespace OCC

View File

@@ -1,70 +0,0 @@
/*
* Copyright (C) by Klaas Freitag <freitag@kde.org>
* Copyright (C) by Olivier Goffart <ogoffart@woboq.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <QStyledItemDelegate>
#include <QMouseEvent>
class QMouseEvent;
namespace OCC {
/**
* @brief The ActivityItemDelegate class
* @ingroup gui
*/
class ActivityItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
enum datarole { ActionIconRole = Qt::UserRole + 1,
UserIconRole,
AccountRole,
ObjectTypeRole,
ActionsLinksRole,
ActionTextRole,
ActionRole,
MessageRole,
PathRole,
LinkRole,
PointInTimeRole,
AccountConnectedRole,
SyncFileStatusRole };
void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override;
QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const override;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
const QModelIndex &index) override;
static int rowHeight();
static int iconHeight();
signals:
void primaryButtonClickedOnItemView(const QModelIndex &index);
void secondaryButtonClickedOnItemView(const QModelIndex &index);
private:
static int _margin;
static int _iconHeight;
static int _primaryButtonWidth;
static int _secondaryButtonWidth;
static int _spaceBetweenButtons;
static int _timeWidth;
static int _buttonHeight;
static const QString _remote_share;
static const QString _call;
};
} // namespace OCC

View File

@@ -1,341 +0,0 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <QtCore>
#include <QAbstractListModel>
#include <QWidget>
#include <QIcon>
#include <QJsonObject>
#include <QJsonDocument>
#include "account.h"
#include "accountstate.h"
#include "accountmanager.h"
#include "folderman.h"
#include "accessmanager.h"
#include "activityitemdelegate.h"
#include "activitydata.h"
#include "activitylistmodel.h"
#include "theme.h"
#include "servernotificationhandler.h"
namespace OCC {
Q_LOGGING_CATEGORY(lcActivity, "nextcloud.gui.activity", QtInfoMsg)
ActivityListModel::ActivityListModel(AccountState *accountState, QWidget *parent)
: QAbstractListModel(parent)
, _accountState(accountState)
{
}
QVariant ActivityListModel::data(const QModelIndex &index, int role) const
{
Activity a;
// filter the get action here
// send only the text of the get action
// if there is more than one send the icon? the ...
if (!index.isValid())
return QVariant();
a = _finalList.at(index.row());
AccountStatePtr ast = AccountManager::instance()->account(a._accName);
if (!ast && _accountState != ast.data())
return QVariant();
QStringList list;
switch (role) {
case ActivityItemDelegate::PathRole:
if(!a._file.isEmpty()){
auto folder = FolderMan::instance()->folder(a._folder);
QString relPath(a._file);
if(folder) relPath.prepend(folder->remotePath());
list = FolderMan::instance()->findFileInLocalFolders(relPath, ast->account());
if (list.count() > 0) {
return QVariant(list.at(0));
}
// File does not exist anymore? Let's try to open its path
list = FolderMan::instance()->findFileInLocalFolders(QFileInfo(relPath).path(), ast->account());
if (list.count() > 0) {
return QVariant(list.at(0));
}
}
return QVariant();
break;
case ActivityItemDelegate::ActionsLinksRole:{
QList<QVariant> customList;
foreach (ActivityLink customItem, a._links) {
QVariant customVariant;
customVariant.setValue(customItem);
customList << customVariant;
}
return customList;
break;
}
case ActivityItemDelegate::ActionIconRole:
if(a._type == Activity::NotificationType){
QIcon cachedIcon = ServerNotificationHandler::iconCache.value(a._id);
if(!cachedIcon.isNull())
return cachedIcon;
else return QIcon(QLatin1String(":/client/resources/bell.svg"));
} else if(a._type == Activity::SyncResultType){
return QIcon(QLatin1String(":/client/resources/state-error.svg"));
} else if(a._type == Activity::SyncFileItemType){
if(a._status == SyncFileItem::NormalError
|| a._status == SyncFileItem::FatalError
|| a._status == SyncFileItem::DetailError
|| a._status == SyncFileItem::BlacklistedError) {
return QIcon(QLatin1String(":/client/resources/state-error.svg"));
} else if(a._status == SyncFileItem::SoftError
|| a._status == SyncFileItem::Conflict
|| a._status == SyncFileItem::Restoration
|| a._status == SyncFileItem::FileLocked){
return QIcon(QLatin1String(":/client/resources/state-warning.svg"));
} else if(a._status == SyncFileItem::FileIgnored){
return QIcon(QLatin1String(":/client/resources/state-info.svg"));
}
return QIcon(QLatin1String(":/client/resources/state-sync.svg"));
}
return QIcon(QLatin1String(":/client/resources/activity.png"));
break;
case ActivityItemDelegate::ObjectTypeRole:
return a._objectType;
break;
case ActivityItemDelegate::ActionRole:{
QVariant type;
type.setValue(a._type);
return type;
break;
}
case ActivityItemDelegate::ActionTextRole:
return a._subject;
break;
case ActivityItemDelegate::MessageRole:
return a._message;
break;
case ActivityItemDelegate::LinkRole:
return a._link;
break;
case ActivityItemDelegate::AccountRole:
return a._accName;
break;
case ActivityItemDelegate::PointInTimeRole:
return Utility::timeAgoInWords(a._dateTime);
break;
case ActivityItemDelegate::AccountConnectedRole:
return (ast && ast->isConnected());
break;
default:
return QVariant();
}
return QVariant();
}
int ActivityListModel::rowCount(const QModelIndex &) const
{
return _finalList.count();
}
bool ActivityListModel::canFetchMore(const QModelIndex &) const
{
// We need to be connected to be able to fetch more
if (_accountState && _accountState->isConnected()) {
// If the fetching is reported to be done or we are currently fetching we can't fetch more
if (!_doneFetching && !_currentlyFetching) {
return true;
}
}
return false;
}
void ActivityListModel::startFetchJob()
{
if (!_accountState->isConnected()) {
return;
}
JsonApiJob *job = new JsonApiJob(_accountState->account(), QLatin1String("ocs/v2.php/cloud/activity"), this);
QObject::connect(job, &JsonApiJob::jsonReceived,
this, &ActivityListModel::slotActivitiesReceived);
QUrlQuery params;
params.addQueryItem(QLatin1String("start"), QString::number(_currentItem));
params.addQueryItem(QLatin1String("count"), QString::number(100));
job->addQueryParams(params);
_currentlyFetching = true;
qCInfo(lcActivity) << "Start fetching activities for " << _accountState->account()->displayName();
job->start();
}
void ActivityListModel::slotActivitiesReceived(const QJsonDocument &json, int statusCode)
{
auto activities = json.object().value("ocs").toObject().value("data").toArray();
ActivityList list;
auto ast = _accountState;
if (!ast) {
return;
}
if (activities.size() == 0) {
_doneFetching = true;
}
_currentlyFetching = false;
_currentItem += activities.size();
foreach (auto activ, activities) {
auto json = activ.toObject();
Activity a;
a._type = Activity::ActivityType;
a._accName = ast->account()->displayName();
a._id = json.value("id").toInt();
a._subject = json.value("subject").toString();
a._message = json.value("message").toString();
a._file = json.value("file").toString();
a._link = QUrl(json.value("link").toString());
a._dateTime = QDateTime::fromString(json.value("date").toString(), Qt::ISODate);
list.append(a);
}
_activityLists.append(list);
emit activityJobStatusCode(statusCode);
combineActivityLists();
}
void ActivityListModel::addErrorToActivityList(Activity activity) {
qCInfo(lcActivity) << "Error successfully added to the notification list: " << activity._subject;
_notificationErrorsLists.prepend(activity);
combineActivityLists();
}
void ActivityListModel::addNotificationToActivityList(Activity activity) {
qCInfo(lcActivity) << "Notification successfully added to the notification list: " << activity._subject;
_notificationLists.prepend(activity);
combineActivityLists();
}
void ActivityListModel::clearNotifications() {
qCInfo(lcActivity) << "Clear the notifications";
_notificationLists.clear();
combineActivityLists();
}
void ActivityListModel::removeActivityFromActivityList(int row) {
Activity activity = _finalList.at(row);
removeActivityFromActivityList(activity);
combineActivityLists();
}
void ActivityListModel::addSyncFileItemToActivityList(Activity activity) {
qCInfo(lcActivity) << "Successfully added to the activity list: " << activity._subject;
_syncFileItemLists.prepend(activity);
combineActivityLists();
}
void ActivityListModel::removeActivityFromActivityList(Activity activity) {
qCInfo(lcActivity) << "Activity/Notification/Error successfully dismissed: " << activity._subject;
qCInfo(lcActivity) << "Trying to remove Activity/Notification/Error from view... ";
int index = -1;
if(activity._type == Activity::ActivityType){
index = _activityLists.indexOf(activity);
if(index != -1) _activityLists.removeAt(index);
} else if(activity._type == Activity::NotificationType){
index = _notificationLists.indexOf(activity);
if(index != -1) _notificationLists.removeAt(index);
} else {
index = _notificationErrorsLists.indexOf(activity);
if(index != -1) _notificationErrorsLists.removeAt(index);
}
if(index != -1){
qCInfo(lcActivity) << "Activity/Notification/Error successfully removed from the list.";
qCInfo(lcActivity) << "Updating Activity/Notification/Error view.";
combineActivityLists();
}
}
void ActivityListModel::combineActivityLists()
{
ActivityList resultList;
std::sort(_notificationErrorsLists.begin(), _notificationErrorsLists.end());
resultList.append(_notificationErrorsLists);
std::sort(_notificationLists.begin(), _notificationLists.end());
resultList.append(_notificationLists);
std::sort(_syncFileItemLists.begin(), _syncFileItemLists.end());
resultList.append(_syncFileItemLists);
std::sort(_activityLists.begin(), _activityLists.end());
resultList.append(_activityLists);
beginResetModel();
_finalList.clear();
endResetModel();
beginInsertRows(QModelIndex(), 0, resultList.count());
_finalList = resultList;
endInsertRows();
}
bool ActivityListModel::canFetchActivities() const {
return _accountState->isConnected() && _accountState->account()->capabilities().hasActivities();
}
void ActivityListModel::fetchMore(const QModelIndex &)
{
if (canFetchActivities()) {
startFetchJob();
} else {
_doneFetching = true;
combineActivityLists();
}
}
void ActivityListModel::slotRefreshActivity()
{
_activityLists.clear();
_doneFetching = false;
_currentItem = 0;
if (canFetchActivities()) {
startFetchJob();
} else {
_doneFetching = true;
combineActivityLists();
}
}
void ActivityListModel::slotRemoveAccount()
{
_finalList.clear();
_activityLists.clear();
_currentlyFetching = false;
_doneFetching = false;
_currentItem = 0;
}
}

View File

@@ -1,626 +0,0 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <QtGui>
#include <QtWidgets>
#include "activitylistmodel.h"
#include "activitywidget.h"
#include "syncresult.h"
#include "logger.h"
#include "theme.h"
#include "folderman.h"
#include "syncfileitem.h"
#include "folder.h"
#include "openfilemanager.h"
#include "owncloudpropagator.h"
#include "account.h"
#include "accountstate.h"
#include "accountmanager.h"
#include "activityitemdelegate.h"
#include "QProgressIndicator.h"
#include "notificationconfirmjob.h"
#include "servernotificationhandler.h"
#include "theme.h"
#include "ocsjob.h"
#include "configfile.h"
#include "guiutility.h"
#include "socketapi.h"
#include "ui_activitywidget.h"
#include "syncengine.h"
#include <climits>
// time span in milliseconds which has to be between two
// refreshes of the notifications
#define NOTIFICATION_REQUEST_FREE_PERIOD 15000
namespace OCC {
ActivityWidget::ActivityWidget(AccountState *accountState, QWidget *parent)
: QWidget(parent)
, _ui(new Ui::ActivityWidget)
, _notificationRequestsRunning(0)
, _accountState(accountState)
, _accept(tr("Accept"))
, _remote_share("remote_share")
{
_ui->setupUi(this);
// Adjust copyToClipboard() when making changes here!
#if defined(Q_OS_MAC)
_ui->_activityList->setMinimumWidth(400);
#endif
_model = new ActivityListModel(accountState, this);
ActivityItemDelegate *delegate = new ActivityItemDelegate;
delegate->setParent(this);
_ui->_activityList->setItemDelegate(delegate);
_ui->_activityList->setAlternatingRowColors(true);
_ui->_activityList->setModel(_model);
showLabels();
connect(_model, &ActivityListModel::activityJobStatusCode,
this, &ActivityWidget::slotAccountActivityStatus);
connect(_model, &QAbstractItemModel::rowsInserted, this, &ActivityWidget::rowsInserted);
connect(delegate, &ActivityItemDelegate::primaryButtonClickedOnItemView, this, &ActivityWidget::slotPrimaryButtonClickedOnListView);
connect(delegate, &ActivityItemDelegate::secondaryButtonClickedOnItemView, this, &ActivityWidget::slotSecondaryButtonClickedOnListView);
connect(_ui->_activityList, &QListView::activated, this, &ActivityWidget::slotOpenFile);
connect(ProgressDispatcher::instance(), &ProgressDispatcher::progressInfo,
this, &ActivityWidget::slotProgressInfo);
connect(ProgressDispatcher::instance(), &ProgressDispatcher::itemCompleted,
this, &ActivityWidget::slotItemCompleted);
connect(ProgressDispatcher::instance(), &ProgressDispatcher::syncError,
this, &ActivityWidget::addError);
_removeTimer.setInterval(1000);
}
ActivityWidget::~ActivityWidget()
{
delete _ui;
}
void ActivityWidget::slotProgressInfo(const QString &folder, const ProgressInfo &progress)
{
if (progress.status() == ProgressInfo::Reconcile) {
// Wipe all non-persistent entries - as well as the persistent ones
// in cases where a local discovery was done.
auto f = FolderMan::instance()->folder(folder);
if (!f)
return;
const auto &engine = f->syncEngine();
const auto style = engine.lastLocalDiscoveryStyle();
foreach (Activity activity, _model->errorsList()) {
if (activity._folder != folder){
continue;
}
if (style == LocalDiscoveryStyle::FilesystemOnly){
_model->removeActivityFromActivityList(activity);
continue;
}
if(activity._status == SyncFileItem::Conflict && !QFileInfo(f->path() + activity._file).exists()){
_model->removeActivityFromActivityList(activity);
continue;
}
if(activity._status == SyncFileItem::FileLocked && !QFileInfo(f->path() + activity._file).exists()){
_model->removeActivityFromActivityList(activity);
continue;
}
if(activity._status == SyncFileItem::FileIgnored && !QFileInfo(f->path() + activity._file).exists()){
_model->removeActivityFromActivityList(activity);
continue;
}
if(!QFileInfo(f->path() + activity._file).exists()){
_model->removeActivityFromActivityList(activity);
continue;
}
auto path = QFileInfo(activity._file).dir().path().toUtf8();
if (path == ".")
path.clear();
if(engine.shouldDiscoverLocally(path))
_model->removeActivityFromActivityList(activity);
}
}
if (progress.status() == ProgressInfo::Done) {
// We keep track very well of pending conflicts.
// Inform other components about them.
QStringList conflicts;
foreach (Activity activity, _model->errorsList()) {
if (activity._folder == folder
&& activity._status == SyncFileItem::Conflict) {
conflicts.append(activity._file);
}
}
emit ProgressDispatcher::instance()->folderConflicts(folder, conflicts);
}
}
void ActivityWidget::slotItemCompleted(const QString &folder, const SyncFileItemPtr &item){
auto folderInstance = FolderMan::instance()->folder(folder);
if (!folderInstance)
return;
// check if we are adding it to the right account and if it is useful information (protocol errors)
if(folderInstance->accountState() == _accountState){
qCWarning(lcActivity) << "Item " << item->_file << " retrieved resulted in " << item->_errorString;
Activity activity;
activity._type = Activity::SyncFileItemType; //client activity
activity._status = item->_status;
activity._dateTime = QDateTime::fromString(QDateTime::currentDateTime().toString(), Qt::ISODate);
activity._message = item->_originalFile;
activity._link = folderInstance->accountState()->account()->url();
activity._accName = folderInstance->accountState()->account()->displayName();
activity._file = item->_file;
activity._folder = folder;
if(item->_status == SyncFileItem::NoStatus || item->_status == SyncFileItem::Success){
qCWarning(lcActivity) << "Item " << item->_file << " retrieved successfully.";
activity._message.prepend(" ");
activity._message.prepend(tr("Synced"));
_model->addSyncFileItemToActivityList(activity);
} else {
qCWarning(lcActivity) << "Item " << item->_file << " retrieved resulted in error " << item->_errorString;
activity._subject = item->_errorString;
// add 'protocol error' to activity list
_model->addErrorToActivityList(activity);
}
}
}
void ActivityWidget::addError(const QString &folderAlias, const QString &message,
ErrorCategory category)
{
auto folderInstance = FolderMan::instance()->folder(folderAlias);
if (!folderInstance)
return;
if(folderInstance->accountState() == _accountState){
qCWarning(lcActivity) << "Item " << folderInstance->shortGuiLocalPath() << " retrieved resulted in " << message;
Activity activity;
activity._type = Activity::SyncResultType;
activity._status = SyncResult::Error;
activity._dateTime = QDateTime::fromString(QDateTime::currentDateTime().toString(), Qt::ISODate);
activity._subject = message;
activity._message = folderInstance->shortGuiLocalPath();
activity._link = folderInstance->shortGuiLocalPath();
activity._accName = folderInstance->accountState()->account()->displayName();
activity._folder = folderAlias;
if (category == ErrorCategory::InsufficientRemoteStorage) {
ActivityLink link;
link._label = tr("Retry all uploads");
link._link = folderInstance->path();
link._verb = "";
link._isPrimary = true;
activity._links.append(link);
}
// add 'other errors' to activity list
_model->addErrorToActivityList(activity);
}
}
void ActivityWidget::slotPrimaryButtonClickedOnListView(const QModelIndex &index){
QUrl link = qvariant_cast<QString>(index.data(ActivityItemDelegate::LinkRole));
QString objectType = index.data(ActivityItemDelegate::ObjectTypeRole).toString();
if(!link.isEmpty()){
qCWarning(lcActivity) << "Opening" << link.toString() << "in browser for Notification/Activity" << qvariant_cast<QString>(index.data(ActivityItemDelegate::ActionTextRole));
Utility::openBrowser(link, this);
} else if(objectType == _remote_share){
QVariant customItem = index.data(ActivityItemDelegate::ActionsLinksRole).toList().first();
ActivityLink actionLink = qvariant_cast<ActivityLink>(customItem);
if(actionLink._label == _accept){
qCWarning(lcActivity) << objectType << "action" << actionLink._label << "for" << qvariant_cast<QString>(index.data(ActivityItemDelegate::ActionTextRole));
const QString accountName = index.data(ActivityItemDelegate::AccountRole).toString();
slotSendNotificationRequest(accountName, actionLink._link, actionLink._verb, index.row());
} else {
qCWarning(lcActivity) << "Failed: " << objectType << "action" << actionLink._label << "for" << qvariant_cast<QString>(index.data(ActivityItemDelegate::ActionTextRole));
}
}
}
void ActivityWidget::slotSecondaryButtonClickedOnListView(const QModelIndex &index){
QList<QVariant> customList = index.data(ActivityItemDelegate::ActionsLinksRole).toList();
QString objectType = index.data(ActivityItemDelegate::ObjectTypeRole).toString();
QList<ActivityLink> actionLinks;
foreach(QVariant customItem, customList){
actionLinks << qvariant_cast<ActivityLink>(customItem);
}
if(objectType == _remote_share && actionLinks.first()._label == _accept)
actionLinks.removeFirst();
if(qvariant_cast<Activity::Type>(index.data(ActivityItemDelegate::ActionRole)) == Activity::Type::NotificationType){
const QString accountName = index.data(ActivityItemDelegate::AccountRole).toString();
if(actionLinks.size() == 1){
if(actionLinks.at(0)._verb == "DELETE"){
qCWarning(lcActivity) << "Dismissing Notification/Activity" << qvariant_cast<QString>(index.data(ActivityItemDelegate::ActionTextRole));
slotSendNotificationRequest(index.data(ActivityItemDelegate::AccountRole).toString(), actionLinks.at(0)._link, actionLinks.at(0)._verb, index.row());
}
} else if(actionLinks.size() > 1){
QMenu menu;
qCWarning(lcActivity) << "Displaying menu for Notification/Activity" << qvariant_cast<QString>(index.data(ActivityItemDelegate::ActionTextRole));
foreach (ActivityLink actionLink, actionLinks) {
QAction *menuAction = new QAction(actionLink._label, &menu);
connect(menuAction, &QAction::triggered, this, [this, index, accountName, actionLink] {
this->slotSendNotificationRequest(accountName, actionLink._link, actionLink._verb, index.row());
});
menu.addAction(menuAction);
}
menu.exec(QCursor::pos());
}
}
Activity::Type activityType = qvariant_cast<Activity::Type>(index.data(ActivityItemDelegate::ActionRole));
if(activityType == Activity::Type::SyncFileItemType || activityType == Activity::Type::SyncResultType)
slotOpenFile(index);
}
void ActivityWidget::slotNotificationRequestFinished(int statusCode)
{
int row = sender()->property("activityRow").toInt();
// the ocs API returns stat code 100 or 200 inside the xml if it succeeded.
if (statusCode != OCS_SUCCESS_STATUS_CODE && statusCode != OCS_SUCCESS_STATUS_CODE_V2) {
qCWarning(lcActivity) << "Notification Request to Server failed, leave notification visible.";
} else {
// to do use the model to rebuild the list or remove the item
qCWarning(lcActivity) << "Notification Request to Server successed, rebuilding list.";
_model->removeActivityFromActivityList(row);
}
}
void ActivityWidget::slotRefreshActivities()
{
_model->slotRefreshActivity();
}
void ActivityWidget::slotRefreshNotifications()
{
// start a server notification handler if no notification requests
// are running
if (_notificationRequestsRunning == 0) {
ServerNotificationHandler *snh = new ServerNotificationHandler(_accountState);
connect(snh, &ServerNotificationHandler::newNotificationList,
this, &ActivityWidget::slotBuildNotificationDisplay);
snh->slotFetchNotifications();
} else {
qCWarning(lcActivity) << "Notification request counter not zero.";
}
}
void ActivityWidget::slotRemoveAccount()
{
_model->slotRemoveAccount();
}
void ActivityWidget::showLabels()
{
_ui->_bottomLabel->hide(); // hide whatever was there before
QString t("");
QSetIterator<QString> i(_accountsWithoutActivities);
while (i.hasNext()) {
t.append(tr("<br/>Account %1 does not have activities enabled.").arg(i.next()));
}
if(!t.isEmpty()){
_ui->_bottomLabel->setTextFormat(Qt::RichText);
_ui->_bottomLabel->setText(t);
_ui->_bottomLabel->show();
}
}
void ActivityWidget::slotAccountActivityStatus(int statusCode)
{
if (!(_accountState && _accountState->account())) {
return;
}
if (statusCode == 999) {
_accountsWithoutActivities.insert(_accountState->account()->displayName());
} else {
_accountsWithoutActivities.remove(_accountState->account()->displayName());
}
checkActivityWidgetVisibility();
showLabels();
}
// FIXME: Reused from protocol widget. Move over to utilities.
QString ActivityWidget::timeString(QDateTime dt, QLocale::FormatType format) const
{
const QLocale loc = QLocale::system();
QString dtFormat = loc.dateTimeFormat(format);
static const QRegExp re("(HH|H|hh|h):mm(?!:s)");
dtFormat.replace(re, "\\1:mm:ss");
return loc.toString(dt, dtFormat);
}
void ActivityWidget::storeActivityList(QTextStream &ts)
{
ActivityList activities = _model->activityList();
foreach (Activity activity, activities) {
ts << right
// account name
<< qSetFieldWidth(activity._accName.length())
<< activity._accName
// separator
<< qSetFieldWidth(2) << " - "
// date and time
<< qSetFieldWidth(activity._dateTime.toString().length())
<< activity._dateTime.toString()
// separator
<< qSetFieldWidth(2) << " - "
// fileq
<< qSetFieldWidth(activity._file.length())
<< activity._file
// separator
<< qSetFieldWidth(2) << " - "
// subject
<< qSetFieldWidth(activity._subject.length())
<< activity._subject
// separator
<< qSetFieldWidth(2) << " - "
// message
<< qSetFieldWidth(activity._message.length())
<< activity._message
<< endl;
}
}
void ActivityWidget::checkActivityWidgetVisibility()
{
int accountCount = AccountManager::instance()->accounts().count();
bool hasAccountsWithActivity =
_accountsWithoutActivities.count() != accountCount;
_ui->_activityList->setVisible(hasAccountsWithActivity);
emit hideActivityTab(!hasAccountsWithActivity);
}
void ActivityWidget::slotOpenFile(QModelIndex indx)
{
qCDebug(lcActivity) << indx.isValid() << indx.data(ActivityItemDelegate::PathRole).toString() << QFile::exists(indx.data(ActivityItemDelegate::PathRole).toString());
if (indx.isValid()) {
QString fullPath = indx.data(ActivityItemDelegate::PathRole).toString();
if(!fullPath.isEmpty()){
if (QFile::exists(fullPath)) {
showInFileManager(fullPath);
}
}
}
}
// GUI: Display the notifications.
// All notifications in list are coming from the same account
// but in the _widgetForNotifId hash widgets for all accounts are
// collected.
void ActivityWidget::slotBuildNotificationDisplay(const ActivityList &list)
{
// Whether a new notification was added to the list
bool newNotificationShown = false;
_model->clearNotifications();
foreach (auto activity, list) {
if (_blacklistedNotifications.contains(activity)) {
qCInfo(lcActivity) << "Activity in blacklist, skip";
continue;
}
// handle gui logs. In order to NOT annoy the user with every fetching of the
// notifications the notification id is stored in a Set. Only if an id
// is not in the set, it qualifies for guiLog.
// Important: The _guiLoggedNotifications set must be wiped regularly which
// will repeat the gui log.
// after one hour, clear the gui log notification store
if (_guiLogTimer.elapsed() > 60 * 60 * 1000) {
_guiLoggedNotifications.clear();
}
if (!_guiLoggedNotifications.contains(activity._id)) {
newNotificationShown = true;
_guiLoggedNotifications.insert(activity._id);
// Assemble a tray notification for the NEW notification
ConfigFile cfg;
if(cfg.optionalServerNotifications()){
if(AccountManager::instance()->accounts().count() == 1){
emit guiLog(activity._subject, "");
} else {
emit guiLog(activity._subject, activity._accName);
}
}
}
_model->addNotificationToActivityList(activity);
}
// restart the gui log timer now that we show a new notification
if(newNotificationShown) {
_guiLogTimer.start();
}
}
void ActivityWidget::slotSendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row)
{
qCInfo(lcActivity) << "Server Notification Request " << verb << link << "on account" << accountName;
const QStringList validVerbs = QStringList() << "GET"
<< "PUT"
<< "POST"
<< "DELETE";
if (validVerbs.contains(verb)) {
AccountStatePtr acc = AccountManager::instance()->account(accountName);
if (acc) {
NotificationConfirmJob *job = new NotificationConfirmJob(acc->account());
QUrl l(link);
job->setLinkAndVerb(l, verb);
job->setProperty("activityRow", QVariant::fromValue(row));
connect(job, &AbstractNetworkJob::networkError,
this, &ActivityWidget::slotNotifyNetworkError);
connect(job, &NotificationConfirmJob::jobFinished,
this, &ActivityWidget::slotNotifyServerFinished);
job->start();
// count the number of running notification requests. If this member var
// is larger than zero, no new fetching of notifications is started
_notificationRequestsRunning++;
}
} else {
qCWarning(lcActivity) << "Notification Links: Invalid verb:" << verb;
}
}
void ActivityWidget::endNotificationRequest(int replyCode)
{
_notificationRequestsRunning--;
slotNotificationRequestFinished(replyCode);
}
void ActivityWidget::slotNotifyNetworkError(QNetworkReply *reply)
{
NotificationConfirmJob *job = qobject_cast<NotificationConfirmJob *>(sender());
if (!job) {
return;
}
int resultCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
endNotificationRequest(resultCode);
qCWarning(lcActivity) << "Server notify job failed with code " << resultCode;
}
void ActivityWidget::slotNotifyServerFinished(const QString &reply, int replyCode)
{
NotificationConfirmJob *job = qobject_cast<NotificationConfirmJob *>(sender());
if (!job) {
return;
}
endNotificationRequest(replyCode);
qCInfo(lcActivity) << "Server Notification reply code" << replyCode << reply;
}
/* ==================================================================== */
ActivitySettings::ActivitySettings(AccountState *accountState, QWidget *parent)
: QWidget(parent)
, _accountState(accountState)
{
_vbox = new QVBoxLayout(this);
setLayout(_vbox);
_activityWidget = new ActivityWidget(_accountState, this);
_vbox->insertWidget(1, _activityWidget);
connect(_activityWidget, &ActivityWidget::guiLog, this, &ActivitySettings::guiLog);
connect(&_notificationCheckTimer, &QTimer::timeout,
this, &ActivitySettings::slotRegularNotificationCheck);
// Add a progress indicator to spin if the acitivity list is updated.
_progressIndicator = new QProgressIndicator(this);
// connect a model signal to stop the animation
connect(_activityWidget, &ActivityWidget::rowsInserted, _progressIndicator, &QProgressIndicator::stopAnimation);
connect(_activityWidget, &ActivityWidget::rowsInserted, this, &ActivitySettings::slotDisplayActivities);
}
void ActivitySettings::slotDisplayActivities(){
_vbox->removeWidget(_progressIndicator);
}
void ActivitySettings::setNotificationRefreshInterval(std::chrono::milliseconds interval)
{
qCDebug(lcActivity) << "Starting Notification refresh timer with " << interval.count() / 1000 << " sec interval";
_notificationCheckTimer.start(interval.count());
}
void ActivitySettings::slotRemoveAccount()
{
_activityWidget->slotRemoveAccount();
}
void ActivitySettings::slotRefresh()
{
// QElapsedTimer isn't actually constructed as invalid.
if (!_timeSinceLastCheck.contains(_accountState)) {
_timeSinceLastCheck[_accountState].invalidate();
}
QElapsedTimer &timer = _timeSinceLastCheck[_accountState];
// Fetch Activities only if visible and if last check is longer than 15 secs ago
if (timer.isValid() && timer.elapsed() < NOTIFICATION_REQUEST_FREE_PERIOD) {
qCDebug(lcActivity) << "Do not check as last check is only secs ago: " << timer.elapsed() / 1000;
return;
}
if (_accountState && _accountState->isConnected()) {
if (isVisible() || !timer.isValid()) {
_vbox->insertWidget(0, _progressIndicator);
_vbox->setAlignment(_progressIndicator, Qt::AlignHCenter);
_progressIndicator->startAnimation();
_activityWidget->slotRefreshActivities();
}
_activityWidget->slotRefreshNotifications();
timer.start();
}
}
void ActivitySettings::slotRegularNotificationCheck()
{
slotRefresh();
}
bool ActivitySettings::event(QEvent *e)
{
if (e->type() == QEvent::Show) {
slotRefresh();
}
return QWidget::event(e);
}
ActivitySettings::~ActivitySettings()
{
}
}

View File

@@ -1,160 +0,0 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef ACTIVITYWIDGET_H
#define ACTIVITYWIDGET_H
#include <QDialog>
#include <QDateTime>
#include <QLocale>
#include <QAbstractListModel>
#include <chrono>
#include "progressdispatcher.h"
#include "owncloudgui.h"
#include "account.h"
#include "activitydata.h"
#include "accountmanager.h"
#include "ui_activitywidget.h"
class QPushButton;
class QProgressIndicator;
namespace OCC {
class Account;
class AccountStatusPtr;
class JsonApiJob;
class ActivityListModel;
namespace Ui {
class ActivityWidget;
}
class Application;
/**
* @brief The ActivityWidget class
* @ingroup gui
*
* The list widget to display the activities, contained in the
* subsequent ActivitySettings widget.
*/
class ActivityWidget : public QWidget
{
Q_OBJECT
public:
explicit ActivityWidget(AccountState *accountState, QWidget *parent = nullptr);
~ActivityWidget();
QSize sizeHint() const override { return ownCloudGui::settingsDialogSize(); }
void storeActivityList(QTextStream &ts);
/**
* Adjusts the activity tab's and some widgets' visibility
*
* Based on whether activities are enabled and whether notifications are
* available.
*/
void checkActivityWidgetVisibility();
public slots:
void slotOpenFile(QModelIndex indx);
void slotRefreshActivities();
void slotRefreshNotifications();
void slotRemoveAccount();
void slotAccountActivityStatus(int statusCode);
void addError(const QString &folderAlias, const QString &message, ErrorCategory category);
void slotProgressInfo(const QString &folder, const ProgressInfo &progress);
void slotItemCompleted(const QString &folder, const SyncFileItemPtr &item);
signals:
void guiLog(const QString &, const QString &);
void rowsInserted();
void hideActivityTab(bool);
void sendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row);
private slots:
void slotBuildNotificationDisplay(const ActivityList &list);
void slotSendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row);
void slotNotifyNetworkError(QNetworkReply *);
void slotNotifyServerFinished(const QString &reply, int replyCode);
void endNotificationRequest(int replyCode);
void slotNotificationRequestFinished(int statusCode);
void slotPrimaryButtonClickedOnListView(const QModelIndex &index);
void slotSecondaryButtonClickedOnListView(const QModelIndex &index);
private:
void showLabels();
QString timeString(QDateTime dt, QLocale::FormatType format) const;
Ui::ActivityWidget *_ui;
QSet<QString> _accountsWithoutActivities;
QElapsedTimer _guiLogTimer;
QSet<int> _guiLoggedNotifications;
ActivityList _blacklistedNotifications;
QTimer _removeTimer;
// number of currently running notification requests. If non zero,
// no query for notifications is started.
int _notificationRequestsRunning;
ActivityListModel *_model;
AccountState *_accountState;
const QString _accept;
const QString _remote_share;
};
/**
* @brief The ActivitySettings class
* @ingroup gui
*
* Implements a tab for the settings dialog, displaying the three activity
* lists.
*/
class ActivitySettings : public QWidget
{
Q_OBJECT
public:
explicit ActivitySettings(AccountState *accountState, QWidget *parent = nullptr);
~ActivitySettings();
QSize sizeHint() const override { return ownCloudGui::settingsDialogSize(); }
public slots:
void slotRefresh();
void slotRemoveAccount();
void setNotificationRefreshInterval(std::chrono::milliseconds interval);
private slots:
void slotRegularNotificationCheck();
void slotDisplayActivities();
signals:
void guiLog(const QString &, const QString &);
private:
bool event(QEvent *e) override;
ActivityWidget *_activityWidget;
QProgressIndicator *_progressIndicator;
QVBoxLayout *_vbox;
QTimer _notificationCheckTimer;
QHash<AccountState *, QElapsedTimer> _timeSinceLastCheck;
AccountState *_accountState;
};
}
#endif // ActivityWIDGET_H

View File

@@ -1,98 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OCC::ActivityWidget</class>
<widget class="QWidget" name="OCC::ActivityWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>652</width>
<height>556</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListView" name="_activityList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="defaultDropAction">
<enum>Qt::IgnoreAction</enum>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="viewMode">
<enum>QListView::ListMode</enum>
</property>
<property name="modelColumn">
<number>0</number>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="_bottomLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">TextLabel</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>_activityList</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -52,6 +52,7 @@
#include <QMenu>
#include <QMessageBox>
#include <QDesktopServices>
#include <QGuiApplication>
class QSocket;
@@ -122,6 +123,15 @@ Application::Application(int &argc, char **argv)
// TODO: Can't set this without breaking current config paths
// setOrganizationName(QLatin1String(APPLICATION_VENDOR));
setOrganizationDomain(QLatin1String(APPLICATION_REV_DOMAIN));
// setDesktopFilename to provide wayland compatibility (in general: conformance with naming standards)
// but only on Qt >= 5.7, where setDesktopFilename was introduced
#if (QT_VERSION >= 0x050700)
QString desktopFileName = QString(QLatin1String(LINUX_APPLICATION_ID)
+ QLatin1String(".desktop"));
setDesktopFileName(desktopFileName);
#endif
setApplicationName(_theme->appName());
setWindowIcon(_theme->applicationIcon());
setAttribute(Qt::AA_UseHighDpiPixmaps, true);
@@ -253,6 +263,11 @@ Application::Application(int &argc, char **argv)
// Cleanup at Quit.
connect(this, &QCoreApplication::aboutToQuit, this, &Application::slotCleanup);
// Allow other classes to hook into isShowingSettingsDialog() signals (re-auth widgets, for example)
connect(_gui.data(), &ownCloudGui::isShowingSettingsDialog, this, &Application::slotGuiIsShowingSettings);
_gui->createTray();
}
Application::~Application()
@@ -264,6 +279,8 @@ Application::~Application()
}
// Remove the account from the account manager so it can be deleted.
disconnect(AccountManager::instance(), &AccountManager::accountRemoved,
this, &Application::slotAccountStateRemoved);
AccountManager::instance()->shutdown();
}
@@ -375,7 +392,7 @@ void Application::slotownCloudWizardDone(int res)
Utility::setLaunchOnStartup(_theme->appName(), _theme->appNameGUI(), true);
}
_gui->slotShowSettings();
Systray::instance()->showWindow();
}
}
@@ -643,5 +660,9 @@ void Application::showSettingsDialog()
_gui->slotShowSettings();
}
void Application::slotGuiIsShowingSettings()
{
emit isShowingSettingsDialog();
}
} // namespace OCC

View File

@@ -82,6 +82,7 @@ protected:
signals:
void folderRemoved();
void folderStateChanged(Folder *);
void isShowingSettingsDialog();
protected slots:
void slotParseMessage(const QString &, QObject *);
@@ -91,6 +92,7 @@ protected slots:
void slotAccountStateAdded(AccountState *accountState);
void slotAccountStateRemoved(AccountState *accountState);
void slotSystemOnlineConfigurationChanged(QNetworkConfiguration);
void slotGuiIsShowingSettings();
private:
void setHelp();

View File

@@ -249,6 +249,11 @@ void ConnectionValidator::slotCapabilitiesRecieved(const QJsonDocument &json)
return;
}
// Check for the directEditing capability
QUrl directEditingURL = QUrl(caps["files"].toObject()["directEditing"].toObject()["url"].toString());
QString directEditingETag = caps["files"].toObject()["directEditing"].toObject()["etag"].toString();
_account->fetchDirectEditors(directEditingURL, directEditingETag);
fetchUser();
}

View File

@@ -14,10 +14,12 @@
*/
#include <QDesktopServices>
#include <QApplication>
#include <QClipboard>
#include <QTimer>
#include <QBuffer>
#include "account.h"
#include "creds/flow2auth.h"
#include "flow2auth.h"
#include <QJsonObject>
#include <QJsonDocument>
#include "theme.h"
@@ -28,6 +30,17 @@ namespace OCC {
Q_LOGGING_CATEGORY(lcFlow2auth, "nextcloud.sync.credentials.flow2auth", QtInfoMsg)
Flow2Auth::Flow2Auth(Account *account, QObject *parent)
: QObject(parent)
, _account(account)
, _isBusy(false)
, _hasToken(false)
{
_pollTimer.setInterval(1000);
QObject::connect(&_pollTimer, &QTimer::timeout, this, &Flow2Auth::slotPollTimerTimeout);
}
Flow2Auth::~Flow2Auth()
{
}
@@ -47,22 +60,46 @@ QUrl Flow2Auth::authorisationLink() const
void Flow2Auth::openBrowser()
{
_pollTimer.stop();
fetchNewToken(TokenAction::actionOpenBrowser);
}
void Flow2Auth::copyLinkToClipboard()
{
fetchNewToken(TokenAction::actionCopyLinkToClipboard);
}
void Flow2Auth::fetchNewToken(const TokenAction action)
{
if(_isBusy)
return;
_isBusy = true;
_hasToken = false;
emit statusChanged(PollStatus::statusFetchToken, 0);
// Step 1: Initiate a login, do an anonymous POST request
QUrl url = Utility::concatUrlPath(_account->url().toString(), QLatin1String("/index.php/login/v2"));
auto job = _account->sendRequest("POST", url);
// add 'Content-Length: 0' header (see https://github.com/nextcloud/desktop/issues/1473)
QNetworkRequest req;
req.setHeader(QNetworkRequest::ContentLengthHeader, "0");
auto job = _account->sendRequest("POST", url, req);
job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec()));
QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this](QNetworkReply *reply) {
QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this, action](QNetworkReply *reply) {
auto jsonData = reply->readAll();
QJsonParseError jsonParseError;
QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object();
QString pollToken, pollEndpoint, loginUrl;
QString pollToken = json.value("poll").toObject().value("token").toString();
QString pollEndpoint = json.value("poll").toObject().value("endpoint").toString();
QUrl loginUrl = json["login"].toString();
if (reply->error() == QNetworkReply::NoError && jsonParseError.error == QJsonParseError::NoError
&& !json.isEmpty()) {
pollToken = json.value("poll").toObject().value("token").toString();
pollEndpoint = json.value("poll").toObject().value("endpoint").toString();
loginUrl = json["login"].toString();
}
if (reply->error() != QNetworkReply::NoError || jsonParseError.error != QJsonParseError::NoError
|| json.isEmpty() || pollToken.isEmpty() || pollEndpoint.isEmpty() || loginUrl.isEmpty()) {
@@ -81,7 +118,9 @@ void Flow2Auth::openBrowser()
errorReason = tr("The reply from the server did not contain all expected fields");
}
qCWarning(lcFlow2auth) << "Error when getting the loginUrl" << json << errorReason;
emit result(Error);
emit result(Error, errorReason);
_pollTimer.stop();
_isBusy = false;
return;
}
@@ -95,23 +134,50 @@ void Flow2Auth::openBrowser()
ConfigFile cfg;
std::chrono::milliseconds polltime = cfg.remotePollInterval();
qCInfo(lcFlow2auth) << "setting remote poll timer interval to" << polltime.count() << "msec";
_pollTimer.setInterval(polltime.count());
QObject::connect(&_pollTimer, &QTimer::timeout, this, &Flow2Auth::slotPollTimerTimeout);
_pollTimer.start();
_secondsInterval = (polltime.count() / 1000);
_secondsLeft = _secondsInterval;
emit statusChanged(PollStatus::statusPollCountdown, _secondsLeft);
// Try to open Browser
if (!QDesktopServices::openUrl(authorisationLink())) {
// We cannot open the browser, then we claim we don't support Flow2Auth.
// Our UI callee should ask the user to copy and open the link.
emit result(NotSupported, QString());
if(!_pollTimer.isActive()) {
_pollTimer.start();
}
switch(action)
{
case actionOpenBrowser:
// Try to open Browser
if (!QDesktopServices::openUrl(authorisationLink())) {
// We cannot open the browser, then we claim we don't support Flow2Auth.
// Our UI callee will ask the user to copy and open the link.
emit result(NotSupported);
}
break;
case actionCopyLinkToClipboard:
QApplication::clipboard()->setText(authorisationLink().toString(QUrl::FullyEncoded));
emit statusChanged(PollStatus::statusCopyLinkToClipboard, 0);
break;
}
_isBusy = false;
_hasToken = true;
});
}
void Flow2Auth::slotPollTimerTimeout()
{
_pollTimer.stop();
if(_isBusy || !_hasToken)
return;
_isBusy = true;
_secondsLeft--;
if(_secondsLeft > 0) {
emit statusChanged(PollStatus::statusPollCountdown, _secondsLeft);
_isBusy = false;
return;
}
emit statusChanged(PollStatus::statusPollNow, 0);
// Step 2: Poll
QNetworkRequest req;
@@ -128,10 +194,15 @@ void Flow2Auth::slotPollTimerTimeout()
auto jsonData = reply->readAll();
QJsonParseError jsonParseError;
QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object();
QUrl serverUrl;
QString loginName, appPassword;
QUrl serverUrl = json["server"].toString();
QString loginName = json["loginName"].toString();
QString appPassword = json["appPassword"].toString();
if (reply->error() == QNetworkReply::NoError && jsonParseError.error == QJsonParseError::NoError
&& !json.isEmpty()) {
serverUrl = json["server"].toString();
loginName = json["loginName"].toString();
appPassword = json["appPassword"].toString();
}
if (reply->error() != QNetworkReply::NoError || jsonParseError.error != QJsonParseError::NoError
|| json.isEmpty() || serverUrl.isEmpty() || loginName.isEmpty() || appPassword.isEmpty()) {
@@ -151,26 +222,50 @@ void Flow2Auth::slotPollTimerTimeout()
}
qCDebug(lcFlow2auth) << "Error when polling for the appPassword" << json << errorReason;
// We get a 404 until authentication is done, so don't show this error in the GUI.
if(reply->error() != QNetworkReply::ContentNotFoundError)
emit result(Error, errorReason);
// Forget sensitive data
appPassword.clear();
loginName.clear();
// Failed: poll again
_pollTimer.start();
_secondsLeft = _secondsInterval;
_isBusy = false;
return;
}
_pollTimer.stop();
// Success
qCInfo(lcFlow2auth) << "Success getting the appPassword for user: " << loginName << ", server: " << serverUrl.toString();
_account->setUrl(serverUrl);
emit result(LoggedIn, loginName, appPassword);
emit result(LoggedIn, QString(), loginName, appPassword);
// Forget sensitive data
appPassword.clear();
loginName.clear();
_loginUrl.clear();
_pollToken.clear();
_pollEndpoint.clear();
_isBusy = false;
_hasToken = false;
});
}
void Flow2Auth::slotPollNow()
{
// poll now if we're not already doing so
if(_isBusy || !_hasToken)
return;
_secondsLeft = 1;
slotPollTimerTimeout();
}
} // namespace OCC

View File

@@ -25,17 +25,23 @@ namespace OCC {
* Job that does the authorization, grants and fetches the access token via Login Flow v2
*
* See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#login-flow-v2
*
*/
class Flow2Auth : public QObject
{
Q_OBJECT
public:
Flow2Auth(Account *account, QObject *parent)
: QObject(parent)
, _account(account)
{
}
enum TokenAction {
actionOpenBrowser = 1,
actionCopyLinkToClipboard
};
enum PollStatus {
statusPollCountdown = 1,
statusPollNow,
statusFetchToken,
statusCopyLinkToClipboard
};
Flow2Auth(Account *account, QObject *parent);
~Flow2Auth();
enum Result { NotSupported,
@@ -44,6 +50,7 @@ public:
Q_ENUM(Result);
void start();
void openBrowser();
void copyLinkToClipboard();
QUrl authorisationLink() const;
signals:
@@ -51,18 +58,29 @@ signals:
* The state has changed.
* when logged in, appPassword has the value of the app password.
*/
void result(Flow2Auth::Result result, const QString &user = QString(), const QString &appPassword = QString());
void result(Flow2Auth::Result result, const QString &errorString = QString(),
const QString &user = QString(), const QString &appPassword = QString());
void statusChanged(const PollStatus status, int secondsLeft);
public slots:
void slotPollNow();
private slots:
void slotPollTimerTimeout();
private:
void fetchNewToken(const TokenAction action);
Account *_account;
QUrl _loginUrl;
QString _pollToken;
QString _pollEndpoint;
QTimer _pollTimer;
int _secondsLeft;
int _secondsInterval;
bool _isBusy;
bool _hasToken;
};
} // namespace OCC

View File

@@ -0,0 +1,221 @@
/*
* Copyright (C) by Michael Schuster <michael@nextcloud.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "account.h"
#include "keychainchunk.h"
#include "theme.h"
#include "networkjobs.h"
#include "configfile.h"
#include "creds/abstractcredentials.h"
using namespace QKeychain;
namespace OCC {
Q_LOGGING_CATEGORY(lcKeychainChunk, "nextcloud.sync.credentials.keychainchunk", QtInfoMsg)
namespace KeychainChunk {
#if defined(KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK)
static void addSettingsToJob(Account *account, QKeychain::Job *job)
{
Q_UNUSED(account)
auto settings = ConfigFile::settingsWithGroup(Theme::instance()->appName());
settings->setParent(job); // make the job parent to make setting deleted properly
job->setSettings(settings.release());
}
#endif
/*
* Job
*/
Job::Job(QObject *parent)
: QObject(parent)
{
_serviceName = Theme::instance()->appName();
}
/*
* WriteJob
*/
WriteJob::WriteJob(Account *account, const QString &key, const QByteArray &data, QObject *parent)
: Job(parent)
{
_account = account;
_key = key;
// Windows workaround: Split the private key into chunks of 2048 bytes,
// to allow 4k (4096 bit) keys to be saved (obey Windows's limits)
_chunkBuffer = data;
_chunkCount = 0;
}
void WriteJob::start()
{
slotWriteJobDone(nullptr);
}
void WriteJob::slotWriteJobDone(QKeychain::Job *incomingJob)
{
QKeychain::WritePasswordJob *writeJob = static_cast<QKeychain::WritePasswordJob *>(incomingJob);
// errors?
if (writeJob) {
_error = writeJob->error();
_errorString = writeJob->errorString();
if (writeJob->error() != NoError) {
qCWarning(lcKeychainChunk) << "Error while writing" << writeJob->key() << "chunk" << writeJob->errorString();
_chunkBuffer.clear();
}
}
// write a chunk if there is any in the buffer
if (!_chunkBuffer.isEmpty()) {
#if defined(Q_OS_WIN)
// Windows workaround: Split the data into chunks of 2048 bytes,
// to allow 4k (4096 bit) keys to be saved (obey Windows's limits)
auto chunk = _chunkBuffer.left(KeychainChunk::ChunkSize);
_chunkBuffer = _chunkBuffer.right(_chunkBuffer.size() - chunk.size());
#else
// write full data in one chunk on non-Windows, as usual
auto chunk = _chunkBuffer;
_chunkBuffer.clear();
#endif
auto index = (_chunkCount++);
// keep the limit
if (_chunkCount > KeychainChunk::MaxChunks) {
qCWarning(lcKeychainChunk) << "Maximum chunk count exceeded while writing" << writeJob->key() << "chunk" << QString::number(index) << "cutting off after" << QString::number(KeychainChunk::MaxChunks) << "chunks";
writeJob->deleteLater();
_chunkBuffer.clear();
emit finished(this);
return;
}
const QString kck = AbstractCredentials::keychainKey(
_account->url().toString(),
_key + (index > 0 ? (QString(".") + QString::number(index)) : QString()),
_account->id());
QKeychain::WritePasswordJob *job = new QKeychain::WritePasswordJob(_serviceName);
#if defined(KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK)
addSettingsToJob(_account, job);
#endif
job->setInsecureFallback(_insecureFallback);
connect(job, &QKeychain::Job::finished, this, &KeychainChunk::WriteJob::slotWriteJobDone);
// only add the key's (sub)"index" after the first element, to stay compatible with older versions and non-Windows
job->setKey(kck);
job->setBinaryData(chunk);
job->start();
chunk.clear();
} else {
emit finished(this);
}
writeJob->deleteLater();
}
/*
* ReadJob
*/
ReadJob::ReadJob(Account *account, const QString &key, const bool &keychainMigration, QObject *parent)
: Job(parent)
{
_account = account;
_key = key;
_keychainMigration = keychainMigration;
_chunkCount = 0;
_chunkBuffer.clear();
}
void ReadJob::start()
{
_chunkCount = 0;
_chunkBuffer.clear();
const QString kck = AbstractCredentials::keychainKey(
_account->url().toString(),
_key,
_keychainMigration ? QString() : _account->id());
QKeychain::ReadPasswordJob *job = new QKeychain::ReadPasswordJob(_serviceName);
#if defined(KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK)
addSettingsToJob(_account, job);
#endif
job->setInsecureFallback(_insecureFallback);
job->setKey(kck);
connect(job, &QKeychain::Job::finished, this, &KeychainChunk::ReadJob::slotReadJobDone);
job->start();
}
void ReadJob::slotReadJobDone(QKeychain::Job *incomingJob)
{
// Errors or next chunk?
QKeychain::ReadPasswordJob *readJob = static_cast<QKeychain::ReadPasswordJob *>(incomingJob);
if (readJob) {
if (readJob->error() == NoError && readJob->binaryData().length() > 0) {
_chunkBuffer.append(readJob->binaryData());
_chunkCount++;
#if defined(Q_OS_WIN)
// try to fetch next chunk
if (_chunkCount < KeychainChunk::MaxChunks) {
const QString kck = AbstractCredentials::keychainKey(
_account->url().toString(),
_key + QString(".") + QString::number(_chunkCount),
_keychainMigration ? QString() : _account->id());
QKeychain::ReadPasswordJob *job = new QKeychain::ReadPasswordJob(_serviceName);
#if defined(KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK)
addSettingsToJob(_account, job);
#endif
job->setInsecureFallback(_insecureFallback);
job->setKey(kck);
connect(job, &QKeychain::Job::finished, this, &KeychainChunk::ReadJob::slotReadJobDone);
job->start();
readJob->deleteLater();
return;
} else {
qCWarning(lcKeychainChunk) << "Maximum chunk count for" << readJob->key() << "reached, ignoring after" << KeychainChunk::MaxChunks;
}
#endif
} else {
if (readJob->error() != QKeychain::Error::EntryNotFound ||
((readJob->error() == QKeychain::Error::EntryNotFound) && _chunkCount == 0)) {
_error = readJob->error();
_errorString = readJob->errorString();
qCWarning(lcKeychainChunk) << "Unable to read" << readJob->key() << "chunk" << QString::number(_chunkCount) << readJob->errorString();
}
}
readJob->deleteLater();
}
emit finished(this);
}
} // namespace KeychainChunk
} // namespace OCC

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) by Michael Schuster <michael@nextcloud.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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
#ifndef KEYCHAINCHUNK_H
#define KEYCHAINCHUNK_H
#include <QObject>
#include <keychain.h>
#include "accountfwd.h"
// We don't support insecure fallback
// #define KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK
namespace OCC {
namespace KeychainChunk {
/*
* Workaround for Windows:
*
* Split the keychain entry's data into chunks of 2048 bytes,
* to allow 4k (4096 bit) keys / large certs to be saved (see limits in webflowcredentials.h)
*/
static constexpr int ChunkSize = 2048;
static constexpr int MaxChunks = 10;
/*
* @brief: Abstract base class for KeychainChunk jobs.
*/
class Job : public QObject {
Q_OBJECT
public:
Job(QObject *parent = nullptr);
const QKeychain::Error error() const {
return _error;
}
const QString errorString() const {
return _errorString;
}
QByteArray binaryData() const {
return _chunkBuffer;
}
const bool insecureFallback() const {
return _insecureFallback;
}
// If we use it but don't support insecure fallback, give us nice compilation errors ;p
#if defined(KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK)
void setInsecureFallback(const bool &insecureFallback)
{
_insecureFallback = insecureFallback;
}
#endif
protected:
QString _serviceName;
Account *_account;
QString _key;
bool _insecureFallback = false;
bool _keychainMigration = false;
QKeychain::Error _error = QKeychain::NoError;
QString _errorString;
int _chunkCount = 0;
QByteArray _chunkBuffer;
}; // class Job
/*
* @brief: Simple wrapper class for QKeychain::WritePasswordJob, splits too large keychain entry's data into chunks on Windows
*/
class WriteJob : public KeychainChunk::Job {
Q_OBJECT
public:
WriteJob(Account *account, const QString &key, const QByteArray &data, QObject *parent = nullptr);
void start();
signals:
void finished(KeychainChunk::WriteJob *incomingJob);
private slots:
void slotWriteJobDone(QKeychain::Job *incomingJob);
}; // class WriteJob
/*
* @brief: Simple wrapper class for QKeychain::ReadPasswordJob, splits too large keychain entry's data into chunks on Windows
*/
class ReadJob : public KeychainChunk::Job {
Q_OBJECT
public:
ReadJob(Account *account, const QString &key, const bool &keychainMigration, QObject *parent = nullptr);
void start();
signals:
void finished(KeychainChunk::ReadJob *incomingJob);
private slots:
void slotReadJobDone(QKeychain::Job *incomingJob);
}; // class ReadJob
} // namespace KeychainChunk
} // namespace OCC
#endif // KEYCHAINCHUNK_H

View File

@@ -18,6 +18,7 @@
#include "theme.h"
#include "wizard/webview.h"
#include "webflowcredentialsdialog.h"
#include "keychainchunk.h"
using namespace QKeychain;
@@ -75,6 +76,7 @@ private:
QPointer<const WebFlowCredentials> _cred;
};
#if defined(KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK)
static void addSettingsToJob(Account *account, QKeychain::Job *job)
{
Q_UNUSED(account)
@@ -82,6 +84,7 @@ static void addSettingsToJob(Account *account, QKeychain::Job *job)
settings->setParent(job); // make the job parent to make setting deleted properly
job->setSettings(settings.release());
}
#endif
WebFlowCredentials::WebFlowCredentials()
: _ready(false)
@@ -147,25 +150,32 @@ void WebFlowCredentials::fetchFromKeychain() {
}
void WebFlowCredentials::askFromUser() {
// LoginFlowV2 > WebViewFlow > OAuth > Shib > Basic
bool useFlow2 = (_account->serverVersionInt() >= Account::makeServerVersion(16, 0, 0));
// Determine if the old flow has to be used (GS for now)
// Do a DetermineAuthTypeJob to make sure that the server is still using Flow2
DetermineAuthTypeJob *job = new DetermineAuthTypeJob(_account->sharedFromThis(), this);
connect(job, &DetermineAuthTypeJob::authType, [this](DetermineAuthTypeJob::AuthType type) {
// LoginFlowV2 > WebViewFlow > OAuth > Shib > Basic
bool useFlow2 = (type != DetermineAuthTypeJob::WebViewFlow);
_askDialog = new WebFlowCredentialsDialog(_account, useFlow2);
_askDialog = new WebFlowCredentialsDialog(_account, useFlow2);
if (!useFlow2) {
QUrl url = _account->url();
QString path = url.path() + "/index.php/login/flow";
url.setPath(path);
_askDialog->setUrl(url);
}
if (!useFlow2) {
QUrl url = _account->url();
QString path = url.path() + "/index.php/login/flow";
url.setPath(path);
_askDialog->setUrl(url);
}
QString msg = tr("You have been logged out of %1 as user %2. Please login again")
.arg(_account->displayName(), _user);
_askDialog->setInfo(msg);
QString msg = tr("You have been logged out of %1 as user %2. Please login again")
.arg(_account->displayName(), _user);
_askDialog->setInfo(msg);
_askDialog->show();
_askDialog->show();
connect(_askDialog, &WebFlowCredentialsDialog::urlCatched, this, &WebFlowCredentials::slotAskFromUserCredentialsProvided);
connect(_askDialog, &WebFlowCredentialsDialog::urlCatched, this, &WebFlowCredentials::slotAskFromUserCredentialsProvided);
connect(_askDialog, &WebFlowCredentialsDialog::onClose, this, &WebFlowCredentials::slotAskFromUserCancelled);
});
job->start();
qCDebug(lcWebFlowCredentials()) << "User needs to reauth!";
}
@@ -199,10 +209,18 @@ void WebFlowCredentials::slotAskFromUserCredentialsProvided(const QString &user,
emit asked();
_askDialog->close();
delete _askDialog;
_askDialog->deleteLater();
_askDialog = nullptr;
}
void WebFlowCredentials::slotAskFromUserCancelled() {
qCDebug(lcWebFlowCredentials()) << "User cancelled reauth!";
emit asked();
_askDialog->deleteLater();
_askDialog = nullptr;
}
bool WebFlowCredentials::stillValid(QNetworkReply *reply) {
if (reply->error() != QNetworkReply::NoError) {
@@ -223,33 +241,32 @@ void WebFlowCredentials::persist() {
// write cert if there is one
if (!_clientSslCertificate.isNull()) {
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
connect(job, &Job::finished, this, &WebFlowCredentials::slotWriteClientCertPEMJobDone);
job->setKey(keychainKey(_account->url().toString(), _user + clientCertificatePEMC, _account->id()));
job->setBinaryData(_clientSslCertificate.toPem());
auto *job = new KeychainChunk::WriteJob(_account,
_user + clientCertificatePEMC,
_clientSslCertificate.toPem());
connect(job, &KeychainChunk::WriteJob::finished, this, &WebFlowCredentials::slotWriteClientCertPEMJobDone);
job->start();
} else {
// no cert, just write credentials
slotWriteClientCertPEMJobDone();
slotWriteClientCertPEMJobDone(nullptr);
}
}
void WebFlowCredentials::slotWriteClientCertPEMJobDone()
void WebFlowCredentials::slotWriteClientCertPEMJobDone(KeychainChunk::WriteJob *writeJob)
{
if(writeJob)
writeJob->deleteLater();
// write ssl key if there is one
if (!_clientSslKey.isNull()) {
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
connect(job, &Job::finished, this, &WebFlowCredentials::slotWriteClientKeyPEMJobDone);
job->setKey(keychainKey(_account->url().toString(), _user + clientKeyPEMC, _account->id()));
job->setBinaryData(_clientSslKey.toPem());
auto *job = new KeychainChunk::WriteJob(_account,
_user + clientKeyPEMC,
_clientSslKey.toPem());
connect(job, &KeychainChunk::WriteJob::finished, this, &WebFlowCredentials::slotWriteClientKeyPEMJobDone);
job->start();
} else {
// no key, just write credentials
slotWriteClientKeyPEMJobDone();
slotWriteClientKeyPEMJobDone(nullptr);
}
}
@@ -264,7 +281,7 @@ void WebFlowCredentials::writeSingleClientCaCertPEM()
// keep the limit
if (index > (_clientSslCaCertificatesMaxCount - 1)) {
qCWarning(lcWebFlowCredentials) << "Maximum client CA cert count exceeded while writing slot" << QString::number(index) << "), cutting off after " << QString::number(_clientSslCaCertificatesMaxCount) << "certs";
qCWarning(lcWebFlowCredentials) << "Maximum client CA cert count exceeded while writing slot" << QString::number(index) << "cutting off after" << QString::number(_clientSslCaCertificatesMaxCount) << "certs";
_clientSslCaCertificatesWriteQueue.clear();
@@ -272,20 +289,21 @@ void WebFlowCredentials::writeSingleClientCaCertPEM()
return;
}
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
connect(job, &Job::finished, this, &WebFlowCredentials::slotWriteClientCaCertsPEMJobDone);
job->setKey(keychainKey(_account->url().toString(), _user + clientCaCertificatePEMC + QString::number(index), _account->id()));
job->setBinaryData(cert.toPem());
auto *job = new KeychainChunk::WriteJob(_account,
_user + clientCaCertificatePEMC + QString::number(index),
cert.toPem());
connect(job, &KeychainChunk::WriteJob::finished, this, &WebFlowCredentials::slotWriteClientCaCertsPEMJobDone);
job->start();
} else {
slotWriteClientCaCertsPEMJobDone(nullptr);
}
}
void WebFlowCredentials::slotWriteClientKeyPEMJobDone()
void WebFlowCredentials::slotWriteClientKeyPEMJobDone(KeychainChunk::WriteJob *writeJob)
{
if(writeJob)
writeJob->deleteLater();
_clientSslCaCertificatesWriteQueue.clear();
// write ca certs if there are any
@@ -300,16 +318,16 @@ void WebFlowCredentials::slotWriteClientKeyPEMJobDone()
}
}
void WebFlowCredentials::slotWriteClientCaCertsPEMJobDone(QKeychain::Job *incomingJob)
void WebFlowCredentials::slotWriteClientCaCertsPEMJobDone(KeychainChunk::WriteJob *writeJob)
{
// errors / next ca cert?
if (incomingJob && !_clientSslCaCertificates.isEmpty()) {
WritePasswordJob *writeJob = static_cast<WritePasswordJob *>(incomingJob);
if (writeJob && !_clientSslCaCertificates.isEmpty()) {
if (writeJob->error() != NoError) {
qCWarning(lcWebFlowCredentials) << "Error while writing client CA cert" << writeJob->errorString();
}
writeJob->deleteLater();
if (!_clientSslCaCertificatesWriteQueue.isEmpty()) {
// next ca cert
writeSingleClientCaCertPEM();
@@ -319,7 +337,9 @@ void WebFlowCredentials::slotWriteClientCaCertsPEMJobDone(QKeychain::Job *incomi
// done storing ca certs, time for the password
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
#if defined(KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK)
addSettingsToJob(_account, job);
#endif
job->setInsecureFallback(false);
connect(job, &Job::finished, this, &WebFlowCredentials::slotWriteJobDone);
job->setKey(keychainKey(_account->url().toString(), _user, _account->id()));
@@ -358,6 +378,8 @@ void WebFlowCredentials::forgetSensitiveData() {
fetchUser();
_account->deleteAppPassword();
const QString kck = keychainKey(_account->url().toString(), _user, _account->id());
if (kck.isEmpty()) {
qCDebug(lcWebFlowCredentials()) << "InvalidateToken: User is empty, bailing out!";
@@ -367,18 +389,15 @@ void WebFlowCredentials::forgetSensitiveData() {
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
job->setInsecureFallback(false);
job->setKey(kck);
connect(job, &Job::finished, this, [](QKeychain::Job *job) {
DeletePasswordJob *djob = qobject_cast<DeletePasswordJob *>(job);
djob->deleteLater();
});
job->start();
invalidateToken();
/* IMPORTANT
/* TODO: For "Log out" & "Remove account": Remove client CA certs and KEY!
*
* Disabled as long as selecting another cert is not supported by the UI.
*
* Being able to specify a new certificate is important anyway: expiry etc.
*/
//deleteKeychainEntries();
deleteKeychainEntries();
}
void WebFlowCredentials::setAccount(Account *account) {
@@ -416,34 +435,31 @@ void WebFlowCredentials::slotFinished(QNetworkReply *reply) {
if (reply->error() == QNetworkReply::NoError) {
_credentialsValid = true;
/// Used later for remote wipe
_account->writeAppPasswordOnce(_password);
}
}
void WebFlowCredentials::fetchFromKeychainHelper() {
// Read client cert from keychain
const QString kck = keychainKey(
_account->url().toString(),
_user + clientCertificatePEMC,
_keychainMigration ? QString() : _account->id());
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
job->setKey(kck);
connect(job, &Job::finished, this, &WebFlowCredentials::slotReadClientCertPEMJobDone);
auto *job = new KeychainChunk::ReadJob(_account,
_user + clientCertificatePEMC,
_keychainMigration);
connect(job, &KeychainChunk::ReadJob::finished, this, &WebFlowCredentials::slotReadClientCertPEMJobDone);
job->start();
}
void WebFlowCredentials::slotReadClientCertPEMJobDone(QKeychain::Job *incomingJob)
void WebFlowCredentials::slotReadClientCertPEMJobDone(KeychainChunk::ReadJob *readJob)
{
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
Q_ASSERT(!incomingJob->insecureFallback()); // If insecureFallback is set, the next test would be pointless
if (_retryOnKeyChainError && (incomingJob->error() == QKeychain::NoBackendAvailable
|| incomingJob->error() == QKeychain::OtherError)) {
Q_ASSERT(!readJob->insecureFallback()); // If insecureFallback is set, the next test would be pointless
if (_retryOnKeyChainError && (readJob->error() == QKeychain::NoBackendAvailable
|| readJob->error() == QKeychain::OtherError)) {
// Could be that the backend was not yet available. Wait some extra seconds.
// (Issues #4274 and #6522)
// (For kwallet, the error is OtherError instead of NoBackendAvailable, maybe a bug in QtKeychain)
qCInfo(lcWebFlowCredentials) << "Backend unavailable (yet?) Retrying in a few seconds." << incomingJob->errorString();
qCInfo(lcWebFlowCredentials) << "Backend unavailable (yet?) Retrying in a few seconds." << readJob->errorString();
QTimer::singleShot(10000, this, &WebFlowCredentials::fetchFromKeychainHelper);
_retryOnKeyChainError = false;
return;
@@ -452,7 +468,6 @@ void WebFlowCredentials::slotReadClientCertPEMJobDone(QKeychain::Job *incomingJo
#endif
// Store PEM in memory
ReadPasswordJob *readJob = static_cast<ReadPasswordJob *>(incomingJob);
if (readJob->error() == NoError && readJob->binaryData().length() > 0) {
QList<QSslCertificate> sslCertificateList = QSslCertificate::fromData(readJob->binaryData(), QSsl::Pem);
if (sslCertificateList.length() >= 1) {
@@ -460,25 +475,19 @@ void WebFlowCredentials::slotReadClientCertPEMJobDone(QKeychain::Job *incomingJo
}
}
// Load key too
const QString kck = keychainKey(
_account->url().toString(),
_user + clientKeyPEMC,
_keychainMigration ? QString() : _account->id());
readJob->deleteLater();
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
job->setKey(kck);
connect(job, &Job::finished, this, &WebFlowCredentials::slotReadClientKeyPEMJobDone);
// Load key too
auto *job = new KeychainChunk::ReadJob(_account,
_user + clientKeyPEMC,
_keychainMigration);
connect(job, &KeychainChunk::ReadJob::finished, this, &WebFlowCredentials::slotReadClientKeyPEMJobDone);
job->start();
}
void WebFlowCredentials::slotReadClientKeyPEMJobDone(QKeychain::Job *incomingJob)
void WebFlowCredentials::slotReadClientKeyPEMJobDone(KeychainChunk::ReadJob *readJob)
{
// Store key in memory
ReadPasswordJob *readJob = static_cast<ReadPasswordJob *>(incomingJob);
if (readJob->error() == NoError && readJob->binaryData().length() > 0) {
QByteArray clientKeyPEM = readJob->binaryData();
// FIXME Unfortunately Qt has a bug and we can't just use QSsl::Opaque to let it
@@ -493,8 +502,13 @@ void WebFlowCredentials::slotReadClientKeyPEMJobDone(QKeychain::Job *incomingJob
if (_clientSslKey.isNull()) {
qCWarning(lcWebFlowCredentials) << "Could not load SSL key into Qt!";
}
clientKeyPEM.clear();
} else {
qCWarning(lcWebFlowCredentials) << "Unable to read client key" << readJob->errorString();
}
readJob->deleteLater();
// Start fetching client CA certs
_clientSslCaCertificates.clear();
@@ -505,28 +519,20 @@ void WebFlowCredentials::readSingleClientCaCertPEM()
{
// try to fetch a client ca cert
if (_clientSslCaCertificates.count() < _clientSslCaCertificatesMaxCount) {
const QString kck = keychainKey(
_account->url().toString(),
_user + clientCaCertificatePEMC + QString::number(_clientSslCaCertificates.count()),
_keychainMigration ? QString() : _account->id());
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
job->setKey(kck);
connect(job, &Job::finished, this, &WebFlowCredentials::slotReadClientCaCertsPEMJobDone);
auto *job = new KeychainChunk::ReadJob(_account,
_user + clientCaCertificatePEMC + QString::number(_clientSslCaCertificates.count()),
_keychainMigration);
connect(job, &KeychainChunk::ReadJob::finished, this, &WebFlowCredentials::slotReadClientCaCertsPEMJobDone);
job->start();
} else {
qCWarning(lcWebFlowCredentials) << "Maximum client CA cert count exceeded while reading, ignoring after " << _clientSslCaCertificatesMaxCount;
qCWarning(lcWebFlowCredentials) << "Maximum client CA cert count exceeded while reading, ignoring after" << _clientSslCaCertificatesMaxCount;
slotReadClientCaCertsPEMJobDone(nullptr);
}
}
void WebFlowCredentials::slotReadClientCaCertsPEMJobDone(QKeychain::Job *incomingJob) {
// Store key in memory
ReadPasswordJob *readJob = static_cast<ReadPasswordJob *>(incomingJob);
void WebFlowCredentials::slotReadClientCaCertsPEMJobDone(KeychainChunk::ReadJob *readJob) {
// Store cert in memory
if (readJob) {
if (readJob->error() == NoError && readJob->binaryData().length() > 0) {
QList<QSslCertificate> sslCertificateList = QSslCertificate::fromData(readJob->binaryData(), QSsl::Pem);
@@ -534,15 +540,19 @@ void WebFlowCredentials::slotReadClientCaCertsPEMJobDone(QKeychain::Job *incomin
_clientSslCaCertificates.append(sslCertificateList.at(0));
}
readJob->deleteLater();
// try next cert
readSingleClientCaCertPEM();
return;
} else {
if (readJob->error() != QKeychain::Error::EntryNotFound ||
(readJob->error() == QKeychain::Error::EntryNotFound) && _clientSslCaCertificates.count() == 0) {
qCWarning(lcWebFlowCredentials) << "Unable to read client CA cert slot " << QString::number(_clientSslCaCertificates.count()) << readJob->errorString();
((readJob->error() == QKeychain::Error::EntryNotFound) && _clientSslCaCertificates.count() == 0)) {
qCWarning(lcWebFlowCredentials) << "Unable to read client CA cert slot" << QString::number(_clientSslCaCertificates.count()) << readJob->errorString();
}
}
readJob->deleteLater();
}
// Now fetch the actual server password
@@ -552,7 +562,9 @@ void WebFlowCredentials::slotReadClientCaCertsPEMJobDone(QKeychain::Job *incomin
_keychainMigration ? QString() : _account->id());
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
#if defined(KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK)
addSettingsToJob(_account, job);
#endif
job->setInsecureFallback(false);
job->setKey(kck);
connect(job, &Job::finished, this, &WebFlowCredentials::slotReadPasswordJobDone);
@@ -560,7 +572,7 @@ void WebFlowCredentials::slotReadClientCaCertsPEMJobDone(QKeychain::Job *incomin
}
void WebFlowCredentials::slotReadPasswordJobDone(Job *incomingJob) {
QKeychain::ReadPasswordJob *job = static_cast<ReadPasswordJob *>(incomingJob);
QKeychain::ReadPasswordJob *job = qobject_cast<ReadPasswordJob *>(incomingJob);
QKeychain::Error error = job->error();
// If we could not find the entry try the old entries
@@ -583,6 +595,8 @@ void WebFlowCredentials::slotReadPasswordJobDone(Job *incomingJob) {
}
emit fetched();
job->deleteLater();
// If keychain data was read from legacy location, wipe these entries and store new ones
if (_keychainMigration && _ready) {
_keychainMigration = false;
@@ -593,23 +607,60 @@ void WebFlowCredentials::slotReadPasswordJobDone(Job *incomingJob) {
}
void WebFlowCredentials::deleteKeychainEntries(bool oldKeychainEntries) {
auto startDeleteJob = [this, oldKeychainEntries](QString user) {
auto startDeleteJob = [this, oldKeychainEntries](QString key) {
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
#if defined(KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK)
addSettingsToJob(_account, job);
job->setInsecureFallback(true);
#endif
job->setInsecureFallback(false);
job->setKey(keychainKey(_account->url().toString(),
user,
key,
oldKeychainEntries ? QString() : _account->id()));
connect(job, &Job::finished, this, [](QKeychain::Job *job) {
DeletePasswordJob *djob = qobject_cast<DeletePasswordJob *>(job);
djob->deleteLater();
});
job->start();
};
startDeleteJob(_user);
startDeleteJob(_user + clientKeyPEMC);
startDeleteJob(_user + clientCertificatePEMC);
for (auto i = 0; i < _clientSslCaCertificates.count(); i++) {
startDeleteJob(_user + clientCaCertificatePEMC + QString::number(i));
/* IMPORTANT - remove later - FIXME MS@2019-12-07 -->
* TODO: For "Log out" & "Remove account": Remove client CA certs and KEY!
*
* Disabled as long as selecting another cert is not supported by the UI.
*
* Being able to specify a new certificate is important anyway: expiry etc.
*
* We introduce this dirty hack here, to allow deleting them upon Remote Wipe.
*/
if(_account->isRemoteWipeRequested_HACK()) {
// <-- FIXME MS@2019-12-07
startDeleteJob(_user + clientKeyPEMC);
startDeleteJob(_user + clientCertificatePEMC);
for (auto i = 0; i < _clientSslCaCertificates.count(); i++) {
startDeleteJob(_user + clientCaCertificatePEMC + QString::number(i));
}
#if defined(Q_OS_WIN)
// Also delete key / cert sub-chunks (Windows workaround)
// The first chunk (0) has no suffix, to stay compatible with older versions and non-Windows
for (auto chunk = 1; chunk < KeychainChunk::MaxChunks; chunk++) {
const QString strChunkSuffix = QString(".") + QString::number(chunk);
startDeleteJob(_user + clientKeyPEMC + strChunkSuffix);
startDeleteJob(_user + clientCertificatePEMC + strChunkSuffix);
for (auto i = 0; i < _clientSslCaCertificates.count(); i++) {
startDeleteJob(_user + clientCaCertificatePEMC + QString::number(i));
}
}
#endif
// FIXME MS@2019-12-07 -->
}
// <-- FIXME MS@2019-12-07
}
}
} // namespace OCC

View File

@@ -19,6 +19,11 @@ namespace QKeychain {
namespace OCC {
namespace KeychainChunk {
class ReadJob;
class WriteJob;
}
class WebFlowCredentialsDialog;
class WebFlowCredentials : public AbstractCredentials
@@ -61,15 +66,16 @@ private slots:
void slotFinished(QNetworkReply *reply);
void slotAskFromUserCredentialsProvided(const QString &user, const QString &pass, const QString &host);
void slotAskFromUserCancelled();
void slotReadClientCertPEMJobDone(QKeychain::Job *incomingJob);
void slotReadClientKeyPEMJobDone(QKeychain::Job *incomingJob);
void slotReadClientCaCertsPEMJobDone(QKeychain::Job *incommingJob);
void slotReadClientCertPEMJobDone(KeychainChunk::ReadJob *readJob);
void slotReadClientKeyPEMJobDone(KeychainChunk::ReadJob *readJob);
void slotReadClientCaCertsPEMJobDone(KeychainChunk::ReadJob *readJob);
void slotReadPasswordJobDone(QKeychain::Job *incomingJob);
void slotWriteClientCertPEMJobDone();
void slotWriteClientKeyPEMJobDone();
void slotWriteClientCaCertsPEMJobDone(QKeychain::Job *incomingJob);
void slotWriteClientCertPEMJobDone(KeychainChunk::WriteJob *writeJob);
void slotWriteClientKeyPEMJobDone(KeychainChunk::WriteJob *writeJob);
void slotWriteClientCaCertsPEMJobDone(KeychainChunk::WriteJob *writeJob);
void slotWriteJobDone(QKeychain::Job *);
private:
@@ -83,7 +89,7 @@ private:
void writeSingleClientCaCertPEM();
/*
* Since we're limited by Windows limits we just create our own
* Since we're limited by Windows limits, we just create our own
* limit to avoid evil things happening by endless recursion
*
* Better than storing the count and relying on maybe-hacked values
@@ -121,6 +127,6 @@ protected:
WebFlowCredentialsDialog *_askDialog;
};
}
} // namespace OCC
#endif // WEBFLOWCREDENTIALS_H

View File

@@ -4,6 +4,9 @@
#include <QLabel>
#include "theme.h"
#include "application.h"
#include "owncloudgui.h"
#include "headerbanner.h"
#include "wizard/owncloudwizardcommon.h"
#include "wizard/webview.h"
#include "wizard/flow2authwidget.h"
@@ -19,31 +22,59 @@ WebFlowCredentialsDialog::WebFlowCredentialsDialog(Account *account, bool useFlo
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
_layout = new QVBoxLayout(this);
int spacing = _layout->spacing();
int margin = _layout->margin();
_layout->setSpacing(0);
_layout->setMargin(0);
if(_useFlow2) {
_headerBanner = new HeaderBanner(this);
_layout->addWidget(_headerBanner);
Theme *theme = Theme::instance();
_headerBanner->setup(tr("Log in"), theme->wizardHeaderLogo(), theme->wizardHeaderBanner(),
Qt::AutoText, QString::fromLatin1("color:#fff;"));
}
_containerLayout = new QVBoxLayout(this);
_containerLayout->setSpacing(spacing);
_containerLayout->setMargin(margin);
//QString msg = tr("You have been logged out of %1 as user %2, please login again")
// .arg(_account->displayName(), _user);
_infoLabel = new QLabel();
_layout->addWidget(_infoLabel);
_containerLayout->addWidget(_infoLabel);
if (_useFlow2) {
_flow2AuthWidget = new Flow2AuthWidget(account);
_layout->addWidget(_flow2AuthWidget);
_flow2AuthWidget = new Flow2AuthWidget();
_containerLayout->addWidget(_flow2AuthWidget);
connect(_flow2AuthWidget, &Flow2AuthWidget::urlCatched, this, &WebFlowCredentialsDialog::urlCatched);
connect(_flow2AuthWidget, &Flow2AuthWidget::authResult, this, &WebFlowCredentialsDialog::slotFlow2AuthResult);
// Connect styleChanged events to our widgets, so they can adapt (Dark-/Light-Mode switching)
connect(this, &WebFlowCredentialsDialog::styleChanged, _flow2AuthWidget, &Flow2AuthWidget::slotStyleChanged);
// allow Flow2 page to poll on window activation
connect(this, &WebFlowCredentialsDialog::onActivate, _flow2AuthWidget, &Flow2AuthWidget::slotPollNow);
_flow2AuthWidget->startAuth(account);
} else {
_webView = new WebView();
_layout->addWidget(_webView);
_containerLayout->addWidget(_webView);
connect(_webView, &WebView::urlCatched, this, &WebFlowCredentialsDialog::urlCatched);
}
auto app = static_cast<Application *>(qApp);
connect(app, &Application::isShowingSettingsDialog, this, &WebFlowCredentialsDialog::slotShowSettingsDialog);
_errorLabel = new QLabel();
_errorLabel->hide();
_layout->addWidget(_errorLabel);
_containerLayout->addWidget(_errorLabel);
WizardCommon::initErrorLabel(_errorLabel);
_layout->addLayout(_containerLayout);
setLayout(_layout);
customizeStyle();
}
void WebFlowCredentialsDialog::closeEvent(QCloseEvent* e) {
@@ -52,11 +83,17 @@ void WebFlowCredentialsDialog::closeEvent(QCloseEvent* e) {
if (_webView) {
// Force calling WebView::~WebView() earlier so that _profile and _page are
// deleted in the correct order.
delete _webView;
_webView->deleteLater();
_webView = nullptr;
}
if (_flow2AuthWidget)
delete _flow2AuthWidget;
if (_flow2AuthWidget) {
_flow2AuthWidget->resetAuth();
_flow2AuthWidget->deleteLater();
_flow2AuthWidget = nullptr;
}
emit onClose();
}
void WebFlowCredentialsDialog::setUrl(const QUrl &url) {
@@ -69,6 +106,9 @@ void WebFlowCredentialsDialog::setInfo(const QString &msg) {
}
void WebFlowCredentialsDialog::setError(const QString &error) {
// bring window to top
slotShowSettingsDialog();
if (_useFlow2 && _flow2AuthWidget) {
_flow2AuthWidget->setError(error);
return;
@@ -82,4 +122,49 @@ void WebFlowCredentialsDialog::setError(const QString &error) {
}
}
void WebFlowCredentialsDialog::changeEvent(QEvent *e)
{
switch (e->type()) {
case QEvent::StyleChange:
case QEvent::PaletteChange:
case QEvent::ThemeChange:
customizeStyle();
// Notify the other widgets (Dark-/Light-Mode switching)
emit styleChanged();
break;
case QEvent::ActivationChange:
if(isActiveWindow())
emit onActivate();
break;
default:
break;
}
QDialog::changeEvent(e);
}
void WebFlowCredentialsDialog::customizeStyle()
{
// HINT: Customize dialog's own style here, if necessary in the future (Dark-/Light-Mode switching)
}
void WebFlowCredentialsDialog::slotShowSettingsDialog()
{
// bring window to top but slightly delay, to avoid being hidden behind the SettingsDialog
QTimer::singleShot(100, this, [this] {
ownCloudGui::raiseDialog(this);
});
}
void WebFlowCredentialsDialog::slotFlow2AuthResult(Flow2Auth::Result r, const QString &errorString, const QString &user, const QString &appPassword)
{
if(r == Flow2Auth::LoggedIn) {
emit urlCatched(user, appPassword, QString());
} else {
// bring window to top
slotShowSettingsDialog();
}
}
} // namespace OCC

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