Bind settings window to Cinnamon Spiced pref button

This commit is contained in:
2023-12-23 14:02:31 +01:00
parent 132b33bdf8
commit 7c5e86e8dc
12 changed files with 3603 additions and 634 deletions

View File

@@ -15,9 +15,9 @@ const Lang = imports.lang;
const { find_program_in_path } = imports.gi.GLib; const { find_program_in_path } = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
let suntimes = require('./scripts/suntimes') // let suntimes = require('./scripts/suntimes')
let location = require('./scripts/location') // let location = require('./scripts/location')
let communication = require('./scripts/communication') // let communication = require('./scripts/communication')
/******************** Constants ********************/ /******************** Constants ********************/
@@ -64,44 +64,38 @@ CinnamonDynamicWallpaperExtension.prototype = {
/** Configuration */ /** Configuration */
// Image set // Image set
this.bindSettings("sw_image_stretch", "imageStretch", this.settingsUpdated) // this.bindSettings("sw_image_stretch", "imageStretch", this.settingsUpdated)
// Location estimation // // Location estimation
this.bindSettings("sw_auto_location", "autolocation", this.settingsUpdated) // this.bindSettings("sw_auto_location", "autolocation", this.settingsUpdated)
this.bindSettings("sc_location_refresh_time", "locationRefreshTime", this.settingsUpdated) // this.bindSettings("sc_location_refresh_time", "locationRefreshTime", this.settingsUpdated)
this.bindSettings("etr_last_update", "etrLastUpdate") // this.bindSettings("etr_last_update", "etrLastUpdate")
this.bindSettings("etr_latitude", "latitude", this.settingsUpdated) // this.bindSettings("etr_latitude", "latitude", this.settingsUpdated)
this.bindSettings("etr_longitude", "longitude", this.settingsUpdated) // this.bindSettings("etr_longitude", "longitude", this.settingsUpdated)
// Time periods
this.bindSettings("tv_times", "tvTimes")
/** Debugging */
// Logs
this.bindSettings("tv_logs", "tvLogs")
// // Time periods
// this.bindSettings("tv_times", "tvTimes")
// Image Configurator // Image Configurator
this.bindSettings("etr_img_morning_twilight", "img_morning_twilight", this.settingsUpdated) // this.bindSettings("etr_img_morning_twilight", "img_morning_twilight", this.settingsUpdated)
this.bindSettings("etr_img_sunrise", "img_sunrise", this.settingsUpdated) // this.bindSettings("etr_img_sunrise", "img_sunrise", this.settingsUpdated)
this.bindSettings("etr_img_morning", "img_morning", this.settingsUpdated) // this.bindSettings("etr_img_morning", "img_morning", this.settingsUpdated)
this.bindSettings("etr_img_noon", "img_noon", this.settingsUpdated) // this.bindSettings("etr_img_noon", "img_noon", this.settingsUpdated)
this.bindSettings("etr_img_afternoon", "img_afternoon", this.settingsUpdated) // this.bindSettings("etr_img_afternoon", "img_afternoon", this.settingsUpdated)
this.bindSettings("etr_img_evening", "img_evening", this.settingsUpdated) // this.bindSettings("etr_img_evening", "img_evening", this.settingsUpdated)
this.bindSettings("etr_img_sunset", "img_sunset", 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_twilight", "img_night_twilight", this.settingsUpdated)
this.bindSettings("etr_img_night", "img_night", this.settingsUpdated) // this.bindSettings("etr_img_night", "img_night", this.settingsUpdated)
this.bindSettings("etr_morning_twilight_times", "img_morning_twilight_times") // this.bindSettings("etr_morning_twilight_times", "img_morning_twilight_times")
this.bindSettings("etr_sunrise_times", "img_sunrise_times") // this.bindSettings("etr_sunrise_times", "img_sunrise_times")
this.bindSettings("etr_morning_times", "img_morning_times") // this.bindSettings("etr_morning_times", "img_morning_times")
this.bindSettings("etr_noon_times", "img_noon_times") // this.bindSettings("etr_noon_times", "img_noon_times")
this.bindSettings("etr_afternoon_times", "img_afternoon_times") // this.bindSettings("etr_afternoon_times", "img_afternoon_times")
this.bindSettings("etr_evening_times", "img_evening_times") // this.bindSettings("etr_evening_times", "img_evening_times")
this.bindSettings("etr_sunset_times", "img_sunset_times") // this.bindSettings("etr_sunset_times", "img_sunset_times")
this.bindSettings("etr_night_twilight_times", "img_night_twilight_times") // this.bindSettings("etr_night_twilight_times", "img_night_twilight_times")
this.bindSettings("etr_night_times", "img_night_times") // this.bindSettings("etr_night_times", "img_night_times")
// Check for the first startup // Check for the first startup
@@ -126,10 +120,8 @@ CinnamonDynamicWallpaperExtension.prototype = {
} }
} }
this.writeToLogs("Initialization completed")
// Set image initial at desktop wallpaper // Set image initial at desktop wallpaper
this.setImageToTime() //this.setImageToTime()
// Start the main loop, checks in fixed time periods the // Start the main loop, checks in fixed time periods the
this._loop() this._loop()
@@ -158,7 +150,7 @@ CinnamonDynamicWallpaperExtension.prototype = {
*/ */
_loop: function () { _loop: function () {
if (looping) { if (looping) {
this.setImageToTime() //this.setImageToTime()
// Update the location, if the user choose "autoLocation" and the timer has expired // Update the location, if the user choose "autoLocation" and the timer has expired
if ((lastLocationUpdate == -1 || if ((lastLocationUpdate == -1 ||
@@ -171,60 +163,10 @@ CinnamonDynamicWallpaperExtension.prototype = {
// Refresh every 60 seconds // Refresh every 60 seconds
Mainloop.timeout_add_seconds(60, Lang.bind(this, this._loop)); 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 ********************/ /******************** Other functions ********************/
/** /**
@@ -246,8 +188,6 @@ CinnamonDynamicWallpaperExtension.prototype = {
Gio.Settings.sync(); Gio.Settings.sync();
gSetting.apply(); gSetting.apply();
this.writeToLogs("Set new image: " + imageURI)
}, },
@@ -321,18 +261,7 @@ CinnamonDynamicWallpaperExtension.prototype = {
this.etrLastUpdate = lastLocationUpdate.getHours() + ":" + lastLocationUpdate.getMinutes() 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)
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@@ -1,41 +1,41 @@
class PrefenceEnums(enumerate): class PrefenceEnums(enumerate):
EXPANDOVERALLDISPLAY = "expand_over_all_displays" EXPAND_OVER_ALL_DISPLAY = "expand_over_all_displays"
SHOWONLOCKSCREEN = "show_on_lock_screen" SHOW_ON_LOCK_SCREEN = "show_on_lock_screen"
# Which type of image source will be used # Which type of image source will be used
# image_set, heic_file, source_folder # image_set, heic_file, source_folder
IMAGESOURCE = "image_source" IMAGE_SOURCE = "image_source"
SELECTEDIMAGESET = "selected_image_set" SELECTED_IMAGE_SET = "selected_image_set"
SELECTEDSOURCEFOLDER = "selected_source_folder" SELECTED_SOURCE_FOLDER = "selected_source_folder"
PERIOD1IMAGE = "period_1_image" PERIOD_0_IMAGE = "period_0_image"
PERIOD2IMAGE = "period_2_image" PERIOD_1_IMAGE = "period_1_image"
PERIOD3IMAGE = "period_3_image" PERIOD_2_IMAGE = "period_2_image"
PERIOD4IMAGE = "period_4_image" PERIOD_3_IMAGE = "period_3_image"
PERIOD5IMAGE = "period_5_image" PERIOD_4_IMAGE = "period_4_image"
PERIOD6IMAGE = "period_6_image" PERIOD_5_IMAGE = "period_5_image"
PERIOD7IMAGE = "period_7_image" PERIOD_6_IMAGE = "period_6_image"
PERIOD8IMAGE = "period_8_image" PERIOD_7_IMAGE = "period_7_image"
PERIOD9IMAGE = "period_9_image" PERIOD_8_IMAGE = "period_8_image"
PERIOD10IMAGE = "period_10_image" PERIOD_9_IMAGE = "period_9_image"
# How the period will estimage # How the period will estimage
# network_location, custom_location, custom_time_periods # network_location, custom_location, custom_time_periods
PERIODSOURCE = "period_source" PERIOD_SOURCE = "period_source"
LOCATIONREFRESHINTERVALS = "location_refresh_intervals" LOCATION_REFRESH_INTERVALS = "location_refresh_intervals"
LATITUDE = "latitude" LATITUDE = "latitude"
LONGITUDE = "longitude" LONGITUDE = "longitude"
PERIOD1STARTTIME = "period_1_start_time" PERIOD_0_STARTTIME = "period_0_start_time"
PERIOD2STARTTIME = "period_2_start_time" PERIOD_1_STARTTIME = "period_1_start_time"
PERIOD3STARTTIME = "period_3_start_time" PERIOD_2_STARTTIME = "period_2_start_time"
PERIOD4STARTTIME = "period_4_start_time" PERIOD_3_STARTTIME = "period_3_start_time"
PERIOD5STARTTIME = "period_5_start_time" PERIOD_4_STARTTIME = "period_4_start_time"
PERIOD6STARTTIME = "period_6_start_time" PERIOD_5_STARTTIME = "period_5_start_time"
PERIOD7STARTTIME = "period_7_start_time" PERIOD_6_STARTTIME = "period_6_start_time"
PERIOD8STARTTIME = "period_8_start_time" PERIOD_7_STARTTIME = "period_7_start_time"
PERIOD9STARTTIME = "period_9_start_time" PERIOD_8_STARTTIME = "period_8_start_time"
PERIOD10STARTTIME = "period_10_start_time" PERIOD_9_STARTTIME = "period_9_start_time"

View File

@@ -31,7 +31,7 @@
<property name="default-height">400</property> <property name="default-height">400</property>
<property name="icon">../icon.svg</property> <property name="icon">../icon.svg</property>
<property name="gravity">center</property> <property name="gravity">center</property>
<signal name="destroy" handler="onDestroy" swapped="no"/> <signal name="destroy" handler="on_destroy" swapped="no"/>
<child> <child>
<object class="GtkStack" id="stack_main"> <object class="GtkStack" id="stack_main">
<property name="visible">True</property> <property name="visible">True</property>
@@ -76,7 +76,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">True</property> <property name="receives-default">True</property>
<signal name="clicked" handler="onToggleButtonImageSetClicked" swapped="no"/> <signal name="clicked" handler="on_toggle_button_image_set_clicked" swapped="no"/>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
@@ -126,7 +126,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">True</property> <property name="receives-default">True</property>
<signal name="clicked" handler="onToggleButtonHeicFileClicked" swapped="no"/> <signal name="clicked" handler="on_toggle_button_heic_file_clicked" swapped="no"/>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
@@ -176,7 +176,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">True</property> <property name="receives-default">True</property>
<signal name="clicked" handler="onToggleButtonSourceFolderClicked" swapped="no"/> <signal name="clicked" handler="on_toggle_button_source_folder_clicked" swapped="no"/>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
@@ -979,7 +979,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">True</property> <property name="receives-default">True</property>
<signal name="clicked" handler="onToggleButtonNetworkLocationClicked" swapped="no"/> <signal name="clicked" handler="on_toggle_button_network_location_clicked" swapped="no"/>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
@@ -1031,7 +1031,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">True</property> <property name="receives-default">True</property>
<signal name="clicked" handler="onToggleButtonCustomLocationClicked" swapped="no"/> <signal name="clicked" handler="on_toggle_button_custom_location_clicked" swapped="no"/>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
@@ -1081,7 +1081,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">True</property> <property name="receives-default">True</property>
<signal name="clicked" handler="onToggleButtonTimePeriodsClicked" swapped="no"/> <signal name="clicked" handler="on_toggle_button_time_periods_clicked" swapped="no"/>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
@@ -1191,47 +1191,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="adjustment">adjustment1</property> <property name="adjustment">adjustment1</property>
</object> <signal name="changed" handler="on_spb_network_location_refresh_time_changed" swapped="no"/>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="lbr_custom_location_latitude">
<property name="visible">True</property>
<property name="can-focus">True</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="homogeneous">True</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Latitude</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="etr_latitude">
<property name="visible">True</property>
<property name="can-focus">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@@ -1273,6 +1233,50 @@
<object class="GtkEntry" id="etr_longitude"> <object class="GtkEntry" id="etr_longitude">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<signal name="changed" handler="on_etr_longitude_changed" 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>
<object class="GtkListBoxRow" id="lbr_custom_location_latitude">
<property name="visible">True</property>
<property name="can-focus">True</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="homogeneous">True</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Latitude</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="etr_latitude">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="input-purpose">number</property>
<signal name="changed" handler="on_etr_latitude_changed" swapped="no"/>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@@ -2380,7 +2384,7 @@
<property name="margin-end">12</property> <property name="margin-end">12</property>
<property name="margin-top">12</property> <property name="margin-top">12</property>
<property name="margin-bottom">12</property> <property name="margin-bottom">12</property>
<signal name="clicked" handler="onCinnamonSpicesWebsiteButtonClicked" swapped="no"/> <signal name="clicked" handler="on_cinnamon_spices_website_button_clicked" swapped="no"/>
</object> </object>
</child> </child>
</object> </object>
@@ -2448,7 +2452,7 @@
<property name="margin-end">12</property> <property name="margin-end">12</property>
<property name="margin-top">12</property> <property name="margin-top">12</property>
<property name="margin-bottom">12</property> <property name="margin-bottom">12</property>
<signal name="clicked" handler="onGithubWebsiteButtonClicked" swapped="no"/> <signal name="clicked" handler="on_github_website_button_clicked" swapped="no"/>
</object> </object>
</child> </child>
</object> </object>
@@ -2518,7 +2522,7 @@
<property name="margin-end">12</property> <property name="margin-end">12</property>
<property name="margin-top">12</property> <property name="margin-top">12</property>
<property name="margin-bottom">12</property> <property name="margin-bottom">12</property>
<signal name="clicked" handler="onCreateIssueButtonClicked" swapped="no"/> <signal name="clicked" handler="on_create_issue_button_clicked" swapped="no"/>
</object> </object>
</child> </child>
</object> </object>
@@ -2561,7 +2565,7 @@
<property name="double-buffered">False</property> <property name="double-buffered">False</property>
<property name="use-stock">True</property> <property name="use-stock">True</property>
<property name="always-show-image">True</property> <property name="always-show-image">True</property>
<signal name="clicked" handler="onApply" swapped="no"/> <signal name="clicked" handler="on_apply" swapped="no"/>
</object> </object>
</child> </child>
</object> </object>

View File

@@ -5,6 +5,7 @@ import gi, os, subprocess
from scripts.time_bar import create_bar_chart from scripts.time_bar import create_bar_chart
from scripts.cinnamon_pref_handler import * from scripts.cinnamon_pref_handler import *
from scripts.suntimes import * from scripts.suntimes import *
from scripts.location import *
from enums.PreferenceEnums import PrefenceEnums from enums.PreferenceEnums import PrefenceEnums
from enums.ImageSourceEnum import ImageSourceEnum from enums.ImageSourceEnum import ImageSourceEnum
from enums.PeriodSourceEnum import PeriodSourceEnum from enums.PeriodSourceEnum import PeriodSourceEnum
@@ -17,6 +18,8 @@ from gi.repository import Gtk, GdkPixbuf
GLADE_URI = os.path.dirname(os.path.abspath(__file__)) + "/preferences.glade" GLADE_URI = os.path.dirname(os.path.abspath(__file__)) + "/preferences.glade"
class Preferences: class Preferences:
""" Preference window class """ Preference window class
""" """
@@ -28,21 +31,55 @@ class Preferences:
self.builder.add_from_file(GLADE_URI) self.builder.add_from_file(GLADE_URI)
self.builder.connect_signals(self) self.builder.connect_signals(self)
self.suntimes = Suntimes(48.1663, 11.5683) # Load all settings from file
self.settings_dict = {
PrefenceEnums.EXPAND_OVER_ALL_DISPLAY: read_str_from_preferences(PrefenceEnums.EXPAND_OVER_ALL_DISPLAY),
PrefenceEnums.SHOW_ON_LOCK_SCREEN: read_str_from_preferences(PrefenceEnums.SHOW_ON_LOCK_SCREEN),
PrefenceEnums.IMAGE_SOURCE: read_str_from_preferences(PrefenceEnums.IMAGE_SOURCE),
PrefenceEnums.SELECTED_IMAGE_SET: read_str_from_preferences(PrefenceEnums.SELECTED_IMAGE_SET),
PrefenceEnums.PERIOD_0_IMAGE: read_str_from_preferences(PrefenceEnums.PERIOD_0_IMAGE),
PrefenceEnums.PERIOD_1_IMAGE: read_str_from_preferences(PrefenceEnums.PERIOD_1_IMAGE),
PrefenceEnums.PERIOD_2_IMAGE: read_str_from_preferences(PrefenceEnums.PERIOD_2_IMAGE),
PrefenceEnums.PERIOD_3_IMAGE: read_str_from_preferences(PrefenceEnums.PERIOD_3_IMAGE),
PrefenceEnums.PERIOD_4_IMAGE: read_str_from_preferences(PrefenceEnums.PERIOD_4_IMAGE),
PrefenceEnums.PERIOD_5_IMAGE: read_str_from_preferences(PrefenceEnums.PERIOD_5_IMAGE),
PrefenceEnums.PERIOD_6_IMAGE: read_str_from_preferences(PrefenceEnums.PERIOD_6_IMAGE),
PrefenceEnums.PERIOD_7_IMAGE: read_str_from_preferences(PrefenceEnums.PERIOD_7_IMAGE),
PrefenceEnums.PERIOD_8_IMAGE: read_str_from_preferences(PrefenceEnums.PERIOD_8_IMAGE),
PrefenceEnums.PERIOD_9_IMAGE: read_str_from_preferences(PrefenceEnums.PERIOD_9_IMAGE),
PrefenceEnums.PERIOD_SOURCE: read_str_from_preferences(PrefenceEnums.PERIOD_SOURCE),
PrefenceEnums.LOCATION_REFRESH_INTERVALS: read_int_from_preferences(PrefenceEnums.LOCATION_REFRESH_INTERVALS),
PrefenceEnums.LATITUDE: read_float_from_preferences(PrefenceEnums.LATITUDE),
PrefenceEnums.LONGITUDE: read_float_from_preferences(PrefenceEnums.LONGITUDE),
PrefenceEnums.PERIOD_0_STARTTIME: read_str_from_preferences(PrefenceEnums.PERIOD_0_STARTTIME),
PrefenceEnums.PERIOD_1_STARTTIME: read_str_from_preferences(PrefenceEnums.PERIOD_1_STARTTIME),
PrefenceEnums.PERIOD_2_STARTTIME: read_str_from_preferences(PrefenceEnums.PERIOD_2_STARTTIME),
PrefenceEnums.PERIOD_3_STARTTIME: read_str_from_preferences(PrefenceEnums.PERIOD_3_STARTTIME),
PrefenceEnums.PERIOD_4_STARTTIME: read_str_from_preferences(PrefenceEnums.PERIOD_4_STARTTIME),
PrefenceEnums.PERIOD_5_STARTTIME: read_str_from_preferences(PrefenceEnums.PERIOD_5_STARTTIME),
PrefenceEnums.PERIOD_6_STARTTIME: read_str_from_preferences(PrefenceEnums.PERIOD_6_STARTTIME),
PrefenceEnums.PERIOD_7_STARTTIME: read_str_from_preferences(PrefenceEnums.PERIOD_7_STARTTIME),
PrefenceEnums.PERIOD_8_STARTTIME: read_str_from_preferences(PrefenceEnums.PERIOD_8_STARTTIME),
PrefenceEnums.PERIOD_9_STARTTIME: read_str_from_preferences(PrefenceEnums.PERIOD_9_STARTTIME),
}
# Suntimes object
self.suntimes = Suntimes(self.settings_dict[PrefenceEnums.LATITUDE], self.settings_dict[PrefenceEnums.LONGITUDE])
########## UI objects ########## ########## UI objects ##########
## Image Configuration ## Image Configuration
self.tbImageSet = self.builder.get_object("tb_image_set") self.tb_image_set = self.builder.get_object("tb_image_set")
self.tbHeicFile = self.builder.get_object("tb_heic_file") self.tb_heic_file = self.builder.get_object("tb_heic_file")
self.tbSourceFolder = self.builder.get_object("tb_source_folder") self.tb_source_folder = self.builder.get_object("tb_source_folder")
self.lbrImageSet = self.builder.get_object("lbr_image_set") self.lbr_image_set = self.builder.get_object("lbr_image_set")
self.lbrHeicFile = self.builder.get_object("lbr_heic_file") self.lbr_heic_file = self.builder.get_object("lbr_heic_file")
self.lbrSourceFolder = self.builder.get_object("lbr_source_folder") self.lbr_source_folder = self.builder.get_object("lbr_source_folder")
self.imgBar = self.builder.get_object("img_bar") self.img_bar = self.builder.get_object("img_bar")
self.swExpandOverAllDisplays = self.builder.get_object("sw_expand_over_all_displays") self.sw_expand_over_all_displays = self.builder.get_object("sw_expand_over_all_displays")
self.swShowOnLockScreen = self.builder.get_object("sw_show_on_lock_screen") self.sw_show_on_lock_screen = self.builder.get_object("sw_show_on_lock_screen")
self.etr_periods = [ self.etr_periods = [
self.builder.get_object("etr_period_1"), self.builder.get_object("etr_period_2"), self.builder.get_object("etr_period_1"), self.builder.get_object("etr_period_2"),
self.builder.get_object("etr_period_3"), self.builder.get_object("etr_period_4"), self.builder.get_object("etr_period_3"), self.builder.get_object("etr_period_4"),
@@ -52,16 +89,16 @@ class Preferences:
] ]
## Location & Times ## Location & Times
self.tbNetworkLocation = self.builder.get_object("tb_network_location") self.tb_network_location = self.builder.get_object("tb_network_location")
self.tbCustomLocation = self.builder.get_object("tb_custom_location") self.tb_custom_location = self.builder.get_object("tb_custom_location")
self.tbTimePeriods = self.builder.get_object("tb_time_periods") self.tb_time_periods = self.builder.get_object("tb_time_periods")
self.lbrNetworkLocation = self.builder.get_object("lbr_network_location") self.lbr_network_location = self.builder.get_object("lbr_network_location")
self.spbNetworkLocationRefreshTime = self.builder.get_object("spb_network_location_refresh_time") self.spb_network_location_refresh_time = self.builder.get_object("spb_network_location_refresh_time")
self.lbrCustomLocationLongitude = self.builder.get_object("lbr_custom_location_longitude") self.lbr_custom_location_longitude = self.builder.get_object("lbr_custom_location_longitude")
self.lbrCustomLocationLatitude = self.builder.get_object("lbr_custom_location_latitude") self.lbr_custom_location_latitude = self.builder.get_object("lbr_custom_location_latitude")
self.lbrTimePeriods = self.builder.get_object("lbr_time_periods") self.lbr_time_periods = self.builder.get_object("lbr_time_periods")
self.etrLongitude = self.builder.get_object("etr_longitude") self.etr_longitude = self.builder.get_object("etr_longitude")
self.etrLatitude = self.builder.get_object("etr_latitude") self.etr_latitude = self.builder.get_object("etr_latitude")
def show(self): def show(self):
@@ -72,27 +109,27 @@ class Preferences:
# Load from preferences # Load from preferences
if read_str_from_preferences(PrefenceEnums.IMAGESOURCE) == ImageSourceEnum.IMAGESET: if self.settings_dict[PrefenceEnums.IMAGE_SOURCE] == ImageSourceEnum.IMAGESET:
self.tbImageSet.set_active(True) self.tb_image_set.set_active(True)
elif read_str_from_preferences(PrefenceEnums.IMAGESOURCE) == ImageSourceEnum.HEICFILE: elif self.settings_dict[PrefenceEnums.IMAGE_SOURCE] == ImageSourceEnum.HEICFILE:
self.tbHeicFile.set_active(True) self.tb_heic_file.set_active(True)
elif read_str_from_preferences(PrefenceEnums.IMAGESOURCE) == ImageSourceEnum.SOURCEFOLDER: elif self.settings_dict[PrefenceEnums.IMAGE_SOURCE] == ImageSourceEnum.SOURCEFOLDER:
self.tbSourceFolder.set_active(True) self.tb_source_folder.set_active(True)
self.swExpandOverAllDisplays.set_active(read_str_from_preferences(PrefenceEnums.EXPANDOVERALLDISPLAY)) self.sw_expand_over_all_displays.set_active(self.settings_dict[PrefenceEnums.EXPAND_OVER_ALL_DISPLAY])
self.swShowOnLockScreen.set_active(read_str_from_preferences(PrefenceEnums.SHOWONLOCKSCREEN)) self.sw_show_on_lock_screen.set_active(self.settings_dict[PrefenceEnums.SHOW_ON_LOCK_SCREEN])
if read_str_from_preferences(PrefenceEnums.PERIODSOURCE) == PeriodSourceEnum.NETWORKLOCATION: if self.settings_dict[PrefenceEnums.PERIOD_SOURCE] == PeriodSourceEnum.NETWORKLOCATION:
self.tbNetworkLocation.set_active(True) self.tb_network_location.set_active(True)
elif read_str_from_preferences(PrefenceEnums.PERIODSOURCE) == PeriodSourceEnum.CUSTOMLOCATION: elif self.settings_dict[PrefenceEnums.PERIOD_SOURCE] == PeriodSourceEnum.CUSTOMLOCATION:
self.tbCustomLocation.set_active(True) self.tb_custom_location.set_active(True)
elif read_str_from_preferences(PrefenceEnums.PERIODSOURCE) == PeriodSourceEnum.CUSTOMTIMEPERIODS: elif self.settings_dict[PrefenceEnums.PERIOD_SOURCE] == PeriodSourceEnum.CUSTOMTIMEPERIODS:
self.tbTimePeriods.set_active(True) self.tb_time_periods.set_active(True)
self.spbNetworkLocationRefreshTime.set_value(read_int_from_preferences(PrefenceEnums.LOCATIONREFRESHINTERVALS)) self.spb_network_location_refresh_time.set_value(read_int_from_preferences(PrefenceEnums.LOCATION_REFRESH_INTERVALS))
self.etrLatitude.set_text(read_str_from_preferences(PrefenceEnums.LATITUDE)) self.etr_latitude.set_text(str(self.settings_dict[PrefenceEnums.LATITUDE]))
self.etrLongitude.set_text(read_str_from_preferences(PrefenceEnums.LONGITUDE)) self.etr_longitude.set_text(str(self.settings_dict[PrefenceEnums.LONGITUDE]))
########## Time diagram ########## ########## Time diagram ##########
@@ -113,14 +150,14 @@ class Preferences:
# Load to the view # Load to the view
pixbuf = GdkPixbuf.Pixbuf.new_from_file("time_bar.svg") pixbuf = GdkPixbuf.Pixbuf.new_from_file("time_bar.svg")
self.imgBar.set_from_pixbuf(pixbuf) self.img_bar.set_from_pixbuf(pixbuf)
# Show the main window # Show the main window
Gtk.main() Gtk.main()
def onDestroy(self, *args): def on_destroy(self, *args):
""" Lifecycle handler when window will be destroyed """ Lifecycle handler when window will be destroyed
""" """
Gtk.main_quit() Gtk.main_quit()
@@ -130,105 +167,101 @@ class Preferences:
## Image Configuration ## Image Configuration
def onToggleButtonImageSetClicked(self, button): def on_toggle_button_image_set_clicked(self, button):
if button.get_active(): if button.get_active():
self.tbHeicFile.set_active(False) self.settings_dict[PrefenceEnums.IMAGE_SOURCE] = ImageSourceEnum.IMAGESET
self.tbSourceFolder.set_active(False) self.tb_heic_file.set_active(False)
self.tb_source_folder.set_active(False)
self.lbrImageSet.set_visible(True) self.lbr_image_set.set_visible(True)
self.lbrHeicFile.set_visible(False) self.lbr_heic_file.set_visible(False)
self.lbrSourceFolder.set_visible(False) self.lbr_source_folder.set_visible(False)
def onToggleButtonHeicFileClicked(self, button): def on_toggle_button_heic_file_clicked(self, button):
if button.get_active(): if button.get_active():
self.tbImageSet.set_active(False) self.settings_dict[PrefenceEnums.IMAGE_SOURCE] = ImageSourceEnum.HEICFILE
self.tbSourceFolder.set_active(False) self.tb_image_set.set_active(False)
self.tb_source_folder.set_active(False)
self.lbrImageSet.set_visible(False) self.lbr_image_set.set_visible(False)
self.lbrHeicFile.set_visible(True) self.lbr_heic_file.set_visible(True)
self.lbrSourceFolder.set_visible(False) self.lbr_source_folder.set_visible(False)
def onToggleButtonSourceFolderClicked(self, button): def on_toggle_button_source_folder_clicked(self, button):
if button.get_active(): if button.get_active():
self.tbImageSet.set_active(False) self.settings_dict[PrefenceEnums.IMAGE_SOURCE] = ImageSourceEnum.SOURCEFOLDER
self.tbHeicFile.set_active(False) self.tb_image_set.set_active(False)
self.tb_heic_file.set_active(False)
self.lbrImageSet.set_visible(False) self.lbr_image_set.set_visible(False)
self.lbrHeicFile.set_visible(False) self.lbr_heic_file.set_visible(False)
self.lbrSourceFolder.set_visible(True) self.lbr_source_folder.set_visible(True)
## Location & Times ## Location & Times
def onToggleButtonNetworkLocationClicked(self, button): def on_toggle_button_network_location_clicked(self, button):
if button.get_active(): if button.get_active():
self.tbCustomLocation.set_active(False) self.settings_dict[PrefenceEnums.PERIOD_SOURCE] = PeriodSourceEnum.NETWORKLOCATION
self.tbTimePeriods.set_active(False) self.tb_custom_location.set_active(False)
self.tb_time_periods.set_active(False)
self.lbrNetworkLocation.set_visible(True) self.lbr_network_location.set_visible(True)
self.lbrCustomLocationLongitude.set_visible(False) self.lbr_custom_location_longitude.set_visible(False)
self.lbrCustomLocationLatitude.set_visible(False) self.lbr_custom_location_latitude.set_visible(False)
self.lbrTimePeriods.set_visible(False) self.lbr_time_periods.set_visible(False)
def onToggleButtonCustomLocationClicked(self, button): def on_toggle_button_custom_location_clicked(self, button):
if button.get_active(): if button.get_active():
self.tbNetworkLocation.set_active(False) self.settings_dict[PrefenceEnums.PERIOD_SOURCE] = PeriodSourceEnum.CUSTOMLOCATION
self.tbTimePeriods.set_active(False) self.tb_network_location.set_active(False)
self.tb_time_periods.set_active(False)
self.lbrNetworkLocation.set_visible(False) self.lbr_network_location.set_visible(False)
self.lbrCustomLocationLongitude.set_visible(True) self.lbr_custom_location_longitude.set_visible(True)
self.lbrCustomLocationLatitude.set_visible(True) self.lbr_custom_location_latitude.set_visible(True)
self.lbrTimePeriods.set_visible(False) self.lbr_time_periods.set_visible(False)
def onToggleButtonTimePeriodsClicked(self, button): def on_toggle_button_time_periods_clicked(self, button):
if button.get_active(): if button.get_active():
self.tbNetworkLocation.set_active(False) self.settings_dict[PrefenceEnums.PERIOD_SOURCE] = PeriodSourceEnum.CUSTOMTIMEPERIODS
self.tbCustomLocation.set_active(False) self.tb_network_location.set_active(False)
self.tb_custom_location.set_active(False)
self.lbrNetworkLocation.set_visible(False) self.lbr_network_location.set_visible(False)
self.lbrCustomLocationLongitude.set_visible(False) self.lbr_custom_location_longitude.set_visible(False)
self.lbrCustomLocationLatitude.set_visible(False) self.lbr_custom_location_latitude.set_visible(False)
self.lbrTimePeriods.set_visible(True) self.lbr_time_periods.set_visible(True)
def on_spb_network_location_refresh_time_changed(self, spin_button):
self.settings_dict[PrefenceEnums.LOCATION_REFRESH_INTERVALS] = spin_button.get_value()
def on_etr_longitude_changed(self, entry):
self.settings_dict[PrefenceEnums.LONGITUDE] = entry.get_text()
def on_etr_latitude_changed(self, entry):
self.settings_dict[PrefenceEnums.LATITUDE] = entry.get_text()
# About # About
def onCinnamonSpicesWebsiteButtonClicked(self, button): def on_cinnamon_spices_website_button_clicked(self, button):
subprocess.Popen(["xdg-open", "https://cinnamon-spices.linuxmint.com/extensions/view/97"]) subprocess.Popen(["xdg-open", "https://cinnamon-spices.linuxmint.com/extensions/view/97"])
def onGithubWebsiteButtonClicked(self, button): def on_github_website_button_clicked(self, button):
subprocess.Popen(["xdg-open", "https://github.com/TobiZog/cinnamon-dynamic-wallpaper"]) subprocess.Popen(["xdg-open", "https://github.com/TobiZog/cinnamon-dynamic-wallpaper"])
def onCreateIssueButtonClicked(self, button): def on_create_issue_button_clicked(self, button):
subprocess.Popen(["xdg-open", "https://github.com/TobiZog/cinnamon-dynamic-wallpaper/issues/new"]) subprocess.Popen(["xdg-open", "https://github.com/TobiZog/cinnamon-dynamic-wallpaper/issues/new"])
def onApply(self, *args): def on_apply(self, *args):
# todo: Store all values to settings # Store all values to the JSON file
if self.tbImageSet.get_active(): for item in self.settings_dict:
write_to_preferences(PrefenceEnums.IMAGESOURCE, ImageSourceEnum.IMAGESET) write_to_preferences(item, self.settings_dict[item])
elif self.tbHeicFile.get_active():
write_to_preferences(PrefenceEnums.IMAGESOURCE, ImageSourceEnum.HEICFILE)
elif self.tbSourceFolder.get_active():
write_to_preferences(PrefenceEnums.IMAGESOURCE, ImageSourceEnum.SOURCEFOLDER)
write_to_preferences(PrefenceEnums.EXPANDOVERALLDISPLAY, self.swExpandOverAllDisplays.get_active()) # Close the window
write_to_preferences(PrefenceEnums.SHOWONLOCKSCREEN, self.swShowOnLockScreen.get_active()) self.on_destroy()
write_to_preferences(PrefenceEnums.LOCATIONREFRESHINTERVALS, self.spbNetworkLocationRefreshTime.get_value())
write_to_preferences(PrefenceEnums.LATITUDE, self.etrLatitude.get_text())
write_to_preferences(PrefenceEnums.LONGITUDE, self.etrLongitude.get_text())
if self.tbNetworkLocation.get_active():
write_to_preferences(PrefenceEnums.PERIODSOURCE, PeriodSourceEnum.NETWORKLOCATION)
elif self.tbCustomLocation.get_active():
write_to_preferences(PrefenceEnums.PERIODSOURCE, PeriodSourceEnum.CUSTOMLOCATION)
elif self.tbTimePeriods.get_active():
write_to_preferences(PrefenceEnums.PERIODSOURCE, PeriodSourceEnum.CUSTOMTIMEPERIODS)
self.onDestroy()
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -39,8 +39,11 @@ def read_str_from_preferences(parameter: PrefenceEnums) -> str:
Returns: Returns:
str: Value of the parameter str: Value of the parameter
""" """
with open(pref_location, "r") as pref_file: try:
pref_data = json.load(pref_file) with open(pref_location, "r") as pref_file:
pref_data = json.load(pref_file)
except:
return ""
if parameter in pref_data: if parameter in pref_data:
return pref_data[parameter]["value"] return pref_data[parameter]["value"]
@@ -53,4 +56,12 @@ def read_int_from_preferences(parameter: PrefenceEnums) -> int:
if value == "": if value == "":
return 0 return 0
else: else:
return int(value) return int(value)
def read_float_from_preferences(parameter: PrefenceEnums) -> float:
value = read_str_from_preferences(parameter)
if value == "":
return 0.0
else:
return float(value)

View File

@@ -0,0 +1,3 @@
def get_location_by_network() -> list:
#todo
return []

View File

@@ -53,32 +53,4 @@ function showNotification(title, text, showOpenSettings = false) {
// Display it // Display it
source.notify(notification); 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

@@ -1,317 +1,6 @@
{ {
"layout": { "first_start": {
"type": "layout", "type": "generic",
"pages": [ "default": true
"pg_config", }
"pg_logs",
"pg_about"
],
"pg_config": {
"type": "page",
"title": "Configuration",
"sections": [
"sec_image_configuration",
"sec_location",
"sec_times"
]
},
"pg_logs": {
"type": "page",
"title": "Debugging",
"sections": [
"sec_logs",
"sec_report_issue"
]
},
"pg_about": {
"type": "page",
"title": "About",
"sections": [
"sec_project",
"sec_github"
]
},
"sec_image_configuration": {
"type": "section",
"title": "Image set",
"keys": [
"lb_image_configuration",
"btn_config_images",
"sw_image_stretch"
]
},
"sec_location": {
"type": "section",
"title": "Location estimation",
"keys": [
"sw_auto_location",
"sc_location_refresh_time",
"etr_last_update",
"etr_latitude",
"etr_longitude"
]
},
"sec_times": {
"type": "section",
"title": "Time periods",
"keys": [
"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": {
"type": "section",
"title": "About the project",
"keys": [
"lb_about",
"lb_author",
"lb_spices",
"btn_spices"
]
},
"sec_github": {
"type": "section",
"title": "Source Code on GitHub",
"keys": [
"lb_repository",
"btn_open_repository"
]
}
},
"lb_image_configuration": {
"type": "label",
"description": "Choose an included image set or import a heic-file with the Image Configurator"
},
"btn_config_images": {
"type": "button",
"description": "Image Configurator",
"callback": "openImageConfigurator"
},
"sw_image_stretch": {
"type": "switch",
"description": "Expand image over all displays",
"default": false
},
"sw_auto_location": {
"type": "switch",
"default": true,
"description": "Estimate coordinates via network"
},
"sc_location_refresh_time": {
"type": "scale",
"default": 15,
"min": 5,
"max": 60,
"step": 5,
"description": "Interval time to refresh the location via network (min)",
"dependency": "sw_auto_location"
},
"etr_last_update": {
"type": "entry",
"description": "Last location update",
"default": "",
"dependency": "sw_auto_location"
},
"etr_latitude": {
"type": "entry",
"default": "",
"description": "Latitude",
"dependency": "!sw_auto_location"
},
"etr_longitude": {
"type": "entry",
"default": "",
"description": "Longitude",
"dependency": "!sw_auto_location"
},
"tv_times": {
"type": "textview",
"description": "Time sections today",
"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": {
"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."
},
"lb_author": {
"type": "label",
"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": {
"type": "label",
"description": "This project is Open Source. You can visit the whole source code of this extension on GitHub"
},
"btn_open_repository": {
"type": "button",
"description": "Open the Repository",
"callback": "openRepoWebsite"
},
"etr_choosen_image_set": {
"type": "entry",
"default": "lakeside",
"description": ""
},
"etr_img_morning_twilight": {
"type": "entry",
"default": "1.jpg",
"description": ""
},
"etr_img_sunrise": {
"type": "entry",
"default": "2.jpg",
"description": ""
},
"etr_img_morning": {
"type": "entry",
"default": "3.jpg",
"description": ""
},
"etr_img_noon": {
"type": "entry",
"default": "4.jpg",
"description": ""
},
"etr_img_afternoon": {
"type": "entry",
"default": "5.jpg",
"description": ""
},
"etr_img_evening": {
"type": "entry",
"default": "6.jpg",
"description": ""
},
"etr_img_sunset": {
"type": "entry",
"default": "7.jpg",
"description": ""
},
"etr_img_night_twilight": {
"type": "entry",
"default": "8.jpg",
"description": ""
},
"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",
"default": "",
"description": ""
}
} }

View File

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

View File

@@ -1,4 +1,5 @@
{ {
"external-configuration-app": "preferences/preferences.py",
"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",

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 183 KiB