Transpose environments table: variables as rows, environments as columns
This commit is contained in:
parent
5f01c1c49d
commit
ec2cb2768e
@ -20,70 +20,20 @@
|
|||||||
<object class="GtkScrolledWindow">
|
<object class="GtkScrolledWindow">
|
||||||
<property name="vexpand">true</property>
|
<property name="vexpand">true</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="AdwClamp">
|
||||||
<property name="orientation">vertical</property>
|
<property name="maximum-size">1200</property>
|
||||||
<property name="margin-start">12</property>
|
<property name="tightening-threshold">800</property>
|
||||||
<property name="margin-end">12</property>
|
|
||||||
<property name="margin-top">12</property>
|
|
||||||
<property name="margin-bottom">12</property>
|
|
||||||
<property name="spacing">24</property>
|
|
||||||
|
|
||||||
<!-- Variables Section -->
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox">
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<property name="spacing">12</property>
|
|
||||||
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox">
|
|
||||||
<property name="orientation">horizontal</property>
|
|
||||||
<property name="spacing">12</property>
|
|
||||||
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel">
|
|
||||||
<property name="label">Variables</property>
|
|
||||||
<property name="xalign">0</property>
|
|
||||||
<property name="hexpand">True</property>
|
|
||||||
<style>
|
|
||||||
<class name="title-4"/>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
|
|
||||||
<child>
|
|
||||||
<object class="GtkButton" id="add_variable_button">
|
|
||||||
<property name="icon-name">list-add-symbolic</property>
|
|
||||||
<property name="tooltip-text">Add variable</property>
|
|
||||||
<signal name="clicked" handler="on_add_variable_clicked"/>
|
|
||||||
<style>
|
|
||||||
<class name="flat"/>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
|
|
||||||
<child>
|
|
||||||
<object class="GtkFrame">
|
|
||||||
<child>
|
|
||||||
<object class="GtkListBox" id="variables_listbox">
|
|
||||||
<property name="selection-mode">none</property>
|
|
||||||
<style>
|
|
||||||
<class name="boxed-list"/>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
|
|
||||||
<!-- Environments Section -->
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="orientation">vertical</property>
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="margin-start">12</property>
|
||||||
|
<property name="margin-end">12</property>
|
||||||
|
<property name="margin-top">12</property>
|
||||||
|
<property name="margin-bottom">12</property>
|
||||||
<property name="spacing">12</property>
|
<property name="spacing">12</property>
|
||||||
|
|
||||||
|
<!-- Header Section -->
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="orientation">horizontal</property>
|
<property name="orientation">horizontal</property>
|
||||||
@ -100,8 +50,21 @@
|
|||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="add_variable_button">
|
||||||
|
<property name="label">Add Variable</property>
|
||||||
|
<property name="icon-name">list-add-symbolic</property>
|
||||||
|
<property name="tooltip-text">Add variable</property>
|
||||||
|
<signal name="clicked" handler="on_add_variable_clicked"/>
|
||||||
|
<style>
|
||||||
|
<class name="flat"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="add_environment_button">
|
<object class="GtkButton" id="add_environment_button">
|
||||||
|
<property name="label">Add Environment</property>
|
||||||
<property name="icon-name">list-add-symbolic</property>
|
<property name="icon-name">list-add-symbolic</property>
|
||||||
<property name="tooltip-text">Add environment</property>
|
<property name="tooltip-text">Add environment</property>
|
||||||
<signal name="clicked" handler="on_add_environment_clicked"/>
|
<signal name="clicked" handler="on_add_environment_clicked"/>
|
||||||
@ -113,11 +76,12 @@
|
|||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|
||||||
|
<!-- Table Frame -->
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkFrame">
|
<object class="GtkFrame">
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkListBox" id="environments_listbox">
|
<object class="GtkBox" id="table_container">
|
||||||
<property name="selection-mode">none</property>
|
<property name="orientation">vertical</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="boxed-list"/>
|
<class name="boxed-list"/>
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -20,6 +20,8 @@
|
|||||||
from gi.repository import Adw, Gtk, GObject
|
from gi.repository import Adw, Gtk, GObject
|
||||||
from .widgets.variable_row import VariableRow
|
from .widgets.variable_row import VariableRow
|
||||||
from .widgets.environment_row import EnvironmentRow
|
from .widgets.environment_row import EnvironmentRow
|
||||||
|
from .widgets.environment_header_row import EnvironmentHeaderRow
|
||||||
|
from .widgets.variable_data_row import VariableDataRow
|
||||||
|
|
||||||
|
|
||||||
@Gtk.Template(resource_path='/cz/vesp/roster/environments-dialog.ui')
|
@Gtk.Template(resource_path='/cz/vesp/roster/environments-dialog.ui')
|
||||||
@ -28,9 +30,8 @@ class EnvironmentsDialog(Adw.Dialog):
|
|||||||
|
|
||||||
__gtype_name__ = 'EnvironmentsDialog'
|
__gtype_name__ = 'EnvironmentsDialog'
|
||||||
|
|
||||||
variables_listbox = Gtk.Template.Child()
|
table_container = Gtk.Template.Child()
|
||||||
add_variable_button = Gtk.Template.Child()
|
add_variable_button = Gtk.Template.Child()
|
||||||
environments_listbox = Gtk.Template.Child()
|
|
||||||
add_environment_button = Gtk.Template.Child()
|
add_environment_button = Gtk.Template.Child()
|
||||||
|
|
||||||
__gsignals__ = {
|
__gsignals__ = {
|
||||||
@ -41,35 +42,50 @@ class EnvironmentsDialog(Adw.Dialog):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.project = project
|
self.project = project
|
||||||
self.project_manager = project_manager
|
self.project_manager = project_manager
|
||||||
self._populate_variables()
|
self.size_group = Gtk.SizeGroup(mode=Gtk.SizeGroupMode.HORIZONTAL)
|
||||||
self._populate_environments()
|
self.header_row = None
|
||||||
|
self.data_rows = []
|
||||||
|
self._populate_table()
|
||||||
|
|
||||||
def _populate_variables(self):
|
def _populate_table(self):
|
||||||
"""Populate variables list."""
|
"""Populate the transposed environment-variable table."""
|
||||||
# Clear existing
|
# Clear existing
|
||||||
while child := self.variables_listbox.get_first_child():
|
while child := self.table_container.get_first_child():
|
||||||
self.variables_listbox.remove(child)
|
self.table_container.remove(child)
|
||||||
|
|
||||||
# Add variables
|
self.data_rows = []
|
||||||
|
|
||||||
|
# Create header row
|
||||||
|
self.header_row = EnvironmentHeaderRow(
|
||||||
|
self.project.environments,
|
||||||
|
self.size_group
|
||||||
|
)
|
||||||
|
self.header_row.connect('environment-edit-requested',
|
||||||
|
self._on_environment_edit)
|
||||||
|
self.header_row.connect('environment-delete-requested',
|
||||||
|
self._on_environment_delete)
|
||||||
|
self.table_container.append(self.header_row)
|
||||||
|
|
||||||
|
# Add separator
|
||||||
|
separator = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
|
||||||
|
self.table_container.append(separator)
|
||||||
|
|
||||||
|
# Create data rows for each variable
|
||||||
for var_name in self.project.variable_names:
|
for var_name in self.project.variable_names:
|
||||||
row = VariableRow(var_name)
|
row = VariableDataRow(
|
||||||
row.connect('remove-requested', self._on_variable_remove, var_name)
|
var_name,
|
||||||
row.connect('changed', self._on_variable_changed, var_name, row)
|
self.project.environments,
|
||||||
self.variables_listbox.append(row)
|
self.size_group
|
||||||
|
)
|
||||||
|
row.connect('variable-changed',
|
||||||
|
self._on_variable_changed, var_name, row)
|
||||||
|
row.connect('variable-delete-requested',
|
||||||
|
self._on_variable_remove, var_name)
|
||||||
|
row.connect('value-changed',
|
||||||
|
self._on_value_changed, var_name)
|
||||||
|
|
||||||
def _populate_environments(self):
|
self.table_container.append(row)
|
||||||
"""Populate environments list."""
|
self.data_rows.append(row)
|
||||||
# Clear existing
|
|
||||||
while child := self.environments_listbox.get_first_child():
|
|
||||||
self.environments_listbox.remove(child)
|
|
||||||
|
|
||||||
# Add environments
|
|
||||||
for env in self.project.environments:
|
|
||||||
row = EnvironmentRow(env, self.project.variable_names)
|
|
||||||
row.connect('edit-requested', self._on_environment_edit, env)
|
|
||||||
row.connect('delete-requested', self._on_environment_delete, env)
|
|
||||||
row.connect('value-changed', self._on_environment_value_changed, env)
|
|
||||||
self.environments_listbox.append(row)
|
|
||||||
|
|
||||||
@Gtk.Template.Callback()
|
@Gtk.Template.Callback()
|
||||||
def on_add_variable_clicked(self, button):
|
def on_add_variable_clicked(self, button):
|
||||||
@ -95,8 +111,7 @@ class EnvironmentsDialog(Adw.Dialog):
|
|||||||
self.project_manager.add_variable(self.project.id, name)
|
self.project_manager.add_variable(self.project.id, name)
|
||||||
# Reload project data
|
# Reload project data
|
||||||
self._reload_project()
|
self._reload_project()
|
||||||
self._populate_variables()
|
self._populate_table()
|
||||||
self._populate_environments()
|
|
||||||
self.emit('environments-updated')
|
self.emit('environments-updated')
|
||||||
|
|
||||||
dialog.connect("response", on_response)
|
dialog.connect("response", on_response)
|
||||||
@ -117,8 +132,7 @@ class EnvironmentsDialog(Adw.Dialog):
|
|||||||
if response == "delete":
|
if response == "delete":
|
||||||
self.project_manager.delete_variable(self.project.id, var_name)
|
self.project_manager.delete_variable(self.project.id, var_name)
|
||||||
self._reload_project()
|
self._reload_project()
|
||||||
self._populate_variables()
|
self._populate_table()
|
||||||
self._populate_environments()
|
|
||||||
self.emit('environments-updated')
|
self.emit('environments-updated')
|
||||||
|
|
||||||
dialog.connect("response", on_response)
|
dialog.connect("response", on_response)
|
||||||
@ -130,8 +144,7 @@ class EnvironmentsDialog(Adw.Dialog):
|
|||||||
if new_name and new_name != old_name and new_name not in self.project.variable_names:
|
if new_name and new_name != old_name and new_name not in self.project.variable_names:
|
||||||
self.project_manager.rename_variable(self.project.id, old_name, new_name)
|
self.project_manager.rename_variable(self.project.id, old_name, new_name)
|
||||||
self._reload_project()
|
self._reload_project()
|
||||||
self._populate_variables()
|
self._populate_table()
|
||||||
self._populate_environments()
|
|
||||||
self.emit('environments-updated')
|
self.emit('environments-updated')
|
||||||
|
|
||||||
@Gtk.Template.Callback()
|
@Gtk.Template.Callback()
|
||||||
@ -157,7 +170,7 @@ class EnvironmentsDialog(Adw.Dialog):
|
|||||||
if name:
|
if name:
|
||||||
self.project_manager.add_environment(self.project.id, name)
|
self.project_manager.add_environment(self.project.id, name)
|
||||||
self._reload_project()
|
self._reload_project()
|
||||||
self._populate_environments()
|
self._populate_table()
|
||||||
self.emit('environments-updated')
|
self.emit('environments-updated')
|
||||||
|
|
||||||
dialog.connect("response", on_response)
|
dialog.connect("response", on_response)
|
||||||
@ -183,7 +196,7 @@ class EnvironmentsDialog(Adw.Dialog):
|
|||||||
if new_name:
|
if new_name:
|
||||||
self.project_manager.update_environment(self.project.id, environment.id, name=new_name)
|
self.project_manager.update_environment(self.project.id, environment.id, name=new_name)
|
||||||
self._reload_project()
|
self._reload_project()
|
||||||
self._populate_environments()
|
self._populate_table()
|
||||||
self.emit('environments-updated')
|
self.emit('environments-updated')
|
||||||
|
|
||||||
dialog.connect("response", on_response)
|
dialog.connect("response", on_response)
|
||||||
@ -213,15 +226,15 @@ class EnvironmentsDialog(Adw.Dialog):
|
|||||||
if response == "delete":
|
if response == "delete":
|
||||||
self.project_manager.delete_environment(self.project.id, environment.id)
|
self.project_manager.delete_environment(self.project.id, environment.id)
|
||||||
self._reload_project()
|
self._reload_project()
|
||||||
self._populate_environments()
|
self._populate_table()
|
||||||
self.emit('environments-updated')
|
self.emit('environments-updated')
|
||||||
|
|
||||||
dialog.connect("response", on_response)
|
dialog.connect("response", on_response)
|
||||||
dialog.present(self)
|
dialog.present(self)
|
||||||
|
|
||||||
def _on_environment_value_changed(self, widget, var_name, value, environment):
|
def _on_value_changed(self, widget, env_id, value, var_name):
|
||||||
"""Handle environment variable value change."""
|
"""Handle value change in table cell."""
|
||||||
self.project_manager.update_environment_variable(self.project.id, environment.id, var_name, value)
|
self.project_manager.update_environment_variable(self.project.id, env_id, var_name, value)
|
||||||
self.emit('environments-updated')
|
self.emit('environments-updated')
|
||||||
|
|
||||||
def _reload_project(self):
|
def _reload_project(self):
|
||||||
|
|||||||
@ -54,6 +54,9 @@ widgets_sources = [
|
|||||||
'widgets/request_item.py',
|
'widgets/request_item.py',
|
||||||
'widgets/variable_row.py',
|
'widgets/variable_row.py',
|
||||||
'widgets/environment_row.py',
|
'widgets/environment_row.py',
|
||||||
|
'widgets/environment_column_header.py',
|
||||||
|
'widgets/environment_header_row.py',
|
||||||
|
'widgets/variable_data_row.py',
|
||||||
]
|
]
|
||||||
|
|
||||||
install_data(widgets_sources, install_dir: moduledir / 'widgets')
|
install_data(widgets_sources, install_dir: moduledir / 'widgets')
|
||||||
|
|||||||
@ -12,5 +12,8 @@
|
|||||||
<file preprocess="xml-stripblanks">widgets/request-item.ui</file>
|
<file preprocess="xml-stripblanks">widgets/request-item.ui</file>
|
||||||
<file preprocess="xml-stripblanks">widgets/variable-row.ui</file>
|
<file preprocess="xml-stripblanks">widgets/variable-row.ui</file>
|
||||||
<file preprocess="xml-stripblanks">widgets/environment-row.ui</file>
|
<file preprocess="xml-stripblanks">widgets/environment-row.ui</file>
|
||||||
|
<file preprocess="xml-stripblanks">widgets/environment-column-header.ui</file>
|
||||||
|
<file preprocess="xml-stripblanks">widgets/environment-header-row.ui</file>
|
||||||
|
<file preprocess="xml-stripblanks">widgets/variable-data-row.ui</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
</gresources>
|
</gresources>
|
||||||
|
|||||||
@ -23,5 +23,18 @@ from .project_item import ProjectItem
|
|||||||
from .request_item import RequestItem
|
from .request_item import RequestItem
|
||||||
from .variable_row import VariableRow
|
from .variable_row import VariableRow
|
||||||
from .environment_row import EnvironmentRow
|
from .environment_row import EnvironmentRow
|
||||||
|
from .environment_column_header import EnvironmentColumnHeader
|
||||||
|
from .environment_header_row import EnvironmentHeaderRow
|
||||||
|
from .variable_data_row import VariableDataRow
|
||||||
|
|
||||||
__all__ = ['HeaderRow', 'HistoryItem', 'ProjectItem', 'RequestItem', 'VariableRow', 'EnvironmentRow']
|
__all__ = [
|
||||||
|
'HeaderRow',
|
||||||
|
'HistoryItem',
|
||||||
|
'ProjectItem',
|
||||||
|
'RequestItem',
|
||||||
|
'VariableRow',
|
||||||
|
'EnvironmentRow',
|
||||||
|
'EnvironmentColumnHeader',
|
||||||
|
'EnvironmentHeaderRow',
|
||||||
|
'VariableDataRow',
|
||||||
|
]
|
||||||
|
|||||||
52
src/widgets/environment-column-header.ui
Normal file
52
src/widgets/environment-column-header.ui
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk" version="4.0"/>
|
||||||
|
<template class="EnvironmentColumnHeader" parent="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">4</property>
|
||||||
|
<property name="width-request">200</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="name_label">
|
||||||
|
<property name="xalign">0.5</property>
|
||||||
|
<property name="ellipsize">end</property>
|
||||||
|
<property name="max-width-chars">20</property>
|
||||||
|
<style>
|
||||||
|
<class name="heading"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="spacing">4</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="edit_button">
|
||||||
|
<property name="icon-name">document-edit-symbolic</property>
|
||||||
|
<property name="tooltip-text">Edit environment</property>
|
||||||
|
<signal name="clicked" handler="on_edit_clicked"/>
|
||||||
|
<style>
|
||||||
|
<class name="flat"/>
|
||||||
|
<class name="circular"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="delete_button">
|
||||||
|
<property name="icon-name">edit-delete-symbolic</property>
|
||||||
|
<property name="tooltip-text">Delete environment</property>
|
||||||
|
<signal name="clicked" handler="on_delete_clicked"/>
|
||||||
|
<style>
|
||||||
|
<class name="flat"/>
|
||||||
|
<class name="circular"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
||||||
39
src/widgets/environment-header-row.ui
Normal file
39
src/widgets/environment-header-row.ui
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk" version="4.0"/>
|
||||||
|
<template class="EnvironmentHeaderRow" parent="GtkBox">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
|
<property name="margin-start">12</property>
|
||||||
|
<property name="margin-end">12</property>
|
||||||
|
<property name="margin-top">12</property>
|
||||||
|
<property name="margin-bottom">6</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="variable_cell">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<property name="width-request">150</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="variable_label">
|
||||||
|
<property name="label">Variable</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<style>
|
||||||
|
<class name="heading"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="columns_box">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
||||||
55
src/widgets/environment_column_header.py
Normal file
55
src/widgets/environment_column_header.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# environment_column_header.py
|
||||||
|
#
|
||||||
|
# Copyright 2025 Pavel Baksy
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from gi.repository import Gtk, GObject
|
||||||
|
|
||||||
|
|
||||||
|
@Gtk.Template(resource_path='/cz/vesp/roster/widgets/environment-column-header.ui')
|
||||||
|
class EnvironmentColumnHeader(Gtk.Box):
|
||||||
|
"""Widget for displaying an environment column header with edit/delete buttons."""
|
||||||
|
|
||||||
|
__gtype_name__ = 'EnvironmentColumnHeader'
|
||||||
|
|
||||||
|
name_label = Gtk.Template.Child()
|
||||||
|
edit_button = Gtk.Template.Child()
|
||||||
|
delete_button = Gtk.Template.Child()
|
||||||
|
|
||||||
|
__gsignals__ = {
|
||||||
|
'edit-requested': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
|
'delete-requested': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, environment):
|
||||||
|
super().__init__()
|
||||||
|
self.environment = environment
|
||||||
|
self.name_label.set_text(environment.name)
|
||||||
|
|
||||||
|
@Gtk.Template.Callback()
|
||||||
|
def on_edit_clicked(self, button):
|
||||||
|
"""Handle edit button click."""
|
||||||
|
self.emit('edit-requested')
|
||||||
|
|
||||||
|
@Gtk.Template.Callback()
|
||||||
|
def on_delete_clicked(self, button):
|
||||||
|
"""Handle delete button click."""
|
||||||
|
self.emit('delete-requested')
|
||||||
|
|
||||||
|
def update_name(self, name):
|
||||||
|
"""Update the environment name display."""
|
||||||
|
self.name_label.set_text(name)
|
||||||
83
src/widgets/environment_header_row.py
Normal file
83
src/widgets/environment_header_row.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# environment_header_row.py
|
||||||
|
#
|
||||||
|
# Copyright 2025 Pavel Baksy
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from gi.repository import Gtk, GObject
|
||||||
|
from .environment_column_header import EnvironmentColumnHeader
|
||||||
|
|
||||||
|
|
||||||
|
@Gtk.Template(resource_path='/cz/vesp/roster/widgets/environment-header-row.ui')
|
||||||
|
class EnvironmentHeaderRow(Gtk.Box):
|
||||||
|
"""Widget for the header row containing all environment column headers."""
|
||||||
|
|
||||||
|
__gtype_name__ = 'EnvironmentHeaderRow'
|
||||||
|
|
||||||
|
variable_cell = Gtk.Template.Child()
|
||||||
|
variable_label = Gtk.Template.Child()
|
||||||
|
columns_box = Gtk.Template.Child()
|
||||||
|
|
||||||
|
__gsignals__ = {
|
||||||
|
'environment-edit-requested': (GObject.SIGNAL_RUN_FIRST, None, (object,)),
|
||||||
|
'environment-delete-requested': (GObject.SIGNAL_RUN_FIRST, None, (object,)),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, environments, size_group):
|
||||||
|
super().__init__()
|
||||||
|
self.environments = environments
|
||||||
|
self.size_group = size_group
|
||||||
|
self.column_headers = {}
|
||||||
|
|
||||||
|
# Add variable cell to size group for alignment
|
||||||
|
if size_group:
|
||||||
|
size_group.add_widget(self.variable_cell)
|
||||||
|
|
||||||
|
self._populate()
|
||||||
|
|
||||||
|
def _populate(self):
|
||||||
|
"""Populate with environment column headers."""
|
||||||
|
# Clear existing
|
||||||
|
while child := self.columns_box.get_first_child():
|
||||||
|
self.columns_box.remove(child)
|
||||||
|
|
||||||
|
self.column_headers = {}
|
||||||
|
|
||||||
|
# Create column header for each environment
|
||||||
|
for env in self.environments:
|
||||||
|
header = EnvironmentColumnHeader(env)
|
||||||
|
header.connect('edit-requested', self._on_edit_requested, env)
|
||||||
|
header.connect('delete-requested', self._on_delete_requested, env)
|
||||||
|
|
||||||
|
# Add to size group for alignment with data rows
|
||||||
|
if self.size_group:
|
||||||
|
self.size_group.add_widget(header)
|
||||||
|
|
||||||
|
self.columns_box.append(header)
|
||||||
|
self.column_headers[env.id] = header
|
||||||
|
|
||||||
|
def _on_edit_requested(self, widget, environment):
|
||||||
|
"""Handle edit request from column header."""
|
||||||
|
self.emit('environment-edit-requested', environment)
|
||||||
|
|
||||||
|
def _on_delete_requested(self, widget, environment):
|
||||||
|
"""Handle delete request from column header."""
|
||||||
|
self.emit('environment-delete-requested', environment)
|
||||||
|
|
||||||
|
def refresh(self, environments):
|
||||||
|
"""Refresh with updated environments list."""
|
||||||
|
self.environments = environments
|
||||||
|
self._populate()
|
||||||
47
src/widgets/variable-data-row.ui
Normal file
47
src/widgets/variable-data-row.ui
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk" version="4.0"/>
|
||||||
|
<template class="VariableDataRow" parent="GtkBox">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
|
<property name="margin-start">12</property>
|
||||||
|
<property name="margin-end">12</property>
|
||||||
|
<property name="margin-top">6</property>
|
||||||
|
<property name="margin-bottom">6</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="variable_cell">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<property name="width-request">150</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="name_entry">
|
||||||
|
<property name="placeholder-text">Variable name</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<signal name="changed" handler="on_name_changed"/>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="delete_button">
|
||||||
|
<property name="icon-name">edit-delete-symbolic</property>
|
||||||
|
<property name="tooltip-text">Delete variable</property>
|
||||||
|
<signal name="clicked" handler="on_delete_clicked"/>
|
||||||
|
<style>
|
||||||
|
<class name="flat"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="values_box">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
||||||
106
src/widgets/variable_data_row.py
Normal file
106
src/widgets/variable_data_row.py
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
# variable_data_row.py
|
||||||
|
#
|
||||||
|
# Copyright 2025 Pavel Baksy
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from gi.repository import Gtk, GObject
|
||||||
|
|
||||||
|
|
||||||
|
@Gtk.Template(resource_path='/cz/vesp/roster/widgets/variable-data-row.ui')
|
||||||
|
class VariableDataRow(Gtk.Box):
|
||||||
|
"""Widget for a data row with variable name and values for each environment."""
|
||||||
|
|
||||||
|
__gtype_name__ = 'VariableDataRow'
|
||||||
|
|
||||||
|
variable_cell = Gtk.Template.Child()
|
||||||
|
name_entry = Gtk.Template.Child()
|
||||||
|
delete_button = Gtk.Template.Child()
|
||||||
|
values_box = Gtk.Template.Child()
|
||||||
|
|
||||||
|
__gsignals__ = {
|
||||||
|
'variable-changed': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
|
'variable-delete-requested': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
|
'value-changed': (GObject.SIGNAL_RUN_FIRST, None, (str, str)), # env_id, value
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, variable_name, environments, size_group):
|
||||||
|
super().__init__()
|
||||||
|
self.variable_name = variable_name
|
||||||
|
self.environments = environments
|
||||||
|
self.size_group = size_group
|
||||||
|
self.value_entries = {}
|
||||||
|
|
||||||
|
# Set variable name
|
||||||
|
self.name_entry.set_text(variable_name)
|
||||||
|
|
||||||
|
# Add variable cell to size group for alignment
|
||||||
|
if size_group:
|
||||||
|
size_group.add_widget(self.variable_cell)
|
||||||
|
|
||||||
|
self._populate_values()
|
||||||
|
|
||||||
|
def _populate_values(self):
|
||||||
|
"""Populate value entries for each environment."""
|
||||||
|
# Clear existing
|
||||||
|
while child := self.values_box.get_first_child():
|
||||||
|
self.values_box.remove(child)
|
||||||
|
|
||||||
|
self.value_entries = {}
|
||||||
|
|
||||||
|
# Create entry for each environment
|
||||||
|
for env in self.environments:
|
||||||
|
# Create a box to hold the entry (for size group alignment)
|
||||||
|
entry_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||||
|
entry_box.set_width_request(200)
|
||||||
|
|
||||||
|
entry = Gtk.Entry()
|
||||||
|
entry.set_placeholder_text(env.name)
|
||||||
|
entry.set_text(env.variables.get(self.variable_name, ""))
|
||||||
|
entry.set_hexpand(True)
|
||||||
|
entry.connect('changed', self._on_value_changed, env.id)
|
||||||
|
|
||||||
|
entry_box.append(entry)
|
||||||
|
|
||||||
|
# Add entry box to size group for alignment
|
||||||
|
if self.size_group:
|
||||||
|
self.size_group.add_widget(entry_box)
|
||||||
|
|
||||||
|
self.values_box.append(entry_box)
|
||||||
|
self.value_entries[env.id] = entry
|
||||||
|
|
||||||
|
def _on_value_changed(self, entry, env_id):
|
||||||
|
"""Handle value entry changes."""
|
||||||
|
self.emit('value-changed', env_id, entry.get_text())
|
||||||
|
|
||||||
|
@Gtk.Template.Callback()
|
||||||
|
def on_name_changed(self, entry):
|
||||||
|
"""Handle variable name changes."""
|
||||||
|
self.emit('variable-changed')
|
||||||
|
|
||||||
|
@Gtk.Template.Callback()
|
||||||
|
def on_delete_clicked(self, button):
|
||||||
|
"""Handle delete button click."""
|
||||||
|
self.emit('variable-delete-requested')
|
||||||
|
|
||||||
|
def get_variable_name(self):
|
||||||
|
"""Return current variable name."""
|
||||||
|
return self.name_entry.get_text().strip()
|
||||||
|
|
||||||
|
def refresh(self, environments):
|
||||||
|
"""Refresh with updated environments list."""
|
||||||
|
self.environments = environments
|
||||||
|
self._populate_values()
|
||||||
Loading…
x
Reference in New Issue
Block a user