Compare commits

..

1 Commits

Author SHA1 Message Date
Mario Sanchez Prada
df8eccc264 Don't declare StartupNotify=true in panel-specific desktop files
As per the Startup Notification Spec, when an application declares this
in its desktop file, it the launcher (e.g. the shell) will initiate the
startup process, expecting the launchee to finish it with a "remove" X
message once it's ready, unless there's a failure launching it.

The problem here is that this panel-specific desktop files declaring that
key confuses the shell, since it will make it initiate the startup process
but then no "remove" message is ever received if g-c-c was already running,
since the newly launched process will realize it's not the main instance and
will exit gracefully after handing over control of the situation to the
original process, with exit code 0, leaving the startup process unfinished.

Due to this, the shell will keep waiting for a supposedly new application
(as per the the panel-specific desktop file used to launch) to finish, which
will result in the cursor to keep spinning after the app is discarded by the
shell on a timeout.

We should fix this in a more general way (see [2]), since apps exiting due
to handing control over to a previous instance should still send the "remove"
message, but in the meantime let's make our user's lives better by not
declaring this key in any of the panel-specific desktop files.

[1] https://www.freedesktop.org/wiki/Specifications/startup-notification-spec
[2] https://bugzilla.gnome.org/show_bug.cgi?id=795779
2018-05-03 19:08:10 +01:00
1089 changed files with 338708 additions and 394926 deletions

2
.gitignore vendored
View File

