Compare commits

..

5 Commits

Author SHA1 Message Date
Georges Basile Stavracas Neto
a7cb8295fe EOL master 2022-04-26 15:46:10 -03:00
Anders Jonsson
f948a56f98 Update Swedish translation 2022-04-26 18:26:44 +00:00
Yuri Chornoivan
58f5ea715c Update Ukrainian translation 2022-04-26 17:39:23 +00:00
Felipe Borges
5284a1d410 multitasking: Add some new keywords to desktop file
While searching in the Shell, users might input the keywords "Hot
Corner" and "Workspaces".

Fixes #1784
2022-04-26 17:23:45 +00:00
Michael Catanzaro
46bc354cfb sound: remove dog bark sound theme
You're welcome, internet.
2022-04-26 17:17:41 +00:00
1248 changed files with 1 additions and 1389255 deletions

View File

@@ -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

6
.gitignore vendored
View File

@@ -1,6 +0,0 @@
__pycache__
_build/
**/*~
/subprojects/*
!/subprojects/*.wrap
.flatpak-builder/

View File

@@ -1,438 +0,0 @@
include:
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/34f4ade99434043f88e164933f570301fd18b125/templates/fedora.yml'
variables:
FDO_UPSTREAM_REPO: gnome/gnome-control-center
stages:
- prepare
- build
- test
- manual
- deploy
.Log files: &log_files [./*.log, _build/meson-logs/]
.Build logs: &save_build_logs
artifacts:
name: log
when: always
paths: *log_files
.Git Untracked files: &save_untracked_files
artifacts:
name: untracked
paths: [$(pwd)]
expire_in: 3h30min
.Show Info: &environment_information
build-aux/ci/ci-helper.sh "INFO" &&
build-aux/ci/ci-helper.sh "GIT_INFO"
.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 &&
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 ..
##
# Stage: Build
#
# Checks if GNOME Control Center is properly building and installing. This is the
# most important stage of the CI, and no MR should ever be merged if it breaks
# any of them.
##
build:
extends:
- '.fdo.distribution-image@fedora'
- '.fedora.container.common'
<<: *save_untracked_files
stage: build
script:
- *environment_information
- *build_procedure
- echo "== Installing =="
- ninja -C _build install
- echo "== Report =="
- build-aux/ci/ci-helper.sh "WARNINGS"
# 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
dependencies:
- build
script:
- *environment_information
- *build_procedure
- *run_tests
- |
if [[ -n "${CI_COMMIT_TAG}" ]]; then
echo "== Distro Test =="
ninja dist -C _build
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
script:
- *environment_information
- *build_procedure
- *run_tests
- ninja -C _build coverage-html
# Parse the report to get the coverage result
- |
echo == Coverage ==
sed -e 's/<[^>]*>//g' _build/meson-logs/coveragereport/index.html | tr -d ' \t' | grep -A3 -P '^Lines:$' | tr '\n' ' '; echo
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
- $CI_COMMIT_TITLE =~ /^Update.*translation$/
# Runs the address sanitizer.
# - below, at the "sanitizers section"
##
# Stage: Deploy
#
# Publishes the Coverage Report generated above
##
pages:
extends:
- '.fdo.distribution-image@fedora'
- '.fedora.container.common'
stage: deploy
dependencies:
- coverage
script:
- mv _build/meson-logs/coveragereport/ public/
artifacts:
paths:
- public
only:
- main@GNOME/gnome-control-center
except:
variables:
- $CRON_TASK == "BUILD_CI_IMAGES"
- $CI_COMMIT_TITLE =~ /^Update.*translation$/
##
# Stage: Manual
#
# Creates a flatpak
##
flatpak:
stage: manual
image: quay.io/gnome_infrastructure/gnome-runtime-images:gnome-master
artifacts:
name: package
paths:
- $(pwd)/*.flatpak
expire_in: 7 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"
PROJECT_ID: "org.gnome.Settings"
PROJECT_NAME: "gnome-control-center.git"
RUNTIME_REPO: "https://sdk.gnome.org/gnome-nightly.flatpakrepo"
script:
- echo "== Flatpak packaging =="
# Make it a develoment manifest
- sed -i -n "p; s/$PROJECT_NAME//p" ${MANIFEST_PATH}
- >
sed -i "s,\"app-id\" : \"$PROJECT_ID\",\"app-id\" : \"<<ID>>\",g" ${MANIFEST_PATH}
- >
sed -i "s,\"url\" : \"https://gitlab.gnome.org/GNOME/$PROJECT_NAME\",\"branch\" : \"<<current>>\"\,,g" ${MANIFEST_PATH}
- >
sed -i "s,\"url\" : \"https://gitlab.gnome.org/GNOME/\",\"path\" : \".\",g" ${MANIFEST_PATH}
# Adjust the manifest to HEAD
- 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 build-bundle devel ${BUNDLE} --runtime-repo=${RUNTIME_REPO} ${APPID}
cache:
paths:
- .flatpak-builder/cache
when: manual
except:
- tags
- gnome-3-.*
- main@GNOME/gnome-control-center
# 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
script:
- *environment_information
- *build_procedure
- *run_tests
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"
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"

View File

@@ -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()

View File

@@ -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 were 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 "Couldnt 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. Thats why this CI check is OK
# to fail: the idea is that people can look through the output and ignore it if
# its wrong. (That situation can also happen if someone touches pre-existing
# badly formatted code and it doesnt make sense to tidy up the wider coding
# style with the changes theyre 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}

View File

@@ -1,32 +0,0 @@
<!--
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:
1. Open GNOME Settings
2. Change X to something else
3. ...

View File

@@ -1,41 +0,0 @@
# Current problems
<!--
What are the problems that the current project has?
For example:
* User cannot use the keyboard to perform most common actions
or
* User cannot see documents from cloud services
-->
# Goals & use cases
<!--
What are the use cases that this proposal will cover? What are the end goals?
For example:
* User needs to share a file with their friends.
or
* It should be easy to edit a picture within the app.
-->
# Requirements
<!--
What does the solution needs to ensure for being succesful?
For example:
* Work on small form factors and touch
or
* Use the Meson build system and integrate with it
-->
# Relevant art
<!--
Is there any product that has implemented something similar? Put links to other
projects, pictures, links to other code, etc.
-->
# Proposal & plan
<!-- What's the solution and how should be achieved? It can be split in smaller
tasks of minimum change, so they can be delivered across several releases. -->
/label ~"1. Epic"

View File

@@ -1,27 +0,0 @@
<!--
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:
(Add mockups of the proposed feature)
## Design Tasks
* [ ] design tasks
## Development Tasks
* [ ] development tasks
## QA Tasks
* [ ] qa (quality assurance) tasks

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "subprojects/gvc"]
path = subprojects/gvc
url = https://gitlab.gnome.org/GNOME/libgnome-volume-control.git

340
COPYING
View File

@@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

10711
NEWS

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1 @@
[![Build Status](https://gitlab.gnome.org/GNOME/gnome-control-center/badges/main/pipeline.svg)](https://gitlab.gnome.org/GNOME/gnome-control-center/pipelines)
[![Coverage report](https://gitlab.gnome.org/GNOME/gnome-control-center/badges/main/coverage.svg)](https://gnome.pages.gitlab.gnome.org/gnome-control-center/)
[![License](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/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).
## Contributing
See `docs/CONTRIBUTING.md` for details on the contribution process, and `docs/CODING_STYLE.md`
for the coding style guidelines.
Visit the [Settings development wiki](https://gitlab.gnome.org/GNOME/gnome-control-center/-/wikis/home) for more information.
This branch is now unused. Please use the `main` branch for development.

View File

@@ -1,61 +0,0 @@
#!/bin/bash -e
function do_print_labels(){
if [[ -n "${1}" ]]; then
label_len=${#1}
span=$(((54 - $label_len) / 2))
echo
echo "= ======================================================== ="
printf "%s %${span}s %s %${span}s %s\n" "=" "" "$1" "" "="
echo "= ======================================================== ="
else
echo "= ========================= Done ========================= ="
echo
fi
}
function do_show_info(){
local compiler=gcc
echo -n "Processors: "; grep -c ^processor /proc/cpuinfo
grep ^MemTotal /proc/meminfo
id; uname -a
printenv
echo '-----------------------------------------'
cat /etc/*-release
echo '-----------------------------------------'
if [[ ! -z $CC ]]; then
compiler=$CC
fi
echo 'Compiler version'
$compiler --version
echo '-----------------------------------------'
$compiler -dM -E -x c /dev/null
echo '-----------------------------------------'
}
function do_check_warnings(){
cat compilation.log | grep "warning:" | awk '{total+=1}END{print "Total number of warnings: "total}'
}
# ----------- -----------
if [[ $1 == "INFO" ]]; then
do_print_labels 'Build environment '
do_show_info
do_print_labels
elif [[ $1 == "GIT_INFO" ]]; then
do_print_labels 'Commit'
git log --pretty=format:"%h %cd %s" -1; echo
do_print_labels
elif [[ $1 == "WARNINGS" ]]; then
do_print_labels 'Warning Report '
do_check_warnings
do_print_labels
fi

View File

@@ -1,19 +0,0 @@
# https://bugs.freedesktop.org/show_bug.cgi?id=105466
leak:libfontconfig.so.1
# Unknown and unreported bugs
leak:__GI___vasprintf_chk
leak:__interceptor_malloc
leak:__alloc_dir
leak:libglib-2.0.so.0
# Needing attention
leak:<unknown module>
leak:test_timezone_gfx
########
# __GI___vasprintf_chk /usr/src/debug/glibc-2.27.9000-432-g104502102c/debug/vasprintf_chk.c:80
# __alloc_dir ../sysdeps/posix/opendir.c:118
# g_malloc (/lib64/libglib-2.0.so.0+0x523c5)
# g_realloc (/lib64/libglib-2.0.so.0+0x5247d)
########

View File

@@ -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

View File

@@ -1,845 +0,0 @@
{
"app-id" : "org.gnome.Settings",
"runtime" : "org.gnome.Sdk",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gnome-control-center",
"tags" : [
"devel"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"--device=dri",
"--env=DCONF_USER_CONFIG_DIR=.config/dconf",
"--filesystem=host",
"--own-name=org.gnome.SessionManager",
"--share=ipc",
"--share=network",
"--socket=x11",
"--socket=pulseaudio",
"--socket=session-bus",
"--socket=system-bus",
"--socket=wayland"
],
"build-options" : {
"cflags" : "-O2 -g",
"cxxflags" : "-O2 -g",
"env" : {
"V" : "1"
},
"build-args": [
"--share=network"
]
},
"x-run-args" : [
"--verbose"
],
"cleanup" : [
"/include",
"/share/aclocal",
"/man",
"/share/man",
"/share/gtk-doc",
"/share/vala",
"*.la",
"*.a"
],
"modules" : [
{
"name" : "pwquality",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-python-bindings"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/libpwquality/libpwquality.git"
}
]
},
{
"name" : "intltool",
"cleanup" : [ "*" ],
"sources" : [
{
"type" : "archive",
"url" : "https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz",
"sha256" : "67c74d94196b153b774ab9f89b2fa6c6ba79352407037c8c14d5aeb334e959cd"
}
]
},
{
"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"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/accountsservice/accountsservice",
"branch" : "main"
}
]
},
{
"name" : "libusb1",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-udev"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/libusb/libusb.git"
}
]
},
{
"name" : "gusb",
"buildsystem" : "meson",
"config-opts" : [
"-Ddocs=false",
"-Dtests=false",
"-Dvapi=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/hughsie/libgusb.git",
"branch" : "main"
}
]
},
{
"name" : "udev",
"config-opts" : [
"--disable-hwdb",
"--disable-logging",
"--disable-gudev",
"--disable-introspection",
"--disable-keymap",
"--disable-mtd_probe"
],
"cleanup" : [
"/include",
"/etc",
"/libexec",
"/sbin",
"/lib/pkgconfig",
"/man",
"/share/aclocal",
"/share/doc",
"/share/gtk-doc",
"/share/man",
"/share/pkgconfig",
"*.la",
"*.a"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/gentoo/eudev.git"
}
]
},
{
"name" : "colord",
"buildsystem" : "meson",
"config-opts" : [
"-Dargyllcms_sensor=false",
"-Dbash_completion=false",
"-Dman=false",
"-Dudev_rules=false",
"-Dsystemd=false",
"-Dvapi=false",
"-Ddocs=false",
"-Dtests=false",
"-Dinstalled_tests=false"
],
"sources" : [
{
"type" : "git",
"branch" : "main",
"url" : "https://github.com/hughsie/colord.git"
}
]
},
{
"name" : "colord-gtk",
"buildsystem" : "meson",
"config-opts" : [
"-Dman=false"
],
"sources" : [
{
"type" : "git",
"branch" : "main",
"url" : "https://github.com/hughsie/colord-gtk.git"
}
]
},
{
"name" : "rest",
"buildsystem" : "meson",
"config-opts" : [
"-Dgtk_doc=false"
],
"sources" : [
{
"type" : "git",
"branch" : "master",
"url" : "https://gitlab.gnome.org/GNOME/librest.git"
}
]
},
{
"name" : "gnome-online-accounts",
"buildsystem" : "meson",
"build-options" : {
"cflags" : "-Wno-error"
},
"config-opts" : [
"-Dgtk_doc=false",
"-Dintrospection=false",
"-Dvapi=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gnome-online-accounts.git"
}
]
},
{
"name" : "gnome-desktop",
"buildsystem" : "meson",
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gnome-desktop.git"
}
]
},
{
"name" : "geocode-glib",
"buildsystem" : "meson",
"config-opts" : [
"-Denable-installed-tests=false",
"-Denable-introspection=false",
"-Denable-gtk-doc=false",
"-Dsoup2=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/geocode-glib.git"
}
]
},
{
"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"
}
]
},
{
"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"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/upower/upower.git",
"tag" : "v1.90.2"
}
]
},
{
"name" : "libwacom",
"buildsystem" : "meson",
"config-opts" : [
"-Ddocumentation=disabled",
"-Dtests=disabled"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/linuxwacom/libwacom.git"
}
]
},
{
"name" : "libndp",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "archive",
"url" : "http://libndp.org/files/libndp-1.6.tar.gz",
"sha256" : "0c7dfa84e013bd5e569ef2c6292a6f72cfaf14f4ff77a77425e52edc33ffac0e"
}
]
},
{
"name" : "NetworkManager",
"buildsystem" : "meson",
"build-options" : {
"cflags" : "-ltinfo",
"cxxflags" : "-ltinfo"
},
"config-opts" : [
"-Dlibaudit=no",
"-Ddbus_conf_dir=/app/etc/dbus-1/system.d",
"-Ddnsmasq=/usr/bin/true",
"-Ddocs=false",
"-Dintrospection=false",
"-Diptables=/usr/bin/true",
"-Dlibpsl=false",
"-Dmodem_manager=false",
"-Dnmtui=false",
"-Dovs=false",
"-Dppp=false",
"-Dqt=false",
"-Dselinux=false",
"-Dsession_tracking=no",
"-Dsystemdsystemunitdir=/app/lib/systemd/system",
"-Dudev_dir=/app/lib/udev",
"-Dsystemd_journal=false",
"-Dtests=no",
"-Dvapi=false"
],
"sources" : [
{
"type" : "git",
"branch": "main",
"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",
"-Dselinux=false",
"-Dteam=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/network-manager-applet.git",
"branch" : "main"
}
]
},
{
"name" : "ModemManager",
"buildsystem" : "meson",
"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"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git",
"branch" : "main"
}
]
},
{
"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"
}
]
},
{
"name" : "gnome-bluetooth",
"buildsystem" : "meson",
"config-opts" : [
"-Dintrospection=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gnome-bluetooth.git"
}
]
},
{
"name" : "openldap",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-slapd"
],
"sources" : [
{
"type": "archive",
"url": "https://www.openldap.org/software/download/OpenLDAP/openldap-release/openldap-2.6.1.tgz",
"sha256": "9d576ea6962d7db8a2e2808574e8c257c15aef55f403a1fb5a0faf35de70e6f3"
}
]
},
{
"name" : "libtirpc",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "archive",
"url" : "http://downloads.sourceforge.net/sourceforge/libtirpc/libtirpc-1.2.6.tar.bz2",
"sha256" : "4278e9a5181d5af9cd7885322fdecebc444f9a3da87c526e7d47f7a12a37d1cc"
}
]
},
{
"name" : "rpcsvc-proto",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "archive",
"url" : "https://github.com/thkukuk/rpcsvc-proto/archive/v1.4.tar.gz",
"sha256" : "eaa227686b84e8ae20181d2119c0ccac29d82371441844008019a134dafe3613"
}
]
},
{
"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"
}
]
},
{
"name" : "libgtop2",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-introspection"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/libgtop.git"
}
]
},
{
"name" : "udisks",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-introspection",
"--disable-lvm2",
"--enable-daemon=no",
"--with-systemdsystemunitdir=/app/lib/systemd/system",
"--with-tmpfilesdir=/app/lib/tmpfiles.d"
],
"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"
}
]
},
{
"name" : "gnome-control-center",
"buildsystem" : "meson",
"sources" : [
{
"type" : "dir",
"path" : "../../"
}
],
"config-opts" : [
"-Dsnap=false",
"-Dtests=false",
"-Dprofile=development"
]
}
]
}

View File

@@ -1,4 +0,0 @@
#!/bin/sh
gtkdocize --flavour no-tmpl
autoreconf -if

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,13 +0,0 @@
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

View File

@@ -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

View File

@@ -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

View File

@@ -1,291 +0,0 @@
# Style
GNOME Settings has a coding style based on GTK Coding Style, but with a few more
rules. Please read them carefully and, if in doubt, ask a maintainer for directions.
## General
The most important rule is: **see the surrounding code, and copy its style**.
That said, GNOME Settings assumes:
* 2 spaces of indentation
* 120 columns of line width
* Newline before `{`
Another rule that applies to function declarations is that all parameters are
aligned by the last '*'. There are plenty of examples below.
## Comments
Comment blocks should be formatted as following:
```c
/* Single line comment */
/* Multiline comments start at the first line of the comment block,
* but have the closing slash a line after. Every line starts with
* an asterisk that is aligned with every the rest of the block.
*/
```
## Conditionals
Conditionals should either be all in one line, or one per line. Newlines inside
conditionals are aligned by the last parenthesis.
Some examples below:
```c
// Single line if
if (a || b || (c && d))
return;
// Multiline if with nested parenthesis
if (long_boolean_variable_used_in_this_condition_a ||
long_boolean_variable_used_in_this_condition_b ||
(long_boolean_variable_used_in_this_condition_c &&
long_boolean_variable_used_in_this_condition_d))
{
return;
}
// Another single line example with do {} while (...)
do
{
/* something */
}
while (a || b || (c && d));
```
## Structs and Enums
Structures and enums are formatted as following:
```c
struct _FooBar
{
guint32 field_one;
gchar *text;
};
typedef struct
{
FooParent parent;
guint32 field_one;
gchar *text;
struct
{
CustomType *something;
guint something_else;
} inner_struct;
gboolean flag : 1;
} FooBar;
enum
{
FIRST,
SECOND,
LAST,
};
typedef enum
{
FOO_BAR_FIRST,
FOO_BAR_SECOND,
FOO_BAR_LAST,
} FooEnumBar;
```
## Header (.h) files
It is organized by the following structure:
1. GPL header
2. Local includes
3. System includes
4. `G_BEGIN_DECLS`
5. `#defines`
6. `G_DECLARE_{FINAL,DERIVABLE}_TYPE`
7. Public API
8. `G_END_DECLS`
The following style rules apply:
* The '*' and the type come together, without any spaces in between.
* Function names are aligned by the widest return value.
* Parenthesis after function name is aligned by the widest function name
* The last '*' in parameters are aligned by the widest parameter type
* No new line at the end of the file
As an example, this is how a header file should look like (extracted from
the `cc-object-storage.h` file):
```c
/* cc-object-storage.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 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/>.
*/
#pragma once
#include <glib-object.h>
#include <gio/gio.h>
G_BEGIN_DECLS
/* Default storage keys */
#define CC_OBJECT_NMCLIENT "CcObjectStorage::nm-client"
#define CC_TYPE_OBJECT_STORAGE (cc_object_storage_get_type())
G_DECLARE_FINAL_TYPE (CcObjectStorage, cc_object_storage, CC, OBJECT_STORAGE, GObject)
gboolean cc_object_storage_has_object (const gchar *key);
void cc_object_storage_add_object (const gchar *key,
gpointer object);
gpointer cc_object_storage_get_object (const gchar *key);
gpointer cc_object_storage_create_dbus_proxy_sync (GBusType bus_type,
GDBusProxyFlags flags,
const gchar *name,
const gchar *path,
const gchar *interface,
GCancellable *cancellable,
GError **error);
void cc_object_storage_create_dbus_proxy (GBusType bus_type,
GDBusProxyFlags flags,
const gchar *name,
const gchar *path,
const gchar *interface,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
G_END_DECLS
```
## Source code
The source file keeps an order of methods. The order will be as following:
1. GPL header
2. Structures
3. Function prototypes
4. G_DEFINE_TYPE()
5. Enums
6. Static variables
7. Auxiliary methods
8. Callbacks
9. Interface implementations
10. Parent class overrides
11. class_init and init
12. Public API
### Structures
The structures must have the first pointer asterisk aligned one space after the
widest type name. For example:
```c
typedef struct
{
GBusType bus_type;
GDBusProxyFlags flags;
gchar *name;
gchar *path;
gchar *interface;
gboolean cached;
} TaskData;
```
### Function Prototypes
Function prototypes must be formatted just like in header files.
### Auxiliary Methods
Auxiliary method names must have a verb in the dictionary form, and should always
perform an action over something. They don't have the `cc_` prefix. For example:
```c
static void
execute_something_on_data (Foo *data,
Bar *bar)
{
/* ... */
}
```
### Callbacks
* Callbacks always have the `_cb` suffix
* Signal callbacks always have the `on_<object_name>` prefix
* Callback names must have the name of the signal in the past
For example:
```c
static void
on_foo_size_allocated_cb (GtkWidget *widget,
GtkAllocation *allocation,
gpointer user_data)
{
/* ... */
}
```
### Line Splitting
Line splitting works following the GTK code style, but legibility comes over above
all. If a function call looks unbalanced following the GTK style, it is fine to
slightly escape the rules.
For example, this feels extremelly unbalanced:
```c
foo_bar_do_somthing_sync (a,
1,
object,
data,
something
cancellable,
&error);
```
Notice the empty space before the arguments, and how empty and odd it looks. In
comparison, it will look better if written like this:
```c
foo_bar_do_somthing_sync (a, 1, object, data,
something
cancellable,
&error);
```
# Contributing guidelines
See CONTRIBUTIONS.md file for the contribution guidelines, and the Code of Conduct
that contributors are expected to follow.

