From 530ed0c029379f3d958c8c2fb54bbe519e007281 Mon Sep 17 00:00:00 2001
From: Niko Aarnio <niko.aarnio@protonmail.com>
Date: Wed, 27 Nov 2024 13:47:16 +0200
Subject: [PATCH 1/2] redesign plan regulation widget buttons, add expand/hide
 button

---
 .../gui/plan_regulation_widget.py             |  87 +++++---
 .../gui/plan_regulation_widget.ui             | 201 ++++++++++--------
 2 files changed, 181 insertions(+), 107 deletions(-)

diff --git a/arho_feature_template/gui/plan_regulation_widget.py b/arho_feature_template/gui/plan_regulation_widget.py
index 6f0fdbd..2eb19c8 100644
--- a/arho_feature_template/gui/plan_regulation_widget.py
+++ b/arho_feature_template/gui/plan_regulation_widget.py
@@ -1,6 +1,5 @@
 from __future__ import annotations
 
-from collections import defaultdict
 from importlib import resources
 from typing import TYPE_CHECKING, cast
 
@@ -16,6 +15,7 @@
     QMenu,
     QSizePolicy,
     QTextEdit,
+    QToolButton,
     QWidget,
 )
 
@@ -23,8 +23,6 @@
 from arho_feature_template.utils.misc_utils import get_additional_information_name
 
 if TYPE_CHECKING:
-    from numbers import Number
-
     from qgis.PyQt.QtWidgets import QPushButton
 
     from arho_feature_template.core.plan_regulation_group_config import PlanRegulationDefinition
@@ -56,21 +54,23 @@ def __init__(self, config: PlanRegulationConfig, parent=None):
         self.setupUi(self)
 
         # TYPES
+        # self.spacer_layout: QBoxLayout
         self.plan_regulation_name: QLineEdit
         self.form_layout: QFormLayout
 
         self.add_additional_information_btn: QPushButton
-        self.add_regulation_number_btn: QPushButton
-        self.add_file_btn: QPushButton
+        self.add_field_btn: QPushButton
         self.del_btn: QPushButton
+        self.expand_hide_btn: QToolButton
+
+        self.code_label: QLabel
+        self.code: QLineEdit
 
         # INIT
         self.config = config
         self.regulation_number_added = False
-        # Key is related field name, value is 1) widget, 2) tuple of widget and default value
-        # NOTE: Maybe this is not something needed? Instead, when user clicks Ok, write into a YAML
-        # in a separate script?
-        self.attribute_widgets: dict[str, QWidget | tuple[QWidget, str | Number]] = defaultdict(dict)
+        self.expanded = True
+        self.widgets: list[tuple] = []
         self.plan_regulation_name.setText(config.name)
         self.plan_regulation_name.setReadOnly(True)
         self.init_value_fields()
@@ -157,31 +157,58 @@ def init_buttons(self):
         type_main_menu.addMenu(type_menu)
         type_main_menu.addMenu(signifigance_menu)
         self.add_additional_information_btn.setMenu(type_main_menu)
-
-        # REGULATION NUMBER
-        self.add_regulation_number_btn.clicked.connect(self.add_regulation_number)
-
-        # ADD FILE
-        self.add_file_btn.clicked.connect(self.add_file)
+        self.add_additional_information_btn.setIcon(QgsApplication.getThemeIcon("mActionPropertiesWidget.svg"))
+
+        # OTHER INFO / ADD FIELD
+        add_field_menu = QMenu(self)
+        add_field_menu.addAction("Määräysnumero").triggered.connect(self.add_regulation_number)
+        add_field_menu.addAction("Liiteasiakirja").triggered.connect(self.add_file)
+        self.add_field_btn.setMenu(add_field_menu)
+        self.add_field_btn.setIcon(QgsApplication.getThemeIcon("mActionAdd.svg"))
+
+        # EXPAND BTN
+        self.expand_hide_btn.clicked.connect(self._on_expand_hide_btn_clicked)
+
+    def _on_expand_hide_btn_clicked(self):
+        if self.expanded:
+            for label, widget in self.widgets:
+                self.form_layout.removeWidget(label)
+                label.hide()
+                self.form_layout.removeWidget(widget)
+                widget.hide()
+            self.expand_hide_btn.setArrowType(Qt.ArrowType.DownArrow)
+            self.expanded = False
+        else:
+            for label, widget in self.widgets:
+                label.show()
+                widget.show()
+                self.form_layout.addRow(label, widget)
+            self.expand_hide_btn.setArrowType(Qt.ArrowType.UpArrow)
+            self.expanded = True
 
     def add_decimal_input(self, layout: QHBoxLayout, value_type: ValueType):
         value_widget = QgsDoubleSpinBox()