@@ -1,3 +1 @@
__pycache__
_build/
**/*~

View File

@@ -1,127 +1,25 @@
include:
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/5888c7388134cbe4661600222fe9befb10441f6e/templates/fedora.yml'
variables:
FDO_UPSTREAM_REPO: gnome/gnome-control-center
image: fedora:rawhide
stages:
- prepare
- build
- test
- manual
- deploy
.Log files: &log_files [./*.log, _build/meson-logs/]
variables:
DEPENDENCIES: accountsservice-devel cheese-libs-devel chrpath clutter-gtk-devel colord-devel
colord-gtk-devel cups-devel desktop-file-utils docbook-style-xsl gdk-pixbuf2-devel
gettext git glib2-devel gnome-bluetooth-libs-devel gnome-desktop3-devel
gnome-online-accounts-devel gnome-settings-daemon-devel grilo-devel
gsettings-desktop-schemas-devel gtk3-devel ibus-devel intltool libcanberra-devel
libgtop2-devel libgudev-devel libnma-devel libpwquality-devel libsmbclient-devel
libsoup-devel libwacom-devel libX11-devel libXi-devel libxml2-devel libxslt
libXxf86misc-devel meson ModemManager-glib-devel NetworkManager-libnm-devel
polkit-devel pulseaudio-libs-devel upower-devel
python3-dbusmock xorg-x11-server-Xvfb mesa-dri-drivers
.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
before_script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
.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 ==" &&
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:
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: '2021-07-22.0-gnome-40'
FDO_DISTRIBUTION_VERSION: '34'
#############################################
# 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
gnome-settings-daemon-devel
grilo-devel
gsettings-desktop-schemas-devel
gsound-devel
gtk3-devel ibus-devel
intltool
libcanberra-devel
libgtop2-devel
libgudev-devel
libnma-devel
libpwquality-devel
libsmbclient-devel
libsoup-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
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 ..
##
# Stage: Build
@@ -131,29 +29,12 @@ build.container.fedora@x86_64:
# any of them.
##
build:
extends:
- '.fdo.distribution-image@fedora'
- '.fedora.container.common'
<<: *save_untracked_files
stage: build
script:
- *environment_information
- *build_procedure
- echo "== Installing =="
- meson . _build
- ninja -C _build
- 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
@@ -161,202 +42,24 @@ build:
# Runs the unit tests.
##
test:
extends:
- '.fdo.distribution-image@fedora'
- '.fedora.container.common'
<<: *save_build_logs
stage: test
dependencies:
- build
script:
- *environment_information
- *run_tests
- meson . _build
- ninja -C _build
- meson test -C _build --verbose --no-stdsplit
- |
if [[ -n "${CI_COMMIT_TAG}" ]]; then
echo "== Distro Test =="
ninja dist -C _build
fi
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:
- master@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
# Checks if the released version is in a good shape.
##
pages:
extends:
- '.fdo.distribution-image@fedora'
- '.fedora.container.common'
deploy:
stage: deploy
dependencies:
- coverage
script:
- mv _build/meson-logs/coveragereport/ public/
artifacts:
paths:
- public
- meson . _build
- ninja -C _build
- meson test -C _build
- ninja dist -C _build
only:
- master@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: registry.gitlab.gnome.org/gnome/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: "org.gnome.Settings.json"
PATCHES: "build-aux/flatpak/*.patch"
PROJECT_FILE: "build-aux/flatpak/org.gnome.Settings.json"
PROJECT_ID: "org.gnome.Settings"
PROJECT_NAME: "gnome-control-center.git"
RUNTIME_REPO: "https://sdk.gnome.org/gnome-nightly.flatpakrepo"
script:
- echo "== Flatpak packaging =="
# Move needed files to the root folder
- cp ${PATCHES} . || true
- cp ${PROJECT_FILE} ${MANIFEST_PATH}
# Make it a develoment manifest
- sed -i -n "p; s/$PROJECT_NAME//p" ${MANIFEST_PATH}
- >
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 --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-.*
- master@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$/
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"
- tags

View File

@@ -1,13 +1,3 @@
<!--
Not following the communication guidelines [1] will mean your issue or comment
will be removed. Read it carefully before submitting this issue.
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/CONTRIBUTING.md#communication-guideline
-->
Detailed description of the issue. Put as much information as you can, potentially
with images showing the issue.

View File

@@ -1,13 +1,3 @@
<!--
Not following the communication guidelines [1] will mean your issue or comment
will be removed. Read it carefully before submitting this issue.
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/CONTRIBUTING.md#communication-guideline
-->
Detailed description of the feature. Put as much information as you can.
Proposed Mockups:

5
.gitmodules vendored
View File

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

1
AUTHORS Normal file
View File

@@ -0,0 +1 @@
Jonathan Blandford <jrb@redhat.com>

2
ChangeLog Normal file
View File

@@ -0,0 +1,2 @@
The ChangeLog is auto-generated when releasing. If you are seeing this, use
'git log' for a detailed list of changes.

1
MAINTAINERS Normal file
View File

@@ -0,0 +1 @@
See gnome-control-center.doap file

661
NEWS
View File

@@ -1,664 +1,3 @@
================
Version 40.9
================
- Drop unused argument for i18n.merge_file() in Meson rules
- Updated translations
Display
- Do not invert order when constructing modes
Sound
- Update the volume-slider after getting a valid stream
- Clear level bar when stream is empty
================
Version 40.7
================
- Updated translations
================
Version 40.6
================
- Updated translations
================
Version 40.1
================
- Updated translations
About
- Don't show GNOME micro version
Location
- Fix permission store table and id
Network
- Show all IPv6 addresses for an interface
- Display IPv6 gateway
Power
- Fix D-Bus proxy leak
================
Version 40
================
- Updated translations
================
Version 40.rc
================
- Various fixes to the language chooser
- Updated translations
Location
- Wrap label to fit smaller window sizes
Mouse & Touchpad
- Allow horizontal scrolling in test page
Network
- Fix creation of the netmask widget
================
Version 40.beta
================
- Various improvements to fingerprint management
- Show hardware model and vendor in the About panel
- New Keyboard panel design
- New power mode selector in the Power panel
- Updated translations
About
- Show hardware model and vendor
- Use os-release to search for the OS logo
Accessibility
- Major code cleanup
Display
- Try harder to select a good and working scale
Keyboard
- Handle input sources
Power
- Rearrange battery code to a new widget
- Add a new "Power Mode" section
Sharing
- Also disable Traker3
Sound
- Update mute button icon when volume changes
User Accounts
- Fix free of constant string
- Use properly translated fingerprint strings
- Improve transition to parental controls window
- Many improvements to fingerprint management
================
Version 3.38.0
================
- Updated translations
================
Version 3.37.92
================
- Updated translations
Display
- Show screen orientation setting even when accelerometer is present
Wacom
- Group pad/stylus devices together with the group name
================
Version 3.37.90
================
- Rename Universal to Accessibility
- Updated translations
- Clean CI jobs
- Adapt to libhandy-1
Network
- Add support for Enhanced Open Wi-Fi security
- Fix connection editor blanking when removing manual entry
- Small fixes
Thunderbolt
- Plug some memory leaks
User Accounts
- Show "Take a picture" button only when cam is available
================
Version 3.37.3
================
- Update various panels with more modern GTK practices
- Improve how time periods are displayed
- Rework CI images to use FreeDesktop-style templates
- Improve Settings icon
- Updated translations
Applications
- Integrate with parental controls
Date & Time
- Add new time editor UI
Keyboard
- Various cleanups
Lock Screen
- Add USB protection entry when available
Power
- Add option to show battery percentage
- Various smaller UI adjustments
Printers
- Do not authenticate SMB servers when search field is edited
Sharing
- Set label for checkbox properly
- Use gnome-remote-desktop instead of Vino on X11
Sound
- Fix translation of "System Sounds"
- Stop non-interactive profile changes from triggering changed events
User Accounts
- Always show permissions bar, even when no users are listed
- Use custom setting to override faces
- New Fingerprint dialog and various related improvements
- Integrate with parental controls
================
Version 3.36.1
================
- Update man page for info panel change
- Updated translations
Display
- Fix resolution options getting stuck in a low resolution
Sound
- Remove unused files
================
Version 3.36.0
================
- Updated translations
================
Version 3.35.92
================
- Updated translations
Applications
- Update icon
Background
- Remove split desktop and lock screen wallpapers
- Improve visuals of the background icons
Network
- Make VPN gear buttons consistent with oter buttons
================
Version 3.35.91
================
- Share GCancellable code
- Updated translations
Background
- Remove unused GCancellable
Power
- Fix mobile broadband switch logic
Sharing
- Remember password on remote desktop sharing
Thunderbolt
- Fix GCancellable leak
User Accounts
- Always generate user avatars
================
Version 3.35.90
================
- New sidebar panel order and grouping
- Introduce CcPermissionInfoBar
- More code style updates
- Updated translations
Applications
- Add "Run in Background" switch
- Add "Set Desktop Background" switch
- Show snap packages
Network
- Add SAE support
- Many code refactorings
- Switch to use GtkTemplate
Power
- Hide power button the chassis is handset
Printers
- Use CcPermissionInfoBar
Region & Language
- New design for the Formats dialog
User Accounts
- Use CcPermissionInfoBar
- Improved layout
================
Version 3.35.2
================
- Tighten up code style
- Improve timezone for various countries
- Replace deprecated logging functions with modern equivalents
- Updated translations
Background
- Update clock in both preview modes
Date & Time
- Allow changing the timezone when auto-update is prohibited
Display
- Replace CC_DISPLAY_*_GET_PRIVATE
Info
- Implement new design
- Add windowing system field
Network
- Add new hotspot creation dialog
- Major cleanups and code refactorings
- Plug various memory leaks
Privacy
- Drop the panel and replace it by various subpanels
Search
- Make rows and its elements reachable via keyboard
Sharing
- Set new shared folder visible as soon as it gets added
Sound
- Remove leftover canberra-gtk header inclusion
Universal Access
- Make rows and its elements reachable via keyboard
User Accounts
- Use 'pw usershow' to check username validity on FreeBSD
================
Version 3.34.0.1
================
Sound
- Fix sliders not behaving properly
================
Version 3.34.0
================
- Updated translations
================
Version 3.33.90
================
- Updated translations
Background:
- Clarify remove background button
Display:
- Various bugfixes
Search:
- Introduce Drag n' Drop
- Visual polishment
================
Version 3.33.3
================
- Various minor improvements from the Every Detail Matters session
- Add shadows to application icons
- Documented Communication Guidelines
- Development builds with Flatpak working again
- Updated translations
Background:
- Redesigned panel
Display:
- Move Night Light to a tab, instead of a dialog
Keyboard Shortcuts:
- Panel renamed from "Keyboard"
- Minor UI adjustments
Mouse & Touchpad:
- Reinstate keyboard navitation
Power:
- Don't treat all batteries as laptop batteries
Sharing:
- Use a HdyLeaflet
User Accounts:
- Present the default avatar in the avatar popover
Wacom:
- Ensure calibrator UI CSS only applies to its UI
================
Version 3.32.1
================
- Add shadows to application icons
- Updated translations
Applications:
- Fix wrong IDs being passed to portal permission store
Display:
- Various bugfixes to multimonitor setups
Mouse & Touchpad:
- Sync touchpad scrolling switch states correctly
Network:
- Only show Bluetooth devices in Bluetooth section
Online Accounts:
- Fix invisible widgets
Wi-Fi:
- Fix connection names with markup not showing up
================
Version 3.32.0.1
================
- Emergency release with a fix for broken translations and the Display
panel
===============
Version 3.32.0
===============
- Translation updates
===============
Version 3.31.92
===============
- Translation updates
- CI improvements
- Revert making Settings responsive; it needs more polish to reach the
quality we want.
User Accounts:
- Improve behavior when dealing with very long names
- Fix crashes
- Remove custom file size limit for avatars
- Allow bigger custom avatars
===============
Version 3.31.90
===============
- Make Settings and various panels responsive
- Various accessibility fixes
- Translation updates
Printers:
- Various cleanups
Region and Language:
- Make rows reordetable with drag and drop
Sound:
- Redesign the Sound panel
User Accounts:
- Allow Remove User button to be focused
- Round user images
===============
Version 3.31.4
===============
- Introduce the new Applications panel
- Panels can now expose a custom sidebar widget
- Improve CI image building scripts
- Translation updates
Applications:
- Introduce the new Applications panel
Bluetooth:
- Cleanup and reorganize code
Display:
- Add Night Light slider to set temperature
Network:
- Allow Wi-Fi panel to reach narrower sizes
- Cleanups and smaller performance improvement preparations
Notifications:
- Use libhandy's HdyColumn
Online Accounts:
- Use libhandy's HdyColumn
Power:
- Label PENDING_CHARGE state as "Not Charging"
Printers:
- Cleanups and memory leaks plugs
Privacy:
- Use libhandy's HdyColumn
Thunderbolt:
- Fix double-free
User Accounts:
- Rename classes
Wacom:
- Map Wacom-driver-specific generic IDs to 0
===============
Version 3.31.2
===============
- Use X-GNOME-UsesNotifications on various desktop files
- Introduce new icon
- Add interative test panels
- Translation updates
Date & Time:
- Grey out automatic timezone
Display:
- Correctly add minor axis to snapping
- Correctly snap on various situations
Network:
- Cleanup many classes
Online Accounts:
- Track lifecycle of CcGoaPanel across async calls
Privacy:
- Use templates
Region and Language:
- Use a popover instead of a dialog for input options
- Redesign language chooser widget
- Plug various leaks
- Major cleanups
Sharing:
- Bind hostname entry
User Accounts:
- Use templates
- Do not crash when libpwquality fails
Wacom:
- Port calibrator UI to GTK
- Remove clutter-gtk dependency
===============
Version 3.30.0
===============
- Translation updates
===============
Version 3.29.92
===============
- Fix a couple of memory leaks in the tests
- Don't hardcode Python path in tests
- Stop aggressively caching D-Bus objects not related to hardware
CI:
- Improve Flatpak job
User Accounts:
- Silence some compiler warnings
- Remove stub string from translation
Wacom
- Remove unused widgets from the .ui file
Wi-Fi:
- Fix a potential crash
===============
Version 3.29.90
===============
- Use symbolic icons in Shell search
Network:
- Better device names
Power:
- Improve wording of some strings
Region & Language:
- Make Language Chooser dialog implement mockups
Wi-Fi:
- Improve Airplane Mode
==============
Version 3.29.4
==============
- Introduce Dynamic Panel
- Many code cleanups and modernizations
CI:
- Support for multiarch builds (ARMv8 and PPC64)
- Support generating Flatpaks on demand
Display:
- Improve display arrangement widget
Network:
- Add a testsuite
Sharing:
- Expose Remote Desktop work on Wayland
User Accounts:
- Use term "Confirm" instead of "Verify"
- Use the same phrase when passwords do not match
Wacom:
- Hide when no Wacom devices are connected
- Remove deprecated APIs
Wi-Fi:
- Hide when no Wi-Fi adapters are available
==============
Version 3.29.2
==============
- Improve logging engine
- Add an object caching mechanism
- Add a development Flatpak manifest
- Vastly improve CI
- Organize tests
- Add Network tests
- Translation updates
Display:
- Fix a few crashers
Power:
- Fix showing approximate percentages
Thunderbolt:
- Introduce new Thunderbolt panel
User Accounts:
- Port to GTask
- Fix hint for wrong enterprise user/password
===============
Version 3.27.92
===============

View File

@@ -1,11 +1,8 @@
[![Build Status](https://gitlab.gnome.org/GNOME/gnome-control-center/badges/master/pipeline.svg)](https://gitlab.gnome.org/GNOME/gnome-control-center/pipelines)
[![Coverage report](https://gitlab.gnome.org/GNOME/gnome-control-center/badges/master/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/master/COPYING)
GNOME Settings
====================
GNOME Settings is GNOME's main interface for configuration of various aspects of your desktop.
GNOME Settings is GNOME's main interface for configuration of various aspects of
your desktop.
## Contributing
@@ -14,50 +11,30 @@ for the coding style guidelines.
## Reporting Bugs
Before reporting any bugs or opening feature requests, [read the communication guidelines][communication-guidelines].
Bugs should be reported to the GNOME bug tracking system under the product
gnome-control-center. It is available at [GitLab Issues](https://gitlab.gnome.org/GNOME/gnome-control-center/issues).
gnome-control-center. It is available at https://gitlab.gnome.org.
In the report please include the following information:
In the report please include the following information -
* Operating system and version
* For Linux, version of the C library
* Exact error message
* Steps to reproduce the bug
* If the bug is a visual defect, attach a screenshot
* If the bug is a crash, attach a backtrace if possible [see below]
Operating system and version
For Linux, version of the C library
How to reproduce the bug if possible
If the bug was a crash, include the exact text that was printed out
A stacktrace where possible [see below]
### How to get a backtrace
### How to get a stack trace
If the crash is reproducible, follow the steps to obtain a
backtrace:
If the crash is reproducible, it is possible to get a stack trace and
attach it to the bug report. The following steps are used to obtain a
stack trace -
Run the program in gdb [the GNU debugger] or any other debugger
ie. gdb gnome-keyboard-properties
Start the program
ie. (gdb) run
Reproduce the crash and the program will exit to the gdb prompt
Get the back trace
ie. (gdb) bt full
Install debug symbols for gnome-control-center.
Run the program in gdb [the GNU debugger] or any other debugger.
gdb gnome-control-center
Start the program.
(gdb) run
Reproduce the crash and when the program exits to (gdb) prompt, get the backtrace.
(gdb) bt full
Once you have the backtrace, copy and paste it into the 'Comments' field or attach it as
a file to the bug report.
## Testing Unstable Settings
It is quite easy to test and give feedback about the development version of GNOME
Settings. Just access https://gitlab.gnome.org/GNOME/gnome-control-center/environments,
get the latest version, download it, double-click the file, install and run.
Note that GNOME Settings Flatpak will only work if you are running
the latest GNOME version in your host system.
[communication-guidelines]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/CONTRIBUTING.md#communication-guidelines
Once you have the backtrace, copy and paste this either into the
'Comments' field or attach a file with it included.

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,820 +0,0 @@
{
"app-id" : "org.gnome.Settings",
"runtime" : "org.gnome.Sdk",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gnome-control-center",
"rename-desktop-file" : "gnome-control-center.desktop",
"tags" : [
"devel"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"--device=dri",
"--env=DCONF_USER_CONFIG_DIR=.config/dconf",
"--filesystem=host",
"--own-name=org.gnome.ControlCenter",
"--own-name=org.gnome.SessionManager",
"--share=ipc",
"--share=network",
"--socket=x11",
"--socket=pulseaudio",
"--socket=session-bus",
"--socket=system-bus",
"--socket=wayland"
],
"build-options" : {
"cflags" : "-O2 -g",
"cxxflags" : "-O2 -g",
"env" : {
"V" : "1"
}
},
"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-introspection",
"--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" : "accountservice",
"buildsystem" : "meson",
"config-opts" : [
"-Ddocbook=false",
"-Delogind=false",
"-Dgtk_doc=false",
"-Dintrospection=false",
"-Dsystemd=false",
"-Dsystemdsystemunitdir=no"
],
"sources" : [
{
"type" : "git",
"url" : "git://anongit.freedesktop.org/accountsservice"
}
]
},
{
"name" : "libusb1",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-udev"
],
"sources" : [
{
"type" : "git",
"url" : "git://github.com/libusb/libusb.git"
}
]
},
{
"name" : "gusb",
"buildsystem" : "meson",
"config-opts" : [
"-Ddocs=false",
"-Dtests=false",
"-Dvapi=false"
],
"sources" : [
{
"type" : "git",
"url" : "git://github.com/hughsie/libgusb.git"
}
]
},
{
"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" : "git://github.com/gentoo/eudev.git"
}
]
},
{
"name" : "gudev",
"buildsystem" : "meson",
"config-opts" : [
"-Dtests=disabled",
"-Dintrospection=disabled"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/libgudev.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",
"url" : "git://github.com/hughsie/colord.git"
}
]
},
{
"name" : "colord-gtk",
"buildsystem" : "meson",
"config-opts" : [
"-Dman=false"
],
"sources" : [
{
"type" : "git",
"url" : "git://github.com/hughsie/colord-gtk.git"
}
]
},
{
"name" : "rest",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "git",
"branch" : "librest-0-7",
"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-gtk-doc=false",
"-Denable-introspection=false",
"-Denable-installed-tests=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/geocode-glib.git"
}
]
},
{
"name" : "libgweather",
"buildsystem" : "meson",
"config-opts" : [
"-Dglade_catalog=false",
"-Denable_vala=false",
"-Dgtk_doc=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/libgweather.git"
}
]
},
{
"name" : "upower",
"buildsystem" : "autotools",
"config-opts" : [
"--prefix=/app",
"--with-systemdsystemunitdir=/app/lib/systemd/system",
"--disable-gtk-doc",
"--disable-man-pages",
"--disable-tests"
],
"sources" : [
{
"type" : "git",
"url" : "git://anongit.freedesktop.org/upower"
}
]
},
{
"name" : "libwacom",
"buildsystem" : "autotools",
"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",
"-Ddbus_ifaces_dir=/app/share/dbus-1/interfaces",
"-Ddbus_sys_dir=/app/share/dbus-1/system.d",
"-Ddnsmasq=/usr/bin/true",
"-Ddocs=false",
"-Dintrospection=false",
"-Diptables=/usr/bin/true",
"-Djson_validation=false",
"-Dlibnm_glib=false",
"-Dlibpsl=false",
"-Dmodem_manager=false",
"-Dnmtui=false",
"-Dovs=false",
"-Dppp=false",
"-Dqt=false",
"-Dselinux=false",
"-Dsession_tracking=no",
"-Dsystemdsystemunitdir='no'",
"-Dsystemd_journal=false",
"-Dtests=no",
"-Dvapi=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git"
}
]
},
{
"name" : "mobile-broadband-provider-info",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/mobile-broadband-provider-info.git"
}
]
},
{
"name" : "libnma",
"buildsystem" : "meson",
"config-opts" : [
"-Dgtk_doc=false",
"-Dintrospection=false",
"-Dvapi=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/libnma.git"
}
]
},
{
"name" : "network-manager-applet",
"buildsystem" : "meson",
"config-opts" : [
"-Dappindicator=no",
"-Dgtk_doc=false",
"-Dintrospection=false",
"-Dlibnm_gtk=false",
"-Dselinux=false",
"-Dteam=false",
"-Dwwan=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/network-manager-applet.git"
}
]
},
{
"name" : "ModemManager",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-introspection",
"--disable-vala",
"--with-udev-base-dir=/app/lib",
"--with-systemdsystemunitdir=/app/lib/systemd/system",
"--without-mbim",
"--without-qmi"
],
"sources" : [
{
"type" : "git",
"url" : "git://anongit.freedesktop.org/ModemManager/ModemManager"
}
]
},
{
"name" : "gnome-settings-daemon",
"buildsystem" : "meson",
"config-opts" : [
"-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" : "gnome-bluetooth",
"buildsystem" : "meson",
"config-opts" : [
"-Dintrospection=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gnome-bluetooth.git"
}
]
},
{
"name" : "grilo",
"buildsystem" : "meson",
"config-opts" : [
"-Denable-grl-pls=false",
"-Denable-gtk-doc=false",
"-Denable-introspection=false",
"-Denable-test-ui=false",
"-Denable-vala=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/grilo.git"
}
]
},
{
"name" : "openldap",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-slapd"
],
"sources" : [
{
"type" : "archive",
"url" : "https://www.openldap.org/software/download/OpenLDAP/openldap-release/openldap-2.4.46.tgz",
"sha256" : "9a90dcb86b99ae790ccab93b7585a31fbcbeec8c94bf0f7ab0ca0a87ea0c4b2d"
}
]
},
{
"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" : "samba",
"buildsystem" : "autotools",
"config-opts" : [
"--without-json",
"--without-ad-dc",
"--without-pam"
],
"sources" : [
{
"type" : "archive",
"url" : "https://download.samba.org/pub/samba/stable/samba-4.11.0.tar.gz",
"sha256" : "6adf1c74afff1f3f7e14060cc5a36111a6721d644ea51ed1b22da46051e48e9c"
}
]
},
{
"name" : "libgtop2",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-introspection"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/libgtop.git"
}
]
},
{
"name" : "cheese",
"buildsystem" : "meson",
"config-opts" : [
"-Dintrospection=false",
"-Dgtk_doc=false",
"-Dman=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/cheese.git"
}
]
},
{
"name" : "libhandy",
"buildsystem" : "meson",
"config-opts" : [
"-Dexamples=false",
"-Dglade_catalog=disabled",
"-Dintrospection=disabled",
"-Dtests=false",
"-Dvapi=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/libhandy.git"
}
]
},
{
"name" : "gsound",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gsound.git"
}
]
},
{
"name" : "libkmod",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "archive",
"url" : "https://mirrors.edge.kernel.org/pub/linux/utils/kernel/kmod/kmod-25.tar.xz",
"sha256" : "7165e6496656159dcb909a91ed708a0fe273a4b128b4b1dc997ccb5189eef1cd"
}
]
},
{
"name" : "lvm2",
"buildsystem" : "autotools",
"config-opts" : [
"--prefix=/app",
"--enable-cmdlib",
"--enable-dmeventd",
"--enable-pkgconfig",
"--with-usrlibdir=/app/lib",
"--with-usrbindir=/app/bin",
"--with-staticdir=/app/bin"
],
"sources" : [
{
"type" : "archive",
"url" : "https://www.sourceware.org/pub/lvm2/LVM2.2.02.177.tgz",
"sha256" : "4025a23ec9b15c2cb7486d151c29dc953b75efc4d452cfe9dbbc7c0fac8e80f2"
}
],
"post-install" : [
"chmod 755 /app/sbin/dm*",
"chmod 755 /app/sbin/lvm*",
"chmod 755 /app/lib/libdevmapper-event-lvm2.so.2.02",
"chmod 755 /app/lib/libdevmapper-event-lvm2mirror.so",
"chmod 755 /app/lib/libdevmapper-event-lvm2raid.so",
"chmod 755 /app/lib/libdevmapper-event-lvm2snapshot.so",
"chmod 755 /app/lib/libdevmapper-event-lvm2thin.so",
"chmod 755 /app/lib/libdevmapper-event.so.1.02",
"chmod 755 /app/lib/libdevmapper.so.1.02",
"chmod 755 /app/lib/liblvm2cmd.so.2.02"
]
},
{
"name" : "parted",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "archive",
"url" : "http://ftp.gnu.org/gnu/parted/parted-3.2.tar.xz",
"sha256" : "858b589c22297cacdf437f3baff6f04b333087521ab274f7ab677cb8c6bb78e4"
},
{
"type" : "patch",
"path" : "libparted-include.patch"
}
]
},
{
"name" : "mpfr",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "archive",
"url" : "https://www.mpfr.org/mpfr-4.0.2/mpfr-4.0.2.tar.xz",
"sha256" : "1d3be708604eae0e42d578ba93b390c2a145f17743a744d8f3f8c2ad5855a38a"
}
]
},
{
"name" : "bytesize",
"buildsystem" : "autotools",
"config-opts" : [
"--with-gtk-doc=no"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/storaged-project/libbytesize.git"
}
]
},
{
"name" : "cryptsetup",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "archive",
"url" : "https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.xz",
"sha256" : "2b30cd1d0dd606a53ac77b406e1d37798d4b0762fa89de6ea546201906a251bd"
}
]
},
{
"name" : "swig",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "git",
"url" : "https://github.com/swig/swig.git"
}
]
},
{
"name" : "volume-key",
"buildsystem" : "simple",
"build-commands" : [
"autoreconf -i",
"./configure --prefix=/app",
"make install"
],
"sources" : [
{
"type" : "archive",
"url" : "https://github.com/felixonmars/volume_key/archive/volume_key-0.3.11.tar.gz",
"sha256" : "92250506756eca19a0b6f50c16d3502eb5566ea4725645d7c5d87eb5cc8f3fd8"
}
]
},
{
"name" : "libblockdev",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-tests",
"--with-btrfs=no",
"--with-dm=no",
"--with-gtk-doc=no",
"--with-kbd=no",
"--with-lvm=no",
"--with-lvm-dbus=no",
"--with-mpath=no",
"--with-nvdimm=no",
"--with-tools=no",
"--with-vdo=no"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/storaged-project/libblockdev.git"
}
]
},
{
"name" : "atasmart",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "archive",
"url" : "http://0pointer.de/public/libatasmart-0.19.tar.xz",
"sha256" : "61f0ea345f63d28ab2ff0dc352c22271661b66bf09642db3a4049ac9dbdb0f8d"
}
]
},
{
"name" : "udisks",
"buildsystem" : "autotools",
"config-opts" : [
"--disable-introspection",
"--disable-lvm2",
"--with-systemdsystemunitdir=/app/lib/systemd/system",
"--with-tmpfilesdir=/app/lib/tmpfiles.d"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/storaged-project/udisks.git"
}
]
},
{
"name" : "gnome-backgrounds",
"buildsystem" : "meson",
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gnome-backgrounds.git"
}
]
},
{
"name" : "gnome-control-center",
"buildsystem" : "meson",
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gnome-control-center.git"
}
],
"config-opts" : [
"-Dtracing=true",
"-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 +0,0 @@
meson.add_install_script('meson/meson_post_install.py', control_center_datadir)

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 533 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

View File

@@ -0,0 +1,32 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:cc='http://creativecommons.org/ns#' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' xmlns:svg='http://www.w3.org/2000/svg' id='svg7384' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' sodipodi:docname='preferences-system-symbolic.svg' version='1.1' inkscape:version='0.48.1 r9760' height='16.000008' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns='http://www.w3.org/2000/svg' width='16'>
<metadata id='metadata90'>
<rdf:RDF>
<cc:Work rdf:about=''>
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview inkscape:cy='7.8662795' pagecolor='#555753' borderopacity='1' showborder='false' inkscape:bbox-paths='false' guidetolerance='10' inkscape:object-paths='true' inkscape:window-width='1600' showguides='true' inkscape:object-nodes='true' inkscape:snap-bbox='true' inkscape:pageshadow='2' inkscape:guide-bbox='true' inkscape:snap-nodes='true' bordercolor='#666666' objecttolerance='10' id='namedview88' showgrid='false' inkscape:window-maximized='1' inkscape:window-x='0' inkscape:snap-global='true' inkscape:window-y='0' gridtolerance='10' inkscape:window-height='1168' inkscape:snap-others='false' inkscape:snap-to-guides='true' inkscape:current-layer='g4953' inkscape:snap-bbox-midpoints='false' inkscape:zoom='1' inkscape:cx='13.631831' inkscape:snap-grids='true' inkscape:pageopacity='1'>
<inkscape:grid spacingx='1px' spacingy='1px' id='grid4866' empspacing='2' enabled='true' type='xygrid' snapvisiblegridlinesonly='true' visible='true'/>
</sodipodi:namedview>
<title id='title9167'>Gnome Symbolic Icon Theme</title>
<defs id='defs7386'/>
<g inkscape:label='status' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer9' style='display:inline'/>
<g inkscape:label='devices' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer10'/>
<g inkscape:label='apps' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer11'/>
<g inkscape:label='places' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer13'/>
<g inkscape:label='mimetypes' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer14'/>
<g inkscape:label='emblems' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer15' style='display:inline'/>
<g inkscape:label='emotes' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='g71291' style='display:inline'/>
<g inkscape:label='categories' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='g4953' style='display:inline'>
<path inkscape:connector-curvature='0' d='m 445.54914,462.09056 c -0.39933,0 -0.78638,0.0916 -1.14329,0.21572 l 1.88488,1.87971 c 0.38735,0.38627 0.38735,1.00037 0,1.38667 l -0.71069,0.70874 c -0.38735,0.38628 -1.00314,0.38628 -1.39049,0 l -1.88488,-1.87971 c -0.12444,0.35591 -0.2163,0.74191 -0.2163,1.14015 0,1.90608 1.54944,3.45126 3.46077,3.45126 0.39933,0 0.78638,-0.0916 1.14329,-0.2157 l 1.17419,1.17097 a 2.4722239,2.4654407 0 0 1 0.0618,0 l 2.07028,-2.0646 -1.20509,-1.20178 c 0.12444,-0.35592 0.2163,-0.74191 0.2163,-1.14015 0,-1.90609 -1.54944,-3.45128 -3.46077,-3.45128 z m 6.55074,7.88863 -2.07029,2.06459 a 2.4722239,2.4654407 0 0 1 0.0309,0.0924 l 1.14329,1.14015 c -0.12444,0.35596 -0.2163,0.74196 -0.2163,1.14019 0,1.90609 1.54944,3.45129 3.46077,3.45129 0.43346,0 0.8536,-0.10141 1.23599,-0.24653 l -2.00848,-2.00297 c -0.38735,-0.38629 -0.38735,-1.03119 0,-1.41749 l 0.67979,-0.67792 c 0.19367,-0.19315 0.45794,-0.30816 0.71069,-0.30816 0.25276,0 0.51702,0.11501 0.7107,0.30816 l 1.94668,1.94133 c 0.10485,-0.32958 0.1854,-0.68351 0.1854,-1.04771 0,-1.90608 -1.54944,-3.45126 -3.46077,-3.45126 -0.39933,0 -0.78639,0.0916 -1.14329,0.2157 l -1.20509,-1.20179 z' id='path3908' style='font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans'/>
<path inkscape:connector-curvature='0' d='m 455.85825,462 -1.54246,1.43753 c -0.45151,0.42079 -0.5292,1.14883 -0.2663,1.70647 l -5.88822,5.99575 a 1.4916729,1.4875773 0 0 0 -0.0311,2.5e-4 1.4916729,1.4875773 0 0 0 -0.84016,-0.1484 1.4916729,1.4875773 0 0 0 -0.86663,0.44059 l -3.9462,3.99734 a 1.4941171,1.4900149 0 1 0 2.12943,2.09068 l 3.9462,-3.99734 a 1.4916729,1.4875773 0 0 0 0.29713,-1.73771 l 5.88846,-5.96477 c 0.55782,0.24837 1.27325,0.14697 1.70681,-0.2922 L 457.86242,463.9677 455.85824,462 z' id='path3910' style='font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans'/>
</g>
<g inkscape:label='actions' transform='translate(-442.0002,-462)' inkscape:groupmode='layer' id='layer12' style='display:inline'/>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

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,13 +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">
<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>
<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"/>
<g fill="none">
<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" stroke="url(#a)" stroke-width="24" transform="matrix(1 0 0 1 -160 -172)"/>
<path d="m -58 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" stroke="#f6f5f4" stroke-width="20"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -2,12 +2,3 @@ install_subdir(
'hicolor',
install_dir : control_center_icondir
)
if get_option('profile') == 'development'
icondir = join_paths('hicolor', 'scalable', 'apps')
install_data(
join_paths(icondir, 'org.gnome.Settings.Devel.svg'),
install_dir: join_paths(control_center_icondir, icondir),
rename: 'org.gnome.Settings.svg'
)
endif

View File

@@ -7,20 +7,17 @@ Please note we have a Code of Conduct, please follow it in all your interactions
## Pull Request Process
1. Create a fork in GitLab and push your work to there
2. Open a Merge Request
1. Always allow maintainer edits
2. Mark the Merge Request as WIP if your work is not ready to be reviewed
3. Assign the correct maintainer to the Merge Request (see [`MAINTAINERS.md`][maintainers] to select
the correct maintainer)
4. Format commit messages as follows:
1. Ensure your code compiles and doesn't break anything. Run `meson test -C <builddir>` before creating
the pull request.
2. If you're adding new API, it must be properly documented.
3. The commit message is formatted as follows:
```
component: <summary>
A paragraph explaining the problem and its context.
Another one explaining how you solved that.
<link to the issue>
```
4. You may merge the pull request in once you have the sign-off of the maintainers, or if you
@@ -28,8 +25,7 @@ Please note we have a Code of Conduct, please follow it in all your interactions
## 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:
GNOME Settings is a project developed based on GNOME Code of Conduct. You can read it below:
### Summary
@@ -66,147 +62,10 @@ size, disability, ethnicity, gender identity and expression, level of experience
nationality, personal appearance, race, religion, or sexual identity and
orientation.
### Communication Guideline
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/master/docs/MAINTAINERS.md
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -7,100 +7,9 @@ rules. Please read them carefully and, if in doubt, ask a maintainer for directi
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:

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 master 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/master/gnome-control-center.doap

View File

@@ -13,7 +13,6 @@
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
<programming-language>C</programming-language>
<!-- General -->
<maintainer>
<foaf:Person>
<foaf:name>Georges Basile Stavracas Neto</foaf:name>
@@ -21,75 +20,4 @@
<gnome:userid>gbsneto</gnome:userid>
</foaf:Person>
</maintainer>
<!-- General, Region & Language -->
<maintainer>
<foaf:Person>
<foaf:name>Robert Ancell</foaf:name>
<foaf:mbox rdf:resource="mailto:rancell@gnome.org" />
<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>
<!-- Display -->
<maintainer>
<foaf:Person>
<foaf:name>Benjamin Berg</foaf:name>
<foaf:mbox rdf:resource="mailto:bberg@gnome.org" />
<gnome:userid>bberg</gnome:userid>
</foaf:Person>
</maintainer>
<!-- Mouse & Touchpad, Printers -->
<maintainer>
<foaf:Person>
<foaf:name>Felipe Borges</foaf:name>
<foaf:mbox rdf:resource="mailto:felipeborges@gnome.org" />
<gnome:userid>felipeborges</gnome:userid>
</foaf:Person>
</maintainer>
<!-- Online Accounts -->
<maintainer>
<foaf:Person>
<foaf:name>Debarshi Ray</foaf:name>
<foaf:mbox rdf:resource="mailto:debarshir@gnome.org" />
<gnome:userid>debarshir</gnome:userid>
</foaf:Person>
</maintainer>
<!-- Printers -->
<maintainer>
<foaf:Person>
<foaf:name>Marek Kašík</foaf:name>
<foaf:mbox rdf:resource="mailto:mkasik@gnome.org" />
</foaf:Person>
</maintainer>
<!-- Thunderbolt -->
<maintainer>
<foaf:Person>
<foaf:name>Christian Kellner</foaf:name>
<foaf:mbox rdf:resource="mailto:gicmo@gnome.org" />
<gnome:userid>gicmo</gnome:userid>
</foaf:Person>
</maintainer>
<!-- 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

@@ -115,9 +115,9 @@
</varlistentry>
<varlistentry>
<term><option>info-overview</option></term>
<term><option>info</option></term>
<listitem><para>The info-overview panel shows a general
<listitem><para>The info panel shows a general
overview of the system configuration. It also
lets you change the default applications for
various tasks and the handling of removable

View File

@@ -1,8 +1,8 @@
project(
'gnome-control-center', 'c',
version : '40.9',
version : '3.29.0',
license : 'GPL2+',
meson_version : '>= 0.53.0'
meson_version : '>= 0.43.0'
)
control_center_prefix = get_option('prefix')
@@ -30,8 +30,8 @@ enable_tracing = get_option('tracing')
config_h = configuration_data()
py = import('python')
python = py.find_installation('python3')
py3 = import('python3')
python = py3.find_python()
config_h.set_quoted('TEST_NM_PYTHON', python.path())
@@ -41,7 +41,6 @@ set_defines = [
['PACKAGE', meson.project_name()],
['PACKAGE_VERSION', meson.project_version()],
['VERSION', meson.project_version()],
['PROFILE', get_option('profile')],
# i18n
['GETTEXT_PACKAGE', control_center_gettext]
]
@@ -93,48 +92,30 @@ libgvc = subproject(
default_options: [
'static=true',
'alsa=false',
'package_name=' + control_center_gettext,
'package_version=' + meson.project_version(),
]
)
libgvc_dep = libgvc.get_variable('libgvc_dep')
libhandy_dep = dependency('libhandy-1', version: '>= 1.0.0', required: false)
if not libhandy_dep.found()
libhandy = subproject(
'libhandy',
default_options: [
'examples=false',
'glade_catalog=disabled',
'introspection=disabled',
'tests=false',
'vapi=false',
]
)
libhandy_dep = libhandy.get_variable('libhandy_dep')
endif
goa_req_version = '>= 3.25.3'
pulse_req_version = '>= 2.0'
accounts_dep = dependency('accountsservice', version: '>= 0.6.39')
clutter_gtk_dep = dependency('clutter-gtk-1.0', required: false)
colord_dep = dependency('colord', version: '>= 0.1.34')
gdk_pixbuf_dep = dependency('gdk-pixbuf-2.0', version: '>= 2.23.0')
gio_dep = dependency('gio-2.0')
glib_dep = dependency('glib-2.0', version: '>= 2.56.0')
gnome_desktop_dep = dependency('gnome-desktop-3.0', version: '>= 3.33.4')
gnome_settings_dep = dependency('gnome-settings-daemon', version: '>= 3.27.90')
glib_dep = dependency('glib-2.0', version: '>= 2.53.0')
gnome_desktop_dep = dependency('gnome-desktop-3.0', version: '>= 3.27.90')
gnome_settings_dep = dependency('gnome-settings-daemon', version: '>= 3.25.90')
goa_dep = dependency('goa-1.0', version: goa_req_version)
gsettings_desktop_dep = dependency('gsettings-desktop-schemas', version: '>= 40.alpha')
gsettings_desktop_dep = dependency('gsettings-desktop-schemas', version: '>= 3.27.2')
libxml_dep = dependency('libxml-2.0')
polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.114')
polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.103')
pulse_dep = dependency('libpulse', version: pulse_req_version)
pulse_mainloop_dep = dependency('libpulse-mainloop-glib', version: pulse_req_version)
upower_glib_dep = dependency('upower-glib', version: '>= 0.99.8')
gudev_dep = dependency('gudev-1.0', version: '>= 232')
upower_glib_dep = dependency('upower-glib', version: '>= 0.99.6')
x11_dep = dependency('x11')
xi_dep = dependency('xi', version: '>= 1.2')
epoxy_dep = dependency('epoxy')
m_dep = cc.find_library('m')
@@ -142,7 +123,6 @@ common_deps = [
gio_dep,
glib_dep,
gsettings_desktop_dep,
libhandy_dep,
dependency('gio-unix-2.0'),
dependency('gthread-2.0'),
dependency('gtk+-3.0', version: '>= 3.22.20')
@@ -155,7 +135,7 @@ assert(cups_dep.found(), 'CUPS 1.4 or newer not found')
# https://bugzilla.gnome.org/show_bug.cgi?id=696766
cups_cflags = []
if cups_dep.version().version_compare('>= 1.6')
cups_cflags += '-D_PPD_DEPRECATED='
cups_cflags += '-D_PPD_DEPRECATED=""'
endif
# cups headers
@@ -168,14 +148,13 @@ foreach header: check_headers
assert(cc.has_header(header[1], args: cups_cflags), 'CUPS headers not found: ' + header[1])
endforeach
config_h.set10('HAVE_CUPS_HTTPCONNECT2',
cc.has_function('httpConnect2', dependencies: cups_dep),
description: 'Define if httpConnect2() is available in CUPS')
# Optional dependency for the user accounts panel
enable_cheese = get_option('cheese')
if enable_cheese
assert(clutter_gtk_dep.found(), 'cheese support requested, but clutter-gtk library is not available. Use -Dcheese=false to build without it.')
cheese_deps = [
clutter_gtk_dep,
dependency('cheese', version: '>= 3.28.0'),
dependency('cheese-gtk', version: '>= 3.5.91')
]
@@ -191,35 +170,21 @@ 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
snapd_glib_deps = [
dependency('snapd-glib', version: '>= 1.57')
# wayland
enable_wayland = get_option('wayland')
if enable_wayland
wayland_deps = [
dependency('gdk-wayland-3.0'),
dependency('gudev-1.0')
]
endif
config_h.set('HAVE_SNAP', enable_snap,
description: 'Define to 1 if Snap support is enabled')
# malcontent support
enable_malcontent = get_option('malcontent')
if enable_malcontent
malcontent_dep = dependency('malcontent-0', version: '>= 0.7.0')
config_h.set('HAVE_MALCONTENT_0_10', malcontent_dep.version().version_compare('>= 0.10.0'),
description: 'Define to 1 if malcontent ≥ 0.10.0')
endif
config_h.set('HAVE_MALCONTENT', enable_malcontent,
description: 'Define to 1 if malcontent support is enabled')
config_h.set('HAVE_WAYLAND', enable_wayland,
description: 'Define to 1 if Wayland is enabled')
if host_is_linux
# network manager
network_manager_deps = [
dependency('libnm', version: '>= 1.24.0'),
dependency('libnm', version: '>= 1.10.0'),
dependency('libnma', version: '>= 1.8.0'),
dependency('mm-glib', version: '>= 0.7')
]
@@ -233,10 +198,15 @@ if host_is_linux_not_s390
# gnome-bluetooth
gnome_bluetooth_dep = dependency('gnome-bluetooth-1.0', version: '>= 3.18.2')
# Wacom
assert(clutter_gtk_dep.found(), 'clutter-gtk library is required for wacom support, but is not available.')
libwacom_dep = dependency('libwacom', version: '>= 0.7')
wacom_deps = [
clutter_gtk_dep,
libwacom_dep,
dependency('clutter-1.0', version: '>= 1.11.3'),
]
config_h.set('HAVE_WACOM_3D_STYLUS', libwacom_dep.version().version_compare('>= 0.27'),
description: 'Define to 1 if libwacom provides definition for 3D styli')
@@ -255,6 +225,12 @@ config_h.set('HAVE_WACOM', host_is_linux_not_s390,
config_h.set('BUILD_THUNDERBOLT', host_is_linux_not_s390,
description: 'Define to 1 to build the Thunderbolt panel')
# Check for info panel
gnome_session_libexecdir = get_option('gnome_session_libexecdir')
if gnome_session_libexecdir == ''
gnome_session_libexecdir = control_center_libexecdir
endif
gnome = import('gnome')
i18n = import('i18n')
pkg = import('pkgconfig')
@@ -273,16 +249,16 @@ install_subdir(
top_inc = include_directories('.')
shell_inc = include_directories('shell')
subdir('build-aux')
update_from_gsd = find_program('update-from-gsd.sh')
update_from_gsd_in = files('update-from-gsd.in')
update_from_nma_in = files('update-from-nma.in')
subdir('data/icons')
subdir('po')
subdir('panels')
subdir('shell')
subdir('search-provider')
if get_option('tests')
subdir('tests')
endif
subdir('tests')
if get_option('documentation')
subdir('man')
@@ -293,22 +269,25 @@ configure_file(
configuration: config_h
)
summary({
'Documentation': get_option('documentation'),
'Tests': get_option('tests'),
'Tracing': enable_tracing,
'Optimized': control_center_optimized,
})
meson.add_install_script(
'meson_post_install.py',
control_center_datadir
)
summary({
'GNOME Bluetooth': host_is_linux_not_s390,
'NetworkManager': host_is_linux,
'Wacom': host_is_linux_not_s390,
}, section: 'Dependencies')
output = ''
output += '\n ' + meson.project_name() + ' - ' + meson.project_version() + '\n'
output += ' ===================================\n'
output += ' Options \n'
output += ' Documentation .............................. ' + get_option('documentation').to_string() + '\n'
output += ' Tracing .................................... ' + enable_tracing.to_string() + '\n'
output += ' gnome-session libexecdir ................... ' + gnome_session_libexecdir + '\n'
output += ' Optimized .................................. ' + control_center_optimized.to_string() + '\n'
output += ' Panels \n'
output += ' GNOME Bluetooth (Bluetooth panel) .......... ' + host_is_linux_not_s390.to_string() + '\n'
output += ' Cheese (Users panel webcam support) ........ ' + enable_cheese.to_string() + '\n'
output += ' IBus (Region panel IBus support) ........... ' + enable_ibus.to_string() + '\n'
output += ' NetworkManager (Network panel) ............. ' + host_is_linux.to_string() + '\n'
output += ' Wacom (Wacom tablet panel) ................. ' + host_is_linux_not_s390.to_string() + '\n'
output += ' Wayland .................................... ' + enable_wayland.to_string() + '\n'
summary({
'Cheese': enable_cheese,
'IBus': enable_ibus,
'Snap': enable_snap,
'Malcontent': enable_malcontent,
}, section: 'Optional Dependencies')
message(output)

View File

@@ -1,10 +1,6 @@
option('cheese', type: 'boolean', value: true, description: 'build with cheese webcam support')
option('documentation', type: 'boolean', value: false, description: 'build documentation')
option('gnome_session_libexecdir', type: 'string', value: '', description: 'Directory for gnome-session\'s libexecdir')
option('ibus', type: 'boolean', value: true, description: 'build with IBus support')
option('privileged_group', type: 'string', value: 'wheel', description: 'name of group that has elevated permissions')
option('snap', type: 'boolean', value: false, description: 'build with Snap support')
option('tests', type: 'boolean', value: true, description: 'build tests')
option('tracing', type: 'boolean', value: false, description: 'add extra debugging information')
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')

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/control-center/applications">
<file preprocess="xml-stripblanks">cc-action-row.ui</file>
<file preprocess="xml-stripblanks">cc-applications-panel.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>
<file preprocess="xml-stripblanks">cc-toggle-row.ui</file>
<file>cc-applications-panel.css</file>
</gresource>
</gresources>

View File

@@ -1,218 +0,0 @@
/* cc-action-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-action-row.h"
#include "cc-applications-resources.h"
struct _CcActionRow
{
GtkListBoxRow parent;
GtkWidget *title;
GtkWidget *subtitle;
GtkWidget *button;
};
G_DEFINE_TYPE (CcActionRow, cc_action_row, GTK_TYPE_LIST_BOX_ROW)
static int activated_signal;
enum
{
PROP_0,
PROP_TITLE,
PROP_SUBTITLE,
PROP_ACTION,
PROP_ENABLED,
PROP_DESTRUCTIVE
};
static void
clicked_cb (CcActionRow *row)
{
g_signal_emit (row, activated_signal, 0);
}
static void
cc_action_row_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcActionRow *row = CC_ACTION_ROW (object);
switch (prop_id)
{
case PROP_TITLE:
g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->title)));
break;
case PROP_SUBTITLE:
g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->subtitle)));
break;
case PROP_ACTION:
g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (row->button)));
break;
case PROP_ENABLED:
g_value_set_boolean (value, gtk_widget_get_sensitive (row->button));
break;
case PROP_DESTRUCTIVE:
g_value_set_boolean (value,
gtk_style_context_has_class (gtk_widget_get_style_context (row->button), "destructive-action"));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
cc_action_row_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CcActionRow *row = CC_ACTION_ROW (object);
switch (prop_id)
{
case PROP_TITLE:
gtk_label_set_label (GTK_LABEL (row->title), g_value_get_string (value));
break;
case PROP_SUBTITLE:
gtk_label_set_label (GTK_LABEL (row->subtitle), g_value_get_string (value));
gtk_widget_set_visible (row->subtitle, strlen (g_value_get_string (value)) > 0);
break;
case PROP_ACTION:
gtk_button_set_label (GTK_BUTTON (row->button), g_value_get_string (value));
break;
case PROP_ENABLED:
gtk_widget_set_sensitive (row->button, g_value_get_boolean (value));
break;
case PROP_DESTRUCTIVE:
if (g_value_get_boolean (value))
gtk_style_context_add_class (gtk_widget_get_style_context (row->button), "destructive-action");
else
gtk_style_context_remove_class (gtk_widget_get_style_context (row->button), "destructive-action");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
cc_action_row_class_init (CcActionRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->get_property = cc_action_row_get_property;
object_class->set_property = cc_action_row_set_property;
g_object_class_install_property (object_class,
PROP_TITLE,
g_param_spec_string ("title", "title", "title",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_SUBTITLE,
g_param_spec_string ("subtitle", "subtitle", "subtitle",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_ACTION,
g_param_spec_string ("action", "action", "action",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_ENABLED,
g_param_spec_boolean ("enabled", "enabled", "enabled",
TRUE, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_DESTRUCTIVE,
g_param_spec_boolean ("destructive", "destructive", "destructive",
FALSE, G_PARAM_READWRITE));
activated_signal = g_signal_new ("activated",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-action-row.ui");
gtk_widget_class_bind_template_child (widget_class, CcActionRow, title);
gtk_widget_class_bind_template_child (widget_class, CcActionRow, subtitle);
gtk_widget_class_bind_template_child (widget_class, CcActionRow, button);
gtk_widget_class_bind_template_callback (widget_class, clicked_cb);
}
static void
cc_action_row_init (CcActionRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
}
CcActionRow *
cc_action_row_new (void)
{
return CC_ACTION_ROW (g_object_new (CC_TYPE_ACTION_ROW, NULL));
}
void
cc_action_row_set_title (CcActionRow *row,
const gchar *name)
{
gtk_label_set_label (GTK_LABEL (row->title), name);
}
void
cc_action_row_set_subtitle (CcActionRow *row,
const gchar *name)
{
gtk_label_set_label (GTK_LABEL (row->subtitle), name);
gtk_widget_set_visible (row->subtitle, strlen (name) > 0);
}
void
cc_action_row_set_action (CcActionRow *row,
const gchar *action,
gboolean sensitive)
{
gtk_button_set_label (GTK_BUTTON (row->button), action);
gtk_widget_set_sensitive (row->button, sensitive);
}

View File

@@ -1,42 +0,0 @@
/* cc-action-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>
G_BEGIN_DECLS
#define CC_TYPE_ACTION_ROW (cc_action_row_get_type())
G_DECLARE_FINAL_TYPE (CcActionRow, cc_action_row, CC, ACTION_ROW, GtkListBoxRow)
CcActionRow* cc_action_row_new (void);
void cc_action_row_set_title (CcActionRow *row,
const gchar *label);
void cc_action_row_set_subtitle (CcActionRow *row,
const gchar *label);
void cc_action_row_set_action (CcActionRow *row,
const gchar *action,
gboolean sensitive);
G_END_DECLS

View File

@@ -1,51 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcActionRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="activatable">False</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="border-width">12</property>
<property name="spacing">12</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<child>
<object class="GtkLabel" id="title">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<property name="ellipsize">end</property>
</object>
<packing>
<property name="expand">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="subtitle">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<property name="ellipsize">end</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="visible">1</property>
<property name="valign">center</property>
<signal name="clicked" handler="clicked_cb" swapped="yes"/>
</object>
</child>
</object>
</child>
</template>
</interface>

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +0,0 @@
.section-title {
font-weight: bold;
}
.section-subtitle {
opacity: 0.55;
}
.sidebar-icon.fullcolor {
opacity: 1;
}

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,610 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcApplicationsPanel" parent="CcPanel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkScrolledWindow" id="main_scroll">
<property name="visible">1</property>
<property name="hscrollbar-policy">never</property>
<child>
<object class="HdyClamp">
<property name="visible">True</property>
<property name="margin_top">32</property>
<property name="margin_bottom">32</property>
<property name="margin_start">12</property>
<property name="margin_end">12</property>
<child>
<object class="GtkStack" id="stack">
<property name="visible">1</property>
<child>
<object class="GtkBox" id="empty_box">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="valign">center</property>
<child>
<object class="GtkImage">
<property name="visible">1</property>
<property name="valign">start</property>
<property name="pixel-size">80</property>
<property name="icon-name">org.gnome.Software-symbolic</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="fill">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="margin-bottom">15</property>
<property name="label" translatable="yes">No applications</property>
<style>
<class name="dim-label"/>
</style>
<attributes>
<attribute name="scale" value="1.2"/>
</attributes>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="install_button">
<property name="label" translatable="yes">Install some…</property>
<property name="visible">1</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="halign">center</property>
<signal name="clicked" handler="open_software_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
<packing>
<property name="fill">0</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="settings_box">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">24</property>
<property name="hexpand">1</property>
<child>
<object class="GtkBox" id="permission_section">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<style>
<class name="section"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Permissions &amp; Access</property>
<style>
<class name="section-title"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">Data and services that this app has asked for access to and permissions that it requires.</property>
<style>
<class name="section-subtitle"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="permission_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<signal name="row-activated" handler="permission_row_activated_cb" object="CcApplicationsPanel" swapped="yes"/>
<child>
<object class="CcToggleRow" id="camera">
<property name="title" translatable="yes">Camera</property>
<signal name="notify::allowed" handler="camera_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_camera">
<property name="title" translatable="yes">Camera</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="microphone">
<property name="title" translatable="yes">Microphone</property>
<signal name="notify::allowed" 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="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="location">
<property name="title" translatable="yes">Location Services</property>
<signal name="notify::allowed" 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="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcInfoRow" id="builtin">
<property name="title" translatable="yes">Built-in Permissions</property>
<property name="info" translatable="yes">Cannot be changed</property>
<property name="has-expander">True</property>
<property name="is-link">True</property>
</object>
</child>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">Individual permissions for applications can be reviewed in the &lt;a href=&quot;privacy&quot;&gt;Privacy&lt;/a&gt; Settings.</property>
<property name="use-markup">1</property>
<signal name="activate-link" handler="privacy_link_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="integration_section">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<style>
<class name="section"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Integration</property>
<style>
<class name="section-title"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">System features used by this application.</property>
<style>
<class name="section-subtitle"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="integration_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<child>
<object class="CcToggleRow" id="search">
<property name="title" translatable="yes">Search</property>
<signal name="notify::allowed" 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="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="notification">
<property name="title" translatable="yes">Notifications</property>
<signal name="notify::allowed" handler="notification_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcToggleRow" id="background">
<property name="title" translatable="yes">Run in background</property>
<signal name="notify::allowed" handler="background_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="CcToggleRow" id="wallpaper">
<property name="title" translatable="yes">Set Desktop Background</property>
<signal name="notify::allowed" handler="wallpaper_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="CcToggleRow" id="sound">
<property name="title" translatable="yes">Sounds</property>
<signal name="notify::allowed" handler="sound_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_sound">
<property name="title" translatable="yes">Sounds</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="shortcuts">
<property name="title" translatable="yes">Inhibit system keyboard shortcuts</property>
<signal name="notify::allowed" handler="shortcuts_cb" swapped="yes"/>
</object>
</child>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="handler_section">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<style>
<class name="section"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="spacing">6</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Default Handlers</property>
<style>
<class name="section-title"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">Types of files and links that this application opens.</property>
<style>
<class name="section-subtitle"/>
</style>
</object>
</child>
</object>
<packing>
<property name="expand">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="handler_reset">
<property name="visible">1</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="label" translatable="yes">Reset</property>
<signal name="clicked" handler="handler_reset_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="handler_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<signal name="row-activated" handler="handler_row_activated_cb" object="CcApplicationsPanel" swapped="yes"/>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="usage_section">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<style>
<class name="section"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Usage</property>
<style>
<class name="section-title"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">How much resources this application is using.</property>
<style>
<class name="section-subtitle"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="usage_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<signal name="row-activated" handler="storage_row_activated_cb" object="CcApplicationsPanel" swapped="yes"/>
<child>
<object class="CcInfoRow" id="storage">
<property name="title" translatable="yes">Storage</property>
<property name="info">unknown</property>
<property name="has-expander">1</property>
<property name="is-link">1</property>
</object>
</child>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
<object class="GtkLabel" id="title_label">
<property name="visible">1</property>
<property name="label" translatable="yes">Applications</property>
<style>
<class name="title"/>
</style>
</object>
<object class="GtkButton" id="header_button">
<property name="visible">1</property>
<property name="label" translatable="yes">Open in Software</property>
</object>
<!-- Sidebar -->
<object class="GtkBox" id="sidebar_box">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSearchEntry" id="sidebar_search_entry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="has-focus">True</property>
<property name="margin">12</property>
<property name="margin-bottom">6</property>
<signal name="activate" handler="on_sidebar_search_entry_activated_cb" object="CcApplicationsPanel" swapped="yes" />
<signal name="search-changed" handler="on_sidebar_search_entry_search_changed_cb" object="CcApplicationsPanel" swapped="yes" />
<signal name="stop-search" handler="on_sidebar_search_entry_search_stopped_cb" object="CcApplicationsPanel" swapped="yes" />
</object>
</child>
<child>
<object class="GtkListBox" id="sidebar_listbox">
<property name="visible">True</property>
<property name="vexpand">True</property>
<property name="selection-mode">browse</property>
<child type="placeholder">
<object class="GtkBox" id="empty_search_placeholder">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="expand">True</property>
<property name="border_width">18</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">64</property>
<property name="icon_name">edit-find-symbolic</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">No results found</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="scale" value="1.44"/>
</attributes>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Try a different search</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<!-- Built-in Permissions dialog -->
<object class="GtkDialog" id="builtin_dialog">
<property name="title" translatable="yes">Built-in Permissions</property>
<property name="modal">1</property>
<property name="type-hint">dialog</property>
<property name="use-header-bar">1</property>
<property name="resizable">0</property>
<property name="border-width">24</property>
<signal name="delete-event" handler="gtk_widget_hide_on_delete"/>
<child internal-child="vbox">
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="builtin_label">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label">Yadda Yadda</property>
</object>
</child>
<child>
<object class="GtkListBox" id="builtin_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
</object>
</child>
</object>
<!-- Storage dialog -->
<object class="GtkDialog" id="storage_dialog">
<property name="title" translatable="yes">Storage</property>
<property name="modal">1</property>
<property name="type-hint">dialog</property>
<property name="use-header-bar">1</property>
<property name="resizable">0</property>
<property name="border-width">24</property>
<signal name="delete-event" handler="gtk_widget_hide_on_delete"/>
<child internal-child="vbox">
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">How much disk space this application is occupying with app data and caches.</property>
</object>
</child>
<child>
<object class="GtkListBox" id="storage_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<child>
<object class="CcInfoRow" id="app">
<property name="title" translatable="yes">Application</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="use-markup">1</property>
<property name="info">Unknown</property>
</object>
</child>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<child>
<object class="GtkButton" id="clear_cache_button">
<property name="visible">1</property>
<property name="label" translatable="yes">Clear Cache…</property>
<signal name="clicked" handler="clear_cache_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -1,108 +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
{
GtkListBoxRow parent;
GAppInfo *info;
gchar *sortkey;
GtkWidget *box;
GtkWidget *image;
GtkWidget *label;
};
G_DEFINE_TYPE (CcApplicationsRow, cc_applications_row, GTK_TYPE_LIST_BOX_ROW)
static void
cc_applications_row_finalize (GObject *object)
{
CcApplicationsRow *self = CC_APPLICATIONS_ROW (object);
g_object_unref (self->info);
g_free (self->sortkey);
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");
gtk_widget_class_bind_template_child (widget_class, CcApplicationsRow, box);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsRow, image);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsRow, label);
}
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_autofree gchar *key = NULL;
GIcon *icon;
self = g_object_new (CC_TYPE_APPLICATIONS_ROW, NULL);
self->info = g_object_ref (info);
key = g_utf8_casefold (g_app_info_get_display_name (info), -1);
self->sortkey = g_utf8_collate_key (key, -1);
icon = g_app_info_get_icon (info);
if (icon != NULL)
gtk_image_set_from_gicon (GTK_IMAGE (self->image), g_app_info_get_icon (info), GTK_ICON_SIZE_BUTTON);
else
gtk_image_set_from_icon_name (GTK_IMAGE (self->image), "application-x-executable", GTK_ICON_SIZE_BUTTON);
gtk_label_set_label (GTK_LABEL (self->label), g_app_info_get_display_name (info));
return self;
}
GAppInfo *
cc_applications_row_get_info (CcApplicationsRow *self)
{
return self->info;
}
const gchar *
cc_applications_row_get_sort_key (CcApplicationsRow *self)
{
return self->sortkey;
}

View File

@@ -1,36 +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>
G_BEGIN_DECLS
#define CC_TYPE_APPLICATIONS_ROW (cc_applications_row_get_type())
G_DECLARE_FINAL_TYPE (CcApplicationsRow, cc_applications_row, CC, APPLICATIONS_ROW, GtkListBoxRow)
CcApplicationsRow* cc_applications_row_new (GAppInfo *info);
GAppInfo* cc_applications_row_get_info (CcApplicationsRow *row);
const gchar* cc_applications_row_get_sort_key (CcApplicationsRow *row);
G_END_DECLS

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcApplicationsRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child>
<object class="GtkBox" id="box">
<property name="visible">1</property>
<property name="border-width">6</property>
<property name="spacing">12</property>
<child>
<object class="GtkImage" id="image">
<property name="visible">1</property>
<property name="pixel-size">32</property>
<style>
<class name="sidebar-icon"/>
<class name="fullcolor"/>
<class name="lowres-icon"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="ellipsize">end</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,215 +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
{
GtkListBoxRow parent;
GtkWidget *title;
GtkWidget *info;
GtkWidget *expander;
gboolean expanded;
gboolean link;
};
G_DEFINE_TYPE (CcInfoRow, cc_info_row, GTK_TYPE_LIST_BOX_ROW)
enum
{
PROP_0,
PROP_TITLE,
PROP_USE_MARKUP,
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_TITLE:
g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->title)));
break;
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_USE_MARKUP:
g_value_set_boolean (value, gtk_label_get_use_markup (GTK_LABEL (row->title)));
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", GTK_ICON_SIZE_BUTTON);
else if (row->expanded)
gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "pan-down-symbolic", GTK_ICON_SIZE_BUTTON);
else
gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "pan-end-symbolic", GTK_ICON_SIZE_BUTTON);
}
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_TITLE:
gtk_label_set_label (GTK_LABEL (row->title), g_value_get_string (value));
break;
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_USE_MARKUP:
gtk_label_set_use_markup (GTK_LABEL (row->title), 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_TITLE,
g_param_spec_string ("title", "title", "title",
NULL, G_PARAM_READWRITE));
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_USE_MARKUP,
g_param_spec_boolean ("use-markup", "use-markup", "use-markup",
FALSE, 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, title);
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 <gtk/gtk.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, GtkListBoxRow)
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,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcInfoRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="activatable">False</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="border-width">12</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="title">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<property name="ellipsize">end</property>
</object>
</child>
<child>
<object class="GtkLabel" id="info">
<property name="visible">1</property>
<property name="valign">center</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkImage" id="expander">
<property name="valign">center</property>
<property name="icon-name">pan-end-symbolic</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,316 +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"
struct _CcSnapRow
{
GtkListBoxRow parent;
GtkLabel *title_label;
GtkSwitch *slot_toggle;
GtkComboBox *slots_combo;
GtkListStore *slots_combo_model;
GCancellable *cancellable;
SnapdPlug *plug;
SnapdSlot *connected_slot;
GPtrArray *slots;
};
G_DEFINE_TYPE (CcSnapRow, cc_snap_row, GTK_TYPE_LIST_BOX_ROW)
typedef struct
{
CcSnapRow *self;
SnapdSlot *slot;
} ConnectData;
static void
update_state (CcSnapRow *self)
{
gboolean have_single_option;
GtkTreeIter iter;
have_single_option = self->slots->len == 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
{
SnapdSlot *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 ConnectData *
connect_data_new (CcSnapRow *self, SnapdSlot *slot)
{
ConnectData *data;
data = g_new0 (ConnectData, 1);
data->self = self;
data->slot = g_object_ref (slot);
return data;
}
static void
connect_data_free (ConnectData *data)
{
g_clear_object (&data->slot);
g_free (data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ConnectData, connect_data_free)
static void
connect_interface_cb (GObject *client, GAsyncResult *result, gpointer user_data)
{
g_autoptr(ConnectData) data = user_data;
CcSnapRow *self = data->self;
SnapdSlot *slot = data->slot;
g_autoptr(GError) error = NULL;
if (snapd_client_connect_interface_finish (SNAPD_CLIENT (client), result, &error))
{
g_clear_object (&self->connected_slot);
self->connected_slot = g_object_ref (slot);
}
else
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Failed to connect interface: %s", error->message);
}
update_state (self);
enable_controls (self);
}
static void
connect_plug (CcSnapRow *self, SnapdSlot *slot)
{
g_autoptr(SnapdClient) client = NULL;
/* already connected */
if (self->connected_slot == slot)
return;
disable_controls (self);
client = snapd_client_new ();
snapd_client_connect_interface_async (client,
snapd_plug_get_snap (self->plug), snapd_plug_get_name (self->plug),
snapd_slot_get_snap (slot), snapd_slot_get_name (slot),
NULL, NULL,
self->cancellable,
connect_interface_cb, connect_data_new (self, slot));
}
static void
disconnect_interface_cb (GObject *client, GAsyncResult *result, gpointer user_data)
{
CcSnapRow *self = user_data;
g_autoptr(GError) error = NULL;
if (snapd_client_disconnect_interface_finish (SNAPD_CLIENT (client), result, &error))
{
g_clear_object (&self->connected_slot);
}
else
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Failed to disconnect interface: %s", error->message);
}
update_state (self);
enable_controls (self);
}
static void
disconnect_plug (CcSnapRow *self)
{
g_autoptr(SnapdClient) client = NULL;
/* already disconnected */
if (self->connected_slot == NULL)
return;
disable_controls (self);
client = snapd_client_new ();
snapd_client_disconnect_interface_async (client,
snapd_plug_get_snap (self->plug), snapd_plug_get_name (self->plug),
NULL, NULL,
NULL, NULL,
self->cancellable,
disconnect_interface_cb, self);
}
static void
switch_changed_cb (CcSnapRow *self)
{
if (gtk_switch_get_active (self->slot_toggle))
{
if (self->slots->len == 1)
connect_plug (self, g_ptr_array_index (self->slots, 0));
}
else
{
disconnect_plug (self);
}
}
static void
combo_changed_cb (CcSnapRow *self)
{
GtkTreeIter iter;
SnapdSlot *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 void
cc_snap_row_finalize (GObject *object)
{
CcSnapRow *self = CC_SNAP_ROW (object);
g_clear_object (&self->cancellable);
g_clear_object (&self->plug);
g_clear_pointer (&self->slots, g_ptr_array_unref);
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, title_label);
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, SnapdInterface *interface, SnapdPlug *plug, GPtrArray *slots)
{
CcSnapRow *self;
GPtrArray *connected_slots;
g_autofree gchar *label = NULL;
GtkTreeIter iter;
g_return_val_if_fail (SNAPD_IS_PLUG (plug), NULL);
self = CC_SNAP_ROW (g_object_new (CC_TYPE_SNAP_ROW, NULL));
self->cancellable = g_object_ref (cancellable);
self->plug = g_object_ref (plug);
self->slots = g_ptr_array_ref (slots);
connected_slots = snapd_plug_get_connected_slots (plug);
if (connected_slots->len > 0)
{
SnapdSlotRef *connected_slot_ref = g_ptr_array_index (connected_slots, 0);
for (int i = 0; i < slots->len; i++)
{
SnapdSlot *slot = g_ptr_array_index (slots, i);
if (g_strcmp0 (snapd_slot_get_snap (slot), snapd_slot_ref_get_snap (connected_slot_ref)) == 0 &&
g_strcmp0 (snapd_slot_get_name (slot), snapd_slot_ref_get_slot (connected_slot_ref)) == 0)
self->connected_slot = slot;
}
}
if (interface != NULL)
label = snapd_interface_make_label (interface);
else
label = g_strdup (snapd_plug_get_interface (plug));
gtk_label_set_label (self->title_label, 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 (int i = 0; i < slots->len; i++)
{
SnapdSlot *slot = g_ptr_array_index (slots, i);
g_autofree gchar *label = NULL;
label = g_strdup_printf ("%s:%s", snapd_slot_get_snap (slot), snapd_slot_get_name (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,36 +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 <gtk/gtk.h>
#include <snapd-glib/snapd-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, GtkListBoxRow)
CcSnapRow* cc_snap_row_new (GCancellable *cancellable,
SnapdInterface *interface,
SnapdPlug *plug,
GPtrArray *slots);
G_END_DECLS

View File

@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkListStore" id="slots_combo_model">
<columns>
<!-- column-name slot -->
<column type="GObject"/>
<!-- column-name label -->
<column type="gchararray"/>
</columns>
</object>
<template class="CcSnapRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="activatable">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="border-width">12</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="title_label">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<property name="ellipsize">end</property>
</object>
</child>
<child>
<object class="GtkSwitch" id="slot_toggle">
<property name="visible">True</property>
<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="visible">True</property>
<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>
</object>
</child>
</template>
</interface>

View File

@@ -1,144 +0,0 @@
/* cc-toggle-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-toggle-row.h"
#include "cc-applications-resources.h"
struct _CcToggleRow
{
GtkListBoxRow parent;
GtkWidget *title;
GtkWidget *toggle;
};
G_DEFINE_TYPE (CcToggleRow, cc_toggle_row, GTK_TYPE_LIST_BOX_ROW)
enum
{
PROP_0,
PROP_TITLE,
PROP_ALLOWED
};
static void
changed_cb (CcToggleRow *row)
{
g_object_notify (G_OBJECT (row), "allowed");
}
static void
cc_toggle_row_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcToggleRow *row = CC_TOGGLE_ROW (object);
switch (prop_id)
{
case PROP_TITLE:
g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->title)));
break;
case PROP_ALLOWED:
g_value_set_boolean (value, cc_toggle_row_get_allowed (row));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
cc_toggle_row_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CcToggleRow *row = CC_TOGGLE_ROW (object);
switch (prop_id)
{
case PROP_TITLE:
gtk_label_set_label (GTK_LABEL (row->title), g_value_get_string (value));
break;
case PROP_ALLOWED:
cc_toggle_row_set_allowed (row, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
cc_toggle_row_class_init (CcToggleRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->get_property = cc_toggle_row_get_property;
object_class->set_property = cc_toggle_row_set_property;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-toggle-row.ui");
g_object_class_install_property (object_class,
PROP_TITLE,
g_param_spec_string ("title", "title", "title",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_ALLOWED,
g_param_spec_boolean ("allowed", "allowed", "allowed",
FALSE, G_PARAM_READWRITE));
gtk_widget_class_bind_template_child (widget_class, CcToggleRow, title);
gtk_widget_class_bind_template_child (widget_class, CcToggleRow, toggle);
gtk_widget_class_bind_template_callback (widget_class, changed_cb);
}
static void
cc_toggle_row_init (CcToggleRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
}
CcToggleRow *
cc_toggle_row_new (void)
{
return CC_TOGGLE_ROW (g_object_new (CC_TYPE_TOGGLE_ROW, NULL));
}
void
cc_toggle_row_set_allowed (CcToggleRow *self,
gboolean allowed)
{
gtk_switch_set_active (GTK_SWITCH (self->toggle), allowed);
}
gboolean
cc_toggle_row_get_allowed (CcToggleRow *self)
{
return gtk_switch_get_active (GTK_SWITCH (self->toggle));
}

View File

@@ -1,37 +0,0 @@
/* cc-toggle-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>
G_BEGIN_DECLS
#define CC_TYPE_TOGGLE_ROW (cc_toggle_row_get_type())
G_DECLARE_FINAL_TYPE (CcToggleRow, cc_toggle_row, CC, TOGGLE_ROW, GtkListBoxRow)
CcToggleRow* cc_toggle_row_new (void);
void cc_toggle_row_set_allowed (CcToggleRow *row,
gboolean allowed);
gboolean cc_toggle_row_get_allowed (CcToggleRow *row);
G_END_DECLS

View File

@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcToggleRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="activatable">False</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="border-width">12</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="title">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<property name="ellipsize">end</property>
</object>
</child>
<child>
<object class="GtkSwitch" id="toggle">
<property name="visible">1</property>
<property name="valign">center</property>
<signal name="notify::active" handler="changed_cb" swapped="yes"/>
</object>
</child>
</object>
</child>
</template>
</interface>

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,16 +0,0 @@
[Desktop Entry]
Name=Applications
Comment=Control various application permissions and settings
Exec=gnome-control-center applications
# FIXME
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=preferences-desktop-apps
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 Privacy panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=application;flatpak;permission;setting;
X-GNOME-ControlCenter-HasSidebar=true

View File

@@ -1,57 +0,0 @@
panels_list += cappletname
desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
desktop_in = configure_file(
input : desktop + '.in.in',
output : desktop + '.in',
configuration : desktop_conf
)
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-toggle-row.c',
'cc-info-row.c',
'cc-action-row.c',
'globs.c',
'search.c',
'utils.c',
)
resource_data = files('cc-applications-panel.ui')
sources += gnome.compile_resources(
'cc-' + cappletname + '-resources',
cappletname + '.gresource.xml',
c_name : 'cc_' + cappletname,
dependencies : resource_data,
export : true
)
deps = common_deps
if enable_snap
deps += snapd_glib_deps
sources += files('cc-snap-row.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
)

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,268 +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>
#ifdef HAVE_SNAP
#include <snapd-glib/snapd-glib.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <ftw.h>
#include "utils.h"
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_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;
}
void
container_remove_all (GtkContainer *container)
{
g_autoptr(GList) children = NULL;
GList *l;
children = gtk_container_get_children (container);
for (l = children; l; l = l->next)
gtk_widget_destroy (GTK_WIDGET (l->data));
}
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_exit_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(SnapdClient) client = NULL;
g_autoptr(SnapdSnap) snap = NULL;
g_autoptr(GError) error = NULL;
client = snapd_client_new ();
snap = 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 snapd_snap_get_installed_size (snap);
#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,57 +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);
void container_remove_all (GtkContainer *container);
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,9 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/control-center/background">
<file preprocess="xml-stripblanks">cc-background-chooser.ui</file>
<file preprocess="xml-stripblanks">cc-background-panel.ui</file>
<file preprocess="xml-stripblanks">cc-background-preview.ui</file>
<file>preview.css</file>
<file preprocess="xml-stripblanks">background.ui</file>
</gresource>
</gresources>

View File

@@ -0,0 +1,300 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkBox" id="background-panel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin">32</property>
<property name="spacing">12</property>
<property name="valign">center</property>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">24</property>
<child>
<object class="GtkBox" id="vbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButton" id="background-set-button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<object class="GtkBox" id="box2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin">6</property>
<property name="spacing">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkDrawingArea" id="background-desktop-drawingarea">
<property name="width_request">310</property>
<property name="height_request">170</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Background</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">background-set-button</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="bottom-hbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkBox" id="hbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="margin_top">12</property>
<property name="spacing">2</property>
<child>
<object class="GtkImage" id="slide_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">slideshow-symbolic</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="strut">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label"> </property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="slide-label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes" comments="This refers to a slideshow background">Changes throughout the day</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="halign">start</property>
<property name="valign">center</property>
<child>
<object class="GtkButton" id="background-lock-set-button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<object class="GtkBox" id="box3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin">6</property>
<property name="spacing">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkDrawingArea" id="background-lock-drawingarea">
<property name="width_request">310</property>
<property name="height_request">170</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" comments="To translators: This is a noun, not a verb">_Lock Screen</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">background-lock-set-button</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="bottom-hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="margin_top">12</property>
<property name="spacing">2</property>
<child>
<object class="GtkImage" id="slide_image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">slideshow-symbolic</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="strut1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label"> </property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="slide-label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes" comments="This refers to a slideshow background">Changes throughout the day</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<object class="GtkListStore" id="sources-liststore">
<columns>
<!-- column-name source-name -->
<column type="gchararray"/>
<!-- column-name source-id -->
<column type="guint"/>
<!-- column-name source-pointer -->
<column type="gpointer"/>
</columns>
</object>
<object class="GtkListStore" id="style-liststore">
<columns>
<!-- column-name name -->
<column type="gchararray"/>
<!-- column-name value -->
<column type="gint"/>
</columns>
<data>
<row>
<col id="0" translatable="yes" context="background, style">Tile</col>
<col id="1">1</col>
</row>
<row>
<col id="0" translatable="yes" context="background, style">Zoom</col>
<col id="1">5</col>
</row>
<row>
<col id="0" translatable="yes" context="background, style">Center</col>
<col id="1">2</col>
</row>
<row>
<col id="0" translatable="yes" context="background, style">Scale</col>
<col id="1">3</col>
</row>
<row>
<col id="0" translatable="yes" context="background, style">Fill</col>
<col id="1">4</col>
</row>
<row>
<col id="0" translatable="yes" context="background, style">Span</col>
<col id="1">6</col>
</row>
</data>
</object>
<object class="GtkSizeGroup" id="sizegroup">
<property name="mode">vertical</property>
<widgets>
<widget name="slide-label"/>
<widget name="strut"/>
</widgets>
</object>
</interface>

View File

@@ -71,11 +71,21 @@ get_colors_dir (void)
static void
bg_colors_source_add_color (BgColorsSource *self,
GListStore *store,
const char *color)
GnomeDesktopThumbnailFactory *thumb_factory,
GtkListStore *store,
const char *color,
GtkTreeRowReference **ret_row_ref)
{
CcBackgroundItemFlags flags;
g_autoptr(CcBackgroundItem) item = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
cairo_surface_t *surface;
int scale_factor;
int thumbnail_height, thumbnail_width;
GtkTreeIter iter;
thumbnail_height = bg_source_get_thumbnail_height (BG_SOURCE (self));
thumbnail_width = bg_source_get_thumbnail_width (BG_SOURCE (self));
item = cc_background_item_new (NULL);
flags = CC_BACKGROUND_ITEM_HAS_PCOLOR |
@@ -96,24 +106,47 @@ bg_colors_source_add_color (BgColorsSource *self,
cc_background_item_load (item, NULL);
/* insert the item into the liststore */
g_list_store_append (store, item);
scale_factor = bg_source_get_scale_factor (BG_SOURCE (self));
pixbuf = cc_background_item_get_thumbnail (item,
thumb_factory,
thumbnail_width, thumbnail_height,
scale_factor);
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
gtk_list_store_insert_with_values (store, &iter, 0,
0, surface,
1, item,
-1);
cairo_surface_destroy (surface);
if (ret_row_ref)
{
GtkTreePath *path;
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
*ret_row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
gtk_tree_path_free (path);
}
}
static void
bg_colors_source_constructed (GObject *object)
{
BgColorsSource *self = BG_COLORS_SOURCE (object);
g_autoptr(GnomeDesktopThumbnailFactory) thumb_factory = NULL;
guint i;
GListStore *store;
GtkListStore *store;
g_autoptr(GKeyFile) keyfile = NULL;
g_autofree gchar *path = NULL;
G_OBJECT_CLASS (bg_colors_source_parent_class)->constructed (object);
store = bg_source_get_liststore (BG_SOURCE (self));
thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
for (i = 0; i < G_N_ELEMENTS (items); i++)
bg_colors_source_add_color (self, store, items[i].pcolor);
{
bg_colors_source_add_color (self, thumb_factory, store, items[i].pcolor, NULL);
}
keyfile = g_key_file_new ();
path = get_colors_path ();
@@ -123,7 +156,9 @@ bg_colors_source_constructed (GObject *object)
colors = g_key_file_get_string_list (keyfile, "Colors", "custom-colors", NULL, NULL);
for (i = 0; colors != NULL && colors[i] != NULL; i++)
bg_colors_source_add_color (self, store, colors[i]);
{
bg_colors_source_add_color (self, thumb_factory, store, colors[i], NULL);
}
}
}
@@ -132,7 +167,8 @@ bg_colors_source_add (BgColorsSource *self,
GdkRGBA *rgba,
GtkTreeRowReference **ret_row_ref)
{
GListStore *store;
g_autoptr(GnomeDesktopThumbnailFactory) thumb_factory = NULL;
GtkListStore *store;
g_autofree gchar *c = NULL;
g_auto(GStrv) colors = NULL;
gsize len;
@@ -146,9 +182,10 @@ bg_colors_source_add (BgColorsSource *self,
(int)(255*rgba->green),
(int)(255*rgba->blue));
thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
store = bg_source_get_liststore (BG_SOURCE (self));
bg_colors_source_add_color (self, store, c);
bg_colors_source_add_color (self, thumb_factory, store, c, ret_row_ref);
/* Save to the keyfile */
dir = get_colors_dir ();
@@ -212,8 +249,8 @@ bg_colors_source_class_init (BgColorsSourceClass *klass)
}
BgColorsSource *
bg_colors_source_new (GtkWidget *widget)
bg_colors_source_new (GtkWindow *window)
{
return g_object_new (BG_TYPE_COLORS_SOURCE, "widget", widget, NULL);
return g_object_new (BG_TYPE_COLORS_SOURCE, "window", window, NULL);
}

View File

@@ -19,7 +19,8 @@
*
*/
#pragma once
#ifndef _BG_COLORS_SOURCE_H
#define _BG_COLORS_SOURCE_H
#include <gtk/gtk.h>
#include "bg-source.h"
@@ -29,10 +30,12 @@ G_BEGIN_DECLS
#define BG_TYPE_COLORS_SOURCE (bg_colors_source_get_type ())
G_DECLARE_FINAL_TYPE (BgColorsSource, bg_colors_source, BG, COLORS_SOURCE, BgSource)
BgColorsSource *bg_colors_source_new (GtkWidget *widget);
BgColorsSource *bg_colors_source_new (GtkWindow *window);
gboolean bg_colors_source_add (BgColorsSource *self,
GdkRGBA *rgba,
GtkTreeRowReference **ret_row_ref);
G_END_DECLS
#endif /* _BG_COLORS_SOURCE_H */

View File

@@ -45,6 +45,8 @@ struct _BgPicturesSource
CcBackgroundGriloMiner *grl_miner;
GnomeDesktopThumbnailFactory *thumb_factory;
GFileMonitor *picture_dir_monitor;
GFileMonitor *cache_dir_monitor;
@@ -84,6 +86,7 @@ bg_pictures_source_dispose (GObject *object)
}
g_clear_object (&source->grl_miner);
g_clear_object (&source->thumb_factory);
G_OBJECT_CLASS (bg_pictures_source_parent_class)->dispose (object);
}
@@ -93,6 +96,8 @@ bg_pictures_source_finalize (GObject *object)
{
BgPicturesSource *bg_source = BG_PICTURES_SOURCE (object);
g_clear_object (&bg_source->thumb_factory);
g_clear_pointer (&bg_source->known_items, g_hash_table_destroy);
g_clear_object (&bg_source->picture_dir_monitor);
@@ -111,26 +116,23 @@ bg_pictures_source_class_init (BgPicturesSourceClass *klass)
}
static void
remove_placeholder (BgPicturesSource *bg_source,
CcBackgroundItem *item)
remove_placeholder (BgPicturesSource *bg_source, CcBackgroundItem *item)
{
GListStore *store;
guint i;
GtkListStore *store;
GtkTreeIter iter;
GtkTreePath *path;
GtkTreeRowReference *row_ref;
store = bg_source_get_liststore (BG_SOURCE (bg_source));
row_ref = g_object_get_data (G_OBJECT (item), "row-ref");
if (row_ref == NULL)
return;
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
{
g_autoptr(CcBackgroundItem) item_n = NULL;
path = gtk_tree_row_reference_get_path (row_ref);
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
return;
item_n = g_list_model_get_item (G_LIST_MODEL (store), i);
if (item_n == item)
{
g_list_store_remove (store, i);
break;
}
}
gtk_list_store_remove (store, &iter);
}
static gboolean
@@ -161,27 +163,6 @@ swap_rotated_pixbuf (GdkPixbuf *pixbuf)
return tmp_pixbuf;
}
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
picture_scaled (GObject *source_object,
GAsyncResult *res,
@@ -193,7 +174,10 @@ picture_scaled (GObject *source_object,
g_autoptr(GdkPixbuf) pixbuf = NULL;
const char *software;
const char *uri;
GListStore *store;
GtkTreeIter iter;
GtkTreePath *path;
GtkTreeRowReference *row_ref;
GtkListStore *store;
cairo_surface_t *surface = NULL;
int scale_factor;
gboolean rotation_applied;
@@ -254,14 +238,32 @@ picture_scaled (GObject *source_object,
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
cc_background_item_load (item, NULL);
/* insert the item into the liststore */
g_list_store_insert_sorted (store, item, sort_func, bg_source);
row_ref = g_object_get_data (G_OBJECT (item), "row-ref");
if (row_ref == NULL)
{
/* insert the item into the liststore if it did not exist */
gtk_list_store_insert_with_values (store, NULL, -1,
0, surface,
1, item,
-1);
}
else
{
path = gtk_tree_row_reference_get_path (row_ref);
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
{
/* otherwise update the thumbnail */
gtk_list_store_set (store, &iter,
0, surface,
-1);
}
}
g_hash_table_insert (bg_source->known_items,
bg_pictures_source_get_unique_filename (uri),
GINT_TO_POINTER (TRUE));
g_clear_pointer (&surface, cairo_surface_destroy);
g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
}
static void
@@ -365,6 +367,67 @@ in_content_types (const char *content_type)
return FALSE;
}
static gboolean
in_screenshot_types (const char *content_type)
{
guint i;
for (i = 0; screenshot_types[i]; i++)
if (g_str_equal (screenshot_types[i], content_type))
return TRUE;
return FALSE;
}
static cairo_surface_t *
get_content_loading_icon (BgSource *source)
{
GtkIconTheme *theme;
g_autoptr(GtkIconInfo) icon_info = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
g_autoptr(GdkPixbuf) ret = NULL;
g_autoptr(GError) error = NULL;
int scale_factor;
cairo_surface_t *surface;
int thumbnail_height;
int thumbnail_width;
theme = gtk_icon_theme_get_default ();
icon_info = gtk_icon_theme_lookup_icon (theme,
"content-loading-symbolic",
16,
GTK_ICON_LOOKUP_FORCE_SIZE | GTK_ICON_LOOKUP_GENERIC_FALLBACK);
if (icon_info == NULL)
{
g_warning ("Failed to find placeholder icon");
return NULL;
}
pixbuf = gtk_icon_info_load_icon (icon_info, &error);
if (pixbuf == NULL)
{
g_warning ("Failed to load placeholder icon: %s", error->message);
return NULL;
}
thumbnail_height = bg_source_get_thumbnail_height (source);
thumbnail_width = bg_source_get_thumbnail_width (source);
ret = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
TRUE,
8, thumbnail_width, thumbnail_height);
gdk_pixbuf_fill (ret, 0x00000000);
/* Put the icon in the middle */
gdk_pixbuf_copy_area (pixbuf, 0, 0,
gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
ret,
(thumbnail_width - gdk_pixbuf_get_width (pixbuf)) / 2,
(thumbnail_height - gdk_pixbuf_get_height (pixbuf)) / 2);
scale_factor = bg_source_get_scale_factor (source);
surface = gdk_cairo_surface_create_from_pixbuf (ret, scale_factor, NULL);
return surface;
}
static GFile *
bg_pictures_source_get_cache_file (void)
{
@@ -381,15 +444,20 @@ static gboolean
add_single_file (BgPicturesSource *bg_source,
GFile *file,
const gchar *content_type,
guint64 mtime)
guint64 mtime,
GtkTreeRowReference **ret_row_ref)
{
g_autoptr(CcBackgroundItem) item = NULL;
CcBackgroundItemFlags flags = 0;
GtkListStore *store;
GtkTreeIter iter;
GtkTreePath *path = NULL;
GtkTreeRowReference *row_ref = NULL;
cairo_surface_t *surface = NULL;
g_autofree gchar *source_uri = NULL;
g_autofree gchar *uri = NULL;
gboolean needs_download;
gboolean retval = FALSE;
const gchar *pictures_path;
g_autoptr(GFile) pictures_dir = NULL;
g_autoptr(GFile) cache_dir = NULL;
GrlMedia *media;
@@ -403,10 +471,7 @@ add_single_file (BgPicturesSource *bg_source,
/* create a new CcBackgroundItem */
uri = g_file_get_uri (file);
pictures_path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
if (pictures_path == NULL)
pictures_path = g_get_home_dir ();
pictures_dir = g_file_new_for_path (pictures_path);
pictures_dir = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
cache_dir = bg_pictures_source_get_cache_file ();
needs_download = !g_file_has_parent (file, pictures_dir) &&
!g_file_has_parent (file, cache_dir);
@@ -432,6 +497,25 @@ add_single_file (BgPicturesSource *bg_source,
"source-url", source_uri,
NULL);
if (!ret_row_ref && in_screenshot_types (content_type))
goto read_file;
surface = get_content_loading_icon (BG_SOURCE (bg_source));
store = bg_source_get_liststore (BG_SOURCE (bg_source));
/* insert the item into the liststore */
gtk_list_store_insert_with_values (store, &iter, -1,
0, surface,
1, item,
-1);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
g_object_set_data_full (G_OBJECT (item), "row-ref", row_ref, (GDestroyNotify) gtk_tree_row_reference_free);
read_file:
media = g_object_get_data (G_OBJECT (file), "grl-media");
if (media == NULL)
{
@@ -480,20 +564,30 @@ add_single_file (BgPicturesSource *bg_source,
retval = TRUE;
out:
if (ret_row_ref)
{
if (row_ref && retval != FALSE)
*ret_row_ref = gtk_tree_row_reference_copy (row_ref);
else
*ret_row_ref = NULL;
}
gtk_tree_path_free (path);
g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
return retval;
}
static gboolean
add_single_file_from_info (BgPicturesSource *bg_source,
GFile *file,
GFileInfo *info)
add_single_file_from_info (BgPicturesSource *bg_source,
GFile *file,
GFileInfo *info,
GtkTreeRowReference **ret_row_ref)
{
const gchar *content_type;
guint64 mtime;
content_type = g_file_info_get_content_type (info);
mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
return add_single_file (bg_source, file, content_type, mtime);
return add_single_file (bg_source, file, content_type, mtime, ret_row_ref);
}
static gboolean
@@ -518,7 +612,7 @@ add_single_file_from_media (BgPicturesSource *bg_source,
else
mtime_unix = g_get_real_time () / G_USEC_PER_SEC;
return add_single_file (bg_source, file, content_type, (guint64) mtime_unix);
return add_single_file (bg_source, file, content_type, (guint64) mtime_unix, NULL);
}
gboolean
@@ -535,7 +629,7 @@ bg_pictures_source_add (BgPicturesSource *bg_source,
if (info == NULL)
return FALSE;
retval = add_single_file_from_info (bg_source, file, info);
retval = add_single_file_from_info (bg_source, file, info, ret_row_ref);
return retval;
}
@@ -544,19 +638,21 @@ gboolean
bg_pictures_source_remove (BgPicturesSource *bg_source,
const char *uri)
{
GListStore *store;
GtkTreeModel *model;
GtkTreeIter iter;
gboolean cont;
gboolean retval;
guint i;
retval = FALSE;
store = bg_source_get_liststore (BG_SOURCE (bg_source));
model = GTK_TREE_MODEL (bg_source_get_liststore (BG_SOURCE (bg_source)));
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
cont = gtk_tree_model_get_iter_first (model, &iter);
while (cont)
{
g_autoptr(CcBackgroundItem) tmp_item = NULL;
const char *tmp_uri;
tmp_item = g_list_model_get_item (G_LIST_MODEL (store), i);
gtk_tree_model_get (model, &iter, 1, &tmp_item, -1);
tmp_uri = cc_background_item_get_uri (tmp_item);
if (g_str_equal (tmp_uri, uri))
{
@@ -565,10 +661,11 @@ bg_pictures_source_remove (BgPicturesSource *bg_source,
g_hash_table_insert (bg_source->known_items,
uuid, NULL);
g_list_store_remove (store, i);
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
retval = TRUE;
break;
}
cont = gtk_tree_model_iter_next (model, &iter);
}
return retval;
}
@@ -625,7 +722,7 @@ file_info_async_ready (GObject *source,
file = g_file_get_child (parent, g_file_info_get_name (info));
add_single_file_from_info (bg_source, file, info);
add_single_file_from_info (bg_source, file, info, NULL);
}
g_list_foreach (files, (GFunc) g_object_unref, NULL);
@@ -709,6 +806,33 @@ bg_pictures_source_is_known (BgPicturesSource *bg_source,
return GPOINTER_TO_INT (g_hash_table_lookup (bg_source->known_items, uuid));
}
static int
sort_func (GtkTreeModel *model,
GtkTreeIter *a,
GtkTreeIter *b,
BgPicturesSource *bg_source)
{
g_autoptr(CcBackgroundItem) item_a = NULL;
g_autoptr(CcBackgroundItem) item_b = NULL;
guint64 modified_a;
guint64 modified_b;
int retval;
gtk_tree_model_get (model, a,
1, &item_a,
-1);
gtk_tree_model_get (model, b,
1, &item_b,
-1);
modified_a = cc_background_item_get_modified (item_a);
modified_b = cc_background_item_get_modified (item_b);
retval = modified_b - modified_a;
return retval;
}
static void
file_info_ready (GObject *object,
GAsyncResult *res,
@@ -728,7 +852,7 @@ file_info_ready (GObject *object,
return;
}
add_single_file_from_info (BG_PICTURES_SOURCE (user_data), file, info);
add_single_file_from_info (BG_PICTURES_SOURCE (user_data), file, info, NULL);
}
static void
@@ -751,11 +875,13 @@ file_added (GFile *file,
}
static void
files_changed_cb (BgPicturesSource *self,
files_changed_cb (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type)
GFileMonitorEvent event_type,
gpointer user_data)
{
BgPicturesSource *self = BG_PICTURES_SOURCE (user_data);
g_autofree gchar *uri = NULL;
switch (event_type)
@@ -796,10 +922,10 @@ monitor_path (BgPicturesSource *self,
NULL);
if (monitor)
g_signal_connect_object (monitor,
"changed",
G_CALLBACK (files_changed_cb),
self, G_CONNECT_SWAPPED);
g_signal_connect (monitor,
"changed",
G_CALLBACK (files_changed_cb),
self);
return monitor;
}
@@ -821,6 +947,7 @@ bg_pictures_source_init (BgPicturesSource *self)
{
const gchar *pictures_path;
g_autofree gchar *cache_path = NULL;
GtkListStore *store;
self->cancellable = g_cancellable_new ();
self->known_items = g_hash_table_new_full (g_str_hash,
@@ -838,14 +965,29 @@ bg_pictures_source_init (BgPicturesSource *self)
self->cache_dir_monitor = monitor_path (self, cache_path);
self->grl_miner = cc_background_grilo_miner_new ();
g_signal_connect_object (self->grl_miner, "media-found", G_CALLBACK (media_found_cb), self, G_CONNECT_SWAPPED);
g_signal_connect_swapped (self->grl_miner, "media-found", G_CALLBACK (media_found_cb), self);
cc_background_grilo_miner_start (self->grl_miner);
self->thumb_factory =
gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
store = bg_source_get_liststore (BG_SOURCE (self));
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
1,
(GtkTreeIterCompareFunc)sort_func,
self,
NULL);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
1,
GTK_SORT_ASCENDING);
}
BgPicturesSource *
bg_pictures_source_new (GtkWidget *widget)
bg_pictures_source_new (GtkWindow *window)
{
return g_object_new (BG_TYPE_PICTURES_SOURCE, "widget", widget, NULL);
return g_object_new (BG_TYPE_PICTURES_SOURCE, "window", window, NULL);
}
const char * const *

View File

@@ -19,7 +19,9 @@
*
*/
#pragma once
#ifndef _BG_PICTURES_SOURCE_H
#define _BG_PICTURES_SOURCE_H
#include <gtk/gtk.h>
#include "bg-source.h"
@@ -30,7 +32,7 @@ G_BEGIN_DECLS
#define BG_TYPE_PICTURES_SOURCE (bg_pictures_source_get_type ())
G_DECLARE_FINAL_TYPE (BgPicturesSource, bg_pictures_source, BG, PICTURES_SOURCE, BgSource)
BgPicturesSource *bg_pictures_source_new (GtkWidget *widget);
BgPicturesSource *bg_pictures_source_new (GtkWindow *window);
char *bg_pictures_source_get_cache_path (void);
char *bg_pictures_source_get_unique_path(const char *uri);
gboolean bg_pictures_source_add (BgPicturesSource *bg_source,
@@ -44,3 +46,5 @@ gboolean bg_pictures_source_is_known (BgPicturesSource *bg_source
const char * const * bg_pictures_get_support_content_types (void);
G_END_DECLS
#endif /* _BG_PICTURES_SOURCE_H */

View File

@@ -1,470 +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 const gchar * const content_types[] = {
"image/png",
"image/jp2",
"image/jpeg",
"image/bmp",
"image/svg+xml",
"image/x-portable-anymap",
NULL
};
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_strv_contains (content_types, content_type))
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

@@ -23,14 +23,13 @@
#include <cairo-gobject.h>
#define THUMBNAIL_WIDTH 154
#define THUMBNAIL_WIDTH 256
#define THUMBNAIL_HEIGHT (THUMBNAIL_WIDTH * 3 / 4)
typedef struct
{
GnomeDesktopThumbnailFactory *thumbnail_factory;
GListStore *store;
GtkWidget *widget;
GtkListStore *store;
GtkWidget *window;
gint thumbnail_height;
gint thumbnail_width;
} BgSourcePrivate;
@@ -40,7 +39,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (BgSource, bg_source, G_TYPE_OBJECT)
enum
{
PROP_LISTSTORE = 1,
PROP_WIDGET
PROP_WINDOW
};
@@ -53,10 +52,10 @@ bg_source_calculate_thumbnail_dimensions (BgSource *source)
priv->thumbnail_height = THUMBNAIL_HEIGHT;
priv->thumbnail_width = THUMBNAIL_WIDTH;
if (priv->widget == NULL)
if (priv->window == NULL)
return;
scale_factor = gtk_widget_get_scale_factor (priv->widget);
scale_factor = gtk_widget_get_scale_factor (priv->window);
if (scale_factor > 1)
{
priv->thumbnail_height *= scale_factor;
@@ -102,8 +101,8 @@ bg_source_set_property (GObject *object,
switch (property_id)
{
case PROP_WIDGET:
priv->widget = GTK_WIDGET (g_value_get_object (value));
case PROP_WINDOW:
priv->window = GTK_WIDGET (g_value_get_object (value));
break;
default:
@@ -117,7 +116,6 @@ bg_source_dispose (GObject *object)
BgSource *source = BG_SOURCE (object);
BgSourcePrivate *priv = bg_source_get_instance_private (source);
g_clear_object (&priv->thumbnail_factory);
g_clear_object (&priv->store);
G_OBJECT_CLASS (bg_source_parent_class)->dispose (object);
@@ -137,27 +135,26 @@ bg_source_class_init (BgSourceClass *klass)
pspec = g_param_spec_object ("liststore",
"Liststore",
"Liststore used in the source",
G_TYPE_LIST_STORE,
GTK_TYPE_LIST_STORE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_LISTSTORE, pspec);
pspec = g_param_spec_object ("widget",
"Widget",
"Widget used to view the source",
GTK_TYPE_WIDGET,
pspec = g_param_spec_object ("window",
"Window",
"Toplevel window used to view the source",
GTK_TYPE_WINDOW,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_WIDGET, pspec);
g_object_class_install_property (object_class, PROP_WINDOW, pspec);
}
static void
bg_source_init (BgSource *self)
{
BgSourcePrivate *priv = bg_source_get_instance_private (self);
priv->store = g_list_store_new (CC_TYPE_BACKGROUND_ITEM);
priv->thumbnail_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
priv->store = gtk_list_store_new (3, CAIRO_GOBJECT_TYPE_SURFACE, G_TYPE_OBJECT, G_TYPE_STRING);
}
GListStore*
GtkListStore*
bg_source_get_liststore (BgSource *source)
{
BgSourcePrivate *priv;
@@ -176,7 +173,7 @@ bg_source_get_scale_factor (BgSource *source)
g_return_val_if_fail (BG_IS_SOURCE (source), 1);
priv = bg_source_get_instance_private (source);
return gtk_widget_get_scale_factor (priv->widget);
return gtk_widget_get_scale_factor (priv->window);
}
gint
@@ -200,14 +197,3 @@ bg_source_get_thumbnail_width (BgSource *source)
priv = bg_source_get_instance_private (source);
return priv->thumbnail_width;
}
GnomeDesktopThumbnailFactory*
bg_source_get_thumbnail_factory (BgSource *source)
{
BgSourcePrivate *priv;
g_return_val_if_fail (BG_IS_SOURCE (source), NULL);
priv = bg_source_get_instance_private (source);
return priv->thumbnail_factory;
}

View File

@@ -18,10 +18,10 @@
*
*/
#pragma once
#ifndef _BG_SOURCE_H
#define _BG_SOURCE_H
#include <gtk/gtk.h>
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
G_BEGIN_DECLS
@@ -33,7 +33,7 @@ struct _BgSourceClass
GObjectClass parent_class;
};
GListStore* bg_source_get_liststore (BgSource *source);
GtkListStore* bg_source_get_liststore (BgSource *source);
gint bg_source_get_scale_factor (BgSource *source);
@@ -41,6 +41,6 @@ gint bg_source_get_thumbnail_height (BgSource *source);
gint bg_source_get_thumbnail_width (BgSource *source);
GnomeDesktopThumbnailFactory* bg_source_get_thumbnail_factory (BgSource *source);
G_END_DECLS
#endif /* _BG_SOURCE_H */

View File

@@ -25,11 +25,13 @@
#include "cc-background-xml.h"
#include <cairo-gobject.h>
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
#include <gio/gio.h>
struct _BgWallpapersSource
{
BgSource parent_instance;
GnomeDesktopThumbnailFactory *thumb_factory;
CcBackgroundXml *xml;
};
@@ -40,15 +42,38 @@ load_wallpapers (gchar *key,
CcBackgroundItem *item,
BgWallpapersSource *source)
{
GListStore *store = bg_source_get_liststore (BG_SOURCE (source));
GtkTreeIter iter;
g_autoptr(GdkPixbuf) pixbuf = NULL;
GtkListStore *store = bg_source_get_liststore (BG_SOURCE (source));
cairo_surface_t *surface;
gboolean deleted;
gint scale_factor;
gint thumbnail_height;
gint thumbnail_width;
g_object_get (G_OBJECT (item), "is-deleted", &deleted, NULL);
if (deleted)
return;
g_list_store_append (store, item);
gtk_list_store_append (store, &iter);
scale_factor = bg_source_get_scale_factor (BG_SOURCE (source));
thumbnail_height = bg_source_get_thumbnail_height (BG_SOURCE (source));
thumbnail_width = bg_source_get_thumbnail_width (BG_SOURCE (source));
pixbuf = cc_background_item_get_thumbnail (item, source->thumb_factory,
thumbnail_width, thumbnail_height,
scale_factor);
if (pixbuf == NULL)
return;
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
gtk_list_store_set (store, &iter,
0, surface,
1, item,
2, cc_background_item_get_name (item),
-1);
g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
}
static void
@@ -56,14 +81,13 @@ 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);
cc_background_xml_load_list_finish (res);
}
static void
item_added (BgWallpapersSource *self,
CcBackgroundItem *item)
item_added (CcBackgroundXml *xml,
CcBackgroundItem *item,
BgWallpapersSource *self)
{
load_wallpapers (NULL, item, self);
}
@@ -96,8 +120,8 @@ bg_wallpapers_source_constructed (GObject *object)
G_OBJECT_CLASS (bg_wallpapers_source_parent_class)->constructed (object);
g_signal_connect_object (G_OBJECT (self->xml), "added",
G_CALLBACK (item_added), self, G_CONNECT_SWAPPED);
g_signal_connect (G_OBJECT (self->xml), "added",
G_CALLBACK (item_added), self);
/* Try adding the default background first */
load_default_bg (self);
@@ -110,6 +134,7 @@ bg_wallpapers_source_dispose (GObject *object)
{
BgWallpapersSource *self = BG_WALLPAPERS_SOURCE (object);
g_clear_object (&self->thumb_factory);
g_clear_object (&self->xml);
G_OBJECT_CLASS (bg_wallpapers_source_parent_class)->dispose (object);
@@ -118,6 +143,8 @@ bg_wallpapers_source_dispose (GObject *object)
static void
bg_wallpapers_source_init (BgWallpapersSource *self)
{
self->thumb_factory =
gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
self->xml = cc_background_xml_new ();
}
@@ -131,8 +158,8 @@ bg_wallpapers_source_class_init (BgWallpapersSourceClass *klass)
}
BgWallpapersSource *
bg_wallpapers_source_new (GtkWidget *widget)
bg_wallpapers_source_new (GtkWindow *window)
{
return g_object_new (BG_TYPE_WALLPAPERS_SOURCE, "widget", widget, NULL);
return g_object_new (BG_TYPE_WALLPAPERS_SOURCE, "window", window, NULL);
}

View File

@@ -19,7 +19,9 @@
*
*/
#pragma once
#ifndef _BG_WALLPAPERS_SOURCE_H
#define _BG_WALLPAPERS_SOURCE_H
#include <gtk/gtk.h>
#include "bg-source.h"
@@ -29,6 +31,8 @@ G_BEGIN_DECLS
#define BG_TYPE_WALLPAPERS_SOURCE (bg_wallpapers_source_get_type ())
G_DECLARE_FINAL_TYPE (BgWallpapersSource, bg_wallpapers_source, BG, WALLPAPERS_SOURCE, BgSource)
BgWallpapersSource *bg_wallpapers_source_new (GtkWidget *widget);
BgWallpapersSource *bg_wallpapers_source_new (GtkWindow *window);
G_END_DECLS
#endif /* _BG_WALLPAPERS_SOURCE_H */

View File

@@ -0,0 +1,616 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include "cc-background-chooser-dialog.h"
#include "bg-wallpapers-source.h"
#include "bg-pictures-source.h"
#include "bg-colors-source.h"
#include "cc-background-item.h"
#include "cc-background-xml.h"
#define WP_PATH_ID "org.gnome.desktop.background"
#define WP_URI_KEY "picture-uri"
#define WP_OPTIONS_KEY "picture-options"
#define WP_SHADING_KEY "color-shading-type"
#define WP_PCOLOR_KEY "primary-color"
#define WP_SCOLOR_KEY "secondary-color"
enum
{
SOURCE_WALLPAPERS,
SOURCE_PICTURES,
SOURCE_COLORS,
};
struct _CcBackgroundChooserDialog
{
GtkDialog parent_instance;
GtkListStore *sources;
GtkWidget *stack;
GtkWidget *pictures_stack;
BgWallpapersSource *wallpapers_source;
BgPicturesSource *pictures_source;
BgColorsSource *colors_source;
GtkTreeRowReference *item_to_focus;
GnomeDesktopThumbnailFactory *thumb_factory;
GCancellable *copy_cancellable;
GtkWidget *spinner;
gulong row_inserted_id;
gulong row_deleted_id;
gulong row_modified_id;
};
G_DEFINE_TYPE (CcBackgroundChooserDialog, cc_background_chooser_dialog, GTK_TYPE_DIALOG)
enum
{
PROP_0,
};
enum
{
URI_LIST,
COLOR
};
static const GtkTargetEntry color_targets[] =
{
{ "application/x-color", 0, COLOR }
};
static void on_visible_child_notify (CcBackgroundChooserDialog *chooser);
static void
cc_background_chooser_dialog_realize (GtkWidget *widget)
{
CcBackgroundChooserDialog *chooser = CC_BACKGROUND_CHOOSER_DIALOG (widget);
GtkWindow *parent;
parent = gtk_window_get_transient_for (GTK_WINDOW (chooser));
if (parent == NULL)
{
gtk_window_set_default_size (GTK_WINDOW (chooser), -1, 550);
}
else
{
gint width;
gint height;
gtk_window_get_size (parent, &width, &height);
gtk_window_set_default_size (GTK_WINDOW (chooser), -1, (gint) (0.66 * height));
}
GTK_WIDGET_CLASS (cc_background_chooser_dialog_parent_class)->realize (widget);
}
static void
cc_background_chooser_dialog_dispose (GObject *object)
{
CcBackgroundChooserDialog *chooser = CC_BACKGROUND_CHOOSER_DIALOG (object);
if (chooser->copy_cancellable)
{
/* cancel any copy operation */
g_cancellable_cancel (chooser->copy_cancellable);
g_clear_object (&chooser->copy_cancellable);
}
/* GtkStack triggers notify::visible-child during dispose and this
* means that we have to explicitly disconnect the signal handler
* before calling up to the parent implementation, or
* on_visible_child_notify() will get called while we're in an
* inconsistent state.
*/
if (chooser->stack != NULL)
{
g_signal_handlers_disconnect_by_func (chooser->stack, on_visible_child_notify, chooser);
chooser->stack = NULL;
}
g_clear_pointer (&chooser->item_to_focus, gtk_tree_row_reference_free);
g_clear_object (&chooser->pictures_source);
g_clear_object (&chooser->colors_source);
g_clear_object (&chooser->wallpapers_source);
g_clear_object (&chooser->thumb_factory);
G_OBJECT_CLASS (cc_background_chooser_dialog_parent_class)->dispose (object);
}
static GtkWidget *
get_visible_view (CcBackgroundChooserDialog *chooser)
{
GtkWidget *visible;
GtkWidget *icon_view = NULL;
visible = gtk_stack_get_visible_child (GTK_STACK (chooser->stack));
if (GTK_IS_STACK (visible))
{
GtkWidget *sw;
sw = gtk_stack_get_child_by_name (GTK_STACK (visible), "view");
icon_view = gtk_bin_get_child (GTK_BIN (sw));
}
else if (GTK_IS_SCROLLED_WINDOW (visible))
{
icon_view = gtk_bin_get_child (GTK_BIN (visible));
}
else
{
g_assert_not_reached ();
}
return icon_view;
}
static void
possibly_show_empty_pictures_box (GtkTreeModel *model,
CcBackgroundChooserDialog *chooser)
{
GtkTreeIter iter;
if (gtk_tree_model_get_iter_first (model, &iter))
{
gtk_stack_set_visible_child_name (GTK_STACK (chooser->pictures_stack), "view");
}
else
{
gtk_stack_set_visible_child_name (GTK_STACK (chooser->pictures_stack), "empty");
}
}
static void
on_source_modified_cb (GtkTreeModel *tree_model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer user_data)
{
CcBackgroundChooserDialog *chooser = user_data;
GtkTreePath *to_focus_path;
GtkWidget *icon_view;
if (chooser->item_to_focus == NULL)
return;
to_focus_path = gtk_tree_row_reference_get_path (chooser->item_to_focus);
if (gtk_tree_path_compare (to_focus_path, path) != 0)
goto out;
/* Change source */
gtk_stack_set_visible_child_name (GTK_STACK (chooser->stack), "pictures");
/* And select the newly added item */
icon_view = get_visible_view (chooser);
gtk_icon_view_select_path (GTK_ICON_VIEW (icon_view), to_focus_path);
gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (icon_view),
to_focus_path, TRUE, 1.0, 1.0);
g_clear_pointer (&chooser->item_to_focus, gtk_tree_row_reference_free);
out:
gtk_tree_path_free (to_focus_path);
}
static void
on_source_added_cb (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer user_data)
{
possibly_show_empty_pictures_box (model, CC_BACKGROUND_CHOOSER_DIALOG (user_data));
}
static void
on_source_removed_cb (GtkTreeModel *model,
GtkTreePath *path,
gpointer user_data)
{
possibly_show_empty_pictures_box (model, CC_BACKGROUND_CHOOSER_DIALOG (user_data));
}
static void
monitor_pictures_model (CcBackgroundChooserDialog *chooser)
{
GtkTreeModel *model;
model = GTK_TREE_MODEL (bg_source_get_liststore (BG_SOURCE (chooser->pictures_source)));
g_signal_connect (model, "row-inserted", G_CALLBACK (on_source_added_cb), chooser);
g_signal_connect (model, "row-deleted", G_CALLBACK (on_source_removed_cb), chooser);
g_signal_connect (model, "row-changed", G_CALLBACK (on_source_modified_cb), chooser);
possibly_show_empty_pictures_box (model, chooser);
}
static void
on_visible_child_notify (CcBackgroundChooserDialog *chooser)
{
GtkWidget *icon_view;
icon_view = get_visible_view (chooser);
gtk_icon_view_unselect_all (GTK_ICON_VIEW (icon_view));
gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), GTK_RESPONSE_OK, FALSE);
}
static void
on_selection_changed (GtkIconView *icon_view,
CcBackgroundChooserDialog *chooser)
{
GList *list;
list = gtk_icon_view_get_selected_items (icon_view);
gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser),
GTK_RESPONSE_OK,
(list != NULL));
g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
}
static void
on_item_activated (GtkIconView *icon_view,
GtkTreePath *path,
CcBackgroundChooserDialog *chooser)
{
gtk_dialog_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
}
static void
add_custom_wallpaper (CcBackgroundChooserDialog *chooser,
const char *uri)
{
g_clear_pointer (&chooser->item_to_focus, gtk_tree_row_reference_free);
bg_pictures_source_add (chooser->pictures_source, uri, &chooser->item_to_focus);
/* and wait for the item to get added */
}
static gboolean
cc_background_panel_drag_color (CcBackgroundChooserDialog *chooser,
GtkSelectionData *data)
{
gint length;
guint16 *dropped;
GdkRGBA rgba;
GtkTreeRowReference *row_ref;
GtkTreePath *to_focus_path;
GtkWidget *icon_view;
length = gtk_selection_data_get_length (data);
if (length < 0)
return FALSE;
if (length != 8)
{
g_warning ("%s: Received invalid color data", G_STRFUNC);
return FALSE;
}
dropped = (guint16 *) gtk_selection_data_get_data (data);
rgba.red = dropped[0] / 65535.;
rgba.green = dropped[1] / 65535.;
rgba.blue = dropped[2] / 65535.;
rgba.alpha = dropped[3] / 65535.;
if (bg_colors_source_add (chooser->colors_source, &rgba, &row_ref) == FALSE)
return FALSE;
/* Change source */
gtk_stack_set_visible_child_name (GTK_STACK (chooser->stack), "colors");
/* And select the newly added item */
to_focus_path = gtk_tree_row_reference_get_path (row_ref);
icon_view = get_visible_view (chooser);
gtk_icon_view_select_path (GTK_ICON_VIEW (icon_view), to_focus_path);
gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (icon_view),
to_focus_path, TRUE, 1.0, 1.0);
gtk_tree_row_reference_free (row_ref);
gtk_tree_path_free (to_focus_path);
return TRUE;
}
static void
cc_background_panel_drag_items (GtkWidget *widget,
GdkDragContext *context, gint x, gint y,
GtkSelectionData *data, guint info, guint time,
CcBackgroundChooserDialog *chooser)
{
gint i;
char *uri;
g_auto(GStrv) uris = NULL;
gboolean ret = FALSE;
if (info == COLOR)
{
ret = cc_background_panel_drag_color (chooser, data);
goto out;
}
uris = gtk_selection_data_get_uris (data);
if (!uris)
goto out;
for (i = 0; uris[i] != NULL; i++)
{
uri = uris[i];
if (!bg_pictures_source_is_known (chooser->pictures_source, uri))
{
add_custom_wallpaper (chooser, uri);
ret = TRUE;
}
}
out:
gtk_drag_finish (context, ret, FALSE, time);
}
static GtkWidget *
create_view (CcBackgroundChooserDialog *chooser, GtkTreeModel *model)
{
GtkCellRenderer *renderer;
GtkWidget *icon_view;
GtkWidget *sw;
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_widget_set_hexpand (sw, TRUE);
gtk_widget_set_vexpand (sw, TRUE);
icon_view = gtk_icon_view_new ();
gtk_icon_view_set_model (GTK_ICON_VIEW (icon_view), model);
gtk_widget_set_hexpand (icon_view, TRUE);
gtk_container_add (GTK_CONTAINER (sw), icon_view);
g_signal_connect (icon_view, "selection-changed", G_CALLBACK (on_selection_changed), chooser);
g_signal_connect (icon_view, "item-activated", G_CALLBACK (on_item_activated), chooser);
gtk_icon_view_set_columns (GTK_ICON_VIEW (icon_view), 3);
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (icon_view),
renderer,
FALSE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (icon_view),
renderer,
"surface", 0,
NULL);
return sw;
}
static void
cc_background_chooser_dialog_constructed (GObject *object)
{
CcBackgroundChooserDialog *chooser = CC_BACKGROUND_CHOOSER_DIALOG (object);
GtkListStore *model;
GtkWidget *sw;
GtkWidget *vbox;
G_OBJECT_CLASS (cc_background_chooser_dialog_parent_class)->constructed (object);
model = bg_source_get_liststore (BG_SOURCE (chooser->wallpapers_source));
sw = create_view (chooser, GTK_TREE_MODEL (model));
gtk_stack_add_titled (GTK_STACK (chooser->stack), sw, "wallpapers", _("Wallpapers"));
gtk_container_child_set (GTK_CONTAINER (chooser->stack), sw, "position", 0, NULL);
model = bg_source_get_liststore (BG_SOURCE (chooser->pictures_source));
sw = create_view (chooser, GTK_TREE_MODEL (model));
gtk_stack_add_named (GTK_STACK (chooser->pictures_stack), sw, "view");
model = bg_source_get_liststore (BG_SOURCE (chooser->colors_source));
sw = create_view (chooser, GTK_TREE_MODEL (model));
gtk_stack_add_titled (GTK_STACK (chooser->stack), sw, "colors", _("Colors"));
vbox = gtk_dialog_get_content_area (GTK_DIALOG (chooser));
gtk_widget_show_all (vbox);
gtk_stack_set_visible_child_name (GTK_STACK (chooser->stack), "wallpapers");
monitor_pictures_model (chooser);
}
static void
cc_background_chooser_dialog_init (CcBackgroundChooserDialog *chooser)
{
GtkWidget *empty_pictures_box;
GtkWidget *vbox;
GtkWidget *headerbar;
GtkWidget *img;
GtkWidget *labels_grid;
GtkWidget *label;
GtkWidget *switcher;
GtkStyleContext *context;
g_autofree gchar *markup = NULL;
g_autofree gchar *markup2 = NULL;
g_autofree gchar *href = NULL;
const gchar *pictures_dir;
g_autofree gchar *pictures_dir_basename = NULL;
g_autofree gchar *pictures_dir_uri = NULL;
GtkTargetList *target_list;
chooser->wallpapers_source = bg_wallpapers_source_new (GTK_WINDOW (chooser));
chooser->pictures_source = bg_pictures_source_new (GTK_WINDOW (chooser));
chooser->colors_source = bg_colors_source_new (GTK_WINDOW (chooser));
gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
gtk_window_set_resizable (GTK_WINDOW (chooser), FALSE);
/* translators: This is the title of the wallpaper chooser dialog. */
gtk_window_set_title (GTK_WINDOW (chooser), _("Select Background"));
vbox = gtk_dialog_get_content_area (GTK_DIALOG (chooser));
gtk_container_set_border_width (GTK_CONTAINER (vbox), 0);
chooser->stack = gtk_stack_new ();
gtk_stack_set_homogeneous (GTK_STACK (chooser->stack), TRUE);
gtk_container_add (GTK_CONTAINER (vbox), chooser->stack);
g_signal_connect_swapped (chooser->stack, "notify::visible-child", G_CALLBACK (on_visible_child_notify), chooser);
/* Add drag and drop support for bg images */
gtk_drag_dest_set (chooser->stack, GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY);
target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_uri_targets (target_list, URI_LIST);
gtk_target_list_add_table (target_list, color_targets, 1);
gtk_drag_dest_set_target_list (chooser->stack, target_list);
gtk_target_list_unref (target_list);
g_signal_connect (chooser->stack, "drag-data-received", G_CALLBACK (cc_background_panel_drag_items), chooser);
headerbar = gtk_dialog_get_header_bar (GTK_DIALOG (chooser));
switcher = gtk_stack_switcher_new ();
gtk_stack_switcher_set_stack (GTK_STACK_SWITCHER (switcher), GTK_STACK (chooser->stack));
gtk_header_bar_set_custom_title (GTK_HEADER_BAR (headerbar), switcher);
gtk_widget_show (switcher);
chooser->pictures_stack = gtk_stack_new ();
gtk_stack_set_homogeneous (GTK_STACK (chooser->pictures_stack), TRUE);
gtk_stack_add_titled (GTK_STACK (chooser->stack), chooser->pictures_stack, "pictures", _("Pictures"));
empty_pictures_box = gtk_grid_new ();
gtk_grid_set_column_spacing (GTK_GRID (empty_pictures_box), 12);
gtk_orientable_set_orientation (GTK_ORIENTABLE (empty_pictures_box),
GTK_ORIENTATION_HORIZONTAL);
context = gtk_widget_get_style_context (empty_pictures_box);
gtk_style_context_add_class (context, "dim-label");
gtk_stack_add_named (GTK_STACK (chooser->pictures_stack), empty_pictures_box, "empty");
img = gtk_image_new_from_icon_name ("emblem-photos-symbolic", GTK_ICON_SIZE_DIALOG);
gtk_image_set_pixel_size (GTK_IMAGE (img), 64);
gtk_widget_set_halign (img, GTK_ALIGN_END);
gtk_widget_set_valign (img, GTK_ALIGN_CENTER);
gtk_widget_set_hexpand (img, TRUE);
gtk_widget_set_vexpand (img, TRUE);
gtk_widget_show (img);
gtk_container_add (GTK_CONTAINER (empty_pictures_box), img);
labels_grid = gtk_grid_new ();
gtk_widget_set_halign (labels_grid, GTK_ALIGN_START);
gtk_widget_set_valign (labels_grid, GTK_ALIGN_CENTER);
gtk_widget_set_hexpand (labels_grid, TRUE);
gtk_widget_set_vexpand (labels_grid, TRUE);
gtk_grid_set_row_spacing (GTK_GRID (labels_grid), 6);
gtk_orientable_set_orientation (GTK_ORIENTABLE (labels_grid),
GTK_ORIENTATION_VERTICAL);
gtk_widget_show (labels_grid);
gtk_container_add (GTK_CONTAINER (empty_pictures_box), labels_grid);
label = gtk_label_new ("");
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
gtk_widget_set_halign (label, GTK_ALIGN_START);
markup = g_markup_printf_escaped ("<b><span size='large'>%s</span></b>",
/* translators: No pictures were found */
_("No Pictures Found"));
gtk_label_set_markup (GTK_LABEL (label), markup);
gtk_widget_show (label);
gtk_container_add (GTK_CONTAINER (labels_grid), label);
label = gtk_label_new ("");
gtk_label_set_max_width_chars (GTK_LABEL (label), 24);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
gtk_widget_set_halign (label, GTK_ALIGN_START);
pictures_dir = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
if (pictures_dir == NULL)
{
pictures_dir = g_get_home_dir ();
/* translators: "Home" is used in place of the Pictures
* directory in the string below when XDG_PICTURES_DIR is
* undefined */
pictures_dir_basename = g_strdup (_("Home"));
}
else
pictures_dir_basename = g_path_get_basename (pictures_dir);
pictures_dir_uri = g_filename_to_uri (pictures_dir, NULL, NULL);
href = g_markup_printf_escaped ("<a href=\"%s\">%s</a>", pictures_dir_uri, pictures_dir_basename);
/* translators: %s here is the name of the Pictures directory, the string should be translated in
* the context "You can add images to your Pictures folder and they will show up here" */
markup2 = g_strdup_printf (_("You can add images to your %s folder and they will show up here"), href);
gtk_label_set_markup (GTK_LABEL (label), markup2);
gtk_widget_show (label);
gtk_container_add (GTK_CONTAINER (labels_grid), label);
gtk_dialog_add_button (GTK_DIALOG (chooser), _("_Cancel"), GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (chooser), _("_Select"), GTK_RESPONSE_OK);
gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), GTK_RESPONSE_OK, FALSE);
}
static void
cc_background_chooser_dialog_class_init (CcBackgroundChooserDialogClass *klass)
{
GObjectClass *object_class;
GtkWidgetClass *widget_class;
object_class = G_OBJECT_CLASS (klass);
object_class->constructed = cc_background_chooser_dialog_constructed;
object_class->dispose = cc_background_chooser_dialog_dispose;
widget_class = GTK_WIDGET_CLASS (klass);
widget_class->realize = cc_background_chooser_dialog_realize;
}
GtkWidget *
cc_background_chooser_dialog_new (GtkWindow *transient_for)
{
return g_object_new (CC_TYPE_BACKGROUND_CHOOSER_DIALOG,
"transient-for", transient_for,
"use-header-bar", TRUE,
NULL);
}
CcBackgroundItem *
cc_background_chooser_dialog_get_item (CcBackgroundChooserDialog *chooser)
{
GtkTreeIter iter;
GtkTreeModel *model;
GtkWidget *icon_view;
GList *list;
CcBackgroundItem *item;
item = NULL;
icon_view = get_visible_view (chooser);
list = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (icon_view));
if (!list)
return NULL;
model = gtk_icon_view_get_model (GTK_ICON_VIEW (icon_view));
if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) list->data) == FALSE)
goto bail;
gtk_tree_model_get (model, &iter, 1, &item, -1);
bail:
g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
return item;
}

