59 Commits

Author SHA1 Message Date
05cce6540f Changelog 2024-08-08 20:09:03 +02:00
193501a9e7 Readme, PO 2024-08-08 19:44:42 +02:00
900b1f197e Three new image sets 2024-08-08 19:30:43 +02:00
fb91bd3b30 Switch from libheif to imagemagick, fix #23 2024-08-08 18:41:08 +02:00
8b9a708cb4 Bugfix if wallpaper time change between 23:00 and midnight 2024-07-07 19:35:20 +02:00
6afc62a87f Readme with Troubleshooting section, updated translations from linuxmint/cinnamon-spices-extensions 2024-07-07 17:35:43 +02:00
d4cc8f2616 Backing up and restore the slick-greeter file 2024-02-15 20:27:23 +01:00
333bb3b995 Hungarian translation, move current login image to usr/share/pixmaps 2024-02-15 19:58:53 +01:00
77db85cc71 Bugfix for locations near the dateline 2024-02-15 18:31:32 +01:00
1c6060d8d5 Small fixes, changlelog 2024-02-15 17:34:07 +01:00
TobiZog
8da056350a Merge pull request #16 from blogdron/main
Add Russian translation
2024-02-15 17:24:25 +01:00
0ab3297054 Adding support for Login screen wallpaper 2024-02-15 17:04:20 +01:00
blogdron
6ac34770ff Add Russian translation 2024-02-15 16:46:46 +03:00
45e95d0e2b Readme 2024-02-15 13:20:59 +01:00
d2d954b25f Small fix 2024-02-12 12:17:33 +01:00
72144f76c6 Bugfixes, translation 2024-02-12 12:15:45 +01:00
755664230a Adding dutch, german and spanish (rcalixte) translation 2024-02-11 19:34:58 +01:00
aae46e4b1e Readme 2024-02-04 16:11:31 +01:00
14497e21f2 Changelog, Readme, dynamic background example image 2024-02-04 16:08:05 +01:00
34e44f4b3c Observer pattern, Bugfixes 2024-02-04 14:45:12 +01:00
53f5984eb5 MVVM pattern finished, adding multiple location provider 2024-02-02 19:56:14 +01:00
8acc18c7fe Start migration to MVVM 2024-02-02 15:30:33 +01:00
fe1cea9e2b Metadata/Readme for release of 2.1 2024-01-26 18:56:12 +01:00
0bf78c54d0 Bugfix 2024-01-26 18:52:51 +01:00
8a58e66c20 Bugfixes, Smaller UI for displays with reduced resolution 2024-01-23 18:11:13 +01:00
f9a84b18e8 Bugfix, Readme 2024-01-18 20:03:43 +01:00
c53c149d31 New image set (earth), refresh all image sets 2024-01-17 22:23:12 +01:00
17348f7acf Documentation, cleanup 2024-01-17 20:53:18 +01:00
e1b464e36c HEIC import 2024-01-17 20:04:12 +01:00
d97ec091c5 Bugfixes, exchange file chooser button 2024-01-17 19:09:37 +01:00
af63b5ad43 Bugfixes, Readme 2024-01-16 18:14:13 +01:00
3636e3ffac Remove HEIC option for beta release 2024-01-16 17:01:36 +01:00
c04ec20704 Adding OK button, bugfixes 2024-01-16 11:46:36 +01:00
506bb45dda Bugfix 2024-01-14 20:22:44 +01:00
4a4cc9f778 Rewrite preference system 2024-01-14 19:26:33 +01:00
20223b21de Calculating dynamic background gradient, option to stretch image 2024-01-14 15:32:45 +01:00
66e4023b7a HEIC import, reimplement image change system 2024-01-04 19:13:53 +01:00
22920ad712 Load images from source folder to preview 2024-01-04 15:42:11 +01:00
513cb38154 Load preview images on ComboBox changes 2024-01-03 22:47:53 +01:00
14f6548ce7 Documentation 2024-01-03 21:28:24 +01:00
12cd81bf65 Connect image set selection in preferences 2024-01-03 21:13:28 +01:00
1833399aaa Rewrite suntimes.py 2024-01-02 22:11:51 +01:00
4e1da62b90 Adding custom times configuration with live bar chart (#5) 2023-12-26 23:13:43 +01:00
a0fe24bbd1 Improve cinnamon preferences storage & load system 2023-12-26 16:39:31 +01:00
ccaf08e238 Get and display location to the preference UI 2023-12-26 15:29:27 +01:00
1a8a986674 Converting Python scripts to classes 2023-12-25 20:22:31 +01:00
7c5e86e8dc Bind settings window to Cinnamon Spiced pref button 2023-12-23 14:02:31 +01:00
132b33bdf8 New icon, README + CHANGELOG enhanced 2023-12-23 01:42:43 +01:00
0cfe14feed Documentation, change two colors of bar graph 2023-12-22 23:51:09 +01:00
f843e01847 New time period calculation system, bind it also to the UI 2023-12-22 23:20:39 +01:00
d21557b0f1 Read/Write system for Cinnamon preference file 2023-12-21 12:17:12 +01:00
6a997e4945 Preferences UI 2023-12-21 10:31:53 +01:00
d88a21c6f0 New source selection buttons 2023-12-16 05:00:11 +01:00
edc1e62ff3 Migrate time circle to time bar 2023-12-10 00:11:28 +01:00
f087c18ab1 Start preferences redesign 2023-10-12 00:23:56 +02:00
a5b9da3f34 Cleanup 2023-08-25 20:41:47 +02:00
d433ab579d Display period times in Image Configurator, Changelog 2023-08-25 19:55:39 +02:00
78a925ff8a Bugfixes 2023-08-25 19:26:10 +02:00
5ca5b76d7c Log file system implemented 2023-08-25 17:41:42 +02:00
214 changed files with 11710 additions and 1978 deletions

9
.gitignore vendored
View File

@@ -1,7 +1,10 @@
*.glade~
*.glade#
extracted/
custom_images/
*.txt
*.json
*.tar.gz
extracted_images/
selected/
__pycache__
__pycache__
time_bar.svg
time_bar_polylines.svg

View File

@@ -1,3 +1,45 @@
# Version 2.5
- Switch from libheif to imagemagick, HEIC conversion is now possible on Arch and Fedora!
- Three new image sets: desert, island, lake
# Version 2.4
- Adding Login window support
- Adding Russian translation (Thanks to blogdron)
- Adding Hungarian translation (Thanks to vajdao)
- Bugfix: Time period calculation on locations near the dateline, like Japan
# Version 2.3
- Adding Dutch translation
- Adding German translation
- Adding Spanish translation (Thanks to haggen88)
# Version 2.2
- Bugfixes
- Migrate code to MVVM pattern
- Adding option to change the location provider
- Adding example image for dynamic background color
# Version 2.1
- Bugfixes
- Smaller UI for displays with reduced resolution (< 1000px height)
# Version 2.0
- New App icon
- Preferences window redesign - All settings are now in one window accessable!
- Graphic visualizing of the time periods of a day with a bar chart
- Adding custom time periods by user choice
- Adding folder as image source
- Option to display image on lock screens
- Bugfixes
- Remove support for Cinnamon 5.2 and older
- Apply and OK button to test settings without closing the window
# Version 1.4
- Log System
- Bugfixes
- Display times in Image Configurator
- Display time of last location update in Preferences
# Version 1.3
- Adding option to stretch the image over multiple displays

110
README.md
View File

@@ -1,35 +1,40 @@
# Cinnamon Dynamic Wallpaper
<img src="cinnamon-dynamic-wallpaper@TobiZog/5.4/res/icons/icon.svg" alt="drawing" width="200" style="margin-left:auto; margin-right:auto; width:50%; display:block"/>
![](res/wallpaper_merged.jpg)
## About the project
Based on a location, this extension calculates the periods of a day and switches the background image of your Cinnamon desktop. The extension offers the choice between a set of included wallpapers or to select a HEIC-file.
This extension switches the background image of your Cinnamon desktop multiple times in a day, based on a location or custom time periods. You can choose between included image-sets, your own HEIC-file or a source folder with single images. Configuration through a user-friendly configuration window.
### Features
- 8 included image sets
- 9 day periods
- 12 included image sets
- 10 day periods
- HEIF converter
- Image configuration assistent with simple one-click setup for image choose
- Online location estimation or offline with manual latitude and longitude input
- Image configuration assistent with simple one-click setup for image choices
- Online location estimation (three provider) or offline with manual latitude and longitude input
- Time periods individual configured by user
- Offline sun angles estimation
- Image stretching over multiple displays or repeat image for every display
- Creating a color gradient based on the current wallpaper for images which not fill the whole screen
### Tested Cinnamon versions
- 4.8 (Mint 20.1)
- 5.0 (Mint 20.2)
- 5.2 (Mint 20.3)
- 5.4 (Mint 21)
- 5.6 (Mint 21.1)
- 5.8 (Mint 21.2)
- 6.0 (Mint 21.3)
- 6.2 (Mint 22)
### Technology
- Using `JavaScript` for
- Sun angle estimation
- Location estimation
- Change of the desktop wallpapers
- `Python` displays the Image Configurator
- Image Configurator UI was written with `Glade`
- `JavaScript`
- Display desktop notifications
- Calling the Python loop script every 60 seconds to refresh the background image
- `Python`
- Handles the preference window
- Esimates the location
- Changes of the desktop wallpapers
- `Glade`
- Preference window UI design
---
## Installation
### From Built-in Extension Manager
![](res/download-manager.png)
@@ -39,33 +44,78 @@ Based on a location, this extension calculates the periods of a day and switches
3. Search and download it
### From the repo
1. Download the Repository
1. Download the latest from the Releases page on GitHub: https://github.com/TobiZog/cinnamon-dynamic-wallpaper/releases
2. Extract the files
3. Copy the folder `cinnamon-dynamic-wallpaper@TobiZog` to `~/.local/share/cinnamon/extensions/`
## How to use it
---
## Usage
1. Active the Extension via Cinnamon Extension Manager
2. Open the settings
3. Keep `Estimate coordinates via network` active or disable it and insert latitude and longitude in the fields
4. Choose a set of images or disable it and select for every daytime an image manually
## Image Configurator
The Cinnamon Dynamic Wallpaper extension offers an integrated image configuration assistant. Here, you can choose an included image set or import a HEIC-file from your system. You have to choose the images for the time periods after the import.
3. Configure it to your
- You can apply the setted settings without closing the window if you click on "Apply"
4. If your config is complete, click on "OK"
---
## Preferences Window
Because of the lack of configuration options in the standard Cinnamon configuration system for extensions offers this extension a custom preference window.
All configuration will be handled there. You can choose between included image sets, a HEIC file or a folder source and set the image to ten different daytime periods. Time periods will be estimated via network, custom coordinations or custom time periods. Some behaviour preferences (strech image, fill empty background with gradient color) are also here.
![](res/image_configurator.png)
---
## Troubleshooting
### General
At first: Check if the extension is installed AND activated (check symbol on the left in Extension window).
![](res/activated-extension.png)
Many errors on Linux Mint/Cinnamon Desktop will be printed to Melange. You can open it by pressing `Super Key` + `L`.
### The Preference Window doesn't open!
Go to your home directory, open the terminal. Execute the command:
```
python3 .local/share/cinnamon/extensions/cinnamon-dynamic-wallpaper@TobiZog/5.4/src/main.py
```
This will manually start the window. If there are any problems, the terminal will show it. Use these informations to fix the problem or add them to the Issue.
### The extension don't change the wallpaper
Go to your home directory, open the terminal. Execute the command:
```
python3 .local/share/cinnamon/extensions/cinnamon-dynamic-wallpaper@TobiZog/5.4/src/main.py loop
```
It executes the loop-function which handles the wallpaper change. Terminal will show errors. Use these informations to fix the problem or add them to the Issue.
---
## Contribute
### Translation
You want to contribute a language which isn't supported yet? Here is how to do:
1. Fork the cinnamon-spices-extensions project: https://github.com/linuxmint/cinnamon-spices-extensions
2. Pull the repository
3. Open `cinnamon-dynamic-wallpaper@TobiZog/files/cinnamon-dynamic-wallpaper@TobiZog/po/cinnamon-dynamic-wallpaper@TobiZog.pot` with a po-tool like poedit (https://poedit.net/).
4. Create a new translation in your language
5. Push the changes to your repository
6. Create a pull request
---
## Included image sets
The image sets are from https://github.com/adi1090x/dynamic-wallpaper
| Aurora | Beach | Bitday |
| ------ | ----- | ------ |
| ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/images/included_image_sets/aurora/5.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/images/included_image_sets/beach/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/images/included_image_sets/bitday/4.jpg) |
| ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/aurora/5.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/beach/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/bitday/4.jpg) |
| Cliffs | Gradient | Lakeside |
| -------- | --------- | ------ |
| ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/images/included_image_sets/cliffs/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/images/included_image_sets/gradient/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/images/included_image_sets/lakeside/4.jpg) |
| Cliffs | Desert | Earth |
| -------- | --------- | --------- |
| ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/cliffs/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/desert/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/earth/4.jpg) |
| Mountains | Sahara |
| --------- | ------ |
| ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/images/included_image_sets/mountains/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/images/included_image_sets/sahara/4.jpg) |
| Gradient | Island | Lake |
| --- | --- | --- |
![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/gradient/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/island/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/lake/4.jpg) |
| Lakeside | Mountains | Sahara |
| --------- | ------ | ------ |
| ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/lakeside/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/mountains/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/5.4/res/images/included_image_sets/sahara/4.jpg) |