-        label_text = "Desimaali"
+        label = QLabel("Arvo")
         if value_type == ValueType.POSITIVE_DECIMAL:
             value_widget.setMinimum(0.0)
-            label_text += " (positiivinen)"
+            label.setToolTip("Tyyppi: desimaali (positiivinen)")
         else:
             value_widget.setMinimum(-9999.9)
+            label.setToolTip("Tyyppi: desimaali")
         value_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
         layout.addWidget(value_widget)
-        self.form_layout.addRow(label_text, layout)
+        self.form_layout.addRow(label, layout)
+        self.widgets.append((label, value_widget))
 
     def add_positive_integer_input(self, layout: QHBoxLayout):
         value_widget = QgsSpinBox()
         value_widget.setMinimum(0)
         value_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
         layout.addWidget(value_widget)
-        self.form_layout.addRow("Kokonaisluku (positiivinen)", layout)
+        label = QLabel("Arvo")
+        label.setToolTip("Tyyppi: kokonaisluku (positiivinen)")
+        self.form_layout.addRow(label, layout)
+        self.widgets.append((label, value_widget))
 
     def add_positive_integer_range_input(self, layout: QHBoxLayout):
         min_widget = QgsSpinBox()
@@ -194,12 +221,18 @@ def add_positive_integer_range_input(self, layout: QHBoxLayout):
         dash_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
         layout.addWidget(dash_label)
         layout.addWidget(max_widget)
-        self.form_layout.addRow("Kokonaisluku arvoväli (positiivinen)", layout)
+        label = QLabel("Arvo")
+        label.setToolTip("Tyyppi: kokonaisluku arvoväli (positiivinen)")
+        self.form_layout.addRow(label, layout)
+        self.widgets.append((label, layout))
 
     def add_versioned_text_input(self, layout: QHBoxLayout):
         text_widget = QTextEdit()
         layout.addWidget(text_widget)
-        self.form_layout.addRow("Kieliversioitu teksti", layout)
+        label = QLabel("Arvo")
+        label.setToolTip("Tyyppi: kieliversioitu teksti")
+        self.form_layout.addRow(label, layout)
+        self.widgets.append((label, text_widget))
 
     def add_additional_info(self, info_type: str) -> QHBoxLayout:
         layout = QHBoxLayout()
@@ -207,15 +240,21 @@ def add_additional_info(self, info_type: str) -> QHBoxLayout:
         info_type_label = QLineEdit(info_name)
         info_type_label.setReadOnly(True)
         layout.addWidget(info_type_label)
-        self.form_layout.addRow("Lisätiedonlaji", layout)
+        label = QLabel("Lisätiedonlaji")
+        self.form_layout.addRow(label, layout)
+        self.widgets.append((label, info_type_label))
         return layout
 
     def add_regulation_number(self):
         if not self.regulation_number_added:
             number_widget = QgsSpinBox()
-            self.form_layout.addRow("Määräysnumero", number_widget)
+            label = QLabel("Määräysnumero")
+            self.form_layout.addRow(label, number_widget)
+            self.widgets.append((label, number_widget))
             self.regulation_number_added = True
 
     def add_file(self):
         file_input = QgsFileWidget()
