18 Commits
v.1.0 ... v.1.4

Author SHA1 Message Date
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
0d8fa6449c Version Update 2023-07-24 23:36:25 +02:00
8aae370bf8 Adding option to stretch the image over multiple displays 2023-07-24 23:22:16 +02:00
5447ecb930 Readme, changelog 2023-07-13 20:02:52 +02:00
605bc1e8ee More informations in the settings 2023-07-13 19:53:15 +02:00
5f52ae959a Readme, bugfix, documentation 2023-07-13 18:46:40 +02:00
4798b9438d Notification, load at first start a wallpaper, bugfix restart on after first enable 2023-07-13 14:32:13 +02:00
43fcd83b17 Revert "Notification, load at first start a wallpaper, bugfix restart on after first enable"
This reverts commit 1ad5a9fe8b.
2023-07-13 14:31:43 +02:00
1ad5a9fe8b Notification, load at first start a wallpaper, bugfix restart on after first enable 2023-07-13 14:30:47 +02:00
b8996b1f03 Compatibility with Cinnamon 4.8 and higher 2023-07-13 13:40:55 +02:00
34ad4a9589 Working on support for Cinnamon 4.8 and newer 2023-07-13 12:41:31 +02:00
5628dfc4b0 Rename README.md 2023-07-08 18:00:49 +02:00
fef2a534cc Two new image sets 2023-07-08 17:57:16 +02:00
44a7bb1f8f Readme update 2023-07-08 17:35:03 +02:00
52402aaaf4 Adding support for Cinnamon 5.4 and 5.8 2023-07-08 16:39:51 +02:00
101 changed files with 941 additions and 384 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ extracted/
custom_images/ custom_images/
*.txt *.txt
selected/ selected/
__pycache__

View File

@@ -1,3 +1,23 @@
# 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
# Version 1.2
- Compatibility with Cinnamon 4.8 and higher
- Notification on first start
- Bugfix: No more restart needed after first enable
- Load at first start a predefined dynamic wallpaper
- More informations in the settings
# Version 1.1
- Compatibility with Cinnamon 5.4 and 5.8
- Two new image sets
# Version 1.0 # Version 1.0
- Offline sun time calculation - Offline sun time calculation
- Online location estimation or manual input - Online location estimation or manual input

View File