View File

@@ -1,97 +0,0 @@
# Contributing
Thank you for considering contributing to Settings!
All code contributions are made using merge requests.
Please note we have a Code of Conduct, please follow it in all your interactions with the project.
## Creating Merge Requests
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.
The following guidelines will help your change be successfully merged:
* 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.
Please format commit messages as follows:
```
component: <summary>
A paragraph explaining the problem and its context.
Another one explaining how you solved that.
<link to issue(s) this change fixes>
```
## Bug Fixes
Changes that fix bugs include:
* Correcting code that crashes.
* Spelling mistakes in labels.
* Small layout issues (e.g. spacing).
* Use of deprecated APIs.
* Restructuring of code for improved safety.
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.
## User Experience Changes
Changes that impact the user experience of Settings require approval from the
[Design Team][design-team]. This includes:
* 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.

View File

@@ -1,62 +0,0 @@
This document describes how maintainership works on GNOME Settings. It is intended to be a guideline
for future reference.
The list of current maintainers can be found at the [gnome-control-center.doap][doap] DOAP file.
# General Rules
The purpose of the shared maintainership model in GNOME Settings is to avoid as much as possible
pushing unreviewed code in the main repository. Not only it is a good engineering practice, but it
also increases the code quality and reduces the number of bugs.
GNOME Settings has two types of maintainers:
* **General Maintainer**: take care of the whole codebase and of panels without a specific maintainer.
* **Panel Maintainer**: take care of a specific panel with a stronger authority over General
Maintainers.
## For Contributors
Panel Maintainers have a stronger authority over their panels than a General Maintainer. If you are
contributing to a specific panel, and that panel has a dedicate maintainer, they should be the main
point of contact.
In the rare case of Panel Maintainers not being responsive, it is allowed to contact General
Maintainers.
## For Maintainers
If you are a Panel Maintainer, your merge requests will be reviewed by General Maintainer. The
opposite is true as well - General Maintainers contributing to a specific panel will have their
merge requests reviewed by the Panel Maintainer of that panel.
If you are a General Maintainer contributing to an unmaintained panel, or to the main codebase, your
merge requests will be reviewed by another General Maintainer.
Avoid pushing commits without an explicit review, except in the following cases:
* The commit is a translation commit
* The commit is trivial
* The commit is urgent and no reviewers were available in time
When accepting a merge request and allowing the other maintainer to merge, avoid misunderstandings
by being explicit. Suggested acceptance phrase:
`I approve this merge request. You are allowed to merge it.`
### Urgency Commits
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)
* Symptoms:
* Always OR often reproducible; AND
* Crash; OR
* Data loss; OR
* System corruption
* 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

