BlinkGTK Settings API Tutorial (Python/PyGObject)

Last Updated: 2026-01-01
Target Version: BlinkGTK v0.9.29-dev or later
Level: Beginner to Intermediate
Language: English |

日本語


Table of Contents

  1. Introduction
  2. PyGObject Setup
  3. Basic Usage
  4. Settings API Details
  5. Pythonic Patterns
  6. Practical Examples
  7. Migration from WebKitGTK

Introduction

This tutorial teaches you how to use BlinkGTK's Settings API with Python and PyGObject.

What You'll Learn

Prerequisites


PyGObject Setup

Installation

Fedora/RHEL:

sudo dnf install python3-gobject gtk4

Ubuntu/Debian:

sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-4.0

Arch Linux:

sudo pacman -S python-gobject gtk4

openSUSE:

sudo zypper install python3-gobject python3-gobject-Gdk typelib-1_0-Gtk-4_0

Your First Program

#!/usr/bin/env python3
"""Minimal BlinkGTK application"""

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
import blink_gtk


def on_activate(app):
    """Application activation callback"""
    window = Gtk.ApplicationWindow(application=app)
    window.set_title("My First BlinkGTK App")
    window.set_default_size(800, 600)

    web_view = blink_gtk.WebView.new()
    window.set_child(web_view)

    web_view.load_uri("https://example.com")
    window.present()


if __name__ == '__main__':
    blink_gtk.init()

    app = Gtk.Application(application_id='org.example.first')
    app.connect('activate', on_activate)
    app.run()

    blink_gtk.shutdown()

Run:

python3 first_app.py

Basic Usage

JavaScript Control

#!/usr/bin/env python3
"""JavaScript control example"""

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
import blink_gtk


def on_activate(app):
    window = Gtk.ApplicationWindow(application=app)
    window.set_title("JavaScript Control")
    window.set_default_size(800, 600)

    web_view = blink_gtk.WebView.new()
    window.set_child(web_view)

    # Disable JavaScript
    web_view.set_enable_javascript(False)

    # Check status
    js_enabled = web_view.get_enable_javascript()
    print(f"JavaScript: {'Enabled' if js_enabled else 'Disabled'}")

    web_view.load_uri("https://example.com")
    window.present()


if __name__ == '__main__':
    blink_gtk.init()
    app = Gtk.Application(application_id='org.example.jscontrol')
    app.connect('activate', on_activate)
    app.run()
    blink_gtk.shutdown()

User-Agent Modification

#!/usr/bin/env python3
"""User-Agent modification example"""

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
import blink_gtk


def on_activate(app):
    window = Gtk.ApplicationWindow(application=app)
    web_view = blink_gtk.WebView.new()
    window.set_child(web_view)

    # Set custom User-Agent
    custom_ua = "MyPythonApp/1.0 (BlinkGTK; Python 3.11)"
    web_view.set_user_agent(custom_ua)

    # Verify
    current_ua = web_view.get_user_agent()
    print(f"User-Agent: {current_ua}")

    web_view.load_uri("https://example.com")
    window.present()


if __name__ == '__main__':
    blink_gtk.init()
    app = Gtk.Application(application_id='org.example.useragent')
    app.connect('activate', on_activate)
    app.run()
    blink_gtk.shutdown()

Settings API Details

1. JavaScript Control

set_enable_javascript(enabled: bool)

# Enable JavaScript
web_view.set_enable_javascript(True)

# Disable JavaScript
web_view.set_enable_javascript(False)

get_enable_javascript() -> bool

js_enabled = web_view.get_enable_javascript()
print(f"JavaScript: {'Enabled' if js_enabled else 'Disabled'}")

Default value: True (enabled)

2. User-Agent Control

set_user_agent(user_agent: str)

# Mobile emulation
mobile_ua = "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36"
web_view.set_user_agent(mobile_ua)

# Custom User-Agent
custom_ua = f"MyApp/{version} (BlinkGTK; Python {sys.version_info.major}.{sys.version_info.minor})"
web_view.set_user_agent(custom_ua)

get_user_agent() -> str

current_ua = web_view.get_user_agent()
print(f"Current User-Agent: {current_ua}")

3. Image Loading Control

set_auto_load_images(enabled: bool)

# Disable image loading (data saver mode)
web_view.set_auto_load_images(False)

# Enable image loading
web_view.set_auto_load_images(True)

get_auto_load_images() -> bool

images_enabled = web_view.get_auto_load_images()
print(f"Image loading: {'Enabled' if images_enabled else 'Disabled'}")

Default value: True (enabled)

4. Local Storage Control

set_enable_local_storage(enabled: bool)

# Disable local storage (privacy mode)
web_view.set_enable_local_storage(False)

# Enable local storage
web_view.set_enable_local_storage(True)

get_enable_local_storage() -> bool