View File

@@ -0,0 +1,38 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __CC_PANEL_CHOOSER_DIALOG_H__
#define __CC_PANEL_CHOOSER_DIALOG_H__
#include <gtk/gtk.h>
#include "cc-background-item.h"
G_BEGIN_DECLS
#define CC_TYPE_BACKGROUND_CHOOSER_DIALOG (cc_background_chooser_dialog_get_type ())
G_DECLARE_FINAL_TYPE (CcBackgroundChooserDialog, cc_background_chooser_dialog, CC, BACKGROUND_CHOOSER_DIALOG, GtkDialog)
GtkWidget * cc_background_chooser_dialog_new (GtkWindow *transient_for);
CcBackgroundItem * cc_background_chooser_dialog_get_item (CcBackgroundChooserDialog *chooser);
G_END_DECLS
#endif /* __CC_BACKGROUND_CHOOSER_DIALOG_H__ */

View File

@@ -1,385 +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-pictures-source.h"
#include "bg-recent-source.h"
#include "bg-wallpapers-source.h"
#include "cc-background-chooser.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 GtkWidget*
create_widget_func (gpointer model_item,
gpointer user_data)
{
g_autoptr(GdkPixbuf) pixbuf = NULL;
CcBackgroundItem *item;
GtkWidget *overlay;
GtkWidget *child;
GtkWidget *image;
GtkWidget *icon;
GtkWidget *button = NULL;
BgSource *source;
source = BG_SOURCE (user_data);
item = CC_BACKGROUND_ITEM (model_item);
pixbuf = cc_background_item_get_thumbnail (item,
bg_source_get_thumbnail_factory (source),
bg_source_get_thumbnail_width (source),
bg_source_get_thumbnail_height (source),
bg_source_get_scale_factor (source));
image = gtk_image_new_from_gicon (G_ICON (pixbuf), GTK_ICON_SIZE_DIALOG);
gtk_widget_show (image);
icon = gtk_image_new_from_icon_name("slideshow-emblem", GTK_ICON_SIZE_BUTTON);
gtk_image_set_pixel_size (GTK_IMAGE (icon), 16);
gtk_widget_set_margin_start (icon, 8);
gtk_widget_set_margin_end (icon, 8);
gtk_widget_set_margin_top (icon, 8);
gtk_widget_set_margin_bottom (icon, 8);
gtk_widget_set_halign (icon, GTK_ALIGN_END);
gtk_widget_set_valign (icon, GTK_ALIGN_END);
gtk_widget_set_visible (icon, cc_background_item_changes_with_time (item));
gtk_style_context_add_class (gtk_widget_get_style_context (icon), "slideshow-emblem");
if (BG_IS_RECENT_SOURCE (source))
{
button = gtk_button_new_from_icon_name ("window-close-symbolic", GTK_ICON_SIZE_BUTTON);
gtk_widget_set_halign (button, GTK_ALIGN_END);
gtk_widget_set_valign (button, GTK_ALIGN_START);
gtk_widget_set_margin_start (icon, 6);
gtk_widget_set_margin_end (icon, 6);
gtk_widget_set_margin_top (icon, 6);
gtk_widget_set_margin_bottom (icon, 6);
gtk_widget_show (button);
gtk_style_context_add_class (gtk_widget_get_style_context (button), "osd");
gtk_style_context_add_class (gtk_widget_get_style_context (button), "remove-button");
g_signal_connect (button,
"clicked",
G_CALLBACK (on_delete_background_clicked_cb),
source);
}
overlay = gtk_overlay_new ();
gtk_container_add (GTK_CONTAINER (overlay), image);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), icon);
if (button)
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), button);
gtk_widget_show (overlay);
child = gtk_flow_box_child_new();
gtk_widget_set_halign (child, GTK_ALIGN_CENTER);
gtk_widget_set_valign (child, GTK_ALIGN_CENTER);
gtk_container_add (GTK_CONTAINER (child), overlay);
gtk_widget_show (child);
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 (GtkFlowBox *flowbox,
GtkFlowBoxChild *child,
CcBackgroundChooser *self)
{
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
on_file_chooser_response_cb (GtkDialog *filechooser,
gint response,
CcBackgroundChooser *self)
{
if (response == GTK_RESPONSE_ACCEPT)
{
g_autoptr(GSList) filenames = NULL;
GSList *l;
filenames = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (filechooser));
for (l = filenames; l != NULL; l = l->next)
{
g_autofree gchar *filename = l->data;
bg_recent_source_add_file (self->recent_source, filename);
}
}
gtk_widget_destroy (GTK_WIDGET (filechooser));
}
static void
on_file_chooser_selection_changed_cb (GtkFileChooser *chooser,
GnomeDesktopThumbnailFactory *thumbnail_factory)
{
g_autofree gchar *uri = NULL;
uri = gtk_file_chooser_get_uri (chooser);
if (uri)
{
g_autoptr(GFileInfo) file_info = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
g_autofree gchar *mime_type = NULL;
g_autoptr(GFile) file = NULL;
GtkWidget *preview;
preview = gtk_file_chooser_get_preview_widget (chooser);
file = g_file_new_for_uri (uri);
file_info = g_file_query_info (file,
"standard::*",
G_FILE_QUERY_INFO_NONE,
NULL,
NULL);
if (file_info && g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
mime_type = g_strdup (g_file_info_get_content_type (file_info));
if (mime_type)
{
pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumbnail_factory,
uri,
mime_type);
}
gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser),
GTK_RESPONSE_ACCEPT,
pixbuf != NULL);
if (pixbuf)
gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf);
else
gtk_image_set_from_icon_name (GTK_IMAGE (preview), "dialog-question", GTK_ICON_SIZE_DIALOG);
}
gtk_file_chooser_set_preview_widget_active (chooser, TRUE);
}
/* 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(GnomeDesktopThumbnailFactory) factory = NULL;
GtkFileFilter *filter;
GtkWidget *filechooser;
GtkWindow *toplevel;
GtkWidget *preview;
g_return_if_fail (CC_IS_BACKGROUND_CHOOSER (self));
toplevel = (GtkWindow*) gtk_widget_get_toplevel (GTK_WIDGET (self));
filechooser = gtk_file_chooser_dialog_new (_("Select a picture"),
toplevel,
GTK_FILE_CHOOSER_ACTION_OPEN,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Open"), GTK_RESPONSE_ACCEPT,
NULL);
gtk_window_set_modal (GTK_WINDOW (filechooser), TRUE);
preview = gtk_image_new ();
gtk_widget_set_size_request (preview, 154, -1);
gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (filechooser), preview);
gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (filechooser), FALSE);
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (filechooser), TRUE);
gtk_widget_show (preview);
factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
g_signal_connect_after (filechooser,
"selection-changed",
G_CALLBACK (on_file_chooser_selection_changed_cb),
factory);
g_object_set_data_full (G_OBJECT (filechooser),
"factory",
g_object_ref (factory),
g_object_unref);
filter = gtk_file_filter_new ();
gtk_file_filter_add_pixbuf_formats (filter);
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (filechooser), filter);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (filechooser),
g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
g_signal_connect_object (filechooser,
"response",
G_CALLBACK (on_file_chooser_response_cb),
self,
0);
gtk_window_present (GTK_WINDOW (filechooser));
}

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,90 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcBackgroundChooser" parent="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="expand">True</property>
<property name="shadow-type">none</property>
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="expand">True</property>
<style>
<class name="view" />
</style>
<!-- Recent -->
<child>
<object class="GtkBox" id="recent_box">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="orientation">vertical</property>
<property name="halign">center</property>
<child>
<object class="GtkFlowBox" id="recent_flowbox">
<property name="visible">True</property>
<property name="margin">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="no" />
</object>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkFlowBox" id="flowbox">
<property name="visible">True</property>
<property name="margin">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="no" />
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -15,7 +15,9 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef _CC_BACKGROUND_GRILO_MINER_H
#define _CC_BACKGROUND_GRILO_MINER_H
#include <glib-object.h>
@@ -29,3 +31,5 @@ CcBackgroundGriloMiner *cc_background_grilo_miner_new (void);
void cc_background_grilo_miner_start (CcBackgroundGriloMiner *self);
G_END_DECLS
#endif /* _CC_BACKGROUND_GRILO_MINER_H */

