118 lines
3.8 KiB
Go
118 lines
3.8 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package preferences
|
|
|
|
/*
|
|
#include <stdlib.h>
|
|
#include "native.h"
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"fmt"
|
|
"git.stormux.org/storm/cthulhu/internal/interaction"
|
|
"git.stormux.org/storm/cthulhu/internal/tentaclewire"
|
|
"unsafe"
|
|
)
|
|
|
|
func extension_page_key(page ExtensionPage) string { return page.Session + "/" + page.ID }
|
|
|
|
// GTK owns native focus. Refreshes keep unchanged widgets and their unapplied
|
|
// drafts, and move focus to the notebook before removing a revoked page.
|
|
func (session *uiSession) set_extension_pages(pages []ExtensionPage) error {
|
|
selected := C.GoString(C.prefs_extension_selected())
|
|
ids := map[string]bool{}
|
|
for _, page := range pages {
|
|
key := extension_page_key(page)
|
|
if page.Session == "" || ids[key] {
|
|
return fmt.Errorf("invalid extension page identity")
|
|
}
|
|
ids[key] = true
|
|
if err := tentaclewire.ValidateExtensions(tentaclewire.Extensions{Pages: []tentaclewire.PreferencePage{page.PreferencePage}}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
keep := map[string]bool{}
|
|
for _, previous := range session.extensionPages {
|
|
key := extension_page_key(previous)
|
|
for _, page := range pages {
|
|
if extension_page_key(page) == key && page.Revision == previous.Revision {
|
|
keep[key] = true
|
|
break
|
|
}
|
|
}
|
|
if !keep[key] {
|
|
cKey := C.CString(key)
|
|
C.prefs_extension_remove(cKey)
|
|
C.free(unsafe.Pointer(cKey))
|
|
}
|
|
}
|
|
for _, page := range pages {
|
|
key := extension_page_key(page)
|
|
if keep[key] {
|
|
continue
|
|
}
|
|
cKey, title := C.CString(key), C.CString(page.Title)
|
|
C.prefs_extension_add(cKey, title)
|
|
C.free(unsafe.Pointer(title))
|
|
for row, element := range page.Elements {
|
|
id, label := C.CString(element.ID), C.CString(element.Label)
|
|
C.prefs_extension_control(cKey, id, label, C.int(element.Kind), C.int(row), C.int(element.MaxLength), boolean(element.Disabled))
|
|
C.free(unsafe.Pointer(label))
|
|
for _, option := range element.Items {
|
|
optionID, optionLabel := C.CString(option.ID), C.CString(option.Label)
|
|
C.prefs_extension_option(cKey, id, optionID, optionLabel, boolean(option.Disabled))
|
|
C.free(unsafe.Pointer(optionID))
|
|
C.free(unsafe.Pointer(optionLabel))
|
|
}
|
|
value := page.Values[element.ID]
|
|
text := value.Text
|
|
if element.Kind == interaction.List {
|
|
text = value.Selected
|
|
}
|
|
cText := C.CString(text)
|
|
C.prefs_extension_set(cKey, id, C.int(element.Kind), cText, boolean(value.Checked))
|
|
C.free(unsafe.Pointer(cText))
|
|
C.free(unsafe.Pointer(id))
|
|
}
|
|
C.free(unsafe.Pointer(cKey))
|
|
}
|
|
session.extensionPages = pages
|
|
if selected != "" {
|
|
key := C.CString(selected)
|
|
C.prefs_extension_select(key)
|
|
C.free(unsafe.Pointer(key))
|
|
}
|
|
return nil
|
|
}
|
|
func (session *uiSession) extension_drafts() ([]PageDraft, error) {
|
|
var drafts []PageDraft
|
|
for _, page := range session.extensionPages {
|
|
values := map[string]interaction.Value{}
|
|
key := C.CString(extension_page_key(page))
|
|
for _, element := range page.Elements {
|
|
id := C.CString(element.ID)
|
|
value := interaction.Value{}
|
|
switch element.Kind {
|
|
case interaction.List:
|
|
value.Selected = C.GoString(C.prefs_extension_text(key, id, C.int(element.Kind)))
|
|
case interaction.Entry:
|
|
value.Text = C.GoString(C.prefs_extension_text(key, id, C.int(element.Kind)))
|
|
case interaction.CheckBox:
|
|
value.Checked = C.prefs_extension_checked(key, id) != 0
|
|
}
|
|
C.free(unsafe.Pointer(id))
|
|
values[element.ID] = value
|
|
}
|
|
C.free(unsafe.Pointer(key))
|
|
declaration := page.PreferencePage
|
|
declaration.Values = values
|
|
if err := tentaclewire.ValidateExtensions(tentaclewire.Extensions{Pages: []tentaclewire.PreferencePage{declaration}}); err != nil {
|
|
return nil, fmt.Errorf("Check the values on %s: %w", page.Title, err)
|
|
}
|
|
drafts = append(drafts, PageDraft{Session: page.Session, ID: page.ID, Revision: page.Revision, Values: values})
|
|
}
|
|
return drafts, nil
|
|
}
|