prefs.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. // Bing Wallpaper GNOME extension
  2. // Copyright (C) 2017-2023 Michael Carroll
  3. // This extension is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Lesser General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. // See the GNU General Public License, version 3 or later for details.
  8. // Based on GNOME shell extension NASA APOD by Elia Argentieri https://github.com/Elinvention/gnome-shell-extension-nasa-apod
  9. import Gtk from 'gi://Gtk';
  10. import Gdk from 'gi://Gdk';
  11. import Gio from 'gi://Gio';
  12. import Soup from 'gi://Soup';
  13. import Adw from 'gi://Adw';
  14. import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
  15. import * as Config from 'resource:///org/gnome/Shell/Extensions/js/misc/config.js';
  16. import * as Utils from './utils.js';
  17. import Carousel from './carousel.js';
  18. const BingImageURL = Utils.BingImageURL;
  19. var DESKTOP_SCHEMA = 'org.gnome.desktop.background';
  20. // this is pretty wide because of the size of the gallery
  21. var PREFS_DEFAULT_WIDTH = 750;
  22. var PREFS_DEFAULT_HEIGHT = 750;
  23. export default class BingWallpaperExtensionPreferences extends ExtensionPreferences {
  24. fillPreferencesWindow(window) {
  25. // formally globals
  26. let settings = this.getSettings(Utils.BING_SCHEMA);
  27. //let desktop_settings = this.getSettings(Utils.DESKTOP_SCHEMA);
  28. window.set_default_size(PREFS_DEFAULT_WIDTH, PREFS_DEFAULT_HEIGHT);
  29. /*let icon_image = null;*/
  30. let provider = new Gtk.CssProvider();
  31. provider.load_from_path(this.dir.get_path() + '/ui/prefs.css');
  32. Gtk.StyleContext.add_provider_for_display(
  33. Gdk.Display.get_default(),
  34. provider,
  35. Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
  36. let carousel = null;
  37. let httpSession = null;
  38. let log = (msg) => { // avoids need for globals
  39. if (settings.get_boolean('debug-logging'))
  40. console.log("BingWallpaper extension: " + msg); // disable to keep the noise down in journal
  41. }
  42. let buildable = new Gtk.Builder();
  43. // GTK4 removes some properties, and builder breaks when it sees them
  44. buildable.add_from_file( this.dir.get_path() + '/ui/prefsadw.ui' );
  45. // adw or gtk objects we'll attach to below
  46. const settings_page = buildable.get_object('settings_page');
  47. const hideSwitch = buildable.get_object('hideSwitch');
  48. const notifySwitch = buildable.get_object('notifySwitch');
  49. const iconEntry = buildable.get_object('iconEntry');
  50. const bgSwitch = buildable.get_object('bgSwitch');
  51. const shuffleSwitch = buildable.get_object('shuffleSwitch');
  52. const shuffleInterval = buildable.get_object('shuffleInterval');
  53. const folderRow = buildable.get_object('folderRow');
  54. const lockscreen_page = buildable.get_object('lockscreen_page');
  55. const overrideSwitch = buildable.get_object('overrideSwitch');
  56. const blurPresets = buildable.get_object('blurPresets');
  57. const strengthEntry = buildable.get_object('strengthEntry');
  58. const brightnessEntry = buildable.get_object('brightnessEntry');
  59. const blurAdjustment = buildable.get_object('blurAdjustment');
  60. const brightnessAdjustment = buildable.get_object('brightnessAdjustment');
  61. const resolutionEntry = buildable.get_object('resolutionEntry');
  62. const debugSwitch = buildable.get_object('debug_switch');
  63. const revertSwitch = buildable.get_object('revert_switch');
  64. const trash_purge_switch = buildable.get_object('trash_purge_switch');
  65. const delete_previous_switch = buildable.get_object('delete_previous_switch');
  66. const delete_previous_adjustment = buildable.get_object('delete_previous_adjustment');
  67. const always_export_switch = buildable.get_object('always_export_switch');
  68. const gallery_page = buildable.get_object('gallery_page');
  69. const carouselFlowBox = buildable.get_object('carouselFlowBox');
  70. const randomIntervalEntry = buildable.get_object('entry_random_interval');
  71. const debug_page = buildable.get_object('debug_page');
  72. const json_actionrow = buildable.get_object('json_actionrow');
  73. const about_page = buildable.get_object('about_page');
  74. const version_button = buildable.get_object('version_button');
  75. const change_log = buildable.get_object('change_log');
  76. window.add(settings_page);
  77. window.add(lockscreen_page);
  78. window.add(gallery_page);
  79. window.add(debug_page);
  80. window.add(about_page);
  81. iconEntry.set_value(1+Utils.icon_list.indexOf(settings.get_string('icon-name')));
  82. // shuffle intervals
  83. const shuffleIntervals = new Gtk.StringList;
  84. Utils.randomIntervals.forEach((x) => {
  85. shuffleIntervals.append(_(x.title));
  86. });
  87. shuffleInterval.set_model(shuffleIntervals);
  88. shuffleInterval.set_selected(Utils.randomIntervals.map( e => e.value).indexOf(settings.get_string('random-interval-mode')));
  89. // add wallpaper folder open and change buttons
  90. const openBtn = new Gtk.Button( {
  91. child: new Adw.ButtonContent({
  92. icon_name: 'folder-pictures-symbolic',
  93. label: _('Open folder'),
  94. },),
  95. valign: Gtk.Align.CENTER,
  96. halign: Gtk.Align.CENTER,
  97. });
  98. const changeBtn = new Gtk.Button( {
  99. child: new Adw.ButtonContent({
  100. icon_name: 'folder-download-symbolic',
  101. label: _('Change folder'),
  102. },),
  103. valign: Gtk.Align.CENTER,
  104. halign: Gtk.Align.CENTER,
  105. });
  106. folderRow.add_suffix(openBtn);
  107. folderRow.add_suffix(changeBtn);
  108. blurAdjustment.set_value(settings.get_int('lockscreen-blur-strength'));
  109. brightnessAdjustment.set_value(settings.get_int('lockscreen-blur-brightness'));
  110. const defaultBtn = new Gtk.Button( {
  111. child: new Adw.ButtonContent({
  112. icon_name: 'emblem-default-symbolic',
  113. label: _('Default'),
  114. },),
  115. valign: Gtk.Align.CENTER,
  116. halign: Gtk.Align.CENTER,
  117. });
  118. const noBlurBtn = new Gtk.Button( {
  119. child: new Adw.ButtonContent({
  120. icon_name: 'emblem-default-symbolic',
  121. label: _('No blur, slight dim'),
  122. },),
  123. valign: Gtk.Align.CENTER,
  124. halign: Gtk.Align.CENTER,
  125. });
  126. const slightBlurBtn = new Gtk.Button( {
  127. child: new Adw.ButtonContent({
  128. icon_name: 'emblem-default-symbolic',
  129. label: _('Slight blur & dim'),
  130. },),
  131. valign: Gtk.Align.CENTER,
  132. halign: Gtk.Align.CENTER,
  133. });
  134. // add to presets row
  135. blurPresets.add_suffix(defaultBtn);
  136. blurPresets.add_suffix(noBlurBtn);
  137. blurPresets.add_suffix(slightBlurBtn);
  138. randomIntervalEntry.set_value(settings.get_int('random-interval'));
  139. // these buttons either export or import saved JSON data
  140. const buttonImportData = new Gtk.Button( {
  141. child: new Adw.ButtonContent({
  142. icon_name: 'document-send-symbolic',
  143. label: _('Import'),
  144. },),
  145. valign: Gtk.Align.CENTER,
  146. halign: Gtk.Align.CENTER,
  147. });
  148. const buttonExportData = new Gtk.Button( {
  149. child: new Adw.ButtonContent({
  150. icon_name: 'document-save-symbolic',
  151. label: _('Export'),
  152. },),
  153. valign: Gtk.Align.CENTER,
  154. halign: Gtk.Align.CENTER,
  155. });
  156. json_actionrow.add_suffix(buttonImportData);
  157. json_actionrow.add_suffix(buttonExportData);
  158. version_button.set_label(this.metadata.version.toString());
  159. try {
  160. httpSession = new Soup.Session();
  161. httpSession.user_agent = 'User-Agent: Mozilla/5.0 (X11; GNOME Shell/' + Config.PACKAGE_VERSION + '; Linux x86_64; +https://github.com/neffo/bing-wallpaper-gnome-extension ) BingWallpaper Gnome Extension/' + this.metadata.version;
  162. }
  163. catch (e) {
  164. log("Error creating httpSession: " + e);
  165. }
  166. const icon_image = buildable.get_object('icon_image');
  167. // check that these are valid (can be edited through dconf-editor)
  168. Utils.validate_resolution(settings);
  169. Utils.validate_icon(settings, this.path, icon_image);
  170. Utils.validate_interval(settings);
  171. // Indicator & notifications
  172. settings.bind('hide', hideSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
  173. settings.bind('notify', notifySwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
  174. settings.connect('changed::icon-name', () => {
  175. Utils.validate_icon(settings, this.path, icon_image);
  176. iconEntry.set_value(1 + Utils.icon_list.indexOf(settings.get_string('icon-name')));
  177. });
  178. iconEntry.connect('output', () => {
  179. settings.set_string('icon-name', Utils.icon_list[iconEntry.get_value()-1]);
  180. });
  181. // connect switches to settings changes
  182. settings.bind('set-background', bgSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
  183. settings.bind('debug-logging', debugSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
  184. settings.bind('revert-to-current-image', revertSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
  185. //settings.bind('override-unsafe-wayland', unsafeSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
  186. settings.bind('random-interval', randomIntervalEntry, 'value', Gio.SettingsBindFlags.DEFAULT);
  187. settings.bind('trash-deletes-images', trash_purge_switch, 'active', Gio.SettingsBindFlags.DEFAULT);
  188. settings.bind('always-export-bing-json', always_export_switch, 'active', Gio.SettingsBindFlags.DEFAULT);
  189. settings.bind('delete-previous', delete_previous_switch, 'active', Gio.SettingsBindFlags.DEFAULT);
  190. // button opens Nautilus at our image folder
  191. openBtn.connect('clicked', (widget) => {
  192. Utils.openImageFolder(settings);
  193. });
  194. // we populate the tab (gtk4+, gnome 40+), this was previously a button to open a new window in gtk3
  195. carousel = new Carousel(settings, null, null, carouselFlowBox, this.dir.get_path()); // auto load carousel
  196. // this is intended for migrating image folders between computers (or even sharing) or backups
  197. // we export the Bing JSON data to the image directory, so this folder becomes portable
  198. buttonImportData.connect('clicked', () => {
  199. Utils.importBingJSON(settings);
  200. });
  201. buttonExportData.connect('clicked', () => {
  202. Utils.exportBingJSON(settings);
  203. });
  204. // change wallpaper button
  205. const dirChooser = new Gtk.FileDialog( {
  206. accept_label: "Select",
  207. modal: true,
  208. title: _("Select wallpaper download folder"),
  209. });
  210. changeBtn.connect('clicked', (widget) => {
  211. dirChooser.set_initial_folder(Gio.File.new_for_path(Utils.getWallpaperDir(settings)));
  212. dirChooser.select_folder(window, null, (self, res) => {
  213. let new_path = self.select_folder_finish(res).get_uri().replace('file://', '');
  214. log(new_path);
  215. Utils.moveImagesToNewFolder(settings, Utils.getWallpaperDir(settings), new_path);
  216. Utils.setWallpaperDir(settings, new_path);
  217. });
  218. });
  219. // Resolution
  220. const resolutionModel = new Gtk.StringList();
  221. Utils.resolutions.forEach((res) => { // add res to dropdown list (aka a GtkComboText)
  222. resolutionModel.append(res);
  223. });
  224. resolutionEntry.set_model(resolutionModel);
  225. settings.connect('changed::resolution', () => {
  226. resolutionEntry.set_selected(Utils.resolutions.map( e => e.value).indexOf(settings.get_string('resolution')));
  227. });
  228. settings.connect('changed::resolution', () => {
  229. Utils.validate_resolution(settings);
  230. });
  231. // shuffle modes
  232. settings.bind('random-mode-enabled', shuffleSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
  233. /*settings.bind('random-interval-mode', entryShuffleMode, 'active_id', Gio.SettingsBindFlags.DEFAULT);*/
  234. settings.connect('changed::random-interval-mode', () => {
  235. shuffleInterval.set_selected(Utils.randomIntervals.map( e => e.value).indexOf(settings.get_string('random-interval-mode')));
  236. });
  237. // GDM3 lockscreen blur override
  238. settings.bind('override-lockscreen-blur', overrideSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
  239. settings.bind('lockscreen-blur-strength', strengthEntry, 'value', Gio.SettingsBindFlags.DEFAULT);
  240. settings.bind('lockscreen-blur-brightness', brightnessEntry, 'value', Gio.SettingsBindFlags.DEFAULT);
  241. settings.bind('previous-days', delete_previous_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT);
  242. // add a couple of preset buttons
  243. defaultBtn.connect('clicked', (widget) => {
  244. Utils.set_blur_preset(settings, Utils.PRESET_GNOME_DEFAULT);
  245. });
  246. noBlurBtn.connect('clicked', (widget) => {
  247. Utils.set_blur_preset(settings, Utils.PRESET_NO_BLUR);
  248. });
  249. slightBlurBtn.connect('clicked', (widget) => {
  250. Utils.set_blur_preset(settings, Utils.PRESET_SLIGHT_BLUR);
  251. });
  252. // fetch change log (on about page)
  253. if (httpSession)
  254. Utils.fetch_change_log(this.metadata.version.toString(), change_log, httpSession);
  255. }
  256. }