├── .editorconfig
├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yml
│ └── feature_request.yml
├── dependabot.yml
├── pull_request_template.md
└── workflows
│ ├── build.yml
│ ├── dependency-review.yml
│ ├── greetings.yml
│ ├── pypi-dependencies.yml
│ ├── pysa.yml
│ ├── repo.yml
│ ├── translation.yml
│ └── typos.yml
├── .gitignore
├── .gitmodules
├── .pylintrc
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── HACKING.md
├── LICENSE
├── MAINTAINERS.md
├── Makefile
├── README.md
├── ROADMAP.md
├── SECURITY.md
├── build-aux
└── flatpak
│ ├── com.github.GradienceTeam.Gradience.Devel.json
│ ├── com.github.GradienceTeam.Gradience.json
│ └── pypi-dependencies.json
├── data
├── com.github.GradienceTeam.Gradience.appdata.xml.in.in
├── com.github.GradienceTeam.Gradience.desktop.in.in
├── com.github.GradienceTeam.Gradience.gschema.xml.in
├── gradience.gresource.xml
├── icons
│ ├── hicolor
│ │ ├── scalable
│ │ │ └── apps
│ │ │ │ ├── com.github.GradienceTeam.Gradience.Devel.svg
│ │ │ │ └── com.github.GradienceTeam.Gradience.svg
│ │ └── symbolic
│ │ │ └── apps
│ │ │ └── com.github.GradienceTeam.Gradience-symbolic.svg
│ ├── meson.build
│ └── scalable
│ │ └── actions
│ │ ├── adw-gtk3-warning-symbolic.svg
│ │ ├── bug-symbolic.svg
│ │ ├── checkmark-symbolic.svg
│ │ ├── code-symbolic.svg
│ │ ├── color-picker-symbolic.svg
│ │ ├── document-edit-symbolic.svg
│ │ ├── document-save-symbolic.svg
│ │ ├── larger-brush-symbolic.svg
│ │ ├── palette-symbolic.svg
│ │ ├── settings-symbolic.svg
│ │ ├── star-large-symbolic.svg
│ │ └── star-outline-rounded-symbolic.svg
├── images
│ └── welcome.svg
├── meson.build
├── presets
│ ├── adwaita-dark.json
│ ├── adwaita.json
│ └── pretty-purple.json
├── shell
│ ├── meson.build
│ └── templates
│ │ ├── 42
│ │ ├── check-box.template
│ │ ├── colors.template
│ │ ├── gnome-shell.template
│ │ ├── palette.template
│ │ ├── panel.template
│ │ └── switches.template
│ │ ├── 43
│ │ ├── check-box.template
│ │ ├── colors.template
│ │ ├── gnome-shell.template
│ │ ├── palette.template
│ │ ├── panel.template
│ │ └── switches.template
│ │ ├── 44
│ │ ├── check-box.template
│ │ ├── colors.template
│ │ ├── gnome-shell.template
│ │ ├── palette.template
│ │ ├── panel.template
│ │ └── switches.template
│ │ └── 45
│ │ ├── check-box.template
│ │ ├── colors.template
│ │ ├── gnome-shell.template
│ │ ├── palette.template
│ │ ├── panel.template
│ │ └── switches.template
├── style.css
└── ui
│ ├── app_type_dialog.blp
│ ├── builtin_preset_row.blp
│ ├── custom_css_group.blp
│ ├── error_list_row.blp
│ ├── explore_preset_row.blp
│ ├── help_overlay.blp
│ ├── log_out_dialog.blp
│ ├── meson.build
│ ├── monet_theming_group.blp
│ ├── no_plugin_window.blp
│ ├── option_row.blp
│ ├── palette_shades.blp
│ ├── plugin_row.blp
│ ├── preferences_window.blp
│ ├── preset_row.blp
│ ├── presets_manager_window.blp
│ ├── repo_row.blp
│ ├── reset_preset_group.blp
│ ├── save_dialog.blp
│ ├── share_window.blp
│ ├── shell_prefs_window.blp
│ ├── shell_theming_group.blp
│ ├── theming_empty_group.blp
│ ├── welcome_window.blp
│ └── window.blp
├── gradience.doap
├── gradience
├── __init__.py
├── backend
│ ├── __init__.py
│ ├── constants.py.in
│ ├── css_parser.py
│ ├── exceptions.py
│ ├── flatpak_overrides.py
│ ├── globals.py
│ ├── logger.py
│ ├── meson.build
│ ├── models
│ │ ├── __init__.py
│ │ ├── meson.build
│ │ ├── preset.py
│ │ └── repo.py
│ ├── preset_downloader.py
│ ├── struct.md
│ ├── theming
│ │ ├── __init__.py
│ │ ├── meson.build
│ │ ├── monet.py
│ │ ├── preset.py
│ │ └── shell.py
│ └── utils
│ │ ├── __init__.py
│ │ ├── colors.py
│ │ ├── common.py
│ │ ├── gnome.py
│ │ ├── gsettings.py
│ │ ├── meson.build
│ │ ├── networking.py
│ │ ├── subprocess.py
│ │ └── theming.py
├── frontend
│ ├── __init__.py
│ ├── cli
│ │ ├── __init__.py
│ │ ├── cli.in
│ │ └── meson.build
│ ├── dialogs
│ │ ├── __init__.py
│ │ ├── app_type_dialog.py
│ │ ├── meson.build
│ │ ├── save_dialog.py
│ │ └── unsupported_shell_dialog.py
│ ├── gradience.in
│ ├── main.py
│ ├── meson.build
│ ├── schemas
│ │ ├── __init__.py
│ │ ├── meson.build
│ │ ├── preset_schema.py
│ │ └── shell_schema.py
│ ├── struct.md
│ ├── utils
│ │ ├── __init__.py
│ │ ├── actions.py
│ │ ├── meson.build
│ │ └── run_async.py
│ ├── views
│ │ ├── __init__.py
│ │ ├── about_window.py
│ │ ├── main_window.py
│ │ ├── meson.build
│ │ ├── no_plugin_window.py
│ │ ├── plugins_list.py
│ │ ├── preferences_window.py
│ │ ├── presets_manager_window.py
│ │ ├── share_window.py
│ │ ├── shell_prefs_window.py
│ │ └── welcome_window.py
│ └── widgets
│ │ ├── __init__.py
│ │ ├── builtin_preset_row.py
│ │ ├── custom_css_group.py
│ │ ├── error_list_row.py
│ │ ├── explore_preset_row.py
│ │ ├── meson.build
│ │ ├── monet_theming_group.py
│ │ ├── option_row.py
│ │ ├── palette_shades.py
│ │ ├── plugin_row.py
│ │ ├── preset_row.py
│ │ ├── repo_row.py
│ │ ├── reset_preset_group.py
│ │ ├── shell_theming_group.py
│ │ └── theming_empty_group.py
└── meson.build
├── local.sh
├── local_cli.sh
├── meson.build
├── po
├── Gradience.pot
├── LINGUAS
├── POTFILES
├── ar.po
├── az.po
├── cs.po
├── de.po
├── es.po
├── eu.po
├── fi.po
├── fr.po
├── he.po
├── hi.po
├── hr.po
├── id.po
├── it.po
├── ko.po
├── meson.build
├── nl.po
├── oc.po
├── pl.po
├── pt.po
├── pt_BR.po
├── ro.po
├── ru.po
├── sr.po
├── sv.po
├── ta.po
├── tr.po
├── uk.po
├── update_linguas.py
├── update_potfile.sh
└── zh_Hans.po
├── requirements.txt
└── typos.toml
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | end_of_line = lf
9 | charset = utf-8
10 | trim_trailing_whitespace = true
11 | insert_final_newline = true
12 | indent_style = space
13 | indent_size = 4
14 |
15 | [meson.build]
16 | indent_size = 2
17 |
18 | [*.md]
19 | trim_trailing_whitespace = false
20 |
21 | [*.blp]
22 | indent_size = 2
23 |
24 | [*.json]
25 | indent_size = 2
26 |
27 | [*.yml]
28 | indent_size = 2
29 |
30 | [*.xml*]
31 | indent_size = 2
32 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | @GradienceTeam/Core
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: 🐛 Bug Report
2 | description: File a bug report
3 | title: "bug: "
4 | labels: "type/bug"
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | Thank you for taking the time to fill out this bug report!
10 |
11 | - type: checkboxes
12 | attributes:
13 | label: Is there an existing issue for this?
14 | description: Please search to see if an issue already exists for your problem.
15 | options:
16 | - label: I have searched the existing issues
17 | required: true
18 |
19 | - type: textarea
20 | attributes:
21 | label: What happened?
22 | description: A clear and concise description of what the bug is.
23 | placeholder: "Tell us what you see!"
24 | value: "A bug happened!"
25 | validations:
26 | required: true
27 |
28 | - type: textarea
29 | attributes:
30 | label: To Reproduce
31 | description: Steps to reproduce the behavior.
32 | placeholder: |
33 | 1. Go to '…'
34 | 2. Click on '…'
35 | 3. Scroll down to '…'
36 | 4. See error
37 | validations:
38 | required: true
39 |
40 | - type: textarea
41 | attributes:
42 | label: Expected behavior
43 | description: A clear and concise description of what you expected to happen.
44 |
45 | - type: textarea
46 | attributes:
47 | label: Screenshots
48 | description: If applicable, add screenshots to help explain your problem.
49 |
50 | - type: markdown
51 | attributes:
52 | value: "## System"
53 |
54 | - type: input
55 | attributes:
56 | label: OS
57 | description: On which system do you run the app?
58 | placeholder: "Fedora Linux 36 (Workstation Edition)"
59 | validations:
60 | required: true
61 |
62 | - type: input
63 | attributes:
64 | label: DE/WM version
65 | description: Which version of desktop environment / window manager do you use?
66 | placeholder: "GNOME 42.3, i3wm 4.21"
67 | validations:
68 | required: true
69 |
70 | - type: input
71 | attributes:
72 | label: Version
73 | description: Which version of the Gradience do you use?
74 | placeholder: "0.3.0, 0.3.0-7e0386b, `main` branch"
75 | validations:
76 | required: true
77 |
78 | - type: dropdown
79 | attributes:
80 | label: Installation method
81 | description: How did you install Gradience ?
82 | options:
83 | - Flatpak from Flathub
84 | - Flatpak from Github Actions
85 | - Flatpak from manual build
86 | - AUR
87 | - Fedora COPR (lyessaadi/gradience)
88 | - Manual using meson
89 | - Other
90 | validations:
91 | required: true
92 |
93 | - type: textarea
94 | attributes:
95 | label: Enabled system extensions (GNOME specific)
96 | description: "Please paste here a list of enabled extensions, unless you know that this information won't be needed in your issue."
97 | placeholder: "Use `gnome-extensions list --enabled` command to get a list."
98 |
99 | - type: textarea
100 | attributes:
101 | label: Additional context
102 | description: Add any other context about the problem here.
103 |
104 | - type: checkboxes
105 | attributes:
106 | label: Code of Conduct
107 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/GradienceTeam/Gradience/blob/main/CODE_OF_CONDUCT.md)
108 | options:
109 | - label: I agree to follow this project's Code of Conduct
110 | required: true
111 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: 🎨 Preset request
4 | url: https://github.com/GradienceTeam/Community/issues/new?assignees=&labels=enhancement%2Cpreset+request&template=preset_request.yml&title=feat%3A+
5 | about: Request a port of a theme into Gradience
6 | - name: 🔌 Plug-in request
7 | url: https://github.com/GradienceTeam/Plugins/issues/new?assignees=&labels=enhancement%2Cplugin-request&template=plugin_request.yml&title=plug%3A+
8 | about: Request a plugin for customizing an external application or tool
9 | - name: 🚀 GitHub Community
10 | url: https://github.com/orgs/GradienceTeam/discussions
11 | about: Please ask and answer questions here.
12 | - name: 📬 Matrix
13 | url: https://matrix.to/#/#Gradience:matrix.org
14 | about: Chat on matrix.
15 | - name: 🎁️ Share your presets
16 | url: https://GitHub.com/Gradienceteam/Community
17 | about: Share your presets and see them in the explore tab
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: "💡 Feature request"
2 | description: Suggest an idea for this project
3 | title: "feat: "
4 | labels: ["enhancement", "feature-request"]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | Thanks for taking the time to contribute! Contributions are what make the open-source and the GNOME community such an amazing place to learn, and create. Any contributions you make will benefit everybody else and are greatly appreciated.
10 | - type: textarea
11 | id: description
12 | attributes:
13 | label: Feature description
14 | description: A clear and concise description of what the feature request is. Please include if your feature request is related to a problem
15 | validations:
16 | required: true
17 | - type: textarea
18 | id: additional
19 | attributes:
20 | label: Additional Context
21 | description: "List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to add, use case, Stack Overflow links, forum links, screenshots, OS if applicable, etc."
22 | validations:
23 | required: false
24 | - type: checkboxes
25 | attributes:
26 | label: Did you read the Code of Conduct?
27 | options:
28 | - label: I have read the [Code of Conduct](https://github.com/GradienceTeam/Gradience/blob/main/CODE_OF_CONDUCT.md).
29 | required: true
30 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "pip" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "daily"
12 | - package-ecosystem: "github-actions"
13 | directory: "/"
14 | schedule:
15 | interval: "daily"
16 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 |
4 |
5 | Fixes #(issue)
6 |
7 | ## Type of change
8 |
9 |
10 | - [ ] Bugfix (Change which fixes an issue)
11 | - [ ] New feature (Change which adds new functionality)
12 | - [ ] Enhancement (Change which slightly improves existing code)
13 | - [ ] Breaking change (This change will introduce incompatibility with existing functionality)
14 |
15 | ## Changelog
16 |
17 | - Fixed …
18 | - Added …
19 |
20 | ## Testing
21 |
22 | - [ ] I have tested my changes and verified that they work as expected
23 |
24 | ### How to test the changes
25 |
26 |
27 | No information provided.
28 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | # Change the look of Adwaita, with ease
2 | # Copyright (C) 2022 Gradience Team
3 | #
4 | # This program is free software: you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation, either version 3 of the License, or
7 | # (at your option) any later version.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License
15 | # along with this program. If not, see .
16 |
17 |
18 | name: Build
19 |
20 | on:
21 | push:
22 | branches: [ "main" ]
23 | paths-ignore:
24 | - '**/*.md'
25 | pull_request:
26 | paths-ignore:
27 | - '**/*.md'
28 |
29 | jobs:
30 | flatpak:
31 | name: Flatpak
32 | runs-on: ubuntu-latest
33 | container:
34 | image: bilelmoussaoui/flatpak-github-actions:gnome-nightly
35 | options: --privileged
36 | strategy:
37 | matrix:
38 | arch: [x86_64, aarch64]
39 | # Don't fail the whole workflow if one architecture fails
40 | fail-fast: false
41 | steps:
42 | - name: Checkout
43 | uses: actions/checkout@v4
44 |
45 | with:
46 | submodules: recursive
47 |
48 | - name: Install dependencies
49 | run: |
50 | dnf -y install docker
51 |
52 | - name: Set up QEMU
53 | id: qemu
54 | uses: docker/setup-qemu-action@v3
55 | with:
56 | platforms: arm64
57 |
58 | - uses: flatpak/flatpak-github-actions/flatpak-builder@v6.3
59 |
60 | with:
61 | repository-name: gnome-nightly
62 | bundle: gradience-devel.flatpak
63 | manifest-path: build-aux/flatpak/com.github.GradienceTeam.Gradience.Devel.json
64 | cache-key: flatpak-builder-${{ github.sha }}
65 | arch: ${{ matrix.arch }}
66 |
--------------------------------------------------------------------------------
/.github/workflows/dependency-review.yml:
--------------------------------------------------------------------------------
1 | # Dependency Review Action
2 | #
3 | # This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
4 | #
5 | # Source repository: https://github.com/actions/dependency-review-action
6 | # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
7 |
8 |
9 | name: Dependency Review
10 |
11 | on:
12 | pull_request:
13 |
14 | permissions:
15 | contents: read
16 |
17 | jobs:
18 | dependency-review:
19 | runs-on: ubuntu-latest
20 | steps:
21 | - name: Checkout repository
22 | uses: actions/checkout@v4
23 |
24 | - name: Dependency Review
25 | uses: actions/dependency-review-action@v4
26 |
--------------------------------------------------------------------------------
/.github/workflows/greetings.yml:
--------------------------------------------------------------------------------
1 | # Change the look of Adwaita, with ease
2 | # Copyright (C) 2022 Gradience Team
3 | #
4 | # This program is free software: you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation, either version 3 of the License, or
7 | # (at your option) any later version.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License
15 | # along with this program. If not, see .
16 |
17 |
18 | name: Greetings
19 |
20 | on: [pull_request_target, issues]
21 |
22 | jobs:
23 | greeting:
24 | runs-on: ubuntu-latest
25 |
26 | permissions:
27 | issues: write
28 | pull-requests: write
29 | steps:
30 | - uses: actions/first-interaction@v1
31 | with:
32 | repo-token: ${{ secrets.GITHUB_TOKEN }}
33 | issue-message: "Welcome on Gradience. 🥳 We really appreciate your contribution. The core team will review your issue as soon as possible. You can also join the Matrix room: https://matrix.to/#/#Gradience-space:envs.net or the Discord server: https://discord.com/invite/4njFDtfGEZ"
34 | pr-message: "Welcome on Gradience. 🥳 We really appreciate your contribution. The core team will review your pull request as soon as possible. You can also join the Matrix room: https://matrix.to/#/#Gradience-space:envs.net or the Discord server: https://discord.com/invite/4njFDtfGEZ."
35 |
--------------------------------------------------------------------------------
/.github/workflows/pypi-dependencies.yml:
--------------------------------------------------------------------------------
1 | # Change the look of Adwaita, with ease
2 | # Copyright (C) 2022 Gradience Team
3 | #
4 | # This program is free software: you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation, either version 3 of the License, or
7 | # (at your option) any later version.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License
15 | # along with this program. If not, see .
16 |
17 |
18 | name: Generate PyPI Dependencies
19 |
20 | on:
21 | push:
22 | branches: [ "main" ]
23 | paths: requirements.txt
24 | workflow_dispatch:
25 |
26 | jobs:
27 | build:
28 | runs-on: ubuntu-latest
29 | steps:
30 | - uses: actions/checkout@v4
31 | - uses: actions/setup-python@v5.1.0
32 | with:
33 | python-version: '3.10'
34 |
35 | - name: Run a multi-line script
36 | run: |
37 | curl -O https://raw.githubusercontent.com/flatpak/flatpak-builder-tools/master/pip/flatpak-pip-generator
38 | chmod +x flatpak-pip-generator
39 | python -m pip install requirements-parser
40 | ./flatpak-pip-generator --requirements-file=requirements.txt --output pypi-dependencies
41 | mv pypi-dependencies.json build-aux/flatpak/pypi-dependencies.json
42 |
43 | - name: Create pull request
44 | uses: peter-evans/create-pull-request@v6.0.5
45 | with:
46 | author: "AdwCustomizer "
47 | title: "meta: update PyPI dependencies for Flatpak"
48 | body: "This automated PR contains an auto-generated `pypi-dependencies.json` file used in Flatpak manifests."
49 | labels: flatpak, ci/automated-pr
50 | commit-message: "meta: update Flatpak PyPI dependencies"
51 | committer: "AdwCustomizer "
52 | branch: update-pypi-deps
53 |
--------------------------------------------------------------------------------
/.github/workflows/pysa.yml:
--------------------------------------------------------------------------------
1 | # This workflow uses actions that are not certified by GitHub.
2 | # They are provided by a third-party and are governed by
3 | # separate terms of service, privacy policy, and support
4 | # documentation.
5 |
6 | # This workflow integrates Python Static Analyzer (Pysa) with
7 | # GitHub's Code Scanning feature.
8 | #
9 | # Python Static Analyzer (Pysa) is a security-focused static
10 | # analysis tool that tracks flows of data from where they
11 | # originate to where they terminate in a dangerous location.
12 | #
13 | # See https://pyre-check.org/docs/pysa-basics/
14 |
15 |
16 | name: Pysa
17 |
18 | on:
19 | workflow_dispatch:
20 | push:
21 | branches: [ "main" ]
22 | pull_request:
23 | branches: [ "main" ]
24 | schedule:
25 | - cron: '34 17 * * 1'
26 |
27 | permissions:
28 | contents: read
29 |
30 | jobs:
31 | pysa:
32 | permissions:
33 | actions: read
34 | contents: read
35 | security-events: write
36 |
37 | runs-on: ubuntu-latest
38 | steps:
39 | - uses: actions/checkout@v4
40 | with:
41 | submodules: true
42 |
43 | - name: Run Pysa
44 | uses: facebook/pysa-action@f46a63777e59268613bd6e2ff4e29f144ca9e88b
45 | with:
46 | # To customize these inputs:
47 | # See https://github.com/facebook/pysa-action#inputs
48 | repo-directory: './'
49 | requirements-path: 'requirements.txt'
50 | infer-types: true
51 | include-default-sapp-filters: true
52 |
--------------------------------------------------------------------------------
/.github/workflows/repo.yml:
--------------------------------------------------------------------------------
1 | name: Repo
2 |
3 | on:
4 | # Rebuild once a day
5 | #schedule:
6 | # - cron: "0 0 * * *"
7 | push:
8 | workflow_dispatch:
9 |
10 | jobs:
11 | flatter:
12 | name: Flatter
13 | runs-on: ubuntu-latest
14 | container:
15 | image: ghcr.io/andyholmes/flatter/gnome:master
16 | options: --privileged
17 |
18 | strategy:
19 | matrix:
20 | arch: [x86_64, aarch64]
21 | fail-fast: false
22 | # Only one job at a time can use the shared repository cache
23 | max-parallel: 1
24 |
25 | steps:
26 | # Checkout a repository with Flatpak manifests
27 | - name: Checkout
28 | uses: actions/checkout@v4
29 | with:
30 | submodules: recursive
31 |
32 | # See "Multiple Architectures" below
33 | - name: Setup QEMU
34 | if: ${{ matrix.arch == 'aarch64' }}
35 | id: qemu
36 | uses: docker/setup-qemu-action@v3
37 | with:
38 | platforms: arm64
39 |
40 | # See "GPG Signing" below
41 | - name: Setup GPG
42 | id: gpg
43 | uses: crazy-max/ghaction-import-gpg@v6
44 | with:
45 | gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
46 | passphrase: ${{ secrets.GPG_PASSPHRASE }}
47 |
48 | - name: Build
49 | uses: andyholmes/flatter@main
50 | with:
51 | files: |
52 | build-aux/flatpak/com.github.GradienceTeam.Gradience.Devel.json
53 | arch: ${{ matrix.arch }}
54 | gpg-sign: ${{ steps.gpg.outputs.fingerprint }}
55 | upload-bundles: true
56 | upload-pages-artifact: true
57 | upload-pages-includes: |
58 | repo/default.css
59 | repo/index.html
60 |
61 | # See "Github Pages" below
62 | deploy:
63 | name: Deploy
64 | runs-on: ubuntu-latest
65 | needs: flatter
66 | permissions:
67 | pages: write
68 | id-token: write
69 | environment:
70 | name: github-pages
71 | url: ${{ steps.deployment.outputs.page_url }}
72 |
73 | steps:
74 | - name: GitHub Pages
75 | id: deployment
76 | uses: actions/deploy-pages@v4
77 |
--------------------------------------------------------------------------------
/.github/workflows/translation.yml:
--------------------------------------------------------------------------------
1 | # Change the look of Adwaita, with ease
2 | # Copyright (C) 2022 Gradience Team
3 | #
4 | # This program is free software: you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation, either version 3 of the License, or
7 | # (at your option) any later version.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License
15 | # along with this program. If not, see .
16 |
17 |
18 | name: "Translation"
19 |
20 | on:
21 | workflow_dispatch:
22 |
23 | jobs:
24 | generate:
25 | name: Generate .pot and LINGUAS
26 | runs-on: ubuntu-latest
27 |
28 | steps:
29 | - name: Checkout repository
30 | uses: actions/checkout@v4
31 |
32 | - name: Update .pot
33 | uses: GradienceTeam/action-update-pot@main
34 | with:
35 | title: "Gradience POT file"
36 | copyright: "Gradience Team"
37 | license: "GNU GPLv3"
38 | author: "Gradience Team"
39 | commiter: "Gradience Bot"
40 | commiter_email: "AdwCustomizerTeam@proton.me"
41 | env:
42 | GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
43 |
--------------------------------------------------------------------------------
/.github/workflows/typos.yml:
--------------------------------------------------------------------------------
1 | # Change the look of Adwaita, with ease
2 | # Copyright (C) 2022 Gradience Team
3 | #
4 | # This program is free software: you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation, either version 3 of the License, or
7 | # (at your option) any later version.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License
15 | # along with this program. If not, see .
16 |
17 |
18 | name: Typos
19 |
20 | on:
21 | pull_request:
22 | schedule:
23 | - cron: '0 0,12 * * *'
24 | workflow_dispatch:
25 |
26 | jobs:
27 | typos:
28 | name: Typos
29 | runs-on: ubuntu-latest
30 | steps:
31 | - uses: actions/checkout@v4
32 |
33 | - name: Check for typos
34 | uses: crate-ci/typos@v1.22.7
35 | with:
36 | config: typos.toml
37 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "data/submodules"]
2 | path = data/submodules
3 | url = https://github.com/GradienceTeam/Submodules
--------------------------------------------------------------------------------
/.pylintrc:
--------------------------------------------------------------------------------
1 | [MAIN]
2 |
3 | # Use multiple processes to speed up Pylint.
4 | jobs=4
5 |
6 |
7 | [MESSAGES CONTROL]
8 |
9 | # Disable the message, report, category or checker with the given id(s). You
10 | # can either give multiple identifiers separated by comma (,) or put this
11 | # option multiple times (only on the command line, not in the configuration
12 | # file where it should appear only once). You can also use "--disable=all" to
13 | # disable everything first and then re-enable specific checks. For example, if
14 | # you want to run only the similarities checker, you can use "--disable=all
15 | # --enable=similarities". If you want to run only the classes checker, but have
16 | # no Warning level messages displayed, use "--disable=all --enable=classes
17 | # --disable=W".
18 | disable=locally-disabled,
19 | suppressed-message,
20 | useless-suppression,
21 | #line-too-long,
22 | fixme,
23 | missing-module-docstring,
24 | missing-function-docstring,
25 | missing-class-docstring,
26 | invalid-name,
27 | no-member,
28 | too-few-public-methods,
29 | attribute-defined-outside-init,
30 | logging-fstring-interpolation,
31 | unused-argument
32 |
33 |
34 | [FORMAT]
35 |
36 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
37 | # tab).
38 | indent-string=' '
39 |
40 | # Number of spaces of indent required inside a hanging or continued line.
41 | indent-after-paren=4
42 |
43 | # Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
44 | expected-line-ending-format=LF
45 |
46 |
47 | [MISCELLANEOUS]
48 |
49 | # List of note tags to take in consideration, separated by a comma.
50 | notes=FIXME,XXX,TODO
51 |
52 |
53 | [VARIABLES]
54 |
55 | # Tells whether we should check for unused import in __init__ files.
56 | init-import=no
57 |
58 | # A regular expression matching the name of dummy variables (i.e. expectedly
59 | # not used).
60 | dummy-variables-rgx=(_+[a-zA-Z0-9]*?$)|dummy
61 |
62 | # List of additional names supposed to be defined in builtins. Remember that
63 | # you should avoid to define new builtins when possible.
64 | additional-builtins=_
65 |
66 |
67 | [SIMILARITIES]
68 |
69 | # Minimum lines number of a similarity.
70 | min-similarity-lines=4
71 |
72 | # Ignore comments when computing similarities.
73 | ignore-comments=yes
74 |
75 | # Ignore docstrings when computing similarities.
76 | ignore-docstrings=yes
77 |
78 | # Ignore imports when computing similarities.
79 | ignore-imports=no
80 |
--------------------------------------------------------------------------------
/HACKING.md:
--------------------------------------------------------------------------------
1 | ## 🙌 Contribute to Gradience
2 |
3 | ### Code
4 |
5 | Fork this repository, then create a push request when you're done adding features or fixing bugs.
6 |
7 | ### Localization
8 |
9 | You can help Gradience translate into your native language. If you found any typos
10 | or think you can improve a translation, you can use the [Weblate](https://hosted.weblate.org/engage/GradienceTeam) platform.
11 |
12 | [](https://hosted.weblate.org/engage/GradienceTeam)
13 |
14 |
15 | ## 🏗️ Building from source
16 |
17 | ### GNOME Builder
18 |
19 | GNOME Builder is the environment used for developing this application.
20 | It can use Flatpak manifests to create a consistent building and running
21 | environment cross-distro. Thus, it is highly recommended you use it.
22 |
23 | 1. Download [GNOME Builder](https://flathub.org/apps/details/org.gnome.Builder).
24 | 2. In Builder, click the "Clone Repository" button at the bottom, using `https://github.com/GradienceTeam/Gradience.git` as the URL.
25 | 3. Click the build button at the top once the project is loaded.
26 |
27 | ### Flatpak Builder
28 |
29 | `flatpak-builder` is a wrapper around the `flatpak build` command that automates the building of applications and their dependencies.
30 | It uses Flatpak manifests to download and pack needed dependencies with compiled program into a single Flatpak image that can be later distributed or installed on your system. We recommend this method if you have problems with GNOME Builder.
31 |
32 | #### Prerequisites
33 |
34 | - Flatpak Builder `flatpak-builder`
35 | - GNOME SDK runtime `org.gnome.Sdk//44`
36 | - GNOME Platform runtime `org.gnome.Platform//44`
37 |
38 | Install required runtimes:
39 | ```shell
40 | flatpak install org.gnome.Sdk//44 org.gnome.Platform//44
41 | ```
42 |
43 | #### Build Instruction
44 |
45 | ##### User installation
46 | ```shell
47 | git clone https://github.com/GradienceTeam/Gradience.git
48 | cd Gradience
49 | git submodule update --init --recursive
50 | flatpak-builder --install --user --force-clean repo/ build-aux/flatpak/com.github.GradienceTeam.Gradience.json
51 | ```
52 |
53 | ##### System installation
54 | ```shell
55 | git clone https://github.com/GradienceTeam/Gradience.git
56 | cd Gradience
57 | git submodule update --init --recursive
58 | flatpak-builder --install --system --force-clean repo/ build-aux/flatpak/com.github.GradienceTeam.Gradience.json
59 | ```
60 |
61 | ### Meson
62 |
63 | #### Prerequisites
64 |
65 | The following packages are required to build Gradience:
66 |
67 | - Python 3 `python`
68 | - PyGObject `python-gobject`
69 | - Blueprint [`blueprint-compiler`](https://jwestman.pages.gitlab.gnome.org/blueprint-compiler/setup.html)
70 | - GTK 4 `gtk4`
71 | - Libadwaita (>= 1.2.alpha) `libadwaita`
72 | - Libsoup 3 (>= 3.2.0) `libsoup`
73 | - Meson `meson`
74 | - Ninja `ninja-build`
75 |
76 | Required Python libraries:
77 |
78 | ```shell
79 | pip install -r requirements.txt
80 | ```
81 |
82 | #### Build Instruction
83 |
84 | ##### Global installation
85 |
86 | ```shell
87 | git clone https://github.com/GradienceTeam/Gradience.git
88 | cd Gradience
89 | git submodule update --init --recursive
90 | meson setup builddir
91 | meson configure builddir -Dprefix=/usr/local
92 | sudo ninja -C builddir install
93 | ```
94 |
95 | ##### Local build (for testing and development purposes)
96 |
97 | ```shell
98 | git clone https://github.com/GradienceTeam/Gradience.git
99 | cd Gradience
100 | git submodule update --init --recursive
101 | meson setup builddir
102 | meson configure builddir -Dprefix="$(pwd)/builddir"
103 | ninja -C builddir install
104 | ninja -C builddir run
105 | ```
106 |
107 | > **Note**
108 | > During testing and development, as a convenience, you can use the `local.sh` script to quickly rebuild local builds.
109 | > If you want to use CLI in local builds, you should type: `./local_cli.sh ` instead of `gradience-cli`.
110 |
111 |
--------------------------------------------------------------------------------
/MAINTAINERS.md:
--------------------------------------------------------------------------------
1 | # Maintainers
2 |
3 | This application was created by [@ArtyIF](https://github.com/ArtyIF). Now it's maintained by the Gradience Team.
4 |
5 | ## Gradience Team
6 |
7 | - [@0xMRTT](https://github.com/0xMRTT) as main developer
8 | - [@daudix-UFO](https://github.com/daudix-UFO) as designer
9 | - [@LyesSaadi](https://github.com/LyesSaadi) as packager
10 | - [@tfuxu](https://github.com/tfuxu) as developer
11 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | install:
2 | sudo meson setup builddir --prefix=/usr/local --wipe
3 | sudo ninja -C builddir install
4 |
5 | global:
6 | sudo meson setup builddir --prefix=/usr --wipe
7 | sudo ninja -C builddir install
8 |
9 | release:
10 | sudo meson setup builddir --prefix=/usr --Dbuildtype=release --wipe
11 | sudo ninja -C builddir install
12 |
13 | user:
14 | meson setup builddir --prefix="$(shell pwd)/builddir" --buildtype=debug --wipe
15 | ninja -C builddir install
16 | ninja -C builddir run
17 |
--------------------------------------------------------------------------------
/ROADMAP.md:
--------------------------------------------------------------------------------
1 | ## 🛣️ Roadmap
2 |
3 | Gradience is completely usable, if you like to see a new feature, open an issue or submit a PR
4 |
5 | ### Base features
6 |
7 | - [x] Customize named colors, either with a color picker or with text
8 | - [x] Explanations for some named colors
9 | - [x] Partial theme preview
10 | - [x] Built-in presets for Adwaita and Adwaita Dark (based on default Libadwaita colors)
11 | - [x] Apply changes to Libadwaita, GTK 4 (with extracted Libadwaita theme) and GTK 3 (with the adw-gtk3 theme) applications
12 | - [x] Load and create custom presets
13 | - [x] View adw-gtk3's support of variables
14 | - [x] View parsing errors
15 | - [x] Customize palette colors
16 | - [x] Add custom CSS code
17 | - [x] Localization support
18 | - [x] Normalize color variables
19 | - [x] Make the code more secure
20 | - [x] Add preset manager with option to download other users presets
21 | - [x] Release on Flathub
22 | - [x] Add autoload theme from CSS
23 | - [ ] Make UX more foolproof (bruh)
24 | - [ ] Add ability to create light/dark presets **(High priority)**
25 | - [ ] Add a full theme preview instead of GTK 4 Demo
26 | - [ ] Add ability to generate preset from one color
27 |
28 | ### Plugins
29 |
30 | - [x] Add plugin support. Will help integration with others tools.
31 | - [x] Customize Firefox GNOME theme
32 | - [x] Customize GNOME Shell **(High priority)**
33 | - [x] Customize GDM **(High priority)**
34 | - [ ] Customize KvLibadwaita
35 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | ## 🔒️ Security Policy
2 |
3 | ### Supported Versions
4 |
5 | Only two latest versions are officially supported, but older versions get some help too.
6 |
7 | | Version | Supported |
8 | | ------- | ------------------ |
9 | | 0.4.x | :white_check_mark: |
10 | | 0.3.x | :white_check_mark: |
11 | | < 0.2 | :x: |
12 |
13 | ### Reporting a Vulnerability
14 |
15 | Normally Gradience can't have security issues, but if you have found a vulnerability, please don't submit a public issue.
16 |
17 | Instead, report this vulnerability to [AdwCustomizerTeam@proton.me](mailto:AdwCustomizerTeam@proton.me) and include as much details as possible.
18 |
--------------------------------------------------------------------------------
/data/com.github.GradienceTeam.Gradience.desktop.in.in:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=Gradience
3 | Exec=gradience
4 | Icon=@APP_ID@
5 | Terminal=false
6 | Type=Application
7 | Categories=GTK;Utility;
8 | Keywords=AdwCustomizer;Adwaita Manager;GNOME;Customization;
9 | StartupNotify=true
10 |
--------------------------------------------------------------------------------
/data/com.github.GradienceTeam.Gradience.gschema.xml.in:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 1000
6 |
7 |
8 | 700
9 |
10 |
11 | false
12 |
13 |
14 | false
15 |
16 |
17 | true
18 |
19 |
20 | '0.2.2'
21 |
22 |
23 | []
24 |
25 |
26 | ['shell', 'monet']
27 |
28 |
29 | false
30 |
31 |
32 | false
33 |
34 |
35 | false
36 |
37 |
38 | false
39 |
40 |
41 | {}
42 |
43 |
44 | {}
45 |
46 |
47 | []
48 |
49 |
50 | false
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/data/gradience.gresource.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | presets/adwaita.json
5 | presets/adwaita-dark.json
6 | presets/pretty-purple.json
7 | ui/app_type_dialog.ui
8 | ui/builtin_preset_row.ui
9 | ui/custom_css_group.ui
10 | ui/error_list_row.ui
11 | ui/explore_preset_row.ui
12 | ui/monet_theming_group.ui
13 | ui/no_plugin_window.ui
14 | ui/option_row.ui
15 | ui/palette_shades.ui
16 | ui/plugin_row.ui
17 | ui/preferences_window.ui
18 | ui/preset_row.ui
19 | ui/presets_manager_window.ui
20 | ui/repo_row.ui
21 | ui/reset_preset_group.ui
22 | ui/save_dialog.ui
23 | ui/share_window.ui
24 | ui/shell_prefs_window.ui
25 | ui/shell_theming_group.ui
26 | ui/theming_empty_group.ui
27 | ui/welcome_window.ui
28 | ui/window.ui
29 | ui/help_overlay.ui
30 |
31 | images/welcome.svg
32 | style.css
33 |
34 |
35 | icons/scalable/actions/adw-gtk3-warning-symbolic.svg
36 | icons/scalable/actions/bug-symbolic.svg
37 | icons/scalable/actions/checkmark-symbolic.svg
38 | icons/scalable/actions/code-symbolic.svg
39 | icons/scalable/actions/color-picker-symbolic.svg
40 | icons/scalable/actions/document-edit-symbolic.svg
41 | icons/scalable/actions/document-save-symbolic.svg
42 | icons/scalable/actions/larger-brush-symbolic.svg
43 | icons/scalable/actions/palette-symbolic.svg
44 | icons/scalable/actions/settings-symbolic.svg
45 | icons/scalable/actions/star-large-symbolic.svg
46 | icons/scalable/actions/star-outline-rounded-symbolic.svg
47 |
48 |
49 |
--------------------------------------------------------------------------------
/data/icons/hicolor/symbolic/apps/com.github.GradienceTeam.Gradience-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/data/icons/meson.build:
--------------------------------------------------------------------------------
1 | scalable_dir = join_paths('hicolor', 'scalable', 'apps')
2 | install_data(
3 | join_paths(scalable_dir, ('@0@.svg').format(APPLICATION_ID)),
4 | install_dir: join_paths(get_option('datadir'), 'icons', scalable_dir)
5 | )
6 |
7 | symbolic_dir = join_paths('hicolor', 'symbolic', 'apps')
8 | install_data(
9 | join_paths(symbolic_dir, ('@0@-symbolic.svg').format(PROJECT_RDNN_NAME)),
10 | install_dir: join_paths(get_option('datadir'), 'icons', symbolic_dir),
11 | rename: '@0@-symbolic.svg'.format(APPLICATION_ID)
12 | )
13 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/adw-gtk3-warning-symbolic.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/bug-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/checkmark-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/code-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/color-picker-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/document-edit-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/document-save-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/larger-brush-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/palette-symbolic.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/settings-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/star-large-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/data/icons/scalable/actions/star-outline-rounded-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/data/meson.build:
--------------------------------------------------------------------------------
1 | gnome = import('gnome')
2 |
3 | subdir('ui')
4 |
5 | desktop_file = i18n.merge_file(
6 | input: configure_file(
7 | input: '@0@.desktop.in.in'.format(PROJECT_RDNN_NAME),
8 | output: '@BASENAME@',
9 | configuration: conf
10 | ),
11 | output: '@0@.desktop'.format(APPLICATION_ID),
12 | type: 'desktop',
13 | po_dir: '../po',
14 | install: true,
15 | install_dir: join_paths(get_option('datadir'), 'applications')
16 | )
17 |
18 | desktop_utils = find_program('desktop-file-validate', required: false)
19 | if desktop_utils.found()
20 | test('Validate desktop file', desktop_utils,
21 | args: [desktop_file.full_path()]
22 | )
23 | endif
24 |
25 | gnome.compile_resources('gradience',
26 | 'gradience.gresource.xml',
27 | gresource_bundle: true,
28 | source_dir: meson.current_build_dir(),
29 | install: true,
30 | install_dir: PKGDATA_DIR,
31 | dependencies: blueprints
32 | )
33 |
34 | appstream_file = i18n.merge_file(
35 | input: configure_file(
36 | input: '@0@.appdata.xml.in.in'.format(PROJECT_RDNN_NAME),
37 | output: '@BASENAME@',
38 | configuration: configuration_data({
39 | 'APP_ID': APPLICATION_ID,
40 | 'PROJECT_URL': PROJECT_URL,
41 | 'BUGTRACKER_URL': BUGTRACKER_URL,
42 | 'HELP_URL': HELP_URL,
43 | 'TRANSLATE_URL': TRANSLATE_URL
44 | })
45 | ),
46 | output: '@0@.appdata.xml'.format(APPLICATION_ID),
47 | po_dir: '../po',
48 | install: true,
49 | install_dir: join_paths(get_option('datadir'), 'appdata')
50 | )
51 |
52 | appstream_util = find_program('appstream-util', required: false)
53 | if appstream_util.found()
54 | test('Validate appstream file', appstream_util,
55 | args: ['validate', appstream_file.full_path()]
56 | )
57 | endif
58 |
59 | configure_file(
60 | input: '@0@.gschema.xml.in'.format(PROJECT_RDNN_NAME),
61 | output: '@0@.gschema.xml'.format(APPLICATION_ID),
62 | configuration: conf,
63 | install: true,
64 | install_dir: join_paths(get_option('datadir'), 'glib-2.0/schemas')
65 | )
66 |
67 | compile_schemas = find_program('glib-compile-schemas', required: false)
68 | if compile_schemas.found()
69 | test('Validate schema file', compile_schemas,
70 | args: ['--strict', '--dry-run', meson.current_source_dir()]
71 | )
72 | endif
73 |
74 | subdir('icons')
75 | subdir('shell')
76 | subdir('submodules')
--------------------------------------------------------------------------------
/data/presets/adwaita-dark.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Adwaita Dark",
3 | "variables": {
4 | "accent_color": "#78aeed",
5 | "accent_bg_color": "#3584e4",
6 | "accent_fg_color": "#ffffff",
7 | "destructive_color": "#ff7b63",
8 | "destructive_bg_color": "#c01c28",
9 | "destructive_fg_color": "#ffffff",
10 | "success_color": "#8ff0a4",
11 | "success_bg_color": "#26a269",
12 | "success_fg_color": "#ffffff",
13 | "warning_color": "#f8e45c",
14 | "warning_bg_color": "#cd9309",
15 | "warning_fg_color": "rgba(0, 0, 0, 0.8)",
16 | "error_color": "#ff7b63",
17 | "error_bg_color": "#c01c28",
18 | "error_fg_color": "#ffffff",
19 | "window_bg_color": "#242424",
20 | "window_fg_color": "#ffffff",
21 | "view_bg_color": "#1e1e1e",
22 | "view_fg_color": "#ffffff",
23 | "headerbar_bg_color": "#303030",
24 | "headerbar_fg_color": "#ffffff",
25 | "headerbar_border_color": "#ffffff",
26 | "headerbar_backdrop_color": "@window_bg_color",
27 | "headerbar_shade_color": "rgba(0, 0, 0, 0.36)",
28 | "headerbar_darker_shade_color": "rgba(0, 0, 0, 0.9)",
29 | "card_bg_color": "rgba(255, 255, 255, 0.08)",
30 | "card_fg_color": "#ffffff",
31 | "card_shade_color": "rgba(0, 0, 0, 0.36)",
32 | "dialog_bg_color": "#383838",
33 | "dialog_fg_color": "#ffffff",
34 | "popover_bg_color": "#383838",
35 | "popover_fg_color": "#ffffff",
36 | "popover_shade_color": "rgba(0, 0, 0, 0.36)",
37 | "shade_color": "rgba(0, 0, 0, 0.36)",
38 | "scrollbar_outline_color": "rgba(0, 0, 0, 0.5)",
39 | "thumbnail_bg_color": "#383838",
40 | "thumbnail_fg_color": "#ffffff",
41 | "sidebar_bg_color": "#303030",
42 | "sidebar_fg_color": "#ffffff",
43 | "sidebar_backdrop_color": "#2a2a2a",
44 | "sidebar_shade_color": "rgba(0, 0, 0, 0.36)",
45 | "secondary_sidebar_bg_color": "#2a2a2a",
46 | "secondary_sidebar_fg_color": "#ffffff",
47 | "secondary_sidebar_backdrop_color": "#272727",
48 | "secondary_sidebar_shade_color": "rgba(0, 0, 0, 0.36)"
49 | },
50 | "palette": {
51 | "blue_": {
52 | "1": "#99c1f1",
53 | "2": "#62a0ea",
54 | "3": "#3584e4",
55 | "4": "#1c71d8",
56 | "5": "#1a5fb4"
57 | },
58 | "green_": {
59 | "1": "#8ff0a4",
60 | "2": "#57e389",
61 | "3": "#33d17a",
62 | "4": "#2ec27e",
63 | "5": "#26a269"
64 | },
65 | "yellow_": {
66 | "1": "#f9f06b",
67 | "2": "#f8e45c",
68 | "3": "#f6d32d",
69 | "4": "#f5c211",
70 | "5": "#e5a50a"
71 | },
72 | "orange_": {
73 | "1": "#ffbe6f",
74 | "2": "#ffa348",
75 | "3": "#ff7800",
76 | "4": "#e66100",
77 | "5": "#c64600"
78 | },
79 | "red_": {
80 | "1": "#f66151",
81 | "2": "#ed333b",
82 | "3": "#e01b24",
83 | "4": "#c01c28",
84 | "5": "#a51d2d"
85 | },
86 | "purple_": {
87 | "1": "#dc8add",
88 | "2": "#c061cb",
89 | "3": "#9141ac",
90 | "4": "#813d9c",
91 | "5": "#613583"
92 | },
93 | "brown_": {
94 | "1": "#cdab8f",
95 | "2": "#b5835a",
96 | "3": "#986a44",
97 | "4": "#865e3c",
98 | "5": "#63452c"
99 | },
100 | "light_": {
101 | "1": "#ffffff",
102 | "2": "#f6f5f4",
103 | "3": "#deddda",
104 | "4": "#c0bfbc",
105 | "5": "#9a9996"
106 | },
107 | "dark_": {
108 | "1": "#77767b",
109 | "2": "#5e5c64",
110 | "3": "#3d3846",
111 | "4": "#241f31",
112 | "5": "#000000"
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/data/presets/adwaita.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Adwaita",
3 | "variables": {
4 | "accent_color": "#1c71d8",
5 | "accent_bg_color": "#3584e4",
6 | "accent_fg_color": "#ffffff",
7 | "destructive_color": "#c01c28",
8 | "destructive_bg_color": "#e01b24",
9 | "destructive_fg_color": "#ffffff",
10 | "success_color": "#26a269",
11 | "success_bg_color": "#2ec27e",
12 | "success_fg_color": "#ffffff",
13 | "warning_color": "#ae7b03",
14 | "warning_bg_color": "#e5a50a",
15 | "warning_fg_color": "rgba(0, 0, 0, 0.8)",
16 | "error_color": "#c01c28",
17 | "error_bg_color": "#e01b24",
18 | "error_fg_color": "#ffffff",
19 | "window_bg_color": "#fafafa",
20 | "window_fg_color": "rgba(0, 0, 0, 0.8)",
21 | "view_bg_color": "#ffffff",
22 | "view_fg_color": "rgba(0, 0, 0, 0.8)",
23 | "headerbar_bg_color": "#ebebeb",
24 | "headerbar_fg_color": "rgba(0, 0, 0, 0.8)",
25 | "headerbar_border_color": "rgba(0, 0, 0, 0.8)",
26 | "headerbar_backdrop_color": "@window_bg_color",
27 | "headerbar_shade_color": "rgba(0, 0, 0, 0.07)",
28 | "headerbar_darker_shade_color": "rgba(0, 0, 0, 0.12)",
29 | "card_bg_color": "#ffffff",
30 | "card_fg_color": "rgba(0, 0, 0, 0.8)",
31 | "card_shade_color": "rgba(0, 0, 0, 0.07)",
32 | "dialog_bg_color": "#fafafa",
33 | "dialog_fg_color": "rgba(0, 0, 0, 0.8)",
34 | "popover_bg_color": "#ffffff",
35 | "popover_fg_color": "rgba(0, 0, 0, 0.8)",
36 | "popover_shade_color": "rgba(0, 0, 0, 0.07)",
37 | "shade_color": "rgba(0, 0, 0, 0.07)",
38 | "scrollbar_outline_color": "#ffffff",
39 | "thumbnail_bg_color": "#ffffff",
40 | "thumbnail_fg_color": "rgba(0, 0, 0, 0.8)",
41 | "sidebar_bg_color": "#ebebeb",
42 | "sidebar_fg_color": "rgba(0, 0, 0, 0.8)",
43 | "sidebar_backdrop_color": "#f2f2f2",
44 | "sidebar_shade_color": "rgba(0, 0, 0, 0.07)",
45 | "secondary_sidebar_bg_color": "#f3f3f3",
46 | "secondary_sidebar_fg_color": "rgba(0, 0, 0, 0.8)",
47 | "secondary_sidebar_backdrop_color": "#f6f6f6",
48 | "secondary_sidebar_shade_color": "rgba(0, 0, 0, 0.07)"
49 | },
50 | "palette": {
51 | "blue_": {
52 | "1": "#99c1f1",
53 | "2": "#62a0ea",
54 | "3": "#3584e4",
55 | "4": "#1c71d8",
56 | "5": "#1a5fb4"
57 | },
58 | "green_": {
59 | "1": "#8ff0a4",
60 | "2": "#57e389",
61 | "3": "#33d17a",
62 | "4": "#2ec27e",
63 | "5": "#26a269"
64 | },
65 | "yellow_": {
66 | "1": "#f9f06b",
67 | "2": "#f8e45c",
68 | "3": "#f6d32d",
69 | "4": "#f5c211",
70 | "5": "#e5a50a"
71 | },
72 | "orange_": {
73 | "1": "#ffbe6f",
74 | "2": "#ffa348",
75 | "3": "#ff7800",
76 | "4": "#e66100",
77 | "5": "#c64600"
78 | },
79 | "red_": {
80 | "1": "#f66151",
81 | "2": "#ed333b",
82 | "3": "#e01b24",
83 | "4": "#c01c28",
84 | "5": "#a51d2d"
85 | },
86 | "purple_": {
87 | "1": "#dc8add",
88 | "2": "#c061cb",
89 | "3": "#9141ac",
90 | "4": "#813d9c",
91 | "5": "#613583"
92 | },
93 | "brown_": {
94 | "1": "#cdab8f",
95 | "2": "#b5835a",
96 | "3": "#986a44",
97 | "4": "#865e3c",
98 | "5": "#63452c"
99 | },
100 | "light_": {
101 | "1": "#ffffff",
102 | "2": "#f6f5f4",
103 | "3": "#deddda",
104 | "4": "#c0bfbc",
105 | "5": "#9a9996"
106 | },
107 | "dark_": {
108 | "1": "#77767b",
109 | "2": "#5e5c64",
110 | "3": "#3d3846",
111 | "4": "#241f31",
112 | "5": "#000000"
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/data/presets/pretty-purple.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Pretty Purple",
3 | "variables": {
4 | "accent_color": "#dc8add",
5 | "accent_bg_color": "#9141ac",
6 | "accent_fg_color": "#ffffff",
7 | "destructive_color": "#ff7b63",
8 | "destructive_bg_color": "#c01c28",
9 | "destructive_fg_color": "#ffffff",
10 | "success_color": "#8ff0a4",
11 | "success_bg_color": "#26a269",
12 | "success_fg_color": "#ffffff",
13 | "warning_color": "#f8e45c",
14 | "warning_bg_color": "#cd9309",
15 | "warning_fg_color": "rgba(0, 0, 0, 0.8)",
16 | "error_color": "#ff7b63",
17 | "error_bg_color": "#c01c28",
18 | "error_fg_color": "#ffffff",
19 | "window_bg_color": "#241f31",
20 | "window_fg_color": "#ffffff",
21 | "view_bg_color": "#363141",
22 | "view_fg_color": "#ffffff",
23 | "headerbar_bg_color": "#241f31",
24 | "headerbar_fg_color": "#ffffff",
25 | "headerbar_border_color": "#ffffff",
26 | "headerbar_backdrop_color": "@window_bg_color",
27 | "headerbar_shade_color": "rgba(0, 0, 0, 0.36)",
28 | "headerbar_darker_shade_color": "rgba(0, 0, 0, 0.9)",
29 | "card_bg_color": "rgba(255, 255, 255, 0.08)",
30 | "card_fg_color": "#ffffff",
31 | "card_shade_color": "rgba(0, 0, 0, 0.36)",
32 | "dialog_bg_color": "#241f31",
33 | "dialog_fg_color": "#ffffff",
34 | "popover_bg_color": "#241f31",
35 | "popover_fg_color": "#ffffff",
36 | "popover_shade_color": "rgba(0, 0, 0, 0.36)",
37 | "shade_color": "rgba(0, 0, 0, 0.36)",
38 | "scrollbar_outline_color": "rgba(0, 0, 0, 0.5)",
39 | "thumbnail_bg_color": "#241f31",
40 | "thumbnail_fg_color": "#ffffff",
41 | "sidebar_bg_color": "#39314e",
42 | "sidebar_fg_color": "#ffffff",
43 | "secondary_sidebar_bg_color": "#332b45",
44 | "secondary_sidebar_fg_color": "#ffffff",
45 | "sidebar_backdrop_color": "#332b45",
46 | "secondary_sidebar_backdrop_color": "#2c253c",
47 | "sidebar_shade_color": "rgba(0, 0, 0, 0.36)",
48 | "secondary_sidebar_shade_color": "rgba(0, 0, 0, 0.36)"
49 | },
50 | "palette": {
51 | "blue_": {
52 | "1": "#99c1f1",
53 | "2": "#62a0ea",
54 | "3": "#3584e4",
55 | "4": "#1c71d8",
56 | "5": "#1a5fb4"
57 | },
58 | "green_": {
59 | "1": "#8ff0a4",
60 | "2": "#57e389",
61 | "3": "#33d17a",
62 | "4": "#2ec27e",
63 | "5": "#26a269"
64 | },
65 | "yellow_": {
66 | "1": "#f9f06b",
67 | "2": "#f8e45c",
68 | "3": "#f6d32d",
69 | "4": "#f5c211",
70 | "5": "#e5a50a"
71 | },
72 | "orange_": {
73 | "1": "#ffbe6f",
74 | "2": "#ffa348",
75 | "3": "#ff7800",
76 | "4": "#e66100",
77 | "5": "#c64600"
78 | },
79 | "red_": {
80 | "1": "#f66151",
81 | "2": "#ed333b",
82 | "3": "#e01b24",
83 | "4": "#c01c28",
84 | "5": "#a51d2d"
85 | },
86 | "purple_": {
87 | "1": "#dc8add",
88 | "2": "#c061cb",
89 | "3": "#9141ac",
90 | "4": "#813d9c",
91 | "5": "#613583"
92 | },
93 | "brown_": {
94 | "1": "#cdab8f",
95 | "2": "#b5835a",
96 | "3": "#986a44",
97 | "4": "#865e3c",
98 | "5": "#63452c"
99 | },
100 | "light_": {
101 | "1": "#ffffff",
102 | "2": "#f6f5f4",
103 | "3": "#deddda",
104 | "4": "#c0bfbc",
105 | "5": "#9a9996"
106 | },
107 | "dark_": {
108 | "1": "#77767b",
109 | "2": "#5e5c64",
110 | "3": "#3d3846",
111 | "4": "#241f31",
112 | "5": "#000000"
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/data/shell/meson.build:
--------------------------------------------------------------------------------
1 | install_subdir('templates',
2 | install_dir: join_paths(get_option('datadir'), 'gradience', 'shell'),
3 | exclude_files: 'meson.build',
4 | strip_directory : false
5 | )
6 |
--------------------------------------------------------------------------------
/data/shell/templates/42/check-box.template:
--------------------------------------------------------------------------------
1 | /* Check Boxes */
2 |
3 | // these are equal to the size of the SVG assets
4 | $check_height: 24px;
5 | $check_width: 24px;
6 |
7 |
8 | .check-box {
9 | StBoxLayout { spacing: .8em; }
10 | StBin {
11 | width: $check_width;
12 | height: $check_height;
13 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/checkbox-off-light.svg"), url("resource:///org/gnome/shell/theme/checkbox-off.svg"));
14 | }
15 | &:focus StBin { background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/checkbox-off-focused-light.svg"), url("resource:///org/gnome/shell/theme/checkbox-off-focused.svg"));; }
16 | &:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox.svg"); }
17 | &:focus:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox-focused.svg"); }
18 | }
19 |
--------------------------------------------------------------------------------
/data/shell/templates/42/colors.template:
--------------------------------------------------------------------------------
1 | // When color definition differs for dark and light variant,
2 | // it gets @if-ed depending on $variant
3 |
4 | @import '_palette.scss';
5 |
6 | $_dark_base_color: darken(desaturate({{bg_color}}, 2%), 2%);
7 |
8 | $base_color: $_dark_base_color;
9 | $bg_color: if($variant == 'light', darken($base_color, 5%), lighten($base_color, 5%));
10 | $fg_color: if($variant == 'light', transparentize(black, .2), {{fg_color}});
11 |
12 | $accent_fg_color: {{accent_fg_color}};
13 | $selected_fg_color: if($variant == 'light', $accent_fg_color, {{selected_fg_color}});
14 | $selected_bg_color: {{selected_bg_color}};
15 | $selected_borders_color: if($variant == 'light', darken($selected_bg_color, 15%), darken($selected_bg_color, 30%)); // NOTE: Unused in GNOME Shell 42
16 |
17 | $borders_color: if($variant == 'light', transparentize($fg_color, .5), transparentize($fg_color, .9));
18 | $borders_edge: if($variant == 'light', rgba(255,255,255,0.8), lighten($bg_color, 5%));
19 |
20 | $link_color: if($variant == 'light', darken($selected_bg_color, 10%), lighten($selected_bg_color, 20%));
21 | $link_visited_color: if($variant == 'light', darken($selected_bg_color, 20%), lighten($selected_bg_color, 10%)); // NOTE: Unused in GNOME Shell 42
22 |
23 | $warning_color: {{warning_bg_color}};
24 | $error_color: {{error_bg_color}};
25 | $success_color: {{success_bg_color}}; // NOTE: Unused in GNOME Shell 42
26 | $destructive_color: {{destructive_bg_color}};
27 |
28 | // NOTE: Used also in overview for folder colors, in search results, partially in text and for indicators below app icons
29 | $osd_fg_color: {{osd_fg_color}};
30 | $osd_bg_color: $_dark_base_color; // hardcoded for both light & dark
31 | $osd_insensitive_bg_color: transparentize(mix($osd_fg_color, opacify($osd_bg_color, 1), 10%), 0.5); // NOTE: Unused in GNOME Shell 42
32 | $osd_insensitive_fg_color: if($variant == 'light', mix($osd_fg_color, $osd_bg_color, 80%), mix($osd_fg_color, $osd_bg_color, 70%));
33 | $osd_borders_color: transparentize(black, 0.3);
34 | $osd_outer_borders_color: transparentize($osd_fg_color, 0.98);
35 |
36 | $shadow_color: if($variant == 'light', rgba(0,0,0,0.1), rgba(0,0,0,0.2));
37 |
38 | // cards
39 | $card_bg_color: if($variant == 'light', darken($bg_color, 5%), lighten($bg_color, 2%)); // TODO: Allow to modify this value
40 |
41 | // notifications
42 | $bubble_buttons_color: if($variant == 'light', darken($bg_color, 12%), lighten($bg_color, 10%));
43 |
44 | // overview background color
45 | $system_bg_color: darken(desaturate({{system_bg_color}}, 2%), 2%);
46 |
47 | //insensitive state derived colors
48 | $insensitive_fg_color: mix($fg_color, $bg_color, 50%);
49 | $insensitive_bg_color: mix($bg_color, $base_color, 60%);
50 | $insensitive_borders_color: mix($borders_color, $base_color, 60%); // NOTE: Unused in GNOME Shell 42
51 |
52 | //colors for the backdrop state, derived from the main colors.
53 | // NOTE: This entire section doesn't seem to be used anywhere in GNOME Shell 42
54 | $backdrop_base_color: if($variant =='light', darken($base_color,1%), lighten($base_color,1%));
55 | $backdrop_bg_color: $bg_color;
56 | $backdrop_fg_color: mix($fg_color, $backdrop_bg_color, 80%);
57 | $backdrop_insensitive_color: if($variant =='light', darken($backdrop_bg_color,15%), lighten($backdrop_bg_color,15%));
58 | $backdrop_borders_color: mix($borders_color, $bg_color, 90%);
59 | $backdrop_dark_fill: mix($backdrop_borders_color,$backdrop_bg_color, 35%);
60 |
61 | // derived checked colors
62 | $checked_bg_color: if($variant=='light', darken($bg_color, 7%), lighten($bg_color, 7%));
63 | $checked_fg_color: if($variant=='light', darken($fg_color, 7%), lighten($fg_color, 7%)); // NOTE: Unused in GNOME Shell 42
64 |
65 | // derived hover colors
66 | $hover_bg_color: if($variant=='light', darken($bg_color, 3%), lighten($bg_color, 10%));
67 | $hover_fg_color: if($variant=='light', darken($fg_color, 5%), lighten($fg_color, 10%));
68 |
69 | // derived active colors
70 | $active_bg_color: if($variant=='light', darken($bg_color, 5%), lighten($bg_color, 12%));
71 | $active_fg_color: if($variant=='light', darken($fg_color, 5%), lighten($fg_color, 12%));
72 |
--------------------------------------------------------------------------------
/data/shell/templates/42/gnome-shell.template:
--------------------------------------------------------------------------------
1 | $variant: {{theme_variant}};
2 |
3 | /* Generated with Gradience
4 | *
5 | * Issues caused by theming should be reported to Gradience repository, and not to upstream
6 | *
7 | * https://github.com/GradienceTeam/Gradience
8 | */
9 |
10 | @import "gnome-shell-sass/_colors"; //use gtk colors
11 | @import "gnome-shell-sass/_drawing";
12 | @import "gnome-shell-sass/_common";
13 | @import "gnome-shell-sass/_widgets";
14 |
15 | {{custom_css}}
16 |
--------------------------------------------------------------------------------
/data/shell/templates/42/palette.template:
--------------------------------------------------------------------------------
1 | //GNOME Color Palette
2 | $blue_1: {{blue_1}};
3 | $blue_2: {{blue_2}};
4 | $blue_3: {{blue_3}};
5 | $blue_4: {{blue_4}};
6 | $blue_5: {{blue_5}};
7 | $green_1: {{green_1}};
8 | $green_2: {{green_2}};
9 | $green_3: {{green_3}};
10 | $green_4: {{green_4}};
11 | $green_5: {{green_5}};
12 | $yellow_1: {{yellow_1}};
13 | $yellow_2: {{yellow_2}};
14 | $yellow_3: {{yellow_3}};
15 | $yellow_4: {{yellow_4}};
16 | $yellow_5: {{yellow_5}};
17 | $orange_1: {{orange_1}};
18 | $orange_2: {{orange_2}};
19 | $orange_3: {{orange_3}};
20 | $orange_4: {{orange_4}};
21 | $orange_5: {{orange_5}};
22 | $red_1: {{red_1}};
23 | $red_2: {{red_2}};
24 | $red_3: {{red_3}};
25 | $red_4: {{red_4}};
26 | $red_5: {{red_5}};
27 | $purple_1: {{purple_1}};
28 | $purple_2: {{purple_2}};
29 | $purple_3: {{purple_3}};
30 | $purple_4: {{purple_4}};
31 | $purple_5: {{purple_5}};
32 | $brown_1: {{brown_1}};
33 | $brown_2: {{brown_2}};
34 | $brown_3: {{brown_3}};
35 | $brown_4: {{brown_4}};
36 | $brown_5: {{brown_5}};
37 | $light_1: {{light_1}};
38 | $light_2: {{light_2}};
39 | $light_3: {{light_3}};
40 | $light_4: {{light_4}};
41 | $light_5: {{light_5}};
42 | $dark_1: {{dark_1}};
43 | $dark_2: {{dark_2}};
44 | $dark_3: {{dark_3}};
45 | $dark_4: {{dark_4}};
46 | $dark_5: {{dark_5}};
47 |
--------------------------------------------------------------------------------
/data/shell/templates/42/switches.template:
--------------------------------------------------------------------------------
1 | /* Switches */
2 |
3 | // these are equal to the size of the SVG assets
4 | $switch_height: 26px;
5 | $switch_width: 48px;
6 |
7 | .toggle-switch {
8 | color: $fg_color;
9 | height: $switch_height;
10 | width: $switch_width;
11 | background-size: contain;
12 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-off-light.svg"), url("resource:///org/gnome/shell/theme/toggle-off.svg"));
13 | &:checked {
14 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-on-light.svg"), url("asstets/toggle-on.svg"));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/data/shell/templates/43/check-box.template:
--------------------------------------------------------------------------------
1 | /* Check Boxes */
2 |
3 | // these are equal to the size of the SVG assets
4 | $check_height: 24px;
5 | $check_width: 24px;
6 |
7 |
8 | .check-box {
9 | StBoxLayout { spacing: .8em; }
10 | StBin {
11 | width: $check_width;
12 | height: $check_height;
13 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/checkbox-off-light.svg"), url("resource:///org/gnome/shell/theme/checkbox-off.svg"));
14 | }
15 | &:focus StBin { background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/checkbox-off-focused-light.svg"), url("resource:///org/gnome/shell/theme/checkbox-off-focused.svg"));; }
16 | &:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox.svg"); }
17 | &:focus:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox-focused.svg"); }
18 | }
19 |
--------------------------------------------------------------------------------
/data/shell/templates/43/gnome-shell.template:
--------------------------------------------------------------------------------
1 | $variant: {{theme_variant}};
2 |
3 | /* Generated with Gradience
4 | *
5 | * Issues caused by theming should be reported to Gradience repository, and not to upstream
6 | *
7 | * https://github.com/GradienceTeam/Gradience
8 | */
9 |
10 | @import "gnome-shell-sass/_colors"; //use gtk colors
11 | @import "gnome-shell-sass/_drawing";
12 | @import "gnome-shell-sass/_common";
13 | @import "gnome-shell-sass/_widgets";
14 |
15 | {{custom_css}}
16 |
--------------------------------------------------------------------------------
/data/shell/templates/43/palette.template:
--------------------------------------------------------------------------------
1 | //GNOME Color Palette
2 | $blue_1: {{blue_1}};
3 | $blue_2: {{blue_2}};
4 | $blue_3: {{blue_3}};
5 | $blue_4: {{blue_4}};
6 | $blue_5: {{blue_5}};
7 | $green_1: {{green_1}};
8 | $green_2: {{green_2}};
9 | $green_3: {{green_3}};
10 | $green_4: {{green_4}};
11 | $green_5: {{green_5}};
12 | $yellow_1: {{yellow_1}};
13 | $yellow_2: {{yellow_2}};
14 | $yellow_3: {{yellow_3}};
15 | $yellow_4: {{yellow_4}};
16 | $yellow_5: {{yellow_5}};
17 | $orange_1: {{orange_1}};
18 | $orange_2: {{orange_2}};
19 | $orange_3: {{orange_3}};
20 | $orange_4: {{orange_4}};
21 | $orange_5: {{orange_5}};
22 | $red_1: {{red_1}};
23 | $red_2: {{red_2}};
24 | $red_3: {{red_3}};
25 | $red_4: {{red_4}};
26 | $red_5: {{red_5}};
27 | $purple_1: {{purple_1}};
28 | $purple_2: {{purple_2}};
29 | $purple_3: {{purple_3}};
30 | $purple_4: {{purple_4}};
31 | $purple_5: {{purple_5}};
32 | $brown_1: {{brown_1}};
33 | $brown_2: {{brown_2}};
34 | $brown_3: {{brown_3}};
35 | $brown_4: {{brown_4}};
36 | $brown_5: {{brown_5}};
37 | $light_1: {{light_1}};
38 | $light_2: {{light_2}};
39 | $light_3: {{light_3}};
40 | $light_4: {{light_4}};
41 | $light_5: {{light_5}};
42 | $dark_1: {{dark_1}};
43 | $dark_2: {{dark_2}};
44 | $dark_3: {{dark_3}};
45 | $dark_4: {{dark_4}};
46 | $dark_5: {{dark_5}};
47 |
--------------------------------------------------------------------------------
/data/shell/templates/43/switches.template:
--------------------------------------------------------------------------------
1 | /* Switches */
2 |
3 | // these are equal to the size of the SVG assets
4 | $switch_height: 26px;
5 | $switch_width: 48px;
6 |
7 | .toggle-switch {
8 | color: $fg_color;
9 | height: $switch_height;
10 | width: $switch_width;
11 | background-size: contain;
12 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-off-light.svg"), url("resource:///org/gnome/shell/theme/toggle-off.svg"));
13 | &:checked {
14 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-on-light.svg"), url("assets/toggle-on.svg"));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/data/shell/templates/44/check-box.template:
--------------------------------------------------------------------------------
1 | /* Check Boxes */
2 |
3 | // these are equal to the size of the SVG assets
4 | $check_height: 24px;
5 | $check_width: 24px;
6 |
7 |
8 | .check-box {
9 | StBoxLayout { spacing: .8em; }
10 | StBin {
11 | width: $check_width;
12 | height: $check_height;
13 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/checkbox-off-light.svg"), url("resource:///org/gnome/shell/theme/checkbox-off.svg"));
14 | }
15 | &:focus StBin { background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/checkbox-off-focused-light.svg"), url("resource:///org/gnome/shell/theme/checkbox-off-focused.svg"));; }
16 | &:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox.svg"); }
17 | &:focus:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox-focused.svg"); }
18 | }
19 |
--------------------------------------------------------------------------------
/data/shell/templates/44/colors.template:
--------------------------------------------------------------------------------
1 | // When color definition differs for dark and light variant,
2 | // it gets @if-ed depending on $variant
3 |
4 | @import '_palette.scss';
5 |
6 | $is_highcontrast: false;
7 |
8 | $_dark_base_color: darken(desaturate({{bg_color}}, 2%), 2%);
9 |
10 | $base_color: $_dark_base_color;
11 | $bg_color: if($variant == 'light', darken($base_color, 5%), lighten($base_color, 5%));
12 | $fg_color: if($variant == 'light', transparentize(black, .2), {{fg_color}});
13 |
14 | $accent_fg_color: {{accent_fg_color}};
15 | $selected_fg_color: if($variant == 'light', $accent_fg_color, {{selected_fg_color}});
16 | $selected_bg_color: {{selected_bg_color}};
17 | $selected_borders_color: if($variant == 'light', darken($selected_bg_color, 15%), darken($selected_bg_color, 30%));
18 |
19 | $borders_color: if($variant == 'light', transparentize($fg_color, .5), transparentize($fg_color, .9));
20 | $outer_borders_color: if($variant == 'light', rgba(255,255,255,0.8), lighten($bg_color, 5%));
21 |
22 | $link_color: if($variant == 'light', darken($selected_bg_color, 10%), lighten($selected_bg_color, 20%));
23 | $link_visited_color: if($variant == 'light', darken($selected_bg_color, 20%), lighten($selected_bg_color, 10%)); // NOTE: Unused in GNOME Shell 44
24 |
25 | $warning_color: {{warning_bg_color}};
26 | $error_color: {{error_bg_color}};
27 | $success_color: {{success_bg_color}}; // NOTE: Unused in GNOME Shell 44
28 | $destructive_color: {{destructive_bg_color}};
29 |
30 | // NOTE: Used also in overview for folder colors, in search results, partially in text and for indicators below app icons
31 | $osd_fg_color: {{osd_fg_color}};
32 | $osd_bg_color: $_dark_base_color; // hardcoded for both light & dark
33 | $osd_insensitive_bg_color: transparentize(mix($osd_fg_color, opacify($osd_bg_color, 1), 10%), 0.5); // NOTE: Unused in GNOME Shell 44
34 | $osd_insensitive_fg_color: if($variant == 'light', mix($osd_fg_color, $osd_bg_color, 80%), mix($osd_fg_color, $osd_bg_color, 70%));
35 | $osd_borders_color: transparentize(black, 0.3);
36 | $osd_outer_borders_color: transparentize($osd_fg_color, 0.9);
37 |
38 | $shadow_color: if($variant == 'light', rgba(0,0,0,0.1), rgba(0,0,0,0.2));
39 |
40 | // button
41 | $button_mix_factor: 9%;
42 |
43 | // notifications
44 | $bubble_buttons_color: if($variant == 'light', darken($bg_color, 7%), lighten($bg_color, 5%));
45 |
46 | // overview background color
47 | $system_bg_color: darken(desaturate({{system_bg_color}}, 2%), 2%);
48 |
49 | //insensitive state derived colors
50 | $insensitive_fg_color: mix($fg_color, $bg_color, 50%);
51 | $insensitive_bg_color: mix($bg_color, $base_color, 60%);
52 | $insensitive_borders_color: mix($borders_color, $base_color, 60%); // NOTE: Unused in GNOME Shell 44
53 |
54 | //colors for the backdrop state, derived from the main colors.
55 | // NOTE: This entire section doesn't seem to be used anywhere in GNOME Shell 44
56 | $backdrop_base_color: if($variant =='light', darken($base_color,1%), lighten($base_color,1%));
57 | $backdrop_bg_color: $bg_color;
58 | $backdrop_fg_color: mix($fg_color, $backdrop_bg_color, 80%);
59 | $backdrop_insensitive_color: if($variant =='light', darken($backdrop_bg_color,15%), lighten($backdrop_bg_color,15%));
60 | $backdrop_borders_color: mix($borders_color, $bg_color, 90%);
61 | $backdrop_dark_fill: mix($backdrop_borders_color,$backdrop_bg_color, 35%);
62 |
63 | // derived checked colors
64 | $checked_bg_color: if($variant=='light', darken($bg_color, 7%), lighten($bg_color, 7%));
65 | $checked_fg_color: if($variant=='light', darken($fg_color, 7%), lighten($fg_color, 7%)); // NOTE: Unused in GNOME Shell 44
66 |
67 | // derived hover colors
68 | $hover_bg_color: if($variant=='light', darken($bg_color, 3%), lighten($bg_color, 10%));
69 | $hover_fg_color: if($variant=='light', darken($fg_color, 5%), lighten($fg_color, 10%));
70 |
71 | // derived active colors
72 | $active_bg_color: if($variant=='light', darken($bg_color, 5%), lighten($bg_color, 12%));
73 | $active_fg_color: if($variant=='light', darken($fg_color, 5%), lighten($fg_color, 12%));
74 |
--------------------------------------------------------------------------------
/data/shell/templates/44/gnome-shell.template:
--------------------------------------------------------------------------------
1 | $variant: {{theme_variant}};
2 |
3 | /* Generated with Gradience
4 | *
5 | * Issues caused by theming should be reported to Gradience repository, and not to upstream
6 | *
7 | * https://github.com/GradienceTeam/Gradience
8 | */
9 |
10 | @import "gnome-shell-sass/_colors"; //use gtk colors
11 | @import "gnome-shell-sass/_drawing";
12 | @import "gnome-shell-sass/_common";
13 | @import "gnome-shell-sass/_widgets";
14 |
15 | {{custom_css}}
16 |
--------------------------------------------------------------------------------
/data/shell/templates/44/palette.template:
--------------------------------------------------------------------------------
1 | //GNOME Color Palette
2 | $blue_1: {{blue_1}};
3 | $blue_2: {{blue_2}};
4 | $blue_3: {{blue_3}};
5 | $blue_4: {{blue_4}};
6 | $blue_5: {{blue_5}};
7 | $green_1: {{green_1}};
8 | $green_2: {{green_2}};
9 | $green_3: {{green_3}};
10 | $green_4: {{green_4}};
11 | $green_5: {{green_5}};
12 | $yellow_1: {{yellow_1}};
13 | $yellow_2: {{yellow_2}};
14 | $yellow_3: {{yellow_3}};
15 | $yellow_4: {{yellow_4}};
16 | $yellow_5: {{yellow_5}};
17 | $orange_1: {{orange_1}};
18 | $orange_2: {{orange_2}};
19 | $orange_3: {{orange_3}};
20 | $orange_4: {{orange_4}};
21 | $orange_5: {{orange_5}};
22 | $red_1: {{red_1}};
23 | $red_2: {{red_2}};
24 | $red_3: {{red_3}};
25 | $red_4: {{red_4}};
26 | $red_5: {{red_5}};
27 | $purple_1: {{purple_1}};
28 | $purple_2: {{purple_2}};
29 | $purple_3: {{purple_3}};
30 | $purple_4: {{purple_4}};
31 | $purple_5: {{purple_5}};
32 | $brown_1: {{brown_1}};
33 | $brown_2: {{brown_2}};
34 | $brown_3: {{brown_3}};
35 | $brown_4: {{brown_4}};
36 | $brown_5: {{brown_5}};
37 | $light_1: {{light_1}};
38 | $light_2: {{light_2}};
39 | $light_3: {{light_3}};
40 | $light_4: {{light_4}};
41 | $light_5: {{light_5}};
42 | $dark_1: {{dark_1}};
43 | $dark_2: {{dark_2}};
44 | $dark_3: {{dark_3}};
45 | $dark_4: {{dark_4}};
46 | $dark_5: {{dark_5}};
47 |
--------------------------------------------------------------------------------
/data/shell/templates/44/switches.template:
--------------------------------------------------------------------------------
1 | /* Switches */
2 |
3 | // these are equal to the size of the SVG assets
4 | $switch_height: 26px;
5 | $switch_width: 48px;
6 |
7 | .toggle-switch {
8 | color: $fg_color;
9 | height: $switch_height;
10 | width: $switch_width;
11 | background-size: contain;
12 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-off-light.svg"), url("resource:///org/gnome/shell/theme/toggle-off.svg"));
13 | &:checked {
14 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-on-light.svg"), url("assets/toggle-on.svg"));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/data/shell/templates/45/check-box.template:
--------------------------------------------------------------------------------
1 | /* Check Boxes */
2 |
3 | // these are equal to the size of the SVG assets
4 | $check_height: 24px;
5 | $check_width: 24px;
6 |
7 |
8 | .check-box {
9 | StBoxLayout { spacing: .8em; }
10 | StBin {
11 | width: $check_width;
12 | height: $check_height;
13 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/checkbox-off-light.svg"), url("resource:///org/gnome/shell/theme/checkbox-off.svg"));
14 | }
15 | &:focus StBin { background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/checkbox-off-focused-light.svg"), url("resource:///org/gnome/shell/theme/checkbox-off-focused.svg"));; }
16 | &:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox.svg"); }
17 | &:focus:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox-focused.svg"); }
18 | }
19 |
--------------------------------------------------------------------------------
/data/shell/templates/45/gnome-shell.template:
--------------------------------------------------------------------------------
1 | $variant: {{theme_variant}};
2 |
3 | /* Generated with Gradience
4 | *
5 | * Issues caused by theming should be reported to Gradience repository, and not to upstream
6 | *
7 | * https://github.com/GradienceTeam/Gradience
8 | */
9 |
10 | @import "gnome-shell-sass/_colors"; //use gtk colors
11 | @import "gnome-shell-sass/_drawing";
12 | @import "gnome-shell-sass/_common";
13 | @import "gnome-shell-sass/_widgets";
14 |
15 | {{custom_css}}
16 |
--------------------------------------------------------------------------------
/data/shell/templates/45/palette.template:
--------------------------------------------------------------------------------
1 | //GNOME Color Palette
2 | $blue_1: {{blue_1}};
3 | $blue_2: {{blue_2}};
4 | $blue_3: {{blue_3}};
5 | $blue_4: {{blue_4}};
6 | $blue_5: {{blue_5}};
7 | $green_1: {{green_1}};
8 | $green_2: {{green_2}};
9 | $green_3: {{green_3}};
10 | $green_4: {{green_4}};
11 | $green_5: {{green_5}};
12 | $yellow_1: {{yellow_1}};
13 | $yellow_2: {{yellow_2}};
14 | $yellow_3: {{yellow_3}};
15 | $yellow_4: {{yellow_4}};
16 | $yellow_5: {{yellow_5}};
17 | $orange_1: {{orange_1}};
18 | $orange_2: {{orange_2}};
19 | $orange_3: {{orange_3}};
20 | $orange_4: {{orange_4}};
21 | $orange_5: {{orange_5}};
22 | $red_1: {{red_1}};
23 | $red_2: {{red_2}};
24 | $red_3: {{red_3}};
25 | $red_4: {{red_4}};
26 | $red_5: {{red_5}};
27 | $purple_1: {{purple_1}};
28 | $purple_2: {{purple_2}};
29 | $purple_3: {{purple_3}};
30 | $purple_4: {{purple_4}};
31 | $purple_5: {{purple_5}};
32 | $brown_1: {{brown_1}};
33 | $brown_2: {{brown_2}};
34 | $brown_3: {{brown_3}};
35 | $brown_4: {{brown_4}};
36 | $brown_5: {{brown_5}};
37 | $light_1: {{light_1}};
38 | $light_2: {{light_2}};
39 | $light_3: {{light_3}};
40 | $light_4: {{light_4}};
41 | $light_5: {{light_5}};
42 | $dark_1: {{dark_1}};
43 | $dark_2: {{dark_2}};
44 | $dark_3: {{dark_3}};
45 | $dark_4: {{dark_4}};
46 | $dark_5: {{dark_5}};
47 |
--------------------------------------------------------------------------------
/data/shell/templates/45/switches.template:
--------------------------------------------------------------------------------
1 | /* Switches */
2 |
3 | // these are equal to the size of the SVG assets
4 | $switch_height: 26px;
5 | $switch_width: 48px;
6 |
7 | .toggle-switch {
8 | color: $fg_color;
9 | height: $switch_height;
10 | width: $switch_width;
11 | background-size: contain;
12 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-off-light.svg"), url("resource:///org/gnome/shell/theme/toggle-off.svg"));
13 | &:checked {
14 | background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-on-light.svg"), url("assets/toggle-on.svg"));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/data/style.css:
--------------------------------------------------------------------------------
1 | .variant {
2 | padding: 0;
3 | border-radius: 100%;
4 | }
5 |
6 | .variant radio {
7 | color: transparent;
8 | background-color: inherit;
9 | border: 2px solid transparent;
10 | }
11 |
12 | .variant:checked radio {
13 | border: 2px solid @accent_bg_color;
14 | }
15 |
16 | #dark {
17 | background-color: #3d3846;
18 | }
19 |
20 | #light {
21 | background-color: #deddda;
22 | }
23 |
24 | #red {
25 | background-color: #e01b24;
26 | }
27 |
28 | #orange {
29 | background-color: #ff7800;
30 | }
31 |
32 | #yellow {
33 | background-color: #f6d32d;
34 | }
35 |
36 | #blue {
37 | background-color: #3584e4;
38 | }
39 |
40 | #green {
41 | background-color: #33d17a;
42 | }
43 |
44 | .tag {
45 | border-radius: 20px;
46 | background-color: alpha(currentColor, 0.07);
47 | padding: 5px 13px;
48 | margin: 0 2px;
49 | }
50 |
51 | .badge-black {
52 | background-color: #3d3846;
53 | color: #deddda;
54 | }
55 | .badge-white {
56 | background-color: #deddda;
57 | color: #3d3846;
58 | }
59 |
60 | .row-content {
61 | padding: 10px;
62 | }
63 |
64 | .content {
65 | margin: 10px 12px;
66 | }
67 |
--------------------------------------------------------------------------------
/data/ui/app_type_dialog.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceAppTypeDialog : Adw.MessageDialog {
5 | [extra-child]
6 | Box {
7 | orientation: vertical;
8 | spacing: 15;
9 |
10 | Box {
11 | orientation: vertical;
12 | Label {
13 | styles ["heading"]
14 | label: _("Select application types to theme:");
15 | }
16 | CheckButton gtk4-app-type {
17 | label: _("Libadwaita and GTK 4 Applications");
18 | active: true;
19 | }
20 | CheckButton gtk3-app-type {
21 | label: _("GTK 3 Applications (adw-gtk3 theme required)");
22 | }
23 | }
24 | // Box {
25 | // orientation: vertical;
26 | // Label {
27 | // styles ["heading"]
28 | // label: _("Select color mode to theme:");
29 | // }
30 | // CheckButton dark {
31 | // label: _("Dark");
32 | // active: true;
33 | // }
34 | // CheckButton light {
35 | // label: _("Light");
36 | // }
37 | // }
38 | }
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/data/ui/builtin_preset_row.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceBuiltinPresetRow : Adw.ActionRow {
5 | subtitle: _("Made by @GradienceTeam");
6 | activatable-widget: apply_button;
7 |
8 | [suffix]
9 | Button apply_button {
10 | valign: center;
11 | icon-name: "checkmark-symbolic";
12 | tooltip-text: _("Apply Preset");
13 | clicked => $on_apply_button_clicked();
14 | styles [
15 | "flat",
16 | ]
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/data/ui/custom_css_group.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceCustomCSSGroup : Adw.PreferencesGroup {
5 | title: _("Custom Styles");
6 | description: _("Changing this may break some programs. Libadwaita allows applications to hardcode values like padding and margins, and using custom styles may cause unintended breakage.");
7 |
8 | [header-suffix]
9 | DropDown app_type_dropdown {
10 | valign: start;
11 | model: app_type_list;
12 | notify => $on_dropdown_notify();
13 | }
14 |
15 | ScrolledWindow {
16 | min-content-height: 500;
17 | max-content-height: 500;
18 | TextView custom_css_text_view {
19 | styles ["card"]
20 | left-margin: 10;
21 | right-margin: 10;
22 | top-margin: 10;
23 | bottom-margin: 10;
24 | monospace: true;
25 | buffer: TextBuffer {
26 | changed => $on_custom_css_changed();
27 | };
28 | }
29 | }
30 | }
31 |
32 | StringList app_type_list {
33 | strings [_("GTK 4"), _("GTK 3")]
34 | }
35 |
--------------------------------------------------------------------------------
/data/ui/error_list_row.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceErrorListRow : ListBoxRow {
5 | Box {
6 | orientation: vertical;
7 | margin-top: 6;
8 | margin-bottom: 6;
9 | margin-start: 6;
10 | margin-end: 6;
11 |
12 | Box {
13 | orientation: horizontal;
14 | spacing: 6;
15 |
16 | Label error-label {
17 | halign: start;
18 | justify: left;
19 | styles ["heading", "error"]
20 | }
21 |
22 | Label element-label {
23 | halign: start;
24 | justify: left;
25 | styles ["dim-label", "error"]
26 | }
27 | }
28 |
29 | Label line-label {
30 | halign: start;
31 | wrap: true;
32 | justify: left;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/data/ui/explore_preset_row.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceExplorePresetRow : Adw.ActionRow {
5 | activatable-widget: apply_button;
6 |
7 | Box {
8 | spacing: 6;
9 |
10 | //Label badge {
11 | // valign: center;
12 | // label: _("Unknown");
13 |
14 | // styles [
15 | // "tag",
16 | // "caption",
17 | // ]
18 | //}
19 |
20 | Button apply_button {
21 | valign: center;
22 | icon-name: "checkmark-symbolic";
23 | tooltip-text: _("Download and Apply");
24 | clicked => $on_apply_button_clicked();
25 |
26 | styles [
27 | "flat",
28 | ]
29 | }
30 |
31 | Button download_button {
32 | valign: center;
33 | icon-name: "folder-download-symbolic";
34 | tooltip-text: _("Download");
35 | clicked => $on_download_button_clicked();
36 |
37 | styles [
38 | "flat",
39 | ]
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/data/ui/help_overlay.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 |
3 | ShortcutsWindow help_overlay {
4 | modal: true;
5 |
6 | ShortcutsSection {
7 | section-name: "shortcuts";
8 | ShortcutsGroup {
9 | title: C_("shortcut window", "General");
10 |
11 | ShortcutsShortcut {
12 | title: C_("shortcut window", "Show Shortcuts");
13 | action-name: "win.show-help-overlay";
14 | }
15 |
16 | ShortcutsShortcut {
17 | title: C_("shortcut window", "Show Apply Dialog");
18 | action-name: "app.apply_color_scheme";
19 | }
20 |
21 | ShortcutsShortcut {
22 | title: C_("shortcut window", "Manage Presets");
23 | action-name: "app.manage_presets";
24 | }
25 |
26 | ShortcutsShortcut {
27 | title: C_("shortcut window", "Save Preset");
28 | action-name: "app.save_preset";
29 | }
30 |
31 | ShortcutsShortcut {
32 | title: C_("shortcut window", "Go to the Colors Section");
33 | action-name: "app.switch_to_colors_page";
34 | }
35 |
36 | ShortcutsShortcut {
37 | title: C_("shortcut window", "Go to the Theming Section");
38 | action-name: "app.switch_to_theming_page";
39 | }
40 |
41 | ShortcutsShortcut {
42 | title: C_("shortcut window", "Go to the Advanced Section");
43 | action-name: "app.switch_to_advanced_page";
44 | }
45 |
46 | ShortcutsShortcut {
47 | title: C_("shortcut window", "Preferences");
48 | action-name: "app.preferences";
49 | }
50 |
51 | ShortcutsShortcut {
52 | title: C_("shortcut window", "Quit");
53 | action-name: "app.quit";
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/data/ui/log_out_dialog.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceLogOutDialog : Adw.MessageDialog {
5 | heading: _("Log out"); // TODO: redundant? how can we not repeat ourselves?
6 | body: _("Log out to allow changes to take effect.");
7 | }
8 |
--------------------------------------------------------------------------------
/data/ui/meson.build:
--------------------------------------------------------------------------------
1 | blueprints = custom_target('blueprints',
2 | input: files(
3 | 'error_list_row.blp',
4 | 'palette_shades.blp',
5 | 'option_row.blp',
6 | 'window.blp',
7 | 'monet_theming_group.blp',
8 | 'app_type_dialog.blp',
9 | 'custom_css_group.blp',
10 | 'presets_manager_window.blp',
11 | 'reset_preset_group.blp',
12 | 'preferences_window.blp',
13 | 'plugin_row.blp',
14 | 'welcome_window.blp',
15 | 'preset_row.blp',
16 | 'builtin_preset_row.blp',
17 | 'explore_preset_row.blp',
18 | 'help_overlay.blp',
19 | 'save_dialog.blp',
20 | 'shell_prefs_window.blp',
21 | 'shell_theming_group.blp',
22 | 'repo_row.blp',
23 | 'no_plugin_window.blp',
24 | 'share_window.blp',
25 | 'theming_empty_group.blp',
26 | ),
27 | output: '.',
28 | command: [find_program('blueprint-compiler'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@']
29 | )
30 |
--------------------------------------------------------------------------------
/data/ui/monet_theming_group.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceMonetThemingGroup : Adw.PreferencesGroup {
5 | title: _("Monet Engine");
6 | description: _("Generates a Material Design 3 palette by extracting colors of an image.");
7 |
8 | Adw.ExpanderRow monet-theming-expander {
9 | title: _("Monet Engine Options");
10 | subtitle: _("Choose an image and modify generated Monet palette");
11 | expanded: true;
12 |
13 | [action]
14 | Button monet-apply-button {
15 | valign: center;
16 | label: _("Apply");
17 | tooltip-text: _("Apply a palette");
18 | clicked => $on_apply_button_clicked();
19 | styles ["suggested-action"]
20 | }
21 |
22 | Adw.ActionRow file-chooser-row {
23 | title: _("Background Image");
24 | activatable-widget: file-chooser-button;
25 |
26 | [suffix]
27 | Button file-chooser-button {
28 | valign: center;
29 | clicked => $on_file_chooser_button_clicked();
30 |
31 | Adw.ButtonContent {
32 | icon-name: "folder-pictures-symbolic";
33 | label: _("Choose a File");
34 | use-underline: true;
35 | }
36 | }
37 | }
38 | }
39 | }
40 |
41 | Gtk.FileChooserNative monet-file-chooser {
42 | title: _("Choose a Image File");
43 | modal: true;
44 | //response => on_monet_file_chooser_response();
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/data/ui/no_plugin_window.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceNoPluginPrefWindow : Adw.PreferencesWindow {
5 | title: _("Plugin Preferences");
6 | search-enabled: false;
7 | default-height: 400;
8 | default-width: 400;
9 | modal: true;
10 |
11 | Adw.PreferencesPage {
12 | Adw.StatusPage {
13 | name: "empty";
14 | icon-name: "action-unavailable-symbolic";
15 | title: _("No Preferences");
16 | description: _("This plugin has no preferences.");
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/data/ui/option_row.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceOptionRow : Adw.ActionRow {
5 | activatable-widget: color-value;
6 |
7 | [suffix]
8 | MenuButton warning-button {
9 | valign: center;
10 | icon-name: "adw-gtk3-warning-symbolic";
11 | popover: warning-popover;
12 | tooltip-text: _("GTK 3 Support Warning");
13 | styles ["flat"]
14 | }
15 |
16 | [suffix]
17 | MenuButton explanation-button {
18 | valign: center;
19 | icon-name: "dialog-information-symbolic";
20 | popover: explanation-popover;
21 | tooltip-text: _("Explanation");
22 | styles ["flat"]
23 | }
24 |
25 | [suffix]
26 | Stack value-stack {
27 | valign: center;
28 | hhomogeneous: false;
29 | interpolate-size: true;
30 | transition-type: crossfade;
31 |
32 | ColorButton color-value {
33 | rgba: "#00000000";
34 | use-alpha: true;
35 | }
36 | Entry text-value {
37 | text: "#00000000";
38 | }
39 | }
40 |
41 | [suffix]
42 | ToggleButton text-value-toggle {
43 | valign: center;
44 | icon-name: "document-edit-symbolic";
45 | tooltip-text: _("Show Hex");
46 | styles ["flat"]
47 |
48 | toggled => $on_text_value_toggled();
49 | }
50 | }
51 |
52 | Popover warning-popover {
53 | autohide: true;
54 | Label warning-label {
55 | margin-top: 6;
56 | margin-bottom: 6;
57 | margin-start: 6;
58 | margin-end: 6;
59 | max-width-chars: 30;
60 | wrap: true;
61 | justify: center;
62 | }
63 | }
64 |
65 | Popover explanation-popover {
66 | autohide: true;
67 | Label explanation-label {
68 | margin-top: 6;
69 | margin-bottom: 6;
70 | margin-start: 6;
71 | margin-end: 6;
72 | max-width-chars: 30;
73 | wrap: true;
74 | justify: center;
75 | }
76 | }
77 |
78 |
--------------------------------------------------------------------------------
/data/ui/palette_shades.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradiencePaletteShades : Adw.ActionRow {}
5 |
--------------------------------------------------------------------------------
/data/ui/plugin_row.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradiencePluginRow : Adw.ActionRow {
5 | activatable-widget: switch;
6 |
7 | [suffix]
8 | Switch switch {
9 | valign: center;
10 | tooltip-text: _("Toggle Plugin");
11 | state-set => $on_switch_toggled();
12 | }
13 |
14 | // TODO: Detect if plugin has preferences, and if it does display the
15 | // settings button
16 |
17 | // [suffix]
18 | // Button settings-button {
19 | // valign: center;
20 | // icon-name: "settings-symbolic";
21 | // tooltip-text: _("Preferences");
22 | // clicked => $on_settings_plugin_clicked();
23 |
24 | // styles [
25 | // "flat",
26 | // ]
27 | // }
28 |
29 | [suffix]
30 | Button remove-button {
31 | valign: center;
32 | icon-name: "user-trash-symbolic";
33 | tooltip-text: _("Remove Plugin");
34 | clicked => $on_remove_plugin_clicked();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/data/ui/repo_row.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceRepoRow : Adw.ActionRow {
5 | [suffix]
6 | Button remove_button {
7 | valign: center;
8 | icon-name: "user-trash-symbolic";
9 | tooltip-text: _("Remove Preset");
10 | clicked => $on_remove_button_clicked();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/data/ui/reset_preset_group.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceResetPresetGroup : Adw.PreferencesGroup {
5 | title: _("Reset and Restore Theming");
6 | description: _("Reset theming to default or restore previously applied preset.");
7 |
8 | Adw.ActionRow {
9 | title: _("GTK 4/Libadwaita Apps");
10 |
11 | Button restore_libadw_button {
12 | valign: center;
13 | icon-name: "edit-undo-symbolic";
14 | tooltip-text: _("Restore Previous Preset");
15 | clicked => $on_libadw_restore_button_clicked();
16 | styles ["flat"]
17 | }
18 |
19 | Button reset_libadw_button {
20 | valign: center;
21 | label: _("Reset");
22 | tooltip-text: _("Reset Applied Preset");
23 | clicked => $on_libadw_reset_button_clicked();
24 | styles ["destructive-action"]
25 | }
26 | }
27 |
28 | Adw.ActionRow {
29 | title: _("GTK 3 Apps");
30 |
31 | Button restore_gtk3_button {
32 | valign: center;
33 | icon-name: "edit-undo-symbolic";
34 | tooltip-text: _("Restore Previous Preset");
35 | clicked => $on_gtk3_restore_button_clicked();
36 | styles ["flat"]
37 | }
38 |
39 | Button reset_gtk3_button {
40 | valign: center;
41 | label: _("Reset");
42 | tooltip-text: _("Reset Applied Preset");
43 | clicked => $on_gtk3_reset_button_clicked();
44 | styles ["destructive-action"]
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/data/ui/save_dialog.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceSaveDialog : Adw.MessageDialog {
5 | heading: _("Save preset as…");
6 | body-use-markup: true;
7 |
8 | [extra-child]
9 | Entry preset-entry {
10 | placeholder-text: _("Preset Name");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/data/ui/shell_prefs_window.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceShellPrefsWindow : Adw.PreferencesWindow {
5 | title: _("Shell Engine Preferences");
6 | search-enabled: false;
7 | default-height: 620;
8 | default-width: 500;
9 | modal: true;
10 |
11 | Adw.PreferencesPage {
12 | Adw.PreferencesGroup custom-colors-group {
13 | title: _("Shell theme colors");
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/data/ui/shell_theming_group.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceShellThemingGroup: Adw.PreferencesGroup {
5 | title: _("Shell Engine");
6 | description: _("Generates GNOME Shell theme based on current preset.\nWARNING: Extensions that modify the Shell stylesheet may cause issues with themes.");
7 |
8 | // TODO: Fix the warning being under shell-theming-expander
9 | Label {
10 | label: "Warning: Extensions that modify the Shell stylesheet may cause issues with themes";
11 | halign: start;
12 |
13 | styles [
14 | "dim-label",
15 | "warning"
16 | ]
17 | }
18 |
19 | Adw.ExpanderRow shell-theming-expander {
20 | title: _("Shell Engine Options");
21 | subtitle: _("Change the generated GNOME Shell theme");
22 | expanded: true;
23 |
24 | [action]
25 | Button shell-apply-button {
26 | valign: center;
27 | label: _("Apply");
28 | tooltip-text: _("Apply Shell theme");
29 | clicked => $on_apply_button_clicked();
30 |
31 | styles [
32 | "suggested-action"
33 | ]
34 | }
35 |
36 | Adw.ActionRow custom-colors-row {
37 | title: _("Customize Shell Theme");
38 | activatable-widget: custom-colors-button;
39 |
40 | [suffix]
41 | Button custom-colors-button {
42 | valign: center;
43 | label: _("Open Shell Preferences");
44 | clicked => $on_custom_colors_button_clicked();
45 | }
46 | }
47 |
48 | Adw.ComboRow variant-row {
49 | title: _("Preset Variant");
50 | subtitle: _("Select currently applied preset variant");
51 | }
52 | }
53 | }
54 |
55 | Adw.ActionRow other-options-row {
56 | [prefix]
57 | Button restore_libadw_button {
58 | valign: center;
59 | icon-name: "edit-undo-symbolic";
60 | sensitive: false;
61 | //tooltip-text: _("Restore Previous Theme");
62 | tooltip-text: _("Currently unavailable");
63 | clicked => $on_restore_button_clicked();
64 |
65 | styles [
66 | "flat"
67 | ]
68 | }
69 |
70 | [suffix]
71 | Button reset_theme_button {
72 | valign: center;
73 | label: _("Reset Theme");
74 | tooltip-text: _("Reset applied theme");
75 | clicked => $on_reset_theme_clicked();
76 |
77 | styles [
78 | "destructive-action"
79 | ]
80 | }
81 | }
82 |
83 |
--------------------------------------------------------------------------------
/data/ui/theming_empty_group.blp:
--------------------------------------------------------------------------------
1 | using Gtk 4.0;
2 | using Adw 1;
3 |
4 | template $GradienceEmptyThemingGroup : Adw.PreferencesGroup {
5 | title: _("No Theme Engines");
6 | description: _("Theme Engines extend the functionality of Gradience. They can be enabled in the Preferences.");
7 |
8 | Adw.ActionRow open-preferences {
9 | title: _("Open Preferences to manage Theme Engines");
10 |
11 | [suffix]
12 | Button open {
13 | valign: center;
14 | label: _("Open Preferences");
15 | tooltip-text: _("Open Preferences");
16 | action-name: "app.preferences";
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradience.doap:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | Gradience
9 | Change the look of Adwaita, with ease
10 |
11 | Gradience is a tool for customizing Libadwaita applications and the adw-gtk3 theme.
12 |
13 |
14 |
15 |
16 |
17 |
18 | Python
19 |
20 |
21 |
22 | 0xMRTT
23 |
24 | 0xMRTT
25 |
26 |
27 |
28 |
29 |
30 | Gradience Team
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/gradience/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/__init__.py
--------------------------------------------------------------------------------
/gradience/backend/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/backend/__init__.py
--------------------------------------------------------------------------------
/gradience/backend/constants.py.in:
--------------------------------------------------------------------------------
1 | # constants.py.in
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022 Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | rootdir = '/com/github/GradienceTeam/Gradience'
20 | datadir = '@DATA_DIR@'
21 | pkgdatadir = '@PKGDATA_DIR@'
22 | localedir = '@LOCALE_DIR@'
23 |
24 | app_id = '@APP_ID@'
25 | rel_ver = '@RELEASE_VER@'
26 | version = '@VERSION@'
27 | build_type = '@BUILD_TYPE@'
28 |
29 | project_url = '@PROJECT_URL@'
30 | bugtracker_url = '@BUGTRACKER_URL@'
31 | help_url = '@HELP_URL@'
32 | translate_url = '@TRANSLATE_URL@'
33 |
--------------------------------------------------------------------------------
/gradience/backend/css_parser.py:
--------------------------------------------------------------------------------
1 | # css_parser.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022 Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | import re
20 |
21 | from gradience.backend.globals import adw_palette_prefixes
22 |
23 |
24 | # Regular expressions
25 | define_color = re.compile(r"(@define-color .*[^\s])")
26 | not_define_color = re.compile(r"(^(?:(?!@define-color).)*$)")
27 |
28 | def parse_css(path):
29 | css = ""
30 | variables = {}
31 | palette = {}
32 |
33 | for color in adw_palette_prefixes:
34 | palette[color] = {}
35 |
36 | with open(path, "r", encoding="utf-8") as sheet:
37 | for line in sheet:
38 | cdefine_match = re.search(define_color, line)
39 | not_cdefine_match = re.search(not_define_color, line)
40 | if cdefine_match != None: # If @define-color variable declarations were found
41 | palette_part = cdefine_match.__getitem__(1) # Get the second item of the re.Match object
42 | name, color = palette_part.split(" ", 1)[1].split(" ", 1)
43 | if name.startswith(tuple(adw_palette_prefixes)): # Palette colors
44 | palette[name[:-1]][name[-1:]] = color[:-1]
45 | else: # Other color variables
46 | variables[name] = color[:-1]
47 | elif not_cdefine_match != None: # If CSS rules were found
48 | css_part = not_cdefine_match.__getitem__(1)
49 | css += f"{css_part}\n"
50 |
51 | sheet.close()
52 | return variables, palette, css
53 |
--------------------------------------------------------------------------------
/gradience/backend/exceptions.py:
--------------------------------------------------------------------------------
1 | # css_parser.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 |
20 | class GradienceError(Exception):
21 | """ Base class for all other exceptions in Gradience. """
22 | pass
23 |
24 |
25 | # TODO: Move this module somewhere else later
26 | class UnsupportedShellVersion(GradienceError):
27 | """ Exception raised when the shell version is not supported. """
28 | pass
29 |
--------------------------------------------------------------------------------
/gradience/backend/globals.py:
--------------------------------------------------------------------------------
1 | # globals.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022-2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | import os
20 |
21 | from gi.repository import Xdp
22 |
23 | from gradience.backend import constants
24 |
25 |
26 | user_config_dir = os.environ.get(
27 | "XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"
28 | )
29 |
30 | user_data_dir = os.environ.get(
31 | "XDG_DATA_HOME", os.environ["HOME"] + "/.local/share"
32 | )
33 |
34 | user_cache_dir = os.environ.get(
35 | "XDG_CACHE_HOME", os.environ["HOME"] + "/.cache"
36 | )
37 |
38 | presets_dir = os.path.join(user_config_dir, "presets")
39 |
40 | user_plugin_dir = os.path.join(user_data_dir, "gradience", "plugins")
41 | system_plugin_dir = os.path.join(constants.pkgdatadir, "plugins")
42 |
43 | preset_repos_github = {
44 | "Official": "https://github.com/GradienceTeam/Community/raw/next/official.json",
45 | "Curated": "https://github.com/GradienceTeam/Community/raw/next/curated.json"
46 | }
47 |
48 | preset_repos_jsdelivr = {
49 | "Official": "https://cdn.jsdelivr.net/gh/GradienceTeam/Community@next/official.json",
50 | "Curated": "https://cdn.jsdelivr.net/gh/GradienceTeam/Community@next/curated.json"
51 | }
52 |
53 | # preset_repos should be dynamically imported depending of user settings
54 |
55 | # Adwaita named UI colors prefixes list
56 | # NOTE: Remember to update this list if new libadwaita version brings up new variables
57 | adw_variables_prefixes = [
58 | "accent_",
59 | "destructive_",
60 | "success_",
61 | "warning_",
62 | "error_",
63 | "window_",
64 | "view_",
65 | "headerbar_",
66 | "card_",
67 | "dialog_",
68 | "popover_",
69 | "shade_",
70 | "scrollbar_",
71 | "borders"
72 | ]
73 |
74 | # Adwaita named palette colors prefixes list
75 | # NOTE: Remember to update this list if new libadwaita version brings up new variables
76 | adw_palette_prefixes = [
77 | "blue_",
78 | "green_",
79 | "yellow_",
80 | "orange_",
81 | "red_",
82 | "purple_",
83 | "brown_",
84 | "light_",
85 | "dark_"
86 | ]
87 |
88 | def get_gtk_theme_dir(app_type: str):
89 | if app_type == "gtk4":
90 | theme_dir = os.path.join(user_config_dir, "gtk-4.0")
91 |
92 | if app_type == "gtk3":
93 | theme_dir = os.path.join(user_config_dir, "gtk-3.0")
94 |
95 | return theme_dir
96 |
97 | def is_sandboxed():
98 | portal = Xdp.Portal()
99 |
100 | is_sandboxed = portal.running_under_sandbox()
101 |
102 | return is_sandboxed
103 |
--------------------------------------------------------------------------------
/gradience/backend/meson.build:
--------------------------------------------------------------------------------
1 | backenddir = 'gradience/backend'
2 |
3 | configure_file(
4 | input: 'constants.py.in',
5 | output: 'constants.py',
6 | configuration: configuration_data({
7 | 'APP_ID': APPLICATION_ID,
8 | 'RELEASE_VER': meson.project_version(),
9 | 'VERSION': meson.project_version() + VERSION_SUFFIX,
10 | 'BUILD_TYPE': get_option('buildtype'),
11 | 'PROJECT_URL': PROJECT_URL,
12 | 'BUGTRACKER_URL': BUGTRACKER_URL,
13 | 'HELP_URL': HELP_URL,
14 | 'TRANSLATE_URL': TRANSLATE_URL,
15 | 'DATA_DIR': conf.get('DATA_DIR'),
16 | 'PKGDATA_DIR': PKGDATA_DIR,
17 | 'LOCALE_DIR': conf.get('LOCALE_DIR'),
18 | }),
19 | install: true,
20 | install_dir: PY_INSTALLDIR.get_install_dir() / backenddir
21 | )
22 |
23 | subdir('models')
24 | subdir('theming')
25 | subdir('utils')
26 |
27 | gradience_sources = [
28 | '__init__.py',
29 | 'css_parser.py',
30 | 'flatpak_overrides.py',
31 | 'globals.py',
32 | 'logger.py',
33 | 'preset_downloader.py',
34 | 'exceptions.py'
35 | ]
36 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: backenddir)
37 |
--------------------------------------------------------------------------------
/gradience/backend/models/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/backend/models/__init__.py
--------------------------------------------------------------------------------
/gradience/backend/models/meson.build:
--------------------------------------------------------------------------------
1 | modelsdir = 'gradience/backend/models'
2 |
3 | gradience_sources = [
4 | '__init__.py',
5 | 'preset.py',
6 | 'repo.py'
7 | ]
8 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: modelsdir)
9 |
--------------------------------------------------------------------------------
/gradience/backend/models/repo.py:
--------------------------------------------------------------------------------
1 | # repo.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022 Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | import os
20 |
21 | from gradience.backend.utils.common import to_slug_case
22 | from gradience.backend.globals import presets_dir
23 | from gradience.backend.models.preset import Preset
24 |
25 |
26 | class Repo:
27 | presets = {}
28 |
29 | def __init__(self, name):
30 | self.name = to_slug_case(name)
31 | self.path = os.path.join(presets_dir, name)
32 | self.presets = self.get_presets()
33 |
34 | def get_presets(self):
35 | presets = {}
36 | for preset in os.listdir(self.path):
37 | if preset.endswith(".json"):
38 | preset_path = os.path.join(self.path, preset)
39 | presets[preset[:-5]] = Preset().new_from_path(preset_path)
40 | return presets
41 |
--------------------------------------------------------------------------------
/gradience/backend/struct.md:
--------------------------------------------------------------------------------
1 | ## `backend/` directory structure:
2 |
3 | - `models/` - objects containing various types of data, with logic to manipulate them
4 | - `theming/` - theme generation/manipulation specific modules
5 | - `utils/` - general purpose utility modules
6 |
--------------------------------------------------------------------------------
/gradience/backend/theming/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/backend/theming/__init__.py
--------------------------------------------------------------------------------
/gradience/backend/theming/meson.build:
--------------------------------------------------------------------------------
1 | themingdir = 'gradience/backend/theming'
2 |
3 | gradience_sources = [
4 | '__init__.py',
5 | 'monet.py',
6 | 'preset.py',
7 | 'shell.py'
8 | ]
9 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: themingdir)
10 |
--------------------------------------------------------------------------------
/gradience/backend/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/backend/utils/__init__.py
--------------------------------------------------------------------------------
/gradience/backend/utils/common.py:
--------------------------------------------------------------------------------
1 | # common.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022-2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | import re
20 | import os
21 |
22 | from anyascii import anyascii
23 |
24 | from gi.repository import Gio
25 |
26 |
27 | def to_slug_case(non_slug) -> str:
28 | return re.sub(r"[^0-9a-z]+", "-", anyascii(non_slug).lower()).strip("-")
29 |
30 | def extract_version(text, prefix_text=None):
31 | '''
32 | Extracts version number from a provided text.
33 |
34 | You can also set the prefix_text parameter to reduce searching to
35 | lines with only this text prefixed to the version number.
36 | '''
37 | if not prefix_text:
38 | version = re.search(r"\s*([0-9.]+)", text)
39 | else:
40 | version = re.search(prefix_text + r"\s*([0-9.]+)", text)
41 |
42 | return version.__getitem__(1)
43 |
--------------------------------------------------------------------------------
/gradience/backend/utils/gnome.py:
--------------------------------------------------------------------------------
1 | # shell.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | import os
20 |
21 | from gradience.backend.models.preset import Preset
22 | from gradience.backend.utils.subprocess import GradienceSubprocess
23 | from gradience.backend.utils.common import extract_version
24 |
25 | # TODO: Remove this import later (imports from gradience.frontend are not allowed in backend)
26 | from gradience.frontend.schemas.shell_schema import shell_schema
27 |
28 |
29 | # TODO: Return failure if command was not found
30 | def get_shell_version() -> str:
31 | cmd_list = ["gnome-shell", "--version"]
32 | process = GradienceSubprocess()
33 |
34 | completed = process.run(cmd_list, allow_escaping=True)
35 | stdout = process.get_stdout_data(completed, decode=True)
36 |
37 | shell_version = extract_version(stdout, "GNOME Shell")
38 |
39 | return shell_version
40 |
41 | def get_full_shell_version() -> str:
42 | cmd_list = ["gnome-shell", "--version"]
43 | process = GradienceSubprocess()
44 |
45 | completed = process.run(cmd_list, allow_escaping=True)
46 | stdout = process.get_stdout_data(completed, decode=True)
47 |
48 | shell_version = stdout[12:]
49 |
50 | return shell_version
51 |
52 | def is_gnome_available() -> bool:
53 | xdg_current_desktop = os.environ.get("XDG_CURRENT_DESKTOP").lower()
54 |
55 | if "gnome" in xdg_current_desktop:
56 | return True
57 |
58 | return False
59 |
60 | def is_shell_ext_installed(uuid: str, check_enabled: bool = False) -> bool:
61 | """
62 | Checks if Shell extension with provided UUID from `uuid` parameter
63 | is installed in system.
64 |
65 | `check_enabled` parameter allows for checking if extension is enabled.
66 | """
67 |
68 | if check_enabled:
69 | cmd_list = ["gnome-extensions", "list", "--enabled"]
70 | else:
71 | cmd_list = ["gnome-extensions", "list"]
72 |
73 | process = GradienceSubprocess()
74 |
75 | completed = process.run(cmd_list, allow_escaping=True)
76 | stdout = process.get_stdout_data(completed, decode=True)
77 |
78 | ext_list = stdout.split("\n")
79 | if ext_list[-1] == "":
80 | ext_list.pop(-1)
81 |
82 | if uuid in ext_list:
83 | return True
84 |
85 | return False
86 |
87 | def get_shell_colors(preset_variables: Preset.variables) -> dict:
88 | shell_colors = {}
89 |
90 | for variable in shell_schema["variables"]:
91 | shell_colors[variable["name"]] = variable["var_name"]
92 |
93 | for shell_key, var_name in shell_colors.items():
94 | if shell_key == "panel_bg_color":
95 | shell_colors[shell_key] = shell_schema["variables"][5]["default_value"]
96 | continue
97 | shell_colors[shell_key] = preset_variables[var_name]
98 |
99 | return shell_colors
100 |
--------------------------------------------------------------------------------
/gradience/backend/utils/meson.build:
--------------------------------------------------------------------------------
1 | utilsdir = 'gradience/backend/utils'
2 |
3 | gradience_sources = [
4 | '__init__.py',
5 | 'colors.py',
6 | 'common.py',
7 | 'gnome.py',
8 | 'gsettings.py',
9 | 'networking.py',
10 | 'subprocess.py',
11 | 'theming.py'
12 | ]
13 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: utilsdir)
14 |
--------------------------------------------------------------------------------
/gradience/backend/utils/networking.py:
--------------------------------------------------------------------------------
1 | # networking.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from urllib.parse import urlparse
20 |
21 |
22 | def get_preset_repos(use_jsdelivr: bool) -> dict:
23 | if use_jsdelivr:
24 | from gradience.backend.globals import preset_repos_jsdelivr
25 | preset_repos = preset_repos_jsdelivr
26 | else:
27 | from gradience.backend.globals import preset_repos_github
28 | preset_repos = preset_repos_github
29 |
30 | return preset_repos
31 |
32 | def github_to_jsdelivr_url(github_url: str) -> str:
33 | """
34 | Converts Github raw data URL link to JSDelivr CDN link.
35 | """
36 |
37 | jsdelivr_url = None
38 |
39 | # https://github.com/GradienceTeam/Community/raw/next/official/builder.json =>
40 | # https://cdn.jsdelivr.net/gh/GradienceTeam/Community@next/official/builder.json
41 | if "https://github.com" in github_url:
42 | JSDELIVER_FORMAT = "https://cdn.jsdelivr.net/gh/{user}/{repo}@{branch}/{path}"
43 | path = urlparse(github_url).path
44 | user, repo, _, branch, *path = path.strip('/').split('/')
45 | path = "/".join(path)
46 | jsdelivr_url = JSDELIVER_FORMAT.format(user=user, repo=repo, branch=branch, path=path)
47 |
48 | return jsdelivr_url
49 |
--------------------------------------------------------------------------------
/gradience/backend/utils/subprocess.py:
--------------------------------------------------------------------------------
1 | # subprocess.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022-2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | import os
20 | #import signal
21 |
22 | from typing import Union
23 |
24 | import subprocess
25 | from subprocess import SubprocessError, CompletedProcess
26 |
27 | from gradience.backend.logger import Logger
28 |
29 | logging = Logger(logger_name="GradienceSubprocess")
30 |
31 |
32 | # TODO: Check how Dev Toolbox has its backend done fully in async using Gio.Task.
33 | # Example: https://github.com/aleiepure/devtoolbox/blob/main/src/services/gzip_compressor.py
34 | # TODO: Replace subprocess.run() with subprocess.Popen() for more control over subprocesses
35 | class GradienceSubprocess:
36 | """
37 | Wrapper for Python's `subprocess` module to provide an easy to use
38 | synchronous process spawning and stdout data retrievement with support
39 | for Flatpak sandbox escape.
40 |
41 | Documentation: https://docs.python.org/3/library/subprocess.html
42 | """
43 |
44 | def __init__(self):
45 | pass
46 |
47 | def run(self, command: list, timeout: int = None, allow_escaping: bool = False) -> CompletedProcess:
48 | """
49 | Spawns synchronously a new child process (subprocess) using Python's `subprocess` module.
50 |
51 | You can set the `timeout` parameter to kill the process after a
52 | specified amount of seconds.
53 |
54 | You can enable executing commands outside Flatpak sandbox by
55 | enabling `allow_escaping` parameter.
56 | """
57 |
58 | if allow_escaping and os.environ.get('FLATPAK_ID'):
59 | command = ['flatpak-spawn', '--host'] + command
60 |
61 | logging.debug(f"Spawning: {command}")
62 |
63 | try:
64 | process = subprocess.run(command, check=True,
65 | capture_output=True, timeout=timeout)
66 | except SubprocessError:
67 | raise
68 | except FileNotFoundError:
69 | raise
70 |
71 | return process
72 |
73 | def get_stdout_data(self, process: CompletedProcess, decode: bool = False) -> Union[str, bytes]:
74 | """
75 | Returns a data retrieved from stdout stream.
76 |
77 | Default behavior returns a full data collection in bytes array.
78 | Setting ``decode`` parameter to True will automatically decode data to string object.
79 | """
80 |
81 | if decode:
82 | stdout_string = process.stdout.decode()
83 | return stdout_string
84 |
85 | return process.stdout
86 |
87 | '''def stop(self, process: CompletedProcess) -> None:
88 | logging.debug(f"Terminating process, ID {process.get_identifier()}")
89 | process.send_signal(signal.SIGTERM)
90 |
91 | def kill(self, process: CompletedProcess) -> None:
92 | logging.debug(f"Killing process, ID {process.get_identifier()}")
93 | self.cancel_read()
94 | process.send_signal(signal.SIGKILL)'''
95 |
--------------------------------------------------------------------------------
/gradience/backend/utils/theming.py:
--------------------------------------------------------------------------------
1 | # theming.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gradience.backend.models.preset import Preset
20 |
21 |
22 | def generate_gtk_css(app_type: str, preset: Preset) -> str:
23 | variables = preset.variables
24 | palette = preset.palette
25 | custom_css = preset.custom_css
26 |
27 | theming_warning = """/*
28 | Generated with Gradience
29 |
30 | Issues caused by theming should be reported to Gradience repository, and not to upstream
31 |
32 | https://github.com/GradienceTeam/Gradience
33 | */
34 |
35 | """
36 |
37 | gtk_css = ""
38 |
39 | for key in variables.keys():
40 | gtk_css += f"@define-color {key} {variables[key]};\n"
41 |
42 | for prefix_key in palette.keys():
43 | for key in palette[prefix_key].keys():
44 | gtk_css += f"@define-color {prefix_key + key} {palette[prefix_key][key]};\n"
45 |
46 | gtk_css += custom_css.get(app_type, "")
47 |
48 | gtk_css += "\n.navigation-sidebar {\nbackground-color: "
49 | gtk_css += variables["window_bg_color"]
50 | gtk_css += ";\n}"
51 |
52 | final_css = theming_warning + gtk_css
53 |
54 | return final_css
55 |
--------------------------------------------------------------------------------
/gradience/frontend/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/frontend/__init__.py
--------------------------------------------------------------------------------
/gradience/frontend/cli/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/frontend/cli/__init__.py
--------------------------------------------------------------------------------
/gradience/frontend/cli/meson.build:
--------------------------------------------------------------------------------
1 | clidir = 'gradience/frontend/cli'
2 |
3 | configure_file(
4 | input: 'cli.in',
5 | output: 'gradience-cli',
6 | configuration: conf,
7 | install_dir: get_option('bindir')
8 | )
9 |
10 | if get_option('buildtype') == 'debug'
11 | configure_file(
12 | input: 'cli.in',
13 | output: 'local-gradience-cli',
14 | configuration: local_conf,
15 | install_dir: join_paths(meson.project_build_root(), 'gradience', 'frontend')
16 | )
17 | endif
18 |
19 | gradience_sources = [
20 | '__init__.py'
21 | ]
22 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: clidir)
23 |
--------------------------------------------------------------------------------
/gradience/frontend/dialogs/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/frontend/dialogs/__init__.py
--------------------------------------------------------------------------------
/gradience/frontend/dialogs/app_type_dialog.py:
--------------------------------------------------------------------------------
1 | # app_type_dialog.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022-2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gtk, Adw
20 |
21 | from gradience.backend.constants import rootdir
22 |
23 |
24 | @Gtk.Template(resource_path=f"{rootdir}/ui/app_type_dialog.ui")
25 | class GradienceAppTypeDialog(Adw.MessageDialog):
26 | __gtype_name__ = "GradienceAppTypeDialog"
27 |
28 | gtk4_app_type = Gtk.Template.Child("gtk4-app-type")
29 | gtk3_app_type = Gtk.Template.Child("gtk3-app-type")
30 |
31 | def __init__(self, parent, heading, body, ok_res_name, ok_res_label, ok_res_appearance, **kwargs):
32 | super().__init__(**kwargs)
33 |
34 | self.parent = parent
35 | self.app = self.parent.get_application()
36 |
37 | if isinstance(self.parent, Gtk.Window):
38 | self.win = self.parent
39 | else:
40 | self.win = self.app.get_active_window()
41 |
42 | self.set_transient_for(self.win)
43 |
44 | self.set_heading(heading)
45 | self.set_body(body)
46 |
47 | self.add_response("cancel", _("_Cancel"))
48 | self.add_response(ok_res_name, ok_res_label)
49 | self.set_response_appearance(ok_res_name, ok_res_appearance)
50 | self.set_default_response("cancel")
51 | self.set_close_response("cancel")
52 |
53 | def get_app_types(self):
54 | return {
55 | "gtk4": self.gtk4_app_type.get_active(),
56 | "gtk3": self.gtk3_app_type.get_active()
57 | }
58 |
--------------------------------------------------------------------------------
/gradience/frontend/dialogs/meson.build:
--------------------------------------------------------------------------------
1 | dialogsdir = 'gradience/frontend/dialogs'
2 |
3 | gradience_sources = [
4 | '__init__.py',
5 | 'app_type_dialog.py',
6 | 'save_dialog.py',
7 | 'unsupported_shell_dialog.py'
8 | ]
9 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: dialogsdir)
10 |
--------------------------------------------------------------------------------
/gradience/frontend/dialogs/save_dialog.py:
--------------------------------------------------------------------------------
1 | # save_dialog.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gtk, Adw
20 |
21 | from gradience.backend.constants import rootdir
22 |
23 |
24 | # TODO: Make this dialog async when Libadwaita 1.3 becomes available \
25 | # https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/method.MessageDialog.choose.html
26 | @Gtk.Template(resource_path=f"{rootdir}/ui/save_dialog.ui")
27 | class GradienceSaveDialog(Adw.MessageDialog):
28 | __gtype_name__ = "GradienceSaveDialog"
29 |
30 | preset_entry = Gtk.Template.Child("preset-entry")
31 |
32 | def __init__(self, parent, heading=None, body=None, path=None, discard=False, **kwargs):
33 | super().__init__(**kwargs)
34 |
35 | self.parent = parent
36 | self.app = self.parent.get_application()
37 |
38 | self.body = _(
39 | "Saving preset to \n {0}. \n If that preset already "
40 | "exists, it will be overwritten."
41 | )
42 |
43 | if isinstance(self.parent, Gtk.Window):
44 | self.win = self.parent
45 | else:
46 | self.win = self.app.get_active_window()
47 |
48 | self.set_transient_for(self.win)
49 |
50 | if heading:
51 | self.heading = heading
52 | self.set_heading(self.heading)
53 |
54 | if not body and path:
55 | self.set_body(self.body.format(path))
56 | elif body:
57 | self.body = body
58 | self.set_body(self.body)
59 | elif not body and not path:
60 | raise AttributeError("DEV FAULT: You need to either specify 'body' or 'path' parameter")
61 |
62 | self.add_response("cancel", _("_Cancel"))
63 |
64 | if discard:
65 | self.add_response("discard", _("Discard"))
66 | self.set_response_appearance(
67 | "discard", Adw.ResponseAppearance.DESTRUCTIVE
68 | )
69 |
70 | self.add_response("save", _("_Save"))
71 | self.set_default_response("cancel")
72 | self.set_close_response("cancel")
73 |
74 | self.set_response_appearance(
75 | "save", Adw.ResponseAppearance.SUGGESTED
76 | )
77 |
78 |
--------------------------------------------------------------------------------
/gradience/frontend/dialogs/unsupported_shell_dialog.py:
--------------------------------------------------------------------------------
1 | # unsupported_shell_version.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022-2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gtk, Adw
20 |
21 | from gradience.backend.constants import rootdir
22 | from gradience.backend.utils.gnome import get_full_shell_version
23 |
24 | class GradienceUnsupportedShellDialog(Adw.MessageDialog):
25 | __gtype_name__ = "GradienceUnsupportedShellDialog"
26 |
27 | def __init__(self, parent, **kwargs):
28 | super().__init__(**kwargs)
29 |
30 | self.parent = parent
31 | self.app = self.parent.get_application()
32 |
33 | if isinstance(self.parent, Gtk.Window):
34 | self.win = self.parent
35 | else:
36 | self.win = self.app.get_active_window()
37 |
38 | self.set_transient_for(self.win)
39 |
40 | self.set_heading(_(f"Unsupported Shell Version ({get_full_shell_version()})"))
41 | self.set_body(_("The Shell version you are using is not supported by Gradience. Please upgrade to a newer version of GNOME."))
42 |
43 | self.add_response("ok", _("OK"))
44 | self.set_default_response("ok")
45 | self.set_close_response("ok")
46 |
--------------------------------------------------------------------------------
/gradience/frontend/gradience.in:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # gradience.in
4 | #
5 | # Change the look of Adwaita, with ease
6 | # Copyright (C) 2022 Gradience Team
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | import os
22 | import sys
23 | import signal
24 | import locale
25 | import shutil
26 | import gettext
27 |
28 | is_local = @local_build@
29 |
30 | if is_local:
31 | # In the local use case, use gradience module from the sourcetree
32 | sys.path.insert(1, '@PYTHON@')
33 |
34 | # In the local use case the installed schemas go in /data
35 | os.environ["XDG_DATA_DIRS"] = '@SCHEMAS_DIR@:' + os.environ.get("XDG_DATA_DIRS", "")
36 |
37 | shutil.copyfile(
38 | os.path.join('@BUILD_DIR@', "gradience/backend", "constants.py"),
39 | os.path.join('@SOURCE_DIR@', "gradience/backend", "constants.py")
40 | )
41 |
42 | pkgdatadir = '@PKGDATA_DIR@'
43 | localedir = '@LOCALE_DIR@'
44 |
45 | sys.dont_write_bytecode = True
46 |
47 | signal.signal(signal.SIGINT, signal.SIG_DFL)
48 | gettext.install('gradience', localedir)
49 |
50 | locale.bindtextdomain('gradience', localedir)
51 | locale.textdomain('gradience')
52 |
53 |
54 | if __name__ == '__main__':
55 | import gi
56 |
57 | gi.require_version('Gtk', '4.0')
58 | gi.require_version('Adw', '1')
59 | gi.require_version('Xdp', '1.0')
60 | gi.require_version('XdpGtk4', '1.0')
61 | gi.require_version('Soup', '3.0')
62 |
63 | from gi.repository import Gio
64 | resource = Gio.Resource.load(
65 | os.path.join(pkgdatadir, 'gradience.gresource'))
66 | Gio.Resource._register(resource)
67 |
68 | sys.path.insert(1, "/usr/local/lib/python3.10/site-packages")
69 |
70 | from gradience.frontend import main
71 | sys.exit(main.main())
72 |
--------------------------------------------------------------------------------
/gradience/frontend/meson.build:
--------------------------------------------------------------------------------
1 | frontenddir = 'gradience/frontend'
2 |
3 | configure_file(
4 | input: 'gradience.in',
5 | output: 'gradience',
6 | configuration: conf,
7 | install_dir: get_option('bindir')
8 | )
9 |
10 | if get_option('buildtype') == 'debug'
11 | configure_file(
12 | input: 'gradience.in',
13 | output: 'local-gradience',
14 | configuration: local_conf
15 | )
16 |
17 | launcher = join_paths(meson.project_build_root(), moduledir, 'frontend', 'local-' + meson.project_name())
18 |
19 | run_target('run',
20 | command: [launcher]
21 | )
22 | endif
23 |
24 | subdir('cli')
25 | subdir('dialogs')
26 | subdir('schemas')
27 | subdir('utils')
28 | subdir('views')
29 | subdir('widgets')
30 |
31 | gradience_sources = [
32 | '__init__.py',
33 | 'main.py'
34 | ]
35 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: frontenddir)
36 |
--------------------------------------------------------------------------------
/gradience/frontend/schemas/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/frontend/schemas/__init__.py
--------------------------------------------------------------------------------
/gradience/frontend/schemas/meson.build:
--------------------------------------------------------------------------------
1 | schemasdir = 'gradience/frontend/schemas'
2 |
3 | gradience_sources = [
4 | '__init__.py',
5 | 'preset_schema.py',
6 | 'shell_schema.py'
7 | ]
8 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: schemasdir)
9 |
--------------------------------------------------------------------------------
/gradience/frontend/schemas/shell_schema.py:
--------------------------------------------------------------------------------
1 | # shell_schema.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | shell_schema = {
20 | "variables": [
21 | {
22 | "name": "bg_color",
23 | "var_name": "window_bg_color",
24 | "title": _("Base Background Color")
25 | },
26 | {
27 | "name": "fg_color",
28 | "var_name": "window_fg_color",
29 | "title": _("Base Foreground Color")
30 | },
31 | {
32 | "name": "system_bg_color",
33 | "var_name": "window_bg_color",
34 | "title": _("Overview Background Color")
35 | },
36 | {
37 | "name": "selected_bg_color",
38 | "var_name": "accent_bg_color",
39 | "title": _("Accent Background Color")
40 | },
41 | {
42 | "name": "selected_fg_color",
43 | "var_name": "window_fg_color",
44 | "title": _("Accent Foreground Color")
45 | },
46 | # TODO: Fix panel background color injection code
47 | #{
48 | # "name": "panel_bg_color",
49 | # "var_name": "panel_bg_color",
50 | # "title": _("Panel Background Color"),
51 | # "default_value": "#000"
52 | #},
53 | #{
54 | # "name": "osd_bg_color",
55 | # "var_name": "window_bg_color",
56 | # "title": _("OSD Background Color")
57 | #},
58 | {
59 | "name": "osd_fg_color",
60 | "var_name": "window_fg_color",
61 | "title": _("OSD Foreground Color")
62 | }
63 | ]
64 | }
65 |
--------------------------------------------------------------------------------
/gradience/frontend/struct.md:
--------------------------------------------------------------------------------
1 | ## `frontend/` directory structure:
2 |
3 | - `cli/` - frontend command-line based interface for Gradience's backend functions
4 | - `dialogs/` - message boxes and simple popup windows
5 | - `schemas/` - color view schemas, mostly used to dynamically construct views with GradienceOptionRow widget
6 | - `utils/` - general purpose utility modules and helpers for UI related stuff
7 | - `views/` - more extensive widgets (eg. widget groups, lists) and GTK window views
8 | - `widgets/` - simple custom (eg. custom Adw.ActionRow) widgets
9 |
--------------------------------------------------------------------------------
/gradience/frontend/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/frontend/utils/__init__.py
--------------------------------------------------------------------------------
/gradience/frontend/utils/actions.py:
--------------------------------------------------------------------------------
1 | # actions.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gio
20 |
21 |
22 | class ActionHelpers:
23 | def __init__(self, parent):
24 | self.parent = parent
25 |
26 | def create_action(self, name, callback, shortcuts=None):
27 | """Add an application action.
28 |
29 | Args:
30 | name: the name of the action
31 | callback: the function to be called when the action is
32 | activated
33 | shortcuts: an optional list of accelerators
34 | """
35 |
36 | action = Gio.SimpleAction.new(name, None)
37 | action.connect("activate", callback)
38 |
39 | self.parent.add_action(action)
40 |
41 | if shortcuts:
42 | self.parent.set_accels_for_action(f"app.{name}", shortcuts)
43 |
44 | def create_stateful_action(self, name, parameter_type, initial_state, callback, shortcuts=None):
45 | """Add a stateful application action."""
46 |
47 | action = Gio.SimpleAction.new_stateful(
48 | name, parameter_type, initial_state)
49 | action.connect("activate", callback)
50 |
51 | self.parent.add_action(action)
52 |
53 | if shortcuts:
54 | self.parent.set_accels_for_action(f"app.{name}", shortcuts)
55 |
--------------------------------------------------------------------------------
/gradience/frontend/utils/meson.build:
--------------------------------------------------------------------------------
1 | utilsdir = 'gradience/frontend/utils'
2 |
3 | gradience_sources = [
4 | '__init__.py',
5 | 'actions.py',
6 | 'run_async.py'
7 | ]
8 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: utilsdir)
9 |
--------------------------------------------------------------------------------
/gradience/frontend/utils/run_async.py:
--------------------------------------------------------------------------------
1 | # run_async.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022 Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | import sys
20 | import threading
21 | import traceback
22 |
23 | from gi.repository import GLib
24 |
25 | from gradience.backend.logger import Logger
26 |
27 | logging = Logger()
28 |
29 |
30 | class RunAsync(threading.Thread):
31 | def __init__(self, task_func, callback=None, *args, **kwargs):
32 | self.source_id = None
33 | if threading.current_thread() is not threading.main_thread():
34 | raise AssertionError
35 |
36 | super(RunAsync, self).__init__(
37 | target=self.target, args=args, kwargs=kwargs)
38 |
39 | self.task_func = task_func
40 |
41 | self.callback = callback if callback else lambda r, e: None
42 | self.daemon = kwargs.pop("daemon", True)
43 |
44 | self.start()
45 |
46 | def target(self, *args, **kwargs):
47 | result = None
48 | error = None
49 |
50 | logging.debug(f"Running async job [{self.task_func}].")
51 |
52 | try:
53 | result = self.task_func(*args, **kwargs)
54 | except Exception as e:
55 | logging.error(f"Error while running async job: {self.task_func}", exc=e)
56 |
57 | error = exception
58 | _ex_type, _ex_value, trace = sys.exc_info()
59 | traceback.print_tb(trace)
60 | traceback_info = "\n".join(traceback.format_tb(trace))
61 |
62 | logging.error([str(exception), traceback_info])
63 | self.source_id = GLib.idle_add(self.callback, result, error)
64 | return self.source_id
65 |
--------------------------------------------------------------------------------
/gradience/frontend/views/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/frontend/views/__init__.py
--------------------------------------------------------------------------------
/gradience/frontend/views/about_window.py:
--------------------------------------------------------------------------------
1 | # about_window.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gtk, Adw
20 |
21 | from gradience.backend import constants
22 |
23 |
24 | # TRANSLATORS: This is a place to put your credits (formats:
25 | # "Name https://example.com" or "Name ",
26 | # no quotes) and is not meant to be translated literally.
27 | translator_credits = _("translator-credits")
28 |
29 | class GradienceAboutWindow:
30 | def __init__(self, parent):
31 | self.parent = parent
32 | self.app = self.parent.get_application()
33 |
34 | self.setup()
35 |
36 | def setup(self):
37 | self.about_window = Adw.AboutWindow(
38 | application_name="Gradience",
39 | transient_for=self.app.get_active_window(),
40 | application_icon=constants.app_id,
41 | developer_name=_("Gradience Team"),
42 | website=constants.project_url,
43 | support_url=constants.help_url,
44 | issue_url=constants.bugtracker_url,
45 | developers=[
46 | "0xMRTT https://github.com/0xMRTT",
47 | "Artyom Fomin https://github.com/ArtyIF",
48 | "Verantor https://github.com/Verantor",
49 | "tfuxu https://github.com/tfuxu",
50 | "u1F98E https://github.com/u1f98e"
51 | ],
52 | designers=[
53 | "David Lapshin https://github.com/daudix-UFO"
54 | ],
55 | translator_credits=_(translator_credits),
56 | copyright=_("Copyright © 2022-2023 Gradience Team"),
57 | license_type=Gtk.License.GPL_3_0,
58 | version=constants.version,
59 | release_notes_version=constants.rel_ver,
60 | )
61 |
62 | self.about_window.add_credit_section(
63 | _("Plugins by"),
64 | [
65 | _("Contributors on GitHub https://github.com/GradienceTeam/Plugins/graphs/contributors")
66 | ]
67 | )
68 | self.about_window.add_credit_section(
69 | _("Presets by"),
70 | [
71 | _("Contributors on GitHub https://github.com/GradienceTeam/Community/graphs/contributors")
72 | ]
73 | )
74 |
75 | def show_about(self):
76 | self.about_window.present()
77 |
--------------------------------------------------------------------------------
/gradience/frontend/views/meson.build:
--------------------------------------------------------------------------------
1 | viewsdir = 'gradience/frontend/views'
2 |
3 | gradience_sources = [
4 | '__init__.py',
5 | 'about_window.py',
6 | 'main_window.py',
7 | 'no_plugin_window.py',
8 | 'plugins_list.py',
9 | 'preferences_window.py',
10 | 'presets_manager_window.py',
11 | 'share_window.py',
12 | 'shell_prefs_window.py',
13 | 'welcome_window.py'
14 | ]
15 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: viewsdir)
16 |
--------------------------------------------------------------------------------
/gradience/frontend/views/no_plugin_window.py:
--------------------------------------------------------------------------------
1 | # no_plugin_window.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022-2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gtk, Adw
20 |
21 | from gradience.backend.constants import rootdir
22 |
23 |
24 | @Gtk.Template(resource_path=f"{rootdir}/ui/no_plugin_window.ui")
25 | class GradienceNoPluginPrefWindow(Adw.PreferencesWindow):
26 | __gtype_name__ = "GradienceNoPluginPrefWindow"
27 |
28 | def __init__(self, **kwargs):
29 | super().__init__(**kwargs)
30 |
--------------------------------------------------------------------------------
/gradience/frontend/views/shell_prefs_window.py:
--------------------------------------------------------------------------------
1 | # shell_prefs_window.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gtk, Adw
20 |
21 | from gradience.backend.utils.colors import rgb_to_hash
22 | from gradience.backend.constants import rootdir
23 |
24 | from gradience.frontend.widgets.option_row import GradienceOptionRow
25 | from gradience.frontend.schemas.shell_schema import shell_schema
26 |
27 | from gradience.backend.logger import Logger
28 |
29 | logging = Logger()
30 |
31 |
32 | @Gtk.Template(resource_path=f"{rootdir}/ui/shell_prefs_window.ui")
33 | class GradienceShellPrefsWindow(Adw.PreferencesWindow):
34 | __gtype_name__ = "GradienceShellPrefsWindow"
35 |
36 | custom_colors_group = Gtk.Template.Child("custom-colors-group")
37 |
38 | def __init__(self, parent, shell_colors: dict, **kwargs):
39 | super().__init__(**kwargs)
40 |
41 | self.shell_colors = shell_colors
42 |
43 | self.parent = parent
44 | self.settings = parent.settings
45 | self.app = self.parent.get_application()
46 |
47 | self.set_transient_for(self.app.get_active_window())
48 |
49 | self.setup()
50 |
51 | def setup(self):
52 | for variable in shell_schema["variables"]:
53 | pref_variable = GradienceOptionRow(
54 | variable["name"],
55 | variable["title"]
56 | #variable.get("explanation")
57 | )
58 | self.custom_colors_group.add(pref_variable)
59 |
60 | pref_variable.color_value.connect("color-set", self.on_color_value_changed, pref_variable)
61 | pref_variable.text_value.connect("changed", self.on_text_value_changed, pref_variable)
62 |
63 | self.set_colors(pref_variable, variable)
64 |
65 | def set_colors(self, widget, variable):
66 | if len(self.shell_colors) != len(shell_schema["variables"]):
67 | try:
68 | self.shell_colors[variable["name"]] = variable["default_value"]
69 | except KeyError:
70 | try:
71 | self.shell_colors[variable["name"]] = self.app.variables[variable["var_name"]]
72 | except KeyError:
73 | raise
74 | finally:
75 | widget.update_value(self.shell_colors[variable["name"]])
76 | else:
77 | widget.update_value(self.shell_colors[variable["name"]])
78 |
79 | def on_color_value_changed(self, widget, parent, *_args):
80 | color_name = parent.props.name
81 | color_value = widget.get_rgba().to_string()
82 |
83 | if color_value.startswith("rgb") or color_value.startswith("rgba"):
84 | color_hex, alpha = rgb_to_hash(color_value)
85 | if not alpha:
86 | color_value = color_hex
87 |
88 | self.shell_colors[color_name] = color_value
89 |
90 | def on_text_value_changed(self, widget, parent, *_args):
91 | color_name = parent.props.name
92 | color_value = widget.get_text()
93 |
94 | self.shell_colors[color_name] = color_value
95 |
--------------------------------------------------------------------------------
/gradience/frontend/widgets/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GradienceTeam/Gradience/f9651091eb80d9c16359598b7030b18c1ebce6c0/gradience/frontend/widgets/__init__.py
--------------------------------------------------------------------------------
/gradience/frontend/widgets/builtin_preset_row.py:
--------------------------------------------------------------------------------
1 | # builtin_preset_row.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022-2023 Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gtk, Adw
20 |
21 | from gradience.backend.utils.common import to_slug_case
22 | from gradience.backend.constants import rootdir
23 |
24 | from gradience.backend.logger import Logger
25 |
26 | logging = Logger()
27 |
28 |
29 | @Gtk.Template(resource_path=f"{rootdir}/ui/builtin_preset_row.ui")
30 | class GradienceBuiltinPresetRow(Adw.ActionRow):
31 | __gtype_name__ = "GradienceBuiltinPresetRow"
32 |
33 | def __init__(self, name, toast_overlay, author="", **kwargs):
34 | super().__init__(**kwargs)
35 |
36 | self.name = name
37 |
38 | self.set_name(name)
39 | self.set_title(name)
40 |
41 | self.app = Gtk.Application.get_default()
42 |
43 | self.toast_overlay = toast_overlay
44 |
45 | def show_unsaved_dialog(self, *_args):
46 | dialog, preset_entry = self.app.construct_unsaved_dialog()
47 |
48 | def on_unsaved_dialog_response(_widget, response, preset_entry):
49 | if response == "save":
50 | self.app.preset.save_to_file(preset_entry.get_text(), self.app.plugins_list)
51 | self.app.clear_dirty()
52 | self.app.load_preset_from_resource(
53 | f"{rootdir}/presets/" + to_slug_case(self.name) + ".json"
54 | )
55 | elif response == "discard":
56 | self.app.clear_dirty()
57 | self.app.load_preset_from_resource(
58 | f"{rootdir}/presets/" + to_slug_case(self.name) + ".json"
59 | )
60 |
61 | dialog.connect("response", on_unsaved_dialog_response, preset_entry)
62 |
63 | dialog.present()
64 |
65 | @Gtk.Template.Callback()
66 | def on_apply_button_clicked(self, *_args):
67 | logging.debug("apply")
68 |
69 | if self.app.is_dirty:
70 | self.show_unsaved_dialog()
71 | else:
72 | self.app.load_preset_from_resource(
73 | f"{rootdir}/presets/" + to_slug_case(self.name) + ".json"
74 | )
75 |
--------------------------------------------------------------------------------
/gradience/frontend/widgets/custom_css_group.py:
--------------------------------------------------------------------------------
1 | # custom_css_group.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022 Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gtk, Adw
20 |
21 | from gradience.backend.constants import rootdir
22 |
23 | from gradience.backend.logger import Logger
24 |
25 | logging = Logger()
26 |
27 |
28 | @Gtk.Template(resource_path=f"{rootdir}/ui/custom_css_group.ui")
29 | class GradienceCustomCSSGroup(Adw.PreferencesGroup):
30 | __gtype_name__ = "GradienceCustomCSSGroup"
31 |
32 | app_type_dropdown = Gtk.Template.Child("app_type_dropdown")
33 | custom_css_text_view = Gtk.Template.Child("custom_css_text_view")
34 |
35 | def __init__(self, parent, **kwargs):
36 | super().__init__(**kwargs)
37 |
38 | self.parent = parent
39 | self.app = self.parent.get_application()
40 |
41 | self.custom_css = {}
42 |
43 | def load_custom_css(self, custom_css):
44 | self.custom_css = custom_css
45 |
46 | self.custom_css_text_view.get_buffer().set_text(
47 | list(self.custom_css.values())[
48 | self.app_type_dropdown.get_selected()]
49 | )
50 |
51 | def reset_buffer(self):
52 | self.app.update_custom_css_text("gtk3", "")
53 | self.app.update_custom_css_text("gtk4", "")
54 |
55 | self.custom_css_text_view.get_buffer().set_text("")
56 |
57 | @Gtk.Template.Callback()
58 | def on_custom_css_changed(self, buffer):
59 | self.app.mark_as_dirty()
60 | self.app.update_custom_css_text(
61 | list(self.custom_css.keys())[
62 | self.app_type_dropdown.get_selected()],
63 | buffer.props.text
64 | )
65 |
66 | @Gtk.Template.Callback()
67 | def on_dropdown_notify(self, _unused, pspec):
68 | if pspec.name == "selected":
69 | logging.debug(f"Custom CSS values: {self.custom_css.values()}")
70 | logging.debug(f"Selected app type in dropdown: {self.app_type_dropdown.get_selected()}")
71 | self.custom_css_text_view.get_buffer().set_text(
72 | list(self.custom_css.values())[
73 | self.app_type_dropdown.get_selected()]
74 | )
75 |
--------------------------------------------------------------------------------
/gradience/frontend/widgets/error_list_row.py:
--------------------------------------------------------------------------------
1 | # error_list_row.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022 Adwaita Manager Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gtk
20 |
21 | from gradience.backend.constants import rootdir
22 |
23 |
24 | @Gtk.Template(resource_path=f"{rootdir}/ui/error_list_row.ui")
25 | class GradienceErrorListRow(Gtk.ListBoxRow):
26 | __gtype_name__ = "GradienceErrorListRow"
27 |
28 | error_label = Gtk.Template.Child("error-label")
29 | element_label = Gtk.Template.Child("element-label")
30 | line_label = Gtk.Template.Child("line-label")
31 |
32 | def __init__(self, error, element, line, **kwargs):
33 | super().__init__(**kwargs)
34 |
35 | self.error_label.set_label(error)
36 | self.element_label.set_label(element)
37 | self.line_label.set_label(line)
38 |
--------------------------------------------------------------------------------
/gradience/frontend/widgets/explore_preset_row.py:
--------------------------------------------------------------------------------
1 | # explore_preset_row.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022 Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | import os
20 | import json
21 |
22 | from gi.repository import GLib, Gtk, Adw
23 |
24 | from gradience.backend.utils.common import to_slug_case
25 | from gradience.backend.preset_downloader import PresetDownloader
26 | from gradience.backend.constants import rootdir
27 |
28 | from gradience.backend.logger import Logger
29 |
30 | logging = Logger()
31 |
32 |
33 | @Gtk.Template(resource_path=f"{rootdir}/ui/explore_preset_row.ui")
34 | class GradienceExplorePresetRow(Adw.ActionRow):
35 | __gtype_name__ = "GradienceExplorePresetRow"
36 |
37 | apply_button = Gtk.Template.Child("apply_button")
38 | download_button = Gtk.Template.Child("download_button")
39 | # badge = Gtk.Template.Child("badge")
40 |
41 | def __init__(self, name, url, win, repo_name, badge, **kwargs):
42 | super().__init__(**kwargs)
43 |
44 | self.name = name
45 |
46 | self.prefix = to_slug_case(repo_name)
47 |
48 | self.set_name(name)
49 | self.set_title(name)
50 | self.set_subtitle(repo_name)
51 |
52 | # self.badge.set_label(repo_name)
53 | # self.badge.get_style_context().add_class(f"badge-{badge}")
54 |
55 | self.app = Gtk.Application.get_default()
56 | self.win = win
57 | self.toast_overlay = self.win.toast_overlay
58 |
59 | self.url = url
60 |
61 | @Gtk.Template.Callback()
62 | def on_apply_button_clicked(self, *_args):
63 | try:
64 | PresetDownloader().download_preset(to_slug_case(self.name), self.prefix, self.url)
65 | except (GLib.GError, json.JSONDecodeError, OSError):
66 | logging.error("An error occurred while trying to download a preset.")
67 | self.toast_overlay.add_toast(
68 | Adw.Toast(title=_("Preset could not be downloaded"))
69 | )
70 | else:
71 | self.app.load_preset_from_file(
72 | os.path.join(
73 | os.environ.get("XDG_CONFIG_HOME",
74 | os.environ["HOME"] + "/.config"),
75 | "presets",
76 | self.prefix,
77 | to_slug_case(self.name) + ".json",
78 | )
79 | )
80 |
81 | self.toast_overlay.add_toast(
82 | Adw.Toast(title=_("Preset downloaded")))
83 | self.win.reload_pref_group()
84 |
85 | logging.debug("Apply and download completed")
86 |
87 | @Gtk.Template.Callback()
88 | def on_download_button_clicked(self, *_args):
89 | try:
90 | PresetDownloader().download_preset(to_slug_case(self.name), self.prefix, self.url)
91 | except (GLib.GError, json.JSONDecodeError, OSError):
92 | logging.error("An error occurred while trying to download a preset.")
93 | self.toast_overlay.add_toast(
94 | Adw.Toast(title=_("Preset could not be downloaded"))
95 | )
96 | else:
97 | self.toast_overlay.add_toast(
98 | Adw.Toast(title=_("Preset downloaded")))
99 | self.win.reload_pref_group()
100 | logging.debug("Download completed")
101 |
--------------------------------------------------------------------------------
/gradience/frontend/widgets/meson.build:
--------------------------------------------------------------------------------
1 | widgetsdir = 'gradience/frontend/widgets'
2 |
3 | gradience_sources = [
4 | '__init__.py',
5 | 'builtin_preset_row.py',
6 | 'custom_css_group.py',
7 | 'error_list_row.py',
8 | 'explore_preset_row.py',
9 | 'monet_theming_group.py',
10 | 'option_row.py',
11 | 'palette_shades.py',
12 | 'plugin_row.py',
13 | 'preset_row.py',
14 | 'repo_row.py',
15 | 'reset_preset_group.py',
16 | 'shell_theming_group.py',
17 | 'theming_empty_group.py',
18 | ]
19 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: widgetsdir)
20 |
--------------------------------------------------------------------------------
/gradience/frontend/widgets/palette_shades.py:
--------------------------------------------------------------------------------
1 | # palette_shades.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022 Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import Gtk, Gdk, Adw
20 |
21 | from gradience.backend.constants import rootdir
22 |
23 |
24 | @Gtk.Template(resource_path=f"{rootdir}/ui/palette_shades.ui")
25 | class GradiencePaletteShades(Adw.ActionRow):
26 | __gtype_name__ = "GradiencePaletteShades"
27 |
28 | def __init__(self, prefix, color_title, n_shades, **kwargs):
29 | super().__init__(**kwargs)
30 |
31 | self.prefix = prefix
32 | self.set_name(prefix + "shades")
33 | self.set_title(color_title)
34 | self.set_subtitle("@" + prefix + "[1, " + str(n_shades) + "]")
35 |
36 | self.color_pickers = {}
37 | for i in range(1, n_shades + 1):
38 | picker = Gtk.ColorButton()
39 | picker.set_name(prefix + str(i))
40 | picker.set_rgba(Gdk.RGBA(red=0, green=0, blue=0, alpha=0))
41 | picker.set_valign(Gtk.Align.CENTER)
42 | picker.connect("color-set", self.on_color_changed)
43 | self.color_pickers[str(i)] = picker
44 | self.add_suffix(picker)
45 |
46 | def on_color_changed(self, *_args):
47 | shades = {}
48 | for picker_key, picker in self.color_pickers.items():
49 | shades[picker_key] = picker.get_rgba().to_string()
50 | self.update_shades(shades, update_from="color_value")
51 |
52 | def update_shades(self, shades, **kwargs):
53 | for i in range(1, len(shades) + 1):
54 | new_rgba = Gdk.RGBA()
55 | if new_rgba.parse(shades[str(i)]):
56 | self.color_pickers[str(i)].set_rgba(new_rgba)
57 | self.color_pickers[str(i)].set_tooltip_text(shades[str(i)])
58 | if (
59 | Gtk.Application.get_default().is_ready
60 | and kwargs.get("update_from") == "color_value"
61 | ):
62 | Gtk.Application.get_default().palette[self.prefix][str(i)] = shades[
63 | str(i)
64 | ]
65 |
66 | if (
67 | Gtk.Application.get_default().is_ready
68 | and kwargs.get("update_from") == "color_value"
69 | ):
70 | Gtk.Application.get_default().mark_as_dirty()
71 | Gtk.Application.get_default().reload_variables()
72 |
--------------------------------------------------------------------------------
/gradience/frontend/widgets/plugin_row.py:
--------------------------------------------------------------------------------
1 | # plugin_row.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022-2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | import os
20 |
21 | from gi.repository import Gtk, Adw
22 |
23 | from gradience.frontend.views.no_plugin_window import GradienceNoPluginPrefWindow
24 | from gradience.backend.globals import user_plugin_dir
25 | from gradience.backend.constants import rootdir
26 |
27 | from gradience.backend.logger import Logger
28 |
29 | logging = Logger()
30 |
31 |
32 | @Gtk.Template(resource_path=f"{rootdir}/ui/plugin_row.ui")
33 | class GradiencePluginRow(Adw.ActionRow):
34 | __gtype_name__ = "GradiencePluginRow"
35 |
36 | switch = Gtk.Template.Child("switch")
37 | settings_button = Gtk.Template.Child("settings-button")
38 | remove_button = Gtk.Template.Child("remove-button")
39 |
40 | def __init__(self, plugin_object, preset, plugins_list, **kwargs):
41 | super().__init__(**kwargs)
42 |
43 | self.plugins_list = plugins_list
44 |
45 | self.plugin_object = plugin_object
46 | if not os.path.exists(
47 | os.path.join(
48 | user_plugin_dir,
49 | f"{self.plugin_object.plugin_id}.yapsy-plugin"
50 | )
51 | ):
52 | self.remove_button.set_visible(False)
53 |
54 | self.set_name(plugin_object.plugin_id)
55 | self.set_title(plugin_object.title)
56 | self.set_subtitle("@" + plugin_object.plugin_id)
57 |
58 | self.enabled_plugins = self.plugins_list.enabled_plugins
59 | if self.plugin_object.plugin_id in self.enabled_plugins:
60 | self.switch.set_active(True)
61 |
62 | self.give_preset_settings(preset)
63 |
64 | @Gtk.Template.Callback()
65 | def on_settings_plugin_clicked(self, *_args):
66 | has_setting = self.plugin_object.open_settings()
67 | if not has_setting:
68 | win = GradienceNoPluginPrefWindow()
69 | win.set_transient_for(self.plugins_list.win)
70 | win.present()
71 |
72 | @Gtk.Template.Callback()
73 | def on_remove_plugin_clicked(self, *_args):
74 | plugin_yapsy_file = (
75 | os.path.join(
76 | user_plugin_dir,
77 | f"{self.plugin_object.plugin_id}.yapsy-plugin"
78 | )
79 | )
80 | logging.debug(f"remove {plugin_yapsy_file}")
81 | try:
82 | os.remove(plugin_yapsy_file)
83 | except FileNotFoundError:
84 | error_dialog = Adw.MessageDialog(
85 | heading=_("Unable to remove"),
86 | body=_("This is a system plugin, and cannot be removed."),
87 | )
88 | error_dialog.add_response("close", _("Close"))
89 | error_dialog.present()
90 | logging.debug(f"remove {plugin_yapsy_file}")
91 | Gtk.Application.get_default().reload_plugins()
92 |
93 | @Gtk.Template.Callback()
94 | def on_switch_toggled(self, *_args):
95 | if self.switch.get_active():
96 | self.plugins_list.enable_plugin(self.plugin_object.plugin_id)
97 | else:
98 | self.plugins_list.disable_plugin(self.plugin_object.plugin_id)
99 |
100 | def give_preset_settings(self, preset_settings):
101 | self.preset_settings = preset_settings
102 | self.plugin_object.give_preset_settings(preset_settings)
103 |
--------------------------------------------------------------------------------
/gradience/frontend/widgets/repo_row.py:
--------------------------------------------------------------------------------
1 | # repo_row.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022 Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | import os
20 |
21 | from gi.repository import Gtk, Adw
22 |
23 | from gradience.backend.constants import rootdir
24 | from gradience.backend.utils.common import to_slug_case
25 |
26 |
27 | @Gtk.Template(resource_path=f"{rootdir}/ui/repo_row.ui")
28 | class GradienceRepoRow(Adw.ActionRow):
29 | __gtype_name__ = "GradienceRepoRow"
30 |
31 | remove_button = Gtk.Template.Child("remove_button")
32 |
33 | def __init__(self, repo, repo_name, win, deletable=True, **kwargs):
34 | super().__init__(**kwargs)
35 |
36 | self.name = repo_name
37 |
38 | self.set_name(repo_name)
39 | self.set_title(repo_name)
40 | self.set_subtitle(repo)
41 |
42 | self.app = Gtk.Application.get_default()
43 | self.win = win
44 | self.toast_overlay = self.win.toast_overlay
45 |
46 | if not deletable:
47 | self.remove_button.set_visible(False)
48 |
49 | self.path = os.path.join(
50 | os.environ.get("XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"),
51 | "presets",
52 | to_slug_case(repo_name),
53 | )
54 |
55 | if not os.path.exists(self.path):
56 | os.makedirs(self.path)
57 |
58 | @Gtk.Template.Callback()
59 | def on_remove_button_clicked(self, *_args):
60 | self.toast_overlay.add_toast(Adw.Toast(title=_("Repository removed")))
61 |
62 | self.win.remove_repo(self.name)
63 |
64 | self.win.reload_repos_group()
65 |
--------------------------------------------------------------------------------
/gradience/frontend/widgets/reset_preset_group.py:
--------------------------------------------------------------------------------
1 | # reset_preset_group.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from gi.repository import GLib, Gtk, Adw
20 |
21 | from gradience.backend.constants import rootdir
22 | from gradience.backend.logger import Logger
23 | from gradience.backend.theming.preset import PresetUtils
24 |
25 | logging = Logger()
26 |
27 |
28 | @Gtk.Template(resource_path=f"{rootdir}/ui/reset_preset_group.ui")
29 | class GradienceResetPresetGroup(Adw.PreferencesGroup):
30 | __gtype_name__ = "GradienceResetPresetGroup"
31 |
32 | def __init__(self, parent, **kwargs):
33 | super().__init__(**kwargs)
34 |
35 | self.parent = parent
36 |
37 | self.app = self.parent.get_application()
38 | self.win = self.parent
39 |
40 | self.setup_signals()
41 | self.setup()
42 |
43 | def setup_signals(self):
44 | pass
45 |
46 | def setup(self):
47 | pass
48 |
49 | @Gtk.Template.Callback()
50 | def on_libadw_restore_button_clicked(self, *_args):
51 | try:
52 | PresetUtils().restore_preset("gtk4")
53 | except GLib.GError:
54 | self.parent.add_toast(
55 | Adw.Toast(title=_("Unable to restore GTK 4 backup"))
56 | )
57 | else:
58 | toast = Adw.Toast(
59 | title=_("GTK 4 preset has been restored. Log out to apply changes."),
60 | )
61 | self.parent.add_toast(toast)
62 |
63 | @Gtk.Template.Callback()
64 | def on_libadw_reset_button_clicked(self, *_args):
65 | try:
66 | PresetUtils().reset_preset("gtk4")
67 | except GLib.GError:
68 | self.parent.add_toast(
69 | Adw.Toast(title=_("Unable to delete current preset"))
70 | )
71 | else:
72 | toast = Adw.Toast(
73 | title=_("GTK 4 theme has been reset. Log out to apply changes."),
74 | )
75 | self.parent.add_toast(toast)
76 |
77 |
78 | @Gtk.Template.Callback()
79 | def on_gtk3_restore_button_clicked(self, *_args):
80 | try:
81 | PresetUtils().restore_preset("gtk3")
82 | except GLib.GError:
83 | self.parent.add_toast(
84 | Adw.Toast(title=_("Unable to restore GTK 3 backup"))
85 | )
86 | else:
87 | toast = Adw.Toast(
88 | title=_("GTK 3 preset has been restored. Log out to apply changes."),
89 | )
90 | self.parent.add_toast(toast)
91 |
92 | @Gtk.Template.Callback()
93 | def on_gtk3_reset_button_clicked(self, *_args):
94 | try:
95 | PresetUtils().reset_preset("gtk3")
96 | except GLib.GError:
97 | self.parent.add_toast(
98 | Adw.Toast(title=_("Unable to delete current preset"))
99 | )
100 | else:
101 | toast = Adw.Toast(
102 | title=_("GTK 3 theme has been reset. Log out to apply changes."),
103 | )
104 | self.parent.add_toast(toast)
105 |
--------------------------------------------------------------------------------
/gradience/frontend/widgets/theming_empty_group.py:
--------------------------------------------------------------------------------
1 | # theming_empty_group.py
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2023, Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | from enum import Enum
20 |
21 | from gi.repository import Adw, Gio, GLib, Gtk
22 |
23 | from gradience.backend.constants import rootdir
24 | from gradience.backend.exceptions import UnsupportedShellVersion
25 | from gradience.backend.logger import Logger
26 | from gradience.backend.theming.shell import ShellTheme
27 |
28 | from gradience.frontend.views.shell_prefs_window import GradienceShellPrefsWindow
29 |
30 | logging = Logger()
31 |
32 |
33 | @Gtk.Template(resource_path=f"{rootdir}/ui/theming_empty_group.ui")
34 | class GradienceEmptyThemingGroup(Adw.PreferencesGroup):
35 | __gtype_name__ = "GradienceEmptyThemingGroup"
36 |
37 | def __init__(self, parent, **kwargs):
38 | super().__init__(**kwargs)
39 |
40 | self.parent = parent
41 | self.settings = parent.settings
42 | self.app = self.parent.get_application()
43 |
44 | self.setup_signals()
45 | self.setup()
46 |
47 | def setup_signals(self):
48 | pass
49 |
50 | def setup(self):
51 | pass
52 |
--------------------------------------------------------------------------------
/gradience/meson.build:
--------------------------------------------------------------------------------
1 | moduledir = 'gradience'
2 |
3 | subdir('backend')
4 | subdir('frontend')
5 |
6 | gradience_sources = [
7 | '__init__.py'
8 | ]
9 | PY_INSTALLDIR.install_sources(gradience_sources, subdir: moduledir)
10 |
--------------------------------------------------------------------------------
/local.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/bash
2 |
3 | # local.sh
4 | #
5 | # Change the look of Adwaita, with ease
6 | # Copyright (C) 2022 Gradience Team
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | read -p "Do you want to install Python requirements? [N/y] " answer
22 |
23 | if [[ "$answer" == "y" ]]; then
24 | pip3 install -r requirements.txt
25 | elif [[ "$answer" == "n" || "$answer" == "" ]]; then
26 | echo "Skipping requirements installation"
27 | fi
28 |
29 | echo "Cleaning builddir directory"
30 | rm -r builddir
31 |
32 | echo "Rebuilding"
33 | meson setup builddir
34 | meson configure builddir -Dprefix="$(pwd)/builddir" -Dbuildtype=debug
35 | ninja -C builddir install
36 |
37 | echo "Running"
38 | ninja -C builddir run
39 |
--------------------------------------------------------------------------------
/local_cli.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/bash
2 |
3 | # local_cli.sh
4 | #
5 | # Change the look of Adwaita, with ease
6 | # Copyright (C) 2022 Gradience Team
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | python builddir/gradience/frontend/local-gradience-cli "$@"
22 |
--------------------------------------------------------------------------------
/meson.build:
--------------------------------------------------------------------------------
1 | project('gradience',
2 | version: '0.8.0-beta2',
3 | meson_version: '>= 0.59.0',
4 | default_options: [ 'warning_level=2',
5 | 'werror=false',
6 | ],
7 | )
8 |
9 | # Import modules
10 | gnome = import('gnome')
11 | i18n = import('i18n')
12 | python = import('python')
13 |
14 | # Project information
15 | PROJECT_URL = 'https://github.com/GradienceTeam/Gradience'
16 | BUGTRACKER_URL = 'https://github.com/GradienceTeam/Gradience/issues'
17 | HELP_URL = 'https://github.com/GradienceTeam/Gradience/discussions'
18 | TRANSLATE_URL = 'https://hosted.weblate.org/projects/GradienceTeam/gradience'
19 |
20 | # Constants
21 | PROJECT_RDNN_NAME = 'com.github.GradienceTeam.Gradience'
22 |
23 | git_bin = find_program('git', required: false)
24 |
25 | # Set APPLICATION_ID and VERSION_SUFFIX
26 | if get_option('buildtype') == 'debug'
27 | if git_bin.found()
28 | VCS_TAG = run_command('git', 'rev-parse', '--short', 'HEAD', check: true).stdout().strip()
29 | else
30 | VCS_TAG = ''
31 | endif
32 | if VCS_TAG == ''
33 | VERSION_SUFFIX = '-devel'
34 | else
35 | VERSION_SUFFIX = '-@0@'.format(VCS_TAG)
36 | endif
37 | APPLICATION_ID = '@0@.Devel'.format(PROJECT_RDNN_NAME)
38 | else
39 | VERSION_SUFFIX = ''
40 | APPLICATION_ID = PROJECT_RDNN_NAME
41 | endif
42 |
43 | dependency('glib-2.0')
44 | dependency('gtk4', version: '>= 4.5.0')
45 | dependency('libadwaita-1', version: '>= 1.2.alpha')
46 | dependency('pygobject-3.0', version: '>= 3.42.0')
47 | dependency('libsoup-3.0', version: '>= 3.2.0')
48 |
49 | # Python installation directory
50 | PY_INSTALLDIR = python.find_installation('python3', required: true, modules: ['lxml'])
51 |
52 | # Check if python3 is installed
53 | if not PY_INSTALLDIR.found()
54 | error('No valid python3 binary found')
55 | endif
56 |
57 | PKGDATA_DIR = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name())
58 | MODULE_DIR = join_paths(PKGDATA_DIR, 'gradience')
59 | PLUGINS_DIR = join_paths(PKGDATA_DIR, 'gradience', 'plugins')
60 |
61 | # Install configuration data
62 | conf = configuration_data()
63 | conf.set('APP_ID', APPLICATION_ID)
64 | conf.set('PKGDATA_DIR', PKGDATA_DIR)
65 | conf.set('DATA_DIR', join_paths(get_option('prefix'), get_option('datadir')))
66 | conf.set('LOCALE_DIR', join_paths(get_option('prefix'), get_option('localedir')))
67 | conf.set('PYTHON', PY_INSTALLDIR.full_path())
68 | conf.set('VERSION', meson.project_version() + VERSION_SUFFIX)
69 | conf.set('BUILD_TYPE', get_option('buildtype'))
70 | conf.set('SCHEMAS_DIR', PKGDATA_DIR)
71 | conf.set('SOURCE_DIR', meson.current_source_dir())
72 | conf.set('BUILD_DIR', meson.current_build_dir())
73 |
74 | conf.set('local_build', 'False')
75 |
76 | # Local install configuration data
77 | local_conf = configuration_data()
78 | local_conf.set('APP_ID', APPLICATION_ID)
79 | local_conf.set('PKGDATA_DIR', join_paths(meson.current_build_dir(), 'data'))
80 | local_conf.set('LOCALE_DIR', join_paths(get_option('prefix'), get_option('datadir'), 'locale'))
81 | local_conf.set('PYTHON', meson.current_source_dir())
82 | local_conf.set('VERSION', meson.project_version() + VERSION_SUFFIX)
83 | local_conf.set('BUILD_TYPE', get_option('buildtype'))
84 | local_conf.set('SCHEMAS_DIR', join_paths(meson.current_build_dir(), get_option('datadir')))
85 | local_conf.set('SOURCE_DIR', meson.current_source_dir())
86 | local_conf.set('BUILD_DIR', meson.current_build_dir())
87 |
88 | local_conf.set('local_build', 'True')
89 |
90 | # Subdirs
91 | subdir('gradience')
92 | subdir('data')
93 | subdir('po')
94 |
95 | gnome.post_install(
96 | glib_compile_schemas: true,
97 | gtk_update_icon_cache: true,
98 | update_desktop_database: true,
99 | )
100 |
--------------------------------------------------------------------------------
/po/LINGUAS:
--------------------------------------------------------------------------------
1 | ar
2 | cs
3 | de
4 | es
5 | eu
6 | fi
7 | fr
8 | hr
9 | id
10 | it
11 | ko
12 | nl
13 | oc
14 | pl
15 | pt_BR
16 | ru
17 | sv
18 | ta
19 | tr
20 | zh_Hans
21 | ro
22 | az
23 | sr
24 | uk
25 | pt
26 | hi
27 | he
28 |
--------------------------------------------------------------------------------
/po/POTFILES:
--------------------------------------------------------------------------------
1 | data/com.github.GradienceTeam.Gradience.appdata.xml.in.in
2 | data/com.github.GradienceTeam.Gradience.desktop.in.in
3 | data/com.github.GradienceTeam.Gradience.gschema.xml.in
4 | data/ui/app_type_dialog.blp
5 | data/ui/builtin_preset_row.blp
6 | data/ui/custom_css_group.blp
7 | data/ui/explore_preset_row.blp
8 | data/ui/help_overlay.blp
9 | data/ui/log_out_dialog.blp
10 | data/ui/monet_theming_group.blp
11 | data/ui/no_plugin_window.blp
12 | data/ui/option_row.blp
13 | data/ui/plugin_row.blp
14 | data/ui/preferences_window.blp
15 | data/ui/preset_row.blp
16 | data/ui/presets_manager_window.blp
17 | data/ui/repo_row.blp
18 | data/ui/reset_preset_group.blp
19 | data/ui/save_dialog.blp
20 | data/ui/share_window.blp
21 | data/ui/shell_prefs_window.blp
22 | data/ui/shell_theming_group.blp
23 | data/ui/theming_empty_group.blp
24 | data/ui/welcome_window.blp
25 | data/ui/window.blp
26 | gradience/backend/flatpak_overrides.py
27 | gradience/frontend/dialogs/app_type_dialog.py
28 | gradience/frontend/dialogs/save_dialog.py
29 | gradience/frontend/dialogs/unsupported_shell_dialog.py
30 | gradience/frontend/main.py
31 | gradience/frontend/schemas/preset_schema.py
32 | gradience/frontend/schemas/shell_schema.py
33 | gradience/frontend/views/about_window.py
34 | gradience/frontend/views/main_window.py
35 | gradience/frontend/views/plugins_list.py
36 | gradience/frontend/views/presets_manager_window.py
37 | gradience/frontend/views/welcome_window.py
38 | gradience/frontend/widgets/explore_preset_row.py
39 | gradience/frontend/widgets/monet_theming_group.py
40 | gradience/frontend/widgets/option_row.py
41 | gradience/frontend/widgets/plugin_row.py
42 | gradience/frontend/widgets/preset_row.py
43 | gradience/frontend/widgets/repo_row.py
44 | gradience/frontend/widgets/reset_preset_group.py
45 | gradience/frontend/widgets/shell_theming_group.py
46 |
--------------------------------------------------------------------------------
/po/meson.build:
--------------------------------------------------------------------------------
1 | i18n.gettext(meson.project_name(), preset: 'glib')
2 |
--------------------------------------------------------------------------------
/po/update_linguas.py:
--------------------------------------------------------------------------------
1 | # Change the look of Adwaita, with ease
2 | # Copyright (C) 2022 Gradience Team
3 | #
4 | # This program is free software: you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation, either version 3 of the License, or
7 | # (at your option) any later version.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License
15 | # along with this program. If not, see .
16 |
17 |
18 | import os
19 |
20 |
21 | def list_po():
22 | files = []
23 | for _, _, filenames in os.walk("po"):
24 | for file in filenames:
25 | if file.endswith(".po"):
26 | files.append(file.strip(".po"))
27 | return files
28 |
29 |
30 | with open("LINGUAS", "w") as file:
31 | po = "\n".join(list_po())
32 | file.write(po)
33 |
--------------------------------------------------------------------------------
/po/update_potfile.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | po_dir=$(dirname "$(realpath "$0")")
3 | xgettext -f "$po_dir"/POTFILES -o "$po_dir"/Gradience.pot --add-comments=Translators --keyword=_ --keyword=C_1c,2 --from-code=UTF-8
4 | sed -i "s/SOME DESCRIPTIVE TITLE./Gradience POT file/" "$po_dir"/Gradience.pot
5 | sed -i "s/YEAR THE PACKAGE'S COPYRIGHT HOLDER/$(date +%Y) Gradience Team/" "$po_dir"/Gradience.pot
6 | sed -i "s@same license as the PACKAGE package.@GNU GPLv3 license.@" "$po_dir"/Gradience.pot
7 | sed -i "s/FIRST AUTHOR , YEAR./Gradience Team, $(date +%Y)./" "$po_dir"/Gradience.pot
8 |
9 | regex="$po_dir/([a-zA-Z_]*).po"
10 | find "$po_dir" -type f -name "*.po" | sed -rn "s:$regex:\1:p" > "$po_dir/LINGUAS"
11 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # requirements.txt
2 | #
3 | # Change the look of Adwaita, with ease
4 | # Copyright (C) 2022 Gradience Team
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program. If not, see .
18 |
19 | # After changing this file, download the flatpak pip generator script:
20 | # curl -O https://raw.githubusercontent.com/flatpak/flatpak-builder-tools/master/pip/flatpak-pip-generator
21 | # chmod +x flatpak-pip-generator
22 | # Then run:
23 | # ./flatpak-pip-generator --requirements-file=requirements.txt --output pypi-dependencies
24 | # And move output file to build-aux directory:
25 | # mv pypi-dependencies.json build-aux/flatpak/
26 | #
27 | # or more simply, just push and the bot will do this for you.
28 |
29 | anyascii
30 | material-color-utilities-python
31 | svglib
32 | yapsy
33 | Jinja2
34 | libsass
--------------------------------------------------------------------------------
/typos.toml:
--------------------------------------------------------------------------------
1 | [type.po]
2 | extend-glob = ["*.po"]
3 | check-file = false
4 |
5 | [type.svg]
6 | extend-glob = ["*.svg"]
7 | check-file = false
8 |
--------------------------------------------------------------------------------