storage_enabled = web_view.get_enable_local_storage()
print(f"Local storage: {'Enabled' if storage_enabled else 'Disabled'}")

Default value: True (enabled)


Pythonic Patterns

1. Using Type Hints

from typing import Optional
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
import blink_gtk


class BrowserSettings:
    """Browser settings manager class"""

    def __init__(self, web_view: blink_gtk.WebView):
        self.web_view = web_view

    def enable_javascript(self, enabled: bool) -> None:
        """Enable or disable JavaScript"""
        self.web_view.set_enable_javascript(enabled)

    def set_user_agent(self, user_agent: str) -> None:
        """Set User-Agent string"""
        self.web_view.set_user_agent(user_agent)

    def enable_images(self, enabled: bool) -> None:
        """Enable or disable image loading"""
        self.web_view.set_auto_load_images(enabled)

    def enable_storage(self, enabled: bool) -> None:
        """Enable or disable local storage"""
        self.web_view.set_enable_local_storage(enabled)

    def get_settings(self) -> dict[str, any]:
        """Get current settings as dictionary"""
        return {
            'javascript': self.web_view.get_enable_javascript(),
            'images': self.web_view.get_auto_load_images(),
            'storage': self.web_view.get_enable_local_storage(),
            'user_agent': self.web_view.get_user_agent(),
        }

    def apply_settings(self, settings: dict[str, any]) -> None:
        """Apply settings from dictionary"""
        if 'javascript' in settings:
            self.enable_javascript(settings['javascript'])
        if 'images' in settings:
            self.enable_images(settings['images'])
        if 'storage' in settings:
            self.enable_storage(settings['storage'])
        if 'user_agent' in settings:
            self.set_user_agent(settings['user_agent'])

2. Using Properties

class BrowserWindow(Gtk.ApplicationWindow):
    """Browser window with properties"""

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._web_view = blink_gtk.WebView.new()
        self.set_child(self._web_view)

    @property
    def javascript_enabled(self) -> bool:
        """Whether JavaScript is enabled"""
        return self._web_view.get_enable_javascript()

    @javascript_enabled.setter
    def javascript_enabled(self, enabled: bool) -> None:
        """Enable or disable JavaScript"""
        self._web_view.set_enable_javascript(enabled)

    @property
    def user_agent(self) -> str:
        """Current User-Agent string"""
        return self._web_view.get_user_agent()

    @user_agent.setter
    def user_agent(self, ua: str) -> None:
        """Set User-Agent string"""
        self._web_view.set_user_agent(ua)

    @property
    def images_enabled(self) -> bool:
        """Whether image loading is enabled"""
        return self._web_view.get_auto_load_images()

    @images_enabled.setter
    def images_enabled(self, enabled: bool) -> None:
        """Enable or disable image loading"""
        self._web_view.set_auto_load_images(enabled)


# Usage example
window = BrowserWindow(application=app)

# Use as properties
window.javascript_enabled = False
window.user_agent = "MyApp/1.0"
window.images_enabled = False

print(f"JavaScript: {window.javascript_enabled}")
print(f"User-Agent: {window.user_agent}")

3. Context Managers

from contextlib import contextmanager
from typing import Iterator


@contextmanager
def temporary_settings(
    web_view: blink_gtk.WebView,
    **settings
) -> Iterator[None]:
    """
    Context manager for temporary settings changes

    Usage example:
        with temporary_settings(web_view, javascript=False, images=False):
            web_view.load_uri("https://example.com")
        # Settings automatically restored after context exit
    """
    # Save current settings
    original = {
        'javascript': web_view.get_enable_javascript(),
        'images': web_view.get_auto_load_images(),
        'storage': web_view.get_enable_local_storage(),
    }

    # Apply new settings
    if 'javascript' in settings:
        web_view.set_enable_javascript(settings['javascript'])
    if 'images' in settings:
        web_view.set_auto_load_images(settings['images'])
    if 'storage' in settings:
        web_view.set_enable_local_storage(settings['storage'])

    try:
        yield
    finally:
        # Restore original settings
        web_view.set_enable_javascript(original['javascript'])
        web_view.set_auto_load_images(original['images'])
        web_view.set_enable_local_storage(original['storage'])


# Usage example
with temporary_settings(web_view, javascript=False, images=False):
    # Settings are changed within this block
    web_view.load_uri("https://example.com")
# Settings automatically restored after block exit

4. Using Dataclasses

from dataclasses import dataclass