View File

@@ -52,18 +52,11 @@ struct _CcBackgroundItem
guint64 modified;
/* internal */
GdkPixbuf *slideshow_emblem;
GnomeBG *bg;
char *mime_type;
int width;
int height;
struct {
int width;
int height;
int frame;
int scale_factor;
GdkPixbuf *thumbnail;
} cached_thumbnail;
};
enum {
@@ -87,11 +80,70 @@ static void cc_background_item_finalize (GObject *object
G_DEFINE_TYPE (CcBackgroundItem, cc_background_item, G_TYPE_OBJECT)
static GdkPixbuf *slideshow_emblem = NULL;
static GdkPixbuf *
get_emblemed_pixbuf (CcBackgroundItem *item, GdkPixbuf *pixbuf, gint scale_factor)
{
int eh;
int ew;
int h;
int w;
int x;
int y;
if (item->slideshow_emblem == NULL) {
if (slideshow_emblem == NULL) {
g_autoptr(GIcon) icon = NULL;
GtkIconTheme *theme;
g_autoptr(GtkIconInfo) icon_info = NULL;
g_autoptr(GError) error = NULL;
icon = g_themed_icon_new ("slideshow-emblem");
theme = gtk_icon_theme_get_default ();
icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (theme,
icon,
16,
scale_factor,
GTK_ICON_LOOKUP_FORCE_SIZE |
GTK_ICON_LOOKUP_USE_BUILTIN);
if (icon_info == NULL) {
g_warning ("Your icon theme is missing the slideshow-emblem icon, "
"please file a bug against it");
return g_object_ref (pixbuf);
}
slideshow_emblem = gtk_icon_info_load_icon (icon_info, &error);
if (slideshow_emblem == NULL) {
g_warning ("Failed to load slideshow emblem: %s", error->message);
return g_object_ref (pixbuf);
}
g_object_add_weak_pointer (G_OBJECT (slideshow_emblem), (gpointer *) (&slideshow_emblem));
item->slideshow_emblem = slideshow_emblem;
} else {
item->slideshow_emblem = g_object_ref (slideshow_emblem);
}
}
eh = gdk_pixbuf_get_height (slideshow_emblem);
ew = gdk_pixbuf_get_width (slideshow_emblem);
h = gdk_pixbuf_get_height (pixbuf);
w = gdk_pixbuf_get_width (pixbuf);
x = w - ew;
y = h - eh;
gdk_pixbuf_composite (slideshow_emblem, pixbuf, x, y, ew, eh, x, y, 1.0, 1.0, GDK_INTERP_BILINEAR, 255);
return g_object_ref (pixbuf);
}
static void
set_bg_properties (CcBackgroundItem *item)
{
GdkRGBA pcolor = { 0, 0, 0, 0 };
GdkRGBA scolor = { 0, 0, 0, 0 };
GdkColor p, s;
if (item->uri) {
g_autoptr(GFile) file = NULL;
@@ -156,11 +208,7 @@ render_at_size (GnomeBG *bg,
GdkPixbuf *pixbuf;
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
#ifdef GNOME_DESKTOP_BG_API_BREAK
gnome_bg_draw (bg, pixbuf);
#else
gnome_bg_draw (bg, pixbuf, gdk_screen_get_default (), FALSE);
#endif
return pixbuf;
}
@@ -180,14 +228,6 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
g_return_val_if_fail (width > 0 && height > 0, NULL);
/* Use the cached thumbnail if the sizes match */
if (item->cached_thumbnail.thumbnail &&
item->cached_thumbnail.width == width &&
item->cached_thumbnail.height == height &&
item->cached_thumbnail.scale_factor == scale_factor &&
item->cached_thumbnail.frame == frame)
return g_object_ref (item->cached_thumbnail.thumbnail);
set_bg_properties (item);
if (force_size) {
@@ -216,7 +256,13 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
}
}
retval = g_steal_pointer (&pixbuf);
if (pixbuf != NULL
&& frame != -2
&& gnome_bg_changes_with_time (item->bg)) {
retval = get_emblemed_pixbuf (item, pixbuf, scale_factor);
} else {
retval = g_steal_pointer (&pixbuf);
}
gnome_bg_get_image_size (item->bg,
thumbs,
@@ -227,13 +273,6 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
update_size (item);
/* Cache the new thumbnail */
g_set_object (&item->cached_thumbnail.thumbnail, retval);
item->cached_thumbnail.width = width;
item->cached_thumbnail.height = height;
item->cached_thumbnail.scale_factor = scale_factor;
item->cached_thumbnail.frame = frame;
return g_steal_pointer (&retval);
}
@@ -782,7 +821,6 @@ cc_background_item_finalize (GObject *object)
g_return_if_fail (item != NULL);
g_clear_object (&item->cached_thumbnail.thumbnail);
g_free (item->name);
g_free (item->uri);
g_free (item->primary_color);
@@ -795,6 +833,8 @@ cc_background_item_finalize (GObject *object)
if (item->bg != NULL)
g_object_unref (item->bg);
g_clear_object (&item->slideshow_emblem);
G_OBJECT_CLASS (cc_background_item_parent_class)->finalize (object);
}

View File

@@ -17,7 +17,8 @@
*
*/
#pragma once
#ifndef __CC_BACKGROUND_ITEM_H
#define __CC_BACKGROUND_ITEM_H
#include <glib-object.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -81,3 +82,5 @@ gboolean cc_background_item_compare (CcBackgroundItem *s
void cc_background_item_dump (CcBackgroundItem *item);
G_END_DECLS
#endif /* __CC_BACKGROUND_ITEM_H */

View File

@@ -29,9 +29,8 @@
#include "cc-background-panel.h"
#include "cc-background-chooser.h"
#include "cc-background-chooser-dialog.h"
#include "cc-background-item.h"
#include "cc-background-preview.h"
#include "cc-background-resources.h"
#include "cc-background-xml.h"
@@ -49,6 +48,7 @@ struct _CcBackgroundPanel
{
CcPanel parent_instance;
GtkBuilder *builder;
GDBusConnection *connection;
GSettings *settings;
@@ -57,53 +57,232 @@ struct _CcBackgroundPanel
GnomeDesktopThumbnailFactory *thumb_factory;
CcBackgroundItem *current_background;
CcBackgroundItem *current_lock_background;
CcBackgroundChooser *background_chooser;
GtkButton *add_picture_button;
CcBackgroundPreview *desktop_preview;
GCancellable *copy_cancellable;
GtkWidget *spinner;
GtkWidget *chooser;
};
CC_PANEL_REGISTER (CcBackgroundPanel, cc_background_panel)
static void
update_preview (CcBackgroundPanel *panel)
#define WID(y) (GtkWidget *) gtk_builder_get_object (panel->builder, y)
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 *panel = CC_BACKGROUND_PANEL (object);
g_clear_object (&panel->builder);
/* destroying the builder object will also destroy the spinner */
panel->spinner = NULL;
g_clear_object (&panel->settings);
g_clear_object (&panel->lock_settings);
if (panel->copy_cancellable)
{
/* cancel any copy operation */
g_cancellable_cancel (panel->copy_cancellable);
g_clear_object (&panel->copy_cancellable);
}
if (panel->chooser)
{
gtk_widget_destroy (panel->chooser);
panel->chooser = NULL;
}
g_clear_object (&panel->thumb_factory);
G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object);
}
static void
cc_background_panel_finalize (GObject *object)
{
CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object);
g_clear_object (&panel->current_background);
g_clear_object (&panel->current_lock_background);
G_OBJECT_CLASS (cc_background_panel_parent_class)->finalize (object);
}
static void
cc_background_panel_class_init (CcBackgroundPanelClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
panel_class->get_help_uri = cc_background_panel_get_help_uri;
object_class->dispose = cc_background_panel_dispose;
object_class->finalize = cc_background_panel_finalize;
}
static CcBackgroundItem *
get_current_background (CcBackgroundPanel *panel, GSettings *settings)
{
if (settings == panel->settings)
return panel->current_background;
else
return panel->current_lock_background;
}
static void
update_preview (CcBackgroundPanel *panel,
GSettings *settings,
CcBackgroundItem *item)
{
gboolean changes_with_time;
CcBackgroundItem *current_background;
current_background = panel->current_background;
cc_background_preview_set_item (panel->desktop_preview, current_background);
current_background = get_current_background (panel, settings);
if (item && current_background)
{
g_object_unref (current_background);
current_background = cc_background_item_copy (item);
if (settings == panel->settings)
panel->current_background = current_background;
else
panel->current_lock_background = current_background;
cc_background_item_load (current_background, NULL);
}
changes_with_time = FALSE;
if (current_background)
{
changes_with_time = cc_background_item_changes_with_time (current_background);
}
if (settings == panel->settings)
{
gtk_widget_set_visible (WID ("slide_image"), changes_with_time);
gtk_widget_set_visible (WID ("slide-label"), changes_with_time);
gtk_widget_queue_draw (WID ("background-desktop-drawingarea"));
}
else
{
gtk_widget_set_visible (WID ("slide_image1"), changes_with_time);
gtk_widget_set_visible (WID ("slide-label1"), changes_with_time);
gtk_widget_queue_draw (WID ("background-lock-drawingarea"));
}
}
static gchar *
get_save_path (void)
get_save_path (CcBackgroundPanel *panel, GSettings *settings)
{
return g_build_filename (g_get_user_config_dir (),
"gnome-control-center",
"backgrounds",
"last-edited.xml",
settings == panel->settings ? "last-edited.xml" : "last-edited-lock.xml",
NULL);
}
static GdkPixbuf*
get_or_create_cached_pixbuf (CcBackgroundPanel *panel,
GtkWidget *widget,
CcBackgroundItem *background)
{
GtkAllocation allocation;
const gint preview_width = 309;
const gint preview_height = 168;
gint scale_factor;
GdkPixbuf *pixbuf;
pixbuf = g_object_get_data (G_OBJECT (background), "pixbuf");
if (pixbuf == NULL)
{
gtk_widget_get_allocation (widget, &allocation);
scale_factor = gtk_widget_get_scale_factor (widget);
pixbuf = cc_background_item_get_frame_thumbnail (background,
panel->thumb_factory,
preview_width,
preview_height,
scale_factor,
-2, TRUE);
g_object_set_data_full (G_OBJECT (background), "pixbuf", pixbuf, g_object_unref);
}
return pixbuf;
}
static void
reload_current_bg (CcBackgroundPanel *panel)
update_display_preview (CcBackgroundPanel *panel,
GtkWidget *widget,
CcBackgroundItem *background)
{
GdkPixbuf *pixbuf;
cairo_t *cr;
pixbuf = get_or_create_cached_pixbuf (panel, widget, background);
cr = gdk_cairo_create (gtk_widget_get_window (widget));
gdk_cairo_set_source_pixbuf (cr,
pixbuf,
0, 0);
cairo_paint (cr);
cairo_destroy (cr);
}
static gboolean
on_preview_draw (GtkWidget *widget,
cairo_t *cr,
CcBackgroundPanel *panel)
{
update_display_preview (panel, widget, panel->current_background);
return TRUE;
}
static gboolean
on_lock_preview_draw (GtkWidget *widget,
cairo_t *cr,
CcBackgroundPanel *panel)
{
update_display_preview (panel, widget, panel->current_lock_background);
return TRUE;
}
static void
reload_current_bg (CcBackgroundPanel *panel,
GSettings *settings)
{
g_autoptr(CcBackgroundItem) saved = NULL;
CcBackgroundItem *configured;
GSettings *settings = NULL;
g_autofree gchar *uri = NULL;
g_autofree gchar *pcolor = NULL;
g_autofree gchar *scolor = NULL;
/* Load the saved configuration */
uri = get_save_path ();
uri = get_save_path (panel, settings);
saved = cc_background_xml_get_item (uri);
/* initalise the current background information from settings */
settings = panel->settings;
uri = g_settings_get_string (settings, WP_URI_KEY);
if (uri && *uri == '\0')
g_clear_pointer (&uri, g_free);
{
g_clear_pointer (&uri, g_free);
}
else
{
g_autoptr(GFile) file = NULL;
file = g_file_new_for_commandline_arg (uri);
}
configured = cc_background_item_new (uri);
pcolor = g_settings_get_string (settings, WP_PCOLOR_KEY);
@@ -131,8 +310,16 @@ reload_current_bg (CcBackgroundPanel *panel)
NULL);
}
g_clear_object (&panel->current_background);
panel->current_background = configured;
if (settings == panel->settings)
{
g_clear_object (&panel->current_background);
panel->current_background = configured;
}
else
{
g_clear_object (&panel->current_lock_background);
panel->current_lock_background = configured;
}
cc_background_item_load (configured, NULL);
}
@@ -153,15 +340,65 @@ create_save_dir (void)
return TRUE;
}
static void
copy_finished_cb (GObject *source_object,
GAsyncResult *result,
gpointer pointer)
{
g_autoptr(GError) err = NULL;
g_autoptr(CcBackgroundPanel) panel = (CcBackgroundPanel *) pointer;
CcBackgroundItem *item;
CcBackgroundItem *current_background;
GSettings *settings;
if (!g_file_copy_finish (G_FILE (source_object), result, &err))
{
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
return;
}
g_warning ("Failed to copy image to cache location: %s", err->message);
}
item = g_object_get_data (source_object, "item");
settings = g_object_get_data (source_object, "settings");
current_background = get_current_background (panel, settings);
g_settings_apply (settings);
/* the panel may have been destroyed before the callback is run, so be sure
* to check the widgets are not NULL */
if (panel->spinner)
{
gtk_widget_destroy (GTK_WIDGET (panel->spinner));
panel->spinner = NULL;
}
if (current_background)
cc_background_item_load (current_background, NULL);
if (panel->builder)
{
g_autofree gchar *filename = NULL;
update_preview (panel, settings, item);
current_background = get_current_background (panel, settings);
/* Save the source XML if there is one */
filename = get_save_path (panel, settings);
if (create_save_dir ())
cc_background_xml_save (current_background, filename);
}
}
static void
set_background (CcBackgroundPanel *panel,
GSettings *settings,
CcBackgroundItem *item)
{
GDesktopBackgroundStyle style;
CcBackgroundItemFlags flags;
g_autofree gchar *filename = NULL;
gboolean save_settings = TRUE;
const char *uri;
CcBackgroundItemFlags flags;
if (item == NULL)
return;
@@ -169,7 +406,86 @@ set_background (CcBackgroundPanel *panel,
uri = cc_background_item_get_uri (item);
flags = cc_background_item_get_flags (item);
g_settings_set_string (settings, WP_URI_KEY, uri);
if ((flags & CC_BACKGROUND_ITEM_HAS_URI) && uri == NULL)
{
g_settings_set_enum (settings, WP_OPTIONS_KEY, G_DESKTOP_BACKGROUND_STYLE_NONE);
g_settings_set_string (settings, WP_URI_KEY, "");
}
else if (cc_background_item_get_source_url (item) != NULL &&
cc_background_item_get_needs_download (item))
{
g_autoptr(GFile) source = NULL;
g_autoptr(GFile) dest = NULL;
g_autofree gchar *cache_path = NULL;
g_autofree gchar *basename = NULL;
g_autofree gchar *display_name = NULL;
g_autofree gchar *dest_path = NULL;
g_autofree gchar *dest_uri = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
cache_path = bg_pictures_source_get_cache_path ();
if (g_mkdir_with_parents (cache_path, USER_DIR_MODE) < 0)
{
g_warning ("Failed to create directory '%s'", cache_path);
return;
}
dest_path = bg_pictures_source_get_unique_path (cc_background_item_get_source_url (item));
dest = g_file_new_for_path (dest_path);
source = g_file_new_for_uri (cc_background_item_get_source_url (item));
basename = g_file_get_basename (source);
display_name = g_filename_display_name (basename);
dest_path = g_file_get_path (dest);
/* create a blank image to use until the source image is ready */
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
gdk_pixbuf_fill (pixbuf, 0x00000000);
gdk_pixbuf_save (pixbuf, dest_path, "png", NULL, NULL);
if (panel->copy_cancellable)
{
g_cancellable_cancel (panel->copy_cancellable);
g_cancellable_reset (panel->copy_cancellable);
}
if (panel->spinner)
{
gtk_widget_destroy (GTK_WIDGET (panel->spinner));
panel->spinner = NULL;
}
/* create a spinner while the file downloads */
panel->spinner = gtk_spinner_new ();
gtk_spinner_start (GTK_SPINNER (panel->spinner));
gtk_box_pack_start (GTK_BOX (WID ("bottom-hbox")), panel->spinner, FALSE,
FALSE, 6);
gtk_widget_show (panel->spinner);
/* reference the panel in case it is removed before the copy is
* finished */
g_object_ref (panel);
g_object_set_data_full (G_OBJECT (source), "item", g_object_ref (item), g_object_unref);
g_object_set_data (G_OBJECT (source), "settings", settings);
g_file_copy_async (source, dest, G_FILE_COPY_OVERWRITE,
G_PRIORITY_DEFAULT, panel->copy_cancellable,
NULL, NULL,
copy_finished_cb, panel);
dest_uri = g_file_get_uri (dest);
g_settings_set_string (settings, WP_URI_KEY, dest_uri);
g_object_set (G_OBJECT (item),
"uri", dest_uri,
"needs-download", FALSE,
"name", display_name,
NULL);
/* delay the updated drawing of the preview until the copy finishes */
save_settings = FALSE;
}
else
{
g_settings_set_string (settings, WP_URI_KEY, uri);
}
/* Also set the placement if we have a URI and the previous value was none */
if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT)
@@ -189,126 +505,131 @@ set_background (CcBackgroundPanel *panel,
g_settings_set_string (settings, WP_PCOLOR_KEY, cc_background_item_get_pcolor (item));
g_settings_set_string (settings, WP_SCOLOR_KEY, cc_background_item_get_scolor (item));
/* Apply all changes */
g_settings_apply (settings);
/* update the preview information */
if (save_settings != FALSE)
{
g_autofree gchar *filename = NULL;
/* Save the source XML if there is one */
filename = get_save_path ();
if (create_save_dir ())
cc_background_xml_save (panel->current_background, filename);
}
/* Apply all changes */
g_settings_apply (settings);
static void
on_chooser_background_chosen_cb (CcBackgroundPanel *self,
CcBackgroundItem *item)
{
set_background (self, self->settings, item);
set_background (self, self->lock_settings, item);
/* Save the source XML if there is one */
filename = get_save_path (panel, settings);
if (create_save_dir ())
cc_background_xml_save (get_current_background (panel, settings), filename);
}
}
static void
on_add_picture_button_clicked_cb (CcBackgroundPanel *self)
on_chooser_dialog_response (GtkDialog *dialog,
int response_id,
CcBackgroundPanel *panel)
{
cc_background_chooser_select_file (self->background_chooser);
}
if (response_id == GTK_RESPONSE_OK)
{
g_autoptr(CcBackgroundItem) item = NULL;
static const char *
cc_background_panel_get_help_uri (CcPanel *panel)
{
return "help:gnome-help/look-background";
item = cc_background_chooser_dialog_get_item (CC_BACKGROUND_CHOOSER_DIALOG (dialog));
if (item != NULL)
set_background (panel, g_object_get_data (G_OBJECT (dialog), "settings"), item);
}
gtk_widget_destroy (GTK_WIDGET (dialog));
}
static void
cc_background_panel_constructed (GObject *object)
launch_chooser (CcBackgroundPanel *panel,
GSettings *settings)
{
CcBackgroundPanel *self;
CcShell *shell;
GtkWidget *dialog;
self = CC_BACKGROUND_PANEL (object);
shell = cc_panel_get_shell (CC_PANEL (self));
cc_shell_embed_widget_in_header (shell, GTK_WIDGET (self->add_picture_button), GTK_POS_RIGHT);
G_OBJECT_CLASS (cc_background_panel_parent_class)->constructed (object);
dialog = cc_background_chooser_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (WID ("background-panel"))));
g_object_set_data (G_OBJECT (dialog), "settings", settings);
gtk_widget_show (dialog);
g_signal_connect (dialog, "response", G_CALLBACK (on_chooser_dialog_response), panel);
panel->chooser = dialog;
g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer *) &panel->chooser);
}
static void
cc_background_panel_dispose (GObject *object)
on_background_button_clicked (GtkButton *button,
CcBackgroundPanel *panel)
{
CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object);
g_clear_object (&panel->settings);
g_clear_object (&panel->lock_settings);
g_clear_object (&panel->thumb_factory);
G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object);
launch_chooser (panel, panel->settings);
}
static void
cc_background_panel_finalize (GObject *object)
on_lock_button_clicked (GtkButton *button,
CcBackgroundPanel *panel)
{
CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object);
g_clear_object (&panel->current_background);
G_OBJECT_CLASS (cc_background_panel_parent_class)->finalize (object);
launch_chooser (panel, panel->lock_settings);
}
static void
cc_background_panel_class_init (CcBackgroundPanelClass *klass)
on_settings_changed (GSettings *settings,
gchar *key,
CcBackgroundPanel *panel)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
g_type_ensure (CC_TYPE_BACKGROUND_CHOOSER);
g_type_ensure (CC_TYPE_BACKGROUND_PREVIEW);
panel_class->get_help_uri = cc_background_panel_get_help_uri;
object_class->constructed = cc_background_panel_constructed;
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, add_picture_button);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, background_chooser);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, desktop_preview);
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 *panel)
{
reload_current_bg (panel);
update_preview (panel);
reload_current_bg (panel, settings);
update_preview (panel, settings, NULL);
}
static void
cc_background_panel_init (CcBackgroundPanel *panel)
{
g_resources_register (cc_background_get_resource ());
gtk_widget_init_template (GTK_WIDGET (panel));
gchar *objects[] = {"background-panel", NULL };
g_autoptr(GError) err = NULL;
GtkWidget *widget;
panel->connection = g_application_get_dbus_connection (g_application_get_default ());
g_resources_register (cc_background_get_resource ());
panel->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
panel->builder = gtk_builder_new ();
gtk_builder_add_objects_from_resource (panel->builder,
"/org/gnome/control-center/background/background.ui",
objects, &err);
if (err)
{
g_warning ("Could not load ui: %s", err->message);
return;
}
panel->settings = g_settings_new (WP_PATH_ID);
g_settings_delay (panel->settings);
panel->lock_settings = g_settings_new (WP_LOCK_PATH_ID);
g_settings_delay (panel->lock_settings);
/* Load the background */
reload_current_bg (panel);
update_preview (panel);
/* add the top level widget */
widget = WID ("background-panel");
gtk_container_add (GTK_CONTAINER (panel), widget);
gtk_widget_show_all (GTK_WIDGET (panel));
/* setup preview area */
widget = WID ("background-desktop-drawingarea");
g_signal_connect (widget, "draw", G_CALLBACK (on_preview_draw), panel);
widget = WID ("background-lock-drawingarea");
g_signal_connect (widget, "draw", G_CALLBACK (on_lock_preview_draw), panel);
panel->copy_cancellable = g_cancellable_new ();
panel->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
/* Load the backgrounds */
reload_current_bg (panel, panel->settings);
update_preview (panel, panel->settings, NULL);
reload_current_bg (panel, panel->lock_settings);
update_preview (panel, panel->lock_settings, NULL);
/* Background settings */
g_signal_connect_object (panel->settings, "changed", G_CALLBACK (on_settings_changed), panel, G_CONNECT_SWAPPED);
g_signal_connect (panel->settings, "changed", G_CALLBACK (on_settings_changed), panel);
g_signal_connect (panel->lock_settings, "changed", G_CALLBACK (on_settings_changed), panel);
/* Background buttons */
widget = WID ("background-set-button");
g_signal_connect (widget, "clicked", G_CALLBACK (on_background_button_clicked), panel);
widget = WID ("background-lock-set-button");
g_signal_connect (widget, "clicked", G_CALLBACK (on_lock_button_clicked), panel);
}