@@ -6,27 +6,43 @@
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. 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.
### Features ### Features
- 6 included image sets - 8 included image sets
- 9 day periods - 9 day periods
- HEIF converter - HEIF converter
- Image configuration assistent with simple one-click setup for image choose - Image configuration assistent with simple one-click setup for image choose
- Online location estimation - Online location estimation or offline with manual latitude and longitude input
- Offline sun angles estimation - Offline sun angles estimation
- Image stretching over multiple displays or repeat image for every display
### Tested Cinnamon versions ### Tested Cinnamon versions
- 5.6 - 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)
### 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`
## Installation ## Installation
### From Built-in Extension Manager
![](res/download-manager.png)
1. Open "Extensions" in Linux Mint or any other distribution with Cinnamon as Desktop Environment
2. Click on "Download"
3. Search and download it
### From the repo ### From the repo
1. Download the Repository 1. Download the Repository
2. Extract the files 2. Extract the files
3. Copy the folder `cinnamon-dynamic-wallpaper@TobiZog` to `~/.local/share/cinnamon/extensions/` 3. Copy the folder `cinnamon-dynamic-wallpaper@TobiZog` to `~/.local/share/cinnamon/extensions/`
### From Built-in Extension Manager
1. Open "Extensions" in Linux Mint or any other distribution with Cinnamon as Desktop Environment
2. Click on "Download"
3. Search and download it
## How to use it ## How to use it
1. Active the Extension via Cinnamon Extension Manager 1. Active the Extension via Cinnamon Extension Manager
2. Open the settings 2. Open the settings
@@ -44,8 +60,12 @@ The image sets are from https://github.com/adi1090x/dynamic-wallpaper
| Aurora | Beach | Bitday | | Aurora | Beach | Bitday |
| ------ | ----- | ------ | | ------ | ----- | ------ |
| ![](cinnamon-dynamic-wallpaper@TobiZog/images/included_image_sets/aurora/5.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/images/included_image_sets/beach/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/images/included_image_sets/bitday/4.jpg) | | ![](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) |
| Lakeside | Mountains | Sahara | | Cliffs | Gradient | Lakeside |
| -------- | --------- | ------ | | -------- | --------- | ------ |
| ![](cinnamon-dynamic-wallpaper@TobiZog/images/included_image_sets/lakeside/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/images/included_image_sets/mountains/4.jpg) | ![](cinnamon-dynamic-wallpaper@TobiZog/images/included_image_sets/sahara/4.jpg) | | ![](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) |
| 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) |

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,372 @@
/**
* @name Cinnamon-Dynamic-Wallpaper
* @alias TobiZog
* @since 2023-05-17
*
* @description Main application file
*/
/******************** Imports ********************/
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')
let communication = require('./scripts/communication')
/******************** Constants ********************/
const UUID = "cinnamon-dynamic-wallpaper@TobiZog";
const APPNAME = "Cinnamon Dynamic Wallpaper"
const DIRECTORY = imports.ui.extensionSystem.extensionMeta[UUID];
const PATH = DIRECTORY.path;
/******************** Global Variables ********************/
// The extension object
let extension;
// Time and date of the last location update
let lastLocationUpdate = -1
// The last calculated suntime of the day
let lastDayTime = suntimes.DAYPERIOD.NONE
// Loop state
let looping = true
/******************** Objects ********************/
function CinnamonDynamicWallpaperExtension(uuid) {
this._init(uuid);
}
CinnamonDynamicWallpaperExtension.prototype = {
/******************** Lifecycle ********************/
/**
* Initialization
*
* @param {string} uuid Universally Unique Identifier
*/
_init: function(uuid) {
this.settings = new Settings.ExtensionSettings(this, uuid);
/** Configuration */
// Image set
this.bindSettings("sw_image_stretch", "imageStretch", this.settingsUpdated)
// Location estimation
this.bindSettings("sw_auto_location", "autolocation", this.settingsUpdated)
this.bindSettings("sc_location_refresh_time", "locationRefreshTime", this.settingsUpdated)
this.bindSettings("etr_last_update", "etrLastUpdate")
this.bindSettings("etr_latitude", "latitude", this.settingsUpdated)
this.bindSettings("etr_longitude", "longitude", this.settingsUpdated)
// Time periods
this.bindSettings("tv_times", "tvTimes")
/** Debugging */
// Logs
this.bindSettings("tv_logs", "tvLogs")
// 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)
this.bindSettings("etr_morning_twilight_times", "img_morning_twilight_times")
this.bindSettings("etr_sunrise_times", "img_sunrise_times")
this.bindSettings("etr_morning_times", "img_morning_times")
this.bindSettings("etr_noon_times", "img_noon_times")
this.bindSettings("etr_afternoon_times", "img_afternoon_times")
this.bindSettings("etr_evening_times", "img_evening_times")
this.bindSettings("etr_sunset_times", "img_sunset_times")
this.bindSettings("etr_night_twilight_times", "img_night_twilight_times")
this.bindSettings("etr_night_times", "img_night_times")
// Check for the first startup
if (this.settings.getValue("first_start")) {
this.writeToLogs("First time start")
// Welcome notification
communication.showNotification("Welcome to Cinnamon Dynamic Wallpaper",
"Check the preferences to choose a dynamic wallpaper", 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.writeToLogs("Initialization completed")
// Set image initial at desktop wallpaper
this.setImageToTime()
// Start the main loop, checks in fixed time periods the
this._loop()
},
/**
* Binding the settings objects
*
* @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(
Settings.BindingDirection.IN,
ui_name,
js_name,
func
)
},
/**
* Main loop
*/
_loop: function () {
if (looping) {
this.setImageToTime()
// Update the location, if the user choose "autoLocation" and the timer has expired
if ((lastLocationUpdate == -1 ||
lastLocationUpdate.getTime() < new Date().getTime() - this.locationRefreshTime * 60000) &&
this.autolocation)
{
this.updateLocation()
lastLocationUpdate = new Date()
}
// Refresh every 60 seconds
Mainloop.timeout_add_seconds(60, Lang.bind(this, this._loop));
this.writeToLogs("Main loop runs...")
}
},
/******************** Settings handling ********************/
/**
* Handles changes in settings
*/
settingsUpdated: function() {
lastDayTime = suntimes.DAYPERIOD.NONE
this.updateLocation()
this.setImageToTime()
},
/**
* 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")
},
/******************** Other functions ********************/
/**
* 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();
this.writeToLogs("Set new image: " + imageURI)
},
/**
* 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.img_morning_twilight_times = convertToTimeString(timesArray[0][0]) + " - " + convertToTimeString(timesArray[0][1])
this.img_sunrise_times = convertToTimeString(timesArray[1][0]) + " - " + convertToTimeString(timesArray[1][1])
this.img_morning_times = convertToTimeString(timesArray[2][0]) + " - " + convertToTimeString(timesArray[2][1])
this.img_noon_times = convertToTimeString(timesArray[3][0]) + " - " + convertToTimeString(timesArray[3][1])
this.img_afternoon_times = convertToTimeString(timesArray[4][0]) + " - " + convertToTimeString(timesArray[4][1])
this.img_evening_times = convertToTimeString(timesArray[5][0]) + " - " + convertToTimeString(timesArray[5][1])
this.img_sunset_times = convertToTimeString(timesArray[6][0]) + " - " + convertToTimeString(timesArray[6][1])
this.img_night_twilight_times = convertToTimeString(timesArray[7][0]) + " - " + convertToTimeString(timesArray[7][1])
this.img_night_times = convertToTimeString(timesArray[8][0]) + " - " + convertToTimeString(timesArray[8][1])
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 () {
// Update the update information
lastLocationUpdate = new Date()
if (this.autolocation) {
let loc = location.estimateLocation()
this.latitude = loc["latitude"]
this.longitude = loc["longitude"]
this.etrLastUpdate = lastLocationUpdate.getHours() + ":" + lastLocationUpdate.getMinutes()
}
this.writeToLogs("Location updated")
},
/**
* Adding text to the logs
*
* @param {string} msg New message string
*/
writeToLogs: function(msg) {
this.tvLogs = communication.createLogs(this.tvLogs, msg)
}
}
/******************** Lifecycle ********************/
/**
* Lifecycle function on initialization
*
* @param {*} extensionMeta Metadata of the extension
*/
function init(extensionMeta) {
extension = new CinnamonDynamicWallpaperExtension(extensionMeta.uuid);
}
/**
* Lifecycle function on enable
*
* @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;
}
/**
* Lifecycle function on disable
*/
function disable() {
looping = false
}

View File

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

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

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

@@ -250,6 +250,18 @@
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">8</property> <property name="spacing">8</property>
<child>
<object class="GtkLabel" id="lb_times_1">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child> <child>
<object class="GtkImage" id="img_preview_1"> <object class="GtkImage" id="img_preview_1">
<property name="width-request">300</property> <property name="width-request">300</property>
@@ -263,7 +275,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@@ -275,7 +287,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>
@@ -317,6 +329,18 @@
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">8</property> <property name="spacing">8</property>
<child>
<object class="GtkLabel" id="lb_times_2">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child> <child>
<object class="GtkImage" id="img_preview_2"> <object class="GtkImage" id="img_preview_2">
<property name="width-request">300</property> <property name="width-request">300</property>
@@ -329,7 +353,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@@ -340,7 +364,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>
@@ -382,6 +406,18 @@
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">8</property> <property name="spacing">8</property>
<child>
<object class="GtkLabel" id="lb_times_3">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child> <child>
<object class="GtkImage" id="img_preview_3"> <object class="GtkImage" id="img_preview_3">
<property name="width-request">300</property> <property name="width-request">300</property>
@@ -394,7 +430,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@@ -406,7 +442,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>
@@ -448,6 +484,18 @@
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">8</property> <property name="spacing">8</property>
<child>
<object class="GtkLabel" id="lb_times_4">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child> <child>
<object class="GtkImage" id="img_preview_4"> <object class="GtkImage" id="img_preview_4">
<property name="width-request">300</property> <property name="width-request">300</property>
@@ -460,7 +508,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@@ -471,7 +519,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>
@@ -513,6 +561,18 @@
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">8</property> <property name="spacing">8</property>
<child>
<object class="GtkLabel" id="lb_times_5">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child> <child>
<object class="GtkImage" id="img_preview_5"> <object class="GtkImage" id="img_preview_5">
<property name="width-request">300</property> <property name="width-request">300</property>
@@ -525,7 +585,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@@ -537,7 +597,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>
@@ -579,6 +639,18 @@
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">8</property> <property name="spacing">8</property>
<child>
<object class="GtkLabel" id="lb_times_6">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child> <child>
<object class="GtkImage" id="img_preview_6"> <object class="GtkImage" id="img_preview_6">
<property name="width-request">300</property> <property name="width-request">300</property>
@@ -591,7 +663,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@@ -603,7 +675,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>
@@ -645,6 +717,18 @@
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">8</property> <property name="spacing">8</property>
<child>
<object class="GtkLabel" id="lb_times_7">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child> <child>
<object class="GtkImage" id="img_preview_7"> <object class="GtkImage" id="img_preview_7">
<property name="width-request">300</property> <property name="width-request">300</property>
@@ -657,7 +741,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@@ -669,7 +753,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>
@@ -711,6 +795,18 @@
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">8</property> <property name="spacing">8</property>
<child>
<object class="GtkLabel" id="lb_times_8">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child> <child>
<object class="GtkImage" id="img_preview_8"> <object class="GtkImage" id="img_preview_8">
<property name="width-request">300</property> <property name="width-request">300</property>
@@ -723,7 +819,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@@ -735,7 +831,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>
@@ -777,6 +873,18 @@
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">8</property> <property name="spacing">8</property>
<child>
<object class="GtkLabel" id="lb_times_9">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child> <child>
<object class="GtkImage" id="img_preview_9"> <object class="GtkImage" id="img_preview_9">
<property name="width-request">300</property> <property name="width-request">300</property>
@@ -789,7 +897,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@@ -801,7 +909,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>
@@ -853,7 +961,7 @@
<property name="window-position">center</property> <property name="window-position">center</property>
<property name="default-width">1024</property> <property name="default-width">1024</property>
<property name="default-height">768</property> <property name="default-height">768</property>
<property name="icon">../icons/icon.png</property> <property name="icon">../../icon.png</property>
<signal name="destroy" handler="onDestroy" swapped="no"/> <signal name="destroy" handler="onDestroy" swapped="no"/>
<child> <child>
<object class="GtkStack" id="stack_main"> <object class="GtkStack" id="stack_main">

View File

@@ -0,0 +1,6 @@
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,29 +1,39 @@
import gi, os, glob, json, shutil, enum, threading import gi, os, glob, json, shutil, threading, subprocess
from data.enum import Source
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GdkPixbuf from gi.repository import Gtk, GdkPixbuf
PROJECT_DIR = os.path.dirname(os.path.dirname(__file__)) + "/" CONFIGURATOR_DIR = os.path.dirname(os.path.abspath(__file__))
UI_PATH = PROJECT_DIR + "image-configurator/" + "image-configurator.glade" PROJECT_DIR = os.path.dirname(CONFIGURATOR_DIR) + "/"
UI_PATH = CONFIGURATOR_DIR + "/" + "image-configurator.glade"
IMAGE_DIR = PROJECT_DIR + "images/" IMAGE_DIR = PROJECT_DIR + "images/"
IMAGE_EXTRACT_DIR = IMAGE_DIR + "extracted/" IMAGE_EXTRACT_DIR = IMAGE_DIR + "extracted/"
IMAGE_SETS_DIR = IMAGE_DIR + "included_image_sets/" IMAGE_SETS_DIR = IMAGE_DIR + "included_image_sets/"
IMAGE_SELECTED_DIR = IMAGE_DIR + "selected/" IMAGE_SELECTED_DIR = IMAGE_DIR + "selected/"
IMAGE_DEFAULT_DIR = IMAGE_DIR + "default/"
PREF_PATH = os.path.expanduser("~") + \
"/.config/cinnamon/spices/cinnamon-dynamic-wallpaper@TobiZog/cinnamon-dynamic-wallpaper@TobiZog.json"
class Source(enum.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
class ImageConfigurator: class WindowHandler:
def __init__(self) -> None: def __init__(self, pref_path: str) -> None:
########### Class variables ########### ########### Class variables ###########
self.pref_vars = [ self.pref_path = pref_path
self.time_values = [
"etr_morning_twilight_times",
"etr_sunrise_times",
"etr_morning_times",
"etr_noon_times",
"etr_afternoon_times",
"etr_evening_times",
"etr_sunset_times",
"etr_night_twilight_times",
"etr_night_times"
]
self.img_values = [
"etr_img_morning_twilight", "etr_img_morning_twilight",
"etr_img_sunrise", "etr_img_sunrise",
"etr_img_morning", "etr_img_morning",
@@ -39,6 +49,8 @@ class ImageConfigurator:
"aurora", "aurora",
"beach", "beach",
"bitday", "bitday",
"cliffs",
"gradient",
"lakeside", "lakeside",
"mountains", "mountains",
"sahara" "sahara"
@@ -70,6 +82,18 @@ class ImageConfigurator:
self.lb_heic_file = self.builder.get_object("lb_heic_file") self.lb_heic_file = self.builder.get_object("lb_heic_file")
self.fc_heic_file = self.builder.get_object("fc_heic_file") self.fc_heic_file = self.builder.get_object("fc_heic_file")
self.lb_times = [
self.builder.get_object("lb_times_1"),
self.builder.get_object("lb_times_2"),
self.builder.get_object("lb_times_3"),
self.builder.get_object("lb_times_4"),
self.builder.get_object("lb_times_5"),
self.builder.get_object("lb_times_6"),
self.builder.get_object("lb_times_7"),
self.builder.get_object("lb_times_8"),
self.builder.get_object("lb_times_9")
]
self.img_previews = [ self.img_previews = [
self.builder.get_object("img_preview_1"), self.builder.get_object("img_preview_1"),
self.builder.get_object("img_preview_2"), self.builder.get_object("img_preview_2"),
@@ -107,7 +131,6 @@ class ImageConfigurator:
self.image_source = Source.SELECTED self.image_source = Source.SELECTED
# Load preferences # Load preferences
self.loadFromSettings() self.loadFromSettings()
@@ -127,8 +150,9 @@ class ImageConfigurator:
def loadFromSettings(self): def loadFromSettings(self):
""" Load preferences from the Cinnamon preference file """ Load preferences from the Cinnamon preference file
""" """
#try:
# Load the settings # Load the settings
with open(PREF_PATH, "r") as pref_file: with open(self.pref_path, "r") as pref_file:
pref_data = json.load(pref_file) pref_data = json.load(pref_file)
@@ -148,7 +172,9 @@ class ImageConfigurator:
self.cb_image_set.set_active(i) self.cb_image_set.set_active(i)
for i, val in enumerate(self.pref_vars): for i, val in enumerate(self.img_values):
# Bugfix: Load the images only, if there is choosen one
if pref_data[val]['value'] != None:
# Set the preview image # Set the preview image
self.changePreviewImage(i, IMAGE_SELECTED_DIR + pref_data[val]['value']) self.changePreviewImage(i, IMAGE_SELECTED_DIR + pref_data[val]['value'])
@@ -162,12 +188,16 @@ class ImageConfigurator:
else: else:
self.image_source = Source.SET self.image_source = Source.SET
# Print the times of the day
for i, val in enumerate(self.time_values):
self.lb_times[i].set_text(pref_data[val]['value'])
def writeToSettings(self): def writeToSettings(self):
""" Save preferences to the Cinnamon preference file """ Save preferences to the Cinnamon preference file
""" """
# Load the settings # Load the settings
with open(PREF_PATH, "r") as pref_file: with open(self.pref_path, "r") as pref_file:
pref_data = json.load(pref_file) pref_data = json.load(pref_file)
@@ -175,17 +205,19 @@ class ImageConfigurator:
if self.image_source == Source.SET: if self.image_source == Source.SET:
pref_data["etr_choosen_image_set"]["value"] = self.cb_image_set.get_active_text() pref_data["etr_choosen_image_set"]["value"] = self.cb_image_set.get_active_text()
for i, val in enumerate(self.pref_vars): for i, val in enumerate(self.img_values):
pref_data[val]['value'] = str(i + 1) + ".jpg" pref_data[val]['value'] = str(i + 1) + ".jpg"
else: else:
pref_data["etr_choosen_image_set"]["value"] = "custom" pref_data["etr_choosen_image_set"]["value"] = "custom"
for i, val in enumerate(self.pref_vars): for i, val in enumerate(self.img_values):
pref_data[val]['value'] = self.cb_previews[i].get_active_text() image_name = self.cb_previews[i].get_active_text()
pref_data[val]['value'] = image_name
# Write the settings # Write the settings
with open(PREF_PATH, "w") as pref_file: with open(self.pref_path, "w") as pref_file:
json.dump(pref_data, pref_file, separators=(',', ':'), indent=4) json.dump(pref_data, pref_file, separators=(',', ':'), indent=4)
@@ -218,7 +250,7 @@ class ImageConfigurator:
self.image_source = Source.EXTRACT self.image_source = Source.EXTRACT
self.wipeImages(Source.EXTRACT) self.wipeImages(Source.EXTRACT)
os.system("heif-convert " + imageURI + " " + IMAGE_EXTRACT_DIR + "/" + filename + ".jpg") os.system("heif-convert " + imageURI + " " + IMAGE_EXTRACT_DIR + filename + ".jpg")
self.createExtracted() self.createExtracted()
@@ -364,8 +396,3 @@ class ImageConfigurator:
""" UI signal if the window is closed by the user """ UI signal if the window is closed by the user
""" """
Gtk.main_quit() Gtk.main_quit()
if __name__ == "__main__":
ic = ImageConfigurator()
ic.showMainWindow()

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

View File

@@ -0,0 +1,84 @@
/**
* @name Cinnamon-Dynamic-Wallpaper
* @alias TobiZog
* @since 2023-08-25
*
* @description Handles communications with the user (notifications, logs)
*/
/******************** Imports ********************/
const St = imports.gi.St;
const Main = imports.ui.main;
const Util = imports.misc.util;
const MessageTray = imports.ui.messageTray;
/******************** Functions ********************/
/**
* 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
*/
function showNotification(title, text, showOpenSettings = false) {
let source = new MessageTray.Source(this.uuid);
// Parameter
let params = {
icon: new St.Icon({
icon_name: "icon",
icon_type: St.IconType.FULLCOLOR,
icon_size: source.ICON_SIZE
})
};
// The notification itself
let notification = new MessageTray.Notification(source, title, text, params);
// Display the "Open settings" button, if showOpenSettings
if (showOpenSettings) {
notification.addButton("open-settings", _("Open settings"));
notification.connect("action-invoked", () =>
Util.spawnCommandLine("xlet-settings extension " + UUID));
}
// Put all together
Main.messageTray.add(source);
// Display it
source.notify(notification);
}
/**
* Adding a message to the logs
*
* @param {string} logMsg New log message to add
*/
function createLogs(tvLogs, logMsg) {
/**
* Pad a number with leading zeros
*
* @param {number} num Number to format
* @param {number} size Final string length
*
* @returns String with defined length
*/
function pad(num, size) {
var s = "00" + num
return s.substring(s.length - size)
}
// Estimate date and time
let date = new Date()
let formattedDate = pad(date.getHours(), 2) + ":" + pad(date.getMinutes(), 2) + ":" + pad(date.getSeconds(), 2)
// Add the the logs
return formattedDate + "\t" + logMsg + "\n" + tvLogs
}

View File

@@ -0,0 +1,31 @@
/**
* @name Cinnamon-Dynamic-Wallpaper
* @alias TobiZog
* @since 2023
*
* @description Functions to estimate the user location
*/
/******************** Imports ********************/
const Soup = imports.gi.Soup;
/******************** Functions ********************/
/**
* Estimate the location of the user
*
* @returns Location data if succeded or -1 if failed
*/
function estimateLocation() {
let sessionSync = new Soup.SessionSync();
let msg = Soup.Message.new('GET', "https://get.geojs.io/v1/ip/geo.json");
sessionSync.send_message(msg);
if (msg.status_code == 200) {
return JSON.parse(msg.response_body.data);
} else {
return -1;
}
}

View File

@@ -2,8 +2,12 @@
* @name Cinnamon-Dynamic-Wallpaper * @name Cinnamon-Dynamic-Wallpaper
* @alias TobiZog * @alias TobiZog
* @since 2023 * @since 2023
*
* @description Functions to calculate sun time periods
*/ */
/******************** Constants ********************/
const DAYPERIOD = { const DAYPERIOD = {
MTWILIGHT: 0, MTWILIGHT: 0,
SUNRISE: 1, SUNRISE: 1,
@@ -22,6 +26,9 @@ const J1970 = 2440588
const J2000 = 2451545 const J2000 = 2451545
/******************** Functions ********************/
function fromJulian(j) { function fromJulian(j) {
let ms_date = (j + 0.5 - J1970) * DAYMS let ms_date = (j + 0.5 - J1970) * DAYMS
return new Date(ms_date) return new Date(ms_date)
@@ -83,6 +90,14 @@ function subTimesToMinutes(date1, date2) {
} }
/**
* Calculating the start and end time of all time periods of the day
*
* @param {float} latitude Location latitude
* @param {float} longitude Location longitude
*
* @returns JSON of time periods
*/
function calcTimePeriod(latitude, longitude) { function calcTimePeriod(latitude, longitude) {
let todaySunEventsDay = sunEventsOfDay(latitude, longitude, Date.now()) let todaySunEventsDay = sunEventsOfDay(latitude, longitude, Date.now())
let tomorrowSunEventsDay = sunEventsOfDay(latitude, longitude, addMinutesToTime(new Date(), 1440)) let tomorrowSunEventsDay = sunEventsOfDay(latitude, longitude, addMinutesToTime(new Date(), 1440))

View File

@@ -3,8 +3,12 @@
"type": "layout", "type": "layout",
"pages": [ "pages": [
"pg_config", "pg_config",
"pg_logs",
"pg_about" "pg_about"
], ],
"pg_config": { "pg_config": {
"type": "page", "type": "page",
"title": "Configuration", "title": "Configuration",
@@ -14,6 +18,14 @@
"sec_times" "sec_times"
] ]
}, },
"pg_logs": {
"type": "page",
"title": "Debugging",
"sections": [
"sec_logs",
"sec_report_issue"
]
},
"pg_about": { "pg_about": {
"type": "page", "type": "page",
"title": "About", "title": "About",
@@ -22,12 +34,16 @@
"sec_github" "sec_github"
] ]
}, },
"sec_image_configuration": { "sec_image_configuration": {
"type": "section", "type": "section",
"title": "Image set", "title": "Image set",
"keys": [ "keys": [
"lb_image_configuration", "lb_image_configuration",
"btn_config_images" "btn_config_images",
"sw_image_stretch"
] ]
}, },
"sec_location": { "sec_location": {
@@ -36,6 +52,7 @@
"keys": [ "keys": [
"sw_auto_location", "sw_auto_location",
"sc_location_refresh_time", "sc_location_refresh_time",
"etr_last_update",
"etr_latitude", "etr_latitude",
"etr_longitude" "etr_longitude"
] ]
@@ -47,12 +64,34 @@
"tv_times" "tv_times"
] ]
}, },
"sec_logs": {
"type": "section",
"title": "Logs",
"keys": [
"tv_log_description",
"tv_logs"
]
},
"sec_report_issue": {
"type": "section",
"title": "Report an issue",
"keys": [
"lb_report_issue",
"btn_report_issue"
]
},
"sec_project": { "sec_project": {
"type": "section", "type": "section",
"title": "About the project", "title": "About the project",
"keys": [ "keys": [
"lb_about", "lb_about",
"lb_author" "lb_author",
"lb_spices",
"btn_spices"
] ]
}, },
"sec_github": { "sec_github": {
@@ -64,6 +103,9 @@
] ]
} }
}, },
"lb_image_configuration": { "lb_image_configuration": {
"type": "label", "type": "label",
"description": "Choose an included image set or import a heic-file with the Image Configurator" "description": "Choose an included image set or import a heic-file with the Image Configurator"
@@ -73,6 +115,12 @@
"description": "Image Configurator", "description": "Image Configurator",
"callback": "openImageConfigurator" "callback": "openImageConfigurator"
}, },
"sw_image_stretch": {
"type": "switch",
"description": "Expand image over all displays",
"default": false
},
"sw_auto_location": { "sw_auto_location": {
"type": "switch", "type": "switch",
"default": true, "default": true,
@@ -87,6 +135,12 @@
"description": "Interval time to refresh the location via network (min)", "description": "Interval time to refresh the location via network (min)",
"dependency": "sw_auto_location" "dependency": "sw_auto_location"
}, },
"etr_last_update": {
"type": "entry",
"description": "Last location update",
"default": "",
"dependency": "sw_auto_location"
},
"etr_latitude": { "etr_latitude": {
"type": "entry", "type": "entry",
"default": "", "default": "",
@@ -99,11 +153,36 @@
"description": "Longitude", "description": "Longitude",
"dependency": "!sw_auto_location" "dependency": "!sw_auto_location"
}, },
"tv_times": { "tv_times": {
"type": "textview", "type": "textview",
"description": "Time sections today", "description": "Time sections today",
"default": "" "default": ""
}, },
"tv_log_description": {
"type": "label",
"description": "Logs contains informations about time, date and successful or failed operations of the extension.",
"default": ""
},
"tv_logs": {
"type": "textview",
"description": "See all logs",
"default": ""
},
"lb_report_issue": {
"type": "label",
"description": "Do you find an issue? Or want a new feature? Go to the GitHub repository and create a new issue. If you find an error message in the logs above, add it to the issue report."
},
"btn_report_issue": {
"type": "button",
"description": "Submit an Issue",
"callback": "openIssueWebsite"
},
"lb_about": { "lb_about": {
"type": "label", "type": "label",
"description": "Based on a location, this extension calculates the periods of a day and switch the background image of your Cinnamon desktop. The extension offers the choice between a set of predownloaded wallpapers or to select a custom set of images." "description": "Based on a location, this extension calculates the periods of a day and switch the background image of your Cinnamon desktop. The extension offers the choice between a set of predownloaded wallpapers or to select a custom set of images."
@@ -112,6 +191,16 @@
"type": "label", "type": "label",
"description": "Developed by TobiZog" "description": "Developed by TobiZog"
}, },
"lb_spices": {
"type": "label",
"description": "If you want more information or rate the extension, you can visit the site Cinnamon Spices Website."
},
"btn_spices": {
"type": "button",
"description": "Cinnamon Dynamic Wallpaper at Cinnamon Spices Website",
"callback": "openSpicesWebsite"
},
"lb_repository": { "lb_repository": {
"type": "label", "type": "label",
"description": "This project is Open Source. You can visit the whole source code of this extension on GitHub" "description": "This project is Open Source. You can visit the whole source code of this extension on GitHub"
@@ -121,52 +210,106 @@
"description": "Open the Repository", "description": "Open the Repository",
"callback": "openRepoWebsite" "callback": "openRepoWebsite"
}, },
"etr_choosen_image_set": { "etr_choosen_image_set": {
"type": "entry", "type": "entry",
"default": "", "default": "lakeside",
"description": "" "description": ""
}, },
"etr_img_morning_twilight": { "etr_img_morning_twilight": {
"type": "entry", "type": "entry",
"default": "", "default": "1.jpg",
"description": "" "description": ""
}, },
"etr_img_sunrise": { "etr_img_sunrise": {
"type": "entry", "type": "entry",
"default": "", "default": "2.jpg",
"description": "" "description": ""
}, },
"etr_img_morning": { "etr_img_morning": {
"type": "entry", "type": "entry",
"default": "", "default": "3.jpg",
"description": "" "description": ""
}, },
"etr_img_noon": { "etr_img_noon": {
"type": "entry", "type": "entry",
"default": "", "default": "4.jpg",
"description": "" "description": ""
}, },
"etr_img_afternoon": { "etr_img_afternoon": {
"type": "entry", "type": "entry",
"default": "", "default": "5.jpg",
"description": "" "description": ""
}, },
"etr_img_evening": { "etr_img_evening": {
"type": "entry", "type": "entry",
"default": "", "default": "6.jpg",
"description": "" "description": ""
}, },
"etr_img_sunset": { "etr_img_sunset": {
"type": "entry", "type": "entry",
"default": "", "default": "7.jpg",
"description": "" "description": ""
}, },
"etr_img_night_twilight": { "etr_img_night_twilight": {
"type": "entry", "type": "entry",
"default": "", "default": "8.jpg",
"description": "" "description": ""
}, },
"etr_img_night": { "etr_img_night": {
"type": "entry",
"default": "9.jpg",
"description": ""
},
"first_start": {
"type": "generic",
"default": true
},
"etr_morning_twilight_times": {
"type": "entry",
"default": "",
"description": ""
},
"etr_sunrise_times": {
"type": "entry",
"default": "",
"description": ""
},
"etr_morning_times": {
"type": "entry",
"default": "",
"description": ""
},
"etr_noon_times": {
"type": "entry",
"default": "",
"description": ""
},
"etr_afternoon_times": {
"type": "entry",
"default": "",
"description": ""
},
"etr_evening_times": {
"type": "entry",
"default": "",
"description": ""
},
"etr_sunset_times": {
"type": "entry",
"default": "",
"description": ""
},
"etr_night_twilight_times": {
"type": "entry",
"default": "",
"description": ""
},
"etr_night_times": {
"type": "entry", "type": "entry",
"default": "", "default": "",
"description": "" "description": ""

View File

@@ -1,285 +0,0 @@
/**
* @name Cinnamon-Dynamic-Wallpaper
* @alias TobiZog
* @since 2023
*/
/******************** 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')
/******************** Constants ********************/
const UUID = "cinnamon-dynamic-wallpaper@TobiZog";
const APPNAME = "Cinnamon Dynamic Wallpaper"
const DIRECTORY = imports.ui.extensionSystem.extensionMeta[UUID];
const PATH = DIRECTORY.path;
/******************** Global Variables ********************/
// 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
let looping = true
/******************** Objects ********************/
function CinnamonDynamicWallpaperExtension(uuid) {
this._init(uuid);
}
CinnamonDynamicWallpaperExtension.prototype = {
/**
* Initialization
*
* @param {string} uuid Universally Unique Identifier
*/
_init: function(uuid) {
this.settings = new Settings.ExtensionSettings(this, uuid);
this.bindSettings("sw_auto_location", "autolocation", this.updateLocation)
this.bindSettings("sc_location_refresh_time", "locationRefreshTime")
this.bindSettings("etr_latitude", "latitude", this.updateLocation)
this.bindSettings("etr_longitude", "longitude", this.updateLocation)
this.bindSettings("etr_img_morning_twilight", "img_morning_twilight", this.setImageToTime)
this.bindSettings("etr_img_sunrise", "img_sunrise", this.setImageToTime)
this.bindSettings("etr_img_morning", "img_morning", this.setImageToTime)
this.bindSettings("etr_img_noon", "img_noon", this.setImageToTime)
this.bindSettings("etr_img_afternoon", "img_afternoon", this.setImageToTime)
this.bindSettings("etr_img_evening", "img_evening", this.setImageToTime)
this.bindSettings("etr_img_sunset", "img_sunset", this.setImageToTime)
this.bindSettings("etr_img_night_twilight", "img_night_twilight", this.setImageToTime)
this.bindSettings("etr_img_night", "img_night", this.setImageToTime)
this.bindSettings("tv_times", "tvTimes")
this.setImageToTime()
this._loop()
},
bindSettings: function (ui_name, js_name, func = this.on_settings_changed) {
this.settings.bindProperty(
Settings.BindingDirection.IN,
ui_name,
js_name,
func
)
},
/**
* 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) {
let source = new MessageTray.Source(this.uuid);
// Parameter
let params = {
icon: new St.Icon({
icon_name: "icon",
icon_type: St.IconType.FULLCOLOR,
icon_size: source.ICON_SIZE
})
};
// The notification itself
let notification = new MessageTray.Notification(source, title, text, params);
// Display the "Open settings" button, if showOpenSettings
if (showOpenSettings) {
notification.addButton("open-settings", _("Open settings"));
notification.connect("action-invoked", () =>
Util.spawnCommandLine("xlet-settings extension " + UUID));
}
// Put all together
Main.messageTray.add(source);
// 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);
Gio.Settings.sync();
gSetting.apply();
},
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) {
global.log(PATH + "/res/images/selected/" + imageSet[i])
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])
},
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
}
// Refresh the image information, if it's necessary
this.setImageToTime()
// Update the update information
lastLocationUpdate = new Date()
},
/******************** UI Callbacks ********************/
/**
* Callback for settings-schema
* Opens the external heic-importer window
*/
openImageConfigurator: function() {
Util.spawnCommandLine("/usr/bin/env python3 " + DIRECTORY.path + "/image-configurator/image-configurator.py");
},
/**
* Callback for settings-schema
* Opens the browser and navigate to the URL of the respository
*/
openRepoWebsite: function() {
Util.spawnCommandLine("xdg-open https://github.com/TobiZog/cinnamon-dynamic-wallpaper");
},
/**
* 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));
}
}
}
/******************** Lifecycle ********************/
/**
* Lifecycle function on initialization
*
* @param {*} extensionMeta Metadata of the extension
*/
function init(extensionMeta) {
extension = new CinnamonDynamicWallpaperExtension(extensionMeta.uuid);
}
/**
* Lifecycle function on enable
*
* @returns The extension object
*/
function enable() {
// Check for necessary software
if (!find_program_in_path('heif-convert')) {
Util.spawnCommandLine("apturl apt://libheif-examples");
}
// Display the welcome notification on activation
// extension.showNotification(
// APPNAME,
// "Welcome to " + APPNAME + "! Open the settings and configure the extensions.",
// true
// );
return extension;
}
/**
* Lifecycle function on disable
*/
function disable() {
looping = false
}

View File

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

View File

@@ -2,9 +2,15 @@
"uuid": "cinnamon-dynamic-wallpaper@TobiZog", "uuid": "cinnamon-dynamic-wallpaper@TobiZog",
"name": "Cinnamon Dynamic Wallpaper", "name": "Cinnamon Dynamic Wallpaper",
"description": "Cinnamon extension for dynamic desktop backgrounds based on time and location", "description": "Cinnamon extension for dynamic desktop backgrounds based on time and location",
"version": "1.0", "version": "1.4",
"multiversion": true,
"cinnamon-version": [ "cinnamon-version": [
"5.6" "4.8",
"5.0",
"5.2",
"5.4",
"5.6",
"5.8"
], ],
"max-instances": 1, "max-instances": 1,
"url": "https://github.com/TobiZog/cinnamon-dynamic-wallpaper" "url": "https://github.com/TobiZog/cinnamon-dynamic-wallpaper"

View File

@@ -1,14 +0,0 @@
const Soup = imports.gi.Soup;
function estimateLocation() {
let sessionSync = new Soup.SessionSync();
let msg = Soup.Message.new('GET', "https://get.geojs.io/v1/ip/geo.json");
sessionSync.send_message(msg);
if (msg.status_code == 200) {
return JSON.parse(msg.response_body.data);
} else {
return -1;
}
}

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