Feature/ui #1
+41
-29
@@ -13,46 +13,58 @@ def git_push_changes(
|
||||
master_hla_names_rel_path: str,
|
||||
master_ioc_subs_rel_path: str,
|
||||
iocs_overview_rel_path: str,
|
||||
service_manager_ui_rel_path: str,
|
||||
commit_msg: str,
|
||||
):
|
||||
"""
|
||||
Push newly created service to Gitea
|
||||
"""
|
||||
files_to_stage = [
|
||||
service_dir_rel_path,
|
||||
registry_file_rel_path,
|
||||
master_hla_names_rel_path,
|
||||
master_ioc_subs_rel_path,
|
||||
iocs_overview_rel_path,
|
||||
service_manager_ui_rel_path,
|
||||
]
|
||||
logger.info(f"Staging files inside: {files_to_stage}")
|
||||
repo.index.add(files_to_stage)
|
||||
|
||||
# Check if there are changes to avoid empty commit crashes
|
||||
if not repo.is_dirty(index=True, working_tree=False):
|
||||
logger.info("No changes detected. Skipping commit.")
|
||||
return
|
||||
|
||||
logger.info("Committing changes...")
|
||||
repo.index.commit(commit_msg)
|
||||
|
||||
try:
|
||||
logger.info(
|
||||
"Staging files inside: "
|
||||
f"{service_dir_rel_path}, "
|
||||
f"{registry_file_rel_path}, "
|
||||
f"{master_hla_names_rel_path}, "
|
||||
f"{master_ioc_subs_rel_path}..."
|
||||
f"{iocs_overview_rel_path}..."
|
||||
)
|
||||
repo.index.add(
|
||||
[
|
||||
service_dir_rel_path,
|
||||
registry_file_rel_path,
|
||||
master_hla_names_rel_path,
|
||||
master_ioc_subs_rel_path,
|
||||
iocs_overview_rel_path,
|
||||
]
|
||||
)
|
||||
|
||||
# Check if there are changes to avoid empty commit crashes
|
||||
if not repo.is_dirty(index=True, working_tree=False):
|
||||
logger.info("No changes detected. Skipping commit.")
|
||||
return
|
||||
|
||||
logger.info("Committing changes...")
|
||||
repo.index.commit(commit_msg)
|
||||
|
||||
logger.info(f"Pushing branch '{branch_name}' to origin...")
|
||||
origin = repo.remote(name="origin")
|
||||
origin.push(refspec=f"{branch_name}:{branch_name}").raise_if_error()
|
||||
except git.GitCommandError as e:
|
||||
logger.error(f"Push failed due to an error: {e}")
|
||||
logger.info("Rolling back local Git index changes...")
|
||||
|
||||
logger.info("Successfully pushed!")
|
||||
# Step A: Undo the local commit if it was created (moves HEAD back 1 commit, keeps changes)
|
||||
# This prevents leaving a dead/unpushed commit on your local branch
|
||||
try:
|
||||
repo.head.reset("HEAD~1", index=True, working_tree=False)
|
||||
except Exception:
|
||||
# Fallback if the exception happened BEFORE the commit step even ran
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
logger.info(f"Git Operation Failed: {e}")
|
||||
# Step B: Unstage the specific files (Equivalent to: git reset HEAD <files>)
|
||||
# This leaves the files intact but removes them from the staging area
|
||||
repo.index.reset(paths=files_to_stage)
|
||||
logger.info("Staging area successfully reset to clean state.")
|
||||
|
||||
# TODO: we could also force push... need to think about workflow though.
|
||||
raise RuntimeError(
|
||||
f"Failed to push to git due to: {e}.\nDoes the branch already exist in Gitea? If yes, it needs to be deleted first."
|
||||
)
|
||||
|
||||
logger.info("Successfully pushed!")
|
||||
|
||||
|
||||
def delete_local_branch(repo: git.Repo, branch_name: str):
|
||||
|
||||
+180
-2
@@ -1,8 +1,9 @@
|
||||
import re
|
||||
from typing import ClassVar
|
||||
import xml.etree.ElementTree as ET
|
||||
from typing import Any, ClassVar
|
||||
|
||||
import yaml
|
||||
from pydantic import BaseModel, field_validator
|
||||
from pydantic import BaseModel, ConfigDict, field_validator
|
||||
|
||||
from core.enums import ServiceStatus
|
||||
from core.utils import get_git_root
|
||||
@@ -17,6 +18,11 @@ MASTER_HLA_NAMES_FILENAME = MASTER_SERVICE_CONFIG_DIR / "hla_names.yml"
|
||||
|
||||
IOCS_OVERVIEW_FILENAME = REPO_ROOT / "docs" / "ioc" / "ioc_overview.md"
|
||||
|
||||
SERVICE_MANAGER_UI_FILENAME = REPO_ROOT / "qt" / "A_BD_ServiceManager.ui"
|
||||
|
||||
MASTER_SERVICE_DIR = REPO_ROOT / "services" / "master" / "current"
|
||||
MASTER_IOC_SUBS_FILE = MASTER_SERVICE_DIR / "ioc" / "AGEBD-CPCL-MASTER_main.subs"
|
||||
|
||||
|
||||
class Service(BaseModel):
|
||||
name: str
|
||||
@@ -127,3 +133,175 @@ class IocsOverview(BaseModel):
|
||||
def write_to_file(self):
|
||||
with open(self.config_path, "w") as f:
|
||||
f.write(self.content)
|
||||
|
||||
|
||||
class MasterIocSubs(BaseModel):
|
||||
config_path: ClassVar[str] = str(MASTER_IOC_SUBS_FILE)
|
||||
|
||||
content: str
|
||||
|
||||
@classmethod
|
||||
def read_from_file(cls) -> "MasterIocSubs":
|
||||
with open(cls.config_path) as f:
|
||||
file_content = f.read()
|
||||
|
||||
return MasterIocSubs(content=file_content)
|
||||
|
||||
def update_content(
|
||||
self,
|
||||
service_name: str,
|
||||
starton: str = "0", # TODO: ok defaults?
|
||||
autooff: str = "0", # TODO: ok defaults?
|
||||
):
|
||||
"""
|
||||
Parses the configuration text and appends a new row before the closing bracket.
|
||||
"""
|
||||
quoted_service = f'"{service_name}"'
|
||||
new_row = f' {{ "{{{{ agebd_env }}}}", {quoted_service:<22} , "{starton}", "{autooff}" }}'
|
||||
|
||||
# Use regex to find the last closing curly brace of the configuration block
|
||||
# This targets the line that contains only a lone closing brace, optional spaces, and maybe a comma/semicolon.
|
||||
pattern = r"(\s*\n\s*\}(?:;|,)?\s*$)"
|
||||
|
||||
if re.search(pattern, self.content, re.MULTILINE):
|
||||
# Insert our new row right before that closing brace line
|
||||
self.content = re.sub(
|
||||
pattern, f"\n{new_row}\\1", self.content, count=1, flags=re.MULTILINE
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Could not locate the closing structure format '}' inside the configuration."
|
||||
)
|
||||
|
||||
def write_to_file(self) -> None:
|
||||
with open(self.config_path, "w") as f:
|
||||
f.write(self.content)
|
||||
|
||||
|
||||
# TODO: maybe separate models into their own files
|
||||
class ServiceManagerUI(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
config_path: ClassVar[str] = str(SERVICE_MANAGER_UI_FILENAME)
|
||||
|
||||
tree: Any
|
||||
|
||||
@classmethod
|
||||
def read_from_file(cls) -> "ServiceManagerUI":
|
||||
tree = ET.parse(cls.config_path)
|
||||
return ServiceManagerUI(tree=tree)
|
||||
|
||||
def update_xml(self, service: Service, ui_name: str, panelcmd: str) -> None:
|
||||
num_macro_elements = self._update_macro(service=service, ui_name=ui_name, panelcmd=panelcmd)
|
||||
self._update_heights(num_macro_elements=num_macro_elements)
|
||||
|
||||
def _update_macro(self, service: Service, ui_name: str, panelcmd: str) -> int:
|
||||
new_macro_element = _ServiceManagerUIMacroElement(
|
||||
service_name_upper=service.name_upper, ui_name=ui_name, panelcmd=panelcmd
|
||||
)
|
||||
|
||||
num_macro_elements = None
|
||||
root = self.tree.getroot()
|
||||
for widget in root.iter("widget"):
|
||||
if widget.get("class") == "caInclude" and widget.get("name") == "cainclude":
|
||||
for prop in widget.findall("property"):
|
||||
# Update the macro data string
|
||||
if prop.get("name") == "macro":
|
||||
string_elem = prop.find("string")
|
||||
if string_elem is not None and string_elem.text is not None:
|
||||
string_elem.text = (
|
||||
string_elem.text + ";" + new_macro_element.to_string()
|
||||
)
|
||||
# Dynamically update the count match so caInclude renders all rows
|
||||
if prop.get("name") == "numberOfItems":
|
||||
number_elem = prop.find("number")
|
||||
assert number_elem is not None and number_elem.text is not None
|
||||
num_macro_elements = int(number_elem.text)
|
||||
number_elem.text = str(num_macro_elements + 1)
|
||||
|
||||
assert num_macro_elements is not None, "could not find number of macro elements in xml"
|
||||
return num_macro_elements
|
||||
|
||||
def _update_heights(self, num_macro_elements: int) -> None:
|
||||
"""
|
||||
There are 3 heights to be adjusted:
|
||||
|
||||
1. Main window
|
||||
2. Tab widget
|
||||
3. Widget inside the tab widget
|
||||
"""
|
||||
root = self.tree.getroot()
|
||||
|
||||
ca_include_height = self._get_height_cainclude()
|
||||
height_to_add = int(
|
||||
(ca_include_height / num_macro_elements * (num_macro_elements + 1)) - ca_include_height
|
||||
)
|
||||
|
||||
# 1. Main window
|
||||
mainwindow = root.find(".//widget[@class='QMainWindow']")
|
||||
if mainwindow is not None:
|
||||
rect = mainwindow.find("./property[@name='geometry']/rect")
|
||||
assert rect is not None
|
||||
height = rect.find("height")
|
||||
assert height is not None and height.text is not None
|
||||
height.text = str(int(height.text) + height_to_add)
|
||||
|
||||
for widget in root.iter("widget"):
|
||||
widget_name = widget.get("name")
|
||||
|
||||
# 2. Tab widget
|
||||
if widget_name == "tabWidget":
|
||||
rect = widget.find("./property[@name='geometry']/rect")
|
||||
assert rect is not None
|
||||
height = rect.find("height")
|
||||
assert height is not None and height.text is not None
|
||||
height.text = str(int(height.text) + height_to_add)
|
||||
|
||||
# 3. Widget inside the tab widget
|
||||
elif widget_name == "cainclude":
|
||||
rect = widget.find("./property[@name='geometry']/rect")
|
||||
assert rect is not None
|
||||
height = rect.find("height")
|
||||
assert height is not None and height.text is not None
|
||||
height.text = str(int(height.text) + height_to_add)
|
||||
|
||||
def _get_height_cainclude(self) -> int:
|
||||
"""
|
||||
Get the height of the area that includes all the services
|
||||
"""
|
||||
root = self.tree.getroot()
|
||||
cainclude_height = None
|
||||
|
||||
for widget in root.iter("widget"):
|
||||
widget_name = widget.get("name")
|
||||
|
||||
# Target the caInclude Widget of Required Services
|
||||
if widget_name == "cainclude":
|
||||
rect = widget.find("./property[@name='geometry']/rect")
|
||||
assert rect is not None
|
||||
height = rect.find("height")
|
||||
assert height is not None and height.text is not None
|
||||
cainclude_height = int(height.text)
|
||||
|
||||
assert cainclude_height, "could not get height of cainclude widget"
|
||||
return cainclude_height
|
||||
|
||||
def write_to_file(self) -> None:
|
||||
self.tree.write(self.config_path, encoding="utf-8", xml_declaration=True)
|
||||
|
||||
|
||||
class _ServiceManagerUIMacroElement(BaseModel):
|
||||
service_name_upper: str
|
||||
ui_name: str
|
||||
panel: int = 1
|
||||
svc_exist: int = 1
|
||||
panelcmd: str
|
||||
|
||||
def to_string(self) -> str:
|
||||
return (
|
||||
f"IOC=AGEBD-CPCL-{self.service_name_upper},"
|
||||
f"service={self.service_name_upper},"
|
||||
f"name={self.ui_name},"
|
||||
f"panel={self.panel},"
|
||||
f"svc_exist={self.svc_exist},"
|
||||
f"panelcmd={self.panelcmd}"
|
||||
)
|
||||
|
||||
@@ -14,7 +14,14 @@ from core.git import (
|
||||
git_push_changes,
|
||||
switch_branch,
|
||||
)
|
||||
from core.models import IocsOverview, MasterHLANames, Service, ServiceRegistry
|
||||
from core.models import (
|
||||
IocsOverview,
|
||||
MasterHLANames,
|
||||
MasterIocSubs,
|
||||
Service,
|
||||
ServiceManagerUI,
|
||||
ServiceRegistry,
|
||||
)
|
||||
from core.utils import get_git_root
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -23,16 +30,16 @@ REPO_ROOT = get_git_root(__file__)
|
||||
SERVICE_TEMPLATES_DIR = REPO_ROOT / "templates" / "service"
|
||||
SERVICE_DEST_DIR = REPO_ROOT / "services"
|
||||
|
||||
MASTER_SERVICE_DIR = REPO_ROOT / "services" / "master" / "current"
|
||||
MASTER_IOC_SUBS_FILE = MASTER_SERVICE_DIR / "ioc" / "AGEBD-CPCL-MASTER_main.subs"
|
||||
|
||||
# TODO: lots of hardcoded paths. Create config object?
|
||||
|
||||
|
||||
class ServiceCreator:
|
||||
def __init__(self, user: str, ioc_description: str) -> None:
|
||||
def __init__(self, user: str, ioc_description: str, ui_name: str, panelcmd: str) -> None:
|
||||
self.user = user
|
||||
self.ioc_description = ioc_description
|
||||
self.ui_name = ui_name
|
||||
self.panelcmd = panelcmd
|
||||
|
||||
def add_service(self, name: str):
|
||||
repo = git.Repo(REPO_ROOT)
|
||||
@@ -49,6 +56,12 @@ class ServiceCreator:
|
||||
iocs_overview_old = IocsOverview.read_from_file()
|
||||
iocs_overview = IocsOverview.read_from_file()
|
||||
iocs_overview.add_ioc(service, description=self.ioc_description)
|
||||
master_ioc_subs_old = MasterIocSubs.read_from_file()
|
||||
master_ioc_subs = MasterIocSubs.read_from_file()
|
||||
master_ioc_subs.update_content(service_name=service.name_upper)
|
||||
service_manager_old = ServiceManagerUI.read_from_file()
|
||||
service_manager = ServiceManagerUI.read_from_file()
|
||||
service_manager.update_xml(service=service, ui_name=self.ui_name, panelcmd=self.panelcmd)
|
||||
|
||||
branch_name = f"feature/add-service-{service.dir_name}"
|
||||
delete_local_branch(repo, branch_name)
|
||||
@@ -63,12 +76,8 @@ class ServiceCreator:
|
||||
registry.write_to_config()
|
||||
hla_names.write_to_config()
|
||||
iocs_overview.write_to_file()
|
||||
|
||||
self._append_to_master_ioc_subs(
|
||||
service_name=service.name_upper,
|
||||
starton="0", # TODO: ok?
|
||||
autooff="0", # TODO: ok?
|
||||
)
|
||||
master_ioc_subs.write_to_file()
|
||||
service_manager.write_to_file()
|
||||
|
||||
# TODO: can't push if branch already exists in remote
|
||||
git_push_changes(
|
||||
@@ -80,6 +89,7 @@ class ServiceCreator:
|
||||
master_hla_names_rel_path="services/master/current/app/config/hla_names.yml",
|
||||
master_ioc_subs_rel_path="services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs",
|
||||
iocs_overview_rel_path="docs/ioc/ioc_overview.md",
|
||||
service_manager_ui_rel_path="qt/A_BD_ServiceManager.ui",
|
||||
commit_msg=f"feature: add new service {service.name_lower}",
|
||||
)
|
||||
switch_branch(repo, original_branch)
|
||||
@@ -88,6 +98,8 @@ class ServiceCreator:
|
||||
registry_old.write_to_config()
|
||||
hla_names_old.write_to_config()
|
||||
iocs_overview_old.write_to_file()
|
||||
master_ioc_subs_old.write_to_file()
|
||||
service_manager_old.write_to_file()
|
||||
switch_branch(repo, original_branch)
|
||||
raise e
|
||||
|
||||
@@ -137,34 +149,3 @@ class ServiceCreator:
|
||||
logger.error(f"Exit Code: {e.returncode}")
|
||||
logger.error(f"Details:\n{e.stderr}")
|
||||
raise UVError(e.stderr) from e
|
||||
|
||||
def _append_to_master_ioc_subs(
|
||||
self,
|
||||
service_name: str,
|
||||
starton: str,
|
||||
autooff: str,
|
||||
) -> None:
|
||||
"""
|
||||
Parses the configuration text and appends a new row before the closing bracket.
|
||||
"""
|
||||
with open(MASTER_IOC_SUBS_FILE) as f:
|
||||
file_content = f.read()
|
||||
|
||||
quoted_service = f'"{service_name}"'
|
||||
new_row = f' {{ "{{{{ agebd_env }}}}", {quoted_service:<22} , "{starton}", "{autooff}" }}'
|
||||
|
||||
# Use regex to find the last closing curly brace of the configuration block
|
||||
# This targets the line that contains only a lone closing brace, optional spaces, and maybe a comma/semicolon.
|
||||
pattern = r"(\s*\n\s*\}(?:;|,)?\s*$)"
|
||||
|
||||
if re.search(pattern, file_content, re.MULTILINE):
|
||||
# Insert our new row right before that closing brace line
|
||||
updated_content = re.sub(
|
||||
pattern, f"\n{new_row}\\1", file_content, count=1, flags=re.MULTILINE
|
||||
)
|
||||
with open(MASTER_IOC_SUBS_FILE, "w") as f:
|
||||
f.write(updated_content)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Could not locate the closing structure format '}' inside the configuration."
|
||||
)
|
||||
|
||||
+11
-2
@@ -16,12 +16,21 @@ def add(
|
||||
ioc_description: str = typer.Option(
|
||||
..., "--ioc-description", "-d", help="See <repo-root>/docs/ioc/ioc_overview.md for examples"
|
||||
),
|
||||
ui_name: str = typer.Option(
|
||||
..., "--ui-name", help="See <repo-root>/qt/A_BD_ServiceManager.ui for examples"
|
||||
),
|
||||
panelcmd: str = typer.Option(
|
||||
..., "--panelcmd", "-p", help="See <repo-root>/qt/A_BD_ServiceManager.ui for examples"
|
||||
),
|
||||
):
|
||||
init_logging()
|
||||
ServiceCreator(
|
||||
service_creator = ServiceCreator(
|
||||
user=user, # TODO: read from 'whoami'?
|
||||
ioc_description=ioc_description,
|
||||
).add_service(name=name)
|
||||
ui_name=ui_name, # TODO: make this standard?
|
||||
panelcmd=panelcmd, # TODO: make this standard?
|
||||
)
|
||||
service_creator.add_service(name=name)
|
||||
|
||||
|
||||
@service.command()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
next_available_ioc_port: 50001
|
||||
services:
|
||||
- name: master
|
||||
ioc_port: 50000
|
||||
status: active
|
||||
- name: master
|
||||
ioc_port: 50000
|
||||
status: active
|
||||
|
||||
+3
-1
@@ -9,4 +9,6 @@ ssh -J sls-lc -X labrec_b@sls-vserv-bd-hla01-dev.psi.ch
|
||||
Macro substitution
|
||||
```
|
||||
caqtdm -m'TESTAGEBDALH=AGEBD-ALH' A_BD_ServiceManager.ui
|
||||
```
|
||||
```
|
||||
|
||||
# TODO: remove/delete old autodeployed ui files
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,754 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1319</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<widget class="caLed" name="caled_51">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>8</x>
|
||||
<y>0</y>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="rectangular">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="gradientEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="ledWidth">
|
||||
<number>28</number>
|
||||
</property>
|
||||
<property name="ledHeight">
|
||||
<number>28</number>
|
||||
</property>
|
||||
<property name="linearGradient">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="scaleContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">$(IOC):STATUS</string>
|
||||
</property>
|
||||
<property name="colorMode">
|
||||
<enum>caLed::Alarm</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caRelatedDisplay" name="carelateddisplay_26">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>43</x>
|
||||
<y>0</y>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="background">
|
||||
<color>
|
||||
<red>183</red>
|
||||
<green>157</green>
|
||||
<blue>92</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="labels">
|
||||
<string>P</string>
|
||||
</property>
|
||||
<property name="files">
|
||||
<string>/ioc/modules/qt/iocStats.ui</string>
|
||||
</property>
|
||||
<property name="args">
|
||||
<string>IOC=$(IOC)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caFrame" name="caframe">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>1200</x>
|
||||
<y>0</y>
|
||||
<width>110</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="visibility">
|
||||
<enum>caFrame::Calc</enum>
|
||||
</property>
|
||||
<property name="visibilityMode">
|
||||
<enum>caFrame::All</enum>
|
||||
</property>
|
||||
<property name="visibilityCalc">
|
||||
<string notr="true">$(panel)</string>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="channelB">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<widget class="caRelatedDisplay" name="carelateddisplay_23">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="background">
|
||||
<color>
|
||||
<red>183</red>
|
||||
<green>157</green>
|
||||
<blue>92</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="labels">
|
||||
<string>P</string>
|
||||
</property>
|
||||
<property name="files">
|
||||
<string>$(panelcmd)</string>
|
||||
</property>
|
||||
<property name="args">
|
||||
<string>$(macro)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="caFrame" name="caframe_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>277</x>
|
||||
<y>0</y>
|
||||
<width>900</width>
|
||||
<height>120</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="visibility">
|
||||
<enum>caFrame::Calc</enum>
|
||||
</property>
|
||||
<property name="visibilityCalc">
|
||||
<string notr="true">$(svc_exist)</string>
|
||||
</property>
|
||||
<widget class="caLineEdit" name="calineedit_73">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>800</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-ALH:$(service)-STATUS</string>
|
||||
</property>
|
||||
<property name="colorMode">
|
||||
<enum>caLineEdit::Default</enum>
|
||||
</property>
|
||||
<property name="alarmHandling">
|
||||
<enum>caLineEdit::onBackground</enum>
|
||||
</property>
|
||||
<property name="precisionMode">
|
||||
<enum>caLineEdit::User</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caMessageButton" name="camessagebutton_88">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>220</x>
|
||||
<y>0</y>
|
||||
<width>60</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Restart</string>
|
||||
</property>
|
||||
<property name="fontScaleMode">
|
||||
<enum>EPushButton::None</enum>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-MASTER:$(service)-RESTART-REQ</string>
|
||||
</property>
|
||||
<property name="label">
|
||||
<string notr="true">Restart</string>
|
||||
</property>
|
||||
<property name="background">
|
||||
<color>
|
||||
<red>160</red>
|
||||
<green>160</green>
|
||||
<blue>160</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="disableChannel" stdset="0">
|
||||
<string>CONTROL-ONOFF</string>
|
||||
</property>
|
||||
<property name="releaseMessage">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="pressMessage">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caLineEdit" name="calineedit_81">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>690</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-ALH:$(service)-VERSION</string>
|
||||
</property>
|
||||
<property name="colorMode">
|
||||
<enum>caLineEdit::Default</enum>
|
||||
</property>
|
||||
<property name="alarmHandling">
|
||||
<enum>caLineEdit::onBackground</enum>
|
||||
</property>
|
||||
<property name="precisionMode">
|
||||
<enum>caLineEdit::User</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caChoice" name="cachoice_18">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>340</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-ALH:$(service)-ONOFF</string>
|
||||
</property>
|
||||
<property name="stackingMode" stdset="0">
|
||||
<enum>caChoice::Column</enum>
|
||||
</property>
|
||||
<property name="endBit">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caLineEdit" name="calineedit_87">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>500</x>
|
||||
<y>0</y>
|
||||
<width>180</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-ALH:$(service)-STARTTIME</string>
|
||||
</property>
|
||||
<property name="colorMode">
|
||||
<enum>caLineEdit::Default</enum>
|
||||
</property>
|
||||
<property name="alarmHandling">
|
||||
<enum>caLineEdit::onBackground</enum>
|
||||
</property>
|
||||
<property name="precisionMode">
|
||||
<enum>caLineEdit::User</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caLed" name="caled_55">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>300</x>
|
||||
<y>0</y>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="rectangular">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="gradientEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="ledWidth">
|
||||
<number>28</number>
|
||||
</property>
|
||||
<property name="ledHeight">
|
||||
<number>28</number>
|
||||
</property>
|
||||
<property name="linearGradient">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="scaleContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-ALH:$(service)-ALIVE</string>
|
||||
</property>
|
||||
<property name="colorMode">
|
||||
<enum>caLed::Alarm</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caMessageButton" name="camessagebutton_79">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>170</x>
|
||||
<y>0</y>
|
||||
<width>40</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Logs</string>
|
||||
</property>
|
||||
<property name="fontScaleMode">
|
||||
<enum>EPushButton::None</enum>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-MASTER:$(service)-LOGS-REQ</string>
|
||||
</property>
|
||||
<property name="label">
|
||||
<string notr="true">Logs</string>
|
||||
</property>
|
||||
<property name="background">
|
||||
<color>
|
||||
<red>160</red>
|
||||
<green>160</green>
|
||||
<blue>160</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="disableChannel" stdset="0">
|
||||
<string>CONTROL-ONOFF</string>
|
||||
</property>
|
||||
<property name="releaseMessage">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="pressMessage">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caLed" name="caled_58">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>450</x>
|
||||
<y>0</y>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="rectangular">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="gradientEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="ledWidth">
|
||||
<number>28</number>
|
||||
</property>
|
||||
<property name="ledHeight">
|
||||
<number>28</number>
|
||||
</property>
|
||||
<property name="linearGradient">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="scaleContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-ALH:$(service)-ONOFF-RB</string>
|
||||
</property>
|
||||
<property name="colorMode">
|
||||
<enum>caLed::Alarm</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="Line" name="line_20">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>481</x>
|
||||
<y>0</y>
|
||||
<width>20</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="caLabel" name="calabel_47">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>130</x>
|
||||
<y>0</y>
|
||||
<width>201</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>$(name)</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::MarkdownText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="Line" name="line_17">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>108</x>
|
||||
<y>0</y>
|
||||
<width>20</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="Line" name="line_18">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>328</x>
|
||||
<y>0</y>
|
||||
<width>20</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="Line" name="line_19">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>558</x>
|
||||
<y>0</y>
|
||||
<width>20</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="Line" name="line_21">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>1178</x>
|
||||
<y>0</y>
|
||||
<width>20</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caFrame" name="caframe_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>340</x>
|
||||
<y>0</y>
|
||||
<width>101</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="visibility">
|
||||
<enum>caFrame::IfZero</enum>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">Expert-Mode</string>
|
||||
</property>
|
||||
<widget class="caMessageButton" name="camessagebutton_136">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>60</x>
|
||||
<y>0</y>
|
||||
<width>40</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
<property name="fontScaleMode">
|
||||
<enum>EPushButton::None</enum>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-MASTER:$(service)-START-REQ</string>
|
||||
</property>
|
||||
<property name="label">
|
||||
<string notr="true">Start</string>
|
||||
</property>
|
||||
<property name="background">
|
||||
<color>
|
||||
<red>160</red>
|
||||
<green>160</green>
|
||||
<blue>160</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="disableChannel" stdset="0">
|
||||
<string>CONTROL-ONOFF</string>
|
||||
</property>
|
||||
<property name="releaseMessage">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="pressMessage">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="caMessageButton" name="camessagebutton_91">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>0</y>
|
||||
<width>40</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>KILL</string>
|
||||
</property>
|
||||
<property name="fontScaleMode">
|
||||
<enum>EPushButton::None</enum>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-MASTER:$(service)-ABORT-REQ</string>
|
||||
</property>
|
||||
<property name="label">
|
||||
<string notr="true">KILL</string>
|
||||
</property>
|
||||
<property name="background">
|
||||
<color>
|
||||
<red>148</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="disableChannel" stdset="0">
|
||||
<string>CONTROL-ONOFF</string>
|
||||
</property>
|
||||
<property name="releaseMessage">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="pressMessage">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="caFrame" name="caframe_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>80</x>
|
||||
<y>0</y>
|
||||
<width>41</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="visibility">
|
||||
<enum>caFrame::IfZero</enum>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">Expert-Mode</string>
|
||||
</property>
|
||||
<widget class="caMessageButton" name="camessagebutton_123">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>18</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>↺</string>
|
||||
</property>
|
||||
<property name="fontScaleMode">
|
||||
<enum>EPushButton::None</enum>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">$(IOC):RESTART</string>
|
||||
</property>
|
||||
<property name="label">
|
||||
<string notr="true">↺</string>
|
||||
</property>
|
||||
<property name="background">
|
||||
<color>
|
||||
<red>160</red>
|
||||
<green>160</green>
|
||||
<blue>160</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="disableChannel" stdset="0">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="releaseMessage">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="pressMessage">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="caFrame" name="caframe_5">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>1240</x>
|
||||
<y>0</y>
|
||||
<width>71</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="visibility">
|
||||
<enum>caFrame::IfZero</enum>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">Expert-Mode</string>
|
||||
</property>
|
||||
<widget class="caMessageButton" name="camessagebutton_96">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>70</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="channel" stdset="0">
|
||||
<string notr="true">AGEBD-ALH:$(service)-GUIRELOAD</string>
|
||||
</property>
|
||||
<property name="label">
|
||||
<string notr="true">Reload</string>
|
||||
</property>
|
||||
<property name="background">
|
||||
<color>
|
||||
<red>160</red>
|
||||
<green>160</green>
|
||||
<blue>160</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="disableChannel" stdset="0">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="releaseMessage">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="pressMessage">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>caChoice</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>caChoice</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>caRelatedDisplay</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>caRelatedDisplay</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>caMessageButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>caMessageButton</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>caFrame</class>
|
||||
<extends>QFrame</extends>
|
||||
<header>caFrame</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>caLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>caLabel</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>caLed</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>caLed</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>caLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>caLineEdit</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user