Initial QSfera import

This commit is contained in:
Курнат Андрей
2026-06-07 10:20:04 +03:00
commit 2315f25754
16485 changed files with 4826827 additions and 0 deletions
+62
View File
@@ -0,0 +1,62 @@
# Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
#
# You may use this file under the terms of the 3-clause BSD license.
# See the file LICENSE from this package for details.
# This is the clang-format configuration style to be used by Qt,
# based on the rules from https://wiki.qt.io/Qt_Coding_Style and
# https://wiki.qt.io/Coding_Conventions
---
# Webkit style was loosely based on the Qt style
BasedOnStyle: WebKit
Standard: c++17
ColumnLimit: 160
# Disable reflow of qdoc comments: indentation rules are different.
# Translation comments are also excluded
CommentPragmas: "^!|^:"
# We want a space between the type and the star for pointer types
PointerBindsToType: false
# We want to break before the operators, but not before a '='
BreakBeforeBinaryOperators: NonAssignment
# Braces are usually attached, but not after functions or classes declaration
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
# The coding style does not specify the following, but this is what gives
# results closest to the existing code.
AlignAfterOpenBracket: DontAlign
AlwaysBreakTemplateDeclarations: true
# Ideally we should also allow less short function in a single line, but
# clang-format does not handle that
AllowShortFunctionsOnASingleLine: Inline
SortIncludes: true
# macros for which the opening brace stays attached
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE ]
# Allow two empty lines for structuring
MaxEmptyLinesToKeep: 2
KeepEmptyLinesAtTheStartOfBlocks: false
# Properly format c++11 initializer
SpaceBeforeCpp11BracedList: false
Cpp11BracedListStyle: true
+105
View File
@@ -0,0 +1,105 @@
[General]
ShallowClone = False
# Variables defined here override the default value
# The variable names are case-sensitive
[Variables]
#Values need to be overwritten to create a cache
UseCache = True
CreateCache = True
QSferaVersion = 1.0
# this version must match the target in the blueprint
# update MacDeploymentTarget when updating Qt
#QtVersion = 6.8.0
CachePatchLvl = 0
# set WORKSPACE to cwd, override on ci
# with legacy fallback APPVEYOR_BUILD_FOLDER
WORKSPACE = ${Variables:APPVEYOR_BUILD_FOLDER}
APPVEYOR_BUILD_FOLDER = ${Variables:Root}
CiBuild = True
# Settings applicable for all Crafts matrices
# Settings are Category/key=value
# Category is case sensitive
[GeneralSettings]
Version/ConfigVersion = 6
Packager/Destination=${Variables:WORKSPACE}/binaries
Paths/Python = C:/Python36
Paths/DownloadDir = ${Variables:Root}/downloads
Blueprints/BlueprintRoot = ${Variables:Root}/blueprints
CraftDebug/LogDir = ${Variables:Root}/logs
ShortPath/JunctionDir = /_/
Packager/CacheDir = ${Variables:WORKSPACE}/cache
Packager/UseCache = ${Variables:UseCache}
Packager/CreateCache = ${Variables:CreateCache}
#Packager/CacheVersion = ${Variables:QSferaVersion}/Qt_${Variables:QtVersion}_${Variables:CachePatchLvl}
Packager/PackageDebugSymbols = ${Env:CRAFT_PACKAGE_SYMBOLS}
Packager/DownloadDebugSymbolsCache = ${Env:CRAFT_PACKAGE_SYMBOLS}
Packager/AppxPublisherId = CN=44DA8A24-8237-46B0-B4A2-D297A6A22705
Compile/BuildType = RelWithDebInfo
ContinuousIntegration/Enabled = ${Variables:CiBuild}
ContinuousIntegration/UpdateRepository = True
CodeSigning/Enabled = ${Env:SIGN_PACKAGE}
CodeSigning/Protected = True
CodeSigning/Certificate = ${Env:CRAFT_CODESIGN_CERTIFICATE}
CodeSigning/CommonName =
CodeSigning/MacDeveloperId =
CodeSigning/MacAppleID =
CodeSigning/MacKeychainPath = sign-${Env:DRONE_BUILD_NUMBER}.keychain
[BlueprintSettings]
# skip msys in normal builds its only needed for the cache
dev-utils/msys-base.ignored = True
dev-utils/msys.ignored = True
# in the current cache that pulls in the uncached lxml which takes ages to build
dev-utils/gtk-doc.ignored = True
#libs/qt6.version = ${Variables:QtVersion}
[windows-cl-msvc2022-x86_64]
General/ABI = windows-cl-msvc2022-x86_64
[windows-cl-msvc2022-x86_64-debug]
General/ABI = windows-cl-msvc2022-x86_64
Compile/BuildType = Debug
[macos-clang-x86_64]
General/ABI = macos-clang-x86_64
# Packager/PackageType = MacPkgPackager
[macos-clang-x86_64-debug]
General/ABI = macos-clang-x86_64
Compile/BuildType = Debug
[macos-clang-arm64]
General/ABI = macos-clang-arm64
[macos-clang-arm64-debug]
General/ABI = macos-clang-arm64
Compile/BuildType = Debug
[linux-gcc-x86_64]
General/ABI = linux-gcc-x86_64
[linux-gcc-x86_64-BlueprintSettings]
libs/qt6/qtbase.withDBus = True
[linux-gcc-x86_64-debug]
General/ABI = linux-gcc-x86_64
Compile/BuildType = Debug
[linux-gcc-x86_64-debug-BlueprintSettings]
libs/qt6/qtbase.withDBus = True
[Env]
CRAFT_PACKAGE_SYMBOLS = False
CRAFT_CODESIGN_CERTIFICATE =
SIGN_PACKAGE = False
# double fallback
DRONE_BUILD_NUMBER = ${Env:APPVEYOR_BUILD_NUMBER}
APPVEYOR_BUILD_NUMBER = 0
+3
View File
@@ -0,0 +1,3 @@
[General]
version = 2
blueprintrepositories = https://invent.kde.org/packaging/craft-blueprints-kde.git|master|;https://github.com/opencloud-eu/craft-blueprints-opencloud.git|main|
+1
View File
@@ -0,0 +1 @@
c8d0f788e00bdae125a26d9159ce9efdd6325cd2 # Initial application of clang-format
+5
View File
@@ -0,0 +1,5 @@
.tag export-subst
.gitignore export-ignore
.gitattributes export-ignore
.commit-template export-ignore
binary/ export-ignore
+23
View File
@@ -0,0 +1,23 @@
---
name: Bug Report
about: 🪲 Something is broken
title: ''
labels: Type:Bug
assignees: ''
---
## Steps to reproduce
1.
2.
3.
## Expected behavior
- Concise description of what you expected to happen.
## Actual behavior
- A concise description of what happened.
## Setup
- Your operating system
- Client version
- Log
+171
View File
@@ -0,0 +1,171 @@
---
name: User story
about: Converts your idea into an actionable format ready for sprint implementation.
title: ''
labels: Type:Story
assignees: ''
---
# Description
## User Stories
- ***As a ..., I want to ... so that ... (please stick to who, what, why)***
## Value
-
## Acceptance Criteria
-
## Definition of ready
- [ ] Everybody needs to understand the value written in the user story
- [ ] Acceptance criteria have to be defined
- [ ] All dependencies of the user story need to be identified
- [ ] Feature should be seen from an end user perspective
- [ ] Story has to be estimated
- [ ] Story points need to be less than 20
## Definition of done
- Functional requirements
- [ ] Functionality described in the user story works
- [ ] Acceptance criteria are fulfilled
- Quality
- [ ] Code review happened
- [ ] CI is green (that includes new and existing automated tests)
- [ ] Critical code received unit tests by the developer
- Non-functional requirements
- [ ] No sonar cloud issues
- Configuration changes
- [ ] The next branch of the OpenCloud charts is compatible
<details>
<summary>Writing Tips</summary>
## User Story
INVEST Criteria for User Stories
- **Independent**
Should be self-contained in a way that allows being released **without depending on one another**.
- **Negotiable**
Only **capture the essence** of the user's need, leaving room for conversation. A user story should not be written like a contract.
- **Valuable**
Delivers value to the end user.
- **Estimable**
User stories must be estimated so they can be properly prioritized and fit into sprints.
- **Small**
A user story is a small chunk of work that allows it to be completed in a short period of time.
- **Testable**
A user story has to be confirmed via pre-written acceptance criteria.
## Value
Examples:
- Save time
- Reduce risk
- Make it accessible for anyone
## Acceptance Criteria
### What Acceptance Criteria are for
Acceptance Criteria answer one question only:
**How do we know this story is done?**
Not how it is implemented. Not what might be nice. Not future hypotheticals.
#### Tie every AC to user value
Each criterion must protect or enable the user benefit.
**Bad**
- API returns 200 OK
**Good**
- User sees a confirmation that the action succeeded
If the user would not notice a failure, question why the AC exists.
#### Use observable outcomes
ACs must be verifiable by anyone, not just engineers.
**Bad**
- System processes data efficiently
**Good**
- Results are shown within 2 seconds after submission
If you cannot test it without reading code, it is trash.
#### Write from the users perspective
Describe what the user can do or see, not internal behavior.
**Bad**
- Data is stored in the new table
**Good**
- User can see previously saved entries after reload
#### Keep ACs binary
Each AC should be clearly pass or fail.
**Bad**
- Works well on mobile
**Good**
- User can complete the flow on a mobile device without horizontal scrolling
If there is room for interpretation, it will be abused.
#### Cover the happy path first
Do not drown the story in edge cases.
Start with:
- Core flow
- Primary user goal
Add edge cases only if they:
- Prevent real harm
- Block release
- Create user-visible failure
### Avoid solutioning
ACs define what, not how.
**Bad**
- Button is implemented using component X
**Good**
- User can submit the form using a visible primary action
If you lock implementation, you kill collaboration.
#### Use Given / When / Then where helpful
Optional, but useful for clarity.
**Example**
- **Given** the user is logged in
- **When** they submit the form
- **Then** they see a success message and the data is saved
If it adds noise, skip it.
### Litmus test
A good set of ACs allows:
- A developer to build it
- A tester to verify it
- A product manager to accept or reject it
Without further clarification.
If not, rewrite.
</details>
+12
View File
@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
+1
View File
@@ -0,0 +1 @@
_extends: gh-labels
+24
View File
@@ -0,0 +1,24 @@
if ($IsWindows) {
$python = (Get-Command py).Source
$python=(py -c "import sys; print(sys.executable)")
$env:HOME = ${HOME}
} else {
$python = (Get-Command python3).Source
}
# workaround, prevent CraftMaster detecting the platform as android
$env:ANDROID_NDK = $null
$RepoRoot = "{0}/../../" -f ([System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition))
$command = @("${HOME}/craft/CraftMaster/CraftMaster/CraftMaster.py",
"--config", "${RepoRoot}/.craft.ini",
"--config-override", "${RepoRoot}/.github/workflows/craft_override.ini",
"--target", "${env:CRAFT_TARGET}",
"--variables", "WORKSPACE=${HOME}/craft") + $args
Write-Host "Exec: ${python} ${command}"
& $python @command
if ($LASTEXITCODE -ne 0) {
exit 1
}
+25
View File
@@ -0,0 +1,25 @@
$clazyPlugin="ClazyClangTidy"
if($isWindows) {
$clazyPlugin = $null
#$clazy += ".dll" // don't use clazy on windows for now
} elseif($isLinux) {
$clazyPlugin = "${env:KDEROOT}/lib/${clazyPlugin}.so"
} else
{
$clazyPlugin = "${env:KDEROOT}/lib/${clazyPlugin}.dylib"
}
$CLAZY_LEVEL0="clazy-overloaded-signal,clazy-connect-by-name,clazy-connect-non-signal,clazy-qstring-comparison-to-implicit-char,clazy-wrong-qevent-cast,clazy-lambda-in-connect,clazy-lambda-unique-connection,clazy-qdatetime-utc,clazy-qgetenv,clazy-qstring-insensitive-allocation,clazy-fully-qualified-moc-types,clazy-unused-non-trivial-variable,clazy-connect-not-normalized,clazy-mutable-container-key,clazy-qenums,clazy-qmap-with-pointer-key,clazy-qstring-ref,clazy-strict-iterators,clazy-writing-to-temporary,clazy-container-anti-pattern,clazy-qcolor-from-literal,clazy-qfileinfo-exists,clazy-qstring-arg,clazy-empty-qstringliteral,clazy-qt-macros,clazy-temporary-iterator,clazy-wrong-qglobalstatic,clazy-lowercase-qml-type-name,clazy-no-module-include,clazy-use-static-qregularexpression"
$CLAZY_LEVEL1="clazy-auto-unexpected-qstringbuilder,clazy-connect-3arg-lambda,clazy-const-signal-or-slot,clazy-detaching-temporary,clazy-foreach,clazy-incorrect-emit,clazy-install-event-filter,clazy-non-pod-global-static,clazy-post-event,clazy-qdeleteall,clazy-qlatin1string-non-ascii,clazy-qproperty-without-notify,clazy-qstring-left,clazy-range-loop-detach,clazy-range-loop-reference,clazy-returning-data-from-temporary,clazy-rule-of-two-soft,clazy-child-event-qobject-cast,clazy-virtual-signal,clazy-overridden-signal,clazy-qhash-namespace,clazy-skipped-base-method,clazy-readlock-detaching"
$CLAZY_LEVEL2="clazy-ctor-missing-parent-argument,clazy-base-class-event,clazy-copyable-polymorphic,clazy-function-args-by-ref,clazy-function-args-by-value,clazy-global-const-char-pointer,clazy-implicit-casts,clazy-missing-qobject-macro,clazy-missing-typeinfo,clazy-old-style-connect,clazy-qstring-allocations,clazy-returning-void-expression,clazy-rule-of-three,clazy-virtual-call-ctor,clazy-static-pmf"
if ($clazyPlugin)
{
$clazyCommand = @("-load=${clazyPlugin}", "-checks=${CLAZY_LEVEL0},-overloaded-signal,qt-keywords")
} else {
$clazyCommand = @()
}
$clangCommand = $clazyCommand + @("-p", "$env:BUILD_DIR")
run-clang-tidy @clangCommand | Tee-Object -Path "$([System.IO.Path]::GetTempPath())/clang-tidy.log"
+13
View File
@@ -0,0 +1,13 @@
[GeneralSettings]
# creating cache files on github makes no sense
Packager/CreateCache = False
Paths/CCACHE_DIR = ${Env:HOME}/ccache
Compile/UseCCache = True
[linux-gcc-x86_64]
Environment/SourceCommand = export PKG_CONFIG_PATH=(/usr/bin/pkg-config --variable pc_path pkg-config) && source /opt/rh/gcc-toolset-14/enable
[linux-gcc-x86_64-debug]
Environment/SourceCommand = export PKG_CONFIG_PATH=(/usr/bin/pkg-config --variable pc_path pkg-config) && source /opt/rh/gcc-toolset-14/enable
+221
View File
@@ -0,0 +1,221 @@
name: QSfera Desktop CI
on:
push:
branches:
- main
- 'stable-[0-9]+.[0-9]+'
- 'stable-[0-9]+.[0-9]+.[0-9]+'
pull_request:
workflow_dispatch:
inputs:
releaseChannel:
description: 'The release channel'
required: true
default: 'stable'
type: choice
options:
- stable
- beta
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions: {}
defaults:
run:
shell: pwsh
jobs:
# ------------------------------------------------------------------------------------------------------------------------------------------
build:
permissions:
# actions/upload-artifact doesn't need contents: write
contents: read
strategy:
fail-fast: true
matrix:
include:
- target: windows-cl-msvc2022-x86_64
os: windows-latest
container:
- target: macos-clang-arm64
os: macos-latest
container:
- target: linux-gcc-x86_64
os: ubuntu-latest
container: invent-registry.kde.org/sysadmin/ci-images/craft-appimage:latest
name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}
env:
CRAFT_TARGET: ${{ matrix.target }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CRAFT_PACKAGE_SYMBOLS: ${{ github.event_name != 'pull_request' }}
container: ${{ matrix.container }}
steps:
- name: Check out full source code for tooling
if: ${{ matrix.target == 'linux-gcc-x86_64' }}
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check out latest commit
if: ${{ matrix.target != 'linux-gcc-x86_64' }}
uses: actions/checkout@v6
- name: Restore and update cache
if: github.event_name != 'pull_request'
uses: actions/cache@v5
with:
path: |
~/ccache
key: ${{ runner.os }}-${{ matrix.target }}-${{ github.run_id }} # generate a new key every time to trigger an update
restore-keys: ${{ runner.os }}-${{ matrix.target }}
- name: Restore cache
if: github.event_name == 'pull_request'
uses: actions/cache/restore@v5
with:
path: |
~/ccache
key: ${{ runner.os }}-${{ matrix.target }}
- name: Clone CraftMaster
run: |
git clone --depth=1 https://invent.kde.org/kde/craftmaster.git "${home}/craft/CraftMaster/CraftMaster"
- name: Craft setup
run: |
New-Item -Path ~/cache -ItemType Directory -ErrorAction SilentlyContinue
# disable git's safe.directory
git config --global --add safe.directory '*'
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" --setup
- name: Craft unshelve
run: |
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --unshelve "${env:GITHUB_WORKSPACE}/.craft.shelf"
# bootsrtap in case the shelf was empty
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c craft
# ccache
if (-not $IsWindows) {
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c dev-utils/ccache
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --run "ccache -M500MB"
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --run "ccache -s"
}
- name: Prepare
run: |
New-Item -ItemType Directory "${env:GITHUB_WORKSPACE}/binaries/"
# settings
if ("${{ github.ref_type }}" -ne "tag" -or "${{ inputs.releaseChannel }}" -eq "beta" ) {
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --set "forceAsserts=true" opencloud/opencloud-desktop
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --set "buildBeta=true" opencloud/opencloud-desktop
}
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --set "srcDir=${env:GITHUB_WORKSPACE}" opencloud/opencloud-desktop
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --set "buildNumber=${{ github.run_number }}" opencloud/opencloud-desktop
# optional deployment dependencies
if ($IsWindows) {
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c dev-utils/nsis
} elseif($IsLinux) {
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c dev-utils/linuxdeploy
# ensure we have fuse3-devel installed
dnf install -y fuse3-devel
}
- name: Install dependencies
run: |
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --install-deps opencloud/opencloud-desktop
- name: QML format lint
if: matrix.target == 'linux-gcc-x86_64'
run: |
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c libs/qt6/qttools
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --run pwsh -c "git ls-files "*.qml" "*.js" "*.mjs" | %{ qmlformat -i `$_}"
$diff = git diff
if ($diff) {
$diff
exit 1
}
- name: clang-format format lint
if: matrix.target == 'linux-gcc-x86_64'
run: |
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c libs/llvm
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --run git clang-format --force ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
$diff = git diff
if ($diff) {
$diff
exit 1
}
- name: Update Shelf
run: |
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --shelve "${env:GITHUB_WORKSPACE}/.craft.shelf"
Copy-Item "${env:GITHUB_WORKSPACE}/.craft.shelf" "${env:GITHUB_WORKSPACE}/binaries/craft.shelf"
- name: Build
run: |
if ("${{ matrix.target }}" -eq "macos-64-clang-debug" ) {
# https://api.kde.org/ecm/module/ECMEnableSanitizers.html
# address;leak;undefined
# clang: error: unsupported option '-fsanitize=leak' for target 'x86_64-apple-darwin21.6.0'
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --set args="-DECM_ENABLE_SANITIZERS='address;undefined'" opencloud/opencloud-desktop
}
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --no-cache opencloud/opencloud-desktop
- name: Run tests
run: |
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --no-cache --test opencloud/opencloud-desktop
- name: Clang tidy
if: ${{ github.event_name != 'pull_request' }}
run: |
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c libs/llvm dev-utils/clazy python-modules/pip
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --run python3 -m pip install clang-html
$env:BUILD_DIR = $(& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --get buildDir -q opencloud/opencloud-desktop)
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --run pwsh "${env:GITHUB_WORKSPACE}/.github/workflows/.run-clang-tidy.ps1"
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --run python3 -m clang_html "$([System.IO.Path]::GetTempPath())/clang-tidy.log" -o "${env:GITHUB_WORKSPACE}/binaries/clang-tidy.html"
- name: Package
if: matrix.target != 'macos-clang-arm64'
run: |
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --no-cache --package opencloud/opencloud-desktop
- name: Package Appx
if: ${{ matrix.os == 'windows-latest' && github.event_name != 'pull_request' }}
run: |
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --no-cache --package --options "[Packager]PackageType=AppxPackager" --options "[Packager]Destination=${{ github.workspace }}/appx/" opencloud/opencloud-desktop
- name: Prepare artifacts
run: |
Copy-Item "${home}/craft/binaries/*" "${env:GITHUB_WORKSPACE}/binaries/" -ErrorAction SilentlyContinue
if ("${{ github.ref_type }}" -eq "tag" ) {
Get-ChildItem "${env:GITHUB_WORKSPACE}/binaries/" | ForEach-Object {
$newName = $_.Name -replace "opencloud-desktop-HEAD-\d*-", "QSfera_Desktop-${{ github.ref_name }}-"
if ($newName -ne $_.Name) {
Move-Item -Path $_ -Destination (Join-Path $_.Directory $newName) -Force
}
}
}
- name: Upload artifacts
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.target }}-${{ github.run_number }}
path: ${{ github.workspace }}/binaries/*
- name: Upload appx
if: ${{ matrix.os == 'windows-latest' && github.event_name != 'pull_request' }}
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.target }}-appx-${{ github.run_number }}
path: ${{ github.workspace }}/appx/*
+30
View File
@@ -0,0 +1,30 @@
name: "Close stale issues"
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
permissions: {}
jobs:
stale:
permissions:
contents: write # only for delete-branch option
issues: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
debug-only: false
exempt-all-milestones: true
exempt-issue-labels: "blue-ticket, p1-urgent, p2-high, p3-medium, p4-low, QA:team"
days-before-stale: 30
stale-issue-message: "This issue was marked stale because it has been open for 30 days with no activity. Remove the stale label or comment or this will be closed in 7 days."
days-before-close: 7
close-issue-message: "The issue was marked as stale for 7 days and closed automatically."
start-date: "2021-01-01T00:00:00Z"
close-issue-reason: not_planned
# do not close any PRs
only-pr-labels: "never-close-any-prs"
+180
View File
@@ -0,0 +1,180 @@
.gitmodules
*build*/
*flymake*
CMakeLists.txt.user*
.vs/
CMakeSettings.json
*~
*.autosave
doc/_build/*
*.kate-swp
*.kdev4
admin/win/nsi/l10n/pofiles/*.po
*.swp
*~$
build*
cscope.*
tags
t1.cfg
.drone.yml
.idea
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
.drone-secrets.env
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Roslyn cache directories
*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# macOS specific
xcuserdata/
**/.DS_Store
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
## TODO: Comment the next line if you want to checkin your
## web deploy settings but do note that will include unencrypted
## passwords
*.pubxml
# NuGet Packages
packages/*
*.nupkg
## TODO: If the tool you use requires repositories.config
## uncomment the next line
#!packages/repositories.config
# Enable "build/" folder in the NuGet Packages folder since
# NuGet packages use it for MSBuild targets.
# This line needs to be after the ignore of the build folder
# (and the packages folder if the line above has been uncommented)
!packages/build/
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Microsoft Fakes
FakesAssemblies/
# Allow building.adoc to be tracked.
# This exclusion needs to be added at the end, after any previous
# reference to "build"
!building.adoc
# squish test
test/gui/config.ini
test/gui/reports
*/**/__pycache__/
+1
View File
@@ -0,0 +1 @@
$Format:%H$
+9
View File
@@ -0,0 +1,9 @@
[main]
host = https://www.transifex.com
[o:opencloud-eu:p:opencloud-eu:r:desktop]
source_file = translations/desktop_en.ts
source_lang = en
file_filter = translations/desktop_<lang>.ts
type = TS
minimum_perc = 75
+104
View File
@@ -0,0 +1,104 @@
variables:
- &build_image 'opencloudeu/desktop-client-build:ubuntu-24.04-qt6.10'
- &minio_image 'minio/mc:RELEASE.2021-10-07T04-19-58Z'
- &minio_environment
AWS_ACCESS_KEY_ID:
from_secret: cache_s3_access_key
AWS_SECRET_ACCESS_KEY:
from_secret: cache_s3_secret_key
CACHE_BUCKET:
from_secret: cache_s3_bucket
MC_HOST: 'https://s3.ci.opencloud.eu'
- &trigger_path
include:
- test/gui/**
- src/**
- cmake/**
- THEME.cmake
- VERSION.cmake
- CMakeLists.txt
- QSFERA.cmake
- .woodpecker/**
exclude:
- .woodpecker/ready-release-go.yaml
- .woodpecker/translation.yaml
- test/gui/manual-test-plan
when:
- branch:
- main
- stable-*
event:
- push
- manual
path:
<<: *trigger_path
- event: tag
- event: pull_request
path:
<<: *trigger_path
evaluate: |
!(CI_COMMIT_SOURCE_BRANCH matches "next-release/(main|stable-*)" && CI_COMMIT_AUTHOR == "openclouders")
- event: cron
cron: nightly*
workspace:
base: /woodpecker/
path: desktop
steps:
- name: check-caches
image: *minio_image
environment:
<<: *minio_environment
commands:
- mc alias set s3 $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY
- bash test/gui/woodpecker/script.sh check_python_cache
- bash test/gui/woodpecker/script.sh check_browsers_cache
- name: install-python-modules
image: *build_image
commands:
- . ./.woodpecker.env
- if $PYTHON_CACHE_FOUND; then exit 0; fi
- cd test/gui/
- python3 -m venv .venv --system-site-packages
- . .venv/bin/activate
- make pip-install
- tar -czf python-cache.tar.gz .venv
- name: install-browsers
image: *build_image
environment:
PLAYWRIGHT_BROWSERS_PATH: /woodpecker/desktop/test/gui/.playwright
commands:
- . ./.woodpecker.env
- if $BROWSER_CACHE_FOUND; then exit 0; fi
- cd test/gui/
- python3 -m venv .venv --system-site-packages
- . .venv/bin/activate
- grep "^playwright" requirements.txt | pip install -r /dev/stdin
- make install-chromium
- tar -czf playwright-browsers.tar.gz .playwright
- name: upload-browsers-cache
image: *minio_image
environment:
<<: *minio_environment
commands:
- . ./.woodpecker.env
- if $BROWSER_CACHE_FOUND; then exit 0; fi
- playwright_version=$(bash test/gui/woodpecker/script.sh get_playwright_version)
- mc alias set s3 $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY
- mc cp -r -a $CI_WORKSPACE/test/gui/playwright-browsers.tar.gz s3/$CACHE_BUCKET/desktop/browsers-cache/$playwright_version/
- name: upload-python-cache
image: *minio_image
environment:
<<: *minio_environment
commands:
- . ./.woodpecker.env
- if $PYTHON_CACHE_FOUND; then exit 0; fi
- requirements_sha=$(bash test/gui/woodpecker/script.sh get_requirementstxt_hash)
- mc alias set s3 $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY
- mc cp -r -a $CI_WORKSPACE/test/gui/python-cache*.tar.gz s3/$CACHE_BUCKET/desktop/python-cache/$requirements_sha/
+56
View File
@@ -0,0 +1,56 @@
variables:
- &golang_image 'docker.io/golang:1.24'
- &qa_repo 'https://github.com/opencloud-eu/qa.git'
- &qa_repo_branch 'main'
- &current_repo_id '11'
- &ci_woodpecker_url
from_secret: oc_ci_url
when:
- event:
- push
- manual
branch: ${CI_REPO_DEFAULT_BRANCH}
status:
- success
- failure
- event: pull_request
status:
- failure
- event: cron
cron: nightly*
status:
- success
- failure
depends_on:
- build
- ui-tests
skip_clone: true
steps:
- name: notify
image: *golang_image
environment:
HTTP_PROXY:
from_secret: ci_http_proxy
HTTPS_PROXY:
from_secret: ci_http_proxy
MATRIX_HOME_SERVER: matrix.org
MATRIX_ROOM_ALIAS:
from_secret: opencloud-notifications-channel
MATRIX_USER:
from_secret: opencloud-notifications-user
MATRIX_PASSWORD:
from_secret: opencloud-notifications-user-password
QA_REPO: *qa_repo
QA_REPO_BRANCH: *qa_repo_branch
CI_WOODPECKER_URL: *ci_woodpecker_url
CI_REPO_ID: *current_repo_id
CI_WOODPECKER_TOKEN: no-auth-needed-on-this-repo
commands:
- git clone --single-branch --branch $QA_REPO_BRANCH $QA_REPO /tmp/qa
- cd /tmp/qa/scripts/matrix-notification/
- if [ "$CI_PIPELINE_EVENT" = "cron" ]; then MESSAGE_SUFFIX_WHEN_FAILED="CC @artur @pradip.subedi @prashantgrg"; fi
- go run matrix-notification.go
+64
View File
@@ -0,0 +1,64 @@
variables:
- &minio_image 'minio/mc:RELEASE.2021-10-07T04-19-58Z'
- &minio_environment
AWS_ACCESS_KEY_ID:
from_secret: cache_s3_access_key
AWS_SECRET_ACCESS_KEY:
from_secret: cache_s3_secret_key
MC_HOST: 'https://s3.ci.opencloud.eu'
CACHE_BUCKET:
from_secret: cache_s3_bucket
PUBLIC_BUCKET: public
when:
- event:
- push
- manual
branch: ${CI_REPO_DEFAULT_BRANCH}
status:
- success
- failure
- event: pull_request
evaluate: |
!(CI_COMMIT_SOURCE_BRANCH matches "next-release/(main|stable-*)" && CI_COMMIT_AUTHOR == "openclouders")
status:
- success
- failure
- event: cron
cron: nightly*
status:
- success
- failure
depends_on:
- ui-tests
skip_clone: true
matrix:
include:
- JOB_NAME: purge-desktop-build
PURGE_PATH: desktop/client-build/
TTL: 1d
- JOB_NAME: purge-python-cache
PURGE_PATH: desktop/python-cache/
TTL: 14d
- JOB_NAME: purge-browsers-cache
PURGE_PATH: desktop/browsers-cache/
TTL: 14d
- JOB_NAME: purge-logs
PURGE_PATH: desktop/testlogs/
USE_PUBLIC_BUCKET: true
TTL: 7d
steps:
- name: ${JOB_NAME}
image: *minio_image
environment:
<<: *minio_environment
commands:
- mc alias set s3 "$MC_HOST" "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY"
- if [ "$USE_PUBLIC_BUCKET" = "true" ]; then CACHE_BUCKET=$PUBLIC_BUCKET; fi
- to_delete=$(mc find "s3/$CACHE_BUCKET/${PURGE_PATH}" --older-than "${TTL}")
- if [ "$to_delete" = "" ]; then exit 0; fi
- mc rm $to_delete
+12
View File
@@ -0,0 +1,12 @@
when:
event: push
branch: ${CI_REPO_DEFAULT_BRANCH}
steps:
- name: release-helper
image: woodpeckerci/plugin-ready-release-go:latest
settings:
git_email: devops@opencloud.eu
forge_type: github
forge_token:
from_secret: github_token
+43
View File
@@ -0,0 +1,43 @@
variables:
- &ubuntu_image 'ubuntu'
- &git_action_plugin 'quay.io/thegeeklab/wp-git-action:2'
when:
- event: cron
cron: translation-sync
steps:
- name: translation-update
image: *ubuntu_image
environment:
TX_TOKEN:
from_secret: tx_token
commands:
- apt update
- ln -fs /usr/share/zoneinfo/Europe/Berlin /etc/localtime
- apt install -y qt6-l10n-tools git curl
- rm translations/*.ts
- git checkout translations/desktop_en.ts
- /usr/lib/qt6/bin/lupdate src -no-obsolete -ts translations/desktop_en.ts
- curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
- . ~/.profile
- tx push -s
- rm -rf /tmp/tx
- tx pull --force --all
- rm tx LICENSE
- name: translation-push
image: *git_action_plugin
settings:
action:
- commit
- push
author_email: devops@opencloud.eu
author_name: opencloudeu
branch: ${CI_REPO_DEFAULT_BRANCH}
empty_commit: false
message: '[tx] updated from transifex'
netrc_password:
from_secret: github_token
netrc_username:
from_secret: github_username
+159
View File
@@ -0,0 +1,159 @@
variables:
- &opencloud_image 'quay.io/opencloudeu/opencloud-rolling:latest'
- &build_image 'opencloudeu/desktop-client-build:ubuntu-24.04-qt6.10'
- &minio_image 'minio/mc:RELEASE.2021-10-07T04-19-58Z'
- &alpine_image 'alpine:3.22.4'
- &minio_environment
AWS_ACCESS_KEY_ID:
from_secret: cache_s3_access_key
AWS_SECRET_ACCESS_KEY:
from_secret: cache_s3_secret_key
CACHE_BUCKET:
from_secret: cache_s3_bucket
MC_HOST: 'https://s3.ci.opencloud.eu'
PUBLIC_BUCKET: public
when:
- branch:
- main
- stable-*
event:
- push
- manual
- event: pull_request
- event: tag
- event: cron
cron: nightly*
depends_on:
- build
- cache-python
workspace:
base: /woodpecker
path: desktop
matrix:
include:
- MATRIX_NAME: gui-tests-1
SUITES: 'features/activity features/add-account features/delete-files-folders features/edit-files features/login-logout features/move-files-folders'
- MATRIX_NAME: gui-tests-2
SUITES: 'features/remove-account-connection features/spaces features/sync-resources features/tabs-settings features/vfs'
steps:
- name: restore-python-cache
image: *minio_image
environment:
<<: *minio_environment
commands:
- requirements_sha=$(sha1sum test/gui/requirements.txt | cut -d" " -f1)
- mc alias set s3 $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY
- mc cp -a s3/$CACHE_BUCKET/desktop/python-cache/$requirements_sha/python-cache.tar.gz $CI_WORKSPACE
- name: restore-browsers-cache
image: *minio_image
environment:
<<: *minio_environment
commands:
- playwright_version=$(bash test/gui/woodpecker/script.sh get_playwright_version)
- mc alias set s3 $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY
- mc cp -r -a s3/$CACHE_BUCKET/desktop/browsers-cache/$playwright_version/playwright-browsers.tar.gz $CI_WORKSPACE
- name: unzip-browsers-cache
image: owncloud/ubuntu:20.04
commands:
- cd test/gui
- tar -xf $CI_WORKSPACE/playwright-browsers.tar.gz -C ./
- name: install-python-modules
image: *build_image
environment:
PLAYWRIGHT_BROWSERS_PATH: /woodpecker/desktop/test/gui/.playwright
commands:
- cd test/gui
- tar -xf $CI_WORKSPACE/python-cache.tar.gz -C ./
- python3 -m venv .venv --system-site-packages
- . .venv/bin/activate
- make install
- python3 -m pip list -v
- name: opencloud
image: *opencloud_image
detach: true
environment:
FRONTEND_SEARCH_MIN_LENGTH: '2'
GRAPH_AVAILABLE_ROLES: b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5,a8d5fe5e-96e3-418d-825b-534dbdf22b99,fb6c3e19-e378-47e5-b277-9732f9de6e21,58c63c02-1d89-4572-916a-870abc5a1b7d,2d00ce52-1fc2-4dbc-8b95-a73b73395f5a,1c996275-f1c9-4e71-abdf-a42f6495e960,312c0871-5ef7-4b3a-85b6-0e4074c64049,aa97fe03-7980-45ac-9e50-b325749fd7e6,63e64e19-8d43-42ec-a738-2b6af2610efa
IDM_ADMIN_PASSWORD: admin
LDAP_GROUP_SUBSTRING_FILTER_TYPE: any
LDAP_USER_SUBSTRING_FILTER_TYPE: any
OC_INSECURE: true
OC_JWT_SECRET: some-opencloud-jwt-secret
OC_LOG_LEVEL: error
OC_SHOW_USER_EMAIL_IN_RESULTS: true
OC_URL: https://opencloud:9200
PROXY_ENABLE_BASIC_AUTH: true
WEB_UI_CONFIG_FILE: /woodpecker/desktop/test/gui/woodpecker/config-opencloud.json
commands:
- opencloud init
- opencloud server
- name: wait-for-opencloud
image: owncloudci/alpine:latest
commands:
- timeout 300 bash -c 'while [ $(curl -sk -uadmin:admin https://opencloud:9200/graph/v1.0/users/admin -w %{http_code} -o /dev/null) != 200 ]; do sleep 1; done'
- name: restore-desktop-client
image: *minio_image
environment:
<<: *minio_environment
commands:
- mc alias set s3 $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY
- mc cp -a -r s3/$CACHE_BUCKET/desktop/client-build/${CI_COMMIT_SHA}/ $CI_WORKSPACE/build
- ls -lh $CI_WORKSPACE/build/bin
- name: gui-tests
image: *build_image
environment:
# system cache environment variables
PYTHONUSERBASE: /woodpecker/desktop/test/gui/.venv
PLAYWRIGHT_BROWSERS_PATH: /woodpecker/desktop/test/gui/.playwright
# webdriver environment variables
WEBDRIVER_HOST: 0.0.0.0
WEBDRIVER_PORT: 4723
WEBDRIVER_RUNNER: /woodpecker/desktop/test/gui/woodpecker/run_atspi_webdriver.sh
# test environment variables
APP_PATH: /woodpecker/desktop/build/bin/qsfera
BACKEND_HOST: https://opencloud:9200
GUI_TEST_REPORT_DIR: /woodpecker/desktop/test/gui/reports
BEHAVE_TEST_DIR: /woodpecker/desktop/test/gui
# Cannot handle this tags format inside a container: --tags='@smoke and not @skip'
BEHAVE_PARAMETERS: '--tags=@smoke --tags=~@skip ${SUITES}'
# - name: crash-log
# image: *alpine_image
# when:
# - status:
# - success
# - failure
# commands:
# - cat test/gui/tmp/QSfera-crash.log 2>/dev/null || exit 0
- name: upload-test-reports
image: *minio_image
when:
- status: failure
environment:
<<: *minio_environment
commands:
- mc alias set s3 $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY
- mc cp -a -r $CI_WORKSPACE/test/gui/reports s3/$PUBLIC_BUCKET/desktop/testlogs/$CI_PIPELINE_NUMBER/$MATRIX_NAME
- name: gui-test-reports
image: *minio_image
when:
- status: failure
environment:
<<: *minio_environment
commands:
- mc alias set s3 $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY
- bash $CI_WORKSPACE/test/gui/woodpecker/gui_test_reports.sh
+98
View File
@@ -0,0 +1,98 @@
# Changelog
## [3.0.0](https://github.com/opencloud-eu/desktop/releases/tag/v3.0.0) - 2025-11-25
### ❤️ Thanks to all contributors! ❤️
@Copilot, @K900, @Svanvith, @TheOneRing, @anon-pradip, @fschade, @individual-it, @jnweiger, @kulmann, @prashant-gurung899, @saw-jan
### 💥 Breaking changes
- Remove unused code from UploadInfo [[#637](https://github.com/opencloud-eu/desktop/pull/637)]
- Implement a beta channel branding [[#489](https://github.com/opencloud-eu/desktop/pull/489)]
- Use utf16 for the rotating log, to reduce string conversions [[#467](https://github.com/opencloud-eu/desktop/pull/467)]
- Remove unused fields in sqlite table [[#419](https://github.com/opencloud-eu/desktop/pull/419)]
- Add Windows VFS [[#305](https://github.com/opencloud-eu/desktop/pull/305)]
- Enable http2 support by default [[#333](https://github.com/opencloud-eu/desktop/pull/333)]
### 🐛 Bug Fixes
- Terminate sync before an account is removed [[#699](https://github.com/opencloud-eu/desktop/pull/699)]
- Abort if tus did not receive a location header and the upload is not … [[#693](https://github.com/opencloud-eu/desktop/pull/693)]
- Ensure that a retry happens after the minimal ignorelist timeout [[#664](https://github.com/opencloud-eu/desktop/pull/664)]
- Eit error if .well-known was not found [[#663](https://github.com/opencloud-eu/desktop/pull/663)]
- Fix enqueing of paused folders [[#662](https://github.com/opencloud-eu/desktop/pull/662)]
- Pause sync before we terminate [[#642](https://github.com/opencloud-eu/desktop/pull/642)]
- Make sync scheduling more predictable [[#641](https://github.com/opencloud-eu/desktop/pull/641)]
- Don't persist invalid upload info [[#638](https://github.com/opencloud-eu/desktop/pull/638)]
- Fix quota not display until folder synced [[#622](https://github.com/opencloud-eu/desktop/pull/622)]
- Don't use mtime -1 [[#616](https://github.com/opencloud-eu/desktop/pull/616)]
- Properly abort sync on error [[#611](https://github.com/opencloud-eu/desktop/pull/611)]
- Fix plugin loading with ecm 6.19 [[#608](https://github.com/opencloud-eu/desktop/pull/608)]
- Modify APPLICATION_REV_DOMAIN in beta builds to make coinstallable [[#587](https://github.com/opencloud-eu/desktop/pull/587)]
- Only count enabled spaces when computing the number of spaces to sync [[#571](https://github.com/opencloud-eu/desktop/pull/571)]
- Abort sync if connection is lost [[#562](https://github.com/opencloud-eu/desktop/pull/562)]
- Fix: Attempted sync on non syncable Folder [[#533](https://github.com/opencloud-eu/desktop/pull/533)]
- Don't mark restorations as excluded [[#498](https://github.com/opencloud-eu/desktop/pull/498)]
- Sync Scheduler: Ensure the current sync is actually running [[#452](https://github.com/opencloud-eu/desktop/pull/452)]
- Fix leak of accountstates [[#445](https://github.com/opencloud-eu/desktop/pull/445)]
- Fix color for selected space [[#437](https://github.com/opencloud-eu/desktop/pull/437)]
- Don't truncate inode on Windows [[#412](https://github.com/opencloud-eu/desktop/pull/412)]
- Fix printing of duration [[#400](https://github.com/opencloud-eu/desktop/pull/400)]
- Don't try LockFile on directories [[#366](https://github.com/opencloud-eu/desktop/pull/366)]
- OAuth: Only display user name in an error if we have one [[#355](https://github.com/opencloud-eu/desktop/pull/355)]
### 📈 Enhancement
- Ensure the version is included in the crash log [[#691](https://github.com/opencloud-eu/desktop/pull/691)]
- change help URL to the right docs URL [[#466](https://github.com/opencloud-eu/desktop/pull/466)]
- Folder watcher: ignore changes in short lived files [[#455](https://github.com/opencloud-eu/desktop/pull/455)]
- Fix assert in httplogger if a cached request is actuall send [[#456](https://github.com/opencloud-eu/desktop/pull/456)]
- Sync description and space name to Windows [[#443](https://github.com/opencloud-eu/desktop/pull/443)]
- Replace csync C code with std::filesystem [[#393](https://github.com/opencloud-eu/desktop/pull/393)]
- Remove margins around the content widgets [[#377](https://github.com/opencloud-eu/desktop/pull/377)]
### 📦️ Dependencies
- Bump actions/checkout from 5 to 6 [[#709](https://github.com/opencloud-eu/desktop/pull/709)]
- Bump actions/upload-artifact from 4 to 5 [[#620](https://github.com/opencloud-eu/desktop/pull/620)]
- Bump actions/checkout from 4 to 5 [[#502](https://github.com/opencloud-eu/desktop/pull/502)]
- Bump actions/stale from 9 to 10 [[#520](https://github.com/opencloud-eu/desktop/pull/520)]
## [2.0.0](https://github.com/opencloud-eu/desktop/releases/tag/v2.0.0) - 2025-07-03
### ❤️ Thanks to all contributors! ❤️
@TheOneRing, @anon-pradip, @individual-it, @michaelstingl, @prashant-gurung899
### 💥 Breaking changes
- Enable http2 support by default [[#333](https://github.com/opencloud-eu/desktop/pull/333)]
- Since Qt 6.8 network headers are normalized to lowercase [[#308](https://github.com/opencloud-eu/desktop/pull/308)]
- Remove Theme::linkSharing and Theme::userGroupSharing [[#279](https://github.com/opencloud-eu/desktop/pull/279)]
- Remove unsupported solid avatar color branding [[#280](https://github.com/opencloud-eu/desktop/pull/280)]
- Remove Theme::wizardUrlPostfix [[#278](https://github.com/opencloud-eu/desktop/pull/278)]
- Read preconfigured server urls [[#275](https://github.com/opencloud-eu/desktop/pull/275)]
- Require global settings to always be located in /etc/ [[#268](https://github.com/opencloud-eu/desktop/pull/268)]
- Move default exclude file to a resource [[#266](https://github.com/opencloud-eu/desktop/pull/266)]
### 🐛 Bug Fixes
- OAuth: Only display user name in an error if we have one [[#355](https://github.com/opencloud-eu/desktop/pull/355)]
- Fix reuse of existing Space folders [[#311](https://github.com/opencloud-eu/desktop/pull/311)]
- Retry oauth refresh if wellknown request failed [[#310](https://github.com/opencloud-eu/desktop/pull/310)]
- Update KDSingleApplication to 1.2.0 [[#293](https://github.com/opencloud-eu/desktop/pull/293)]
- Fix casing of Spaces [[#272](https://github.com/opencloud-eu/desktop/pull/272)]
- Restart the client if the server url changed [[#254](https://github.com/opencloud-eu/desktop/pull/254)]
- Directly schedule sync once the etag changed [[#253](https://github.com/opencloud-eu/desktop/pull/253)]
- Update quota exeeded message [[#248](https://github.com/opencloud-eu/desktop/pull/248)]
- Fix sync location with manual setup [[#243](https://github.com/opencloud-eu/desktop/pull/243)]
- Properly handle `server_error` response from IDP [[#231](https://github.com/opencloud-eu/desktop/pull/231)]
### 📈 Enhancement
- Remove settings update from connection validator, update settings only oce per hour [[#301](https://github.com/opencloud-eu/desktop/pull/301)]
- Handle return key for the url wizard page [[#300](https://github.com/opencloud-eu/desktop/pull/300)]
- Show profile images in Desktop Client [[#297](https://github.com/opencloud-eu/desktop/pull/297)]
- Enable native tooltips for the accounts on Qt >= 6.8.3 [[#255](https://github.com/opencloud-eu/desktop/pull/255)]
- Update dependencies to Qt 6.8.3 and OpenSSL 3.4.1 [[#252](https://github.com/opencloud-eu/desktop/pull/252)]
+160
View File
@@ -0,0 +1,160 @@
cmake_minimum_required(VERSION 3.18)
include(VERSION.cmake)
project(QSferaDesktop LANGUAGES CXX VERSION ${MIRALL_VERSION_MAJOR}.${MIRALL_VERSION_MINOR}.${MIRALL_VERSION_PATCH})
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(FeatureSummary)
find_package(ECM 6.0.0 REQUIRED NO_MODULE)
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules")
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH})
# disable pointless warning in KDECMakeSettings
set(APPLE_SUPPRESS_X11_WARNING ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
include(KDEInstallDirs)
include(KDECMakeSettings)
include(ECMMarkNonGuiExecutable)
include(ECMSetupVersion)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(ECMEnableSanitizers)
include(ECMQmlModule)
find_package(Qt6 COMPONENTS Core Concurrent Network Widgets Xml Quick QuickWidgets QuickControls2 Linguist REQUIRED)
qt6_standard_project_setup(REQUIRES 6.8)
get_target_property (QT_QMAKE_EXECUTABLE Qt::qmake IMPORTED_LOCATION)
message(STATUS "Using Qt ${Qt6_VERSION_MAJOR}.${Qt6_VERSION_MINOR}.${Qt6_VERSION_PATCH} (${QT_QMAKE_EXECUTABLE})")
if (UNIX AND NOT APPLE)
find_package(Qt6 REQUIRED COMPONENTS DBus)
endif()
if(UNIT_TESTING)
message(DEPRECATION "Setting UNIT_TESTING is deprecated please use BUILD_TESTING")
set(BUILD_TESTING TRUE)
endif()
include(CTest)
include(OCBundleResources)
include(OCApplyCommonSettings)
include("${CMAKE_CURRENT_LIST_DIR}/THEME.cmake")
if(NOT WITH_CRASHREPORTER)
message(STATUS "Build of crashreporter disabled.")
else()
# obviously, a crash reported without the URL set is pretty pointless and won't work
if(NOT DEFINED CRASHREPORTER_SUBMIT_URL)
message(FATAL_ERROR "No crash reporter submit URL provided")
endif()
endif()
include(GenerateExportHeader)
include(GetGitRevisionDescription)
# used in src/csync/CMakeLists.txt
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
# if we cannot get it from git, directly try .tag (packages)
# this will work if the tar balls have been properly created
# via git-archive.
if ("${GIT_SHA1}" STREQUAL "GITDIR-NOTFOUND")
file(READ ${CMAKE_SOURCE_DIR}/.tag sha1_candidate)
string(REPLACE "\n" "" sha1_candidate ${sha1_candidate})
if (NOT ${sha1_candidate} STREQUAL "$Format:%H$")
message("${sha1_candidate}")
set (GIT_SHA1 "${sha1_candidate}")
endif()
endif()
message(STATUS "GIT_SHA1 ${GIT_SHA1}")
option(NO_MSG_HANDLER "Don't redirect QDebug outputs to the log window/file" OFF)
if (APPLE)
# this option builds the shell integration, currently only available on MacOS
option(BUILD_SHELL_INTEGRATION "BUILD_SHELL_INTEGRATION" ON)
endif()
# build the auto updater component
option(WITH_AUTO_UPDATER "WITH_AUTO_UPDATER" OFF)
option(WITH_UPDATE_NOTIFICATION "Whether to check for new releases" ON)
# create a co-installable client, that uses a separate profile
option(BETA_CHANNEL_BUILD "Use a standalone profile for a beta release" OFF)
# build with -DQT_FORCE_ASSERTS
option(FORCE_ASSERTS "FORCE_ASSERTS" OFF)
option(WITH_APPIMAGEUPDATER OFF "Enable built-in libappimageupdate based updater on Linux")
add_feature_info(AppImageUpdate WITH_APPIMAGEUPDATER "Built-in libappimageupdate based updater")
option(WITH_EXTERNAL_BRANDING "A URL to an external branding repo" "")
# specify additional vfs plugins
set(VIRTUAL_FILE_SYSTEM_PLUGINS off cfapi openvfs CACHE STRING "Name of internal plugin in src/libsync/vfs or the locations of virtual file plugins")
if(APPLE)
set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesign key's TeamIdentifier/Organizational Unit" )
endif()
if (WITH_AUTO_UPDATER)
if(APPLE)
find_package(Sparkle REQUIRED)
endif(APPLE)
if(WITH_APPIMAGEUPDATER)
find_package(AppImageUpdate REQUIRED)
endif()
endif()
if(UNIX AND NOT APPLE)
find_package(Inotify REQUIRED)
endif()
find_package(ZLIB REQUIRED)
find_package(SQLite3 3.9.0 REQUIRED)
# in the ownBrander themes, the icon files are named after the shortname
# the theme included in this repository defines a custom icon name, therefore we set the shortname as a fallback if the
# theme does not define the variable
if (NOT DEFINED APPLICATION_ICON_NAME)
set(APPLICATION_ICON_NAME "${APPLICATION_SHORTNAME}")
endif()
file(GLOB_RECURSE QSFERA_ICONS "${OEM_THEME_DIR}/theme/colored/*-${APPLICATION_ICON_NAME}-icon.png")
MESSAGE(STATUS "QSFERA_ICONS: ${APPLICATION_ICON_NAME}: ${QSFERA_ICONS}")
add_subdirectory(src)
if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/admin)
add_subdirectory(admin)
endif(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/admin)
if(BUILD_SHELL_INTEGRATION)
add_subdirectory(shell_integration)
endif()
if(BUILD_TESTING)
add_subdirectory(test)
endif()
if(ECM_VERSION VERSION_GREATER_EQUAL 5.79)
message(STATUS "Suitable ECM ${ECM_VERSION} found, installing clang-format git hook")
include(KDEGitCommitHooks)
kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)
else()
message(WARNING "ECM ${ECM_VERSION} too old, cannot install clang-format git hook")
endif()
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES INCLUDE_QUIET_PACKAGES)
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
+39
View File
@@ -0,0 +1,39 @@
# Shipping
This readme file is for distribution packagers and provides some reasoning and hints about shipping the desktop client for a seamless experience on the Linux desktop.
For that, `КуСфера` and the distributions need to collaborate.
## Integration Problems
`КуСфера` can be shipped as an AppImage because it is independent of the underlying distro and easy to install, as long as the distribution is not providing a package on its own which is frequently updated.
With AppImage, there comes one problem: For the integration into the desktop file managers which are provided by the distribution (such as Dolphin for KDE and Nautilus), icons and partly also binary code is needed. That is needed to provide the necessary information to enable the file managers to show for example icon overlays.
So far, the necessary code and resources were bundled with the desktop client code, but now the desktop shell integrations resources were split off, so that they can be released and shipped separately.
## Solution
The idea is that everything that is needed to integrate into the desktop apps such as dolphin are part of the Linux distribution that any user chooses to use. Ideally they are packages maintained downstream in the Linux distributions and can be installed via the native package management.
Since these parts are very rarely changing, these packages are very stable and thus, packaging efforts a very, very low.
The actual client code, which changes far more often, is either also provided by the Linux distro downstream or by `КуСфера` as an AppImage. Shipping an AppImage reduces the effort to package for all distros out there.
User now only have to install the AppImage with the latest client, and the shell integrations from their Linux distro package management. The AppImage based client automagically connects to the shell integration code and the overlay icons and menu additions in the file managers work.
With that, the user gets on the one hand very frequently updated desktop clients directly from the project, and nice integration with the desktop technology that is delivered from the distribution.
## Packaging Hints
Here are some hints for packagers of Linux distributions to provide the best `КуСфера` integration experience:
The shell integrations are available for KDE Dolphin, Nautilus and Caja. While KDE Dolphin needs compiled code, the latter two are using Python.
Each of them should be available as separate distro package, so that they can be suggested to complement "their" file manager.
All of these packages should depend on the desktop extension resources package, which basically only contains the overlay icons. They can optionally be branded with a distro-specific theme.
None of the three file manager integration packages (for Dolphin, Nautilus or Caja) need a dependency on the main `КуСфера` package anymore, so that they do not change in foreseeable times.
If the distro decides to ship an own package of the client or lets their user install the provided AppImage, the experience will be perfect in any case.
+23
View File
@@ -0,0 +1,23 @@
set( APPLICATION_NAME "КуСфера")
set( APPLICATION_SHORTNAME "QSfera" )
set( APPLICATION_EXECUTABLE "qsfera" )
set( APPLICATION_VENDOR "QSfera" )
set( APPLICATION_ICON_NAME "qsfera" )
set( APPLICATION_REV_DOMAIN "eu.qsfera.desktop" )
set( APPLICATION_DEFAULT_SERVER_URL "https://qsfera.kusoft.xyz" )
if(BETA_CHANNEL_BUILD)
set( APPLICATION_NAME "${APPLICATION_NAME} Beta")
set( APPLICATION_SHORTNAME "${APPLICATION_SHORTNAME} Beta" )
set( APPLICATION_EXECUTABLE "${APPLICATION_EXECUTABLE}_beta" )
set( APPLICATION_VENDOR "${APPLICATION_VENDOR} Beta" )
set( APPLICATION_REV_DOMAIN "${APPLICATION_REV_DOMAIN}.beta" )
endif()
# TODO: re enable once we got icons
#set( MAC_INSTALLER_BACKGROUND_FILE "${CMAKE_SOURCE_DIR}/admin/osx/installer-background.png")
set( THEME_CLASS "QSferaTheme" )
set( THEME_INCLUDE "qsferatheme.h" )
option( WITH_CRASHREPORTER "Build crashreporter" OFF )
+21
View File
@@ -0,0 +1,21 @@
# `КуСфера`
## Introduction
`КуСфера` — настольный клиент синхронизации файлов для сервера QSfera; исполняемый файл и пакетные идентификаторы используют `qsfera`/`QSfera`.
## Build
Branding defaults are defined in `QSFERA.cmake`. The generated desktop entry uses `qsfera.desktop.in`, and the command-line desktop entry uses `qsferacmd.desktop.in`.
## License
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.
+33
View File
@@ -0,0 +1,33 @@
if(WITH_EXTERNAL_BRANDING)
include(FetchContent)
FetchContent_Declare(branding
GIT_REPOSITORY ${WITH_EXTERNAL_BRANDING}
GIT_TAG main
)
FetchContent_MakeAvailable(branding)
set(OEM_THEME_DIR ${branding_SOURCE_DIR} CACHE STRING "The directory containing a custom theme")
else()
if (EXISTS "${PROJECT_SOURCE_DIR}/branding")
set(OEM_THEME_DIR "${PROJECT_SOURCE_DIR}/branding" CACHE STRING "The directory containing a custom theme")
else()
set(OEM_THEME_DIR "${PROJECT_SOURCE_DIR}/src/resources/" CACHE STRING "Define directory containing a custom theme")
endif()
endif()
if (EXISTS "${OEM_THEME_DIR}/OEM.cmake")
include("${OEM_THEME_DIR}/OEM.cmake")
else()
include ("${CMAKE_CURRENT_LIST_DIR}/QSFERA.cmake")
endif()
message(STATUS "Branding: ${APPLICATION_NAME}")
if(NOT CRASHREPORTER_EXECUTABLE)
set(CRASHREPORTER_EXECUTABLE "${APPLICATION_EXECUTABLE}_crash_reporter")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/VERSION.cmake")
+19
View File
@@ -0,0 +1,19 @@
set( MIRALL_VERSION_MAJOR 4 )
set( MIRALL_VERSION_MINOR 0 )
set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_VERSION_YEAR 2026 )
set( MIRALL_SOVERSION 0 )
if( NOT DEFINED MIRALL_VERSION_BUILD )
set( MIRALL_VERSION_BUILD "0" ) # Integer ID. Generated by the build system
endif( NOT DEFINED MIRALL_VERSION_BUILD )
# Composite defines
# Used e.g. for libraries Keep at x.y.z.
set( MIRALL_VERSION "${MIRALL_VERSION_MAJOR}.${MIRALL_VERSION_MINOR}.${MIRALL_VERSION_PATCH}" )
# Version with Build ID. Used in the installer
set( MIRALL_VERSION_FULL "${MIRALL_VERSION}" )
if( MIRALL_VERSION_BUILD )
set( MIRALL_VERSION_FULL "${MIRALL_VERSION_FULL}.${MIRALL_VERSION_BUILD}" )
endif( MIRALL_VERSION_BUILD )
set( MIRALL_VERSION_STRING "${MIRALL_VERSION_FULL}" )
+2
View File
@@ -0,0 +1,2 @@
# traverse into osx subdirectory to install and patch the create-pack script
add_subdirectory(osx)
+39
View File
@@ -0,0 +1,39 @@
Param
(
[string]$ProductName="QSfera"
)
<#
.SYNOPSIS
Cleans up leftover Windows VFS sync roots and CLSID entries.
.DESCRIPTION
Removes registry entries for specified product and test artifacts.
WARNING: This script will restart Windows Explorer.
.PARAMETER ProductName
The product name to clean up. Defaults to "QSfera".
.NOTES
Requires Administrator privileges.
#>
# OC-TEST is used by our unit tests
# https://github.com/MicrosoftDocs/winrt-api/issues/1130
$SyncRootManager = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SyncRootManager"
$GetRootItem = Get-Item $SyncRootManager
Get-ChildItem -Path $SyncRootManager | ForEach-Object {
$name = $_.Name.Substring($GetRootItem.Name.Length + 1)
if ($name.StartsWith("OC-TEST", [System.StringComparison]::CurrentCultureIgnoreCase) -or $name.StartsWith("$ProductName", [System.StringComparison]::CurrentCultureIgnoreCase)) {
Write-Host "Removing sync root: ${name} `"${_}`""
Remove-Item -Recurse $_.PsPath
}
}
Get-ChildItem -Path "HKCU:\Software\Classes\CLSID\" | ForEach-Object {
$key = (get-itemproperty $_.PsPath)."(default)"
if ($key) {
if ($key.StartsWith("OC-TEST", [System.StringComparison]::CurrentCultureIgnoreCase) -or $key.StartsWith("$ProductName", [System.StringComparison]::CurrentCultureIgnoreCase)) {
Write-Host "Removing: ${key} `"${_}`""
Remove-Item -Recurse $_.PsPath
}
}
}
Get-Process explorer | Stop-Process
Pause
+16
View File
@@ -0,0 +1,16 @@
# Check if variable MAC_INSTALLER_BACKGROUND_FILE is defined. That might come
# from the OEM.cmake for branded clients or from QSFERA.cmake for the non
# branded client.
# Make sure that the MAC_INSTALLER_BACKGROUND_FILE contains the full path, ie.
# includes CMAKE_SOURCE_DIR or so.
if (DEFINED MAC_INSTALLER_BACKGROUND_FILE )
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "true")
else()
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "false")
endif()
configure_file(macosx.pkgproj.cmake ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj @ONLY)
configure_file(pre_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh @ONLY)
configure_file(post_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/post_install.sh @ONLY)
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
enable-background="new 0 0 595.275 311.111"
xml:space="preserve"
height="200"
width="320"
version="1.1"
y="0px"
x="0px"
viewBox="0 0 35 0"
id="svg2"
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
sodipodi:docname="installer-background.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata
id="metadata12"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs10" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1301"
id="namedview8"
showgrid="false"
inkscape:zoom="1.18"
inkscape:cx="-49.576271"
inkscape:cy="100.84746"
inkscape:window-x="1280"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="svg2"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" /><rect
x="0"
y="0"
width="320"
height="200"
fill="#20434f"
id="rect1"
style="stroke-width:0.494105" /><g
id="g1"
transform="matrix(0.390625,0,0,0.390625,59.992188,0)"><polygon
points="255.98,342.75 271.89,333.57 271.89,267.12 329.08,234.1 329.08,215.78 313.18,206.6 255.6,239.84 198.83,207.06 182.93,216.24 182.93,234.56 240.12,267.58 240.12,333.59 "
fill="#e2baff"
id="polygon1" /><polygon
points="256,103.24 401.95,187.5 401.95,150.82 256,66.56 110.05,150.82 110.05,187.5 "
fill="#e2baff"
id="polygon2" /><polygon
points="256,445.43 401.95,361.17 401.95,324.5 256,408.76 110.06,324.5 110.06,361.17 "
fill="#e2baff"
id="polygon3" /></g></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+987
View File
@@ -0,0 +1,987 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PACKAGES</key>
<array>
<dict>
<key>MUST-CLOSE-APPLICATION-ITEMS</key>
<array/>
<key>MUST-CLOSE-APPLICATIONS</key>
<false/>
<key>PACKAGE_FILES</key>
<dict>
<key>DEFAULT_INSTALL_LOCATION</key>
<string>/</string>
<key>HIERARCHY</key>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>@APPLICATION_SHORTNAME@.app</string>
<key>PATH_TYPE</key>
<integer>3</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>3</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Utilities</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Applications</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>509</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Application Support</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Documentation</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Filesystems</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Frameworks</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Input Methods</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Internet Plug-Ins</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>LaunchAgents</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>LaunchDaemons</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>PreferencePanes</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Preferences</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Printers</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>PrivilegedHelperTools</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>1005</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>QuickLook</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>QuickTime</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Screen Savers</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Scripts</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Services</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Widgets</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Automator</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Extensions</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Library</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Extensions</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Library</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>System</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Shared</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>1023</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Users</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>/</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<key>PAYLOAD_TYPE</key>
<integer>0</integer>
<key>PRESERVE_EXTENDED_ATTRIBUTES</key>
<false/>
<key>SHOW_INVISIBLE</key>
<false/>
<key>SPLIT_FORKS</key>
<true/>
<key>TREAT_MISSING_FILES_AS_WARNING</key>
<false/>
<key>VERSION</key>
<integer>5</integer>
</dict>
<key>PACKAGE_SCRIPTS</key>
<dict>
<key>POSTINSTALL_PATH</key>
<dict>
<key>PATH</key>
<string>@CMAKE_CURRENT_BINARY_DIR@/post_install.sh</string>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>PREINSTALL_PATH</key>
<dict>
<key>PATH</key>
<string>@CMAKE_CURRENT_BINARY_DIR@/pre_install.sh</string>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>RESOURCES</key>
<array/>
</dict>
<key>PACKAGE_SETTINGS</key>
<dict>
<key>AUTHENTICATION</key>
<integer>1</integer>
<key>CONCLUSION_ACTION</key>
<integer>0</integer>
<key>FOLLOW_SYMBOLIC_LINKS</key>
<false/>
<key>IDENTIFIER</key>
<string>@APPLICATION_REV_DOMAIN@</string>
<key>LOCATION</key>
<integer>0</integer>
<key>NAME</key>
<string>@APPLICATION_NAME@</string>
<key>OVERWRITE_PERMISSIONS</key>
<false/>
<key>PAYLOAD_SIZE</key>
<integer>-1</integer>
<key>REFERENCE_PATH</key>
<string></string>
<key>RELOCATABLE</key>
<false/>
<key>USE_HFS+_COMPRESSION</key>
<false/>
<key>VERSION</key>
<string>@MIRALL_VERSION_FULL@</string>
</dict>
<key>TYPE</key>
<integer>0</integer>
<key>UUID</key>
<string>7D7219B7-1897-48C3-8533-842BDEC46F71</string>
</dict>
</array>
<key>PROJECT</key>
<dict>
<key>PROJECT_COMMENTS</key>
<dict>
<key>NOTES</key>
<data>
PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1M
IDQuMDEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQv
c3RyaWN0LmR0ZCI+CjxodG1sPgo8aGVhZD4KPG1ldGEgaHR0cC1l
cXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7
IGNoYXJzZXQ9VVRGLTgiPgo8bWV0YSBodHRwLWVxdWl2PSJDb250
ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp
dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u
dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD
b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjEzNDMuMTQiPgo8c3R5bGUg
dHlwZT0idGV4dC9jc3MiPgo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5
Pgo8L2JvZHk+CjwvaHRtbD4K
</data>
</dict>
<key>PROJECT_PRESENTATION</key>
<dict>
<key>BACKGROUND</key>
<dict>
<key>ALIGNMENT</key>
<integer>6</integer>
<key>APPAREANCES</key>
<dict>
<key>DARK_AQUA</key>
<dict>
<key>ALIGNMENT</key>
<integer>6</integer>
<key>BACKGROUND_PATH</key>
<dict>
<key>PATH</key>
<string>@MAC_INSTALLER_BACKGROUND_FILE@</string>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>CUSTOM</key>
<true/>
<key>LAYOUT_DIRECTION</key>
<integer>0</integer>
<key>SCALING</key>
<integer>0</integer>
</dict>
<key>LIGHT_AQUA</key>
<dict>
<key>ALIGNMENT</key>
<integer>6</integer>
<key>BACKGROUND_PATH</key>
<dict>
<key>PATH</key>
<string>@MAC_INSTALLER_BACKGROUND_FILE@</string>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>CUSTOM</key>
<true/>
<key>LAYOUT_DIRECTION</key>
<integer>0</integer>
<key>SCALING</key>
<integer>0</integer>
</dict>
</dict>
<key>BACKGROUND_PATH</key>
<dict>
<key>PATH</key>
<string>@MAC_INSTALLER_BACKGROUND_FILE@</string>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>CUSTOM</key>
<@MAC_INSTALLER_DO_CUSTOM_BACKGROUND@/>
<key>LAYOUT_DIRECTION</key>
<integer>0</integer>
<key>SCALING</key>
<integer>0</integer>
<key>SHARED_SETTINGS_FOR_ALL_APPAREANCES</key>
<true/>
</dict>
<key>INSTALLATION TYPE</key>
<dict>
<key>HIERARCHIES</key>
<dict>
<key>INSTALLER</key>
<dict>
<key>LIST</key>
<array>
<dict>
<key>DESCRIPTION</key>
<array/>
<key>OPTIONS</key>
<dict>
<key>HIDDEN</key>
<false/>
<key>STATE</key>
<integer>1</integer>
</dict>
<key>PACKAGE_UUID</key>
<string>7D7219B7-1897-48C3-8533-842BDEC46F71</string>
<key>TITLE</key>
<array/>
<key>TOOLTIP</key>
<array/>
<key>TYPE</key>
<integer>0</integer>
<key>UUID</key>
<string>9647ADC0-BD53-4D7D-A561-73D383AACDE1</string>
</dict>
</array>
<key>REMOVED</key>
<dict/>
</dict>
</dict>
<key>MODE</key>
<integer>1</integer>
</dict>
<key>INSTALLATION_STEPS</key>
<array>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewIntroductionController</string>
<key>INSTALLER_PLUGIN</key>
<string>Introduction</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewReadMeController</string>
<key>INSTALLER_PLUGIN</key>
<string>ReadMe</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewLicenseController</string>
<key>INSTALLER_PLUGIN</key>
<string>License</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewDestinationSelectController</string>
<key>INSTALLER_PLUGIN</key>
<string>TargetSelect</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewInstallationTypeController</string>
<key>INSTALLER_PLUGIN</key>
<string>PackageSelection</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewInstallationController</string>
<key>INSTALLER_PLUGIN</key>
<string>Install</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewSummaryController</string>
<key>INSTALLER_PLUGIN</key>
<string>Summary</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
</array>
<key>INTRODUCTION</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
</dict>
<key>LICENSE</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
<key>MODE</key>
<integer>0</integer>
</dict>
<key>README</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
</dict>
<key>SUMMARY</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
</dict>
<key>TITLE</key>
<dict>
<key>LOCALIZATIONS</key>
<array>
<dict>
<key>LANGUAGE</key>
<string>English</string>
<key>VALUE</key>
<string>@APPLICATION_NAME@</string>
</dict>
</array>
</dict>
</dict>
<key>PROJECT_REQUIREMENTS</key>
<dict>
<key>LIST</key>
<array/>
<key>RESOURCES</key>
<array/>
<key>ROOT_VOLUME_ONLY</key>
<false/>
</dict>
<key>PROJECT_SETTINGS</key>
<dict>
<key>ADVANCED_OPTIONS</key>
<dict>
<key>installer-script.domains:enable_localSystem</key>
<integer>1</integer>
</dict>
<key>BUILD_FORMAT</key>
<integer>0</integer>
<key>BUILD_PATH</key>
<dict>
<key>PATH</key>
<string>@CMAKE_INSTALL_PREFIX@/.</string>
<key>PATH_TYPE</key>
<integer>3</integer>
</dict>
<key>EXCLUDED_FILES</key>
<array>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.DS_Store</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove .DS_Store files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove ".DS_Store" files created by the Finder.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.pbdevelopment</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove .pbdevelopment files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove ".pbdevelopment" files created by ProjectBuilder or Xcode.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>CVS</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.cvsignore</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.cvspass</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.svn</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.git</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.gitignore</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove SCM metadata</string>
<key>PROXY_TOOLTIP</key>
<string>Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>classes.nib</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>designable.db</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>info.nib</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Optimize nib files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>Resources Disabled</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove Resources Disabled folders</string>
<key>PROXY_TOOLTIP</key>
<string>Remove "Resources Disabled" folders.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>SEPARATOR</key>
<true/>
</dict>
</array>
<key>NAME</key>
<string>@APPLICATION_NAME@ Installer</string>
<key>PAYLOAD_ONLY</key>
<false/>
<key>REFERENCE_FOLDER_PATH</key>
<string></string>
<key>TREAT_MISSING_PRESENTATION_DOCUMENTS_AS_WARNING</key>
<false/>
</dict>
</dict>
<key>TYPE</key>
<integer>0</integer>
<key>VERSION</key>
<integer>2</integer>
</dict>
</plist>
+27
View File
@@ -0,0 +1,27 @@
#!/bin/bash
## log stdout stderr and set -x to a file
# exec > ~/@APPLICATION_EXECUTABLE@-post-install.log
# exec 2>&1
# BASH_XTRACEFD=1
# set -x
LOGGED_IN_USER_ID=$(id -u "${USER}")
# Always enable the new 10.10 finder plugin if available
if [[ -x "$(command -v pluginkit)" ]]; then
# add it to DB. This happens automatically too but we try to push it a bit harder for issue #3463
pluginkit -a "/Applications/@APPLICATION_EXECUTABLE@.app/Contents/PlugIns/FinderSyncExt.appex/"
# Since El Capitan we need to sleep #4650
sleep 10s
# enable it
pluginkit -e use -i "@APPLICATION_REV_DOMAIN@.FinderSyncExt"
fi
if [[ -f "${INSTALLER_TEMP}/OC_RESTART_NEEDED" ]]; then
if [[ "${COMMAND_LINE_INSTALL}" = "" ]]; then
/bin/launchctl kickstart "gui/${LOGGED_IN_USER_ID}/@APPLICATION_REV_DOMAIN@"
fi
fi
exit 0
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
## log stdout stderr and set -x to a file
# exec > "~/@APPLICATION_EXECUTABLE@-pre-install.log"
# exec 2>&1
# BASH_XTRACEFD=1
# set -x
# don't grep in one line, to avaoid grepping the grep process...
PROCESSES=$(ps aux)
OC_INSTANCE=$(echo "${PROCESSES}" | grep "/Applications/@APPLICATION_EXECUTABLE@.app/Contents/MacOS/@APPLICATION_EXECUTABLE@")
if [[ "${OC_INSTANCE}" != "" ]]; then
kill $(echo "${OC_INSTANCE}" | awk '{print $2}')
touch $INSTALLER_TEMP/OC_RESTART_NEEDED
fi
exit 0
+12
View File
@@ -0,0 +1,12 @@
-----BEGIN PUBLIC KEY-----
MIIBtzCCASsGByqGSM44BAEwggEeAoGBANC50nTWzroQwwawgaV4jd5TjjqbGKDH
6CWbZzyfJ246mJcrwTfM2h5Z80GwLSNFBIjtLGpFd7Wd+CI1dY8oIOYxnYgWDSJC
Al1RMoUSSwx0LRr8J3gojcvvsrhk/t57o9bjXynE2tiP1fwzPb+B3NH/02fMnzfH
k+B8/8GOnX8dAhUA9PZ1QrH/mN+7ckiGjmoegZdv9tMCgYBPEj2850r8+9tXljU4
X0s1NKBfiyhBGw/quJMZ3k0fQ/tpOyYwXYBg+9GBVc4pF1CKMVGoBS6XnLrZ1OkC
OP9g+NNH5cLOKrBxjtd1GPG8UF/sZpak2sVfuNKzRtFT/6WFHc3f7C+LiDFZ2aPO
A+Kr5MZJ8xxYDYj16WV2nKgoQgOBhQACgYEAuQzycfUZKm7MR9WZSFF9uQ3N3SQr
PKYggCl6GTdWYmrsFyXLEBmb3m2qXxx9AcfR2LdkTp/CRCzm+HD6wyHVAAVG2kI2
mWafcahlx/lVMd2yytdRE5pjpjLxw7rrt/fvSZsGwUswQJLl4iDWoE+mFfaaZnnM
JKoiKLX7LUFOPaU=
-----END PUBLIC KEY-----
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Inspired by https://github.com/sparkle-project/Sparkle/issues/896#issuecomment-339904848
if [ "${#}" -ne 3 ]; then
echo "$(basename ${0}):"
echo
echo " This script can be used to verify the .tbz.sig file in releases during manual testing"
echo " It does the same verification as Sparkle but is itself *not* used by Sparkle."
echo
echo " Usage: ${0} public_key_path update_archive_path base64_signature_content"
echo
exit 1
fi
set -euxo pipefail
# Make sure we are using system openssl and not one from brew
openssl() {
/usr/bin/openssl "${@}"
}
openssl dgst -sha1 -binary < "${2}" | openssl dgst -sha1 -verify "${1}" -signature <(echo "${3}" | openssl enc -base64 -d)
@@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+13
View File
@@ -0,0 +1,13 @@
CMake - Cross Platform Makefile Generator
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of Kitware, Inc., the Insight Software Consortium, nor the names of their contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+66
View File
@@ -0,0 +1,66 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindSQLite3
-----------
Find the SQLite libraries, v3
IMPORTED targets
^^^^^^^^^^^^^^^^
This module defines the following :prop_tgt:`IMPORTED` target:
``SQLite::SQLite3``
Result variables
^^^^^^^^^^^^^^^^
This module will set the following variables if found:
``SQLite3_INCLUDE_DIRS``
where to find sqlite3.h, etc.
``SQLite3_LIBRARIES``
the libraries to link against to use SQLite3.
``SQLite3_VERSION``
version of the SQLite3 library found
``SQLite3_FOUND``
TRUE if found
#]=======================================================================]
# Look for the necessary header
find_path(SQLite3_INCLUDE_DIR NAMES sqlite3.h)
mark_as_advanced(SQLite3_INCLUDE_DIR)
# Look for the necessary library
find_library(SQLite3_LIBRARY NAMES sqlite3 sqlite)
mark_as_advanced(SQLite3_LIBRARY)
# Extract version information from the header file
if(SQLite3_INCLUDE_DIR)
file(STRINGS ${SQLite3_INCLUDE_DIR}/sqlite3.h _ver_line
REGEX "^#define SQLITE_VERSION *\"[0-9]+\\.[0-9]+\\.[0-9]+\""
LIMIT_COUNT 1)
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+"
SQLite3_VERSION "${_ver_line}")
unset(_ver_line)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SQLite3
REQUIRED_VARS SQLite3_INCLUDE_DIR SQLite3_LIBRARY
VERSION_VAR SQLite3_VERSION)
# Create the imported target
if(SQLite3_FOUND)
set(SQLite3_INCLUDE_DIRS ${SQLite3_INCLUDE_DIR})
set(SQLite3_LIBRARIES ${SQLite3_LIBRARY})
if(NOT TARGET SQLite::SQLite3)
add_library(SQLite::SQLite3 UNKNOWN IMPORTED)
set_target_properties(SQLite::SQLite3 PROPERTIES
IMPORTED_LOCATION "${SQLite3_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${SQLite3_INCLUDE_DIR}")
endif()
endif()
+21
View File
@@ -0,0 +1,21 @@
# Find Sparkle.framework
#
# Once done this will define
# SPARKLE_FOUND - system has Sparkle
# SPARKLE_LIBRARY - The framework needed to use Sparkle
# Copyright (c) 2009, Vittorio Giovara <vittorio.giovara@gmail.com>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
include(FindPackageHandleStandardArgs)
find_library(SPARKLE_LIBRARY NAMES Sparkle)
find_package_handle_standard_args(Sparkle DEFAULT_MSG SPARKLE_LIBRARY)
mark_as_advanced(SPARKLE_LIBRARY)
@@ -0,0 +1,116 @@
# - Returns a version string from Git
#
# These functions force a re-configure on each git commit so that you can
# trust the values of the variables in your build system.
#
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
#
# Returns the refspec and sha hash of the current head revision
#
# git_describe(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the source tree, and adjusting
# the output so that it tests false if an error occurs.
#
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe --exact-match on the source tree,
# and adjusting the output so that it tests false if there was no exact
# matching tag.
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
if(__get_git_revision_description)
return()
endif()
set(__get_git_revision_description YES)
# We must run the following at "include" time, not at function call time,
# to find the path to this module rather than the path to a calling list file
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
function(get_git_head_revision _refspecvar _hashvar)
set(GIT_DIR "${PROJECT_SOURCE_DIR}/.git")
if (NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
return()
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
if(NOT EXISTS "${GIT_DIR}/HEAD")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
"${GIT_DATA}/grabRef.cmake"
@ONLY)
include("${GIT_DATA}/grabRef.cmake")
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
return()
endif()
# TODO sanitize
#if((${ARGN}" MATCHES "&&") OR
# (ARGN MATCHES "||") OR
# (ARGN MATCHES "\\;"))
# message("Please report the following error to the project!")
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
#endif()
#message(STATUS "Arguments to execute_process: ${ARGN}")
execute_process(COMMAND
"${GIT_EXECUTABLE}"
describe
${hash}
${ARGN}
WORKING_DIRECTORY
"${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE
res
OUTPUT_VARIABLE
out
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var} "${out}" PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
set(${_var} "${out}" PARENT_SCOPE)
endfunction()
@@ -0,0 +1,38 @@
#
# Internal file for GetGitRevisionDescription.cmake
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
set(HEAD_HASH)
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
if(HEAD_CONTENTS MATCHES "ref")
# named branch
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
set(HEAD_HASH "${HEAD_REF}")
endif()
else()
# detached HEAD
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
endif()
if(NOT HEAD_HASH)
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
string(STRIP "${HEAD_HASH}" HEAD_HASH)
endif()
@@ -0,0 +1,37 @@
include(OCApplyCommonSettings)
function(add_vfs_plugin)
set(options "")
set(oneValueArgs NAME)
set(multiValueArgs SRC LIBS)
cmake_parse_arguments(__PLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
add_library(vfs_${__PLUGIN_NAME} MODULE
${__PLUGIN_SRC}
)
apply_common_target_settings(vfs_${__PLUGIN_NAME})
set_target_properties(vfs_${__PLUGIN_NAME} PROPERTIES OUTPUT_NAME "QSfera_vfs_${__PLUGIN_NAME}")
target_link_libraries(vfs_${__PLUGIN_NAME} PRIVATE
libsync
${__PLUGIN_LIBS}
)
if(APPLE)
set_target_properties(vfs_${__PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "$<TARGET_FILE_DIR:qsfera>/../PlugIns/")
# make the plugins available to the tests
add_custom_command(TARGET vfs_${__PLUGIN_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND}
ARGS -E create_symlink "$<TARGET_FILE:vfs_${__PLUGIN_NAME}>" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<TARGET_FILE_NAME:vfs_${__PLUGIN_NAME}>")
else()
install(TARGETS vfs_${__PLUGIN_NAME} DESTINATION "${KDE_INSTALL_PLUGINDIR}")
endif()
if (TARGET qsfera)
add_dependencies(qsfera vfs_${__PLUGIN_NAME})
endif()
if (TARGET cmd)
add_dependencies(cmd vfs_${__PLUGIN_NAME})
endif()
endfunction()
@@ -0,0 +1,70 @@
include(OCRcVersion)
if (MSVC)
# ecm sets /W3 we set /W4
string(REGEX REPLACE "/W3" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()
# common target settings that are used by all important targets
function(apply_common_target_settings targetName)
add_windows_version_info(${targetName})
if(FORCE_ASSERTS)
target_compile_definitions(${targetName}
PRIVATE
QT_FORCE_ASSERTS
)
endif()
target_compile_definitions(${targetName}
PRIVATE
QT_NO_CAST_TO_ASCII
QT_NO_CAST_FROM_ASCII
QT_NO_URL_CAST_FROM_STRING
QT_NO_CAST_FROM_BYTEARRAY
QT_USE_QSTRINGBUILDER
QT_MESSAGELOGCONTEXT # enable function name and line number in debug output
QT_NO_FOREACH
QT_DISABLE_DEPRECATED_BEFORE=0x060200
QT_NO_CONTEXTLESS_CONNECT
)
if(WIN32)
target_compile_definitions(${targetName}
PRIVATE
# Get APIs from from Win10 onwards.
_WIN32_WINNT=_WIN32_WINNT_WIN10
WINVER=_WIN32_WINNT_WIN10
NTDDI_VERSION=NTDDI_WIN10_RS2
)
endif()
if(MSVC)
target_compile_options(${targetName}
PRIVATE
# enable linter like warnings with msvc
# this includes deprecations
# https://learn.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level?view=msvc-170
/W4
# treat unhandled switch cases as error
/we4062
# Worder
/w15038
# werror on unused function
# The given function is local and not referenced in the body of the module; therefore, the function is dead code.
/we4505
# 4505 for anonymous namespaces, apparently undocumented https://developercommunity.visualstudio.com/t/warning-C4505-missing-on-anonymous-names/10413660
/we5245
/we4930
# A variable is declared and initialized but not used.
/we4189
)
elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
target_compile_options(${targetName}
PRIVATE
# treat unhandled switch cases as error
-Werror=switch
-Werror=unused-function
-Werror=unused-but-set-variable
)
endif()
endfunction()
@@ -0,0 +1,170 @@
function(__add_file_to_qrc_file)
set(options "")
set(oneValueArgs QRC_PATH FILE_PATH ALIAS)
set(multiValueArgs)
cmake_parse_arguments(__ADD_FILE_TO_QRC_FILE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
foreach(param QRC_PATH FILE_PATH)
if(NOT __ADD_FILE_TO_QRC_FILE_${param})
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Argument missing: ${param}")
endif()
endforeach()
set(line "<file ")
if(__ADD_FILE_TO_QRC_FILE_ALIAS)
set(line "${line} alias=\"${__ADD_FILE_TO_QRC_FILE_ALIAS}\"")
endif()
set(line "${line}>${__ADD_FILE_TO_QRC_FILE_FILE_PATH}</file>")
file(APPEND ${__ADD_FILE_TO_QRC_FILE_QRC_PATH} " ${line}\n")
endfunction()
function(__addIcon QRC_PATH THEME ICON_NAME)
set(options)
set(oneValueArgs SRC_PATH)
set(multiValueArgs)
cmake_parse_arguments(_ICON "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT _ICON_SRC_PATH)
set(_ICON_SRC_PATH ${THEME})
endif()
set(icon "theme/${_ICON_SRC_PATH}/${ICON_NAME}.svg")
set(iconAlias "${APPLICATION_SHORTNAME}/theme/${THEME}/${ICON_NAME}.svg")
if (EXISTS ${OEM_THEME_DIR}/${icon})
file(APPEND "${QRC_PATH}" "<file alias=\"${iconAlias}\">${OEM_THEME_DIR}/${icon}</file>\n")
else()
set(icon "theme/${_ICON_SRC_PATH}/${ICON_NAME}.png")
set(iconAlias "${APPLICATION_SHORTNAME}/theme/${THEME}/${ICON_NAME}.png")
if (EXISTS ${OEM_THEME_DIR}/${icon})
__add_file_to_qrc_file(
QRC_PATH ${QRC_PATH}
FILE_PATH ${OEM_THEME_DIR}/${icon}
ALIAS ${iconAlias}
)
else()
set(SIZES "16;22;32;48;64;128;256;512;1024")
foreach(size ${SIZES})
set(icon "theme/${_ICON_SRC_PATH}/${ICON_NAME}-${size}.png")
set(iconAlias "${APPLICATION_SHORTNAME}/theme/${THEME}/${ICON_NAME}-${size}.png")
if (EXISTS ${OEM_THEME_DIR}/${icon})
__add_file_to_qrc_file(
QRC_PATH ${QRC_PATH}
FILE_PATH ${OEM_THEME_DIR}/${icon}
ALIAS ${iconAlias}
)
endif()
endforeach()
endif()
endif()
endfunction()
function(__write_qrc_file_header QRC_PATH FILES_PREFIX)
file(WRITE ${QRC_PATH} "<RCC>\n")
file(APPEND ${QRC_PATH} " <qresource prefix=\"/client/\">\n")
endfunction()
function(__write_qrc_file_footer QRC_PATH)
file(APPEND ${QRC_PATH} " </qresource>\n")
file(APPEND ${QRC_PATH} "</RCC>\n")
endfunction()
# add the icons for url buttons to the theme
function(__addUrlIcons QRC_PATH)
file(GLOB_RECURSE QSFERA_URL_ICONS "${OEM_THEME_DIR}/theme/universal/urlIcons/*")
foreach(icon ${QSFERA_URL_ICONS})
get_filename_component(iconName ${icon} NAME_WE)
__addIcon(${QRC_PATH} "universal" "urlIcons/${iconName}")
endforeach()
endfunction()
function(generate_theme TARGET QSFERA_SIDEBAR_ICONS_OUT)
if(NOT "${OEM_THEME_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}/src/resources/")
set(QRC_PATH ${CMAKE_CURRENT_BINARY_DIR}/theme.qrc)
__write_qrc_file_header(${QRC_PATH} theme)
# ownbrander
__addIcon(${QRC_PATH} "universal" "${APPLICATION_ICON_NAME}-icon" SRC_PATH "colored")
__addIcon(${QRC_PATH} "universal" "wizard_logo" SRC_PATH "colored")
# full theme
__addIcon(${QRC_PATH} "universal" "${APPLICATION_ICON_NAME}-icon")
__addIcon(${QRC_PATH} "universal" "wizard_logo")
__addUrlIcons(${QRC_PATH})
foreach(theme IN ITEMS colored dark black white)
foreach(state IN ITEMS ok error information offline pause sync)
__addIcon(${QRC_PATH} ${theme} "state-${state}")
endforeach()
endforeach()
__write_qrc_file_footer(${QRC_PATH})
target_sources(${TARGET} PRIVATE ${QRC_PATH})
target_compile_definitions(${TARGET} PRIVATE BRANDING_AVAILABLE)
# add executable icon on windows and osx
file(GLOB_RECURSE QSFERA_SIDEBAR_ICONS "${OEM_THEME_DIR}/theme/colored/*-${APPLICATION_ICON_NAME}-sidebar.png")
else()
file(GLOB_RECURSE QSFERA_SIDEBAR_ICONS "${OEM_THEME_DIR}/theme/colored/*-${APPLICATION_ICON_NAME}-icon-sidebar.png")
endif()
if (NOT QSFERA_SIDEBAR_ICONS)
message(WARNING "The branding does not provide sidebar icons falling back to vanilla icons")
file(GLOB_RECURSE QSFERA_SIDEBAR_ICONS "${PROJECT_SOURCE_DIR}/src/resources/theme/colored/*-qsfera-icon-sidebar.png")
endif()
set(${QSFERA_SIDEBAR_ICONS_OUT} ${QSFERA_SIDEBAR_ICONS} PARENT_SCOPE)
endfunction()
function(generate_qrc_file)
set(options "")
set(oneValueArgs QRC_PATH PREFIX)
set(multiValueArgs FILES)
cmake_parse_arguments(GENERATE_QRC_FILE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
foreach(param ${oneValueArgs} ${multiValueArgs})
if(NOT GENERATE_QRC_FILE_${param})
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Argument missing: ${param}")
endif()
endforeach()
__write_qrc_file_header(${GENERATE_QRC_FILE_QRC_PATH} ${GENERATE_QRC_FILE_PREFIX})
foreach(file ${GENERATE_QRC_FILE_FILES})
get_filename_component(file_name ${file} NAME)
set(file_alias ${GENERATE_QRC_FILE_PREFIX}/${file_name})
__add_file_to_qrc_file(
QRC_PATH ${GENERATE_QRC_FILE_QRC_PATH}
FILE_PATH ${file}
ALIAS ${file_alias}
)
endforeach()
__write_qrc_file_footer(${GENERATE_QRC_FILE_QRC_PATH})
endfunction()
# add resources to a target using the Qt resources system
# parameters:
# - TARGET: the target to bundle the resources with
# - PREFIX: virtual "subdirectory" the files will be available from
# - FILES: the files to bundle
function(add_resources_to_target)
set(options "")
set(oneValueArgs TARGET PREFIX)
set(multiValueArgs FILES)
cmake_parse_arguments(ADD_RESOURCES_TO_TARGET "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
foreach(param ${oneValueArgs} ${multiValueArgs})
if(NOT ADD_RESOURCES_TO_TARGET_${param})
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Argument missing: ${param}")
endif()
endforeach()
set(qrc_path ${CMAKE_CURRENT_BINARY_DIR}/${ADD_RESOURCES_TO_TARGET_TARGET}-${ADD_RESOURCES_TO_TARGET_PREFIX}.qrc)
generate_qrc_file(
QRC_PATH ${qrc_path}
PREFIX ${ADD_RESOURCES_TO_TARGET_PREFIX}
FILES "${ADD_RESOURCES_TO_TARGET_FILES}"
)
target_sources(${ADD_RESOURCES_TO_TARGET_TARGET} PRIVATE ${qrc_path})
endfunction()
+31
View File
@@ -0,0 +1,31 @@
set(_VERSION_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
include(${PROJECT_SOURCE_DIR}/VERSION.cmake)
include(${PROJECT_SOURCE_DIR}/THEME.cmake)
function(add_windows_version_info targetName)
if(NOT WIN32)
return()
endif()
if(MIRALL_VERSION_BUILD)
set(OC_RC_VERSION_BUILD ${MIRALL_VERSION_BUILD})
else()
set(OC_RC_VERSION_BUILD 0)
endif()
get_target_property(TARGET_TYPE ${targetName} TYPE)
if(${TARGET_TYPE} STREQUAL "EXECUTABLE")
set(OC_RC_TYPE "VFT_APP")
elseif(${TARGET_TYPE} STREQUAL "SHARED_LIBRARY" OR ${TARGET_TYPE} STREQUAL "MODULE_LIBRARY")
set(OC_RC_TYPE "VFT_DLL")
else()
# only create version.rc for dll's and executables
return()
endif()
set(OC_RC_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${targetName}-oc_rc_version.rc)
configure_file(${_VERSION_SOURCE_DIR}/version.rc.in ${OC_RC_OUTPUT} @ONLY)
target_sources(${targetName} PRIVATE ${OC_RC_OUTPUT})
endfunction()
+34
View File
@@ -0,0 +1,34 @@
#include <winresrc.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION @MIRALL_VERSION_MAJOR@,@MIRALL_VERSION_MINOR@,@MIRALL_VERSION_PATCH@,@OC_RC_VERSION_BUILD@
PRODUCTVERSION @MIRALL_VERSION_MAJOR@,@MIRALL_VERSION_MINOR@,@MIRALL_VERSION_PATCH@,@OC_RC_VERSION_BUILD@
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS__WINDOWS32
FILETYPE @OC_RC_TYPE@
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "@APPLICATION_VENDOR@\0"
VALUE "LegalCopyright", "Copyright (C) 2025 OpenCloud GmbH\r\nCopyright (C) 2014-@MIRALL_VERSION_YEAR@ ownCloud GmbH\0"
VALUE "FileVersion", "@MIRALL_VERSION_FULL@\0"
VALUE "Comments", "@MIRALL_VERSION_STRING@\0"
VALUE "FileDescription", "@APPLICATION_NAME@\0"
VALUE "ProductName", "@APPLICATION_NAME@\0"
VALUE "ProductVersion", "@MIRALL_VERSION_STRING@\0"
END
END
BLOCK "VarFileInfo"
BEGIN
// English US, Unicode
VALUE "Translation", 0x0409, 1200
END
END
+17
View File
@@ -0,0 +1,17 @@
# configuration for Black.
# NOTE: you have to use single-quoted strings in TOML for regular expressions.
# It's the equivalent of r-strings in Python. Multiline strings are treated as
# verbose regular expressions by Black. Use [ ] to denote a significant space
# character.
[tool.black]
line-length = 88
target-version = ['py36', 'py37', 'py38']
include = '\.pyi?$'
skip-string-normalization = true
extend-exclude = '''
# A regex preceded with ^/ will apply only to files and directories
# in the root of the project.
/test/gui/shared/scripts/names.py
'''
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

+170
View File
@@ -0,0 +1,170 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Exec=@APPLICATION_EXECUTABLE@ --showsettings
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
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Settings;Quit;
StartupWMClass=@APPLICATION_EXECUTABLE@
# Translations
Comment[oc]=@APPLICATION_NAME@ sincronizacion del client
GenericName[oc]=Dorsièr de Sincronizacion
Name[oc]=@APPLICATION_NAME@ sincronizacion del client
Comment[ar]=@APPLICATION_NAME@ زبون مزامنة مكتبي
GenericName[ar]=مزامنة المجلد
Name[ar]=@APPLICATION_NAME@ زبون مزامنة مكتبي
Comment[bg_BG]=@APPLICATION_NAME@ клиент за десктоп синхронизация
GenericName[bg_BG]=Синхронизиране на папката
Name[bg_BG]=@APPLICATION_NAME@ клиент десктоп синхронизация
Comment[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
GenericName[ca]=Sincronització de carpetes
Name[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
Comment[da]=@APPLICATION_NAME@ skrivebordsklient til synkronisering
GenericName[da]=Mappesynkronisering
Name[da]=@APPLICATION_NAME@ skrivebordsklient til synk
Comment[de]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
GenericName[de]=Ordner-Synchronisation
Name[de]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
Comment[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
GenericName[ja_JP]=フォルダー同期
Name[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
Comment[el]=@APPLICATION_NAME@ συγχρονισμός επιφάνειας εργασίας πελάτη
GenericName[el]=Συγχρονισμός φακέλου
Name[el]=@APPLICATION_NAME@ συγχρονισμός επιφάνειας εργασίας πελάτη
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
GenericName[en_GB]=Folder Sync
Name[en_GB]=@APPLICATION_NAME@ desktop sync client
Comment[es]=@APPLICATION_NAME@ cliente de sincronización de escritorio
GenericName[es]=Sincronización de carpeta
Name[es]=@APPLICATION_NAME@ cliente de sincronización de escritorio
Comment[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
GenericName[de_DE]=Ordner-Synchronisation
Name[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
Comment[eu]=@APPLICATION_NAME@ mahaigaineko sinkronizazio bezeroa
GenericName[eu]=Karpetaren sinkronizazioa
Name[eu]=@APPLICATION_NAME@ mahaigaineko sinkronizazio bezeroa
GenericName[fa]=همسان سازی پوشه‌ها
Name[fa]=@APPLICATION_EXECUTABLE@ نسخه‌ی همسان سازی مشتری
Comment[fr]=Client de synchronisation @APPLICATION_NAME@
GenericName[fr]=Synchronisation de dossier
Name[fr]=Client de synchronisation @APPLICATION_NAME@
Comment[gl]=@APPLICATION_NAME@ cliente de sincronización para escritorio
GenericName[gl]=Sincronizar Cartafol
Name[gl]=@APPLICATION_NAME@ cliente de sincronización para escritorio
Comment[he]=@APPLICATION_NAME@ לקוח סנכון שולחן עבודה
GenericName[he]=סנכון תיקייה
Name[he]=@APPLICATION_NAME@ לקוח סנכרון שולחן עבודה
Comment[ia]=@APPLICATION_NAME@ cliente de synchronisation pro scriptorio
GenericName[ia]=Synchronisar Dossier
Name[ia]=@APPLICATION_NAME@ cliente de synchronisation pro scriptorio
Comment[id]=Klien sinkronisasi desktop @APPLICATION_NAME@
GenericName[id]=Folder Sync
Name[id]=Klien sync desktop @APPLICATION_NAME@
Comment[is]=@APPLICATION_NAME@ skjáborðsforrit samstillingar
GenericName[is]=Samstilling möppu
Name[is]=@APPLICATION_NAME@ skjáborðsforrit samstillingar
Comment[it]=Client di sincronizzazione del desktop di @APPLICATION_NAME@
GenericName[it]=Sincronizzazione cartella
Name[it]=Client di sincronizzazione del desktop di @APPLICATION_NAME@
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
GenericName[ko]=폴더 동기화
Name[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
Comment[lo]=@APPLICATION_NAME@ ການປະສານຂໍ້ມູນຄອມພິວເຕີລູກຂ່າຍ
GenericName[lo]=ໂຟນເດີຊິງ
Name[lo]=@APPLICATION_NAME@ ຊິງຄອມພິວເຕີລູກຂ່າຍ
Comment[mk]=@APPLICATION_NAME@ десктор клиент за синхронизација
GenericName[mk]=Папка за синхронизација
Name[mk]=@APPLICATION_NAME@ десктор клиент за синхронизација
Comment[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
GenericName[hu_HU]=Mappaszinkronizálás
Name[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
Comment[af_ZA]=@APPLICATION_NAME@ werkskermsinchroniseerkliënt
GenericName[af_ZA]=Vouersinchronisering
Name[af_ZA]=@APPLICATION_NAME@ werkskermsinchroniseerkliënt
Comment[nl]=@APPLICATION_NAME@ desktop synchronisatie client
GenericName[nl]=Mappen sync
Name[nl]=@APPLICATION_NAME@ desktop sync client
Comment[et_EE]=@APPLICATION_NAME@ sünkroonimise klient töölauale
GenericName[et_EE]=Kaustade sünkroonimine
Name[et_EE]=@APPLICATION_NAME@ sünkroonimise klient töölauale
Comment[pl]=@APPLICATION_NAME@ klient synchronizacji dla komputerów stacjonarnych
GenericName[pl]=Folder Synchronizacji
Name[pl]=@APPLICATION_NAME@ klient synchronizacji dla komputerów stacjonarnych
Comment[pt_BR]=@APPLICATION_NAME@ cliente de sincronização do computador
GenericName[pt_BR]=Sincronização de Pasta
Name[pt_BR]=@APPLICATION_NAME@ cliente de sincronização de desktop
Comment[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
GenericName[cs_CZ]=Synchronizace adresáře
Name[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
Comment[ru]=Настольный клиент синхронизации @APPLICATION_NAME@
GenericName[ru]=Синхронизация каталогов
Name[ru]=Настольный клиент синхронизации @APPLICATION_NAME@
Comment[sl]=@APPLICATION_NAME@ Program za usklajevanje datotek z namizjem
GenericName[sl]=Usklajevanje map
Name[sl]=@APPLICATION_NAME@ Program za usklajevanje datotek z namizjem
Comment[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
GenericName[sq]=Njëkohësim Dosjesh
Name[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
Comment[fi_FI]=@APPLICATION_NAME@ työpöytäsynkronointisovellus
GenericName[fi_FI]=Kansion synkronointi
Name[fi_FI]=@APPLICATION_NAME@ työpöytäsynkronointisovellus
Comment[sv]=@APPLICATION_NAME@ desktop synkroniseringsklient
GenericName[sv]=Mappsynk
Name[sv]=@APPLICATION_NAME@ desktop synk-klient
Comment[tr]=@APPLICATION_NAME@ masaüstü eşitleme istemcisi
GenericName[tr]=Dosya Eşitleme
Name[tr]=@APPLICATION_NAME@ masaüstü eşitleme istemcisi
Comment[uk]=Настільний клієнт синхронізації @APPLICATION_NAME@
GenericName[uk]=Синхронізація теки
Name[uk]=Настільний клієнт синхронізації @APPLICATION_NAME@
Comment[ro]=@APPLICATION_NAME@ client de sincronizare pe desktop
GenericName[ro]=Sincronizare director
Name[ro]=@APPLICATION_NAME@ client de sincronizare pe desktop
Comment[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
GenericName[zh_CN]=文件夹同步
Name[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
Comment[zh_HK]=桌面版同步客户端
Comment[zh_TW]=@APPLICATION_NAME@ 桌面同步客戶端
GenericName[zh_TW]=資料夾同步
Name[zh_TW]=@APPLICATION_NAME@ 桌面同步客戶端
Comment[es_AR]=Cliente de sincronización para escritorio @APPLICATION_NAME@
GenericName[es_AR]=Sincronización de directorio
Name[es_AR]=Cliente de sincronización para escritorio @APPLICATION_NAME@
Comment[lt_LT]=@APPLICATION_NAME@ darbalaukio sinchronizavimo programa
GenericName[lt_LT]=Katalogo sinchnorizacija
Name[lt_LT]=@APPLICATION_NAME@ darbalaukio programa
Comment[th_TH]=@APPLICATION_NAME@ ประสานข้อมูลด้วยโปรแกรมบนเดสก์ท็อป
GenericName[th_TH]=ประสานข้อมูลโฟลเดอร์
Name[th_TH]= @APPLICATION_NAME@ ประสานข้อมูลด้วยโปรแกรมบนเดสก์ท็อป
Comment[es_MX]=Cliente de escritorio para sincronziación de @APPLICATION_NAME@
GenericName[es_MX]=Sincronización de Carpetas
Name[es_MX]=Cliente de escritorio para sincronziación de @APPLICATION_NAME@
Comment[nb_NO]=@APPLICATION_NAME@ skrivebordssynkroniseringsklient
GenericName[nb_NO]=Mappesynkronisering
Name[nb_NO]=@APPLICATION_NAME@ skrivebordssynkroniseringsklient
Comment[nn_NO]=@APPLICATION_NAME@ klient for å synkronisera frå skrivebord
GenericName[nn_NO]=Mappe synkronisering
Name[nn_NO]=@APPLICATION_NAME@ klient for å synkronisera frå skrivebord
Comment[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização para PC
GenericName[pt_PT]=Sincronizar Pasta
Name[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização para PC
Comment[lb]=@APPLICATION_NAME@ Desktop Synchronisatioun Client
GenericName[lb]=Dossier Dync
Name[lb]=@APPLICATION_NAME@ Desktop Sync Client
[Desktop Action Settings]
Exec=@APPLICATION_EXECUTABLE@ --showsettings
Name=Show @APPLICATION_NAME@ settings
Icon=@APPLICATION_ICON_NAME@
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_ICON_NAME@
+12
View File
@@ -0,0 +1,12 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Terminal=true
Exec=@APPLICATION_EXECUTABLE@cmd
Name=@APPLICATION_NAME@ commandline sync client
Comment=@APPLICATION_NAME@ commandline synchronization client
GenericName=Folder Sync Commandline
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-AppImage-Integrate=false
NoDisplay=true
+112
View File
@@ -0,0 +1,112 @@
export default {
changeTypes: [
{
title: '💥 Breaking changes',
labels: ['breaking', 'Type:Breaking-Change'],
bump: 'major',
weight: 3
},
{
title: '🔒 Security',
labels: ['security', 'Type:Security'],
bump: 'patch',
weight: 2
},
{
title: '✨ Features',
labels: ['feature', 'Type:Feature'],
bump: 'minor',
weight: 1
},
{
title: '📈 Enhancement',
labels: ['enhancement', 'refactor', 'Type:Enhancement'],
bump: 'minor'
},
{
title: '🐛 Bug Fixes',
labels: ['bug', 'Type:Bug'],
bump: 'patch'
},
{
title: '📦️ Dependencies',
labels: ['dependency', 'dependencies', 'Type:Dependencies'],
bump: 'patch',
weight: -1
}
],
useVersionPrefixV: true,
getLatestTag: ({ exec }) => {
// the plugin uses the latest tag to determine the next version
// and the changes that are included in the upcoming release.
const branch = getBranch(exec)
let tags = getTags(exec)
if (branch.startsWith('stable-')) {
const [_, majorAndMinor] = branch.split('-')
// we only care about tags that are within the range of the current stable branch.
// e.g. if the branch is stable-1.2, we only care about tags that are v1.2.x.
const matchingTags = tags.filter((t) => t.startsWith(`v${majorAndMinor}`))
if (matchingTags.length) {
tags = matchingTags
}
}
return tags.pop() || 'v0.0.0'
},
useLatestRelease: ({ exec, nextVersion }) => {
// check if the release should be marked as latest release on GitHub.
const tags = getTags(exec)
const latestTag = tags.pop() || 'v0.0.0'
return compareVersions(latestTag, nextVersion) === -1
}
}
const parseVersion = (tag: string) => {
const version = tag.startsWith('v') ? tag.slice(1) : tag
const [main, pre] = version.split('-')
const [major, minor, patch] = main.split('.').map(Number)
return { major, minor, patch, pre }
}
const getBranch = (exec: any): string => {
return exec('git rev-parse --abbrev-ref HEAD', {
silent: true
}).stdout.trim()
}
const getTags = (exec: any) => {
exec('git fetch --tags', { silent: true })
const tagsOutput = exec('git tag', { silent: true }).stdout.trim()
const tags: string[] = tagsOutput ? tagsOutput.split('\n') : []
return tags.filter((tag) => tag.startsWith('v')).sort(compareVersions)
}
const compareVersions = (a: string, b: string) => {
const va = parseVersion(a)
const vb = parseVersion(b)
if (va.major !== vb.major) {
return va.major - vb.major
}
if (va.minor !== vb.minor) {
return va.minor - vb.minor
}
if (va.patch !== vb.patch) {
return va.patch - vb.patch
}
if (va.pre && !vb.pre) {
return -1
}
if (!va.pre && vb.pre) {
return 1
}
if (va.pre && vb.pre) {
return va.pre.localeCompare(vb.pre)
}
return 0
}
+16
View File
@@ -0,0 +1,16 @@
@echo off
setlocal
set "QSFERA_EXE=%USERPROFILE%\craft\CraftMaster\windows-cl-msvc2022-x86_64\bin\qsfera.exe"
for %%I in ("%QSFERA_EXE%") do set "QSFERA_DIR=%%~dpI"
if not exist "%QSFERA_EXE%" (
echo QSfera executable was not found:
echo "%QSFERA_EXE%"
echo.
echo Build and install the desktop app first, then run this file again.
pause
exit /b 1
)
start "" /D "%QSFERA_DIR%" "%QSFERA_EXE%" --show
+3
View File
@@ -0,0 +1,3 @@
if (APPLE)
add_subdirectory(MacOSX)
endif()
@@ -0,0 +1,27 @@
if(APPLE)
set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/${APPLICATION_ICON_NAME}.icns")
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(XCODE_CONFIG "Debug")
else()
set(XCODE_CONFIG "Release")
endif()
# The bundle identifier and application group need to have compatible values with the client
# to be able to open a Mach port across the extension's sandbox boundary.
# Pass the info through the xcodebuild command line and make sure that the project uses
# those user-defined settings to build the plist.
add_custom_target( mac_overlayplugin ALL
xcodebuild -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/QSferaFinderExtension/QSferaFinderExtension.xcodeproj
-target FinderSyncExt -configuration "${XCODE_CONFIG}" "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}"
"OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}"
"OC_APPLICATION_NAME=${APPLICATION_NAME}"
"OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}"
"OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
COMMENT building Mac Overlay icons
VERBATIM)
add_dependencies(mac_overlayplugin qsfera) # for the ${APPLICATION_ICON_NAME}.icns to be generated
add_custom_command(TARGET mac_overlayplugin POST_BUILD COMMAND ${CMAKE_COMMAND}
ARGS -E copy_directory "${CMAKE_CURRENT_BINARY_DIR}/${XCODE_CONFIG}/FinderSyncExt.appex" "$<TARGET_FILE_DIR:qsfera>/../PlugIns/FinderSyncExt.appex")
endif()
@@ -0,0 +1,28 @@
/*
* Copyright (C) by Jocelyn Turcotte <jturcotte@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.
*/
#import "SyncClientProxy.h"
#import <Cocoa/Cocoa.h>
#import <FinderSync/FinderSync.h>
@interface FinderSync : FIFinderSync <SyncClientProxyDelegate> {
SyncClientProxy *_syncClientProxy;
NSMutableSet *_registeredDirectories;
NSString *_shareMenuTitle;
NSMutableDictionary *_strings;
NSMutableArray *_menuItems;
}
@end
@@ -0,0 +1,194 @@
/*
* Copyright (C) by Jocelyn Turcotte <jturcotte@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.
*/
#import "FinderSync.h"
@implementation FinderSync
- (instancetype)init
{
self = [super init];
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
NSBundle *extBundle = [NSBundle bundleForClass:[self class]];
// This was added to the bundle's Info.plist to get it from the build system
NSString *socketApiPrefix = [extBundle objectForInfoDictionaryKey:@"SocketApiPrefix"];
NSImage *ok = [extBundle imageForResource:@"ok.icns"];
NSImage *ok_swm = [extBundle imageForResource:@"ok_swm.icns"];
NSImage *sync = [extBundle imageForResource:@"sync.icns"];
NSImage *warning = [extBundle imageForResource:@"warning.icns"];
NSImage *error = [extBundle imageForResource:@"error.icns"];
[syncController setBadgeImage:ok label:@"Up to date" forBadgeIdentifier:@"OK"];
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"SYNC"];
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"NEW"];
[syncController setBadgeImage:warning label:@"Ignored" forBadgeIdentifier:@"IGNORE"];
[syncController setBadgeImage:error label:@"Error" forBadgeIdentifier:@"ERROR"];
[syncController setBadgeImage:ok_swm label:@"Shared" forBadgeIdentifier:@"OK+SWM"];
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"SYNC+SWM"];
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"NEW+SWM"];
[syncController setBadgeImage:warning label:@"Ignored" forBadgeIdentifier:@"IGNORE+SWM"];
[syncController setBadgeImage:error label:@"Error" forBadgeIdentifier:@"ERROR+SWM"];
// The Mach port name needs to:
// - Be prefixed with the code signing Team ID
// - Then infixed with the sandbox App Group
// - The App Group itself must be a prefix of (or equal to) the application bundle identifier
// We end up in the official signed client with: 9B5WD74GWJ.eu.qsfera.desktop.socketApi
// With ad-hoc signing (the '-' signing identity) we must drop the Team ID.
// When the code isn't sandboxed (e.g. the OC client or the legacy overlay icon extension)
// the OS doesn't seem to put any restriction on the port name, so we just follow what
// the sandboxed App Extension needs.
// https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24
NSString *serverName = [socketApiPrefix stringByAppendingString:@".socketApi"];
// NSLog(@"FinderSync serverName %@", serverName);
_syncClientProxy = [[SyncClientProxy alloc] initWithDelegate:self serverName:serverName];
_registeredDirectories = [[NSMutableSet alloc] init];
_strings = [[NSMutableDictionary alloc] init];
[_syncClientProxy start];
return self;
}
#pragma mark - Primary Finder Sync protocol methods
- (void)requestBadgeIdentifierForURL:(NSURL *)url
{
BOOL isDir;
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDir] == NO) {
NSLog(@"ERROR: Could not determine file type of %@", [url path]);
isDir = NO;
}
NSString *normalizedPath = [[url path] decomposedStringWithCanonicalMapping];
[_syncClientProxy askForIcon:normalizedPath isDirectory:isDir];
}
#pragma mark - Menu and toolbar item support
- (NSString *)selectedPathsSeparatedByRecordSeparator
{
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
NSMutableString *string = [[NSMutableString alloc] init];
[syncController.selectedItemURLs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (string.length > 0) {
[string appendString:@"\x1e"]; // record separator
}
NSString *normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
[string appendString:normalizedPath];
}];
return string;
}
- (NSMenu *)menuForMenuKind:(FIMenuKind)whichMenu
{
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
NSMutableSet *rootPaths = [[NSMutableSet alloc] init];
[syncController.directoryURLs enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { [rootPaths addObject:[obj path]]; }];
NSString *paths = [self selectedPathsSeparatedByRecordSeparator];
// calling this IPC calls us back from client with several MENU_ITEM entries and then our askOnSocket returns again
[_syncClientProxy askOnSocket:paths query:@"GET_MENU_ITEMS"];
id contextMenuTitle = [_strings objectForKey:@"CONTEXT_MENU_TITLE"];
if (contextMenuTitle && _menuItems.count != 0) {
NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
NSMenu *subMenu = [[NSMenu alloc] initWithTitle:@""];
NSMenuItem *subMenuItem = [menu addItemWithTitle:contextMenuTitle action:nil keyEquivalent:@""];
subMenuItem.submenu = subMenu;
subMenuItem.image = [[NSBundle mainBundle] imageForResource:@"app.icns"];
// There is an annoying bug in macOS (at least 10.13.3), it does not use/copy over the representedObject of a menu item
// So we have to use tag instead.
int idx = 0;
for (NSArray *item in _menuItems) {
NSMenuItem *actionItem = [subMenu addItemWithTitle:[item valueForKey:@"text"] action:@selector(subMenuActionClicked:) keyEquivalent:@""];
[actionItem setTag:idx];
[actionItem setTarget:self];
NSString *flags = [item valueForKey:@"flags"]; // e.g. "d"
if ([flags rangeOfString:@"d"].location != NSNotFound) {
[actionItem setEnabled:false];
}
idx++;
}
return menu;
}
return nil;
}
- (void)subMenuActionClicked:(id)sender
{
long idx = [(NSMenuItem *)sender tag];
NSString *command = [[_menuItems objectAtIndex:idx] valueForKey:@"command"];
NSString *paths = [self selectedPathsSeparatedByRecordSeparator];
[_syncClientProxy askOnSocket:paths query:command];
}
#pragma mark - SyncClientProxyDelegate implementation
- (void)setResultForPath:(NSString *)path result:(NSString *)result
{
NSString *normalizedPath = [path decomposedStringWithCanonicalMapping];
[[FIFinderSyncController defaultController] setBadgeIdentifier:result forURL:[NSURL fileURLWithPath:normalizedPath]];
}
- (void)reFetchFileNameCacheForPath:(NSString *)path
{
}
- (void)registerPath:(NSString *)path
{
assert(_registeredDirectories);
[_registeredDirectories addObject:[NSURL fileURLWithPath:path]];
[FIFinderSyncController defaultController].directoryURLs = _registeredDirectories;
}
- (void)unregisterPath:(NSString *)path
{
[_registeredDirectories removeObject:[NSURL fileURLWithPath:path]];
[FIFinderSyncController defaultController].directoryURLs = _registeredDirectories;
}
- (void)setString:(NSString *)key value:(NSString *)value
{
[_strings setObject:value forKey:key];
}
- (void)resetMenuItems
{
_menuItems = [[NSMutableArray alloc] init];
}
- (void)addMenuItem:(NSDictionary *)item
{
[_menuItems addObject:item];
}
- (void)connectionDidDie
{
[_strings removeAllObjects];
[_registeredDirectories removeAllObjects];
// For some reason the FIFinderSync cache doesn't seem to be cleared for the root item when
// we reset the directoryURLs (seen on macOS 10.12 at least).
// First setting it to the FS root and then setting it to nil seems to work around the issue.
[FIFinderSyncController defaultController].directoryURLs = [NSSet setWithObject:[NSURL fileURLWithPath:@"/"]];
// This will tell Finder that this extension isn't attached to any directory
// until we can reconnect to the sync client.
[FIFinderSyncController defaultController].directoryURLs = nil;
}
@end
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
</array>
</dict>
</plist>
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SocketApiPrefix</key>
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>$(OC_APPLICATION_NAME) Extensions</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(OC_APPLICATION_REV_DOMAIN).$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
<true/>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict/>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.FinderSync</string>
<key>NSExtensionPrincipalClass</key>
<string>FinderSync</string>
</dict>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
@@ -0,0 +1,44 @@
/*
* Copyright (C) by Jocelyn Turcotte <jturcotte@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.
*/
#import <Foundation/Foundation.h>
@protocol SyncClientProxyDelegate <NSObject>
- (void)setResultForPath:(NSString *)path result:(NSString *)result;
- (void)reFetchFileNameCacheForPath:(NSString *)path;
- (void)registerPath:(NSString *)path;
- (void)unregisterPath:(NSString *)path;
- (void)setString:(NSString *)key value:(NSString *)value;
- (void)resetMenuItems;
- (void)addMenuItem:(NSDictionary *)item;
- (void)connectionDidDie;
@end
@protocol ChannelProtocol <NSObject>
- (void)sendMessage:(NSData *)msg;
@end
@interface SyncClientProxy : NSObject <ChannelProtocol> {
NSString *_serverName;
NSDistantObject<ChannelProtocol> *_remoteEnd;
}
@property (weak) id<SyncClientProxyDelegate> delegate;
- (instancetype)initWithDelegate:(id)arg1 serverName:(NSString *)serverName;
- (void)start;
- (void)askOnSocket:(NSString *)path query:(NSString *)verb;
- (void)askForIcon:(NSString *)path isDirectory:(BOOL)isDir;
@end
@@ -0,0 +1,156 @@
/*
* Copyright (C) by Jocelyn Turcotte <jturcotte@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.
*/
#import "SyncClientProxy.h"
@protocol ServerProtocol <NSObject>
- (void)registerClient:(id)client;
@end
@interface SyncClientProxy ()
- (void)registerTransmitter:(id)tx;
@end
@implementation SyncClientProxy
- (instancetype)initWithDelegate:(id)arg1 serverName:(NSString *)serverName
{
self = [super init];
self.delegate = arg1;
_serverName = serverName;
_remoteEnd = nil;
return self;
}
#pragma mark - Connection setup
- (void)start
{
if (_remoteEnd)
return;
// Lookup the server connection
NSConnection *conn = [NSConnection connectionWithRegisteredName:_serverName host:nil];
if (!conn) {
// Could not connect to the sync client
[self scheduleRetry];
return;
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectionDidDie:) name:NSConnectionDidDieNotification object:conn];
NSDistantObject<ServerProtocol> *server = (NSDistantObject<ServerProtocol> *)[conn rootProxy];
assert(server);
// This saves a few Mach messages, enable "Distributed Objects" in the scheme's Run diagnostics to watch
[server setProtocolForProxy:@protocol(ServerProtocol)];
// Send an object to the server to act as the channel rx, we'll receive the tx through registerTransmitter
[server registerClient:self];
}
- (void)registerTransmitter:(id)tx;
{
// The server replied with the distant object that we will use for tx
_remoteEnd = (NSDistantObject<ChannelProtocol> *)tx;
[_remoteEnd setProtocolForProxy:@protocol(ChannelProtocol)];
// Everything is set up, start querying
[self askOnSocket:@"" query:@"GET_STRINGS"];
}
- (void)scheduleRetry
{
[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(start) userInfo:nil repeats:NO];
}
- (void)connectionDidDie:(NSNotification *)notification
{
#pragma unused(notification)
_remoteEnd = nil;
[_delegate connectionDidDie];
[self scheduleRetry];
}
#pragma mark - Communication logic
- (void)sendMessage:(NSData *)msg
{
NSString *answer = [[NSString alloc] initWithData:msg encoding:NSUTF8StringEncoding];
// Cut the trailing newline. We always only receive one line from the client.
answer = [answer substringToIndex:[answer length] - 1];
NSArray *chunks = [answer componentsSeparatedByString:@":"];
if ([[chunks objectAtIndex:0] isEqualToString:@"STATUS"]) {
NSString *result = [chunks objectAtIndex:1];
NSString *path = [chunks objectAtIndex:2];
if ([chunks count] > 3) {
for (int i = 2; i < [chunks count] - 1; i++) {
path = [NSString stringWithFormat:@"%@:%@", path, [chunks objectAtIndex:i + 1]];
}
}
[_delegate setResultForPath:path result:result];
} else if ([[chunks objectAtIndex:0] isEqualToString:@"UPDATE_VIEW"]) {
NSString *path = [chunks objectAtIndex:1];
[_delegate reFetchFileNameCacheForPath:path];
} else if ([[chunks objectAtIndex:0] isEqualToString:@"REGISTER_PATH"]) {
NSString *path = [chunks objectAtIndex:1];
[_delegate registerPath:path];
} else if ([[chunks objectAtIndex:0] isEqualToString:@"UNREGISTER_PATH"]) {
NSString *path = [chunks objectAtIndex:1];
[_delegate unregisterPath:path];
} else if ([[chunks objectAtIndex:0] isEqualToString:@"GET_STRINGS"]) {
// BEGIN and END messages, do nothing.
} else if ([[chunks objectAtIndex:0] isEqualToString:@"STRING"]) {
[_delegate setString:[chunks objectAtIndex:1] value:[chunks objectAtIndex:2]];
} else if ([[chunks objectAtIndex:0] isEqualToString:@"GET_MENU_ITEMS"]) {
if ([[chunks objectAtIndex:1] isEqualToString:@"BEGIN"]) {
[_delegate resetMenuItems];
} else if ([[chunks objectAtIndex:1] isEqualToString:@"END"]) {
// Don't do anything special, the askOnSocket call in FinderSync menuForMenuKind will return after this line
}
} else if ([[chunks objectAtIndex:0] isEqualToString:@"MENU_ITEM"]) {
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
[item setValue:[chunks objectAtIndex:1] forKey:@"command"]; // e.g. "COPY_PRIVATE_LINK"
[item setValue:[chunks objectAtIndex:2] forKey:@"flags"]; // e.g. "d"
[item setValue:[chunks objectAtIndex:3] forKey:@"text"]; // e.g. "Copy private link to clipboard"
[_delegate addMenuItem:item];
} else {
NSLog(@"SyncState: Unknown command %@", [chunks objectAtIndex:0]);
}
}
- (void)askOnSocket:(NSString *)path query:(NSString *)verb
{
NSString *query = [NSString stringWithFormat:@"%@:%@\n", verb, path];
@try {
[_remoteEnd sendMessage:[query dataUsingEncoding:NSUTF8StringEncoding]];
} @catch (NSException *e) {
// Do nothing and wait for connectionDidDie
}
}
- (void)askForIcon:(NSString *)path isDirectory:(BOOL)isDir
{
NSString *verb = isDir ? @"RETRIEVE_FOLDER_STATUS" : @"RETRIEVE_FILE_STATUS";
[self askOnSocket:path query:verb];
}
@end
@@ -0,0 +1,533 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
C2B573BA1B1CD91E00303B36 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; };
C2B573D21B1CD94B00303B36 /* main.m in Resources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; };
C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573DD1B1CD9CE00303B36 /* FinderSync.m */; };
C2B573E21B1CD9CE00303B36 /* FinderSyncExt.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
C2B573F31B1DAD6400303B36 /* error.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EB1B1DAD6400303B36 /* error.iconset */; };
C2B573F41B1DAD6400303B36 /* ok_swm.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */; };
C2B573F51B1DAD6400303B36 /* ok.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573ED1B1DAD6400303B36 /* ok.iconset */; };
C2B573F71B1DAD6400303B36 /* sync.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EF1B1DAD6400303B36 /* sync.iconset */; };
C2B573F91B1DAD6400303B36 /* warning.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573F11B1DAD6400303B36 /* warning.iconset */; };
C2C932F01F0BFC6700C8BCB3 /* SyncClientProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = C2C932EF1F0BFC6700C8BCB3 /* SyncClientProxy.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C2B573951B1CD88000303B36 /* Project object */;
proxyType = 1;
remoteGlobalIDString = C2B573D61B1CD9CE00303B36;
remoteInfo = FinderSyncExt;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
C2B573E11B1CD9CE00303B36 /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
C2B573E21B1CD9CE00303B36 /* FinderSyncExt.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
C2B573B11B1CD91E00303B36 /* desktopclient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = desktopclient.app; sourceTree = BUILT_PRODUCTS_DIR; };
C2B573B51B1CD91E00303B36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C2B573B91B1CD91E00303B36 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = FinderSyncExt.appex; sourceTree = BUILT_PRODUCTS_DIR; };
C2B573DA1B1CD9CE00303B36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C2B573DB1B1CD9CE00303B36 /* FinderSyncExt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = FinderSyncExt.entitlements; sourceTree = "<group>"; };
C2B573DC1B1CD9CE00303B36 /* FinderSync.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FinderSync.h; sourceTree = "<group>"; };
C2B573DD1B1CD9CE00303B36 /* FinderSync.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FinderSync.m; sourceTree = "<group>"; };
C2B573EB1B1DAD6400303B36 /* error.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = error.iconset; path = ../../icons/nopadding/error.iconset; sourceTree = SOURCE_ROOT; };
C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = ok_swm.iconset; path = ../../icons/nopadding/ok_swm.iconset; sourceTree = SOURCE_ROOT; };
C2B573ED1B1DAD6400303B36 /* ok.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = ok.iconset; path = ../../icons/nopadding/ok.iconset; sourceTree = SOURCE_ROOT; };
C2B573EF1B1DAD6400303B36 /* sync.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = sync.iconset; path = ../../icons/nopadding/sync.iconset; sourceTree = SOURCE_ROOT; };
C2B573F11B1DAD6400303B36 /* warning.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = warning.iconset; path = ../../icons/nopadding/warning.iconset; sourceTree = SOURCE_ROOT; };
C2C932EE1F0BFC6700C8BCB3 /* SyncClientProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SyncClientProxy.h; sourceTree = "<group>"; };
C2C932EF1F0BFC6700C8BCB3 /* SyncClientProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SyncClientProxy.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
C2B573AE1B1CD91E00303B36 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
C2B573D41B1CD9CE00303B36 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
C2B573941B1CD88000303B36 = {
isa = PBXGroup;
children = (
C2B573B31B1CD91E00303B36 /* desktopclient */,
C2B573D81B1CD9CE00303B36 /* FinderSyncExt */,
C2B573B21B1CD91E00303B36 /* Products */,
);
sourceTree = "<group>";
};
C2B573B21B1CD91E00303B36 /* Products */ = {
isa = PBXGroup;
children = (
C2B573B11B1CD91E00303B36 /* desktopclient.app */,
C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */,
);
name = Products;
sourceTree = "<group>";
};
C2B573B31B1CD91E00303B36 /* desktopclient */ = {
isa = PBXGroup;
children = (
C2B573B41B1CD91E00303B36 /* Supporting Files */,
);
path = desktopclient;
sourceTree = "<group>";
};
C2B573B41B1CD91E00303B36 /* Supporting Files */ = {
isa = PBXGroup;
children = (
C2B573B51B1CD91E00303B36 /* Info.plist */,
C2B573B91B1CD91E00303B36 /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
C2B573D81B1CD9CE00303B36 /* FinderSyncExt */ = {
isa = PBXGroup;
children = (
C2C932EE1F0BFC6700C8BCB3 /* SyncClientProxy.h */,
C2C932EF1F0BFC6700C8BCB3 /* SyncClientProxy.m */,
C2B573DC1B1CD9CE00303B36 /* FinderSync.h */,
C2B573DD1B1CD9CE00303B36 /* FinderSync.m */,
C2B573D91B1CD9CE00303B36 /* Supporting Files */,
);
path = FinderSyncExt;
sourceTree = "<group>";
};
C2B573D91B1CD9CE00303B36 /* Supporting Files */ = {
isa = PBXGroup;
children = (
C2B573EB1B1DAD6400303B36 /* error.iconset */,
C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */,
C2B573ED1B1DAD6400303B36 /* ok.iconset */,
C2B573EF1B1DAD6400303B36 /* sync.iconset */,
C2B573F11B1DAD6400303B36 /* warning.iconset */,
C2B573DA1B1CD9CE00303B36 /* Info.plist */,
C2B573DB1B1CD9CE00303B36 /* FinderSyncExt.entitlements */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
C2B573B01B1CD91E00303B36 /* desktopclient */ = {
isa = PBXNativeTarget;
buildConfigurationList = C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */;
buildPhases = (
C2B573AD1B1CD91E00303B36 /* Sources */,
C2B573AE1B1CD91E00303B36 /* Frameworks */,
C2B573AF1B1CD91E00303B36 /* Resources */,
C2B573E11B1CD9CE00303B36 /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */,
);
name = desktopclient;
productName = desktopclient;
productReference = C2B573B11B1CD91E00303B36 /* desktopclient.app */;
productType = "com.apple.product-type.application";
};
C2B573D61B1CD9CE00303B36 /* FinderSyncExt */ = {
isa = PBXNativeTarget;
buildConfigurationList = C2B573E31B1CD9CE00303B36 /* Build configuration list for PBXNativeTarget "FinderSyncExt" */;
buildPhases = (
C2B573D31B1CD9CE00303B36 /* Sources */,
C2B573D41B1CD9CE00303B36 /* Frameworks */,
C2B573D51B1CD9CE00303B36 /* Resources */,
5B3335471CA058E200E11A45 /* ShellScript */,
);
buildRules = (
);
dependencies = (
);
name = FinderSyncExt;
productName = FinderSyncExt;
productReference = C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
C2B573951B1CD88000303B36 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0630;
TargetAttributes = {
C2B573B01B1CD91E00303B36 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = 9B5WD74GWJ;
};
C2B573D61B1CD9CE00303B36 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = 9B5WD74GWJ;
SystemCapabilities = {
com.apple.ApplicationGroups.Mac = {
enabled = 1;
};
};
};
};
};
buildConfigurationList = C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "QSferaFinderExtension" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
mainGroup = C2B573941B1CD88000303B36;
productRefGroup = C2B573B21B1CD91E00303B36 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
C2B573B01B1CD91E00303B36 /* desktopclient */,
C2B573D61B1CD9CE00303B36 /* FinderSyncExt */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
C2B573AF1B1CD91E00303B36 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C2B573D21B1CD94B00303B36 /* main.m in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C2B573D51B1CD9CE00303B36 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C2B573F91B1DAD6400303B36 /* warning.iconset in Resources */,
C2B573F31B1DAD6400303B36 /* error.iconset in Resources */,
C2B573F71B1DAD6400303B36 /* sync.iconset in Resources */,
C2B573F41B1DAD6400303B36 /* ok_swm.iconset in Resources */,
C2B573F51B1DAD6400303B36 /* ok.iconset in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
5B3335471CA058E200E11A45 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [[ ${OC_OEM_SHARE_ICNS} ]]; then\n cp ${OC_OEM_SHARE_ICNS} ${BUILT_PRODUCTS_DIR}/FinderSyncExt.appex/Contents/Resources/app.icns\nfi";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
C2B573AD1B1CD91E00303B36 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C2B573BA1B1CD91E00303B36 /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C2B573D31B1CD9CE00303B36 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C2C932F01F0BFC6700C8BCB3 /* SyncClientProxy.m in Sources */,
C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C2B573D61B1CD9CE00303B36 /* FinderSyncExt */;
targetProxy = C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
C2B573991B1CD88000303B36 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Debug;
};
C2B5739A1B1CD88000303B36 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Release;
};
C2B573CD1B1CD91E00303B36 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = desktopclient/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
};
name = Debug;
};
C2B573CE1B1CD91E00303B36 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = desktopclient/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
};
name = Release;
};
C2B573E41B1CD9CE00303B36 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = FinderSyncExt/FinderSyncExt.entitlements;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = FinderSyncExt/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = YES;
OC_APPLICATION_NAME = "КуСфера";
OC_APPLICATION_REV_DOMAIN = eu.qsfera.desktop;
OC_OEM_SHARE_ICNS = "";
OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX = "";
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
SKIP_INSTALL = YES;
};
name = Debug;
};
C2B573E51B1CD9CE00303B36 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
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";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = FinderSyncExt/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
OC_APPLICATION_NAME = "КуСфера";
OC_APPLICATION_REV_DOMAIN = eu.qsfera.desktop;
OC_OEM_SHARE_ICNS = "";
OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX = "";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "QSferaFinderExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C2B573991B1CD88000303B36 /* Debug */,
C2B5739A1B1CD88000303B36 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C2B573CD1B1CD91E00303B36 /* Debug */,
C2B573CE1B1CD91E00303B36 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C2B573E31B1CD9CE00303B36 /* Build configuration list for PBXNativeTarget "FinderSyncExt" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C2B573E41B1CD9CE00303B36 /* Debug */,
C2B573E51B1CD9CE00303B36 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = C2B573951B1CD88000303B36 /* Project object */;
}
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C2B573D61B1CD9CE00303B36"
BuildableName = "FinderSyncExt.appex"
BlueprintName = "FinderSyncExt"
ReferencedContainer = "container:QSferaFinderExtension.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C2B573B01B1CD91E00303B36"
BuildableName = "desktopclient.app"
BlueprintName = "desktopclient"
ReferencedContainer = "container:QSferaFinderExtension.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C2B573D61B1CD9CE00303B36"
BuildableName = "FinderSyncExt.appex"
BlueprintName = "FinderSyncExt"
ReferencedContainer = "container:QSferaFinderExtension.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C2B573B01B1CD91E00303B36"
BuildableName = "desktopclient.app"
BlueprintName = "desktopclient"
ReferencedContainer = "container:QSferaFinderExtension.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
askForAppToLaunch = "Yes"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C2B573B01B1CD91E00303B36"
BuildableName = "desktopclient.app"
BlueprintName = "desktopclient"
ReferencedContainer = "container:QSferaFinderExtension.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>eu.qsfera.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
@@ -0,0 +1,16 @@
//
// main.m
// desktopclient
//
// Created by Jocelyn Turcotte on 01/06/15.
//
//
// This is fake application bundle with the same bundle ID as the real desktop client.
// Xcode needs a wrapping application to allow the extension to be debugged.
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[]) {
return NSApplicationMain(argc, argv);
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
enable-background="new 0 0 128 128"
viewBox="0 0 128 128"
y="0px"
x="0px"
id="Sync"
version="1.1"><metadata
id="metadata29"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs27" /><g
transform="matrix(0.96875,0,0,0.96875,2,2)"
id="g3"><g
id="g5"><g
id="g7"><circle
style="fill:#e0d92d"
id="circle9"
r="61.900002"
cy="64"
cx="64" /><path
style="fill:#8e7409"
id="path11"
d="M 64,128 C 28.7,128 0,99.3 0,64 0,28.7 28.7,0 64,0 c 35.3,0 64,28.7 64,64 0,35.3 -28.7,64 -64,64 z M 64,4.1 C 31,4.1 4.1,31 4.1,64 4.1,97 31,123.9 64,123.9 97,123.9 123.9,97 123.9,64 123.9,31 97,4.1 64,4.1 Z" /></g></g><g
id="g13"><g
id="g15"><g
id="g17"><path
style="fill:#ffffff"
id="path19"
d="m 64,107.4 c -5.6,0 -10.2,-4.6 -10.2,-10.2 0,-5.6 4.6,-10.2 10.2,-10.2 5.6,0 10.2,4.6 10.2,10.2 0,5.6 -4.6,10.2 -10.2,10.2 z M 64,81.3 C 55.7,81.3 55.7,74 55.7,71.1 L 52,30.9 52,30.8 c 0,-5.6 5.4,-10.2 12,-10.2 6.6,0 12,4.6 12,10.2 l 0,0.1 -3.7,40.3 c 0,2.8 0,10.1 -8.3,10.1 z" /></g><g
id="g21"><path
style="fill:#8e7409"
id="path23"
d="m 64,21.9 c 5.9,0 10.7,4 10.7,8.8 L 71,71 c 0,4.9 -1.1,8.8 -7,8.8 -5.9,0 -6.9,-4 -6.9,-8.8 L 53.4,30.7 C 53.3,25.9 58.1,21.9 64,21.9 m 0,66.4 c 4.9,0 8.9,4 8.9,8.8 0,4.9 -4,8.9 -8.9,8.9 -4.9,0 -8.9,-4 -8.9,-8.9 0,-4.8 4,-8.8 8.9,-8.8 m 0,-69.1 c -3.5,0 -6.8,1.1 -9.3,3.2 -2.7,2.2 -4.1,5.2 -4.1,8.4 l 0,0.1 0,0.1 3.7,40.1 c 0,2.3 0.2,5.2 1.7,7.6 1.6,2.6 4.3,3.9 8,3.9 3.7,0 6.4,-1.3 8,-3.9 1.5,-2.3 1.7,-5.3 1.7,-7.6 l 3.7,-40.1 0,-0.1 0,-0.1 c 0,-3.2 -1.5,-6.2 -4.1,-8.4 -2.5,-2.1 -5.8,-3.2 -9.3,-3.2 l 0,0 z m 0,66.4 c -6.4,0 -11.6,5.2 -11.6,11.6 0,6.4 5.2,11.6 11.6,11.6 6.4,0 11.6,-5.2 11.6,-11.6 0,-6.4 -5.2,-11.6 -11.6,-11.6 l 0,0 z" /></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
enable-background="new 0 0 128 128"
viewBox="0 0 128 128"
y="0px"
x="0px"
id="Sync"
version="1.1"><metadata
id="metadata27"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs25" /><g
transform="matrix(0.96875,0,0,0.96875,2,2)"
id="g3"><g
id="g5"><g
id="g7"><circle
style="fill:#b23015"
id="circle9"
r="61.900002"
cy="64"
cx="64" /><path
style="fill:#981d05"
id="path11"
d="M 64,128 C 28.7,128 0,99.3 0,64 0,28.7 28.7,0 64,0 c 35.3,0 64,28.7 64,64 0,35.3 -28.7,64 -64,64 z M 64,4.1 C 31,4.1 4.1,31 4.1,64 4.1,97 31,123.9 64,123.9 97,123.9 123.9,97 123.9,64 123.9,31 97,4.1 64,4.1 Z" /></g></g><g
id="g13"><g
id="g15"><path
style="fill:#ffffff"
id="path17"
d="m 41.8,95.2 c -2.4,0 -4.4,-0.9 -6.2,-2.6 -1.7,-1.7 -2.7,-3.9 -2.8,-6.4 -0.1,-2.6 0.7,-4.8 2.5,-6.8 L 50.8,64 35.4,48.6 c -1.9,-1.9 -2.7,-4 -2.5,-6.5 0.2,-2.3 1.1,-4.5 2.7,-6.3 l 0,0 0,0 c 1.9,-1.9 4,-2.9 6.3,-2.9 0.2,0 0.4,0 0.6,0 2.4,0.2 4.5,1.1 6.4,2.8 l 0,0 15.1,15 15.4,-15.2 c 1.8,-1.8 3.9,-2.7 6.3,-2.7 0.1,0 0.1,0 0.2,0 2.4,0.1 4.6,1 6.5,2.8 l 0,0 c 1.7,1.7 2.6,3.9 2.6,6.5 0,2.6 -0.9,4.8 -2.6,6.6 L 77.4,64 92.5,79.2 c 1.7,1.7 2.6,3.9 2.7,6.5 0.1,2.6 -0.8,5 -2.7,6.9 -1.7,1.7 -4,2.6 -6.6,2.6 -2.6,0 -4.9,-1 -6.8,-3 L 64,77.4 48.9,92.6 l 0,0 c -1.7,1.5 -3.8,2.4 -6.4,2.6 -0.2,0 -0.5,0 -0.7,0 z" /></g><g
id="g19"><path
style="fill:#981d05"
id="path21"
d="m 41.9,34.1 c 0.2,0 0.3,0 0.5,0 2,0.2 3.9,1 5.5,2.5 l 16,16 16.4,-16.2 c 1.5,-1.5 3.3,-2.3 5.3,-2.3 0.1,0 0.1,0 0.2,0 2.1,0 4,0.8 5.6,2.4 1.5,1.5 2.2,3.3 2.2,5.6 0,2.2 -0.7,4.1 -2.2,5.7 l -16,16.2 16,16.2 c 1.5,1.5 2.3,3.3 2.3,5.6 0.1,2.3 -0.7,4.2 -2.3,5.9 -1.5,1.5 -3.3,2.2 -5.6,2.2 -2.3,0 -4.2,-0.9 -5.9,-2.6 L 64,75.5 48,91.7 c -1.5,1.3 -3.3,2.1 -5.5,2.2 -0.2,0 -0.4,0 -0.6,0 -2,0 -3.7,-0.7 -5.2,-2.2 -1.5,-1.5 -2.3,-3.3 -2.4,-5.5 -0.1,-2.2 0.6,-4.1 2.2,-5.7 L 52.7,64 36.3,47.6 C 34.7,46 34,44.2 34.2,42.2 c 0.2,-2.1 0.9,-3.9 2.3,-5.6 1.8,-1.6 3.5,-2.5 5.4,-2.5 m 0,-2.7 c -2.6,0 -5,1.1 -7.2,3.3 l -0.1,0.1 -0.1,0.1 c -1.8,2.1 -2.8,4.5 -3,7.1 -0.2,2.9 0.8,5.5 2.9,7.6 L 48.9,64 34.4,78.5 l 0,0 0,0 c -2.1,2.2 -3.1,4.8 -2.9,7.8 0.2,2.9 1.2,5.3 3.2,7.3 2,2 4.4,3 7.2,3 0.3,0 0.5,0 0.8,0 2.8,-0.2 5.2,-1.2 7.2,-2.9 L 50,93.6 50.1,93.5 64,79.4 78,93.2 c 2.2,2.3 4.8,3.4 7.8,3.4 3,0 5.6,-1 7.6,-3 2.2,-2.2 3.3,-4.9 3.1,-7.9 -0.1,-3 -1.2,-5.5 -3.1,-7.5 L 79.3,64 93.4,49.8 l 0,0 0,0 c 2,-2.1 3,-4.6 3,-7.6 0,-3 -1,-5.5 -3,-7.5 l 0,0 0,0 c -2.2,-2 -4.7,-3.1 -7.4,-3.2 -0.1,0 -0.1,0 -0.2,0 -2.8,0 -5.2,1 -7.3,3.1 L 64,48.8 49.9,34.7 l 0,-0.1 -0.1,-0.1 c -2.1,-1.9 -4.5,-2.9 -7.2,-3.2 -0.2,0.1 -0.5,0.1 -0.7,0.1 l 0,0 z" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

@@ -0,0 +1,8 @@
#!/bin/sh
# Dimensions taken from https://www.apriorit.com/dev-blog/357-shell-extentions-basics-samples-common-problems#_Toc408244375
convert -background transparent attention.svg -gravity SouthWest \( -clone 0 -resize 10x10 -extent 16x16 \) \( -clone 0 -resize 16x16 -extent 32x32 \) \( -clone 0 -resize 24x24 -extent 48x48 \) \( -clone 0 -resize 128x128 -extent 256x256 \) -delete 0 ../../../windows/OCOverlays/ico/Warning.ico
convert -background transparent error.svg -gravity SouthWest \( -clone 0 -resize 10x10 -extent 16x16 \) \( -clone 0 -resize 16x16 -extent 32x32 \) \( -clone 0 -resize 24x24 -extent 48x48 \) \( -clone 0 -resize 128x128 -extent 256x256 \) -delete 0 ../../../windows/OCOverlays/ico/Error.ico
convert -background transparent ok.svg -gravity SouthWest \( -clone 0 -resize 10x10 -extent 16x16 \) \( -clone 0 -resize 16x16 -extent 32x32 \) \( -clone 0 -resize 24x24 -extent 48x48 \) \( -clone 0 -resize 128x128 -extent 256x256 \) -delete 0 ../../../windows/OCOverlays/ico/OK.ico
convert -background transparent shared.svg -gravity SouthWest \( -clone 0 -resize 10x10 -extent 16x16 \) \( -clone 0 -resize 16x16 -extent 32x32 \) \( -clone 0 -resize 24x24 -extent 48x48 \) \( -clone 0 -resize 128x128 -extent 256x256 \) -delete 0 ../../../windows/OCOverlays/ico/OK_Shared.ico
convert -background transparent sync.svg -gravity SouthWest \( -clone 0 -resize 10x10 -extent 16x16 \) \( -clone 0 -resize 16x16 -extent 32x32 \) \( -clone 0 -resize 24x24 -extent 48x48 \) \( -clone 0 -resize 128x128 -extent 256x256 \) -delete 0 ../../../windows/OCOverlays/ico/Sync.ico
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
enable-background="new 0 0 128 128"
viewBox="0 0 128 128"
y="0px"
x="0px"
id="Sync"
version="1.1"><metadata
id="metadata25"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs23" /><g
transform="matrix(0.96875,0,0,0.96875,2,2)"
id="g3"><g
id="g5"><path
style="fill:#5eb220"
id="path7"
d="m 64,2.1 c 34.2,0 61.9,27.7 61.9,61.9 0,34.2 -27.7,61.9 -61.9,61.9 C 29.8,125.9 2.1,98.2 2.1,64 2.1,29.8 29.8,2.1 64,2.1 Z" /><path
style="fill:#3a9804"
id="path9"
d="M 64,128 C 28.7,128 0,99.3 0,64 0,28.7 28.7,0 64,0 c 35.3,0 64,28.7 64,64 0,35.3 -28.7,64 -64,64 z M 64,4.1 C 31,4.1 4.1,31 4.1,64 4.1,97 31,123.9 64,123.9 97,123.9 123.9,97 123.9,64 123.9,31 97,4.1 64,4.1 Z" /></g><g
id="g11"><g
id="g13"><polygon
style="fill:#ffffff"
id="polygon15"
points="35.9,63.8 53,77.3 87.1,31 100.3,40.7 61.3,93.9 56.2,100.7 25.7,76.8 " /></g><g
id="g17"><path
style="fill:#3a9804"
id="path19"
d="M 87.3,32.4 98.9,41 94.6,46.8 60.4,93.2 56,99.2 50.2,94.6 32.8,81.1 27.1,76.7 36,65.3 l 5.7,4.4 11.5,9 L 83,38.2 87.3,32.4 M 86.8,29.5 85.6,31.2 81.3,37 52.8,75.8 43,68.1 37.3,63.7 35.7,62.4 34.4,64 25.5,75.4 24.3,77 l 1.6,1.3 5.7,4.4 17.4,13.6 5.8,4.6 1.7,1.3 1.3,-1.7 4.4,-6 34.1,-46.5 4.3,-5.8 1.2,-1.7 -1.7,-1.2 -11.6,-8.5 -1.7,-1.3 0,0 z" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
id="Sync"
x="0px"
y="0px"
viewBox="0 0 128 128"
enable-background="new 0 0 128 128"
xml:space="preserve"><metadata
id="metadata37"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs35" /><g
id="g3362"><g
id="g5"
transform="matrix(0.96875,0,0,0.96875,2,2)"><g
id="g7"><g
id="g9"><path
d="m 64,2.1 c 34.2,0 61.9,27.7 61.9,61.9 0,34.2 -27.7,61.9 -61.9,61.9 C 29.8,125.9 2.1,98.2 2.1,64 2.1,29.8 29.8,2.1 64,2.1 Z"
id="path11"
style="fill:#5eb220" /></g><g
id="g13"><path
d="M 64,128 C 28.7,128 0,99.3 0,64 0,28.7 28.7,0 64,0 c 35.3,0 64,28.7 64,64 0,35.3 -28.7,64 -64,64 z M 64,4.1 C 31,4.1 4.1,31 4.1,64 4.1,97 31,123.9 64,123.9 97,123.9 123.9,97 123.9,64 123.9,31 97,4.1 64,4.1 Z"
id="path15"
style="fill:#3a9804" /></g></g></g><g
transform="matrix(0.96875,0,0,0.96875,0.50025,-1002.0125)"
id="g17"><g
id="g19"><g
id="g21"><path
d="m 83.9,1059.9 c -7.9,0 -14.2,6.4 -14.2,14.2 0,0.4 0,0.9 0.1,1.3 l -27.4,14 c -2.5,-2.1 -5.7,-3.4 -9.2,-3.4 -7.9,0 -14.2,6.4 -14.2,14.2 0,7.9 6.4,14.2 14.2,14.2 3.2,0 6.1,-1 8.5,-2.8 l 28.2,14.3 c 0,0.2 -0.1,0.5 -0.1,0.8 0,7.9 6.4,14.2 14.2,14.2 7.8,0 14.2,-6.4 14.2,-14.2 0,-7.9 -6.4,-14.2 -14.2,-14.2 -3.7,0 -7.1,1.4 -9.6,3.7 l -27.2,-13.9 c 0.1,-0.7 0.2,-1.4 0.2,-2.2 0,-0.4 -0.1,-0.8 -0.1,-1.2 l 27.5,-14 c 2.5,2.1 5.7,3.4 9.2,3.4 7.9,0 14.2,-6.4 14.2,-14.2 -0.1,-7.9 -6.5,-14.3 -14.3,-14.2 l 0,0 z"
id="path23"
style="fill:#ffffff" /><path
d="m 83.9,1141.9 c -8.4,0 -15.2,-6.8 -15.2,-15.1 0,-0.1 0,-0.2 0,-0.2 l -27.1,-13.8 c -2.5,1.7 -5.4,2.6 -8.5,2.6 -8.3,0 -15.1,-6.8 -15.1,-15.1 0,-8.3 6.8,-15.1 15.1,-15.1 3.4,0 6.7,1.1 9.4,3.2 L 68.8,1075 c 0,-0.3 0,-0.5 0,-0.8 0,-8 6.2,-14.6 14.1,-15.1 l 0,0 1,-0.1 c 8.3,0 15.1,6.8 15.1,15.1 0,8.4 -6.8,15.2 -15.1,15.2 -3.4,0 -6.7,-1.1 -9.3,-3.2 l -26.4,13.4 c 0,0.2 0,0.5 0,0.7 0,0.6 -0.1,1.1 -0.1,1.7 l 26.1,13.3 c 2.7,-2.3 6.2,-3.5 9.7,-3.5 8.3,0 15.1,6.8 15.1,15.2 0,8.2 -6.8,15 -15.1,15 z m -42.5,-31.3 29.2,14.9 -0.1,0.9 c 0,0.1 0,0.3 0,0.4 0,7.3 6,13.3 13.3,13.3 7.3,0 13.3,-6 13.3,-13.3 0,-7.3 -6,-13.3 -13.3,-13.3 -3.3,0 -6.5,1.2 -9,3.5 l -0.5,0.4 -28.3,-14.5 0.1,-0.6 c 0.1,-0.7 0.2,-1.4 0.2,-2.1 0,-0.3 0,-0.5 0,-0.8 l -0.1,-1 28.5,-14.5 0.5,0.4 c 2.4,2 5.5,3.2 8.6,3.2 7.3,0 13.3,-6 13.3,-13.3 0,-7.1 -5.6,-12.9 -12.6,-13.3 l -0.7,0 c -7.3,0 -13.3,6 -13.3,13.3 0,0.4 0,0.7 0.1,1.1 l 0.1,0.6 -0.5,0.4 -28,14.3 -0.5,-0.4 c -2.4,-2 -5.5,-3.2 -8.6,-3.2 -7.3,0 -13.3,6 -13.3,13.3 0,7.3 6,13.3 13.3,13.3 2.9,0 5.6,-0.9 7.9,-2.6 l 0.4,-0.4 z"
id="path25"
style="fill:#3a9804" /></g><g
id="g27"><path
d="m 83.9,1141.2 c -8,0 -14.4,-6.5 -14.4,-14.4 0,-0.2 0,-0.3 0,-0.5 0,-0.1 0,-0.1 0,-0.2 l -28,-14.2 c -2.4,1.8 -5.4,2.7 -8.5,2.7 -7.9,0 -14.4,-6.5 -14.4,-14.4 0,-7.9 6.5,-14.4 14.4,-14.4 3.4,0 6.7,1.2 9.3,3.4 l 27.2,-13.9 0,-0.1 c 0,-0.4 -0.1,-0.7 -0.1,-1.1 0,-7.9 6.4,-14.3 14.2,-14.4 l 0,-0.1 0.2,0 c 7.9,0 14.4,6.5 14.4,14.4 0,8 -6.5,14.4 -14.4,14.4 -3.4,0 -6.6,-1.2 -9.2,-3.3 l -27.2,13.9 0,0.2 c 0,0.3 0.1,0.6 0.1,0.9 0,0.7 -0.1,1.4 -0.2,2.1 l 27,13.8 c 2.6,-2.4 6.1,-3.7 9.6,-3.7 7.9,0 14.4,6.5 14.4,14.4 0,8 -6.5,14.5 -14.4,14.5 z m -42.4,-29.8 0,0 28.4,14.4 0,0.1 c 0,0.1 0,0.2 0,0.3 0,0.2 0,0.3 0,0.5 0,7.7 6.3,14 14.1,14 7.7,0 14,-6.3 14,-14 0,-7.8 -6.3,-14.1 -14,-14.1 -3.5,0 -6.9,1.3 -9.5,3.7 l -0.1,0.1 -0.1,-0.1 -27.3,-14 0,-0.1 c 0.1,-0.7 0.2,-1.4 0.2,-2.2 0,-0.3 0,-0.6 -0.1,-0.9 0,-0.1 0,-0.2 0,-0.3 l 0,-0.1 0.1,-0.1 27.6,-14 0.1,0.1 c 2.5,2.1 5.8,3.3 9.1,3.3 7.7,0 14,-6.3 14,-14.1 0,-7.7 -6.2,-13.9 -13.8,-14 l 0,0.1 -0.2,0 c -7.8,0 -14.1,6.3 -14.1,14 0,0.4 0,0.7 0.1,1 l 0,0.3 -0.1,0.1 -27.5,14 -0.1,-0.1 c -2.5,-2.2 -5.8,-3.3 -9.1,-3.3 -7.7,0 -14,6.3 -14,14 0,7.7 6.3,14 14,14 2.9,0.2 5.8,-0.7 8.3,-2.6 l 0,0 z"
id="path29"
style="fill:#ffffff" /><path
d="m 83.9,1142.1 c -8.5,0 -15.3,-6.9 -15.3,-15.3 0,0 0,-0.1 0,-0.1 L 41.7,1113 c -2.5,1.7 -5.5,2.6 -8.6,2.6 -8.4,0 -15.3,-6.9 -15.3,-15.3 0,-8.4 6.9,-15.3 15.3,-15.3 3.4,0 6.7,1.1 9.4,3.2 l 26.1,-13.3 c 0,-0.2 0,-0.4 0,-0.7 0,-8 6.2,-14.6 14.1,-15.3 l 0,0 1,-0.1 c 8.6,0 15.5,6.9 15.5,15.3 0,8.5 -6.9,15.3 -15.3,15.3 -3.4,0 -6.7,-1.1 -9.3,-3.2 l -26.2,13.3 c 0,0.2 0,0.4 0,0.6 0,0.5 0,1 -0.1,1.6 l 25.8,13.2 c 2.7,-2.3 6.2,-3.5 9.7,-3.5 8.4,0 15.3,6.9 15.3,15.3 0.1,8.5 -6.8,15.4 -15.2,15.4 z m -42.6,-31.7 0.7,0.3 28.8,14.7 -0.1,1.1 c 0,0.1 0,0.2 0,0.4 0,7.2 5.9,13.1 13.1,13.1 7.2,0 13.1,-5.9 13.1,-13.1 0,-7.2 -5.9,-13.1 -13.1,-13.1 -3.3,0 -6.4,1.2 -8.8,3.4 l -0.5,0.4 -0.6,-0.2 -28,-14.3 0.1,-0.6 c 0.1,-0.8 0.2,-1.5 0.2,-2.2 0,-0.3 0,-0.5 0,-0.8 l -0.1,-1 0.5,-0.4 28.2,-14.4 0.5,0.4 c 2.5,2.1 5.5,3.2 8.6,3.2 7.2,0 13.1,-5.9 13.1,-13.1 0,-6.9 -5.5,-12.7 -12.3,-13.1 l -0.6,0 c -7.5,0 -13.4,5.9 -13.4,13.1 0,0.3 0,0.7 0.1,1 l 0.1,1 -0.5,0.3 -28.2,14.4 -0.5,-0.4 c -2.4,-2.1 -5.5,-3.2 -8.6,-3.2 -7.2,0 -13.1,5.9 -13.1,13.1 0,7.2 5.9,13.1 13.1,13.1 2.9,0 5.6,-0.9 7.8,-2.5 l 0.4,-0.6 z"
id="path31"
style="fill:#3a9804" /></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
enable-background="new 0 0 128 128"
viewBox="0 0 128 128"
y="0px"
x="0px"
id="Sync"
version="1.1"><metadata
id="metadata37"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs35" /><g
transform="matrix(0.96875,0,0,0.96875,2,2)"
id="g3"><g
id="g5"><circle
style="fill:#2268ab"
id="circle7"
r="61.933998"
cy="64"
cx="64" /><path
style="fill:#114999"
id="path9"
d="M 64,128 C 28.711,128 0,99.289 0,64 0,28.711 28.711,0 64,0 c 35.289,0 64,28.711 64,64 0,35.289 -28.711,64 -64,64 z M 64,4.132 C 30.989,4.132 4.132,30.987 4.132,64 4.132,97.013 30.989,123.868 64,123.868 97.011,123.868 123.868,97.013 123.868,64 123.868,30.987 97.011,4.132 64,4.132 Z" /></g><g
id="g11"><g
id="g13"><g
id="g15"><path
style="fill:#ffffff"
id="path17"
d="M 85.311,53.564 C 81.354,45.453 73.09,40.257 64.047,40.257 c -1.375,0 -2.764,0.121 -4.125,0.364 -8.236,1.448 -15.172,7.237 -18.111,15.105 l -0.264,0.705 -14.818,2.616 0.346,-1.871 C 29.911,41.813 42.143,29.669 57.511,26.96 c 2.164,-0.38 4.361,-0.575 6.543,-0.575 12.025,0 23.222,5.73 30.3,15.411 l 4.771,-6.193 1.889,21.721 0.325,1.479 -0.046,0.004 0,0.007 -23.129,4.048 7.147,-9.298 z" /></g><g
id="g19"><path
style="fill:#114999"
id="path21"
d="m 64.053,27.711 c 12.314,0 23.643,6.318 30.25,16.325 l 3.8,-4.938 1.6,18.411 c 0.007,0.048 0.025,0.111 0.036,0.159 l -0.025,0.003 0.014,0.074 -18.446,3.232 5.568,-7.243 C 82.854,44.818 73.914,38.936 64.047,38.936 c -1.436,0 -2.889,0.125 -4.353,0.38 -9.054,1.595 -16.114,7.893 -19.121,15.948 l -12.197,2.152 c 2.672,-14.457 14.061,-26.452 29.368,-29.152 2.117,-0.373 4.227,-0.553 6.309,-0.553 m 0,-2.647 c -2.257,0 -4.536,0.2 -6.768,0.595 -7.957,1.405 -15.164,5.177 -20.846,10.911 -5.55,5.605 -9.239,12.65 -10.664,20.368 l -0.693,3.745 3.754,-0.661 12.196,-2.152 1.49,-0.264 0.528,-1.415 c 1.343,-3.602 3.6,-6.819 6.525,-9.307 3.014,-2.557 6.668,-4.273 10.575,-4.962 1.289,-0.225 2.596,-0.343 3.896,-0.343 8.264,0 15.839,4.602 19.704,11.845 l -4.564,5.941 -4.143,5.386 6.697,-1.168 18.443,-3.232 1.371,-0.24 1.393,-0.173 -0.625,-2.82 -1.582,-18.248 -0.593,-6.761 -4.143,5.377 -1.65,2.145 C 91.132,35.633 87.118,32.268 82.579,29.799 76.9,26.702 70.489,25.064 64.053,25.064 l 0,0 z" /></g></g><g
id="g23"><g
id="g25"><path
style="fill:#ffffff"
id="path27"
d="M 64.032,101.541 C 52.05,101.541 40.875,95.84 33.778,86.2 l -4.825,6.289 -1.918,-21.98 c -0.007,-0.032 -0.011,-0.063 -0.014,-0.087 l -0.147,-1.245 13.597,-2.398 0.018,0.096 9.422,-1.653 -7.093,9.234 c 3.979,8.048 12.221,13.207 21.211,13.207 1.368,0 2.761,-0.12 4.125,-0.362 8.154,-1.439 15.068,-7.148 18.036,-14.902 l 0.268,-0.704 14.857,-2.62 -0.361,1.884 C 99.543,78.37 95.968,85.127 90.618,90.5 c -5.475,5.498 -12.411,9.121 -20.057,10.466 -2.157,0.382 -4.354,0.575 -6.529,0.575 z" /></g><g
id="g29"><path
style="fill:#114999"
id="path31"
d="m 46.793,67.111 -5.518,7.182 c 4.021,8.855 12.918,14.691 22.754,14.691 1.432,0 2.89,-0.123 4.353,-0.384 8.975,-1.581 15.997,-7.784 19.043,-15.732 l 12.232,-2.159 c -2.743,14.366 -14.086,26.268 -29.325,28.957 -2.118,0.37 -4.221,0.554 -6.3,0.554 -12.278,0 -23.582,-6.291 -30.204,-16.255 l -3.85,5.019 -1.632,-18.652 C 28.339,70.307 28.339,70.28 28.335,70.259 l 11.054,-1.948 c 0.004,0.029 0.018,0.059 0.025,0.095 l 7.379,-1.295 m 6.239,-3.779 -6.697,1.173 -4.764,0.834 -0.014,-0.093 -2.629,0.463 -11.05,1.948 -2.471,0.432 0.304,2.487 c 0.004,0.029 0.007,0.059 0.011,0.095 l 1.622,18.545 0.589,6.779 4.143,-5.398 1.711,-2.23 c 3.225,3.986 7.239,7.329 11.761,9.784 5.675,3.084 12.068,4.713 18.486,4.713 2.25,0 4.525,-0.2 6.761,-0.591 7.914,-1.398 15.097,-5.145 20.765,-10.841 5.535,-5.559 9.232,-12.555 10.696,-20.223 l 0.718,-3.768 -3.775,0.668 -12.232,2.156 -1.475,0.259 -0.536,1.402 c -1.361,3.55 -3.618,6.723 -6.529,9.173 -2.996,2.522 -6.629,4.218 -10.503,4.902 -1.29,0.225 -2.6,0.343 -3.893,0.343 -8.214,0 -15.764,-4.564 -19.65,-11.746 l 4.511,-5.872 4.14,-5.394 0,0 z" /></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

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