View File

@@ -1,15 +0,0 @@
<?xml version="1.0"?>
<its:rules xmlns:its="http://www.w3.org/2005/11/its"
xmlns:gt="https://www.gnu.org/s/gettext/ns/its/extensions/1.0"
version="2.0">
<its:translateRule selector="/KeyListEntries" translate="no"/>
<its:translateRule selector="/KeyListEntries/@name" translate="yes"/>
<its:translateRule selector="//KeyListEntry" translate="yes"/>
<its:translateRule selector="//KeyListEntry/@description" translate="yes"/>
<gt:contextRule selector="//KeyListEntry[@msgctxt]" contextPointer="@msgctxt"/>
<!-- Extracted strings are consumed by the library and are never
merged back; we don't want to escape special characters. -->
<gt:escapeRule selector="/KeyListEntries" escape="no"/>
</its:rules>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0"?>
<locatingRules>
<locatingRule name="GnomeKeybindings" pattern="*.xml">
<documentRule localName="KeyListEntries" target="gnome-keybindings.its"/>
</locatingRule>
</locatingRules>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0"?>
<its:rules xmlns:its="http://www.w3.org/2005/11/its"
version="2.0">
<its:translateRule selector="/sounds" translate="no"/>
<its:translateRule selector="//name" translate="yes"/>
</its:rules>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0"?>
<locatingRules>
<locatingRule name="sounds" pattern="*.xml">
<documentRule localName="sounds" target="sounds.its"/>
</locatingRule>
</locatingRules>

View File

@@ -1,59 +0,0 @@
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:gnome="http://api.gnome.org/doap-extensions#"
xmlns="http://usefulinc.com/ns/doap#">
<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" />
<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:Person>
</maintainer>
<!-- General -->
<maintainer>
<foaf:Person>
<foaf:name>Robert Ancell</foaf:name>
<foaf:mbox rdf:resource="mailto:robert.ancell@canonical.com" />
<gnome:userid>rancell</gnome:userid>
</foaf:Person>
</maintainer>
<!-- Bluetooth -->
<maintainer>
<foaf:Person>
<foaf:name>Bastien Nocera</foaf:name>
<foaf:mbox rdf:resource="mailto:hadess@gnome.org" />
<gnome:userid>hadess</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:Person>
</maintainer>
<!-- Wacom -->
<maintainer>
<foaf:Person>
<foaf:name>Carlos Garnacho</foaf:name>
<foaf:mbox rdf:resource="mailto:carlosg@gnome.org" />
<gnome:userid>carlosg</gnome:userid>
</foaf:Person>
</maintainer>
</Project>

View File

@@ -1,361 +0,0 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<refentry id="gnome-control-center">
<refentryinfo>
<title>gnome-control-center</title>
<productname>GNOME</productname>
<authorgroup>
<author>
<contrib>Maintainer</contrib>
<firstname>Bastien</firstname>
<surname>Nocera</surname>
<email>hadess@hadess.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>gnome-control-center</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="manual">User Commands</refmiscinfo>
</refmeta>
<refnamediv>
<refname>gnome-control-center</refname>
<refpurpose>Configure GNOME settings</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>gnome-control-center <arg choice="opt" rep="repeat">OPTION</arg> <arg choice="opt">PANEL</arg> <arg choice="opt" rep="repeat">ARG</arg></command>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>gnome-control-center</command> is a graphical
user interface to configure various aspects of GNOME.</para>
<para>When run without arguments, the shell displays the
<firstterm>overview</firstterm>, which shows all available
configuration panels. The overview allows to open individual
panels by clicking on them. It also has a search entry
to find panels by searching keywords.</para>
<para>It is also possible to specify a panel name
as commandline argument to go directly to that panel.
Individual panels may accept further arguments to specify
which tab to open (for multi-tabbed panels) or which
item to display (for panels with lists).</para>
<para>Note that <command>gnome-control-center</command>
is not meant to expose each and every setting that is
available. The settings that can be found here represent
what is considered useful and commonly needed options.
For more exotic or uncommon options, you can look at
<command>gnome-tweak-tool</command> or the
<command>gsettings</command> commandline utility.</para>
</refsect1>
<refsect1>
<title>Panels</title>
<para>The following panel names can be specified:</para>
<variablelist>
<varlistentry>
<term><option>background</option></term>
<listitem><para>The background panel lets you
set your desktop background.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>bluetooth</option></term>
<listitem><para>The bluetooth panel lets you
configure your computer's Bluetooth adapter,
and pair the computer with Bluetooth keyboards,
phones, etc.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>color</option></term>
<listitem><para>The color panel can calibrate
monitors, web cams and printers for accurate
color reproduction.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>datetime</option></term>
<listitem><para>The datetime panel lets you
set the timezone and time format.</para>
<para>Some operations in this panel
affect all user accounts on the computer
and require privieges.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>display</option></term>
<listitem><para>The display panel configures
the resolution and arrangement of monitors
and laptop panels. Note that monitors can be
rearranged by drag-and-drop, and you can change
which monitor is your main display by dragging
the black bar.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>info-overview</option></term>
<listitem><para>The info-overview 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
media.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>keyboard</option></term>
<listitem><para>The keyboard panel can
change how the keyboard reacts to key
presses and lets you change keyboard
shortcuts or create custom shortcuts.</para>
<para>You can open this panel on a
specific tab by passing <option>typing</option>
or <option>shortcuts</option> as extra
argument.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>mouse</option></term>
<listitem><para>The mouse panel can change
how mice and touchpads react to user
input.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>network</option></term>
<listitem><para>The network panel provides
a view of available network devices (wired,
wireless or mobile) and their current
configuration. It also provides a way to
create new VPN connections and configure
proxy settings.</para>
<para>You can open this panel on a
specific dialog by passing
<option>create-wifi</option>,
<option>connect-hidden-wifi</option>,
<option>connect-3g</option>,
<option>connect-8021x-wifi</option> or
<option>show-device</option> as extra
argument. The last three parameters
require an additional extra argument for
the network object in the form
<replaceable>/org/freedesktop/NetworkManager/Devices/0</replaceable>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>notifications</option></term>
<listitem><para>The notifications panel provides
a way to control the display of notifications.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>online-accounts</option></term>
<listitem><para>The online-accounts panel
shows your configured online accounts and
lets you add or remove accounts.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>power</option></term>
<listitem><para>The power panel shows
the fill level of batteries and can
configure what happens when the computer
is idle or runs out of battery.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>printers</option></term>
<listitem><para>The printers panel shows
all known printers and their status. It is
possible to inspect queued print jobs and
add new printers.</para>
<para>Some operations in this panel require
privileges.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>privacy</option></term>
<listitem><para>The privacy panel allows
to control visible file usage history, temporary
files, and name.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>region</option></term>
<listitem><para>The region panel
contains regional settings such as
the display language, formatting for
times, dates, numbers, and input sources.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>search</option></term>
<listitem><para>The search panel controls
the results visible in the overview, and the
files and folders to be indexed.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>screen</option></term>
<listitem><para>The screen panel contains
settings that control the screen brightness
and screen lock behavior.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>sharing</option></term>
<listitem><para>The sharing panel contains
settings that control what is shared over the
network.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>sound</option></term>
<listitem><para>The sound panel shows
all known sound devices and their configuration,
including volume and balance settings.</para>
<para>You can open this panel on a
specific tab by passing
<option>output</option>,
<option>input</option>,
<option>hardware</option>,
<option>effects</option> or
<option>applications</option> as extra
argument.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>universal-access</option></term>
<listitem><para>The universal-access panel
contains settings for accessible technologies
such as the screen reader, magnifier, screen
keyboard and AccessX options.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>user-accounts</option></term>
<listitem><para>The user-accounts panel
shows all user accounts that exist on the
computer and allows to change them in some
ways, such as changing the user name, password
or permissions. It also allows to create
or remove accounts.</para>
<para>Some operations in this panel require
privileges.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>wacom</option></term>
<listitem><para>the wacom panel shows
connected Wacom graphics tablets and lets
you calibrate and configure such devices.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Options</title>
<variablelist>
<varlistentry>
<term><option>-?</option>, <option>--help</option></term>
<listitem><para>Prints a short help
text and exits.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem><para>Prints the program version
and exits.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option>, <option>--verbose</option></term>
<listitem><para>Enables verbose mode.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-l</option>, <option>--list</option></term>
<listitem><para>Lists the available panels
and exits.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-o</option>, <option>--overview</option></term>
<listitem><para>Opens the overview.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-s</option> <replaceable>term</replaceable>, <option>--search</option> <replaceable>term</replaceable></term>
<listitem><para>Sets the following search term.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Exit status</title>
<para>On success 0 is returned, a non-zero failure
code otherwise.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>gsettings</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@@ -1,26 +0,0 @@
xsltproc = find_program('xsltproc', required: false)
assert(xsltproc.found(), 'xsltproc is required to build documentation')
xsltproc_cmd = [
xsltproc,
'--output', '@OUTPUT@',
'--nonet',
'--stringparam', 'man.output.quietly', '1',
'--stringparam', 'funcsynopsis.style', 'ansi',
'--stringparam', 'man.th.extra1.suppress', '1',
'--stringparam', 'man.authors.section.enabled', '0',
'--stringparam', 'man.copyright.section.enabled', '0',
'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl',
'@INPUT@'
]
output = meson.project_name() + '.1'
custom_target(
output,
input : meson.project_name() + '.xml',
output : output,
command : xsltproc_cmd,
install : true,
install_dir : join_paths(control_center_mandir, 'man1')
)

View File