-        self.form_layout.addRow("Liiteasiakirja", file_input)
+        label = QLabel("Liiteasiakirja")
+        self.form_layout.addRow(label, file_input)
+        self.widgets.append((label, file_input))
diff --git a/arho_feature_template/gui/plan_regulation_widget.ui b/arho_feature_template/gui/plan_regulation_widget.ui
index e6f5225..e767ec4 100644
--- a/arho_feature_template/gui/plan_regulation_widget.ui
+++ b/arho_feature_template/gui/plan_regulation_widget.ui
@@ -7,131 +7,166 @@
     <x>0</x>
     <y>0</y>
     <width>694</width>
-    <height>108</height>
+    <height>131</height>
    </rect>
   </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
+  <property name="styleSheet">
+   <string notr="true"/>
+  </property>
   <layout class="QVBoxLayout" name="verticalLayout">
-   <item>
-    <layout class="QFormLayout" name="form_layout">
-     <item row="0" column="0">
-      <widget class="QLabel" name="label_4">
-       <property name="text">
-        <string>Kaavamääräyslaji</string>
-       </property>
-      </widget>
-     </item>
-     <item row="0" column="1">
-      <layout class="QHBoxLayout" name="horizontalLayout">
-       <item>
-        <widget class="QLineEdit" name="plan_regulation_name"/>
-       </item>
-       <item>
-        <widget class="QPushButton" name="del_btn">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="maximumSize">
-          <size>
-           <width>30</width>
-           <height>16777215</height>
-          </size>
-         </property>
-         <property name="text">
-          <string/>
-         </property>
-        </widget>
-       </item>
-      </layout>
-     </item>
-    </layout>
-   </item>
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout_2">
      <item>
-      <widget class="QPushButton" name="add_additional_information_btn">
-       <property name="text">
-        <string>Lisätieto</string>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
        </property>
-      </widget>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
      </item>
      <item>
-      <widget class="QPushButton" name="add_regulation_number_btn">
+      <widget class="QPushButton" name="add_additional_information_btn">
        <property name="text">
-        <string>Määräysnumero</string>
+        <string>Lisätieto</string>
        </property>
       </widget>
      </item>
      <item>
-      <widget class="QPushButton" name="add_file_btn">
+      <widget class="QPushButton" name="add_field_btn">
        <property name="text">
-        <string>Liiteasiakirja</string>
+        <string>Muu tieto</string>
        </property>
       </widget>
      </item>
      <item>
-      <spacer name="horizontalSpacer_3">
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
+      <widget class="QPushButton" name="del_btn">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
        </property>
-       <property name="sizeHint" stdset="0">
+       <property name="maximumSize">
         <size>
-         <width>40</width>
-         <height>20</height>
+         <width>16777215</width>
+         <height>16777215</height>
         </size>
        </property>
-      </spacer>
+       <property name="text">
+        <string>Poista</string>
+       </property>
+      </widget>
      </item>
     </layout>
    </item>
    <item>
-    <layout class="QHBoxLayout" name="horizontalLayout_4">
-     <item>
-      <spacer name="horizontalSpacer_4">
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeType">
-        <enum>QSizePolicy::Fixed</enum>
-       </property>
-       <property name="sizeHint" stdset="0">
-        <size>
-         <width>40</width>
-         <height>20</height>
-        </size>
+    <layout class="QFormLayout" name="form_layout">
+     <item row="0" column="0">
+      <widget class="QLabel" name="label_4">
+       <property name="text">
+        <string>Kaavamääräyslaji</string>
        </property>
-      </spacer>
+      </widget>
      </item>
+     <item row="0" column="1">
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <widget class="QLineEdit" name="plan_regulation_name"/>
+       </item>
+       <item>
+        <widget class="QToolButton" name="expand_hide_btn">
+         <property name="text">
+          <string>Laajenna</string>
+         </property>
+         <property name="autoRaise">
+          <bool>false</bool>
+         </property>
+         <property name="arrowType">
+          <enum>Qt::UpArrow</enum>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QVBoxLayout" name="spacer_layout">
      <item>
-      <widget class="Line" name="line">
-       <property name="minimumSize">
-        <size>
-         <width>0</width>
-         <height>20</height>
-        </size>
-       </property>
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-      </widget>
+      <layout class="QHBoxLayout" name="horizontalLayout_4">
+       <item>
+        <spacer name="horizontalSpacer_4">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeType">
+          <enum>QSizePolicy::Fixed</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="Line" name="line">
+         <property name="minimumSize">
+          <size>
+           <width>0</width>
+           <height>20</height>
+          </size>
+         </property>
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer_5">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeType">
+          <enum>QSizePolicy::Fixed</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
      </item>
      <item>
