Compare commits
25 Commits
wip/ssh-so
...
3.30.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bb655555e | ||
|
|
4cd05ea9fd | ||
|
|
928ac108d5 | ||
|
|
22957ff55a | ||
|
|
4002b06f3a | ||
|
|
b54bb72cb9 | ||
|
|
e037fdf1a0 | ||
|
|
81dec85a2c | ||
|
|
d3026098b0 | ||
|
|
c89e088a71 | ||
|
|
230f659a39 | ||
|
|
63378ac30d | ||
|
|
84910f796c | ||
|
|
16ac4761ab | ||
|
|
f049eaf36e | ||
|
|
689b21f48b | ||
|
|
ebf0f702a6 | ||
|
|
0f5f0bd23a | ||
|
|
8384c29510 | ||
|
|
c8d19ed0da | ||
|
|
eb9235ef30 | ||
|
|
11877d3da7 | ||
|
|
b3b5aa2235 | ||
|
|
84d7270df1 | ||
|
|
a24c28cbcd |
@@ -1,12 +0,0 @@
|
||||
# See https://wiki.apertis.org/Guidelines/Coding_conventions#Code_formatting
|
||||
BasedOnStyle: GNU
|
||||
AlwaysBreakAfterDefinitionReturnType: All
|
||||
BreakBeforeBinaryOperators: None
|
||||
BinPackParameters: false
|
||||
SpaceAfterCStyleCast: true
|
||||
PointerAlignment: Right
|
||||
# Our column limit is actually 80, but setting that results in clang-format
|
||||
# making a lot of dubious hanging-indent choices; disable it and assume the
|
||||
# developer will line wrap appropriately. clang-format will still check
|
||||
# existing hanging indents.
|
||||
ColumnLimit: 0
|
||||
5
.gitignore
vendored
@@ -1,6 +1,3 @@
|
||||
__pycache__
|
||||
_build/
|
||||
**/*~
|
||||
/subprojects/*
|
||||
!/subprojects/*.wrap
|
||||
.flatpak-builder/
|
||||
**/*~
|
||||
399
.gitlab-ci.yml
@@ -1,14 +1,9 @@
|
||||
include:
|
||||
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/34f4ade99434043f88e164933f570301fd18b125/templates/fedora.yml'
|
||||
|
||||
variables:
|
||||
FDO_UPSTREAM_REPO: gnome/gnome-control-center
|
||||
|
||||
image: claudioandre/settings:job-502.6_fedora.dev # temporarily pinned to old tag
|
||||
stages:
|
||||
- prepare
|
||||
- build
|
||||
- test
|
||||
- manual
|
||||
- review
|
||||
- deploy
|
||||
|
||||
.Log files: &log_files [./*.log, _build/meson-logs/]
|
||||
@@ -31,160 +26,13 @@ stages:
|
||||
|
||||
.Build procedure: &build_procedure
|
||||
echo "== Building ==" &&
|
||||
dnf install -y dnf5-plugins &&
|
||||
git clone https://gitlab.gnome.org/GNOME/gtk.git &&
|
||||
cd gtk &&
|
||||
dnf5 builddep -y gtk4 &&
|
||||
meson setup . _build -Dprefix=/usr -Dlibdir=lib64 &&
|
||||
ninja -C _build install &&
|
||||
cd .. &&
|
||||
rm -rf _build/ &&
|
||||
meson . _build ${BUILD_OPTS} -Dprofile=development &&
|
||||
meson . _build ${BUILD_OPTS} &&
|
||||
ninja -C _build 2>&1 | tee compilation.log
|
||||
|
||||
.Run Tests: &run_tests
|
||||
echo "== Testing ==" &&
|
||||
meson test -C _build --verbose --no-stdsplit
|
||||
|
||||
.fedora.container.common:
|
||||
# As of 2022-03-07 runners not tagged with "crun" have broken seccomp rules
|
||||
# affecting the close_range syscall and breaking g_spawn
|
||||
# Note that "asan" tests are disabled for the same reason, see below.
|
||||
# https://gitlab.gnome.org/Infrastructure/GitLab/-/issues/545
|
||||
tags: [ crun ]
|
||||
variables:
|
||||
# When branching a stable release, change 'main'
|
||||
# to the release number/branch to ensure that
|
||||
# a new image will be created, tailored for the
|
||||
# stable branch.
|
||||
# Could probably also switch away from rawhide,
|
||||
# to stable fedora branch as well.
|
||||
FDO_DISTRIBUTION_TAG: '2023-06-07.0-main'
|
||||
FDO_DISTRIBUTION_VERSION: rawhide
|
||||
|
||||
#############################################
|
||||
# Create CI Docker Images #
|
||||
#############################################
|
||||
|
||||
# See also https://gitlab.freedesktop.org/freedesktop/ci-templates
|
||||
build.container.fedora@x86_64:
|
||||
extends:
|
||||
- '.fdo.container-build@fedora'
|
||||
- '.fedora.container.common'
|
||||
stage: 'prepare'
|
||||
variables:
|
||||
# no need to pull the whole tree for rebuilding the image
|
||||
GIT_STRATEGY: none
|
||||
# Expiry sets fdo.expires on the image
|
||||
FDO_EXPIRES_AFTER: 8w
|
||||
# NOTES:
|
||||
# - gobject-introspection-devel is needed for gsettings-desktop-schemas
|
||||
FDO_DISTRIBUTION_PACKAGES: >-
|
||||
@c-development @development-tools
|
||||
git
|
||||
llvm clang libasan libtsan libubsan gcovr
|
||||
meson
|
||||
accountsservice-devel
|
||||
cheese-libs-devel
|
||||
chrpath
|
||||
colord-devel colord-gtk-devel
|
||||
cups-devel
|
||||
desktop-file-utils
|
||||
docbook-style-xsl
|
||||
flatpak-devel
|
||||
gdk-pixbuf2-devel
|
||||
gettext
|
||||
glib2-devel
|
||||
gobject-introspection-devel
|
||||
gnome-bluetooth-libs-devel
|
||||
gnome-desktop3-devel
|
||||
gnome-online-accounts-devel
|
||||
grilo-devel
|
||||
gsettings-desktop-schemas-devel
|
||||
gsound-devel
|
||||
gtk3-devel ibus-devel
|
||||
gtk4-devel
|
||||
intltool
|
||||
appstream-devel
|
||||
sassc
|
||||
libadwaita-devel
|
||||
libcanberra-devel
|
||||
libgtop2-devel
|
||||
libgudev-devel
|
||||
libnma-devel
|
||||
libnotify-devel
|
||||
libpwquality-devel
|
||||
libsmbclient-devel
|
||||
libsoup3-devel
|
||||
libudisks2-devel
|
||||
libwacom-devel
|
||||
libX11-devel
|
||||
libXi-devel
|
||||
libxml2-devel
|
||||
libxslt
|
||||
ModemManager-glib-devel
|
||||
NetworkManager-libnm-devel
|
||||
polkit-devel
|
||||
pulseaudio-libs-devel
|
||||
upower-devel
|
||||
python3-dbusmock
|
||||
xorg-x11-server-Xvfb
|
||||
mesa-dri-drivers
|
||||
libsecret-devel
|
||||
geocode-glib2-devel
|
||||
libgweather-devel
|
||||
lcms2-devel
|
||||
geoclue2-devel
|
||||
libnotify-devel
|
||||
alsa-lib-devel
|
||||
nss-devel
|
||||
gcr3-devel
|
||||
gcr-devel
|
||||
setxkbmap
|
||||
appstream-devel
|
||||
FDO_DISTRIBUTION_EXEC: |-
|
||||
git clone https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas.git && \
|
||||
cd gsettings-desktop-schemas && \
|
||||
meson . _build --prefix=/usr && \
|
||||
ninja -C _build && \
|
||||
ninja -C _build install && \
|
||||
cd .. && \
|
||||
git clone https://gitlab.gnome.org/GNOME/gnome-desktop.git && \
|
||||
cd gnome-desktop && \
|
||||
meson . _build --prefix=/usr -Ddesktop_docs=false && \
|
||||
ninja -C _build && \
|
||||
ninja -C _build install && \
|
||||
cd .. && \
|
||||
git clone https://gitlab.gnome.org/GNOME/gnome-bluetooth.git && \
|
||||
cd gnome-bluetooth && \
|
||||
meson . _build --prefix=/usr -Dsendto=false && \
|
||||
ninja -C _build && \
|
||||
ninja -C _build install && \
|
||||
cd .. && \
|
||||
git clone https://gitlab.gnome.org/GNOME/libnma.git && \
|
||||
cd libnma && \
|
||||
meson . _build --prefix=/usr -Dlibnma_gtk4=true -Dmobile_broadband_provider_info=false -Dgcr=false -Dgtk_doc=false && \
|
||||
ninja -C _build && \
|
||||
ninja -C _build install && \
|
||||
cd .. && \
|
||||
git clone https://github.com/hughsie/colord-gtk.git && \
|
||||
cd colord-gtk && \
|
||||
meson . _build --prefix=/usr -Dgtk4=true -Ddocs=false -Dtests=false -Dman=false && \
|
||||
ninja -C _build && \
|
||||
ninja -C _build install && \
|
||||
cd .. && \
|
||||
git clone https://gitlab.gnome.org/GNOME/libgweather.git && \
|
||||
cd libgweather && \
|
||||
meson . _build --prefix=/usr -Denable_vala=false -Dgtk_doc=false -Dintrospection=false && \
|
||||
ninja -C _build && \
|
||||
ninja -C _build install && \
|
||||
cd .. && \
|
||||
git clone https://gitlab.gnome.org/GNOME/gnome-settings-daemon.git && \
|
||||
cd gnome-settings-daemon && \
|
||||
meson . _build --prefix=/usr && \
|
||||
ninja -C _build && \
|
||||
ninja -C _build install && \
|
||||
cd ..
|
||||
ninja -C _build test
|
||||
|
||||
##
|
||||
# Stage: Build
|
||||
@@ -194,10 +42,6 @@ build.container.fedora@x86_64:
|
||||
# any of them.
|
||||
##
|
||||
build:
|
||||
extends:
|
||||
- '.fdo.distribution-image@fedora'
|
||||
- '.fedora.container.common'
|
||||
|
||||
<<: *save_untracked_files
|
||||
stage: build
|
||||
|
||||
@@ -214,32 +58,12 @@ build:
|
||||
# Save all but git-related files
|
||||
- rm -rf .git .gitignore .gitmodules
|
||||
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
|
||||
##
|
||||
# Stage: Test
|
||||
#
|
||||
# Runs static checks.
|
||||
# Runs the unit tests.
|
||||
##
|
||||
style-check-diff:
|
||||
extends:
|
||||
- '.fdo.distribution-image@fedora'
|
||||
- '.fedora.container.common'
|
||||
needs:
|
||||
- build.container.fedora@x86_64
|
||||
stage: test
|
||||
when: always
|
||||
allow_failure: true
|
||||
script:
|
||||
- .gitlab-ci/run-style-check-diff.sh
|
||||
|
||||
test:
|
||||
extends:
|
||||
- '.fdo.distribution-image@fedora'
|
||||
- '.fedora.container.common'
|
||||
<<: *save_build_logs
|
||||
stage: test
|
||||
|
||||
@@ -248,36 +72,31 @@ test:
|
||||
|
||||
script:
|
||||
- *environment_information
|
||||
- *build_procedure
|
||||
- *run_tests
|
||||
|
||||
- |
|
||||
if [[ -n "${CI_COMMIT_TAG}" ]]; then
|
||||
*run_tests
|
||||
|
||||
echo "== Distro Test =="
|
||||
ninja dist -C _build
|
||||
else
|
||||
echo "== Testing =="
|
||||
meson test -C _build --verbose --no-stdsplit
|
||||
fi
|
||||
|
||||
artifacts:
|
||||
reports:
|
||||
junit: "_build/meson-logs/testlog.junit.xml"
|
||||
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
- $CI_COMMIT_TITLE =~ /^Update.*translation$/
|
||||
|
||||
# Runs the coverage test.
|
||||
coverage:
|
||||
extends:
|
||||
- '.fdo.distribution-image@fedora'
|
||||
- '.fedora.container.common'
|
||||
<<: *save_build_logs
|
||||
stage: test
|
||||
variables:
|
||||
BUILD_OPTS: "-Db_coverage=true"
|
||||
coverage: '/^Lines:.\d+.\d+.(\d+\.\d+\%)/'
|
||||
only:
|
||||
- main@GNOME/gnome-control-center
|
||||
- master@GNOME/gnome-control-center
|
||||
|
||||
script:
|
||||
- *environment_information
|
||||
@@ -293,7 +112,6 @@ coverage:
|
||||
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
- $CI_COMMIT_TITLE =~ /^Update.*translation$/
|
||||
|
||||
# Runs the address sanitizer.
|
||||
@@ -305,9 +123,6 @@ coverage:
|
||||
# Publishes the Coverage Report generated above
|
||||
##
|
||||
pages:
|
||||
extends:
|
||||
- '.fdo.distribution-image@fedora'
|
||||
- '.fedora.container.common'
|
||||
stage: deploy
|
||||
dependencies:
|
||||
- coverage
|
||||
@@ -317,7 +132,7 @@ pages:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- main@GNOME/gnome-control-center
|
||||
- master@GNOME/gnome-control-center
|
||||
|
||||
except:
|
||||
variables:
|
||||
@@ -331,18 +146,19 @@ pages:
|
||||
##
|
||||
flatpak:
|
||||
stage: manual
|
||||
image: quay.io/gnome_infrastructure/gnome-runtime-images:gnome-master
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
|
||||
artifacts:
|
||||
name: package
|
||||
paths:
|
||||
- $(pwd)/*.flatpak
|
||||
expire_in: 7 days
|
||||
expire_in: 2 days
|
||||
|
||||
variables:
|
||||
OLD_APPID: "org.gnome.Settings"
|
||||
APPID: "org.gnome.SettingsDevel"
|
||||
BUNDLE: "org.gnome.SettingsDevel.flatpak"
|
||||
MANIFEST_PATH: "build-aux/flatpak/org.gnome.Settings.json"
|
||||
MANIFEST_PATH: "org.gnome.Settings.json"
|
||||
PATCHES: "build-aux/flatpak/*.patch"
|
||||
PROJECT_FILE: "build-aux/flatpak/org.gnome.Settings.json"
|
||||
PROJECT_ID: "org.gnome.Settings"
|
||||
PROJECT_NAME: "gnome-control-center.git"
|
||||
RUNTIME_REPO: "https://sdk.gnome.org/gnome-nightly.flatpakrepo"
|
||||
@@ -350,6 +166,10 @@ flatpak:
|
||||
script:
|
||||
- echo "== Flatpak packaging =="
|
||||
|
||||
# Move needed files to the root folder
|
||||
- cp ${PATCHES} . || true
|
||||
- cp ${PROJECT_FILE} ${MANIFEST_PATH}
|
||||
|
||||
# Make it a develoment manifest
|
||||
- sed -i -n "p; s/$PROJECT_NAME//p" ${MANIFEST_PATH}
|
||||
- >
|
||||
@@ -363,11 +183,7 @@ flatpak:
|
||||
- sed -i "s,<<ID>>,$APPID,g" ${MANIFEST_PATH}
|
||||
- sed -i "s,<<current>>,origin/$CI_COMMIT_REF_NAME,g" ${MANIFEST_PATH}
|
||||
|
||||
# Update the icon name
|
||||
- mv data/icons/hicolor/scalable/apps/$OLD_APPID.svg data/icons/hicolor/scalable/apps/$APPID.svg
|
||||
- mv data/icons/hicolor/symbolic/apps/$OLD_APPID-symbolic.svg data/icons/hicolor/symbolic/apps/$APPID-symbolic.svg
|
||||
|
||||
- flatpak-builder --bundle-sources --disable-rofiles-fuse --repo=devel build ${MANIFEST_PATH}
|
||||
- flatpak-builder --bundle-sources --repo=devel build ${MANIFEST_PATH}
|
||||
- flatpak build-bundle devel ${BUNDLE} --runtime-repo=${RUNTIME_REPO} ${APPID}
|
||||
|
||||
cache:
|
||||
@@ -377,14 +193,42 @@ flatpak:
|
||||
except:
|
||||
- tags
|
||||
- gnome-3-.*
|
||||
- main@GNOME/gnome-control-center
|
||||
- master@GNOME/gnome-control-center
|
||||
|
||||
review:
|
||||
stage: review
|
||||
dependencies:
|
||||
- flatpak
|
||||
|
||||
when: manual
|
||||
variables:
|
||||
BUNDLE: "org.gnome.SettingsDevel.flatpak"
|
||||
script:
|
||||
- echo "Generating flatpak deployment"
|
||||
artifacts:
|
||||
paths:
|
||||
- ${BUNDLE}
|
||||
expire_in: 30 days
|
||||
environment:
|
||||
name: review/$CI_COMMIT_REF_NAME
|
||||
url: https://gitlab.gnome.org/$CI_PROJECT_PATH/-/jobs/$CI_JOB_ID/artifacts/raw/${BUNDLE}
|
||||
on_stop: stop_review
|
||||
except:
|
||||
- tags
|
||||
- gnome-3-.*
|
||||
- master@GNOME/gnome-control-center
|
||||
|
||||
stop_review:
|
||||
stage: review
|
||||
script:
|
||||
- echo "Stopping flatpak deployment"
|
||||
when: manual
|
||||
environment:
|
||||
name: review/$CI_COMMIT_REF_NAME
|
||||
action: stop
|
||||
|
||||
# Runs the sanitizers [address, thread, undefined, and memory].
|
||||
.sanitizer: &sanitizer
|
||||
extends:
|
||||
- '.fdo.distribution-image@fedora'
|
||||
- '.fedora.container.common'
|
||||
<<: *save_build_logs
|
||||
stage: manual
|
||||
when: manual
|
||||
@@ -395,44 +239,135 @@ flatpak:
|
||||
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
- $CI_COMMIT_TITLE =~ /^Update.*translation$/
|
||||
|
||||
# Disabled because we currently need "crun" tagged runners, see above
|
||||
#asan:
|
||||
# extends:
|
||||
# - '.fdo.distribution-image@fedora'
|
||||
# - '.fedora.container.common'
|
||||
# <<: *sanitizer
|
||||
# # ASAN requires debugging capabilities
|
||||
# tags: [ asan ]
|
||||
# stage: manual
|
||||
# when: manual
|
||||
# variables:
|
||||
# BUILD_OPTS: "-Db_sanitize=address"
|
||||
# LSAN_OPTIONS: "suppressions=${CI_PROJECT_DIR}/build-aux/ci/lsan.supp"
|
||||
asan:
|
||||
<<: *sanitizer
|
||||
stage: test
|
||||
when: on_success
|
||||
variables:
|
||||
BUILD_OPTS: "-Db_sanitize=address"
|
||||
LSAN_OPTIONS: "suppressions=${CI_PROJECT_DIR}/build-aux/ci/lsan.supp"
|
||||
|
||||
tsan:
|
||||
extends:
|
||||
- '.fdo.distribution-image@fedora'
|
||||
- '.fedora.container.common'
|
||||
<<: *sanitizer
|
||||
variables:
|
||||
BUILD_OPTS: "-Db_sanitize=thread"
|
||||
|
||||
ubsan:
|
||||
extends:
|
||||
- '.fdo.distribution-image@fedora'
|
||||
- '.fedora.container.common'
|
||||
<<: *sanitizer
|
||||
variables:
|
||||
BUILD_OPTS: "-Db_sanitize=undefined"
|
||||
|
||||
msan:
|
||||
extends:
|
||||
- '.fdo.distribution-image@fedora'
|
||||
- '.fedora.container.common'
|
||||
<<: *sanitizer
|
||||
variables:
|
||||
BUILD_OPTS: "-Db_sanitize=memory"
|
||||
CC: "clang"
|
||||
|
||||
# Runs multiarch build test.
|
||||
.qemu: &multiarch
|
||||
<<: *save_build_logs
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
|
||||
script:
|
||||
# Register QEMU archs
|
||||
- docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||
|
||||
# Run the multiarch test job using QEMU
|
||||
- 'docker run -v $(pwd):/cwd $IMAGE bash -e -c "cd /cwd &&
|
||||
echo == Building == &&
|
||||
rm -rf _build/ &&
|
||||
meson . _build ${BUILD_OPTS} &&
|
||||
ninja -C _build 2>&1 | tee compilation.log &&
|
||||
|
||||
echo == Testing == &&
|
||||
ninja -C _build test"
|
||||
'
|
||||
|
||||
except:
|
||||
variables:
|
||||
- $CI_COMMIT_TITLE =~ /^Update.*translation$/
|
||||
|
||||
armv8:
|
||||
<<: *multiarch
|
||||
stage: manual
|
||||
when: manual
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay
|
||||
IMAGE: "claudioandre/settings:fedora.aarch64"
|
||||
|
||||
ppc64le:
|
||||
<<: *multiarch
|
||||
stage: manual
|
||||
when: manual
|
||||
allow_failure: true
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay
|
||||
IMAGE: "claudioandre/settings:fedora.ppc64le"
|
||||
|
||||
#############################################
|
||||
# Create CI Docker Images #
|
||||
#############################################
|
||||
.Docker image template: &create_docker_image
|
||||
image: docker:latest
|
||||
stage: deploy
|
||||
services:
|
||||
- docker:dind
|
||||
only:
|
||||
variables:
|
||||
- $CRON_TASK == "BUILD_CI_IMAGES"
|
||||
|
||||
script:
|
||||
# Skip the build (if requested)
|
||||
- |
|
||||
if [[ -z "${CI_COMMIT_MESSAGE##*[skip images]*}" && -z "${CI_COMMIT_MESSAGE##*[$NAME]*}" ]]; then
|
||||
echo "== Nothing to do =="
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get multiarch stuff
|
||||
- |
|
||||
if [[ -n "${TARGET_ARCH}" ]]; then
|
||||
docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||
wget https://github.com/multiarch/qemu-user-static/releases/download/v2.12.0/x86_64_qemu-${TARGET_ARCH}-static.tar.gz
|
||||
fi
|
||||
|
||||
# Build using the Dockerfile
|
||||
- docker build -f "$DOCKERFILE" -t "$CI_REGISTRY_IMAGE:$NAME" .
|
||||
|
||||
# Prepare to publish
|
||||
- docker tag "$CI_REGISTRY_IMAGE:$NAME" "$CI_REGISTRY_IMAGE:job-"$CI_JOB_ID"_$NAME"
|
||||
- docker images
|
||||
- docker login ${CI_REGISTRY} -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD}
|
||||
|
||||
# Publish (if running on a schedule)
|
||||
- |
|
||||
if [[ "${CI_PIPELINE_SOURCE}" == "schedule" ]]; then
|
||||
docker push "$CI_REGISTRY_IMAGE"
|
||||
fi
|
||||
|
||||
fedora.dev:
|
||||
<<: *create_docker_image
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay
|
||||
DOCKERFILE: "build-aux/ci/Dockerfile.fedora.rawhide"
|
||||
NAME: "fedora.dev"
|
||||
|
||||
fedora.aarch64:
|
||||
<<: *create_docker_image
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay
|
||||
DOCKERFILE: "build-aux/ci/Dockerfile.arm64v8.fedora.rawhide"
|
||||
NAME: "fedora.aarch64"
|
||||
TARGET_ARCH: "aarch64"
|
||||
|
||||
fedora.ppc64le:
|
||||
<<: *create_docker_image
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay
|
||||
DOCKERFILE: "build-aux/ci/Dockerfile.ppc64le.fedora.rawhide"
|
||||
NAME: "fedora.ppc64le"
|
||||
TARGET_ARCH: "ppc64le"
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# === clang-format-diff.py - ClangFormat Diff Reformatter ---*- python -*-=== #
|
||||
#
|
||||
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
# See https://llvm.org/LICENSE.txt for license information.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
# ===---------------------------------------------------------------------=== #
|
||||
|
||||
"""
|
||||
This script reads input from a unified diff and reformats all the changed
|
||||
lines. This is useful to reformat all the lines touched by a specific patch.
|
||||
Example usage for git/svn users:
|
||||
|
||||
git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i
|
||||
svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
|
||||
|
||||
"""
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import argparse
|
||||
import difflib
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
if sys.version_info.major >= 3:
|
||||
from io import StringIO
|
||||
else:
|
||||
from io import BytesIO as StringIO
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument('-i', action='store_true', default=False,
|
||||
help='apply edits to files instead of displaying a '
|
||||
'diff')
|
||||
parser.add_argument('-p', metavar='NUM', default=0,
|
||||
help='strip the smallest prefix containing P slashes')
|
||||
parser.add_argument('-regex', metavar='PATTERN', default=None,
|
||||
help='custom pattern selecting file paths to reformat '
|
||||
'(case sensitive, overrides -iregex)')
|
||||
parser.add_argument('-iregex', metavar='PATTERN',
|
||||
default=r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc'
|
||||
r'|js|ts|proto|protodevel|java|cs)',
|
||||
help='custom pattern selecting file paths to reformat '
|
||||
'(case insensitive, overridden by -regex)')
|
||||
parser.add_argument('-sort-includes', action='store_true', default=False,
|
||||
help='let clang-format sort include blocks')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='be more verbose, ineffective without -i')
|
||||
parser.add_argument('-style',
|
||||
help='formatting style to apply (LLVM, Google, '
|
||||
'Chromium, Mozilla, WebKit)')
|
||||
parser.add_argument('-binary', default='clang-format',
|
||||
help='location of binary to use for clang-format')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Extract changed lines for each file.
|
||||
filename = None
|
||||
lines_by_file = {}
|
||||
for line in sys.stdin:
|
||||
match = re.search(r'^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
|
||||
if match:
|
||||
filename = match.group(2)
|
||||
if filename is None:
|
||||
continue
|
||||
|
||||
if args.regex is not None:
|
||||
if not re.match('^%s$' % args.regex, filename):
|
||||
continue
|
||||
else:
|
||||
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
|
||||
continue
|
||||
|
||||
match = re.search(r'^@@.*\+(\d+)(,(\d+))?', line)
|
||||
if match:
|
||||
start_line = int(match.group(1))
|
||||
line_count = 1
|
||||
if match.group(3):
|
||||
line_count = int(match.group(3))
|
||||
if line_count == 0:
|
||||
continue
|
||||
end_line = start_line + line_count - 1
|
||||
lines_by_file.setdefault(filename, []).extend(
|
||||
['-lines', str(start_line) + ':' + str(end_line)])
|
||||
|
||||
# Reformat files containing changes in place.
|
||||
# We need to count amount of bytes generated in the output of
|
||||
# clang-format-diff. If clang-format-diff doesn't generate any bytes it
|
||||
# means there is nothing to format.
|
||||
format_line_counter = 0
|
||||
for filename, lines in lines_by_file.items():
|
||||
if args.i and args.verbose:
|
||||
print('Formatting {}'.format(filename))
|
||||
command = [args.binary, filename]
|
||||
if args.i:
|
||||
command.append('-i')
|
||||
if args.sort_includes:
|
||||
command.append('-sort-includes')
|
||||
command.extend(lines)
|
||||
if args.style:
|
||||
command.extend(['-style', args.style])
|
||||
p = subprocess.Popen(command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=None,
|
||||
stdin=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
stdout, _ = p.communicate()
|
||||
if p.returncode != 0:
|
||||
sys.exit(p.returncode)
|
||||
|
||||
if not args.i:
|
||||
with open(filename) as f:
|
||||
code = f.readlines()
|
||||
formatted_code = StringIO(stdout).readlines()
|
||||
diff = difflib.unified_diff(code, formatted_code,
|
||||
filename, filename,
|
||||
'(before formatting)',
|
||||
'(after formatting)')
|
||||
diff_string = ''.join(diff)
|
||||
if diff_string:
|
||||
format_line_counter += sys.stdout.write(diff_string)
|
||||
|
||||
if format_line_counter > 0:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,62 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
ancestor_horizon=31 # days (one month)
|
||||
|
||||
# Recently, git is picky about directory ownership. Tell it not to worry.
|
||||
git config --global --add safe.directory "$PWD"
|
||||
|
||||
# We need to add a new remote for the upstream target branch, since this script
|
||||
# could be running in a personal fork of the repository which has out of date
|
||||
# branches.
|
||||
#
|
||||
# Limit the fetch to a certain date horizon to limit the amount of data we get.
|
||||
# If the branch was forked from origin/main before this horizon, it should
|
||||
# probably be rebased.
|
||||
if ! git ls-remote --exit-code upstream >/dev/null 2>&1 ; then
|
||||
git remote add upstream https://gitlab.gnome.org/GNOME/gnome-control-center.git
|
||||
fi
|
||||
|
||||
# Work out the newest common ancestor between the detached HEAD that this CI job
|
||||
# has checked out, and the upstream target branch (which will typically be
|
||||
# `upstream/main` or `upstream/glib-2-62`).
|
||||
# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` or `${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}`
|
||||
# are only defined if we’re running in a merge request pipeline,
|
||||
# fall back to `${CI_DEFAULT_BRANCH}` or `${CI_COMMIT_BRANCH}` respectively
|
||||
# otherwise.
|
||||
|
||||
source_branch="${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:-${CI_COMMIT_BRANCH}}"
|
||||
target_branch="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}"
|
||||
git fetch --shallow-since="$(date --date="${ancestor_horizon} days ago" +%Y-%m-%d)" origin "${source_branch}"
|
||||
git fetch --shallow-since="$(date --date="${ancestor_horizon} days ago" +%Y-%m-%d)" upstream "${target_branch}"
|
||||
|
||||
newest_common_ancestor_sha=$(git merge-base upstream/${target_branch} origin/${source_branch})
|
||||
if [ -z "${newest_common_ancestor_sha}" ]; then
|
||||
echo "Couldn’t find common ancestor with upstream main branch. This typically"
|
||||
echo "happens if you branched from main a long time ago. Please update"
|
||||
echo "your clone, rebase, and re-push your branch."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git diff -U0 --no-color "${newest_common_ancestor_sha}" | .gitlab-ci/clang-format-diff.py -binary "clang-format" -p1
|
||||
exit_status=$?
|
||||
|
||||
# The style check is not infallible. The clang-format configuration cannot
|
||||
# perfectly describe GGNOME Settings’ coding style: in particular, it cannot align
|
||||
# function arguments. The documented coding style for GNOME Settings takes priority over
|
||||
# clang-format suggestions. Hopefully we can eventually improve clang-format to
|
||||
# be configurable enough for our coding style. That’s why this CI check is OK
|
||||
# to fail: the idea is that people can look through the output and ignore it if
|
||||
# it’s wrong. (That situation can also happen if someone touches pre-existing
|
||||
# badly formatted code and it doesn’t make sense to tidy up the wider coding
|
||||
# style with the changes they’re making.)
|
||||
echo ""
|
||||
echo "Note that clang-format output is advisory and cannot always match the"
|
||||
echo "GNOME Settings coding style, documented at:"
|
||||
echo " https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/CODING_STYLE.md"
|
||||
echo "Warnings from this tool can be ignored in favour of the documented "
|
||||
echo "coding style, or in favour of matching the style of existing"
|
||||
echo "surrounding code."
|
||||
|
||||
exit ${exit_status}
|
||||
@@ -1,31 +1,7 @@
|
||||
<!--
|
||||
|
||||
Not following the communication guidelines [1] will mean your issue or comment
|
||||
will be removed. Read it carefully before submitting this issue.
|
||||
|
||||
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/CODE_OF_CONDUCT.md#communication-guidelines
|
||||
|
||||
Detailed description of the issue. Put as much information as you can, potentially
|
||||
with images showing the issue.
|
||||
-->
|
||||
|
||||
## Relevant information
|
||||
|
||||
* GNOME Settings version
|
||||
<!-- Find with the command "gnome-control-center --version" -->
|
||||
|
||||
* Operating system (distribution)
|
||||
<!-- Find with the command "cat /etc/os-release" -->
|
||||
|
||||
* Error message
|
||||
<!-- Reproduce the issue while running with the command "G_MESSAGES_DEBUG=all gnome-control-center" -->
|
||||
|
||||
* Backtrace (if you are experiencing a crash)
|
||||
<!-- Check for instructions at https://wiki.gnome.org/GettingInTouch/Bugzilla/GettingTraces -->
|
||||
|
||||
* Screenshots
|
||||
|
||||
## Steps to reproduce:
|
||||
Steps to reproduce:
|
||||
|
||||
1. Open GNOME Settings
|
||||
2. Change X to something else
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
<!--
|
||||
|
||||
Not following the communication guidelines [1] will mean your issue or comment
|
||||
will be removed. Read it carefully before submitting this issue.
|
||||
|
||||
|
||||
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/CODE_OF_CONDUCT.md#communication-guidelines
|
||||
|
||||
-->
|
||||
|
||||
Detailed description of the feature. Put as much information as you can.
|
||||
|
||||
Proposed Mockups:
|
||||
|
||||
62
README.md
@@ -1,27 +1,53 @@
|
||||
[](https://gitlab.gnome.org/GNOME/gnome-control-center/pipelines)
|
||||
[](https://gnome.pages.gitlab.gnome.org/gnome-control-center/)
|
||||
[](https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/COPYING)
|
||||
[](https://gitlab.gnome.org/GNOME/gnome-control-center/pipelines)
|
||||
[](https://gnome.pages.gitlab.gnome.org/gnome-control-center/)
|
||||
[](https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/COPYING)
|
||||
|
||||
GNOME Settings
|
||||
====================
|
||||
|
||||
GNOME Settings is GNOME's main interface for configuration of various aspects of your desktop.
|
||||
|
||||
If you are looking for usage tips and instructions, you can find it at the [User Documentation](https://help.gnome.org/users/gnome-help/stable/prefs.html) (translated in various languages).
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
Before reporting any bugs or opening feature requests, [read the communication guidelines](https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/CODE_OF_CONDUCT.md#communication-guidelines).
|
||||
|
||||
Report issues to the [GNOME issue tracking system](https://gitlab.gnome.org/GNOME/gnome-control-center/issues).
|
||||
|
||||
## Feature Requests
|
||||
|
||||
For feature requests or conceptual changes, please start a topic on [GNOME Discourse](https://discourse.gnome.org/tags/settings).
|
||||
GNOME Settings is GNOME's main interface for configuration of various aspects of
|
||||
your desktop.
|
||||
|
||||
## Contributing
|
||||
|
||||
See `docs/CONTRIBUTING.md` for details on the contribution process, and `docs/CODING_STYLE.md`
|
||||
See `docs/CONTRIBUTING.md` for details on the contribution process, and `docs/HACKING.md`
|
||||
for the coding style guidelines.
|
||||
|
||||
Visit the [Settings development wiki](https://gitlab.gnome.org/GNOME/gnome-control-center/-/wikis/home) for more information.
|
||||
## Testing Unstable Settings
|
||||
|
||||
It is quite easy to test and give feedback about the development version of GNOME
|
||||
Settings. Just access https://gitlab.gnome.org/GNOME/gnome-control-center/environments,
|
||||
get the latest version, download it, double-click the file, install and run.
|
||||
|
||||
Note that GNOME Settings Flatpak will only work if you are running
|
||||
the latest GNOME version in your host system.
|
||||
|
||||
## Reporting Bugs
|
||||
|
||||
Bugs should be reported to the GNOME bug tracking system under the product
|
||||
gnome-control-center. It is available at [GitLab Issues](https://gitlab.gnome.org/GNOME/gnome-control-center/issues).
|
||||
|
||||
In the report please include the following information -
|
||||
|
||||
Operating system and version
|
||||
For Linux, version of the C library
|
||||
How to reproduce the bug if possible
|
||||
If the bug was a crash, include the exact text that was printed out
|
||||
A stacktrace where possible [see below]
|
||||
|
||||
### How to get a stack trace
|
||||
|
||||
If the crash is reproducible, it is possible to get a stack trace and
|
||||
attach it to the bug report. The following steps are used to obtain a
|
||||
stack trace -
|
||||
|
||||
Run the program in gdb [the GNU debugger] or any other debugger
|
||||
ie. gdb gnome-keyboard-properties
|
||||
Start the program
|
||||
ie. (gdb) run
|
||||
Reproduce the crash and the program will exit to the gdb prompt
|
||||
Get the back trace
|
||||
ie. (gdb) bt full
|
||||
|
||||
Once you have the backtrace, copy and paste this either into the
|
||||
'Comments' field or attach a file with it included.
|
||||
|
||||
26
build-aux/ci/Dockerfile.arm64v8.fedora.rawhide
Normal file
@@ -0,0 +1,26 @@
|
||||
FROM arm64v8/fedora:rawhide
|
||||
MAINTAINER Claudio André (c) 2018 V1.0
|
||||
|
||||
LABEL architecture="aarch64"
|
||||
LABEL version="1.0"
|
||||
LABEL description="Multiarch Docker image to run CI for GNOME Settings."
|
||||
|
||||
ADD x86_64_qemu-aarch64-static.tar.gz /usr/bin
|
||||
|
||||
RUN dnf -y --nogpgcheck upgrade && \
|
||||
dnf -y install \
|
||||
@c-development @development-tools clang \
|
||||
accountsservice-devel cheese-libs-devel chrpath clutter-gtk-devel colord-devel \
|
||||
colord-gtk-devel cups-devel desktop-file-utils docbook-style-xsl gdk-pixbuf2-devel \
|
||||
gettext git glib2-devel gnome-bluetooth-libs-devel gnome-desktop3-devel \
|
||||
gnome-online-accounts-devel gnome-settings-daemon-devel grilo-devel \
|
||||
gsettings-desktop-schemas-devel gtk3-devel ibus-devel intltool libcanberra-devel \
|
||||
libgtop2-devel libgudev-devel libnma-devel libpwquality-devel libsmbclient-devel \
|
||||
libsoup-devel libwacom-devel libX11-devel libXi-devel libxml2-devel libxslt \
|
||||
libXxf86misc-devel meson ModemManager-glib-devel NetworkManager-libnm-devel \
|
||||
polkit-devel pulseaudio-libs-devel upower-devel \
|
||||
python3-dbusmock xorg-x11-server-Xvfb mesa-dri-drivers libsecret-devel && \
|
||||
dnf -y clean all
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
24
build-aux/ci/Dockerfile.fedora.rawhide
Normal file
@@ -0,0 +1,24 @@
|
||||
FROM fedora:rawhide
|
||||
MAINTAINER Claudio André (c) 2018 V1.0
|
||||
|
||||
LABEL architecture="x86_64"
|
||||
LABEL version="1.0"
|
||||
LABEL description="Docker image to run CI for GNOME Settings."
|
||||
|
||||
RUN dnf -y --nogpgcheck upgrade && \
|
||||
dnf -y install \
|
||||
@c-development @development-tools clang \
|
||||
accountsservice-devel cheese-libs-devel chrpath clutter-gtk-devel colord-devel \
|
||||
colord-gtk-devel cups-devel desktop-file-utils docbook-style-xsl gdk-pixbuf2-devel \
|
||||
gettext git glib2-devel gnome-bluetooth-libs-devel gnome-desktop3-devel \
|
||||
gnome-online-accounts-devel gnome-settings-daemon-devel grilo-devel \
|
||||
gsettings-desktop-schemas-devel gtk3-devel ibus-devel intltool libcanberra-devel \
|
||||
libgtop2-devel libgudev-devel libnma-devel libpwquality-devel libsmbclient-devel \
|
||||
libsoup-devel libwacom-devel libX11-devel libXi-devel libxml2-devel libxslt \
|
||||
libXxf86misc-devel meson ModemManager-glib-devel NetworkManager-libnm-devel \
|
||||
polkit-devel pulseaudio-libs-devel upower-devel \
|
||||
python3-dbusmock xorg-x11-server-Xvfb mesa-dri-drivers libsecret-devel llvm && \
|
||||
dnf -y clean all
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
26
build-aux/ci/Dockerfile.ppc64le.fedora.rawhide
Normal file
@@ -0,0 +1,26 @@
|
||||
FROM ppc64le/fedora:rawhide
|
||||
MAINTAINER Claudio André (c) 2018 V1.0
|
||||
|
||||
LABEL architecture="ppc64le"
|
||||
LABEL version="1.0"
|
||||
LABEL description="Multiarch Docker image to run CI for GNOME Settings."
|
||||
|
||||
ADD x86_64_qemu-ppc64le-static.tar.gz /usr/bin
|
||||
|
||||
RUN dnf -y --nogpgcheck upgrade && \
|
||||
dnf -y install \
|
||||
@c-development @development-tools clang \
|
||||
accountsservice-devel cheese-libs-devel chrpath clutter-gtk-devel colord-devel \
|
||||
colord-gtk-devel cups-devel desktop-file-utils docbook-style-xsl gdk-pixbuf2-devel \
|
||||
gettext git glib2-devel gnome-bluetooth-libs-devel gnome-desktop3-devel \
|
||||
gnome-online-accounts-devel gnome-settings-daemon-devel grilo-devel \
|
||||
gsettings-desktop-schemas-devel gtk3-devel ibus-devel intltool libcanberra-devel \
|
||||
libgtop2-devel libgudev-devel libnma-devel libpwquality-devel libsmbclient-devel \
|
||||
libsoup-devel libwacom-devel libX11-devel libXi-devel libxml2-devel libxslt \
|
||||
libXxf86misc-devel meson ModemManager-glib-devel NetworkManager-libnm-devel \
|
||||
polkit-devel pulseaudio-libs-devel upower-devel \
|
||||
python3-dbusmock xorg-x11-server-Xvfb mesa-dri-drivers libsecret-devel && \
|
||||
dnf -y clean all
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
@@ -3,7 +3,6 @@ leak:libfontconfig.so.1
|
||||
|
||||
# Unknown and unreported bugs
|
||||
leak:__GI___vasprintf_chk
|
||||
leak:__interceptor_malloc
|
||||
leak:__alloc_dir
|
||||
leak:libglib-2.0.so.0
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
From ba5e0451b51c983e40afd123b6e0d3eddb55e610 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Sat, 24 Mar 2018 17:37:02 +0000
|
||||
Subject: linux: Include <sys/sysmacros.h> for major() macro.
|
||||
|
||||
Since glibc 2.27 this header is required.
|
||||
---
|
||||
libparted/arch/linux.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
|
||||
index 31b98ab..7e86b51 100644
|
||||
--- a/libparted/arch/linux.c
|
||||
+++ b/libparted/arch/linux.c
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <sys/utsname.h> /* for uname() */
|
||||
#include <scsi/scsi.h>
|
||||
#include <assert.h>
|
||||
+#include <sys/sysmacros.h>
|
||||
#ifdef ENABLE_DEVICE_MAPPER
|
||||
#include <libdevmapper.h>
|
||||
#endif
|
||||
@@ -1,9 +1,11 @@
|
||||
{
|
||||
"app-id" : "org.gnome.Settings",
|
||||
"runtime" : "org.gnome.Sdk",
|
||||
"runtime" : "org.gnome.Platform",
|
||||
"runtime-version" : "master",
|
||||
"sdk" : "org.gnome.Sdk",
|
||||
"command" : "gnome-control-center",
|
||||
"rename-desktop-file" : "gnome-control-center.desktop",
|
||||
"rename-icon" : "gnome-control-center",
|
||||
"tags" : [
|
||||
"devel"
|
||||
],
|
||||
@@ -12,6 +14,7 @@
|
||||
"--device=dri",
|
||||
"--env=DCONF_USER_CONFIG_DIR=.config/dconf",
|
||||
"--filesystem=host",
|
||||
"--own-name=org.gnome.ControlCenter",
|
||||
"--own-name=org.gnome.SessionManager",
|
||||
"--share=ipc",
|
||||
"--share=network",
|
||||
@@ -26,10 +29,7 @@
|
||||
"cxxflags" : "-O2 -g",
|
||||
"env" : {
|
||||
"V" : "1"
|
||||
},
|
||||
"build-args": [
|
||||
"--share=network"
|
||||
]
|
||||
}
|
||||
},
|
||||
"x-run-args" : [
|
||||
"--verbose"
|
||||
@@ -49,7 +49,6 @@
|
||||
"name" : "pwquality",
|
||||
"buildsystem" : "autotools",
|
||||
"config-opts" : [
|
||||
"--disable-python-bindings"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
@@ -59,69 +58,67 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "intltool",
|
||||
"cleanup" : [ "*" ],
|
||||
"name" : "mozjs52",
|
||||
"build-options" : {
|
||||
"arch" : {
|
||||
"i386" : {
|
||||
"config-opts" : [
|
||||
"--host=i586-unknown-linux-gnu"
|
||||
]
|
||||
},
|
||||
"arm" : {
|
||||
"config-opts" : [
|
||||
"--host=arm-unknown-linux-gnueabi"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"config-opts": [
|
||||
"--enable-posix-nspr-emulation",
|
||||
"--with-system-zlib",
|
||||
"--without-system-icu",
|
||||
"--with-intl-api",
|
||||
"--disable-jemalloc",
|
||||
"AUTOCONF=autoconf"
|
||||
],
|
||||
"builddir" : true,
|
||||
"subdir" : "js/src",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "archive",
|
||||
"url" : "https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz",
|
||||
"sha256" : "67c74d94196b153b774ab9f89b2fa6c6ba79352407037c8c14d5aeb334e959cd"
|
||||
"url" : "https://download.gnome.org/teams/releng/tarballs-needing-help/mozjs/mozjs-52.2.1gnome1.tar.gz",
|
||||
"sha256" : "31697943b1dbbb51ba9aee35b8269a353c487d7af4d336010b90054dc4f9b0af"
|
||||
}
|
||||
],
|
||||
"cleanup" : [
|
||||
"libjs_static.ajs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "polkit",
|
||||
"buildsystem" : "autotools",
|
||||
"config-opts" : [
|
||||
"--disable-polkitd",
|
||||
"--disable-man-pages",
|
||||
"--disable-examples",
|
||||
"--disable-gtk-doc",
|
||||
"--disable-libelogind",
|
||||
"--disable-libsystemd-login",
|
||||
"--with-systemdsystemunitdir=no",
|
||||
"--with-authdb=dummy",
|
||||
"--with-authfw=none"
|
||||
],
|
||||
"rm-configure" : true,
|
||||
"cleanup" : [
|
||||
"/bin/*",
|
||||
"/etc/pam.d",
|
||||
"/etc/dbus-1",
|
||||
"/share/dbus-1/system-services/*",
|
||||
"/share/polkit-1",
|
||||
"/lib/polkit-1"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "archive",
|
||||
"url" : "https://www.freedesktop.org/software/polkit/releases/polkit-0.116.tar.gz",
|
||||
"sha256" : "88170c9e711e8db305a12fdb8234fac5706c61969b94e084d0f117d8ec5d34b1"
|
||||
},
|
||||
{
|
||||
"type" : "patch",
|
||||
"path" : "polkit-build-Add-option-to-build-without-polkitd.patch"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "polkit-autogen",
|
||||
"dest-filename" : "autogen.sh"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "accountsservice",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dsystemdsystemunitdir=no",
|
||||
"-Dintrospection=false",
|
||||
"-Dvapi=false"
|
||||
"--disable-introspection",
|
||||
"--disable-libelogind"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.freedesktop.org/accountsservice/accountsservice",
|
||||
"branch" : "main"
|
||||
"url" : "git://anongit.freedesktop.org/polkit"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "accountservice",
|
||||
"buildsystem" : "autotools",
|
||||
"config-opts" : [
|
||||
"--disable-systemd",
|
||||
"--disable-elogind"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "git://anongit.freedesktop.org/accountsservice"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -134,7 +131,7 @@
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/libusb/libusb.git"
|
||||
"url" : "git://github.com/libusb/libusb.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -149,8 +146,7 @@
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/hughsie/libgusb.git",
|
||||
"branch" : "main"
|
||||
"url" : "git://github.com/hughsie/libgusb.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -182,7 +178,20 @@
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/gentoo/eudev.git"
|
||||
"url" : "git://github.com/gentoo/eudev.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "gudev",
|
||||
"buildsystem" : "autotools",
|
||||
"config-opts" : [
|
||||
"--disable-umockdev"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/libgudev.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -194,58 +203,47 @@
|
||||
"-Dbash_completion=false",
|
||||
"-Dman=false",
|
||||
"-Dudev_rules=false",
|
||||
"-Dsystemd=false",
|
||||
"-Dvapi=false",
|
||||
"-Ddocs=false",
|
||||
"-Dtests=false",
|
||||
"-Dinstalled_tests=false"
|
||||
"-Dsystemd=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch" : "main",
|
||||
"url" : "https://github.com/hughsie/colord.git"
|
||||
"url" : "git://github.com/hughsie/colord.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "colord-gtk",
|
||||
"buildsystem" : "meson",
|
||||
"buildsystem" : "autotools",
|
||||
"config-opts" : [
|
||||
"-Dman=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch" : "main",
|
||||
"url" : "https://github.com/hughsie/colord-gtk.git"
|
||||
"url" : "git://github.com/hughsie/colord-gtk.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "rest",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dgtk_doc=false"
|
||||
],
|
||||
"buildsystem" : "autotools",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch" : "master",
|
||||
"branch" : "librest-0-7",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/librest.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "gnome-online-accounts",
|
||||
"buildsystem" : "meson",
|
||||
"buildsystem" : "autotools",
|
||||
"build-options" : {
|
||||
"cflags" : "-Wno-error"
|
||||
},
|
||||
"config-opts" : [
|
||||
"-Dgtk_doc=false",
|
||||
"-Dintrospection=false",
|
||||
"-Dvapi=false"
|
||||
"--disable-telepathy",
|
||||
"--disable-documentation"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
@@ -267,12 +265,6 @@
|
||||
{
|
||||
"name" : "geocode-glib",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Denable-installed-tests=false",
|
||||
"-Denable-introspection=false",
|
||||
"-Denable-gtk-doc=false",
|
||||
"-Dsoup2=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
@@ -283,46 +275,26 @@
|
||||
{
|
||||
"name" : "libgweather",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Denable_vala=false",
|
||||
"-Dgtk_doc=false",
|
||||
"-Dintrospection=false",
|
||||
"-Dtests=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/libgweather.git",
|
||||
"branch" : "main"
|
||||
"url" : "https://gitlab.gnome.org/GNOME/libgweather.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "upower",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dsystemdsystemunitdir=/app/lib/systemd/system",
|
||||
"-Dudevrulesdir=/app/lib/udev",
|
||||
"-Dudevhwdbdir=/app/lib/udev",
|
||||
"-Dgtk-doc=false",
|
||||
"-Dman=false",
|
||||
"-Dintrospection=disabled"
|
||||
],
|
||||
"buildsystem" : "autotools",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.freedesktop.org/upower/upower.git",
|
||||
"tag" : "v1.90.2"
|
||||
"url" : "git://anongit.freedesktop.org/upower"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "libwacom",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Ddocumentation=disabled",
|
||||
"-Dtests=disabled"
|
||||
],
|
||||
"buildsystem" : "autotools",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
@@ -336,7 +308,7 @@
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "archive",
|
||||
"url" : "http://libndp.org/files/libndp-1.6.tar.gz",
|
||||
"url" : " http://libndp.org/files/libndp-1.6.tar.gz",
|
||||
"sha256" : "0c7dfa84e013bd5e569ef2c6292a6f72cfaf14f4ff77a77425e52edc33ffac0e"
|
||||
}
|
||||
]
|
||||
@@ -351,10 +323,14 @@
|
||||
"config-opts" : [
|
||||
"-Dlibaudit=no",
|
||||
"-Ddbus_conf_dir=/app/etc/dbus-1/system.d",
|
||||
"-Ddbus_ifaces_dir=/app/share/dbus-1/interfaces",
|
||||
"-Ddbus_sys_dir=/app/share/dbus-1/system.d",
|
||||
"-Ddnsmasq=/usr/bin/true",
|
||||
"-Ddocs=false",
|
||||
"-Dintrospection=false",
|
||||
"-Diptables=/usr/bin/true",
|
||||
"-Djson_validation=false",
|
||||
"-Dlibnm_glib=false",
|
||||
"-Dlibpsl=false",
|
||||
"-Dmodem_manager=false",
|
||||
"-Dnmtui=false",
|
||||
@@ -363,8 +339,7 @@
|
||||
"-Dqt=false",
|
||||
"-Dselinux=false",
|
||||
"-Dsession_tracking=no",
|
||||
"-Dsystemdsystemunitdir=/app/lib/systemd/system",
|
||||
"-Dudev_dir=/app/lib/udev",
|
||||
"-Dsystemdsystemunitdir='no'",
|
||||
"-Dsystemd_journal=false",
|
||||
"-Dtests=no",
|
||||
"-Dvapi=false"
|
||||
@@ -372,124 +347,56 @@
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch": "main",
|
||||
"tag": "1.14.0",
|
||||
"commit" : "2979c891c4af7584780924e92b6d448b7d6cd328",
|
||||
"url" : "https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "mobile-broadband-provider-info",
|
||||
"buildsystem" : "autotools",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch": "main",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/mobile-broadband-provider-info.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "libnma",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dlibnma_gtk4=true",
|
||||
"-Dgtk_doc=false",
|
||||
"-Dintrospection=false",
|
||||
"-Dvapi=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/libnma.git",
|
||||
"branch" : "main"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "network-manager-applet",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dappindicator=no",
|
||||
"-Dwwan=false",
|
||||
"-Dgtk_doc=false",
|
||||
"-Dintrospection=false",
|
||||
"-Dlibnm_gtk=false",
|
||||
"-Dselinux=false",
|
||||
"-Dteam=false"
|
||||
"-Dteam=false",
|
||||
"-Dwwan=false",
|
||||
"-Dmobile_broadband_provider_info=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/network-manager-applet.git",
|
||||
"branch" : "main"
|
||||
"url" : "https://gitlab.gnome.org/GNOME/network-manager-applet.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "ModemManager",
|
||||
"buildsystem" : "meson",
|
||||
"buildsystem" : "autotools",
|
||||
"config-opts" : [
|
||||
"-Dintrospection=false",
|
||||
"-Dbash_completion=false",
|
||||
"-Dudevdir=/app/lib/udev",
|
||||
"-Dsystemdsystemunitdir=/app/lib/systemd/system",
|
||||
"-Ddbus_policy_dir=/app/etc/dbus-1/system.d",
|
||||
"-Dsystemd_journal=false",
|
||||
"-Dtests=false",
|
||||
"-Dman=false",
|
||||
"-Dfuzzer=false",
|
||||
"-Dexamples=false",
|
||||
"-Dmbim=false",
|
||||
"-Dplugin_dell=disabled",
|
||||
"-Dplugin_foxconn=disabled",
|
||||
"-Dplugin_fibocom=disabled",
|
||||
"-Dqmi=false",
|
||||
"-Dqrtr=false"
|
||||
"--disable-introspection",
|
||||
"--disable-vala",
|
||||
"--with-udev-base-dir=/app/lib",
|
||||
"--without-mbim",
|
||||
"--without-qmi"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git",
|
||||
"branch" : "main"
|
||||
"url" : "git://anongit.freedesktop.org/ModemManager/ModemManager"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "gnome-settings-daemon",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dudev_dir=/app/lib/udev",
|
||||
"-Dsystemd=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/gnome-settings-daemon.git"
|
||||
}
|
||||
],
|
||||
"modules": [
|
||||
{
|
||||
"name": "libcanberra",
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "http://0pointer.de/lennart/projects/libcanberra/libcanberra-0.30.tar.xz",
|
||||
"sha256": "c2b671e67e0c288a69fc33dc1b6f1b534d07882c2aceed37004bf48c601afa72"
|
||||
}
|
||||
],
|
||||
"config-opts": [
|
||||
"--disable-alsa",
|
||||
"--disable-null",
|
||||
"--disable-oss"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "gsound",
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/gsound.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -505,6 +412,23 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "grilo",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Denable-grl-pls=false",
|
||||
"-Denable-gtk-doc=false",
|
||||
"-Denable-introspection=false",
|
||||
"-Denable-test-ui=false",
|
||||
"-Denable-vala=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/grilo.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "openldap",
|
||||
"buildsystem" : "autotools",
|
||||
@@ -513,9 +437,9 @@
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://www.openldap.org/software/download/OpenLDAP/openldap-release/openldap-2.6.1.tgz",
|
||||
"sha256": "9d576ea6962d7db8a2e2808574e8c257c15aef55f403a1fb5a0faf35de70e6f3"
|
||||
"type" : "archive",
|
||||
"url" : "https://www.openldap.org/software/download/OpenLDAP/openldap-release/openldap-2.4.46.tgz",
|
||||
"sha256" : "9a90dcb86b99ae790ccab93b7585a31fbcbeec8c94bf0f7ab0ca0a87ea0c4b2d"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -525,8 +449,8 @@
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "archive",
|
||||
"url" : "http://downloads.sourceforge.net/sourceforge/libtirpc/libtirpc-1.2.6.tar.bz2",
|
||||
"sha256" : "4278e9a5181d5af9cd7885322fdecebc444f9a3da87c526e7d47f7a12a37d1cc"
|
||||
"url" : "http://downloads.sourceforge.net/sourceforge/libtirpc/libtirpc-1.0.3.tar.bz2",
|
||||
"sha256" : "86c3a78fc1bddefa96111dd233124c703b22a78884203c55c3e06b3be6a0fd5e"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -541,61 +465,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "lmdb",
|
||||
"buildsystem" : "simple",
|
||||
"build-commands" : [
|
||||
"cd libraries/liblmdb/ && make prefix=/app install"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "archive",
|
||||
"url" : "https://github.com/LMDB/lmdb/archive/LMDB_0.9.23.tar.gz",
|
||||
"sha256" : "abf42e91f046787ed642d9eb21812a5c473f3ba5854124484d16eadbe0aa9c81"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "yapp-driver",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"perl Makefile.PL",
|
||||
"make install -j1"
|
||||
],
|
||||
"build-options" : {
|
||||
"env" : {
|
||||
"PERL5LIB": "/app/lib/perl5/",
|
||||
"PERL_MM_OPT": "INSTALL_BASE=/app"
|
||||
}
|
||||
},
|
||||
"cleanup": [ "*" ],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://cpan.metacpan.org/authors/id/W/WB/WBRASWELL/Parse-Yapp-1.21.tar.gz",
|
||||
"sha256": "3810e998308fba2e0f4f26043035032b027ce51ce5c8a52a8b8e340ca65f13e5"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "samba",
|
||||
"buildsystem" : "autotools",
|
||||
"config-opts" : [
|
||||
"--without-json",
|
||||
"--without-ad-dc",
|
||||
"--without-pam"
|
||||
],
|
||||
"build-options" : {
|
||||
"env" : {
|
||||
"PERL5LIB": "/app/lib/perl5/",
|
||||
"PERL_MM_OPT": "INSTALL_BASE=/app"
|
||||
}
|
||||
},
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "archive",
|
||||
"url" : "https://download.samba.org/pub/samba/stable/samba-4.14.5.tar.gz",
|
||||
"sha256" : "bb6ef5d2f16b85288d823578abc453d9a80514c42e5a2ea2c4e3c60dc42335c3"
|
||||
"url" : "https://download.samba.org/pub/samba/stable/samba-4.8.1.tar.gz",
|
||||
"sha256" : "8ef7367507f16b7a5e2f6aed5bcdbd1143feca79aa2a07c9b21292b17d7f789d"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -613,216 +490,15 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "udisks",
|
||||
"name" : "cheese",
|
||||
"buildsystem" : "autotools",
|
||||
"config-opts" : [
|
||||
"--disable-introspection",
|
||||
"--disable-lvm2",
|
||||
"--enable-daemon=no",
|
||||
"--with-systemdsystemunitdir=/app/lib/systemd/system",
|
||||
"--with-tmpfilesdir=/app/lib/tmpfiles.d"
|
||||
"--disable-introspection"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/storaged-project/udisks.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python3-jinja2",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"jinja2\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/1d/97/2288fe498044284f39ab8950703e88abbac2abbdf65524d576157af70556/MarkupSafe-2.1.1.tar.gz",
|
||||
"sha256": "7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/bc/c3/f068337a370801f372f2f8f6bad74a5c140f6fda3d9de154052708dd3c65/Jinja2-3.1.2-py3-none-any.whl",
|
||||
"sha256": "6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python3-attrs",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"attrs\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/f0/eb/fcb708c7bf5056045e9e98f62b93bd7467eb718b0202e7698eb11d66416c/attrs-23.1.0-py3-none-any.whl",
|
||||
"sha256": "1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "libei",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dliboeffis=disabled",
|
||||
"-Dtests=disabled"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch" : "main",
|
||||
"url" : "https://gitlab.freedesktop.org/libinput/libei.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "mutter",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dgles2=false",
|
||||
"-Dglx=false",
|
||||
"-Dxwayland=false",
|
||||
"-Dwayland=false",
|
||||
"-Dsystemd=false",
|
||||
"-Dnative_backend=false",
|
||||
"-Dremote_desktop=false",
|
||||
"-Degl_device=false",
|
||||
"-Dudev=false",
|
||||
"-Dstartup_notification=false",
|
||||
"-Dsm=false",
|
||||
"-Dintrospection=true",
|
||||
"-Ddocs=false",
|
||||
"-Dtests=false",
|
||||
"-Dnative_tests=false",
|
||||
"-Dprofiler=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch" : "main",
|
||||
"url" : "https://gitlab.gnome.org/gnome/mutter.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "libical",
|
||||
"buildsystem" : "cmake",
|
||||
"config-opts" : [
|
||||
"-DICAL_BUILD_DOCS=false",
|
||||
"-DICAL_GLIB=true",
|
||||
"-DLIBICAL_BUILD_TESTING=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/libical/libical.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "evolution-data-server",
|
||||
"buildsystem" : "cmake",
|
||||
"config-opts" : [
|
||||
"-DWITH_LIBDB=OFF"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/evolution-data-server.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "libstartup-notification",
|
||||
"buildsystem" : "autotools",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.freedesktop.org/xdg/startup-notification.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "sassc",
|
||||
"buildsystem" : "simple",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/sass/libsass"
|
||||
},
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/sass/sassc.git",
|
||||
"dest" : "sassc"
|
||||
}
|
||||
],
|
||||
"build-commands" : [
|
||||
"make -C sassc",
|
||||
"PREFIX=/app make -C sassc install"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "cogl",
|
||||
"buildsystem" : "autotools",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"tag" : "cogl-1.22",
|
||||
"url" : "https://gitlab.gnome.org/Archive/cogl.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "clutter",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dbackends='system'",
|
||||
"-Ddrivers='all'",
|
||||
"-Dbuild_tests=false",
|
||||
"-Dbuild_examples=false",
|
||||
"-Ddocumentation=false",
|
||||
"-Dintrospection=true",
|
||||
"-Dpixbuf_tests=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/clutter.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "gnome-shell",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dextensions_tool=false",
|
||||
"-Dextensions_app=false",
|
||||
"-Dgtk_doc=false",
|
||||
"-Dman=false",
|
||||
"-Dtests=false",
|
||||
"-Dnetworkmanager=false",
|
||||
"-Dcamera_monitor=false",
|
||||
"-Dsystemd=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch" : "main",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/gnome-shell.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "gnome-backgrounds",
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch": "main",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/gnome-backgrounds.git"
|
||||
"url" : "https://gitlab.gnome.org/GNOME/cheese.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -831,14 +507,12 @@
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "dir",
|
||||
"path" : "../../"
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/gnome-control-center.git"
|
||||
}
|
||||
],
|
||||
"config-opts" : [
|
||||
"-Dsnap=false",
|
||||
"-Dtests=false",
|
||||
"-Dprofile=development"
|
||||
"-Dtracing=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
gtkdocize --flavour no-tmpl
|
||||
autoreconf -if
|
||||
@@ -1,132 +0,0 @@
|
||||
From 1073a44277316348d40d86ecec908f1d4812f360 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Mon, 27 May 2019 11:49:09 -0700
|
||||
Subject: [PATCH] flatpak: make polkit suitable for use within flatpak
|
||||
|
||||
This is based on patches from Patrick Griffis with additional fixes
|
||||
to allow us to disable use of PAM within Flaptak.
|
||||
---
|
||||
configure.ac | 20 ++++++++++++++++----
|
||||
src/Makefile.am | 6 +++++-
|
||||
src/polkitagent/Makefile.am | 5 +++++
|
||||
test/Makefile.am | 6 +++++-
|
||||
4 files changed, 31 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 5cedb4e..729d78d 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -79,11 +79,13 @@ PKG_CHECK_MODULES(GLIB, [gmodule-2.0 gio-unix-2.0 >= 2.30.0])
|
||||
AC_SUBST(GLIB_CFLAGS)
|
||||
AC_SUBST(GLIB_LIBS)
|
||||
|
||||
-PKG_CHECK_MODULES(LIBJS, [mozjs-60])
|
||||
+AS_IF([test x${enable_polkitd} = yes], [
|
||||
+ PKG_CHECK_MODULES(LIBJS, [mozjs-60])
|
||||
|
||||
-AC_SUBST(LIBJS_CFLAGS)
|
||||
-AC_SUBST(LIBJS_CXXFLAGS)
|
||||
-AC_SUBST(LIBJS_LIBS)
|
||||
+ AC_SUBST(LIBJS_CFLAGS)
|
||||
+ AC_SUBST(LIBJS_CXXFLAGS)
|
||||
+ AC_SUBST(LIBJS_LIBS)
|
||||
+])
|
||||
|
||||
EXPAT_LIB=""
|
||||
AC_ARG_WITH(expat, [ --with-expat=<dir> Use expat from here],
|
||||
@@ -236,6 +238,15 @@ if test "x$with_systemdsystemunitdir" != "xno"; then
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$systemdsystemunitdir"])
|
||||
|
||||
+dnl ---------------------------------------------------------------------------
|
||||
+dnl - Disable polkitd when using library alone
|
||||
+dnl ---------------------------------------------------------------------------
|
||||
+
|
||||
+AC_ARG_ENABLE([polkitd],
|
||||
+ [AS_HELP_STRING([--disable-polkitd], [Do not build polkitd])],
|
||||
+ [enable_polkitd=$enableval], [enable_polkitd=yes])
|
||||
+AM_CONDITIONAL(BUILD_POLKITD, [test x${enable_polkitd} = yes])
|
||||
+
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl - User for running polkitd
|
||||
dnl ---------------------------------------------------------------------------
|
||||
@@ -579,6 +590,7 @@ echo "
|
||||
Session tracking: ${SESSION_TRACKING}
|
||||
PAM support: ${have_pam}
|
||||
systemdsystemunitdir: ${systemdsystemunitdir}
|
||||
+ polkitd: ${enable_polkitd}
|
||||
polkitd user: ${POLKITD_USER}"
|
||||
|
||||
if test "$have_pam" = yes ; then
|
||||
diff --git a/src/Makefile.am b/src/Makefile.am
|
||||
index 09fc7b3..c6fe91b 100644
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -1,5 +1,9 @@
|
||||
|
||||
-SUBDIRS = polkit polkitbackend polkitagent programs
|
||||
+SUBDIRS = polkit polkitagent programs
|
||||
+
|
||||
+if BUILD_POLKITD
|
||||
+SUBDIRS += polkitbackend
|
||||
+endif
|
||||
|
||||
if BUILD_EXAMPLES
|
||||
SUBDIRS += examples
|
||||
diff --git a/src/polkitagent/Makefile.am b/src/polkitagent/Makefile.am
|
||||
index 49720db..633f9d4 100644
|
||||
--- a/src/polkitagent/Makefile.am
|
||||
+++ b/src/polkitagent/Makefile.am
|
||||
@@ -79,6 +79,7 @@ libpolkit_agent_1_la_LIBADD = \
|
||||
|
||||
libpolkit_agent_1_la_LDFLAGS = -export-symbols-regex '(^polkit_.*)'
|
||||
|
||||
+if !POLKIT_AUTHFW_NONE
|
||||
libprivdir = $(prefix)/lib/polkit-1
|
||||
libpriv_PROGRAMS = polkit-agent-helper-1
|
||||
|
||||
@@ -113,6 +114,8 @@ polkit_agent_helper_1_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
+endif # !POLKIT_AUTHFW_NONE
|
||||
+
|
||||
if HAVE_INTROSPECTION
|
||||
|
||||
girdir = $(INTROSPECTION_GIRDIR)
|
||||
@@ -142,6 +145,7 @@ include $(INTROSPECTION_MAKEFILE)
|
||||
|
||||
endif # HAVE_INTROSPECTION
|
||||
|
||||
+if !POLKIT_AUTHFW_NONE
|
||||
# polkit-agent-helper-1 need to be setuid root because it's used to
|
||||
# authenticate not only the invoking user, but possibly also root
|
||||
# and/or other users.
|
||||
@@ -149,6 +153,7 @@ endif # HAVE_INTROSPECTION
|
||||
install-data-hook:
|
||||
-chown root $(DESTDIR)$(libprivdir)/polkit-agent-helper-1
|
||||
-chmod 4755 $(DESTDIR)$(libprivdir)/polkit-agent-helper-1
|
||||
+endif # !POLKIT_AUTHFW_NONE
|
||||
|
||||
EXTRA_DIST = polkitagentmarshal.list polkitagentenumtypes.h.template polkitagentenumtypes.c.template
|
||||
CLEANFILES = $(gir_DATA) $(typelibs_DATA)
|
||||
diff --git a/test/Makefile.am b/test/Makefile.am
|
||||
index 59d0680..d43b0fe 100644
|
||||
--- a/test/Makefile.am
|
||||
+++ b/test/Makefile.am
|
||||
@@ -1,7 +1,11 @@
|
||||
|
||||
-SUBDIRS = mocklibc . polkit polkitbackend
|
||||
+SUBDIRS = mocklibc . polkit
|
||||
AM_CFLAGS = $(GLIB_CFLAGS)
|
||||
|
||||
+if BUILD_POLKITD
|
||||
+SUBDIRS += polkitbackend
|
||||
+endif
|
||||
+
|
||||
noinst_LTLIBRARIES = libpolkit-test-helper.la
|
||||
libpolkit_test_helper_la_SOURCES = polkittesthelper.c polkittesthelper.h
|
||||
libpolkit_test_helper_la_LIBADD = $(GLIB_LIBS)
|
||||
--
|
||||
2.21.0
|
||||
|
||||
5
build-aux/meson.build
Normal file
@@ -0,0 +1,5 @@
|
||||
update_from_gsd = find_program('meson/update-from-gsd.sh')
|
||||
update_from_gsd_in = files('meson/update-from-gsd.in')
|
||||
update_from_nma_in = files('meson/update-from-nma.in')
|
||||
|
||||
meson.add_install_script('meson/meson_post_install.py', control_center_datadir)
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
def usage():
|
||||
print('Usage:')
|
||||
print('find_xdg_file.py FILENAME')
|
||||
print('')
|
||||
print('Looks for FILENAME in the XDG data directories and returns if path if found')
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
filename = sys.argv[1]
|
||||
|
||||
data_home = os.getenv('XDG_DATA_HOME')
|
||||
if not data_home or data_home == '':
|
||||
data_home = os.path.join(os.path.expanduser("~"), "local", "share")
|
||||
|
||||
data_dirs_str = os.getenv('XDG_DATA_DIRS')
|
||||
if not data_dirs_str or data_dirs_str == '':
|
||||
data_dirs_str = '/usr/local/share/:/usr/share/'
|
||||
|
||||
dirs = []
|
||||
dirs += [ data_home ]
|
||||
for _dir in data_dirs_str.split(':'):
|
||||
dirs += [ _dir ]
|
||||
|
||||
for _dir in dirs:
|
||||
full_path = os.path.join(_dir, filename)
|
||||
if os.path.exists(full_path):
|
||||
print(full_path)
|
||||
sys.exit(0)
|
||||
|
||||
print(f"'{filename}' not found in XDG data directories")
|
||||
sys.exit(1)
|
||||
15
build-aux/meson/meson_post_install.py
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
gsettingsschemadir = os.path.join(sys.argv[1], 'glib-2.0', 'schemas')
|
||||
icondir = os.path.join(sys.argv[1], 'icons', 'hicolor')
|
||||
|
||||
if not os.environ.get('DESTDIR'):
|
||||
print('Compiling gsettings schemas...')
|
||||
subprocess.call(['glib-compile-schemas', gsettingsschemadir])
|
||||
|
||||
print('Update icon cache...')
|
||||
subprocess.call(['gtk-update-icon-cache', '-f', '-t', icondir])
|
||||
10
build-aux/meson/update-from-gsd.in
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd @working_dir@
|
||||
|
||||
export FILES="@source_files@"
|
||||
export DIR="@input_dir@"
|
||||
|
||||
@program@ &&
|
||||
git add @source_files@ &&
|
||||
git commit -m "@source_message@"
|
||||
26
build-aux/meson/update-from-gsd.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
function die() {
|
||||
echo $*
|
||||
exit 1
|
||||
}
|
||||
|
||||
if test -z "$DIR"; then
|
||||
echo "Must set DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$FILES"; then
|
||||
echo "Must set FILES"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for FILE in $FILES; do
|
||||
if cmp -s $DIR/$FILE $FILE; then
|
||||
echo "File $FILE is unchanged"
|
||||
else
|
||||
cp $DIR/$FILE $FILE || die "Could not move $DIR/$FILE to $FILE"
|
||||
echo "Updated $FILE"
|
||||
git add $FILE
|
||||
fi
|
||||
done
|
||||
19
build-aux/meson/update-from-nma.in
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd @working_dir@
|
||||
|
||||
export FILES="@source_files@"
|
||||
export DIR="@input_dir@"
|
||||
|
||||
@program@ &&
|
||||
patch -p4 < @source_patch@ &&
|
||||
git add @source_files@ &&
|
||||
git commit -m "@source_message@"
|
||||
|
||||
export FILES="@resource_data@"
|
||||
export DIR="@input_dir@"
|
||||
|
||||
@program@ &&
|
||||
patch -p4 < @resource_patch@ &&
|
||||
git add @resource_data@ &&
|
||||
git commit -m "@resource_message@"
|
||||
2854
data/icons/gnome-control-center-src.svg
Normal file
|
After Width: | Height: | Size: 533 KiB |
BIN
data/icons/hicolor/16x16/apps/gnome-control-center.png
Normal file
|
After Width: | Height: | Size: 819 B |
BIN
data/icons/hicolor/24x24/apps/gnome-control-center.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
data/icons/hicolor/32x32/apps/gnome-control-center.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
data/icons/hicolor/48x48/apps/gnome-control-center.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
data/icons/hicolor/512x512/apps/gnome-control-center.png
Normal file
|
After Width: | Height: | Size: 109 KiB |
@@ -0,0 +1,32 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg xmlns:cc='http://creativecommons.org/ns#' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' xmlns:svg='http://www.w3.org/2000/svg' id='svg7384' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' sodipodi:docname='preferences-system-symbolic.svg' version='1.1' inkscape:version='0.48.1 r9760' height='16.000008' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns='http://www.w3.org/2000/svg' width='16'>
|
||||
<metadata id='metadata90'>
|
||||
<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>Gnome Symbolic Icon Theme</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview inkscape:cy='7.8662795' pagecolor='#555753' borderopacity='1' showborder='false' inkscape:bbox-paths='false' guidetolerance='10' inkscape:object-paths='true' inkscape:window-width='1600' showguides='true' inkscape:object-nodes='true' inkscape:snap-bbox='true' inkscape:pageshadow='2' inkscape:guide-bbox='true' inkscape:snap-nodes='true' bordercolor='#666666' objecttolerance='10' id='namedview88' showgrid='false' inkscape:window-maximized='1' inkscape:window-x='0' inkscape:snap-global='true' inkscape:window-y='0' gridtolerance='10' inkscape:window-height='1168' inkscape:snap-others='false' inkscape:snap-to-guides='true' inkscape:current-layer='g4953' inkscape:snap-bbox-midpoints='false' inkscape:zoom='1' inkscape:cx='13.631831' inkscape:snap-grids='true' inkscape:pageopacity='1'>
|
||||
<inkscape:grid spacingx='1px' spacingy='1px' id='grid4866' empspacing='2' enabled='true' type='xygrid' snapvisiblegridlinesonly='true' visible='true'/>
|
||||
</sodipodi:namedview>
|
||||
<title id='title9167'>Gnome Symbolic Icon Theme</title>
|
||||
<defs id='defs7386'/>
|
||||
<g inkscape:label='status' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer9' style='display:inline'/>
|
||||
<g inkscape:label='devices' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer10'/>
|
||||
<g inkscape:label='apps' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer11'/>
|
||||
<g inkscape:label='places' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer13'/>
|
||||
<g inkscape:label='mimetypes' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer14'/>
|
||||
<g inkscape:label='emblems' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer15' style='display:inline'/>
|
||||
<g inkscape:label='emotes' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='g71291' style='display:inline'/>
|
||||
<g inkscape:label='categories' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='g4953' style='display:inline'>
|
||||
<path inkscape:connector-curvature='0' d='m 445.54914,462.09056 c -0.39933,0 -0.78638,0.0916 -1.14329,0.21572 l 1.88488,1.87971 c 0.38735,0.38627 0.38735,1.00037 0,1.38667 l -0.71069,0.70874 c -0.38735,0.38628 -1.00314,0.38628 -1.39049,0 l -1.88488,-1.87971 c -0.12444,0.35591 -0.2163,0.74191 -0.2163,1.14015 0,1.90608 1.54944,3.45126 3.46077,3.45126 0.39933,0 0.78638,-0.0916 1.14329,-0.2157 l 1.17419,1.17097 a 2.4722239,2.4654407 0 0 1 0.0618,0 l 2.07028,-2.0646 -1.20509,-1.20178 c 0.12444,-0.35592 0.2163,-0.74191 0.2163,-1.14015 0,-1.90609 -1.54944,-3.45128 -3.46077,-3.45128 z m 6.55074,7.88863 -2.07029,2.06459 a 2.4722239,2.4654407 0 0 1 0.0309,0.0924 l 1.14329,1.14015 c -0.12444,0.35596 -0.2163,0.74196 -0.2163,1.14019 0,1.90609 1.54944,3.45129 3.46077,3.45129 0.43346,0 0.8536,-0.10141 1.23599,-0.24653 l -2.00848,-2.00297 c -0.38735,-0.38629 -0.38735,-1.03119 0,-1.41749 l 0.67979,-0.67792 c 0.19367,-0.19315 0.45794,-0.30816 0.71069,-0.30816 0.25276,0 0.51702,0.11501 0.7107,0.30816 l 1.94668,1.94133 c 0.10485,-0.32958 0.1854,-0.68351 0.1854,-1.04771 0,-1.90608 -1.54944,-3.45126 -3.46077,-3.45126 -0.39933,0 -0.78639,0.0916 -1.14329,0.2157 l -1.20509,-1.20179 z' id='path3908' style='font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans'/>
|
||||
<path inkscape:connector-curvature='0' d='m 455.85825,462 -1.54246,1.43753 c -0.45151,0.42079 -0.5292,1.14883 -0.2663,1.70647 l -5.88822,5.99575 a 1.4916729,1.4875773 0 0 0 -0.0311,2.5e-4 1.4916729,1.4875773 0 0 0 -0.84016,-0.1484 1.4916729,1.4875773 0 0 0 -0.86663,0.44059 l -3.9462,3.99734 a 1.4941171,1.4900149 0 1 0 2.12943,2.09068 l 3.9462,-3.99734 a 1.4916729,1.4875773 0 0 0 0.29713,-1.73771 l 5.88846,-5.96477 c 0.55782,0.24837 1.27325,0.14697 1.70681,-0.2922 L 457.86242,463.9677 455.85824,462 z' id='path3910' style='font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans'/>
|
||||
|
||||
</g>
|
||||
<g inkscape:label='actions' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer12' style='display:inline'/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
@@ -1,109 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="64" x2="64" y1="262.5" y2="232">
|
||||
<stop offset="0" stop-color="#9a9996"/>
|
||||
<stop offset="1" stop-color="#77767b"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="b" cx="-243.066583" cy="-74.599978" gradientUnits="userSpaceOnUse" r="28.266656">
|
||||
<stop offset="0" stop-color="#d5d3cf"/>
|
||||
<stop offset="1" stop-color="#949390"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="c" gradientUnits="userSpaceOnUse" x1="203.999985" x2="267.999985" y1="-64" y2="-64">
|
||||
<stop offset="0" stop-color="#d5d3cf"/>
|
||||
<stop offset="1" stop-color="#f6f5f4"/>
|
||||
</linearGradient>
|
||||
<clipPath id="d">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<clipPath id="e">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<filter id="f" height="100%" width="100%" x="0%" y="0%">
|
||||
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||
</filter>
|
||||
<mask id="g">
|
||||
<g clip-path="url(#e)" filter="url(#f)">
|
||||
<g clip-path="url(#d)">
|
||||
<path d="m 667 292 h -6 l -2 -16 h 10 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(1 0 0 1 -600 -170)"/>
|
||||
<path d="m 661 180 h 6 l 2 16 h -10 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(1 0 0 1 -600 -170)"/>
|
||||
<path d="m 667.000092 291.999908 h -6 l -2 -16 h 10 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0 1 -1 0 299.999908 -598.000092)"/>
|
||||
<path d="m 661.000092 179.999908 h 6 l 2 16 h -10 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0 1 -1 0 299.999908 -598.000092)"/>
|
||||
<path d="m 666.999051 291.998922 l -5.999272 -0.00042 l -2.001544 -15.998026 l 9.999915 0.000049 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -391.041005)"/>
|
||||
<path d="m 661.001107 180.000804 l 5.999273 0.000419 l 2.001544 15.998026 l -10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -391.041005)"/>
|
||||
<path d="m 667.000347 291.998468 l -5.999273 0.00042 l -2.002482 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -61.618176)"/>
|
||||
<path d="m 660.999745 180.00119 l 5.999273 -0.00042 l 2.002481 16.00035 l -10.003298 -0.001904 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -61.618176)"/>
|
||||
<path d="m 666.999018 291.999047 l -5.999273 -0.00042 l -2.001544 -15.998026 l 10.003298 -0.001904 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -470.382008)"/>
|
||||
<path d="m 661.001074 180.000929 l 5.999273 0.00042 l 2.001543 15.998025 l -10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -470.382008)"/>
|
||||
<path d="m 667.00038 291.998593 l -5.999273 0.00042 l -2.002481 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -627.040914)"/>
|
||||
<path d="m 660.999779 180.001315 l 5.999272 -0.00042 l 1.999099 15.998397 l -9.999915 0.000049 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -627.040914)"/>
|
||||
<path d="m 667 292 h -6 l -2 -16 h 10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(1 0 0 1 -600 -172)"/>
|
||||
<path d="m 661 180 h 6 l 2 16 h -10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(1 0 0 1 -600 -172)"/>
|
||||
<path d="m 667.000092 291.999908 h -6 l -2 -16 h 10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0 1 -1 0 299.999908 -600.000092)"/>
|
||||
<path d="m 661.000092 179.999908 h 6 l 2 16 h -10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0 1 -1 0 299.999908 -600.000092)"/>
|
||||
<path d="m 666.999051 291.998922 l -5.999272 -0.00042 l -2.001544 -15.998026 l 9.999915 0.000049 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -393.041005)"/>
|
||||
<path d="m 661.001107 180.000804 l 5.999273 0.000419 l 2.001544 15.998026 l -10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -393.041005)"/>
|
||||
<path d="m 667.000347 291.998468 l -5.999273 0.00042 l -2.002482 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -63.618176)"/>
|
||||
<path d="m 660.999745 180.00119 l 5.999273 -0.00042 l 2.002481 16.00035 l -10.003298 -0.001904 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -63.618176)"/>
|
||||
<path d="m 666.999018 291.999047 l -5.999273 -0.00042 l -2.001544 -15.998026 l 10.003298 -0.001904 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -472.382008)"/>
|
||||
<path d="m 661.001074 180.000929 l 5.999273 0.00042 l 2.001543 15.998025 l -10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -472.382008)"/>
|
||||
<path d="m 667.00038 291.998593 l -5.999273 0.00042 l -2.002481 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -629.040914)"/>
|
||||
<path d="m 660.999779 180.001315 l 5.999272 -0.00042 l 1.999099 15.998397 l -9.999915 0.000049 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -629.040914)"/>
|
||||
<path d="m 100 238 c 0 19.882812 -16.117188 36 -36 36 s -36 -16.117188 -36 -36 s 16.117188 -36 36 -36 s 36 16.117188 36 36 z m 0 0" fill="none" stroke="url(#a)" stroke-width="24" transform="matrix(1 0 0 1 0 -172)"/>
|
||||
<path d="m 102 236 c 0 20.988281 -17.011719 38 -38 38 s -38 -17.011719 -38 -38 s 17.011719 -38 38 -38 s 38 17.011719 38 38 z m 0 0" fill="none" stroke="#f6f5f4" stroke-width="20" transform="matrix(1 0 0 1 0 -172)"/>
|
||||
<path d="m -209.5 -64 c 0 14.636719 -11.863281 26.5 -26.5 26.5 s -26.5 -11.863281 -26.5 -26.5 s 11.863281 -26.5 26.5 -26.5 s 26.5 11.863281 26.5 26.5 z m 0 0" fill="none" stroke="url(#b)" stroke-linecap="square" stroke-linejoin="round" stroke-width="5" transform="matrix(0 -1 -1 0 0 -172)"/>
|
||||
<path d="m 268 -64 c 0 17.671875 -14.328125 32 -32 32 s -32 -14.328125 -32 -32 s 14.328125 -32 32 -32 s 32 14.328125 32 32 z m 0 0" fill="none" stroke="url(#c)" stroke-linecap="square" stroke-linejoin="round" stroke-width="8" transform="matrix(0 1 -1 0 0 -172)"/>
|
||||
</g>
|
||||
</g>
|
||||
</mask>
|
||||
<mask id="h">
|
||||
<g filter="url(#f)">
|
||||
<rect fill-opacity="0.8" height="128" width="128"/>
|
||||
</g>
|
||||
</mask>
|
||||
<linearGradient id="i" gradientTransform="matrix(0 0.37 -0.98462 0 295.38501 -30.360001)" gradientUnits="userSpaceOnUse" x1="300" x2="428" y1="235" y2="235">
|
||||
<stop offset="0" stop-color="#f9f06b"/>
|
||||
<stop offset="1" stop-color="#f5c211"/>
|
||||
</linearGradient>
|
||||
<clipPath id="j">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<clipPath id="k">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<g stroke-linecap="round" stroke-linejoin="round" stroke-width="8">
|
||||
<path d="m 67 122 h -6 l -2 -16 h 10 z m 0 0" fill="#9a9996" stroke="#9a9996"/>
|
||||
<path d="m 61 10 h 6 l 2 16 h -10 z m 0 0" fill="#9a9996" stroke="#9a9996"/>
|
||||
<path d="m 667.000092 291.999908 h -6 l -2 -16 h 10 z m 0 0" fill="#9a9996" stroke="#9a9996" transform="matrix(0 1 -1 0 299.999908 -598.000092)"/>
|
||||
<path d="m 661.000092 179.999908 h 6 l 2 16 h -10 z m 0 0" fill="#9a9996" stroke="#9a9996" transform="matrix(0 1 -1 0 299.999908 -598.000092)"/>
|
||||
<path d="m 666.999051 291.998922 l -5.999272 -0.00042 l -2.001544 -15.998026 l 9.999915 0.000049 z m 0 0" fill="#9a9996" stroke="#9a9996" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -391.041005)"/>
|
||||
<path d="m 661.001107 180.000804 l 5.999273 0.000419 l 2.001544 15.998026 l -10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -391.041005)"/>
|
||||
<path d="m 667.000347 291.998468 l -5.999273 0.00042 l -2.002482 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -61.618176)"/>
|
||||
<path d="m 660.999745 180.00119 l 5.999273 -0.00042 l 2.002481 16.00035 l -10.003298 -0.001904 z m 0 0" fill="#9a9996" stroke="#9a9996" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -61.618176)"/>
|
||||
<path d="m 666.999018 291.999047 l -5.999273 -0.00042 l -2.001544 -15.998026 l 10.003298 -0.001904 z m 0 0" fill="#9a9996" stroke="#9a9996" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -470.382008)"/>
|
||||
<path d="m 661.001074 180.000929 l 5.999273 0.00042 l 2.001543 15.998025 l -10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -470.382008)"/>
|
||||
<path d="m 667.00038 291.998593 l -5.999273 0.00042 l -2.002481 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -627.040914)"/>
|
||||
<path d="m 660.999779 180.001315 l 5.999272 -0.00042 l 1.999099 15.998397 l -9.999915 0.000049 z m 0 0" fill="#9a9996" stroke="#9a9996" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -627.040914)"/>
|
||||
<path d="m 67 120 h -6 l -2 -16 h 10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4"/>
|
||||
<path d="m 61 8 h 6 l 2 16 h -10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4"/>
|
||||
<path d="m 667.000092 291.999908 h -6 l -2 -16 h 10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" transform="matrix(0 1 -1 0 299.999908 -600.000092)"/>
|
||||
<path d="m 661.000092 179.999908 h 6 l 2 16 h -10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" transform="matrix(0 1 -1 0 299.999908 -600.000092)"/>
|
||||
<path d="m 666.999051 291.998922 l -5.999272 -0.00042 l -2.001544 -15.998026 l 9.999915 0.000049 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -393.041005)"/>
|
||||
<path d="m 661.001107 180.000804 l 5.999273 0.000419 l 2.001544 15.998026 l -10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -393.041005)"/>
|
||||
<path d="m 667.000347 291.998468 l -5.999273 0.00042 l -2.002482 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -63.618176)"/>
|
||||
<path d="m 660.999745 180.00119 l 5.999273 -0.00042 l 2.002481 16.00035 l -10.003298 -0.001904 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -63.618176)"/>
|
||||
<path d="m 666.999018 291.999047 l -5.999273 -0.00042 l -2.001544 -15.998026 l 10.003298 -0.001904 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -472.382008)"/>
|
||||
<path d="m 661.001074 180.000929 l 5.999273 0.00042 l 2.001543 15.998025 l -10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -472.382008)"/>
|
||||
<path d="m 667.00038 291.998593 l -5.999273 0.00042 l -2.002481 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -629.040914)"/>
|
||||
<path d="m 660.999779 180.001315 l 5.999272 -0.00042 l 1.999099 15.998397 l -9.999915 0.000049 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -629.040914)"/>
|
||||
</g>
|
||||
<path d="m 100 238 c 0 19.882812 -16.117188 36 -36 36 s -36 -16.117188 -36 -36 s 16.117188 -36 36 -36 s 36 16.117188 36 36 z m 0 0" fill="none" stroke="url(#a)" stroke-width="24" transform="matrix(1 0 0 1 0 -172)"/>
|
||||
<path d="m 102 64 c 0 20.988281 -17.011719 38 -38 38 s -38 -17.011719 -38 -38 s 17.011719 -38 38 -38 s 38 17.011719 38 38 z m 0 0" fill="none" stroke="#f6f5f4" stroke-width="20"/>
|
||||
<path d="m -209.5 -64 c 0 14.636719 -11.863281 26.5 -26.5 26.5 s -26.5 -11.863281 -26.5 -26.5 s 11.863281 -26.5 26.5 -26.5 s 26.5 11.863281 26.5 26.5 z m 0 0" fill="none" stroke="url(#b)" stroke-linecap="square" stroke-linejoin="round" stroke-width="5" transform="matrix(0 -1 -1 0 0 -172)"/>
|
||||
<path d="m 268 -64 c 0 17.671875 -14.328125 32 -32 32 s -32 -14.328125 -32 -32 s 14.328125 -32 32 -32 s 32 14.328125 32 32 z m 0 0" fill="none" stroke="url(#c)" stroke-linecap="square" stroke-linejoin="round" stroke-width="8" transform="matrix(0 1 -1 0 0 -172)"/>
|
||||
<g clip-path="url(#k)" mask="url(#g)">
|
||||
<g clip-path="url(#j)" mask="url(#h)">
|
||||
<path d="m 128 80.640625 v 47.359375 h -128 v -47.359375 z m 0 0" fill="url(#i)"/>
|
||||
<path d="m 13.308594 80.640625 l 47.355468 47.359375 h 21.214844 l -47.359375 -47.359375 z m 42.421875 0 l 47.363281 47.359375 h 21.214844 l -47.363282 -47.359375 z m 42.429687 0 l 29.839844 29.839844 v -21.210938 l -8.628906 -8.628906 z m -98.160156 7.90625 v 21.214844 l 18.238281 18.238281 h 21.214844 z m 0 0"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,45 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="64" x2="64" y1="262.5" y2="232">
|
||||
<stop offset="0" stop-color="#9a9996"/>
|
||||
<stop offset="1" stop-color="#77767b"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="b" cx="-243.066583" cy="-74.599978" gradientUnits="userSpaceOnUse" r="28.266656">
|
||||
<stop offset="0" stop-color="#d5d3cf"/>
|
||||
<stop offset="1" stop-color="#949390"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="c" gradientUnits="userSpaceOnUse" x1="203.999985" x2="267.999985" y1="-64" y2="-64">
|
||||
<stop offset="0" stop-color="#d5d3cf"/>
|
||||
<stop offset="1" stop-color="#f6f5f4"/>
|
||||
</linearGradient>
|
||||
<g stroke-width="8">
|
||||
<path d="m 67 122 h -6 l -2 -16 h 10 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="m 61 10 h 6 l 2 16 h -10 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="m 667.000092 291.999908 h -6 l -2 -16 h 10 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0 1 -1 0 299.999908 -598.000092)"/>
|
||||
<path d="m 661.000092 179.999908 h 6 l 2 16 h -10 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0 1 -1 0 299.999908 -598.000092)"/>
|
||||
<path d="m 666.999051 291.998922 l -5.999272 -0.00042 l -2.001544 -15.998026 l 9.999915 0.000049 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -391.041005)"/>
|
||||
<path d="m 661.001107 180.000804 l 5.999273 0.000419 l 2.001544 15.998026 l -10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -391.041005)"/>
|
||||
<path d="m 667.000347 291.998468 l -5.999273 0.00042 l -2.002482 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -61.618176)"/>
|
||||
<path d="m 660.999745 180.00119 l 5.999273 -0.00042 l 2.002481 16.00035 l -10.003298 -0.001904 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -61.618176)"/>
|
||||
<path d="m 666.999018 291.999047 l -5.999273 -0.00042 l -2.001544 -15.998026 l 10.003298 -0.001904 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -470.382008)"/>
|
||||
<path d="m 661.001074 180.000929 l 5.999273 0.00042 l 2.001543 15.998025 l -10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -470.382008)"/>
|
||||
<path d="m 667.00038 291.998593 l -5.999273 0.00042 l -2.002481 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -627.040914)"/>
|
||||
<path d="m 660.999779 180.001315 l 5.999272 -0.00042 l 1.999099 15.998397 l -9.999915 0.000049 z m 0 0" fill="#9a9996" stroke="#9a9996" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -627.040914)"/>
|
||||
<path d="m 67 120 h -6 l -2 -16 h 10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="m 61 8 h 6 l 2 16 h -10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="m 667.000092 291.999908 h -6 l -2 -16 h 10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0 1 -1 0 299.999908 -600.000092)"/>
|
||||
<path d="m 661.000092 179.999908 h 6 l 2 16 h -10 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0 1 -1 0 299.999908 -600.000092)"/>
|
||||
<path d="m 666.999051 291.998922 l -5.999272 -0.00042 l -2.001544 -15.998026 l 9.999915 0.000049 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -393.041005)"/>
|
||||
<path d="m 661.001107 180.000804 l 5.999273 0.000419 l 2.001544 15.998026 l -10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" transform="matrix(-0.5 0.866025 -0.866025 -0.5 600.381916 -393.041005)"/>
|
||||
<path d="m 667.000347 291.998468 l -5.999273 0.00042 l -2.002482 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -63.618176)"/>
|
||||
<path d="m 660.999745 180.00119 l 5.999273 -0.00042 l 2.002481 16.00035 l -10.003298 -0.001904 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" transform="matrix(-0.866025 0.5 -0.5 -0.866025 757.040822 -63.618176)"/>
|
||||
<path d="m 666.999018 291.999047 l -5.999273 -0.00042 l -2.001544 -15.998026 l 10.003298 -0.001904 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -472.382008)"/>
|
||||
<path d="m 661.001074 180.000929 l 5.999273 0.00042 l 2.001543 15.998025 l -10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0.866025 0.5 -0.5 0.866025 -393.040914 -472.382008)"/>
|
||||
<path d="m 667.00038 291.998593 l -5.999273 0.00042 l -2.002481 -16.00035 l 10.003298 0.001905 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -629.040914)"/>
|
||||
<path d="m 660.999779 180.001315 l 5.999272 -0.00042 l 1.999099 15.998397 l -9.999915 0.000049 z m 0 0" fill="#f6f5f4" stroke="#f6f5f4" stroke-linecap="round" stroke-linejoin="round" transform="matrix(0.5 0.866025 -0.866025 0.5 -63.618084 -629.040914)"/>
|
||||
</g>
|
||||
<path d="m 100 238 c 0 19.882812 -16.117188 36 -36 36 s -36 -16.117188 -36 -36 s 16.117188 -36 36 -36 s 36 16.117188 36 36 z m 0 0" fill="none" stroke="url(#a)" stroke-width="24" transform="matrix(1 0 0 1 0 -172)"/>
|
||||
<path d="m 102 64 c 0 20.988281 -17.011719 38 -38 38 s -38 -17.011719 -38 -38 s 17.011719 -38 38 -38 s 38 17.011719 38 38 z m 0 0" fill="none" stroke="#f6f5f4" stroke-width="20"/>
|
||||
<path d="m -209.5 -64 c 0 14.636719 -11.863281 26.5 -26.5 26.5 s -26.5 -11.863281 -26.5 -26.5 s 11.863281 -26.5 26.5 -26.5 s 26.5 11.863281 26.5 26.5 z m 0 0" fill="none" stroke="url(#b)" stroke-linecap="square" stroke-linejoin="round" stroke-width="5" transform="matrix(0 -1 -1 0 0 -172)"/>
|
||||
<path d="m 268 -64 c 0 17.671875 -14.328125 32 -32 32 s -32 -14.328125 -32 -32 s 14.328125 -32 32 -32 s 32 14.328125 32 32 z m 0 0" fill="none" stroke="url(#c)" stroke-linecap="square" stroke-linejoin="round" stroke-width="8" transform="matrix(0 1 -1 0 0 -172)"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.3 KiB |
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<path d="m 7.480469 0.015625 h 1.066406 c 0.589844 0 1.066406 0.476563 1.066406 1.066406 v 1.066407 c 0 0.589843 -0.476562 1.066406 -1.066406 1.066406 h -1.066406 c -0.589844 0 -1.066407 -0.476563 -1.066407 -1.066406 v -1.066407 c 0 -0.589843 0.476563 -1.066406 1.066407 -1.066406 z m 0 12.796875 h 1.066406 c 0.589844 0 1.066406 0.476562 1.066406 1.070312 v 1.0625 c 0 0.59375 -0.476562 1.070313 -1.066406 1.070313 h -1.066406 c -0.589844 0 -1.066407 -0.476563 -1.066407 -1.070313 v -1.0625 c 0 -0.59375 0.476563 -1.070312 1.066407 -1.070312 z m -5.5 -10.078125 l 0.753906 -0.753906 c 0.199219 -0.199219 0.46875 -0.3125 0.753906 -0.3125 c 0.28125 0 0.554688 0.113281 0.753907 0.3125 l 0.753906 0.753906 c 0.417968 0.417969 0.417968 1.089844 0 1.507813 l -0.753906 0.753906 c -0.199219 0.203125 -0.472657 0.316406 -0.753907 0.316406 c -0.285156 0 -0.554687 -0.113281 -0.753906 -0.316406 l -0.753906 -0.753906 c -0.203125 -0.199219 -0.316407 -0.46875 -0.316407 -0.753907 c 0 -0.28125 0.113282 -0.554687 0.316407 -0.753906 z m 9.050781 9.050781 l 0.753906 -0.753906 c 0.199219 -0.199219 0.472656 -0.3125 0.753906 -0.3125 c 0.285157 0 0.554688 0.113281 0.753907 0.3125 l 0.753906 0.753906 c 0.417969 0.417969 0.417969 1.089844 0 1.507813 l -0.753906 0.753906 c -0.199219 0.203125 -0.46875 0.316406 -0.753907 0.316406 c -0.28125 0 -0.554687 -0.113281 -0.753906 -0.316406 l -0.753906 -0.753906 c -0.203125 -0.199219 -0.3125 -0.46875 -0.3125 -0.753907 c 0 -0.28125 0.109375 -0.554687 0.3125 -0.753906 z m -11.015625 -3.238281 v -1.066406 c 0 -0.589844 0.472656 -1.066407 1.066406 -1.066407 h 1.066407 c 0.589843 0 1.066406 0.476563 1.066406 1.066407 v 1.066406 c 0 0.589844 -0.476563 1.066406 -1.066406 1.066406 h -1.066407 c -0.59375 0 -1.066406 -0.476562 -1.066406 -1.066406 z m 12.796875 0 v -1.066406 c 0 -0.589844 0.476562 -1.066407 1.066406 -1.066407 h 1.066406 c 0.59375 0 1.070313 0.476563 1.070313 1.066407 v 1.066406 c 0 0.589844 -0.476563 1.066406 -1.070313 1.066406 h -1.066406 c -0.589844 0 -1.066406 -0.476562 -1.066406 -1.066406 z m -10.078125 5.5 l -0.753906 -0.753906 c -0.203125 -0.199219 -0.316407 -0.46875 -0.316407 -0.753907 c 0 -0.28125 0.113282 -0.554687 0.316407 -0.753906 l 0.753906 -0.753906 c 0.199219 -0.199219 0.46875 -0.3125 0.753906 -0.3125 c 0.28125 0 0.554688 0.113281 0.753907 0.3125 l 0.753906 0.753906 c 0.417968 0.417969 0.417968 1.089844 0 1.507813 l -0.753906 0.753906 c -0.199219 0.203125 -0.472657 0.316406 -0.753907 0.316406 c -0.285156 0 -0.554687 -0.113281 -0.753906 -0.316406 z m 9.050781 -9.050781 l -0.753906 -0.753906 c -0.203125 -0.199219 -0.3125 -0.46875 -0.3125 -0.753907 c 0 -0.28125 0.109375 -0.554687 0.3125 -0.753906 l 0.753906 -0.753906 c 0.199219 -0.199219 0.472656 -0.3125 0.753906 -0.3125 c 0.285157 0 0.554688 0.113281 0.753907 0.3125 l 0.753906 0.753906 c 0.417969 0.417969 0.417969 1.089844 0 1.507813 l -0.753906 0.753906 c -0.199219 0.203125 -0.46875 0.316406 -0.753907 0.316406 c -0.28125 0 -0.554687 -0.113281 -0.753906 -0.316406 z m 0 0" fill="#241f31"/>
|
||||
<path d="m 8.015625 1.515625 c -3.574219 0 -6.5 2.925781 -6.5 6.5 c 0 3.570313 2.925781 6.5 6.5 6.5 c 3.570313 0 6.5 -2.929687 6.5 -6.5 c 0 -3.574219 -2.929687 -6.5 -6.5 -6.5 z m 0 3 c 1.949219 0 3.5 1.546875 3.5 3.5 c 0 1.949219 -1.550781 3.5 -3.5 3.5 c -1.953125 0 -3.5 -1.550781 -3.5 -3.5 c 0 -1.953125 1.546875 -3.5 3.5 -3.5 z m 0 0" fill="#241f31"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB |
@@ -2,12 +2,3 @@ install_subdir(
|
||||
'hicolor',
|
||||
install_dir : control_center_icondir
|
||||
)
|
||||
|
||||
if get_option('profile') == 'development'
|
||||
icondir = join_paths('hicolor', 'scalable', 'apps')
|
||||
install_data(
|
||||
join_paths(icondir, 'org.gnome.Settings.Devel.svg'),
|
||||
install_dir: join_paths(control_center_icondir, icondir),
|
||||
rename: 'org.gnome.Settings.svg'
|
||||
)
|
||||
endif
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
# These are the people responsible for Settings panels and domain-specific
|
||||
# parts of the GNOME Settings codebase.
|
||||
#
|
||||
# If you open a merge request for files listed here, please add the following
|
||||
# people to the list of reviewers.
|
||||
|
||||
# The syntax of this file is defined by GitLab:
|
||||
# https://docs.gitlab.com/ee/user/project/code_owners.html
|
||||
# Which, in turn, is similar to the .gitignore and .gitattributes files:
|
||||
#
|
||||
# - comments start with `#`
|
||||
# - the first column contains paths and globs
|
||||
# - the second column contains GitLab user names or email addresses,
|
||||
# separated by spaces
|
||||
#
|
||||
# The last matching glob (rather than the union of *all* matching globs) gives
|
||||
# the owners of a piece of code.
|
||||
#
|
||||
# If you want to be responsible for code reviews in specific sections of
|
||||
# the GNOME Settings code base, add yourself here.
|
||||
|
||||
# General maintainers
|
||||
* @felipeborges @robert_ancell
|
||||
|
||||
# Panels
|
||||
## About
|
||||
panels/info-overview/* @cyberphantom52
|
||||
|
||||
## Accessibility
|
||||
panels/universal-access/* @pksadiq
|
||||
|
||||
## Apps
|
||||
panels/applications/cc-default-apps-* @nishalkulkarni
|
||||
panels/applications/cc-removable-media-settings* @nishalkulkarni
|
||||
|
||||
## Bluetooth
|
||||
panels/bluetooth/* @hadess
|
||||
|
||||
## Printers
|
||||
panels/printers/* @mkasik
|
||||
|
||||
## Sound
|
||||
panels/sound/* @melix99
|
||||
|
||||
## Wacom
|
||||
panels/wacom/* @carlosg
|
||||
|
||||
## WWAN (Cellular)
|
||||
panels/wwan/* @pksadiq
|
||||
@@ -1,184 +0,0 @@
|
||||
# Code of Conduct
|
||||
|
||||
GNOME Settings is a project developed based on GNOME Code of Conduct and GitHub's community
|
||||
guidelines. You can read it below:
|
||||
|
||||
## Summary
|
||||
|
||||
GNOME creates software for a better world. We achieve this by behaving well towards
|
||||
each other.
|
||||
|
||||
Therefore this document suggests what we consider ideal behaviour, so you know what
|
||||
to expect when getting involved in GNOME. This is who we are and what we want to be.
|
||||
There is no official enforcement of these principles, and this should not be interpreted
|
||||
like a legal document.
|
||||
|
||||
## Advice
|
||||
|
||||
* **Be respectful and considerate**: Disagreement is no excuse for poor behaviour or personal
|
||||
attacks. Remember that a community where people feel uncomfortable is not a productive one.
|
||||
|
||||
* **Be patient and generous**: If someone asks for help it is because they need it. Do politely
|
||||
suggest specific documentation or more appropriate venues where appropriate, but avoid
|
||||
aggressive or vague responses such as "RTFM".
|
||||
|
||||
* **Assume people mean well**: Remember that decisions are often a difficult choice between
|
||||
competing priorities. If you disagree, please do so politely. If something seems outrageous,
|
||||
check that you did not misinterpret it. Ask for clarification, but do not assume the worst.
|
||||
|
||||
* **Try to be concise**: Avoid repeating what has been said already. Making a conversation larger
|
||||
makes it difficult to follow, and people often feel personally attacked if they receive multiple
|
||||
messages telling them the same thing.
|
||||
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Communication Guidelines
|
||||
|
||||
It is of ultimate importance to maintain a community in which everyone feels free to express
|
||||
themselves, review, and comment on each others ideas, both technical and otherwise. Correspondingly,
|
||||
an environment in which individuals are silenced, berated, or are otherwise afraid to speak up is
|
||||
unlikely to foster fruitful dialog.
|
||||
|
||||
Everyone interacting with members of the community should always keep in mind the asymmetry of
|
||||
communication: while your interaction with community members (and in particular, maintainers and
|
||||
long-term contributors) may be singular and fleeting, these members generally interact with a high
|
||||
volume of individuals each day. Before writing a comment, opening a new issue, or engaging as part
|
||||
of any forum or IRC discussion, please take a moment to appreciate that fact.
|
||||
|
||||
While communicating, it is expected that all involved participants be respectful and civil at all
|
||||
times and refrain from personal attacks.
|
||||
|
||||
### Communication Rules
|
||||
|
||||
The following behavior will not be tolerated on any occasion:
|
||||
|
||||
* **Threats of violence**: You may not threaten violence towards others or use the site to organize,
|
||||
promote, or incite acts of real-world violence or terrorism. Think carefully about the words you
|
||||
use, the images you post, and even the software you write, and how they may be interpreted by
|
||||
others. Even if you mean something as a joke, it might not be received that way. If you think
|
||||
that someone else might interpret the content you post as a threat or as promoting violence or
|
||||
terrorism, stop. Don't post it. In extraordinary cases, we may report threats of violence to law
|
||||
enforcement if we think there may be a genuine risk of physical harm or a threat to public safety.
|
||||
|
||||
* **Hate speech and discrimination**: While it is not forbidden to broach topics such as age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience, nationality,
|
||||
personal appearance, race, religion, or sexual identity and orientation, we do not tolerate speech
|
||||
that attacks a person or group of people on the basis of who they are. When approached in an
|
||||
aggressive or insulting manner these (and other) sensitive topics can make others feel unwelcome,
|
||||
or perhaps even unsafe. While there's always the potential for misunderstandings, we expect our
|
||||
community members to remain respectful and civil when discussing sensitive topics.
|
||||
|
||||
* **Bullying and harassment**: We do not tolerate bullying, harassment, or any other means of
|
||||
habitual badgering or intimidation targeted at a specific person or group of people. In general,
|
||||
if your actions are unwanted and you cease to terminate this form of engagement, there is a good
|
||||
chance that your behavior will be classified as bullying or harassment.
|
||||
|
||||
* **Impersonation**: You may not seek to mislead others as to your identity by copying another
|
||||
person's avatar, posting content under their email address, using a similar username, or otherwise
|
||||
posing as someone else. Impersonation and identity theft is a form of harassment.
|
||||
|
||||
* **Doxxing and invasion of privacy**: Don't post other people's personal information, such as phone
|
||||
numbers, private email addresses, physical addresses, credit card numbers, Social Security/National
|
||||
Identity numbers, or passwords. Depending on the context, we may consider such behavior to be an
|
||||
invasion of privacy, with particularly egregious examples potentially escalating to the point of
|
||||
legal action, such as when the released material presents a safety risk to the subject.
|
||||
|
||||
* **Obscene content**: In essence, do not post pornography, gore, or any other depiction of violence.
|
||||
|
||||
### General Advice
|
||||
|
||||
The following advice will help to increase the efficiency of communication with community members:
|
||||
|
||||
* Do not post "me too" comments. Use the GitLab reactions instead, e.g. “thumbs up” or “thumbs down”.
|
||||
* Avoid adding priority, time, or relevance hints if you are not involved with the development of
|
||||
the application. For example, `“This is an urgent issue”`, or `“This should be fixed now”`, or
|
||||
even `“The majority of users need this feature”`.
|
||||
* Do not use passive-aggressive communication tactics.
|
||||
* When reporting technical problems with the application, such as misbehavior or crashes, focus on
|
||||
sharing as many details as possible and avoid adding non-technical information to it.
|
||||
|
||||
An example of a **good** issue report:
|
||||
|
||||
```
|
||||
GNOME Settings crashes when opening the Wi-Fi panel with 3+ Wi-Fi adapters
|
||||
|
||||
Steps to reproduce (assuming 3+ Wi-Fi adapters are present):
|
||||
|
||||
1. Open GNOME Settings
|
||||
2. Select the Wi-Fi panel
|
||||
3. Observe the crash
|
||||
|
||||
This does not happen with 2 or less adapters. Here is a backtrace of the
|
||||
crash: backtrace.txt
|
||||
```
|
||||
|
||||
In contrast, here is an example of a **bad** issue report:
|
||||
|
||||
```
|
||||
GNOME Settings crashed while I was trying to connect to the internet. How can such
|
||||
a thing happen and nobody notice? Did you not test it before releasing it?
|
||||
|
||||
This should be fixed as quick as possible!
|
||||
```
|
||||
|
||||
* When asking for new features, try and add as much information as possible to justify its relevance,
|
||||
why should it not be implemented as an auxiliary program, what problems it would solve, and offer
|
||||
suggestions about how you think it should be implemented.
|
||||
|
||||
Example of a **good** feature request:
|
||||
|
||||
```
|
||||
GNOME Settings needs to expose IPv6 options
|
||||
|
||||
As of now, the connection editor dialog does not allow editing various IPv6
|
||||
options. This is relevant because without some of these options, it is not
|
||||
possible to have a valid IPv6 configuration and, consequently, not have access
|
||||
to various websites and services.
|
||||
|
||||
The list of missing configurations that are essential is:
|
||||
|
||||
* <Feature A>
|
||||
* <Feature B>
|
||||
|
||||
Optionally, the following configurations can also be added:
|
||||
|
||||
* <Feature C>
|
||||
* <Feature D>
|
||||
|
||||
Here is a quick sketch I have made showing how I think these options
|
||||
should be exposed as a user interface: sketch.png.
|
||||
```
|
||||
|
||||
Example of a **bad** feature request:
|
||||
|
||||
```
|
||||
Merge GNOME Tweaks in GNOME Settings
|
||||
|
||||
The options in GNOME Tweaks are absolutely essential to the majority of us
|
||||
users. Why was it not merged already? This is an urgent issue and should
|
||||
have been addressed years ago. You should allocate all your resources on
|
||||
merging those two applications.
|
||||
```
|
||||
|
||||
### What happens if someone breaks these rules or guidelines?
|
||||
|
||||
Actions that may be taken in response to an abusive comment include but are not limited to:
|
||||
|
||||
* Content removal (when breaking any of the guidelines or rules)
|
||||
* Content blocking (when breaking any of the guidelines or rules)
|
||||
* Formal report to the Code of Conduct Committee (when breaking any of the rules)
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
[maintainers]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/MAINTAINERS.md
|
||||
@@ -1,97 +1,75 @@
|
||||
# Contributing
|
||||
|
||||
Thank you for considering contributing to Settings!
|
||||
|
||||
All code contributions are made using merge requests.
|
||||
When contributing to the development of GNOME Settings, please first discuss the change you wish to
|
||||
make via issue, email, or any other method with the maintainers before making a change.
|
||||
|
||||
Please note we have a Code of Conduct, please follow it in all your interactions with the project.
|
||||
|
||||
## Creating Merge Requests
|
||||
## Pull Request Process
|
||||
|
||||
To open a merge request fork the Settings project, and then create a branch for your change.
|
||||
When the change is ready, submit a merge request.
|
||||
1. Create a fork in GitLab and push your work to there
|
||||
2. Open a Merge Request
|
||||
1. Always allow maintainer edits
|
||||
2. Mark the Merge Request as WIP if your work is not ready to be reviewed
|
||||
3. Assign the correct maintainer to the Merge Request (see [`MAINTAINERS.md`][maintainers] to select
|
||||
the correct maintainer)
|
||||
4. Format commit messages as follows:
|
||||
```
|
||||
component: <summary>
|
||||
|
||||
A paragraph explaining the problem and its context.
|
||||
|
||||
Another one explaining how you solved that.
|
||||
|
||||
<link to the issue>
|
||||
```
|
||||
4. You may merge the pull request in once you have the sign-off of the maintainers, or if you
|
||||
do not have permission to do that, you may request the second reviewer to merge it for you.
|
||||
|
||||
The following guidelines will help your change be successfully merged:
|
||||
## Code of Conduct
|
||||
|
||||
* Keep the change as small as possible. If you can split it into multiple merge requests please do
|
||||
so.
|
||||
* Use multiple commits. This makes is easier to review and helps to diagnose bugs in the future.
|
||||
* Use clear commit messages (see below).
|
||||
* Attach screenshots of the change.
|
||||
* Link to relevant issues this change is related to.
|
||||
* Always set the merge request to allow maintainer edits - this makes it easier
|
||||
for a maintainer to make small improvements to land the change faster.
|
||||
GNOME Settings is a project developed based on GNOME Code of Conduct. You can read it below:
|
||||
|
||||
Please format commit messages as follows:
|
||||
### Summary
|
||||
|
||||
```
|
||||
component: <summary>
|
||||
GNOME creates software for a better world. We achieve this by behaving well towards
|
||||
each other.
|
||||
|
||||
A paragraph explaining the problem and its context.
|
||||
Therefore this document suggests what we consider ideal behaviour, so you know what
|
||||
to expect when getting involved in GNOME. This is who we are and what we want to be.
|
||||
There is no official enforcement of these principles, and this should not be interpreted
|
||||
like a legal document.
|
||||
|
||||
Another one explaining how you solved that.
|
||||
### Advice
|
||||
|
||||
<link to issue(s) this change fixes>
|
||||
```
|
||||
* **Be respectful and considerate**: Disagreement is no excuse for poor behaviour or personal
|
||||
attacks. Remember that a community where people feel uncomfortable is not a productive one.
|
||||
|
||||
## Bug Fixes
|
||||
* **Be patient and generous**: If someone asks for help it is because they need it. Do politely
|
||||
suggest specific documentation or more appropriate venues where appropriate, but avoid
|
||||
aggressive or vague responses such as "RTFM".
|
||||
|
||||
Changes that fix bugs include:
|
||||
* **Assume people mean well**: Remember that decisions are often a difficult choice between
|
||||
competing priorities. If you disagree, please do so politely. If something seems outrageous,
|
||||
check that you did not misinterpret it. Ask for clarification, but do not assume the worst.
|
||||
|
||||
* Correcting code that crashes.
|
||||
* Spelling mistakes in labels.
|
||||
* Small layout issues (e.g. spacing).
|
||||
* Use of deprecated APIs.
|
||||
* Restructuring of code for improved safety.
|
||||
* **Try to be concise**: Avoid repeating what has been said already. Making a conversation larger
|
||||
makes it difficult to follow, and people often feel personally attacked if they receive multiple
|
||||
messages telling them the same thing.
|
||||
|
||||
Please include clear information in the commit message(s) and merge request that indicate what is
|
||||
being fixed by the change.
|
||||
|
||||
These changes will be reviewed for correctness, and then merged once this is complete.
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## User Experience Changes
|
||||
### Attribution
|
||||
|
||||
Changes that impact the user experience of Settings require approval from the
|
||||
[Design Team][design-team]. This includes:
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
* Addition or removal of features in existing panels.
|
||||
* Changes to the layout of panels.
|
||||
* New panels.
|
||||
|
||||
Please include before/after screenshots in the merge request to show what is being changed.
|
||||
|
||||
For one of these changes to be merged one of the following is required:
|
||||
|
||||
* The change is shown in an existing mockup done by the design team (linked to in the merge request
|
||||
or issue).
|
||||
* A comment from a design team member in the merge request or issue approving the change.
|
||||
|
||||
If a merge request is opened without the above the "Needs Design" label attached to it and will not
|
||||
be merged until design approval is received.
|
||||
|
||||
Once design approval is obtained, the change will be reviewed for correctness, and then merged once
|
||||
this is complete.
|
||||
If design approval is not obtained, the merge request will be closed.
|
||||
|
||||
[design-team]: https://gitlab.gnome.org/Teams/Design
|
||||
|
||||
## Reviews
|
||||
|
||||
All changes require approval from one or more Settings maintainers.
|
||||
Reviews are likely to ask for changes to be made, please respond to these as soon as you are able
|
||||
and ask for clarification if the requests are not clear.
|
||||
|
||||
When the change is ready to land a maintainer will mark it as approved.
|
||||
Then the change can be merged by either a maintainer or the submitter if they have suitable
|
||||
permissions.
|
||||
|
||||
## Draft Merge Requests
|
||||
|
||||
Merge requests marked as draft will not be reviewed by Settings maintainers or merged.
|
||||
When the change is ready for review please mark the merge request as ready.
|
||||
|
||||
## Inactive Merge Requests
|
||||
|
||||
If a merge request has comments from maintainers that have not been responded to within 4 weeks this
|
||||
merge request is considered to be inactive and will be closed. The reporter may re-open it at a
|
||||
later date if they respond to the comments.
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
[maintainers]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/MAINTAINERS.md
|
||||
|
||||
@@ -50,7 +50,7 @@ by being explicit. Suggested acceptance phrase:
|
||||
Urgency commits should never happen, but in case they're needed, they are defined by the following
|
||||
criteria:
|
||||
|
||||
* On stable branches (or `main` right after a stable release)
|
||||
* On stable branches (or master right after a stable release)
|
||||
* Symptoms:
|
||||
* Always OR often reproducible; AND
|
||||
* Crash; OR
|
||||
@@ -59,4 +59,4 @@ criteria:
|
||||
* Quickly followed by an emergency release (at most 2 days after the commit)
|
||||
|
||||
|
||||
[doap]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/gnome-control-center.doap
|
||||
[doap]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/gnome-control-center.doap
|
||||
|
||||
@@ -7,26 +7,26 @@
|
||||
<name xml:lang="en">GNOME Settings</name>
|
||||
<shortdesc xml:lang="en">GNOME's main interface to configure various aspects of the desktop</shortdesc>
|
||||
<description xml:lang="en">GNOME's main interface to configure various aspects of the desktop</description>
|
||||
<support-forum rdf:resource="https://discourse.gnome.org/c/desktop/" />
|
||||
<download-page rdf:resource="https://download.gnome.org/sources/gnome-control-center/" />
|
||||
<bug-database rdf:resource="https://gitlab.gnome.org/GNOME/gnome-control-center/issues" />
|
||||
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnomecc-list" />
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/gnome-control-center/" />
|
||||
<bug-database rdf:resource="http://gitlab.gnome.org/GNOME/gnome-control-center/issues" />
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
|
||||
<programming-language>C</programming-language>
|
||||
|
||||
<!-- General -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Felipe Borges</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:felipeborges@gnome.org" />
|
||||
<gnome:userid>felipeborges</gnome:userid>
|
||||
<foaf:name>Georges Basile Stavracas Neto</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:gbsneto@gnome.org" />
|
||||
<gnome:userid>gbsneto</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- General -->
|
||||
<!-- General, Region & Language -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Robert Ancell</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:robert.ancell@canonical.com" />
|
||||
<foaf:mbox rdf:resource="mailto:rancell@gnome.org" />
|
||||
<gnome:userid>rancell</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
@@ -40,11 +40,47 @@
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- Mouse & Touchpad, Printers -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Felipe Borges</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:felipeborges@gnome.org" />
|
||||
<gnome:userid>felipeborges</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- Online Accounts -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Debarshi Ray</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:debarshir@gnome.org" />
|
||||
<gnome:userid>debarshir</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- Printers -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Marek Kašík</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:mkasik@redhat.com" />
|
||||
<foaf:mbox rdf:resource="mailto:mkasik@gnome.org" />
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- Thunderbolt -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Christian Kellner</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:gicmo@gnome.org" />
|
||||
<gnome:userid>gicmo</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- User Accounts -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Ondrej Holy</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:oholy@gnome.org" />
|
||||
<gnome:userid>oholy</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
|
||||
@@ -115,9 +115,9 @@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>info-overview</option></term>
|
||||
<term><option>info</option></term>
|
||||
|
||||
<listitem><para>The info-overview panel shows a general
|
||||
<listitem><para>The info panel shows a general
|
||||
overview of the system configuration. It also
|
||||
lets you change the default applications for
|
||||
various tasks and the handling of removable
|
||||
|
||||
247
meson.build
@@ -1,8 +1,8 @@
|
||||
project(
|
||||
'gnome-control-center', 'c',
|
||||
version : '46.alpha',
|
||||
version : '3.30.1',
|
||||
license : 'GPL2+',
|
||||
meson_version : '>= 0.58.0'
|
||||
meson_version : '>= 0.43.0'
|
||||
)
|
||||
|
||||
control_center_prefix = get_option('prefix')
|
||||
@@ -25,19 +25,15 @@ host_is_linux_not_s390 = host_is_linux and not host_machine.cpu().contains('s390
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
# Tracing
|
||||
enable_tracing = get_option('tracing')
|
||||
|
||||
config_h = configuration_data()
|
||||
|
||||
py = import('python')
|
||||
python = py.find_installation('python3')
|
||||
py3 = import('python3')
|
||||
python = py3.find_python()
|
||||
|
||||
config_h.set_quoted('TEST_NM_PYTHON', python.full_path())
|
||||
|
||||
if get_option('profile') == 'development'
|
||||
profile = 'Devel'
|
||||
else
|
||||
profile = ''
|
||||
endif
|
||||
application_id = 'org.gnome.Settings@0@'.format(profile)
|
||||
config_h.set_quoted('TEST_NM_PYTHON', python.path())
|
||||
|
||||
# defines
|
||||
set_defines = [
|
||||
@@ -45,7 +41,6 @@ set_defines = [
|
||||
['PACKAGE', meson.project_name()],
|
||||
['PACKAGE_VERSION', meson.project_version()],
|
||||
['VERSION', meson.project_version()],
|
||||
['PROFILE', get_option('profile')],
|
||||
# i18n
|
||||
['GETTEXT_PACKAGE', control_center_gettext]
|
||||
]
|
||||
@@ -54,17 +49,6 @@ foreach define: set_defines
|
||||
config_h.set_quoted(define[0], define[1])
|
||||
endforeach
|
||||
|
||||
distributor_logo = get_option('distributor_logo')
|
||||
if (distributor_logo != '')
|
||||
config_h.set_quoted('DISTRIBUTOR_LOGO', distributor_logo,
|
||||
description: 'Define to absolute path of distributor logo')
|
||||
dark_mode_distributor_logo = get_option('dark_mode_distributor_logo')
|
||||
if (dark_mode_distributor_logo != '')
|
||||
config_h.set_quoted('DARK_MODE_DISTRIBUTOR_LOGO', dark_mode_distributor_logo,
|
||||
description: 'Define to absolute path of distributor logo for use in dark mode')
|
||||
endif
|
||||
endif
|
||||
|
||||
# meson does not support octal values, so it must be handled as a
|
||||
# string. See: https://github.com/mesonbuild/meson/issues/2047
|
||||
config_h.set('USER_DIR_MODE', '0700',
|
||||
@@ -73,15 +57,6 @@ config_h.set('USER_DIR_MODE', '0700',
|
||||
# compiler flags
|
||||
common_flags = ['-DHAVE_CONFIG_H']
|
||||
|
||||
# We have so many deprecation warnings that it becomes impossible to notice any other useful
|
||||
# warning, thus making the compiler output completely useless. Ideally, we should fix all
|
||||
# of those but, until then, it's better to add this flag so that we avoid adding even more
|
||||
# warnings by accident. If you want to fix some of those, just build Settings with:
|
||||
# meson _build -Ddeprecated-declarions=enabled
|
||||
if get_option('deprecated-declarations').disabled()
|
||||
common_flags += '-Wno-deprecated-declarations'
|
||||
endif
|
||||
|
||||
# Only add this when optimizing is enabled (default)
|
||||
optimized_src = '''
|
||||
#if __OPTIMIZE__ == 0
|
||||
@@ -117,8 +92,6 @@ libgvc = subproject(
|
||||
default_options: [
|
||||
'static=true',
|
||||
'alsa=false',
|
||||
'package_name=' + control_center_gettext,
|
||||
'package_version=' + meson.project_version(),
|
||||
]
|
||||
)
|
||||
libgvc_dep = libgvc.get_variable('libgvc_dep')
|
||||
@@ -126,73 +99,23 @@ libgvc_dep = libgvc.get_variable('libgvc_dep')
|
||||
goa_req_version = '>= 3.25.3'
|
||||
pulse_req_version = '>= 2.0'
|
||||
|
||||
gtk_dep = dependency(
|
||||
'gtk4',
|
||||
version: '>= 4.11.2',
|
||||
fallback: ['gtk', 'gtk_dep'],
|
||||
default_options: [
|
||||
'introspection=disabled',
|
||||
'demos=false',
|
||||
'build-testsuite=false',
|
||||
'build-tests=false',
|
||||
'build-examples=false',
|
||||
]
|
||||
)
|
||||
|
||||
libadwaita_dep = dependency(
|
||||
'libadwaita-1',
|
||||
version: '>= 1.4.alpha',
|
||||
required: false
|
||||
)
|
||||
# FIXME: this is a workaround because interactive-tests don't work with libadwaita as a subproject. See !1754
|
||||
libadwaita_is_subproject = not libadwaita_dep.found()
|
||||
if libadwaita_is_subproject
|
||||
libadwaita = subproject(
|
||||
'libadwaita',
|
||||
default_options: [
|
||||
'examples=false',
|
||||
'introspection=disabled',
|
||||
'tests=false',
|
||||
'vapi=false',
|
||||
],
|
||||
)
|
||||
libadwaita_dep = libadwaita.get_variable('libadwaita_dep')
|
||||
endif
|
||||
|
||||
tecla_dep = dependency(
|
||||
'tecla',
|
||||
required: false
|
||||
)
|
||||
|
||||
# Needs to be a subproject since tecla does not declare dependencies
|
||||
tecla_is_subproject = not tecla_dep.found()
|
||||
if tecla_is_subproject
|
||||
tecla = subproject(
|
||||
'tecla'
|
||||
)
|
||||
endif
|
||||
|
||||
accounts_dep = dependency('accountsservice', version: '>= 0.6.39')
|
||||
clutter_gtk_dep = dependency('clutter-gtk-1.0', required: false)
|
||||
colord_dep = dependency('colord', version: '>= 0.1.34')
|
||||
gdk_pixbuf_dep = dependency('gdk-pixbuf-2.0', version: '>= 2.23.0')
|
||||
gio_dep = dependency('gio-2.0')
|
||||
glib_dep = dependency('glib-2.0', version: '>= 2.76.6')
|
||||
gnome_desktop_dep = dependency('gnome-desktop-4')
|
||||
gnome_bg_dep = dependency('gnome-bg-4')
|
||||
gnome_rr_dep = dependency('gnome-rr-4')
|
||||
gnome_settings_dep = dependency('gnome-settings-daemon', version: '>= 41.0')
|
||||
glib_dep = dependency('glib-2.0', version: '>= 2.53.0')
|
||||
gnome_desktop_dep = dependency('gnome-desktop-3.0', version: '>= 3.27.90')
|
||||
gnome_settings_dep = dependency('gnome-settings-daemon', version: '>= 3.25.90')
|
||||
goa_dep = dependency('goa-1.0', version: goa_req_version)
|
||||
gsettings_desktop_dep = dependency('gsettings-desktop-schemas', version: '>= 42.alpha')
|
||||
gsettings_desktop_dep = dependency('gsettings-desktop-schemas', version: '>= 3.27.2')
|
||||
libxml_dep = dependency('libxml-2.0')
|
||||
polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.103')
|
||||
pulse_dep = dependency('libpulse', version: pulse_req_version)
|
||||
pulse_mainloop_dep = dependency('libpulse-mainloop-glib', version: pulse_req_version)
|
||||
upower_glib_dep = dependency('upower-glib', version: '>= 0.99.8')
|
||||
gudev_dep = dependency('gudev-1.0', version: '>= 232')
|
||||
x11_dep = dependency('x11', version: '>= 1.8')
|
||||
upower_glib_dep = dependency('upower-glib', version: '>= 0.99.6')
|
||||
x11_dep = dependency('x11')
|
||||
xi_dep = dependency('xi', version: '>= 1.2')
|
||||
epoxy_dep = dependency('epoxy')
|
||||
gcr_dep = dependency('gcr-base-3')
|
||||
pwquality_dep = dependency('pwquality', version: '>= 1.2.2')
|
||||
|
||||
m_dep = cc.find_library('m')
|
||||
|
||||
@@ -200,21 +123,11 @@ common_deps = [
|
||||
gio_dep,
|
||||
glib_dep,
|
||||
gsettings_desktop_dep,
|
||||
libadwaita_dep,
|
||||
dependency('gio-unix-2.0'),
|
||||
dependency('gthread-2.0'),
|
||||
gtk_dep,
|
||||
dependency('gtk+-3.0', version: '>= 3.22.20')
|
||||
]
|
||||
|
||||
polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.103')
|
||||
# Also verify that polkit ITS files exist:
|
||||
# https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/491
|
||||
polkit_files = [ 'gettext/its/polkit.its', 'gettext/its/polkit.loc' ]
|
||||
foreach polkit_file: polkit_files
|
||||
r = run_command('build-aux/meson/find_xdg_file.py', polkit_file, check: true)
|
||||
assert(r.returncode() == 0, 'ITS support missing from polkit, please upgrade or contact your distribution')
|
||||
endforeach
|
||||
|
||||
# Check for CUPS 1.4 or newer
|
||||
cups_dep = dependency('cups', version : '>= 1.4', required: false)
|
||||
assert(cups_dep.found(), 'CUPS 1.4 or newer not found')
|
||||
@@ -222,7 +135,7 @@ assert(cups_dep.found(), 'CUPS 1.4 or newer not found')
|
||||
# https://bugzilla.gnome.org/show_bug.cgi?id=696766
|
||||
cups_cflags = []
|
||||
if cups_dep.version().version_compare('>= 1.6')
|
||||
cups_cflags += '-D_PPD_DEPRECATED='
|
||||
cups_cflags += '-D_PPD_DEPRECATED=""'
|
||||
endif
|
||||
|
||||
# cups headers
|
||||
@@ -235,9 +148,19 @@ foreach header: check_headers
|
||||
assert(cc.has_header(header[1], args: cups_cflags), 'CUPS headers not found: ' + header[1])
|
||||
endforeach
|
||||
|
||||
config_h.set10('HAVE_CUPS_HTTPCONNECT2',
|
||||
cc.has_function('httpConnect2', dependencies: cups_dep),
|
||||
description: 'Define if httpConnect2() is available in CUPS')
|
||||
# Optional dependency for the user accounts panel
|
||||
enable_cheese = get_option('cheese')
|
||||
if enable_cheese
|
||||
assert(clutter_gtk_dep.found(), 'cheese support requested, but clutter-gtk library is not available. Use -Dcheese=false to build without it.')
|
||||
|
||||
cheese_deps = [
|
||||
clutter_gtk_dep,
|
||||
dependency('cheese', version: '>= 3.28.0'),
|
||||
dependency('cheese-gtk', version: '>= 3.5.91')
|
||||
]
|
||||
endif
|
||||
config_h.set('HAVE_CHEESE', enable_cheese,
|
||||
description: 'Define to 1 to enable cheese webcam support')
|
||||
|
||||
# IBus support
|
||||
enable_ibus = get_option('ibus')
|
||||
@@ -247,57 +170,43 @@ endif
|
||||
config_h.set('HAVE_IBUS', enable_ibus,
|
||||
description: 'Defined if IBus support is enabled')
|
||||
|
||||
# thunderbolt
|
||||
config_h.set10('HAVE_FN_EXPLICIT_BZERO',
|
||||
cc.has_function('explicit_bzero', prefix: '''#include <string.h>'''),
|
||||
description: 'Define if explicit_bzero is available')
|
||||
|
||||
# Snap support
|
||||
enable_snap = get_option('snap')
|
||||
if enable_snap
|
||||
json_glib_dep = dependency('json-glib-1.0')
|
||||
libsoup_dep = dependency('libsoup-3.0')
|
||||
# wayland
|
||||
enable_wayland = get_option('wayland')
|
||||
if enable_wayland
|
||||
wayland_deps = [
|
||||
dependency('gdk-wayland-3.0'),
|
||||
dependency('gudev-1.0')
|
||||
]
|
||||
endif
|
||||
config_h.set('HAVE_SNAP', enable_snap,
|
||||
description: 'Define to 1 if Snap support is enabled')
|
||||
|
||||
# malcontent support
|
||||
enable_malcontent = get_option('malcontent')
|
||||
if enable_malcontent
|
||||
malcontent_dep = dependency('malcontent-0', version: '>= 0.7.0')
|
||||
config_h.set('HAVE_MALCONTENT_0_10', malcontent_dep.version().version_compare('>= 0.10.0'),
|
||||
description: 'Define to 1 if malcontent ≥ 0.10.0')
|
||||
endif
|
||||
config_h.set('HAVE_MALCONTENT', enable_malcontent,
|
||||
description: 'Define to 1 if malcontent support is enabled')
|
||||
config_h.set('HAVE_WAYLAND', enable_wayland,
|
||||
description: 'Define to 1 if Wayland is enabled')
|
||||
|
||||
if host_is_linux
|
||||
# ModemManager
|
||||
mm_dep = dependency('mm-glib', version: '>= 0.7')
|
||||
# NetworkManager
|
||||
# network manager
|
||||
network_manager_deps = [
|
||||
dependency('libnm', version: '>= 1.24.0'),
|
||||
dependency('libnma-gtk4', version: '>= 1.10.2'),
|
||||
mm_dep,
|
||||
dependency('libnm', version: '>= 1.10.0'),
|
||||
dependency('libnma', version: '>= 1.8.0'),
|
||||
dependency('mm-glib', version: '>= 0.7')
|
||||
]
|
||||
endif
|
||||
config_h.set('BUILD_NETWORK', host_is_linux,
|
||||
description: 'Define to 1 to build the Network panel')
|
||||
config_h.set('HAVE_NETWORK_MANAGER', host_is_linux,
|
||||
description: 'Define to 1 if NetworkManager is available')
|
||||
config_h.set('BUILD_WWAN', host_is_linux,
|
||||
description: 'Define to 1 to build the WWan panel')
|
||||
config_h.set('HAVE_WWAN', host_is_linux,
|
||||
description: 'Define to 1 if WWan is available')
|
||||
|
||||
if host_is_linux_not_s390
|
||||
# gnome-bluetooth
|
||||
gnome_bluetooth_dep = dependency('gnome-bluetooth-ui-3.0')
|
||||
gnome_bluetooth_dep = dependency('gnome-bluetooth-1.0', version: '>= 3.18.2')
|
||||
|
||||
# Wacom
|
||||
assert(clutter_gtk_dep.found(), 'clutter-gtk library is required for wacom support, but is not available.')
|
||||
|
||||
libwacom_dep = dependency('libwacom', version: '>= 0.7')
|
||||
|
||||
wacom_deps = [
|
||||
clutter_gtk_dep,
|
||||
libwacom_dep,
|
||||
dependency('clutter-1.0', version: '>= 1.11.3'),
|
||||
]
|
||||
config_h.set('HAVE_WACOM_3D_STYLUS', libwacom_dep.version().version_compare('>= 0.27'),
|
||||
description: 'Define to 1 if libwacom provides definition for 3D styli')
|
||||
@@ -316,12 +225,21 @@ config_h.set('HAVE_WACOM', host_is_linux_not_s390,
|
||||
config_h.set('BUILD_THUNDERBOLT', host_is_linux_not_s390,
|
||||
description: 'Define to 1 to build the Thunderbolt panel')
|
||||
|
||||
# Check for info panel
|
||||
gnome_session_libexecdir = get_option('gnome_session_libexecdir')
|
||||
if gnome_session_libexecdir == ''
|
||||
gnome_session_libexecdir = control_center_libexecdir
|
||||
endif
|
||||
|
||||
gnome = import('gnome')
|
||||
i18n = import('i18n')
|
||||
pkg = import('pkgconfig')
|
||||
|
||||
po_dir = join_paths(meson.project_source_root(), 'po')
|
||||
its_dir = join_paths(meson.project_source_root(), 'gettext')
|
||||
desktop_conf = configuration_data()
|
||||
desktop_conf.set('VERSION', meson.project_version())
|
||||
|
||||
po_dir = join_paths(meson.source_root(), 'po')
|
||||
its_dir = join_paths(meson.source_root(), 'gettext')
|
||||
|
||||
install_subdir(
|
||||
'gettext',
|
||||
@@ -331,44 +249,37 @@ install_subdir(
|
||||
top_inc = include_directories('.')
|
||||
shell_inc = include_directories('shell')
|
||||
|
||||
subdir('build-aux')
|
||||
subdir('data/icons')
|
||||
subdir('po')
|
||||
subdir('panels')
|
||||
subdir('shell')
|
||||
subdir('search-provider')
|
||||
|
||||
if get_option('tests')
|
||||
subdir('tests')
|
||||
endif
|
||||
subdir('tests')
|
||||
|
||||
if get_option('documentation')
|
||||
subdir('man')
|
||||
endif
|
||||
|
||||
gnome.post_install(
|
||||
glib_compile_schemas: true,
|
||||
gtk_update_icon_cache: true,
|
||||
)
|
||||
|
||||
configure_file(
|
||||
output: 'config.h',
|
||||
configuration: config_h
|
||||
)
|
||||
|
||||
summary({
|
||||
'Documentation': get_option('documentation'),
|
||||
'Tests': get_option('tests'),
|
||||
'Optimized': control_center_optimized,
|
||||
})
|
||||
output = ''
|
||||
output += '\n ' + meson.project_name() + ' - ' + meson.project_version() + '\n'
|
||||
output += ' ===================================\n'
|
||||
output += ' Options \n'
|
||||
output += ' Documentation .............................. ' + get_option('documentation').to_string() + '\n'
|
||||
output += ' Tracing .................................... ' + enable_tracing.to_string() + '\n'
|
||||
output += ' gnome-session libexecdir ................... ' + gnome_session_libexecdir + '\n'
|
||||
output += ' Optimized .................................. ' + control_center_optimized.to_string() + '\n'
|
||||
output += ' Panels \n'
|
||||
output += ' GNOME Bluetooth (Bluetooth panel) .......... ' + host_is_linux_not_s390.to_string() + '\n'
|
||||
output += ' Cheese (Users panel webcam support) ........ ' + enable_cheese.to_string() + '\n'
|
||||
output += ' IBus (Region panel IBus support) ........... ' + enable_ibus.to_string() + '\n'
|
||||
output += ' NetworkManager (Network panel) ............. ' + host_is_linux.to_string() + '\n'
|
||||
output += ' Wacom (Wacom tablet panel) ................. ' + host_is_linux_not_s390.to_string() + '\n'
|
||||
output += ' Wayland .................................... ' + enable_wayland.to_string() + '\n'
|
||||
|
||||
summary({
|
||||
'GNOME Bluetooth': host_is_linux_not_s390,
|
||||
'NetworkManager': host_is_linux,
|
||||
'Wacom': host_is_linux_not_s390,
|
||||
}, section: 'Dependencies')
|
||||
|
||||
summary({
|
||||
'IBus': enable_ibus,
|
||||
'Snap': enable_snap,
|
||||
'Malcontent': enable_malcontent,
|
||||
}, section: 'Optional Dependencies')
|
||||
message(output)
|
||||
@@ -1,11 +1,6 @@
|
||||
option('deprecated-declarations', type: 'feature', value: 'disabled', description: 'build with deprecated declaration warnings')
|
||||
option('cheese', type: 'boolean', value: true, description: 'build with cheese webcam support')
|
||||
option('documentation', type: 'boolean', value: false, description: 'build documentation')
|
||||
option('gnome_session_libexecdir', type: 'string', value: '', description: 'Directory for gnome-session\'s libexecdir')
|
||||
option('ibus', type: 'boolean', value: true, description: 'build with IBus support')
|
||||
option('privileged_group', type: 'string', value: 'wheel', description: 'name of group that has elevated permissions')
|
||||
option('snap', type: 'boolean', value: true, description: 'build with Snap support')
|
||||
option('tests', type: 'boolean', value: true, description: 'build tests')
|
||||
option('wayland', type: 'boolean', value: true, description: 'build with Wayland support')
|
||||
option('profile', type: 'combo', choices: ['default','development'], value: 'default')
|
||||
option('malcontent', type: 'boolean', value: false, description: 'build with malcontent support')
|
||||
option('distributor_logo', type: 'string', description: 'absolute path to distributor logo for the About panel')
|
||||
option('dark_mode_distributor_logo', type: 'string', description: 'absolute path to distributor logo dark mode variant')
|
||||
option('tracing', type: 'boolean', value: false, description: 'add extra debugging information')
|
||||
option('wayland', type: 'boolean', value: true, description: 'build with Wayland support')
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gnome/control-center/applications">
|
||||
<file preprocess="xml-stripblanks">cc-applications-panel.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-default-apps-page.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-removable-media-settings.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-applications-row.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-info-row.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-snap-row.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
@@ -1,30 +0,0 @@
|
||||
/* cc-applications-panel.h
|
||||
*
|
||||
* Copyright 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <shell/cc-panel.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_APPLICATIONS_PANEL (cc_applications_panel_get_type())
|
||||
G_DECLARE_FINAL_TYPE (CcApplicationsPanel, cc_applications_panel, CC, APPLICATIONS_PANEL, CcPanel)
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,599 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcApplicationsPanel" parent="CcPanel">
|
||||
<property name="child">
|
||||
<object class="AdwNavigationView" id="navigation_view">
|
||||
|
||||
<!-- App Search Page (Main Ladning Page) -->
|
||||
<child>
|
||||
<object class="AdwNavigationPage">
|
||||
<property name="title" translatable="yes">Apps</property>
|
||||
<property name="child">
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar"/>
|
||||
</child>
|
||||
|
||||
<property name="content">
|
||||
<object class="AdwPreferencesPage" id="app_search_stack_page">
|
||||
<!-- Searchbar -->
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="AdwClamp">
|
||||
<property name="maximum-size">280</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="app_search_entry">
|
||||
<property name="placeholder_text" translatable="yes">Search apps</property>
|
||||
<signal name="activate" handler="on_app_search_entry_activated_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
<signal name="search-changed" handler="on_app_search_entry_search_changed_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
<signal name="stop-search" handler="on_app_search_entry_search_stopped_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Default Apps Row -->
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="CcListRow">
|
||||
<property name="activatable">True</property>
|
||||
<property name="title" translatable="yes">_Default Apps</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="show-arrow">True</property>
|
||||
<property name="action-name">navigation.push</property>
|
||||
<property name="action-target">'default-apps'</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Apps List -->
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="GtkStack" id="app_listbox_stack">
|
||||
<property name="vhomogeneous">False</property>
|
||||
<child>
|
||||
<!-- Empty search results placeholder -->
|
||||
<object class="GtkBox" id="empty_search_placeholder">
|
||||
<!--AdwStatusPage can't be used here, see: https://gitlab.gnome.org/GNOME/libadwaita/-/issues/697-->
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="valign">center</property>
|
||||
|
||||
<!--Use AdwClamp like AdwStatusPage-->
|
||||
<child>
|
||||
<object class="AdwClamp">
|
||||
<style>
|
||||
<class name="status-page"/>
|
||||
</style>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="pixel_size">128</property>
|
||||
<property name="icon_name">computer-fail-symbolic</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
<class name="icon"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">No Apps Found</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="wrap-mode">word-char</property>
|
||||
<property name="justify">center</property>
|
||||
<style>
|
||||
<class name="title"/>
|
||||
<class name="title-1"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="install_button">
|
||||
<property name="label" translatable="yes">_Find in Software</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="halign">center</property>
|
||||
<signal name="clicked" handler="open_software_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
<style>
|
||||
<class name="pill"/>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBox" id="app_listbox">
|
||||
<property name="selection-mode">none</property>
|
||||
<style>
|
||||
<class name="boxed-list" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Default Apps Page -->
|
||||
<child>
|
||||
<object class="AdwNavigationPage">
|
||||
<property name="title" translatable="yes">Default Apps</property>
|
||||
<property name="tag">default-apps</property>
|
||||
<property name="child">
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar"/>
|
||||
</child>
|
||||
|
||||
<property name="content">
|
||||
<object class="AdwPreferencesPage">
|
||||
<!-- Default Apps Settings -->
|
||||
<child>
|
||||
<object class="CcDefaultAppsPage" id="default_apps_page" />
|
||||
</child>
|
||||
|
||||
<!-- Removable Media Settings -->
|
||||
<child>
|
||||
<object class="CcRemovableMediaSettings" id="removable_media_settings" />
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- App Settings Page -->
|
||||
<child>
|
||||
<object class="AdwNavigationPage" id="app_settings_page">
|
||||
<property name="title" translatable="yes">App Settings</property>
|
||||
<property name="tag">settings-box</property>
|
||||
<property name="child">
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar"/>
|
||||
</child>
|
||||
|
||||
<property name="content">
|
||||
<object class="AdwPreferencesPage" id="settings_box">
|
||||
<!-- App icon & buttons -->
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">18</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="app_icon_image">
|
||||
<property name="icon-name">org.gnome.Software</property>
|
||||
<property name="pixel-size">96</property>
|
||||
<style>
|
||||
<class name="icon-dropshadow" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel" id="app_name_label">
|
||||
<property name="wrap">True</property>
|
||||
<style>
|
||||
<class name="title" />
|
||||
<class name="title-1" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="halign">center</property>
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<property name="spacing">18</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="launch_button">
|
||||
<property name="label" translatable="yes">_Open</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="can-shrink">True</property>
|
||||
<signal name="clicked" handler="on_launch_button_clicked_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
<style>
|
||||
<class name="pill" />
|
||||
<class name="suggested-action" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="view_details_button">
|
||||
<property name="label" translatable="yes">App _Details</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="can-shrink">True</property>
|
||||
<style>
|
||||
<class name="pill" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup" id="integration_section">
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="search">
|
||||
<property name="title" translatable="yes">_Search</property>
|
||||
<property name="subtitle" translatable="yes">Receive system searches and send results</property>
|
||||
<property name="use-underline">True</property>
|
||||
<signal name="notify::active" handler="search_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="no_search">
|
||||
<property name="title" translatable="yes">_Search</property>
|
||||
<property name="subtitle" translatable="yes">Receive system searches and send results</property>
|
||||
<property name="info" translatable="yes">Disabled</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="notification">
|
||||
<property name="title" translatable="yes">_Notifications</property>
|
||||
<property name="subtitle" translatable="yes">Show system notifications</property>
|
||||
<property name="use-underline">True</property>
|
||||
<signal name="notify::active" handler="notification_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="background">
|
||||
<property name="title" translatable="yes">_Run in Background</property>
|
||||
<property name="subtitle" translatable="yes">Allow activity when the app is closed</property>
|
||||
<property name="use-underline">True</property>
|
||||
<signal name="notify::active" handler="background_cb" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="screenshot">
|
||||
<property name="title" translatable="yes">Scr_eenshots</property>
|
||||
<property name="subtitle" translatable="yes">Take pictures of the screen at any time</property>
|
||||
<property name="use-underline">True</property>
|
||||
<signal name="notify::active" handler="screenshot_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="wallpaper">
|
||||
<property name="title" translatable="yes">Change _Wallpaper</property>
|
||||
<property name="subtitle" translatable="yes">Change the desktop wallpaper.</property>
|
||||
<property name="use-underline">True</property>
|
||||
<signal name="notify::active" handler="wallpaper_cb" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="sound">
|
||||
<property name="title" translatable="yes">So_unds</property>
|
||||
<property name="subtitle" translatable="yes">Reproduce sounds.</property>
|
||||
<property name="use-underline">True</property>
|
||||
<signal name="notify::active" handler="sound_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="no_sound">
|
||||
<property name="title" translatable="yes">So_unds</property>
|
||||
<property name="subtitle" translatable="yes">Reproduce sounds</property>
|
||||
<property name="info" translatable="yes">Disabled</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="shortcuts">
|
||||
<property name="title" translatable="yes">_Inhibit Shortcuts</property>
|
||||
<property name="subtitle" translatable="yes">Block standard keyboard shortcuts</property>
|
||||
<property name="use-underline">True</property>
|
||||
<signal name="notify::active" handler="shortcuts_cb" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="camera">
|
||||
<property name="title" translatable="yes">Camera</property>
|
||||
<property name="subtitle" translatable="yes">Take pictures with the camera</property>
|
||||
<signal name="notify::active" handler="camera_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="no_camera">
|
||||
<property name="title" translatable="yes">C_amera</property>
|
||||
<property name="subtitle" translatable="yes">Take pictures with the camera</property>
|
||||
<property name="info" translatable="yes">Disabled</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="microphone">
|
||||
<property name="title" translatable="yes">_Microphone</property>
|
||||
<property name="subtitle" translatable="yes">Record audio with the microphone</property>
|
||||
<property name="use-underline">True</property>
|
||||
<signal name="notify::active" handler="microphone_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="no_microphone">
|
||||
<property name="title" translatable="yes">_Microphone</property>
|
||||
<property name="subtitle" translatable="yes">Record audio with the microphone</property>
|
||||
<property name="info" translatable="yes">Disabled</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="location">
|
||||
<property name="title" translatable="yes">_Location Services</property>
|
||||
<property name="subtitle" translatable="yes">Access device location data</property>
|
||||
<property name="use-underline">True</property>
|
||||
<signal name="notify::active" handler="location_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="no_location">
|
||||
<property name="title" translatable="yes">_Location Services</property>
|
||||
<property name="subtitle" translatable="yes">Access device location data</property>
|
||||
<property name="info" translatable="yes">Disabled</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup" id="usage_section">
|
||||
<child>
|
||||
<object class="CcInfoRow" id="builtin">
|
||||
<property name="title" translatable="yes">Re_quired Access</property>
|
||||
<property name="subtitle" translatable="yes">System access that is required by the app</property>
|
||||
<property name="has-expander">True</property>
|
||||
<property name="is-link">True</property>
|
||||
<signal name="activated" handler="on_builtin_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="handler_row">
|
||||
<property name="title" translatable="yes">_File &amp; Link Associations</property>
|
||||
<property name="has-expander">True</property>
|
||||
<property name="is-link">True</property>
|
||||
<signal name="activated" handler="on_handler_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="storage">
|
||||
<property name="title" translatable="yes">S_torage</property>
|
||||
<property name="has-expander">1</property>
|
||||
<property name="is-link">1</property>
|
||||
<signal name="activated" handler="on_storage_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
|
||||
<!-- Built-in Permissions dialog -->
|
||||
<object class="AdwWindow" id="builtin_dialog">
|
||||
<property name="title" translatable="yes">Required Access</property>
|
||||
<property name="modal">1</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="hide-on-close">True</property>
|
||||
<property name="default-width">500</property>
|
||||
<property name="default-height">400</property>
|
||||
<property name="width-request">360</property>
|
||||
<property name="height-request">294</property>
|
||||
<child>
|
||||
<object class="GtkShortcutController">
|
||||
<property name="scope">managed</property>
|
||||
<child>
|
||||
<object class="GtkShortcut">
|
||||
<property name="trigger">Escape</property>
|
||||
<property name="action">action(window.close)</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar"/>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="AdwPreferencesPage" id="builtin_page">
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="GtkListBox" id="builtin_list">
|
||||
<property name="selection-mode">none</property>
|
||||
<style>
|
||||
<class name="boxed-list"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<!-- File & Link handlers dialog -->
|
||||
<object class="AdwWindow" id="handler_dialog">
|
||||
<property name="title" translatable="yes">File & Link Associations</property>
|
||||
<property name="modal">1</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="hide-on-close">True</property>
|
||||
<property name="default-width">500</property>
|
||||
<property name="default-height">400</property>
|
||||
<property name="width-request">360</property>
|
||||
<property name="height-request">294</property>
|
||||
<child>
|
||||
<object class="GtkShortcutController">
|
||||
<property name="scope">managed</property>
|
||||
<child>
|
||||
<object class="GtkShortcut">
|
||||
<property name="trigger">Escape</property>
|
||||
<property name="action">action(window.close)</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar"/>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="AdwPreferencesPage" id="handler_page">
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup" id="handler_file_group">
|
||||
<property name="title" translatable="yes">File Types</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup" id="handler_link_group">
|
||||
<property name="title" translatable="yes">Link Types</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="GtkButton" id="handler_reset">
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-top">12</property>
|
||||
<property name="label" translatable="yes">_Reset</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="halign">center</property>
|
||||
<signal name="clicked" handler="handler_reset_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
<style>
|
||||
<class name="destructive-action" />
|
||||
<class name="pill" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<!-- Storage dialog -->
|
||||
<object class="AdwWindow" id="storage_dialog">
|
||||
<property name="title" translatable="yes">Storage</property>
|
||||
<property name="modal">1</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="hide-on-close">True</property>
|
||||
<property name="default-width">420</property>
|
||||
<property name="width-request">360</property>
|
||||
<property name="height-request">294</property>
|
||||
<child>
|
||||
<object class="GtkShortcutController">
|
||||
<property name="scope">managed</property>
|
||||
<child>
|
||||
<object class="GtkShortcut">
|
||||
<property name="trigger">Escape</property>
|
||||
<property name="action">action(window.close)</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar"/>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="AdwPreferencesPage">
|
||||
<property name="description" translatable="yes">How much disk space this app is occupying with app data and caches.</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="CcInfoRow" id="app">
|
||||
<property name="title" translatable="yes">App</property>
|
||||
<property name="info">Unknown</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="data">
|
||||
<property name="title" translatable="yes">Data</property>
|
||||
<property name="info">Unknown</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="cache">
|
||||
<property name="title" translatable="yes">Cache</property>
|
||||
<property name="info">Unknown</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="total">
|
||||
<property name="title" translatable="yes"><b>Total</b></property>
|
||||
<property name="info">Unknown</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="GtkButton" id="clear_cache_button">
|
||||
<property name="label" translatable="yes">_Clear Cache</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="halign">center</property>
|
||||
<signal name="clicked" handler="clear_cache_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
<style>
|
||||
<class name="pill" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object class="GtkSizeGroup">
|
||||
<property name="mode">horizontal</property>
|
||||
<widgets>
|
||||
<widget name="launch_button" />
|
||||
<widget name="view_details_button" />
|
||||
</widgets>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -1,95 +0,0 @@
|
||||
/* cc-applications-row.c
|
||||
*
|
||||
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "cc-applications-row.h"
|
||||
#include "cc-applications-resources.h"
|
||||
|
||||
struct _CcApplicationsRow
|
||||
{
|
||||
AdwActionRow parent;
|
||||
|
||||
GAppInfo *info;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcApplicationsRow, cc_applications_row, ADW_TYPE_ACTION_ROW)
|
||||
|
||||
static void
|
||||
cc_applications_row_finalize (GObject *object)
|
||||
{
|
||||
CcApplicationsRow *self = CC_APPLICATIONS_ROW (object);
|
||||
|
||||
g_object_unref (self->info);
|
||||
|
||||
G_OBJECT_CLASS (cc_applications_row_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_applications_row_class_init (CcApplicationsRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = cc_applications_row_finalize;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-applications-row.ui");
|
||||
}
|
||||
|
||||
static void
|
||||
cc_applications_row_init (CcApplicationsRow *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
CcApplicationsRow *
|
||||
cc_applications_row_new (GAppInfo *info)
|
||||
{
|
||||
CcApplicationsRow *self;
|
||||
g_autoptr(GIcon) icon = NULL;
|
||||
GtkWidget *w;
|
||||
|
||||
self = g_object_new (CC_TYPE_APPLICATIONS_ROW, NULL);
|
||||
|
||||
self->info = g_object_ref (info);
|
||||
|
||||
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (self), TRUE);
|
||||
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self),
|
||||
g_markup_escape_text (g_app_info_get_display_name (info), -1));
|
||||
|
||||
icon = g_app_info_get_icon (info);
|
||||
if (icon != NULL)
|
||||
g_object_ref (icon);
|
||||
else
|
||||
icon = g_themed_icon_new ("application-x-executable");
|
||||
w = gtk_image_new_from_gicon (icon);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (w), "lowres-icon");
|
||||
gtk_image_set_icon_size (GTK_IMAGE (w), GTK_ICON_SIZE_LARGE);
|
||||
adw_action_row_add_prefix (ADW_ACTION_ROW (self), w);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
GAppInfo *
|
||||
cc_applications_row_get_info (CcApplicationsRow *self)
|
||||
{
|
||||
return self->info;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/* cc-applications-row.h
|
||||
*
|
||||
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <adwaita.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_APPLICATIONS_ROW (cc_applications_row_get_type())
|
||||
G_DECLARE_FINAL_TYPE (CcApplicationsRow, cc_applications_row, CC, APPLICATIONS_ROW, AdwActionRow)
|
||||
|
||||
CcApplicationsRow* cc_applications_row_new (GAppInfo *info);
|
||||
|
||||
GAppInfo* cc_applications_row_get_info (CcApplicationsRow *row);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcApplicationsRow" parent="AdwActionRow">
|
||||
|
||||
<child type="suffix">
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">go-next-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</template>
|
||||
</interface>
|
||||
@@ -1,130 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.org>
|
||||
* Copyright (C) 2010 Red Hat, Inc
|
||||
* Copyright (C) 2008 William Jon McCann <jmccann@redhat.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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#ifdef BUILD_WWAN
|
||||
#include <libmm-glib.h>
|
||||
#endif
|
||||
|
||||
#include "cc-default-apps-page.h"
|
||||
#include "cc-default-apps-row.h"
|
||||
|
||||
#include "shell/cc-object-storage.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *content_type;
|
||||
/* Patterns used to filter supported mime types
|
||||
when changing preferred applications. NULL
|
||||
means no other types should be changed */
|
||||
const char *extra_type_filter;
|
||||
} DefaultAppData;
|
||||
|
||||
struct _CcDefaultAppsPage
|
||||
{
|
||||
AdwPreferencesGroup parent;
|
||||
|
||||
GtkWidget *web_row;
|
||||
GtkWidget *mail_row;
|
||||
GtkWidget *calendar_row;
|
||||
GtkWidget *music_row;
|
||||
GtkWidget *video_row;
|
||||
GtkWidget *photos_row;
|
||||
GtkWidget *calls_row;
|
||||
GtkWidget *sms_row;
|
||||
|
||||
#ifdef BUILD_WWAN
|
||||
MMManager *mm_manager;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
G_DEFINE_TYPE (CcDefaultAppsPage, cc_default_apps_page, ADW_TYPE_PREFERENCES_GROUP)
|
||||
|
||||
#ifdef BUILD_WWAN
|
||||
static void
|
||||
update_modem_apps_visibility (CcDefaultAppsPage *self)
|
||||
{
|
||||
GList *devices;
|
||||
gboolean has_mm_objects;
|
||||
|
||||
devices = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self->mm_manager));
|
||||
has_mm_objects = g_list_length (devices) > 0;
|
||||
|
||||
gtk_widget_set_visible (self->calls_row, has_mm_objects);
|
||||
gtk_widget_set_visible (self->sms_row, has_mm_objects);
|
||||
|
||||
g_list_free_full (devices, (GDestroyNotify)g_object_unref);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
on_row_selected_item_changed (CcDefaultAppsRow *row)
|
||||
{
|
||||
cc_default_apps_row_update_default_app (row);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_default_apps_page_class_init (CcDefaultAppsPageClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-default-apps-page.ui");
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPage, web_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPage, mail_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPage, calendar_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPage, music_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPage, video_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPage, photos_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPage, calls_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPage, sms_row);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_row_selected_item_changed);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_default_apps_page_init (CcDefaultAppsPage *self)
|
||||
{
|
||||
g_type_ensure (CC_TYPE_DEFAULT_APPS_ROW);
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
#ifdef BUILD_WWAN
|
||||
if (cc_object_storage_has_object ("CcObjectStorage::mm-manager"))
|
||||
{
|
||||
self->mm_manager = cc_object_storage_get_object ("CcObjectStorage::mm-manager");
|
||||
|
||||
g_signal_connect_swapped (self->mm_manager, "object-added",
|
||||
G_CALLBACK (update_modem_apps_visibility), self);
|
||||
g_signal_connect_swapped (self->mm_manager, "object-removed",
|
||||
G_CALLBACK (update_modem_apps_visibility), self);
|
||||
|
||||
update_modem_apps_visibility (self);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CcDefaultAppsPage *
|
||||
cc_default_apps_page_new (void)
|
||||
{
|
||||
return g_object_new (CC_TYPE_DEFAULT_APPS_PAGE,
|
||||
NULL);
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcDefaultAppsPage" parent="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Links &amp; Files</property>
|
||||
<property name="description" translatable="yes">Apps which are used to open common links and files</property>
|
||||
<child>
|
||||
<object class="CcDefaultAppsRow" id="web_row">
|
||||
<property name="title" translatable="yes">_Web</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="content-type">x-scheme-handler/http</property>
|
||||
<property name="filters">text/html;application/xhtml+xml;x-scheme-handler/https</property>
|
||||
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcDefaultAppsRow" id="mail_row">
|
||||
<property name="title" translatable="yes">_Mail</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="content-type">x-scheme-handler/mailto</property>
|
||||
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcDefaultAppsRow" id="calendar_row">
|
||||
<property name="title" translatable="yes">_Calendar</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="content-type">text/calendar</property>
|
||||
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcDefaultAppsRow" id="music_row">
|
||||
<property name="title" translatable="yes">M_usic</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="content-type">audio/x-vorbis+ogg</property>
|
||||
<property name="filters">audio/*</property>
|
||||
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcDefaultAppsRow" id="video_row">
|
||||
<property name="title" translatable="yes">_Video</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="content-type">video/x-ogm+ogg</property>
|
||||
<property name="filters">video/*</property>
|
||||
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcDefaultAppsRow" id="photos_row">
|
||||
<property name="title" translatable="yes">_Photos</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="content-type">image/jpeg</property>
|
||||
<property name="filters">image/*</property>
|
||||
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcDefaultAppsRow" id="calls_row">
|
||||
<property name="visible">False</property>
|
||||
<property name="title" translatable="yes" comments="Translators: This is a telephone call">Ca_lls</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="content-type">x-scheme-handler/tel</property>
|
||||
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcDefaultAppsRow" id="sms_row">
|
||||
<property name="visible">False</property>
|
||||
<property name="title" translatable="yes">_SMS</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="content-type">x-scheme-handler/sms</property>
|
||||
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -1,222 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright 2022 Christopher Davis <christopherdavis@gnome.org>
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "cc-default-apps-row.h"
|
||||
|
||||
struct _CcDefaultAppsRow
|
||||
{
|
||||
AdwComboRow parent_instance;
|
||||
|
||||
char *content_type;
|
||||
char *filters;
|
||||
|
||||
GListStore *model;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE (CcDefaultAppsRow, cc_default_apps_row, ADW_TYPE_COMBO_ROW)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CONTENT_TYPE,
|
||||
PROP_FILTERS,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static char *
|
||||
get_app_display_name (GAppInfo *info)
|
||||
{
|
||||
return g_strdup (g_app_info_get_display_name (info));
|
||||
}
|
||||
|
||||
static void
|
||||
cc_default_apps_row_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcDefaultAppsRow *self = CC_DEFAULT_APPS_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CONTENT_TYPE:
|
||||
g_value_set_string (value, self->content_type);
|
||||
break;
|
||||
case PROP_FILTERS:
|
||||
g_value_set_string (value, self->filters);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_default_apps_row_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcDefaultAppsRow *self = CC_DEFAULT_APPS_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CONTENT_TYPE:
|
||||
self->content_type = g_strdup (g_value_get_string (value));
|
||||
break;
|
||||
case PROP_FILTERS:
|
||||
self->filters = g_strdup (g_value_get_string (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_default_apps_row_constructed (GObject *object)
|
||||
{
|
||||
CcDefaultAppsRow *self;
|
||||
g_autoptr (GAppInfo) default_app, app = NULL;
|
||||
g_autoptr (GList) recommended_apps, l = NULL;
|
||||
GtkExpression *name_expr;
|
||||
|
||||
G_OBJECT_CLASS (cc_default_apps_row_parent_class)->constructed (object);
|
||||
|
||||
self = CC_DEFAULT_APPS_ROW (object);
|
||||
default_app = g_app_info_get_default_for_type (self->content_type, FALSE);
|
||||
recommended_apps = g_app_info_get_recommended_for_type (self->content_type);
|
||||
self->model = g_list_store_new (G_TYPE_APP_INFO);
|
||||
|
||||
/* Add the default separately because it may not be in the list of recommended apps */
|
||||
if (G_IS_APP_INFO (default_app))
|
||||
g_list_store_append (self->model, default_app);
|
||||
|
||||
for (l = recommended_apps; l != NULL; l = l->next) {
|
||||
app = l->data;
|
||||
|
||||
if (!G_IS_APP_INFO (app) || (default_app != NULL && g_app_info_equal (app, default_app)))
|
||||
continue;
|
||||
|
||||
g_list_store_append (self->model, app);
|
||||
}
|
||||
|
||||
adw_combo_row_set_model (ADW_COMBO_ROW (self), G_LIST_MODEL (self->model));
|
||||
|
||||
name_expr = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
|
||||
0, NULL,
|
||||
G_CALLBACK (get_app_display_name),
|
||||
NULL, NULL);
|
||||
adw_combo_row_set_expression (ADW_COMBO_ROW (self), name_expr);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_default_apps_row_class_init (CcDefaultAppsRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = cc_default_apps_row_get_property;
|
||||
object_class->set_property = cc_default_apps_row_set_property;
|
||||
object_class->constructed = cc_default_apps_row_constructed;
|
||||
|
||||
properties[PROP_CONTENT_TYPE] =
|
||||
g_param_spec_string ("content-type",
|
||||
NULL, NULL, NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_FILTERS] =
|
||||
g_param_spec_string ("filters",
|
||||
NULL, NULL, NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_default_apps_row_init (CcDefaultAppsRow *self)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
cc_default_apps_row_update_default_app (CcDefaultAppsRow *self)
|
||||
{
|
||||
g_autoptr(GAppInfo) info = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
int i;
|
||||
|
||||
info = G_APP_INFO (adw_combo_row_get_selected_item (ADW_COMBO_ROW (self)));
|
||||
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
if (g_app_info_set_as_default_for_type (info, self->content_type, &error) == FALSE)
|
||||
{
|
||||
g_warning ("Failed to set '%s' as the default app for '%s': %s",
|
||||
g_app_info_get_name (info), self->content_type, error->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Set '%s' as the default handler for '%s'",
|
||||
g_app_info_get_name (info), self->content_type);
|
||||
}
|
||||
|
||||
if (self->filters)
|
||||
{
|
||||
g_auto(GStrv) entries = NULL;
|
||||
const char *const *mime_types;
|
||||
g_autoptr(GPtrArray) patterns = NULL;
|
||||
|
||||
entries = g_strsplit (self->filters, ";", -1);
|
||||
patterns = g_ptr_array_new_with_free_func ((GDestroyNotify) g_pattern_spec_free);
|
||||
for (i = 0; entries[i] != NULL; i++)
|
||||
{
|
||||
GPatternSpec *pattern = g_pattern_spec_new (entries[i]);
|
||||
g_ptr_array_add (patterns, pattern);
|
||||
}
|
||||
|
||||
mime_types = g_app_info_get_supported_types (info);
|
||||
for (i = 0; mime_types && mime_types[i]; i++)
|
||||
{
|
||||
int j;
|
||||
gboolean matched = FALSE;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
|
||||
for (j = 0; j < patterns->len; j++)
|
||||
{
|
||||
GPatternSpec *pattern = g_ptr_array_index (patterns, j);
|
||||
if (g_pattern_spec_match_string (pattern, mime_types[i]))
|
||||
matched = TRUE;
|
||||
}
|
||||
if (!matched)
|
||||
continue;
|
||||
|
||||
if (g_app_info_set_as_default_for_type (info, mime_types[i], &local_error) == FALSE)
|
||||
{
|
||||
g_warning ("Failed to set '%s' as the default app for secondary "
|
||||
"content type '%s': %s",
|
||||
g_app_info_get_name (info), mime_types[i], local_error->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Set '%s' as the default handler for '%s'",
|
||||
g_app_info_get_name (info), mime_types[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright 2022 Christopher Davis <christopherdavis@gnome.org>
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <adwaita.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_DEFAULT_APPS_ROW (cc_default_apps_row_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (CcDefaultAppsRow, cc_default_apps_row, CC, DEFAULT_APPS_ROW, AdwComboRow)
|
||||
|
||||
void cc_default_apps_row_update_default_app (CcDefaultAppsRow *self);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,187 +0,0 @@
|
||||
/* cc-info-row.c
|
||||
*
|
||||
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "cc-info-row.h"
|
||||
#include "cc-applications-resources.h"
|
||||
|
||||
struct _CcInfoRow
|
||||
{
|
||||
AdwActionRow parent;
|
||||
|
||||
GtkWidget *info;
|
||||
GtkWidget *expander;
|
||||
|
||||
gboolean expanded;
|
||||
gboolean link;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcInfoRow, cc_info_row, ADW_TYPE_ACTION_ROW)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_INFO,
|
||||
PROP_HAS_EXPANDER,
|
||||
PROP_IS_LINK,
|
||||
PROP_EXPANDED
|
||||
};
|
||||
|
||||
static void
|
||||
cc_info_row_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcInfoRow *row = CC_INFO_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_INFO:
|
||||
g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->info)));
|
||||
break;
|
||||
case PROP_HAS_EXPANDER:
|
||||
g_value_set_boolean (value, gtk_widget_get_visible (row->expander));
|
||||
break;
|
||||
case PROP_IS_LINK:
|
||||
g_value_set_boolean (value, row->link);
|
||||
break;
|
||||
case PROP_EXPANDED:
|
||||
g_value_set_boolean (value, cc_info_row_get_expanded (row));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_expander (CcInfoRow *row)
|
||||
{
|
||||
if (row->link)
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "go-next-symbolic");
|
||||
else if (row->expanded)
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "pan-down-symbolic");
|
||||
else
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "pan-end-symbolic");
|
||||
}
|
||||
|
||||
static void
|
||||
cc_info_row_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcInfoRow *row = CC_INFO_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_INFO:
|
||||
gtk_label_set_label (GTK_LABEL (row->info), g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_HAS_EXPANDER:
|
||||
gtk_widget_set_visible (row->expander, g_value_get_boolean (value));
|
||||
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_IS_LINK:
|
||||
row->link = g_value_get_boolean (value);
|
||||
update_expander (row);
|
||||
break;
|
||||
|
||||
case PROP_EXPANDED:
|
||||
cc_info_row_set_expanded (row, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_info_row_class_init (CcInfoRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->get_property = cc_info_row_get_property;
|
||||
object_class->set_property = cc_info_row_set_property;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-info-row.ui");
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_INFO,
|
||||
g_param_spec_string ("info", "info", "info",
|
||||
NULL, G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_HAS_EXPANDER,
|
||||
g_param_spec_boolean ("has-expander", "has-expander", "has-expander",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_EXPANDED,
|
||||
g_param_spec_boolean ("expanded", "expanded", "expanded",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_IS_LINK,
|
||||
g_param_spec_boolean ("is-link", "is-link", "is-link",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcInfoRow, info);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcInfoRow, expander);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_info_row_init (CcInfoRow *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
CcInfoRow *
|
||||
cc_info_row_new (void)
|
||||
{
|
||||
return CC_INFO_ROW (g_object_new (CC_TYPE_INFO_ROW, NULL));
|
||||
}
|
||||
|
||||
gboolean
|
||||
cc_info_row_get_expanded (CcInfoRow *row)
|
||||
{
|
||||
return row->expanded;
|
||||
}
|
||||
|
||||
void
|
||||
cc_info_row_set_expanded (CcInfoRow *row,
|
||||
gboolean expanded)
|
||||
{
|
||||
if (row->expanded == expanded)
|
||||
return;
|
||||
|
||||
row->expanded = expanded;
|
||||
update_expander (row);
|
||||
|
||||
g_object_notify (G_OBJECT (row), "expanded");
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/* cc-info-row.h
|
||||
*
|
||||
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <adwaita.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_INFO_ROW (cc_info_row_get_type())
|
||||
G_DECLARE_FINAL_TYPE (CcInfoRow, cc_info_row, CC, INFO_ROW, AdwActionRow)
|
||||
|
||||
CcInfoRow* cc_info_row_new (void);
|
||||
|
||||
void cc_info_row_set_expanded (CcInfoRow *row,
|
||||
gboolean expanded);
|
||||
|
||||
gboolean cc_info_row_get_expanded (CcInfoRow *row);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcInfoRow" parent="AdwActionRow">
|
||||
<property name="use-underline">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="info">
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="expander">
|
||||
<property name="visible">False</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="icon-name">pan-end-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -1,588 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.org>
|
||||
* Copyright (C) 2010 Red Hat, Inc
|
||||
* Copyright (C) 2008 William Jon McCann <jmccann@redhat.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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <shell/cc-panel.h>
|
||||
|
||||
#include "cc-applications-panel.h"
|
||||
#include "cc-removable-media-settings.h"
|
||||
|
||||
/* Autorun options */
|
||||
#define PREF_MEDIA_AUTORUN_NEVER "autorun-never"
|
||||
#define PREF_MEDIA_AUTORUN_X_CONTENT_START_APP "autorun-x-content-start-app"
|
||||
#define PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE "autorun-x-content-ignore"
|
||||
#define PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER "autorun-x-content-open-folder"
|
||||
|
||||
#define CUSTOM_ITEM_ASK "cc-item-ask"
|
||||
#define CUSTOM_ITEM_DO_NOTHING "cc-item-do-nothing"
|
||||
#define CUSTOM_ITEM_OPEN_FOLDER "cc-item-open-folder"
|
||||
|
||||
#define MEDIA_HANDLING_SCHEMA "org.gnome.desktop.media-handling"
|
||||
|
||||
struct _CcRemovableMediaSettings
|
||||
{
|
||||
AdwPreferencesGroup parent;
|
||||
|
||||
GtkWidget *cd_audio_row;
|
||||
GtkWidget *dvd_video_row;
|
||||
GtkWidget *music_player_row;
|
||||
GtkWidget *photos_row;
|
||||
GtkWidget *software_row;
|
||||
GtkWidget *other_media_row;
|
||||
|
||||
GtkSwitch *autorun_never_switch;
|
||||
|
||||
GtkAppChooserButton *audio_cdda_chooser;
|
||||
GtkAppChooserButton *dcf_chooser;
|
||||
GtkAppChooserButton *music_player_chooser;
|
||||
GtkDialog *other_type_dialog;
|
||||
GtkLabel *other_action_label;
|
||||
GtkBox *other_action_box;
|
||||
GtkComboBox *other_type_combo_box;
|
||||
GtkListStore *other_type_list_store;
|
||||
GtkAppChooserButton *software_chooser;
|
||||
GtkAppChooserButton *video_dvd_chooser;
|
||||
|
||||
GtkAppChooserButton *other_application_chooser;
|
||||
GSettings *settings;
|
||||
};
|
||||
|
||||
|
||||
G_DEFINE_TYPE (CcRemovableMediaSettings, cc_removable_media_settings, ADW_TYPE_PREFERENCES_GROUP)
|
||||
|
||||
static char **
|
||||
remove_elem_from_str_array (char **v,
|
||||
const char *s)
|
||||
{
|
||||
GPtrArray *array;
|
||||
guint idx;
|
||||
|
||||
array = g_ptr_array_new ();
|
||||
|
||||
for (idx = 0; v[idx] != NULL; idx++) {
|
||||
if (g_strcmp0 (v[idx], s) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
g_ptr_array_add (array, v[idx]);
|
||||
}
|
||||
|
||||
g_ptr_array_add (array, NULL);
|
||||
|
||||
g_free (v);
|
||||
|
||||
return (char **) g_ptr_array_free (array, FALSE);
|
||||
}
|
||||
|
||||
static char **
|
||||
add_elem_to_str_array (char **v,
|
||||
const char *s)
|
||||
{
|
||||
GPtrArray *array;
|
||||
guint idx;
|
||||
|
||||
array = g_ptr_array_new ();
|
||||
|
||||
for (idx = 0; v[idx] != NULL; idx++) {
|
||||
g_ptr_array_add (array, v[idx]);
|
||||
}
|
||||
|
||||
g_ptr_array_add (array, g_strdup (s));
|
||||
g_ptr_array_add (array, NULL);
|
||||
|
||||
g_free (v);
|
||||
|
||||
return (char **) g_ptr_array_free (array, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
autorun_get_preferences (CcRemovableMediaSettings *self,
|
||||
const char *x_content_type,
|
||||
gboolean *pref_start_app,
|
||||
gboolean *pref_ignore,
|
||||
gboolean *pref_open_folder)
|
||||
{
|
||||
g_auto(GStrv) x_content_start_app = NULL;
|
||||
g_auto(GStrv) x_content_ignore = NULL;
|
||||
g_auto(GStrv) x_content_open_folder = NULL;
|
||||
|
||||
g_return_if_fail (pref_start_app != NULL);
|
||||
g_return_if_fail (pref_ignore != NULL);
|
||||
g_return_if_fail (pref_open_folder != NULL);
|
||||
|
||||
*pref_start_app = FALSE;
|
||||
*pref_ignore = FALSE;
|
||||
*pref_open_folder = FALSE;
|
||||
x_content_start_app = g_settings_get_strv (self->settings,
|
||||
PREF_MEDIA_AUTORUN_X_CONTENT_START_APP);
|
||||
x_content_ignore = g_settings_get_strv (self->settings,
|
||||
PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE);
|
||||
x_content_open_folder = g_settings_get_strv (self->settings,
|
||||
PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER);
|
||||
if (x_content_start_app != NULL) {
|
||||
*pref_start_app = g_strv_contains ((const gchar * const *) x_content_start_app, x_content_type);
|
||||
}
|
||||
if (x_content_ignore != NULL) {
|
||||
*pref_ignore = g_strv_contains ((const gchar * const *) x_content_ignore, x_content_type);
|
||||
}
|
||||
if (x_content_open_folder != NULL) {
|
||||
*pref_open_folder = g_strv_contains ((const gchar * const *) x_content_open_folder, x_content_type);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
autorun_set_preferences (CcRemovableMediaSettings *self,
|
||||
const char *x_content_type,
|
||||
gboolean pref_start_app,
|
||||
gboolean pref_ignore,
|
||||
gboolean pref_open_folder)
|
||||
{
|
||||
g_auto(GStrv) x_content_start_app = NULL;
|
||||
g_auto(GStrv) x_content_ignore = NULL;
|
||||
g_auto(GStrv) x_content_open_folder = NULL;
|
||||
|
||||
g_assert (x_content_type != NULL);
|
||||
|
||||
x_content_start_app = g_settings_get_strv (self->settings,
|
||||
PREF_MEDIA_AUTORUN_X_CONTENT_START_APP);
|
||||
x_content_ignore = g_settings_get_strv (self->settings,
|
||||
PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE);
|
||||
x_content_open_folder = g_settings_get_strv (self->settings,
|
||||
PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER);
|
||||
|
||||
x_content_start_app = remove_elem_from_str_array (x_content_start_app, x_content_type);
|
||||
if (pref_start_app) {
|
||||
x_content_start_app = add_elem_to_str_array (x_content_start_app, x_content_type);
|
||||
}
|
||||
g_settings_set_strv (self->settings,
|
||||
PREF_MEDIA_AUTORUN_X_CONTENT_START_APP, (const gchar * const*) x_content_start_app);
|
||||
|
||||
x_content_ignore = remove_elem_from_str_array (x_content_ignore, x_content_type);
|
||||
if (pref_ignore) {
|
||||
x_content_ignore = add_elem_to_str_array (x_content_ignore, x_content_type);
|
||||
}
|
||||
g_settings_set_strv (self->settings,
|
||||
PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE, (const gchar * const*) x_content_ignore);
|
||||
|
||||
x_content_open_folder = remove_elem_from_str_array (x_content_open_folder, x_content_type);
|
||||
if (pref_open_folder) {
|
||||
x_content_open_folder = add_elem_to_str_array (x_content_open_folder, x_content_type);
|
||||
}
|
||||
g_settings_set_strv (self->settings,
|
||||
PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER, (const gchar * const*) x_content_open_folder);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_custom_item_activated_cb (CcRemovableMediaSettings *self,
|
||||
const gchar *item,
|
||||
GtkAppChooser *app_chooser)
|
||||
{
|
||||
g_autofree gchar *content_type = NULL;
|
||||
|
||||
content_type = gtk_app_chooser_get_content_type (app_chooser);
|
||||
|
||||
if (g_strcmp0 (item, CUSTOM_ITEM_ASK) == 0) {
|
||||
autorun_set_preferences (self, content_type,
|
||||
FALSE, FALSE, FALSE);
|
||||
} else if (g_strcmp0 (item, CUSTOM_ITEM_OPEN_FOLDER) == 0) {
|
||||
autorun_set_preferences (self, content_type,
|
||||
FALSE, FALSE, TRUE);
|
||||
} else if (g_strcmp0 (item, CUSTOM_ITEM_DO_NOTHING) == 0) {
|
||||
autorun_set_preferences (self, content_type,
|
||||
FALSE, TRUE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_chooser_changed_cb (CcRemovableMediaSettings *self,
|
||||
GtkAppChooser *chooser)
|
||||
{
|
||||
g_autoptr(GAppInfo) info = NULL;
|
||||
g_autofree gchar *content_type = NULL;
|
||||
|
||||
info = gtk_app_chooser_get_app_info (chooser);
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
content_type = gtk_app_chooser_get_content_type (chooser);
|
||||
autorun_set_preferences (self, content_type,
|
||||
TRUE, FALSE, FALSE);
|
||||
g_app_info_set_as_default_for_type (info, content_type, NULL);
|
||||
}
|
||||
|
||||
/* FIXME: Port away from GtkAppChooserButton entirely */
|
||||
static void
|
||||
ellipsize_app_chooser (GtkAppChooserButton *button)
|
||||
{
|
||||
GtkWidget *child;
|
||||
g_autoptr (GList) cells = NULL;
|
||||
GtkCellRenderer *renderer;
|
||||
|
||||
g_assert (GTK_IS_APP_CHOOSER_BUTTON (button));
|
||||
|
||||
child = gtk_widget_get_first_child (GTK_WIDGET (button));
|
||||
|
||||
g_assert (GTK_IS_CELL_LAYOUT (child));
|
||||
|
||||
cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (child));
|
||||
|
||||
g_assert (g_list_length (cells) > 0);
|
||||
|
||||
renderer = g_list_last (cells)->data;
|
||||
|
||||
g_assert (GTK_IS_CELL_RENDERER_TEXT (renderer));
|
||||
|
||||
g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_chooser (CcRemovableMediaSettings *self,
|
||||
GtkAppChooserButton *button,
|
||||
const gchar *heading)
|
||||
{
|
||||
gboolean pref_ask;
|
||||
gboolean pref_start_app;
|
||||
gboolean pref_ignore;
|
||||
gboolean pref_open_folder;
|
||||
g_autoptr(GAppInfo) info = NULL;
|
||||
g_autofree gchar *content_type = NULL;
|
||||
|
||||
content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (button));
|
||||
|
||||
/* fetch preferences for this content type */
|
||||
autorun_get_preferences (self, content_type,
|
||||
&pref_start_app, &pref_ignore, &pref_open_folder);
|
||||
pref_ask = !pref_start_app && !pref_ignore && !pref_open_folder;
|
||||
|
||||
info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (button));
|
||||
|
||||
/* append the separator only if we have >= 1 apps in the chooser */
|
||||
if (info != NULL) {
|
||||
gtk_app_chooser_button_append_separator (button);
|
||||
}
|
||||
|
||||
gtk_app_chooser_button_append_custom_item (button, CUSTOM_ITEM_ASK,
|
||||
_("Ask what to do"),
|
||||
NULL);
|
||||
|
||||
gtk_app_chooser_button_append_custom_item (button, CUSTOM_ITEM_DO_NOTHING,
|
||||
_("Do nothing"),
|
||||
NULL);
|
||||
|
||||
gtk_app_chooser_button_append_custom_item (button, CUSTOM_ITEM_OPEN_FOLDER,
|
||||
_("Open folder"),
|
||||
NULL);
|
||||
|
||||
gtk_app_chooser_button_set_show_dialog_item (button, TRUE);
|
||||
|
||||
if (heading)
|
||||
gtk_app_chooser_button_set_heading (button, _(heading));
|
||||
|
||||
if (pref_ask) {
|
||||
gtk_app_chooser_button_set_active_custom_item (button, CUSTOM_ITEM_ASK);
|
||||
} else if (pref_ignore) {
|
||||
gtk_app_chooser_button_set_active_custom_item (button, CUSTOM_ITEM_DO_NOTHING);
|
||||
} else if (pref_open_folder) {
|
||||
gtk_app_chooser_button_set_active_custom_item (button, CUSTOM_ITEM_OPEN_FOLDER);
|
||||
}
|
||||
|
||||
g_signal_connect_object (button, "changed",
|
||||
G_CALLBACK (on_chooser_changed_cb), self, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (button, "custom-item-activated",
|
||||
G_CALLBACK (on_custom_item_activated_cb), self, G_CONNECT_SWAPPED);
|
||||
|
||||
ellipsize_app_chooser (button);
|
||||
}
|
||||
|
||||
static void
|
||||
on_other_type_combo_box_changed (CcRemovableMediaSettings *self)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
g_autofree gchar *x_content_type = NULL;
|
||||
|
||||
if (!gtk_combo_box_get_active_iter (self->other_type_combo_box, &iter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (self->other_type_list_store), &iter,
|
||||
1, &x_content_type,
|
||||
-1);
|
||||
|
||||
if (self->other_application_chooser != NULL) {
|
||||
gtk_box_remove (self->other_action_box, GTK_WIDGET (self->other_application_chooser));
|
||||
self->other_application_chooser = NULL;
|
||||
}
|
||||
|
||||
self->other_application_chooser = GTK_APP_CHOOSER_BUTTON (gtk_app_chooser_button_new (x_content_type));
|
||||
gtk_box_append (self->other_action_box, GTK_WIDGET (self->other_application_chooser));
|
||||
prepare_chooser (self, self->other_application_chooser, NULL);
|
||||
|
||||
gtk_label_set_mnemonic_widget (self->other_action_label, GTK_WIDGET (self->other_application_chooser));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_extra_options_dialog_close_request (CcRemovableMediaSettings *self)
|
||||
{
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->other_type_dialog), FALSE);
|
||||
|
||||
if (self->other_application_chooser != NULL) {
|
||||
gtk_box_remove (self->other_action_box, GTK_WIDGET (self->other_application_chooser));
|
||||
self->other_application_chooser = NULL;
|
||||
}
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_extra_options_button_clicked (CcRemovableMediaSettings *self)
|
||||
{
|
||||
GtkWidget *app_panel = gtk_widget_get_ancestor(GTK_WIDGET (self), CC_TYPE_APPLICATIONS_PANEL);
|
||||
CcShell *shell = cc_panel_get_shell (CC_PANEL (app_panel));
|
||||
GtkWidget *toplevel = cc_shell_get_toplevel (shell);
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (self->other_type_dialog), GTK_WINDOW (toplevel));
|
||||
gtk_window_set_modal (GTK_WINDOW (self->other_type_dialog), TRUE);
|
||||
gtk_window_set_title (GTK_WINDOW (self->other_type_dialog), _("Other Media"));
|
||||
/* update other_application_chooser */
|
||||
on_other_type_combo_box_changed (self);
|
||||
gtk_window_present (GTK_WINDOW (self->other_type_dialog));
|
||||
}
|
||||
|
||||
#define OFFSET(x) (G_STRUCT_OFFSET (CcRemovableMediaSettings, x))
|
||||
#define WIDGET_FROM_OFFSET(x) (G_STRUCT_MEMBER (GtkWidget*, self, x))
|
||||
|
||||
static void
|
||||
info_panel_setup_media (CcRemovableMediaSettings *self)
|
||||
{
|
||||
guint n;
|
||||
GList *l, *content_types;
|
||||
GtkTreeIter iter;
|
||||
|
||||
struct {
|
||||
gint widget_offset;
|
||||
const gchar *content_type;
|
||||
const gchar *heading;
|
||||
} const defs[] = {
|
||||
{ OFFSET (audio_cdda_chooser), "x-content/audio-cdda", N_("Select an app for audio CDs") },
|
||||
{ OFFSET (video_dvd_chooser), "x-content/video-dvd", N_("Select an app for video DVDs") },
|
||||
{ OFFSET (music_player_chooser), "x-content/audio-player", N_("Select an app to run when a music player is connected") },
|
||||
{ OFFSET (dcf_chooser), "x-content/image-dcf", N_("Select an app to run when a camera is connected") },
|
||||
{ OFFSET (software_chooser), "x-content/unix-software", N_("Select an app for software CDs") },
|
||||
};
|
||||
|
||||
struct {
|
||||
const gchar *content_type;
|
||||
const gchar *description;
|
||||
} const other_defs[] = {
|
||||
/* translators: these strings are duplicates of shared-mime-info
|
||||
* strings, just here to fix capitalization of the English originals.
|
||||
* If the shared-mime-info translation works for your language,
|
||||
* simply leave these untranslated.
|
||||
*/
|
||||
{ "x-content/audio-dvd", N_("audio DVD") },
|
||||
{ "x-content/blank-bd", N_("blank Blu-ray disc") },
|
||||
{ "x-content/blank-cd", N_("blank CD disc") },
|
||||
{ "x-content/blank-dvd", N_("blank DVD disc") },
|
||||
{ "x-content/blank-hddvd", N_("blank HD DVD disc") },
|
||||
{ "x-content/video-bluray", N_("Blu-ray video disc") },
|
||||
{ "x-content/ebook-reader", N_("e-book reader") },
|
||||
{ "x-content/video-hddvd", N_("HD DVD video disc") },
|
||||
{ "x-content/image-picturecd", N_("Picture CD") },
|
||||
{ "x-content/video-svcd", N_("Super Video CD") },
|
||||
{ "x-content/video-vcd", N_("Video CD") },
|
||||
{ "x-content/win32-software", N_("Windows software") },
|
||||
};
|
||||
|
||||
for (n = 0; n < G_N_ELEMENTS (defs); n++) {
|
||||
prepare_chooser (self,
|
||||
GTK_APP_CHOOSER_BUTTON (WIDGET_FROM_OFFSET (defs[n].widget_offset)),
|
||||
defs[n].heading);
|
||||
}
|
||||
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->other_type_list_store),
|
||||
1, GTK_SORT_ASCENDING);
|
||||
|
||||
|
||||
content_types = g_content_types_get_registered ();
|
||||
|
||||
for (l = content_types; l != NULL; l = l->next) {
|
||||
char *content_type = l->data;
|
||||
g_autofree char *description = NULL;
|
||||
|
||||
if (!g_str_has_prefix (content_type, "x-content/"))
|
||||
continue;
|
||||
|
||||
for (n = 0; n < G_N_ELEMENTS (defs); n++) {
|
||||
if (g_content_type_is_a (content_type, defs[n].content_type)) {
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
|
||||
for (n = 0; n < G_N_ELEMENTS (other_defs); n++) {
|
||||
if (strcmp (content_type, other_defs[n].content_type) == 0) {
|
||||
const gchar *s = other_defs[n].description;
|
||||
if (s == _(s))
|
||||
description = g_content_type_get_description (content_type);
|
||||
else
|
||||
description = g_strdup (_(s));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (description == NULL) {
|
||||
g_debug ("Content type '%s' is missing from the info panel", content_type);
|
||||
description = g_content_type_get_description (content_type);
|
||||
}
|
||||
|
||||
gtk_list_store_append (self->other_type_list_store, &iter);
|
||||
|
||||
gtk_list_store_set (self->other_type_list_store, &iter,
|
||||
0, description,
|
||||
1, content_type,
|
||||
-1);
|
||||
skip:
|
||||
;
|
||||
}
|
||||
|
||||
g_list_free_full (content_types, g_free);
|
||||
|
||||
gtk_combo_box_set_active (self->other_type_combo_box, 0);
|
||||
|
||||
g_settings_bind (self->settings,
|
||||
PREF_MEDIA_AUTORUN_NEVER,
|
||||
self->autorun_never_switch,
|
||||
"active",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
g_settings_bind (self->settings,
|
||||
PREF_MEDIA_AUTORUN_NEVER,
|
||||
self->cd_audio_row,
|
||||
"sensitive",
|
||||
G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||||
|
||||
g_settings_bind (self->settings,
|
||||
PREF_MEDIA_AUTORUN_NEVER,
|
||||
self->dvd_video_row,
|
||||
"sensitive",
|
||||
G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||||
|
||||
g_settings_bind (self->settings,
|
||||
PREF_MEDIA_AUTORUN_NEVER,
|
||||
self->music_player_row,
|
||||
"sensitive",
|
||||
G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||||
|
||||
g_settings_bind (self->settings,
|
||||
PREF_MEDIA_AUTORUN_NEVER,
|
||||
self->photos_row,
|
||||
"sensitive",
|
||||
G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||||
|
||||
g_settings_bind (self->settings,
|
||||
PREF_MEDIA_AUTORUN_NEVER,
|
||||
self->software_row,
|
||||
"sensitive",
|
||||
G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||||
|
||||
g_settings_bind (self->settings,
|
||||
PREF_MEDIA_AUTORUN_NEVER,
|
||||
self->other_media_row,
|
||||
"sensitive",
|
||||
G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cc_removable_media_settings_finalize (GObject *object)
|
||||
{
|
||||
CcRemovableMediaSettings *self = CC_REMOVABLE_MEDIA_SETTINGS (object);
|
||||
|
||||
g_clear_object (&self->settings);
|
||||
|
||||
G_OBJECT_CLASS (cc_removable_media_settings_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_removable_media_settings_dispose (GObject *object)
|
||||
{
|
||||
CcRemovableMediaSettings *self = CC_REMOVABLE_MEDIA_SETTINGS (object);
|
||||
|
||||
g_clear_pointer ((GtkWindow **) &self->other_type_dialog, gtk_window_destroy);
|
||||
|
||||
G_OBJECT_CLASS (cc_removable_media_settings_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_removable_media_settings_class_init (CcRemovableMediaSettingsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = cc_removable_media_settings_finalize;
|
||||
object_class->dispose = cc_removable_media_settings_dispose;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-removable-media-settings.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, audio_cdda_chooser);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, autorun_never_switch);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, dcf_chooser);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, music_player_chooser);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, other_type_dialog);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, other_action_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, other_action_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, other_type_combo_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, other_type_list_store);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, software_chooser);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, video_dvd_chooser);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, cd_audio_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, dvd_video_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, music_player_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, photos_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, software_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaSettings, other_media_row);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_extra_options_dialog_close_request);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_extra_options_button_clicked);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_other_type_combo_box_changed);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_removable_media_settings_init (CcRemovableMediaSettings *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
self->settings = g_settings_new (MEDIA_HANDLING_SCHEMA);
|
||||
|
||||
info_panel_setup_media (self);
|
||||
}
|
||||
|
||||
CcRemovableMediaSettings *
|
||||
cc_removable_media_settings_new (void)
|
||||
{
|
||||
return g_object_new (CC_TYPE_REMOVABLE_MEDIA_SETTINGS,
|
||||
NULL);
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.0 -->
|
||||
<template class="CcRemovableMediaSettings" parent="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Removable Media</property>
|
||||
<property name="description" translatable="yes">Apps which are launched when media or drives are connected</property>
|
||||
<child>
|
||||
<object class="AdwActionRow" id="disable_autostart_row">
|
||||
<property name="title" translatable="yes">D_isable Autostart</property>
|
||||
<property name="subtitle" translatable="yes">Never prompt or start apps on media insertion</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable_widget">autorun_never_switch</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="autorun_never_switch">
|
||||
<property name="receives_default">False</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow" id="cd_audio_row">
|
||||
<property name="title" translatable="yes">CD _Audio</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable_widget">audio_cdda_chooser</property>
|
||||
<child>
|
||||
<object class="GtkAppChooserButton" id="audio_cdda_chooser">
|
||||
<property name="valign">center</property>
|
||||
<property name="content_type">x-content/audio-cdda</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow" id="dvd_video_row">
|
||||
<property name="title" translatable="yes">_DVD Video</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable_widget">video_dvd_chooser</property>
|
||||
<child>
|
||||
<object class="GtkAppChooserButton" id="video_dvd_chooser">
|
||||
<property name="valign">center</property>
|
||||
<property name="content_type">x-content/video-dvd</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow" id="music_player_row">
|
||||
<property name="title" translatable="yes">Music Pla_yer</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable_widget">music_player_chooser</property>
|
||||
<child>
|
||||
<object class="GtkAppChooserButton" id="music_player_chooser">
|
||||
<property name="valign">center</property>
|
||||
<property name="content_type">x-content/audio-player</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow" id="photos_row">
|
||||
<property name="title" translatable="yes">P_hotos</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable_widget">dcf_chooser</property>
|
||||
<child>
|
||||
<object class="GtkAppChooserButton" id="dcf_chooser">
|
||||
<property name="valign">center</property>
|
||||
<property name="content_type">x-content/image-dcf</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow" id="software_row">
|
||||
<property name="title" translatable="yes">Sof_tware</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable_widget">software_chooser</property>
|
||||
<child>
|
||||
<object class="GtkAppChooserButton" id="software_chooser">
|
||||
<property name="valign">center</property>
|
||||
<property name="content_type">x-content/unix-software</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcListRow" id="other_media_row">
|
||||
<property name="title" translatable="yes">_Other Media</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="show-arrow">True</property>
|
||||
<property name="subtitle" translatable="yes">Select how other media should be handled</property>
|
||||
<signal name="activated" handler="on_extra_options_button_clicked" object="CcRemovableMediaSettings"/>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
||||
<object class="GtkSizeGroup">
|
||||
<widgets>
|
||||
<widget name="audio_cdda_chooser"/>
|
||||
<widget name="video_dvd_chooser"/>
|
||||
<widget name="music_player_chooser"/>
|
||||
<widget name="dcf_chooser"/>
|
||||
<widget name="software_chooser"/>
|
||||
</widgets>
|
||||
</object>
|
||||
|
||||
<object class="AdwWindow" id="other_type_dialog">
|
||||
<property name="resizable">False</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="hide-on-close">True</property>
|
||||
<signal name="close-request" handler="on_extra_options_dialog_close_request" object="CcRemovableMediaSettings" swapped="yes"/>
|
||||
<child>
|
||||
<object class="GtkShortcutController">
|
||||
<property name="scope">managed</property>
|
||||
<child>
|
||||
<object class="GtkShortcut">
|
||||
<property name="trigger">Escape</property>
|
||||
<property name="action">action(window.close)</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar"/>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="GtkBox">
|
||||
<property name="margin-top">18</property>
|
||||
<property name="margin-bottom">18</property>
|
||||
<property name="margin-start">18</property>
|
||||
<property name="margin-end">18</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">6</property>
|
||||
<property name="margin-start">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="column_spacing">6</property>
|
||||
<property name="row_spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="other_type_combo_box">
|
||||
<property name="model">other_type_list_store</property>
|
||||
<signal name="changed" handler="on_other_type_combo_box_changed" object="CcRemovableMediaSettings" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="other_action_label">
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">_Action:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="other_action_box">
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">_Type:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">other_type_combo_box</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
<object class="GtkListStore" id="other_type_list_store">
|
||||
<columns>
|
||||
<!-- column-name description -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name content-type -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -1,455 +0,0 @@
|
||||
/* cc-snap-row.c
|
||||
*
|
||||
* Copyright 2019 Canonical Ltd.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "cc-snap-row.h"
|
||||
#include "cc-applications-resources.h"
|
||||
#include "cc-snapd-client.h"
|
||||
|
||||
#define CHANGE_POLL_TIME 100
|
||||
|
||||
struct _CcSnapRow
|
||||
{
|
||||
AdwActionRow parent;
|
||||
|
||||
GtkSwitch *slot_toggle;
|
||||
GtkComboBox *slots_combo;
|
||||
GtkListStore *slots_combo_model;
|
||||
|
||||
GCancellable *cancellable;
|
||||
|
||||
CcSnapdClient *client;
|
||||
JsonObject *plug;
|
||||
JsonObject *connected_slot;
|
||||
JsonArray *slots;
|
||||
JsonObject *target_slot;
|
||||
|
||||
gchar *change_id;
|
||||
guint change_timeout;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcSnapRow, cc_snap_row, ADW_TYPE_ACTION_ROW)
|
||||
|
||||
static void
|
||||
update_state (CcSnapRow *self)
|
||||
{
|
||||
gboolean have_single_option;
|
||||
GtkTreeIter iter;
|
||||
|
||||
have_single_option = json_array_get_length (self->slots) == 1;
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->slot_toggle), have_single_option);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->slots_combo), !have_single_option);
|
||||
|
||||
gtk_switch_set_active (self->slot_toggle, self->connected_slot != NULL);
|
||||
|
||||
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->slots_combo_model), &iter))
|
||||
{
|
||||
do
|
||||
{
|
||||
JsonObject *slot;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (self->slots_combo_model), &iter, 0, &slot, -1);
|
||||
if (slot == self->connected_slot)
|
||||
gtk_combo_box_set_active_iter (self->slots_combo, &iter);
|
||||
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->slots_combo_model), &iter));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
disable_controls (CcSnapRow *self)
|
||||
{
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self->slot_toggle), FALSE);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self->slots_combo), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
enable_controls (CcSnapRow *self)
|
||||
{
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self->slot_toggle), TRUE);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self->slots_combo), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
change_complete (CcSnapRow *self)
|
||||
{
|
||||
g_clear_object (&self->client);
|
||||
g_clear_pointer (&self->target_slot, json_object_unref);
|
||||
g_clear_pointer (&self->change_id, g_free);
|
||||
g_clear_handle_id (&self->change_timeout, g_source_remove);
|
||||
|
||||
update_state (self);
|
||||
enable_controls (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
poll_change_cb (gpointer user_data)
|
||||
{
|
||||
CcSnapRow *self = user_data;
|
||||
g_autoptr(JsonObject) change = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
change = cc_snapd_client_get_change_sync (self->client, self->change_id, self->cancellable, &error);
|
||||
if (change == NULL)
|
||||
{
|
||||
g_warning ("Failed to monitor change %s: %s", self->change_id, error->message);
|
||||
change_complete (self);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
if (json_object_get_boolean_member (change, "ready"))
|
||||
{
|
||||
const gchar *status = json_object_get_string_member (change, "status");
|
||||
|
||||
if (g_strcmp0 (status, "Done") == 0)
|
||||
{
|
||||
g_clear_pointer (&self->connected_slot, json_object_unref);
|
||||
self->connected_slot = self->target_slot ? json_object_ref (self->target_slot) : NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Change completed with status %s", status);
|
||||
}
|
||||
|
||||
change_complete (self);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
monitor_change (CcSnapRow *self, const gchar *change_id)
|
||||
{
|
||||
g_free (self->change_id);
|
||||
self->change_id = g_strdup (change_id);
|
||||
g_clear_handle_id (&self->change_timeout, g_source_remove);
|
||||
self->change_timeout = g_timeout_add (CHANGE_POLL_TIME, poll_change_cb, self);
|
||||
}
|
||||
|
||||
static CcSnapdClient *
|
||||
get_client(CcSnapRow *self)
|
||||
{
|
||||
if (self->client == NULL)
|
||||
self->client = cc_snapd_client_new ();
|
||||
return self->client;
|
||||
}
|
||||
|
||||
static void
|
||||
connect_plug (CcSnapRow *self, JsonObject *slot)
|
||||
{
|
||||
g_autofree gchar *change_id = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
/* already connected */
|
||||
if (self->connected_slot != NULL &&
|
||||
g_strcmp0 (json_object_get_string_member (self->connected_slot, "snap"),
|
||||
json_object_get_string_member (slot, "snap")) == 0 &&
|
||||
g_strcmp0 (json_object_get_string_member (self->connected_slot, "slot"),
|
||||
json_object_get_string_member (slot, "slot")) == 0)
|
||||
return;
|
||||
|
||||
disable_controls (self);
|
||||
|
||||
change_id = cc_snapd_client_connect_interface_sync (get_client (self),
|
||||
json_object_get_string_member (self->plug, "snap"),
|
||||
json_object_get_string_member (self->plug, "plug"),
|
||||
json_object_get_string_member (slot, "snap"),
|
||||
json_object_get_string_member (slot, "slot"),
|
||||
self->cancellable,
|
||||
&error);
|
||||
if (change_id == NULL)
|
||||
{
|
||||
g_warning ("Failed to connect plug: %s", error->message);
|
||||
change_complete (self);
|
||||
return;
|
||||
}
|
||||
|
||||
g_clear_pointer (&self->target_slot, json_object_unref);
|
||||
self->target_slot = json_object_ref (slot);
|
||||
monitor_change (self, change_id);
|
||||
}
|
||||
|
||||
static void
|
||||
disconnect_plug (CcSnapRow *self)
|
||||
{
|
||||
g_autofree gchar *change_id = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
/* already disconnected */
|
||||
if (self->connected_slot == NULL)
|
||||
return;
|
||||
|
||||
disable_controls (self);
|
||||
|
||||
change_id = cc_snapd_client_disconnect_interface_sync (get_client (self),
|
||||
json_object_get_string_member (self->plug, "snap"),
|
||||
json_object_get_string_member (self->plug, "plug"),
|
||||
"", "",
|
||||
self->cancellable, &error);
|
||||
if (change_id == NULL)
|
||||
{
|
||||
g_warning ("Failed to disconnect plug: %s", error->message);
|
||||
change_complete (self);
|
||||
return;
|
||||
}
|
||||
|
||||
g_clear_pointer (&self->target_slot, json_object_unref);
|
||||
monitor_change (self, change_id);
|
||||
}
|
||||
|
||||
static void
|
||||
switch_changed_cb (CcSnapRow *self)
|
||||
{
|
||||
if (gtk_switch_get_active (self->slot_toggle))
|
||||
{
|
||||
if (json_array_get_length (self->slots) == 1)
|
||||
connect_plug (self, json_array_get_object_element (self->slots, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect_plug (self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
combo_changed_cb (CcSnapRow *self)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
JsonObject *slot = NULL;
|
||||
|
||||
if (!gtk_combo_box_get_active_iter (self->slots_combo, &iter))
|
||||
return;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (self->slots_combo_model), &iter, 0, &slot, -1);
|
||||
if (slot != NULL)
|
||||
connect_plug (self, slot);
|
||||
else
|
||||
disconnect_plug (self);
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
make_interface_label (const gchar *interface_name)
|
||||
{
|
||||
if (strcmp (interface_name, "account-control") == 0)
|
||||
return _("Add user accounts and change passwords");
|
||||
else if (strcmp (interface_name, "alsa") == 0)
|
||||
return _("Play and record sound");
|
||||
else if (strcmp (interface_name, "audio-playback") == 0)
|
||||
return _("Play audio");
|
||||
else if (strcmp (interface_name, "audio-record") == 0)
|
||||
return _("Record audio");
|
||||
else if (strcmp (interface_name, "avahi-observe") == 0)
|
||||
return _("Detect network devices using mDNS/DNS-SD (Bonjour/zeroconf)");
|
||||
else if (strcmp (interface_name, "bluetooth-control") == 0)
|
||||
return _("Access bluetooth hardware directly");
|
||||
else if (strcmp (interface_name, "bluez") == 0)
|
||||
return _("Use bluetooth devices");
|
||||
else if (strcmp (interface_name, "camera") == 0)
|
||||
return _("Use your camera");
|
||||
else if (strcmp (interface_name, "cups-control") == 0)
|
||||
return _("Print documents");
|
||||
else if (strcmp (interface_name, "joystick") == 0)
|
||||
return _("Use any connected joystick");
|
||||
else if (strcmp (interface_name, "docker") == 0)
|
||||
return _("Allow connecting to the Docker service");
|
||||
else if (strcmp (interface_name, "firewall-control") == 0)
|
||||
return _("Configure network firewall");
|
||||
else if (strcmp (interface_name, "fuse-support") == 0)
|
||||
return _("Setup and use privileged FUSE filesystems");
|
||||
else if (strcmp (interface_name, "fwupd") == 0)
|
||||
return _("Update firmware on this device");
|
||||
else if (strcmp (interface_name, "hardware-observe") == 0)
|
||||
return _("Access hardware information");
|
||||
else if (strcmp (interface_name, "hardware-random-control") == 0)
|
||||
return _("Provide entropy to hardware random number generator");
|
||||
else if (strcmp (interface_name, "hardware-random-observe") == 0)
|
||||
return _("Use hardware-generated random numbers");
|
||||
else if (strcmp (interface_name, "home") == 0)
|
||||
return _("Access files in your home folder");
|
||||
else if (strcmp (interface_name, "libvirt") == 0)
|
||||
return _("Access libvirt service");
|
||||
else if (strcmp (interface_name, "locale-control") == 0)
|
||||
return _("Change system language and region settings");
|
||||
else if (strcmp (interface_name, "location-control") == 0)
|
||||
return _("Change location settings and providers");
|
||||
else if (strcmp (interface_name, "location-observe") == 0)
|
||||
return _("Access your location");
|
||||
else if (strcmp (interface_name, "log-observe") == 0)
|
||||
return _("Read system and application logs");
|
||||
else if (strcmp (interface_name, "lxd") == 0)
|
||||
return _("Access LXD service");
|
||||
else if (strcmp (interface_name, "modem-manager") == 0)
|
||||
return _("Use and configure modems");
|
||||
else if (strcmp (interface_name, "mount-observe") == 0)
|
||||
return _("Read system mount information and disk quotas");
|
||||
else if (strcmp (interface_name, "mpris") == 0)
|
||||
return _("Control music and video players");
|
||||
else if (strcmp (interface_name, "network-control") == 0)
|
||||
return _("Change low-level network settings");
|
||||
else if (strcmp (interface_name, "network-manager") == 0)
|
||||
return _("Access the NetworkManager service to read and change network settings");
|
||||
else if (strcmp (interface_name, "network-observe") == 0)
|
||||
return _("Read access to network settings");
|
||||
else if (strcmp (interface_name, "network-setup-control") == 0)
|
||||
return _("Change network settings");
|
||||
else if (strcmp (interface_name, "network-setup-observe") == 0)
|
||||
return _("Read network settings");
|
||||
else if (strcmp (interface_name, "ofono") == 0)
|
||||
return _("Access the ofono service to read and change network settings for mobile telephony");
|
||||
else if (strcmp (interface_name, "openvswitch") == 0)
|
||||
return _("Control Open vSwitch hardware");
|
||||
else if (strcmp (interface_name, "optical-drive") == 0)
|
||||
return _("Read from CD/DVD");
|
||||
else if (strcmp (interface_name, "password-manager-service") == 0)
|
||||
return _("Read, add, change, or remove saved passwords");
|
||||
else if (strcmp (interface_name, "ppp") == 0)
|
||||
return _("Access pppd and ppp devices for configuring Point-to-Point Protocol connections");
|
||||
else if (strcmp (interface_name, "process-control") == 0)
|
||||
return _("Pause or end any process on the system");
|
||||
else if (strcmp (interface_name, "pulseaudio") == 0)
|
||||
return _("Play and record sound");
|
||||
else if (strcmp (interface_name, "raw-usb") == 0)
|
||||
return _("Access USB hardware directly");
|
||||
else if (strcmp (interface_name, "removable-media") == 0)
|
||||
return _("Read/write files on removable storage devices");
|
||||
else if (strcmp (interface_name, "screen-inhibit-control") == 0)
|
||||
return _("Prevent screen sleep/lock");
|
||||
else if (strcmp (interface_name, "serial-port") == 0)
|
||||
return _("Access serial port hardware");
|
||||
else if (strcmp (interface_name, "shutdown") == 0)
|
||||
return _("Restart or power off the device");
|
||||
else if (strcmp (interface_name, "snapd-control") == 0)
|
||||
return _("Install, remove and configure software");
|
||||
else if (strcmp (interface_name, "storage-framework-service") == 0)
|
||||
return _("Access Storage Framework service");
|
||||
else if (strcmp (interface_name, "system-observe") == 0)
|
||||
return _("Read process and system information");
|
||||
else if (strcmp (interface_name, "system-trace") == 0)
|
||||
return _("Monitor and control any running program");
|
||||
else if (strcmp (interface_name, "time-control") == 0)
|
||||
return _("Change the date and time");
|
||||
else if (strcmp (interface_name, "timeserver-control") == 0)
|
||||
return _("Change time server settings");
|
||||
else if (strcmp (interface_name, "timezone-control") == 0)
|
||||
return _("Change the time zone");
|
||||
else if (strcmp (interface_name, "udisks2") == 0)
|
||||
return _("Access the UDisks2 service for configuring disks and removable media");
|
||||
else if (strcmp (interface_name, "upower-observe") == 0)
|
||||
return _("Access energy usage data");
|
||||
else if (strcmp (interface_name, "u2f-devices") == 0)
|
||||
return _("Read/write access to U2F devices exposed");
|
||||
else
|
||||
return interface_name;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_snap_row_finalize (GObject *object)
|
||||
{
|
||||
CcSnapRow *self = CC_SNAP_ROW (object);
|
||||
|
||||
g_clear_object (&self->cancellable);
|
||||
g_clear_object (&self->client);
|
||||
g_clear_pointer (&self->plug, json_object_unref);
|
||||
g_clear_pointer (&self->slots, json_array_unref);
|
||||
g_clear_pointer (&self->target_slot, json_object_unref);
|
||||
g_clear_pointer (&self->change_id, g_free);
|
||||
g_clear_handle_id (&self->change_timeout, g_source_remove);
|
||||
self->change_timeout = 0;
|
||||
|
||||
G_OBJECT_CLASS (cc_snap_row_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_snap_row_class_init (CcSnapRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = cc_snap_row_finalize;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-snap-row.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcSnapRow, slot_toggle);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcSnapRow, slots_combo);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcSnapRow, slots_combo_model);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, combo_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, switch_changed_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_snap_row_init (CcSnapRow *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
CcSnapRow *
|
||||
cc_snap_row_new (GCancellable *cancellable, JsonObject *plug, JsonArray *slots)
|
||||
{
|
||||
CcSnapRow *self;
|
||||
const gchar *label = NULL;
|
||||
GtkTreeIter iter;
|
||||
|
||||
self = CC_SNAP_ROW (g_object_new (CC_TYPE_SNAP_ROW, NULL));
|
||||
|
||||
self->cancellable = g_object_ref (cancellable);
|
||||
self->plug = json_object_ref (plug);
|
||||
self->slots = json_array_ref (slots);
|
||||
|
||||
if (json_object_has_member (plug, "connections"))
|
||||
{
|
||||
JsonArray *connected_slots = json_object_get_array_member (plug, "connections");
|
||||
JsonObject *connected_slot_ref = json_array_get_object_element (connected_slots, 0);
|
||||
|
||||
for (guint i = 0; i < json_array_get_length (slots); i++)
|
||||
{
|
||||
JsonObject *slot = json_array_get_object_element (slots, i);
|
||||
|
||||
if (g_strcmp0 (json_object_get_string_member (slot, "snap"),
|
||||
json_object_get_string_member (connected_slot_ref, "snap")) == 0 &&
|
||||
g_strcmp0 (json_object_get_string_member (slot, "slot"),
|
||||
json_object_get_string_member (connected_slot_ref, "slot")) == 0)
|
||||
self->connected_slot = slot;
|
||||
}
|
||||
}
|
||||
|
||||
label = make_interface_label (json_object_get_string_member (plug, "interface"));
|
||||
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), label);
|
||||
|
||||
/* Add option into combo box */
|
||||
gtk_list_store_append (self->slots_combo_model, &iter);
|
||||
gtk_list_store_set (self->slots_combo_model, &iter, 1, "--", -1);
|
||||
for (guint i = 0; i < json_array_get_length (slots); i++)
|
||||
{
|
||||
JsonObject *slot = json_array_get_object_element (slots, i);
|
||||
g_autofree gchar *label = NULL;
|
||||
|
||||
label = g_strdup_printf ("%s:%s", json_object_get_string_member (slot, "snap"),
|
||||
json_object_get_string_member (slot, "slot"));
|
||||
gtk_list_store_append (self->slots_combo_model, &iter);
|
||||
gtk_list_store_set (self->slots_combo_model, &iter, 0, slot, 1, label, -1);
|
||||
}
|
||||
|
||||
update_state (self);
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/* cc-snap-row.h
|
||||
*
|
||||
* Copyright 2019 Canonical Ltd.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <adwaita.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_SNAP_ROW (cc_snap_row_get_type())
|
||||
G_DECLARE_FINAL_TYPE (CcSnapRow, cc_snap_row, CC, SNAP_ROW, AdwActionRow)
|
||||
|
||||
CcSnapRow* cc_snap_row_new (GCancellable *cancellable,
|
||||
JsonObject *plug,
|
||||
JsonArray *slots);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkListStore" id="slots_combo_model">
|
||||
<columns>
|
||||
<!-- column-name slot -->
|
||||
<column type="JsonObject"/>
|
||||
<!-- column-name label -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<template class="CcSnapRow" parent="AdwActionRow">
|
||||
<property name="can-focus">True</property>
|
||||
<property name="activatable">False</property>
|
||||
<property name="activatable-widget">slot_toggle</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="slot_toggle">
|
||||
<property name="valign">center</property>
|
||||
<signal name="notify::active" handler="switch_changed_cb" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="slots_combo">
|
||||
<property name="valign">center</property>
|
||||
<property name="model">slots_combo_model</property>
|
||||
<signal name="changed" handler="combo_changed_cb" swapped="yes"/>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="ellipsize">end</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -1,290 +0,0 @@
|
||||
/* cc-snapd-client.c
|
||||
*
|
||||
* Copyright 2023 Canonical Ltd.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <libsoup/soup.h>
|
||||
|
||||
#include "cc-snapd-client.h"
|
||||
|
||||
// Unix socket that snapd communicates on.
|
||||
#define SNAPD_SOCKET_PATH "/var/run/snapd.socket"
|
||||
|
||||
struct _CcSnapdClient
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
// HTTP connection to snapd.
|
||||
SoupSession *session;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcSnapdClient, cc_snapd_client, G_TYPE_OBJECT)
|
||||
|
||||
// Make an HTTP request to send to snapd.
|
||||
static SoupMessage *
|
||||
make_message (const gchar *method, const gchar *path, JsonNode *request_body)
|
||||
{
|
||||
g_autofree gchar *uri = NULL;
|
||||
SoupMessage *msg;
|
||||
SoupMessageHeaders *request_headers;
|
||||
|
||||
uri = g_strdup_printf("http://locahost%s", path);
|
||||
msg = soup_message_new (method, uri);
|
||||
request_headers = soup_message_get_request_headers (msg);
|
||||
// Allow authentication via polkit.
|
||||
soup_message_headers_append (request_headers, "X-Allow-Interaction", "true");
|
||||
if (request_body != NULL)
|
||||
{
|
||||
g_autoptr(JsonGenerator) generator = NULL;
|
||||
g_autofree gchar *body_text = NULL;
|
||||
gsize body_length;
|
||||
g_autoptr(GBytes) body_bytes = NULL;
|
||||
|
||||
generator = json_generator_new ();
|
||||
json_generator_set_root (generator, request_body);
|
||||
body_text = json_generator_to_data (generator, &body_length);
|
||||
body_bytes = g_bytes_new (body_text, body_length);
|
||||
soup_message_set_request_body_from_bytes (msg, "application/json", body_bytes);
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
// Process an HTTP response recveived from snapd.
|
||||
static JsonObject *
|
||||
process_body (SoupMessage *msg, GBytes *body, GError **error)
|
||||
{
|
||||
const gchar *content_type;
|
||||
g_autoptr(JsonParser) parser = NULL;
|
||||
const gchar *body_data;
|
||||
size_t body_length;
|
||||
JsonNode *root;
|
||||
JsonObject *response;
|
||||
gint64 status_code;
|
||||
g_autoptr(GError) internal_error = NULL;
|
||||
|
||||
content_type = soup_message_headers_get_one (soup_message_get_response_headers (msg), "Content-Type");
|
||||
if (g_strcmp0 (content_type, "application/json") != 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid content type %s returned", content_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parser = json_parser_new ();
|
||||
body_data = g_bytes_get_data (body, &body_length);
|
||||
if (!json_parser_load_from_data (parser, body_data, body_length, &internal_error))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Failed to decode JSON content: %s", internal_error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
root = json_parser_get_root (parser);
|
||||
if (!JSON_NODE_HOLDS_OBJECT (root))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Returned JSON not an object");
|
||||
return NULL;
|
||||
}
|
||||
response = json_node_get_object (root);
|
||||
status_code = json_object_get_int_member (response, "status-code");
|
||||
if (status_code != SOUP_STATUS_OK && status_code != SOUP_STATUS_ACCEPTED)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid status code %" G_GINT64_FORMAT, status_code);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return json_object_ref (response);
|
||||
}
|
||||
|
||||
// Send an HTTP request to snapd and process the response.
|
||||
static JsonObject *
|
||||
call_sync (CcSnapdClient *self,
|
||||
const gchar *method, const gchar *path, JsonNode *request_body,
|
||||
GCancellable *cancellable, GError **error)
|
||||
{
|
||||
g_autoptr(SoupMessage) msg = NULL;
|
||||
g_autoptr(GBytes) response_body = NULL;
|
||||
|
||||
msg = make_message (method, path, request_body);
|
||||
response_body = soup_session_send_and_read (self->session, msg, cancellable, error);
|
||||
if (response_body == NULL)
|
||||
return NULL;
|
||||
|
||||
return process_body (msg, response_body, error);
|
||||
}
|
||||
|
||||
// Perform a snap interface action.
|
||||
static gchar *
|
||||
call_interfaces_sync (CcSnapdClient *self,
|
||||
const gchar *action,
|
||||
const gchar *plug_snap, const gchar *plug_name,
|
||||
const gchar *slot_snap, const gchar *slot_name,
|
||||
GCancellable *cancellable, GError **error)
|
||||
{
|
||||
g_autoptr(JsonBuilder) builder = NULL;
|
||||
g_autoptr(JsonObject) response = NULL;
|
||||
const gchar *change_id;
|
||||
|
||||
builder = json_builder_new();
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "action");
|
||||
json_builder_add_string_value (builder, action);
|
||||
json_builder_set_member_name (builder, "plugs");
|
||||
json_builder_begin_array (builder);
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "snap");
|
||||
json_builder_add_string_value (builder, plug_snap);
|
||||
json_builder_set_member_name (builder, "plug");
|
||||
json_builder_add_string_value (builder, plug_name);
|
||||
json_builder_end_object (builder);
|
||||
json_builder_end_array (builder);
|
||||
json_builder_set_member_name (builder, "slots");
|
||||
json_builder_begin_array (builder);
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "snap");
|
||||
json_builder_add_string_value (builder, slot_snap);
|
||||
json_builder_set_member_name (builder, "slot");
|
||||
json_builder_add_string_value (builder, slot_name);
|
||||
json_builder_end_object (builder);
|
||||
json_builder_end_array (builder);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
response = call_sync (self, "POST", "/v2/interfaces",
|
||||
json_builder_get_root (builder), cancellable, error);
|
||||
if (response == NULL)
|
||||
return NULL;
|
||||
|
||||
change_id = json_object_get_string_member (response, "change");
|
||||
|
||||
return g_strdup (change_id);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_snapd_client_dispose (GObject *object)
|
||||
{
|
||||
CcSnapdClient *self = CC_SNAPD_CLIENT (object);
|
||||
|
||||
g_clear_object(&self->session);
|
||||
|
||||
G_OBJECT_CLASS (cc_snapd_client_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_snapd_client_class_init (CcSnapdClientClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = cc_snapd_client_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_snapd_client_init (CcSnapdClient *self)
|
||||
{
|
||||
g_autoptr(GSocketAddress) address = g_unix_socket_address_new (SNAPD_SOCKET_PATH);
|
||||
self->session = soup_session_new_with_options ("remote-connectable", address, NULL);
|
||||
}
|
||||
|
||||
CcSnapdClient *
|
||||
cc_snapd_client_new (void)
|
||||
{
|
||||
return CC_SNAPD_CLIENT (g_object_new (CC_TYPE_SNAPD_CLIENT, NULL));
|
||||
}
|
||||
|
||||
JsonObject *
|
||||
cc_snapd_client_get_snap_sync (CcSnapdClient *self, const gchar *name, GCancellable *cancellable, GError **error)
|
||||
{
|
||||
g_autofree gchar *path = NULL;
|
||||
g_autoptr(JsonObject) response = NULL;
|
||||
JsonObject *result;
|
||||
|
||||
path = g_strdup_printf ("/v2/snaps/%s", name);
|
||||
response = call_sync (self, "GET", path, NULL, cancellable, error);
|
||||
if (response == NULL)
|
||||
return NULL;
|
||||
result = json_object_get_object_member (response, "result");
|
||||
if (result == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid response to %s", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return json_object_ref (result);
|
||||
}
|
||||
|
||||
JsonObject *
|
||||
cc_snapd_client_get_change_sync (CcSnapdClient *self, const gchar *change_id, GCancellable *cancellable, GError **error)
|
||||
{
|
||||
g_autofree gchar *path = NULL;
|
||||
g_autoptr(JsonObject) response = NULL;
|
||||
JsonObject *result;
|
||||
|
||||
path = g_strdup_printf ("/v2/changes/%s", change_id);
|
||||
response = call_sync (self, "GET", path, NULL, cancellable, error);
|
||||
if (response == NULL)
|
||||
return NULL;
|
||||
result = json_object_get_object_member (response, "result");
|
||||
if (result == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid response to %s", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return json_object_ref (result);
|
||||
}
|
||||
|
||||
gboolean
|
||||
cc_snapd_client_get_all_connections_sync (CcSnapdClient *self,
|
||||
JsonArray **plugs, JsonArray **slots,
|
||||
GCancellable *cancellable, GError **error)
|
||||
{
|
||||
g_autoptr(JsonObject) response = NULL;
|
||||
JsonObject *result;
|
||||
|
||||
response = call_sync (self, "GET", "/v2/connections?select=all", NULL, cancellable, error);
|
||||
if (response == NULL)
|
||||
return FALSE;
|
||||
result = json_object_get_object_member (response, "result");
|
||||
if (result == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid response to /v2/connections");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*plugs = json_array_ref (json_object_get_array_member (result, "plugs"));
|
||||
*slots = json_array_ref (json_object_get_array_member (result, "slots"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gchar *
|
||||
cc_snapd_client_connect_interface_sync (CcSnapdClient *self,
|
||||
const gchar *plug_snap, const gchar *plug_name,
|
||||
const gchar *slot_snap, const gchar *slot_name,
|
||||
GCancellable *cancellable, GError **error)
|
||||
{
|
||||
return call_interfaces_sync (self, "connect", plug_snap, plug_name, slot_snap, slot_name, cancellable, error);
|
||||
}
|
||||
|
||||
gchar *
|
||||
cc_snapd_client_disconnect_interface_sync (CcSnapdClient *self,
|
||||
const gchar *plug_snap, const gchar *plug_name,
|
||||
const gchar *slot_snap, const gchar *slot_name,
|
||||
GCancellable *cancellable, GError **error)
|
||||
{
|
||||
return call_interfaces_sync (self, "disconnect", plug_snap, plug_name, slot_snap, slot_name, cancellable, error);
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/* cc-snapd-client.h
|
||||
*
|
||||
* Copyright 2023 Canonical Ltd.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_SNAPD_CLIENT (cc_snapd_client_get_type())
|
||||
G_DECLARE_FINAL_TYPE (CcSnapdClient, cc_snapd_client, CC, SNAPD_CLIENT, GObject)
|
||||
|
||||
// Creates a client to contact snapd.
|
||||
CcSnapdClient *cc_snapd_client_new (void);
|
||||
|
||||
// Get information on an installed snap.
|
||||
JsonObject *cc_snapd_client_get_snap_sync (CcSnapdClient *client,
|
||||
const gchar *name,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
// Get information on a snap change.
|
||||
JsonObject *cc_snapd_client_get_change_sync (CcSnapdClient *client,
|
||||
const gchar *change_id,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
// Get the state of the snap interface connections.
|
||||
gboolean cc_snapd_client_get_all_connections_sync (CcSnapdClient *client,
|
||||
JsonArray **plugs,
|
||||
JsonArray **slots,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
// Connect a plug to a slot. Returns the change ID to monitor for completion of this task.
|
||||
gchar *cc_snapd_client_connect_interface_sync (CcSnapdClient *client,
|
||||
const gchar *plug_snap,
|
||||
const gchar *plug_name,
|
||||
const gchar *slot_snap,
|
||||
const gchar *slot_name,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
// Disconnect a plug to a slot. Returns the change ID to monitor for completion of this task.
|
||||
gchar *cc_snapd_client_disconnect_interface_sync (CcSnapdClient *client,
|
||||
const gchar *plug_snap,
|
||||
const gchar *plug_name,
|
||||
const gchar *slot_snap,
|
||||
const gchar *slot_name,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,62 +0,0 @@
|
||||
/* globs.c
|
||||
*
|
||||
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "globs.h"
|
||||
|
||||
/* parse mime/globs and return a string->string hash table */
|
||||
GHashTable *
|
||||
parse_globs (void)
|
||||
{
|
||||
GHashTable *globs;
|
||||
const gchar * const *dirs;
|
||||
gint i;
|
||||
|
||||
globs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
|
||||
dirs = g_get_system_data_dirs ();
|
||||
|
||||
for (i = 0; dirs[i]; i++)
|
||||
{
|
||||
g_autofree gchar *file = g_build_filename (dirs[i], "mime", "globs", NULL);
|
||||
g_autofree gchar *contents = NULL;
|
||||
|
||||
if (g_file_get_contents (file, &contents, NULL, NULL))
|
||||
{
|
||||
g_auto(GStrv) strv = NULL;
|
||||
int i;
|
||||
|
||||
strv = g_strsplit (contents, "\n", 0);
|
||||
for (i = 0; strv[i]; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = NULL;
|
||||
|
||||
if (strv[i][0] == '#' || strv[i][0] == '\0')
|
||||
continue;
|
||||
|
||||
parts = g_strsplit (strv[i], ":", 2);
|
||||
g_hash_table_insert (globs, g_strdup (parts[0]), g_strdup (parts[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return globs;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/* globs.h
|
||||
*
|
||||
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GHashTable* parse_globs (void);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,15 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Apps
|
||||
Comment=Control various app permissions and settings
|
||||
Exec=gnome-control-center applications
|
||||
# FIXME
|
||||
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
|
||||
Icon=org.gnome.Settings-applications-symbolic
|
||||
Terminal=false
|
||||
Type=Application
|
||||
NoDisplay=true
|
||||
StartupNotify=true
|
||||
Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-AccountSettings;
|
||||
OnlyShowIn=GNOME;Unity;
|
||||
# Translators: Search terms to find the Apps panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
|
||||
Keywords=application;flatpak;permission;setting;default;preferred;media;autorun;cd;dvd;usb;audio;video;disc;removable;device;system;
|
||||
@@ -1,14 +0,0 @@
|
||||
install_data(
|
||||
'scalable/org.gnome.Settings-applications-symbolic.svg',
|
||||
install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
|
||||
)
|
||||
|
||||
install_data(
|
||||
'scalable/org.gnome.Settings-default-apps-symbolic.svg',
|
||||
install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
|
||||
)
|
||||
|
||||
install_data(
|
||||
'scalable/org.gnome.Settings-removable-media-symbolic.svg',
|
||||
install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
|
||||
)
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 2 0 c -1.089844 0 -2 0.910156 -2 2 v 3 c 0 1.089844 0.910156 2 2 2 h 3 c 1.089844 0 2 -0.910156 2 -2 v -3 c 0 -1.089844 -0.910156 -2 -2 -2 z m 8 0 c -1.089844 0 -2 0.910156 -2 2 v 3 c 0 1.089844 0.910156 2 2 2 h 3 c 1.089844 0 2 -0.910156 2 -2 v -3 c 0 -1.089844 -0.910156 -2 -2 -2 z m -8 2 h 3 v 3 h -3 z m 8 0 h 3 v 3 h -3 z m -8 6 c -1.089844 0 -2 0.910156 -2 2 v 3 c 0 1.089844 0.910156 2 2 2 h 3 c 1.089844 0 2 -0.910156 2 -2 v -3 c 0 -1.089844 -0.910156 -2 -2 -2 z m 8 0 c -1.089844 0 -2 0.910156 -2 2 v 3 c 0 1.089844 0.910156 2 2 2 h 3 c 1.089844 0 2 -0.910156 2 -2 v -3 c 0 -1.089844 -0.910156 -2 -2 -2 z m -8 2 h 3 v 3 h -3 z m 8 0 h 3 v 3 h -3 z m 0 0" fill="#2e3436"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 830 B |
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 7.988281 0.0078125 c -0.429687 0 -0.8125 0.2734375 -0.949219 0.6835935 l -1.449218 4.339844 l -4.589844 -0.015625 c -0.9804688 -0.003906 -1.382812 1.257813 -0.582031 1.820313 l 3.625 2.554687 l -1.5 4.285156 c -0.316407 0.902344 0.6875 1.691407 1.492187 1.171875 l 4.003906 -2.59375 l 3.894532 2.585938 c 0.800781 0.53125 1.816406 -0.257813 1.5 -1.160156 l -1.503906 -4.289063 l 3.644531 -2.578125 c 0.789062 -0.5625 0.394531 -1.808594 -0.574219 -1.8125 l -4.660156 -0.015625 l -1.402344 -4.285156 c -0.132812 -0.410157 -0.515625 -0.6875002 -0.949219 -0.6914065 z m 0 0" fill="#2e3436"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 737 B |
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 12 6 v 5 c 0 2.210938 -1.789062 4 -4 4 s -4 -1.789062 -4 -4 v -5 c 0 -0.550781 0.449219 -1 1 -1 h 6 c 0.550781 0 1 0.449219 1 1 z m -7 -5.5 v 3.5 h 6 v -3.5 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 h -5 c -0.277344 0 -0.5 0.222656 -0.5 0.5 z m 1 0.5 h 1 v 1 h -1 z m 3 0 h 1 v 1 h -1 z m 0 0" fill="#474747"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 457 B |
@@ -1,62 +0,0 @@
|
||||
panels_list += cappletname
|
||||
desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
|
||||
|
||||
i18n.merge_file(
|
||||
type : 'desktop',
|
||||
input : desktop + '.in',
|
||||
output : desktop,
|
||||
po_dir : po_dir,
|
||||
install : true,
|
||||
install_dir : control_center_desktopdir
|
||||
)
|
||||
|
||||
sources = files(
|
||||
'cc-applications-panel.c',
|
||||
'cc-applications-row.c',
|
||||
'cc-info-row.c',
|
||||
'cc-default-apps-page.c',
|
||||
'cc-default-apps-row.c',
|
||||
'cc-removable-media-settings.c',
|
||||
'globs.c',
|
||||
'search.c',
|
||||
'utils.c',
|
||||
)
|
||||
|
||||
resource_data = files(
|
||||
'cc-applications-panel.ui',
|
||||
'cc-default-apps-page.ui',
|
||||
'cc-removable-media-settings.ui',
|
||||
)
|
||||
|
||||
sources += gnome.compile_resources(
|
||||
'cc-' + cappletname + '-resources',
|
||||
cappletname + '.gresource.xml',
|
||||
c_name : 'cc_' + cappletname,
|
||||
dependencies: resource_data,
|
||||
export : true
|
||||
)
|
||||
|
||||
deps = common_deps
|
||||
|
||||
if host_is_linux
|
||||
deps += mm_dep
|
||||
endif
|
||||
|
||||
if enable_snap
|
||||
deps += [ json_glib_dep, libsoup_dep ]
|
||||
sources += [ 'cc-snap-row.c', 'cc-snapd-client.c' ]
|
||||
endif
|
||||
|
||||
if enable_malcontent
|
||||
deps += malcontent_dep
|
||||
endif
|
||||
|
||||
panels_libs += static_library(
|
||||
cappletname,
|
||||
sources : sources,
|
||||
include_directories : [ top_inc, common_inc ],
|
||||
dependencies : deps,
|
||||
c_args : cflags
|
||||
)
|
||||
|
||||
subdir('icons')
|
||||
@@ -1,133 +0,0 @@
|
||||
/* search.c
|
||||
*
|
||||
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "search.h"
|
||||
|
||||
|
||||
#define SHELL_PROVIDER_GROUP "Shell Search Provider"
|
||||
|
||||
static void
|
||||
add_one_provider (GHashTable *search_providers,
|
||||
GFile *file)
|
||||
{
|
||||
g_autoptr(GKeyFile) keyfile = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autofree gchar *app_id = NULL;
|
||||
g_autofree gchar *path = NULL;
|
||||
gboolean default_disabled;
|
||||
|
||||
path = g_file_get_path (file);
|
||||
keyfile = g_key_file_new ();
|
||||
g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_warning ("Error loading %s: %s - search provider will be ignored",
|
||||
path, error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_key_file_has_group (keyfile, SHELL_PROVIDER_GROUP))
|
||||
{
|
||||
g_debug ("Shell search provider group missing from '%s', ignoring", path);
|
||||
return;
|
||||
}
|
||||
|
||||
app_id = g_key_file_get_string (keyfile, SHELL_PROVIDER_GROUP, "DesktopId", &error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_warning ("Unable to read desktop ID from %s: %s - search provider will be ignored",
|
||||
path, error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_str_has_suffix (app_id, ".desktop"))
|
||||
app_id[strlen (app_id) - strlen (".desktop")] = '\0';
|
||||
|
||||
default_disabled = g_key_file_get_boolean (keyfile, SHELL_PROVIDER_GROUP, "DefaultDisabled", NULL);
|
||||
|
||||
g_hash_table_insert (search_providers, g_strdup (app_id), GINT_TO_POINTER (default_disabled));
|
||||
}
|
||||
|
||||
static void
|
||||
parse_search_providers_one_dir (GHashTable *search_providers,
|
||||
const gchar *system_dir)
|
||||
{
|
||||
g_autoptr(GFileEnumerator) enumerator = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GFile) providers_location = NULL;
|
||||
g_autofree gchar *providers_path = NULL;
|
||||
|
||||
providers_path = g_build_filename (system_dir, "gnome-shell", "search-providers", NULL);
|
||||
providers_location = g_file_new_for_path (providers_path);
|
||||
|
||||
enumerator = g_file_enumerate_children (providers_location,
|
||||
"standard::type,standard::name,standard::content-type",
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL, &error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
|
||||
!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_warning ("Error opening %s: %s - search provider configuration won't be possible",
|
||||
providers_path, error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GFile *provider = NULL;
|
||||
|
||||
if (!g_file_enumerator_iterate (enumerator, NULL, &provider, NULL, &error))
|
||||
{
|
||||
g_warning ("Error while reading %s: %s - search provider configuration won't be possible",
|
||||
providers_path, error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (provider == NULL)
|
||||
break;
|
||||
|
||||
add_one_provider (search_providers, provider);
|
||||
}
|
||||
}
|
||||
|
||||
/* parse gnome-shell/search-provider files and return a string->boolean hash table */
|
||||
GHashTable *
|
||||
parse_search_providers (void)
|
||||
{
|
||||
GHashTable *search_providers;
|
||||
const gchar * const *dirs;
|
||||
gint i;
|
||||
|
||||
search_providers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
dirs = g_get_system_data_dirs ();
|
||||
|
||||
for (i = 0; dirs[i]; i++)
|
||||
parse_search_providers_one_dir (search_providers, dirs[i]);
|
||||
|
||||
return search_providers;
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/* globs.h
|
||||
*
|
||||
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GHashTable* parse_search_providers (void);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,257 +0,0 @@
|
||||
/* utils.c
|
||||
*
|
||||
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
|
||||
#include <config.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ftw.h>
|
||||
|
||||
#include "utils.h"
|
||||
#ifdef HAVE_SNAP
|
||||
#include "cc-snapd-client.h"
|
||||
#endif
|
||||
|
||||
static gint
|
||||
ftw_remove_cb (const gchar *path,
|
||||
const struct stat *sb,
|
||||
gint typeflags,
|
||||
struct FTW *ftwbuf)
|
||||
{
|
||||
remove (path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
file_remove_thread_func (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GFile *file = source_object;
|
||||
g_autofree gchar *path = g_file_get_path (file);
|
||||
|
||||
nftw (path, ftw_remove_cb, 20, FTW_PHYS | FTW_DEPTH);
|
||||
|
||||
if (g_task_set_return_on_cancel (task, FALSE))
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
file_remove_async (GFile *file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
g_autoptr(GTask) task = g_task_new (file, cancellable, callback, data);
|
||||
g_task_set_return_on_cancel (task, TRUE);
|
||||
g_task_run_in_thread (task, file_remove_thread_func);
|
||||
}
|
||||
|
||||
gboolean
|
||||
file_remove_finish (GFile *file,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, file), FALSE);
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static GPrivate size_key = G_PRIVATE_INIT (g_free);
|
||||
|
||||
static gint
|
||||
ftw_size_cb (const gchar *path,
|
||||
const struct stat *sb,
|
||||
gint typeflags,
|
||||
struct FTW *ftwbuf)
|
||||
{
|
||||
guint64 *size = (guint64*)g_private_get (&size_key);
|
||||
if (typeflags == FTW_F)
|
||||
*size += sb->st_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
file_size_thread_func (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GFile *file = source_object;
|
||||
g_autofree gchar *path = g_file_get_path (file);
|
||||
guint64 *total;
|
||||
|
||||
g_private_replace (&size_key, g_new0 (guint64, 1));
|
||||
|
||||
nftw (path, ftw_size_cb, 20, FTW_DEPTH);
|
||||
|
||||
total = g_new0 (guint64, 1);
|
||||
*total = *(guint64*)g_private_get (&size_key);
|
||||
|
||||
if (g_task_set_return_on_cancel (task, FALSE))
|
||||
g_task_return_pointer (task, total, g_free);
|
||||
}
|
||||
|
||||
void
|
||||
file_size_async (GFile *file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
g_autoptr(GTask) task = g_task_new (file, cancellable, callback, data);
|
||||
g_task_set_return_on_cancel (task, TRUE);
|
||||
g_task_run_in_thread (task, file_size_thread_func);
|
||||
}
|
||||
|
||||
gboolean
|
||||
file_size_finish (GFile *file,
|
||||
GAsyncResult *result,
|
||||
guint64 *size,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree guint64 *data = NULL;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, file), FALSE);
|
||||
data = g_task_propagate_pointer (G_TASK (result), error);
|
||||
if (data == NULL)
|
||||
return FALSE;
|
||||
if (size != NULL)
|
||||
*size = *data;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_output_of (const gchar **argv)
|
||||
{
|
||||
g_autofree gchar *output = NULL;
|
||||
int status;
|
||||
|
||||
if (!g_spawn_sync (NULL,
|
||||
(gchar**) argv,
|
||||
NULL,
|
||||
G_SPAWN_SEARCH_PATH,
|
||||
NULL, NULL,
|
||||
&output, NULL,
|
||||
&status, NULL))
|
||||
return NULL;
|
||||
|
||||
if (!g_spawn_check_wait_status (status, NULL))
|
||||
return NULL;
|
||||
|
||||
return g_steal_pointer (&output);
|
||||
}
|
||||
|
||||
GKeyFile *
|
||||
get_flatpak_metadata (const gchar *app_id)
|
||||
{
|
||||
const gchar *argv[5] = { "flatpak", "info", "-m", "app", NULL };
|
||||
g_autofree gchar *data = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GKeyFile) keyfile = NULL;
|
||||
|
||||
argv[3] = app_id;
|
||||
|
||||
data = get_output_of (argv);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
keyfile = g_key_file_new ();
|
||||
if (!g_key_file_load_from_data (keyfile, data, -1, 0, &error))
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_steal_pointer (&keyfile);
|
||||
}
|
||||
|
||||
guint64
|
||||
get_flatpak_app_size (const gchar *app_id)
|
||||
{
|
||||
const gchar *argv[5] = { "flatpak", "info", "-s", "app", NULL };
|
||||
g_autofree gchar *data = NULL;
|
||||
guint64 factor;
|
||||
double val;
|
||||
|
||||
argv[3] = app_id;
|
||||
|
||||
data = get_output_of (argv);
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
|
||||
data = g_strstrip (data);
|
||||
|
||||
if (g_str_has_suffix (data, "kB") || g_str_has_suffix (data, "kb"))
|
||||
factor = 1000;
|
||||
else if (g_str_has_suffix (data, "MB") || g_str_has_suffix (data, "Mb"))
|
||||
factor = 1000 * 1000;
|
||||
else if (g_str_has_suffix (data, "GB") || g_str_has_suffix (data, "Gb"))
|
||||
factor = 1000 * 1000 * 1000;
|
||||
else if (g_str_has_suffix (data, "KiB") || g_str_has_suffix (data, "Kib"))
|
||||
factor = 1024;
|
||||
else if (g_str_has_suffix (data, "MiB") || g_str_has_suffix (data, "Mib"))
|
||||
factor = 1024 * 1024;
|
||||
else if (g_str_has_suffix (data, "GiB") || g_str_has_suffix (data, "Gib"))
|
||||
factor = 1024 * 1024 * 1024;
|
||||
else
|
||||
factor = 1;
|
||||
|
||||
val = g_ascii_strtod (data, NULL);
|
||||
|
||||
return (guint64)(val * factor);
|
||||
}
|
||||
|
||||
guint64
|
||||
get_snap_app_size (const gchar *snap_name)
|
||||
{
|
||||
#ifdef HAVE_SNAP
|
||||
g_autoptr(CcSnapdClient) client = NULL;
|
||||
g_autoptr(JsonObject) snap = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
client = cc_snapd_client_new ();
|
||||
snap = cc_snapd_client_get_snap_sync (client, snap_name, NULL, &error);
|
||||
if (snap == NULL)
|
||||
{
|
||||
g_warning ("Failed to get snap size: %s", error->message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return json_object_get_int_member (snap, "installed-size");
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
char *
|
||||
get_app_id (GAppInfo *info)
|
||||
{
|
||||
gchar *app_id = g_strdup (g_app_info_get_id (info));
|
||||
|
||||
if (g_str_has_suffix (app_id, ".desktop"))
|
||||
app_id[strlen (app_id) - strlen (".desktop")] = '\0';
|
||||
|
||||
return app_id;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/* utils.h
|
||||
*
|
||||
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void file_remove_async (GFile *file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer data);
|
||||
|
||||
gboolean file_remove_finish (GFile *file,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
void file_size_async (GFile *file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer data);
|
||||
|
||||
gboolean file_size_finish (GFile *file,
|
||||
GAsyncResult *result,
|
||||
guint64 *size,
|
||||
GError **error);
|
||||
|
||||
GKeyFile* get_flatpak_metadata (const gchar *app_id);
|
||||
|
||||
guint64 get_flatpak_app_size (const gchar *app_id);
|
||||
|
||||
guint64 get_snap_app_size (const gchar *snap_name);
|
||||
|
||||
gchar* get_app_id (GAppInfo *info);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 4.233 4.233" xmlns="http://www.w3.org/2000/svg"><path d="M3.843.627a.397.397 0 0 0-.56.034L1.45 2.73l-.775-.763a.397.397 0 0 0-.56.004.397.397 0 0 0 .003.562L1.191 3.59a.397.397 0 0 0 .576-.02l2.11-2.382a.397.397 0 0 0-.034-.56Z" style="fill:#3d3846"/></svg>
|
||||
|
Before Width: | Height: | Size: 299 B |
@@ -1,14 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gnome/control-center/background">
|
||||
<file preprocess="xml-stripblanks">cc-background-chooser.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-background-panel.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-background-preview.ui</file>
|
||||
<file>preview.css</file>
|
||||
</gresource>
|
||||
|
||||
<gresource prefix="/org/gnome/Settings/icons/scalable/actions">
|
||||
<file preprocess="xml-stripblanks">background-selected-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks">slideshow-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks">background.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
300
panels/background/background.ui
Normal file
@@ -0,0 +1,300 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.0 -->
|
||||
<object class="GtkBox" id="background-panel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin">32</property>
|
||||
<property name="spacing">12</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">24</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="background-set-button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin">6</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkDrawingArea" id="background-desktop-drawingarea">
|
||||
<property name="width_request">310</property>
|
||||
<property name="height_request">170</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">_Background</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">background-set-button</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="bottom-hbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="slide_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">slideshow-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="strut">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label"> </property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="slide-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes" comments="This refers to a slideshow background">Changes throughout the day</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="background-lock-set-button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin">6</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkDrawingArea" id="background-lock-drawingarea">
|
||||
<property name="width_request">310</property>
|
||||
<property name="height_request">170</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes" comments="To translators: This is a noun, not a verb">_Lock Screen</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">background-lock-set-button</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="bottom-hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="slide_image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">slideshow-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="strut1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label"> </property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="slide-label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes" comments="This refers to a slideshow background">Changes throughout the day</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkListStore" id="sources-liststore">
|
||||
<columns>
|
||||
<!-- column-name source-name -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name source-id -->
|
||||
<column type="guint"/>
|
||||
<!-- column-name source-pointer -->
|
||||
<column type="gpointer"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkListStore" id="style-liststore">
|
||||
<columns>
|
||||
<!-- column-name name -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name value -->
|
||||
<column type="gint"/>
|
||||
</columns>
|
||||
<data>
|
||||
<row>
|
||||
<col id="0" translatable="yes" context="background, style">Tile</col>
|
||||
<col id="1">1</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes" context="background, style">Zoom</col>
|
||||
<col id="1">5</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes" context="background, style">Center</col>
|
||||
<col id="1">2</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes" context="background, style">Scale</col>
|
||||
<col id="1">3</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes" context="background, style">Fill</col>
|
||||
<col id="1">4</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes" context="background, style">Span</col>
|
||||
<col id="1">6</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="sizegroup">
|
||||
<property name="mode">vertical</property>
|
||||
<widgets>
|
||||
<widget name="slide-label"/>
|
||||
<widget name="strut"/>
|
||||
</widgets>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -71,11 +71,21 @@ get_colors_dir (void)
|
||||
|
||||
static void
|
||||
bg_colors_source_add_color (BgColorsSource *self,
|
||||
GListStore *store,
|
||||
const char *color)
|
||||
GnomeDesktopThumbnailFactory *thumb_factory,
|
||||
GtkListStore *store,
|
||||
const char *color,
|
||||
GtkTreeRowReference **ret_row_ref)
|
||||
{
|
||||
CcBackgroundItemFlags flags;
|
||||
g_autoptr(CcBackgroundItem) item = NULL;
|
||||
g_autoptr(GdkPixbuf) pixbuf = NULL;
|
||||
cairo_surface_t *surface;
|
||||
int scale_factor;
|
||||
int thumbnail_height, thumbnail_width;
|
||||
GtkTreeIter iter;
|
||||
|
||||
thumbnail_height = bg_source_get_thumbnail_height (BG_SOURCE (self));
|
||||
thumbnail_width = bg_source_get_thumbnail_width (BG_SOURCE (self));
|
||||
|
||||
item = cc_background_item_new (NULL);
|
||||
flags = CC_BACKGROUND_ITEM_HAS_PCOLOR |
|
||||
@@ -96,24 +106,47 @@ bg_colors_source_add_color (BgColorsSource *self,
|
||||
cc_background_item_load (item, NULL);
|
||||
|
||||
/* insert the item into the liststore */
|
||||
g_list_store_append (store, item);
|
||||
scale_factor = bg_source_get_scale_factor (BG_SOURCE (self));
|
||||
pixbuf = cc_background_item_get_thumbnail (item,
|
||||
thumb_factory,
|
||||
thumbnail_width, thumbnail_height,
|
||||
scale_factor);
|
||||
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
|
||||
gtk_list_store_insert_with_values (store, &iter, 0,
|
||||
0, surface,
|
||||
1, item,
|
||||
-1);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
if (ret_row_ref)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
|
||||
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
|
||||
*ret_row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bg_colors_source_constructed (GObject *object)
|
||||
{
|
||||
BgColorsSource *self = BG_COLORS_SOURCE (object);
|
||||
g_autoptr(GnomeDesktopThumbnailFactory) thumb_factory = NULL;
|
||||
guint i;
|
||||
GListStore *store;
|
||||
GtkListStore *store;
|
||||
g_autoptr(GKeyFile) keyfile = NULL;
|
||||
g_autofree gchar *path = NULL;
|
||||
|
||||
G_OBJECT_CLASS (bg_colors_source_parent_class)->constructed (object);
|
||||
|
||||
store = bg_source_get_liststore (BG_SOURCE (self));
|
||||
thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (items); i++)
|
||||
bg_colors_source_add_color (self, store, items[i].pcolor);
|
||||
{
|
||||
bg_colors_source_add_color (self, thumb_factory, store, items[i].pcolor, NULL);
|
||||
}
|
||||
|
||||
keyfile = g_key_file_new ();
|
||||
path = get_colors_path ();
|
||||
@@ -123,7 +156,9 @@ bg_colors_source_constructed (GObject *object)
|
||||
|
||||
colors = g_key_file_get_string_list (keyfile, "Colors", "custom-colors", NULL, NULL);
|
||||
for (i = 0; colors != NULL && colors[i] != NULL; i++)
|
||||
bg_colors_source_add_color (self, store, colors[i]);
|
||||
{
|
||||
bg_colors_source_add_color (self, thumb_factory, store, colors[i], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +167,8 @@ bg_colors_source_add (BgColorsSource *self,
|
||||
GdkRGBA *rgba,
|
||||
GtkTreeRowReference **ret_row_ref)
|
||||
{
|
||||
GListStore *store;
|
||||
g_autoptr(GnomeDesktopThumbnailFactory) thumb_factory = NULL;
|
||||
GtkListStore *store;
|
||||
g_autofree gchar *c = NULL;
|
||||
g_auto(GStrv) colors = NULL;
|
||||
gsize len;
|
||||
@@ -146,9 +182,10 @@ bg_colors_source_add (BgColorsSource *self,
|
||||
(int)(255*rgba->green),
|
||||
(int)(255*rgba->blue));
|
||||
|
||||
thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
|
||||
store = bg_source_get_liststore (BG_SOURCE (self));
|
||||
|
||||
bg_colors_source_add_color (self, store, c);
|
||||
bg_colors_source_add_color (self, thumb_factory, store, c, ret_row_ref);
|
||||
|
||||
/* Save to the keyfile */
|
||||
dir = get_colors_dir ();
|
||||
@@ -212,8 +249,8 @@ bg_colors_source_class_init (BgColorsSourceClass *klass)
|
||||
}
|
||||
|
||||
BgColorsSource *
|
||||
bg_colors_source_new (GtkWidget *widget)
|
||||
bg_colors_source_new (GtkWindow *window)
|
||||
{
|
||||
return g_object_new (BG_TYPE_COLORS_SOURCE, "widget", widget, NULL);
|
||||
return g_object_new (BG_TYPE_COLORS_SOURCE, "window", window, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef _BG_COLORS_SOURCE_H
|
||||
#define _BG_COLORS_SOURCE_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "bg-source.h"
|
||||
@@ -29,10 +30,12 @@ G_BEGIN_DECLS
|
||||
#define BG_TYPE_COLORS_SOURCE (bg_colors_source_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (BgColorsSource, bg_colors_source, BG, COLORS_SOURCE, BgSource)
|
||||
|
||||
BgColorsSource *bg_colors_source_new (GtkWidget *widget);
|
||||
BgColorsSource *bg_colors_source_new (GtkWindow *window);
|
||||
|
||||
gboolean bg_colors_source_add (BgColorsSource *self,
|
||||
GdkRGBA *rgba,
|
||||
GtkTreeRowReference **ret_row_ref);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _BG_COLORS_SOURCE_H */
|
||||
|
||||
997
panels/background/bg-pictures-source.c
Normal file
@@ -0,0 +1,997 @@
|
||||
/* bg-pictures-source.c */
|
||||
/*
|
||||
* Copyright (C) 2010 Intel, Inc
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Thomas Wood <thomas.wood@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "bg-pictures-source.h"
|
||||
|
||||
#include "cc-background-grilo-miner.h"
|
||||
#include "cc-background-item.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <cairo-gobject.h>
|
||||
#include <gio/gio.h>
|
||||
#include <grilo.h>
|
||||
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
|
||||
#include <gdesktop-enums.h>
|
||||
|
||||
#define ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_NAME "," \
|
||||
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED
|
||||
|
||||
struct _BgPicturesSource
|
||||
{
|
||||
BgSource parent_instance;
|
||||
|
||||
GCancellable *cancellable;
|
||||
|
||||
CcBackgroundGriloMiner *grl_miner;
|
||||
|
||||
GnomeDesktopThumbnailFactory *thumb_factory;
|
||||
|
||||
GFileMonitor *picture_dir_monitor;
|
||||
GFileMonitor *cache_dir_monitor;
|
||||
|
||||
GHashTable *known_items;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (BgPicturesSource, bg_pictures_source, BG_TYPE_SOURCE)
|
||||
|
||||
const char * const content_types[] = {
|
||||
"image/png",
|
||||
"image/jp2",
|
||||
"image/jpeg",
|
||||
"image/bmp",
|
||||
"image/svg+xml",
|
||||
"image/x-portable-anymap",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char * const screenshot_types[] = {
|
||||
"image/png",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *bg_pictures_source_get_unique_filename (const char *uri);
|
||||
|
||||
static void picture_opened_for_read (GObject *source_object, GAsyncResult *res, gpointer user_data);
|
||||
|
||||
static void
|
||||
bg_pictures_source_dispose (GObject *object)
|
||||
{
|
||||
BgPicturesSource *source = BG_PICTURES_SOURCE (object);
|
||||
|
||||
if (source->cancellable)
|
||||
{
|
||||
g_cancellable_cancel (source->cancellable);
|
||||
g_clear_object (&source->cancellable);
|
||||
}
|
||||
|
||||
g_clear_object (&source->grl_miner);
|
||||
g_clear_object (&source->thumb_factory);
|
||||
|
||||
G_OBJECT_CLASS (bg_pictures_source_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
bg_pictures_source_finalize (GObject *object)
|
||||
{
|
||||
BgPicturesSource *bg_source = BG_PICTURES_SOURCE (object);
|
||||
|
||||
g_clear_object (&bg_source->thumb_factory);
|
||||
|
||||
g_clear_pointer (&bg_source->known_items, g_hash_table_destroy);
|
||||
|
||||
g_clear_object (&bg_source->picture_dir_monitor);
|
||||
g_clear_object (&bg_source->cache_dir_monitor);
|
||||
|
||||
G_OBJECT_CLASS (bg_pictures_source_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
bg_pictures_source_class_init (BgPicturesSourceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = bg_pictures_source_dispose;
|
||||
object_class->finalize = bg_pictures_source_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_placeholder (BgPicturesSource *bg_source, CcBackgroundItem *item)
|
||||
{
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path;
|
||||
GtkTreeRowReference *row_ref;
|
||||
|
||||
store = bg_source_get_liststore (BG_SOURCE (bg_source));
|
||||
row_ref = g_object_get_data (G_OBJECT (item), "row-ref");
|
||||
if (row_ref == NULL)
|
||||
return;
|
||||
|
||||
path = gtk_tree_row_reference_get_path (row_ref);
|
||||
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
|
||||
return;
|
||||
|
||||
gtk_list_store_remove (store, &iter);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
picture_needs_rotation (GdkPixbuf *pixbuf)
|
||||
{
|
||||
const gchar *str;
|
||||
|
||||
str = gdk_pixbuf_get_option (pixbuf, "orientation");
|
||||
if (str == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (*str == '5' || *str == '6' || *str == '7' || *str == '8')
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
swap_rotated_pixbuf (GdkPixbuf *pixbuf)
|
||||
{
|
||||
GdkPixbuf *tmp_pixbuf;
|
||||
|
||||
tmp_pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf);
|
||||
if (tmp_pixbuf == NULL)
|
||||
return pixbuf;
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
return tmp_pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
picture_scaled (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
BgPicturesSource *bg_source;
|
||||
CcBackgroundItem *item;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GdkPixbuf) pixbuf = NULL;
|
||||
const char *software;
|
||||
const char *uri;
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path;
|
||||
GtkTreeRowReference *row_ref;
|
||||
GtkListStore *store;
|
||||
cairo_surface_t *surface = NULL;
|
||||
int scale_factor;
|
||||
gboolean rotation_applied;
|
||||
|
||||
item = g_object_get_data (source_object, "item");
|
||||
pixbuf = gdk_pixbuf_new_from_stream_finish (res, &error);
|
||||
if (pixbuf == NULL)
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
g_warning ("Failed to load image: %s", error->message);
|
||||
remove_placeholder (BG_PICTURES_SOURCE (user_data), item);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* since we were not cancelled, we can now cast user_data
|
||||
* back to BgPicturesSource.
|
||||
*/
|
||||
bg_source = BG_PICTURES_SOURCE (user_data);
|
||||
store = bg_source_get_liststore (BG_SOURCE (bg_source));
|
||||
uri = cc_background_item_get_uri (item);
|
||||
if (uri == NULL)
|
||||
uri = cc_background_item_get_source_url (item);
|
||||
|
||||
/* Ignore screenshots */
|
||||
software = gdk_pixbuf_get_option (pixbuf, "tEXt::Software");
|
||||
if (software != NULL &&
|
||||
g_str_equal (software, "gnome-screenshot"))
|
||||
{
|
||||
g_debug ("Ignored URL '%s' as it's a screenshot from gnome-screenshot", uri);
|
||||
remove_placeholder (BG_PICTURES_SOURCE (user_data), item);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process embedded orientation */
|
||||
rotation_applied = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "rotation-applied"));
|
||||
|
||||
if (!rotation_applied && picture_needs_rotation (pixbuf))
|
||||
{
|
||||
/* the width and height of pixbuf we requested are wrong for EXIF
|
||||
* orientations 5, 6, 7 and 8. the file has to be reloaded. */
|
||||
g_autoptr(GFile) file = NULL;
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
g_object_set_data (G_OBJECT (item), "needs-rotation", GINT_TO_POINTER (TRUE));
|
||||
g_object_set_data_full (G_OBJECT (file), "item", g_object_ref (item), g_object_unref);
|
||||
g_file_read_async (G_FILE (file), G_PRIORITY_DEFAULT,
|
||||
bg_source->cancellable,
|
||||
picture_opened_for_read, bg_source);
|
||||
return;
|
||||
}
|
||||
|
||||
pixbuf = swap_rotated_pixbuf (pixbuf);
|
||||
|
||||
scale_factor = bg_source_get_scale_factor (BG_SOURCE (bg_source));
|
||||
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
|
||||
cc_background_item_load (item, NULL);
|
||||
|
||||
row_ref = g_object_get_data (G_OBJECT (item), "row-ref");
|
||||
if (row_ref == NULL)
|
||||
{
|
||||
/* insert the item into the liststore if it did not exist */
|
||||
gtk_list_store_insert_with_values (store, NULL, -1,
|
||||
0, surface,
|
||||
1, item,
|
||||
-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
path = gtk_tree_row_reference_get_path (row_ref);
|
||||
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
|
||||
{
|
||||
/* otherwise update the thumbnail */
|
||||
gtk_list_store_set (store, &iter,
|
||||
0, surface,
|
||||
-1);
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_insert (bg_source->known_items,
|
||||
bg_pictures_source_get_unique_filename (uri),
|
||||
GINT_TO_POINTER (TRUE));
|
||||
|
||||
g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
picture_opened_for_read (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
BgPicturesSource *bg_source;
|
||||
CcBackgroundItem *item;
|
||||
g_autoptr(GFileInputStream) stream = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
gint thumbnail_height;
|
||||
gint thumbnail_width;
|
||||
gboolean needs_rotation;
|
||||
|
||||
item = g_object_get_data (source_object, "item");
|
||||
stream = g_file_read_finish (G_FILE (source_object), res, &error);
|
||||
if (stream == NULL)
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
g_autofree gchar *filename = g_file_get_path (G_FILE (source_object));
|
||||
g_warning ("Failed to load picture '%s': %s", filename, error->message);
|
||||
remove_placeholder (BG_PICTURES_SOURCE (user_data), item);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* since we were not cancelled, we can now cast user_data
|
||||
* back to BgPicturesSource.
|
||||
*/
|
||||
bg_source = BG_PICTURES_SOURCE (user_data);
|
||||
|
||||
needs_rotation = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "needs-rotation"));
|
||||
if (needs_rotation)
|
||||
{
|
||||
/* swap width and height for EXIF orientations that need it */
|
||||
thumbnail_width = bg_source_get_thumbnail_height (BG_SOURCE (bg_source));
|
||||
thumbnail_height = bg_source_get_thumbnail_width (BG_SOURCE (bg_source));
|
||||
g_object_set_data (G_OBJECT (item), "rotation-applied", GINT_TO_POINTER (TRUE));
|
||||
}
|
||||
else
|
||||
{
|
||||
thumbnail_width = bg_source_get_thumbnail_width (BG_SOURCE (bg_source));
|
||||
thumbnail_height = bg_source_get_thumbnail_height (BG_SOURCE (bg_source));
|
||||
}
|
||||
|
||||
g_object_set_data_full (G_OBJECT (stream), "item", g_object_ref (item), g_object_unref);
|
||||
gdk_pixbuf_new_from_stream_at_scale_async (G_INPUT_STREAM (stream),
|
||||
thumbnail_width, thumbnail_height,
|
||||
TRUE,
|
||||
bg_source->cancellable,
|
||||
picture_scaled, bg_source);
|
||||
}
|
||||
|
||||
static void
|
||||
picture_copied_for_read (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
BgPicturesSource *bg_source;
|
||||
CcBackgroundItem *item;
|
||||
g_autoptr(GError) error = NULL;
|
||||
GFile *thumbnail_file = G_FILE (source_object);
|
||||
GFile *native_file;
|
||||
|
||||
if (!g_file_copy_finish (thumbnail_file, res, &error))
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
|
||||
{
|
||||
g_autofree gchar *uri = NULL;
|
||||
|
||||
uri = g_file_get_uri (thumbnail_file);
|
||||
g_warning ("Failed to download '%s': %s", uri, error->message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bg_source = BG_PICTURES_SOURCE (user_data);
|
||||
|
||||
native_file = g_object_get_data (G_OBJECT (thumbnail_file), "native-file");
|
||||
item = g_object_get_data (G_OBJECT (thumbnail_file), "item");
|
||||
g_object_set_data_full (G_OBJECT (native_file), "item", g_object_ref (item), g_object_unref);
|
||||
g_file_read_async (native_file,
|
||||
G_PRIORITY_DEFAULT,
|
||||
bg_source->cancellable,
|
||||
picture_opened_for_read,
|
||||
bg_source);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
in_content_types (const char *content_type)
|
||||
{
|
||||
guint i;
|
||||
for (i = 0; content_types[i]; i++)
|
||||
if (g_str_equal (content_types[i], content_type))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
in_screenshot_types (const char *content_type)
|
||||
{
|
||||
guint i;
|
||||
for (i = 0; screenshot_types[i]; i++)
|
||||
if (g_str_equal (screenshot_types[i], content_type))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
get_content_loading_icon (BgSource *source)
|
||||
{
|
||||
GtkIconTheme *theme;
|
||||
g_autoptr(GtkIconInfo) icon_info = NULL;
|
||||
g_autoptr(GdkPixbuf) pixbuf = NULL;
|
||||
g_autoptr(GdkPixbuf) ret = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
int scale_factor;
|
||||
cairo_surface_t *surface;
|
||||
int thumbnail_height;
|
||||
int thumbnail_width;
|
||||
|
||||
theme = gtk_icon_theme_get_default ();
|
||||
icon_info = gtk_icon_theme_lookup_icon (theme,
|
||||
"content-loading-symbolic",
|
||||
16,
|
||||
GTK_ICON_LOOKUP_FORCE_SIZE | GTK_ICON_LOOKUP_GENERIC_FALLBACK);
|
||||
if (icon_info == NULL)
|
||||
{
|
||||
g_warning ("Failed to find placeholder icon");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pixbuf = gtk_icon_info_load_icon (icon_info, &error);
|
||||
if (pixbuf == NULL)
|
||||
{
|
||||
g_warning ("Failed to load placeholder icon: %s", error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
thumbnail_height = bg_source_get_thumbnail_height (source);
|
||||
thumbnail_width = bg_source_get_thumbnail_width (source);
|
||||
ret = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
TRUE,
|
||||
8, thumbnail_width, thumbnail_height);
|
||||
gdk_pixbuf_fill (ret, 0x00000000);
|
||||
|
||||
/* Put the icon in the middle */
|
||||
gdk_pixbuf_copy_area (pixbuf, 0, 0,
|
||||
gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
|
||||
ret,
|
||||
(thumbnail_width - gdk_pixbuf_get_width (pixbuf)) / 2,
|
||||
(thumbnail_height - gdk_pixbuf_get_height (pixbuf)) / 2);
|
||||
|
||||
scale_factor = bg_source_get_scale_factor (source);
|
||||
surface = gdk_cairo_surface_create_from_pixbuf (ret, scale_factor, NULL);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static GFile *
|
||||
bg_pictures_source_get_cache_file (void)
|
||||
{
|
||||
g_autofree gchar *path = NULL;
|
||||
GFile *file;
|
||||
|
||||
path = bg_pictures_source_get_cache_path ();
|
||||
file = g_file_new_for_path (path);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
add_single_file (BgPicturesSource *bg_source,
|
||||
GFile *file,
|
||||
const gchar *content_type,
|
||||
guint64 mtime,
|
||||
GtkTreeRowReference **ret_row_ref)
|
||||
{
|
||||
g_autoptr(CcBackgroundItem) item = NULL;
|
||||
CcBackgroundItemFlags flags = 0;
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path = NULL;
|
||||
GtkTreeRowReference *row_ref = NULL;
|
||||
cairo_surface_t *surface = NULL;
|
||||
g_autofree gchar *source_uri = NULL;
|
||||
g_autofree gchar *uri = NULL;
|
||||
gboolean needs_download;
|
||||
gboolean retval = FALSE;
|
||||
g_autoptr(GFile) pictures_dir = NULL;
|
||||
g_autoptr(GFile) cache_dir = NULL;
|
||||
GrlMedia *media;
|
||||
|
||||
/* find png and jpeg files */
|
||||
if (!content_type)
|
||||
goto out;
|
||||
if (!in_content_types (content_type))
|
||||
goto out;
|
||||
|
||||
/* create a new CcBackgroundItem */
|
||||
uri = g_file_get_uri (file);
|
||||
|
||||
pictures_dir = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
|
||||
cache_dir = bg_pictures_source_get_cache_file ();
|
||||
needs_download = !g_file_has_parent (file, pictures_dir) &&
|
||||
!g_file_has_parent (file, cache_dir);
|
||||
|
||||
if (!needs_download)
|
||||
{
|
||||
source_uri = g_strdup (uri);
|
||||
flags |= CC_BACKGROUND_ITEM_HAS_URI;
|
||||
}
|
||||
else
|
||||
{
|
||||
source_uri = g_steal_pointer (&uri);
|
||||
}
|
||||
|
||||
item = cc_background_item_new (uri);
|
||||
flags |= CC_BACKGROUND_ITEM_HAS_SHADING | CC_BACKGROUND_ITEM_HAS_PLACEMENT;
|
||||
g_object_set (G_OBJECT (item),
|
||||
"flags", flags,
|
||||
"shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
|
||||
"placement", G_DESKTOP_BACKGROUND_STYLE_ZOOM,
|
||||
"modified", mtime,
|
||||
"needs-download", needs_download,
|
||||
"source-url", source_uri,
|
||||
NULL);
|
||||
|
||||
if (!ret_row_ref && in_screenshot_types (content_type))
|
||||
goto read_file;
|
||||
|
||||
surface = get_content_loading_icon (BG_SOURCE (bg_source));
|
||||
store = bg_source_get_liststore (BG_SOURCE (bg_source));
|
||||
|
||||
/* insert the item into the liststore */
|
||||
gtk_list_store_insert_with_values (store, &iter, -1,
|
||||
0, surface,
|
||||
1, item,
|
||||
-1);
|
||||
|
||||
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
|
||||
row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
|
||||
g_object_set_data_full (G_OBJECT (item), "row-ref", row_ref, (GDestroyNotify) gtk_tree_row_reference_free);
|
||||
|
||||
|
||||
read_file:
|
||||
|
||||
media = g_object_get_data (G_OBJECT (file), "grl-media");
|
||||
if (media == NULL)
|
||||
{
|
||||
g_object_set_data_full (G_OBJECT (file), "item", g_object_ref (item), g_object_unref);
|
||||
g_file_read_async (file, G_PRIORITY_DEFAULT,
|
||||
bg_source->cancellable,
|
||||
picture_opened_for_read, bg_source);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_autoptr(GFile) native_file = NULL;
|
||||
g_autoptr(GFile) thumbnail_file = NULL;
|
||||
g_autofree gchar *native_dir = NULL;
|
||||
g_autofree gchar *native_path = NULL;
|
||||
const gchar *title;
|
||||
const gchar *thumbnail_uri;
|
||||
|
||||
title = grl_media_get_title (media);
|
||||
g_object_set (G_OBJECT (item), "name", title, NULL);
|
||||
|
||||
thumbnail_uri = grl_media_get_thumbnail (media);
|
||||
thumbnail_file = g_file_new_for_uri (thumbnail_uri);
|
||||
|
||||
native_path = gnome_desktop_thumbnail_path_for_uri (source_uri, GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
|
||||
native_file = g_file_new_for_path (native_path);
|
||||
|
||||
native_dir = g_path_get_dirname (native_path);
|
||||
g_mkdir_with_parents (native_dir, USER_DIR_MODE);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (thumbnail_file), "item", g_object_ref (item), g_object_unref);
|
||||
g_object_set_data_full (G_OBJECT (thumbnail_file),
|
||||
"native-file",
|
||||
g_object_ref (native_file),
|
||||
g_object_unref);
|
||||
g_file_copy_async (thumbnail_file,
|
||||
native_file,
|
||||
G_FILE_COPY_ALL_METADATA,
|
||||
G_PRIORITY_DEFAULT,
|
||||
bg_source->cancellable,
|
||||
NULL,
|
||||
NULL,
|
||||
picture_copied_for_read,
|
||||
bg_source);
|
||||
}
|
||||
|
||||
retval = TRUE;
|
||||
|
||||
out:
|
||||
if (ret_row_ref)
|
||||
{
|
||||
if (row_ref && retval != FALSE)
|
||||
*ret_row_ref = gtk_tree_row_reference_copy (row_ref);
|
||||
else
|
||||
*ret_row_ref = NULL;
|
||||
}
|
||||
gtk_tree_path_free (path);
|
||||
g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
add_single_file_from_info (BgPicturesSource *bg_source,
|
||||
GFile *file,
|
||||
GFileInfo *info,
|
||||
GtkTreeRowReference **ret_row_ref)
|
||||
{
|
||||
const gchar *content_type;
|
||||
guint64 mtime;
|
||||
|
||||
content_type = g_file_info_get_content_type (info);
|
||||
mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
|
||||
return add_single_file (bg_source, file, content_type, mtime, ret_row_ref);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
add_single_file_from_media (BgPicturesSource *bg_source,
|
||||
GFile *file,
|
||||
GrlMedia *media)
|
||||
{
|
||||
GDateTime *mtime;
|
||||
const gchar *content_type;
|
||||
gint64 mtime_unix;
|
||||
|
||||
content_type = grl_media_get_mime (media);
|
||||
|
||||
/* only GRL_METADATA_KEY_CREATION_DATE is implemented in the Flickr
|
||||
* plugin, GRL_METADATA_KEY_MODIFICATION_DATE is not
|
||||
*/
|
||||
mtime = grl_media_get_creation_date (media);
|
||||
if (!mtime)
|
||||
mtime = grl_media_get_modification_date (media);
|
||||
if (mtime)
|
||||
mtime_unix = g_date_time_to_unix (mtime);
|
||||
else
|
||||
mtime_unix = g_get_real_time () / G_USEC_PER_SEC;
|
||||
|
||||
return add_single_file (bg_source, file, content_type, (guint64) mtime_unix, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
bg_pictures_source_add (BgPicturesSource *bg_source,
|
||||
const char *uri,
|
||||
GtkTreeRowReference **ret_row_ref)
|
||||
{
|
||||
g_autoptr(GFile) file = NULL;
|
||||
GFileInfo *info;
|
||||
gboolean retval;
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
info = g_file_query_info (file, ATTRIBUTES, G_FILE_QUERY_INFO_NONE, NULL, NULL);
|
||||
if (info == NULL)
|
||||
return FALSE;
|
||||
|
||||
retval = add_single_file_from_info (bg_source, file, info, ret_row_ref);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
gboolean
|
||||
bg_pictures_source_remove (BgPicturesSource *bg_source,
|
||||
const char *uri)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
gboolean cont;
|
||||
gboolean retval;
|
||||
|
||||
retval = FALSE;
|
||||
model = GTK_TREE_MODEL (bg_source_get_liststore (BG_SOURCE (bg_source)));
|
||||
|
||||
cont = gtk_tree_model_get_iter_first (model, &iter);
|
||||
while (cont)
|
||||
{
|
||||
g_autoptr(CcBackgroundItem) tmp_item = NULL;
|
||||
const char *tmp_uri;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 1, &tmp_item, -1);
|
||||
tmp_uri = cc_background_item_get_uri (tmp_item);
|
||||
if (g_str_equal (tmp_uri, uri))
|
||||
{
|
||||
char *uuid;
|
||||
uuid = bg_pictures_source_get_unique_filename (uri);
|
||||
g_hash_table_insert (bg_source->known_items,
|
||||
uuid, NULL);
|
||||
|
||||
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
|
||||
retval = TRUE;
|
||||
break;
|
||||
}
|
||||
cont = gtk_tree_model_iter_next (model, &iter);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
file_sort_func (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
GFileInfo *file_a = G_FILE_INFO (a);
|
||||
GFileInfo *file_b = G_FILE_INFO (b);
|
||||
guint64 modified_a, modified_b;
|
||||
|
||||
modified_a = g_file_info_get_attribute_uint64 (file_a, G_FILE_ATTRIBUTE_TIME_MODIFIED);
|
||||
|
||||
modified_b = g_file_info_get_attribute_uint64 (file_b, G_FILE_ATTRIBUTE_TIME_MODIFIED);
|
||||
|
||||
return modified_b - modified_a;
|
||||
}
|
||||
|
||||
static void
|
||||
file_info_async_ready (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
BgPicturesSource *bg_source;
|
||||
GList *files, *l;
|
||||
g_autoptr(GError) err = NULL;
|
||||
GFile *parent;
|
||||
|
||||
files = g_file_enumerator_next_files_finish (G_FILE_ENUMERATOR (source),
|
||||
res,
|
||||
&err);
|
||||
if (err)
|
||||
{
|
||||
if (!g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_warning ("Could not get pictures file information: %s", err->message);
|
||||
|
||||
g_list_foreach (files, (GFunc) g_object_unref, NULL);
|
||||
g_list_free (files);
|
||||
return;
|
||||
}
|
||||
|
||||
bg_source = BG_PICTURES_SOURCE (user_data);
|
||||
|
||||
parent = g_file_enumerator_get_container (G_FILE_ENUMERATOR (source));
|
||||
|
||||
files = g_list_sort (files, file_sort_func);
|
||||
|
||||
/* iterate over the available files */
|
||||
for (l = files; l; l = g_list_next (l))
|
||||
{
|
||||
GFileInfo *info = l->data;
|
||||
g_autoptr(GFile) file = NULL;
|
||||
|
||||
file = g_file_get_child (parent, g_file_info_get_name (info));
|
||||
|
||||
add_single_file_from_info (bg_source, file, info, NULL);
|
||||
}
|
||||
|
||||
g_list_foreach (files, (GFunc) g_object_unref, NULL);
|
||||
g_list_free (files);
|
||||
}
|
||||
|
||||
static void
|
||||
dir_enum_async_ready (GObject *s,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
BgPicturesSource *source = (BgPicturesSource *) user_data;
|
||||
g_autoptr(GFileEnumerator) enumerator = NULL;
|
||||
g_autoptr(GError) err = NULL;
|
||||
|
||||
enumerator = g_file_enumerate_children_finish (G_FILE (s), res, &err);
|
||||
|
||||
if (err)
|
||||
{
|
||||
if (!g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_warning ("Could not fill pictures source: %s", err->message);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get the files */
|
||||
g_file_enumerator_next_files_async (enumerator,
|
||||
G_MAXINT,
|
||||
G_PRIORITY_LOW,
|
||||
source->cancellable,
|
||||
file_info_async_ready,
|
||||
user_data);
|
||||
}
|
||||
|
||||
char *
|
||||
bg_pictures_source_get_cache_path (void)
|
||||
{
|
||||
return g_build_filename (g_get_user_cache_dir (),
|
||||
"gnome-control-center",
|
||||
"backgrounds",
|
||||
NULL);
|
||||
}
|
||||
|
||||
static char *
|
||||
bg_pictures_source_get_unique_filename (const char *uri)
|
||||
{
|
||||
g_autoptr(GChecksum) csum = NULL;
|
||||
char *ret;
|
||||
|
||||
csum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
g_checksum_update (csum, (guchar *) uri, -1);
|
||||
ret = g_strdup (g_checksum_get_string (csum));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
bg_pictures_source_get_unique_path (const char *uri)
|
||||
{
|
||||
g_autoptr(GFile) parent = NULL;
|
||||
g_autoptr(GFile) file = NULL;
|
||||
g_autofree gchar *cache_path = NULL;
|
||||
g_autofree gchar *filename = NULL;
|
||||
|
||||
cache_path = bg_pictures_source_get_cache_path ();
|
||||
parent = g_file_new_for_path (cache_path);
|
||||
|
||||
filename = bg_pictures_source_get_unique_filename (uri);
|
||||
file = g_file_get_child (parent, filename);
|
||||
|
||||
return g_file_get_path (file);
|
||||
}
|
||||
|
||||
gboolean
|
||||
bg_pictures_source_is_known (BgPicturesSource *bg_source,
|
||||
const char *uri)
|
||||
{
|
||||
g_autofree gchar *uuid = NULL;
|
||||
|
||||
uuid = bg_pictures_source_get_unique_filename (uri);
|
||||
|
||||
return GPOINTER_TO_INT (g_hash_table_lookup (bg_source->known_items, uuid));
|
||||
}
|
||||
|
||||
static int
|
||||
sort_func (GtkTreeModel *model,
|
||||
GtkTreeIter *a,
|
||||
GtkTreeIter *b,
|
||||
BgPicturesSource *bg_source)
|
||||
{
|
||||
g_autoptr(CcBackgroundItem) item_a = NULL;
|
||||
g_autoptr(CcBackgroundItem) item_b = NULL;
|
||||
guint64 modified_a;
|
||||
guint64 modified_b;
|
||||
int retval;
|
||||
|
||||
gtk_tree_model_get (model, a,
|
||||
1, &item_a,
|
||||
-1);
|
||||
gtk_tree_model_get (model, b,
|
||||
1, &item_b,
|
||||
-1);
|
||||
|
||||
modified_a = cc_background_item_get_modified (item_a);
|
||||
modified_b = cc_background_item_get_modified (item_b);
|
||||
|
||||
retval = modified_b - modified_a;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
file_info_ready (GObject *object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GFileInfo *info;
|
||||
GError *error = NULL;
|
||||
GFile *file = G_FILE (object);
|
||||
|
||||
info = g_file_query_info_finish (file, res, &error);
|
||||
|
||||
if (!info)
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_warning ("Problem looking up file info: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
add_single_file_from_info (BG_PICTURES_SOURCE (user_data), file, info, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
file_added (GFile *file,
|
||||
BgPicturesSource *self)
|
||||
{
|
||||
g_autofree gchar *uri = NULL;
|
||||
uri = g_file_get_uri (file);
|
||||
|
||||
if (!bg_pictures_source_is_known (self, uri))
|
||||
{
|
||||
g_file_query_info_async (file,
|
||||
ATTRIBUTES,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
G_PRIORITY_LOW,
|
||||
NULL,
|
||||
file_info_ready,
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
files_changed_cb (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event_type,
|
||||
gpointer user_data)
|
||||
{
|
||||
BgPicturesSource *self = BG_PICTURES_SOURCE (user_data);
|
||||
g_autofree gchar *uri = NULL;
|
||||
|
||||
switch (event_type)
|
||||
{
|
||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||
file_added (file, self);
|
||||
break;
|
||||
|
||||
case G_FILE_MONITOR_EVENT_DELETED:
|
||||
uri = g_file_get_uri (file);
|
||||
bg_pictures_source_remove (self, uri);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static GFileMonitor *
|
||||
monitor_path (BgPicturesSource *self,
|
||||
const char *path)
|
||||
{
|
||||
GFileMonitor *monitor;
|
||||
g_autoptr(GFile) dir = NULL;
|
||||
|
||||
g_mkdir_with_parents (path, USER_DIR_MODE);
|
||||
|
||||
dir = g_file_new_for_path (path);
|
||||
g_file_enumerate_children_async (dir,
|
||||
ATTRIBUTES,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
G_PRIORITY_LOW, self->cancellable,
|
||||
dir_enum_async_ready, self);
|
||||
|
||||
monitor = g_file_monitor_directory (dir,
|
||||
G_FILE_MONITOR_NONE,
|
||||
self->cancellable,
|
||||
NULL);
|
||||
|
||||
if (monitor)
|
||||
g_signal_connect (monitor,
|
||||
"changed",
|
||||
G_CALLBACK (files_changed_cb),
|
||||
self);
|
||||
|
||||
return monitor;
|
||||
}
|
||||
|
||||
static void
|
||||
media_found_cb (BgPicturesSource *self, GrlMedia *media)
|
||||
{
|
||||
g_autoptr(GFile) file = NULL;
|
||||
const gchar *uri;
|
||||
|
||||
uri = grl_media_get_url (media);
|
||||
file = g_file_new_for_uri (uri);
|
||||
g_object_set_data_full (G_OBJECT (file), "grl-media", g_object_ref (media), g_object_unref);
|
||||
add_single_file_from_media (self, file, media);
|
||||
}
|
||||
|
||||
static void
|
||||
bg_pictures_source_init (BgPicturesSource *self)
|
||||
{
|
||||
const gchar *pictures_path;
|
||||
g_autofree gchar *cache_path = NULL;
|
||||
GtkListStore *store;
|
||||
|
||||
self->cancellable = g_cancellable_new ();
|
||||
self->known_items = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
NULL);
|
||||
|
||||
pictures_path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
|
||||
if (pictures_path == NULL)
|
||||
pictures_path = g_get_home_dir ();
|
||||
|
||||
self->picture_dir_monitor = monitor_path (self, pictures_path);
|
||||
|
||||
cache_path = bg_pictures_source_get_cache_path ();
|
||||
self->cache_dir_monitor = monitor_path (self, cache_path);
|
||||
|
||||
self->grl_miner = cc_background_grilo_miner_new ();
|
||||
g_signal_connect_swapped (self->grl_miner, "media-found", G_CALLBACK (media_found_cb), self);
|
||||
cc_background_grilo_miner_start (self->grl_miner);
|
||||
|
||||
self->thumb_factory =
|
||||
gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
|
||||
|
||||
store = bg_source_get_liststore (BG_SOURCE (self));
|
||||
|
||||
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
|
||||
1,
|
||||
(GtkTreeIterCompareFunc)sort_func,
|
||||
self,
|
||||
NULL);
|
||||
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
|
||||
1,
|
||||
GTK_SORT_ASCENDING);
|
||||
}
|
||||
|
||||
BgPicturesSource *
|
||||
bg_pictures_source_new (GtkWindow *window)
|
||||
{
|
||||
return g_object_new (BG_TYPE_PICTURES_SOURCE, "window", window, NULL);
|
||||
}
|
||||
|
||||
const char * const *
|
||||
bg_pictures_get_support_content_types (void)
|
||||
{
|
||||
return content_types;
|
||||
}
|
||||
50
panels/background/bg-pictures-source.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* bg-pictures-source.h */
|
||||
/*
|
||||
* Copyright (C) 2010 Intel, Inc
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Thomas Wood <thomas.wood@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _BG_PICTURES_SOURCE_H
|
||||
#define _BG_PICTURES_SOURCE_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "bg-source.h"
|
||||
#include "cc-background-item.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define BG_TYPE_PICTURES_SOURCE (bg_pictures_source_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (BgPicturesSource, bg_pictures_source, BG, PICTURES_SOURCE, BgSource)
|
||||
|
||||
BgPicturesSource *bg_pictures_source_new (GtkWindow *window);
|
||||
char *bg_pictures_source_get_cache_path (void);
|
||||
char *bg_pictures_source_get_unique_path(const char *uri);
|
||||
gboolean bg_pictures_source_add (BgPicturesSource *bg_source,
|
||||
const char *uri,
|
||||
GtkTreeRowReference **ret_row_ref);
|
||||
gboolean bg_pictures_source_remove (BgPicturesSource *bg_source,
|
||||
const char *uri);
|
||||
gboolean bg_pictures_source_is_known (BgPicturesSource *bg_source,
|
||||
const char *uri);
|
||||
|
||||
const char * const * bg_pictures_get_support_content_types (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _BG_PICTURES_SOURCE_H */
|
||||
@@ -1,459 +0,0 @@
|
||||
/* bg-recent-source.c
|
||||
*
|
||||
* Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "bg-recent-source"
|
||||
|
||||
#include "bg-recent-source.h"
|
||||
#include "cc-background-item.h"
|
||||
|
||||
#define ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_NAME "," \
|
||||
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED
|
||||
|
||||
struct _BgRecentSource
|
||||
{
|
||||
BgSource parent;
|
||||
|
||||
GFile *backgrounds_folder;
|
||||
GFileMonitor *monitor;
|
||||
|
||||
GCancellable *cancellable;
|
||||
GHashTable *items;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (BgRecentSource, bg_recent_source, BG_TYPE_SOURCE)
|
||||
|
||||
static int
|
||||
sort_func (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcBackgroundItem *item_a;
|
||||
CcBackgroundItem *item_b;
|
||||
guint64 modified_a;
|
||||
guint64 modified_b;
|
||||
int retval;
|
||||
|
||||
item_a = (CcBackgroundItem *) a;
|
||||
item_b = (CcBackgroundItem *) b;
|
||||
modified_a = cc_background_item_get_modified (item_a);
|
||||
modified_b = cc_background_item_get_modified (item_b);
|
||||
|
||||
retval = modified_b - modified_a;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
add_file_from_info (BgRecentSource *self,
|
||||
GFile *file,
|
||||
GFileInfo *info)
|
||||
{
|
||||
g_autoptr(CcBackgroundItem) item = NULL;
|
||||
CcBackgroundItemFlags flags = 0;
|
||||
g_autofree gchar *source_uri = NULL;
|
||||
g_autofree gchar *uri = NULL;
|
||||
GListStore *store;
|
||||
const gchar *content_type;
|
||||
guint64 mtime;
|
||||
|
||||
content_type = g_file_info_get_content_type (info);
|
||||
mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
|
||||
|
||||
if (!content_type || !g_content_type_is_a (content_type, "image/*"))
|
||||
return;
|
||||
|
||||
uri = g_file_get_uri (file);
|
||||
item = cc_background_item_new (uri);
|
||||
flags |= CC_BACKGROUND_ITEM_HAS_SHADING | CC_BACKGROUND_ITEM_HAS_PLACEMENT;
|
||||
g_object_set (G_OBJECT (item),
|
||||
"flags", flags,
|
||||
"shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
|
||||
"placement", G_DESKTOP_BACKGROUND_STYLE_ZOOM,
|
||||
"modified", mtime,
|
||||
"needs-download", FALSE,
|
||||
"source-url", source_uri,
|
||||
NULL);
|
||||
|
||||
store = bg_source_get_liststore (BG_SOURCE (self));
|
||||
g_list_store_insert_sorted (store, item, sort_func, self);
|
||||
|
||||
g_hash_table_insert (self->items, g_strdup (uri), g_object_ref (item));
|
||||
}
|
||||
|
||||
static void
|
||||
remove_item (BgRecentSource *self,
|
||||
CcBackgroundItem *item)
|
||||
{
|
||||
GListStore *store;
|
||||
const gchar *uri;
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (BG_IS_RECENT_SOURCE (self));
|
||||
g_return_if_fail (CC_IS_BACKGROUND_ITEM (item));
|
||||
|
||||
uri = cc_background_item_get_uri (item);
|
||||
store = bg_source_get_liststore (BG_SOURCE (self));
|
||||
|
||||
g_debug ("Removing wallpaper %s", uri);
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
|
||||
{
|
||||
g_autoptr(CcBackgroundItem) tmp = NULL;
|
||||
|
||||
tmp = g_list_model_get_item (G_LIST_MODEL (store), i);
|
||||
|
||||
if (tmp == item)
|
||||
{
|
||||
g_list_store_remove (store, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_remove (self->items, cc_background_item_get_uri (item));
|
||||
}
|
||||
|
||||
static void
|
||||
query_info_finished_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
BgRecentSource *self;
|
||||
g_autoptr(GFileInfo) file_info = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
GFile *file = NULL;
|
||||
|
||||
file = G_FILE (source);
|
||||
file_info = g_file_query_info_finish (file, result, &error);
|
||||
if (error)
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_warning ("Could not get pictures file information: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
self = BG_RECENT_SOURCE (user_data);
|
||||
|
||||
g_debug ("Adding wallpaper %s (%d)",
|
||||
g_file_info_get_name (file_info),
|
||||
G_IS_FILE (self->backgrounds_folder));
|
||||
|
||||
add_file_from_info (self, file, file_info);
|
||||
}
|
||||
|
||||
static void
|
||||
on_file_changed_cb (BgRecentSource *self,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event_type)
|
||||
{
|
||||
g_autofree gchar *uri = NULL;
|
||||
|
||||
switch (event_type)
|
||||
{
|
||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||
g_file_query_info_async (file,
|
||||
ATTRIBUTES,
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
G_PRIORITY_DEFAULT,
|
||||
self->cancellable,
|
||||
query_info_finished_cb,
|
||||
self);
|
||||
break;
|
||||
|
||||
case G_FILE_MONITOR_EVENT_DELETED:
|
||||
uri = g_file_get_uri (file);
|
||||
remove_item (self, g_hash_table_lookup (self->items, uri));
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
file_sort_func (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
GFileInfo *file_a = G_FILE_INFO (a);
|
||||
GFileInfo *file_b = G_FILE_INFO (b);
|
||||
guint64 modified_a, modified_b;
|
||||
|
||||
modified_a = g_file_info_get_attribute_uint64 (file_a, G_FILE_ATTRIBUTE_TIME_MODIFIED);
|
||||
modified_b = g_file_info_get_attribute_uint64 (file_b, G_FILE_ATTRIBUTE_TIME_MODIFIED);
|
||||
|
||||
return modified_b - modified_a;
|
||||
}
|
||||
|
||||
static void
|
||||
file_info_async_ready_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
BgRecentSource *self;
|
||||
g_autolist(GFileInfo) file_infos = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
GFile *parent = NULL;
|
||||
GList *l;
|
||||
|
||||
file_infos = g_file_enumerator_next_files_finish (G_FILE_ENUMERATOR (source),
|
||||
result,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_warning ("Could not get pictures file information: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
self = BG_RECENT_SOURCE (user_data);
|
||||
parent = g_file_enumerator_get_container (G_FILE_ENUMERATOR (source));
|
||||
|
||||
file_infos = g_list_sort (file_infos, file_sort_func);
|
||||
|
||||
for (l = file_infos; l; l = l->next)
|
||||
{
|
||||
g_autoptr(GFile) file = NULL;
|
||||
GFileInfo *info;
|
||||
|
||||
info = l->data;
|
||||
file = g_file_get_child (parent, g_file_info_get_name (info));
|
||||
|
||||
g_debug ("Found recent wallpaper %s", g_file_info_get_name (info));
|
||||
|
||||
add_file_from_info (self, file, info);
|
||||
}
|
||||
|
||||
g_file_enumerator_close (G_FILE_ENUMERATOR (source), self->cancellable, &error);
|
||||
|
||||
if (error)
|
||||
g_warning ("Error closing file enumerator: %s", error->message);
|
||||
}
|
||||
|
||||
static void
|
||||
enumerate_children_finished_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
BgRecentSource *self;
|
||||
g_autoptr(GFileEnumerator) enumerator = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
enumerator = g_file_enumerate_children_finish (G_FILE (source), result, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_warning ("Could not fill pictures source: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
self = BG_RECENT_SOURCE (user_data);
|
||||
g_file_enumerator_next_files_async (enumerator,
|
||||
G_MAXINT,
|
||||
G_PRIORITY_DEFAULT,
|
||||
self->cancellable,
|
||||
file_info_async_ready_cb,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
load_backgrounds (BgRecentSource *self)
|
||||
{
|
||||
g_autofree gchar *backgrounds_path = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
if (!g_file_make_directory_with_parents (self->backgrounds_folder, self->cancellable, &error) &&
|
||||
!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
|
||||
{
|
||||
g_critical ("Failed to create local background directory: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
backgrounds_path = g_file_get_path (self->backgrounds_folder);
|
||||
g_debug ("Enumerating wallpapers under %s", backgrounds_path);
|
||||
|
||||
g_file_enumerate_children_async (self->backgrounds_folder,
|
||||
ATTRIBUTES,
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
G_PRIORITY_DEFAULT,
|
||||
self->cancellable,
|
||||
enumerate_children_finished_cb,
|
||||
self);
|
||||
|
||||
self->monitor = g_file_monitor_directory (self->backgrounds_folder,
|
||||
G_FILE_MONITOR_WATCH_MOVES,
|
||||
self->cancellable,
|
||||
&error);
|
||||
|
||||
if (!self->monitor)
|
||||
{
|
||||
g_critical ("Failed to monitor background directory: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
g_signal_connect_object (self->monitor, "changed", G_CALLBACK (on_file_changed_cb), self, G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
static void
|
||||
on_file_copied_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(BgRecentSource) self = BG_RECENT_SOURCE (user_data);
|
||||
g_autofree gchar *original_file = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
g_file_copy_finish (G_FILE (source), result, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_critical ("Failed to copy file: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
original_file = g_file_get_path (G_FILE (source));
|
||||
g_debug ("Successfully copied wallpaper: %s", original_file);
|
||||
}
|
||||
|
||||
static void
|
||||
on_file_deleted_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(BgRecentSource) self = BG_RECENT_SOURCE (user_data);
|
||||
g_autofree gchar *original_file = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
g_file_delete_finish (G_FILE (source), result, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_critical ("Failed to delete wallpaper: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
original_file = g_file_get_path (G_FILE (source));
|
||||
g_debug ("Successfully deleted wallpaper: %s", original_file);
|
||||
}
|
||||
|
||||
/* GObject overrides */
|
||||
|
||||
static void
|
||||
bg_recent_source_finalize (GObject *object)
|
||||
{
|
||||
BgRecentSource *self = (BgRecentSource *)object;
|
||||
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_clear_object (&self->cancellable);
|
||||
g_clear_object (&self->monitor);
|
||||
|
||||
G_OBJECT_CLASS (bg_recent_source_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
bg_recent_source_class_init (BgRecentSourceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = bg_recent_source_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
bg_recent_source_init (BgRecentSource *self)
|
||||
{
|
||||
g_autofree gchar *backgrounds_path = NULL;
|
||||
|
||||
backgrounds_path = g_build_filename (g_get_user_data_dir (), "backgrounds", NULL);
|
||||
|
||||
self->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
self->cancellable = g_cancellable_new ();
|
||||
self->backgrounds_folder = g_file_new_for_path (backgrounds_path);
|
||||
|
||||
load_backgrounds (self);
|
||||
}
|
||||
|
||||
BgRecentSource*
|
||||
bg_recent_source_new (GtkWidget *widget)
|
||||
{
|
||||
return g_object_new (BG_TYPE_RECENT_SOURCE,
|
||||
"widget", widget,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
bg_recent_source_add_file (BgRecentSource *self,
|
||||
const gchar *path)
|
||||
{
|
||||
g_autoptr(GDateTime) now = NULL;
|
||||
g_autofree gchar *destination_name = NULL;
|
||||
g_autofree gchar *formatted_now = NULL;
|
||||
g_autofree gchar *basename = NULL;
|
||||
g_autoptr(GFile) destination = NULL;
|
||||
g_autoptr(GFile) file = NULL;
|
||||
|
||||
g_return_if_fail (BG_IS_RECENT_SOURCE (self));
|
||||
g_return_if_fail (path && *path);
|
||||
|
||||
g_debug ("Importing wallpaper %s", path);
|
||||
|
||||
now = g_date_time_new_now_local ();
|
||||
formatted_now = g_date_time_format (now, "%Y-%m-%d-%H-%M-%S");
|
||||
|
||||
file = g_file_new_for_path (path);
|
||||
|
||||
basename = g_file_get_basename (file);
|
||||
destination_name = g_strdup_printf ("%s-%s", formatted_now, basename);
|
||||
destination = g_file_get_child (self->backgrounds_folder, destination_name);
|
||||
|
||||
g_file_copy_async (file,
|
||||
destination,
|
||||
G_FILE_COPY_NONE,
|
||||
G_PRIORITY_DEFAULT,
|
||||
self->cancellable,
|
||||
NULL, NULL,
|
||||
on_file_copied_cb,
|
||||
g_object_ref (self));
|
||||
}
|
||||
|
||||
void
|
||||
bg_recent_source_remove_item (BgRecentSource *self,
|
||||
CcBackgroundItem *item)
|
||||
{
|
||||
g_autoptr(GFile) file = NULL;
|
||||
const gchar *uri;
|
||||
|
||||
g_return_if_fail (BG_IS_RECENT_SOURCE (self));
|
||||
g_return_if_fail (CC_IS_BACKGROUND_ITEM (item));
|
||||
|
||||
uri = cc_background_item_get_uri (item);
|
||||
file = g_file_new_for_uri (uri);
|
||||
|
||||
g_file_delete_async (file,
|
||||
G_PRIORITY_DEFAULT,
|
||||
self->cancellable,
|
||||
on_file_deleted_cb,
|
||||
g_object_ref (self));
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/* bg-recent-source.h
|
||||
*
|
||||
* Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "bg-source.h"
|
||||
#include "cc-background-item.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define BG_TYPE_RECENT_SOURCE (bg_recent_source_get_type())
|
||||
G_DECLARE_FINAL_TYPE (BgRecentSource, bg_recent_source, BG, RECENT_SOURCE, BgSource)
|
||||
|
||||
BgRecentSource* bg_recent_source_new (GtkWidget *widget);
|
||||
|
||||
void bg_recent_source_add_file (BgRecentSource *self,
|
||||
const gchar *path);
|
||||
|
||||
void bg_recent_source_remove_item (BgRecentSource *self,
|
||||
CcBackgroundItem *item);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -23,14 +23,13 @@
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
|
||||
#define THUMBNAIL_WIDTH 144
|
||||
#define THUMBNAIL_WIDTH 256
|
||||
#define THUMBNAIL_HEIGHT (THUMBNAIL_WIDTH * 3 / 4)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GnomeDesktopThumbnailFactory *thumbnail_factory;
|
||||
GListStore *store;
|
||||
GtkWidget *widget;
|
||||
GtkListStore *store;
|
||||
GtkWidget *window;
|
||||
gint thumbnail_height;
|
||||
gint thumbnail_width;
|
||||
} BgSourcePrivate;
|
||||
@@ -40,7 +39,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (BgSource, bg_source, G_TYPE_OBJECT)
|
||||
enum
|
||||
{
|
||||
PROP_LISTSTORE = 1,
|
||||
PROP_WIDGET
|
||||
PROP_WINDOW
|
||||
};
|
||||
|
||||
|
||||
@@ -53,10 +52,10 @@ bg_source_calculate_thumbnail_dimensions (BgSource *source)
|
||||
priv->thumbnail_height = THUMBNAIL_HEIGHT;
|
||||
priv->thumbnail_width = THUMBNAIL_WIDTH;
|
||||
|
||||
if (priv->widget == NULL)
|
||||
if (priv->window == NULL)
|
||||
return;
|
||||
|
||||
scale_factor = gtk_widget_get_scale_factor (priv->widget);
|
||||
scale_factor = gtk_widget_get_scale_factor (priv->window);
|
||||
if (scale_factor > 1)
|
||||
{
|
||||
priv->thumbnail_height *= scale_factor;
|
||||
@@ -102,8 +101,8 @@ bg_source_set_property (GObject *object,
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_WIDGET:
|
||||
priv->widget = GTK_WIDGET (g_value_get_object (value));
|
||||
case PROP_WINDOW:
|
||||
priv->window = GTK_WIDGET (g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -117,7 +116,6 @@ bg_source_dispose (GObject *object)
|
||||
BgSource *source = BG_SOURCE (object);
|
||||
BgSourcePrivate *priv = bg_source_get_instance_private (source);
|
||||
|
||||
g_clear_object (&priv->thumbnail_factory);
|
||||
g_clear_object (&priv->store);
|
||||
|
||||
G_OBJECT_CLASS (bg_source_parent_class)->dispose (object);
|
||||
@@ -137,27 +135,26 @@ bg_source_class_init (BgSourceClass *klass)
|
||||
pspec = g_param_spec_object ("liststore",
|
||||
"Liststore",
|
||||
"Liststore used in the source",
|
||||
G_TYPE_LIST_STORE,
|
||||
GTK_TYPE_LIST_STORE,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_LISTSTORE, pspec);
|
||||
|
||||
pspec = g_param_spec_object ("widget",
|
||||
"Widget",
|
||||
"Widget used to view the source",
|
||||
GTK_TYPE_WIDGET,
|
||||
pspec = g_param_spec_object ("window",
|
||||
"Window",
|
||||
"Toplevel window used to view the source",
|
||||
GTK_TYPE_WINDOW,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_WIDGET, pspec);
|
||||
g_object_class_install_property (object_class, PROP_WINDOW, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
bg_source_init (BgSource *self)
|
||||
{
|
||||
BgSourcePrivate *priv = bg_source_get_instance_private (self);
|
||||
priv->store = g_list_store_new (CC_TYPE_BACKGROUND_ITEM);
|
||||
priv->thumbnail_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
|
||||
priv->store = gtk_list_store_new (3, CAIRO_GOBJECT_TYPE_SURFACE, G_TYPE_OBJECT, G_TYPE_STRING);
|
||||
}
|
||||
|
||||
GListStore*
|
||||
GtkListStore*
|
||||
bg_source_get_liststore (BgSource *source)
|
||||
{
|
||||
BgSourcePrivate *priv;
|
||||
@@ -176,7 +173,7 @@ bg_source_get_scale_factor (BgSource *source)
|
||||
g_return_val_if_fail (BG_IS_SOURCE (source), 1);
|
||||
|
||||
priv = bg_source_get_instance_private (source);
|
||||
return gtk_widget_get_scale_factor (priv->widget);
|
||||
return gtk_widget_get_scale_factor (priv->window);
|
||||
}
|
||||
|
||||
gint
|
||||
@@ -200,14 +197,3 @@ bg_source_get_thumbnail_width (BgSource *source)
|
||||
priv = bg_source_get_instance_private (source);
|
||||
return priv->thumbnail_width;
|
||||
}
|
||||
|
||||
GnomeDesktopThumbnailFactory*
|
||||
bg_source_get_thumbnail_factory (BgSource *source)
|
||||
{
|
||||
BgSourcePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (BG_IS_SOURCE (source), NULL);
|
||||
|
||||
priv = bg_source_get_instance_private (source);
|
||||
return priv->thumbnail_factory;
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef _BG_SOURCE_H
|
||||
#define _BG_SOURCE_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -33,7 +33,7 @@ struct _BgSourceClass
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GListStore* bg_source_get_liststore (BgSource *source);
|
||||
GtkListStore* bg_source_get_liststore (BgSource *source);
|
||||
|
||||
gint bg_source_get_scale_factor (BgSource *source);
|
||||
|
||||
@@ -41,6 +41,6 @@ gint bg_source_get_thumbnail_height (BgSource *source);
|
||||
|
||||
gint bg_source_get_thumbnail_width (BgSource *source);
|
||||
|
||||
GnomeDesktopThumbnailFactory* bg_source_get_thumbnail_factory (BgSource *source);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _BG_SOURCE_H */
|
||||
|
||||
@@ -25,56 +25,55 @@
|
||||
#include "cc-background-xml.h"
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
struct _BgWallpapersSource
|
||||
{
|
||||
BgSource parent_instance;
|
||||
GnomeDesktopThumbnailFactory *thumb_factory;
|
||||
CcBackgroundXml *xml;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (BgWallpapersSource, bg_wallpapers_source, BG_TYPE_SOURCE)
|
||||
|
||||
static int
|
||||
sort_func (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcBackgroundItem *item_a;
|
||||
CcBackgroundItem *item_b;
|
||||
const char *name_a;
|
||||
const char *name_b;
|
||||
|
||||
item_a = (CcBackgroundItem *) a;
|
||||
item_b = (CcBackgroundItem *) b;
|
||||
|
||||
name_a = cc_background_item_get_name (item_a);
|
||||
name_b = cc_background_item_get_name (item_b);
|
||||
|
||||
if (name_a && strcmp (name_a, "Default Background") == 0)
|
||||
return -1;
|
||||
if (name_b && strcmp (name_b, "Default Background") == 0)
|
||||
return 1;
|
||||
|
||||
|
||||
return strcmp (cc_background_item_get_name (item_a),
|
||||
cc_background_item_get_name (item_b));
|
||||
}
|
||||
|
||||
static void
|
||||
load_wallpapers (gchar *key,
|
||||
CcBackgroundItem *item,
|
||||
BgWallpapersSource *source)
|
||||
{
|
||||
GListStore *store = bg_source_get_liststore (BG_SOURCE (source));
|
||||
GtkTreeIter iter;
|
||||
g_autoptr(GdkPixbuf) pixbuf = NULL;
|
||||
GtkListStore *store = bg_source_get_liststore (BG_SOURCE (source));
|
||||
cairo_surface_t *surface;
|
||||
gboolean deleted;
|
||||
gint scale_factor;
|
||||
gint thumbnail_height;
|
||||
gint thumbnail_width;
|
||||
|
||||
g_object_get (G_OBJECT (item), "is-deleted", &deleted, NULL);
|
||||
|
||||
if (deleted)
|
||||
return;
|
||||
|
||||
g_list_store_insert_sorted (store, item, sort_func, NULL);
|
||||
gtk_list_store_append (store, &iter);
|
||||
|
||||
scale_factor = bg_source_get_scale_factor (BG_SOURCE (source));
|
||||
thumbnail_height = bg_source_get_thumbnail_height (BG_SOURCE (source));
|
||||
thumbnail_width = bg_source_get_thumbnail_width (BG_SOURCE (source));
|
||||
pixbuf = cc_background_item_get_thumbnail (item, source->thumb_factory,
|
||||
thumbnail_width, thumbnail_height,
|
||||
scale_factor);
|
||||
if (pixbuf == NULL)
|
||||
return;
|
||||
|
||||
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
|
||||
gtk_list_store_set (store, &iter,
|
||||
0, surface,
|
||||
1, item,
|
||||
2, cc_background_item_get_name (item),
|
||||
-1);
|
||||
g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -88,8 +87,9 @@ list_load_cb (GObject *source_object,
|
||||
}
|
||||
|
||||
static void
|
||||
item_added (BgWallpapersSource *self,
|
||||
CcBackgroundItem *item)
|
||||
item_added (CcBackgroundXml *xml,
|
||||
CcBackgroundItem *item,
|
||||
BgWallpapersSource *self)
|
||||
{
|
||||
load_wallpapers (NULL, item, self);
|
||||
}
|
||||
@@ -122,8 +122,8 @@ bg_wallpapers_source_constructed (GObject *object)
|
||||
|
||||
G_OBJECT_CLASS (bg_wallpapers_source_parent_class)->constructed (object);
|
||||
|
||||
g_signal_connect_object (G_OBJECT (self->xml), "added",
|
||||
G_CALLBACK (item_added), self, G_CONNECT_SWAPPED);
|
||||
g_signal_connect (G_OBJECT (self->xml), "added",
|
||||
G_CALLBACK (item_added), self);
|
||||
|
||||
/* Try adding the default background first */
|
||||
load_default_bg (self);
|
||||
@@ -136,6 +136,7 @@ bg_wallpapers_source_dispose (GObject *object)
|
||||
{
|
||||
BgWallpapersSource *self = BG_WALLPAPERS_SOURCE (object);
|
||||
|
||||
g_clear_object (&self->thumb_factory);
|
||||
g_clear_object (&self->xml);
|
||||
|
||||
G_OBJECT_CLASS (bg_wallpapers_source_parent_class)->dispose (object);
|
||||
@@ -144,6 +145,8 @@ bg_wallpapers_source_dispose (GObject *object)
|
||||
static void
|
||||
bg_wallpapers_source_init (BgWallpapersSource *self)
|
||||
{
|
||||
self->thumb_factory =
|
||||
gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
|
||||
self->xml = cc_background_xml_new ();
|
||||
}
|
||||
|
||||
@@ -157,8 +160,8 @@ bg_wallpapers_source_class_init (BgWallpapersSourceClass *klass)
|
||||
}
|
||||
|
||||
BgWallpapersSource *
|
||||
bg_wallpapers_source_new (GtkWidget *widget)
|
||||
bg_wallpapers_source_new (GtkWindow *window)
|
||||
{
|
||||
return g_object_new (BG_TYPE_WALLPAPERS_SOURCE, "widget", widget, NULL);
|
||||
return g_object_new (BG_TYPE_WALLPAPERS_SOURCE, "window", window, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _BG_WALLPAPERS_SOURCE_H
|
||||
#define _BG_WALLPAPERS_SOURCE_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "bg-source.h"
|
||||
@@ -29,6 +31,8 @@ G_BEGIN_DECLS
|
||||
#define BG_TYPE_WALLPAPERS_SOURCE (bg_wallpapers_source_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (BgWallpapersSource, bg_wallpapers_source, BG, WALLPAPERS_SOURCE, BgSource)
|
||||
|
||||
BgWallpapersSource *bg_wallpapers_source_new (GtkWidget *widget);
|
||||
BgWallpapersSource *bg_wallpapers_source_new (GtkWindow *window);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _BG_WALLPAPERS_SOURCE_H */
|
||||
|
||||
616
panels/background/cc-background-chooser-dialog.c
Normal file
@@ -0,0 +1,616 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2012 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "cc-background-chooser-dialog.h"
|
||||
#include "bg-wallpapers-source.h"
|
||||
#include "bg-pictures-source.h"
|
||||
#include "bg-colors-source.h"
|
||||
|
||||
#include "cc-background-item.h"
|
||||
#include "cc-background-xml.h"
|
||||
|
||||
#define WP_PATH_ID "org.gnome.desktop.background"
|
||||
#define WP_URI_KEY "picture-uri"
|
||||
#define WP_OPTIONS_KEY "picture-options"
|
||||
#define WP_SHADING_KEY "color-shading-type"
|
||||
#define WP_PCOLOR_KEY "primary-color"
|
||||
#define WP_SCOLOR_KEY "secondary-color"
|
||||
|
||||
enum
|
||||
{
|
||||
SOURCE_WALLPAPERS,
|
||||
SOURCE_PICTURES,
|
||||
SOURCE_COLORS,
|
||||
};
|
||||
|
||||
struct _CcBackgroundChooserDialog
|
||||
{
|
||||
GtkDialog parent_instance;
|
||||
|
||||
GtkListStore *sources;
|
||||
GtkWidget *stack;
|
||||
GtkWidget *pictures_stack;
|
||||
|
||||
BgWallpapersSource *wallpapers_source;
|
||||
BgPicturesSource *pictures_source;
|
||||
BgColorsSource *colors_source;
|
||||
|
||||
GtkTreeRowReference *item_to_focus;
|
||||
|
||||
GnomeDesktopThumbnailFactory *thumb_factory;
|
||||
|
||||
GCancellable *copy_cancellable;
|
||||
|
||||
GtkWidget *spinner;
|
||||
|
||||
gulong row_inserted_id;
|
||||
gulong row_deleted_id;
|
||||
gulong row_modified_id;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcBackgroundChooserDialog, cc_background_chooser_dialog, GTK_TYPE_DIALOG)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
URI_LIST,
|
||||
COLOR
|
||||
};
|
||||
|
||||
static const GtkTargetEntry color_targets[] =
|
||||
{
|
||||
{ "application/x-color", 0, COLOR }
|
||||
};
|
||||
|
||||
static void on_visible_child_notify (CcBackgroundChooserDialog *chooser);
|
||||
|
||||
static void
|
||||
cc_background_chooser_dialog_realize (GtkWidget *widget)
|
||||
{
|
||||
CcBackgroundChooserDialog *chooser = CC_BACKGROUND_CHOOSER_DIALOG (widget);
|
||||
GtkWindow *parent;
|
||||
|
||||
parent = gtk_window_get_transient_for (GTK_WINDOW (chooser));
|
||||
|
||||
if (parent == NULL)
|
||||
{
|
||||
gtk_window_set_default_size (GTK_WINDOW (chooser), -1, 550);
|
||||
}
|
||||
else
|
||||
{
|
||||
gint width;
|
||||
gint height;
|
||||
|
||||
gtk_window_get_size (parent, &width, &height);
|
||||
gtk_window_set_default_size (GTK_WINDOW (chooser), -1, (gint) (0.66 * height));
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (cc_background_chooser_dialog_parent_class)->realize (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_chooser_dialog_dispose (GObject *object)
|
||||
{
|
||||
CcBackgroundChooserDialog *chooser = CC_BACKGROUND_CHOOSER_DIALOG (object);
|
||||
|
||||
if (chooser->copy_cancellable)
|
||||
{
|
||||
/* cancel any copy operation */
|
||||
g_cancellable_cancel (chooser->copy_cancellable);
|
||||
|
||||
g_clear_object (&chooser->copy_cancellable);
|
||||
}
|
||||
|
||||
/* GtkStack triggers notify::visible-child during dispose and this
|
||||
* means that we have to explicitly disconnect the signal handler
|
||||
* before calling up to the parent implementation, or
|
||||
* on_visible_child_notify() will get called while we're in an
|
||||
* inconsistent state.
|
||||
*/
|
||||
if (chooser->stack != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (chooser->stack, on_visible_child_notify, chooser);
|
||||
chooser->stack = NULL;
|
||||
}
|
||||
|
||||
g_clear_pointer (&chooser->item_to_focus, gtk_tree_row_reference_free);
|
||||
g_clear_object (&chooser->pictures_source);
|
||||
g_clear_object (&chooser->colors_source);
|
||||
g_clear_object (&chooser->wallpapers_source);
|
||||
g_clear_object (&chooser->thumb_factory);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_chooser_dialog_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
get_visible_view (CcBackgroundChooserDialog *chooser)
|
||||
{
|
||||
GtkWidget *visible;
|
||||
GtkWidget *icon_view = NULL;
|
||||
|
||||
visible = gtk_stack_get_visible_child (GTK_STACK (chooser->stack));
|
||||
if (GTK_IS_STACK (visible))
|
||||
{
|
||||
GtkWidget *sw;
|
||||
|
||||
sw = gtk_stack_get_child_by_name (GTK_STACK (visible), "view");
|
||||
icon_view = gtk_bin_get_child (GTK_BIN (sw));
|
||||
}
|
||||
else if (GTK_IS_SCROLLED_WINDOW (visible))
|
||||
{
|
||||
icon_view = gtk_bin_get_child (GTK_BIN (visible));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return icon_view;
|
||||
}
|
||||
|
||||
static void
|
||||
possibly_show_empty_pictures_box (GtkTreeModel *model,
|
||||
CcBackgroundChooserDialog *chooser)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_model_get_iter_first (model, &iter))
|
||||
{
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (chooser->pictures_stack), "view");
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (chooser->pictures_stack), "empty");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_source_modified_cb (GtkTreeModel *tree_model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcBackgroundChooserDialog *chooser = user_data;
|
||||
GtkTreePath *to_focus_path;
|
||||
GtkWidget *icon_view;
|
||||
|
||||
if (chooser->item_to_focus == NULL)
|
||||
return;
|
||||
|
||||
to_focus_path = gtk_tree_row_reference_get_path (chooser->item_to_focus);
|
||||
|
||||
if (gtk_tree_path_compare (to_focus_path, path) != 0)
|
||||
goto out;
|
||||
|
||||
/* Change source */
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (chooser->stack), "pictures");
|
||||
|
||||
/* And select the newly added item */
|
||||
icon_view = get_visible_view (chooser);
|
||||
gtk_icon_view_select_path (GTK_ICON_VIEW (icon_view), to_focus_path);
|
||||
gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (icon_view),
|
||||
to_focus_path, TRUE, 1.0, 1.0);
|
||||
g_clear_pointer (&chooser->item_to_focus, gtk_tree_row_reference_free);
|
||||
|
||||
out:
|
||||
gtk_tree_path_free (to_focus_path);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_source_added_cb (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer user_data)
|
||||
{
|
||||
possibly_show_empty_pictures_box (model, CC_BACKGROUND_CHOOSER_DIALOG (user_data));
|
||||
}
|
||||
|
||||
static void
|
||||
on_source_removed_cb (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
gpointer user_data)
|
||||
{
|
||||
possibly_show_empty_pictures_box (model, CC_BACKGROUND_CHOOSER_DIALOG (user_data));
|
||||
}
|
||||
|
||||
static void
|
||||
monitor_pictures_model (CcBackgroundChooserDialog *chooser)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
|
||||
model = GTK_TREE_MODEL (bg_source_get_liststore (BG_SOURCE (chooser->pictures_source)));
|
||||
|
||||
g_signal_connect (model, "row-inserted", G_CALLBACK (on_source_added_cb), chooser);
|
||||
g_signal_connect (model, "row-deleted", G_CALLBACK (on_source_removed_cb), chooser);
|
||||
g_signal_connect (model, "row-changed", G_CALLBACK (on_source_modified_cb), chooser);
|
||||
|
||||
possibly_show_empty_pictures_box (model, chooser);
|
||||
}
|
||||
|
||||
static void
|
||||
on_visible_child_notify (CcBackgroundChooserDialog *chooser)
|
||||
{
|
||||
GtkWidget *icon_view;
|
||||
|
||||
icon_view = get_visible_view (chooser);
|
||||
gtk_icon_view_unselect_all (GTK_ICON_VIEW (icon_view));
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), GTK_RESPONSE_OK, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_selection_changed (GtkIconView *icon_view,
|
||||
CcBackgroundChooserDialog *chooser)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
list = gtk_icon_view_get_selected_items (icon_view);
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser),
|
||||
GTK_RESPONSE_OK,
|
||||
(list != NULL));
|
||||
|
||||
g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
|
||||
}
|
||||
|
||||
static void
|
||||
on_item_activated (GtkIconView *icon_view,
|
||||
GtkTreePath *path,
|
||||
CcBackgroundChooserDialog *chooser)
|
||||
{
|
||||
gtk_dialog_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
add_custom_wallpaper (CcBackgroundChooserDialog *chooser,
|
||||
const char *uri)
|
||||
{
|
||||
g_clear_pointer (&chooser->item_to_focus, gtk_tree_row_reference_free);
|
||||
|
||||
bg_pictures_source_add (chooser->pictures_source, uri, &chooser->item_to_focus);
|
||||
/* and wait for the item to get added */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cc_background_panel_drag_color (CcBackgroundChooserDialog *chooser,
|
||||
GtkSelectionData *data)
|
||||
{
|
||||
gint length;
|
||||
guint16 *dropped;
|
||||
GdkRGBA rgba;
|
||||
GtkTreeRowReference *row_ref;
|
||||
GtkTreePath *to_focus_path;
|
||||
GtkWidget *icon_view;
|
||||
|
||||
length = gtk_selection_data_get_length (data);
|
||||
|
||||
if (length < 0)
|
||||
return FALSE;
|
||||
|
||||
if (length != 8)
|
||||
{
|
||||
g_warning ("%s: Received invalid color data", G_STRFUNC);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dropped = (guint16 *) gtk_selection_data_get_data (data);
|
||||
rgba.red = dropped[0] / 65535.;
|
||||
rgba.green = dropped[1] / 65535.;
|
||||
rgba.blue = dropped[2] / 65535.;
|
||||
rgba.alpha = dropped[3] / 65535.;
|
||||
|
||||
if (bg_colors_source_add (chooser->colors_source, &rgba, &row_ref) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
/* Change source */
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (chooser->stack), "colors");
|
||||
|
||||
/* And select the newly added item */
|
||||
to_focus_path = gtk_tree_row_reference_get_path (row_ref);
|
||||
icon_view = get_visible_view (chooser);
|
||||
gtk_icon_view_select_path (GTK_ICON_VIEW (icon_view), to_focus_path);
|
||||
gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (icon_view),
|
||||
to_focus_path, TRUE, 1.0, 1.0);
|
||||
gtk_tree_row_reference_free (row_ref);
|
||||
gtk_tree_path_free (to_focus_path);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_panel_drag_items (GtkWidget *widget,
|
||||
GdkDragContext *context, gint x, gint y,
|
||||
GtkSelectionData *data, guint info, guint time,
|
||||
CcBackgroundChooserDialog *chooser)
|
||||
{
|
||||
gint i;
|
||||
char *uri;
|
||||
g_auto(GStrv) uris = NULL;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (info == COLOR)
|
||||
{
|
||||
ret = cc_background_panel_drag_color (chooser, data);
|
||||
goto out;
|
||||
}
|
||||
|
||||
uris = gtk_selection_data_get_uris (data);
|
||||
if (!uris)
|
||||
goto out;
|
||||
|
||||
for (i = 0; uris[i] != NULL; i++)
|
||||
{
|
||||
uri = uris[i];
|
||||
if (!bg_pictures_source_is_known (chooser->pictures_source, uri))
|
||||
{
|
||||
add_custom_wallpaper (chooser, uri);
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
gtk_drag_finish (context, ret, FALSE, time);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_view (CcBackgroundChooserDialog *chooser, GtkTreeModel *model)
|
||||
{
|
||||
GtkCellRenderer *renderer;
|
||||
GtkWidget *icon_view;
|
||||
GtkWidget *sw;
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
||||
gtk_widget_set_hexpand (sw, TRUE);
|
||||
gtk_widget_set_vexpand (sw, TRUE);
|
||||
|
||||
icon_view = gtk_icon_view_new ();
|
||||
gtk_icon_view_set_model (GTK_ICON_VIEW (icon_view), model);
|
||||
gtk_widget_set_hexpand (icon_view, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (sw), icon_view);
|
||||
g_signal_connect (icon_view, "selection-changed", G_CALLBACK (on_selection_changed), chooser);
|
||||
g_signal_connect (icon_view, "item-activated", G_CALLBACK (on_item_activated), chooser);
|
||||
|
||||
gtk_icon_view_set_columns (GTK_ICON_VIEW (icon_view), 3);
|
||||
|
||||
renderer = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (icon_view),
|
||||
renderer,
|
||||
FALSE);
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (icon_view),
|
||||
renderer,
|
||||
"surface", 0,
|
||||
NULL);
|
||||
|
||||
return sw;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_chooser_dialog_constructed (GObject *object)
|
||||
{
|
||||
CcBackgroundChooserDialog *chooser = CC_BACKGROUND_CHOOSER_DIALOG (object);
|
||||
GtkListStore *model;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *vbox;
|
||||
|
||||
G_OBJECT_CLASS (cc_background_chooser_dialog_parent_class)->constructed (object);
|
||||
|
||||
model = bg_source_get_liststore (BG_SOURCE (chooser->wallpapers_source));
|
||||
sw = create_view (chooser, GTK_TREE_MODEL (model));
|
||||
gtk_stack_add_titled (GTK_STACK (chooser->stack), sw, "wallpapers", _("Wallpapers"));
|
||||
gtk_container_child_set (GTK_CONTAINER (chooser->stack), sw, "position", 0, NULL);
|
||||
|
||||
model = bg_source_get_liststore (BG_SOURCE (chooser->pictures_source));
|
||||
sw = create_view (chooser, GTK_TREE_MODEL (model));
|
||||
gtk_stack_add_named (GTK_STACK (chooser->pictures_stack), sw, "view");
|
||||
|
||||
model = bg_source_get_liststore (BG_SOURCE (chooser->colors_source));
|
||||
sw = create_view (chooser, GTK_TREE_MODEL (model));
|
||||
gtk_stack_add_titled (GTK_STACK (chooser->stack), sw, "colors", _("Colors"));
|
||||
|
||||
vbox = gtk_dialog_get_content_area (GTK_DIALOG (chooser));
|
||||
gtk_widget_show_all (vbox);
|
||||
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (chooser->stack), "wallpapers");
|
||||
monitor_pictures_model (chooser);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_chooser_dialog_init (CcBackgroundChooserDialog *chooser)
|
||||
{
|
||||
GtkWidget *empty_pictures_box;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *headerbar;
|
||||
GtkWidget *img;
|
||||
GtkWidget *labels_grid;
|
||||
GtkWidget *label;
|
||||
GtkWidget *switcher;
|
||||
GtkStyleContext *context;
|
||||
g_autofree gchar *markup = NULL;
|
||||
g_autofree gchar *markup2 = NULL;
|
||||
g_autofree gchar *href = NULL;
|
||||
const gchar *pictures_dir;
|
||||
g_autofree gchar *pictures_dir_basename = NULL;
|
||||
g_autofree gchar *pictures_dir_uri = NULL;
|
||||
GtkTargetList *target_list;
|
||||
|
||||
chooser->wallpapers_source = bg_wallpapers_source_new (GTK_WINDOW (chooser));
|
||||
chooser->pictures_source = bg_pictures_source_new (GTK_WINDOW (chooser));
|
||||
chooser->colors_source = bg_colors_source_new (GTK_WINDOW (chooser));
|
||||
|
||||
gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
|
||||
gtk_window_set_resizable (GTK_WINDOW (chooser), FALSE);
|
||||
/* translators: This is the title of the wallpaper chooser dialog. */
|
||||
gtk_window_set_title (GTK_WINDOW (chooser), _("Select Background"));
|
||||
|
||||
vbox = gtk_dialog_get_content_area (GTK_DIALOG (chooser));
|
||||
gtk_container_set_border_width (GTK_CONTAINER (vbox), 0);
|
||||
|
||||
chooser->stack = gtk_stack_new ();
|
||||
gtk_stack_set_homogeneous (GTK_STACK (chooser->stack), TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), chooser->stack);
|
||||
g_signal_connect_swapped (chooser->stack, "notify::visible-child", G_CALLBACK (on_visible_child_notify), chooser);
|
||||
|
||||
/* Add drag and drop support for bg images */
|
||||
gtk_drag_dest_set (chooser->stack, GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY);
|
||||
target_list = gtk_target_list_new (NULL, 0);
|
||||
gtk_target_list_add_uri_targets (target_list, URI_LIST);
|
||||
gtk_target_list_add_table (target_list, color_targets, 1);
|
||||
gtk_drag_dest_set_target_list (chooser->stack, target_list);
|
||||
gtk_target_list_unref (target_list);
|
||||
g_signal_connect (chooser->stack, "drag-data-received", G_CALLBACK (cc_background_panel_drag_items), chooser);
|
||||
|
||||
headerbar = gtk_dialog_get_header_bar (GTK_DIALOG (chooser));
|
||||
|
||||
switcher = gtk_stack_switcher_new ();
|
||||
gtk_stack_switcher_set_stack (GTK_STACK_SWITCHER (switcher), GTK_STACK (chooser->stack));
|
||||
gtk_header_bar_set_custom_title (GTK_HEADER_BAR (headerbar), switcher);
|
||||
gtk_widget_show (switcher);
|
||||
|
||||
chooser->pictures_stack = gtk_stack_new ();
|
||||
gtk_stack_set_homogeneous (GTK_STACK (chooser->pictures_stack), TRUE);
|
||||
gtk_stack_add_titled (GTK_STACK (chooser->stack), chooser->pictures_stack, "pictures", _("Pictures"));
|
||||
|
||||
empty_pictures_box = gtk_grid_new ();
|
||||
gtk_grid_set_column_spacing (GTK_GRID (empty_pictures_box), 12);
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (empty_pictures_box),
|
||||
GTK_ORIENTATION_HORIZONTAL);
|
||||
context = gtk_widget_get_style_context (empty_pictures_box);
|
||||
gtk_style_context_add_class (context, "dim-label");
|
||||
gtk_stack_add_named (GTK_STACK (chooser->pictures_stack), empty_pictures_box, "empty");
|
||||
img = gtk_image_new_from_icon_name ("emblem-photos-symbolic", GTK_ICON_SIZE_DIALOG);
|
||||
gtk_image_set_pixel_size (GTK_IMAGE (img), 64);
|
||||
gtk_widget_set_halign (img, GTK_ALIGN_END);
|
||||
gtk_widget_set_valign (img, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_hexpand (img, TRUE);
|
||||
gtk_widget_set_vexpand (img, TRUE);
|
||||
gtk_widget_show (img);
|
||||
gtk_container_add (GTK_CONTAINER (empty_pictures_box), img);
|
||||
labels_grid = gtk_grid_new ();
|
||||
gtk_widget_set_halign (labels_grid, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (labels_grid, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_hexpand (labels_grid, TRUE);
|
||||
gtk_widget_set_vexpand (labels_grid, TRUE);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (labels_grid), 6);
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (labels_grid),
|
||||
GTK_ORIENTATION_VERTICAL);
|
||||
gtk_widget_show (labels_grid);
|
||||
gtk_container_add (GTK_CONTAINER (empty_pictures_box), labels_grid);
|
||||
label = gtk_label_new ("");
|
||||
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
|
||||
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||||
markup = g_markup_printf_escaped ("<b><span size='large'>%s</span></b>",
|
||||
/* translators: No pictures were found */
|
||||
_("No Pictures Found"));
|
||||
gtk_label_set_markup (GTK_LABEL (label), markup);
|
||||
gtk_widget_show (label);
|
||||
gtk_container_add (GTK_CONTAINER (labels_grid), label);
|
||||
label = gtk_label_new ("");
|
||||
gtk_label_set_max_width_chars (GTK_LABEL (label), 24);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
|
||||
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||||
|
||||
pictures_dir = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
|
||||
if (pictures_dir == NULL)
|
||||
{
|
||||
pictures_dir = g_get_home_dir ();
|
||||
/* translators: "Home" is used in place of the Pictures
|
||||
* directory in the string below when XDG_PICTURES_DIR is
|
||||
* undefined */
|
||||
pictures_dir_basename = g_strdup (_("Home"));
|
||||
}
|
||||
else
|
||||
pictures_dir_basename = g_path_get_basename (pictures_dir);
|
||||
|
||||
pictures_dir_uri = g_filename_to_uri (pictures_dir, NULL, NULL);
|
||||
href = g_markup_printf_escaped ("<a href=\"%s\">%s</a>", pictures_dir_uri, pictures_dir_basename);
|
||||
|
||||
/* translators: %s here is the name of the Pictures directory, the string should be translated in
|
||||
* the context "You can add images to your Pictures folder and they will show up here" */
|
||||
markup2 = g_strdup_printf (_("You can add images to your %s folder and they will show up here"), href);
|
||||
gtk_label_set_markup (GTK_LABEL (label), markup2);
|
||||
gtk_widget_show (label);
|
||||
gtk_container_add (GTK_CONTAINER (labels_grid), label);
|
||||
|
||||
gtk_dialog_add_button (GTK_DIALOG (chooser), _("_Cancel"), GTK_RESPONSE_CANCEL);
|
||||
gtk_dialog_add_button (GTK_DIALOG (chooser), _("_Select"), GTK_RESPONSE_OK);
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), GTK_RESPONSE_OK, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_chooser_dialog_class_init (CcBackgroundChooserDialogClass *klass)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
object_class = G_OBJECT_CLASS (klass);
|
||||
object_class->constructed = cc_background_chooser_dialog_constructed;
|
||||
object_class->dispose = cc_background_chooser_dialog_dispose;
|
||||
|
||||
widget_class = GTK_WIDGET_CLASS (klass);
|
||||
widget_class->realize = cc_background_chooser_dialog_realize;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
cc_background_chooser_dialog_new (GtkWindow *transient_for)
|
||||
{
|
||||
return g_object_new (CC_TYPE_BACKGROUND_CHOOSER_DIALOG,
|
||||
"transient-for", transient_for,
|
||||
"use-header-bar", TRUE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
CcBackgroundItem *
|
||||
cc_background_chooser_dialog_get_item (CcBackgroundChooserDialog *chooser)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeModel *model;
|
||||
GtkWidget *icon_view;
|
||||
GList *list;
|
||||
CcBackgroundItem *item;
|
||||
|
||||
item = NULL;
|
||||
icon_view = get_visible_view (chooser);
|
||||
list = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (icon_view));
|
||||
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
model = gtk_icon_view_get_model (GTK_ICON_VIEW (icon_view));
|
||||
|
||||
if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) list->data) == FALSE)
|
||||
goto bail;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 1, &item, -1);
|
||||
|
||||
bail:
|
||||
g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
|
||||
|
||||
return item;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright 2020 Canonical Ltd.
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2012 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -14,19 +14,25 @@
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __CC_PANEL_CHOOSER_DIALOG_H__
|
||||
#define __CC_PANEL_CHOOSER_DIALOG_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <adwaita.h>
|
||||
|
||||
#include "cc-background-item.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE (CcOnlineAccountProviderRow, cc_online_account_provider_row, CC, ONLINE_ACCOUNT_PROVIDER_ROW, AdwActionRow)
|
||||
#define CC_TYPE_BACKGROUND_CHOOSER_DIALOG (cc_background_chooser_dialog_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (CcBackgroundChooserDialog, cc_background_chooser_dialog, CC, BACKGROUND_CHOOSER_DIALOG, GtkDialog)
|
||||
|
||||
CcOnlineAccountProviderRow *cc_online_account_provider_row_new (GVariant *provider);
|
||||
GtkWidget * cc_background_chooser_dialog_new (GtkWindow *transient_for);
|
||||
|
||||
GVariant *cc_online_account_provider_row_get_provider (CcOnlineAccountProviderRow *row);
|
||||
CcBackgroundItem * cc_background_chooser_dialog_get_item (CcBackgroundChooserDialog *chooser);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CC_BACKGROUND_CHOOSER_DIALOG_H__ */
|
||||
@@ -1,340 +0,0 @@
|
||||
/* cc-background-chooser.c
|
||||
*
|
||||
* Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "cc-background-chooser"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
|
||||
|
||||
#include "bg-colors-source.h"
|
||||
#include "bg-recent-source.h"
|
||||
#include "bg-wallpapers-source.h"
|
||||
#include "cc-background-chooser.h"
|
||||
#include "cc-background-paintable.h"
|
||||
|
||||
struct _CcBackgroundChooser
|
||||
{
|
||||
GtkBox parent;
|
||||
|
||||
GtkFlowBox *flowbox;
|
||||
GtkWidget *recent_box;
|
||||
GtkFlowBox *recent_flowbox;
|
||||
|
||||
gboolean recent_selected;
|
||||
|
||||
BgWallpapersSource *wallpapers_source;
|
||||
BgRecentSource *recent_source;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcBackgroundChooser, cc_background_chooser, GTK_TYPE_BOX)
|
||||
|
||||
enum
|
||||
{
|
||||
BACKGROUND_CHOSEN,
|
||||
N_SIGNALS,
|
||||
};
|
||||
|
||||
static guint signals [N_SIGNALS];
|
||||
|
||||
static void
|
||||
emit_background_chosen (CcBackgroundChooser *self)
|
||||
{
|
||||
g_autoptr(GList) list = NULL;
|
||||
CcBackgroundItem *item;
|
||||
GtkFlowBox *flowbox;
|
||||
|
||||
flowbox = self->recent_selected ? self->recent_flowbox : self->flowbox;
|
||||
list = gtk_flow_box_get_selected_children (flowbox);
|
||||
g_assert (g_list_length (list) == 1);
|
||||
|
||||
item = g_object_get_data (list->data, "item");
|
||||
|
||||
g_signal_emit (self, signals[BACKGROUND_CHOSEN], 0, item);
|
||||
}
|
||||
|
||||
static void
|
||||
on_delete_background_clicked_cb (GtkButton *button,
|
||||
BgRecentSource *source)
|
||||
{
|
||||
GtkWidget *parent;
|
||||
CcBackgroundItem *item;
|
||||
|
||||
parent = gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (button)));
|
||||
g_assert (GTK_IS_FLOW_BOX_CHILD (parent));
|
||||
|
||||
item = g_object_get_data (G_OBJECT (parent), "item");
|
||||
|
||||
bg_recent_source_remove_item (source, item);
|
||||
}
|
||||
|
||||
static void
|
||||
direction_changed_cb (GtkWidget *widget,
|
||||
GtkTextDirection *previous_direction,
|
||||
GdkPaintable *paintable)
|
||||
{
|
||||
g_object_set (paintable,
|
||||
"text-direction", gtk_widget_get_direction (widget),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
create_widget_func (gpointer model_item,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(CcBackgroundPaintable) paintable = NULL;
|
||||
CcBackgroundItem *item;
|
||||
GtkWidget *overlay;
|
||||
GtkWidget *child;
|
||||
GtkWidget *picture;
|
||||
GtkWidget *icon;
|
||||
GtkWidget *check;
|
||||
GtkWidget *button = NULL;
|
||||
BgSource *source;
|
||||
|
||||
source = BG_SOURCE (user_data);
|
||||
item = CC_BACKGROUND_ITEM (model_item);
|
||||
|
||||
paintable = cc_background_paintable_new (source, item);
|
||||
|
||||
picture = gtk_picture_new_for_paintable (GDK_PAINTABLE (paintable));
|
||||
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
|
||||
|
||||
g_object_bind_property (picture, "scale-factor",
|
||||
paintable, "scale-factor", G_BINDING_SYNC_CREATE);
|
||||
g_signal_connect_object (picture, "direction-changed",
|
||||
G_CALLBACK (direction_changed_cb), paintable, 0);
|
||||
|
||||
icon = gtk_image_new_from_icon_name ("slideshow-symbolic");
|
||||
gtk_widget_set_halign (icon, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (icon, GTK_ALIGN_END);
|
||||
gtk_widget_set_visible (icon, cc_background_item_changes_with_time (item));
|
||||
gtk_widget_add_css_class (icon, "slideshow-icon");
|
||||
|
||||
check = gtk_image_new_from_icon_name ("background-selected-symbolic");
|
||||
gtk_widget_set_halign (check, GTK_ALIGN_END);
|
||||
gtk_widget_set_valign (check, GTK_ALIGN_END);
|
||||
gtk_widget_add_css_class (check, "selected-check");
|
||||
|
||||
if (BG_IS_RECENT_SOURCE (source))
|
||||
{
|
||||
button = gtk_button_new_from_icon_name ("window-close-symbolic");
|
||||
gtk_widget_set_halign (button, GTK_ALIGN_END);
|
||||
gtk_widget_set_valign (button, GTK_ALIGN_START);
|
||||
|
||||
gtk_widget_add_css_class (button, "osd");
|
||||
gtk_widget_add_css_class (button, "circular");
|
||||
gtk_widget_add_css_class (button, "remove-button");
|
||||
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (button), _("Remove Background"));
|
||||
|
||||
g_signal_connect (button,
|
||||
"clicked",
|
||||
G_CALLBACK (on_delete_background_clicked_cb),
|
||||
source);
|
||||
}
|
||||
|
||||
overlay = gtk_overlay_new ();
|
||||
gtk_widget_set_overflow (overlay, GTK_OVERFLOW_HIDDEN);
|
||||
gtk_widget_add_css_class (overlay, "background-thumbnail");
|
||||
gtk_overlay_set_child (GTK_OVERLAY (overlay), picture);
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), icon);
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), check);
|
||||
if (button)
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), button);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (overlay),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL,
|
||||
cc_background_item_get_name (item),
|
||||
-1);
|
||||
|
||||
|
||||
child = gtk_flow_box_child_new ();
|
||||
gtk_widget_set_halign (child, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (child, GTK_ALIGN_CENTER);
|
||||
gtk_flow_box_child_set_child (GTK_FLOW_BOX_CHILD (child), overlay);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (child), "item", g_object_ref (item), g_object_unref);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
static void
|
||||
update_recent_visibility (CcBackgroundChooser *self)
|
||||
{
|
||||
GListStore *store;
|
||||
gboolean has_items;
|
||||
|
||||
store = bg_source_get_liststore (BG_SOURCE (self->recent_source));
|
||||
has_items = g_list_model_get_n_items (G_LIST_MODEL (store)) != 0;
|
||||
|
||||
gtk_widget_set_visible (self->recent_box, has_items);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_flowbox (CcBackgroundChooser *self)
|
||||
{
|
||||
GListStore *store;
|
||||
|
||||
store = bg_source_get_liststore (BG_SOURCE (self->wallpapers_source));
|
||||
|
||||
gtk_flow_box_bind_model (self->flowbox,
|
||||
G_LIST_MODEL (store),
|
||||
create_widget_func,
|
||||
self->wallpapers_source,
|
||||
NULL);
|
||||
|
||||
store = bg_source_get_liststore (BG_SOURCE (self->recent_source));
|
||||
|
||||
gtk_flow_box_bind_model (self->recent_flowbox,
|
||||
G_LIST_MODEL (store),
|
||||
create_widget_func,
|
||||
self->recent_source,
|
||||
NULL);
|
||||
|
||||
update_recent_visibility (self);
|
||||
g_signal_connect_object (store,
|
||||
"items-changed",
|
||||
G_CALLBACK (update_recent_visibility),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
static void
|
||||
on_item_activated_cb (CcBackgroundChooser *self,
|
||||
GtkFlowBoxChild *child,
|
||||
GtkFlowBox *flowbox)
|
||||
{
|
||||
self->recent_selected = flowbox == self->recent_flowbox;
|
||||
if (self->recent_selected)
|
||||
gtk_flow_box_unselect_all (self->flowbox);
|
||||
else
|
||||
gtk_flow_box_unselect_all (self->recent_flowbox);
|
||||
emit_background_chosen (self);
|
||||
}
|
||||
|
||||
static void
|
||||
file_dialog_open_cb (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcBackgroundChooser *self = CC_BACKGROUND_CHOOSER (user_data);
|
||||
GtkFileDialog *file_dialog = GTK_FILE_DIALOG (source_object);
|
||||
g_autoptr(GListModel) files = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
guint i;
|
||||
|
||||
files = gtk_file_dialog_open_multiple_finish (file_dialog, res, &error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_warning ("Failed to pick backgrounds: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (files); i++)
|
||||
{
|
||||
g_autoptr(GFile) file = g_list_model_get_item (files, i);
|
||||
g_autofree gchar *filename = g_file_get_path (file);
|
||||
|
||||
bg_recent_source_add_file (self->recent_source, filename);
|
||||
}
|
||||
}
|
||||
|
||||
/* GObject overrides */
|
||||
|
||||
static void
|
||||
cc_background_chooser_finalize (GObject *object)
|
||||
{
|
||||
CcBackgroundChooser *self = (CcBackgroundChooser *)object;
|
||||
|
||||
g_clear_object (&self->recent_source);
|
||||
g_clear_object (&self->wallpapers_source);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_chooser_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_chooser_class_init (CcBackgroundChooserClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = cc_background_chooser_finalize;
|
||||
|
||||
signals[BACKGROUND_CHOSEN] = g_signal_new ("background-chosen",
|
||||
CC_TYPE_BACKGROUND_CHOOSER,
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
CC_TYPE_BACKGROUND_ITEM);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-chooser.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundChooser, flowbox);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundChooser, recent_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundChooser, recent_flowbox);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_item_activated_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_chooser_init (CcBackgroundChooser *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
self->recent_source = bg_recent_source_new (GTK_WIDGET (self));
|
||||
self->wallpapers_source = bg_wallpapers_source_new (GTK_WIDGET (self));
|
||||
setup_flowbox (self);
|
||||
}
|
||||
|
||||
void
|
||||
cc_background_chooser_select_file (CcBackgroundChooser *self)
|
||||
{
|
||||
g_autoptr(GFile) pictures_folder = NULL;
|
||||
GtkFileFilter *filter;
|
||||
GtkFileDialog *file_dialog;
|
||||
GtkWindow *toplevel;
|
||||
GListStore *filters;
|
||||
|
||||
g_return_if_fail (CC_IS_BACKGROUND_CHOOSER (self));
|
||||
|
||||
toplevel = (GtkWindow*) gtk_widget_get_native (GTK_WIDGET (self));
|
||||
|
||||
file_dialog = gtk_file_dialog_new ();
|
||||
gtk_file_dialog_set_title (file_dialog, _("Select a picture"));
|
||||
gtk_file_dialog_set_modal (file_dialog, TRUE);
|
||||
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_add_pixbuf_formats (filter);
|
||||
|
||||
filters = g_list_store_new (GTK_TYPE_FILE_FILTER);
|
||||
g_list_store_append (filters, filter);
|
||||
gtk_file_dialog_set_filters (file_dialog, G_LIST_MODEL (filters));
|
||||
|
||||
pictures_folder = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
|
||||
gtk_file_dialog_set_initial_folder (file_dialog, pictures_folder);
|
||||
|
||||
gtk_file_dialog_open_multiple (file_dialog,
|
||||
toplevel,
|
||||
NULL,
|
||||
file_dialog_open_cb,
|
||||
self);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/* cc-background-chooser.h
|
||||
*
|
||||
* Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_BACKGROUND_CHOOSER (cc_background_chooser_get_type())
|
||||
G_DECLARE_FINAL_TYPE (CcBackgroundChooser, cc_background_chooser, CC, BACKGROUND_CHOOSER, GtkBox)
|
||||
|
||||
void cc_background_chooser_select_file (CcBackgroundChooser *self);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcBackgroundChooser" parent="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<!-- Recent -->
|
||||
<child>
|
||||
<object class="GtkBox" id="recent_box">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">center</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkFlowBox" id="recent_flowbox">
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">12</property>
|
||||
<property name="column-spacing">12</property>
|
||||
<property name="row-spacing">12</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="min-children-per-line">1</property>
|
||||
<property name="max-children-per-line">8</property>
|
||||
<property name="activate-on-single-click">True</property>
|
||||
<property name="selection-mode">single</property>
|
||||
<signal name="child-activated" handler="on_item_activated_cb" object="CcBackgroundChooser" swapped="yes" />
|
||||
<style>
|
||||
<class name="background-flowbox"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkFlowBox" id="flowbox">
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">12</property>
|
||||
<property name="column-spacing">12</property>
|
||||
<property name="row-spacing">12</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="min-children-per-line">1</property>
|
||||
<property name="max-children-per-line">8</property>
|
||||
<property name="activate-on-single-click">True</property>
|
||||
<property name="selection-mode">single</property>
|
||||
<signal name="child-activated" handler="on_item_activated_cb" object="CcBackgroundChooser" swapped="yes" />
|
||||
<style>
|
||||
<class name="background-flowbox"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</template>
|
||||
</interface>
|
||||
315
panels/background/cc-background-grilo-miner.c
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <grilo.h>
|
||||
|
||||
#define GOA_API_IS_SUBJECT_TO_CHANGE
|
||||
#include <goa/goa.h>
|
||||
|
||||
#include "bg-pictures-source.h"
|
||||
#include "cc-background-grilo-miner.h"
|
||||
|
||||
struct _CcBackgroundGriloMiner
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GCancellable *cancellable;
|
||||
GList *accounts;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcBackgroundGriloMiner, cc_background_grilo_miner, G_TYPE_OBJECT)
|
||||
|
||||
enum
|
||||
{
|
||||
MEDIA_FOUND,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
#define REMOTE_ITEM_COUNT 50
|
||||
|
||||
static gchar *
|
||||
get_grilo_id (GoaObject *goa_object)
|
||||
{
|
||||
GoaAccount *account;
|
||||
|
||||
account = goa_object_peek_account (goa_object);
|
||||
return g_strdup_printf ("grl-flickr-%s", goa_account_get_id (account));
|
||||
}
|
||||
|
||||
static void
|
||||
is_online_data_cached (GObject *object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcBackgroundGriloMiner *self;
|
||||
GError *error = NULL;
|
||||
GFileInfo *info = NULL;
|
||||
GFile *cache_file = G_FILE (object);
|
||||
GrlMedia *media;
|
||||
const gchar *uri;
|
||||
|
||||
info = g_file_query_info_finish (cache_file, res, &error);
|
||||
if (info == NULL)
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
goto out;
|
||||
}
|
||||
|
||||
self = CC_BACKGROUND_GRILO_MINER (user_data);
|
||||
|
||||
media = g_object_get_data (G_OBJECT (cache_file), "grl-media");
|
||||
uri = grl_media_get_url (media);
|
||||
|
||||
if (info != NULL)
|
||||
{
|
||||
g_debug ("Ignored URL '%s' as it is already in the cache", uri);
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_signal_emit (self, signals[MEDIA_FOUND], 0, media);
|
||||
|
||||
out:
|
||||
g_clear_object (&info);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
static void
|
||||
searched_online_source (GrlSource *source,
|
||||
guint operation_id,
|
||||
GrlMedia *media,
|
||||
guint remaining,
|
||||
gpointer user_data,
|
||||
const GError *error)
|
||||
{
|
||||
CcBackgroundGriloMiner *self = CC_BACKGROUND_GRILO_MINER (user_data);
|
||||
g_autoptr(GFile) cache_file = NULL;
|
||||
const gchar *uri;
|
||||
g_autofree gchar *cache_path = NULL;
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
const gchar *source_id;
|
||||
|
||||
source_id = grl_source_get_id (source);
|
||||
g_warning ("Error searching %s: %s", source_id, error->message);
|
||||
grl_operation_cancel (operation_id);
|
||||
remaining = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
uri = grl_media_get_url (media);
|
||||
cache_path = bg_pictures_source_get_unique_path (uri);
|
||||
cache_file = g_file_new_for_path (cache_path);
|
||||
g_object_set_data_full (G_OBJECT (cache_file), "grl-media", media, g_object_unref);
|
||||
g_file_query_info_async (cache_file,
|
||||
G_FILE_ATTRIBUTE_STANDARD_TYPE,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
G_PRIORITY_DEFAULT,
|
||||
self->cancellable,
|
||||
is_online_data_cached,
|
||||
self);
|
||||
|
||||
out:
|
||||
if (remaining == 0)
|
||||
g_object_unref (self);
|
||||
}
|
||||
|
||||
static void
|
||||
query_online_source (CcBackgroundGriloMiner *self, GrlSource *source)
|
||||
{
|
||||
const GList *keys;
|
||||
GrlCaps *caps;
|
||||
GrlOperationOptions *options;
|
||||
|
||||
keys = grl_source_supported_keys (source);
|
||||
caps = grl_source_get_caps (source, GRL_OP_BROWSE);
|
||||
options = grl_operation_options_new (caps);
|
||||
grl_operation_options_set_count (options, REMOTE_ITEM_COUNT);
|
||||
grl_operation_options_set_resolution_flags (options, GRL_RESOLVE_FAST_ONLY);
|
||||
grl_operation_options_set_type_filter (options, GRL_TYPE_FILTER_IMAGE);
|
||||
|
||||
grl_source_search (source, NULL, keys, options, searched_online_source, g_object_ref (self));
|
||||
g_object_unref (options);
|
||||
}
|
||||
|
||||
static void
|
||||
add_online_source_cb (CcBackgroundGriloMiner *self,
|
||||
GrlSource *source)
|
||||
{
|
||||
GList *l;
|
||||
gboolean found = FALSE;
|
||||
const gchar *source_id;
|
||||
|
||||
source_id = grl_source_get_id (source);
|
||||
for (l = self->accounts; l != NULL && !found; l = l->next)
|
||||
{
|
||||
GoaObject *goa_object = GOA_OBJECT (l->data);
|
||||
g_autofree gchar *account_id = NULL;
|
||||
|
||||
account_id = get_grilo_id (goa_object);
|
||||
if (g_strcmp0 (source_id, account_id) == 0)
|
||||
{
|
||||
query_online_source (self, source);
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
client_async_ready (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcBackgroundGriloMiner *self;
|
||||
g_autoptr(GError) error = NULL;
|
||||
GList *accounts = NULL;
|
||||
GList *photo_accounts = NULL;
|
||||
GList *l;
|
||||
GoaClient *client = NULL;
|
||||
GrlRegistry *registry;
|
||||
|
||||
client = goa_client_new_finish (res, &error);
|
||||
if (client == NULL)
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_warning ("Failed to create GoaClient: %s", error->message);
|
||||
goto out;
|
||||
}
|
||||
|
||||
self = CC_BACKGROUND_GRILO_MINER (user_data);
|
||||
|
||||
accounts = goa_client_get_accounts (client);
|
||||
for (l = accounts; l != NULL; l = l->next)
|
||||
{
|
||||
GoaObject *goa_object = GOA_OBJECT (l->data);
|
||||
GoaAccount *account;
|
||||
GoaPhotos *photos;
|
||||
const gchar *provider_type;
|
||||
|
||||
account = goa_object_peek_account (goa_object);
|
||||
provider_type = goa_account_get_provider_type (account);
|
||||
|
||||
photos = goa_object_peek_photos (goa_object);
|
||||
if (photos != NULL && g_strcmp0 (provider_type, "flickr") == 0)
|
||||
photo_accounts = g_list_prepend (photo_accounts, g_object_ref (goa_object));
|
||||
}
|
||||
|
||||
if (photo_accounts == NULL)
|
||||
goto out;
|
||||
|
||||
registry = grl_registry_get_default ();
|
||||
|
||||
for (l = photo_accounts; l != NULL; l = l->next)
|
||||
{
|
||||
GoaObject *goa_object = GOA_OBJECT (l->data);
|
||||
GrlSource *source;
|
||||
g_autofree gchar *account_id = NULL;
|
||||
|
||||
account_id = get_grilo_id (goa_object);
|
||||
source = grl_registry_lookup_source (registry, account_id);
|
||||
if (source != NULL)
|
||||
query_online_source (self, source);
|
||||
}
|
||||
|
||||
self->accounts = photo_accounts;
|
||||
photo_accounts = NULL;
|
||||
|
||||
g_signal_connect_object (registry, "source-added", G_CALLBACK (add_online_source_cb), self, G_CONNECT_SWAPPED);
|
||||
|
||||
out:
|
||||
g_list_free_full (photo_accounts, g_object_unref);
|
||||
g_list_free_full (accounts, g_object_unref);
|
||||
g_clear_object (&client);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_online_accounts (CcBackgroundGriloMiner *self)
|
||||
{
|
||||
goa_client_new (self->cancellable, client_async_ready, self);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_grilo_miner_dispose (GObject *object)
|
||||
{
|
||||
CcBackgroundGriloMiner *self = CC_BACKGROUND_GRILO_MINER (object);
|
||||
|
||||
if (self->cancellable)
|
||||
{
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_clear_object (&self->cancellable);
|
||||
}
|
||||
|
||||
if (self->accounts)
|
||||
{
|
||||
g_list_free_full (self->accounts, g_object_unref);
|
||||
self->accounts = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (cc_background_grilo_miner_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_grilo_miner_init (CcBackgroundGriloMiner *self)
|
||||
{
|
||||
self->cancellable = g_cancellable_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_grilo_miner_class_init (CcBackgroundGriloMinerClass *klass)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GrlRegistry *registry;
|
||||
|
||||
object_class->dispose = cc_background_grilo_miner_dispose;
|
||||
|
||||
signals[MEDIA_FOUND] = g_signal_new ("media-found",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, /* class_offset */
|
||||
NULL, /* accumulator */
|
||||
NULL, /* accu_data */
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
GRL_TYPE_MEDIA);
|
||||
|
||||
grl_init (NULL, NULL);
|
||||
registry = grl_registry_get_default ();
|
||||
|
||||
error = NULL;
|
||||
if (!grl_registry_load_all_plugins (registry, FALSE, &error) ||
|
||||
!grl_registry_activate_plugin_by_id (registry, "grl-flickr", &error))
|
||||
g_warning ("%s", error->message);
|
||||
}
|
||||
|
||||
CcBackgroundGriloMiner *
|
||||
cc_background_grilo_miner_new (void)
|
||||
{
|
||||
return g_object_new (CC_TYPE_BACKGROUND_GRILO_MINER, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
cc_background_grilo_miner_start (CcBackgroundGriloMiner *self)
|
||||
{
|
||||
setup_online_accounts (self);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
/* cc-keyboard-shortcut-dialog.h
|
||||
*
|
||||
* Copyright (C) 2020 System76, Inc.
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* 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
|
||||
@@ -14,22 +13,23 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Ian Douglas Scott <idscott@system76.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <adwaita.h>
|
||||
#ifndef _CC_BACKGROUND_GRILO_MINER_H
|
||||
#define _CC_BACKGROUND_GRILO_MINER_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_KEYBOARD_SHORTCUT_DIALOG (cc_keyboard_shortcut_dialog_get_type ())
|
||||
#define CC_TYPE_BACKGROUND_GRILO_MINER (cc_background_grilo_miner_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (CcBackgroundGriloMiner, cc_background_grilo_miner, CC, BACKGROUND_GRILO_MINER, GObject);
|
||||
|
||||
G_DECLARE_FINAL_TYPE (CcKeyboardShortcutDialog, cc_keyboard_shortcut_dialog, CC, KEYBOARD_SHORTCUT_DIALOG, AdwWindow)
|
||||
CcBackgroundGriloMiner *cc_background_grilo_miner_new (void);
|
||||
|
||||
GtkWidget* cc_keyboard_shortcut_dialog_new (void);
|
||||
void cc_background_grilo_miner_start (CcBackgroundGriloMiner *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _CC_BACKGROUND_GRILO_MINER_H */
|
||||
@@ -26,20 +26,12 @@
|
||||
#include <gio/gio.h>
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
#include <gnome-bg/gnome-bg.h>
|
||||
#include <libgnome-desktop/gnome-bg.h>
|
||||
#include <gdesktop-enums.h>
|
||||
|
||||
#include "cc-background-item.h"
|
||||
#include "gdesktop-enums-types.h"
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
int frame;
|
||||
int scale_factor;
|
||||
GdkPixbuf *thumbnail;
|
||||
} CachedThumbnail;
|
||||
|
||||
struct _CcBackgroundItem
|
||||
{
|
||||
GObject parent_instance;
|
||||
@@ -47,7 +39,6 @@ struct _CcBackgroundItem
|
||||
/* properties */
|
||||
char *name;
|
||||
char *uri;
|
||||
char *uri_dark;
|
||||
char *size;
|
||||
GDesktopBackgroundStyle placement;
|
||||
GDesktopBackgroundShading shading;
|
||||
@@ -61,22 +52,17 @@ struct _CcBackgroundItem
|
||||
guint64 modified;
|
||||
|
||||
/* internal */
|
||||
GdkPixbuf *slideshow_emblem;
|
||||
GnomeBG *bg;
|
||||
char *mime_type;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
GnomeBG *bg_dark;
|
||||
|
||||
CachedThumbnail cached_thumbnail;
|
||||
CachedThumbnail cached_thumbnail_dark;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_NAME,
|
||||
PROP_URI,
|
||||
PROP_URI_DARK,
|
||||
PROP_PLACEMENT,
|
||||
PROP_SHADING,
|
||||
PROP_PRIMARY_COLOR,
|
||||
@@ -94,6 +80,64 @@ static void cc_background_item_finalize (GObject *object
|
||||
|
||||
G_DEFINE_TYPE (CcBackgroundItem, cc_background_item, G_TYPE_OBJECT)
|
||||
|
||||
static GdkPixbuf *slideshow_emblem = NULL;
|
||||
|
||||
static GdkPixbuf *
|
||||
get_emblemed_pixbuf (CcBackgroundItem *item, GdkPixbuf *pixbuf, gint scale_factor)
|
||||
{
|
||||
int eh;
|
||||
int ew;
|
||||
int h;
|
||||
int w;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
if (item->slideshow_emblem == NULL) {
|
||||
if (slideshow_emblem == NULL) {
|
||||
g_autoptr(GIcon) icon = NULL;
|
||||
GtkIconTheme *theme;
|
||||
g_autoptr(GtkIconInfo) icon_info = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
icon = g_themed_icon_new ("slideshow-emblem");
|
||||
theme = gtk_icon_theme_get_default ();
|
||||
icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (theme,
|
||||
icon,
|
||||
16,
|
||||
scale_factor,
|
||||
GTK_ICON_LOOKUP_FORCE_SIZE |
|
||||
GTK_ICON_LOOKUP_USE_BUILTIN);
|
||||
if (icon_info == NULL) {
|
||||
g_warning ("Your icon theme is missing the slideshow-emblem icon, "
|
||||
"please file a bug against it");
|
||||
return g_object_ref (pixbuf);
|
||||
}
|
||||
|
||||
slideshow_emblem = gtk_icon_info_load_icon (icon_info, &error);
|
||||
if (slideshow_emblem == NULL) {
|
||||
g_warning ("Failed to load slideshow emblem: %s", error->message);
|
||||
return g_object_ref (pixbuf);
|
||||
}
|
||||
|
||||
g_object_add_weak_pointer (G_OBJECT (slideshow_emblem), (gpointer *) (&slideshow_emblem));
|
||||
item->slideshow_emblem = slideshow_emblem;
|
||||
} else {
|
||||
item->slideshow_emblem = g_object_ref (slideshow_emblem);
|
||||
}
|
||||
}
|
||||
|
||||
eh = gdk_pixbuf_get_height (slideshow_emblem);
|
||||
ew = gdk_pixbuf_get_width (slideshow_emblem);
|
||||
h = gdk_pixbuf_get_height (pixbuf);
|
||||
w = gdk_pixbuf_get_width (pixbuf);
|
||||
x = w - ew;
|
||||
y = h - eh;
|
||||
|
||||
gdk_pixbuf_composite (slideshow_emblem, pixbuf, x, y, ew, eh, x, y, 1.0, 1.0, GDK_INTERP_BILINEAR, 255);
|
||||
|
||||
return g_object_ref (pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
set_bg_properties (CcBackgroundItem *item)
|
||||
{
|
||||
@@ -109,15 +153,6 @@ set_bg_properties (CcBackgroundItem *item)
|
||||
gnome_bg_set_filename (item->bg, filename);
|
||||
}
|
||||
|
||||
if (item->uri_dark) {
|
||||
g_autoptr(GFile) file = NULL;
|
||||
g_autofree gchar *filename = NULL;
|
||||
|
||||
file = g_file_new_for_commandline_arg (item->uri_dark);
|
||||
filename = g_file_get_path (file);
|
||||
gnome_bg_set_filename (item->bg_dark, filename);
|
||||
}
|
||||
|
||||
if (item->primary_color != NULL) {
|
||||
gdk_rgba_parse (&pcolor, item->primary_color);
|
||||
}
|
||||
@@ -126,9 +161,7 @@ set_bg_properties (CcBackgroundItem *item)
|
||||
}
|
||||
|
||||
gnome_bg_set_rgba (item->bg, item->shading, &pcolor, &scolor);
|
||||
gnome_bg_set_rgba (item->bg_dark, item->shading, &pcolor, &scolor);
|
||||
gnome_bg_set_placement (item->bg, item->placement);
|
||||
gnome_bg_set_placement (item->bg_dark, item->placement);
|
||||
}
|
||||
|
||||
|
||||
@@ -143,20 +176,9 @@ cc_background_item_changes_with_time (CcBackgroundItem *item)
|
||||
if (item->bg != NULL) {
|
||||
changes = gnome_bg_changes_with_time (item->bg);
|
||||
}
|
||||
if (item->bg_dark != NULL) {
|
||||
changes |= gnome_bg_changes_with_time (item->bg_dark);
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cc_background_item_has_dark_version (CcBackgroundItem *item)
|
||||
{
|
||||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), FALSE);
|
||||
|
||||
return item->uri && item->uri_dark;
|
||||
}
|
||||
|
||||
static void
|
||||
update_size (CcBackgroundItem *item)
|
||||
{
|
||||
@@ -168,9 +190,6 @@ update_size (CcBackgroundItem *item)
|
||||
if (gnome_bg_has_multiple_sizes (item->bg) || gnome_bg_changes_with_time (item->bg)) {
|
||||
item->size = g_strdup (_("multiple sizes"));
|
||||
} else {
|
||||
gdk_pixbuf_get_file_info (gnome_bg_get_filename (item->bg),
|
||||
&item->width,
|
||||
&item->height);
|
||||
/* translators: 100 × 100px
|
||||
* Note that this is not an "x", but U+00D7 MULTIPLICATION SIGN */
|
||||
item->size = g_strdup_printf (_("%d × %d"),
|
||||
@@ -180,6 +199,19 @@ update_size (CcBackgroundItem *item)
|
||||
}
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
render_at_size (GnomeBG *bg,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
|
||||
gnome_bg_draw (bg, pixbuf, gdk_screen_get_default (), FALSE);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
GdkPixbuf *
|
||||
cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
|
||||
GnomeDesktopThumbnailFactory *thumbs,
|
||||
@@ -187,62 +219,60 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
|
||||
int height,
|
||||
int scale_factor,
|
||||
int frame,
|
||||
gboolean dark)
|
||||
gboolean force_size)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
CachedThumbnail *thumbnail;
|
||||
GnomeBG *bg;
|
||||
g_autoptr(GdkMonitor) monitor = NULL;
|
||||
GdkDisplay *display;
|
||||
GListModel *monitors;
|
||||
GdkRectangle monitor_layout;
|
||||
g_autoptr(GdkPixbuf) pixbuf = NULL;
|
||||
g_autoptr(GdkPixbuf) retval = NULL;
|
||||
|
||||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||||
g_return_val_if_fail (width > 0 && height > 0, NULL);
|
||||
|
||||
thumbnail = dark ? &item->cached_thumbnail_dark : &item->cached_thumbnail;
|
||||
bg = dark ? item->bg_dark : item->bg;
|
||||
|
||||
/* Use the cached thumbnail if the sizes match */
|
||||
if (thumbnail->thumbnail &&
|
||||
thumbnail->width == width &&
|
||||
thumbnail->height == height &&
|
||||
thumbnail->scale_factor == scale_factor &&
|
||||
thumbnail->frame == frame)
|
||||
return g_object_ref (thumbnail->thumbnail);
|
||||
|
||||
set_bg_properties (item);
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
monitors = gdk_display_get_monitors (display);
|
||||
monitor = g_list_model_get_item (monitors, 0);
|
||||
gdk_monitor_get_geometry (monitor, &monitor_layout);
|
||||
|
||||
if (frame >= 0) {
|
||||
pixbuf = gnome_bg_create_frame_thumbnail (bg,
|
||||
thumbs,
|
||||
&monitor_layout,
|
||||
width,
|
||||
height,
|
||||
frame);
|
||||
if (force_size) {
|
||||
/* FIXME: this doesn't play nice with slideshow stepping at all,
|
||||
* because it will always render the current slideshow frame, which
|
||||
* might not be what we want.
|
||||
* We're lacking an API to draw a high-res GnomeBG manually choosing
|
||||
* the slideshow frame though, so we can't do much better than this
|
||||
* for now.
|
||||
*/
|
||||
pixbuf = render_at_size (item->bg, width, height);
|
||||
} else {
|
||||
pixbuf = gnome_bg_create_thumbnail (bg,
|
||||
thumbs,
|
||||
&monitor_layout,
|
||||
width,
|
||||
height);
|
||||
if (frame >= 0) {
|
||||
pixbuf = gnome_bg_create_frame_thumbnail (item->bg,
|
||||
thumbs,
|
||||
gdk_screen_get_default (),
|
||||
width,
|
||||
height,
|
||||
frame);
|
||||
} else {
|
||||
pixbuf = gnome_bg_create_thumbnail (item->bg,
|
||||
thumbs,
|
||||
gdk_screen_get_default (),
|
||||
width,
|
||||
height);
|
||||
}
|
||||
}
|
||||
|
||||
if (pixbuf != NULL
|
||||
&& frame != -2
|
||||
&& gnome_bg_changes_with_time (item->bg)) {
|
||||
retval = get_emblemed_pixbuf (item, pixbuf, scale_factor);
|
||||
} else {
|
||||
retval = g_steal_pointer (&pixbuf);
|
||||
}
|
||||
|
||||
gnome_bg_get_image_size (item->bg,
|
||||
thumbs,
|
||||
width,
|
||||
height,
|
||||
&item->width,
|
||||
&item->height);
|
||||
|
||||
update_size (item);
|
||||
|
||||
/* Cache the new thumbnail */
|
||||
g_set_object (&thumbnail->thumbnail, pixbuf);
|
||||
thumbnail->width = width;
|
||||
thumbnail->height = height;
|
||||
thumbnail->scale_factor = scale_factor;
|
||||
thumbnail->frame = frame;
|
||||
|
||||
return pixbuf;
|
||||
return g_steal_pointer (&retval);
|
||||
}
|
||||
|
||||
|
||||
@@ -251,10 +281,9 @@ cc_background_item_get_thumbnail (CcBackgroundItem *item,
|
||||
GnomeDesktopThumbnailFactory *thumbs,
|
||||
int width,
|
||||
int height,
|
||||
int scale_factor,
|
||||
gboolean dark)
|
||||
int scale_factor)
|
||||
{
|
||||
return cc_background_item_get_frame_thumbnail (item, thumbs, width, height, scale_factor, -1, dark);
|
||||
return cc_background_item_get_frame_thumbnail (item, thumbs, width, height, scale_factor, -1, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -364,21 +393,6 @@ _set_uri (CcBackgroundItem *item,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_set_uri_dark (CcBackgroundItem *item,
|
||||
const char *value)
|
||||
{
|
||||
g_free (item->uri_dark);
|
||||
if (value && *value == '\0') {
|
||||
item->uri_dark = NULL;
|
||||
} else {
|
||||
if (value && strstr (value, "://") == NULL)
|
||||
g_warning ("URI '%s' is invalid", value);
|
||||
item->uri_dark = g_strdup (value);
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
cc_background_item_get_uri (CcBackgroundItem *item)
|
||||
{
|
||||
@@ -387,14 +401,6 @@ cc_background_item_get_uri (CcBackgroundItem *item)
|
||||
return item->uri;
|
||||
}
|
||||
|
||||
const char *
|
||||
cc_background_item_get_uri_dark (CcBackgroundItem *item)
|
||||
{
|
||||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||||
|
||||
return item->uri_dark;
|
||||
}
|
||||
|
||||
static void
|
||||
_set_placement (CcBackgroundItem *item,
|
||||
GDesktopBackgroundStyle value)
|
||||
@@ -566,9 +572,6 @@ cc_background_item_set_property (GObject *object,
|
||||
case PROP_URI:
|
||||
_set_uri (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_URI_DARK:
|
||||
_set_uri_dark (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_PLACEMENT:
|
||||
_set_placement (self, g_value_get_enum (value));
|
||||
break;
|
||||
@@ -619,12 +622,9 @@ cc_background_item_get_property (GObject *object,
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, self->name);
|
||||
break;
|
||||
case PROP_URI:
|
||||
case PROP_URI:
|
||||
g_value_set_string (value, self->uri);
|
||||
break;
|
||||
case PROP_URI_DARK:
|
||||
g_value_set_string (value, self->uri_dark);
|
||||
break;
|
||||
case PROP_PLACEMENT:
|
||||
g_value_set_enum (value, self->placement);
|
||||
break;
|
||||
@@ -702,13 +702,6 @@ cc_background_item_class_init (CcBackgroundItemClass *klass)
|
||||
"uri",
|
||||
NULL,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_URI_DARK,
|
||||
g_param_spec_string ("uri-dark",
|
||||
"uri-dark",
|
||||
"uri-dark",
|
||||
NULL,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_PLACEMENT,
|
||||
g_param_spec_enum ("placement",
|
||||
@@ -805,7 +798,6 @@ static void
|
||||
cc_background_item_init (CcBackgroundItem *item)
|
||||
{
|
||||
item->bg = gnome_bg_new ();
|
||||
item->bg_dark = gnome_bg_new ();
|
||||
|
||||
item->shading = G_DESKTOP_BACKGROUND_SHADING_SOLID;
|
||||
item->placement = G_DESKTOP_BACKGROUND_STYLE_SCALED;
|
||||
@@ -828,8 +820,6 @@ cc_background_item_finalize (GObject *object)
|
||||
|
||||
g_return_if_fail (item != NULL);
|
||||
|
||||
g_clear_object (&item->cached_thumbnail.thumbnail);
|
||||
g_clear_object (&item->cached_thumbnail_dark.thumbnail);
|
||||
g_free (item->name);
|
||||
g_free (item->uri);
|
||||
g_free (item->primary_color);
|
||||
@@ -839,8 +829,10 @@ cc_background_item_finalize (GObject *object)
|
||||
g_free (item->source_url);
|
||||
g_free (item->source_xml);
|
||||
|
||||
g_clear_object (&item->bg);
|
||||
g_clear_object (&item->bg_dark);
|
||||
if (item->bg != NULL)
|
||||
g_object_unref (item->bg);
|
||||
|
||||
g_clear_object (&item->slideshow_emblem);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_item_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -999,10 +991,6 @@ cc_background_item_compare (CcBackgroundItem *saved,
|
||||
if (files_equal (saved->uri, configured->uri) == FALSE)
|
||||
return FALSE;
|
||||
}
|
||||
if (flags & CC_BACKGROUND_ITEM_HAS_URI_DARK) {
|
||||
if (files_equal (saved->uri_dark, configured->uri_dark) == FALSE)
|
||||
return FALSE;
|
||||
}
|
||||
if (flags & CC_BACKGROUND_ITEM_HAS_SHADING) {
|
||||
if (saved->shading != configured->shading)
|
||||
return FALSE;
|
||||
|
||||
@@ -17,13 +17,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __CC_BACKGROUND_ITEM_H
|
||||
#define __CC_BACKGROUND_ITEM_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
|
||||
#include <gdesktop-enums.h>
|
||||
#include <gnome-bg/gnome-bg.h>
|
||||
#include <libgnome-desktop/gnome-bg.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -35,8 +36,7 @@ typedef enum {
|
||||
CC_BACKGROUND_ITEM_HAS_PLACEMENT = 1 << 1,
|
||||
CC_BACKGROUND_ITEM_HAS_PCOLOR = 1 << 2,
|
||||
CC_BACKGROUND_ITEM_HAS_SCOLOR = 1 << 3,
|
||||
CC_BACKGROUND_ITEM_HAS_URI = 1 << 4,
|
||||
CC_BACKGROUND_ITEM_HAS_URI_DARK = 1 << 5
|
||||
CC_BACKGROUND_ITEM_HAS_URI = 1 << 4
|
||||
} CcBackgroundItemFlags;
|
||||
|
||||
#define CC_BACKGROUND_ITEM_HAS_ALL (CC_BACKGROUND_ITEM_HAS_SHADING & \
|
||||
@@ -47,29 +47,26 @@ typedef enum {
|
||||
|
||||
CcBackgroundItem * cc_background_item_new (const char *uri);
|
||||
CcBackgroundItem * cc_background_item_copy (CcBackgroundItem *item);
|
||||
gboolean cc_background_item_load (CcBackgroundItem *item,
|
||||
GFileInfo *info);
|
||||
gboolean cc_background_item_load (CcBackgroundItem *item,
|
||||
GFileInfo *info);
|
||||
gboolean cc_background_item_changes_with_time (CcBackgroundItem *item);
|
||||
gboolean cc_background_item_has_dark_version (CcBackgroundItem *item);
|
||||
|
||||
GdkPixbuf * cc_background_item_get_thumbnail (CcBackgroundItem *item,
|
||||
GnomeDesktopThumbnailFactory *thumbs,
|
||||
int width,
|
||||
int height,
|
||||
int scale_factor,
|
||||
gboolean dark);
|
||||
int scale_factor);
|
||||
GdkPixbuf * cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
|
||||
GnomeDesktopThumbnailFactory *thumbs,
|
||||
int width,
|
||||
int height,
|
||||
int scale_factor,
|
||||
int frame,
|
||||
gboolean dark);
|
||||
gboolean force_size);
|
||||
|
||||
GDesktopBackgroundStyle cc_background_item_get_placement (CcBackgroundItem *item);
|
||||
GDesktopBackgroundShading cc_background_item_get_shading (CcBackgroundItem *item);
|
||||
const char * cc_background_item_get_uri (CcBackgroundItem *item);
|
||||
const char * cc_background_item_get_uri_dark (CcBackgroundItem *item);
|
||||
const char * cc_background_item_get_source_url (CcBackgroundItem *item);
|
||||
const char * cc_background_item_get_source_xml (CcBackgroundItem *item);
|
||||
CcBackgroundItemFlags cc_background_item_get_flags (CcBackgroundItem *item);
|
||||
@@ -85,3 +82,5 @@ gboolean cc_background_item_compare (CcBackgroundItem *s
|
||||
void cc_background_item_dump (CcBackgroundItem *item);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CC_BACKGROUND_ITEM_H */
|
||||
|
||||
@@ -1,314 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2021 Alexander Mikhaylenko <alexm@gnome.org>
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "cc-background-paintable.h"
|
||||
|
||||
struct _CcBackgroundPaintable
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
BgSource *source;
|
||||
CcBackgroundItem *item;
|
||||
int scale_factor;
|
||||
GtkTextDirection text_direction;
|
||||
|
||||
GdkPaintable *texture;
|
||||
GdkPaintable *dark_texture;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SOURCE,
|
||||
PROP_ITEM,
|
||||
PROP_SCALE_FACTOR,
|
||||
PROP_TEXT_DIRECTION,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static void cc_background_paintable_paintable_init (GdkPaintableInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (CcBackgroundPaintable, cc_background_paintable, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
cc_background_paintable_paintable_init))
|
||||
|
||||
static void
|
||||
update_cache (CcBackgroundPaintable *self)
|
||||
{
|
||||
g_autoptr (GdkPixbuf) pixbuf = NULL;
|
||||
GnomeDesktopThumbnailFactory *factory;
|
||||
int width, height;
|
||||
|
||||
g_clear_object (&self->texture);
|
||||
g_clear_object (&self->dark_texture);
|
||||
|
||||
factory = bg_source_get_thumbnail_factory (self->source);
|
||||
width = bg_source_get_thumbnail_width (self->source);
|
||||
height = bg_source_get_thumbnail_height (self->source);
|
||||
|
||||
pixbuf = cc_background_item_get_thumbnail (self->item,
|
||||
factory,
|
||||
width,
|
||||
height,
|
||||
self->scale_factor,
|
||||
FALSE);
|
||||
|
||||
self->texture = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
|
||||
|
||||
if (cc_background_item_has_dark_version (self->item))
|
||||
{
|
||||
g_autoptr (GdkPixbuf) dark_pixbuf = NULL;
|
||||
|
||||
dark_pixbuf = cc_background_item_get_thumbnail (self->item,
|
||||
factory,
|
||||
width,
|
||||
height,
|
||||
self->scale_factor,
|
||||
TRUE);
|
||||
self->dark_texture = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (dark_pixbuf));
|
||||
}
|
||||
|
||||
gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_paintable_dispose (GObject *object)
|
||||
{
|
||||
CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
|
||||
|
||||
g_clear_object (&self->item);
|
||||
g_clear_object (&self->source);
|
||||
g_clear_object (&self->texture);
|
||||
g_clear_object (&self->dark_texture);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_paintable_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_paintable_constructed (GObject *object)
|
||||
{
|
||||
CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_paintable_parent_class)->constructed (object);
|
||||
|
||||
update_cache (self);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_paintable_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SOURCE:
|
||||
g_value_set_object (value, self->source);
|
||||
break;
|
||||
|
||||
case PROP_ITEM:
|
||||
g_value_set_object (value, self->item);
|
||||
break;
|
||||
|
||||
case PROP_SCALE_FACTOR:
|
||||
g_value_set_int (value, self->scale_factor);
|
||||
break;
|
||||
|
||||
case PROP_TEXT_DIRECTION:
|
||||
g_value_set_enum (value, self->text_direction);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_paintable_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SOURCE:
|
||||
g_set_object (&self->source, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_ITEM:
|
||||
g_set_object (&self->item, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_SCALE_FACTOR:
|
||||
self->scale_factor = g_value_get_int (value);
|
||||
update_cache (self);
|
||||
break;
|
||||
|
||||
case PROP_TEXT_DIRECTION:
|
||||
self->text_direction = g_value_get_enum (value);
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_paintable_class_init (CcBackgroundPaintableClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = cc_background_paintable_dispose;
|
||||
object_class->constructed = cc_background_paintable_constructed;
|
||||
object_class->get_property = cc_background_paintable_get_property;
|
||||
object_class->set_property = cc_background_paintable_set_property;
|
||||
|
||||
properties[PROP_SOURCE] =
|
||||
g_param_spec_object ("source",
|
||||
"Source",
|
||||
"Source",
|
||||
BG_TYPE_SOURCE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_ITEM] =
|
||||
g_param_spec_object ("item",
|
||||
"Item",
|
||||
"Item",
|
||||
CC_TYPE_BACKGROUND_ITEM,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SCALE_FACTOR] =
|
||||
g_param_spec_int ("scale-factor",
|
||||
"Scale Factor",
|
||||
"Scale Factor",
|
||||
1, G_MAXINT, 1,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_TEXT_DIRECTION] =
|
||||
g_param_spec_enum ("text-direction",
|
||||
"Text Direction",
|
||||
"Text Direction",
|
||||
GTK_TYPE_TEXT_DIRECTION,
|
||||
GTK_TEXT_DIR_LTR,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_paintable_init (CcBackgroundPaintable *self)
|
||||
{
|
||||
self->scale_factor = 1;
|
||||
self->text_direction = GTK_TEXT_DIR_LTR;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_paintable_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
|
||||
gboolean is_rtl;
|
||||
|
||||
if (!self->dark_texture)
|
||||
{
|
||||
gdk_paintable_snapshot (self->texture, snapshot, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
is_rtl = self->text_direction == GTK_TEXT_DIR_RTL;
|
||||
|
||||
gtk_snapshot_push_clip (GTK_SNAPSHOT (snapshot),
|
||||
&GRAPHENE_RECT_INIT (is_rtl ? width / 2.0f : 0.0f,
|
||||
0.0f,
|
||||
width / 2.0f,
|
||||
height));
|
||||
gdk_paintable_snapshot (self->texture, snapshot, width, height);
|
||||
gtk_snapshot_pop (GTK_SNAPSHOT (snapshot));
|
||||
|
||||
gtk_snapshot_push_clip (GTK_SNAPSHOT (snapshot),
|
||||
&GRAPHENE_RECT_INIT (is_rtl ? 0.0f : width / 2.0f,
|
||||
0.0f,
|
||||
width / 2.0f,
|
||||
height));
|
||||
gdk_paintable_snapshot (self->dark_texture, snapshot, width, height);
|
||||
gtk_snapshot_pop (GTK_SNAPSHOT (snapshot));
|
||||
}
|
||||
|
||||
static int
|
||||
cc_background_paintable_get_intrinsic_width (GdkPaintable *paintable)
|
||||
{
|
||||
CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
|
||||
|
||||
return gdk_paintable_get_intrinsic_width (self->texture) / self->scale_factor;
|
||||
}
|
||||
|
||||
static int
|
||||
cc_background_paintable_get_intrinsic_height (GdkPaintable *paintable)
|
||||
{
|
||||
CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
|
||||
|
||||
return gdk_paintable_get_intrinsic_height (self->texture) / self->scale_factor;
|
||||
}
|
||||
|
||||
static double
|
||||
cc_background_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
|
||||
{
|
||||
CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
|
||||
|
||||
return gdk_paintable_get_intrinsic_aspect_ratio (self->texture);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_paintable_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = cc_background_paintable_snapshot;
|
||||
iface->get_intrinsic_width = cc_background_paintable_get_intrinsic_width;
|
||||
iface->get_intrinsic_height = cc_background_paintable_get_intrinsic_height;
|
||||
iface->get_intrinsic_aspect_ratio = cc_background_paintable_get_intrinsic_aspect_ratio;
|
||||
}
|
||||
|
||||
CcBackgroundPaintable *
|
||||
cc_background_paintable_new (BgSource *source,
|
||||
CcBackgroundItem *item)
|
||||
{
|
||||
g_return_val_if_fail (BG_IS_SOURCE (source), NULL);
|
||||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||||
|
||||
return g_object_new (CC_TYPE_BACKGROUND_PAINTABLE,
|
||||
"source", source,
|
||||
"item", item,
|
||||
NULL);
|
||||
}
|
||||
@@ -29,202 +29,266 @@
|
||||
|
||||
#include "cc-background-panel.h"
|
||||
|
||||
#include "cc-background-chooser.h"
|
||||
#include "cc-background-chooser-dialog.h"
|
||||
#include "cc-background-item.h"
|
||||
#include "cc-background-preview.h"
|
||||
#include "cc-background-resources.h"
|
||||
#include "cc-background-xml.h"
|
||||
|
||||
#include "bg-pictures-source.h"
|
||||
|
||||
#define WP_PATH_ID "org.gnome.desktop.background"
|
||||
#define WP_LOCK_PATH_ID "org.gnome.desktop.screensaver"
|
||||
#define WP_URI_KEY "picture-uri"
|
||||
#define WP_URI_DARK_KEY "picture-uri-dark"
|
||||
#define WP_OPTIONS_KEY "picture-options"
|
||||
#define WP_SHADING_KEY "color-shading-type"
|
||||
#define WP_PCOLOR_KEY "primary-color"
|
||||
#define WP_SCOLOR_KEY "secondary-color"
|
||||
|
||||
#define INTERFACE_PATH_ID "org.gnome.desktop.interface"
|
||||
#define INTERFACE_COLOR_SCHEME_KEY "color-scheme"
|
||||
|
||||
struct _CcBackgroundPanel
|
||||
{
|
||||
CcPanel parent_instance;
|
||||
|
||||
GtkBuilder *builder;
|
||||
GDBusConnection *connection;
|
||||
|
||||
GSettings *settings;
|
||||
GSettings *lock_settings;
|
||||
GSettings *interface_settings;
|
||||
|
||||
GDBusProxy *proxy;
|
||||
GnomeDesktopThumbnailFactory *thumb_factory;
|
||||
|
||||
CcBackgroundItem *current_background;
|
||||
CcBackgroundItem *current_lock_background;
|
||||
|
||||
CcBackgroundChooser *background_chooser;
|
||||
CcBackgroundPreview *default_preview;
|
||||
CcBackgroundPreview *dark_preview;
|
||||
GtkToggleButton *default_toggle;
|
||||
GtkToggleButton *dark_toggle;
|
||||
GCancellable *copy_cancellable;
|
||||
|
||||
GtkWidget *spinner;
|
||||
GtkWidget *chooser;
|
||||
};
|
||||
|
||||
CC_PANEL_REGISTER (CcBackgroundPanel, cc_background_panel)
|
||||
|
||||
static void
|
||||
load_custom_css (CcBackgroundPanel *self)
|
||||
{
|
||||
g_autoptr(GtkCssProvider) provider = NULL;
|
||||
#define WID(y) (GtkWidget *) gtk_builder_get_object (panel->builder, y)
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/background/preview.css");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
static const char *
|
||||
cc_background_panel_get_help_uri (CcPanel *panel)
|
||||
{
|
||||
return "help:gnome-help/look-background";
|
||||
}
|
||||
|
||||
static void
|
||||
reload_color_scheme_toggles (CcBackgroundPanel *self)
|
||||
cc_background_panel_dispose (GObject *object)
|
||||
{
|
||||
GDesktopColorScheme scheme;
|
||||
CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object);
|
||||
|
||||
scheme = g_settings_get_enum (self->interface_settings, INTERFACE_COLOR_SCHEME_KEY);
|
||||
g_clear_object (&panel->builder);
|
||||
|
||||
if (scheme == G_DESKTOP_COLOR_SCHEME_DEFAULT)
|
||||
/* destroying the builder object will also destroy the spinner */
|
||||
panel->spinner = NULL;
|
||||
|
||||
g_clear_object (&panel->settings);
|
||||
g_clear_object (&panel->lock_settings);
|
||||
|
||||
if (panel->copy_cancellable)
|
||||
{
|
||||
gtk_toggle_button_set_active (self->default_toggle, TRUE);
|
||||
/* cancel any copy operation */
|
||||
g_cancellable_cancel (panel->copy_cancellable);
|
||||
|
||||
g_clear_object (&panel->copy_cancellable);
|
||||
}
|
||||
else if (scheme == G_DESKTOP_COLOR_SCHEME_PREFER_DARK)
|
||||
|
||||
if (panel->chooser)
|
||||
{
|
||||
gtk_toggle_button_set_active (self->dark_toggle, TRUE);
|
||||
gtk_widget_destroy (panel->chooser);
|
||||
panel->chooser = NULL;
|
||||
}
|
||||
|
||||
g_clear_object (&panel->thumb_factory);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_panel_finalize (GObject *object)
|
||||
{
|
||||
CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object);
|
||||
|
||||
g_clear_object (&panel->current_background);
|
||||
g_clear_object (&panel->current_lock_background);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_panel_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_panel_class_init (CcBackgroundPanelClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
|
||||
|
||||
panel_class->get_help_uri = cc_background_panel_get_help_uri;
|
||||
|
||||
object_class->dispose = cc_background_panel_dispose;
|
||||
object_class->finalize = cc_background_panel_finalize;
|
||||
}
|
||||
|
||||
static CcBackgroundItem *
|
||||
get_current_background (CcBackgroundPanel *panel, GSettings *settings)
|
||||
{
|
||||
if (settings == panel->settings)
|
||||
return panel->current_background;
|
||||
else
|
||||
return panel->current_lock_background;
|
||||
}
|
||||
|
||||
static void
|
||||
update_preview (CcBackgroundPanel *panel,
|
||||
GSettings *settings,
|
||||
CcBackgroundItem *item)
|
||||
{
|
||||
gboolean changes_with_time;
|
||||
CcBackgroundItem *current_background;
|
||||
|
||||
current_background = get_current_background (panel, settings);
|
||||
|
||||
if (item && current_background)
|
||||
{
|
||||
g_object_unref (current_background);
|
||||
current_background = cc_background_item_copy (item);
|
||||
if (settings == panel->settings)
|
||||
panel->current_background = current_background;
|
||||
else
|
||||
panel->current_lock_background = current_background;
|
||||
cc_background_item_load (current_background, NULL);
|
||||
}
|
||||
|
||||
changes_with_time = FALSE;
|
||||
|
||||
if (current_background)
|
||||
{
|
||||
changes_with_time = cc_background_item_changes_with_time (current_background);
|
||||
}
|
||||
|
||||
if (settings == panel->settings)
|
||||
{
|
||||
gtk_widget_set_visible (WID ("slide_image"), changes_with_time);
|
||||
gtk_widget_set_visible (WID ("slide-label"), changes_with_time);
|
||||
|
||||
gtk_widget_queue_draw (WID ("background-desktop-drawingarea"));
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_toggle_button_set_active (self->default_toggle, FALSE);
|
||||
gtk_toggle_button_set_active (self->dark_toggle, FALSE);
|
||||
gtk_widget_set_visible (WID ("slide_image1"), changes_with_time);
|
||||
gtk_widget_set_visible (WID ("slide-label1"), changes_with_time);
|
||||
|
||||
gtk_widget_queue_draw (WID ("background-lock-drawingarea"));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
transition_screen (CcBackgroundPanel *self)
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
if (!self->proxy)
|
||||
return;
|
||||
|
||||
g_dbus_proxy_call_sync (self->proxy,
|
||||
"ScreenTransition",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
&error);
|
||||
|
||||
if (error)
|
||||
g_warning ("Couldn't transition screen: %s", error->message);
|
||||
}
|
||||
|
||||
static void
|
||||
set_color_scheme (CcBackgroundPanel *self,
|
||||
GDesktopColorScheme color_scheme)
|
||||
{
|
||||
GDesktopColorScheme scheme;
|
||||
|
||||
scheme = g_settings_get_enum (self->interface_settings,
|
||||
INTERFACE_COLOR_SCHEME_KEY);
|
||||
|
||||
/* We have to check the equality manually to avoid starting an unnecessary
|
||||
* screen transition */
|
||||
if (color_scheme == scheme)
|
||||
return;
|
||||
|
||||
transition_screen (self);
|
||||
|
||||
g_settings_set_enum (self->interface_settings,
|
||||
INTERFACE_COLOR_SCHEME_KEY,
|
||||
color_scheme);
|
||||
}
|
||||
|
||||
/* Color schemes */
|
||||
|
||||
static void
|
||||
on_color_scheme_toggle_active_cb (CcBackgroundPanel *self)
|
||||
{
|
||||
if (gtk_toggle_button_get_active (self->default_toggle))
|
||||
set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_DEFAULT);
|
||||
else if (gtk_toggle_button_get_active (self->dark_toggle))
|
||||
set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_PREFER_DARK);
|
||||
}
|
||||
|
||||
static void
|
||||
got_transition_proxy_cb (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
CcBackgroundPanel *self = data;
|
||||
|
||||
self->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
|
||||
|
||||
if (self->proxy == NULL)
|
||||
{
|
||||
g_warning ("Error creating proxy: %s", error->message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Background */
|
||||
|
||||
static void
|
||||
update_preview (CcBackgroundPanel *self)
|
||||
{
|
||||
CcBackgroundItem *current_background;
|
||||
|
||||
current_background = self->current_background;
|
||||
cc_background_preview_set_item (self->default_preview, current_background);
|
||||
cc_background_preview_set_item (self->dark_preview, current_background);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_save_path (void)
|
||||
get_save_path (CcBackgroundPanel *panel, GSettings *settings)
|
||||
{
|
||||
return g_build_filename (g_get_user_config_dir (),
|
||||
"gnome-control-center",
|
||||
"backgrounds",
|
||||
"last-edited.xml",
|
||||
settings == panel->settings ? "last-edited.xml" : "last-edited-lock.xml",
|
||||
NULL);
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
get_or_create_cached_pixbuf (CcBackgroundPanel *panel,
|
||||
GtkWidget *widget,
|
||||
CcBackgroundItem *background)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
const gint preview_width = 309;
|
||||
const gint preview_height = 168;
|
||||
gint scale_factor;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
pixbuf = g_object_get_data (G_OBJECT (background), "pixbuf");
|
||||
if (pixbuf == NULL)
|
||||
{
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
scale_factor = gtk_widget_get_scale_factor (widget);
|
||||
pixbuf = cc_background_item_get_frame_thumbnail (background,
|
||||
panel->thumb_factory,
|
||||
preview_width,
|
||||
preview_height,
|
||||
scale_factor,
|
||||
-2, TRUE);
|
||||
g_object_set_data_full (G_OBJECT (background), "pixbuf", pixbuf, g_object_unref);
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
reload_current_bg (CcBackgroundPanel *self)
|
||||
update_display_preview (CcBackgroundPanel *panel,
|
||||
GtkWidget *widget,
|
||||
CcBackgroundItem *background)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
cairo_t *cr;
|
||||
|
||||
pixbuf = get_or_create_cached_pixbuf (panel, widget, background);
|
||||
|
||||
cr = gdk_cairo_create (gtk_widget_get_window (widget));
|
||||
gdk_cairo_set_source_pixbuf (cr,
|
||||
pixbuf,
|
||||
0, 0);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_preview_draw (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
CcBackgroundPanel *panel)
|
||||
{
|
||||
update_display_preview (panel, widget, panel->current_background);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_lock_preview_draw (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
CcBackgroundPanel *panel)
|
||||
{
|
||||
update_display_preview (panel, widget, panel->current_lock_background);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
reload_current_bg (CcBackgroundPanel *panel,
|
||||
GSettings *settings)
|
||||
{
|
||||
g_autoptr(CcBackgroundItem) saved = NULL;
|
||||
CcBackgroundItem *configured;
|
||||
GSettings *settings = NULL;
|
||||
g_autofree gchar *uri = NULL;
|
||||
g_autofree gchar *dark_uri = NULL;
|
||||
g_autofree gchar *pcolor = NULL;
|
||||
g_autofree gchar *scolor = NULL;
|
||||
|
||||
/* Load the saved configuration */
|
||||
uri = get_save_path ();
|
||||
uri = get_save_path (panel, settings);
|
||||
saved = cc_background_xml_get_item (uri);
|
||||
|
||||
/* initalise the current background information from settings */
|
||||
settings = self->settings;
|
||||
uri = g_settings_get_string (settings, WP_URI_KEY);
|
||||
if (uri && *uri == '\0')
|
||||
g_clear_pointer (&uri, g_free);
|
||||
|
||||
|
||||
{
|
||||
g_clear_pointer (&uri, g_free);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_autoptr(GFile) file = NULL;
|
||||
file = g_file_new_for_commandline_arg (uri);
|
||||
}
|
||||
configured = cc_background_item_new (uri);
|
||||
|
||||
dark_uri = g_settings_get_string (settings, WP_URI_DARK_KEY);
|
||||
pcolor = g_settings_get_string (settings, WP_PCOLOR_KEY);
|
||||
scolor = g_settings_get_string (settings, WP_SCOLOR_KEY);
|
||||
g_object_set (G_OBJECT (configured),
|
||||
"name", _("Current background"),
|
||||
"uri-dark", dark_uri,
|
||||
"placement", g_settings_get_enum (settings, WP_OPTIONS_KEY),
|
||||
"shading", g_settings_get_enum (settings, WP_SHADING_KEY),
|
||||
"primary-color", pcolor,
|
||||
@@ -246,8 +310,16 @@ reload_current_bg (CcBackgroundPanel *self)
|
||||
NULL);
|
||||
}
|
||||
|
||||
g_clear_object (&self->current_background);
|
||||
self->current_background = configured;
|
||||
if (settings == panel->settings)
|
||||
{
|
||||
g_clear_object (&panel->current_background);
|
||||
panel->current_background = configured;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_clear_object (&panel->current_lock_background);
|
||||
panel->current_lock_background = configured;
|
||||
}
|
||||
cc_background_item_load (configured, NULL);
|
||||
}
|
||||
|
||||
@@ -269,63 +341,64 @@ create_save_dir (void)
|
||||
}
|
||||
|
||||
static void
|
||||
reset_settings_if_defaults (CcBackgroundPanel *self,
|
||||
GSettings *settings,
|
||||
gboolean check_dark)
|
||||
copy_finished_cb (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer pointer)
|
||||
{
|
||||
gsize i;
|
||||
const char *keys[] = {
|
||||
WP_URI_KEY, /* this key needs to be first */
|
||||
WP_URI_DARK_KEY,
|
||||
WP_OPTIONS_KEY,
|
||||
WP_SHADING_KEY,
|
||||
WP_PCOLOR_KEY,
|
||||
WP_SCOLOR_KEY,
|
||||
NULL
|
||||
};
|
||||
g_autoptr(GError) err = NULL;
|
||||
g_autoptr(CcBackgroundPanel) panel = (CcBackgroundPanel *) pointer;
|
||||
CcBackgroundItem *item;
|
||||
CcBackgroundItem *current_background;
|
||||
GSettings *settings;
|
||||
|
||||
for (i = 0; keys[i] != NULL; i++)
|
||||
if (!g_file_copy_finish (G_FILE (source_object), result, &err))
|
||||
{
|
||||
g_autoptr (GVariant) default_value = NULL;
|
||||
g_autoptr (GVariant) user_value = NULL;
|
||||
gboolean setting_is_default;
|
||||
|
||||
if (!check_dark && g_str_equal (keys[i], WP_URI_DARK_KEY))
|
||||
continue;
|
||||
|
||||
default_value = g_settings_get_default_value (settings, keys[i]);
|
||||
user_value = g_settings_get_value (settings, keys[i]);
|
||||
|
||||
setting_is_default = g_variant_equal (default_value, user_value);
|
||||
|
||||
/* As a courtesy to distros that are a little lackadaisical about making sure
|
||||
* schema defaults match the settings in the background item with the default
|
||||
* picture, we only look at the URI to determine if we shouldn't clean out dconf.
|
||||
*
|
||||
* In otherwords, we still clean out the picture-uri key from dconf when a user
|
||||
* selects the default background in control-center, even if after selecting it
|
||||
* e.g., primary-color still mismatches with schema defaults.
|
||||
*/
|
||||
if (g_str_equal (keys[i], WP_URI_KEY) && !setting_is_default)
|
||||
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
return;
|
||||
|
||||
if (setting_is_default)
|
||||
g_settings_reset (settings, keys[i]);
|
||||
}
|
||||
g_warning ("Failed to copy image to cache location: %s", err->message);
|
||||
}
|
||||
item = g_object_get_data (source_object, "item");
|
||||
settings = g_object_get_data (source_object, "settings");
|
||||
current_background = get_current_background (panel, settings);
|
||||
|
||||
g_settings_apply (settings);
|
||||
|
||||
/* the panel may have been destroyed before the callback is run, so be sure
|
||||
* to check the widgets are not NULL */
|
||||
|
||||
if (panel->spinner)
|
||||
{
|
||||
gtk_widget_destroy (GTK_WIDGET (panel->spinner));
|
||||
panel->spinner = NULL;
|
||||
}
|
||||
|
||||
if (current_background)
|
||||
cc_background_item_load (current_background, NULL);
|
||||
|
||||
if (panel->builder)
|
||||
{
|
||||
g_autofree gchar *filename = NULL;
|
||||
|
||||
update_preview (panel, settings, item);
|
||||
current_background = get_current_background (panel, settings);
|
||||
|
||||
/* Save the source XML if there is one */
|
||||
filename = get_save_path (panel, settings);
|
||||
if (create_save_dir ())
|
||||
cc_background_xml_save (current_background, filename);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_background (CcBackgroundPanel *self,
|
||||
set_background (CcBackgroundPanel *panel,
|
||||
GSettings *settings,
|
||||
CcBackgroundItem *item,
|
||||
gboolean set_dark)
|
||||
CcBackgroundItem *item)
|
||||
{
|
||||
GDesktopBackgroundStyle style;
|
||||
CcBackgroundItemFlags flags;
|
||||
g_autofree gchar *filename = NULL;
|
||||
gboolean save_settings = TRUE;
|
||||
const char *uri;
|
||||
CcBackgroundItemFlags flags;
|
||||
|
||||
if (item == NULL)
|
||||
return;
|
||||
@@ -333,18 +406,85 @@ set_background (CcBackgroundPanel *self,
|
||||
uri = cc_background_item_get_uri (item);
|
||||
flags = cc_background_item_get_flags (item);
|
||||
|
||||
g_settings_set_string (settings, WP_URI_KEY, uri);
|
||||
|
||||
if (set_dark)
|
||||
if ((flags & CC_BACKGROUND_ITEM_HAS_URI) && uri == NULL)
|
||||
{
|
||||
const char *uri_dark;
|
||||
g_settings_set_enum (settings, WP_OPTIONS_KEY, G_DESKTOP_BACKGROUND_STYLE_NONE);
|
||||
g_settings_set_string (settings, WP_URI_KEY, "");
|
||||
}
|
||||
else if (cc_background_item_get_source_url (item) != NULL &&
|
||||
cc_background_item_get_needs_download (item))
|
||||
{
|
||||
g_autoptr(GFile) source = NULL;
|
||||
g_autoptr(GFile) dest = NULL;
|
||||
g_autofree gchar *cache_path = NULL;
|
||||
g_autofree gchar *basename = NULL;
|
||||
g_autofree gchar *display_name = NULL;
|
||||
g_autofree gchar *dest_path = NULL;
|
||||
g_autofree gchar *dest_uri = NULL;
|
||||
g_autoptr(GdkPixbuf) pixbuf = NULL;
|
||||
|
||||
uri_dark = cc_background_item_get_uri_dark (item);
|
||||
cache_path = bg_pictures_source_get_cache_path ();
|
||||
if (g_mkdir_with_parents (cache_path, USER_DIR_MODE) < 0)
|
||||
{
|
||||
g_warning ("Failed to create directory '%s'", cache_path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uri_dark && uri_dark[0])
|
||||
g_settings_set_string (settings, WP_URI_DARK_KEY, uri_dark);
|
||||
else
|
||||
g_settings_set_string (settings, WP_URI_DARK_KEY, uri);
|
||||
dest_path = bg_pictures_source_get_unique_path (cc_background_item_get_source_url (item));
|
||||
dest = g_file_new_for_path (dest_path);
|
||||
source = g_file_new_for_uri (cc_background_item_get_source_url (item));
|
||||
basename = g_file_get_basename (source);
|
||||
display_name = g_filename_display_name (basename);
|
||||
dest_path = g_file_get_path (dest);
|
||||
|
||||
/* create a blank image to use until the source image is ready */
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
|
||||
gdk_pixbuf_fill (pixbuf, 0x00000000);
|
||||
gdk_pixbuf_save (pixbuf, dest_path, "png", NULL, NULL);
|
||||
|
||||
if (panel->copy_cancellable)
|
||||
{
|
||||
g_cancellable_cancel (panel->copy_cancellable);
|
||||
g_cancellable_reset (panel->copy_cancellable);
|
||||
}
|
||||
|
||||
if (panel->spinner)
|
||||
{
|
||||
gtk_widget_destroy (GTK_WIDGET (panel->spinner));
|
||||
panel->spinner = NULL;
|
||||
}
|
||||
|
||||
/* create a spinner while the file downloads */
|
||||
panel->spinner = gtk_spinner_new ();
|
||||
gtk_spinner_start (GTK_SPINNER (panel->spinner));
|
||||
gtk_box_pack_start (GTK_BOX (WID ("bottom-hbox")), panel->spinner, FALSE,
|
||||
FALSE, 6);
|
||||
gtk_widget_show (panel->spinner);
|
||||
|
||||
/* reference the panel in case it is removed before the copy is
|
||||
* finished */
|
||||
g_object_ref (panel);
|
||||
g_object_set_data_full (G_OBJECT (source), "item", g_object_ref (item), g_object_unref);
|
||||
g_object_set_data (G_OBJECT (source), "settings", settings);
|
||||
g_file_copy_async (source, dest, G_FILE_COPY_OVERWRITE,
|
||||
G_PRIORITY_DEFAULT, panel->copy_cancellable,
|
||||
NULL, NULL,
|
||||
copy_finished_cb, panel);
|
||||
dest_uri = g_file_get_uri (dest);
|
||||
|
||||
g_settings_set_string (settings, WP_URI_KEY, dest_uri);
|
||||
g_object_set (G_OBJECT (item),
|
||||
"uri", dest_uri,
|
||||
"needs-download", FALSE,
|
||||
"name", display_name,
|
||||
NULL);
|
||||
|
||||
/* delay the updated drawing of the preview until the copy finishes */
|
||||
save_settings = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_settings_set_string (settings, WP_URI_KEY, uri);
|
||||
}
|
||||
|
||||
/* Also set the placement if we have a URI and the previous value was none */
|
||||
@@ -365,138 +505,131 @@ set_background (CcBackgroundPanel *self,
|
||||
g_settings_set_string (settings, WP_PCOLOR_KEY, cc_background_item_get_pcolor (item));
|
||||
g_settings_set_string (settings, WP_SCOLOR_KEY, cc_background_item_get_scolor (item));
|
||||
|
||||
/* Apply all changes */
|
||||
g_settings_apply (settings);
|
||||
/* update the preview information */
|
||||
if (save_settings != FALSE)
|
||||
{
|
||||
g_autofree gchar *filename = NULL;
|
||||
|
||||
/* Clean out dconf if the user went back to distro defaults */
|
||||
reset_settings_if_defaults (self, settings, set_dark);
|
||||
/* Apply all changes */
|
||||
g_settings_apply (settings);
|
||||
|
||||
/* Save the source XML if there is one */
|
||||
filename = get_save_path ();
|
||||
if (create_save_dir ())
|
||||
cc_background_xml_save (self->current_background, filename);
|
||||
/* Save the source XML if there is one */
|
||||
filename = get_save_path (panel, settings);
|
||||
if (create_save_dir ())
|
||||
cc_background_xml_save (get_current_background (panel, settings), filename);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_chooser_background_chosen_cb (CcBackgroundPanel *self,
|
||||
CcBackgroundItem *item)
|
||||
on_chooser_dialog_response (GtkDialog *dialog,
|
||||
int response_id,
|
||||
CcBackgroundPanel *panel)
|
||||
{
|
||||
set_background (self, self->settings, item, TRUE);
|
||||
set_background (self, self->lock_settings, item, FALSE);
|
||||
if (response_id == GTK_RESPONSE_OK)
|
||||
{
|
||||
g_autoptr(CcBackgroundItem) item = NULL;
|
||||
|
||||
item = cc_background_chooser_dialog_get_item (CC_BACKGROUND_CHOOSER_DIALOG (dialog));
|
||||
if (item != NULL)
|
||||
set_background (panel, g_object_get_data (G_OBJECT (dialog), "settings"), item);
|
||||
}
|
||||
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
on_add_picture_button_clicked_cb (CcBackgroundPanel *self)
|
||||
launch_chooser (CcBackgroundPanel *panel,
|
||||
GSettings *settings)
|
||||
{
|
||||
cc_background_chooser_select_file (self->background_chooser);
|
||||
}
|
||||
GtkWidget *dialog;
|
||||
|
||||
static const char *
|
||||
cc_background_panel_get_help_uri (CcPanel *panel)
|
||||
{
|
||||
return "help:gnome-help/look-background";
|
||||
dialog = cc_background_chooser_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (WID ("background-panel"))));
|
||||
g_object_set_data (G_OBJECT (dialog), "settings", settings);
|
||||
gtk_widget_show (dialog);
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (on_chooser_dialog_response), panel);
|
||||
panel->chooser = dialog;
|
||||
g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer *) &panel->chooser);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_panel_dispose (GObject *object)
|
||||
on_background_button_clicked (GtkButton *button,
|
||||
CcBackgroundPanel *panel)
|
||||
{
|
||||
CcBackgroundPanel *self = CC_BACKGROUND_PANEL (object);
|
||||
|
||||
g_clear_object (&self->settings);
|
||||
g_clear_object (&self->lock_settings);
|
||||
g_clear_object (&self->interface_settings);
|
||||
g_clear_object (&self->proxy);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object);
|
||||
launch_chooser (panel, panel->settings);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_panel_finalize (GObject *object)
|
||||
on_lock_button_clicked (GtkButton *button,
|
||||
CcBackgroundPanel *panel)
|
||||
{
|
||||
CcBackgroundPanel *self = CC_BACKGROUND_PANEL (object);
|
||||
|
||||
g_clear_object (&self->current_background);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_panel_parent_class)->finalize (object);
|
||||
launch_chooser (panel, panel->lock_settings);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_panel_class_init (CcBackgroundPanelClass *klass)
|
||||
on_settings_changed (GSettings *settings,
|
||||
gchar *key,
|
||||
CcBackgroundPanel *panel)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
g_type_ensure (CC_TYPE_BACKGROUND_CHOOSER);
|
||||
g_type_ensure (CC_TYPE_BACKGROUND_PREVIEW);
|
||||
|
||||
panel_class->get_help_uri = cc_background_panel_get_help_uri;
|
||||
|
||||
object_class->dispose = cc_background_panel_dispose;
|
||||
object_class->finalize = cc_background_panel_finalize;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-panel.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, background_chooser);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_preview);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_preview);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_toggle);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_toggle);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_color_scheme_toggle_active_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_chooser_background_chosen_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_add_picture_button_clicked_cb);
|
||||
reload_current_bg (panel, settings);
|
||||
update_preview (panel, settings, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_settings_changed (CcBackgroundPanel *self)
|
||||
cc_background_panel_init (CcBackgroundPanel *panel)
|
||||
{
|
||||
reload_current_bg (self);
|
||||
update_preview (self);
|
||||
}
|
||||
gchar *objects[] = {"background-panel", NULL };
|
||||
g_autoptr(GError) err = NULL;
|
||||
GtkWidget *widget;
|
||||
|
||||
static void
|
||||
cc_background_panel_init (CcBackgroundPanel *self)
|
||||
{
|
||||
panel->connection = g_application_get_dbus_connection (g_application_get_default ());
|
||||
g_resources_register (cc_background_get_resource ());
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
panel->builder = gtk_builder_new ();
|
||||
gtk_builder_add_objects_from_resource (panel->builder,
|
||||
"/org/gnome/control-center/background/background.ui",
|
||||
objects, &err);
|
||||
|
||||
self->connection = g_application_get_dbus_connection (g_application_get_default ());
|
||||
if (err)
|
||||
{
|
||||
g_warning ("Could not load ui: %s", err->message);
|
||||
return;
|
||||
}
|
||||
|
||||
self->settings = g_settings_new (WP_PATH_ID);
|
||||
g_settings_delay (self->settings);
|
||||
|
||||
self->lock_settings = g_settings_new (WP_LOCK_PATH_ID);
|
||||
g_settings_delay (self->lock_settings);
|
||||
panel->settings = g_settings_new (WP_PATH_ID);
|
||||
g_settings_delay (panel->settings);
|
||||
|
||||
self->interface_settings = g_settings_new (INTERFACE_PATH_ID);
|
||||
panel->lock_settings = g_settings_new (WP_LOCK_PATH_ID);
|
||||
g_settings_delay (panel->lock_settings);
|
||||
|
||||
/* Load the background */
|
||||
reload_current_bg (self);
|
||||
update_preview (self);
|
||||
/* add the top level widget */
|
||||
widget = WID ("background-panel");
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (panel), widget);
|
||||
gtk_widget_show_all (GTK_WIDGET (panel));
|
||||
|
||||
/* setup preview area */
|
||||
widget = WID ("background-desktop-drawingarea");
|
||||
g_signal_connect (widget, "draw", G_CALLBACK (on_preview_draw), panel);
|
||||
widget = WID ("background-lock-drawingarea");
|
||||
g_signal_connect (widget, "draw", G_CALLBACK (on_lock_preview_draw), panel);
|
||||
|
||||
panel->copy_cancellable = g_cancellable_new ();
|
||||
|
||||
panel->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
|
||||
|
||||
/* Load the backgrounds */
|
||||
reload_current_bg (panel, panel->settings);
|
||||
update_preview (panel, panel->settings, NULL);
|
||||
reload_current_bg (panel, panel->lock_settings);
|
||||
update_preview (panel, panel->lock_settings, NULL);
|
||||
|
||||
/* Background settings */
|
||||
g_signal_connect_object (self->settings, "changed", G_CALLBACK (on_settings_changed), self, G_CONNECT_SWAPPED);
|
||||
g_signal_connect (panel->settings, "changed", G_CALLBACK (on_settings_changed), panel);
|
||||
g_signal_connect (panel->lock_settings, "changed", G_CALLBACK (on_settings_changed), panel);
|
||||
|
||||
/* Interface settings */
|
||||
reload_color_scheme_toggles (self);
|
||||
|
||||
g_signal_connect_object (self->interface_settings,
|
||||
"changed::" INTERFACE_COLOR_SCHEME_KEY,
|
||||
G_CALLBACK (reload_color_scheme_toggles),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL,
|
||||
"org.gnome.Shell",
|
||||
"/org/gnome/Shell",
|
||||
"org.gnome.Shell",
|
||||
NULL,
|
||||
got_transition_proxy_cb,
|
||||
self);
|
||||
|
||||
load_custom_css (self);
|
||||
/* Background buttons */
|
||||
widget = WID ("background-set-button");
|
||||
g_signal_connect (widget, "clicked", G_CALLBACK (on_background_button_clicked), panel);
|
||||
widget = WID ("background-lock-set-button");
|
||||
g_signal_connect (widget, "clicked", G_CALLBACK (on_lock_button_clicked), panel);
|
||||
}
|
||||
|
||||