@dataclass
class BrowserConfig:
    """Browser configuration dataclass"""
    javascript: bool = True
    images: bool = True
    storage: bool = True
    user_agent: str = ""

    def apply_to(self, web_view: blink_gtk.WebView) -> None:
        """Apply configuration to WebView"""
        web_view.set_enable_javascript(self.javascript)
        web_view.set_auto_load_images(self.images)
        web_view.set_enable_local_storage(self.storage)
        if self.user_agent:
            web_view.set_user_agent(self.user_agent)

    @classmethod
    def from_web_view(cls, web_view: blink_gtk.WebView) -> 'BrowserConfig':
        """Get current configuration from WebView"""
        return cls(
            javascript=web_view.get_enable_javascript(),
            images=web_view.get_auto_load_images(),
            storage=web_view.get_enable_local_storage(),
            user_agent=web_view.get_user_agent(),
        )


# Usage example
# Define presets
DATA_SAVER = BrowserConfig(javascript=False, images=False)
PRIVACY_MODE = BrowserConfig(javascript=False, images=False, storage=False)
NORMAL_MODE = BrowserConfig()

# Apply preset
DATA_SAVER.apply_to(web_view)

# Get current configuration
current_config = BrowserConfig.from_web_view(web_view)
print(f"JavaScript: {current_config.javascript}")

Practical Examples

Example 1: Data Saver Mode

#!/usr/bin/env python3
"""Data saver mode implementation"""

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
import blink_gtk


class DataSaverBrowser(Gtk.ApplicationWindow):
    """Browser with data saver mode"""

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.set_title("Data Saver Browser")
        self.set_default_size(800, 600)

        # Build UI
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        # Data saver switch
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        hbox.set_margin_start(10)
        hbox.set_margin_end(10)
        hbox.set_margin_top(10)
        hbox.set_margin_bottom(10)

        label = Gtk.Label(label="Data Saver Mode:")
        self.data_saver_switch = Gtk.Switch()
        self.data_saver_switch.connect('notify::active', self.on_data_saver_toggled)

        hbox.append(label)
        hbox.append(self.data_saver_switch)

        # WebView
        self.web_view = blink_gtk.WebView.new()

        vbox.append(hbox)
        vbox.append(self.web_view)

        self.web_view.set_vexpand(True)
        self.set_child(vbox)

    def on_data_saver_toggled(self, switch, _):
        """Toggle data saver mode"""
        enabled = switch.get_active()

        if enabled:
            # Enable data saver mode
            self.web_view.set_enable_javascript(False)
            self.web_view.set_auto_load_images(False)
            print("Data Saver Mode: Enabled")
        else:
            # Normal mode
            self.web_view.set_enable_javascript(True)
            self.web_view.set_auto_load_images(True)
            print("Data Saver Mode: Disabled")


def on_activate(app):
    window = DataSaverBrowser(application=app)
    window.web_view.load_uri("https://www.chromium.org")
    window.present()


if __name__ == '__main__':
    blink_gtk.init()
    app = Gtk.Application(application_id='org.example.datasaver')
    app.connect('activate', on_activate)
    app.run()
    blink_gtk.shutdown()

Example 2: Browser with Settings Panel

#!/usr/bin/env python3
"""Browser with settings panel"""

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
import blink_gtk


