Compare commits
155 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55c4da8f14 | ||
|
|
1ea311c99a | ||
|
|
a67273baee | ||
|
|
3e1af78e68 | ||
|
|
690eb414cb | ||
|
|
689df1196d | ||
|
|
009841d96f | ||
|
|
b1de78f49c | ||
|
|
50db1aa131 | ||
|
|
ef888ffb03 | ||
|
|
bf3f73935a | ||
|
|
ec59d41d95 | ||
|
|
321b62439a | ||
|
|
076554379f | ||
|
|
5fb204781c | ||
|
|
df390a2d58 | ||
|
|
e7f5d53457 | ||
|
|
2d8f17006f | ||
|
|
dfe78834b4 | ||
|
|
34a96eee19 | ||
|
|
136f731c32 | ||
|
|
41648dad9f | ||
|
|
e03e1e08bb | ||
|
|
933ef2f682 | ||
|
|
061ce1aeb3 | ||
|
|
0936bc098a | ||
|
|
116442edb3 | ||
|
|
dc924f640b | ||
|
|
b3cba63f06 | ||
|
|
7ab65011ab | ||
|
|
adc440f793 | ||
|
|
2208b9c301 | ||
|
|
2085196638 | ||
|
|
6e5bafd3fd | ||
|
|
4daf99ad3a | ||
|
|
ac9055aac3 | ||
|
|
467089b8cd | ||
|
|
1335f85c7b | ||
|
|
7066feab5e | ||
|
|
3fbd0ba7da | ||
|
|
3ed6b8cc4e | ||
|
|
c1f37877c4 | ||
|
|
b81449836d | ||
|
|
156f9f503c | ||
|
|
553ebc3c6e | ||
|
|
ee8a64a184 | ||
|
|
8f76e1fb93 | ||
|
|
e03fe497a8 | ||
|
|
8bcd8fdb88 | ||
|
|
438dee2585 | ||
|
|
9901e697ee | ||
|
|
8e8b89c000 | ||
|
|
57def32b32 | ||
|
|
c929b64cd2 | ||
|
|
18aed24592 | ||
|
|
ab63e495e4 | ||
|
|
14aa827aaa | ||
|
|
91b2885ce1 | ||
|
|
d59b6e79ab | ||
|
|
6c6513913e | ||
|
|
157ac67ace | ||
|
|
c7b618f873 | ||
|
|
5a8f72176a | ||
|
|
2434b6006f | ||
|
|
d32d75c638 | ||
|
|
a91f0e620a | ||
|
|
da3723e7d0 | ||
|
|
c44953c776 | ||
|
|
5087cf97e1 | ||
|
|
8e0a0f7672 | ||
|
|
4ae8f1a369 | ||
|
|
0000570007 | ||
|
|
1e69fe0e40 | ||
|
|
e4c67b67e9 | ||
|
|
b771c3b972 | ||
|
|
2eeee2e097 | ||
|
|
706b7bdc41 | ||
|
|
a5b66b405f | ||
|
|
86c996e006 | ||
|
|
4012ca17fd | ||
|
|
63025db137 | ||
|
|
36f53768ca | ||
|
|
f69926a95a | ||
|
|
a91663d714 | ||
|
|
ddfd4343e2 | ||
|
|
608aac8fff | ||
|
|
6f6fcb463c | ||
|
|
2145e0d8de | ||
|
|
19d95a72fa | ||
|
|
9d7d3d1781 | ||
|
|
0fbe64d6d9 | ||
|
|
ae9f9df102 | ||
|
|
8052e1bc89 | ||
|
|
55b09def37 | ||
|
|
7ac1301b26 | ||
|
|
2ca936f0e8 | ||
|
|
8a3cc50ed6 | ||
|
|
086aaacab2 | ||
|
|
210d11b974 | ||
|
|
9cafaf0606 | ||
|
|
3eba181d7b | ||
|
|
7e726c0c46 | ||
|
|
1f28814b88 | ||
|
|
00c3fad3b1 | ||
|
|
9c864bf34a | ||
|
|
28af0f16d3 | ||
|
|
4a20dcb2ed | ||
|
|
a8c1b82ed8 | ||
|
|
8ae2d124c7 | ||
|
|
f794b14bc9 | ||
|
|
51fc40a60e | ||
|
|
aad990ed17 | ||
|
|
41e2f537e6 | ||
|
|
bf0e6ccff2 | ||
|
|
7d884a6e9b | ||
|
|
fe26b96b14 | ||
|
|
afadaf363c | ||
|
|
ed5693624b | ||
|
|
cbcb717f68 | ||
|
|
3005d4abc1 | ||
|
|
ff5ab8f715 | ||
|
|
0151a0ac25 | ||
|
|
e6cc73fd1d | ||
|
|
b068891cf3 | ||
|
|
063d89abe8 | ||
|
|
8e6b89dbbd | ||
|
|
a8b62b25e0 | ||
|
|
b593dc4e64 | ||
|
|
0d0504aea1 | ||
|
|
c928bd14b8 | ||
|
|
107685efdc | ||
|
|
0bbcc3b8b3 | ||
|
|
099948e3ff | ||
|
|
c6a111c15e | ||
|
|
3b8fb9c0f3 | ||
|
|
f185cda349 | ||
|
|
af469c99b6 | ||
|
|
60e3f003bb | ||
|
|
3b9e94a03f | ||
|
|
79c2c4578b | ||
|
|
44bd8b4d9b | ||
|
|
0a64988649 | ||
|
|
c1520aac66 | ||
|
|
a23cd79762 | ||
|
|
8df3f8c9e5 | ||
|
|
d39ec251af | ||
|
|
4ed667e4e5 | ||
|
|
01a42dfea1 | ||
|
|
49f5fd9b78 | ||
|
|
d8aaec6a98 | ||
|
|
3481206fa9 | ||
|
|
da2f0e52c7 | ||
|
|
f8a05fe2dc | ||
|
|
946919c850 | ||
|
|
2d263f5ea9 |
5
.gitignore
vendored
@@ -1,6 +1,3 @@
|
||||
__pycache__
|
||||
_build/
|
||||
**/*~
|
||||
/subprojects/*
|
||||
!/subprojects/*.wrap
|
||||
.flatpak-builder/
|
||||
**/*~
|
||||
@@ -31,19 +31,6 @@ stages:
|
||||
|
||||
.Build procedure: &build_procedure
|
||||
echo "== Building ==" &&
|
||||
dnf install -y dnf5-plugins &&
|
||||
git clone https://gitlab.gnome.org/GNOME/glib.git &&
|
||||
cd glib &&
|
||||
dnf builddep -y glib &&
|
||||
meson setup . _build -Dprefix=/usr -Dlibdir=lib64 &&
|
||||
ninja -C _build install &&
|
||||
cd .. && rm -rf _build/ &&
|
||||
git clone https://gitlab.gnome.org/GNOME/gtk.git &&
|
||||
cd gtk &&
|
||||
dnf builddep -y gtk4 &&
|
||||
meson setup . _build -Dprefix=/usr -Dlibdir=lib64 &&
|
||||
ninja -C _build install &&
|
||||
cd .. &&
|
||||
rm -rf _build/ &&
|
||||
meson . _build ${BUILD_OPTS} -Dprofile=development &&
|
||||
ninja -C _build 2>&1 | tee compilation.log
|
||||
@@ -65,7 +52,7 @@ stages:
|
||||
# stable branch.
|
||||
# Could probably also switch away from rawhide,
|
||||
# to stable fedora branch as well.
|
||||
FDO_DISTRIBUTION_TAG: '2023-06-07.0-main'
|
||||
FDO_DISTRIBUTION_TAG: '2022-10-25.0-main'
|
||||
FDO_DISTRIBUTION_VERSION: rawhide
|
||||
|
||||
#############################################
|
||||
@@ -111,8 +98,6 @@ build.container.fedora@x86_64:
|
||||
gtk3-devel ibus-devel
|
||||
gtk4-devel
|
||||
intltool
|
||||
appstream-devel
|
||||
sassc
|
||||
libadwaita-devel
|
||||
libcanberra-devel
|
||||
libgtop2-devel
|
||||
@@ -121,7 +106,7 @@ build.container.fedora@x86_64:
|
||||
libnotify-devel
|
||||
libpwquality-devel
|
||||
libsmbclient-devel
|
||||
libsoup3-devel
|
||||
libsoup-devel
|
||||
libudisks2-devel
|
||||
libwacom-devel
|
||||
libX11-devel
|
||||
@@ -137,17 +122,15 @@ build.container.fedora@x86_64:
|
||||
xorg-x11-server-Xvfb
|
||||
mesa-dri-drivers
|
||||
libsecret-devel
|
||||
geocode-glib2-devel
|
||||
geocode-glib-devel
|
||||
libgweather-devel
|
||||
lcms2-devel
|
||||
geoclue2-devel
|
||||
libnotify-devel
|
||||
alsa-lib-devel
|
||||
nss-devel
|
||||
gcr3-devel
|
||||
gcr-devel
|
||||
setxkbmap
|
||||
appstream-devel
|
||||
FDO_DISTRIBUTION_EXEC: |-
|
||||
git clone https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas.git && \
|
||||
cd gsettings-desktop-schemas && \
|
||||
@@ -266,7 +249,7 @@ coverage:
|
||||
BUILD_OPTS: "-Db_coverage=true"
|
||||
coverage: '/^Lines:.\d+.\d+.(\d+\.\d+\%)/'
|
||||
only:
|
||||
- main@GNOME/gnome-control-center
|
||||
- master@GNOME/gnome-control-center
|
||||
|
||||
script:
|
||||
- *environment_information
|
||||
@@ -306,7 +289,7 @@ pages:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- main@GNOME/gnome-control-center
|
||||
- master@GNOME/gnome-control-center
|
||||
|
||||
except:
|
||||
variables:
|
||||
@@ -320,7 +303,7 @@ pages:
|
||||
##
|
||||
flatpak:
|
||||
stage: manual
|
||||
image: quay.io/gnome_infrastructure/gnome-runtime-images:gnome-master
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
|
||||
artifacts:
|
||||
name: package
|
||||
paths:
|
||||
@@ -366,7 +349,7 @@ flatpak:
|
||||
except:
|
||||
- tags
|
||||
- gnome-3-.*
|
||||
- main@GNOME/gnome-control-center
|
||||
- master@GNOME/gnome-control-center
|
||||
|
||||
|
||||
# Runs the sanitizers [address, thread, undefined, and memory].
|
||||
|
||||
@@ -4,7 +4,7 @@ Not following the communication guidelines [1] will mean your issue or comment
|
||||
will be removed. Read it carefully before submitting this issue.
|
||||
|
||||
|
||||
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/CODE_OF_CONDUCT.md#communication-guidelines
|
||||
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/CONTRIBUTING.md#communication-guideline
|
||||
|
||||
-->
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Not following the communication guidelines [1] will mean your issue or comment
|
||||
will be removed. Read it carefully before submitting this issue.
|
||||
|
||||
|
||||
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/CODE_OF_CONDUCT.md#communication-guidelines
|
||||
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/CONTRIBUTING.md#communication-guideline
|
||||
|
||||
-->
|
||||
|
||||
|
||||
429
NEWS
@@ -1,372 +1,151 @@
|
||||
===============
|
||||
Version 45.beta
|
||||
===============
|
||||
|
||||
- Prevent loading last-panel unconditionally on startup
|
||||
- Multiple settings rows got ported to use the AdwSwitchRow widget
|
||||
- Various accessibility label fixes
|
||||
- Various memory leak fixes
|
||||
|
||||
About
|
||||
- New About panel displaying system information in a more compact way
|
||||
|
||||
Applications
|
||||
- Fix crash when opening the Apps panel as the last-opened panel
|
||||
|
||||
Datetime
|
||||
- Add description explaining the "Clock & Calendar" settings
|
||||
|
||||
Displays
|
||||
- Replace deprecated GtkComboBox with AdwComboRow
|
||||
|
||||
Keyboard
|
||||
- Fix "Move up/down" movement options in the input list
|
||||
- Spawn "tecla" app to display the keyboard map (replaces gkbd-keyboard-display)
|
||||
- Fix alignment of the "Set Shorcut..." button
|
||||
|
||||
Network
|
||||
- Use an AdwSwitchRow widget to enable/disable Wi-Fi
|
||||
|
||||
Online Accounts
|
||||
- Improve "offiline" message text
|
||||
- Use banner to indicate when the system is offline
|
||||
- Add panel description text and section titles
|
||||
|
||||
Sound
|
||||
- Make output test whell smaller
|
||||
- Ellipsize long device name label
|
||||
|
||||
Printers
|
||||
- Use the "card" style for printer entries
|
||||
|
||||
Privacy
|
||||
- New Privacy panel containing all the panels under the Privacy category
|
||||
|
||||
Region
|
||||
- Fix preview buttoins in the format chooser
|
||||
|
||||
Search
|
||||
- Fix "Move up/down" movement options in the app search list
|
||||
|
||||
Users
|
||||
- Show "Other Users" section only when there are users to show
|
||||
- Make entire panel insensitive when the user has no permission to make changes
|
||||
- Fix focus issues when selecting avatar image from a file
|
||||
- Fix g_critical errors when loading file metadata for avatars
|
||||
|
||||
================
|
||||
Version 45.alpha
|
||||
Version 42.10
|
||||
================
|
||||
|
||||
- Add placeholder text to various search entries
|
||||
- Set a minimum size for various dialogs
|
||||
- Make dialogs close when pressing the Escape key
|
||||
- Replace deprecated GTK4 methods with new replacements
|
||||
- Depend on snapd-glib-2 (soup3 version)
|
||||
- Accessibility improvements
|
||||
- Fix monitor order in display settings
|
||||
- Add 32:9 aspect ration in display settings
|
||||
- Fix warning in user panel in initialization of avatar widget
|
||||
- Updated translations
|
||||
|
||||
Common
|
||||
- Fix time entry for RTL languages
|
||||
- Use ToastOverlay
|
||||
- Show start title buttons in header bar
|
||||
- Allow more theming of rows
|
||||
- Only return to last panel if it didn't crash
|
||||
- Improvements to panel activation
|
||||
- Improvements to panel searching
|
||||
================
|
||||
Version 42.9
|
||||
================
|
||||
|
||||
- Updated translations
|
||||
|
||||
Network:
|
||||
- Fix possible race in tests
|
||||
|
||||
================
|
||||
Version 42.4
|
||||
================
|
||||
|
||||
- Updated translations
|
||||
- Added various accessibility labels
|
||||
- Initialize locale early
|
||||
|
||||
About
|
||||
- Show only the GNOME major version
|
||||
- Update hostname only after apply is clicked
|
||||
|
||||
Accessibility
|
||||
- Present the checked state on the list row itself
|
||||
|
||||
Appearance
|
||||
- Clear out dconf if user picks defaults
|
||||
- Don't load version.xml info we don't use
|
||||
|
||||
Applications
|
||||
- Always use bold for app name in dialogs
|
||||
- Use header capitalization in the "No apps" AdwStatusPage
|
||||
- Don't recurse into symlinks when clearing app cache
|
||||
|
||||
Color
|
||||
- Do not try to access to null pointer in destruction
|
||||
- Dim information text & fix "Learn more" link alignment
|
||||
|
||||
Date and Time
|
||||
- Fix NTP switch getting out of sync
|
||||
- Add top bar clock and calendar switches
|
||||
- Move "Time Format" row out of "Clock" section
|
||||
- Merge "Clock" and "Calendar" sections
|
||||
|
||||
Default Apps
|
||||
- Don't crash when there are no apps for a mimetype
|
||||
|
||||
Device Security
|
||||
- Skip security attributes that have been obsoleted by others
|
||||
- Ddon't translate technical report
|
||||
|
||||
Display
|
||||
- Allow configuring all monitors and apply settings at once
|
||||
- Try snapping all the displays after a config change
|
||||
- Don't leak config manager proxy
|
||||
- Use AdwPreferencesPage
|
||||
- Fix display enabled toggle visibility
|
||||
- Fix gaps when numbering unusable displays
|
||||
- Fix stuck window subtitle
|
||||
- Fix invalid panel state after canceling changes
|
||||
- Check best_mode exist before adding flag
|
||||
|
||||
Info
|
||||
- Show each GPU in it's own line
|
||||
|
||||
Mouse
|
||||
- Prevent infinite loop on settings changes
|
||||
- Do not bind sensitivity to touchpad settings
|
||||
- Simplify binding of touchpad sensitive widgets
|
||||
- Hide entire "Touchpad" row when touchpad cannot be disabled
|
||||
|
||||
Keyboard
|
||||
- Fix cancel button issue
|
||||
- Add "Compose" and "Character" keywords
|
||||
- Add ellipsis to the "Add Shortcut" button label
|
||||
- Fix "Add Custom Shortcut" in others sections
|
||||
- Drop "Left Alt" as compose key option
|
||||
|
||||
Network
|
||||
- Validate max length of hotspot SSID
|
||||
- Keep current mode when enabling proxy
|
||||
- Increase maximum MTU value from 10000 to 65536
|
||||
- Fix incorrect styling in WiFi list
|
||||
- Make the security status and signal strength read by screen readers
|
||||
- Add a confirmation dialog when forgetting a connection
|
||||
- Center panel title when subtitle isn't visible
|
||||
- Rename "Other Devices" to "Bluetooth"
|
||||
- Fix crash when importing wrong vpn file
|
||||
- Drop legacy vpn_export function
|
||||
- Close Connection Editor dialog when clicking Apply button
|
||||
- Add delete icon in saved WiFi connections list
|
||||
- Move WiFi controls out of headerbar
|
||||
|
||||
Notifications
|
||||
- Replace "Applications" with "App Notifications"
|
||||
|
||||
Power
|
||||
- Label the main "battery" as UPS if that's what it is
|
||||
- Hide automatic suspend row in VM
|
||||
|
||||
Region
|
||||
- Fix label of formats for the login screen
|
||||
|
||||
Sharing
|
||||
- Disable AdwActionRow markup for networks
|
||||
- Fix network row visible name bug
|
||||
- Remove global master switch
|
||||
- Fix visual bug for active indicators
|
||||
- Add icons next to each row
|
||||
- Add subtitle to each panel row
|
||||
|
||||
Sound
|
||||
- Make bass audible on low quality hardware
|
||||
- Prevent duplicate sound device entries
|
||||
|
||||
Thunderbolt
|
||||
- Update page to be more similar to other pages
|
||||
- Modernize Device Dialog UI
|
||||
|
||||
Usage
|
||||
- Fix confirmation dialog when clearing history
|
||||
|
||||
Users
|
||||
- Remove account activity window
|
||||
- Set language-chooser to hide on close
|
||||
- Add popover explaining about the "Administrator" option
|
||||
- Add a popover describing the autologin functionality
|
||||
- Move "Add User" button out of the user listbox
|
||||
- Improve avatar crop mechanics
|
||||
- Improve rounding of avatar crop edges
|
||||
- Draw avatar crop corners to inside of crop
|
||||
|
||||
Wacom
|
||||
- Rename "Test Your Settings" button to "Test Settings"
|
||||
|
||||
================
|
||||
Version 44.rc
|
||||
================
|
||||
|
||||
- Improve state of switchers throughout the app
|
||||
- Updated translations
|
||||
|
||||
Keyboard
|
||||
- Various fixes to the shortcut editor
|
||||
|
||||
Mouse & Touchpad
|
||||
- Polish the panel redesign
|
||||
|
||||
Printers
|
||||
- Update to more modern CUPS APIs
|
||||
|
||||
================
|
||||
Version 44.beta
|
||||
================
|
||||
|
||||
- Redesigned Sound panel
|
||||
- Redesigned Mouse & Touchpad panel
|
||||
- Share Wi-Fi networks using QR code
|
||||
- Many consistency improvements
|
||||
- WireGuard support
|
||||
- Updated translations
|
||||
|
||||
Mouse & Touchpad
|
||||
- Redesign the panel with videos of the preferences
|
||||
- Move mouse test into a separate dialog
|
||||
|
||||
Network
|
||||
- Add support for sharing Wi-Fi networks through QR code
|
||||
- Add WireGuard support
|
||||
|
||||
Sound
|
||||
- Move application volumes to a dialog
|
||||
- Move sound themes to a dialog
|
||||
|
||||
================
|
||||
Version 44.alpha
|
||||
================
|
||||
|
||||
- Redesigned Accessibility panel
|
||||
- Many consistency improvements
|
||||
- Updated translations
|
||||
|
||||
About
|
||||
- Add "Firmware Version" row
|
||||
|
||||
Accessibility
|
||||
- Redesign the panel with new a navigation pattern
|
||||
- Fix crash when there's no device rows to show
|
||||
|
||||
Cellular
|
||||
- Various fixes
|
||||
- Improve dbus error messaging
|
||||
- Handle cases when SIM ID is not present
|
||||
- Prevent duplicate entries in the SIM providers list
|
||||
|
||||
Date & Time
|
||||
- Improve month selector
|
||||
Keyboard
|
||||
- Fix activation of input source toggle button
|
||||
- Fix permission_acquired always returning FALSE
|
||||
|
||||
Device Security
|
||||
- Improve date and time formatting
|
||||
- Simplify technical descriptions
|
||||
|
||||
Display
|
||||
- Improve error state of Night Light
|
||||
|
||||
Sound
|
||||
- Start implementing the new designs
|
||||
|
||||
Thunderbolt
|
||||
- Hide panel if no Thunderbolt device is found
|
||||
|
||||
================
|
||||
Version 43.1
|
||||
================
|
||||
|
||||
- Updated translations
|
||||
Mouse
|
||||
- Set rows as actiavatable widgets
|
||||
|
||||
Network
|
||||
- Fix crashes editing networks
|
||||
- Fix crashes when EAP password is missing
|
||||
- Fix wrong signal of SEA password visibility toggle
|
||||
- Prevent crash when disconnecting wifi device
|
||||
- Use mime-types for file chooser filtering TLS files
|
||||
|
||||
Online Accounts
|
||||
- Fix crash when failing to find GOA helper executable
|
||||
|
||||
Power
|
||||
- Don't assert if we can't find the widget for a profile
|
||||
- Prevent terminal from getting spammed with ALS logs
|
||||
|
||||
Printers
|
||||
- Small visual improvements
|
||||
- Fix loading of UI resources
|
||||
- Show empty-state when removing the last printer
|
||||
|
||||
Region
|
||||
- Fix creating rows for locales without a country
|
||||
- Fix critical when changing language
|
||||
- Fix permission_acquired always returning FALSE
|
||||
|
||||
Search
|
||||
- Fix reordering of list rows
|
||||
|
||||
Users
|
||||
- Show a fallback avatar when failing to load one
|
||||
|
||||
Wifi
|
||||
- Allow accessing settings of known wifi networks
|
||||
|
||||
================
|
||||
Version 43.0
|
||||
Version 42.4
|
||||
================
|
||||
|
||||
- Updated translations
|
||||
|
||||
================
|
||||
Version 43.rc
|
||||
================
|
||||
|
||||
- Fix initial AM/PM label value
|
||||
- Remove no longer used icon
|
||||
- Select panel only if non-folded when search is canceled
|
||||
- Updated translations
|
||||
|
||||
Appearance
|
||||
- Allow backgrounds to use any image format
|
||||
|
||||
Device Security
|
||||
- Several UI improvements
|
||||
Background
|
||||
- Restore support for multiple file selection
|
||||
- Allow more image formats
|
||||
|
||||
Display
|
||||
- Fix primary monitor selection
|
||||
|
||||
Info
|
||||
- Improve dark theme support
|
||||
|
||||
Keyboard
|
||||
- Fix activation of input source toggle button
|
||||
- Improve handling of Shift shortcuts
|
||||
Network
|
||||
- Fix network profiles shown on wrong device
|
||||
- Various crash fixes
|
||||
|
||||
Power
|
||||
- Fix blank screen and power button behavior settings
|
||||
|
||||
Printers
|
||||
- Show empty state after removing last printer
|
||||
|
||||
Search
|
||||
- Fix Move Up and Move Down actions
|
||||
|
||||
Sound
|
||||
- Fix sound alert selection
|
||||
|
||||
Wacom
|
||||
- Better support Wacom Express Key Remote
|
||||
|
||||
================
|
||||
Version 43.beta
|
||||
================
|
||||
|
||||
- Updated translations
|
||||
|
||||
Cellular
|
||||
- Add WWAN 5G connection support
|
||||
|
||||
Device Security
|
||||
- Polish failure messages
|
||||
- Various style updates
|
||||
|
||||
Display
|
||||
- Support privacy screens
|
||||
|
||||
Info
|
||||
- Show build id in a separate row
|
||||
|
||||
Network
|
||||
- Fix VPN empty state
|
||||
|
||||
Sound
|
||||
- Update default sounds
|
||||
- Fix blank-screen settings not applying
|
||||
- Fix "Power Button Behavior" setting not applying
|
||||
|
||||
User Accounts
|
||||
- Fix back button not appearing sometimes
|
||||
- Disconnect fingerprint reading devices when closing dialog
|
||||
|
||||
Sharing
|
||||
- Don't set remote-desktop password entry if pw_generate fails
|
||||
- Don't assert if we can't find the widget for a profile
|
||||
|
||||
================
|
||||
Version 43.alpha
|
||||
Version 42.3
|
||||
================
|
||||
|
||||
- Improved accessibility in various panels
|
||||
- New Device Security panel
|
||||
- Updated translations
|
||||
|
||||
Date & Time
|
||||
- Update visual style of the timezone map
|
||||
|
||||
Display
|
||||
- Various visual improvements
|
||||
- Use virtual clone modes when mirroring
|
||||
|
||||
Network
|
||||
- Prevent crash by disconnecting device.
|
||||
- Fix Wi-Fi network with "&" in name not appearing.
|
||||
- Fix warning when panel closed.
|
||||
|
||||
================
|
||||
Version 42.2
|
||||
================
|
||||
|
||||
- Updated translations
|
||||
|
||||
Applications
|
||||
- Fix Snap permissions support failing to compile
|
||||
- Fix CcInfoRow having the wrong parent
|
||||
- Fix crash crash when switching between two apps
|
||||
|
||||
Background
|
||||
- Make sure the size of the light/dark previews are the same
|
||||
|
||||
Keyboard
|
||||
- Fix crash resetting all keyboard shortcuts
|
||||
|
||||
Network:
|
||||
- Stop freeze when closing wired connection properties with Escape
|
||||
|
||||
Sharing
|
||||
- Fix close button on Verify Encryption dialog
|
||||
- Turn off RDP gsettings key when turning off RDP
|
||||
|
||||
Shell
|
||||
- Initialise locale early
|
||||
|
||||
Sound
|
||||
- Remove dog barking sounds
|
||||
- Update theme correctly so other apps respond to change
|
||||
|
||||
================
|
||||
Version 42.1
|
||||
|
||||
10
README.md
@@ -1,6 +1,6 @@
|
||||
[](https://gitlab.gnome.org/GNOME/gnome-control-center/pipelines)
|
||||
[](https://gnome.pages.gitlab.gnome.org/gnome-control-center/)
|
||||
[](https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/COPYING)
|
||||
[](https://gitlab.gnome.org/GNOME/gnome-control-center/pipelines)
|
||||
[](https://gnome.pages.gitlab.gnome.org/gnome-control-center/)
|
||||
[](https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/COPYING)
|
||||
|
||||
GNOME Settings
|
||||
====================
|
||||
@@ -9,7 +9,7 @@ GNOME Settings is GNOME's main interface for configuration of various aspects of
|
||||
|
||||
## Contributing
|
||||
|
||||
See `docs/CONTRIBUTING.md` for details on the contribution process, and `docs/CODING_STYLE.md`
|
||||
See `docs/CONTRIBUTING.md` for details on the contribution process, and `docs/HACKING.md`
|
||||
for the coding style guidelines.
|
||||
|
||||
## Reporting Bugs
|
||||
@@ -60,4 +60,4 @@ 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/main/docs/CODE_OF_CONDUCT.md#communication-guidelines
|
||||
[communication-guidelines]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/CONTRIBUTING.md#communication-guidelines
|
||||
|
||||
@@ -26,10 +26,7 @@
|
||||
"cxxflags" : "-O2 -g",
|
||||
"env" : {
|
||||
"V" : "1"
|
||||
},
|
||||
"build-args": [
|
||||
"--share=network"
|
||||
]
|
||||
}
|
||||
},
|
||||
"x-run-args" : [
|
||||
"--verbose"
|
||||
@@ -59,13 +56,13 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "intltool",
|
||||
"cleanup" : [ "*" ],
|
||||
"sources" : [
|
||||
"name": "intltool",
|
||||
"cleanup": [ "*" ],
|
||||
"sources": [
|
||||
{
|
||||
"type" : "archive",
|
||||
"url" : "https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz",
|
||||
"sha256" : "67c74d94196b153b774ab9f89b2fa6c6ba79352407037c8c14d5aeb334e959cd"
|
||||
"type": "archive",
|
||||
"url": "https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz",
|
||||
"sha256": "67c74d94196b153b774ab9f89b2fa6c6ba79352407037c8c14d5aeb334e959cd"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -75,6 +72,7 @@
|
||||
"config-opts" : [
|
||||
"--disable-polkitd",
|
||||
"--disable-man-pages",
|
||||
"--disable-introspection",
|
||||
"--disable-examples",
|
||||
"--disable-gtk-doc",
|
||||
"--disable-libelogind",
|
||||
@@ -110,18 +108,20 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "accountsservice",
|
||||
"name" : "accountservice",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dsystemdsystemunitdir=no",
|
||||
"-Ddocbook=false",
|
||||
"-Delogind=false",
|
||||
"-Dgtk_doc=false",
|
||||
"-Dintrospection=false",
|
||||
"-Dvapi=false"
|
||||
"-Dsystemd=false",
|
||||
"-Dsystemdsystemunitdir=no"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.freedesktop.org/accountsservice/accountsservice",
|
||||
"branch" : "main"
|
||||
"url" : "git://anongit.freedesktop.org/accountsservice"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -186,6 +186,20 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
@@ -224,14 +238,11 @@
|
||||
},
|
||||
{
|
||||
"name" : "rest",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dgtk_doc=false"
|
||||
],
|
||||
"buildsystem" : "autotools",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch" : "master",
|
||||
"branch" : "librest-0-7",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/librest.git"
|
||||
}
|
||||
]
|
||||
@@ -268,10 +279,9 @@
|
||||
"name" : "geocode-glib",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Denable-installed-tests=false",
|
||||
"-Denable-introspection=false",
|
||||
"-Denable-gtk-doc=false",
|
||||
"-Dsoup2=false"
|
||||
"-Denable-introspection=false",
|
||||
"-Denable-installed-tests=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
@@ -284,10 +294,9 @@
|
||||
"name" : "libgweather",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dglade_catalog=false",
|
||||
"-Denable_vala=false",
|
||||
"-Dgtk_doc=false",
|
||||
"-Dintrospection=false",
|
||||
"-Dtests=false"
|
||||
"-Dgtk_doc=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
@@ -333,7 +342,7 @@
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "archive",
|
||||
"url" : "http://libndp.org/files/libndp-1.6.tar.gz",
|
||||
"url" : " http://libndp.org/files/libndp-1.6.tar.gz",
|
||||
"sha256" : "0c7dfa84e013bd5e569ef2c6292a6f72cfaf14f4ff77a77425e52edc33ffac0e"
|
||||
}
|
||||
]
|
||||
@@ -348,10 +357,14 @@
|
||||
"config-opts" : [
|
||||
"-Dlibaudit=no",
|
||||
"-Ddbus_conf_dir=/app/etc/dbus-1/system.d",
|
||||
"-Ddbus_ifaces_dir=/app/share/dbus-1/interfaces",
|
||||
"-Ddbus_sys_dir=/app/share/dbus-1/system.d",
|
||||
"-Ddnsmasq=/usr/bin/true",
|
||||
"-Ddocs=false",
|
||||
"-Dintrospection=false",
|
||||
"-Diptables=/usr/bin/true",
|
||||
"-Djson_validation=false",
|
||||
"-Dlibnm_glib=false",
|
||||
"-Dlibpsl=false",
|
||||
"-Dmodem_manager=false",
|
||||
"-Dnmtui=false",
|
||||
@@ -406,9 +419,12 @@
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dappindicator=no",
|
||||
"-Dwwan=false",
|
||||
"-Dgtk_doc=false",
|
||||
"-Dintrospection=false",
|
||||
"-Dlibnm_gtk=false",
|
||||
"-Dselinux=false",
|
||||
"-Dteam=false"
|
||||
"-Dteam=false",
|
||||
"-Dwwan=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
@@ -618,142 +634,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "mutter",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dgles2=false",
|
||||
"-Dglx=false",
|
||||
"-Dxwayland=false",
|
||||
"-Dwayland=false",
|
||||
"-Dsystemd=false",
|
||||
"-Dnative_backend=false",
|
||||
"-Dremote_desktop=false",
|
||||
"-Degl_device=false",
|
||||
"-Dudev=false",
|
||||
"-Dstartup_notification=false",
|
||||
"-Dsm=false",
|
||||
"-Dintrospection=true",
|
||||
"-Ddocs=false",
|
||||
"-Dtests=false",
|
||||
"-Dprofiler=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch" : "main",
|
||||
"url" : "https://gitlab.gnome.org/gnome/mutter.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "libical",
|
||||
"buildsystem" : "cmake",
|
||||
"config-opts" : [
|
||||
"-DICAL_BUILD_DOCS=false",
|
||||
"-DICAL_GLIB=true",
|
||||
"-DLIBICAL_BUILD_TESTING=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/libical/libical.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "evolution-data-server",
|
||||
"buildsystem" : "cmake",
|
||||
"config-opts" : [
|
||||
"-DWITH_LIBDB=OFF"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/evolution-data-server.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "libstartup-notification",
|
||||
"buildsystem" : "autotools",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.freedesktop.org/xdg/startup-notification.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "sassc",
|
||||
"buildsystem" : "simple",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/sass/libsass"
|
||||
},
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/sass/sassc.git",
|
||||
"dest" : "sassc"
|
||||
}
|
||||
],
|
||||
"build-commands" : [
|
||||
"make -C sassc",
|
||||
"PREFIX=/app make -C sassc install"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "cogl",
|
||||
"buildsystem" : "autotools",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"tag" : "cogl-1.22",
|
||||
"url" : "https://gitlab.gnome.org/Archive/cogl.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "clutter",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dbackends='system'",
|
||||
"-Ddrivers='all'",
|
||||
"-Dbuild_tests=false",
|
||||
"-Dbuild_examples=false",
|
||||
"-Ddocumentation=false",
|
||||
"-Dintrospection=true",
|
||||
"-Dpixbuf_tests=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/clutter.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "gnome-shell",
|
||||
"buildsystem" : "meson",
|
||||
"config-opts" : [
|
||||
"-Dextensions_tool=false",
|
||||
"-Dextensions_app=false",
|
||||
"-Dgtk_doc=false",
|
||||
"-Dman=false",
|
||||
"-Dtests=false",
|
||||
"-Dnetworkmanager=false",
|
||||
"-Dsystemd=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"branch" : "main",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/gnome-shell.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "gnome-backgrounds",
|
||||
"buildsystem" : "meson",
|
||||
@@ -770,11 +650,12 @@
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "dir",
|
||||
"path" : "../../"
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/gnome-control-center.git"
|
||||
}
|
||||
],
|
||||
"config-opts" : [
|
||||
"-Dtracing=true",
|
||||
"-Dprofile=development"
|
||||
]
|
||||
}
|
||||
|
||||
1
build-aux/meson.build
Normal file
@@ -0,0 +1 @@
|
||||
meson.add_install_script('meson/meson_post_install.py', control_center_datadir)
|
||||
15
build-aux/meson/meson_post_install.py
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
gsettingsschemadir = os.path.join(sys.argv[1], 'glib-2.0', 'schemas')
|
||||
icondir = os.path.join(sys.argv[1], 'icons', 'hicolor')
|
||||
|
||||
if not os.environ.get('DESTDIR'):
|
||||
print('Compiling gsettings schemas...')
|
||||
subprocess.call(['glib-compile-schemas', gsettingsschemadir])
|
||||
|
||||
print('Update icon cache...')
|
||||
subprocess.call(['gtk-update-icon-cache', '-f', '-t', icondir])
|
||||
@@ -1,184 +0,0 @@
|
||||
# Code of Conduct
|
||||
|
||||
GNOME Settings is a project developed based on GNOME Code of Conduct and GitHub's community
|
||||
guidelines. You can read it below:
|
||||
|
||||
## Summary
|
||||
|
||||
GNOME creates software for a better world. We achieve this by behaving well towards
|
||||
each other.
|
||||
|
||||
Therefore this document suggests what we consider ideal behaviour, so you know what
|
||||
to expect when getting involved in GNOME. This is who we are and what we want to be.
|
||||
There is no official enforcement of these principles, and this should not be interpreted
|
||||
like a legal document.
|
||||
|
||||
## Advice
|
||||
|
||||
* **Be respectful and considerate**: Disagreement is no excuse for poor behaviour or personal
|
||||
attacks. Remember that a community where people feel uncomfortable is not a productive one.
|
||||
|
||||
* **Be patient and generous**: If someone asks for help it is because they need it. Do politely
|
||||
suggest specific documentation or more appropriate venues where appropriate, but avoid
|
||||
aggressive or vague responses such as "RTFM".
|
||||
|
||||
* **Assume people mean well**: Remember that decisions are often a difficult choice between
|
||||
competing priorities. If you disagree, please do so politely. If something seems outrageous,
|
||||
check that you did not misinterpret it. Ask for clarification, but do not assume the worst.
|
||||
|
||||
* **Try to be concise**: Avoid repeating what has been said already. Making a conversation larger
|
||||
makes it difficult to follow, and people often feel personally attacked if they receive multiple
|
||||
messages telling them the same thing.
|
||||
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Communication Guidelines
|
||||
|
||||
It is of ultimate importance to maintain a community in which everyone feels free to express
|
||||
themselves, review, and comment on each others ideas, both technical and otherwise. Correspondingly,
|
||||
an environment in which individuals are silenced, berated, or are otherwise afraid to speak up is
|
||||
unlikely to foster fruitful dialog.
|
||||
|
||||
Everyone interacting with members of the community should always keep in mind the asymmetry of
|
||||
communication: while your interaction with community members (and in particular, maintainers and
|
||||
long-term contributors) may be singular and fleeting, these members generally interact with a high
|
||||
volume of individuals each day. Before writing a comment, opening a new issue, or engaging as part
|
||||
of any forum or IRC discussion, please take a moment to appreciate that fact.
|
||||
|
||||
While communicating, it is expected that all involved participants be respectful and civil at all
|
||||
times and refrain from personal attacks.
|
||||
|
||||
### Communication Rules
|
||||
|
||||
The following behavior will not be tolerated on any occasion:
|
||||
|
||||
* **Threats of violence**: You may not threaten violence towards others or use the site to organize,
|
||||
promote, or incite acts of real-world violence or terrorism. Think carefully about the words you
|
||||
use, the images you post, and even the software you write, and how they may be interpreted by
|
||||
others. Even if you mean something as a joke, it might not be received that way. If you think
|
||||
that someone else might interpret the content you post as a threat or as promoting violence or
|
||||
terrorism, stop. Don't post it. In extraordinary cases, we may report threats of violence to law
|
||||
enforcement if we think there may be a genuine risk of physical harm or a threat to public safety.
|
||||
|
||||
* **Hate speech and discrimination**: While it is not forbidden to broach topics such as age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience, nationality,
|
||||
personal appearance, race, religion, or sexual identity and orientation, we do not tolerate speech
|
||||
that attacks a person or group of people on the basis of who they are. When approached in an
|
||||
aggressive or insulting manner these (and other) sensitive topics can make others feel unwelcome,
|
||||
or perhaps even unsafe. While there's always the potential for misunderstandings, we expect our
|
||||
community members to remain respectful and civil when discussing sensitive topics.
|
||||
|
||||
* **Bullying and harassment**: We do not tolerate bullying, harassment, or any other means of
|
||||
habitual badgering or intimidation targeted at a specific person or group of people. In general,
|
||||
if your actions are unwanted and you cease to terminate this form of engagement, there is a good
|
||||
chance that your behavior will be classified as bullying or harassment.
|
||||
|
||||
* **Impersonation**: You may not seek to mislead others as to your identity by copying another
|
||||
person's avatar, posting content under their email address, using a similar username, or otherwise
|
||||
posing as someone else. Impersonation and identity theft is a form of harassment.
|
||||
|
||||
* **Doxxing and invasion of privacy**: Don't post other people's personal information, such as phone
|
||||
numbers, private email addresses, physical addresses, credit card numbers, Social Security/National
|
||||
Identity numbers, or passwords. Depending on the context, we may consider such behavior to be an
|
||||
invasion of privacy, with particularly egregious examples potentially escalating to the point of
|
||||
legal action, such as when the released material presents a safety risk to the subject.
|
||||
|
||||
* **Obscene content**: In essence, do not post pornography, gore, or any other depiction of violence.
|
||||
|
||||
### General Advice
|
||||
|
||||
The following advice will help to increase the efficiency of communication with community members:
|
||||
|
||||
* Do not post "me too" comments. Use the GitLab reactions instead, e.g. “thumbs up” or “thumbs down”.
|
||||
* Avoid adding priority, time, or relevance hints if you are not involved with the development of
|
||||
the application. For example, `“This is an urgent issue”`, or `“This should be fixed now”`, or
|
||||
even `“The majority of users need this feature”`.
|
||||
* Do not use passive-aggressive communication tactics.
|
||||
* When reporting technical problems with the application, such as misbehavior or crashes, focus on
|
||||
sharing as many details as possible and avoid adding non-technical information to it.
|
||||
|
||||
An example of a **good** issue report:
|
||||
|
||||
```
|
||||
GNOME Settings crashes when opening the Wi-Fi panel with 3+ Wi-Fi adapters
|
||||
|
||||
Steps to reproduce (assuming 3+ Wi-Fi adapters are present):
|
||||
|
||||
1. Open GNOME Settings
|
||||
2. Select the Wi-Fi panel
|
||||
3. Observe the crash
|
||||
|
||||
This does not happen with 2 or less adapters. Here is a backtrace of the
|
||||
crash: backtrace.txt
|
||||
```
|
||||
|
||||
In contrast, here is an example of a **bad** issue report:
|
||||
|
||||
```
|
||||
GNOME Settings crashed while I was trying to connect to the internet. How can such
|
||||
a thing happen and nobody notice? Did you not test it before releasing it?
|
||||
|
||||
This should be fixed as quick as possible!
|
||||
```
|
||||
|
||||
* When asking for new features, try and add as much information as possible to justify its relevance,
|
||||
why should it not be implemented as an auxiliary program, what problems it would solve, and offer
|
||||
suggestions about how you think it should be implemented.
|
||||
|
||||
Example of a **good** feature request:
|
||||
|
||||
```
|
||||
GNOME Settings needs to expose IPv6 options
|
||||
|
||||
As of now, the connection editor dialog does not allow editing various IPv6
|
||||
options. This is relevant because without some of these options, it is not
|
||||
possible to have a valid IPv6 configuration and, consequently, not have access
|
||||
to various websites and services.
|
||||
|
||||
The list of missing configurations that are essential is:
|
||||
|
||||
* <Feature A>
|
||||
* <Feature B>
|
||||
|
||||
Optionally, the following configurations can also be added:
|
||||
|
||||
* <Feature C>
|
||||
* <Feature D>
|
||||
|
||||
Here is a quick sketch I have made showing how I think these options
|
||||
should be exposed as a user interface: sketch.png.
|
||||
```
|
||||
|
||||
Example of a **bad** feature request:
|
||||
|
||||
```
|
||||
Merge GNOME Tweaks in GNOME Settings
|
||||
|
||||
The options in GNOME Tweaks are absolutely essential to the majority of us
|
||||
users. Why was it not merged already? This is an urgent issue and should
|
||||
have been addressed years ago. You should allocate all your resources on
|
||||
merging those two applications.
|
||||
```
|
||||
|
||||
### What happens if someone breaks these rules or guidelines?
|
||||
|
||||
Actions that may be taken in response to an abusive comment include but are not limited to:
|
||||
|
||||
* Content removal (when breaking any of the guidelines or rules)
|
||||
* Content blocking (when breaking any of the guidelines or rules)
|
||||
* Formal report to the Code of Conduct Committee (when breaking any of the rules)
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
[maintainers]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/MAINTAINERS.md
|
||||
@@ -1,97 +1,212 @@
|
||||
# Contributing
|
||||
|
||||
Thank you for considering contributing to Settings!
|
||||
|
||||
All code contributions are made using merge requests.
|
||||
When contributing to the development of GNOME Settings, please first discuss the change you wish to
|
||||
make via issue, email, or any other method with the maintainers before making a change.
|
||||
|
||||
Please note we have a Code of Conduct, please follow it in all your interactions with the project.
|
||||
|
||||
## Creating Merge Requests
|
||||
## Pull Request Process
|
||||
|
||||
To open a merge request fork the Settings project, and then create a branch for your change.
|
||||
When the change is ready, submit a merge request.
|
||||
1. Create a fork in GitLab and push your work to there
|
||||
2. Open a Merge Request
|
||||
1. Always allow maintainer edits
|
||||
2. Mark the Merge Request as WIP if your work is not ready to be reviewed
|
||||
3. Assign the correct maintainer to the Merge Request (see [`MAINTAINERS.md`][maintainers] to select
|
||||
the correct maintainer)
|
||||
4. Format commit messages as follows:
|
||||
```
|
||||
component: <summary>
|
||||
|
||||
A paragraph explaining the problem and its context.
|
||||
|
||||
Another one explaining how you solved that.
|
||||
|
||||
<link to the issue>
|
||||
```
|
||||
4. You may merge the pull request in once you have the sign-off of the maintainers, or if you
|
||||
do not have permission to do that, you may request the second reviewer to merge it for you.
|
||||
|
||||
The following guidelines will help your change be successfully merged:
|
||||
## Code of Conduct
|
||||
|
||||
* Keep the change as small as possible. If you can split it into multiple merge requests please do
|
||||
so.
|
||||
* Use multiple commits. This makes is easier to review and helps to diagnose bugs in the future.
|
||||
* Use clear commit messages (see below).
|
||||
* Attach screenshots of the change.
|
||||
* Link to relevant issues this change is related to.
|
||||
* Always set the merge request to allow maintainer edits - this makes it easier
|
||||
for a maintainer to make small improvements to land the change faster.
|
||||
GNOME Settings is a project developed based on GNOME Code of Conduct and GitHub's community
|
||||
guidelines. You can read it below:
|
||||
|
||||
Please format commit messages as follows:
|
||||
### Summary
|
||||
|
||||
```
|
||||
component: <summary>
|
||||
GNOME creates software for a better world. We achieve this by behaving well towards
|
||||
each other.
|
||||
|
||||
A paragraph explaining the problem and its context.
|
||||
Therefore this document suggests what we consider ideal behaviour, so you know what
|
||||
to expect when getting involved in GNOME. This is who we are and what we want to be.
|
||||
There is no official enforcement of these principles, and this should not be interpreted
|
||||
like a legal document.
|
||||
|
||||
Another one explaining how you solved that.
|
||||
### Advice
|
||||
|
||||
<link to issue(s) this change fixes>
|
||||
```
|
||||
* **Be respectful and considerate**: Disagreement is no excuse for poor behaviour or personal
|
||||
attacks. Remember that a community where people feel uncomfortable is not a productive one.
|
||||
|
||||
## Bug Fixes
|
||||
* **Be patient and generous**: If someone asks for help it is because they need it. Do politely
|
||||
suggest specific documentation or more appropriate venues where appropriate, but avoid
|
||||
aggressive or vague responses such as "RTFM".
|
||||
|
||||
Changes that fix bugs include:
|
||||
* **Assume people mean well**: Remember that decisions are often a difficult choice between
|
||||
competing priorities. If you disagree, please do so politely. If something seems outrageous,
|
||||
check that you did not misinterpret it. Ask for clarification, but do not assume the worst.
|
||||
|
||||
* Correcting code that crashes.
|
||||
* Spelling mistakes in labels.
|
||||
* Small layout issues (e.g. spacing).
|
||||
* Use of deprecated APIs.
|
||||
* Restructuring of code for improved safety.
|
||||
* **Try to be concise**: Avoid repeating what has been said already. Making a conversation larger
|
||||
makes it difficult to follow, and people often feel personally attacked if they receive multiple
|
||||
messages telling them the same thing.
|
||||
|
||||
Please include clear information in the commit message(s) and merge request that indicate what is
|
||||
being fixed by the change.
|
||||
|
||||
These changes will be reviewed for correctness, and then merged once this is complete.
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## User Experience Changes
|
||||
### Communication Guideline
|
||||
|
||||
Changes that impact the user experience of Settings require approval from the
|
||||
[Design Team][design-team]. This includes:
|
||||
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.
|
||||
|
||||
* Addition or removal of features in existing panels.
|
||||
* Changes to the layout of panels.
|
||||
* New panels.
|
||||
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.
|
||||
|
||||
Please include before/after screenshots in the merge request to show what is being changed.
|
||||
While communicating, it is expected that all involved participants be respectful and civil at all
|
||||
times and refrain from personal attacks.
|
||||
|
||||
For one of these changes to be merged one of the following is required:
|
||||
#### Communication Rules
|
||||
|
||||
* The change is shown in an existing mockup done by the design team (linked to in the merge request
|
||||
or issue).
|
||||
* A comment from a design team member in the merge request or issue approving the change.
|
||||
The following behavior will not be tolerated on any occasion:
|
||||
|
||||
If a merge request is opened without the above the "Needs Design" label attached to it and will not
|
||||
be merged until design approval is received.
|
||||
* **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.
|
||||
|
||||
Once design approval is obtained, the change will be reviewed for correctness, and then merged once
|
||||
this is complete.
|
||||
If design approval is not obtained, the merge request will be closed.
|
||||
* **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.
|
||||
|
||||
[design-team]: https://gitlab.gnome.org/Teams/Design
|
||||
* **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.
|
||||
|
||||
## Reviews
|
||||
* **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.
|
||||
|
||||
All changes require approval from one or more Settings maintainers.
|
||||
Reviews are likely to ask for changes to be made, please respond to these as soon as you are able
|
||||
and ask for clarification if the requests are not clear.
|
||||
* **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.
|
||||
|
||||
When the change is ready to land a maintainer will mark it as approved.
|
||||
Then the change can be merged by either a maintainer or the submitter if they have suitable
|
||||
permissions.
|
||||
* **Obscene content**: In essence, do not post pornography, gore, or any other depiction of violence.
|
||||
|
||||
## Draft Merge Requests
|
||||
#### General Advice
|
||||
|
||||
Merge requests marked as draft will not be reviewed by Settings maintainers or merged.
|
||||
When the change is ready for review please mark the merge request as ready.
|
||||
The following advice will help to increase the efficiency of communication with community members:
|
||||
|
||||
## Inactive Merge Requests
|
||||
* 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.
|
||||
|
||||
If a merge request has comments from maintainers that have not been responded to within 4 weeks this
|
||||
merge request is considered to be inactive and will be closed. The reporter may re-open it at a
|
||||
later date if they respond to the comments.
|
||||
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
|
||||
|
||||
@@ -50,7 +50,7 @@ by being explicit. Suggested acceptance phrase:
|
||||
Urgency commits should never happen, but in case they're needed, they are defined by the following
|
||||
criteria:
|
||||
|
||||
* On stable branches (or `main` right after a stable release)
|
||||
* On stable branches (or master right after a stable release)
|
||||
* Symptoms:
|
||||
* Always OR often reproducible; AND
|
||||
* Crash; OR
|
||||
@@ -59,4 +59,4 @@ criteria:
|
||||
* Quickly followed by an emergency release (at most 2 days after the commit)
|
||||
|
||||
|
||||
[doap]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/gnome-control-center.doap
|
||||
[doap]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/gnome-control-center.doap
|
||||
|
||||
@@ -13,20 +13,20 @@
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
|
||||
<programming-language>C</programming-language>
|
||||
|
||||
<!-- General, About, Camera, File History & Trash, Location, Microphone, Mouse & Touchpad, Printers, Search, Thunderbolt, User Accounts -->
|
||||
<!-- General, Multitasking -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Felipe Borges</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:felipeborges@gnome.org" />
|
||||
<gnome:userid>felipeborges</gnome:userid>
|
||||
<foaf:name>Georges Basile Stavracas Neto</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:gbsneto@gnome.org" />
|
||||
<gnome:userid>gbsneto</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- General -->
|
||||
<!-- General, Region & Language -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Robert Ancell</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:robert.ancell@canonical.com" />
|
||||
<foaf:mbox rdf:resource="mailto:rancell@gnome.org" />
|
||||
<gnome:userid>rancell</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
@@ -49,11 +49,38 @@
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- Mouse & Touchpad, Printers -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Felipe Borges</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:felipeborges@gnome.org" />
|
||||
<gnome:userid>felipeborges</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- Online Accounts -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Debarshi Ray</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:debarshir@gnome.org" />
|
||||
<gnome:userid>debarshir</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- Printers -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Marek Kašík</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:mkasik@redhat.com" />
|
||||
<foaf:mbox rdf:resource="mailto:mkasik@gnome.org" />
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<!-- Thunderbolt -->
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Christian Kellner</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:gicmo@gnome.org" />
|
||||
<gnome:userid>gicmo</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
|
||||
89
meson.build
@@ -1,8 +1,8 @@
|
||||
project(
|
||||
'gnome-control-center', 'c',
|
||||
version : '45.beta',
|
||||
version : '42.10',
|
||||
license : 'GPL2+',
|
||||
meson_version : '>= 0.57.0'
|
||||
meson_version : '>= 0.53.0'
|
||||
)
|
||||
|
||||
control_center_prefix = get_option('prefix')
|
||||
@@ -25,19 +25,15 @@ host_is_linux_not_s390 = host_is_linux and not host_machine.cpu().contains('s390
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
# Tracing
|
||||
enable_tracing = get_option('tracing')
|
||||
|
||||
config_h = configuration_data()
|
||||
|
||||
py = import('python')
|
||||
python = py.find_installation('python3')
|
||||
|
||||
config_h.set_quoted('TEST_NM_PYTHON', python.full_path())
|
||||
|
||||
if get_option('profile') == 'development'
|
||||
profile = 'Devel'
|
||||
else
|
||||
profile = ''
|
||||
endif
|
||||
application_id = 'org.gnome.Settings@0@'.format(profile)
|
||||
config_h.set_quoted('TEST_NM_PYTHON', python.path())
|
||||
|
||||
# defines
|
||||
set_defines = [
|
||||
@@ -54,17 +50,6 @@ foreach define: set_defines
|
||||
config_h.set_quoted(define[0], define[1])
|
||||
endforeach
|
||||
|
||||
distributor_logo = get_option('distributor_logo')
|
||||
if (distributor_logo != '')
|
||||
config_h.set_quoted('DISTRIBUTOR_LOGO', distributor_logo,
|
||||
description: 'Define to absolute path of distributor logo')
|
||||
dark_mode_distributor_logo = get_option('dark_mode_distributor_logo')
|
||||
if (dark_mode_distributor_logo != '')
|
||||
config_h.set_quoted('DARK_MODE_DISTRIBUTOR_LOGO', dark_mode_distributor_logo,
|
||||
description: 'Define to absolute path of distributor logo for use in dark mode')
|
||||
endif
|
||||
endif
|
||||
|
||||
# meson does not support octal values, so it must be handled as a
|
||||
# string. See: https://github.com/mesonbuild/meson/issues/2047
|
||||
config_h.set('USER_DIR_MODE', '0700',
|
||||
@@ -117,44 +102,18 @@ libgvc_dep = libgvc.get_variable('libgvc_dep')
|
||||
goa_req_version = '>= 3.25.3'
|
||||
pulse_req_version = '>= 2.0'
|
||||
|
||||
gtk_dep = dependency(
|
||||
'gtk4',
|
||||
version: '>= 4.11.2',
|
||||
fallback: ['gtk', 'gtk_dep'],
|
||||
default_options: [
|
||||
'introspection=disabled',
|
||||
'demos=false',
|
||||
'build-testsuite=false',
|
||||
'build-tests=false',
|
||||
'build-examples=false',
|
||||
]
|
||||
)
|
||||
|
||||
libadwaita_dep = dependency(
|
||||
'libadwaita-1',
|
||||
version: '>= 1.4.alpha',
|
||||
required: false
|
||||
version: '>= 1.1',
|
||||
fallback: ['libadwaita', 'libadwaita_dep'],
|
||||
default_options: ['examples=false', 'introspection=disabled', 'tests=false', 'vapi=false'],
|
||||
)
|
||||
# FIXME: this is a workaround because interactive-tests don't work with libadwaita as a subproject. See !1754
|
||||
libadwaita_is_subproject = not libadwaita_dep.found()
|
||||
if libadwaita_is_subproject
|
||||
libadwaita = subproject(
|
||||
'libadwaita',
|
||||
default_options: [
|
||||
'examples=false',
|
||||
'introspection=disabled',
|
||||
'tests=false',
|
||||
'vapi=false',
|
||||
],
|
||||
)
|
||||
libadwaita_dep = libadwaita.get_variable('libadwaita_dep')
|
||||
endif
|
||||
|
||||
accounts_dep = dependency('accountsservice', version: '>= 0.6.39')
|
||||
colord_dep = dependency('colord', version: '>= 0.1.34')
|
||||
gdk_pixbuf_dep = dependency('gdk-pixbuf-2.0', version: '>= 2.23.0')
|
||||
gio_dep = dependency('gio-2.0')
|
||||
glib_dep = dependency('glib-2.0', version: '>= 2.75.0')
|
||||
glib_dep = dependency('glib-2.0', version: '>= 2.68.0')
|
||||
gnome_desktop_dep = dependency('gnome-desktop-4')
|
||||
gnome_bg_dep = dependency('gnome-bg-4')
|
||||
gnome_rr_dep = dependency('gnome-rr-4')
|
||||
@@ -166,7 +125,7 @@ pulse_dep = dependency('libpulse', version: pulse_req_version)
|
||||
pulse_mainloop_dep = dependency('libpulse-mainloop-glib', version: pulse_req_version)
|
||||
upower_glib_dep = dependency('upower-glib', version: '>= 0.99.8')
|
||||
gudev_dep = dependency('gudev-1.0', version: '>= 232')
|
||||
x11_dep = dependency('x11', version: '>= 1.8')
|
||||
x11_dep = dependency('x11')
|
||||
xi_dep = dependency('xi', version: '>= 1.2')
|
||||
epoxy_dep = dependency('epoxy')
|
||||
gcr_dep = dependency('gcr-base-3')
|
||||
@@ -181,7 +140,7 @@ common_deps = [
|
||||
libadwaita_dep,
|
||||
dependency('gio-unix-2.0'),
|
||||
dependency('gthread-2.0'),
|
||||
gtk_dep,
|
||||
dependency('gtk4', version: '>= 4.4'),
|
||||
]
|
||||
|
||||
polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.103')
|
||||
@@ -234,7 +193,7 @@ config_h.set10('HAVE_FN_EXPLICIT_BZERO',
|
||||
enable_snap = get_option('snap')
|
||||
if enable_snap
|
||||
snapd_glib_deps = [
|
||||
dependency('snapd-glib-2', version: '>= 1.62')
|
||||
dependency('snapd-glib', version: '>= 1.57')
|
||||
]
|
||||
endif
|
||||
config_h.set('HAVE_SNAP', enable_snap,
|
||||
@@ -251,13 +210,11 @@ config_h.set('HAVE_MALCONTENT', enable_malcontent,
|
||||
description: 'Define to 1 if malcontent support is enabled')
|
||||
|
||||
if host_is_linux
|
||||
# ModemManager
|
||||
mm_dep = dependency('mm-glib', version: '>= 0.7')
|
||||
# NetworkManager
|
||||
# network manager
|
||||
network_manager_deps = [
|
||||
dependency('libnm', version: '>= 1.24.0'),
|
||||
dependency('libnma-gtk4', version: '>= 1.10.2'),
|
||||
mm_dep,
|
||||
dependency('libnma-gtk4', version: '>= 1.8.0'),
|
||||
dependency('mm-glib', version: '>= 0.7')
|
||||
]
|
||||
endif
|
||||
config_h.set('BUILD_NETWORK', host_is_linux,
|
||||
@@ -299,8 +256,11 @@ gnome = import('gnome')
|
||||
i18n = import('i18n')
|
||||
pkg = import('pkgconfig')
|
||||
|
||||
po_dir = join_paths(meson.project_source_root(), 'po')
|
||||
its_dir = join_paths(meson.project_source_root(), 'gettext')
|
||||
desktop_conf = configuration_data()
|
||||
desktop_conf.set('VERSION', meson.project_version())
|
||||
|
||||
po_dir = join_paths(meson.source_root(), 'po')
|
||||
its_dir = join_paths(meson.source_root(), 'gettext')
|
||||
|
||||
install_subdir(
|
||||
'gettext',
|
||||
@@ -310,6 +270,7 @@ install_subdir(
|
||||
top_inc = include_directories('.')
|
||||
shell_inc = include_directories('shell')
|
||||
|
||||
subdir('build-aux')
|
||||
subdir('data/icons')
|
||||
subdir('po')
|
||||
subdir('panels')
|
||||
@@ -324,11 +285,6 @@ if get_option('documentation')
|
||||
subdir('man')
|
||||
endif
|
||||
|
||||
gnome.post_install(
|
||||
glib_compile_schemas: true,
|
||||
gtk_update_icon_cache: true,
|
||||
)
|
||||
|
||||
configure_file(
|
||||
output: 'config.h',
|
||||
configuration: config_h
|
||||
@@ -337,6 +293,7 @@ configure_file(
|
||||
summary({
|
||||
'Documentation': get_option('documentation'),
|
||||
'Tests': get_option('tests'),
|
||||
'Tracing': enable_tracing,
|
||||
'Optimized': control_center_optimized,
|
||||
})
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@ option('ibus', type: 'boolean', value: true, description: 'build with IBus suppo
|
||||
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')
|
||||
option('distributor_logo', type: 'string', description: 'absolute path to distributor logo for the About panel')
|
||||
option('dark_mode_distributor_logo', type: 'string', description: 'absolute path to distributor logo dark mode variant')
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
<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>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "cc-applications-panel.h"
|
||||
#include "cc-applications-row.h"
|
||||
#include "cc-toggle-row.h"
|
||||
#include "cc-info-row.h"
|
||||
#include "cc-applications-resources.h"
|
||||
#include "cc-util.h"
|
||||
@@ -92,24 +93,23 @@ struct _CcApplicationsPanel
|
||||
GtkButton *install_button;
|
||||
|
||||
AdwPreferencesGroup *integration_section;
|
||||
AdwSwitchRow *notification;
|
||||
AdwSwitchRow *background;
|
||||
AdwSwitchRow *wallpaper;
|
||||
AdwSwitchRow *screenshot;
|
||||
AdwSwitchRow *sound;
|
||||
CcToggleRow *notification;
|
||||
CcToggleRow *background;
|
||||
CcToggleRow *wallpaper;
|
||||
CcToggleRow *sound;
|
||||
CcInfoRow *no_sound;
|
||||
AdwSwitchRow *search;
|
||||
CcToggleRow *search;
|
||||
CcInfoRow *no_search;
|
||||
AdwSwitchRow *camera;
|
||||
CcToggleRow *camera;
|
||||
CcInfoRow *no_camera;
|
||||
AdwSwitchRow *location;
|
||||
CcToggleRow *location;
|
||||
CcInfoRow *no_location;
|
||||
AdwSwitchRow *shortcuts;
|
||||
AdwSwitchRow *microphone;
|
||||
CcToggleRow *shortcuts;
|
||||
CcToggleRow *microphone;
|
||||
CcInfoRow *no_microphone;
|
||||
CcInfoRow *builtin;
|
||||
GtkDialog *builtin_dialog;
|
||||
AdwPreferencesPage *builtin_page;
|
||||
AdwPreferencesGroup *builtin_group;
|
||||
GtkListBox *builtin_list;
|
||||
#ifdef HAVE_SNAP
|
||||
GList *snap_permission_rows;
|
||||
@@ -117,8 +117,8 @@ struct _CcApplicationsPanel
|
||||
|
||||
GtkButton *handler_reset;
|
||||
GtkDialog *handler_dialog;
|
||||
AdwPreferencesPage *handler_page;
|
||||
CcInfoRow *handler_row;
|
||||
GtkLabel *handler_title_label;
|
||||
AdwPreferencesGroup *handler_file_group;
|
||||
AdwPreferencesGroup *handler_link_group;
|
||||
GList *file_handler_rows;
|
||||
@@ -376,7 +376,7 @@ search_cb (CcApplicationsPanel *self)
|
||||
if (self->current_app_id)
|
||||
set_search_enabled (self,
|
||||
self->current_app_id,
|
||||
adw_switch_row_get_active (self->search));
|
||||
cc_toggle_row_get_allowed (self->search));
|
||||
}
|
||||
|
||||
/* --- notification permissions (flatpaks and non-flatpak) --- */
|
||||
@@ -424,7 +424,7 @@ static void
|
||||
notification_cb (CcApplicationsPanel *self)
|
||||
{
|
||||
if (self->current_app_id)
|
||||
set_notification_allowed (self, adw_switch_row_get_active (self->notification));
|
||||
set_notification_allowed (self, cc_toggle_row_get_allowed (self->notification));
|
||||
}
|
||||
|
||||
static gchar *
|
||||
@@ -481,7 +481,7 @@ static void
|
||||
background_cb (CcApplicationsPanel *self)
|
||||
{
|
||||
if (self->current_app_id)
|
||||
set_background_allowed (self, adw_switch_row_get_active (self->background));
|
||||
set_background_allowed (self, cc_toggle_row_get_allowed (self->background));
|
||||
}
|
||||
|
||||
/* --- wallpaper --- */
|
||||
@@ -512,38 +512,7 @@ static void
|
||||
wallpaper_cb (CcApplicationsPanel *self)
|
||||
{
|
||||
if (self->current_app_id)
|
||||
set_wallpaper_allowed (self, adw_switch_row_get_active (self->wallpaper));
|
||||
}
|
||||
|
||||
/* --- screenshot --- */
|
||||
|
||||
static void
|
||||
get_screenshot_allowed (CcApplicationsPanel *self,
|
||||
const gchar *app_id,
|
||||
gboolean *set,
|
||||
gboolean *allowed)
|
||||
{
|
||||
g_auto(GStrv) perms = get_portal_permissions (self, "screenshot", "screenshot", app_id);
|
||||
|
||||
*set = perms != NULL;
|
||||
*allowed = perms == NULL || strcmp (perms[0], "no") != 0;
|
||||
}
|
||||
|
||||
static void
|
||||
set_screenshot_allowed (CcApplicationsPanel *self,
|
||||
gboolean allowed)
|
||||
{
|
||||
const gchar *perms[2] = { NULL, NULL };
|
||||
|
||||
perms[0] = allowed ? "yes" : "no";
|
||||
set_portal_permissions (self, "screenshot", "screenshot", self->current_app_id, perms);
|
||||
}
|
||||
|
||||
static void
|
||||
screenshot_cb (CcApplicationsPanel *self)
|
||||
{
|
||||
if (self->current_app_id)
|
||||
set_screenshot_allowed (self, adw_switch_row_get_active (self->screenshot));
|
||||
set_wallpaper_allowed (self, cc_toggle_row_get_allowed (self->wallpaper));
|
||||
}
|
||||
|
||||
/* --- shortcuts permissions (flatpak) --- */
|
||||
@@ -575,7 +544,7 @@ set_shortcuts_allowed (CcApplicationsPanel *self,
|
||||
|
||||
/* "GRANTED" and "DENIED" here match the values set by the "inhibit shortcut
|
||||
* dialog" is GNOME Shell:
|
||||
* https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/inhibitShortcutsDialog.js
|
||||
* https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/master/js/ui/inhibitShortcutsDialog.js
|
||||
*/
|
||||
perms[0] = granted ? "GRANTED" : "DENIED";
|
||||
perms[1] = NULL;
|
||||
@@ -587,7 +556,7 @@ static void
|
||||
shortcuts_cb (CcApplicationsPanel *self)
|
||||
{
|
||||
if (self->current_app_id)
|
||||
set_shortcuts_allowed (self, adw_switch_row_get_active (self->shortcuts));
|
||||
set_shortcuts_allowed (self, cc_toggle_row_get_allowed (self->shortcuts));
|
||||
}
|
||||
|
||||
/* --- device (microphone, camera, speaker) permissions (flatpak) --- */
|
||||
@@ -624,21 +593,21 @@ static void
|
||||
microphone_cb (CcApplicationsPanel *self)
|
||||
{
|
||||
if (self->current_portal_app_id)
|
||||
set_device_allowed (self, "microphone", adw_switch_row_get_active (self->microphone));
|
||||
set_device_allowed (self, "microphone", cc_toggle_row_get_allowed (self->microphone));
|
||||
}
|
||||
|
||||
static void
|
||||
sound_cb (CcApplicationsPanel *self)
|
||||
{
|
||||
if (self->current_portal_app_id)
|
||||
set_device_allowed (self, "speakers", adw_switch_row_get_active (self->sound));
|
||||
set_device_allowed (self, "speakers", cc_toggle_row_get_allowed (self->sound));
|
||||
}
|
||||
|
||||
static void
|
||||
camera_cb (CcApplicationsPanel *self)
|
||||
{
|
||||
if (self->current_portal_app_id)
|
||||
set_device_allowed (self, "camera", adw_switch_row_get_active (self->camera));
|
||||
set_device_allowed (self, "camera", cc_toggle_row_get_allowed (self->camera));
|
||||
}
|
||||
|
||||
/* --- location permissions (flatpak) --- */
|
||||
@@ -675,7 +644,7 @@ static void
|
||||
location_cb (CcApplicationsPanel *self)
|
||||
{
|
||||
if (self->current_portal_app_id)
|
||||
set_location_allowed (self, adw_switch_row_get_active (self->location));
|
||||
set_location_allowed (self, cc_toggle_row_get_allowed (self->location));
|
||||
}
|
||||
|
||||
/* --- permissions section --- */
|
||||
@@ -846,8 +815,8 @@ add_static_permissions (CcApplicationsPanel *self,
|
||||
if (str && g_str_equal (str, "talk"))
|
||||
added += add_static_permission_row (self, _("Settings"), _("Can change settings"));
|
||||
|
||||
text = g_strdup_printf (_("<b>%s</b> requires access to the following system resources. To stop this access, the app must be removed."), g_app_info_get_display_name (info));
|
||||
adw_preferences_page_set_description (self->builtin_page, text);
|
||||
text = g_strdup_printf (_("%s has the following permissions built-in. These cannot be altered. If you are concerned about these permissions, consider removing this application."), g_app_info_get_display_name (info));
|
||||
adw_preferences_group_set_description (self->builtin_group, text);
|
||||
|
||||
return added > 0;
|
||||
}
|
||||
@@ -887,7 +856,7 @@ update_integration_section (CcApplicationsPanel *self,
|
||||
|
||||
disabled = g_settings_get_boolean (self->search_settings, "disable-external");
|
||||
get_search_enabled (self, app_id, &set, &allowed);
|
||||
adw_switch_row_set_active (self->search, allowed);
|
||||
cc_toggle_row_set_allowed (self->search, allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->search), set && !disabled);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->no_search), set && disabled);
|
||||
|
||||
@@ -896,11 +865,11 @@ update_integration_section (CcApplicationsPanel *self,
|
||||
g_autofree gchar *desktop_id = g_strconcat (app_id, ".desktop", NULL);
|
||||
get_shortcuts_allowed (self, desktop_id, &set, &allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->shortcuts), set);
|
||||
adw_switch_row_set_active (self->shortcuts, allowed);
|
||||
cc_toggle_row_set_allowed (self->shortcuts, allowed);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->shortcuts), FALSE);
|
||||
gtk_widget_hide (GTK_WIDGET (self->shortcuts));
|
||||
}
|
||||
|
||||
#ifdef HAVE_SNAP
|
||||
@@ -911,48 +880,43 @@ update_integration_section (CcApplicationsPanel *self,
|
||||
{
|
||||
g_clear_object (&self->notification_settings);
|
||||
get_notification_allowed (self, portal_app_id, &set, &allowed);
|
||||
adw_switch_row_set_active (self->notification, allowed);
|
||||
cc_toggle_row_set_allowed (self->notification, allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->notification), set);
|
||||
has_any |= set;
|
||||
|
||||
get_background_allowed (self, portal_app_id, &set, &allowed);
|
||||
adw_switch_row_set_active (self->background, allowed);
|
||||
cc_toggle_row_set_allowed (self->background, allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->background), set);
|
||||
has_any |= set;
|
||||
|
||||
get_wallpaper_allowed (self, portal_app_id, &set, &allowed);
|
||||
adw_switch_row_set_active (self->wallpaper, allowed);
|
||||
cc_toggle_row_set_allowed (self->wallpaper, allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->wallpaper), set);
|
||||
has_any |= set;
|
||||
|
||||
get_screenshot_allowed (self, portal_app_id, &set, &allowed);
|
||||
adw_switch_row_set_active (self->screenshot, allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->screenshot), set);
|
||||
has_any |= set;
|
||||
|
||||
disabled = g_settings_get_boolean (self->privacy_settings, "disable-sound-output");
|
||||
get_device_allowed (self, "speakers", portal_app_id, &set, &allowed);
|
||||
adw_switch_row_set_active (self->sound, allowed);
|
||||
cc_toggle_row_set_allowed (self->sound, allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->sound), set && !disabled);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->no_sound), set && disabled);
|
||||
|
||||
disabled = g_settings_get_boolean (self->privacy_settings, "disable-camera");
|
||||
get_device_allowed (self, "camera", portal_app_id, &set, &allowed);
|
||||
adw_switch_row_set_active (self->camera, allowed);
|
||||
cc_toggle_row_set_allowed (self->camera, allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->camera), set && !disabled);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->no_camera), set && disabled);
|
||||
has_any |= set;
|
||||
|
||||
disabled = g_settings_get_boolean (self->privacy_settings, "disable-microphone");
|
||||
get_device_allowed (self, "microphone", portal_app_id, &set, &allowed);
|
||||
adw_switch_row_set_active (self->microphone, allowed);
|
||||
cc_toggle_row_set_allowed (self->microphone, allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->microphone), set && !disabled);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->no_microphone), set && disabled);
|
||||
has_any |= set;
|
||||
|
||||
disabled = !g_settings_get_boolean (self->location_settings, "enabled");
|
||||
get_location_allowed (self, portal_app_id, &set, &allowed);
|
||||
adw_switch_row_set_active (self->location, allowed);
|
||||
cc_toggle_row_set_allowed (self->location, allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->location), set && !disabled);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->no_location), set && disabled);
|
||||
has_any |= set;
|
||||
@@ -965,21 +929,20 @@ update_integration_section (CcApplicationsPanel *self,
|
||||
{
|
||||
g_set_object (&self->notification_settings, get_notification_settings (app_id));
|
||||
get_notification_allowed (self, app_id, &set, &allowed);
|
||||
adw_switch_row_set_active (self->notification, allowed);
|
||||
cc_toggle_row_set_allowed (self->notification, allowed);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->notification), set);
|
||||
has_any |= set;
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->background), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->wallpaper), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->screenshot), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->sound), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->no_sound), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->camera), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->no_camera), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->microphone), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->no_microphone), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->location), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->no_location), FALSE);
|
||||
gtk_widget_hide (GTK_WIDGET (self->background));
|
||||
gtk_widget_hide (GTK_WIDGET (self->wallpaper));
|
||||
gtk_widget_hide (GTK_WIDGET (self->sound));
|
||||
gtk_widget_hide (GTK_WIDGET (self->no_sound));
|
||||
gtk_widget_hide (GTK_WIDGET (self->camera));
|
||||
gtk_widget_hide (GTK_WIDGET (self->no_camera));
|
||||
gtk_widget_hide (GTK_WIDGET (self->microphone));
|
||||
gtk_widget_hide (GTK_WIDGET (self->no_microphone));
|
||||
gtk_widget_hide (GTK_WIDGET (self->location));
|
||||
gtk_widget_hide (GTK_WIDGET (self->no_location));
|
||||
}
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->integration_section), has_any);
|
||||
@@ -1028,7 +991,7 @@ add_scheme (CcApplicationsPanel *self,
|
||||
g_object_set_data_full (G_OBJECT (button), "type", g_strdup (type), g_free);
|
||||
g_signal_connect_object (button, "clicked", G_CALLBACK (unset_cb), self, G_CONNECT_SWAPPED);
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->handler_link_group), TRUE);
|
||||
gtk_widget_show (GTK_WIDGET (self->handler_link_group));
|
||||
adw_preferences_group_add (self->handler_link_group, GTK_WIDGET (row));
|
||||
|
||||
self->link_handler_rows = g_list_prepend (self->link_handler_rows, row);
|
||||
@@ -1060,7 +1023,7 @@ add_file_type (CcApplicationsPanel *self,
|
||||
g_object_set_data_full (G_OBJECT (button), "type", g_strdup (type), g_free);
|
||||
g_signal_connect_object (button, "clicked", G_CALLBACK (unset_cb), self, G_CONNECT_SWAPPED);
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->handler_file_group), TRUE);
|
||||
gtk_widget_show (GTK_WIDGET (self->handler_file_group));
|
||||
adw_preferences_group_add (self->handler_file_group, GTK_WIDGET (row));
|
||||
|
||||
self->file_handler_rows = g_list_prepend (self->file_handler_rows, row);
|
||||
@@ -1070,7 +1033,7 @@ static void
|
||||
add_handler_row (CcApplicationsPanel *self,
|
||||
const gchar *type)
|
||||
{
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->handler_row), TRUE);
|
||||
gtk_widget_show (GTK_WIDGET (self->handler_row));
|
||||
|
||||
if (g_content_type_is_a (type, "x-scheme-handler/*"))
|
||||
add_scheme (self, type);
|
||||
@@ -1153,9 +1116,9 @@ update_handler_dialog (CcApplicationsPanel *self,
|
||||
|
||||
remove_all_handler_rows (self);
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->handler_row), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->handler_file_group), FALSE);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->handler_link_group), FALSE);
|
||||
gtk_widget_hide (GTK_WIDGET (self->handler_row));
|
||||
gtk_widget_hide (GTK_WIDGET (self->handler_file_group));
|
||||
gtk_widget_hide (GTK_WIDGET (self->handler_link_group));
|
||||
|
||||
types = g_app_info_get_supported_types (info);
|
||||
if (types == NULL || types[0] == NULL)
|
||||
@@ -1197,13 +1160,14 @@ update_handler_dialog (CcApplicationsPanel *self,
|
||||
|
||||
header_title = g_strdup_printf (_("<b>%s</b> is used to open the following types of files and links."),
|
||||
g_app_info_get_display_name (info));
|
||||
adw_preferences_page_set_description (self->handler_page, header_title);
|
||||
gtk_label_set_markup (self->handler_title_label, header_title);
|
||||
}
|
||||
|
||||
/* --- usage section --- */
|
||||
|
||||
static void
|
||||
on_builtin_row_activated_cb (CcApplicationsPanel *self)
|
||||
on_builtin_row_activated_cb (GtkListBoxRow *row,
|
||||
CcApplicationsPanel *self)
|
||||
{
|
||||
CcShell *shell = cc_panel_get_shell (CC_PANEL (self));
|
||||
|
||||
@@ -1213,7 +1177,8 @@ on_builtin_row_activated_cb (CcApplicationsPanel *self)
|
||||
}
|
||||
|
||||
static void
|
||||
on_handler_row_activated_cb (CcApplicationsPanel *self)
|
||||
on_handler_row_activated_cb (GtkListBoxRow *row,
|
||||
CcApplicationsPanel *self)
|
||||
{
|
||||
CcShell *shell = cc_panel_get_shell (CC_PANEL (self));
|
||||
|
||||
@@ -1223,7 +1188,8 @@ on_handler_row_activated_cb (CcApplicationsPanel *self)
|
||||
}
|
||||
|
||||
static void
|
||||
on_storage_row_activated_cb (CcApplicationsPanel *self)
|
||||
on_storage_row_activated_cb (GtkListBoxRow *row,
|
||||
CcApplicationsPanel *self)
|
||||
{
|
||||
CcShell *shell = cc_panel_get_shell (CC_PANEL (self));
|
||||
|
||||
@@ -1244,7 +1210,7 @@ update_total_size (CcApplicationsPanel *self)
|
||||
g_object_set (self->total, "info", formatted_size, NULL);
|
||||
|
||||
/* Translators: '%s' is the formatted size, e.g. "26.2 MB" */
|
||||
subtitle = g_strdup_printf (_("%s of disk space used."), formatted_size);
|
||||
subtitle = g_strdup_printf (_("%s of disk space used"), formatted_size);
|
||||
g_object_set (self->storage, "subtitle", subtitle, NULL);
|
||||
}
|
||||
|
||||
@@ -1408,9 +1374,9 @@ update_panel (CcApplicationsPanel *self,
|
||||
|
||||
if (row == NULL)
|
||||
{
|
||||
adw_window_title_set_title (self->header_title, _("Apps"));
|
||||
adw_window_title_set_title (self->header_title, _("Applications"));
|
||||
gtk_stack_set_visible_child (self->stack, self->empty_box);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->view_details_button), FALSE);
|
||||
gtk_widget_hide (GTK_WIDGET (GTK_WIDGET (self->view_details_button)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1575,7 +1541,8 @@ select_app (CcApplicationsPanel *self,
|
||||
}
|
||||
|
||||
static void
|
||||
on_launch_button_clicked_cb (CcApplicationsPanel *self)
|
||||
on_launch_button_clicked_cb (GtkButton *button,
|
||||
CcApplicationsPanel *self)
|
||||
{
|
||||
g_autoptr(GdkAppLaunchContext) context = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
@@ -1750,7 +1717,7 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app_name_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_dialog);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_page);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_group);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_list);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, cache);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, camera);
|
||||
@@ -1758,11 +1725,11 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, data);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, empty_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_dialog);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_page);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_file_group);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_link_group);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_reset);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_title_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, header_title);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, install_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, integration_section);
|
||||
@@ -1777,7 +1744,6 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, notification);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, background);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, wallpaper);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, screenshot);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, shortcuts);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sidebar_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sidebar_listbox);
|
||||
@@ -1799,7 +1765,6 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
|
||||
gtk_widget_class_bind_template_callback (widget_class, notification_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, background_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, wallpaper_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, screenshot_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, shortcuts_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, privacy_link_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, sound_cb);
|
||||
@@ -1825,6 +1790,7 @@ cc_applications_panel_init (CcApplicationsPanel *self)
|
||||
|
||||
g_resources_register (cc_applications_get_resource ());
|
||||
|
||||
g_type_ensure(CC_TYPE_TOGGLE_ROW);
|
||||
g_type_ensure(CC_TYPE_INFO_ROW);
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<child type="titlebar">
|
||||
<object class="AdwHeaderBar">
|
||||
<property name="show-end-title-buttons">True</property>
|
||||
<property name="show-start-title-buttons" bind-source="CcApplicationsPanel" bind-property="folded" bind-flags="default|sync-create" />
|
||||
<property name="show-start-title-buttons">False</property>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="visible" bind-source="CcApplicationsPanel" bind-property="folded" bind-flags="default|sync-create" />
|
||||
@@ -16,7 +16,7 @@
|
||||
</child>
|
||||
<property name="title-widget">
|
||||
<object class="AdwWindowTitle" id="header_title">
|
||||
<property name="title" translatable="yes">Apps</property>
|
||||
<property name="title" translatable="yes">Applications</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
@@ -28,11 +28,10 @@
|
||||
<child>
|
||||
<object class="AdwStatusPage" id="empty_box">
|
||||
<property name="icon-name">org.gnome.Software-symbolic</property>
|
||||
<property name="title" translatable="yes">No Apps</property>
|
||||
<property name="title" translatable="yes">No applications</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="install_button">
|
||||
<property name="label" translatable="yes">_Install Some…</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="label" translatable="yes">Install some…</property>
|
||||
<property name="halign">center</property>
|
||||
<signal name="clicked" handler="open_software_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
<style>
|
||||
@@ -82,9 +81,8 @@
|
||||
<property name="spacing">18</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="launch_button">
|
||||
<property name="label" translatable="yes">_Open</property>
|
||||
<property name="use-underline">True</property>
|
||||
<signal name="clicked" handler="on_launch_button_clicked_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
<property name="label" translatable="yes">Open</property>
|
||||
<signal name="clicked" handler="on_launch_button_clicked_cb" object="CcApplicationsPanel" swapped="no" />
|
||||
<style>
|
||||
<class name="pill" />
|
||||
<class name="suggested-action" />
|
||||
@@ -93,8 +91,7 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="view_details_button">
|
||||
<property name="label" translatable="yes">App _Details</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="label" translatable="yes">View Details</property>
|
||||
<style>
|
||||
<class name="pill" />
|
||||
</style>
|
||||
@@ -111,107 +108,100 @@
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup" id="integration_section">
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="search">
|
||||
<object class="CcToggleRow" id="search">
|
||||
<property name="title" translatable="yes">Search</property>
|
||||
<property name="subtitle" translatable="yes">Receive system searches and send results</property>
|
||||
<signal name="notify::active" handler="search_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
<property name="subtitle" translatable="yes">Receive system searches and send results.</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="subtitle" translatable="yes">Receive system searches and send results</property>
|
||||
<property name="subtitle" translatable="yes">Receive system searches and send results.</property>
|
||||
<property name="info" translatable="yes">Disabled</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="notification">
|
||||
<object class="CcToggleRow" id="notification">
|
||||
<property name="title" translatable="yes">Notifications</property>
|
||||
<property name="subtitle" translatable="yes">Show system notifications</property>
|
||||
<signal name="notify::active" handler="notification_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
<property name="subtitle" translatable="yes">Show system notifications.</property>
|
||||
<signal name="notify::allowed" handler="notification_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="background">
|
||||
<property name="title" translatable="yes">Run in Background</property>
|
||||
<property name="subtitle" translatable="yes">Allow activity when the app is closed</property>
|
||||
<signal name="notify::active" handler="background_cb" swapped="yes"/>
|
||||
<object class="CcToggleRow" id="background">
|
||||
<property name="title" translatable="yes">Run in background</property>
|
||||
<property name="subtitle" translatable="yes">Allow activity when the app is closed.</property>
|
||||
<signal name="notify::allowed" handler="background_cb" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="screenshot">
|
||||
<property name="title" translatable="yes">Screenshots</property>
|
||||
<property name="subtitle" translatable="yes">Take pictures of the screen at any time</property>
|
||||
<signal name="notify::active" handler="screenshot_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="wallpaper">
|
||||
<object class="CcToggleRow" id="wallpaper">
|
||||
<property name="title" translatable="yes">Change Wallpaper</property>
|
||||
<property name="subtitle" translatable="yes">Change the desktop wallpaper.</property>
|
||||
<signal name="notify::active" handler="wallpaper_cb" swapped="yes"/>
|
||||
<signal name="notify::allowed" handler="wallpaper_cb" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="sound">
|
||||
<object class="CcToggleRow" id="sound">
|
||||
<property name="title" translatable="yes">Sounds</property>
|
||||
<property name="subtitle" translatable="yes">Reproduce sounds.</property>
|
||||
<signal name="notify::active" handler="sound_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
<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="subtitle" translatable="yes">Reproduce sounds</property>
|
||||
<property name="subtitle" translatable="yes">Reproduce sounds.</property>
|
||||
<property name="info" translatable="yes">Disabled</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="shortcuts">
|
||||
<object class="CcToggleRow" id="shortcuts">
|
||||
<property name="title" translatable="yes">Inhibit Shortcuts</property>
|
||||
<property name="subtitle" translatable="yes">Block standard keyboard shortcuts</property>
|
||||
<signal name="notify::active" handler="shortcuts_cb" swapped="yes"/>
|
||||
<property name="subtitle" translatable="yes">Block standard keyboard shortcuts.</property>
|
||||
<signal name="notify::allowed" handler="shortcuts_cb" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="camera">
|
||||
<object class="CcToggleRow" id="camera">
|
||||
<property name="title" translatable="yes">Camera</property>
|
||||
<property name="subtitle" translatable="yes">Take pictures with the camera</property>
|
||||
<signal name="notify::active" handler="camera_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
<property name="subtitle" translatable="yes">Take pictures with the 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="subtitle" translatable="yes">Take pictures with the camera</property>
|
||||
<property name="subtitle" translatable="yes">Take pictures with the camera.</property>
|
||||
<property name="info" translatable="yes">Disabled</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="microphone">
|
||||
<object class="CcToggleRow" id="microphone">
|
||||
<property name="title" translatable="yes">Microphone</property>
|
||||
<property name="subtitle" translatable="yes">Record audio with the microphone</property>
|
||||
<signal name="notify::active" handler="microphone_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
<property name="subtitle" translatable="yes">Record audio with the 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="subtitle" translatable="yes">Record audio with the microphone</property>
|
||||
<property name="subtitle" translatable="yes">Record audio with the microphone.</property>
|
||||
<property name="info" translatable="yes">Disabled</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="location">
|
||||
<object class="CcToggleRow" id="location">
|
||||
<property name="title" translatable="yes">Location Services</property>
|
||||
<property name="subtitle" translatable="yes">Access device location data</property>
|
||||
<signal name="notify::active" handler="location_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
<property name="subtitle" translatable="yes">Access device location data.</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="subtitle" translatable="yes">Access device location data</property>
|
||||
<property name="subtitle" translatable="yes">Access device location data.</property>
|
||||
<property name="info" translatable="yes">Disabled</property>
|
||||
</object>
|
||||
</child>
|
||||
@@ -222,11 +212,11 @@
|
||||
<object class="AdwPreferencesGroup" id="usage_section">
|
||||
<child>
|
||||
<object class="CcInfoRow" id="builtin">
|
||||
<property name="title" translatable="yes">Required Access</property>
|
||||
<property name="title" translatable="yes">Built-in Permissions</property>
|
||||
<property name="subtitle" translatable="yes">System access that is required by the app</property>
|
||||
<property name="has-expander">True</property>
|
||||
<property name="is-link">True</property>
|
||||
<signal name="activated" handler="on_builtin_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
<signal name="activated" handler="on_builtin_row_activated_cb" object="CcApplicationsPanel" swapped="no" />
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -234,7 +224,7 @@
|
||||
<property name="title" translatable="yes">File &amp; Link Associations</property>
|
||||
<property name="has-expander">True</property>
|
||||
<property name="is-link">True</property>
|
||||
<signal name="activated" handler="on_handler_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
<signal name="activated" handler="on_handler_row_activated_cb" object="CcApplicationsPanel" swapped="no" />
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -242,7 +232,7 @@
|
||||
<property name="title" translatable="yes">Storage</property>
|
||||
<property name="has-expander">1</property>
|
||||
<property name="is-link">1</property>
|
||||
<signal name="activated" handler="on_storage_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
|
||||
<signal name="activated" handler="on_storage_row_activated_cb" object="CcApplicationsPanel" swapped="no" />
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -258,7 +248,6 @@
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="sidebar_search_entry">
|
||||
<property name="placeholder_text" translatable="yes">Search apps</property>
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<property name="margin-start">12</property>
|
||||
@@ -327,19 +316,15 @@
|
||||
|
||||
<!-- Built-in Permissions dialog -->
|
||||
<object class="GtkDialog" id="builtin_dialog">
|
||||
<property name="title" translatable="yes">Required Access</property>
|
||||
<property name="title" translatable="yes">Built-in Permissions</property>
|
||||
<property name="modal">1</property>
|
||||
<property name="use-header-bar">1</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="hide-on-close">True</property>
|
||||
<property name="default-width">500</property>
|
||||
<property name="default-height">400</property>
|
||||
<property name="width-request">360</property>
|
||||
<property name="height-request">294</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesPage" id="builtin_page">
|
||||
<object class="AdwPreferencesPage">
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<object class="AdwPreferencesGroup" id="builtin_group">
|
||||
<child>
|
||||
<object class="GtkListBox" id="builtin_list">
|
||||
<property name="selection-mode">none</property>
|
||||
@@ -363,10 +348,19 @@
|
||||
<property name="hide-on-close">True</property>
|
||||
<property name="default-width">500</property>
|
||||
<property name="default-height">400</property>
|
||||
<property name="width-request">360</property>
|
||||
<property name="height-request">294</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesPage" id="handler_page">
|
||||
<object class="AdwPreferencesPage">
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="GtkLabel" id="handler_title_label">
|
||||
<property name="wrap">True</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup" id="handler_file_group">
|
||||
@@ -411,12 +405,12 @@
|
||||
<property name="default-height">420</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesPage">
|
||||
<property name="description" translatable="yes">How much disk space this app is occupying with app data and caches.</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="description" translatable="yes">How much disk space this application is occupying with app data and caches.</property>
|
||||
<child>
|
||||
<object class="CcInfoRow" id="app">
|
||||
<property name="title" translatable="yes">App</property>
|
||||
<property name="title" translatable="yes">Application</property>
|
||||
<property name="info">Unknown</property>
|
||||
</object>
|
||||
</child>
|
||||
@@ -444,8 +438,7 @@
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="GtkButton" id="clear_cache_button">
|
||||
<property name="label" translatable="yes">_Clear Cache…</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="label" translatable="yes">Clear Cache…</property>
|
||||
<signal name="clicked" handler="clear_cache_cb" object="CcApplicationsPanel" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
<template class="CcSnapRow" parent="AdwActionRow">
|
||||
<property name="can-focus">True</property>
|
||||
<property name="activatable">False</property>
|
||||
<property name="activatable-widget">slot_toggle</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="slot_toggle">
|
||||
<property name="valign">center</property>
|
||||
|
||||
130
panels/applications/cc-toggle-row.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/* 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
|
||||
{
|
||||
AdwActionRow parent;
|
||||
|
||||
GtkWidget *toggle;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcToggleRow, cc_toggle_row, ADW_TYPE_ACTION_ROW)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
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_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_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_ALLOWED,
|
||||
g_param_spec_boolean ("allowed", "allowed", "allowed",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
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));
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* Copyright 2022 Purism SPC
|
||||
* Copyright 2022 Mohammed Sadiq <sadiq@sadiqpk.org>
|
||||
/* 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
|
||||
@@ -16,25 +15,23 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author(s):
|
||||
* Mohammed Sadiq <sadiq@sadiqpk.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "tz.h"
|
||||
#include <adwaita.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_TZ_ITEM (cc_tz_item_get_type ())
|
||||
#define CC_TYPE_TOGGLE_ROW (cc_toggle_row_get_type())
|
||||
G_DECLARE_FINAL_TYPE (CcToggleRow, cc_toggle_row, CC, TOGGLE_ROW, AdwActionRow)
|
||||
|
||||
G_DECLARE_FINAL_TYPE (CcTzItem, cc_tz_item, CC, TZ_ITEM, GObject)
|
||||
CcToggleRow* cc_toggle_row_new (void);
|
||||
|
||||
CcTzItem *cc_tz_item_new (TzLocation *location);
|
||||
TzLocation *cc_tz_item_get_location (CcTzItem *self);
|
||||
void cc_toggle_row_set_allowed (CcToggleRow *row,
|
||||
gboolean allowed);
|
||||
|
||||
gboolean cc_toggle_row_get_allowed (CcToggleRow *row);
|
||||
|
||||
G_END_DECLS
|
||||
12
panels/applications/cc-toggle-row.ui
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcToggleRow" parent="AdwActionRow">
|
||||
<property name="activatable-widget">toggle</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="toggle">
|
||||
<property name="valign">center</property>
|
||||
<signal name="notify::active" handler="changed_cb" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Name=Apps
|
||||
Comment=Control various app permissions and settings
|
||||
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)!
|
||||
@@ -11,6 +11,6 @@ NoDisplay=true
|
||||
StartupNotify=true
|
||||
Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-AccountSettings;
|
||||
OnlyShowIn=GNOME;Unity;
|
||||
# Translators: Search terms to find the Apps panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
|
||||
# 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
|
||||
@@ -1,9 +1,15 @@
|
||||
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',
|
||||
input : desktop_in,
|
||||
output : desktop,
|
||||
po_dir : po_dir,
|
||||
install : true,
|
||||
@@ -13,17 +19,21 @@ i18n.merge_file(
|
||||
sources = files(
|
||||
'cc-applications-panel.c',
|
||||
'cc-applications-row.c',
|
||||
'cc-toggle-row.c',
|
||||
'cc-info-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,
|
||||
export : true
|
||||
c_name : 'cc_' + cappletname,
|
||||
dependencies : resource_data,
|
||||
export : true
|
||||
)
|
||||
|
||||
deps = common_deps
|
||||
|
||||
@@ -35,32 +35,6 @@ struct _BgWallpapersSource
|
||||
|
||||
G_DEFINE_TYPE (BgWallpapersSource, bg_wallpapers_source, BG_TYPE_SOURCE)
|
||||
|
||||
static int
|
||||
sort_func (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcBackgroundItem *item_a;
|
||||
CcBackgroundItem *item_b;
|
||||
const char *name_a;
|
||||
const char *name_b;
|
||||
|
||||
item_a = (CcBackgroundItem *) a;
|
||||
item_b = (CcBackgroundItem *) b;
|
||||
|
||||
name_a = cc_background_item_get_name (item_a);
|
||||
name_b = cc_background_item_get_name (item_b);
|
||||
|
||||
if (name_a && strcmp (name_a, "Default Background") == 0)
|
||||
return -1;
|
||||
if (name_b && strcmp (name_b, "Default Background") == 0)
|
||||
return 1;
|
||||
|
||||
|
||||
return strcmp (cc_background_item_get_name (item_a),
|
||||
cc_background_item_get_name (item_b));
|
||||
}
|
||||
|
||||
static void
|
||||
load_wallpapers (gchar *key,
|
||||
CcBackgroundItem *item,
|
||||
@@ -74,7 +48,7 @@ load_wallpapers (gchar *key,
|
||||
if (deleted)
|
||||
return;
|
||||
|
||||
g_list_store_insert_sorted (store, item, sort_func, NULL);
|
||||
g_list_store_append (store, item);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -157,10 +157,10 @@ create_widget_func (gpointer model_item,
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), check);
|
||||
if (button)
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), button);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (overlay),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL,
|
||||
cc_background_item_get_name (item),
|
||||
-1);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (overlay),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL,
|
||||
cc_background_item_get_name (item),
|
||||
-1);
|
||||
|
||||
|
||||
child = gtk_flow_box_child_new ();
|
||||
@@ -215,9 +215,9 @@ setup_flowbox (CcBackgroundChooser *self)
|
||||
}
|
||||
|
||||
static void
|
||||
on_item_activated_cb (CcBackgroundChooser *self,
|
||||
on_item_activated_cb (GtkFlowBox *flowbox,
|
||||
GtkFlowBoxChild *child,
|
||||
GtkFlowBox *flowbox)
|
||||
CcBackgroundChooser *self)
|
||||
{
|
||||
self->recent_selected = flowbox == self->recent_flowbox;
|
||||
if (self->recent_selected)
|
||||
@@ -228,31 +228,26 @@ on_item_activated_cb (CcBackgroundChooser *self,
|
||||
}
|
||||
|
||||
static void
|
||||
file_dialog_open_cb (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
on_file_chooser_response_cb (GtkDialog *filechooser,
|
||||
gint response,
|
||||
CcBackgroundChooser *self)
|
||||
{
|
||||
CcBackgroundChooser *self = CC_BACKGROUND_CHOOSER (user_data);
|
||||
GtkFileDialog *file_dialog = GTK_FILE_DIALOG (source_object);
|
||||
g_autoptr(GListModel) files = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
guint i;
|
||||
|
||||
files = gtk_file_dialog_open_multiple_finish (file_dialog, res, &error);
|
||||
|
||||
if (error != NULL)
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
g_warning ("Failed to pick backgrounds: %s", error->message);
|
||||
return;
|
||||
g_autoptr(GListModel) files = NULL;
|
||||
guint i;
|
||||
|
||||
files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (filechooser));
|
||||
for (i = 0; i < g_list_model_get_n_items (files); i++)
|
||||
{
|
||||
g_autoptr(GFile) file = g_list_model_get_item (files, i);
|
||||
g_autofree gchar *filename = g_file_get_path (file);
|
||||
|
||||
bg_recent_source_add_file (self->recent_source, filename);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (files); i++)
|
||||
{
|
||||
g_autoptr(GFile) file = g_list_model_get_item (files, i);
|
||||
g_autofree gchar *filename = g_file_get_path (file);
|
||||
|
||||
bg_recent_source_add_file (self->recent_source, filename);
|
||||
}
|
||||
gtk_window_destroy (GTK_WINDOW (filechooser));
|
||||
}
|
||||
|
||||
/* GObject overrides */
|
||||
@@ -308,31 +303,35 @@ cc_background_chooser_select_file (CcBackgroundChooser *self)
|
||||
{
|
||||
g_autoptr(GFile) pictures_folder = NULL;
|
||||
GtkFileFilter *filter;
|
||||
GtkFileDialog *file_dialog;
|
||||
GtkWidget *filechooser;
|
||||
GtkWindow *toplevel;
|
||||
GListStore *filters;
|
||||
|
||||
g_return_if_fail (CC_IS_BACKGROUND_CHOOSER (self));
|
||||
|
||||
toplevel = (GtkWindow*) gtk_widget_get_native (GTK_WIDGET (self));
|
||||
|
||||
file_dialog = gtk_file_dialog_new ();
|
||||
gtk_file_dialog_set_title (file_dialog, _("Select a picture"));
|
||||
gtk_file_dialog_set_modal (file_dialog, TRUE);
|
||||
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);
|
||||
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_add_pixbuf_formats (filter);
|
||||
|
||||
filters = g_list_store_new (GTK_TYPE_FILE_FILTER);
|
||||
g_list_store_append (filters, filter);
|
||||
gtk_file_dialog_set_filters (file_dialog, G_LIST_MODEL (filters));
|
||||
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (filechooser), filter);
|
||||
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (filechooser), TRUE);
|
||||
|
||||
pictures_folder = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
|
||||
gtk_file_dialog_set_initial_folder (file_dialog, pictures_folder);
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (filechooser),
|
||||
pictures_folder,
|
||||
NULL);
|
||||
|
||||
gtk_file_dialog_open_multiple (file_dialog,
|
||||
toplevel,
|
||||
NULL,
|
||||
file_dialog_open_cb,
|
||||
self);
|
||||
g_signal_connect_object (filechooser,
|
||||
"response",
|
||||
G_CALLBACK (on_file_chooser_response_cb),
|
||||
self,
|
||||
0);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (filechooser));
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<property name="max-children-per-line">8</property>
|
||||
<property name="activate-on-single-click">True</property>
|
||||
<property name="selection-mode">single</property>
|
||||
<signal name="child-activated" handler="on_item_activated_cb" object="CcBackgroundChooser" swapped="yes" />
|
||||
<signal name="child-activated" handler="on_item_activated_cb" object="CcBackgroundChooser" swapped="no" />
|
||||
<style>
|
||||
<class name="background-flowbox"/>
|
||||
</style>
|
||||
@@ -53,7 +53,7 @@
|
||||
<property name="max-children-per-line">8</property>
|
||||
<property name="activate-on-single-click">True</property>
|
||||
<property name="selection-mode">single</property>
|
||||
<signal name="child-activated" handler="on_item_activated_cb" object="CcBackgroundChooser" swapped="yes" />
|
||||
<signal name="child-activated" handler="on_item_activated_cb" object="CcBackgroundChooser" swapped="no" />
|
||||
<style>
|
||||
<class name="background-flowbox"/>
|
||||
</style>
|
||||
|
||||
@@ -57,14 +57,15 @@ struct _CcBackgroundPanel
|
||||
GSettings *lock_settings;
|
||||
GSettings *interface_settings;
|
||||
|
||||
GnomeDesktopThumbnailFactory *thumb_factory;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
CcBackgroundItem *current_background;
|
||||
|
||||
CcBackgroundChooser *background_chooser;
|
||||
CcBackgroundPreview *default_preview;
|
||||
CcBackgroundPreview *light_preview;
|
||||
CcBackgroundPreview *dark_preview;
|
||||
GtkToggleButton *default_toggle;
|
||||
GtkToggleButton *light_toggle;
|
||||
GtkToggleButton *dark_toggle;
|
||||
};
|
||||
|
||||
@@ -83,7 +84,7 @@ load_custom_css (CcBackgroundPanel *self)
|
||||
}
|
||||
|
||||
static void
|
||||
reload_color_scheme_toggles (CcBackgroundPanel *self)
|
||||
reload_light_dark_toggles (CcBackgroundPanel *self)
|
||||
{
|
||||
GDesktopColorScheme scheme;
|
||||
|
||||
@@ -91,7 +92,7 @@ reload_color_scheme_toggles (CcBackgroundPanel *self)
|
||||
|
||||
if (scheme == G_DESKTOP_COLOR_SCHEME_DEFAULT)
|
||||
{
|
||||
gtk_toggle_button_set_active (self->default_toggle, TRUE);
|
||||
gtk_toggle_button_set_active (self->light_toggle, TRUE);
|
||||
}
|
||||
else if (scheme == G_DESKTOP_COLOR_SCHEME_PREFER_DARK)
|
||||
{
|
||||
@@ -99,7 +100,7 @@ reload_color_scheme_toggles (CcBackgroundPanel *self)
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_toggle_button_set_active (self->default_toggle, FALSE);
|
||||
gtk_toggle_button_set_active (self->light_toggle, FALSE);
|
||||
gtk_toggle_button_set_active (self->dark_toggle, FALSE);
|
||||
}
|
||||
}
|
||||
@@ -148,9 +149,9 @@ set_color_scheme (CcBackgroundPanel *self,
|
||||
/* Color schemes */
|
||||
|
||||
static void
|
||||
on_color_scheme_toggle_active_cb (CcBackgroundPanel *self)
|
||||
on_light_dark_toggle_active_cb (CcBackgroundPanel *self)
|
||||
{
|
||||
if (gtk_toggle_button_get_active (self->default_toggle))
|
||||
if (gtk_toggle_button_get_active (self->light_toggle))
|
||||
set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_DEFAULT);
|
||||
else if (gtk_toggle_button_get_active (self->dark_toggle))
|
||||
set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_PREFER_DARK);
|
||||
@@ -176,13 +177,13 @@ got_transition_proxy_cb (GObject *source_object,
|
||||
/* Background */
|
||||
|
||||
static void
|
||||
update_preview (CcBackgroundPanel *self)
|
||||
update_preview (CcBackgroundPanel *panel)
|
||||
{
|
||||
CcBackgroundItem *current_background;
|
||||
|
||||
current_background = self->current_background;
|
||||
cc_background_preview_set_item (self->default_preview, current_background);
|
||||
cc_background_preview_set_item (self->dark_preview, current_background);
|
||||
current_background = panel->current_background;
|
||||
cc_background_preview_set_item (panel->light_preview, current_background);
|
||||
cc_background_preview_set_item (panel->dark_preview, current_background);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
@@ -196,7 +197,7 @@ get_save_path (void)
|
||||
}
|
||||
|
||||
static void
|
||||
reload_current_bg (CcBackgroundPanel *self)
|
||||
reload_current_bg (CcBackgroundPanel *panel)
|
||||
{
|
||||
g_autoptr(CcBackgroundItem) saved = NULL;
|
||||
CcBackgroundItem *configured;
|
||||
@@ -211,7 +212,7 @@ reload_current_bg (CcBackgroundPanel *self)
|
||||
saved = cc_background_xml_get_item (uri);
|
||||
|
||||
/* initalise the current background information from settings */
|
||||
settings = self->settings;
|
||||
settings = panel->settings;
|
||||
uri = g_settings_get_string (settings, WP_URI_KEY);
|
||||
if (uri && *uri == '\0')
|
||||
g_clear_pointer (&uri, g_free);
|
||||
@@ -246,8 +247,8 @@ reload_current_bg (CcBackgroundPanel *self)
|
||||
NULL);
|
||||
}
|
||||
|
||||
g_clear_object (&self->current_background);
|
||||
self->current_background = configured;
|
||||
g_clear_object (&panel->current_background);
|
||||
panel->current_background = configured;
|
||||
cc_background_item_load (configured, NULL);
|
||||
}
|
||||
|
||||
@@ -269,55 +270,7 @@ create_save_dir (void)
|
||||
}
|
||||
|
||||
static void
|
||||
reset_settings_if_defaults (CcBackgroundPanel *self,
|
||||
GSettings *settings,
|
||||
gboolean check_dark)
|
||||
{
|
||||
gsize i;
|
||||
const char *keys[] = {
|
||||
WP_URI_KEY, /* this key needs to be first */
|
||||
WP_URI_DARK_KEY,
|
||||
WP_OPTIONS_KEY,
|
||||
WP_SHADING_KEY,
|
||||
WP_PCOLOR_KEY,
|
||||
WP_SCOLOR_KEY,
|
||||
NULL
|
||||
};
|
||||
|
||||
for (i = 0; keys[i] != NULL; i++)
|
||||
{
|
||||
g_autoptr (GVariant) default_value = NULL;
|
||||
g_autoptr (GVariant) user_value = NULL;
|
||||
gboolean setting_is_default;
|
||||
|
||||
if (!check_dark && g_str_equal (keys[i], WP_URI_DARK_KEY))
|
||||
continue;
|
||||
|
||||
default_value = g_settings_get_default_value (settings, keys[i]);
|
||||
user_value = g_settings_get_value (settings, keys[i]);
|
||||
|
||||
setting_is_default = g_variant_equal (default_value, user_value);
|
||||
|
||||
/* As a courtesy to distros that are a little lackadaisical about making sure
|
||||
* schema defaults match the settings in the background item with the default
|
||||
* picture, we only look at the URI to determine if we shouldn't clean out dconf.
|
||||
*
|
||||
* In otherwords, we still clean out the picture-uri key from dconf when a user
|
||||
* selects the default background in control-center, even if after selecting it
|
||||
* e.g., primary-color still mismatches with schema defaults.
|
||||
*/
|
||||
if (g_str_equal (keys[i], WP_URI_KEY) && !setting_is_default)
|
||||
return;
|
||||
|
||||
if (setting_is_default)
|
||||
g_settings_reset (settings, keys[i]);
|
||||
}
|
||||
|
||||
g_settings_apply (settings);
|
||||
}
|
||||
|
||||
static void
|
||||
set_background (CcBackgroundPanel *self,
|
||||
set_background (CcBackgroundPanel *panel,
|
||||
GSettings *settings,
|
||||
CcBackgroundItem *item,
|
||||
gboolean set_dark)
|
||||
@@ -368,13 +321,10 @@ set_background (CcBackgroundPanel *self,
|
||||
/* Apply all changes */
|
||||
g_settings_apply (settings);
|
||||
|
||||
/* Clean out dconf if the user went back to distro defaults */
|
||||
reset_settings_if_defaults (self, settings, set_dark);
|
||||
|
||||
/* Save the source XML if there is one */
|
||||
filename = get_save_path ();
|
||||
if (create_save_dir ())
|
||||
cc_background_xml_save (self->current_background, filename);
|
||||
cc_background_xml_save (panel->current_background, filename);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -400,12 +350,13 @@ cc_background_panel_get_help_uri (CcPanel *panel)
|
||||
static void
|
||||
cc_background_panel_dispose (GObject *object)
|
||||
{
|
||||
CcBackgroundPanel *self = CC_BACKGROUND_PANEL (object);
|
||||
CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object);
|
||||
|
||||
g_clear_object (&self->settings);
|
||||
g_clear_object (&self->lock_settings);
|
||||
g_clear_object (&self->interface_settings);
|
||||
g_clear_object (&self->proxy);
|
||||
g_clear_object (&panel->settings);
|
||||
g_clear_object (&panel->lock_settings);
|
||||
g_clear_object (&panel->interface_settings);
|
||||
g_clear_object (&panel->thumb_factory);
|
||||
g_clear_object (&panel->proxy);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -413,9 +364,9 @@ cc_background_panel_dispose (GObject *object)
|
||||
static void
|
||||
cc_background_panel_finalize (GObject *object)
|
||||
{
|
||||
CcBackgroundPanel *self = CC_BACKGROUND_PANEL (object);
|
||||
CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object);
|
||||
|
||||
g_clear_object (&self->current_background);
|
||||
g_clear_object (&panel->current_background);
|
||||
|
||||
G_OBJECT_CLASS (cc_background_panel_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -438,54 +389,56 @@ cc_background_panel_class_init (CcBackgroundPanelClass *klass)
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-panel.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, background_chooser);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_preview);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, light_preview);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_preview);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_toggle);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, light_toggle);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_toggle);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_color_scheme_toggle_active_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_light_dark_toggle_active_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_chooser_background_chosen_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_add_picture_button_clicked_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
on_settings_changed (CcBackgroundPanel *self)
|
||||
on_settings_changed (CcBackgroundPanel *panel)
|
||||
{
|
||||
reload_current_bg (self);
|
||||
update_preview (self);
|
||||
reload_current_bg (panel);
|
||||
update_preview (panel);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_background_panel_init (CcBackgroundPanel *self)
|
||||
cc_background_panel_init (CcBackgroundPanel *panel)
|
||||
{
|
||||
g_resources_register (cc_background_get_resource ());
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
gtk_widget_init_template (GTK_WIDGET (panel));
|
||||
|
||||
self->connection = g_application_get_dbus_connection (g_application_get_default ());
|
||||
panel->connection = g_application_get_dbus_connection (g_application_get_default ());
|
||||
|
||||
self->settings = g_settings_new (WP_PATH_ID);
|
||||
g_settings_delay (self->settings);
|
||||
panel->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
|
||||
|
||||
panel->settings = g_settings_new (WP_PATH_ID);
|
||||
g_settings_delay (panel->settings);
|
||||
|
||||
self->lock_settings = g_settings_new (WP_LOCK_PATH_ID);
|
||||
g_settings_delay (self->lock_settings);
|
||||
panel->lock_settings = g_settings_new (WP_LOCK_PATH_ID);
|
||||
g_settings_delay (panel->lock_settings);
|
||||
|
||||
self->interface_settings = g_settings_new (INTERFACE_PATH_ID);
|
||||
panel->interface_settings = g_settings_new (INTERFACE_PATH_ID);
|
||||
|
||||
/* Load the background */
|
||||
reload_current_bg (self);
|
||||
update_preview (self);
|
||||
reload_current_bg (panel);
|
||||
update_preview (panel);
|
||||
|
||||
/* Background settings */
|
||||
g_signal_connect_object (self->settings, "changed", G_CALLBACK (on_settings_changed), self, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (panel->settings, "changed", G_CALLBACK (on_settings_changed), panel, G_CONNECT_SWAPPED);
|
||||
|
||||
/* Interface settings */
|
||||
reload_color_scheme_toggles (self);
|
||||
reload_light_dark_toggles (panel);
|
||||
|
||||
g_signal_connect_object (self->interface_settings,
|
||||
g_signal_connect_object (panel->interface_settings,
|
||||
"changed::" INTERFACE_COLOR_SCHEME_KEY,
|
||||
G_CALLBACK (reload_color_scheme_toggles),
|
||||
self,
|
||||
G_CALLBACK (reload_light_dark_toggles),
|
||||
panel,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
|
||||
@@ -496,7 +449,7 @@ cc_background_panel_init (CcBackgroundPanel *self)
|
||||
"org.gnome.Shell",
|
||||
NULL,
|
||||
got_transition_proxy_cb,
|
||||
self);
|
||||
panel);
|
||||
|
||||
load_custom_css (self);
|
||||
load_custom_css (panel);
|
||||
}
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
<property name="margin-bottom">12</property>
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="default_toggle">
|
||||
<object class="GtkToggleButton" id="light_toggle">
|
||||
<accessibility>
|
||||
<relation name="labelled-by">default_label</relation>
|
||||
<relation name="labelled-by">light_label</relation>
|
||||
</accessibility>
|
||||
<signal name="notify::active" handler="on_color_scheme_toggle_active_cb" swapped="true"/>
|
||||
<signal name="notify::active" handler="on_light_dark_toggle_active_cb" swapped="true"/>
|
||||
<child>
|
||||
<object class="CcBackgroundPreview" id="default_preview"/>
|
||||
<object class="CcBackgroundPreview" id="light_preview"/>
|
||||
</child>
|
||||
<style>
|
||||
<class name="background-preview-button"/>
|
||||
@@ -45,8 +45,8 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="default_label">
|
||||
<property name="label" translatable="yes">Default</property>
|
||||
<object class="GtkLabel" id="light_label">
|
||||
<property name="label" translatable="yes">Light</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
@@ -55,11 +55,11 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="dark_toggle">
|
||||
<property name="group">default_toggle</property>
|
||||
<property name="group">light_toggle</property>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">dark_label</relation>
|
||||
</accessibility>
|
||||
<signal name="notify::active" handler="on_color_scheme_toggle_active_cb" swapped="true"/>
|
||||
<signal name="notify::active" handler="on_light_dark_toggle_active_cb" swapped="true"/>
|
||||
<child>
|
||||
<object class="CcBackgroundPreview" id="dark_preview">
|
||||
<property name="is-dark">True</property>
|
||||
|
||||
@@ -342,10 +342,11 @@ cc_background_xml_load_xml_internal (CcBackgroundXml *xml,
|
||||
}
|
||||
|
||||
static void
|
||||
gnome_wp_file_changed (CcBackgroundXml *xml,
|
||||
gnome_wp_file_changed (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event_type)
|
||||
GFileMonitorEvent event_type,
|
||||
CcBackgroundXml *data)
|
||||
{
|
||||
g_autofree gchar *filename = NULL;
|
||||
|
||||
@@ -353,7 +354,7 @@ gnome_wp_file_changed (CcBackgroundXml *xml,
|
||||
case G_FILE_MONITOR_EVENT_CHANGED:
|
||||
case G_FILE_MONITOR_EVENT_CREATED:
|
||||
filename = g_file_get_path (file);
|
||||
cc_background_xml_load_xml_internal (xml, filename, FALSE);
|
||||
cc_background_xml_load_xml_internal (data, filename, FALSE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -380,9 +381,9 @@ cc_background_xml_add_monitor (GFile *directory,
|
||||
return;
|
||||
}
|
||||
|
||||
g_signal_connect_swapped (monitor, "changed",
|
||||
G_CALLBACK (gnome_wp_file_changed),
|
||||
data);
|
||||
g_signal_connect (monitor, "changed",
|
||||
G_CALLBACK (gnome_wp_file_changed),
|
||||
data);
|
||||
|
||||
data->monitors = g_slist_prepend (data->monitors, monitor);
|
||||
}
|
||||
|
||||
@@ -11,4 +11,4 @@ StartupNotify=true
|
||||
Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalizationSettings;
|
||||
OnlyShowIn=GNOME;
|
||||
# Translators: Search terms to find the Appearance panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
|
||||
Keywords=Background;Wallpaper;Screen;Desktop;Style;Light;Dark;Appearance;
|
||||
Keywords=Background;Wallpaper;Screen;Desktop;Style;Light;Dark;
|
||||
@@ -1,9 +1,15 @@
|
||||
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',
|
||||
input: desktop_in,
|
||||
output: desktop,
|
||||
po_dir: po_dir,
|
||||
install: true,
|
||||
@@ -19,7 +25,7 @@ common_sources = []
|
||||
|
||||
enums = 'gdesktop-enums-types'
|
||||
enums_header = files(
|
||||
gsettings_desktop_dep.get_variable(pkgconfig: 'prefix') + '/include/gsettings-desktop-schemas/gdesktop-enums.h',
|
||||
gsettings_desktop_dep.get_pkgconfig_variable('prefix') + '/include/gsettings-desktop-schemas/gdesktop-enums.h',
|
||||
'cc-background-item.h'
|
||||
)
|
||||
|
||||
@@ -42,10 +48,18 @@ 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',
|
||||
)
|
||||
|
||||
common_sources += gnome.compile_resources(
|
||||
'cc-@0@-resources'.format(cappletname),
|
||||
cappletname + '.gresource.xml',
|
||||
c_name: 'cc_' + cappletname,
|
||||
dependencies: resource_data,
|
||||
export: true
|
||||
)
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ background-preview .window {
|
||||
|
||||
background-preview .window .header-bar {
|
||||
min-height: 15px;
|
||||
box-shadow: inset 0 -1px @borders;
|
||||
}
|
||||
|
||||
background-preview .window.light {
|
||||
@@ -19,10 +20,6 @@ background-preview .window.light {
|
||||
color: alpha(black, .8);
|
||||
}
|
||||
|
||||
background-preview .window.light .header-bar {
|
||||
box-shadow: inset 0 -1px alpha(black, .07);
|
||||
}
|
||||
|
||||
background-preview .window.front.light .header-bar {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
@@ -32,10 +29,6 @@ background-preview .window.dark {
|
||||
color: white;
|
||||
}
|
||||
|
||||
background-preview .window.dark .header-bar {
|
||||
box-shadow: inset 0 -1px alpha(black, .36);
|
||||
}
|
||||
|
||||
background-preview .window.front.dark .header-bar {
|
||||
background-color: #303030;
|
||||
}
|
||||
|
||||
@@ -117,8 +117,8 @@ class GccDBusTestCase(DBusTestCase):
|
||||
adapter.UpdateProperties('org.bluez.Adapter1',
|
||||
{'Powered': dbus.Boolean(self.hci0_powered, variant_level=1)})
|
||||
self.devices = []
|
||||
self.add_device('hci0', '22:33:44:55:66:77', "Bastienʼs mouse", True, 0x580, 'input-mouse')
|
||||
self.add_device('hci0', '22:33:44:55:66:78', 'Bloutouf keyboard & keys', True, 0x540, 'input-keyboard')
|
||||
self.add_device('hci0', '22:33:44:55:66:77', "Bastien's mouse", True, 0x580, 'input-mouse')
|
||||
self.add_device('hci0', '22:33:44:55:66:78', 'Bloutouf keyboard', True, 0x540, 'input-keyboard')
|
||||
self.add_device('hci0', '60:8B:0E:55:66:79', 'iPhoone 19S', True, 0x20C, 'phone')
|
||||
# Uncategorised audio device
|
||||
self.add_device('hci0', '22:33:44:55:66:79', 'MEGA Speakers', True, 0x200400, 'audio-card')
|
||||
|
||||
@@ -80,29 +80,25 @@ airplane_mode_changed_cb (GObject *source_object,
|
||||
{
|
||||
g_autoptr(GVariant) ret = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
gboolean state = GPOINTER_TO_UINT (user_data);
|
||||
|
||||
if (!g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
|
||||
res, &error)) {
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
CcBluetoothPanel *self = CC_BLUETOOTH_PANEL (user_data);
|
||||
gboolean state = gtk_switch_get_active (self->enable_switch);
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_warning ("Failed to change Bluetooth killswitch state to %s: %s",
|
||||
state ? "on" : "off", error->message);
|
||||
}
|
||||
} else {
|
||||
CcBluetoothPanel *self = CC_BLUETOOTH_PANEL (user_data);
|
||||
gboolean state = gtk_switch_get_active (self->enable_switch);
|
||||
CcBluetoothPanel *self = user_data;
|
||||
|
||||
g_debug ("Changed Bluetooth killswitch state to %s",
|
||||
state ? "on" : "off");
|
||||
|
||||
gtk_switch_set_state (self->enable_switch, state);
|
||||
if (!bluetooth_settings_widget_get_default_adapter_powered (self->settings_widget))
|
||||
bluetooth_settings_widget_set_default_adapter_powered(self->settings_widget, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static void
|
||||
enable_switch_state_set_cb (CcBluetoothPanel *self, gboolean state)
|
||||
{
|
||||
g_debug ("Power switched to %s", state ? "on" : "off");
|
||||
@@ -114,8 +110,6 @@ enable_switch_state_set_cb (CcBluetoothPanel *self, gboolean state)
|
||||
-1,
|
||||
cc_panel_get_cancellable (CC_PANEL (self)),
|
||||
airplane_mode_changed_cb, self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -162,7 +156,7 @@ adapter_status_changed_cb (CcBluetoothPanel *self)
|
||||
gtk_widget_set_valign (GTK_WIDGET (self->stack), valign);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self->header_box), sensitive);
|
||||
g_signal_handlers_block_by_func (self->enable_switch, enable_switch_state_set_cb, self);
|
||||
gtk_switch_set_active (self->enable_switch, powered);
|
||||
gtk_switch_set_state (self->enable_switch, powered);
|
||||
g_signal_handlers_unblock_by_func (self->enable_switch, enable_switch_state_set_cb, self);
|
||||
|
||||
gtk_stack_set_visible_child (self->stack, page);
|
||||
|
||||
@@ -29,24 +29,22 @@
|
||||
<object class="AdwStatusPage" id="disabled_page">
|
||||
<property name="icon-name">bluetooth-active-symbolic</property>
|
||||
<property name="title" translatable="yes">Bluetooth Turned Off</property>
|
||||
<property name="description" translatable="yes">Turn on to connect devices and receive file transfers</property>
|
||||
<property name="description" translatable="yes">Turn on to connect devices and receive file transfers.</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwStatusPage" id="airplane_page">
|
||||
<property name="icon-name">airplane-mode-symbolic</property>
|
||||
<property name="title" translatable="yes">Airplane Mode is On</property>
|
||||
<property name="description" translatable="yes">Bluetooth is disabled when airplane mode is on</property>
|
||||
<property name="description" translatable="yes">Bluetooth is disabled when airplane mode is on.</property>
|
||||
<property name="child">
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">_Turn Off Airplane Mode</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="label" translatable="yes">Turn Off Airplane Mode</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<signal name="clicked" handler="airplane_mode_off_button_clicked_cb" object="CcBluetoothPanel" swapped="yes"/>
|
||||
<style>
|
||||
<class name="pill"/>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
@@ -10,5 +10,9 @@ NoDisplay=true
|
||||
Categories=GTK;GNOME;Settings;X-GNOME-NetworkSettings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-ConnectivitySettings;
|
||||
OnlyShowIn=GNOME;Unity;
|
||||
StartupNotify=true
|
||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||
X-GNOME-Bugzilla-Product=gnome-bluetooth
|
||||
X-GNOME-Bugzilla-Component=properties
|
||||
X-GNOME-Bugzilla-Version=@VERSION@
|
||||
# Translators: Search terms to find the Bluetooth panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
|
||||
Keywords=share;sharing;bluetooth;obex;
|
||||
@@ -1,9 +1,15 @@
|
||||
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',
|
||||
input: desktop_in,
|
||||
output: desktop,
|
||||
po_dir: po_dir,
|
||||
install: true,
|
||||
@@ -12,10 +18,13 @@ i18n.merge_file(
|
||||
|
||||
sources = files('cc-bluetooth-panel.c')
|
||||
|
||||
resource_data = files('cc-bluetooth-panel.ui')
|
||||
|
||||
sources += gnome.compile_resources(
|
||||
'cc-' + cappletname + '-resources',
|
||||
cappletname + '.gresource.xml',
|
||||
c_name: 'cc_' + cappletname,
|
||||
dependencies: resource_data,
|
||||
export: true
|
||||
)
|
||||
|
||||
|
||||
6
panels/camera/camera.gresource.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gnome/control-center/camera">
|
||||
<file preprocess="xml-stripblanks">cc-camera-panel.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
@@ -18,24 +18,26 @@
|
||||
* Author: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#include "cc-camera-page.h"
|
||||
#include "cc-camera-panel.h"
|
||||
#include "cc-camera-resources.h"
|
||||
#include "cc-util.h"
|
||||
|
||||
#include <adwaita.h>
|
||||
#include <gio/gdesktopappinfo.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#define APP_PERMISSIONS_TABLE "devices"
|
||||
#define APP_PERMISSIONS_ID "camera"
|
||||
|
||||
struct _CcCameraPage
|
||||
struct _CcCameraPanel
|
||||
{
|
||||
AdwNavigationPage parent_instance;
|
||||
CcPanel parent_instance;
|
||||
|
||||
GtkStack *stack;
|
||||
GtkListBox *camera_apps_list_box;
|
||||
AdwSwitchRow *camera_row;
|
||||
GtkSwitch *main_switch;
|
||||
|
||||
GSettings *privacy_settings;
|
||||
GCancellable *cancellable;
|
||||
|
||||
GDBusProxy *perm_store;
|
||||
GVariant *camera_apps_perms;
|
||||
@@ -45,11 +47,11 @@ struct _CcCameraPage
|
||||
GtkSizeGroup *camera_icon_size_group;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcCameraPage, cc_camera_page, ADW_TYPE_NAVIGATION_PAGE)
|
||||
CC_PANEL_REGISTER (CcCameraPanel, cc_camera_panel)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CcCameraPage *self;
|
||||
CcCameraPanel *self;
|
||||
GtkWidget *widget;
|
||||
gchar *app_id;
|
||||
gboolean changing_state;
|
||||
@@ -94,22 +96,19 @@ on_camera_app_state_set (GtkSwitch *widget,
|
||||
{
|
||||
CameraAppStateData *data = (CameraAppStateData *) user_data;
|
||||
GVariantBuilder builder;
|
||||
CcCameraPage *self;
|
||||
CcCameraPanel *self;
|
||||
GVariantIter iter;
|
||||
GVariant *params;
|
||||
const gchar *key;
|
||||
gchar **value;
|
||||
gboolean active_camera;
|
||||
|
||||
self = data->self;
|
||||
|
||||
if (data->changing_state)
|
||||
return TRUE;
|
||||
|
||||
active_camera = !g_settings_get_boolean (self->privacy_settings,
|
||||
"disable-camera");
|
||||
data->changing_state = TRUE;
|
||||
data->pending_state = active_camera && state;
|
||||
data->pending_state = state;
|
||||
|
||||
g_variant_iter_init (&iter, self->camera_apps_perms);
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
|
||||
@@ -145,36 +144,17 @@ on_camera_app_state_set (GtkSwitch *widget,
|
||||
params,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
self->cancellable,
|
||||
cc_panel_get_cancellable (CC_PANEL (self)),
|
||||
on_perm_store_set_done,
|
||||
data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_app_switch_state (GValue *value,
|
||||
GVariant *variant,
|
||||
gpointer data)
|
||||
{
|
||||
GtkSwitch *w = GTK_SWITCH (data);
|
||||
gboolean active_camera;
|
||||
gboolean active_app;
|
||||
gboolean state;
|
||||
|
||||
active_camera = !g_variant_get_boolean (variant);
|
||||
active_app = gtk_switch_get_active (w);
|
||||
state = active_camera && active_app;
|
||||
|
||||
g_value_set_boolean (value, state);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
add_camera_app (CcCameraPage *self,
|
||||
const gchar *app_id,
|
||||
gboolean enabled)
|
||||
add_camera_app (CcCameraPanel *self,
|
||||
const gchar *app_id,
|
||||
gboolean enabled)
|
||||
{
|
||||
g_autofree gchar *desktop_id = NULL;
|
||||
CameraAppStateData *data;
|
||||
@@ -210,17 +190,11 @@ add_camera_app (CcCameraPage *self,
|
||||
gtk_switch_set_active (GTK_SWITCH (w), enabled);
|
||||
gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
|
||||
adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
|
||||
|
||||
g_settings_bind_with_mapping (self->privacy_settings,
|
||||
"disable-camera",
|
||||
w,
|
||||
"state",
|
||||
G_SETTINGS_BIND_GET,
|
||||
update_app_switch_state,
|
||||
NULL,
|
||||
g_object_ref (w),
|
||||
g_object_unref);
|
||||
|
||||
g_settings_bind (self->privacy_settings,
|
||||
"disable-camera",
|
||||
w,
|
||||
"sensitive",
|
||||
G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||||
g_hash_table_insert (self->camera_app_switches,
|
||||
g_strdup (app_id),
|
||||
g_object_ref (w));
|
||||
@@ -239,10 +213,24 @@ add_camera_app (CcCameraPage *self,
|
||||
}
|
||||
|
||||
/* Steals permissions and permissions_data references */
|
||||
|
||||
static gboolean
|
||||
to_child_name (GBinding *binding,
|
||||
const GValue *from,
|
||||
GValue *to,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (g_value_get_boolean (from))
|
||||
g_value_set_string (to, "content");
|
||||
else
|
||||
g_value_set_string (to, "empty");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_perm_store (CcCameraPage *self,
|
||||
GVariant *permissions,
|
||||
GVariant *permissions_data)
|
||||
update_perm_store (CcCameraPanel *self,
|
||||
GVariant *permissions,
|
||||
GVariant *permissions_data)
|
||||
{
|
||||
GVariantIter iter;
|
||||
const gchar *key;
|
||||
@@ -292,7 +280,7 @@ on_perm_store_lookup_done (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcCameraPage *self = user_data;
|
||||
CcCameraPanel *self = user_data;
|
||||
GVariant *ret, *permissions, *permissions_data;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
@@ -322,7 +310,7 @@ on_perm_store_ready (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcCameraPage *self;
|
||||
CcCameraPanel *self;
|
||||
g_autoptr(GVariant) params = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
GDBusProxy *proxy;
|
||||
@@ -345,18 +333,15 @@ on_perm_store_ready (GObject *source_object,
|
||||
params,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
self->cancellable,
|
||||
cc_panel_get_cancellable (CC_PANEL (self)),
|
||||
on_perm_store_lookup_done,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_camera_page_finalize (GObject *object)
|
||||
cc_camera_panel_finalize (GObject *object)
|
||||
{
|
||||
CcCameraPage *self = CC_CAMERA_PAGE (object);
|
||||
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_clear_object (&self->cancellable);
|
||||
CcCameraPanel *self = CC_CAMERA_PANEL (object);
|
||||
|
||||
g_clear_object (&self->privacy_settings);
|
||||
g_clear_object (&self->perm_store);
|
||||
@@ -365,38 +350,55 @@ cc_camera_page_finalize (GObject *object)
|
||||
g_clear_pointer (&self->camera_apps_data, g_variant_unref);
|
||||
g_clear_pointer (&self->camera_app_switches, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (cc_camera_page_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (cc_camera_panel_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static const char *
|
||||
cc_camera_panel_get_help_uri (CcPanel *panel)
|
||||
{
|
||||
return "help:gnome-help/camera";
|
||||
}
|
||||
|
||||
static void
|
||||
cc_camera_page_class_init (CcCameraPageClass *klass)
|
||||
cc_camera_panel_class_init (CcCameraPanelClass *klass)
|
||||
{
|
||||
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = cc_camera_page_finalize;
|
||||
panel_class->get_help_uri = cc_camera_panel_get_help_uri;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/privacy/cc-camera-page.ui");
|
||||
object_class->finalize = cc_camera_panel_finalize;
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcCameraPage, camera_apps_list_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcCameraPage, camera_row);
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/camera/cc-camera-panel.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcCameraPanel, stack);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcCameraPanel, camera_apps_list_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcCameraPanel, main_switch);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_camera_page_init (CcCameraPage *self)
|
||||
cc_camera_panel_init (CcCameraPanel *self)
|
||||
{
|
||||
g_resources_register (cc_camera_get_resource ());
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
self->camera_icon_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
|
||||
|
||||
self->privacy_settings = g_settings_new ("org.gnome.desktop.privacy");
|
||||
|
||||
self->cancellable = g_cancellable_new ();
|
||||
|
||||
g_settings_bind (self->privacy_settings, "disable-camera",
|
||||
self->camera_row, "active",
|
||||
self->main_switch, "active",
|
||||
G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||||
|
||||
g_object_bind_property_full (self->main_switch, "active",
|
||||
self->stack, "visible-child-name",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
to_child_name,
|
||||
NULL,
|
||||
NULL, NULL);
|
||||
|
||||
self->camera_app_switches = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
@@ -408,7 +410,7 @@ cc_camera_page_init (CcCameraPage *self)
|
||||
"org.freedesktop.impl.portal.PermissionStore",
|
||||
"/org/freedesktop/impl/portal/PermissionStore",
|
||||
"org.freedesktop.impl.portal.PermissionStore",
|
||||
self->cancellable,
|
||||
cc_panel_get_cancellable (CC_PANEL (self)),
|
||||
on_perm_store_ready,
|
||||
self);
|
||||
}
|
||||
@@ -20,11 +20,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <adwaita.h>
|
||||
#include <shell/cc-panel.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_CAMERA_PAGE (cc_camera_page_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (CcCameraPage, cc_camera_page, CC, CAMERA_PAGE, AdwNavigationPage)
|
||||
#define CC_TYPE_CAMERA_PANEL (cc_camera_panel_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (CcCameraPanel, cc_camera_panel, CC, CAMERA_PANEL, CcPanel)
|
||||
|
||||
G_END_DECLS
|
||||
75
panels/camera/cc-camera-panel.ui
Normal file
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcCameraPanel" parent="CcPanel">
|
||||
|
||||
<child type="titlebar-end">
|
||||
<object class="GtkSwitch" id="main_switch">
|
||||
<accessibility>
|
||||
<property name="label" translatable="yes">Enable</property>
|
||||
</accessibility>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child type="content">
|
||||
<object class="GtkStack" id="stack">
|
||||
|
||||
<!-- Empty page -->
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">empty</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage">
|
||||
<property name="icon-name">camera-disabled-symbolic</property>
|
||||
<property name="title" translatable="yes">Camera is Turned Off</property>
|
||||
<property name="description" translatable="yes">No applications can capture photos or video.</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Cameras -->
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">content</property>
|
||||
<property name="child">
|
||||
<object class="AdwPreferencesPage">
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="description" translatable="yes">Use of the camera allows applications to capture photos and video. Disabling the camera may cause some applications to not function properly.
|
||||
|
||||
Allow the applications below to use your camera.</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="camera_apps_list_box">
|
||||
<property name="selection-mode">none</property>
|
||||
<style>
|
||||
<class name="boxed-list"/>
|
||||
</style>
|
||||
|
||||
<child type="placeholder">
|
||||
<object class="GtkLabel">
|
||||
<property name="margin-start">18</property>
|
||||
<property name="margin-end">18</property>
|
||||
<property name="margin-top">18</property>
|
||||
<property name="margin-bottom">18</property>
|
||||
<property name="label" translatable="yes">No Applications Have Asked for Camera Access</property>
|
||||
<property name="wrap">true</property>
|
||||
<property name="max-width-chars">50</property>
|
||||
<style>
|
||||
<class name="dim-label" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
19
panels/camera/gnome-camera-panel.desktop.in.in
Normal file
@@ -0,0 +1,19 @@
|
||||
[Desktop Entry]
|
||||
Name=Camera
|
||||
Comment=Protect your pictures
|
||||
Exec=gnome-control-center camera
|
||||
# FIXME
|
||||
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
|
||||
Icon=org.gnome.Settings-camera-symbolic
|
||||
Terminal=false
|
||||
Type=Application
|
||||
NoDisplay=true
|
||||
StartupNotify=true
|
||||
Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PrivacySettings;
|
||||
OnlyShowIn=GNOME;Unity;
|
||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||
X-GNOME-Bugzilla-Product=gnome-control-center
|
||||
X-GNOME-Bugzilla-Component=privacy
|
||||
X-GNOME-Bugzilla-Version=@VERSION@
|
||||
# Translators: Search terms to find the Privacy panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
|
||||
Keywords=screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;network;identity;
|
||||
@@ -1,4 +1,4 @@
|
||||
install_data(
|
||||
'scalable/org.gnome.Settings-privacy-symbolic.svg',
|
||||
'scalable/org.gnome.Settings-camera-symbolic.svg',
|
||||
install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
|
||||
)
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 6.414062 0 c -0.265624 0 -0.519531 0.105469 -0.707031 0.292969 l -1.707031 1.707031 h -1.085938 c -1.644531 0 -2.9999995 1.355469 -2.9999995 3 v 7 c 0 1.644531 1.3554685 3 2.9999995 3 h 10 c 1.644532 0 3 -1.355469 3 -3 v -7 c 0 -1.644531 -1.355468 -3 -3 -3 h -1.085937 l -1.707031 -1.707031 c -0.1875 -0.1875 -0.441406 -0.292969 -0.707032 -0.292969 z m 0.414063 2 h 2.171875 l 1.707031 1.707031 c 0.1875 0.1875 0.441407 0.292969 0.707031 0.292969 h 1.5 c 0.570313 0 1 0.429688 1 1 v 7 c 0 0.570312 -0.429687 1 -1 1 h -10 c -0.570312 0 -1 -0.429688 -1 -1 v -7 c 0 -0.570312 0.429688 -1 1 -1 h 1.5 c 0.265626 0 0.519532 -0.105469 0.707032 -0.292969 z m 1.085937 3 c -1.644531 0 -3 1.355469 -3 3 s 1.585938 3 3 3 c 1.414063 0 3 -1.355469 3 -3 s -1.355468 -3 -3 -3 z m 0 2 c 0.5625 0 1 0.4375 1 1 s -0.4375 1 -1 1 s -1 -0.4375 -1 -1 s 0.4375 -1 1 -1 z m 0 0" fill="#2e3434"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1021 B |
41
panels/camera/meson.build
Normal file
@@ -0,0 +1,41 @@
|
||||
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-camera-panel.c')
|
||||
|
||||
resource_data = files('cc-camera-panel.ui')
|
||||
|
||||
sources += gnome.compile_resources(
|
||||
'cc-' + cappletname + '-resources',
|
||||
cappletname + '.gresource.xml',
|
||||
c_name: 'cc_' + cappletname,
|
||||
dependencies: resource_data,
|
||||
export: true
|
||||
)
|
||||
|
||||
cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
|
||||
|
||||
panels_libs += static_library(
|
||||
cappletname,
|
||||
sources: sources,
|
||||
include_directories: [top_inc, common_inc],
|
||||
dependencies: common_deps,
|
||||
c_args: cflags
|
||||
)
|
||||
|
||||
subdir('icons')
|
||||
@@ -442,6 +442,7 @@ cc_color_calibrate_finished (CcColorCalibrate *calibrate,
|
||||
gtk_widget_set_visible (widget, FALSE);
|
||||
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
|
||||
"button_done"));
|
||||
gtk_widget_set_visible (widget, TRUE);
|
||||
|
||||
str = g_string_new ("");
|
||||
if (code == CD_SESSION_ERROR_NONE)
|
||||
@@ -602,6 +603,96 @@ cc_color_calibrate_cancel (CcColorCalibrate *calibrate)
|
||||
g_main_loop_quit (calibrate->loop);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cc_color_calibrate_move_and_resize_window (GtkWindow *window,
|
||||
CdDevice *device,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GListModel) monitors = NULL;
|
||||
g_autoptr(GdkMonitor) monitor = NULL;
|
||||
const gchar *xrandr_name;
|
||||
gboolean ret = TRUE;
|
||||
GdkRectangle rect;
|
||||
GdkDisplay *display;
|
||||
gint i;
|
||||
gint monitor_num = -1;
|
||||
gint num_monitors;
|
||||
|
||||
/* find the monitor num of the device output */
|
||||
display = gdk_display_get_default ();
|
||||
monitors = gdk_display_get_monitors (display);
|
||||
num_monitors = g_list_model_get_n_items (monitors);
|
||||
xrandr_name = cd_device_get_metadata_item (device, CD_DEVICE_METADATA_XRANDR_NAME);
|
||||
for (i = 0; i < num_monitors; i++)
|
||||
{
|
||||
g_autoptr(GdkMonitor) m = NULL;
|
||||
const gchar *plug_name;
|
||||
|
||||
m = g_list_model_get_item (monitors, i);
|
||||
plug_name = gdk_monitor_get_model (m);
|
||||
|
||||
if (g_strcmp0 (plug_name, xrandr_name) == 0)
|
||||
monitor_num = i;
|
||||
}
|
||||
if (monitor_num == -1)
|
||||
{
|
||||
ret = FALSE;
|
||||
g_set_error (error,
|
||||
CD_SESSION_ERROR,
|
||||
CD_SESSION_ERROR_INTERNAL,
|
||||
"failed to find output %s",
|
||||
xrandr_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* move the window, and set it to the right size */
|
||||
monitor = g_list_model_get_item (monitors, monitor_num);
|
||||
gdk_monitor_get_geometry (monitor, &rect);
|
||||
g_debug ("Setting window to %ix%i with size %ix%i",
|
||||
rect.x, rect.y, rect.width, rect.height);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
#if 0
|
||||
static void
|
||||
cc_color_calibrate_window_realize_cb (CcColorCalibrate *self)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = GTK_WIDGET (gtk_builder_get_object (self->builder,
|
||||
"dialog_calibrate"));
|
||||
gtk_window_fullscreen (GTK_WINDOW (widget));
|
||||
gtk_window_maximize (GTK_WINDOW (widget));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cc_color_calibrate_window_state_cb (CcColorCalibrate *calibrate,
|
||||
GdkEvent *event)
|
||||
{
|
||||
gboolean ret;
|
||||
g_autoptr(GError) error = NULL;
|
||||
GdkEventWindowState *event_state = (GdkEventWindowState *) event;
|
||||
GtkWindow *window;
|
||||
|
||||
window = GTK_WINDOW (gtk_builder_get_object (calibrate->builder,
|
||||
"dialog_calibrate"));
|
||||
|
||||
/* check event */
|
||||
if (event->type != GDK_WINDOW_STATE)
|
||||
return TRUE;
|
||||
if (event_state->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)
|
||||
return TRUE;
|
||||
|
||||
/* resize to the correct screen */
|
||||
ret = cc_color_calibrate_move_and_resize_window (window,
|
||||
calibrate->device,
|
||||
&error);
|
||||
if (!ret)
|
||||
g_warning ("Failed to resize window: %s", error->message);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
cc_color_calibrate_button_done_cb (CcColorCalibrate *calibrate)
|
||||
{
|
||||
@@ -860,13 +951,15 @@ cc_color_calibrate_start (CcColorCalibrate *calibrate,
|
||||
window = GTK_WINDOW (gtk_builder_get_object (calibrate->builder,
|
||||
"dialog_calibrate"));
|
||||
gtk_window_set_modal (window, TRUE);
|
||||
gtk_window_present (window);
|
||||
gtk_widget_show (GTK_WIDGET (window));
|
||||
|
||||
/* show correct buttons */
|
||||
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
|
||||
"button_cancel"));
|
||||
gtk_widget_set_visible (widget, TRUE);
|
||||
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
|
||||
"button_start"));
|
||||
gtk_widget_set_visible (widget, TRUE);
|
||||
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
|
||||
"button_resume"));
|
||||
gtk_widget_set_visible (widget, FALSE);
|
||||
@@ -878,7 +971,7 @@ cc_color_calibrate_start (CcColorCalibrate *calibrate,
|
||||
cc_color_calibrate_inhibit (calibrate, parent);
|
||||
|
||||
g_main_loop_run (calibrate->loop);
|
||||
gtk_window_close (window);
|
||||
gtk_widget_hide (GTK_WIDGET (window));
|
||||
|
||||
/* we can go idle now */
|
||||
cc_color_calibrate_uninhibit (calibrate);
|
||||
@@ -896,6 +989,14 @@ cc_color_calibrate_start (CcColorCalibrate *calibrate,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cc_color_calibrate_delete_event_cb (CcColorCalibrate *calibrate)
|
||||
{
|
||||
/* do not destroy the window */
|
||||
cc_color_calibrate_cancel (calibrate);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_color_calibrate_finalize (GObject *object)
|
||||
{
|
||||
@@ -973,11 +1074,24 @@ cc_color_calibrate_init (CcColorCalibrate *calibrate)
|
||||
"button_cancel"));
|
||||
g_signal_connect_object (widget, "clicked",
|
||||
G_CALLBACK (cc_color_calibrate_button_cancel_cb), calibrate, G_CONNECT_SWAPPED);
|
||||
gtk_widget_set_visible (widget, TRUE);
|
||||
gtk_widget_show (widget);
|
||||
|
||||
/* setup the specialist calibration window */
|
||||
window = GTK_WINDOW (gtk_builder_get_object (calibrate->builder,
|
||||
"dialog_calibrate"));
|
||||
/*
|
||||
g_signal_connect_object (window, "draw",
|
||||
G_CALLBACK (cc_color_calibrate_alpha_window_draw), calibrate, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (window, "realize",
|
||||
G_CALLBACK (cc_color_calibrate_window_realize_cb), calibrate, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (window, "window-state-event",
|
||||
G_CALLBACK (cc_color_calibrate_window_state_cb), calibrate, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (window, "delete-event",
|
||||
G_CALLBACK (cc_color_calibrate_delete_event_cb), calibrate, G_CONNECT_SWAPPED);
|
||||
cc_color_calibrate_alpha_screen_changed_cb (calibrate);
|
||||
g_signal_connect_object (window, "screen-changed",
|
||||
G_CALLBACK (cc_color_calibrate_alpha_screen_changed_cb), calibrate, G_CONNECT_SWAPPED);
|
||||
*/
|
||||
calibrate->window = window;
|
||||
}
|
||||
|
||||
|
||||
@@ -253,6 +253,7 @@ cc_color_device_clicked_expander_cb (CcColorDevice *color_device)
|
||||
static void
|
||||
cc_color_device_init (CcColorDevice *color_device)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GtkWidget *box;
|
||||
|
||||
/* description */
|
||||
@@ -281,6 +282,7 @@ cc_color_device_init (CcColorDevice *color_device)
|
||||
gtk_widget_set_valign (color_device->widget_button, GTK_ALIGN_CENTER);
|
||||
gtk_widget_add_css_class (color_device->widget_button, "flat");
|
||||
gtk_button_set_child (GTK_BUTTON (color_device->widget_button), color_device->widget_arrow);
|
||||
gtk_widget_set_visible (color_device->widget_arrow, TRUE);
|
||||
gtk_widget_set_margin_top (color_device->widget_button, 9);
|
||||
gtk_widget_set_margin_bottom (color_device->widget_button, 9);
|
||||
gtk_widget_set_margin_end (color_device->widget_button, 12);
|
||||
@@ -288,7 +290,8 @@ cc_color_device_init (CcColorDevice *color_device)
|
||||
|
||||
/* not calibrated */
|
||||
color_device->widget_nocalib = gtk_label_new (_("Not calibrated"));
|
||||
gtk_widget_add_css_class (color_device->widget_nocalib, "dim-label");
|
||||
context = gtk_widget_get_style_context (color_device->widget_nocalib);
|
||||
gtk_style_context_add_class (context, "dim-label");
|
||||
gtk_widget_set_margin_end (color_device->widget_nocalib, 18);
|
||||
gtk_box_append (GTK_BOX (box), color_device->widget_nocalib);
|
||||
|
||||
|
||||
@@ -417,8 +417,28 @@
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox3">
|
||||
<property name="spacing">9</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup" id="pref_group_devices"/>
|
||||
<object class="GtkLabel" id="label_intro">
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Each device needs an up to date color profile to be color managed.</property>
|
||||
<property name="wrap">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_padding">
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLinkButton" id="linkbutton_help">
|
||||
<property name="label" translatable="yes">Learn more</property>
|
||||
<property name="has_tooltip">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Learn more about color management</property>
|
||||
<property name="uri">help:gnome-help/color-whyimportant</property>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">label_intro</relation>
|
||||
</accessibility>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
@@ -10,6 +10,10 @@ NoDisplay=true
|
||||
StartupNotify=true
|
||||
Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;HardwareSettings;X-GNOME-DevicesSettings;
|
||||
OnlyShowIn=GNOME;Unity;
|
||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||
X-GNOME-Bugzilla-Product=gnome-control-center
|
||||
X-GNOME-Bugzilla-Component=color
|
||||
X-GNOME-Bugzilla-Version=@VERSION@
|
||||
# Translators: Search terms to find the Color panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
|
||||
Keywords=Color;ICC;Profile;Calibrate;Printer;Display;
|
||||
# Notifications are emitted by gnome-settings-daemon
|
||||
@@ -1,9 +1,15 @@
|
||||
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',
|
||||
input: desktop_in,
|
||||
output: desktop,
|
||||
po_dir: po_dir,
|
||||
install: true,
|
||||
@@ -19,10 +25,16 @@ sources = files(
|
||||
'cc-color-profile.c'
|
||||
)
|
||||
|
||||
resource_data = files(
|
||||
'cc-color-calibrate.ui',
|
||||
'cc-color-panel.ui',
|
||||
)
|
||||
|
||||
sources += gnome.compile_resources(
|
||||
'cc-' + cappletname + '-resources',
|
||||
cappletname + '.gresource.xml',
|
||||
c_name: 'cc_' + cappletname,
|
||||
dependencies: resource_data,
|
||||
export: true
|
||||
)
|
||||
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
|
||||
struct _CcHostnameEntry
|
||||
{
|
||||
AdwEntryRow parent;
|
||||
GtkEntry parent;
|
||||
|
||||
GDBusProxy *hostnamed_proxy;
|
||||
guint set_hostname_timeout_source_id;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcHostnameEntry, cc_hostname_entry, ADW_TYPE_ENTRY_ROW)
|
||||
G_DEFINE_TYPE (CcHostnameEntry, cc_hostname_entry, GTK_TYPE_ENTRY)
|
||||
|
||||
#define SET_HOSTNAME_TIMEOUT 1
|
||||
|
||||
@@ -207,6 +207,9 @@ cc_hostname_entry_constructed (GObject *object)
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
|
||||
}
|
||||
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self),
|
||||
g_permission_get_allowed (permission));
|
||||
|
||||
self->hostnamed_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL,
|
||||
@@ -231,9 +234,7 @@ cc_hostname_entry_constructed (GObject *object)
|
||||
else
|
||||
gtk_editable_set_text (GTK_EDITABLE (self), "");
|
||||
|
||||
g_signal_connect (self, "apply", G_CALLBACK (text_changed_cb), NULL);
|
||||
|
||||
adw_entry_row_set_show_apply_button (ADW_ENTRY_ROW (self), TRUE);
|
||||
g_signal_connect (self, "changed", G_CALLBACK (text_changed_cb), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <adwaita.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_HOSTNAME_ENTRY (cc_hostname_entry_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (CcHostnameEntry, cc_hostname_entry, CC, HOSTNAME_ENTRY, AdwEntryRow)
|
||||
G_DECLARE_FINAL_TYPE (CcHostnameEntry, cc_hostname_entry, CC, HOSTNAME_ENTRY, GtkEntry)
|
||||
|
||||
CcHostnameEntry *cc_hostname_entry_new (void);
|
||||
gchar* cc_hostname_entry_get_hostname (CcHostnameEntry *entry);
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
/* cc-illustrated-row.c
|
||||
*
|
||||
* Copyright 2018 Purism SPC
|
||||
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||
* 2023 Red Hat, Inc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 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 "cc-illustrated-row.h"
|
||||
|
||||
struct _CcIllustratedRow
|
||||
{
|
||||
CcVerticalRow parent;
|
||||
|
||||
GtkBox *picture_box;
|
||||
GtkPicture *picture;
|
||||
gchar *resource_path;
|
||||
|
||||
GtkMediaStream *media_stream;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE (CcIllustratedRow, cc_illustrated_row, CC_TYPE_VERTICAL_ROW);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_RESOURCE,
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
on_picture_leave_cb (CcIllustratedRow *self)
|
||||
{
|
||||
GtkMediaStream *stream = GTK_MEDIA_STREAM (gtk_picture_get_paintable (self->picture));
|
||||
|
||||
gtk_media_stream_set_loop (stream, FALSE);
|
||||
gtk_media_stream_pause (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
on_picture_hover_cb (CcIllustratedRow *self)
|
||||
{
|
||||
GtkMediaStream *stream = GTK_MEDIA_STREAM (gtk_picture_get_paintable (self->picture));
|
||||
|
||||
gtk_media_stream_set_loop (stream, TRUE);
|
||||
gtk_media_stream_play (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_illustrated_row_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcIllustratedRow *self = CC_ILLUSTRATED_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_RESOURCE:
|
||||
g_value_set_string (value, self->resource_path);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_illustrated_row_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcIllustratedRow *self = CC_ILLUSTRATED_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_RESOURCE:
|
||||
cc_illustrated_row_set_resource (self, g_value_get_string (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_illustrated_row_finalize (GObject *object)
|
||||
{
|
||||
CcIllustratedRow *self = CC_ILLUSTRATED_ROW (object);
|
||||
|
||||
g_clear_pointer (&self->resource_path, g_free);
|
||||
G_OBJECT_CLASS (cc_illustrated_row_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_illustrated_row_class_init (CcIllustratedRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->get_property = cc_illustrated_row_get_property;
|
||||
object_class->set_property = cc_illustrated_row_set_property;
|
||||
object_class->finalize = cc_illustrated_row_finalize;
|
||||
|
||||
props[PROP_RESOURCE] =
|
||||
g_param_spec_string ("resource",
|
||||
"Resource",
|
||||
"Resource",
|
||||
"",
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, props);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-illustrated-row.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcIllustratedRow, picture);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcIllustratedRow, picture_box);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_hover_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_leave_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_illustrated_row_init (CcIllustratedRow *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
gtk_widget_set_name (GTK_WIDGET (self), "illustrated-row");
|
||||
gtk_widget_add_css_class (GTK_WIDGET (self), "illustrated-row");
|
||||
}
|
||||
|
||||
void
|
||||
cc_illustrated_row_set_resource (CcIllustratedRow *self,
|
||||
const gchar *resource_path)
|
||||
{
|
||||
g_return_if_fail (CC_IS_ILLUSTRATED_ROW (self));
|
||||
|
||||
if (self->media_stream != NULL)
|
||||
g_clear_object (&self->media_stream);
|
||||
|
||||
g_set_str (&self->resource_path, resource_path);
|
||||
self->media_stream = gtk_media_file_new_for_resource (self->resource_path);
|
||||
|
||||
gtk_picture_set_paintable (self->picture, GDK_PAINTABLE (self->media_stream));
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->picture_box),
|
||||
self->resource_path != NULL &&
|
||||
g_strcmp0 (self->resource_path, "") != 0);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_RESOURCE]);
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/* cc-illustrated-row.h
|
||||
*
|
||||
* Copyright 2018 Purism SPC
|
||||
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||
* 2023 Red Hat, Inc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <adwaita.h>
|
||||
|
||||
#include "cc-vertical-row.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_ILLUSTRATED_ROW (cc_illustrated_row_get_type())
|
||||
G_DECLARE_FINAL_TYPE (CcIllustratedRow, cc_illustrated_row, CC, ILLUSTRATED_ROW, CcVerticalRow)
|
||||
|
||||
struct _CcIllustratedRowClass
|
||||
{
|
||||
CcVerticalRowClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[4];
|
||||
};
|
||||
|
||||
void cc_illustrated_row_set_resource (CcIllustratedRow *self,
|
||||
const gchar *resource_path);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcIllustratedRow" parent="CcVerticalRow">
|
||||
<child>
|
||||
<object class="GtkEventControllerMotion">
|
||||
<signal name="enter" handler="on_picture_hover_cb" object="CcIllustratedRow" swapped="yes"/>
|
||||
<signal name="leave" handler="on_picture_leave_cb" object="CcIllustratedRow" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="content">
|
||||
<object class="GtkBox" id="picture_box">
|
||||
<property name="visible">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<style>
|
||||
<class name="frame" />
|
||||
<class name="background" />
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkPicture" id="picture">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="margin-top">18</property>
|
||||
<property name="margin-bottom">18</property>
|
||||
<property name="margin-start">18</property>
|
||||
<property name="margin-end">18</property>
|
||||
<property name="height-request">128</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -68,6 +68,7 @@ add_all_languages (CcLanguageChooser *self)
|
||||
continue;
|
||||
|
||||
row = cc_language_row_new (locale_ids[i]);
|
||||
gtk_widget_show (GTK_WIDGET (row));
|
||||
is_initial = (g_hash_table_lookup (initial, locale_ids[i]) != NULL);
|
||||
cc_language_row_set_is_extra (row, !is_initial);
|
||||
gtk_list_box_prepend (self->language_listbox, GTK_WIDGET (row));
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="language_filter_entry">
|
||||
<property name="placeholder_text" translatable="yes">Language or country</property>
|
||||
<property name="width_chars">30</property>
|
||||
<signal name="search-changed" handler="language_filter_entry_search_changed_cb" object="CcLanguageChooser" swapped="yes"/>
|
||||
</object>
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* cc-list-row.c
|
||||
*
|
||||
* Copyright 2023 Red Hat Inc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 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/>.
|
||||
*
|
||||
* Author(s):
|
||||
* Felipe Borges <felipeborges@gnome.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "cc-list-row-info-button"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "cc-common-resources.h"
|
||||
#include "cc-list-row-info-button.h"
|
||||
|
||||
struct _CcListRowInfoButton
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button;
|
||||
GtkLabel *label;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcListRowInfoButton, cc_list_row_info_button, GTK_TYPE_WIDGET)
|
||||
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_TEXT,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS];
|
||||
|
||||
static void
|
||||
cc_list_row_info_button_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcListRowInfoButton *self = (CcListRowInfoButton *)object;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TEXT:
|
||||
g_value_set_string (value, gtk_label_get_label (self->label));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_list_row_info_button_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcListRowInfoButton *self = (CcListRowInfoButton *)object;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TEXT:
|
||||
gtk_label_set_label (self->label, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_list_row_info_button_dispose (GObject *object)
|
||||
{
|
||||
CcListRowInfoButton *self = CC_LIST_ROW_INFO_BUTTON (object);
|
||||
|
||||
g_clear_pointer (&self->button, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (cc_list_row_info_button_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_list_row_info_button_class_init (CcListRowInfoButtonClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->dispose = cc_list_row_info_button_dispose;
|
||||
object_class->get_property = cc_list_row_info_button_get_property;
|
||||
object_class->set_property = cc_list_row_info_button_set_property;
|
||||
|
||||
properties[PROP_TEXT] =
|
||||
g_param_spec_string ("text",
|
||||
"Text",
|
||||
"Set text for the popover label",
|
||||
NULL,
|
||||
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/"
|
||||
"common/cc-list-row-info-button.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcListRowInfoButton, button);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcListRowInfoButton, label);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_list_row_info_button_init (CcListRowInfoButton *self)
|
||||
{
|
||||
g_resources_register (cc_common_get_resource ());
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
void
|
||||
cc_list_row_info_button_set_text (CcListRowInfoButton *self,
|
||||
const gchar *text)
|
||||
{
|
||||
g_return_if_fail (CC_IS_LIST_ROW_INFO_BUTTON (self));
|
||||
|
||||
if (!text)
|
||||
text = "";
|
||||
|
||||
if (g_str_equal (text, gtk_label_get_label (self->label)))
|
||||
return;
|
||||
|
||||
gtk_label_set_text (self->label, text);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TEXT]);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* cc-list-row-info-button.h
|
||||
*
|
||||
* Copyright 2023 Red Hat Inc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 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/>.
|
||||
*
|
||||
* Author(s):
|
||||
* Felipe Borges <felipeborges@gnome.org>
|
||||
*
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_LIST_ROW_INFO_BUTTON (cc_list_row_info_button_get_type())
|
||||
G_DECLARE_FINAL_TYPE (CcListRowInfoButton, cc_list_row_info_button, CC, LIST_ROW_INFO_BUTTON, GtkWidget)
|
||||
|
||||
void cc_list_row_info_button_set_text (CcListRowInfoButton *self,
|
||||
const gchar *text);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcListRowInfoButton" parent="GtkWidget">
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="button">
|
||||
<property name="icon-name">info-symbolic</property>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
</style>
|
||||
<accessibility>
|
||||
<property name="label" translatable="yes">More information</property>
|
||||
</accessibility>
|
||||
<property name="popover">
|
||||
<object class="GtkPopover">
|
||||
<child>
|
||||
<object class="GtkLabel" id="label">
|
||||
<property name="halign">center</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="max-width-chars">50</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -40,6 +40,11 @@ struct _CcListRow
|
||||
|
||||
GtkImage *arrow;
|
||||
gboolean show_arrow;
|
||||
|
||||
GtkSwitch *enable_switch;
|
||||
gboolean show_switch;
|
||||
|
||||
gboolean switch_active;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcListRow, cc_list_row, ADW_TYPE_ACTION_ROW)
|
||||
@@ -49,11 +54,30 @@ enum {
|
||||
PROP_0,
|
||||
PROP_SECONDARY_LABEL,
|
||||
PROP_SHOW_ARROW,
|
||||
PROP_SHOW_SWITCH,
|
||||
PROP_ACTIVE,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS];
|
||||
|
||||
static void
|
||||
cc_list_row_switch_active_cb (CcListRow *self)
|
||||
{
|
||||
gboolean switch_active;
|
||||
|
||||
g_assert (CC_IS_LIST_ROW (self));
|
||||
g_assert (self->show_switch);
|
||||
|
||||
switch_active = gtk_switch_get_active (self->enable_switch);
|
||||
|
||||
if (switch_active == self->switch_active)
|
||||
return;
|
||||
|
||||
self->switch_active = switch_active;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIVE]);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_list_row_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
@@ -72,6 +96,10 @@ cc_list_row_get_property (GObject *object,
|
||||
g_value_set_boolean (value, self->show_arrow);
|
||||
break;
|
||||
|
||||
case PROP_ACTIVE:
|
||||
g_value_set_boolean (value, self->switch_active);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@@ -95,6 +123,20 @@ cc_list_row_set_property (GObject *object,
|
||||
cc_list_row_set_show_arrow (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_SHOW_SWITCH:
|
||||
cc_list_row_set_show_switch (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_ACTIVE:
|
||||
g_signal_handlers_block_by_func (self->enable_switch,
|
||||
cc_list_row_switch_active_cb, self);
|
||||
gtk_switch_set_active (self->enable_switch,
|
||||
g_value_get_boolean (value));
|
||||
self->switch_active = g_value_get_boolean (value);
|
||||
g_signal_handlers_unblock_by_func (self->enable_switch,
|
||||
cc_list_row_switch_active_cb, self);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@@ -123,6 +165,20 @@ cc_list_row_class_init (CcListRowClass *klass)
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SHOW_SWITCH] =
|
||||
g_param_spec_boolean ("show-switch",
|
||||
"Show Switch",
|
||||
"Whether to show a switch at the end of row",
|
||||
FALSE,
|
||||
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_ACTIVE] =
|
||||
g_param_spec_boolean ("active",
|
||||
"Active",
|
||||
"The active state of the switch",
|
||||
FALSE,
|
||||
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,
|
||||
@@ -131,6 +187,9 @@ cc_list_row_class_init (CcListRowClass *klass)
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcListRow, secondary_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcListRow, arrow);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcListRow, enable_switch);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, cc_list_row_switch_active_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -146,6 +205,7 @@ cc_list_row_set_show_arrow (CcListRow *self,
|
||||
gboolean show_arrow)
|
||||
{
|
||||
g_return_if_fail (CC_IS_LIST_ROW (self));
|
||||
g_return_if_fail (!self->show_switch);
|
||||
|
||||
if (self->show_arrow == show_arrow)
|
||||
return;
|
||||
@@ -154,11 +214,37 @@ cc_list_row_set_show_arrow (CcListRow *self,
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_ARROW]);
|
||||
}
|
||||
|
||||
void
|
||||
cc_list_row_set_show_switch (CcListRow *self,
|
||||
gboolean show_switch)
|
||||
{
|
||||
g_return_if_fail (CC_IS_LIST_ROW (self));
|
||||
|
||||
self->show_switch = !!show_switch;
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->enable_switch), self->show_switch);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->arrow), !self->show_switch);
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->secondary_label), !self->show_switch);
|
||||
|
||||
adw_action_row_set_activatable_widget (ADW_ACTION_ROW (self),
|
||||
self->show_switch ? GTK_WIDGET (self->enable_switch) : NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
cc_list_row_get_active (CcListRow *self)
|
||||
{
|
||||
g_return_val_if_fail (CC_IS_LIST_ROW (self), FALSE);
|
||||
g_return_val_if_fail (self->show_switch, FALSE);
|
||||
|
||||
return self->switch_active;
|
||||
}
|
||||
|
||||
void
|
||||
cc_list_row_set_secondary_label (CcListRow *self,
|
||||
const gchar *label)
|
||||
{
|
||||
g_return_if_fail (CC_IS_LIST_ROW (self));
|
||||
g_return_if_fail (!self->show_switch);
|
||||
|
||||
if (!label)
|
||||
label = "";
|
||||
@@ -175,6 +261,7 @@ cc_list_row_set_secondary_markup (CcListRow *self,
|
||||
const gchar *markup)
|
||||
{
|
||||
g_return_if_fail (CC_IS_LIST_ROW (self));
|
||||
g_return_if_fail (!self->show_switch);
|
||||
|
||||
if (!markup)
|
||||
markup = "";
|
||||
@@ -185,3 +272,12 @@ cc_list_row_set_secondary_markup (CcListRow *self,
|
||||
gtk_label_set_markup (self->secondary_label, markup);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SECONDARY_LABEL]);
|
||||
}
|
||||
|
||||
void
|
||||
cc_list_row_set_switch_sensitive (CcListRow *self,
|
||||
gboolean sensitive)
|
||||
{
|
||||
g_return_if_fail (CC_IS_LIST_ROW (self));
|
||||
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self->enable_switch), sensitive);
|
||||
}
|
||||
|
||||
@@ -34,9 +34,14 @@ G_DECLARE_FINAL_TYPE (CcListRow, cc_list_row, CC, LIST_ROW, AdwActionRow)
|
||||
|
||||
void cc_list_row_set_show_arrow (CcListRow *self,
|
||||
gboolean show_arrow);
|
||||
void cc_list_row_set_show_switch (CcListRow *self,
|
||||
gboolean show_switch);
|
||||
gboolean cc_list_row_get_active (CcListRow *self);
|
||||
void cc_list_row_set_secondary_label (CcListRow *self,
|
||||
const gchar *label);
|
||||
void cc_list_row_set_secondary_markup (CcListRow *self,
|
||||
const gchar *markup);
|
||||
void cc_list_row_set_switch_sensitive (CcListRow *self,
|
||||
gboolean sensitive);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -15,6 +15,15 @@
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Switch -->
|
||||
<child type="suffix">
|
||||
<object class="GtkSwitch" id="enable_switch">
|
||||
<property name="visible">False</property>
|
||||
<property name="valign">center</property>
|
||||
<signal name="notify::active" handler="cc_list_row_switch_active_cb" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Arrow -->
|
||||
<child type="suffix">
|
||||
<object class="GtkImage" id="arrow">
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <adwaita.h>
|
||||
|
||||
#include "cc-permission-infobar.h"
|
||||
|
||||
@@ -36,10 +35,9 @@ struct _CcPermissionInfobar
|
||||
{
|
||||
AdwBin parent_instance;
|
||||
|
||||
AdwBanner *banner;
|
||||
GPermission *permission;
|
||||
|
||||
GCancellable *cancellable;
|
||||
GtkRevealer *revealer;
|
||||
GtkLabel *title;
|
||||
GtkLockButton *lock_button;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcPermissionInfobar, cc_permission_infobar, ADW_TYPE_BIN)
|
||||
@@ -47,109 +45,27 @@ G_DEFINE_TYPE (CcPermissionInfobar, cc_permission_infobar, ADW_TYPE_BIN)
|
||||
static void
|
||||
on_permission_changed (CcPermissionInfobar *self)
|
||||
{
|
||||
gboolean is_authorized = g_permission_get_allowed (self->permission);
|
||||
GPermission *permission;
|
||||
gboolean is_authorized;
|
||||
|
||||
adw_banner_set_revealed (self->banner, !is_authorized);
|
||||
}
|
||||
permission = gtk_lock_button_get_permission (self->lock_button);
|
||||
is_authorized = g_permission_get_allowed (permission);
|
||||
|
||||
static void
|
||||
acquire_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPermissionInfobar *self = CC_PERMISSION_INFOBAR (user_data);
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
if (!g_permission_acquire_finish (self->permission, result, &error))
|
||||
{
|
||||
g_warning ("Error acquiring permission: %s", error->message);
|
||||
}
|
||||
|
||||
g_clear_object (&self->cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
release_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPermissionInfobar *self = CC_PERMISSION_INFOBAR (user_data);
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
if (!g_permission_release_finish (self->permission, result, &error))
|
||||
{
|
||||
g_warning ("Error releasing permission: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_clear_object (&self->cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
banner_button_clicked_cb (CcPermissionInfobar *self)
|
||||
{
|
||||
/* if we already have a pending interactive check or permission is not set,
|
||||
* then do nothing
|
||||
*/
|
||||
if (self->cancellable != NULL || self->permission == NULL)
|
||||
return;
|
||||
|
||||
if (g_permission_get_allowed (self->permission))
|
||||
{
|
||||
if (g_permission_get_can_release (self->permission))
|
||||
{
|
||||
self->cancellable = g_cancellable_new ();
|
||||
|
||||
g_permission_release_async (self->permission,
|
||||
self->cancellable,
|
||||
release_cb,
|
||||
self);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_permission_get_can_acquire (self->permission))
|
||||
{
|
||||
self->cancellable = g_cancellable_new ();
|
||||
|
||||
g_permission_acquire_async (self->permission,
|
||||
self->cancellable,
|
||||
acquire_cb,
|
||||
self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_permission_infobar_dispose (GObject *object)
|
||||
{
|
||||
CcPermissionInfobar *self = CC_PERMISSION_INFOBAR (object);
|
||||
|
||||
if (self->cancellable != NULL)
|
||||
{
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
}
|
||||
|
||||
g_clear_object (&self->cancellable);
|
||||
|
||||
G_OBJECT_CLASS (cc_permission_infobar_parent_class)->dispose (object);
|
||||
gtk_revealer_set_reveal_child (self->revealer, !is_authorized);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_permission_infobar_class_init (CcPermissionInfobarClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->dispose = cc_permission_infobar_dispose;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
"/org/gnome/control-center/"
|
||||
"common/cc-permission-infobar.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcPermissionInfobar, banner);
|
||||
gtk_widget_class_bind_template_callback (widget_class,
|
||||
banner_button_clicked_cb);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcPermissionInfobar, revealer);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcPermissionInfobar, title);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcPermissionInfobar, lock_button);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -167,13 +83,7 @@ cc_permission_infobar_set_permission (CcPermissionInfobar *self,
|
||||
{
|
||||
g_return_if_fail (CC_IS_PERMISSION_INFOBAR (self));
|
||||
|
||||
if (permission == NULL)
|
||||
{
|
||||
g_warning ("Missing GPermission object");
|
||||
return;
|
||||
}
|
||||
|
||||
self->permission = permission;
|
||||
gtk_lock_button_set_permission (self->lock_button, permission);
|
||||
|
||||
g_signal_connect_object (permission, "notify",
|
||||
G_CALLBACK (on_permission_changed),
|
||||
@@ -195,12 +105,8 @@ cc_permission_infobar_set_title (CcPermissionInfobar *self,
|
||||
{
|
||||
g_return_if_fail (CC_IS_PERMISSION_INFOBAR (self));
|
||||
|
||||
if (self->permission == NULL)
|
||||
title = _("Error: some settings cannot be unlocked");
|
||||
|
||||
if (title == NULL)
|
||||
title = _("Unlock to Change Settings");
|
||||
|
||||
adw_banner_set_title (self->banner, title);
|
||||
adw_banner_set_button_label (self->banner, self->permission ? _("_Unlock…") : NULL);
|
||||
gtk_label_set_text (self->title, title);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcPermissionInfobar" parent="AdwBin">
|
||||
<property name="valign">start</property>
|
||||
<child>
|
||||
<object class="AdwBanner" id="banner">
|
||||
<property name="revealed">True</property>
|
||||
<property name="title" translatable="yes">Error: some settings cannot be unlocked</property>
|
||||
<property name="button-label" translatable="yes">_Unlock…</property>
|
||||
<signal name="button-clicked" handler="banner_button_clicked_cb" swapped="yes"/>
|
||||
<object class="GtkRevealer" id="revealer">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="reveal-child">True</property>
|
||||
<child>
|
||||
<object class="GtkInfoBar">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">system-lock-screen-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="title">
|
||||
<property name="halign">start</property>
|
||||
<!-- Actual string set in code -->
|
||||
<property name="label"></property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Some settings must be unlocked before they can be changed.</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkCenterBox">
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<child type="end">
|
||||
<object class="GtkLockButton" id="lock_button">
|
||||
<property name="receives-default">True</property>
|
||||
<property name="label" translatable="yes">Unlock…</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
||||
@@ -1,440 +0,0 @@
|
||||
/* cc-split-row.c
|
||||
*
|
||||
* Copyright 2018 Purism SPC
|
||||
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||
* 2023 Red Hat, Inc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 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 "cc-split-row.h"
|
||||
|
||||
struct _CcSplitRow
|
||||
{
|
||||
CcVerticalRow parent;
|
||||
|
||||
GtkPicture *default_option_picture;
|
||||
GtkPicture *alternative_option_picture;
|
||||
|
||||
GtkCheckButton *alternative_option_checkbutton;
|
||||
GtkCheckButton *default_option_checkbutton;
|
||||
|
||||
gchar *alternative_resource_path;
|
||||
gchar *default_resource_path;
|
||||
|
||||
gchar *alternative_option_title;
|
||||
gchar *alternative_option_subtitle;
|
||||
gchar *default_option_title;
|
||||
gchar *default_option_subtitle;
|
||||
|
||||
gboolean use_default;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE (CcSplitRow, cc_split_row, CC_TYPE_VERTICAL_ROW);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_USE_DEFAULT,
|
||||
PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE,
|
||||
PROP_ALTERNATIVE_OPTION_TITLE,
|
||||
PROP_ALTERNATIVE_OPTION_SUBTITLE,
|
||||
PROP_DEFAULT_ILLUSTRATION_RESOURCE,
|
||||
PROP_DEFAULT_OPTION_TITLE,
|
||||
PROP_DEFAULT_OPTION_SUBTITLE,
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
on_default_option_click_released_cb (CcSplitRow *self)
|
||||
{
|
||||
gtk_widget_activate (GTK_WIDGET (self->default_option_checkbutton));
|
||||
}
|
||||
|
||||
static void
|
||||
on_alternative_option_click_released_cb (CcSplitRow *self)
|
||||
{
|
||||
gtk_widget_activate (GTK_WIDGET (self->alternative_option_checkbutton));
|
||||
}
|
||||
|
||||
static void
|
||||
focus_leave (GtkPicture *picture)
|
||||
{
|
||||
GtkMediaStream *stream;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
paintable = gtk_picture_get_paintable (picture);
|
||||
|
||||
if (!GTK_IS_MEDIA_STREAM (paintable))
|
||||
return;
|
||||
|
||||
stream = GTK_MEDIA_STREAM (paintable);
|
||||
gtk_media_stream_set_loop (stream, FALSE);
|
||||
gtk_media_stream_pause (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
on_default_option_focus_leave_cb (CcSplitRow *self)
|
||||
{
|
||||
focus_leave (self->default_option_picture);
|
||||
}
|
||||
|
||||
static void
|
||||
on_alternative_option_focus_leave_cb (CcSplitRow *self)
|
||||
{
|
||||
focus_leave (self->alternative_option_picture);
|
||||
}
|
||||
|
||||
static void
|
||||
focus_enter (GtkPicture *picture)
|
||||
{
|
||||
GtkMediaStream *stream;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
paintable = gtk_picture_get_paintable (picture);
|
||||
|
||||
if (!GTK_IS_MEDIA_STREAM (paintable))
|
||||
return;
|
||||
|
||||
stream = GTK_MEDIA_STREAM (paintable);
|
||||
gtk_media_stream_set_loop (stream, TRUE);
|
||||
gtk_media_stream_play (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
on_default_option_focus_enter_cb (CcSplitRow *self)
|
||||
{
|
||||
focus_enter (self->default_option_picture);
|
||||
}
|
||||
|
||||
static void
|
||||
on_alternative_option_focus_enter_cb (CcSplitRow *self)
|
||||
{
|
||||
focus_enter (self->alternative_option_picture);
|
||||
}
|
||||
|
||||
static void
|
||||
on_checkbutton_toggled_cb (CcSplitRow *self)
|
||||
{
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_DEFAULT]);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_split_row_dispose (GObject *object)
|
||||
{
|
||||
CcSplitRow *self = CC_SPLIT_ROW (object);
|
||||
|
||||
g_clear_pointer (&self->default_resource_path, g_free);
|
||||
g_clear_pointer (&self->alternative_resource_path, g_free);
|
||||
g_clear_pointer (&self->alternative_option_title, g_free);
|
||||
g_clear_pointer (&self->alternative_option_subtitle, g_free);
|
||||
g_clear_pointer (&self->default_option_title, g_free);
|
||||
g_clear_pointer (&self->default_option_subtitle, g_free);
|
||||
|
||||
G_OBJECT_CLASS (cc_split_row_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_split_row_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcSplitRow *self = CC_SPLIT_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_USE_DEFAULT:
|
||||
g_value_set_boolean (value, gtk_check_button_get_active (self->default_option_checkbutton));
|
||||
break;
|
||||
case PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE:
|
||||
g_value_set_string (value, cc_split_row_get_alternative_illustration_resource (self));
|
||||
break;
|
||||
case PROP_ALTERNATIVE_OPTION_TITLE:
|
||||
g_value_set_string (value, cc_split_row_get_alternative_option_title (self));
|
||||
break;
|
||||
case PROP_ALTERNATIVE_OPTION_SUBTITLE:
|
||||
g_value_set_string (value, cc_split_row_get_alternative_option_subtitle (self));
|
||||
break;
|
||||
case PROP_DEFAULT_ILLUSTRATION_RESOURCE:
|
||||
g_value_set_string (value, cc_split_row_get_default_illustration_resource (self));
|
||||
break;
|
||||
case PROP_DEFAULT_OPTION_TITLE:
|
||||
g_value_set_string (value, cc_split_row_get_default_option_title (self));
|
||||
break;
|
||||
case PROP_DEFAULT_OPTION_SUBTITLE:
|
||||
g_value_set_string (value, cc_split_row_get_default_option_subtitle (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_split_row_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcSplitRow *self = CC_SPLIT_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_USE_DEFAULT:
|
||||
cc_split_row_set_use_default (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE:
|
||||
cc_split_row_set_alternative_illustration_resource (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_ALTERNATIVE_OPTION_TITLE:
|
||||
cc_split_row_set_alternative_option_title (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_ALTERNATIVE_OPTION_SUBTITLE:
|
||||
cc_split_row_set_alternative_option_subtitle (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_DEFAULT_ILLUSTRATION_RESOURCE:
|
||||
cc_split_row_set_default_illustration_resource (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_DEFAULT_OPTION_TITLE:
|
||||
cc_split_row_set_default_option_title (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_DEFAULT_OPTION_SUBTITLE:
|
||||
cc_split_row_set_default_option_subtitle (self, g_value_get_string (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_split_row_class_init (CcSplitRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->dispose = cc_split_row_dispose;
|
||||
object_class->get_property = cc_split_row_get_property;
|
||||
object_class->set_property = cc_split_row_set_property;
|
||||
|
||||
props[PROP_USE_DEFAULT] =
|
||||
g_param_spec_boolean ("use-default",
|
||||
"Use Default",
|
||||
"Use Default",
|
||||
TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE] =
|
||||
g_param_spec_string ("alternative-illustration-resource",
|
||||
"Alternative illustration resource",
|
||||
"Alternative illustration resource",
|
||||
"",
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
props[PROP_ALTERNATIVE_OPTION_TITLE] =
|
||||
g_param_spec_string ("alternative-option-title",
|
||||
"Alternative option title",
|
||||
"Alternative option title",
|
||||
"",
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
props[PROP_ALTERNATIVE_OPTION_SUBTITLE] =
|
||||
g_param_spec_string ("alternative-option-subtitle",
|
||||
"Alternative option subtitle",
|
||||
"Alternative option subtitle",
|
||||
"",
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
props[PROP_DEFAULT_ILLUSTRATION_RESOURCE] =
|
||||
g_param_spec_string ("default-illustration-resource",
|
||||
"Default illustration resource",
|
||||
"Default illustration resource",
|
||||
"",
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
props[PROP_DEFAULT_OPTION_TITLE] =
|
||||
g_param_spec_string ("default-option-title",
|
||||
"Default option title",
|
||||
"Default option title",
|
||||
"",
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
props[PROP_DEFAULT_OPTION_SUBTITLE] =
|
||||
g_param_spec_string ("default-option-subtitle",
|
||||
"Default option subtitle",
|
||||
"Default option subtitle",
|
||||
"",
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, props);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-split-row.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcSplitRow, alternative_option_checkbutton);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcSplitRow, alternative_option_picture);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcSplitRow, default_option_checkbutton);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcSplitRow, default_option_picture);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_checkbutton_toggled_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_default_option_click_released_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_alternative_option_click_released_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_default_option_focus_enter_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_alternative_option_focus_enter_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_default_option_focus_leave_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_alternative_option_focus_leave_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_split_row_init (CcSplitRow *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
gtk_widget_set_name (GTK_WIDGET (self), "split-row");
|
||||
gtk_widget_add_css_class (GTK_WIDGET (self), "split-row");
|
||||
}
|
||||
|
||||
const gchar *
|
||||
cc_split_row_get_default_illustration_resource (CcSplitRow *self)
|
||||
{
|
||||
return self->default_resource_path;
|
||||
}
|
||||
|
||||
void
|
||||
cc_split_row_set_default_illustration_resource (CcSplitRow *self,
|
||||
const gchar *resource_path)
|
||||
{
|
||||
g_autoptr(GtkMediaStream) media_file = NULL;
|
||||
|
||||
g_return_if_fail (CC_IS_SPLIT_ROW (self));
|
||||
|
||||
g_set_str (&self->default_resource_path, resource_path);
|
||||
media_file = gtk_media_file_new_for_resource (resource_path);
|
||||
|
||||
gtk_picture_set_paintable (self->default_option_picture, GDK_PAINTABLE (media_file));
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->default_option_picture),
|
||||
resource_path != NULL && g_strcmp0 (resource_path, "") != 0);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEFAULT_ILLUSTRATION_RESOURCE]);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
cc_split_row_get_alternative_illustration_resource (CcSplitRow *self)
|
||||
{
|
||||
return self->alternative_resource_path;
|
||||
}
|
||||
|
||||
void
|
||||
cc_split_row_set_alternative_illustration_resource (CcSplitRow *self,
|
||||
const gchar *resource_path)
|
||||
{
|
||||
g_autoptr(GtkMediaStream) media_file = NULL;
|
||||
|
||||
g_return_if_fail (CC_IS_SPLIT_ROW (self));
|
||||
|
||||
g_set_str (&self->alternative_resource_path, resource_path);
|
||||
media_file = gtk_media_file_new_for_resource (resource_path);
|
||||
gtk_media_stream_set_loop (media_file, TRUE);
|
||||
|
||||
gtk_picture_set_paintable (self->alternative_option_picture, GDK_PAINTABLE (media_file));
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->alternative_option_picture),
|
||||
resource_path != NULL && g_strcmp0 (resource_path, "") != 0);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE]);
|
||||
}
|
||||
|
||||
void
|
||||
cc_split_row_set_use_default (CcSplitRow *self,
|
||||
gboolean use_default)
|
||||
{
|
||||
g_return_if_fail (CC_IS_SPLIT_ROW (self));
|
||||
|
||||
gtk_check_button_set_active (use_default ? self->default_option_checkbutton : self->alternative_option_checkbutton, TRUE);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_DEFAULT]);
|
||||
}
|
||||
|
||||
gboolean
|
||||
cc_split_row_get_use_default (CcSplitRow *self)
|
||||
{
|
||||
return gtk_check_button_get_active (self->default_option_checkbutton);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
cc_split_row_get_default_option_title (CcSplitRow *self)
|
||||
{
|
||||
g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
|
||||
|
||||
return self->default_option_title;
|
||||
}
|
||||
|
||||
void
|
||||
cc_split_row_set_default_option_title (CcSplitRow *self,
|
||||
const gchar *title)
|
||||
{
|
||||
g_return_if_fail (CC_IS_SPLIT_ROW (self));
|
||||
|
||||
if (g_set_str (&self->default_option_title, title))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEFAULT_OPTION_TITLE]);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
cc_split_row_get_default_option_subtitle (CcSplitRow *self)
|
||||
{
|
||||
g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
|
||||
|
||||
return self->default_option_subtitle;
|
||||
}
|
||||
|
||||
void
|
||||
cc_split_row_set_default_option_subtitle (CcSplitRow *self,
|
||||
const gchar *subtitle)
|
||||
{
|
||||
g_return_if_fail (CC_IS_SPLIT_ROW (self));
|
||||
|
||||
if (g_set_str (&self->default_option_subtitle, subtitle))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEFAULT_OPTION_SUBTITLE]);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
cc_split_row_get_alternative_option_title (CcSplitRow *self)
|
||||
{
|
||||
g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
|
||||
|
||||
return self->alternative_option_title;
|
||||
}
|
||||
|
||||
void
|
||||
cc_split_row_set_alternative_option_title (CcSplitRow *self,
|
||||
const gchar *title)
|
||||
{
|
||||
g_return_if_fail (CC_IS_SPLIT_ROW (self));
|
||||
|
||||
if (g_set_str (&self->alternative_option_title, title))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALTERNATIVE_OPTION_TITLE]);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
cc_split_row_get_alternative_option_subtitle (CcSplitRow *self)
|
||||
{
|
||||
g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
|
||||
|
||||
return self->alternative_option_subtitle;
|
||||
}
|
||||
|
||||
void
|
||||
cc_split_row_set_alternative_option_subtitle (CcSplitRow *self,
|
||||
const gchar *subtitle)
|
||||
{
|
||||
g_return_if_fail (CC_IS_SPLIT_ROW (self));
|
||||
|
||||
if (g_set_str (&self->alternative_option_subtitle, subtitle))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALTERNATIVE_OPTION_SUBTITLE]);
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/* cc-vertical-row.h
|
||||
*
|
||||
* Copyright 2018 Purism SPC
|
||||
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||
* 2023 Red Hat, Inc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <adwaita.h>
|
||||
|
||||
#include "cc-vertical-row.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_SPLIT_ROW (cc_split_row_get_type())
|
||||
G_DECLARE_FINAL_TYPE (CcSplitRow, cc_split_row, CC, SPLIT_ROW, CcVerticalRow)
|
||||
|
||||
struct _CcSplitRowClass
|
||||
{
|
||||
CcVerticalRowClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[4];
|
||||
};
|
||||
|
||||
void cc_split_row_set_default_illustration_resource (CcSplitRow *self,
|
||||
const gchar *resource_path);
|
||||
|
||||
const gchar *cc_split_row_get_default_illustration_resource (CcSplitRow *self);
|
||||
|
||||
void cc_split_row_set_alternative_illustration_resource (CcSplitRow *self,
|
||||
const gchar *resource_path);
|
||||
|
||||
const gchar *cc_split_row_get_alternative_illustration_resource (CcSplitRow *self);
|
||||
|
||||
void cc_split_row_set_use_default (CcSplitRow *self,
|
||||
gboolean use_default);
|
||||
|
||||
gboolean cc_split_row_get_use_default (CcSplitRow *self);
|
||||
|
||||
const gchar *cc_split_row_get_default_option_title (CcSplitRow *self);
|
||||
|
||||
void cc_split_row_set_default_option_title (CcSplitRow *self,
|
||||
const gchar *title);
|
||||
const gchar *cc_split_row_get_default_option_subtitle (CcSplitRow *self);
|
||||
|
||||
void cc_split_row_set_default_option_subtitle (CcSplitRow *self,
|
||||
const gchar *subtitle);
|
||||
const gchar *cc_split_row_get_alternative_option_title (CcSplitRow *self);
|
||||
|
||||
void cc_split_row_set_alternative_option_title (CcSplitRow *self,
|
||||
const gchar *title);
|
||||
const gchar *cc_split_row_get_alternative_option_subtitle (CcSplitRow *self);
|
||||
|
||||
void cc_split_row_set_alternative_option_subtitle (CcSplitRow *self,
|
||||
const gchar *subtitle);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,172 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcSplitRow" parent="CcVerticalRow">
|
||||
<child type="content">
|
||||
<object class="GtkBox">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="spacing">24</property>
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
|
||||
<!-- Default Option -->
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkEventControllerMotion">
|
||||
<signal name="enter" handler="on_default_option_focus_enter_cb" object="CcSplitRow" swapped="yes" />
|
||||
<signal name="leave" handler="on_default_option_focus_leave_cb" object="CcSplitRow" swapped="yes" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkGestureClick">
|
||||
<signal name="released" handler="on_default_option_click_released_cb" object="CcSplitRow" swapped="yes" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwBin">
|
||||
<style>
|
||||
<class name="background"/>
|
||||
<class name="frame"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkPicture" id="default_option_picture">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="margin-top">18</property>
|
||||
<property name="margin-bottom">18</property>
|
||||
<property name="margin-start">18</property>
|
||||
<property name="margin-end">18</property>
|
||||
<property name="height-request">128</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="default_option_checkbutton">
|
||||
<property name="margin-start">6</property>
|
||||
<property name="group">alternative_option_checkbutton</property>
|
||||
<signal name="toggled" handler="on_checkbutton_toggled_cb" object="CcSplitRow" swapped="yes"/>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0.0</property>
|
||||
<binding name="label">
|
||||
<lookup name="default-option-title">CcSplitRow</lookup>
|
||||
</binding>
|
||||
<style>
|
||||
<class name="title" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0.0</property>
|
||||
<binding name="label">
|
||||
<lookup name="default-option-subtitle">CcSplitRow</lookup>
|
||||
</binding>
|
||||
<style>
|
||||
<class name="subtitle" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Alternative Option -->
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkEventControllerMotion">
|
||||
<signal name="enter" handler="on_alternative_option_focus_enter_cb" object="CcSplitRow" swapped="yes" />
|
||||
<signal name="leave" handler="on_alternative_option_focus_leave_cb" object="CcSplitRow" swapped="yes" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkGestureClick">
|
||||
<signal name="released" handler="on_alternative_option_click_released_cb" object="CcSplitRow" swapped="yes" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwBin">
|
||||
<style>
|
||||
<class name="background"/>
|
||||
<class name="frame"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkPicture" id="alternative_option_picture">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="margin-top">18</property>
|
||||
<property name="margin-bottom">18</property>
|
||||
<property name="margin-start">18</property>
|
||||
<property name="margin-end">18</property>
|
||||
<property name="height-request">128</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="alternative_option_checkbutton">
|
||||
<property name="margin-start">6</property>
|
||||
<signal name="toggled" handler="on_checkbutton_toggled_cb" object="CcSplitRow" swapped="yes"/>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0.0</property>
|
||||
<binding name="label">
|
||||
<lookup name="alternative-option-title">CcSplitRow</lookup>
|
||||
</binding>
|
||||
<style>
|
||||
<class name="title" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0.0</property>
|
||||
<binding name="label">
|
||||
<lookup name="alternative-option-subtitle">CcSplitRow</lookup>
|
||||
</binding>
|
||||
<style>
|
||||
<class name="subtitle" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -108,7 +108,6 @@ time_editor_time_changed_cb (CcTimeEditor *self)
|
||||
{
|
||||
g_assert (CC_IS_TIME_EDITOR (self));
|
||||
|
||||
time_editor_clock_changed_cb (self);
|
||||
g_signal_emit (self, signals[TIME_CHANGED], 0);
|
||||
}
|
||||
|
||||
@@ -236,7 +235,6 @@ cc_time_editor_constructed (GObject *object)
|
||||
{
|
||||
CcTimeEditor *self = (CcTimeEditor *)object;
|
||||
GDateTime *date;
|
||||
GtkWidget *grid;
|
||||
char *label;
|
||||
|
||||
G_OBJECT_CLASS (cc_time_editor_parent_class)->constructed (object);
|
||||
@@ -254,10 +252,6 @@ cc_time_editor_constructed (GObject *object)
|
||||
gtk_label_set_label (self->pm_label, label);
|
||||
g_date_time_unref (date);
|
||||
g_free (label);
|
||||
|
||||
/* Force LTR so we don't reorder clock buttons for RTL languages */
|
||||
grid = gtk_widget_get_parent (GTK_WIDGET (self->hour_up_button));
|
||||
gtk_widget_set_direction (grid, GTK_TEXT_DIR_LTR);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -337,10 +337,11 @@ on_text_toggle_overwrite_cb (GtkText *text,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_key_pressed_cb (CcTimeEntry *self,
|
||||
on_key_pressed_cb (GtkEventControllerKey *key_controller,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
GdkModifierType state)
|
||||
GdkModifierType state,
|
||||
CcTimeEntry *self)
|
||||
{
|
||||
/* Allow entering numbers */
|
||||
if (!(state & GDK_SHIFT_MASK) &&
|
||||
@@ -411,7 +412,6 @@ cc_time_entry_constructed (GObject *object)
|
||||
|
||||
G_OBJECT_CLASS (cc_time_entry_parent_class)->constructed (object);
|
||||
|
||||
gtk_widget_set_direction (GTK_WIDGET (self->text), GTK_TEXT_DIR_LTR);
|
||||
time_entry_fill_time (CC_TIME_ENTRY (object));
|
||||
|
||||
list = pango_attr_list_new ();
|
||||
@@ -516,7 +516,7 @@ cc_time_entry_init (CcTimeEntry *self)
|
||||
|
||||
key_controller = gtk_event_controller_key_new ();
|
||||
gtk_event_controller_set_propagation_phase (key_controller, GTK_PHASE_CAPTURE);
|
||||
g_signal_connect_swapped (key_controller, "key-pressed", G_CALLBACK (on_key_pressed_cb), self);
|
||||
g_signal_connect (key_controller, "key-pressed", G_CALLBACK (on_key_pressed_cb), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), key_controller);
|
||||
|
||||
self->text = g_object_new (GTK_TYPE_TEXT,
|
||||
@@ -568,8 +568,6 @@ cc_time_entry_set_time (CcTimeEntry *self,
|
||||
self->minute = CLAMP (minute, 0, 59);
|
||||
|
||||
cc_time_entry_set_am_pm (self, is_am_pm);
|
||||
|
||||
g_signal_emit (self, signals[TIME_CHANGED], 0);
|
||||
time_entry_fill_time (self);
|
||||
}
|
||||
|
||||
|
||||
@@ -145,23 +145,6 @@ cc_util_get_smart_date (GDateTime *date)
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
cc_util_get_smart_date_time (GDateTime *date)
|
||||
{
|
||||
g_autofree gchar *date_str = NULL;
|
||||
g_autofree gchar *smart_date = NULL;
|
||||
|
||||
if (date == NULL)
|
||||
return NULL;
|
||||
|
||||
smart_date = cc_util_get_smart_date (date);
|
||||
date_str = g_date_time_format (date, "\%X");
|
||||
/* TRANSLATORS: This is the datetime format in the style of
|
||||
"Aug 1, 10:10:10 PM", "Feb 24, 2013, 10:10:10 PM", "Today, 10:10:10 AM",
|
||||
and "Yesterday, 10:10:10 AM" */
|
||||
return g_strdup_printf (_("%1$s, %2$s"), smart_date, date_str);
|
||||
}
|
||||
|
||||
/* Copied from src/plugins/properties/bacon-video-widget-properties.c
|
||||
* in totem */
|
||||
char *
|
||||
|
||||
@@ -24,5 +24,4 @@
|
||||
|
||||
char * cc_util_normalize_casefold_and_unaccent (const char *str);
|
||||
char * cc_util_get_smart_date (GDateTime *date);
|
||||
char * cc_util_get_smart_date_time (GDateTime *date);
|
||||
char * cc_util_time_to_string_text (gint64 msecs);
|
||||
|
||||
@@ -1,606 +0,0 @@
|
||||
/* cc-vertical-row.c
|
||||
*
|
||||
* Copyright 2018 Purism SPC
|
||||
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||
* 2023 Red Hat, Inc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 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 "cc-vertical-row.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AdwPreferencesRow parent;
|
||||
|
||||
GtkBox *content_box;
|
||||
GtkBox *header;
|
||||
GtkImage *image;
|
||||
GtkBox *prefixes;
|
||||
GtkLabel *subtitle;
|
||||
GtkBox *suffixes;
|
||||
GtkLabel *title;
|
||||
GtkBox *title_box;
|
||||
|
||||
GtkWidget *previous_parent;
|
||||
|
||||
gboolean use_underline;
|
||||
gint title_lines;
|
||||
gint subtitle_lines;
|
||||
GtkWidget *activatable_widget;
|
||||
} CcVerticalRowPrivate;
|
||||
|
||||
static GtkBuildableIface *parent_buildable_iface;
|
||||
|
||||
static void cc_vertical_row_buildable_init (GtkBuildableIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (CcVerticalRow, cc_vertical_row, ADW_TYPE_PREFERENCES_ROW,
|
||||
G_ADD_PRIVATE (CcVerticalRow) G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, cc_vertical_row_buildable_init))
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_ICON_NAME,
|
||||
PROP_ACTIVATABLE_WIDGET,
|
||||
PROP_SUBTITLE,
|
||||
PROP_USE_UNDERLINE,
|
||||
PROP_TITLE_LINES,
|
||||
PROP_SUBTITLE_LINES,
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_ACTIVATED,
|
||||
SIGNAL_LAST_SIGNAL,
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPS] = { NULL, };
|
||||
static guint signals[SIGNAL_LAST_SIGNAL] = { 0, };
|
||||
|
||||
static void
|
||||
row_activated_cb (CcVerticalRow *self,
|
||||
GtkListBoxRow *row)
|
||||
{
|
||||
/* No need to use GTK_LIST_BOX_ROW() for a pointer comparison. */
|
||||
if ((GtkListBoxRow *) self == row)
|
||||
cc_vertical_row_activate (self);
|
||||
}
|
||||
|
||||
static void
|
||||
parent_cb (CcVerticalRow *self)
|
||||
{
|
||||
GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self));
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
if (priv->previous_parent != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (priv->previous_parent,
|
||||
G_CALLBACK (row_activated_cb),
|
||||
self);
|
||||
priv->previous_parent = NULL;
|
||||
}
|
||||
|
||||
if (parent == NULL || !GTK_IS_LIST_BOX (parent))
|
||||
return;
|
||||
|
||||
priv->previous_parent = parent;
|
||||
g_signal_connect_swapped (parent, "row-activated", G_CALLBACK (row_activated_cb), self);
|
||||
}
|
||||
|
||||
static void
|
||||
update_subtitle_visibility (CcVerticalRow *self)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (priv->subtitle),
|
||||
gtk_label_get_text (priv->subtitle) != NULL &&
|
||||
g_strcmp0 (gtk_label_get_text (priv->subtitle), "") != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_vertical_row_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcVerticalRow *self = CC_VERTICAL_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ICON_NAME:
|
||||
g_value_set_string (value, cc_vertical_row_get_icon_name (self));
|
||||
break;
|
||||
case PROP_ACTIVATABLE_WIDGET:
|
||||
g_value_set_object (value, (GObject *) cc_vertical_row_get_activatable_widget (self));
|
||||
break;
|
||||
case PROP_SUBTITLE:
|
||||
g_value_set_string (value, cc_vertical_row_get_subtitle (self));
|
||||
break;
|
||||
case PROP_SUBTITLE_LINES:
|
||||
g_value_set_int (value, cc_vertical_row_get_subtitle_lines (self));
|
||||
break;
|
||||
case PROP_TITLE_LINES:
|
||||
g_value_set_int (value, cc_vertical_row_get_title_lines (self));
|
||||
break;
|
||||
case PROP_USE_UNDERLINE:
|
||||
g_value_set_boolean (value, cc_vertical_row_get_use_underline (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_vertical_row_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcVerticalRow *self = CC_VERTICAL_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ICON_NAME:
|
||||
cc_vertical_row_set_icon_name (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_ACTIVATABLE_WIDGET:
|
||||
cc_vertical_row_set_activatable_widget (self, (GtkWidget*) g_value_get_object (value));
|
||||
break;
|
||||
case PROP_SUBTITLE:
|
||||
cc_vertical_row_set_subtitle (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_SUBTITLE_LINES:
|
||||
cc_vertical_row_set_subtitle_lines (self, g_value_get_int (value));
|
||||
break;
|
||||
case PROP_TITLE_LINES:
|
||||
cc_vertical_row_set_title_lines (self, g_value_get_int (value));
|
||||
break;
|
||||
case PROP_USE_UNDERLINE:
|
||||
cc_vertical_row_set_use_underline (self, g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_vertical_row_dispose (GObject *object)
|
||||
{
|
||||
CcVerticalRow *self = CC_VERTICAL_ROW (object);
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
if (priv->previous_parent != NULL) {
|
||||
g_signal_handlers_disconnect_by_func (priv->previous_parent, G_CALLBACK (row_activated_cb), self);
|
||||
priv->previous_parent = NULL;
|
||||
}
|
||||
|
||||
cc_vertical_row_set_activatable_widget (self, NULL);
|
||||
g_clear_pointer ((GtkWidget**)&priv->header, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (cc_vertical_row_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_vertical_row_class_init (CcVerticalRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->get_property = cc_vertical_row_get_property;
|
||||
object_class->set_property = cc_vertical_row_set_property;
|
||||
object_class->dispose = cc_vertical_row_dispose;
|
||||
|
||||
props[PROP_ICON_NAME] =
|
||||
g_param_spec_string ("icon-name",
|
||||
"Icon name",
|
||||
"Icon name",
|
||||
"",
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PROP_ACTIVATABLE_WIDGET] =
|
||||
g_param_spec_object ("activatable-widget",
|
||||
"Activatable widget",
|
||||
"The widget to be activated when the row is activated",
|
||||
GTK_TYPE_WIDGET,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
props[PROP_SUBTITLE] =
|
||||
g_param_spec_string ("subtitle",
|
||||
"Subtitle",
|
||||
"Subtitle",
|
||||
"",
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PROP_USE_UNDERLINE] =
|
||||
g_param_spec_boolean ("use-underline",
|
||||
"Use underline",
|
||||
"If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PROP_TITLE_LINES] =
|
||||
g_param_spec_int ("title-lines",
|
||||
"Number of title lines",
|
||||
"The desired number of title lines",
|
||||
0, G_MAXINT,
|
||||
1,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PROP_SUBTITLE_LINES] =
|
||||
g_param_spec_int ("subtitle-lines",
|
||||
"Number of subtitle lines",
|
||||
"The desired number of subtitle lines",
|
||||
0, G_MAXINT,
|
||||
1,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, props);
|
||||
|
||||
signals[SIGNAL_ACTIVATED] =
|
||||
g_signal_new ("activated",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-vertical-row.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, content_box);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, header);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, image);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, prefixes);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, subtitle);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, suffixes);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, title);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, title_box);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
string_is_not_empty (GBinding *binding,
|
||||
const GValue *from_value,
|
||||
GValue *to_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
const gchar *string = g_value_get_string (from_value);
|
||||
|
||||
g_value_set_boolean (to_value, string != NULL && g_strcmp0 (string, "") != 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_vertical_row_init (CcVerticalRow *self)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
priv->title_lines = 1;
|
||||
priv->subtitle_lines = 1;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
g_object_bind_property_full (self, "title",
|
||||
priv->title, "visible",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
string_is_not_empty,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
update_subtitle_visibility (self);
|
||||
|
||||
g_signal_connect (self, "notify::parent", G_CALLBACK (parent_cb), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_vertical_row_buildable_add_child (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *type)
|
||||
{
|
||||
CcVerticalRow *self = CC_VERTICAL_ROW (buildable);
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
if (!priv->header)
|
||||
parent_buildable_iface->add_child (buildable, builder, child, type);
|
||||
else if (type && strcmp (type, "prefix") == 0)
|
||||
cc_vertical_row_add_prefix (self, GTK_WIDGET (child));
|
||||
else if (type && strcmp (type, "content") == 0)
|
||||
cc_vertical_row_add_content (self, GTK_WIDGET (child));
|
||||
else if (!type && GTK_IS_WIDGET (child))
|
||||
{
|
||||
gtk_box_append (priv->suffixes, GTK_WIDGET (child));
|
||||
gtk_widget_set_visible (GTK_WIDGET (priv->suffixes), TRUE);
|
||||
}
|
||||
else
|
||||
parent_buildable_iface->add_child (buildable, builder, child, type);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_vertical_row_buildable_init (GtkBuildableIface *iface)
|
||||
{
|
||||
parent_buildable_iface = g_type_interface_peek_parent (iface);
|
||||
iface->add_child = cc_vertical_row_buildable_add_child;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
cc_vertical_row_get_subtitle (CcVerticalRow *self)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), NULL);
|
||||
|
||||
return gtk_label_get_text (priv->subtitle);
|
||||
}
|
||||
|
||||
void
|
||||
cc_vertical_row_set_subtitle (CcVerticalRow *self,
|
||||
const gchar *subtitle)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
|
||||
|
||||
if (g_strcmp0 (gtk_label_get_text (priv->subtitle), subtitle) == 0)
|
||||
return;
|
||||
|
||||
gtk_label_set_text (priv->subtitle, subtitle);
|
||||
gtk_widget_set_visible (GTK_WIDGET (priv->subtitle),
|
||||
subtitle != NULL && g_strcmp0 (subtitle, "") != 0);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBTITLE]);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
cc_vertical_row_get_icon_name (CcVerticalRow *self)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), NULL);
|
||||
|
||||
return gtk_image_get_icon_name (priv->image);
|
||||
}
|
||||
|
||||
void
|
||||
cc_vertical_row_set_icon_name (CcVerticalRow *self,
|
||||
const gchar *icon_name)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
const gchar *old_icon_name;
|
||||
|
||||
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
|
||||
|
||||
old_icon_name = gtk_image_get_icon_name (priv->image);
|
||||
if (g_strcmp0 (old_icon_name, icon_name) == 0)
|
||||
return;
|
||||
|
||||
gtk_image_set_from_icon_name (priv->image, icon_name);
|
||||
gtk_widget_set_visible (GTK_WIDGET (priv->image),
|
||||
icon_name != NULL && g_strcmp0 (icon_name, "") != 0);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_NAME]);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
cc_vertical_row_get_activatable_widget (CcVerticalRow *self)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), NULL);
|
||||
|
||||
return priv->activatable_widget;
|
||||
}
|
||||
|
||||
static void
|
||||
activatable_widget_weak_notify (gpointer data,
|
||||
GObject *where_the_object_was)
|
||||
{
|
||||
CcVerticalRow *self = CC_VERTICAL_ROW (data);
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
priv->activatable_widget = NULL;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVATABLE_WIDGET]);
|
||||
}
|
||||
|
||||
void
|
||||
cc_vertical_row_set_activatable_widget (CcVerticalRow *self,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
|
||||
g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
|
||||
|
||||
if (priv->activatable_widget == widget)
|
||||
return;
|
||||
|
||||
if (priv->activatable_widget)
|
||||
g_object_weak_unref (G_OBJECT (priv->activatable_widget),
|
||||
activatable_widget_weak_notify,
|
||||
self);
|
||||
|
||||
priv->activatable_widget = widget;
|
||||
|
||||
if (priv->activatable_widget != NULL) {
|
||||
g_object_weak_ref (G_OBJECT (priv->activatable_widget),
|
||||
activatable_widget_weak_notify,
|
||||
self);
|
||||
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (self), TRUE);
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (priv->activatable_widget),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, priv->title, NULL,
|
||||
GTK_ACCESSIBLE_RELATION_DESCRIBED_BY, priv->subtitle, NULL,
|
||||
-1);
|
||||
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVATABLE_WIDGET]);
|
||||
}
|
||||
|
||||
gboolean
|
||||
cc_vertical_row_get_use_underline (CcVerticalRow *self)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), FALSE);
|
||||
|
||||
return priv->use_underline;
|
||||
}
|
||||
|
||||
void
|
||||
cc_vertical_row_set_use_underline (CcVerticalRow *self,
|
||||
gboolean use_underline)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
|
||||
|
||||
use_underline = !!use_underline;
|
||||
|
||||
if (priv->use_underline == use_underline)
|
||||
return;
|
||||
|
||||
priv->use_underline = use_underline;
|
||||
adw_preferences_row_set_use_underline (ADW_PREFERENCES_ROW (self), priv->use_underline);
|
||||
gtk_label_set_use_underline (priv->title, priv->use_underline);
|
||||
gtk_label_set_use_underline (priv->subtitle, priv->use_underline);
|
||||
gtk_label_set_mnemonic_widget (priv->title, GTK_WIDGET (self));
|
||||
gtk_label_set_mnemonic_widget (priv->subtitle, GTK_WIDGET (self));
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_UNDERLINE]);
|
||||
}
|
||||
|
||||
gint
|
||||
cc_vertical_row_get_title_lines (CcVerticalRow *self)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), 0);
|
||||
|
||||
return priv->title_lines;
|
||||
}
|
||||
|
||||
void
|
||||
cc_vertical_row_set_title_lines (CcVerticalRow *self,
|
||||
gint title_lines)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
|
||||
g_return_if_fail (title_lines >= 0);
|
||||
|
||||
if (priv->title_lines == title_lines)
|
||||
return;
|
||||
|
||||
priv->title_lines = title_lines;
|
||||
|
||||
gtk_label_set_lines (priv->title, title_lines);
|
||||
gtk_label_set_ellipsize (priv->title, title_lines == 0 ? PANGO_ELLIPSIZE_NONE : PANGO_ELLIPSIZE_END);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TITLE_LINES]);
|
||||
}
|
||||
|
||||
gint
|
||||
cc_vertical_row_get_subtitle_lines (CcVerticalRow *self)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), 0);
|
||||
|
||||
return priv->subtitle_lines;
|
||||
}
|
||||
|
||||
void
|
||||
cc_vertical_row_set_subtitle_lines (CcVerticalRow *self,
|
||||
gint subtitle_lines)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
|
||||
g_return_if_fail (subtitle_lines >= 0);
|
||||
|
||||
if (priv->subtitle_lines == subtitle_lines)
|
||||
return;
|
||||
|
||||
priv->subtitle_lines = subtitle_lines;
|
||||
|
||||
gtk_label_set_lines (priv->subtitle, subtitle_lines);
|
||||
gtk_label_set_ellipsize (priv->subtitle, subtitle_lines == 0 ? PANGO_ELLIPSIZE_NONE : PANGO_ELLIPSIZE_END);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBTITLE_LINES]);
|
||||
}
|
||||
|
||||
void
|
||||
cc_vertical_row_add_prefix (CcVerticalRow *self,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
|
||||
g_return_if_fail (GTK_IS_WIDGET (self));
|
||||
|
||||
gtk_box_append (priv->prefixes, widget);
|
||||
gtk_widget_set_visible (GTK_WIDGET (priv->prefixes), TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
cc_vertical_row_add_content (CcVerticalRow *self,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
|
||||
g_return_if_fail (GTK_IS_WIDGET (self));
|
||||
|
||||
/* HACK: the content box pushes the title too much to the top, so we
|
||||
* need to compensate this here.
|
||||
*/
|
||||
gtk_widget_set_margin_top (GTK_WIDGET (priv->header), 12);
|
||||
|
||||
gtk_box_append (priv->content_box, widget);
|
||||
gtk_widget_set_visible (GTK_WIDGET (priv->content_box), TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
cc_vertical_row_activate (CcVerticalRow *self)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
|
||||
|
||||
if (priv->activatable_widget)
|
||||
gtk_widget_mnemonic_activate (priv->activatable_widget, FALSE);
|
||||
|
||||
g_signal_emit (self, signals[SIGNAL_ACTIVATED], 0);
|
||||
}
|
||||
|
||||
void
|
||||
cc_vertical_row_remove (CcVerticalRow *self,
|
||||
GtkWidget *child)
|
||||
{
|
||||
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
|
||||
GtkWidget *parent;
|
||||
|
||||
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
|
||||
g_return_if_fail (GTK_IS_WIDGET (child));
|
||||
|
||||
parent = gtk_widget_get_parent (child);
|
||||
|
||||
if (parent == GTK_WIDGET (priv->prefixes))
|
||||
gtk_box_remove (priv->prefixes, child);
|
||||
else if (parent == GTK_WIDGET (priv->suffixes))
|
||||
gtk_box_remove (priv->suffixes, child);
|
||||
else if (parent == GTK_WIDGET (priv->content_box))
|
||||
gtk_box_remove (priv->content_box, child);
|
||||
else
|
||||
g_warning ("%p is not a child of %p", child, self);
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/* cc-vertical-row.h
|
||||
*
|
||||
* Copyright 2018 Purism SPC
|
||||
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||
* 2023 Red Hat, Inc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <adwaita.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_VERTICAL_ROW (cc_vertical_row_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE (CcVerticalRow, cc_vertical_row, CC, VERTICAL_ROW, AdwPreferencesRow)
|
||||
|
||||
struct _CcVerticalRowClass
|
||||
{
|
||||
AdwPreferencesRowClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[4];
|
||||
};
|
||||
|
||||
const gchar *cc_vertical_row_get_subtitle (CcVerticalRow *self);
|
||||
void cc_vertical_row_set_subtitle (CcVerticalRow *self,
|
||||
const gchar *subtitle);
|
||||
|
||||
const gchar *cc_vertical_row_get_icon_name (CcVerticalRow *self);
|
||||
void cc_vertical_row_set_icon_name (CcVerticalRow *self,
|
||||
const gchar *icon_name);
|
||||
|
||||
GtkWidget *cc_vertical_row_get_activatable_widget (CcVerticalRow *self);
|
||||
void cc_vertical_row_set_activatable_widget (CcVerticalRow *self,
|
||||
GtkWidget *widget);
|
||||
|
||||
gboolean cc_vertical_row_get_use_underline (CcVerticalRow *self);
|
||||
void cc_vertical_row_set_use_underline (CcVerticalRow *self,
|
||||
gboolean use_underline);
|
||||
|
||||
gint cc_vertical_row_get_title_lines (CcVerticalRow *self);
|
||||
void cc_vertical_row_set_title_lines (CcVerticalRow *self,
|
||||
gint title_lines);
|
||||
|
||||
gint cc_vertical_row_get_subtitle_lines (CcVerticalRow *self);
|
||||
void cc_vertical_row_set_subtitle_lines (CcVerticalRow *self,
|
||||
gint subtitle_lines);
|
||||
|
||||
void cc_vertical_row_add_prefix (CcVerticalRow *self,
|
||||
GtkWidget *widget);
|
||||
|
||||
void cc_vertical_row_add_content (CcVerticalRow *self,
|
||||
GtkWidget *widget);
|
||||
|
||||
void cc_vertical_row_activate (CcVerticalRow *self);
|
||||
|
||||
void cc_vertical_row_remove (CcVerticalRow *self,
|
||||
GtkWidget *child);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,14 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gnome/control-center/common">
|
||||
<file preprocess="xml-stripblanks">cc-illustrated-row.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-language-chooser.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-language-row.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-list-row.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-list-row-info-button.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-time-editor.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-permission-infobar.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-split-row.ui</file>
|
||||
<file preprocess="xml-stripblanks">cc-vertical-row.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
@@ -24,10 +24,19 @@ 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-language-chooser.ui',
|
||||
'cc-language-row.ui',
|
||||
'cc-list-row.ui',
|
||||
'cc-time-editor.ui',
|
||||
'cc-permission-infobar.ui',
|
||||
)
|
||||
|
||||
common_sources += gnome.compile_resources(
|
||||
'cc-common-resources',
|
||||
'common.gresource.xml',
|
||||
c_name: 'cc_common',
|
||||
dependencies: resource_data,
|
||||
export: true
|
||||
)
|
||||
|
||||
@@ -54,15 +63,11 @@ libwidgets_dep = declare_dependency(
|
||||
|
||||
sources = common_sources + files(
|
||||
'cc-common-language.c',
|
||||
'cc-illustrated-row.c',
|
||||
'cc-language-chooser.c',
|
||||
'cc-language-row.c',
|
||||
'cc-list-row.c',
|
||||
'cc-list-row-info-button.c',
|
||||
'cc-time-editor.c',
|
||||
'cc-permission-infobar.c',
|
||||
'cc-split-row.c',
|
||||
'cc-vertical-row.c',
|
||||
'cc-util.c'
|
||||
)
|
||||
|
||||
@@ -118,3 +123,4 @@ configure_file(
|
||||
configuration: polkit_conf,
|
||||
install_dir: join_paths(control_center_datadir, 'polkit-1', 'rules.d')
|
||||
)
|
||||
|
||||
|
||||
@@ -20,21 +20,18 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "cc-list-row.h"
|
||||
#include "cc-time-editor.h"
|
||||
#include "cc-datetime-panel.h"
|
||||
#include "cc-datetime-resources.h"
|
||||
#include "cc-list-row.h"
|
||||
|
||||
#include <langinfo.h>
|
||||
#include <sys/time.h>
|
||||
#include "cc-tz-dialog.h"
|
||||
#include "cc-timezone-map.h"
|
||||
#include "timedated.h"
|
||||
#include "date-endian.h"
|
||||
#define GNOME_DESKTOP_USE_UNSTABLE_API
|
||||
|
||||
#include <gdesktop-enums.h>
|
||||
#include "gdesktop-enums-types.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <libintl.h>
|
||||
@@ -48,6 +45,12 @@
|
||||
#define DEFAULT_TZ "Europe/London"
|
||||
#define GETTEXT_PACKAGE_TIMEZONES GETTEXT_PACKAGE "-timezones"
|
||||
|
||||
enum {
|
||||
CITY_COL_CITY_HUMAN_READABLE,
|
||||
CITY_COL_ZONE,
|
||||
CITY_NUM_COLS
|
||||
};
|
||||
|
||||
#define DATETIME_PERMISSION "org.gnome.controlcenter.datetime.configure"
|
||||
#define DATETIME_TZ_PERMISSION "org.freedesktop.timedate1.set-timezone"
|
||||
#define LOCATION_SETTINGS "org.gnome.system.location"
|
||||
@@ -55,12 +58,6 @@
|
||||
|
||||
#define CLOCK_SCHEMA "org.gnome.desktop.interface"
|
||||
#define CLOCK_FORMAT_KEY "clock-format"
|
||||
#define CLOCK_SHOW_WEEKDAY_KEY "clock-show-weekday"
|
||||
#define CLOCK_SHOW_DATE_KEY "clock-show-date"
|
||||
#define CLOCK_SHOW_SECONDS_KEY "clock-show-seconds"
|
||||
|
||||
#define CALENDAR_SCHEMA "org.gnome.desktop.calendar"
|
||||
#define CALENDAR_SHOW_WEEK_NUMBERS_KEY "show-weekdate"
|
||||
|
||||
#define FILECHOOSER_SCHEMA "org.gtk.Settings.FileChooser"
|
||||
|
||||
@@ -71,6 +68,8 @@ struct _CcDateTimePanel
|
||||
{
|
||||
CcPanel parent_instance;
|
||||
|
||||
GtkWidget *map;
|
||||
|
||||
GList *toplevels;
|
||||
|
||||
TzLocation *current_location;
|
||||
@@ -80,45 +79,40 @@ struct _CcDateTimePanel
|
||||
GDateTime *date;
|
||||
|
||||
GSettings *clock_settings;
|
||||
GSettings *calendar_settings;
|
||||
GSettings *datetime_settings;
|
||||
GSettings *filechooser_settings;
|
||||
GDesktopClockFormat clock_format;
|
||||
AdwActionRow *auto_datetime_row;
|
||||
AdwActionRow *auto_timezone_row;
|
||||
GtkSwitch *auto_timezone_switch;
|
||||
AdwActionRow *datetime_row;
|
||||
GtkDialog *datetime_dialog;
|
||||
GtkLabel *datetime_label;
|
||||
GtkSpinButton *day_spinbutton;
|
||||
AdwComboRow *timeformat_row;
|
||||
GtkSpinButton *h_spinbutton;
|
||||
GtkWidget *weekday_row;
|
||||
GtkWidget *weekday_switch;
|
||||
GtkWidget *date_switch;
|
||||
GtkWidget *seconds_switch;
|
||||
GtkWidget *week_numbers_switch;
|
||||
GtkFrame *aspectmap;
|
||||
GtkWidget *auto_datetime_row;
|
||||
GtkWidget *auto_timezone_row;
|
||||
GtkWidget *auto_timezone_switch;
|
||||
GtkListStore *city_liststore;
|
||||
GtkTreeModelSort *city_modelsort;
|
||||
GtkWidget *date_grid;
|
||||
GtkWidget *datetime_button;
|
||||
GtkWidget *datetime_dialog;
|
||||
GtkWidget *datetime_label;
|
||||
GtkWidget *day_spinbutton;
|
||||
GtkWidget *timeformat_row;
|
||||
GtkWidget *h_spinbutton;
|
||||
GtkLockButton *lock_button;
|
||||
GtkListBox *date_box;
|
||||
AdwActionRow *day_row;
|
||||
GtkSingleSelection *month_model;
|
||||
GtkPopover *month_popover;
|
||||
CcListRow *month_row;
|
||||
AdwActionRow *year_row;
|
||||
GtkSwitch *network_time_switch;
|
||||
CcTimeEditor *time_editor;
|
||||
AdwActionRow *timezone_row;
|
||||
CcTzDialog *timezone_dialog;
|
||||
GtkLabel *timezone_label;
|
||||
GtkSpinButton *year_spinbutton;
|
||||
GtkListBoxRow *day_row;
|
||||
AdwComboRow *month_row;
|
||||
GtkListBoxRow *year_row;
|
||||
GtkWidget *network_time_switch;
|
||||
GtkWidget *time_editor;
|
||||
GtkWidget *timezone_button;
|
||||
GtkWidget *timezone_dialog;
|
||||
GtkWidget *timezone_label;
|
||||
GtkWidget *timezone_searchentry;
|
||||
GtkWidget *year_spinbutton;
|
||||
|
||||
GnomeWallClock *clock_tracker;
|
||||
|
||||
Timedate1 *dtm;
|
||||
GCancellable *cancellable;
|
||||
|
||||
gboolean pending_ntp_state;
|
||||
|
||||
GPermission *permission;
|
||||
GPermission *tz_permission;
|
||||
GSettings *location_settings;
|
||||
@@ -133,31 +127,30 @@ static void update_time (CcDateTimePanel *self);
|
||||
static void
|
||||
cc_date_time_panel_dispose (GObject *object)
|
||||
{
|
||||
CcDateTimePanel *self = CC_DATE_TIME_PANEL (object);
|
||||
CcDateTimePanel *panel = CC_DATE_TIME_PANEL (object);
|
||||
|
||||
if (self->cancellable)
|
||||
if (panel->cancellable)
|
||||
{
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_clear_object (&self->cancellable);
|
||||
g_cancellable_cancel (panel->cancellable);
|
||||
g_clear_object (&panel->cancellable);
|
||||
}
|
||||
|
||||
if (self->toplevels)
|
||||
if (panel->toplevels)
|
||||
{
|
||||
g_list_free_full (self->toplevels, (GDestroyNotify) gtk_window_destroy);
|
||||
self->toplevels = NULL;
|
||||
g_list_free_full (panel->toplevels, (GDestroyNotify) gtk_window_destroy);
|
||||
panel->toplevels = NULL;
|
||||
}
|
||||
|
||||
g_clear_object (&self->clock_tracker);
|
||||
g_clear_object (&self->dtm);
|
||||
g_clear_object (&self->permission);
|
||||
g_clear_object (&self->tz_permission);
|
||||
g_clear_object (&self->location_settings);
|
||||
g_clear_object (&self->clock_settings);
|
||||
g_clear_object (&self->calendar_settings);
|
||||
g_clear_object (&self->datetime_settings);
|
||||
g_clear_object (&self->filechooser_settings);
|
||||
g_clear_object (&panel->clock_tracker);
|
||||
g_clear_object (&panel->dtm);
|
||||
g_clear_object (&panel->permission);
|
||||
g_clear_object (&panel->tz_permission);
|
||||
g_clear_object (&panel->location_settings);
|
||||
g_clear_object (&panel->clock_settings);
|
||||
g_clear_object (&panel->datetime_settings);
|
||||
g_clear_object (&panel->filechooser_settings);
|
||||
|
||||
g_clear_pointer (&self->date, g_date_time_unref);
|
||||
g_clear_pointer (&panel->date, g_date_time_unref);
|
||||
|
||||
G_OBJECT_CLASS (cc_date_time_panel_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -168,7 +161,7 @@ cc_date_time_panel_get_help_uri (CcPanel *panel)
|
||||
return "help:gnome-help/clock";
|
||||
}
|
||||
|
||||
static void clock_settings_changed_cb (CcDateTimePanel *self,
|
||||
static void clock_settings_changed_cb (CcDateTimePanel *panel,
|
||||
gchar *key);
|
||||
|
||||
static char *
|
||||
@@ -188,7 +181,9 @@ format_clock_name_cb (AdwEnumListItem *item,
|
||||
}
|
||||
|
||||
static void
|
||||
change_clock_settings (CcDateTimePanel *self)
|
||||
change_clock_settings (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
CcDateTimePanel *self)
|
||||
{
|
||||
GDesktopClockFormat value;
|
||||
AdwEnumListItem *item;
|
||||
@@ -196,7 +191,7 @@ change_clock_settings (CcDateTimePanel *self)
|
||||
g_signal_handlers_block_by_func (self->clock_settings, clock_settings_changed_cb,
|
||||
self);
|
||||
|
||||
item = ADW_ENUM_LIST_ITEM (adw_combo_row_get_selected_item (self->timeformat_row));
|
||||
item = ADW_ENUM_LIST_ITEM (adw_combo_row_get_selected_item (ADW_COMBO_ROW (self->timeformat_row)));
|
||||
value = adw_enum_list_item_get_value (item);
|
||||
|
||||
g_settings_set_enum (self->clock_settings, CLOCK_FORMAT_KEY, value);
|
||||
@@ -220,9 +215,9 @@ clock_settings_changed_cb (CcDateTimePanel *self,
|
||||
|
||||
g_signal_handlers_block_by_func (self->timeformat_row, change_clock_settings, self);
|
||||
|
||||
adw_combo_row_set_selected (self->timeformat_row, value);
|
||||
adw_combo_row_set_selected (ADW_COMBO_ROW (self->timeformat_row), value);
|
||||
|
||||
cc_time_editor_set_am_pm (self->time_editor,
|
||||
cc_time_editor_set_am_pm (CC_TIME_EDITOR (self->time_editor),
|
||||
value == G_DESKTOP_CLOCK_FORMAT_12H);
|
||||
update_time (self);
|
||||
|
||||
@@ -242,7 +237,7 @@ update_time (CcDateTimePanel *self)
|
||||
else
|
||||
use_ampm = FALSE;
|
||||
|
||||
cc_time_editor_set_time (self->time_editor,
|
||||
cc_time_editor_set_time (CC_TIME_EDITOR (self->time_editor),
|
||||
g_date_time_get_hour (self->date),
|
||||
g_date_time_get_minute (self->date));
|
||||
|
||||
@@ -259,8 +254,8 @@ update_time (CcDateTimePanel *self)
|
||||
}
|
||||
|
||||
self->month = g_date_time_get_month (self->date);
|
||||
gtk_single_selection_set_selected (self->month_model, self->month - 1);
|
||||
gtk_label_set_text (self->datetime_label, label);
|
||||
adw_combo_row_set_selected (self->month_row, self->month - 1);
|
||||
gtk_label_set_text (GTK_LABEL (self->datetime_label), label);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -316,10 +311,6 @@ set_using_ntp_cb (GObject *source,
|
||||
/* TODO: display any error in a user friendly way */
|
||||
g_warning ("Could not set system to use NTP: %s", error->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_switch_set_state (self->network_time_switch, self->pending_ntp_state);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -340,10 +331,12 @@ queue_set_datetime (CcDateTimePanel *self)
|
||||
}
|
||||
|
||||
static void
|
||||
queue_set_ntp (CcDateTimePanel *self,
|
||||
gboolean using_ntp)
|
||||
queue_set_ntp (CcDateTimePanel *self)
|
||||
{
|
||||
self->pending_ntp_state = using_ntp;
|
||||
gboolean using_ntp;
|
||||
/* for now just do it */
|
||||
using_ntp = gtk_switch_get_active (GTK_SWITCH (self->network_time_switch));
|
||||
|
||||
timedate1_call_set_ntp (self->dtm,
|
||||
using_ntp,
|
||||
TRUE,
|
||||
@@ -373,21 +366,40 @@ change_date (CcDateTimePanel *self)
|
||||
guint y, d;
|
||||
g_autoptr(GDateTime) old_date = NULL;
|
||||
|
||||
y = gtk_spin_button_get_value_as_int (self->year_spinbutton);
|
||||
d = gtk_spin_button_get_value_as_int (self->day_spinbutton);
|
||||
y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (self->year_spinbutton));
|
||||
d = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (self->day_spinbutton));
|
||||
|
||||
old_date = self->date;
|
||||
self->date = g_date_time_new_local (y, self->month, d,
|
||||
g_date_time_get_hour (old_date),
|
||||
g_date_time_get_minute (old_date),
|
||||
g_date_time_get_second (old_date));
|
||||
cc_time_editor_set_time (self->time_editor,
|
||||
cc_time_editor_set_time (CC_TIME_EDITOR (self->time_editor),
|
||||
g_date_time_get_hour (self->date),
|
||||
g_date_time_get_minute (self->date));
|
||||
|
||||
queue_set_datetime (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
city_changed_cb (CcDateTimePanel *self,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter,
|
||||
GtkEntryCompletion *completion)
|
||||
{
|
||||
GtkWidget *entry;
|
||||
g_autofree gchar *zone = NULL;
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
CITY_COL_ZONE, &zone, -1);
|
||||
cc_timezone_map_set_timezone (CC_TIMEZONE_MAP (self->map), zone);
|
||||
|
||||
entry = gtk_entry_completion_get_entry (completion);
|
||||
gtk_editable_set_text (GTK_EDITABLE (entry), "");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char *
|
||||
translated_city_name (TzLocation *loc)
|
||||
{
|
||||
@@ -418,8 +430,18 @@ translated_city_name (TzLocation *loc)
|
||||
static void
|
||||
update_timezone (CcDateTimePanel *self)
|
||||
{
|
||||
g_autofree gchar *bubble_text = NULL;
|
||||
g_autofree gchar *city_country = NULL;
|
||||
g_autofree gchar *label = NULL;
|
||||
g_autofree gchar *time_label = NULL;
|
||||
g_autofree gchar *utc_label = NULL;
|
||||
g_autofree gchar *tz_desc = NULL;
|
||||
gboolean use_ampm;
|
||||
|
||||
if (self->clock_format == G_DESKTOP_CLOCK_FORMAT_12H)
|
||||
use_ampm = TRUE;
|
||||
else
|
||||
use_ampm = FALSE;
|
||||
|
||||
city_country = translated_city_name (self->current_location);
|
||||
|
||||
@@ -428,7 +450,63 @@ update_timezone (CcDateTimePanel *self)
|
||||
label = g_strdup_printf (C_("timezone desc", "%s (%s)"),
|
||||
g_date_time_get_timezone_abbreviation (self->date),
|
||||
city_country);
|
||||
gtk_label_set_text (self->timezone_label, label);
|
||||
gtk_label_set_text (GTK_LABEL (self->timezone_label), label);
|
||||
|
||||
/* Translators: UTC here means the Coordinated Universal Time.
|
||||
* %:::z will be replaced by the offset from UTC e.g. UTC+02 */
|
||||
utc_label = g_date_time_format (self->date, _("UTC%:::z"));
|
||||
|
||||
if (use_ampm)
|
||||
{
|
||||
/* Translators: This is the time format used in 12-hour mode. */
|
||||
time_label = g_date_time_format (self->date, _("%l:%M %p"));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Translators: This is the time format used in 24-hour mode. */
|
||||
time_label = g_date_time_format (self->date, _("%R"));
|
||||
}
|
||||
|
||||
/* Update the text bubble in the timezone map */
|
||||
/* Translators: "timezone (utc shift)" */
|
||||
tz_desc = g_strdup_printf (C_("timezone map", "%s (%s)"),
|
||||
g_date_time_get_timezone_abbreviation (self->date),
|
||||
utc_label);
|
||||
bubble_text = g_strdup_printf ("<b>%s</b>\n"
|
||||
"<small>%s</small>\n"
|
||||
"<b>%s</b>",
|
||||
tz_desc,
|
||||
city_country,
|
||||
time_label);
|
||||
cc_timezone_map_set_bubble_text (CC_TIMEZONE_MAP (self->map), bubble_text);
|
||||
}
|
||||
|
||||
static void
|
||||
location_changed_cb (CcDateTimePanel *self,
|
||||
TzLocation *location)
|
||||
{
|
||||
g_autoptr(GDateTime) old_date = NULL;
|
||||
g_autoptr(GTimeZone) timezone = NULL;
|
||||
|
||||
g_debug ("location changed to %s/%s", location->country, location->zone);
|
||||
|
||||
self->current_location = location;
|
||||
|
||||
timezone = g_time_zone_new_identifier (location->zone);
|
||||
if (!timezone)
|
||||
{
|
||||
g_warning ("Could not find timezone \"%s\", using UTC instead", location->zone);
|
||||
timezone = g_time_zone_new_utc ();
|
||||
}
|
||||
|
||||
old_date = self->date;
|
||||
self->date = g_date_time_to_timezone (old_date, timezone);
|
||||
cc_time_editor_set_time (CC_TIME_EDITOR (self->time_editor),
|
||||
g_date_time_get_hour (self->date),
|
||||
g_date_time_get_minute (self->date));
|
||||
|
||||
update_timezone (self);
|
||||
queue_set_timezone (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -439,20 +517,41 @@ get_initial_timezone (CcDateTimePanel *self)
|
||||
timezone = timedate1_get_timezone (self->dtm);
|
||||
|
||||
if (timezone == NULL ||
|
||||
!cc_tz_dialog_set_tz (self->timezone_dialog, timezone))
|
||||
!cc_timezone_map_set_timezone (CC_TIMEZONE_MAP (self->map), timezone))
|
||||
{
|
||||
g_warning ("Timezone '%s' is unhandled, setting %s as default", timezone ? timezone : "(null)", DEFAULT_TZ);
|
||||
cc_tz_dialog_set_tz (self->timezone_dialog, DEFAULT_TZ);
|
||||
cc_timezone_map_set_timezone (CC_TIMEZONE_MAP (self->map), DEFAULT_TZ);
|
||||
}
|
||||
|
||||
self->current_location = cc_tz_dialog_get_selected_location (self->timezone_dialog);
|
||||
self->current_location = cc_timezone_map_get_location (CC_TIMEZONE_MAP (self->map));
|
||||
update_timezone (self);
|
||||
}
|
||||
|
||||
static void
|
||||
day_changed (CcDateTimePanel *self)
|
||||
load_cities (TzLocation *loc,
|
||||
GtkListStore *city_store)
|
||||
{
|
||||
change_date (self);
|
||||
g_autofree gchar *human_readable = NULL;
|
||||
|
||||
human_readable = translated_city_name (loc);
|
||||
gtk_list_store_insert_with_values (city_store, NULL, 0,
|
||||
CITY_COL_CITY_HUMAN_READABLE, human_readable,
|
||||
CITY_COL_ZONE, loc->zone,
|
||||
-1);
|
||||
}
|
||||
|
||||
static void
|
||||
load_regions_model (GtkListStore *cities)
|
||||
{
|
||||
g_autoptr(TzDB) db = NULL;
|
||||
|
||||
db = tz_load_db ();
|
||||
g_ptr_array_foreach (db->locations, (GFunc) load_cities, cities);
|
||||
}
|
||||
|
||||
static void
|
||||
day_changed (CcDateTimePanel *panel)
|
||||
{
|
||||
change_date (panel);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -461,67 +560,75 @@ month_year_changed (CcDateTimePanel *self)
|
||||
guint y;
|
||||
guint num_days;
|
||||
GtkAdjustment *adj;
|
||||
GtkSpinButton *day_spin;
|
||||
|
||||
y = gtk_spin_button_get_value_as_int (self->year_spinbutton);
|
||||
y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (self->year_spinbutton));
|
||||
|
||||
/* Check the number of days in that month */
|
||||
num_days = g_date_get_days_in_month (self->month, y);
|
||||
|
||||
adj = GTK_ADJUSTMENT (gtk_spin_button_get_adjustment (self->day_spinbutton));
|
||||
day_spin = GTK_SPIN_BUTTON (self->day_spinbutton);
|
||||
adj = GTK_ADJUSTMENT (gtk_spin_button_get_adjustment (day_spin));
|
||||
gtk_adjustment_set_upper (adj, num_days + 1);
|
||||
|
||||
if (gtk_spin_button_get_value_as_int (self->day_spinbutton) > num_days)
|
||||
gtk_spin_button_set_value (self->day_spinbutton, num_days);
|
||||
if (gtk_spin_button_get_value_as_int (day_spin) > num_days)
|
||||
gtk_spin_button_set_value (day_spin, num_days);
|
||||
|
||||
change_date (self);
|
||||
}
|
||||
|
||||
static void
|
||||
on_date_box_row_activated_cb (CcDateTimePanel *self,
|
||||
GtkListBoxRow *row)
|
||||
on_month_row_selected_changed_cb (AdwComboRow *month_row,
|
||||
GParamSpec *pspec,
|
||||
CcDateTimePanel *self)
|
||||
{
|
||||
g_assert (CC_IS_DATE_TIME_PANEL (self));
|
||||
|
||||
if (row == GTK_LIST_BOX_ROW (self->month_row))
|
||||
gtk_popover_popup (self->month_popover);
|
||||
}
|
||||
|
||||
static void
|
||||
on_month_selection_changed_cb (CcDateTimePanel *self)
|
||||
{
|
||||
guint i;
|
||||
unsigned int i;
|
||||
|
||||
g_assert (CC_IS_DATE_TIME_PANEL (self));
|
||||
g_assert (ADW_IS_COMBO_ROW (month_row));
|
||||
|
||||
i = gtk_single_selection_get_selected (self->month_model);
|
||||
i = adw_combo_row_get_selected (month_row);
|
||||
g_assert (i >= 0 && i < 12);
|
||||
|
||||
self->month = i + 1;
|
||||
month_year_changed (self);
|
||||
|
||||
gtk_popover_popdown (self->month_popover);
|
||||
}
|
||||
|
||||
static void
|
||||
on_clock_changed (CcDateTimePanel *self,
|
||||
on_clock_changed (CcDateTimePanel *panel,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
g_date_time_unref (self->date);
|
||||
self->date = g_date_time_new_now_local ();
|
||||
update_time (self);
|
||||
update_timezone (self);
|
||||
g_date_time_unref (panel->date);
|
||||
panel->date = g_date_time_new_now_local ();
|
||||
update_time (panel);
|
||||
update_timezone (panel);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
change_ntp (CcDateTimePanel *self,
|
||||
gboolean state)
|
||||
change_ntp (CcDateTimePanel *self)
|
||||
{
|
||||
queue_set_ntp (self, state);
|
||||
queue_set_ntp (self);
|
||||
|
||||
/* The new state will be visible once we see the reply. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_ntp_changed (CcDateTimePanel *self)
|
||||
{
|
||||
gboolean ntp_on;
|
||||
|
||||
g_object_get (self->dtm, "ntp", &ntp_on, NULL);
|
||||
|
||||
g_signal_handlers_block_by_func (self->network_time_switch, change_ntp, self);
|
||||
|
||||
g_object_set (self->network_time_switch,
|
||||
"state", ntp_on,
|
||||
NULL);
|
||||
|
||||
g_signal_handlers_unblock_by_func (self->network_time_switch, change_ntp, self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_ntp_available (CcDateTimePanel *self)
|
||||
{
|
||||
@@ -549,38 +656,40 @@ on_permission_changed (CcDateTimePanel *self)
|
||||
allowed = (self->permission != NULL && g_permission_get_allowed (self->permission));
|
||||
location_allowed = g_settings_get_boolean (self->location_settings, LOCATION_ENABLED);
|
||||
tz_allowed = (self->tz_permission != NULL && g_permission_get_allowed (self->tz_permission));
|
||||
using_ntp = gtk_switch_get_active (self->network_time_switch);
|
||||
auto_timezone = gtk_switch_get_active (self->auto_timezone_switch);
|
||||
using_ntp = gtk_switch_get_active (GTK_SWITCH (self->network_time_switch));
|
||||
auto_timezone = gtk_switch_get_active (GTK_SWITCH (self->auto_timezone_switch));
|
||||
|
||||
/* All the widgets but the lock button and the 24h setting */
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self->auto_datetime_row), allowed);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self->auto_timezone_row), location_allowed && (allowed || tz_allowed));
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self->datetime_row), allowed && !using_ntp);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self->timezone_row), (allowed || tz_allowed) && (!auto_timezone || !location_allowed));
|
||||
gtk_widget_set_sensitive (self->auto_datetime_row, allowed);
|
||||
gtk_widget_set_sensitive (self->auto_timezone_row, location_allowed && (allowed || tz_allowed));
|
||||
gtk_widget_set_sensitive (self->datetime_button, allowed && !using_ntp);
|
||||
gtk_widget_set_sensitive (self->timezone_button, (allowed || tz_allowed) && (!auto_timezone || !location_allowed));
|
||||
|
||||
/* Hide the subdialogs if we no longer have permissions */
|
||||
if (!allowed)
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->datetime_dialog), FALSE);
|
||||
gtk_widget_hide (GTK_WIDGET (self->datetime_dialog));
|
||||
if (!allowed && !tz_allowed)
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->timezone_dialog), FALSE);
|
||||
gtk_widget_hide (GTK_WIDGET (self->timezone_dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
on_location_settings_changed (CcDateTimePanel *self)
|
||||
on_location_settings_changed (CcDateTimePanel *panel)
|
||||
{
|
||||
on_permission_changed (self);
|
||||
on_permission_changed (panel);
|
||||
}
|
||||
|
||||
static void
|
||||
on_can_ntp_changed (CcDateTimePanel *self)
|
||||
{
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->auto_datetime_row), is_ntp_available (self));
|
||||
gtk_widget_set_visible (self->auto_datetime_row, is_ntp_available (self));
|
||||
}
|
||||
|
||||
static void
|
||||
on_timezone_changed (CcDateTimePanel *self)
|
||||
{
|
||||
g_signal_handlers_block_by_func (self->map, location_changed_cb, self);
|
||||
get_initial_timezone (self);
|
||||
g_signal_handlers_unblock_by_func (self->map, location_changed_cb, self);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -616,7 +725,7 @@ on_timedated_properties_changed (CcDateTimePanel *self,
|
||||
|
||||
static void
|
||||
run_dialog (CcDateTimePanel *self,
|
||||
GtkDialog *dialog)
|
||||
GtkWidget *dialog)
|
||||
{
|
||||
GtkWidget *parent;
|
||||
|
||||
@@ -665,7 +774,7 @@ switch_to_row_transform_func (GBinding *binding,
|
||||
|
||||
static void
|
||||
bind_switch_to_row (CcDateTimePanel *self,
|
||||
GtkSwitch *gtkswitch,
|
||||
GtkWidget *gtkswitch,
|
||||
GtkWidget *listrow)
|
||||
{
|
||||
g_object_bind_property_full (gtkswitch, "active",
|
||||
@@ -675,27 +784,18 @@ bind_switch_to_row (CcDateTimePanel *self,
|
||||
NULL, self, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
panel_tz_selection_changed_cb (CcDateTimePanel *self)
|
||||
{
|
||||
g_assert (CC_IS_DATE_TIME_PANEL (self));
|
||||
|
||||
self->current_location = cc_tz_dialog_get_selected_location (self->timezone_dialog);
|
||||
queue_set_timezone (self);
|
||||
}
|
||||
|
||||
static void
|
||||
list_box_row_activated (CcDateTimePanel *self,
|
||||
GtkListBoxRow *row)
|
||||
|
||||
{
|
||||
if (row == GTK_LIST_BOX_ROW (self->datetime_row))
|
||||
if (row == GTK_LIST_BOX_ROW (self->datetime_button))
|
||||
{
|
||||
run_dialog (self, self->datetime_dialog);
|
||||
}
|
||||
else if (row == GTK_LIST_BOX_ROW (self->timezone_row))
|
||||
else if (row == GTK_LIST_BOX_ROW (self->timezone_button))
|
||||
{
|
||||
run_dialog (self, GTK_DIALOG (self->timezone_dialog));
|
||||
run_dialog (self, self->timezone_dialog);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -712,14 +812,32 @@ time_changed_cb (CcDateTimePanel *self,
|
||||
self->date = g_date_time_new_local (g_date_time_get_year (old_date),
|
||||
g_date_time_get_month (old_date),
|
||||
g_date_time_get_day_of_month (old_date),
|
||||
cc_time_editor_get_hour (self->time_editor),
|
||||
cc_time_editor_get_minute (self->time_editor),
|
||||
cc_time_editor_get_hour (CC_TIME_EDITOR (self->time_editor)),
|
||||
cc_time_editor_get_minute (CC_TIME_EDITOR (self->time_editor)),
|
||||
g_date_time_get_second (old_date));
|
||||
|
||||
update_time (self);
|
||||
queue_set_datetime (self);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_timezone_dialog (CcDateTimePanel *self)
|
||||
{
|
||||
g_autoptr(GtkEntryCompletion) completion = NULL;
|
||||
|
||||
/* set up timezone map */
|
||||
self->map = (GtkWidget *) cc_timezone_map_new ();
|
||||
gtk_frame_set_child (self->aspectmap, self->map);
|
||||
|
||||
/* Create the completion object */
|
||||
completion = gtk_entry_completion_new ();
|
||||
gtk_entry_set_completion (GTK_ENTRY (self->timezone_searchentry), completion);
|
||||
|
||||
gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (self->city_modelsort));
|
||||
|
||||
gtk_entry_completion_set_text_column (completion, CITY_COL_CITY_HUMAN_READABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_datetime_dialog (CcDateTimePanel *self)
|
||||
{
|
||||
@@ -735,9 +853,6 @@ setup_datetime_dialog (CcDateTimePanel *self)
|
||||
".gnome-control-center-datetime-setup-time>label {\n"
|
||||
" font-size: 250%;\n"
|
||||
"}\n"
|
||||
"gridview.month-grid > child {\n"
|
||||
" background: transparent;\n"
|
||||
"}\n"
|
||||
".gnome-control-center-datetime-setup-time>spinbutton>entry {\n"
|
||||
" padding: 8px 13px;\n"
|
||||
"}", -1);
|
||||
@@ -751,7 +866,8 @@ setup_datetime_dialog (CcDateTimePanel *self)
|
||||
g_date_time_get_year (self->date));
|
||||
adjustment = (GtkAdjustment*) gtk_adjustment_new (g_date_time_get_day_of_month (self->date), 1,
|
||||
num_days + 1, 1, 10, 1);
|
||||
gtk_spin_button_set_adjustment (self->day_spinbutton, adjustment);
|
||||
gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (self->day_spinbutton),
|
||||
adjustment);
|
||||
g_signal_connect_object (G_OBJECT (self->day_spinbutton), "value-changed",
|
||||
G_CALLBACK (day_changed), self, G_CONNECT_SWAPPED);
|
||||
|
||||
@@ -759,13 +875,14 @@ setup_datetime_dialog (CcDateTimePanel *self)
|
||||
adjustment = (GtkAdjustment*) gtk_adjustment_new (g_date_time_get_year (self->date),
|
||||
1, G_MAXDOUBLE, 1,
|
||||
10, 1);
|
||||
gtk_spin_button_set_adjustment (self->year_spinbutton, adjustment);
|
||||
gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (self->year_spinbutton),
|
||||
adjustment);
|
||||
g_signal_connect_object (G_OBJECT (self->year_spinbutton), "value-changed",
|
||||
G_CALLBACK (month_year_changed), self, G_CONNECT_SWAPPED);
|
||||
|
||||
/* Month */
|
||||
self->month = g_date_time_get_month (self->date);
|
||||
gtk_single_selection_set_selected (self->month_model, self->month - 1);
|
||||
adw_combo_row_set_selected (self->month_row, self->month - 1);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -773,41 +890,39 @@ sort_date_box (GtkListBoxRow *a,
|
||||
GtkListBoxRow *b,
|
||||
CcDateTimePanel *self)
|
||||
{
|
||||
GtkListBoxRow *day_row, *month_row, *year_row;
|
||||
GtkListBoxRow *month_row;
|
||||
|
||||
g_assert (CC_IS_DATE_TIME_PANEL (self));
|
||||
|
||||
day_row = GTK_LIST_BOX_ROW (self->day_row);
|
||||
month_row = GTK_LIST_BOX_ROW (self->month_row);
|
||||
year_row = GTK_LIST_BOX_ROW (self->year_row);
|
||||
|
||||
switch (date_endian_get_default (FALSE)) {
|
||||
case DATE_ENDIANESS_BIG:
|
||||
/* year, month, day */
|
||||
if (a == year_row || b == day_row)
|
||||
if (a == self->year_row || b == self->day_row)
|
||||
return -1;
|
||||
if (a == day_row || b == year_row)
|
||||
if (a == self->day_row || b == self->year_row)
|
||||
return 1;
|
||||
|
||||
case DATE_ENDIANESS_LITTLE:
|
||||
/* day, month, year */
|
||||
if (a == day_row || b == year_row)
|
||||
if (a == self->day_row || b == self->year_row)
|
||||
return -1;
|
||||
if (a == year_row || b == day_row)
|
||||
if (a == self->year_row || b == self->day_row)
|
||||
return 1;
|
||||
|
||||
case DATE_ENDIANESS_MIDDLE:
|
||||
/* month, day, year */
|
||||
if (a == month_row || b == year_row)
|
||||
if (a == month_row || b == self->year_row)
|
||||
return -1;
|
||||
if (a == year_row || b == month_row)
|
||||
if (a == self->year_row || b == month_row)
|
||||
return 1;
|
||||
|
||||
case DATE_ENDIANESS_YDM:
|
||||
/* year, day, month */
|
||||
if (a == year_row || b == month_row)
|
||||
if (a == self->year_row || b == month_row)
|
||||
return -1;
|
||||
if (a == month_row || b == year_row)
|
||||
if (a == month_row || b == self->year_row)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -825,45 +940,37 @@ cc_date_time_panel_class_init (CcDateTimePanelClass *klass)
|
||||
|
||||
panel_class->get_help_uri = cc_date_time_panel_get_help_uri;
|
||||
|
||||
g_type_ensure (CC_TYPE_LIST_ROW);
|
||||
g_type_ensure (CC_TYPE_TZ_DIALOG);
|
||||
g_type_ensure (G_DESKTOP_TYPE_DESKTOP_CLOCK_FORMAT);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/datetime/cc-datetime-panel.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, aspectmap);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, auto_datetime_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, auto_timezone_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, auto_timezone_switch);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, city_liststore);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, city_modelsort);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, date_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_dialog);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, day_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, day_spinbutton);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timeformat_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, weekday_switch);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, date_switch);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, seconds_switch);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, week_numbers_switch);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, lock_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, month_model);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, month_popover);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, month_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, network_time_switch);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, time_editor);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_dialog);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_searchentry);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, year_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, year_spinbutton);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, panel_tz_selection_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, list_box_row_activated);
|
||||
gtk_widget_class_bind_template_callback (widget_class, time_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, change_clock_settings);
|
||||
gtk_widget_class_bind_template_callback (widget_class, format_clock_name_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_date_box_row_activated_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_month_selection_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_month_row_selected_changed_cb);
|
||||
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE_TIMEZONES, "UTF-8");
|
||||
|
||||
@@ -923,25 +1030,24 @@ cc_date_time_panel_init (CcDateTimePanel *self)
|
||||
self->toplevels = g_list_append (self->toplevels, self->datetime_dialog);
|
||||
self->toplevels = g_list_append (self->toplevels, self->timezone_dialog);
|
||||
|
||||
/* setup_timezone_dialog (self); */
|
||||
setup_timezone_dialog (self);
|
||||
setup_datetime_dialog (self);
|
||||
|
||||
/* set up network time switch */
|
||||
bind_switch_to_row (self,
|
||||
self->network_time_switch,
|
||||
GTK_WIDGET (self->datetime_row));
|
||||
g_object_bind_property (self->dtm, "ntp",
|
||||
self->network_time_switch, "active",
|
||||
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
|
||||
|
||||
self->datetime_button);
|
||||
g_signal_connect_object (self->dtm, "notify::ntp",
|
||||
G_CALLBACK (on_ntp_changed), self, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (self->network_time_switch, "state-set",
|
||||
G_CALLBACK (change_ntp), self, G_CONNECT_SWAPPED);
|
||||
on_ntp_changed (self);
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (self->auto_datetime_row), is_ntp_available (self));
|
||||
gtk_widget_set_visible (self->auto_datetime_row, is_ntp_available (self));
|
||||
|
||||
/* Timezone settings */
|
||||
g_object_bind_property_full (self->auto_timezone_switch, "active",
|
||||
self->timezone_row, "sensitive",
|
||||
self->timezone_button, "sensitive",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
(GBindingTransformFunc) tz_switch_to_row_transform_func,
|
||||
NULL, self, NULL);
|
||||
@@ -962,32 +1068,23 @@ cc_date_time_panel_init (CcDateTimePanel *self)
|
||||
g_signal_connect_object (self->clock_settings, "changed::" CLOCK_FORMAT_KEY,
|
||||
G_CALLBACK (clock_settings_changed_cb), self, G_CONNECT_SWAPPED);
|
||||
|
||||
/* setup top bar clock setting switches */
|
||||
g_settings_bind (self->clock_settings, CLOCK_SHOW_WEEKDAY_KEY,
|
||||
self->weekday_switch, "active",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
g_settings_bind (self->clock_settings, CLOCK_SHOW_DATE_KEY,
|
||||
self->date_switch, "active",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
g_settings_bind (self->clock_settings, CLOCK_SHOW_SECONDS_KEY,
|
||||
self->seconds_switch, "active",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
/* Calendar settings */
|
||||
self->calendar_settings = g_settings_new (CALENDAR_SCHEMA);
|
||||
|
||||
g_settings_bind (self->calendar_settings, CALENDAR_SHOW_WEEK_NUMBERS_KEY,
|
||||
self->week_numbers_switch, "active",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
update_time (self);
|
||||
|
||||
load_regions_model (GTK_LIST_STORE (self->city_liststore));
|
||||
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->city_modelsort), CITY_COL_CITY_HUMAN_READABLE,
|
||||
GTK_SORT_ASCENDING);
|
||||
|
||||
/* After the initial setup, so we can be sure that
|
||||
* the model is filled up */
|
||||
get_initial_timezone (self);
|
||||
|
||||
g_signal_connect_object (gtk_entry_get_completion (GTK_ENTRY (self->timezone_searchentry)),
|
||||
"match-selected", G_CALLBACK (city_changed_cb), self, G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (self->map, "location-changed",
|
||||
G_CALLBACK (location_changed_cb), self, G_CONNECT_SWAPPED);
|
||||
|
||||
/* Watch changes of timedated remote service properties */
|
||||
g_signal_connect_object (self->dtm, "g-properties-changed",
|
||||
G_CALLBACK (on_timedated_properties_changed), self, G_CONNECT_SWAPPED);
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
|
||||
<object class="CcTzDialog" id="timezone_dialog">
|
||||
<signal name="tz-selected" handler="panel_tz_selection_changed_cb" swapped="yes"/>
|
||||
<object class="GtkListStore" id="city_liststore">
|
||||
<columns>
|
||||
<!-- column-name city-human-readable -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name zone -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkTreeModelSort" id="city_modelsort">
|
||||
<property name="model">city_liststore</property>
|
||||
</object>
|
||||
|
||||
<object class="GtkDialog" id="datetime_dialog">
|
||||
<property name="title" translatable="yes">Date & Time</property>
|
||||
<property name="modal">True</property>
|
||||
@@ -34,7 +40,6 @@
|
||||
<object class="GtkListBox" id="date_box">
|
||||
<property name="width-request">320</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<signal name="row-activated" handler="on_date_box_row_activated_cb" swapped="yes"/>
|
||||
<style>
|
||||
<class name="boxed-list"/>
|
||||
</style>
|
||||
@@ -57,28 +62,27 @@
|
||||
|
||||
<!-- Month row -->
|
||||
<child>
|
||||
<object class="CcListRow" id="month_row">
|
||||
<object class="AdwComboRow" id="month_row">
|
||||
<property name="title" translatable="yes">Month</property>
|
||||
<binding name="secondary-label">
|
||||
<lookup name="string" type="GtkStringObject">
|
||||
<lookup name="selected-item">month_model</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<child type="suffix">
|
||||
<object class="GtkBox">
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">pan-down-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPopover" id="month_popover">
|
||||
<property name="child">month_grid</property>
|
||||
</object>
|
||||
</child>
|
||||
<signal name="notify::selected" handler="on_month_row_selected_changed_cb" object="CcDateTimePanel" swapped="no" />
|
||||
<property name="model">
|
||||
<object class="GtkStringList">
|
||||
<items>
|
||||
<item translatable="yes">January</item>
|
||||
<item translatable="yes">February</item>
|
||||
<item translatable="yes">March</item>
|
||||
<item translatable="yes">April</item>
|
||||
<item translatable="yes">May</item>
|
||||
<item translatable="yes">June</item>
|
||||
<item translatable="yes">July</item>
|
||||
<item translatable="yes">August</item>
|
||||
<item translatable="yes">September</item>
|
||||
<item translatable="yes">October</item>
|
||||
<item translatable="yes">November</item>
|
||||
<item translatable="yes">December</item>
|
||||
</items>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
@@ -105,6 +109,44 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDialog" id="timezone_dialog">
|
||||
<property name="title" translatable="yes">Time Zone</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="use_header_bar">1</property>
|
||||
<property name="hide-on-close">True</property>
|
||||
<child internal-child="headerbar">
|
||||
<object class="GtkHeaderBar" id="dialog_header_bar">
|
||||
<property name="show-title-buttons">True</property>
|
||||
<child type="title">
|
||||
<object class="GtkEntry" id="timezone_searchentry">
|
||||
<property name="halign">center</property>
|
||||
<property name="margin_start">5</property>
|
||||
<property name="margin_end">5</property>
|
||||
<property name="width_chars">40</property>
|
||||
<property name="primary_icon_name">edit-find-symbolic</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">False</property>
|
||||
<property name="placeholder_text" translatable="yes">Search for a city</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="dialog_vbox7">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkFrame" id="aspectmap">
|
||||
<property name="margin_start">5</property>
|
||||
<property name="margin_end">5</property>
|
||||
<property name="margin_top">5</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<template class="CcDateTimePanel" parent="CcPanel">
|
||||
|
||||
<child type="titlebar-end">
|
||||
@@ -126,12 +168,15 @@
|
||||
<child>
|
||||
<object class="GtkSwitch" id="network_time_switch">
|
||||
<property name="valign">center</property>
|
||||
<accessibility>
|
||||
<property name="label" translatable="yes">Enable</property>
|
||||
</accessibility>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow" id="datetime_row">
|
||||
<object class="AdwActionRow" id="datetime_button">
|
||||
<property name="title" translatable="yes">Date &amp; _Time</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable">True</property>
|
||||
@@ -163,12 +208,15 @@
|
||||
<child>
|
||||
<object class="GtkSwitch" id="auto_timezone_switch">
|
||||
<property name="valign">center</property>
|
||||
<accessibility>
|
||||
<property name="label" translatable="yes">Enabled</property>
|
||||
</accessibility>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow" id="timezone_row">
|
||||
<object class="AdwActionRow" id="timezone_button">
|
||||
<property name="title" translatable="yes">Time Z_one</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable">True</property>
|
||||
@@ -196,10 +244,10 @@
|
||||
<object class="AdwComboRow" id="timeformat_row">
|
||||
<property name="title" translatable="yes">Time _Format</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="notify::selected-item" handler="change_clock_settings" object="CcDateTimePanel" swapped="yes"/>
|
||||
<signal name="notify::selected-item" handler="change_clock_settings" object="CcDateTimePanel" swapped="no"/>
|
||||
<property name="model">
|
||||
<object class="AdwEnumListModel">
|
||||
<property name="enum-type">GDesktopClockFormat</property>
|
||||
<property name="enum_type">GDesktopClockFormat</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="expression">
|
||||
@@ -209,106 +257,7 @@
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Clock &amp; Calendar</property>
|
||||
<property name="description" translatable="yes">Control how the time and date is shown in the top bar</property>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Week Day</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable_widget">weekday_switch</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="weekday_switch">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Date</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable_widget">date_switch</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="date_switch">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Seconds</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable_widget">seconds_switch</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="seconds_switch">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Week Numbers</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="activatable_widget">week_numbers_switch</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="week_numbers_switch">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
||||
<object class="GtkGridView" id="month_grid">
|
||||
<property name="halign">start</property>
|
||||
<property name="margin-start">3</property>
|
||||
<property name="margin-end">3</property>
|
||||
<property name="margin-top">3</property>
|
||||
<property name="margin-bottom">3</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="max-columns">6</property>
|
||||
<property name="min-columns">6</property>
|
||||
<property name="enable-rubberband">False</property>
|
||||
<style>
|
||||
<class name="month-grid"/>
|
||||
</style>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/org/gnome/control-center/datetime/cc-month-row.ui</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="model">
|
||||
<object class="GtkSingleSelection" id="month_model">
|
||||
<property name="autoselect">False</property>
|
||||
<signal name="selection-changed" handler="on_month_selection_changed_cb" swapped="yes"/>
|
||||
<property name="model">
|
||||
<object class="GtkStringList">
|
||||
<items>
|
||||
<item translatable="yes">January</item>
|
||||
<item translatable="yes">February</item>
|
||||
<item translatable="yes">March</item>
|
||||
<item translatable="yes">April</item>
|
||||
<item translatable="yes">May</item>
|
||||
<item translatable="yes">June</item>
|
||||
<item translatable="yes">July</item>
|
||||
<item translatable="yes">August</item>
|
||||
<item translatable="yes">September</item>
|
||||
<item translatable="yes">October</item>
|
||||
<item translatable="yes">November</item>
|
||||
<item translatable="yes">December</item>
|
||||
</items>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
</interface>
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="activatable">False</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
|
||||
<!-- Month name -->
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="width-request">96</property>
|
||||
<style>
|
||||
<class name="title"/>
|
||||
</style>
|
||||
<binding name="label">
|
||||
<lookup name="string" type="GtkStringObject">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Check Image -->
|
||||
<child>
|
||||
<object class="GtkImage" id="select_image">
|
||||
<property name="visible" bind-source="GtkListItem" bind-property="selected" bind-flags="sync-create" />
|
||||
<property name="icon-name">object-select-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Placeholder too keep check image space intact -->
|
||||
<child>
|
||||
<object class="AdwBin" id="image_placeholder">
|
||||
<property name="visible" bind-source="select_image" bind-flags="sync-create|invert-boolean" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
|
||||
<object class="GtkSizeGroup">
|
||||
<property name="mode">both</property>
|
||||
<widgets>
|
||||
<widget name="select_image"/>
|
||||
<widget name="image_placeholder"/>
|
||||
</widgets>
|
||||
</object>
|
||||
|
||||
</interface>
|
||||
577
panels/datetime/cc-timezone-map.c
Normal file
@@ -0,0 +1,577 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Intel, Inc
|
||||
*
|
||||
* Portions from Ubiquity, Copyright (C) 2009 Canonical Ltd.
|
||||
* Written by Evan Dandrea <evand@ubuntu.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Thomas Wood <thomas.wood@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cc-timezone-map.h"
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "tz.h"
|
||||
|
||||
#define PIN_HOT_POINT_X 8
|
||||
#define PIN_HOT_POINT_Y 15
|
||||
|
||||
#define DATETIME_RESOURCE_PATH "/org/gnome/control-center/datetime"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gdouble offset;
|
||||
guchar red;
|
||||
guchar green;
|
||||
guchar blue;
|
||||
guchar alpha;
|
||||
} CcTimezoneMapOffset;
|
||||
|
||||
struct _CcTimezoneMap
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GdkTexture *orig_background;
|
||||
GdkTexture *orig_background_dim;
|
||||
|
||||
GdkTexture *background;
|
||||
GdkTexture *color_map;
|
||||
GdkTexture *pin;
|
||||
|
||||
gdouble selected_offset;
|
||||
|
||||
TzDB *tzdb;
|
||||
TzLocation *location;
|
||||
|
||||
gchar *bubble_text;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcTimezoneMap, cc_timezone_map, GTK_TYPE_WIDGET)
|
||||
|
||||
enum
|
||||
{
|
||||
LOCATION_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
static GdkTexture *
|
||||
texture_from_resource (const gchar *resource_path,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree gchar *full_path = g_strdup_printf ("resource://%s", resource_path);
|
||||
g_autoptr(GFile) file = g_file_new_for_uri (full_path);
|
||||
g_autoptr(GdkTexture) texture = gdk_texture_new_from_file (file, error);
|
||||
|
||||
return g_steal_pointer (&texture);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_timezone_map_dispose (GObject *object)
|
||||
{
|
||||
CcTimezoneMap *self = CC_TIMEZONE_MAP (object);
|
||||
|
||||
g_clear_object (&self->color_map);
|
||||
g_clear_object (&self->orig_background);
|
||||
g_clear_object (&self->orig_background_dim);
|
||||
g_clear_object (&self->background);
|
||||
g_clear_object (&self->pin);
|
||||
g_clear_pointer (&self->bubble_text, g_free);
|
||||
|
||||
G_OBJECT_CLASS (cc_timezone_map_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_timezone_map_finalize (GObject *object)
|
||||
{
|
||||
CcTimezoneMap *self = CC_TIMEZONE_MAP (object);
|
||||
|
||||
g_clear_pointer (&self->tzdb, tz_db_free);
|
||||
|
||||
G_OBJECT_CLASS (cc_timezone_map_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/* GtkWidget functions */
|
||||
static void
|
||||
cc_timezone_map_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
gint for_size,
|
||||
gint *minimum,
|
||||
gint *natural,
|
||||
gint *minimum_baseline,
|
||||
gint *natural_baseline)
|
||||
{
|
||||
CcTimezoneMap *map = CC_TIMEZONE_MAP (widget);
|
||||
gint size;
|
||||
|
||||
switch (orientation)
|
||||
{
|
||||
case GTK_ORIENTATION_HORIZONTAL:
|
||||
size = gdk_texture_get_width (map->orig_background);
|
||||
break;
|
||||
|
||||
case GTK_ORIENTATION_VERTICAL:
|
||||
size = gdk_texture_get_height (map->orig_background);
|
||||
break;
|
||||
}
|
||||
|
||||
if (minimum != NULL)
|
||||
*minimum = size;
|
||||
if (natural != NULL)
|
||||
*natural = size;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_timezone_map_size_allocate (GtkWidget *widget,
|
||||
gint width,
|
||||
gint height,
|
||||
gint baseline)
|
||||
{
|
||||
CcTimezoneMap *map = CC_TIMEZONE_MAP (widget);
|
||||
GdkTexture *texture;
|
||||
|
||||
if (!gtk_widget_is_sensitive (widget))
|
||||
texture = map->orig_background_dim;
|
||||
else
|
||||
texture = map->orig_background;
|
||||
|
||||
g_clear_object (&map->background);
|
||||
map->background = g_object_ref (texture);
|
||||
|
||||
GTK_WIDGET_CLASS (cc_timezone_map_parent_class)->size_allocate (widget,
|
||||
width,
|
||||
height,
|
||||
baseline);
|
||||
}
|
||||
|
||||
static gdouble
|
||||
convert_longitude_to_x (gdouble longitude, gint map_width)
|
||||
{
|
||||
const gdouble xdeg_offset = -6;
|
||||
gdouble x;
|
||||
|
||||
x = (map_width * (180.0 + longitude) / 360.0)
|
||||
+ (map_width * xdeg_offset / 180.0);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
static gdouble
|
||||
radians (gdouble degrees)
|
||||
{
|
||||
return (degrees / 360.0) * G_PI * 2;
|
||||
}
|
||||
|
||||
static gdouble
|
||||
convert_latitude_to_y (gdouble latitude, gdouble map_height)
|
||||
{
|
||||
gdouble bottom_lat = -59;
|
||||
gdouble top_lat = 81;
|
||||
gdouble top_per, y, full_range, top_offset, map_range;
|
||||
|
||||
top_per = top_lat / 180.0;
|
||||
y = 1.25 * log (tan (G_PI_4 + 0.4 * radians (latitude)));
|
||||
full_range = 4.6068250867599998;
|
||||
top_offset = full_range * top_per;
|
||||
map_range = fabs (1.25 * log (tan (G_PI_4 + 0.4 * radians (bottom_lat))) - top_offset);
|
||||
y = fabs (y - top_offset);
|
||||
y = y / map_range;
|
||||
y = y * map_height;
|
||||
return y;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_text_bubble (CcTimezoneMap *map,
|
||||
GtkSnapshot *snapshot,
|
||||
gint width,
|
||||
gint height,
|
||||
gdouble pointx,
|
||||
gdouble pointy)
|
||||
{
|
||||
static const double corner_radius = 9.0;
|
||||
static const double margin_top = 12.0;
|
||||
static const double margin_bottom = 12.0;
|
||||
static const double margin_left = 24.0;
|
||||
static const double margin_right = 24.0;
|
||||
|
||||
GskRoundedRect rounded_rect;
|
||||
PangoRectangle text_rect;
|
||||
PangoLayout *layout;
|
||||
GdkRGBA rgba;
|
||||
double x;
|
||||
double y;
|
||||
double bubble_width;
|
||||
double bubble_height;
|
||||
|
||||
if (!map->bubble_text)
|
||||
return;
|
||||
|
||||
layout = gtk_widget_create_pango_layout (GTK_WIDGET (map), NULL);
|
||||
|
||||
/* Layout the text */
|
||||
pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
|
||||
pango_layout_set_spacing (layout, 3);
|
||||
pango_layout_set_markup (layout, map->bubble_text, -1);
|
||||
|
||||
pango_layout_get_pixel_extents (layout, NULL, &text_rect);
|
||||
|
||||
/* Calculate the bubble size based on the text layout size */
|
||||
bubble_width = text_rect.width + margin_left + margin_right;
|
||||
bubble_height = text_rect.height + margin_top + margin_bottom;
|
||||
|
||||
if (pointx < width / 2)
|
||||
x = pointx + 25;
|
||||
else
|
||||
x = pointx - bubble_width - 25;
|
||||
|
||||
y = pointy - bubble_height / 2;
|
||||
|
||||
/* Make sure it fits in the visible area */
|
||||
x = CLAMP (x, 0, width - bubble_width);
|
||||
y = CLAMP (y, 0, height - bubble_height);
|
||||
|
||||
gtk_snapshot_save (snapshot);
|
||||
|
||||
gsk_rounded_rect_init (&rounded_rect,
|
||||
&GRAPHENE_RECT_INIT (x, y, bubble_width, bubble_height),
|
||||
&GRAPHENE_SIZE_INIT (corner_radius, corner_radius),
|
||||
&GRAPHENE_SIZE_INIT (corner_radius, corner_radius),
|
||||
&GRAPHENE_SIZE_INIT (corner_radius, corner_radius),
|
||||
&GRAPHENE_SIZE_INIT (corner_radius, corner_radius));
|
||||
|
||||
gtk_snapshot_push_rounded_clip (snapshot, &rounded_rect);
|
||||
|
||||
rgba = (GdkRGBA) {
|
||||
.red = 0.2,
|
||||
.green = 0.2,
|
||||
.blue = 0.2,
|
||||
.alpha = 0.7,
|
||||
};
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
&rgba,
|
||||
&GRAPHENE_RECT_INIT (x, y, bubble_width, bubble_height));
|
||||
|
||||
|
||||
rgba = (GdkRGBA) {
|
||||
.red = 1.0,
|
||||
.green = 1.0,
|
||||
.blue = 1.0,
|
||||
.alpha = 1.0,
|
||||
};
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x + margin_left, y + margin_top));
|
||||
gtk_snapshot_append_layout (snapshot, layout, &rgba);
|
||||
|
||||
gtk_snapshot_pop (snapshot);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
g_object_unref (layout);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_timezone_map_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
CcTimezoneMap *map = CC_TIMEZONE_MAP (widget);
|
||||
g_autoptr(GdkTexture) orig_highlight = NULL;
|
||||
g_autofree gchar *file = NULL;
|
||||
g_autoptr(GError) err = NULL;
|
||||
gdouble pointx, pointy;
|
||||
gint width, height;
|
||||
char buf[16];
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
/* paint background */
|
||||
gtk_snapshot_append_texture (snapshot,
|
||||
map->background,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
/* paint highlight */
|
||||
if (gtk_widget_is_sensitive (widget))
|
||||
{
|
||||
file = g_strdup_printf (DATETIME_RESOURCE_PATH "/timezone_%s.png",
|
||||
g_ascii_formatd (buf, sizeof (buf),
|
||||
"%g", map->selected_offset));
|
||||
}
|
||||
else
|
||||
{
|
||||
file = g_strdup_printf (DATETIME_RESOURCE_PATH "/timezone_%s_dim.png",
|
||||
g_ascii_formatd (buf, sizeof (buf),
|
||||
"%g", map->selected_offset));
|
||||
|
||||
}
|
||||
|
||||
orig_highlight = texture_from_resource (file, &err);
|
||||
|
||||
if (!orig_highlight)
|
||||
{
|
||||
g_warning ("Could not load highlight: %s",
|
||||
(err) ? err->message : "Unknown Error");
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_snapshot_append_texture (snapshot,
|
||||
orig_highlight,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
}
|
||||
|
||||
if (map->location)
|
||||
{
|
||||
pointx = convert_longitude_to_x (map->location->longitude, width);
|
||||
pointy = convert_latitude_to_y (map->location->latitude, height);
|
||||
|
||||
pointx = CLAMP (floor (pointx), 0, width);
|
||||
pointy = CLAMP (floor (pointy), 0, height);
|
||||
|
||||
draw_text_bubble (map, snapshot, width, height, pointx, pointy);
|
||||
|
||||
if (map->pin)
|
||||
{
|
||||
gtk_snapshot_append_texture (snapshot,
|
||||
map->pin,
|
||||
&GRAPHENE_RECT_INIT (pointx - PIN_HOT_POINT_X,
|
||||
pointy - PIN_HOT_POINT_Y,
|
||||
gdk_texture_get_width (map->pin),
|
||||
gdk_texture_get_height (map->pin)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_cursor (GtkWidget *widget)
|
||||
{
|
||||
const gchar *cursor_name = NULL;
|
||||
|
||||
if (!gtk_widget_get_realized (widget))
|
||||
return;
|
||||
|
||||
if (gtk_widget_is_sensitive (widget))
|
||||
cursor_name = "pointer";
|
||||
|
||||
gtk_widget_set_cursor_from_name (widget, cursor_name);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_timezone_map_state_flags_changed (GtkWidget *widget,
|
||||
GtkStateFlags prev_state)
|
||||
{
|
||||
update_cursor (widget);
|
||||
|
||||
if (GTK_WIDGET_CLASS (cc_timezone_map_parent_class)->state_flags_changed)
|
||||
GTK_WIDGET_CLASS (cc_timezone_map_parent_class)->state_flags_changed (widget, prev_state);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cc_timezone_map_class_init (CcTimezoneMapClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->dispose = cc_timezone_map_dispose;
|
||||
object_class->finalize = cc_timezone_map_finalize;
|
||||
|
||||
widget_class->measure = cc_timezone_map_measure;
|
||||
widget_class->size_allocate = cc_timezone_map_size_allocate;
|
||||
widget_class->snapshot = cc_timezone_map_snapshot;
|
||||
widget_class->state_flags_changed = cc_timezone_map_state_flags_changed;
|
||||
|
||||
signals[LOCATION_CHANGED] = g_signal_new ("location-changed",
|
||||
CC_TYPE_TIMEZONE_MAP,
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__POINTER,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
}
|
||||
|
||||
|
||||
static gint
|
||||
sort_locations (TzLocation *a,
|
||||
TzLocation *b)
|
||||
{
|
||||
if (a->dist > b->dist)
|
||||
return 1;
|
||||
|
||||
if (a->dist < b->dist)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
set_location (CcTimezoneMap *map,
|
||||
TzLocation *location)
|
||||
{
|
||||
g_autoptr(TzInfo) info = NULL;
|
||||
|
||||
map->location = location;
|
||||
|
||||
info = tz_info_from_location (map->location);
|
||||
|
||||
map->selected_offset = tz_location_get_base_utc_offset (map->location)
|
||||
/ (60.0*60.0);
|
||||
gtk_widget_queue_draw (GTK_WIDGET (map));
|
||||
|
||||
g_signal_emit (map, signals[LOCATION_CHANGED], 0, map->location);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
map_clicked_cb (GtkGestureClick *self,
|
||||
gint n_press,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
CcTimezoneMap *map)
|
||||
{
|
||||
const GPtrArray *array;
|
||||
gint width, height;
|
||||
GList *distances = NULL;
|
||||
gint i;
|
||||
|
||||
/* work out the coordinates */
|
||||
|
||||
array = tz_get_locations (map->tzdb);
|
||||
|
||||
width = gtk_widget_get_width (GTK_WIDGET (map));
|
||||
height = gtk_widget_get_height (GTK_WIDGET (map));
|
||||
|
||||
for (i = 0; i < array->len; i++)
|
||||
{
|
||||
gdouble pointx, pointy, dx, dy;
|
||||
TzLocation *loc = array->pdata[i];
|
||||
|
||||
pointx = convert_longitude_to_x (loc->longitude, width);
|
||||
pointy = convert_latitude_to_y (loc->latitude, height);
|
||||
|
||||
dx = pointx - x;
|
||||
dy = pointy - y;
|
||||
|
||||
loc->dist = dx * dx + dy * dy;
|
||||
distances = g_list_prepend (distances, loc);
|
||||
|
||||
}
|
||||
distances = g_list_sort (distances, (GCompareFunc) sort_locations);
|
||||
|
||||
|
||||
set_location (map, (TzLocation*) distances->data);
|
||||
|
||||
g_list_free (distances);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_timezone_map_init (CcTimezoneMap *map)
|
||||
{
|
||||
GtkGesture *click_gesture;
|
||||
GError *err = NULL;
|
||||
|
||||
map->orig_background = texture_from_resource (DATETIME_RESOURCE_PATH "/bg.png", &err);
|
||||
if (!map->orig_background)
|
||||
{
|
||||
g_warning ("Could not load background image: %s",
|
||||
(err) ? err->message : "Unknown error");
|
||||
g_clear_error (&err);
|
||||
}
|
||||
|
||||
map->orig_background_dim = texture_from_resource (DATETIME_RESOURCE_PATH "/bg_dim.png", &err);
|
||||
if (!map->orig_background_dim)
|
||||
{
|
||||
g_warning ("Could not load background image: %s",
|
||||
(err) ? err->message : "Unknown error");
|
||||
g_clear_error (&err);
|
||||
}
|
||||
|
||||
map->color_map = texture_from_resource (DATETIME_RESOURCE_PATH "/cc.png", &err);
|
||||
if (!map->color_map)
|
||||
{
|
||||
g_warning ("Could not load background image: %s",
|
||||
(err) ? err->message : "Unknown error");
|
||||
g_clear_error (&err);
|
||||
}
|
||||
|
||||
map->pin = texture_from_resource (DATETIME_RESOURCE_PATH "/pin.png", &err);
|
||||
if (!map->pin)
|
||||
{
|
||||
g_warning ("Could not load pin icon: %s",
|
||||
(err) ? err->message : "Unknown error");
|
||||
g_clear_error (&err);
|
||||
}
|
||||
|
||||
map->tzdb = tz_load_db ();
|
||||
|
||||
click_gesture = gtk_gesture_click_new ();
|
||||
g_signal_connect (click_gesture, "pressed", G_CALLBACK (map_clicked_cb), map);
|
||||
gtk_widget_add_controller (GTK_WIDGET (map), GTK_EVENT_CONTROLLER (click_gesture));
|
||||
}
|
||||
|
||||
CcTimezoneMap *
|
||||
cc_timezone_map_new (void)
|
||||
{
|
||||
return g_object_new (CC_TYPE_TIMEZONE_MAP, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
cc_timezone_map_set_timezone (CcTimezoneMap *map,
|
||||
const gchar *timezone)
|
||||
{
|
||||
GPtrArray *locations;
|
||||
guint i;
|
||||
g_autofree gchar *real_tz = NULL;
|
||||
gboolean ret;
|
||||
|
||||
real_tz = tz_info_get_clean_name (map->tzdb, timezone);
|
||||
|
||||
locations = tz_get_locations (map->tzdb);
|
||||
ret = FALSE;
|
||||
|
||||
for (i = 0; i < locations->len; i++)
|
||||
{
|
||||
TzLocation *loc = locations->pdata[i];
|
||||
|
||||
if (!g_strcmp0 (loc->zone, real_tz ? real_tz : timezone))
|
||||
{
|
||||
set_location (map, loc);
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret)
|
||||
gtk_widget_queue_draw (GTK_WIDGET (map));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
cc_timezone_map_set_bubble_text (CcTimezoneMap *map,
|
||||
const gchar *text)
|
||||
{
|
||||
g_free (map->bubble_text);
|
||||
map->bubble_text = g_strdup (text);
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (map));
|
||||
}
|
||||
|
||||
TzLocation *
|
||||
cc_timezone_map_get_location (CcTimezoneMap *map)
|
||||
{
|
||||
return map->location;
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2023 Cyber Phantom <inam123451@gmail.com>
|
||||
/*
|
||||
* Copyright (C) 2010 Intel, Inc
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -15,21 +14,26 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Thomas Wood <thomas.wood@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "tz.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_INFO_ENTRY (cc_info_entry_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (CcInfoEntry, cc_info_entry, CC, INFO_ENTRY, GtkBox)
|
||||
#define CC_TYPE_TIMEZONE_MAP (cc_timezone_map_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (CcTimezoneMap, cc_timezone_map, CC, TIMEZONE_MAP, GtkWidget)
|
||||
|
||||
void cc_info_entry_set_value (CcInfoEntry *self,
|
||||
const gchar *value);
|
||||
GtkWidget *cc_info_entry_new (const gchar *label,
|
||||
const gchar *value);
|
||||
CcTimezoneMap *cc_timezone_map_new (void);
|
||||
|
||||
gboolean cc_timezone_map_set_timezone (CcTimezoneMap *map,
|
||||
const gchar *timezone);
|
||||
void cc_timezone_map_set_bubble_text (CcTimezoneMap *map,
|
||||
const gchar *text);
|
||||
TzLocation * cc_timezone_map_get_location (CcTimezoneMap *map);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -1,329 +0,0 @@
|
||||
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* cc-tz-dialog.c
|
||||
*
|
||||
* Copyright 2022 Purism SPC
|
||||
* Copyright 2022 Mohammed Sadiq <sadiq@sadiqpk.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 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/>.
|
||||
*
|
||||
* Author(s):
|
||||
* Mohammed Sadiq <sadiq@sadiqpk.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "cc-tz-dialog"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "cc-tz-dialog.h"
|
||||
#include "tz.h"
|
||||
|
||||
struct _CcTzDialog
|
||||
{
|
||||
AdwWindow parent_instance;
|
||||
|
||||
GtkSearchEntry *location_entry;
|
||||
|
||||
GtkStack *main_stack;
|
||||
AdwStatusPage *empty_page;
|
||||
GtkScrolledWindow *tz_page;
|
||||
GtkListView *tz_view;
|
||||
|
||||
TzDB *tz_db;
|
||||
GListStore *tz_store;
|
||||
GtkFilterListModel *tz_filtered_model;
|
||||
GtkNoSelection *tz_selection_model;
|
||||
|
||||
CcTzItem *selected_item;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcTzDialog, cc_tz_dialog, ADW_TYPE_WINDOW)
|
||||
|
||||
enum {
|
||||
TZ_SELECTED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[N_SIGNALS];
|
||||
|
||||
static gboolean
|
||||
match_tz_item (CcTzItem *item,
|
||||
CcTzDialog *self)
|
||||
{
|
||||
g_auto(GStrv) strv = NULL;
|
||||
g_autofree char *country = NULL;
|
||||
g_autofree char *name = NULL;
|
||||
g_autofree char *zone = NULL;
|
||||
const char *search_terms;
|
||||
|
||||
g_assert (CC_IS_TZ_ITEM (item));
|
||||
g_assert (CC_IS_TZ_DIALOG (self));
|
||||
|
||||
search_terms = gtk_editable_get_text (GTK_EDITABLE (self->location_entry));
|
||||
|
||||
if (!search_terms || !*search_terms)
|
||||
return TRUE;
|
||||
|
||||
g_object_get (item,
|
||||
"country", &country,
|
||||
"name", &name,
|
||||
"zone", &zone,
|
||||
NULL);
|
||||
|
||||
if (!name || !zone || !country)
|
||||
return FALSE;
|
||||
|
||||
/* Search for each word separated by spaces */
|
||||
strv = g_strsplit (search_terms, " ", 0);
|
||||
|
||||
/*
|
||||
* List the item only if the value contain each word.
|
||||
* ie, for a search "as kol" it will match "Asia/Kolkata"
|
||||
* not "Asia/Karachi"
|
||||
*/
|
||||
for (guint i = 0; strv[i]; i++)
|
||||
{
|
||||
const char *str = strv[i];
|
||||
|
||||
if (!str || !*str)
|
||||
continue;
|
||||
|
||||
if (!strcasestr (name, str) &&
|
||||
!strcasestr (zone, str) &&
|
||||
!strcasestr (country, str))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
load_tz (CcTzDialog *self)
|
||||
{
|
||||
GPtrArray *locations;
|
||||
|
||||
g_assert (CC_IS_TZ_DIALOG (self));
|
||||
|
||||
self->tz_db = tz_load_db ();
|
||||
g_assert (self->tz_db);
|
||||
|
||||
locations = tz_get_locations (self->tz_db);
|
||||
g_assert (locations);
|
||||
|
||||
for (guint i = 0; i < locations->len; i++)
|
||||
{
|
||||
g_autoptr(CcTzItem) item = NULL;
|
||||
TzLocation *location;
|
||||
|
||||
location = locations->pdata[i];
|
||||
item = cc_tz_item_new (location);
|
||||
|
||||
g_list_store_append (self->tz_store, item);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tz_selection_model_changed_cb (CcTzDialog *self)
|
||||
{
|
||||
guint n_items;
|
||||
|
||||
g_assert (CC_IS_TZ_DIALOG (self));
|
||||
|
||||
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->tz_selection_model));
|
||||
|
||||
if (n_items)
|
||||
gtk_stack_set_visible_child (self->main_stack, GTK_WIDGET (self->tz_page));
|
||||
else
|
||||
gtk_stack_set_visible_child (self->main_stack, GTK_WIDGET (self->empty_page));
|
||||
}
|
||||
|
||||
static void
|
||||
tz_dialog_search_changed_cb (CcTzDialog *self)
|
||||
{
|
||||
GtkFilter *filter;
|
||||
|
||||
g_assert (CC_IS_TZ_DIALOG (self));
|
||||
|
||||
filter = gtk_filter_list_model_get_filter (self->tz_filtered_model);
|
||||
|
||||
gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
|
||||
}
|
||||
|
||||
static void
|
||||
tz_dialog_row_activated_cb (CcTzDialog *self,
|
||||
guint position)
|
||||
{
|
||||
GListModel *model;
|
||||
|
||||
g_assert (CC_IS_TZ_DIALOG (self));
|
||||
|
||||
g_clear_object (&self->selected_item);
|
||||
|
||||
model = G_LIST_MODEL (self->tz_selection_model);
|
||||
self->selected_item = g_list_model_get_item (model, position);
|
||||
|
||||
gtk_window_close (GTK_WINDOW (self));
|
||||
g_signal_emit (self, signals[TZ_SELECTED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_tz_dialog_map (GtkWidget *widget)
|
||||
{
|
||||
CcTzDialog *self = (CcTzDialog *)widget;
|
||||
|
||||
gtk_editable_set_text (GTK_EDITABLE (self->location_entry), "");
|
||||
gtk_widget_grab_focus (GTK_WIDGET (self->location_entry));
|
||||
|
||||
GTK_WIDGET_CLASS (cc_tz_dialog_parent_class)->map (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_tz_dialog_finalize (GObject *object)
|
||||
{
|
||||
CcTzDialog *self = (CcTzDialog *)object;
|
||||
|
||||
g_clear_object (&self->tz_store);
|
||||
g_clear_pointer (&self->tz_db, tz_db_free);
|
||||
|
||||
G_OBJECT_CLASS (cc_tz_dialog_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_tz_dialog_class_init (CcTzDialogClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = cc_tz_dialog_finalize;
|
||||
|
||||
widget_class->map = cc_tz_dialog_map;
|
||||
|
||||
signals[TZ_SELECTED] =
|
||||
g_signal_new ("tz-selected",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "window.close", NULL);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
"/org/gnome/control-center/"
|
||||
"datetime/cc-tz-dialog.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, location_entry);
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, main_stack);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, empty_page);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, tz_page);
|
||||
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, tz_view);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, tz_dialog_search_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, tz_dialog_row_activated_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_tz_dialog_init (CcTzDialog *self)
|
||||
{
|
||||
GtkSortListModel *tz_sorted_model;
|
||||
GtkExpression *expression;
|
||||
GtkSorter *sorter;
|
||||
GtkFilter *filter;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
self->tz_store = g_list_store_new (CC_TYPE_TZ_ITEM);
|
||||
load_tz (self);
|
||||
|
||||
/* Sort items by name */
|
||||
expression = gtk_property_expression_new (CC_TYPE_TZ_ITEM, NULL, "name");
|
||||
sorter = GTK_SORTER (gtk_string_sorter_new (expression));
|
||||
tz_sorted_model = gtk_sort_list_model_new (G_LIST_MODEL (self->tz_store), sorter);
|
||||
|
||||
filter = (GtkFilter *)gtk_custom_filter_new ((GtkCustomFilterFunc) match_tz_item, self, NULL);
|
||||
self->tz_filtered_model = gtk_filter_list_model_new (G_LIST_MODEL (tz_sorted_model), filter);
|
||||
self->tz_selection_model = gtk_no_selection_new (G_LIST_MODEL (self->tz_filtered_model));
|
||||
|
||||
g_signal_connect_object (self->tz_selection_model, "items-changed",
|
||||
G_CALLBACK (tz_selection_model_changed_cb),
|
||||
self, G_CONNECT_SWAPPED);
|
||||
tz_selection_model_changed_cb (self);
|
||||
|
||||
gtk_list_view_set_model (self->tz_view, GTK_SELECTION_MODEL (self->tz_selection_model));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
cc_tz_dialog_new (void)
|
||||
{
|
||||
return g_object_new (CC_TYPE_TZ_DIALOG, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
cc_tz_dialog_set_tz (CcTzDialog *self,
|
||||
const char *timezone)
|
||||
{
|
||||
g_autofree gchar *tz = NULL;
|
||||
guint n_items;
|
||||
|
||||
g_return_val_if_fail (CC_IS_TZ_DIALOG (self), FALSE);
|
||||
g_return_val_if_fail (timezone && *timezone, FALSE);
|
||||
|
||||
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->tz_store));
|
||||
tz = tz_info_get_clean_name (self->tz_db, timezone);
|
||||
|
||||
for (guint i = 0; i < n_items; i++)
|
||||
{
|
||||
g_autoptr(CcTzItem) item = NULL;
|
||||
TzLocation *loc;
|
||||
|
||||
item = g_list_model_get_item (G_LIST_MODEL (self->tz_store), i);
|
||||
loc = cc_tz_item_get_location (item);
|
||||
|
||||
if (g_strcmp0 (loc->zone, tz ? tz : timezone) == 0)
|
||||
{
|
||||
g_set_object (&self->selected_item, item);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CcTzItem *
|
||||
cc_tz_dialog_get_selected_tz (CcTzDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (CC_IS_TZ_DIALOG (self), NULL);
|
||||
|
||||
return self->selected_item;
|
||||
}
|
||||
|
||||
TzLocation *
|
||||
cc_tz_dialog_get_selected_location (CcTzDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (CC_IS_TZ_DIALOG (self), NULL);
|
||||
|
||||
if (!self->selected_item)
|
||||
return NULL;
|
||||
|
||||
return cc_tz_item_get_location (self->selected_item);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <adwaita.h>
|
||||
|
||||
#include "cc-tz-item.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TYPE_TZ_DIALOG (cc_tz_dialog_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (CcTzDialog, cc_tz_dialog, CC, TZ_DIALOG, AdwWindow)
|
||||
|
||||
GtkWidget *cc_tz_dialog_new (void);
|
||||
gboolean cc_tz_dialog_set_tz (CcTzDialog *self,
|
||||
const char *timezone);
|
||||
CcTzItem *cc_tz_dialog_get_selected_tz (CcTzDialog *self);
|
||||
TzLocation *cc_tz_dialog_get_selected_location (CcTzDialog *self);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -1,80 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="CcTzDialog" parent="AdwWindow">
|
||||
<property name="modal">True</property>
|
||||
<property name="hide-on-close">True</property>
|
||||
<property name="title" translatable="yes">Select Time Zone</property>
|
||||
<property name="width-request">360</property>
|
||||
<property name="height-request">300</property>
|
||||
<property name="default-height">540</property>
|
||||
|
||||
<property name="content">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwHeaderBar">
|
||||
<property name="show-start-title-buttons">True</property>
|
||||
<property name="show-end-title-buttons">True</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- SearchBar -->
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="location_entry">
|
||||
<property name="placeholder_text" translatable="yes">Search cities</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<property name="width-chars">24</property>
|
||||
<signal name="search-changed" handler="tz_dialog_search_changed_cb" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkStack" id="main_stack">
|
||||
<property name="vexpand">True</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwStatusPage" id="empty_page">
|
||||
<property name="margin-top">18</property>
|
||||
<property name="title" translatable="yes">No Results</property>
|
||||
<property name="icon-name">system-search-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="tz_page">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<object class="AdwClampScrollable">
|
||||
<child>
|
||||
<object class="GtkListView" id="tz_view">
|
||||
<property name="show-separators">True</property>
|
||||
<property name="single-click-activate">True</property>
|
||||
<signal name="activate" handler="tz_dialog_row_activated_cb" swapped="yes"/>
|
||||
<style>
|
||||
/* fixme: 'boxed-list' gives nice rounded borders, but we can't use
|
||||
* it here as it works only with GtkListBox, not with GtkListView */
|
||||
<class name="frame"/>
|
||||
</style>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/org/gnome/control-center/datetime/cc-tz-row.ui</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -1,285 +0,0 @@
|
||||
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* Copyright 2022 Purism SPC
|
||||
* Copyright 2022 Mohammed Sadiq <sadiq@sadiqpk.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 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/>.
|
||||
*
|
||||
* Author(s):
|
||||
* Mohammed Sadiq <sadiq@sadiqpk.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "cc-tz-item"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#define GNOME_DESKTOP_USE_UNSTABLE_API
|
||||
#include <libgnome-desktop/gnome-languages.h>
|
||||
#include <libgnome-desktop/gnome-wall-clock.h>
|
||||
|
||||
#include "cc-tz-item.h"
|
||||
|
||||
#define DEFAULT_TZ "Europe/London"
|
||||
#define GETTEXT_PACKAGE_TIMEZONES GETTEXT_PACKAGE "-timezones"
|
||||
|
||||
struct _CcTzItem
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GSettings *desktop_settings;
|
||||
GTimeZone *tz;
|
||||
GnomeWallClock *wall_clock;
|
||||
|
||||
TzLocation *tz_location;
|
||||
TzInfo *tz_info;
|
||||
|
||||
char *name;
|
||||
char *country;
|
||||
char *time;
|
||||
char *offset; /* eg: UTC+530 */
|
||||
char *zone;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcTzItem, cc_tz_item, G_TYPE_OBJECT)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_COUNTRY,
|
||||
PROP_NAME,
|
||||
PROP_OFFSET,
|
||||
PROP_TIME,
|
||||
PROP_ZONE,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS];
|
||||
|
||||
/* Adapted from cc-datetime-panel.c */
|
||||
static void
|
||||
generate_city_name (CcTzItem *self,
|
||||
TzLocation *loc)
|
||||
{
|
||||
g_auto(GStrv) split_translated = NULL;
|
||||
gint length;
|
||||
|
||||
/* Load the translation for it */
|
||||
self->zone = g_strdup (dgettext (GETTEXT_PACKAGE_TIMEZONES, loc->zone));
|
||||
g_strdelimit (self->zone, "_", ' ');
|
||||
split_translated = g_regex_split_simple ("[\\x{2044}\\x{2215}\\x{29f8}\\x{ff0f}/]",
|
||||
self->zone,
|
||||
0, 0);
|
||||
|
||||
length = g_strv_length (split_translated);
|
||||
self->country = gnome_get_country_from_code (loc->country, NULL);
|
||||
self->name = g_strdup (split_translated[length-1]);
|
||||
}
|
||||
|
||||
static const char *
|
||||
tz_item_get_time (CcTzItem *self)
|
||||
{
|
||||
g_autoptr(GDateTime) now = NULL;
|
||||
GDesktopClockFormat format;
|
||||
|
||||
g_assert (CC_IS_TZ_ITEM (self));
|
||||
|
||||
if (self->time)
|
||||
return self->time;
|
||||
|
||||
now = g_date_time_new_now (self->tz);
|
||||
format = g_settings_get_enum (self->desktop_settings, "clock-format");
|
||||
|
||||
self->time = gnome_wall_clock_string_for_datetime (self->wall_clock, now, format, TRUE, FALSE, FALSE);
|
||||
|
||||
return self->time;
|
||||
}
|
||||
|
||||
static void
|
||||
tz_item_clock_changed_cb (CcTzItem *self)
|
||||
{
|
||||
gboolean had_time;
|
||||
|
||||
g_assert (CC_IS_TZ_ITEM (self));
|
||||
|
||||
had_time = !!self->time;
|
||||
|
||||
/* Clear the time, so that it'll be re-created when asked for one */
|
||||
g_clear_pointer (&self->time, g_free);
|
||||
|
||||
if (had_time)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TIME]);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_tz_item_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcTzItem *self = (CcTzItem *)object;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_COUNTRY:
|
||||
g_value_set_string (value, self->country);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, self->name);
|
||||
break;
|
||||
|
||||
case PROP_OFFSET:
|
||||
g_value_set_string (value, self->offset);
|
||||
break;
|
||||
|
||||
case PROP_TIME:
|
||||
g_value_set_string (value, tz_item_get_time (self));
|
||||
break;
|
||||
|
||||
case PROP_ZONE:
|
||||
g_value_set_string (value, self->zone);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_tz_item_finalize (GObject *object)
|
||||
{
|
||||
CcTzItem *self = (CcTzItem *)object;
|
||||
|
||||
g_clear_object (&self->desktop_settings);
|
||||
g_clear_object (&self->wall_clock);
|
||||
|
||||
g_clear_pointer (&self->tz, g_time_zone_unref);
|
||||
g_clear_pointer (&self->tz_info, tz_info_free);
|
||||
|
||||
g_clear_pointer (&self->name, g_free);
|
||||
g_clear_pointer (&self->country, g_free);
|
||||
g_clear_pointer (&self->time, g_free);
|
||||
g_clear_pointer (&self->offset, g_free);
|
||||
g_clear_pointer (&self->zone, g_free);
|
||||
|
||||
G_OBJECT_CLASS (cc_tz_item_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_tz_item_class_init (CcTzItemClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = cc_tz_item_get_property;
|
||||
object_class->finalize = cc_tz_item_finalize;
|
||||
|
||||
properties[PROP_COUNTRY] =
|
||||
g_param_spec_string ("country",
|
||||
"Timezone Country",
|
||||
"Timezone Country",
|
||||
NULL,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name",
|
||||
"Timezone Name",
|
||||
"Timezone Name",
|
||||
NULL,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_OFFSET] =
|
||||
g_param_spec_string ("offset",
|
||||
"Timezone offset",
|
||||
"Timezone offset",
|
||||
NULL,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_TIME] =
|
||||
g_param_spec_string ("time",
|
||||
"Timezone time",
|
||||
"Timezone time",
|
||||
NULL,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_ZONE] =
|
||||
g_param_spec_string ("zone",
|
||||
"Timezone zone",
|
||||
"Timezone zone",
|
||||
NULL,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_tz_item_init (CcTzItem *self)
|
||||
{
|
||||
self->desktop_settings = g_settings_new ("org.gnome.desktop.interface");
|
||||
self->wall_clock = gnome_wall_clock_new ();
|
||||
|
||||
g_signal_connect_object (self->wall_clock, "notify::clock",
|
||||
G_CALLBACK (tz_item_clock_changed_cb),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (self->desktop_settings, "changed::clock-format",
|
||||
G_CALLBACK (tz_item_clock_changed_cb),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
CcTzItem *
|
||||
cc_tz_item_new (TzLocation *location)
|
||||
{
|
||||
CcTzItem *self;
|
||||
GString *offset;
|
||||
|
||||
g_return_val_if_fail (location, NULL);
|
||||
|
||||
self = g_object_new (CC_TYPE_TZ_ITEM, NULL);
|
||||
self->tz_location = location;
|
||||
self->tz_info = tz_info_from_location (location);
|
||||
generate_city_name (self, location);
|
||||
|
||||
self->tz = g_time_zone_new_offset (self->tz_info->utc_offset);
|
||||
|
||||
offset = g_string_new (g_time_zone_get_identifier (self->tz));
|
||||
/* Strip the seconds, eg: +05:30:00 -> +05:30 */
|
||||
g_string_set_size (offset, offset->len - 3);
|
||||
/* eg: +05:30 -> +0530*/
|
||||
g_string_replace (offset, ":", "", 0);
|
||||
|
||||
/* If the timezone is UTC remove the time, which will always be [+]0000 */
|
||||
if (g_str_has_suffix (offset->str, "0000"))
|
||||
g_string_set_size (offset, 0);
|
||||
|
||||
/* eg: +0530 -> UTC+0530 */
|
||||
g_string_prepend (offset, "UTC");
|
||||
|
||||
self->offset = g_string_free (offset, FALSE);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
TzLocation *
|
||||
cc_tz_item_get_location (CcTzItem *self)
|
||||
{
|
||||
g_return_val_if_fail (CC_IS_TZ_ITEM (self), NULL);
|
||||
|
||||
return self->tz_location;
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkGrid">
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">12</property>
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<property name="row-spacing">6</property>
|
||||
<property name="column-spacing">6</property>
|
||||
|
||||
<!-- Location -->
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="xalign">0</property>
|
||||
<style>
|
||||
<class name="title"/>
|
||||
</style>
|
||||
<binding name="label">
|
||||
<lookup name="name" type="CcTzItem">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Country -->
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="xalign">0</property>
|
||||
<style>
|
||||
<class name="heading"/>
|
||||
</style>
|
||||
<binding name="label">
|
||||
<lookup name="country" type="CcTzItem">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">3</property>
|
||||
<style>
|
||||
<class name="caption"/>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
|
||||
<!-- Zone Name -->
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="zone" type="CcTzItem">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Zone Name -->
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="margin-start">3</property>
|
||||
<property name="margin-end">3</property>
|
||||
<property name="label">•</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Offset from GMT -->
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="offset" type="CcTzItem">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- Current time for the given timezone -->
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">end</property>
|
||||
<attributes>
|
||||
<attribute name="font-features" value="tnum"/>
|
||||
</attributes>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<binding name="label">
|
||||
<lookup name="time" type="CcTzItem">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
<property name="row">0</property>
|
||||
<property name="row-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
BIN
panels/datetime/data/bg.png
Normal file
|
After Width: | Height: | Size: 208 KiB |
BIN
panels/datetime/data/bg_dim.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
panels/datetime/data/cc.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
panels/datetime/data/pin.png
Normal file
|
After Width: | Height: | Size: 666 B |
BIN
panels/datetime/data/timezone_-1.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
panels/datetime/data/timezone_-10.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
panels/datetime/data/timezone_-10_dim.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
panels/datetime/data/timezone_-11.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
panels/datetime/data/timezone_-11_dim.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
panels/datetime/data/timezone_-1_dim.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
panels/datetime/data/timezone_-2.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |