#29 Port prefs to GTK4
Merged 4 years ago by fmuellner. Opened 4 years ago by fmuellner.
fmuellner/background-logo-extension gtk4  into  master

prefs: Port to GTK4
Florian Müllner • 4 years ago  
prefs: Replace FileChooserButton
Florian Müllner • 4 years ago  
file modified
+64 -44
@@ -1,5 +1,13 @@ 

  /* exported init, buildPrefsWidget */

- const { Gdk, GdkPixbuf, Gio, GnomeDesktop, GObject, Gtk } = imports.gi;

+ const { Gdk, GdkPixbuf, Gio, GLib, GObject, Gtk } = imports.gi;

+ const ByteArray = imports.byteArray;

+ 

+ let GnomeDesktop = null;

+ try {

+     GnomeDesktop = imports.gi.GnomeDesktop;

+ } catch (e) {

+     // not compatible with GTK4 yet

+ }

  

  const ExtensionUtils = imports.misc.extensionUtils;

  
@@ -12,13 +20,14 @@ 

      _init() {

          super._init({

              halign: Gtk.Align.CENTER,

-             margin: 24,

+             margin_top: 24,

+             margin_bottom: 24,

+             margin_start: 24,

+             margin_end: 24,

              column_spacing: 12,

              row_spacing: 6,

          });

  

-         this.connect('screen-changed', this._onScreenChanged.bind(this));

- 

          this._settings = ExtensionUtils.getSettings();

          this._settings.connect('changed', (settings, key) => {

              if (key === 'logo-file' ||
@@ -30,22 +39,37 @@ 

          this._preview = new Gtk.DrawingArea({

              halign: Gtk.Align.CENTER,

              margin_bottom: 18,

+             width_request: PREVIEW_WIDTH,

+             height_request: PREVIEW_WIDTH * 9 / 16,

          });

-         this._preview.connect('draw', this._drawPreview.bind(this));

+         this._preview.set_draw_func(this._drawPreview.bind(this));

          this.attach(this._preview, 0, 0, 2, 1);

  

-         let filter = new Gtk.FileFilter();

+         const filter = new Gtk.FileFilter();

          filter.add_pixbuf_formats();

  

-         let fileChooser = new Gtk.FileChooserButton({

+         this._fileChooser = new Gtk.FileChooserNative({

              title: 'Select an Image',

              filter,

+             modal: true,

+         });

+         this._fileChooser.connect('response',  (dlg, response) => {

+             if (response !== Gtk.ResponseType.ACCEPT)

+                 return;

+             this._settings.set_string('logo-file', dlg.get_file().get_path());

          });

-         fileChooser.set_filename(this._settings.get_string('logo-file'));

-         fileChooser.connect('file-set',  () => {

-             this._settings.set_string('logo-file', fileChooser.get_filename());

+ 

+         this._logoPicker = new Gtk.Button({

+             label: '(None)',

+         });

+         this._logoPicker.connect('clicked', () => {

+             this._fileChooser.transient_for = this.get_root();

+             this._fileChooser.show();

          });

-         this._addRow(1, 'Logo image', fileChooser);

+         this._settings.connect('changed::logo-file',

+             this._updateLogoPicker.bind(this));

+         this._updateLogoPicker();

+         this._addRow(1, 'Logo image', this._logoPicker);

  

          let comboBox = new Gtk.ComboBoxText();

          comboBox.append('center', 'Center');
@@ -115,10 +139,7 @@ 

          return adj;

      }

  

-     _drawPreview(preview, cr) {

-         let width = preview.get_allocated_width();

-         let height = preview.get_allocated_height();

- 

+     _drawPreview(preview, cr, width, height) {

          if (!this._background)

              this._createBackgroundThumbnail(width, height);

          Gdk.cairo_set_source_pixbuf(cr, this._background, 0, 0);
@@ -132,19 +153,29 @@ 

          cr.paintWithAlpha(this._settings.get_uint('logo-opacity') / 255.0);

      }

  

+     _getSlideShowSlide(file, width, height) {

+         if (GnomeDesktop) {

+             const slideShow = new GnomeDesktop.BGSlideShow({ file });

+             slideShow.load();

+ 

+             const [progress_, duration_, isFixed_, filename1, filename2_] =

+                 slideShow.get_current_slide(width, height);

+             return Gio.File.new_for_commandline_arg(filename1);

+         } else {

+             const [, contents] = file.load_contents(null);

+             const str = ByteArray.toString(contents);

+             const [, filename1] = str.match(/<file>(.*)<\/file>/);

+             return Gio.File.new_for_commandline_arg(filename1);

+         }

+     }

+ 

      _createBackgroundThumbnail(width, height) {

          let settings = new Gio.Settings({ schema_id: BACKGROUND_SCHEMA });

          let uri = settings.get_default_value('picture-uri').deep_unpack();

          let file = Gio.File.new_for_commandline_arg(uri);

  

-         if (uri.endsWith('.xml')) {

-             let slideShow = new GnomeDesktop.BGSlideShow({ file });

-             slideShow.load();

- 

-             let [progress_, duration_, isFixed_, filename1, filename2_] =

-                 slideShow.get_current_slide(width, height);

-             file = Gio.File.new_for_commandline_arg(filename1);

-         }

+         if (uri.endsWith('.xml'))

+             file = this._getSlideShowSlide(file, width, height);

          let pixbuf = GdkPixbuf.Pixbuf.new_from_file(file.get_path());

          this._background = pixbuf.scale_simple(

              width, height, GdkPixbuf.InterpType.BILINEAR);
@@ -163,7 +194,7 @@ 

      }

  

      _getLogoPosition(width, height) {

-         let scaledBorder = this._settings.get_uint('logo-border') * this._scale;

+         let scaledBorder = this._settings.get_uint('logo-border');

          let x, y;

          switch (this._settings.get_string('logo-position')) {

          case 'center':
@@ -186,23 +217,15 @@ 

          return [x, y];

      }

  

-     _onScreenChanged() {

-         let screen = this.get_screen();

-         if (!screen)

-             return;

- 

-         let rect = screen.get_monitor_geometry(screen.get_primary_monitor());

- 

-         // If we can't get the actual geometry (wayland), use sane fallbacks

-         if (rect.width === 0 || rect.height === 0) {

-             rect.width = PREVIEW_WIDTH;

-             rect.height = PREVIEW_WIDTH * 9 / 16;

-         }

+     _updateLogoPicker() {

+         const filename = this._settings.get_string('logo-file');

+         this._logoPicker.label = GLib.basename(filename);

+     }

  

-         this._scale = PREVIEW_WIDTH / rect.width;

-         this._preview.set_size_request(

-             PREVIEW_WIDTH,

-             PREVIEW_WIDTH * rect.height / rect.width);

+     on_destroy() {

+         if (this._fileChooser)

+             this._fileChooser.destroy();

+         this._fileChooser = null;

      }

  });

  
@@ -210,8 +233,5 @@ 

  }

  

  function buildPrefsWidget() {

-     let widget = new BackgroundLogoPrefsWidget();

-     widget.show_all();

- 

-     return widget;

+     return new BackgroundLogoPrefsWidget();

  }

The process that embeds extension preferences has been ported to GTK4 for GNOME 40, so extensions must port as well to keep their preferences working.

The main issue here is that gnome-desktop doesn't have a GTK4 port yet, other changes are more or less straight-forward.

Pull-Request has been merged by fmuellner

4 years ago
Metadata