@@ -1,374 +0,0 @@
project(
'gnome-control-center', 'c',
version : '46.alpha',
license : 'GPL2+',
meson_version : '>= 0.58.0'
)
control_center_prefix = get_option('prefix')
control_center_bindir = join_paths(control_center_prefix, get_option('bindir'))
control_center_datadir = join_paths(control_center_prefix, get_option('datadir'))
control_center_libexecdir = join_paths(control_center_prefix, get_option('libexecdir'))
control_center_localedir = join_paths(control_center_prefix, get_option('localedir'))
control_center_mandir = join_paths(control_center_prefix, get_option('mandir'))
control_center_sysconfdir = join_paths(control_center_prefix, get_option('sysconfdir'))
control_center_pkgdatadir = join_paths(control_center_datadir, meson.project_name())
control_center_desktopdir = join_paths(control_center_datadir, 'applications')
control_center_icondir = join_paths(control_center_datadir, 'icons')
control_center_schemadir = join_paths (control_center_datadir, 'glib-2.0', 'schemas')
control_center_gettext = meson.project_name() + '-2.0'
host_is_linux = host_machine.system().contains('linux')
host_is_linux_not_s390 = host_is_linux and not host_machine.cpu().contains('s390')
cc = meson.get_compiler('c')
config_h = configuration_data()
py = import('python')
python = py.find_installation('python3')
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)
# defines
set_defines = [
# package
['PACKAGE', meson.project_name()],
['PACKAGE_VERSION', meson.project_version()],
['VERSION', meson.project_version()],
['PROFILE', get_option('profile')],
# i18n
['GETTEXT_PACKAGE', control_center_gettext]
]
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',
description: 'Permissions for creating the user\'s config, cache and data directories')
# 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
#error No optimization
#endif
'''
control_center_optimized = get_option('buildtype').contains('optimized') and cc.compiles(optimized_src)
if control_center_optimized
common_flags += '-Wp,-D_FORTIFY_SOURCE=2'
endif
if get_option('buildtype').contains('debug')
test_cflags = [
'-Wcast-align',
'-Wmissing-field-initializers',
'-Wmissing-declarations',
'-Wmissing-prototypes',
'-Wnested-externs',
'-Wno-strict-aliasing',
'-Wno-sign-compare'
]
common_flags += cc.get_supported_arguments(test_cflags)
endif
add_project_arguments(common_flags, language: 'c')
# Check that we meet the dependencies
libgvc = subproject(
'gvc',
default_options: [
'static=true',
'alsa=false',
'package_name=' + control_center_gettext,
'package_version=' + meson.project_version(),
]
)
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')
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')
goa_dep = dependency('goa-1.0', version: goa_req_version)
gsettings_desktop_dep = dependency('gsettings-desktop-schemas', version: '>= 42.alpha')
libxml_dep = dependency('libxml-2.0')
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')
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')
common_deps = [
gio_dep,
glib_dep,
gsettings_desktop_dep,
libadwaita_dep,
dependency('gio-unix-2.0'),
dependency('gthread-2.0'),
gtk_dep,
]
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')
# https://bugzilla.gnome.org/show_bug.cgi?id=696766
cups_cflags = []
if cups_dep.version().version_compare('>= 1.6')
cups_cflags += '-D_PPD_DEPRECATED='
endif
# cups headers
check_headers = [
['HAVE_CUPS_CUPS_H', 'cups/cups.h'],
['HAVE_CUPS_PPD_H', 'cups/ppd.h']
]
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')
# IBus support
enable_ibus = get_option('ibus')
if enable_ibus
ibus_dep = dependency('ibus-1.0', version: '>= 1.5.2')
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')
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')
if host_is_linux
# ModemManager
mm_dep = dependency('mm-glib', version: '>= 0.7')
# NetworkManager
network_manager_deps = [
dependency('libnm', version: '>= 1.24.0'),
dependency('libnma-gtk4', version: '>= 1.10.2'),
mm_dep,
]
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')
libwacom_dep = dependency('libwacom', version: '>= 0.7')
wacom_deps = [
libwacom_dep,
]
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')
else
message('Bluetooth and Wacom panels will not be built (no USB support on this platform)')
message('Thunderbolt panel will not be built (not supported on this platform)')
endif
config_h.set('BUILD_BLUETOOTH', host_is_linux_not_s390,
description: 'Define to 1 to build the Bluetooth panel')
config_h.set('HAVE_BLUETOOTH', host_is_linux_not_s390,
description: 'Define to 1 if bluetooth support is available')
config_h.set('BUILD_WACOM', host_is_linux_not_s390,
description: 'Define to 1 to build the Wacom panel')
config_h.set('HAVE_WACOM', host_is_linux_not_s390,
description: 'Define to 1 if Wacom is supportted')
config_h.set('BUILD_THUNDERBOLT', host_is_linux_not_s390,
description: 'Define to 1 to build the Thunderbolt panel')
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')
install_subdir(
'gettext',
install_dir: control_center_datadir
)
top_inc = include_directories('.')
shell_inc = include_directories('shell')
subdir('data/icons')
subdir('po')
subdir('panels')
subdir('shell')
subdir('search-provider')
if get_option('tests')
subdir('tests')
endif
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,
})
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')

View File

@@ -1,11 +0,0 @@
option('deprecated-declarations', type: 'feature', value: 'disabled', description: 'build with deprecated declaration warnings')
option('documentation', type: 'boolean', value: false, description: 'build documentation')
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')

View File

@@ -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>

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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;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 &amp; 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">&lt;b&gt;Total&lt;/b&gt;</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>

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -1,31 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.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/>.
*
*/
#pragma once
#include <adwaita.h>
G_BEGIN_DECLS
#define CC_TYPE_DEFAULT_APPS_PAGE (cc_default_apps_page_get_type ())
G_DECLARE_FINAL_TYPE (CcDefaultAppsPage, cc_default_apps_page, CC, DEFAULT_APPS_PAGE, AdwPreferencesGroup)
CcDefaultAppsPage *cc_default_apps_page_new (void);
G_END_DECLS

View File

@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcDefaultAppsPage" parent="AdwPreferencesGroup">
<property name="title" translatable="yes">Links &amp;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>

View File

@@ -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]);
}
}
}
}

View File

@@ -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

View File

@@ -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");
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -1,31 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.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/>.
*
*/
#pragma once
#include <adwaita.h>
G_BEGIN_DECLS
#define CC_TYPE_REMOVABLE_MEDIA_SETTINGS (cc_removable_media_settings_get_type ())
G_DECLARE_FINAL_TYPE (CcRemovableMediaSettings, cc_removable_media_settings, CC, REMOVABLE_MEDIA_SETTINGS, AdwPreferencesGroup)
CcRemovableMediaSettings* cc_removable_media_settings_new (void);
G_END_DECLS

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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')
)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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')

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -1,14 +0,0 @@
<?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>
</gresource>
</gresources>

View File

@@ -1,219 +0,0 @@
/* bg-colors-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-colors-source.h"
#include "cc-background-item.h"
#include <cairo-gobject.h>
#include <glib/gi18n-lib.h>
#include <gdesktop-enums.h>
struct _BgColorsSource
{
BgSource parent_instance;
};
G_DEFINE_TYPE (BgColorsSource, bg_colors_source, BG_TYPE_SOURCE)
struct {
GDesktopBackgroundShading type;
int orientation;
const char *pcolor;
} items[] = {
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#000000" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#db5d33" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#008094" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#5d479d" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#ab2876" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#fad166" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#437740" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#d272c4" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#ed9116" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#ff89a9" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#7a8aa2" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#888888" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#475b52" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#425265" },
{ G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#7a634b" },
};
static gchar *
get_colors_path (void)
{
return g_build_filename (g_get_user_config_dir (), "gnome-control-center", "backgrounds", "colors.ini", NULL);
}
static char *
get_colors_dir (void)
{
return g_build_filename (g_get_user_config_dir (), "gnome-control-center", "backgrounds", NULL);
}
static void
bg_colors_source_add_color (BgColorsSource *self,
GListStore *store,
const char *color)
{
CcBackgroundItemFlags flags;
g_autoptr(CcBackgroundItem) item = NULL;
item = cc_background_item_new (NULL);
flags = CC_BACKGROUND_ITEM_HAS_PCOLOR |
CC_BACKGROUND_ITEM_HAS_SCOLOR |
CC_BACKGROUND_ITEM_HAS_SHADING |
CC_BACKGROUND_ITEM_HAS_PLACEMENT |
CC_BACKGROUND_ITEM_HAS_URI;
/* It does have a URI, it's "none" */
g_object_set (G_OBJECT (item),
"uri", "file:///" DATADIR "/gnome-control-center/pixmaps/noise-texture-light.png",
"primary-color", color,
"secondary-color", color,
"shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
"placement", G_DESKTOP_BACKGROUND_STYLE_WALLPAPER,
"flags", flags,
NULL);
cc_background_item_load (item, NULL);
/* insert the item into the liststore */
g_list_store_append (store, item);
}
static void
bg_colors_source_constructed (GObject *object)
{
BgColorsSource *self = BG_COLORS_SOURCE (object);
guint i;
GListStore *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));
for (i = 0; i < G_N_ELEMENTS (items); i++)
bg_colors_source_add_color (self, store, items[i].pcolor);
keyfile = g_key_file_new ();
path = get_colors_path ();
if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL))
{
g_auto(GStrv) colors = NULL;
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]);
}
}
gboolean
bg_colors_source_add (BgColorsSource *self,
GdkRGBA *rgba,
GtkTreeRowReference **ret_row_ref)
{
GListStore *store;
g_autofree gchar *c = NULL;
g_auto(GStrv) colors = NULL;
gsize len;
g_autoptr(GKeyFile) keyfile = NULL;
g_autoptr(GError) error = NULL;
g_autofree gchar *dir = NULL;
g_autofree gchar *path = NULL;
c = g_strdup_printf ("#%02x%02x%02x",
(int)(255*rgba->red),
(int)(255*rgba->green),
(int)(255*rgba->blue));
store = bg_source_get_liststore (BG_SOURCE (self));
bg_colors_source_add_color (self, store, c);
/* Save to the keyfile */
dir = get_colors_dir ();
g_mkdir_with_parents (dir, 0700);
path = get_colors_path ();
colors = NULL;
len = 0;
keyfile = g_key_file_new ();
if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL))
colors = g_key_file_get_string_list (keyfile, "Colors", "custom-colors", &len, NULL);
if (len == 0 && colors != NULL)
g_clear_pointer (&colors, g_strfreev);
if (colors == NULL)
{
colors = g_new0 (char *, 2);
colors[0] = g_steal_pointer (&c);
len = 1;
}
else
{
char **new_colors;
guint i;
new_colors = g_new0 (char *, len + 2);
for (i = 0; colors[i] != NULL; i++)
{
new_colors[i] = colors[i];
colors[i] = NULL;
}
new_colors[len] = g_steal_pointer (&c);
len++;
g_strfreev (colors);
colors = new_colors;
}
g_key_file_set_string_list (keyfile, "Colors", "custom-colors", (const gchar * const*) colors, len);
if (!g_key_file_save_to_file (keyfile, path, &error))
g_warning ("Could not save custom color: %s", error->message);
return TRUE;
}
static void
bg_colors_source_init (BgColorsSource *self)
{
}
static void
bg_colors_source_class_init (BgColorsSourceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = bg_colors_source_constructed;
}
BgColorsSource *
bg_colors_source_new (GtkWidget *widget)
{
return g_object_new (BG_TYPE_COLORS_SOURCE, "widget", widget, NULL);
}

View File

@@ -1,38 +0,0 @@
/* bg-colors-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>
*
*/
#pragma once
#include <gtk/gtk.h>
#include "bg-source.h"
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);
gboolean bg_colors_source_add (BgColorsSource *self,
GdkRGBA *rgba,
GtkTreeRowReference **ret_row_ref);
G_END_DECLS

View File

@@ -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));
}

View File

@@ -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

View File

@@ -1,213 +0,0 @@
/*
* 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 "bg-source.h"
#include "cc-background-item.h"
#include <cairo-gobject.h>
#define THUMBNAIL_WIDTH 144
#define THUMBNAIL_HEIGHT (THUMBNAIL_WIDTH * 3 / 4)
typedef struct
{
GnomeDesktopThumbnailFactory *thumbnail_factory;
GListStore *store;
GtkWidget *widget;
gint thumbnail_height;
gint thumbnail_width;
} BgSourcePrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (BgSource, bg_source, G_TYPE_OBJECT)
enum
{
PROP_LISTSTORE = 1,
PROP_WIDGET
};
static void
bg_source_calculate_thumbnail_dimensions (BgSource *source)
{
BgSourcePrivate *priv = bg_source_get_instance_private (source);
gint scale_factor;
priv->thumbnail_height = THUMBNAIL_HEIGHT;
priv->thumbnail_width = THUMBNAIL_WIDTH;
if (priv->widget == NULL)
return;
scale_factor = gtk_widget_get_scale_factor (priv->widget);
if (scale_factor > 1)
{
priv->thumbnail_height *= scale_factor;
priv->thumbnail_width *= scale_factor;
}
}
static void
bg_source_constructed (GObject *object)
{
G_OBJECT_CLASS (bg_source_parent_class)->constructed (object);
bg_source_calculate_thumbnail_dimensions (BG_SOURCE (object));
}
static void
bg_source_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
BgSource *source = BG_SOURCE (object);
switch (property_id)
{
case PROP_LISTSTORE:
g_value_set_object (value, bg_source_get_liststore (source));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
bg_source_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
BgSource *source = BG_SOURCE (object);
BgSourcePrivate *priv = bg_source_get_instance_private (source);
switch (property_id)
{
case PROP_WIDGET:
priv->widget = GTK_WIDGET (g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
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);
}
static void
bg_source_class_init (BgSourceClass *klass)
{
GParamSpec *pspec;
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = bg_source_constructed;
object_class->get_property = bg_source_get_property;
object_class->set_property = bg_source_set_property;
object_class->dispose = bg_source_dispose;
pspec = g_param_spec_object ("liststore",
"Liststore",
"Liststore used in the source",
G_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,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_WIDGET, 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);
}
GListStore*
bg_source_get_liststore (BgSource *source)
{
BgSourcePrivate *priv;
g_return_val_if_fail (BG_IS_SOURCE (source), NULL);
priv = bg_source_get_instance_private (source);
return priv->store;
}
gint
bg_source_get_scale_factor (BgSource *source)
{
BgSourcePrivate *priv;
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);
}
gint
bg_source_get_thumbnail_height (BgSource *source)
{
BgSourcePrivate *priv;
g_return_val_if_fail (BG_IS_SOURCE (source), THUMBNAIL_HEIGHT);
priv = bg_source_get_instance_private (source);
return priv->thumbnail_height;
}
gint
bg_source_get_thumbnail_width (BgSource *source)
{
BgSourcePrivate *priv;
g_return_val_if_fail (BG_IS_SOURCE (source), THUMBNAIL_WIDTH);
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;
}

View File

@@ -1,46 +0,0 @@
/*
* 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>
*
*/
#pragma once
#include <gtk/gtk.h>
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
G_BEGIN_DECLS
#define BG_TYPE_SOURCE (bg_source_get_type ())
G_DECLARE_DERIVABLE_TYPE (BgSource, bg_source, BG, SOURCE, GObject)
struct _BgSourceClass
{
GObjectClass parent_class;
};
GListStore* bg_source_get_liststore (BgSource *source);
gint bg_source_get_scale_factor (BgSource *source);
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

View File

@@ -1,164 +0,0 @@
/* bg-wallpapers-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 "bg-wallpapers-source.h"
#include "cc-background-item.h"
#include "cc-background-xml.h"
#include <cairo-gobject.h>
#include <gio/gio.h>
struct _BgWallpapersSource
{
BgSource parent_instance;
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));
gboolean deleted;
g_object_get (G_OBJECT (item), "is-deleted", &deleted, NULL);
if (deleted)
return;
g_list_store_insert_sorted (store, item, sort_func, NULL);
}
static void
list_load_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
if (!cc_background_xml_load_list_finish (CC_BACKGROUND_XML (source_object), res, &error))
g_warning ("Failed to load background list: %s", error->message);
}
static void
item_added (BgWallpapersSource *self,
CcBackgroundItem *item)
{
load_wallpapers (NULL, item, self);
}
static void
load_default_bg (BgWallpapersSource *self)
{
const char * const *system_data_dirs;
guint i;
/* FIXME We could do this nicer if we had the XML source in GSettings */
system_data_dirs = g_get_system_data_dirs ();
for (i = 0; system_data_dirs[i]; i++) {
g_autofree gchar *filename = NULL;
filename = g_build_filename (system_data_dirs[i],
"gnome-background-properties",
"adwaita.xml",
NULL);
if (cc_background_xml_load_xml (self->xml, filename))
break;
}
}
static void
bg_wallpapers_source_constructed (GObject *object)
{
BgWallpapersSource *self = BG_WALLPAPERS_SOURCE (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);
/* Try adding the default background first */
load_default_bg (self);
cc_background_xml_load_list_async (self->xml, NULL, list_load_cb, self);
}
static void
bg_wallpapers_source_dispose (GObject *object)
{
BgWallpapersSource *self = BG_WALLPAPERS_SOURCE (object);
g_clear_object (&self->xml);
G_OBJECT_CLASS (bg_wallpapers_source_parent_class)->dispose (object);
}
static void
bg_wallpapers_source_init (BgWallpapersSource *self)
{
self->xml = cc_background_xml_new ();
}
static void
bg_wallpapers_source_class_init (BgWallpapersSourceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = bg_wallpapers_source_constructed;
object_class->dispose = bg_wallpapers_source_dispose;
}
BgWallpapersSource *
bg_wallpapers_source_new (GtkWidget *widget)
{
return g_object_new (BG_TYPE_WALLPAPERS_SOURCE, "widget", widget, NULL);
}

View File

@@ -1,34 +0,0 @@
/* bg-wallpapers-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>
*
*/
#pragma once
#include <gtk/gtk.h>
#include "bg-source.h"
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);
G_END_DECLS

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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>

File diff suppressed because it is too large Load Diff

View File

@@ -1,87 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2010-2011 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/>.
*
*/
#pragma once
#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>
G_BEGIN_DECLS
#define CC_TYPE_BACKGROUND_ITEM (cc_background_item_get_type ())
G_DECLARE_FINAL_TYPE (CcBackgroundItem, cc_background_item, CC, BACKGROUND_ITEM, GObject)
typedef enum {
CC_BACKGROUND_ITEM_HAS_SHADING = 1 << 0,
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
} CcBackgroundItemFlags;
#define CC_BACKGROUND_ITEM_HAS_ALL (CC_BACKGROUND_ITEM_HAS_SHADING & \
CC_BACKGROUND_ITEM_HAS_PLACEMENT & \
CC_BACKGROUND_ITEM_HAS_PCOLOR & \
CC_BACKGROUND_ITEM_HAS_SCOLOR & \
CC_BACKGROUND_ITEM_HAS_FNAME)
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_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);
GdkPixbuf * cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
GnomeDesktopThumbnailFactory *thumbs,
int width,
int height,
int scale_factor,
int frame,
gboolean dark);
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);
const char * cc_background_item_get_pcolor (CcBackgroundItem *item);
const char * cc_background_item_get_scolor (CcBackgroundItem *item);
const char * cc_background_item_get_name (CcBackgroundItem *item);
const char * cc_background_item_get_size (CcBackgroundItem *item);
gboolean cc_background_item_get_needs_download (CcBackgroundItem *item);
guint64 cc_background_item_get_modified (CcBackgroundItem *item);
gboolean cc_background_item_compare (CcBackgroundItem *saved,
CcBackgroundItem *configured);
void cc_background_item_dump (CcBackgroundItem *item);
G_END_DECLS

View File

@@ -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);
}

View File

@@ -1,35 +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/>.
*
*/
#pragma once
#include <gtk/gtk.h>
#include "bg-source.h"
#include "cc-background-item.h"
G_BEGIN_DECLS
#define CC_TYPE_BACKGROUND_PAINTABLE (cc_background_paintable_get_type ())
G_DECLARE_FINAL_TYPE (CcBackgroundPaintable, cc_background_paintable, CC, BACKGROUND_PAINTABLE, GObject)
CcBackgroundPaintable * cc_background_paintable_new (BgSource *source,
CcBackgroundItem *item);
G_END_DECLS

View File

@@ -1,502 +0,0 @@
/*
* 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 <string.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <glib/gstdio.h>
#include <gdesktop-enums.h>
#include "cc-background-panel.h"
#include "cc-background-chooser.h"
#include "cc-background-item.h"
#include "cc-background-preview.h"
#include "cc-background-resources.h"
#include "cc-background-xml.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;
GDBusConnection *connection;
GSettings *settings;
GSettings *lock_settings;
GSettings *interface_settings;
GDBusProxy *proxy;
CcBackgroundItem *current_background;
CcBackgroundChooser *background_chooser;
CcBackgroundPreview *default_preview;
CcBackgroundPreview *dark_preview;
GtkToggleButton *default_toggle;
GtkToggleButton *dark_toggle;
};
CC_PANEL_REGISTER (CcBackgroundPanel, cc_background_panel)
static void
load_custom_css (CcBackgroundPanel *self)
{
g_autoptr(GtkCssProvider) provider = NULL;
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 void
reload_color_scheme_toggles (CcBackgroundPanel *self)
{
GDesktopColorScheme scheme;
scheme = g_settings_get_enum (self->interface_settings, INTERFACE_COLOR_SCHEME_KEY);
if (scheme == G_DESKTOP_COLOR_SCHEME_DEFAULT)
{
gtk_toggle_button_set_active (self->default_toggle, TRUE);
}
else if (scheme == G_DESKTOP_COLOR_SCHEME_PREFER_DARK)
{
gtk_toggle_button_set_active (self->dark_toggle, TRUE);
}
else
{
gtk_toggle_button_set_active (self->default_toggle, FALSE);
gtk_toggle_button_set_active (self->dark_toggle, FALSE);
}
}
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)
{
return g_build_filename (g_get_user_config_dir (),
"gnome-control-center",
"backgrounds",
"last-edited.xml",
NULL);
}
static void
reload_current_bg (CcBackgroundPanel *self)
{
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 ();
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);
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,
"secondary-color", scolor,
NULL);
if (saved != NULL && cc_background_item_compare (saved, configured))
{
CcBackgroundItemFlags flags;
flags = cc_background_item_get_flags (saved);
/* Special case for colours */
if (cc_background_item_get_placement (saved) == G_DESKTOP_BACKGROUND_STYLE_NONE)
flags &=~ (CC_BACKGROUND_ITEM_HAS_PCOLOR | CC_BACKGROUND_ITEM_HAS_SCOLOR);
g_object_set (G_OBJECT (configured),
"name", cc_background_item_get_name (saved),
"flags", flags,
"source-url", cc_background_item_get_source_url (saved),
"source-xml", cc_background_item_get_source_xml (saved),
NULL);
}
g_clear_object (&self->current_background);
self->current_background = configured;
cc_background_item_load (configured, NULL);
}
static gboolean
create_save_dir (void)
{
g_autofree char *path = NULL;
path = g_build_filename (g_get_user_config_dir (),
"gnome-control-center",
"backgrounds",
NULL);
if (g_mkdir_with_parents (path, USER_DIR_MODE) < 0)
{
g_warning ("Failed to create directory '%s'", path);
return FALSE;
}
return TRUE;
}
static void
reset_settings_if_defaults (CcBackgroundPanel *self,
GSettings *settings,
gboolean check_dark)
{
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
};
for (i = 0; keys[i] != NULL; i++)
{
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)
return;
if (setting_is_default)
g_settings_reset (settings, keys[i]);
}
g_settings_apply (settings);
}
static void
set_background (CcBackgroundPanel *self,
GSettings *settings,
CcBackgroundItem *item,
gboolean set_dark)
{
GDesktopBackgroundStyle style;
CcBackgroundItemFlags flags;
g_autofree gchar *filename = NULL;
const char *uri;
if (item == NULL)
return;
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)
{
const char *uri_dark;
uri_dark = cc_background_item_get_uri_dark (item);
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);
}
/* Also set the placement if we have a URI and the previous value was none */
if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT)
{
g_settings_set_enum (settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item));
}
else if (uri != NULL)
{
style = g_settings_get_enum (settings, WP_OPTIONS_KEY);
if (style == G_DESKTOP_BACKGROUND_STYLE_NONE)
g_settings_set_enum (settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item));
}
if (flags & CC_BACKGROUND_ITEM_HAS_SHADING)
g_settings_set_enum (settings, WP_SHADING_KEY, cc_background_item_get_shading (item));
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);
/* Clean out dconf if the user went back to distro defaults */
reset_settings_if_defaults (self, settings, set_dark);
/* Save the source XML if there is one */
filename = get_save_path ();
if (create_save_dir ())
cc_background_xml_save (self->current_background, filename);
}
static void
on_chooser_background_chosen_cb (CcBackgroundPanel *self,
CcBackgroundItem *item)
{
set_background (self, self->settings, item, TRUE);
set_background (self, self->lock_settings, item, FALSE);
}
static void
on_add_picture_button_clicked_cb (CcBackgroundPanel *self)
{
cc_background_chooser_select_file (self->background_chooser);
}
static const char *
cc_background_panel_get_help_uri (CcPanel *panel)
{
return "help:gnome-help/look-background";
}
static void
cc_background_panel_dispose (GObject *object)
{
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);
}
static void
cc_background_panel_finalize (GObject *object)
{
CcBackgroundPanel *self = CC_BACKGROUND_PANEL (object);
g_clear_object (&self->current_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);
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);
}
static void
on_settings_changed (CcBackgroundPanel *self)
{
reload_current_bg (self);
update_preview (self);
}
static void
cc_background_panel_init (CcBackgroundPanel *self)
{
g_resources_register (cc_background_get_resource ());
gtk_widget_init_template (GTK_WIDGET (self));
self->connection = g_application_get_dbus_connection (g_application_get_default ());
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);
self->interface_settings = g_settings_new (INTERFACE_PATH_ID);
/* Load the background */
reload_current_bg (self);
update_preview (self);
/* Background settings */
g_signal_connect_object (self->settings, "changed", G_CALLBACK (on_settings_changed), self, G_CONNECT_SWAPPED);
/* 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);
}

View File

@@ -1,30 +0,0 @@
/*
* 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>
*
*/
#pragma once
#include <shell/cc-panel.h>
G_BEGIN_DECLS
#define CC_TYPE_BACKGROUND_PANEL (cc_background_panel_get_type ())
G_DECLARE_FINAL_TYPE (CcBackgroundPanel, cc_background_panel, CC, BACKGROUND_PANEL, CcPanel)
G_END_DECLS

View File

@@ -1,142 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcBackgroundPanel" parent="CcPanel">
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
<property name="content">
<object class="AdwPreferencesPage">
<child>
<object class="AdwPreferencesGroup">
<property name="title" translatable="yes">Style</property>
<child>
<object class="AdwPreferencesRow">
<property name="activatable">False</property>
<property name="focusable">False</property>
<child>
<object class="AdwClamp">
<property name="maximum_size">400</property>
<property name="tightening_threshold">300</property>
<child>
<object class="GtkGrid">
<property name="column-homogeneous">True</property>
<property name="column-spacing">24</property>
<property name="row-spacing">12</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">18</property>
<property name="margin-bottom">12</property>
<property name="hexpand">True</property>
<child>
<object class="GtkToggleButton" id="default_toggle">
<accessibility>
<relation name="labelled-by">default_label</relation>
</accessibility>
<signal name="notify::active" handler="on_color_scheme_toggle_active_cb" swapped="true"/>
<child>
<object class="CcBackgroundPreview" id="default_preview"/>
</child>
<style>
<class name="background-preview-button"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="default_label">
<property name="label" translatable="yes">Default</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkToggleButton" id="dark_toggle">
<property name="group">default_toggle</property>
<accessibility>
<relation name="labelled-by">dark_label</relation>
</accessibility>
<signal name="notify::active" handler="on_color_scheme_toggle_active_cb" swapped="true"/>
<child>
<object class="CcBackgroundPreview" id="dark_preview">
<property name="is-dark">True</property>
</object>
</child>
<style>
<class name="background-preview-button"/>
</style>
<layout>
<property name="column">1</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="dark_label">
<property name="label" translatable="yes">Dark</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="AdwPreferencesGroup">
<property name="title" translatable="yes">Background</property>
<property name="header-suffix">
<object class="GtkButton">
<child>
<object class="AdwButtonContent">
<property name="icon-name">list-add-symbolic</property>
<property name="label" translatable="yes">Add Picture…</property>
</object>
</child>
<signal name="clicked" handler="on_add_picture_button_clicked_cb" object="CcBackgroundPanel" swapped="yes" />
<style>
<class name="flat"/>
</style>
</object>
</property>
<child>
<object class="AdwBin">
<style>
<class name="card"/>
</style>
<child>
<object class="CcBackgroundChooser" id="background_chooser">
<property name="hexpand">True</property>
<signal name="background-chosen" handler="on_chooser_background_chosen_cb" object="CcBackgroundPanel" swapped="yes" />
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</property>
</template>
</interface>

View File

@@ -1,348 +0,0 @@
/* cc-background-preview.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
*/
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
#include "cc-background-preview.h"
struct _CcBackgroundPreview
{
GtkWidget parent;
GtkWidget *drawing_area;
GtkWidget *light_dark_window;
GtkWidget *dark_window;
GnomeDesktopThumbnailFactory *thumbnail_factory;
gboolean is_dark;
CcBackgroundItem *item;
};
G_DEFINE_TYPE (CcBackgroundPreview, cc_background_preview, GTK_TYPE_WIDGET)
enum
{
PROP_0,
PROP_IS_DARK,
PROP_ITEM,
N_PROPS
};
static GParamSpec *properties [N_PROPS];
/* Callbacks */
static void
draw_preview_func (GtkDrawingArea *drawing_area,
cairo_t *cr,
gint width,
gint height,
gpointer user_data)
{
CcBackgroundPreview *self = CC_BACKGROUND_PREVIEW (user_data);
g_autoptr(GdkPixbuf) pixbuf = NULL;
gint scale_factor;
if (!self->item)
return;
scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (drawing_area));
pixbuf = cc_background_item_get_thumbnail (self->item,
self->thumbnail_factory,
width,
height,
scale_factor,
self->is_dark &&
cc_background_item_has_dark_version (self->item));
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
cairo_paint (cr);
}
/* GObject overrides */
static void
cc_background_preview_dispose (GObject *object)
{
CcBackgroundPreview *self = (CcBackgroundPreview *)object;
g_clear_pointer (&self->drawing_area, gtk_widget_unparent);
g_clear_pointer (&self->light_dark_window, gtk_widget_unparent);
g_clear_pointer (&self->dark_window, gtk_widget_unparent);
G_OBJECT_CLASS (cc_background_preview_parent_class)->dispose (object);
}
static void
cc_background_preview_finalize (GObject *object)
{
CcBackgroundPreview *self = (CcBackgroundPreview *)object;
g_clear_object (&self->item);
g_clear_object (&self->thumbnail_factory);
G_OBJECT_CLASS (cc_background_preview_parent_class)->finalize (object);
}
static void
set_is_dark (CcBackgroundPreview *self,
gboolean is_dark)
{
self->is_dark = is_dark;
if (self->is_dark)
{
gtk_widget_add_css_class (self->light_dark_window, "dark");
gtk_widget_remove_css_class (self->light_dark_window, "light");
}
else
{
gtk_widget_add_css_class (self->light_dark_window, "light");
gtk_widget_remove_css_class (self->light_dark_window, "dark");
}
}
static void
cc_background_preview_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcBackgroundPreview *self = CC_BACKGROUND_PREVIEW (object);
switch (prop_id)
{
case PROP_IS_DARK:
g_value_set_boolean (value, self->is_dark);
break;
case PROP_ITEM:
g_value_set_object (value, self->item);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
cc_background_preview_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CcBackgroundPreview *self = CC_BACKGROUND_PREVIEW (object);
switch (prop_id)
{
case PROP_IS_DARK:
set_is_dark (self, g_value_get_boolean (value));
break;
case PROP_ITEM:
cc_background_preview_set_item (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static GtkSizeRequestMode
cc_background_preview_get_request_mode (GtkWidget *widget)
{
return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
}
static void
get_primary_monitor_geometry (int *width, int *height)
{
GdkDisplay *display;
GListModel *monitors;
display = gdk_display_get_default ();
monitors = gdk_display_get_monitors (display);
if (monitors)
{
g_autoptr(GdkMonitor) primary_monitor = NULL;
GdkRectangle monitor_layout;
primary_monitor = g_list_model_get_item (monitors, 0);
gdk_monitor_get_geometry (primary_monitor, &monitor_layout);
if (width)
*width = monitor_layout.width;
if (height)
*height = monitor_layout.height;
return;
}
if (width)
*width = 1920;
if (height)
*height = 1080;
}
static void
cc_background_preview_measure (GtkWidget *widget,
GtkOrientation orientation,
gint for_size,
gint *minimum,
gint *natural,
gint *minimum_baseline,
gint *natural_baseline)
{
GtkWidget *child;
int width;
get_primary_monitor_geometry (&width, NULL);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
*natural = width;
else if (for_size < 0)
*natural = 0;
else
*natural = floor ((double) for_size * 0.75); /* 4:3 aspect ratio */
if (orientation == GTK_ORIENTATION_VERTICAL)
*minimum = *natural;
else
*minimum = 0;
for (child = gtk_widget_get_first_child (widget);
child;
child = gtk_widget_get_next_sibling (child))
{
int child_min, child_nat;
gtk_widget_measure (child, orientation, for_size,
&child_min, &child_nat, NULL, NULL);
*minimum = MAX (*minimum, child_min);
*natural = MAX (*natural, child_nat);
}
}
static void
cc_background_preview_size_allocate (GtkWidget *widget,
gint width,
gint height,
gint baseline)
{
CcBackgroundPreview *self = CC_BACKGROUND_PREVIEW (widget);
int window_width, window_height, margin_x, margin_y;
int opposite_margin_x, opposite_margin_y;
GskTransform *front_transform, *back_transform;
gboolean is_rtl;
window_width = ceil (width * 0.5);
window_height = ceil (height * 0.5);
margin_x = floor (width * 0.15);
margin_y = floor (height * 0.15);
opposite_margin_x = width - window_width - margin_x;
opposite_margin_y = height - window_height - margin_y;
is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
front_transform =
gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (is_rtl ? opposite_margin_x : margin_x,
opposite_margin_y));
back_transform =
gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (is_rtl ? margin_x : opposite_margin_x,
margin_y));
gtk_widget_allocate (self->drawing_area, width, height, baseline, NULL);
gtk_widget_allocate (self->dark_window, window_width, window_height,
baseline, back_transform);
gtk_widget_allocate (self->light_dark_window, window_width, window_height,
baseline, front_transform);
}
static void
cc_background_preview_class_init (CcBackgroundPreviewClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = cc_background_preview_dispose;
object_class->finalize = cc_background_preview_finalize;
object_class->get_property = cc_background_preview_get_property;
object_class->set_property = cc_background_preview_set_property;
widget_class->get_request_mode = cc_background_preview_get_request_mode;
widget_class->measure = cc_background_preview_measure;
widget_class->size_allocate = cc_background_preview_size_allocate;
properties[PROP_IS_DARK] = g_param_spec_boolean ("is-dark",
"Is dark",
"Whether the preview is dark",
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
properties[PROP_ITEM] = g_param_spec_object ("item",
"Item",
"Background item",
CC_TYPE_BACKGROUND_ITEM,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-preview.ui");
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, drawing_area);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, light_dark_window);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, dark_window);
gtk_widget_class_set_css_name (widget_class, "background-preview");
}
static void
cc_background_preview_init (CcBackgroundPreview *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
self->thumbnail_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
}
CcBackgroundItem*
cc_background_preview_get_item (CcBackgroundPreview *self)
{
g_return_val_if_fail (CC_IS_BACKGROUND_PREVIEW (self), NULL);
return self->item;
}
void
cc_background_preview_set_item (CcBackgroundPreview *self,
CcBackgroundItem *item)
{
g_return_if_fail (CC_IS_BACKGROUND_PREVIEW (self));
g_return_if_fail (CC_IS_BACKGROUND_ITEM (item));
if (!g_set_object (&self->item, item))
return;
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (self->drawing_area),
draw_preview_func, self, NULL);
gtk_widget_queue_draw (self->drawing_area);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ITEM]);
}

View File

@@ -1,36 +0,0 @@
/* cc-background-preview.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>
#include "cc-background-item.h"
G_BEGIN_DECLS
#define CC_TYPE_BACKGROUND_PREVIEW (cc_background_preview_get_type())
G_DECLARE_FINAL_TYPE (CcBackgroundPreview, cc_background_preview, CC, BACKGROUND_PREVIEW, GtkWidget)
CcBackgroundItem* cc_background_preview_get_item (CcBackgroundPreview *self);
void cc_background_preview_set_item (CcBackgroundPreview *self,
CcBackgroundItem *item);
G_END_DECLS

View File

@@ -1,55 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<template class="CcBackgroundPreview" parent="GtkWidget">
<property name="overflow">hidden</property>
<property name="width-request">2</property>
<property name="height-request">2</property>
<!-- Wallpaper -->
<child>
<object class="GtkDrawingArea" id="drawing_area"/>
</child>
<!-- Always dark window -->
<child>
<object class="AdwBin" id="dark_window">
<property name="overflow">hidden</property>
<style>
<class name="window"/>
<class name="back"/>
<class name="dark"/>
</style>
<child>
<object class="AdwBin">
<style>
<class name="header-bar"/>
</style>
<property name="valign">start</property>
</object>
</child>
</object>
</child>
<!-- Light/dark window -->
<child>
<object class="AdwBin" id="light_dark_window">
<property name="overflow">hidden</property>
<style>
<class name="window"/>
<class name="front"/>
<class name="light"/>
</style>
<child>
<object class="AdwBin">
<style>
<class name="header-bar"/>
</style>
<property name="valign">start</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,668 +0,0 @@
/*
* Authors: Rodney Dawes <dobey@ximian.com>
* Bastien Nocera <hadess@hadess.net>
*
* Copyright 2003-2006 Novell, Inc. (www.novell.com)
* Copyright 2011 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 <gio/gio.h>
#include <string.h>
#include <libxml/parser.h>
#include <gdesktop-enums.h>
#include "gdesktop-enums-types.h"
#include "cc-background-item.h"
#include "cc-background-xml.h"
/* The number of items we signal as "added" before
* returning to the main loop */
#define NUM_ITEMS_PER_BATCH 1
struct _CcBackgroundXml
{
GObject parent_instance;
GHashTable *wp_hash;
GAsyncQueue *item_added_queue;
guint item_added_id;
GSList *monitors; /* GSList of GFileMonitor */
};
enum {
ADDED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (CcBackgroundXml, cc_background_xml, G_TYPE_OBJECT)
static gboolean
cc_background_xml_get_bool (const xmlNode *parent,
const gchar *prop_name)
{
xmlChar *prop;
gboolean ret_val = FALSE;
g_return_val_if_fail (parent != NULL, FALSE);
g_return_val_if_fail (prop_name != NULL, FALSE);
prop = xmlGetProp ((xmlNode *) parent, (xmlChar*)prop_name);
if (prop != NULL) {
if (!g_ascii_strcasecmp ((gchar *)prop, "true") || !g_ascii_strcasecmp ((gchar *)prop, "1")) {
ret_val = TRUE;
} else {
ret_val = FALSE;
}
xmlFree (prop);
}
return ret_val;
}
static struct {
int value;
const char *string;
} lookups[] = {
{ G_DESKTOP_BACKGROUND_SHADING_HORIZONTAL, "horizontal-gradient" },
{ G_DESKTOP_BACKGROUND_SHADING_VERTICAL, "vertical-gradient" },
};
static int
enum_string_to_value (GType type,
const char *string)
{
GEnumClass *eclass;
GEnumValue *value;
eclass = G_ENUM_CLASS (g_type_class_peek (type));
value = g_enum_get_value_by_nick (eclass, string);
/* Here's a bit of hand-made parsing, bad bad */
if (value == NULL) {
guint i;
for (i = 0; i < G_N_ELEMENTS (lookups); i++) {
if (g_str_equal (lookups[i].string, string))
return lookups[i].value;
}
g_warning ("Unhandled value '%s' for enum '%s'",
string, G_FLAGS_CLASS_TYPE_NAME (eclass));
return 0;
}
return value->value;
}
static gboolean
idle_emit (CcBackgroundXml *xml)
{
gint i;
g_async_queue_lock (xml->item_added_queue);
for (i = 0; i < NUM_ITEMS_PER_BATCH; i++) {
g_autoptr(GObject) item = NULL;
item = g_async_queue_try_pop_unlocked (xml->item_added_queue);
if (item == NULL)
break;
g_signal_emit (G_OBJECT (xml), signals[ADDED], 0, item);
}
g_async_queue_unlock (xml->item_added_queue);
if (g_async_queue_length (xml->item_added_queue) > 0) {
return TRUE;
} else {
xml->item_added_id = 0;
return FALSE;
}
}
static void
emit_added_in_idle (CcBackgroundXml *xml,
GObject *object)
{
g_async_queue_lock (xml->item_added_queue);
g_async_queue_push_unlocked (xml->item_added_queue, object);
if (xml->item_added_id == 0)
xml->item_added_id = g_idle_add ((GSourceFunc) idle_emit, xml);
g_async_queue_unlock (xml->item_added_queue);
}
#define NONE "(none)"
#define UNSET_FLAG(flag) G_STMT_START{ (flags&=~(flag)); }G_STMT_END
#define SET_FLAG(flag) G_STMT_START{ (flags|=flag); }G_STMT_END
static gboolean
cc_background_xml_load_xml_internal (CcBackgroundXml *xml,
const gchar *filename,
gboolean in_thread)
{
xmlDoc * wplist;
xmlNode * root, * list, * wpa;
xmlChar * nodelang;
const gchar * const * syslangs;
gint i;
gboolean retval;
wplist = xmlParseFile (filename);
retval = FALSE;
if (!wplist)
return retval;
syslangs = g_get_language_names ();
root = xmlDocGetRootElement (wplist);
for (list = root->children; list != NULL; list = list->next) {
if (!strcmp ((gchar *)list->name, "wallpaper")) {
g_autoptr(CcBackgroundItem) item = NULL;
CcBackgroundItemFlags flags;
g_autofree gchar *uri = NULL;
g_autofree gchar *cname = NULL;
g_autofree gchar *id = NULL;
flags = 0;
item = cc_background_item_new (NULL);
g_object_set (G_OBJECT (item),
"is-deleted", cc_background_xml_get_bool (list, "deleted"),
"source-xml", filename,
NULL);
for (wpa = list->children; wpa != NULL; wpa = wpa->next) {
if (wpa->type == XML_COMMENT_NODE) {
continue;
} else if (!strcmp ((gchar *)wpa->name, "filename")) {
if (wpa->last != NULL && wpa->last->content != NULL) {
gchar *content = g_strstrip ((gchar *)wpa->last->content);
g_autofree gchar *bg_uri = NULL;
/* FIXME same rubbish as in other parts of the code */
if (strcmp (content, NONE) == 0) {
bg_uri = NULL;
} else {
g_autoptr(GFile) file = NULL;
g_autofree gchar *dirname = NULL;
dirname = g_path_get_dirname (filename);
file = g_file_new_for_commandline_arg_and_cwd (content, dirname);
bg_uri = g_file_get_uri (file);
}
SET_FLAG(CC_BACKGROUND_ITEM_HAS_URI);
g_object_set (G_OBJECT (item), "uri", bg_uri, NULL);
} else {
break;
}
} else if (!strcmp ((gchar *)wpa->name, "filename-dark")) {
if (wpa->last != NULL && wpa->last->content != NULL) {
gchar *content = g_strstrip ((gchar *)wpa->last->content);
g_autofree gchar *bg_uri = NULL;
/* FIXME same rubbish as in other parts of the code */
if (strcmp (content, NONE) == 0) {
bg_uri = NULL;
} else {
g_autoptr(GFile) file = NULL;
g_autofree gchar *dirname = NULL;
dirname = g_path_get_dirname (filename);
file = g_file_new_for_commandline_arg_and_cwd (content, dirname);
bg_uri = g_file_get_uri (file);
}
SET_FLAG(CC_BACKGROUND_ITEM_HAS_URI_DARK);
g_object_set (G_OBJECT (item), "uri-dark", bg_uri, NULL);
} else {
break;
}
} else if (!strcmp ((gchar *)wpa->name, "name")) {
if (wpa->last != NULL && wpa->last->content != NULL) {
g_autofree gchar *name = NULL;
nodelang = xmlNodeGetLang (wpa->last);
g_object_get (G_OBJECT (item), "name", &name, NULL);
if (name == NULL && nodelang == NULL) {
g_free (cname);
cname = g_strdup (g_strstrip ((gchar *)wpa->last->content));
g_object_set (G_OBJECT (item), "name", cname, NULL);
} else {
for (i = 0; syslangs[i] != NULL; i++) {
if (!strcmp (syslangs[i], (gchar *)nodelang)) {
g_object_set (G_OBJECT (item), "name",
g_strstrip ((gchar *)wpa->last->content), NULL);
break;
}
}
}
xmlFree (nodelang);
} else {
break;
}
} else if (!strcmp ((gchar *)wpa->name, "options")) {
if (wpa->last != NULL) {
g_object_set (G_OBJECT (item), "placement",
enum_string_to_value (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE,
g_strstrip ((gchar *)wpa->last->content)), NULL);
SET_FLAG(CC_BACKGROUND_ITEM_HAS_PLACEMENT);
}
} else if (!strcmp ((gchar *)wpa->name, "shade_type")) {
if (wpa->last != NULL) {
g_object_set (G_OBJECT (item), "shading",
enum_string_to_value (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING,
g_strstrip ((gchar *)wpa->last->content)), NULL);
SET_FLAG(CC_BACKGROUND_ITEM_HAS_SHADING);
}
} else if (!strcmp ((gchar *)wpa->name, "pcolor")) {
if (wpa->last != NULL) {
g_object_set (G_OBJECT (item), "primary-color",
g_strstrip ((gchar *)wpa->last->content), NULL);
SET_FLAG(CC_BACKGROUND_ITEM_HAS_PCOLOR);
}
} else if (!strcmp ((gchar *)wpa->name, "scolor")) {
if (wpa->last != NULL) {
g_object_set (G_OBJECT (item), "secondary-color",
g_strstrip ((gchar *)wpa->last->content), NULL);
SET_FLAG(CC_BACKGROUND_ITEM_HAS_SCOLOR);
}
} else if (!strcmp ((gchar *)wpa->name, "source_url")) {
if (wpa->last != NULL) {
g_object_set (G_OBJECT (item),
"source-url", g_strstrip ((gchar *)wpa->last->content),
"needs-download", FALSE,
NULL);
}
} else if (!strcmp ((gchar *)wpa->name, "text")) {
/* Do nothing here, libxml2 is being weird */
} else {
g_debug ("Unknown Tag in %s: %s", filename, wpa->name);
}
}
/* Check whether the target file exists */
{
const char *uri;
uri = cc_background_item_get_uri (item);
if (uri != NULL)
{
g_autoptr(GFile) file = NULL;
file = g_file_new_for_uri (uri);
if (g_file_query_exists (file, NULL) == FALSE)
{
g_clear_pointer (&cname, g_free);
g_clear_object (&item);
continue;
}
}
}
/* FIXME, this is a broken way of doing,
* need to use proper code here */
uri = g_filename_to_uri (filename, NULL, NULL);
id = g_strdup_printf ("%s#%s", uri, cname);
/* Make sure we don't already have this one and that filename exists */
if (g_hash_table_lookup (xml->wp_hash, id) != NULL) {
continue;
}
g_object_set (G_OBJECT (item), "flags", flags, NULL);
g_hash_table_insert (xml->wp_hash,
g_strdup (id),
g_object_ref (item));
if (in_thread)
emit_added_in_idle (xml, g_object_ref (G_OBJECT (item)));
else
g_signal_emit (G_OBJECT (xml), signals[ADDED], 0, item);
retval = TRUE;
}
}
xmlFreeDoc (wplist);
return retval;
}
static void
gnome_wp_file_changed (CcBackgroundXml *xml,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type)
{
g_autofree gchar *filename = NULL;
switch (event_type) {
case G_FILE_MONITOR_EVENT_CHANGED:
case G_FILE_MONITOR_EVENT_CREATED:
filename = g_file_get_path (file);
cc_background_xml_load_xml_internal (xml, filename, FALSE);
break;
default:
break;
}
}
static void
cc_background_xml_add_monitor (GFile *directory,
CcBackgroundXml *data)
{
GFileMonitor *monitor;
g_autoptr(GError) error = NULL;
monitor = g_file_monitor_directory (directory,
G_FILE_MONITOR_NONE,
NULL,
&error);
if (error != NULL) {
g_autofree gchar *path = NULL;
path = g_file_get_parse_name (directory);
g_warning ("Unable to monitor directory %s: %s",
path, error->message);
return;
}
g_signal_connect_swapped (monitor, "changed",
G_CALLBACK (gnome_wp_file_changed),
data);
data->monitors = g_slist_prepend (data->monitors, monitor);
}
static void
cc_background_xml_load_from_dir (const gchar *path,
CcBackgroundXml *data,
gboolean in_thread)
{
g_autoptr(GFile) directory = NULL;
g_autoptr(GFileEnumerator) enumerator = NULL;
g_autoptr(GError) error = NULL;
if (!g_file_test (path, G_FILE_TEST_IS_DIR)) {
return;
}
directory = g_file_new_for_path (path);
enumerator = g_file_enumerate_children (directory,
G_FILE_ATTRIBUTE_STANDARD_NAME,
G_FILE_QUERY_INFO_NONE,
NULL,
&error);
if (error != NULL) {
g_warning ("Unable to check directory %s: %s", path, error->message);
return;
}
while (TRUE) {
g_autoptr(GFileInfo) info = NULL;
const gchar *filename;
g_autofree gchar *fullpath = NULL;
info = g_file_enumerator_next_file (enumerator, NULL, NULL);
if (info == NULL) {
g_file_enumerator_close (enumerator, NULL, NULL);
cc_background_xml_add_monitor (directory, data);
return;
}
filename = g_file_info_get_name (info);
fullpath = g_build_filename (path, filename, NULL);
cc_background_xml_load_xml_internal (data, fullpath, in_thread);
}
}
static void
cc_background_xml_load_list (CcBackgroundXml *data,
gboolean in_thread)
{
const char * const *system_data_dirs;
g_autofree gchar *datadir = NULL;
gint i;
datadir = g_build_filename (g_get_user_data_dir (),
"gnome-background-properties",
NULL);
cc_background_xml_load_from_dir (datadir, data, in_thread);
system_data_dirs = g_get_system_data_dirs ();
for (i = 0; system_data_dirs[i]; i++) {
g_autofree gchar *sdatadir = NULL;
sdatadir = g_build_filename (system_data_dirs[i],
"gnome-background-properties",
NULL);
cc_background_xml_load_from_dir (sdatadir, data, in_thread);
}
}
gboolean
cc_background_xml_load_list_finish (CcBackgroundXml *xml,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (g_task_is_valid (result, xml), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
load_list_thread (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
CcBackgroundXml *xml = CC_BACKGROUND_XML (source_object);
cc_background_xml_load_list (xml, TRUE);
g_task_return_boolean (task, TRUE);
}
void
cc_background_xml_load_list_async (CcBackgroundXml *xml,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
g_return_if_fail (CC_IS_BACKGROUND_XML (xml));
task = g_task_new (xml, cancellable, callback, user_data);
g_task_run_in_thread (task, load_list_thread);
}
gboolean
cc_background_xml_load_xml (CcBackgroundXml *xml,
const gchar *filename)
{
g_return_val_if_fail (CC_IS_BACKGROUND_XML (xml), FALSE);
if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) == FALSE)
return FALSE;
return cc_background_xml_load_xml_internal (xml, filename, FALSE);
}
static void
single_xml_added (CcBackgroundXml *xml,
CcBackgroundItem *item,
CcBackgroundItem **ret)
{
g_assert (*ret == NULL);
*ret = g_object_ref (item);
}
CcBackgroundItem *
cc_background_xml_get_item (const char *filename)
{
g_autoptr(CcBackgroundXml) xml = NULL;
CcBackgroundItem *item = NULL;
if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) == FALSE)
return NULL;
xml = cc_background_xml_new ();
g_signal_connect (G_OBJECT (xml), "added",
G_CALLBACK (single_xml_added), &item);
if (cc_background_xml_load_xml (xml, filename) == FALSE)
return NULL;
return item;
}
static const char *
enum_to_str (GType type,
int v)
{
GEnumClass *eclass;
GEnumValue *value;
eclass = G_ENUM_CLASS (g_type_class_peek (type));
value = g_enum_get_value (eclass, v);
g_assert (value);
return value->value_nick;
}
void
cc_background_xml_save (CcBackgroundItem *item,
const char *filename)
{
xmlDoc *wp;
xmlNode *root, *wallpaper;
xmlNode *xml_item G_GNUC_UNUSED;
const char * none = "(none)";
const char *placement_str, *shading_str;
g_autofree gchar *name = NULL;
g_autofree gchar *pcolor = NULL;
g_autofree gchar *scolor = NULL;
g_autofree gchar *uri = NULL;
g_autofree gchar *source_url = NULL;
CcBackgroundItemFlags flags;
GDesktopBackgroundStyle placement;
GDesktopBackgroundShading shading;
xmlKeepBlanksDefault (0);
wp = xmlNewDoc ((xmlChar *)"1.0");
xmlCreateIntSubset (wp, (xmlChar *)"wallpapers", NULL, (xmlChar *)"gnome-wp-list.dtd");
root = xmlNewNode (NULL, (xmlChar *)"wallpapers");
xmlDocSetRootElement (wp, root);
g_object_get (G_OBJECT (item),
"name", &name,
"uri", &uri,
"shading", &shading,
"placement", &placement,
"primary-color", &pcolor,
"secondary-color", &scolor,
"source-url", &source_url,
"flags", &flags,
NULL);
placement_str = enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE, placement);
shading_str = enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING, shading);
wallpaper = xmlNewChild (root, NULL, (xmlChar *)"wallpaper", NULL);
xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"name", (xmlChar *)name);
if (flags & CC_BACKGROUND_ITEM_HAS_URI &&
uri != NULL)
{
g_autoptr(GFile) file = NULL;
g_autofree gchar *fname = NULL;
file = g_file_new_for_commandline_arg (uri);
fname = g_file_get_path (file);
xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"filename", (xmlChar *)fname);
}
else if (flags & CC_BACKGROUND_ITEM_HAS_URI)
{
xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"filename", (xmlChar *)none);
}
if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT)
xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"options", (xmlChar *)placement_str);
if (flags & CC_BACKGROUND_ITEM_HAS_SHADING)
xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"shade_type", (xmlChar *)shading_str);
if (flags & CC_BACKGROUND_ITEM_HAS_PCOLOR)
xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"pcolor", (xmlChar *)pcolor);
if (flags & CC_BACKGROUND_ITEM_HAS_SCOLOR)
xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"scolor", (xmlChar *)scolor);
if (source_url != NULL)
xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"source_url", (xmlChar *)source_url);
xmlSaveFormatFile (filename, wp, 1);
xmlFreeDoc (wp);
}
static void
cc_background_xml_finalize (GObject *object)
{
CcBackgroundXml *xml;
g_return_if_fail (object != NULL);
g_return_if_fail (CC_IS_BACKGROUND_XML (object));
xml = CC_BACKGROUND_XML (object);
g_slist_free_full (xml->monitors, g_object_unref);
g_clear_pointer (&xml->wp_hash, g_hash_table_destroy);
if (xml->item_added_id != 0) {
g_source_remove (xml->item_added_id);
xml->item_added_id = 0;
}
g_clear_pointer (&xml->item_added_queue, g_async_queue_unref);
G_OBJECT_CLASS (cc_background_xml_parent_class)->finalize (object);
}
static void
cc_background_xml_class_init (CcBackgroundXmlClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = cc_background_xml_finalize;
signals[ADDED] = g_signal_new ("added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, CC_TYPE_BACKGROUND_ITEM);
}
static void
cc_background_xml_init (CcBackgroundXml *xml)
{
xml->wp_hash = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_object_unref);
xml->item_added_queue = g_async_queue_new_full ((GDestroyNotify) g_object_unref);
}
CcBackgroundXml *
cc_background_xml_new (void)
{
return CC_BACKGROUND_XML (g_object_new (CC_TYPE_BACKGROUND_XML, NULL));
}

View File

@@ -1,46 +0,0 @@
/*
* Authors: Rodney Dawes <dobey@ximian.com>
*
* Copyright 2003-2012 Novell, Inc. (www.novell.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/>.
*/
#pragma once
#include <gtk/gtk.h>
#include <gio/gio.h>
G_BEGIN_DECLS
#define CC_TYPE_BACKGROUND_XML (cc_background_xml_get_type ())
G_DECLARE_FINAL_TYPE (CcBackgroundXml, cc_background_xml, CC, BACKGROUND_XML, GObject)
CcBackgroundXml *cc_background_xml_new (void);
void cc_background_xml_save (CcBackgroundItem *item,
const char *filename);
CcBackgroundItem *cc_background_xml_get_item (const char *filename);
gboolean cc_background_xml_load_xml (CcBackgroundXml *data,
const char *filename);
void cc_background_xml_load_list_async (CcBackgroundXml *xml,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean cc_background_xml_load_list_finish (CcBackgroundXml *xml,
GAsyncResult *result,
GError **error);
G_END_DECLS

View File

@@ -1,14 +0,0 @@
[Desktop Entry]
Name=Appearance
Comment=Change your background image or the UI colors
Exec=gnome-control-center background
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=org.gnome.Settings-appearance-symbolic
Terminal=false
Type=Application
NoDisplay=true
StartupNotify=true
Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalizationSettings;
OnlyShowIn=GNOME;
# Translators: Search terms to find the Appearance panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=Background;Wallpaper;Screen;Desktop;Style;Light;Dark;Appearance;

View File

@@ -1,4 +0,0 @@
install_data(
'scalable/org.gnome.Settings-appearance-symbolic.svg',
install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
)

View File

@@ -1,9 +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">
<g fill="#2e3436">
<path d="m 3.011719 1 c -1.644531 0 -3.0000002 1.355469 -3.0000002 3 v 6 c 0 1.644531 1.3554692 3 3.0000002 3 h 10 c 1.644531 0 3 -1.355469 3 -3 v -6 c 0 -0.570312 -0.167969 -1.101562 -0.449219 -1.558594 l -1.550781 1.554688 v 6.003906 c 0 0.570312 -0.429688 1 -1 1 h -10 c -0.570313 0 -1 -0.429688 -1 -1 v -6 c 0 -0.570312 0.429687 -1 1 -1 h 5.96875 l 2.007812 -2 z m 0 0"/>
<path d="m 11.011719 7 c 0 1.65625 -1.339844 3.007812 -3 3 h -3 v -3 c 0 -1.660156 1.34375 -3 3 -3 c 1.660156 0 3 1.339844 3 3 z m 0 0"/>
<path d="m 13.410156 0 l -3.46875 3.457031 c 0.683594 0.355469 1.234375 0.910157 1.589844 1.589844 l 0.171875 -0.171875 l 0.007813 0.007812 l 4.300781 -4.300781 v -0.582031 z m 0 0"/>
<path d="m 5.011719 14 c -1.105469 0 -2 0.894531 -2 2 h 10 c 0 -1.105469 -0.894531 -2 -2 -2 z m 0 0"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 999 B

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