class SettingsPanel(Gtk.Box):
    """Settings panel widget"""

    def __init__(self, web_view: blink_gtk.WebView):
        super().__init__(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        self.web_view = web_view

        self.set_margin_start(10)
        self.set_margin_end(10)
        self.set_margin_top(10)
        self.set_margin_bottom(10)

        # JavaScript
        self.append(Gtk.Label(label="JavaScript:"))
        self.js_switch = Gtk.Switch()
        self.js_switch.set_active(True)
        self.js_switch.connect('notify::active',
                              lambda s, _: web_view.set_enable_javascript(s.get_active()))
        self.append(self.js_switch)

        # Images
        self.append(Gtk.Label(label="Images:"))
        self.images_switch = Gtk.Switch()
        self.images_switch.set_active(True)
        self.images_switch.connect('notify::active',
                                   lambda s, _: web_view.set_auto_load_images(s.get_active()))
        self.append(self.images_switch)

        # Storage
        self.append(Gtk.Label(label="Storage:"))
        self.storage_switch = Gtk.Switch()
        self.storage_switch.set_active(True)
        self.storage_switch.connect('notify::active',
                                    lambda s, _: web_view.set_enable_local_storage(s.get_active()))
        self.append(self.storage_switch)


class BrowserWindow(Gtk.ApplicationWindow):
    """Browser window with settings panel"""

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.set_title("Browser with Settings")
        self.set_default_size(1000, 700)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        # WebView
        self.web_view = blink_gtk.WebView.new()

        # Settings panel
        self.settings_panel = SettingsPanel(self.web_view)

        vbox.append(self.settings_panel)
        vbox.append(self.web_view)

        self.web_view.set_vexpand(True)
        self.set_child(vbox)


def on_activate(app):
    window = BrowserWindow(application=app)
    window.web_view.load_uri("https://www.chromium.org")
    window.present()


if __name__ == '__main__':
    blink_gtk.init()
    app = Gtk.Application(application_id='org.example.settings')
    app.connect('activate', on_activate)
    app.run()
    blink_gtk.shutdown()

Example 3: Profile System

#!/usr/bin/env python3
"""Profile system implementation"""

from dataclasses import dataclass
from enum import Enum
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
import blink_gtk


class ProfileType(Enum):
    """Profile types"""
    NORMAL = "Normal"
    DATA_SAVER = "Data Saver"
    PRIVACY = "Privacy"
    MOBILE = "Mobile"


@dataclass
class BrowserProfile:
    """Browser profile"""
    name: str
    javascript: bool
    images: bool
    storage: bool
    user_agent: str = ""

    def apply_to(self, web_view: blink_gtk.WebView) -> None:
        """Apply profile to WebView"""
        web_view.set_enable_javascript(self.javascript)
        web_view.set_auto_load_images(self.images)
        web_view.set_enable_local_storage(self.storage)
        if self.user_agent:
            web_view.set_user_agent(self.user_agent)


# Profile definitions
PROFILES = {
    ProfileType.NORMAL: BrowserProfile(
        name="Normal Mode",
        javascript=True,
        images=True,
        storage=True,
    ),
    ProfileType.DATA_SAVER: BrowserProfile(
        name="Data Saver Mode",
        javascript=False,
        images=False,
        storage=True,
    ),
    ProfileType.PRIVACY: BrowserProfile(
        name="Privacy Mode",
        javascript=False,
        images=False,
        storage=False,
    ),
    ProfileType.MOBILE: BrowserProfile(
        name="Mobile Emulation",
        javascript=True,
        images=True,
        storage=True,
        user_agent="Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36",
    ),
}


class ProfileBrowser(Gtk.ApplicationWindow):
    """Browser with profile switching"""

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.set_title("Profile Browser")
        self.set_default_size(1000, 700)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        # Profile selection
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        hbox.set_margin_start(10)
        hbox.set_margin_end(10)
        hbox.set_margin_top(10)

        hbox.append(Gtk.Label(label="Profile:"))

        self.profile_combo = Gtk.ComboBoxText()
        for profile_type in ProfileType:
            self.profile_combo.append(profile_type.value, profile_type.value)
        self.profile_combo.set_active(0)
        self.profile_combo.connect('changed', self.on_profile_changed)

        hbox.append(self.profile_combo)

        # WebView
        self.web_view = blink_gtk.WebView.new()

        vbox.append(hbox)
        vbox.append(self.web_view)

        self.web_view.set_vexpand(True)
        self.set_child(vbox)

    def on_profile_changed(self, combo):
        """Profile change handler"""
        profile_name = combo.get_active_text()

        # Find and apply profile
        for profile_type, profile in PROFILES.items():
            if profile.name == profile_name:
                profile.apply_to(self.web_view)
                print(f"Profile applied: {profile.name}")
                break


def on_activate(app):
    window = ProfileBrowser(application=app)
    window.web_view.load_uri("https://www.chromium.org")
    window.present()


if __name__ == '__main__':
    blink_gtk.init()
    app = Gtk.Application(application_id='org.example.profiles')
    app.connect('activate', on_activate)
    app.run()
    blink_gtk.shutdown()

Migration from WebKitGTK

API Correspondence Table

WebKitGTK (Python) BlinkGTK (Python) Compatibility
settings.set_enable_javascript(enabled) web_view.set_enable_javascript(enabled) Yes
settings.get_enable_javascript() web_view.get_enable_javascript() Yes
settings.set_user_agent(ua) web_view.set_user_agent(ua) Yes
settings.get_user_agent() web_view.get_user_agent() Yes
settings.set_auto_load_images(enabled) web_view.set_auto_load_images(enabled) Yes
settings.get_auto_load_images() web_view.get_auto_load_images() Yes
settings.set_enable_local_storage(enabled) web_view.set_enable_local_storage(enabled) Yes
settings.get_enable_local_storage() web_view.get_enable_local_storage() Yes

Migration Example

Before (WebKitGTK):

import gi
gi.require_version('WebKit2', '4.1')
from gi.repository import WebKit2

web_view = WebKit2.WebView()
settings = web_view.get_settings()

settings.set_enable_javascript(False)
settings.set_user_agent("MyApp/1.0")

After (BlinkGTK):

import blink_gtk

web_view = blink_gtk.WebView.new()

# No Settings object needed, set directly on WebView
web_view.set_enable_javascript(False)
web_view.set_user_agent("MyApp/1.0")

Key Differences:


Summary

In this tutorial, you learned how to use the BlinkGTK Settings API with Python/PyGObject.

What You Learned

Next Steps


Author: BlinkGTK Development Team
License: BSD 3-Clause
Feedback: daisy19@gmail.com