-      <spacer name="horizontalSpacer_5">
+      <spacer name="verticalSpacer">
        <property name="orientation">
-        <enum>Qt::Horizontal</enum>
+        <enum>Qt::Vertical</enum>
        </property>
        <property name="sizeType">
         <enum>QSizePolicy::Fixed</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
-         <width>40</width>
-         <height>20</height>
+         <width>20</width>
+         <height>15</height>
         </size>
        </property>
       </spacer>

From e8359a0b5d5be34a94f3d8604f4656825ab895af Mon Sep 17 00:00:00 2001
From: Niko Aarnio <niko.aarnio@protonmail.com>
Date: Wed, 27 Nov 2024 15:27:23 +0200
Subject: [PATCH 2/2] fix expand button by not nesting layouts inside form
 layout of plan regulation, add topic tag (name) and theme

---
 .../gui/plan_regulation_widget.py             | 138 +++++++++---------
 1 file changed, 73 insertions(+), 65 deletions(-)

diff --git a/arho_feature_template/gui/plan_regulation_widget.py b/arho_feature_template/gui/plan_regulation_widget.py
index 2eb19c8..fcdbbb4 100644
--- a/arho_feature_template/gui/plan_regulation_widget.py
+++ b/arho_feature_template/gui/plan_regulation_widget.py
@@ -9,7 +9,6 @@
 from qgis.PyQt.QtCore import Qt, pyqtSignal
 from qgis.PyQt.QtWidgets import (
     QFormLayout,
-    QHBoxLayout,
     QLabel,
     QLineEdit,
     QMenu,
@@ -20,7 +19,7 @@
 )
 
 from arho_feature_template.core.plan_regulation_config import PlanRegulationConfig, Unit, ValueType
-from arho_feature_template.utils.misc_utils import get_additional_information_name
+from arho_feature_template.utils.misc_utils import get_additional_information_name, get_layer_by_name
 
 if TYPE_CHECKING:
     from qgis.PyQt.QtWidgets import QPushButton
@@ -70,7 +69,7 @@ def __init__(self, config: PlanRegulationConfig, parent=None):
         self.config = config
         self.regulation_number_added = False
         self.expanded = True
-        self.widgets: list[tuple] = []
+        self.widgets: list[tuple[QLabel, QWidget]] = []
         self.plan_regulation_name.setText(config.name)
         self.plan_regulation_name.setReadOnly(True)
         self.init_value_fields()
@@ -80,44 +79,35 @@ def populate_from_definition(self, definition: PlanRegulationDefinition):
         # Additional information
         for info in definition.additional_information:
             info_type: str = cast("str", info["type"])
-            layout = self.add_additional_info(info_type)
-            if info_type in ADDITIONAL_INFORMATION_TYPES_WITH_INPUT:
+            self.add_additional_info(info_type)
+            if info_type == "kayttotarkoituskohdistus":
                 info_value_widget = QLineEdit()
-                layout.addWidget(info_value_widget)
+                label = QLabel(get_additional_information_name(info_type))
                 value = info.get("value")
                 if value:
                     info_value_widget.setText(value)
+                self.form_layout.addRow(label, info_value_widget)
 
         # TODO: Other saved information from PlanRegulationDefinition
 
     def init_value_fields(self):
-        layout = QHBoxLayout()
         value_type = self.config.value_type
         if value_type:
-            self._add_value_input(value_type, layout)
+            self._add_value_input(value_type, self.config.unit)
 
-        unit = self.config.unit
-        if unit:
-            self._add_value_unit(unit, layout)
-
-    def _add_value_input(self, value_type: ValueType, layout: QHBoxLayout):
+    def _add_value_input(self, value_type: ValueType, unit: Unit | None):
         if value_type in [ValueType.DECIMAL, ValueType.POSITIVE_DECIMAL]:
-            self.add_decimal_input(layout, value_type)
+            self.add_decimal_input(value_type, unit)
         elif value_type == ValueType.POSITIVE_INTEGER:
-            self.add_positive_integer_input(layout)
+            self.add_positive_integer_input(unit)
         elif value_type == ValueType.POSITIVE_INTEGER_RANGE:
-            self.add_positive_integer_range_input(layout)
+            self.add_positive_integer_range_input(unit)
         elif value_type == ValueType.VERSIONED_TEXT:
-            self.add_versioned_text_input(layout)
+            self.add_versioned_text_input()
         else:
             msg = f"Invalid input value type for plan regulation: {value_type}"
             raise ValueError(msg)
 
-    def _add_value_unit(self, unit: Unit, layout: QHBoxLayout):
-        # NOTE: Unit could also be suffix in the QgsSpinBox, could be clearer?
-        unit_label = QLabel(unit.value)
-        layout.addWidget(unit_label)
-
     def init_buttons(self):
         # DEL
         self.del_btn.setIcon(QgsApplication.getThemeIcon("mActionDeleteSelected.svg"))
@@ -163,6 +153,16 @@ def init_buttons(self):
         add_field_menu = QMenu(self)
         add_field_menu.addAction("Määräysnumero").triggered.connect(self.add_regulation_number)
         add_field_menu.addAction("Liiteasiakirja").triggered.connect(self.add_file)
+        add_field_menu.addAction("Aihetunniste").triggered.connect(self.add_topic_tag)
+
+        theme_menu = QMenu("Kaavoitusteema", self)
+        language = "fin"
+        for feature in get_layer_by_name("Kaavoitusteemat").getFeatures():
+            name = feature["name"][language]
+            action = theme_menu.addAction(name)
+            action.triggered.connect(lambda _, name=name: self.add_theme(name))
+        add_field_menu.addMenu(theme_menu)
+
         self.add_field_btn.setMenu(add_field_menu)
         self.add_field_btn.setIcon(QgsApplication.getThemeIcon("mActionAdd.svg"))
 
@@ -171,22 +171,28 @@ def init_buttons(self):
 
     def _on_expand_hide_btn_clicked(self):
         if self.expanded:
-            for label, widget in self.widgets:
+            for label, value_widget in self.widgets:
                 self.form_layout.removeWidget(label)
                 label.hide()
-                self.form_layout.removeWidget(widget)
-                widget.hide()
+                self.form_layout.removeWidget(value_widget)
+                value_widget.hide()
             self.expand_hide_btn.setArrowType(Qt.ArrowType.DownArrow)
             self.expanded = False
         else:
-            for label, widget in self.widgets:
+            for label, value_widget in self.widgets:
+                self.form_layout.addRow(label, value_widget)
                 label.show()
-                widget.show()
-                self.form_layout.addRow(label, widget)
+                value_widget.show()
             self.expand_hide_btn.setArrowType(Qt.ArrowType.UpArrow)
             self.expanded = True
 
-    def add_decimal_input(self, layout: QHBoxLayout, value_type: ValueType):
+    def _add_widgets_to_form(self, label: QLabel, widget: QWidget):
+        self.form_layout.addRow(label, widget)
+        self.widgets.append((label, widget))
+        if not self.expanded:
+            self._on_expand_hide_btn_clicked()
+
+    def add_decimal_input(self, value_type: ValueType, unit: Unit | None):
         value_widget = QgsDoubleSpinBox()
         label = QLabel("Arvo")
         if value_type == ValueType.POSITIVE_DECIMAL:
@@ -196,65 +202,67 @@ def add_decimal_input(self, layout: QHBoxLayout, value_type: ValueType):
             value_widget.setMinimum(-9999.9)
             label.setToolTip("Tyyppi: desimaali")
         value_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
-        layout.addWidget(value_widget)
-        self.form_layout.addRow(label, layout)
-        self.widgets.append((label, value_widget))
+        if unit:
+            value_widget.setSuffix(f" {unit.value}")
+        self._add_widgets_to_form(label, value_widget)
 