View File

@@ -1 +0,0 @@
../5.4/extension.js

View File

@@ -1 +0,0 @@
../5.4/icon/

View File

@@ -1 +0,0 @@
../5.4/icons/icon.png

View File

@@ -1 +0,0 @@
../5.4/icons/

View File

@@ -1 +0,0 @@
../../5.4/image-configurator/data/

View File

@@ -1 +0,0 @@
../../5.4/image-configurator/image-configurator.glade

View File

@@ -1,6 +0,0 @@
import os
import windowHandler
if __name__ == "__main__":
wh = windowHandler.WindowHandler(os.path.expanduser("~") + "/.cinnamon/configs/cinnamon-dynamic-wallpaper@TobiZog/cinnamon-dynamic-wallpaper@TobiZog.json")
wh.showMainWindow()

View File

@@ -1 +0,0 @@
../../5.4/image-configurator/windowHandler.py

View File

@@ -1 +0,0 @@
../5.4/images/

View File

@@ -1 +0,0 @@
../5.4/scripts/

View File

@@ -1 +0,0 @@
../5.4/settings-schema.json

View File

@@ -1,23 +1,24 @@
/**
* @name Cinnamon-Dynamic-Wallpaper
* @alias TobiZog
* @since 2023
* @name Cinnamon-Dynamic-Wallpaper
* @alias TobiZog
* @since 2023-05-17
*
* @description Main application file
*/
/******************** Imports ********************/
const MessageTray = imports.ui.messageTray;
const St = imports.gi.St;
const Main = imports.ui.main;
const Util = imports.misc.util;
const Settings = imports.ui.settings;
const Mainloop = imports.mainloop;
const Lang = imports.lang;
const { find_program_in_path } = imports.gi.GLib;
const Gio = imports.gi.Gio;
let suntimes = require('./scripts/suntimes')
let location = require('./scripts/location')
const MessageTray = imports.ui.messageTray;
const St = imports.gi.St;
const Main = imports.ui.main;
const Gettext = imports.gettext;
const GLib = imports.gi.GLib;
/******************** Constants ********************/
@@ -33,12 +34,7 @@ const PATH = DIRECTORY.path;
// The extension object
let extension;
// Time and date of the last location update
let lastLocationUpdate = new Date()
// The last calculated suntime of the day
let lastDayTime = suntimes.DAYPERIOD.NONE
// Loop state
let looping = true
@@ -49,64 +45,54 @@ function CinnamonDynamicWallpaperExtension(uuid) {
}
function _(str) {
let customTranslation = Gettext.dgettext(UUID, str);
if (customTranslation !== str) {
return customTranslation;
}
return Gettext.gettext(str);
}
CinnamonDynamicWallpaperExtension.prototype = {
/******************** Lifecycle ********************/
/**
* Initialization
*
* @param {string} uuid Universally Unique Identifier
*/
_init: function(uuid) {
_init: function(uuid) {
this.settings = new Settings.ExtensionSettings(this, uuid);
// Image set
this.bindSettings("sw_image_stretch", "imageStretch", this.settingsUpdated)
Gettext.bindtextdomain(UUID, GLib.get_home_dir() + '/.local/share/locale');
// Location estimation
this.bindSettings("sw_auto_location", "autolocation", this.settingsUpdated)
this.bindSettings("sc_location_refresh_time", "locationRefreshTime", this.settingsUpdated)
this.bindSettings("etr_latitude", "latitude", this.settingsUpdated)
this.bindSettings("etr_longitude", "longitude", this.settingsUpdated)
// Time periods
this.bindSettings("tv_times", "tvTimes")
// Image Configurator
this.bindSettings("etr_img_morning_twilight", "img_morning_twilight", this.settingsUpdated)
this.bindSettings("etr_img_sunrise", "img_sunrise", this.settingsUpdated)
this.bindSettings("etr_img_morning", "img_morning", this.settingsUpdated)
this.bindSettings("etr_img_noon", "img_noon", this.settingsUpdated)
this.bindSettings("etr_img_afternoon", "img_afternoon", this.settingsUpdated)
this.bindSettings("etr_img_evening", "img_evening", this.settingsUpdated)
this.bindSettings("etr_img_sunset", "img_sunset", this.settingsUpdated)
this.bindSettings("etr_img_night_twilight", "img_night_twilight", this.settingsUpdated)
this.bindSettings("etr_img_night", "img_night", this.settingsUpdated)
// Check for the first startup
if (this.settings.getValue("first_start")) {
// Welcome notification
this.showNotification("Welcome to Cinnamon Dynamic Wallpaper",
"Check the preferences to choose a dynamic wallpaper", true)
this.showNotification(_("Welcome to Cinnamon Dynamic Wallpaper"),
_("Check the preferences to choose a dynamic wallpaper"), true)
// Check for necessary software
if (!find_program_in_path('convert')) {
// Run on Ubuntu/Debian based distros with APT package manager
if(GLib.find_program_in_path("apturl")) {
Util.spawnCommandLine("apturl apt://imagemagick");
} else {
// Notification on other distros
this.showNotification(_("imagemagick is not installed"),
_("Please install the package manually for the full range of functions"), true)
}
}
// Hide the notification on system restart
this.settings.setValue("first_start", false)
// Create the folder for the selected images
Util.spawnCommandLine("mkdir " + DIRECTORY.path + "/images/selected/")
// Link the default wallpaper to the folder
for (let i = 1; i <= 9; i++) {
Util.spawnCommandLine("ln -s " +
DIRECTORY.path + "/images/included_image_sets/lakeside/" + i + ".jpg " +
DIRECTORY.path + "/images/selected/" + i + ".jpg");
}
this.settings.setValue("source_folder", DIRECTORY["path"] + "/res/images/included_image_sets/lakeside/")
}
// Set image initial at desktop wallpaper
this.setImageToTime()
// Start the main loop, checks in fixed time periods the
// Start the main loop, checks in fixed time periods
this._loop()
},
@@ -114,9 +100,9 @@ CinnamonDynamicWallpaperExtension.prototype = {
/**
* Binding the settings objects
*
* @param {*} ui_name Name of preference in settings-schema.json
* @param {*} js_name Name of preference in JavaScript
* @param {*} func Function to call on change
* @param {string} ui_name Name of preference in settings-schema.json
* @param {string} js_name Name of preference in JavaScript
* @param {Function} func Function to call on change
*/
bindSettings: function (ui_name, js_name, func = this.on_settings_changed) {
this.settings.bindProperty(
@@ -129,25 +115,24 @@ CinnamonDynamicWallpaperExtension.prototype = {
/**
* Handles changes in settings
* Main loop
*/
settingsUpdated: function() {
lastDayTime = suntimes.DAYPERIOD.NONE
_loop: function () {
if (looping) {
try {
Util.spawnCommandLine("/usr/bin/env python3 " + DIRECTORY.path + "/src/main.py loop")
} catch(e) {
this.showNotification(_("Error!"),
_("Cinnamon Dynamic Wallpaper got an error while running the loop script. Please create an issue on GitHub."))
}
this.updateLocation()
this.setImageToTime()
// Refresh every 60 seconds
Mainloop.timeout_add_seconds(60, Lang.bind(this, this._loop));
}
},
/**
* Displaying a desktop notification
*
* @param {string} title The Title in the notification
* @param {string} text The text in the notification
* @param {boolean} showOpenSettings Display the "Open settings" button in the notification,
* defaults to false
*/
showNotification: function (title, text, showOpenSettings = false) {
showNotification(title, text, showOpenSettings = false) {
let source = new MessageTray.Source(this.uuid);
// Parameter
@@ -158,7 +143,6 @@ CinnamonDynamicWallpaperExtension.prototype = {
icon_size: source.ICON_SIZE
})
};
// The notification itself
let notification = new MessageTray.Notification(source, title, text, params);
@@ -167,7 +151,7 @@ CinnamonDynamicWallpaperExtension.prototype = {
notification.addButton("open-settings", _("Open settings"));
notification.connect("action-invoked", () =>
Util.spawnCommandLine("xlet-settings extension " + UUID));
Util.spawnCommandLine("/usr/bin/env python3 " + DIRECTORY.path + "/src/main.py"));
}
// Put all together
@@ -175,149 +159,6 @@ CinnamonDynamicWallpaperExtension.prototype = {
// Display it
source.notify(notification);
},
/**
* Changes the desktop background image
*
* @param {jpg} imageURI The new desktop image
*/
changeWallpaper: function(imageURI) {
let gSetting = new Gio.Settings({schema: 'org.cinnamon.desktop.background'});
gSetting.set_string('picture-uri', imageURI);
if (this.imageStretch) {
gSetting.set_string('picture-options', 'spanned')
}
else
{
gSetting.set_string('picture-options', 'zoom')
}
Gio.Settings.sync();
gSetting.apply();
},
/**
* Estimate the right image based on time period of the day
*/
setImageToTime: function() {
let times = suntimes.calcTimePeriod(this.latitude, this.longitude)
let now = new Date()
let timesArray = [
times["morning_twilight"], times["sunrise"], times["morning"],
times["noon"], times["afternoon"], times["evening"],
times["sunset"], times["night_twilight"], times["night"]
]
let imageSet = [
this.img_morning_twilight, this.img_sunrise, this.img_morning,
this.img_noon, this.img_afternoon, this.img_evening,
this.img_sunset, this.img_night_twilight, this.img_night
]
for(let i = 0; i < timesArray.length; i++) {
if(timesArray[i][0] <= now && now <= timesArray[i][1] && i != lastDayTime) {
this.changeWallpaper("file://" + PATH + "/images/selected/" + imageSet[i])
lastDayTime = i
break
}
}
function convertToTimeString(time) {
return time.getHours().toString().padStart(2, "0") + ":" + time.getMinutes().toString().padStart(2, "0")
}
this.tvTimes =
"Morning Twilight:\t\t" + convertToTimeString(timesArray[0][0]) + " - " + convertToTimeString(timesArray[0][1]) +
"\nSunrise:\t\t\t\t" + convertToTimeString(timesArray[1][0]) + " - " + convertToTimeString(timesArray[1][1]) +
"\nMorning:\t\t\t" + convertToTimeString(timesArray[2][0]) + " - " + convertToTimeString(timesArray[2][1]) +
"\nNoon:\t\t\t\t" + convertToTimeString(timesArray[3][0]) + " - " + convertToTimeString(timesArray[3][1]) +
"\nAfternoon:\t\t\t" + convertToTimeString(timesArray[4][0]) + " - " + convertToTimeString(timesArray[4][1]) +
"\nEvening:\t\t\t" + convertToTimeString(timesArray[5][0]) + " - " + convertToTimeString(timesArray[5][1]) +
"\nSunset:\t\t\t\t" + convertToTimeString(timesArray[6][0]) + " - " + convertToTimeString(timesArray[6][1]) +
"\nNight Twilight:\t\t" + convertToTimeString(timesArray[7][0]) + " - " + convertToTimeString(timesArray[7][1]) +
"\nNight:\t\t\t\t" + convertToTimeString(timesArray[8][0]) + " - " + convertToTimeString(timesArray[8][1])
},
/**
* Get the location of the user
* Callback for changes in preferences
*/
updateLocation: function () {
if (this.autolocation) {
let loc = location.estimateLocation()
this.latitude = loc["latitude"]
this.longitude = loc["longitude"]
} else {
this.latitude = this.latitude
this.longitude = this.longitude
}
// Update the update information
lastLocationUpdate = new Date()
},
/**
* Main loop
*/
_loop: function () {
if (looping) {
this.setImageToTime()
if (lastLocationUpdate < new Date().getTime() - this.locationRefreshTime * 1000) {
this.updateLocation()
lastLocationUpdate = new Date()
}
// Refresh every 60 seconds
Mainloop.timeout_add_seconds(60, Lang.bind(this, this._loop));
}
},
/******************** UI Callbacks ********************/
/**
* Callback for settings-schema
* Opens the external image configurator window
*/
openImageConfigurator: function() {
Util.spawnCommandLine("/usr/bin/env python3 " +
DIRECTORY.path + "/image-configurator/image-configurator.py");
},
/**
* Callback for settings-schema
* Opens the browser and navigates to the URL of the respository
*/
openRepoWebsite: function() {
Util.spawnCommandLine("xdg-open https://github.com/TobiZog/cinnamon-dynamic-wallpaper");
},
/**
* Callback for settings-schema
* Opens the browser and navigates to the URL of the Cinnamon Spices extension
*/
openSpicesWebsite: function() {
Util.spawnCommandLine("xdg-open https://cinnamon-spices.linuxmint.com/extensions/view/97")
},
/**
* Callback for settings-schema
* Opens the browser and navigates to the GitHub issue page
*/
openIssueWebsite: function() {
Util.spawnCommandLine("xdg-open https://github.com/TobiZog/cinnamon-dynamic-wallpaper/issues/new")
}
}
@@ -341,11 +182,6 @@ function init(extensionMeta) {
* @returns The extension object
*/
function enable() {
// Check for necessary software
if (!find_program_in_path('heif-convert')) {
Util.spawnCommandLine("apturl apt://libheif-examples");
}
return extension;
}
@@ -355,4 +191,4 @@ function enable() {
*/
function disable() {
looping = false
}
}

View File

@@ -1 +0,0 @@
icons/icon.png

View File

@@ -0,0 +1 @@
res/icons/icon.svg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,6 +0,0 @@
from enum import Enum
class Source(Enum):
SELECTED = 0 # Load previous selected images
EXTRACT = 1 # Use a custom image set from a heic file
SET = 2 # Use an included image set

View File

@@ -1,925 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkFileFilter" id="filefilter1">
<patterns>
<pattern>*.heic</pattern>
</patterns>
</object>
<object class="GtkScrolledWindow" id="page_config">
<property name="width-request">100</property>
<property name="height-request">80</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vscroll-policy">natural</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">8</property>
<property name="margin-end">8</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.009999999776482582</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<!-- n-columns=2 n-rows=2 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">8</property>
<property name="margin-end">8</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<property name="row-spacing">8</property>
<property name="column-spacing">8</property>
<property name="column-homogeneous">True</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Use an included or a custom image set?</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rb_included_image_set">
<property name="label" translatable="yes">Use an included image set</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
<signal name="toggled" handler="onRadioImageSet" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rb_external_image_set">
<property name="label" translatable="yes">Import a heic-file</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
<property name="group">rb_included_image_set</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Image Source</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.009999999776482582</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<!-- n-columns=2 n-rows=2 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">8</property>
<property name="margin-end">8</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<property name="row-spacing">8</property>
<property name="column-spacing">8</property>
<property name="column-homogeneous">True</property>
<child>
<object class="GtkLabel" id="lb_image_set">
<property name="height-request">36</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Select an image-set</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkFileChooserButton" id="fc_heic_file">
<property name="can-focus">False</property>
<property name="no-show-all">True</property>
<property name="filter">filefilter1</property>
<property name="title" translatable="yes"/>
<signal name="file-set" handler="onHeifSelected" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lb_heic_file">
<property name="height-request">36</property>
<property name="can-focus">False</property>
<property name="no-show-all">True</property>
<property name="label" translatable="yes">Choose the file, which you want to use</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="cb_image_set">
<property name="visible">True</property>
<property name="can-focus">False</property>
<signal name="changed" handler="onImageSetSelected" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Image Set</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">True</property>
<property name="label-xalign">0.009999999776482582</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="bottom-padding">8</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<!-- n-columns=3 n-rows=3 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="row-spacing">8</property>
<property name="column-spacing">8</property>
<property name="row-homogeneous">True</property>
<property name="column-homogeneous">True</property>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.5</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="top-padding">8</property>
<property name="bottom-padding">8</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkImage" id="img_preview_1">
<property name="width-request">300</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">True</property>
<property name="stock">gtk-missing-image</property>
<property name="pixel-size">30</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="cb_preview_1">
<property name="visible">True</property>
<property name="can-focus">False</property>
<signal name="changed" handler="onPreviewComboboxSelected" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Morning Twilight</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.5</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="top-padding">8</property>
<property name="bottom-padding">8</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkImage" id="img_preview_2">
<property name="width-request">300</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">True</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="cb_preview_2">
<property name="can-focus">False</property>
<signal name="changed" handler="onPreviewComboboxSelected" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Sunrise</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.5</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="top-padding">8</property>
<property name="bottom-padding">8</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkImage" id="img_preview_3">
<property name="width-request">300</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">True</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="cb_preview_3">
<property name="visible">True</property>
<property name="can-focus">False</property>
<signal name="changed" handler="onPreviewComboboxSelected" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Morning</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.5</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="top-padding">8</property>
<property name="bottom-padding">8</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkImage" id="img_preview_4">
<property name="width-request">300</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">True</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="cb_preview_4">
<property name="can-focus">False</property>
<signal name="changed" handler="onPreviewComboboxSelected" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Noon</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.5</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="top-padding">8</property>
<property name="bottom-padding">8</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkImage" id="img_preview_5">
<property name="width-request">300</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">True</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="cb_preview_5">
<property name="visible">True</property>
<property name="can-focus">False</property>
<signal name="changed" handler="onPreviewComboboxSelected" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Afternoon</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.5</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="top-padding">8</property>
<property name="bottom-padding">8</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkImage" id="img_preview_6">
<property name="width-request">300</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">True</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="cb_preview_6">
<property name="visible">True</property>
<property name="can-focus">False</property>
<signal name="changed" handler="onPreviewComboboxSelected" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Evening</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.5</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="top-padding">8</property>
<property name="bottom-padding">8</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkImage" id="img_preview_7">
<property name="width-request">300</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">True</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="cb_preview_7">
<property name="visible">True</property>
<property name="can-focus">False</property>
<signal name="changed" handler="onPreviewComboboxSelected" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Sunset</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.5</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="top-padding">8</property>
<property name="bottom-padding">8</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkImage" id="img_preview_8">
<property name="width-request">300</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">True</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="cb_preview_8">
<property name="visible">True</property>
<property name="can-focus">False</property>
<signal name="changed" handler="onPreviewComboboxSelected" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Night Twilight</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0.5</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="top-padding">8</property>
<property name="bottom-padding">8</property>
<property name="left-padding">8</property>
<property name="right-padding">8</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkImage" id="img_preview_9">
<property name="width-request">300</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">True</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="cb_preview_9">
<property name="visible">True</property>
<property name="can-focus">False</property>
<signal name="changed" handler="onPreviewComboboxSelected" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Night</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">Preview</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
<object class="GtkWindow" id="main_window">
<property name="can-focus">False</property>
<property name="window-position">center</property>
<property name="default-width">1024</property>
<property name="default-height">768</property>
<property name="icon">../../icon.png</property>
<signal name="destroy" handler="onDestroy" swapped="no"/>
<child>
<object class="GtkStack" id="stack_main">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="transition-type">crossfade</property>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="title" translatable="yes">Cinnamon Dynamic Wallpaper</property>
<property name="subtitle" translatable="yes">Image Configuration</property>
<property name="show-close-button">True</property>
<child>
<object class="GtkButton">
<property name="label">gtk-apply</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="use-stock">True</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="onApply" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
<object class="GtkBox" id="page_load">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">8</property>
<property name="margin-end">8</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkSpinner">
<property name="height-request">64</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="active">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Proceeding...</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</interface>

View File

@@ -1,6 +0,0 @@
import os
import windowHandler
if __name__ == "__main__":
wh = windowHandler.WindowHandler(os.path.expanduser("~") + "/.config/cinnamon/spices/cinnamon-dynamic-wallpaper@TobiZog/cinnamon-dynamic-wallpaper@TobiZog.json")
wh.showMainWindow()

View File

@@ -1,367 +0,0 @@
import gi, os, glob, json, shutil, threading, subprocess
from data.enum import Source
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GdkPixbuf
CONFIGURATOR_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_DIR = os.path.dirname(CONFIGURATOR_DIR) + "/"
UI_PATH = CONFIGURATOR_DIR + "/" + "image-configurator.glade"
IMAGE_DIR = PROJECT_DIR + "images/"
IMAGE_EXTRACT_DIR = IMAGE_DIR + "extracted/"
IMAGE_SETS_DIR = IMAGE_DIR + "included_image_sets/"
IMAGE_SELECTED_DIR = IMAGE_DIR + "selected/"
class WindowHandler:
def __init__(self, pref_path: str) -> None:
########### Class variables ###########
self.pref_path = pref_path
self.pref_vars = [
"etr_img_morning_twilight",
"etr_img_sunrise",
"etr_img_morning",
"etr_img_noon",
"etr_img_afternoon",
"etr_img_evening",
"etr_img_sunset",
"etr_img_night_twilight",
"etr_img_night"
]
self.img_sets = [
"aurora",
"beach",
"bitday",
"cliffs",
"gradient",
"lakeside",
"mountains",
"sahara"
]
########### Create the folder ###########
try:
os.mkdir(IMAGE_EXTRACT_DIR)
except:
pass
try:
os.mkdir(IMAGE_SELECTED_DIR)
except:
pass
########### GTK stuff ###########
self.builder = Gtk.Builder()
self.builder.add_from_file(UI_PATH)
self.builder.connect_signals(self)
########### Glade Ressources ###########
self.rb_included_image_set = self.builder.get_object("rb_included_image_set")
self.rb_external_image_set = self.builder.get_object("rb_external_image_set")
self.lb_image_set = self.builder.get_object("lb_image_set")
self.cb_image_set = self.builder.get_object("cb_image_set")
self.lb_heic_file = self.builder.get_object("lb_heic_file")
self.fc_heic_file = self.builder.get_object("fc_heic_file")
self.img_previews = [
self.builder.get_object("img_preview_1"),
self.builder.get_object("img_preview_2"),
self.builder.get_object("img_preview_3"),
self.builder.get_object("img_preview_4"),
self.builder.get_object("img_preview_5"),
self.builder.get_object("img_preview_6"),
self.builder.get_object("img_preview_7"),
self.builder.get_object("img_preview_8"),
self.builder.get_object("img_preview_9")
]
self.cb_previews = [
self.builder.get_object("cb_preview_1"),
self.builder.get_object("cb_preview_2"),
self.builder.get_object("cb_preview_3"),
self.builder.get_object("cb_preview_4"),
self.builder.get_object("cb_preview_5"),
self.builder.get_object("cb_preview_6"),
self.builder.get_object("cb_preview_7"),
self.builder.get_object("cb_preview_8"),
self.builder.get_object("cb_preview_9")
]
# The GtkStack
self.stack_main = self.builder.get_object("stack_main")
self.stack_main.add_named(self.builder.get_object("page_config"), "config")
self.stack_main.add_named(self.builder.get_object("page_load"), "load")
self.stack_main.set_visible_child_name("config")
########### Load predefinitions and settings ###########
for set in self.img_sets:
self.cb_image_set.append_text(set)
self.image_source = Source.SELECTED
# Load preferences
self.loadFromSettings()
def showMainWindow(self):
""" Opens the main window, starts the Gtk main routine
"""
window = self.builder.get_object("main_window")
window.show_all()
self.imageSetVisibility(self.image_source)
self.rb_external_image_set.set_active(self.image_source == Source.EXTRACT)
Gtk.main()
def loadFromSettings(self):
""" Load preferences from the Cinnamon preference file
"""
#try:
# Load the settings
with open(self.pref_path, "r") as pref_file:
pref_data = json.load(pref_file)
# Get all images in the "selected" folder
choosable_images = os.listdir(IMAGE_SELECTED_DIR)
choosable_images.sort()
# Add the founded image names to the ComboBoxes
if pref_data["etr_choosen_image_set"]["value"] == "custom":
for combobox in self.cb_previews:
for option in choosable_images:
combobox.append_text(option)
else:
for i, set in enumerate(self.img_sets):
if set == pref_data["etr_choosen_image_set"]["value"]:
self.cb_image_set.set_active(i)
for i, val in enumerate(self.pref_vars):
# Set the preview image
self.changePreviewImage(i, IMAGE_SELECTED_DIR + pref_data[val]['value'])
# Set the ComboBox selection
if pref_data["etr_choosen_image_set"]["value"] == "custom":
self.image_source = Source.EXTRACT
for j, set in enumerate(choosable_images):
if set == pref_data[val]["value"]:
self.cb_previews[i].set_active(j)
else:
self.image_source = Source.SET
#except:
# pass
def writeToSettings(self):
""" Save preferences to the Cinnamon preference file
"""
# Load the settings
with open(self.pref_path, "r") as pref_file:
pref_data = json.load(pref_file)
# Update the settings
if self.image_source == Source.SET:
pref_data["etr_choosen_image_set"]["value"] = self.cb_image_set.get_active_text()
for i, val in enumerate(self.pref_vars):
pref_data[val]['value'] = str(i + 1) + ".jpg"
else:
pref_data["etr_choosen_image_set"]["value"] = "custom"
for i, val in enumerate(self.pref_vars):
pref_data[val]['value'] = self.cb_previews[i].get_active_text()
# Write the settings
with open(self.pref_path, "w") as pref_file:
json.dump(pref_data, pref_file, separators=(',', ':'), indent=4)
def changePreviewImage(self, imageId: int, imageURI: str):
""" Exchanges the image in the preview
Args:
imageId (int): The number of the preview (0-8)
imageURI (str): URI to the new image
"""
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file(imageURI)
pixbuf = pixbuf.scale_simple(300, 200, GdkPixbuf.InterpType.BILINEAR)
self.img_previews[imageId].set_from_pixbuf(pixbuf)
except:
pass
def extractHeifImages(self, imageURI: str):
""" Extract all images in a heif file
Args:
imageURI (str): URI to the heif file
"""
imageURI = imageURI.replace("%20", "\ ")
filename = imageURI[imageURI.rfind("/") + 1:imageURI.rfind(".")]
self.image_source = Source.EXTRACT
self.wipeImages(Source.EXTRACT)
os.system("heif-convert " + imageURI + " " + IMAGE_EXTRACT_DIR + "/" + filename + ".jpg")
self.createExtracted()
def wipeImages(self, source: Source):
""" Removes all image of a folder
Args:
source (Source): Choose the folder by selecting the Source
"""
if source == Source.EXTRACT:
dir = IMAGE_EXTRACT_DIR + "*"
elif source == Source.SELECTED:
dir = IMAGE_SELECTED_DIR + "*"
for file in glob.glob(dir):
os.remove(file)
def createExtracted(self):
""" Create the extracted images array
"""
try:
if self.image_source == Source.SELECTED:
self.extracted = os.listdir(IMAGE_SELECTED_DIR)
elif self.image_source == Source.EXTRACT:
self.extracted = os.listdir(IMAGE_EXTRACT_DIR)
self.extracted.sort()
for combobox in self.cb_previews:
for option in self.extracted:
combobox.append_text(option)
except:
pass
self.stack_main.set_visible_child_name("config")
def copyToSelected(self, source: Source):
""" Copies the extracted images to "res/"
"""
# Clean the "selected folder up"
self.wipeImages(Source.SELECTED)
# Estimate the source folder
if source == Source.EXTRACT:
source_folder = IMAGE_EXTRACT_DIR
else:
source_folder = IMAGE_SETS_DIR + self.cb_image_set.get_active_text() + "/"
# Copy it to "selected/"
for image in os.listdir(source_folder):
shutil.copy(source_folder + image, IMAGE_SELECTED_DIR + image)
def imageSetVisibility(self, source: Source):
""" Toggle the visibility of the option in the "Image set" box
Args:
source (Source): Toggle by type of Source
"""
self.image_source = source
self.lb_image_set.set_visible(source == Source.SET)
self.cb_image_set.set_visible(source == Source.SET)
self.lb_heic_file.set_visible(source != Source.SET)
self.fc_heic_file.set_visible(source != Source.SET)
for i in range(0, 9):
self.cb_previews[i].set_visible(source != Source.SET)
########## UI Signals ##########
def onImageSetSelected(self, cb):
""" UI signal if the image set combo box value changed
Args:
cb (GtkComboBox): The active ComboBox
"""
if self.image_source != Source.SELECTED:
set_name = cb.get_active_text()
for i, _ in enumerate(self.img_previews):
self.changePreviewImage(i, IMAGE_SETS_DIR + set_name + "/" + str(i + 1) + ".jpg")
def onRadioImageSet(self, rb):
""" UI signal if the radio buttons are toggled
Args:
rb (GtkRadioButton): The toggled RadioButton
"""
if rb.get_active():
self.imageSetVisibility(Source.SET)
else:
self.imageSetVisibility(Source.EXTRACT)
def onHeifSelected(self, fc):
""" UI signal if the filechooser has a file selected
Args:
fc (filechooser): The selected filechooser
"""
# Get the URI to the file
uri = fc.get_file().get_uri()
uri = uri[7:]
self.stack_main.set_visible_child_name("load")
thread = threading.Thread(target=self.extractHeifImages, args=(uri, ))
thread.daemon = True
thread.start()
def onPreviewComboboxSelected(self, cb):
""" UI signal if one of the preview combobox is selected
Args:
cb (ComboBox): The selected combobox
"""
number = Gtk.Buildable.get_name(cb)
number = number[number.rfind("_") + 1:]
if self.image_source == Source.EXTRACT:
self.changePreviewImage(int(number) - 1, IMAGE_EXTRACT_DIR + cb.get_active_text())
def onApply(self, *args):
""" UI signal if the user presses the "Apply" button
"""
self.writeToSettings()
self.copyToSelected(self.image_source)
Gtk.main_quit()
def onDestroy(self, *args):
""" UI signal if the window is closed by the user
"""
Gtk.main_quit()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 454 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 470 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 681 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 654 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 631 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 465 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<linearGradient id="a" gradientTransform="matrix(0.232143 0 0 0.328947 -9.109985 263.79837)" gradientUnits="userSpaceOnUse" x1="88.595886" x2="536.595886" y1="-449.394012" y2="-449.394012">
<stop offset="0" stop-color="#77767b"/>
<stop offset="0.0384615" stop-color="#c0bfbc"/>
<stop offset="0.0768555" stop-color="#9a9996"/>
<stop offset="0.923077" stop-color="#9a9996"/>
<stop offset="0.961538" stop-color="#c0bfbc"/>
<stop offset="1" stop-color="#77767b"/>
</linearGradient>
<linearGradient id="b" gradientTransform="matrix(0.978582 0 0 0.937323 -9.031522 -9.577706)" gradientUnits="userSpaceOnUse" x1="20.937046" x2="127.213333" y1="76.334984" y2="76.334984">
<stop offset="0" stop-color="#066996"/>
<stop offset="1" stop-color="#001533"/>
</linearGradient>
<path d="m 19.457031 15.972656 h 88 c 4.417969 0 8 3.582032 8 8 v 84 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -84 c 0 -4.417968 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/>
<path d="m 17.328125 11.972656 h 92.257813 c 3.242187 0 5.871093 2.519532 5.871093 5.625 v 88.75 c 0 3.105469 -2.628906 5.625 -5.871093 5.625 h -92.257813 c -3.242187 0 -5.871094 -2.519531 -5.871094 -5.625 v -88.75 c 0 -3.105468 2.628907 -5.625 5.871094 -5.625 z m 0 0" fill="url(#b)"/>
<path d="m 63.945312 74.6875 c 0 10.257812 -8.671874 18.574219 -19.367187 18.574219 s -19.367187 -8.316407 -19.367187 -18.574219 s 8.671874 -18.574219 19.367187 -18.574219 s 19.367187 8.316407 19.367187 18.574219 z m 0 0" fill="#f7c22c"/>
<path d="m 61.160156 74.136719 c 0 10.03125 -8.128906 18.164062 -18.160156 18.164062 c -10.027344 0 -18.160156 -8.132812 -18.160156 -18.164062 c 0 -10.027344 8.132812 -18.160157 18.160156 -18.160157 c 10.03125 0 18.160156 8.132813 18.160156 18.160157 z m 0 0" fill="#f7d97e"/>
<path d="m 85.46875 19.277344 c 7.65625 3.941406 12.472656 11.832031 12.472656 20.445312 c 0 12.695313 -10.292968 22.992188 -22.992187 22.992188 c -0.074219 -0.007813 -0.148438 -0.011719 -0.222657 -0.019532 c 3.253907 1.679688 6.863282 2.558594 10.527344 2.5625 c 12.695313 0 22.992188 -10.296874 22.992188 -22.992187 c -0.003906 -12.613281 -10.167969 -22.871094 -22.777344 -22.988281 z m 0 0" fill="#eaa22f"/>
<path d="m 82.804688 18.175781 c 7.660156 3.9375 12.472656 11.828125 12.476562 20.441407 c 0 12.699218 -10.296875 22.992187 -22.992188 22.992187 c -0.078124 -0.003906 -0.152343 -0.011719 -0.226562 -0.015625 c 3.253906 1.679688 6.863281 2.554688 10.527344 2.558594 c 12.699218 0 22.992187 -10.292969 22.992187 -22.992188 c -0.003906 -12.613281 -10.164062 -22.867187 -22.777343 -22.984375 z m 0 0" fill="#ffc61b"/>
<g fill="#f7d97e">
<path d="m 44.394531 45.09375 c 0.527344 0 0.953125 0.445312 0.953125 1 v 7.558594 c 0 0.554687 -0.425781 1 -0.953125 1 c -0.527343 0 -0.957031 -0.445313 -0.957031 -1 v -7.558594 c 0 -0.554688 0.429688 -1 0.957031 -1 z m 0 0"/>
<path d="m 44.222656 94.574219 c 0.527344 0 0.953125 0.449219 0.953125 1 v 7.5625 c 0 0.554687 -0.425781 1 -0.953125 1 s -0.957031 -0.445313 -0.957031 -1 v -7.5625 c 0 -0.550781 0.429687 -1 0.957031 -1 z m 0 0"/>
<path d="m 65.402344 74.839844 c 0 -0.527344 0.449218 -0.953125 1 -0.953125 h 7.5625 c 0.550781 0 1 0.425781 1 0.953125 s -0.449219 0.957031 -1 0.957031 h -7.5625 c -0.550782 0 -1 -0.429687 -1 -0.957031 z m 0 0"/>
<path d="m 13.84375 74.300781 c 0 -0.527343 0.445312 -0.957031 1 -0.957031 h 7.558594 c 0.554687 0 1 0.429688 1 0.957031 c 0 0.527344 -0.445313 0.953125 -1 0.953125 h -7.558594 c -0.554688 0 -1 -0.425781 -1 -0.953125 z m 0 0"/>
<path d="m 22.230469 53.699219 c 0.371093 -0.375 0.988281 -0.359375 1.378906 0.03125 l 5.347656 5.347656 c 0.390625 0.390625 0.40625 1.007813 0.03125 1.382813 c -0.371093 0.371093 -0.992187 0.355468 -1.382812 -0.035157 l -5.34375 -5.34375 c -0.390625 -0.390625 -0.40625 -1.011719 -0.03125 -1.382812 z m 0 0"/>
<path d="m 59.175781 88.910156 c 0.371094 -0.375 0.992188 -0.359375 1.382813 0.03125 l 5.347656 5.347656 c 0.390625 0.390626 0.402344 1.007813 0.03125 1.382813 c -0.375 0.371094 -0.992188 0.355469 -1.382812 -0.035156 l -5.347657 -5.34375 c -0.390625 -0.390625 -0.40625 -1.011719 -0.03125 -1.382813 z m 0 0"/>
<path d="m 59.378906 60.664062 c -0.371094 -0.371093 -0.359375 -0.992187 0.03125 -1.382812 l 5.347656 -5.34375 c 0.390626 -0.390625 1.007813 -0.40625 1.382813 -0.035156 c 0.371094 0.375 0.359375 0.992187 -0.03125 1.382812 l -5.347656 5.347656 c -0.390625 0.390626 -1.007813 0.40625 -1.382813 0.03125 z m 0 0"/>
<path d="m 22.867188 95.21875 c -0.375 -0.375 -0.359376 -0.992188 0.03125 -1.382812 l 5.34375 -5.347657 c 0.390624 -0.390625 1.011718 -0.40625 1.382812 -0.03125 c 0.375 0.371094 0.359375 0.992188 -0.03125 1.382813 l -5.347656 5.347656 c -0.390625 0.390625 -1.007813 0.402344 -1.378906 0.03125 z m 0 0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 KiB

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