View File

@@ -18,7 +18,9 @@
*
*/
#pragma once
#ifndef _CC_BACKGROUND_PANEL_H
#define _CC_BACKGROUND_PANEL_H
#include <shell/cc-panel.h>
@@ -28,3 +30,5 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (CcBackgroundPanel, cc_background_panel, CC, BACKGROUND_PANEL, CcPanel)
G_END_DECLS
#endif /* _CC_BACKGROUND_PANEL_H */

View File

@@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<template class="CcBackgroundPanel" parent="CcPanel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="HdyClamp">
<property name="visible">1</property>
<property name="maximum_size">300</property>
<property name="tightening_threshold">200</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">24</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">18</property>
<property name="margin-bottom">18</property>
<property name="hexpand">True</property>
<child>
<object class="CcBackgroundPreview" id="desktop_preview">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="CcBackgroundChooser" id="background_chooser">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="expand">True</property>
<signal name="background-chosen" handler="on_chooser_background_chosen_cb" object="CcBackgroundPanel" swapped="yes" />
</object>
</child>
</object>
</child>
</template>
<!-- Header button -->
<object class="GtkButton" id="add_picture_button">
<property name="visible">True</property>
<property name="label" translatable="yes">Add Picture…</property>
<signal name="clicked" handler="on_add_picture_button_clicked_cb" object="CcBackgroundPanel" swapped="yes" />
</object>
</interface>