-    def add_positive_integer_input(self, layout: QHBoxLayout):
+    def add_positive_integer_input(self, unit: Unit | None):
         value_widget = QgsSpinBox()
         value_widget.setMinimum(0)
         value_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
-        layout.addWidget(value_widget)
+        if unit:
+            value_widget.setSuffix(f" {unit.value}")
         label = QLabel("Arvo")
         label.setToolTip("Tyyppi: kokonaisluku (positiivinen)")
-        self.form_layout.addRow(label, layout)
-        self.widgets.append((label, value_widget))
+        self._add_widgets_to_form(label, value_widget)
 
-    def add_positive_integer_range_input(self, layout: QHBoxLayout):
+    def add_positive_integer_range_input(self, unit: Unit | None):
         min_widget = QgsSpinBox()
         min_widget.setMinimum(0)
+        min_label = QLabel("Arvo minimi")
+        min_label.setToolTip("Tyyppi: kokonaisluku arvoväli (positiivinen)")
+
         max_widget = QgsSpinBox()
         max_widget.setMinimum(0)
-        layout.addWidget(min_widget)
-        dash_label = QLabel(" — ")
-        dash_label.setAlignment(Qt.AlignCenter)
-        dash_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
-        layout.addWidget(dash_label)
-        layout.addWidget(max_widget)
-        label = QLabel("Arvo")
-        label.setToolTip("Tyyppi: kokonaisluku arvoväli (positiivinen)")
-        self.form_layout.addRow(label, layout)
-        self.widgets.append((label, layout))
+        max_label = QLabel("Arvo maksimi")
+        max_label.setToolTip("Tyyppi: kokonaisluku arvoväli (positiivinen)")
+        if unit:
+            min_widget.setSuffix(f" {unit.value}")
+            max_widget.setSuffix(f" {unit.value}")
+        self._add_widgets_to_form(min_label, min_widget)
+        self._add_widgets_to_form(max_label, max_widget)
 
-    def add_versioned_text_input(self, layout: QHBoxLayout):
+    def add_versioned_text_input(self):
         text_widget = QTextEdit()
-        layout.addWidget(text_widget)
         label = QLabel("Arvo")
         label.setToolTip("Tyyppi: kieliversioitu teksti")
-        self.form_layout.addRow(label, layout)
-        self.widgets.append((label, text_widget))
-
-    def add_additional_info(self, info_type: str) -> QHBoxLayout:
-        layout = QHBoxLayout()
-        info_name = get_additional_information_name(info_type)
-        info_type_label = QLineEdit(info_name)
-        info_type_label.setReadOnly(True)
-        layout.addWidget(info_type_label)
+        self._add_widgets_to_form(label, text_widget)
+
+    def add_additional_info(self, info_type: str):
+        info_type_line = QLineEdit(get_additional_information_name(info_type))
+        info_type_line.setReadOnly(True)
         label = QLabel("Lisätiedonlaji")
-        self.form_layout.addRow(label, layout)
-        self.widgets.append((label, info_type_label))
-        return layout
+        self._add_widgets_to_form(label, info_type_line)
 
     def add_regulation_number(self):
         if not self.regulation_number_added:
             number_widget = QgsSpinBox()
             label = QLabel("Määräysnumero")
-            self.form_layout.addRow(label, number_widget)
-            self.widgets.append((label, number_widget))
+            self._add_widgets_to_form(label, number_widget)
             self.regulation_number_added = True
 
     def add_file(self):
         file_input = QgsFileWidget()
         label = QLabel("Liiteasiakirja")
-        self.form_layout.addRow(label, file_input)
-        self.widgets.append((label, file_input))
+        self._add_widgets_to_form(label, file_input)
+
+    def add_topic_tag(self):
+        text_input = QLineEdit()
+        label = QLabel("Aihetunniste")
+        self._add_widgets_to_form(label, text_input)
+
+    def add_theme(self, theme_name: str):
+        theme_type_line = QLineEdit(theme_name)
+        theme_type_line.setReadOnly(True)
+        label = QLabel("Kaavoitusteema")
+        self._add_widgets_to_form(label, theme_type_line)