View File

@@ -1,382 +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
{
GtkBox parent;
GtkImage *animated_background_icon;
GtkLabel *desktop_clock_label;
GtkFrame *desktop_frame;
GtkDrawingArea *drawing_area;
GtkFrame *lock_frame;
GtkLabel *lock_screen_label;
GtkStack *stack;
GnomeDesktopThumbnailFactory *thumbnail_factory;
CcBackgroundItem *item;
GSettings *desktop_settings;
guint lock_screen_time_timeout_id;
gboolean is_lock_screen;
GDateTime *previous_time;
gboolean is_24h_format;
};
G_DEFINE_TYPE (CcBackgroundPreview, cc_background_preview, GTK_TYPE_BOX)
enum
{
PROP_0,
PROP_IS_LOCK_SCREEN,
PROP_ITEM,
N_PROPS
};
static GParamSpec *properties [N_PROPS];
/* Auxiliary methods */
static void
update_lock_screen_label (CcBackgroundPreview *self,
gboolean force)
{
g_autoptr(GDateTime) now = NULL;
g_autofree gchar *label = NULL;
now = g_date_time_new_now_local ();
/* Don't update the label if the hour:minute pair did not change */
if (!force && self->previous_time &&
g_date_time_get_hour (now) == g_date_time_get_hour (self->previous_time) &&
g_date_time_get_minute (now) == g_date_time_get_minute (self->previous_time))
{
return;
}
if (self->is_24h_format)
label = g_date_time_format (now, "%R");
else
label = g_date_time_format (now, "%I:%M %p");
gtk_label_set_label (self->lock_screen_label, label);
gtk_label_set_label (self->desktop_clock_label, label);
g_clear_pointer (&self->previous_time, g_date_time_unref);
self->previous_time = g_steal_pointer (&now);
}
static void
update_clock_format (CcBackgroundPreview *self)
{
g_autofree gchar *clock_format = NULL;
gboolean is_24h_format;
clock_format = g_settings_get_string (self->desktop_settings, "clock-format");
is_24h_format = g_strcmp0 (clock_format, "24h") == 0;
if (is_24h_format != self->is_24h_format)
{
self->is_24h_format = is_24h_format;
update_lock_screen_label (self, TRUE);
}
}
static void
load_custom_css (CcBackgroundPreview *self)
{
g_autoptr(GtkCssProvider) provider = NULL;
/* use custom CSS */
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_screen (gdk_screen_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
static gboolean
update_clock_cb (gpointer data)
{
CcBackgroundPreview *self = data;
update_lock_screen_label (self, FALSE);
return G_SOURCE_CONTINUE;
}
static void
start_monitor_time (CcBackgroundPreview *self)
{
if (self->lock_screen_time_timeout_id > 0)
return;
self->lock_screen_time_timeout_id = g_timeout_add_seconds (1,
update_clock_cb,
self);
}
static void
stop_monitor_time (CcBackgroundPreview *self)
{
if (self->lock_screen_time_timeout_id > 0)
{
g_source_remove (self->lock_screen_time_timeout_id);
self->lock_screen_time_timeout_id = 0;
}
}
/* Callbacks */
static gboolean
on_preview_draw_cb (CcBackgroundPreview *self,
cairo_t *cr)
{
g_autoptr(GdkPixbuf) pixbuf = NULL;
GtkAllocation allocation;
gint scale_factor;
if (!self->item)
return FALSE;
scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (self->drawing_area));
gtk_widget_get_allocation (GTK_WIDGET (self->drawing_area), &allocation);
pixbuf = cc_background_item_get_frame_thumbnail (self->item,
self->thumbnail_factory,
allocation.width,
allocation.height,
scale_factor,
0,
TRUE);
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
cairo_paint (cr);
return TRUE;
}
/* GObject overrides */
static void
cc_background_preview_finalize (GObject *object)
{
CcBackgroundPreview *self = (CcBackgroundPreview *)object;
g_clear_object (&self->desktop_settings);
g_clear_object (&self->item);
g_clear_object (&self->thumbnail_factory);
g_clear_pointer (&self->previous_time, g_date_time_unref);
stop_monitor_time (self);
G_OBJECT_CLASS (cc_background_preview_parent_class)->finalize (object);
}
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_LOCK_SCREEN:
g_value_set_boolean (value, self->is_lock_screen);
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_LOCK_SCREEN:
self->is_lock_screen = g_value_get_boolean (value);
gtk_stack_set_visible_child (self->stack,
self->is_lock_screen ? GTK_WIDGET (self->lock_frame) : GTK_WIDGET (self->desktop_frame));
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 gfloat
get_primary_monitor_aspect_ratio (void)
{
GdkDisplay *display;
GdkMonitor *primary_monitor;
gfloat aspect_ratio;
display = gdk_display_get_default ();
primary_monitor = gdk_display_get_primary_monitor (display);
aspect_ratio = 16.0 / 9.0;
if (primary_monitor)
{
GdkRectangle monitor_layout;
gdk_monitor_get_geometry (primary_monitor, &monitor_layout);
aspect_ratio = monitor_layout.width / (gfloat) monitor_layout.height;
}
return aspect_ratio;
}
static void
cc_background_preview_get_preferred_height_for_width (GtkWidget *widget,
gint width,
gint *minimum,
gint *natural)
{
gfloat aspect_ratio = get_primary_monitor_aspect_ratio ();
*minimum = *natural = MAX (2, width / aspect_ratio);
}
static void
cc_background_preview_get_preferred_width_for_height (GtkWidget *widget,
gint height,
gint *minimum,
gint *natural)
{
gfloat aspect_ratio = get_primary_monitor_aspect_ratio ();
*minimum = *natural = MAX (2, height * aspect_ratio);
}
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->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->get_preferred_height_for_width = cc_background_preview_get_preferred_height_for_width;
widget_class->get_preferred_width_for_height = cc_background_preview_get_preferred_width_for_height;
properties[PROP_IS_LOCK_SCREEN] = g_param_spec_boolean ("is-lock-screen",
"Lock screen",
"Whether the preview is of the lock screen",
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, animated_background_icon);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, desktop_clock_label);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, desktop_frame);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, drawing_area);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, lock_frame);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, lock_screen_label);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, stack);
gtk_widget_class_bind_template_callback (widget_class, on_preview_draw_cb);
}
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);
self->desktop_settings = g_settings_new ("org.gnome.desktop.interface");
g_signal_connect_object (self->desktop_settings,
"changed::clock-format",
G_CALLBACK (update_clock_format),
self,
G_CONNECT_SWAPPED);
update_clock_format (self);
load_custom_css (self);
start_monitor_time (self);
}
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_widget_set_visible (GTK_WIDGET (self->animated_background_icon),
cc_background_item_changes_with_time (item));
gtk_widget_queue_draw (GTK_WIDGET (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, GtkBox)
CcBackgroundItem* cc_background_preview_get_item (CcBackgroundPreview *self);
void cc_background_preview_set_item (CcBackgroundPreview *self,
CcBackgroundItem *item);
G_END_DECLS

View File

@@ -1,152 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<template class="CcBackgroundPreview" parent="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">False</property>
<style>
<class name="frame" />
</style>
<child>
<object class="GtkOverlay">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<!-- Wallpaper -->
<child>
<object class="GtkDrawingArea" id="drawing_area">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="expand">True</property>
<signal name="draw" handler="on_preview_draw_cb" object="CcBackgroundPreview" swapped="yes" />
</object>
</child>
<!-- Desktop / Lock Screen widgets -->
<child type="overlay">
<object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="expand">True</property>
<child>
<object class="GtkFrame" id="desktop_frame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="shadow-type">none</property>
<property name="valign">start</property>
<style>
<class name="desktop-preview" />
</style>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Activities</property>
</object>
</child>
<child type="center">
<object class="GtkLabel" id="desktop_clock_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="spacing">4</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="icon-name">network-wireless-symbolic</property>
<property name="pixel-size">6</property>
</object>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="icon-name">audio-volume-high-symbolic</property>
<property name="pixel-size">6</property>
</object>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="icon-name">battery-low-symbolic</property>
<property name="pixel-size">6</property>
</object>
</child>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkFrame" id="lock_frame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="shadow-type">none</property>
<child>
<object class="GtkLabel" id="lock_screen_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="expand">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
</object>
</child>
<style>
<class name="lock-screen-preview" />
</style>
</object>
</child>
</object>
</child>
<!-- Wallpaper -->
<child type="overlay">
<object class="GtkImage" id="animated_background_icon">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="valign">end</property>
<property name="margin-end">8</property>
<property name="margin-bottom">8</property>
<property name="pixel-size">16</property>
<property name="icon-name">slideshow-emblem</property>
<style>
<class name="slideshow-icon" />
</style>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -22,6 +22,7 @@
#include <gio/gio.h>
#include <string.h>
#include <libxml/parser.h>
#include <libgnome-desktop/gnome-bg.h>
#include <gdesktop-enums.h>
#include "gdesktop-enums-types.h"
@@ -199,10 +200,7 @@ cc_background_xml_load_xml_internal (CcBackgroundXml *xml,
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);
file = g_file_new_for_commandline_arg (content);
bg_uri = g_file_get_uri (file);
}
SET_FLAG(CC_BACKGROUND_ITEM_HAS_URI);
@@ -271,7 +269,7 @@ cc_background_xml_load_xml_internal (CcBackgroundXml *xml,
} 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);
g_warning ("Unknown Tag in %s: %s", filename, wpa->name);
}
}
@@ -309,7 +307,7 @@ cc_background_xml_load_xml_internal (CcBackgroundXml *xml,
g_strdup (id),
g_object_ref (item));
if (in_thread)
emit_added_in_idle (xml, g_object_ref (G_OBJECT (item)));
emit_added_in_idle (xml, g_object_ref (item));
else
g_signal_emit (G_OBJECT (xml), signals[ADDED], 0, item);
retval = TRUE;
@@ -433,39 +431,42 @@ cc_background_xml_load_list (CcBackgroundXml *data,
}
}
gboolean
cc_background_xml_load_list_finish (CcBackgroundXml *xml,
GAsyncResult *result,
GError **error)
const GHashTable *
cc_background_xml_load_list_finish (GAsyncResult *async_result)
{
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);
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (async_result);
CcBackgroundXml *data;
g_return_val_if_fail (G_IS_ASYNC_RESULT (async_result), NULL);
g_warn_if_fail (g_simple_async_result_get_source_tag (result) == cc_background_xml_load_list_async);
data = CC_BACKGROUND_XML (g_simple_async_result_get_op_res_gpointer (result));
return data->wp_hash;
}
static void
load_list_thread (GTask *task,
gpointer source_object,
gpointer task_data,
load_list_thread (GSimpleAsyncResult *res,
GObject *object,
GCancellable *cancellable)
{
CcBackgroundXml *xml = CC_BACKGROUND_XML (source_object);
cc_background_xml_load_list (xml, TRUE);
g_task_return_boolean (task, TRUE);
CcBackgroundXml *data;
data = g_simple_async_result_get_op_res_gpointer (res);
cc_background_xml_load_list (data, TRUE);
}
void
cc_background_xml_load_list_async (CcBackgroundXml *xml,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
void cc_background_xml_load_list_async (CcBackgroundXml *xml,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
g_autoptr(GSimpleAsyncResult) result = 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);
result = g_simple_async_result_new (G_OBJECT (xml), callback, user_data, cc_background_xml_load_list_async);
g_simple_async_result_set_op_res_gpointer (result, xml, NULL);
g_simple_async_result_run_in_thread (result, (GSimpleAsyncThreadFunc) load_list_thread, G_PRIORITY_LOW, cancellable);
}
gboolean
@@ -611,8 +612,6 @@ cc_background_xml_finalize (GObject *object)
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

View File

@@ -17,8 +17,10 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef _CC_BACKGROUND_XML_H_
#define _CC_BACKGROUND_XML_H_
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
@@ -29,18 +31,19 @@ G_DECLARE_FINAL_TYPE (CcBackgroundXml, cc_background_xml, CC, BACKGROUND_XML, GO
CcBackgroundXml *cc_background_xml_new (void);
void cc_background_xml_save (CcBackgroundItem *item,
const char *filename);
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,
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 *data,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean cc_background_xml_load_list_finish (CcBackgroundXml *xml,
GAsyncResult *result,
GError **error);
gpointer user_data);
const GHashTable *cc_background_xml_load_list_finish (GAsyncResult *async_result);
G_END_DECLS
#endif

View File

@@ -7,7 +7,6 @@ Icon=preferences-desktop-wallpaper
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 Background panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!

View File

@@ -8,6 +8,7 @@ desktop_in = configure_file(
)
i18n.merge_file(
desktop,
type: 'desktop',
input: desktop_in,
output: desktop,
@@ -42,10 +43,10 @@ enums_header = files(
common_sources += gnome.mkenums(
enums + '.h',
sources: enums_header,
fhead: '#pragma once\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n',
fhead: '#ifndef __GDESKTOP_ENUMS_TYPES_H__\n#define __GDESKTOP_ENUMS_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n',
fprod: '/* enumerations from "@filename@" */\n',
vhead: 'GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define G_DESKTOP_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n',
ftail: 'G_END_DECLS\n'
ftail: 'G_END_DECLS\n\n#endif /* __GDESKTOP_ENUMS_TYPES_H__ */'
)
common_sources += gnome.mkenums(
@@ -58,12 +59,7 @@ common_sources += gnome.mkenums(
vtail: ' { 0, NULL, NULL }\n };\n etype = g_@type@_register_static ("@EnumName@", values);\n }\n return etype;\n}\n'
)
resource_data = files(
'cc-background-chooser.ui',
'cc-background-panel.ui',
'cc-background-preview.ui',
'preview.css',
)
resource_data = files('background.ui')
common_sources += gnome.compile_resources(
'cc-@0@-resources'.format(cappletname),
@@ -76,15 +72,12 @@ common_sources += gnome.compile_resources(
sources = common_sources + files(
'bg-colors-source.c',
'bg-pictures-source.c',
'bg-recent-source.c',
'bg-source.c',
'bg-wallpapers-source.c',
'cc-background-chooser.c',
'cc-background-chooser-dialog.c',
'cc-background-grilo-miner.c',
'cc-background-item.c',
'cc-background-panel.c',
'cc-background-preview.c',
'cc-background-xml.c',
'cc-background-xml.c'
)
deps = common_deps + [
@@ -97,13 +90,20 @@ deps = common_deps + [
]
cflags += [
'-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir),
'-DDATADIR="@0@"'.format(control_center_datadir),
'-DGNOME_DESKTOP_USE_UNSTABLE_API'
]
if gnome_desktop_dep.version().version_compare('>=3.35.4')
cflags += '-DGNOME_DESKTOP_BG_API_BREAK'
endif
libbackground_chooser = static_library(
cappletname + '-chooser',
sources: sources,
include_directories: top_inc,
dependencies: deps,
c_args: cflags
)
sources = common_sources + files('cc-background-panel.c')
panels_libs += static_library(
cappletname,
@@ -111,4 +111,16 @@ panels_libs += static_library(
include_directories: top_inc,
dependencies: deps,
c_args: cflags,
link_with: libbackground_chooser
)
test_name = 'test-chooser-dialog'
executable(
test_name,
test_name + '.c',
include_directories: top_inc,
dependencies: deps,
c_args: cflags,
link_with: libbackground_chooser
)

View File

@@ -1,40 +0,0 @@
frame.desktop-preview {
min-height: 10px;
padding: 0 4px;
background-color: black;
}
frame.desktop-preview image {
color: white;
}
frame.desktop-preview label {
color: white;
font-weight: bold;
font-size: 6px;
}
frame.lock-screen-preview {
border: solid rgba(0, 0, 0, 0.33);
border-width: 10px 0 0 0;
}
frame.lock-screen-preview label {
color: white;
font-weight: bold;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
font-size: 1.2em;
}
image.slideshow-icon {
color: white;
-gtk-icon-shadow: 0 1px 2px rgba(0, 0, 0, 0.33);
}
button.remove-button {
border-radius: 9999px;
-gtk-outline-radius: 9999px;
padding: 1px 0px; /* circles instead of ellipses */
background-origin: padding-box, border-box;
background-clip: padding-box, border-box;
}

View File

@@ -0,0 +1,37 @@
#include <gtk/gtk.h>
#include "cc-background-chooser-dialog.h"
static void
on_dialog_response (GtkDialog *dialog,
int response_id,
gpointer user_data)
{
g_debug ("response: %d", response_id);
if (response_id == GTK_RESPONSE_OK) {
g_autoptr(CcBackgroundItem) item = NULL;
item = cc_background_chooser_dialog_get_item (CC_BACKGROUND_CHOOSER_DIALOG (dialog));
cc_background_item_dump (item);
}
gtk_widget_destroy (GTK_WIDGET (dialog));
gtk_main_quit ();
}
int main (int argc, char **argv)
{
GtkWidget *dialog;
g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
gtk_init (&argc, &argv);
dialog = cc_background_chooser_dialog_new (NULL);
gtk_window_set_modal (GTK_WINDOW (dialog), FALSE);
g_signal_connect (G_OBJECT (dialog), "response",
G_CALLBACK (on_dialog_response), NULL);
gtk_widget_show_all (dialog);
gtk_main ();
return 0;
}

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/control-center/bluetooth">
<file preprocess="xml-stripblanks">cc-bluetooth-panel.ui</file>
<file preprocess="xml-stripblanks">bluetooth.ui</file>
</gresource>
</gresources>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.16.0 on Fri Nov 29 16:46:49 2013 -->
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkBox" id="box_power">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkSwitch" id="switch_bluetooth">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="valign">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">4</property>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
</object>
</interface>

View File

@@ -22,6 +22,7 @@
#include <config.h>
#endif
#include <glib/gi18n-lib.h>
#include <shell/cc-shell.h>
#include <shell/cc-object-storage.h>
#include <bluetooth-settings-widget.h>
@@ -29,35 +30,54 @@
#include "cc-bluetooth-panel.h"
#include "cc-bluetooth-resources.h"
struct _CcBluetoothPanel {
CcPanel parent_instance;
#define WID(s) GTK_WIDGET (gtk_builder_get_object (self->builder, s))
GtkBox *airplane_box;
GtkBox *disabled_box;
GtkSwitch *enable_switch;
GtkBox *header_box;
GtkBox *hw_airplane_box;
GtkBox *no_devices_box;
BluetoothSettingsWidget *settings_widget;
GtkStack *stack;
#define BLUETOOTH_NO_DEVICES_PAGE "no-devices-page"
#define BLUETOOTH_DISABLED_PAGE "disabled-page"
#define BLUETOOTH_AIRPLANE_PAGE "airplane-page"
#define BLUETOOTH_HW_AIRPLANE_PAGE "hw-airplane-page"
#define BLUETOOTH_WORKING_PAGE "working-page"
struct _CcBluetoothPanel {
CcPanel parent_instance;
GtkBuilder *builder;
GtkWidget *stack;
GtkWidget *widget;
GCancellable *cancellable;
/* Killswitch */
GDBusProxy *rfkill;
GDBusProxy *properties;
gboolean airplane_mode;
gboolean bt_airplane_mode;
gboolean hardware_airplane_mode;
gboolean has_airplane_mode;
GtkWidget *kill_switch_header;
GDBusProxy *rfkill, *properties;
gboolean airplane_mode;
gboolean bt_airplane_mode;
gboolean hardware_airplane_mode;
gboolean has_airplane_mode;
};
CC_PANEL_REGISTER (CcBluetoothPanel, cc_bluetooth_panel)
static void cc_bluetooth_panel_finalize (GObject *object);
static void cc_bluetooth_panel_constructed (GObject *object);
static const char *
cc_bluetooth_panel_get_help_uri (CcPanel *panel)
{
return "help:gnome-help/bluetooth";
}
static void
cc_bluetooth_panel_class_init (CcBluetoothPanelClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
object_class->constructed = cc_bluetooth_panel_constructed;
object_class->finalize = cc_bluetooth_panel_finalize;
panel_class->get_help_uri = cc_bluetooth_panel_get_help_uri;
}
static void
cc_bluetooth_panel_finalize (GObject *object)
{
@@ -65,8 +85,12 @@ cc_bluetooth_panel_finalize (GObject *object)
self = CC_BLUETOOTH_PANEL (object);
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->properties);
g_clear_object (&self->rfkill);
g_clear_object (&self->kill_switch_header);
G_OBJECT_CLASS (cc_bluetooth_panel_parent_class)->finalize (object);
}
@@ -79,16 +103,20 @@ cc_bluetooth_panel_constructed (GObject *object)
G_OBJECT_CLASS (cc_bluetooth_panel_parent_class)->constructed (object);
/* add kill switch widgets */
self->kill_switch_header = g_object_ref (WID ("box_power"));
cc_shell_embed_widget_in_header (cc_panel_get_shell (CC_PANEL (self)),
GTK_WIDGET (self->header_box), GTK_POS_RIGHT);
self->kill_switch_header);
gtk_widget_show_all (self->kill_switch_header);
}
static void
enable_switch_changed_cb (CcBluetoothPanel *self)
power_callback (GObject *object,
GParamSpec *spec,
CcBluetoothPanel *self)
{
gboolean state;
state = gtk_switch_get_active (self->enable_switch);
state = gtk_switch_get_active (GTK_SWITCH (WID ("switch_bluetooth")));
g_debug ("Power switched to %s", state ? "on" : "off");
g_dbus_proxy_call (self->properties,
"Set",
@@ -96,89 +124,96 @@ enable_switch_changed_cb (CcBluetoothPanel *self)
g_variant_new_boolean (!state)),
G_DBUS_CALL_FLAGS_NONE,
-1,
cc_panel_get_cancellable (CC_PANEL (self)),
self->cancellable,
NULL, NULL);
}
static void
adapter_status_changed_cb (CcBluetoothPanel *self)
cc_bluetooth_panel_update_power (CcBluetoothPanel *self)
{
GtkAlign valign;
GObject *toggle;
gboolean sensitive, powered, change_powered;
GtkWidget *page;
const char *page;
g_debug ("Updating airplane mode: BluetoothHasAirplaneMode %d, BluetoothHardwareAirplaneMode %d, BluetoothAirplaneMode %d, AirplaneMode %d",
self->has_airplane_mode, self->hardware_airplane_mode, self->bt_airplane_mode, self->airplane_mode);
change_powered = TRUE;
valign = GTK_ALIGN_CENTER;
valign = GTK_ALIGN_CENTER;
if (self->has_airplane_mode == FALSE) {
g_debug ("No Bluetooth available");
sensitive = FALSE;
powered = FALSE;
page = GTK_WIDGET (self->no_devices_box);
page = BLUETOOTH_NO_DEVICES_PAGE;
} else if (self->hardware_airplane_mode) {
g_debug ("Bluetooth is Hard blocked");
sensitive = FALSE;
powered = FALSE;
page = GTK_WIDGET (self->hw_airplane_box);
page = BLUETOOTH_HW_AIRPLANE_PAGE;
} else if (self->airplane_mode) {
g_debug ("Airplane mode is on, Wi-Fi and Bluetooth are disabled");
sensitive = FALSE;
powered = FALSE;
page = GTK_WIDGET (self->airplane_box);
page = BLUETOOTH_AIRPLANE_PAGE;
} else if (self->bt_airplane_mode ||
!bluetooth_settings_widget_get_default_adapter_powered (self->settings_widget)) {
!bluetooth_settings_widget_get_default_adapter_powered (BLUETOOTH_SETTINGS_WIDGET (self->widget))) {
g_debug ("Default adapter is unpowered, but should be available");
sensitive = TRUE;
change_powered = FALSE;
page = GTK_WIDGET (self->disabled_box);
page = BLUETOOTH_DISABLED_PAGE;
} else {
g_debug ("Bluetooth is available and powered");
sensitive = TRUE;
powered = TRUE;
page = GTK_WIDGET (self->settings_widget);
page = BLUETOOTH_WORKING_PAGE;
valign = GTK_ALIGN_FILL;
}
gtk_widget_set_valign (GTK_WIDGET (self->stack), valign);
gtk_widget_set_sensitive (GTK_WIDGET (self->header_box), sensitive);
gtk_widget_set_valign (self->stack, valign);
gtk_widget_set_sensitive (WID ("box_power") , sensitive);
toggle = G_OBJECT (WID ("switch_bluetooth"));
if (change_powered) {
g_signal_handlers_block_by_func (self->enable_switch, enable_switch_changed_cb, self);
gtk_switch_set_active (self->enable_switch, powered);
g_signal_handlers_unblock_by_func (self->enable_switch, enable_switch_changed_cb, self);
g_signal_handlers_block_by_func (toggle, power_callback, self);
gtk_switch_set_active (GTK_SWITCH (toggle), powered);
g_signal_handlers_unblock_by_func (toggle, power_callback, self);
}
gtk_stack_set_visible_child (self->stack, page);
gtk_stack_set_visible_child_name (GTK_STACK (self->stack), page);
}
static void
airplane_mode_changed (CcBluetoothPanel *self)
airplane_mode_changed (GDBusProxy *proxy,
GVariant *changed_properties,
GStrv invalidated_properties,
CcBluetoothPanel *self)
{
g_autoptr(GVariant) airplane_mode = NULL;
g_autoptr(GVariant) bluetooth_airplane_mode = NULL;
g_autoptr(GVariant) bluetooth_hardware_airplane_mode = NULL;
g_autoptr(GVariant) bluetooth_has_airplane_mode = NULL;
GVariant *v;
airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "AirplaneMode");
self->airplane_mode = g_variant_get_boolean (airplane_mode);
v = g_dbus_proxy_get_cached_property (self->rfkill, "AirplaneMode");
self->airplane_mode = g_variant_get_boolean (v);
g_variant_unref (v);
bluetooth_airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothAirplaneMode");
self->bt_airplane_mode = g_variant_get_boolean (bluetooth_airplane_mode);
v = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothAirplaneMode");
self->bt_airplane_mode = g_variant_get_boolean (v);
g_variant_unref (v);
bluetooth_hardware_airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothHardwareAirplaneMode");
self->hardware_airplane_mode = g_variant_get_boolean (bluetooth_hardware_airplane_mode);
v = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothHardwareAirplaneMode");
self->hardware_airplane_mode = g_variant_get_boolean (v);
g_variant_unref (v);
bluetooth_has_airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothHasAirplaneMode");
self->has_airplane_mode = g_variant_get_boolean (bluetooth_has_airplane_mode);
v = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothHasAirplaneMode");
self->has_airplane_mode = g_variant_get_boolean (v);
g_variant_unref (v);
adapter_status_changed_cb (self);
cc_bluetooth_panel_update_power (self);
}
static void
airplane_mode_off_button_clicked_cb (CcBluetoothPanel *self)
on_airplane_mode_off_clicked (GtkButton *button,
CcBluetoothPanel *self)
{
g_debug ("Airplane Mode Off clicked, disabling airplane mode");
g_dbus_proxy_call (self->rfkill,
@@ -188,58 +223,92 @@ airplane_mode_off_button_clicked_cb (CcBluetoothPanel *self)
g_variant_new_boolean (FALSE)),
G_DBUS_CALL_FLAGS_NONE,
-1,
cc_panel_get_cancellable (CC_PANEL (self)),
self->cancellable,
NULL, NULL);
}
static void
panel_changed_cb (CcBluetoothPanel *self,
const char *panel)
add_stack_page (CcBluetoothPanel *self,
const char *message,
const char *explanation,
const char *name)
{
CcShell *shell;
g_autoptr(GError) error = NULL;
GtkWidget *label, *image, *box;
char *str;
shell = cc_panel_get_shell (CC_PANEL (self));
if (cc_shell_set_active_panel_from_id (shell, panel, NULL, &error) == FALSE)
g_warning ("Failed to activate '%s' panel: %s", panel, error->message);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
g_object_set (G_OBJECT (box), "margin-top", 64, "margin-bottom", 64, NULL);
if (g_str_equal (name, BLUETOOTH_AIRPLANE_PAGE) ||
g_str_equal (name, BLUETOOTH_HW_AIRPLANE_PAGE)) {
image = gtk_image_new_from_icon_name ("airplane-mode-symbolic",
GTK_ICON_SIZE_DIALOG);
} else {
image = gtk_image_new_from_icon_name ("bluetooth-active-symbolic",
GTK_ICON_SIZE_DIALOG);
}
gtk_image_set_pixel_size (GTK_IMAGE (image), 192);
gtk_style_context_add_class (gtk_widget_get_style_context (image), "dim-label");
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 24);
str = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>", message);
label = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL (label), str);
g_free (str);
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
label = gtk_label_new (explanation);
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
if (g_str_equal (name, BLUETOOTH_AIRPLANE_PAGE)) {
GtkWidget *button;
button = gtk_button_new_with_label (_("Turn Off Airplane Mode"));
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (on_airplane_mode_off_clicked), self);
gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 24);
}
gtk_stack_add_named (GTK_STACK (self->stack), box, name);
gtk_widget_show_all (box);
}
static void
cc_bluetooth_panel_class_init (CcBluetoothPanelClass *klass)
panel_changed (GtkWidget *settings_widget,
const char *panel,
CcBluetoothPanel *self)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
CcShell *shell;
GError *error = NULL;
object_class->constructed = cc_bluetooth_panel_constructed;
object_class->finalize = cc_bluetooth_panel_finalize;
panel_class->get_help_uri = cc_bluetooth_panel_get_help_uri;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/bluetooth/cc-bluetooth-panel.ui");
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, airplane_box);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, disabled_box);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, enable_switch);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, header_box);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, no_devices_box);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, hw_airplane_box);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, settings_widget);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, stack);
gtk_widget_class_bind_template_callback (widget_class, adapter_status_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, airplane_mode_off_button_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, enable_switch_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, panel_changed_cb);
shell = cc_panel_get_shell (CC_PANEL (self));
if (cc_shell_set_active_panel_from_id (shell, panel, NULL, &error) == FALSE) {
g_warning ("Failed to activate '%s' panel: %s", panel, error->message);
g_error_free (error);
}
}
static void
cc_bluetooth_panel_init (CcBluetoothPanel *self)
{
bluetooth_settings_widget_get_type ();
GError *error = NULL;
g_resources_register (cc_bluetooth_get_resource ());
gtk_widget_init_template (GTK_WIDGET (self));
self->builder = gtk_builder_new ();
gtk_builder_set_translation_domain (self->builder, GETTEXT_PACKAGE);
gtk_builder_add_from_resource (self->builder,
"/org/gnome/control-center/bluetooth/bluetooth.ui",
&error);
if (error != NULL) {
g_warning ("Could not load ui: %s", error->message);
g_error_free (error);
return;
}
self->cancellable = g_cancellable_new ();
/* RFKill */
self->rfkill = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION,
@@ -255,7 +324,29 @@ cc_bluetooth_panel_init (CcBluetoothPanel *self)
"org.freedesktop.DBus.Properties",
NULL, NULL);
airplane_mode_changed (self);
self->stack = gtk_stack_new ();
gtk_stack_set_homogeneous (GTK_STACK (self->stack), TRUE);
add_stack_page (self, _("No Bluetooth Found"), _("Plug in a dongle to use Bluetooth."), BLUETOOTH_NO_DEVICES_PAGE);
add_stack_page (self, _("Bluetooth Turned Off"), _("Turn on to connect devices and receive file transfers."), BLUETOOTH_DISABLED_PAGE);
add_stack_page (self, _("Airplane Mode is on"), _("Bluetooth is disabled when airplane mode is on."), BLUETOOTH_AIRPLANE_PAGE);
add_stack_page (self, _("Hardware Airplane Mode is on"), _("Turn off the Airplane mode switch to enable Bluetooth."), BLUETOOTH_HW_AIRPLANE_PAGE);
self->widget = bluetooth_settings_widget_new ();
g_signal_connect (G_OBJECT (self->widget), "panel-changed",
G_CALLBACK (panel_changed), self);
gtk_stack_add_named (GTK_STACK (self->stack),
self->widget, BLUETOOTH_WORKING_PAGE);
gtk_widget_show (self->widget);
gtk_widget_show (self->stack);
gtk_container_add (GTK_CONTAINER (self), self->stack);
airplane_mode_changed (NULL, NULL, NULL, self);
g_signal_connect_object (self->rfkill, "g-properties-changed",
G_CALLBACK (airplane_mode_changed), self, G_CONNECT_SWAPPED);
G_CALLBACK (airplane_mode_changed), self, 0);
g_signal_connect_object (G_OBJECT (self->widget), "adapter-status-changed",
G_CALLBACK (cc_bluetooth_panel_update_power), self, G_CONNECT_SWAPPED);
g_signal_connect (G_OBJECT (WID ("switch_bluetooth")), "notify::active",
G_CALLBACK (power_callback), self);
}

View File

@@ -22,7 +22,8 @@
*
*/
#pragma once
#ifndef _CC_BLUETOOTH_PANEL_H
#define _CC_BLUETOOTH_PANEL_H
#include <shell/cc-shell.h>
@@ -32,3 +33,6 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (CcBluetoothPanel, cc_bluetooth_panel, CC, BLUETOOTH_PANEL, CcPanel)
G_END_DECLS
#endif /* _CC_BLUETOOTH_PANEL_H */

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