GUI a scríobh do 1C RAC, nó arís faoi Tcl/Tk

Agus muid ag plé leis an ábhar conas a oibríonn táirgí 1C i dtimpeallacht Linux, thángthas ar mhíbhuntáiste amháin - an easpa uirlis il-ardán grafach áisiúil chun braisle de fhreastalaithe 1C a bhainistiú. Agus socraíodh an míbhuntáiste seo a cheartú trí GUI a scríobh le haghaidh fóntais an chonsóil raca. Roghnaíodh Tcl/tk mar an teanga forbartha mar, i mo thuairim, an ceann is oiriúnaí don tasc seo. Agus mar sin, ba mhaith liom roinnt gnéithe suimiúla den réiteach a chur i láthair san ábhar seo.

Chun oibriú beidh dáiltí tcl/tk agus 1C uait. Agus ós rud é gur chinn mé an leas is fearr a bhaint as cumais an tseachadta tcl/tk bunúsach gan úsáid a bhaint as pacáistí tríú páirtí, beidh leagan 8.6.7 de dhíth orm, lena n-áirítear ttk - pacáiste le heilimintí grafacha breise, a bhfuil ttk ag teastáil uainn go príomha. ::TreeView, ceadaíonn sé sonraí a thaispeáint i bhfoirm struchtúr crann agus i bhfoirm tábla (liosta). Chomh maith leis sin, sa leagan nua, tá an obair le heisceachtaí athoibrithe (an t-ordú iarracht, a úsáidtear sa tionscadal nuair a bhíonn orduithe seachtracha á rith).

Tá roinnt comhad sa tionscadal (cé nach gcuireann aon rud cosc ​​ort ó gach rud a dhéanamh i gceann amháin):

rac_gui.cfg - cumraíocht réamhshocraithe
rac_gui.tcl - príomhscript seolta
Tá comhaid san eolaire lib a luchtaítear go huathoibríoch ag am tosaithe:
function.tcl - comhad le nósanna imeachta
gui.tcl - príomh-chomhéadan grafach
images.tcl - leabharlann íomhá base64

Go deimhin, cuireann an comhad rac_gui.tcl tús leis an ateangaire, cuireann sé tús le hathróga, lódálann sé modúil, cumraíochtaí, agus mar sin de. Ábhar an chomhaid le tuairimí:

rac_gui.tcl

#!/bin/sh
exec wish "$0" -- "$@"

# Устанавливаем текущий каталог
set dir(root) [pwd]
# Устанавливаем рабочий каталог, если его нет то создаём
set dir(work) [file join $env(HOME) .rac_gui]
if {[file exists $dir(work)] == 0 } {
    file mkdir $dir(work)    
}
# каталог с модулями
set dir(lib) "[file join $dir(root) lib]"

# загружаем пользовательский конфиг, если он отсутствует, то копируем дефолтный
if {[file exists [file join $dir(work) rac_gui.cfg]] ==0} {
    file copy [file join [pwd] rac_gui.cfg] [file join $dir(work) rac_gui.cfg]
} 
source [file join $dir(work) rac_gui.cfg]
# Код проверки наличия rac и правильности указания пути в конфиге
# если программа не найдена то будет выведен диалог для указания корректного пути
# и этот путь будет записан в пользовательский конфиг
if {[file exists $rac_cmd] == 0} {
    set rac_cmd [tk_getOpenFile -initialdir $env(HOME) -parent . -title "Укажите путь до rac" -initialfile rac]
    file copy [file join $dir(work) rac_gui.cfg] [file join $dir(work) rac_gui.cfg.bak] 
    set orig_file [open [file join $dir(work) rac_gui.cfg.bak] "r"]
    set file [open [file join $dir(work) rac_gui.cfg] "w"]
    while {[gets $orig_file line] >=0 } {
        if {[string match "set rac_cmd*" $line]} {
            puts $file "set rac_cmd $rac_cmd"
        } else {
            puts $file $line
        }
    }
    close $file
    close $orig_file
    #return "$host:$port"
    file delete [file join $dir(work) 1c_srv.cfg.bak] 
} else {
    puts "Found $rac_cmd"
}

set cluster_user ""
set cluster_pwd ""
set agent_user ""
set agent_pwd ""
## LOAD FILE ##
# Загружаем модули кроме gui.tcl так как его надо загрузить последним
foreach modFile [lsort [glob -nocomplain [file join $dir(lib) *.tcl]]] {
    if {[file tail $modFile] ne "gui.tcl"} {
        source $modFile
        puts "Loaded module $modFile"
    }
}
source [file join $dir(lib) gui.tcl]
source [file join $dir(work) rac_gui.cfg]

# Читаем файл со списком серверов 1С
# и добавляем в дерево
if [file exists [file join $dir(work) 1c_srv.cfg]] {
    set f [open [file join $dir(work) 1c_srv.cfg] "RDONLY"]
    while {[gets $f line] >=0} {
        .frm_tree.tree insert {} end -id "server::$line" -text "$line" -values "$line"
    }    
}

Tar éis gach rud atá ag teastáil a íoslódáil agus seiceáil le haghaidh láithreacht na fóntais rac, seolfar fuinneog ghrafach. Tá trí ghné i gcomhéadan an chláir:

Barra uirlisí, crann agus liosta

Rinne mé ábhar an “chrainn” chomh cosúil agus is féidir leis an trealamh caighdeánach Windows ó 1C.

GUI a scríobh do 1C RAC, nó arís faoi Tcl/Tk

Tá an príomhchód a fhoirmíonn an fhuinneog seo sa chomhad
lib/gui.tcl

# установка размера и положения основного окна
# можно установить в переменную topLevelGeometry в конфиг программы
if {[info exists topLevelGeometry]} {
    wm geometry . $topLevelGeometry
} else {
    wm geometry . 1024x768
}
# Заголовок окна
wm title . "1C Rac GUI"
wm iconname . "1C Rac Gui"
# иконка окна (берется из файла lib/imges.tcl)
wm iconphoto . tcl
wm protocol . WM_DELETE_WINDOW Quit
wm overrideredirect . 0
wm positionfrom . user

ttk::style theme use clam

# Панель инсрументов
set frm_tool [frame .frm_tool]
pack $frm_tool -side left -fill y 
ttk::panedwindow .panel -orient horizontal -style TPanedwindow
pack .panel -expand true -fill both
pack propagate .panel false

ttk::button $frm_tool.btn_add  -command Add  -image add_grey_32
ttk::button $frm_tool.btn_del  -command Del -image del_grey_32
ttk::button $frm_tool.btn_edit  -command Edit -image edit_grey_32
ttk::button $frm_tool.btn_quit -command Quit -image quit_grey_32

pack $frm_tool.btn_add $frm_tool.btn_del $frm_tool.btn_edit -side top -padx 5 -pady 5
pack $frm_tool.btn_quit  -side bottom -padx 5 -pady 5

# Дерево с полосами прокрутки
set frm_tree [frame .frm_tree]

ttk::scrollbar $frm_tree.hsb1 -orient horizontal -command [list $frm_tree.tree xview]
ttk::scrollbar $frm_tree.vsb1 -orient vertical -command [list $frm_tree.tree yview]
set tree [ttk::treeview $frm_tree.tree -show tree 
-xscrollcommand [list $frm_tree.hsb1 set] -yscrollcommand [list $frm_tree.vsb1 set]]

grid $tree -row 0 -column 0 -sticky nsew
grid $frm_tree.vsb1 -row 0 -column 1 -sticky nsew
grid $frm_tree.hsb1 -row 1 -column 0 -sticky nsew
grid columnconfigure $frm_tree 0 -weight 1
grid rowconfigure $frm_tree 0 -weight 1

# назначение обработчика нажатия кнопкой мыши
bind $frm_tree.tree <ButtonRelease> "TreePress $frm_tree.tree"

# Список для данных (таблица)
set frm_work [frame .frm_work]
ttk::scrollbar $frm_work.hsb -orient horizontal -command [list $frm_work.tree_work xview]
ttk::scrollbar $frm_work.vsb -orient vertical -command [list $frm_work.tree_work yview]
set tree_work [
    ttk::treeview $frm_work.tree_work 
    -show headings  -columns "par val" -displaycolumns "par val"
    -xscrollcommand [list $frm_work.hsb set] 
    -yscrollcommand [list $frm_work.vsb set]
]
# Установка цветов для чередования в таблице
$tree_work tag configure dark -background $color(dark_table_bg)
$tree_work tag configure light -background $color(light_table_bg)

# Размещение элементов на форме
grid $tree_work -row 0 -column 0 -sticky nsew
grid $frm_work.vsb -row 0 -column 1 -sticky nsew
grid $frm_work.hsb -row 1 -column 0 -sticky nsew
grid columnconfigure $frm_work 0 -weight 1
grid rowconfigure $frm_work 0 -weight 1
pack $frm_tree $frm_work -side left -expand true -fill both

#.panel add $frm_tool -weight 1
.panel add $frm_tree -weight 1 
.panel add $frm_work -weight 1

Seo a leanas an t-algartam chun oibriú leis an gclár:

1. Ar dtús, ní mór duit an príomhfhreastalaí braisle a chur leis (i.e., an freastalaí bainistíochta braisle (i Linux, seolfar an bhainistíocht leis an ordú “/opt/1C/v8.3/x86_64/ras braisle —daemon”)).

Chun seo a dhéanamh, cliceáil ar an gcnaipe “+” agus san fhuinneog a osclaíonn, cuir isteach seoladh an fhreastalaí agus an port:

GUI a scríobh do 1C RAC, nó arís faoi Tcl/Tk

Ina dhiaidh sin, feicfear ár bhfreastalaí sa chrann trí chliceáil air, osclófar liosta braislí nó taispeánfar earráid cheangail.

2. Má chliceálann tú ar ainm an bhraisle, osclófar liosta feidhmeanna atá ar fáil dó.

3. ...

Agus mar sin de, i.e. chun braisle nua a chur leis, roghnaigh aon cheann atá ar fáil sa liosta agus brúigh an cnaipe “+” sa bharra uirlisí agus taispeánfar an dialóg nua leis:

GUI a scríobh do 1C RAC, nó arís faoi Tcl/Tk

Feidhmíonn na cnaipí sa bharra uirlisí feidhmeanna ag brath ar an gcomhthéacs, i.e. Ag brath ar cén eilimint den chrann nó den liosta a roghnaítear, déanfar nós imeachta amháin nó eile.

Breathnaímid ar shampla an chnaipe cuir (“+”):

Cód giniúna cnaipe:

ttk::button $frm_tool.btn_add  -command Add  -image add_grey_32

Anseo feicimid nuair a bhrúitear an cnaipe, go gcuirfear an nós imeachta “Add” i gcrích, a chód:

proc Add {} {
    global active_cluster host
    # Определяем идентификатор выделенного элемента
    set id  [.frm_tree.tree selection] 
    # Определяем значение этого элемента
    set values [.frm_tree.tree item [.frm_tree.tree selection] -values]
    set key [lindex [split $id "::"] 0]
    # в зависимости от того что выделили будет запущена нужная процедура
    if {$key eq "" || $key eq "server"} {
        set host [ Add::server ]
        return
    }
    Add::$key .frm_tree.tree $host $values
}

Seo ceann de na buntáistí a bhaineann le tickle: is féidir leat luach athróige a chur ar aghaidh mar ainm nós imeachta:

Add::$key .frm_tree.tree $host $values

Is é sin, mar shampla, má dhírímid ar an bpríomhfhreastalaí agus brúigh “+”, ansin seolfar an nós imeachta Add ::server, más rud é ag an mbraisle - Add ::braisle agus mar sin de (scríobhfaidh mé faoi cá bhfuil an Tagann na “eochracha” riachtanacha ó thíos), tarraingíonn na nósanna imeachta liostaithe gnéithe grafacha a oireann don chomhthéacs.

Mar a d'fhéadfadh a bheith tugtha faoi deara agat cheana féin, tá na foirmeacha cosúil i stíl - ní haon ionadh é seo, toisc go bhfuil siad ar taispeáint le nós imeachta amháin, níos cruinne príomhfhráma na foirme (fuinneog, cnaipí, íomhá, lipéad), ainm an nós imeachta. AddTopLevel

proc AddToplevel {lbl img {win_name .add}} {
    set cmd "destroy $win_name"
    if [winfo exists $win_name] {destroy $win_name}
    toplevel $win_name
    wm title $win_name $lbl
    wm iconphoto $win_name tcl
    # метка с иконкой
    ttk::label $win_name.lbl -image $img
    # фрейм с полями ввода
    set frm [ttk::labelframe $win_name.frm -text $lbl -labelanchor nw]
    
    grid columnconfigure $frm 0 -weight 1
    grid rowconfigure $frm 0 -weight 1
    # фрейм и кнопки
    set frm_btn [frame $win_name.frm_btn -border 0]
    ttk::button $frm_btn.btn_ok -image ok_grey_24 -command { }
    ttk::button $frm_btn.btn_cancel -command $cmd -image quit_grey_24 
    grid $win_name.lbl -row 0 -column 0 -sticky nw -padx 5 -pady 10
    grid $frm -row 0 -column 1 -sticky nw -padx 5 -pady 5
    grid $frm_btn -row 1 -column 1 -sticky se -padx 5 -pady 5
    pack  $frm_btn.btn_cancel  -side right
    pack  $frm_btn.btn_ok  -side right -padx 10
    return $frm
}

Paraiméadair glaonna: teideal, ainm íomhá don íocón ón leabharlann (lib/images.tcl) agus paraiméadar ainm fuinneoige roghnach (réamhshocraithe .add). Mar sin, má ghlacaimid na samplaí thuas chun an príomhfhreastalaí agus an bhraisle a chur leis, beidh an glao mar a leanas:

AddToplevel "Добавление основного сервера" server_grey_64

AddToplevel "Добавление кластера" cluster_grey_64

Bhuel, ag leanúint leis na samplaí seo, taispeánfaidh mé na nósanna imeachta a thaispeánann dialóga cuir le haghaidh freastalaí nó braisle.

Cuir:: freastalaí

proc Add::server {} {
    global default
    # выводим основную форму
    set frm [AddToplevel "Добавление основного сервера" server_grey_64]
    # добавляем етки и поля ввода на эту форму
    label $frm.lbl_host -text "Адрес сервера"
    entry  $frm.ent_host
    label $frm.lbl_port -text "Порт"
    entry $frm.ent_port 
    $frm.ent_port  insert end $default(port)
    grid $frm.lbl_host -row 0 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_host -row 0 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_port -row 1 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_port -row 1 -column 1 -sticky nsew -padx 5 -pady 5
    grid columnconfigure $frm 0 -weight 1
    grid rowconfigure $frm 0 -weight 1
    #set frm_btn [frame .add.frm_btn -border 0]
    # переопределяем обработчик нажатия кнопки
    .add.frm_btn.btn_ok configure -command {
        set host [SaveMainServer [.add.frm.ent_host get] [.add.frm.ent_port get]]
        .frm_tree.tree insert {} end -id "server::$host" -text "$host" -values "$host"
        destroy .add
        return $host
    }
    return $frm
}

Cuir:: braisle

proc Add::cluster {tree host values} {
    global default lifetime_limit expiration_timeout session_fault_tolerance_level
    global max_memory_size max_memory_time_limit errors_count_threshold security_level
    global load_balancing_mode kill_problem_processes 
    agent_user agent_pwd cluster_user cluster_pwd auth_agent
    if {$agent_user ne "" && $agent_pwd ne ""} {
        set auth_agent "--agent-user=$agent_user --agent-pwd=$agent_pwd"
    } else {
        set auth_agent ""
    }
    # устанавливаем глобальные переменные ()
    set lifetime_limit $default(lifetime_limit)
    set expiration_timeout $default(expiration_timeout)
    set session_fault_tolerance_level $default(session_fault_tolerance_level)
    set max_memory_size $default(max_memory_size)
    set max_memory_time_limit $default(max_memory_time_limit)
    set errors_count_threshold $default(errors_count_threshold)
    set security_level [lindex $default(security_level) 0]
    set load_balancing_mode [lindex $default(load_balancing_mode) 0]
    
    set frm [AddToplevel "Добавление кластера" cluster_grey_64]
    
    label $frm.lbl_host -text "Адрес основного сервера"
    entry  $frm.ent_host
    label $frm.lbl_port -text "Порт"
    entry $frm.ent_port 
    $frm.ent_port  insert end $default(port)
    label $frm.lbl_name -text "Название кластера"
    entry  $frm.ent_name
    label $frm.lbl_secure_connect -text "Защищённое соединение"
    ttk::combobox $frm.cb_security_level -textvariable security_level -values $default(security_level)
    label $frm.lbl_expiration_timeout -text "Останавливать выключенные процессы через:"
    entry  $frm.ent_expiration_timeout -textvariable expiration_timeout
    label $frm.lbl_session_fault_tolerance_level -text "Уровень отказоустойчивости"
    entry  $frm.ent_session_fault_tolerance_level -textvariable session_fault_tolerance_level
    label $frm.lbl_load_balancing_mode -text "Режим распределения нагрузки"
    ttk::combobox $frm.cb_load_balancing_mode -textvariable load_balancing_mode 
    -values $default(load_balancing_mode)
    label $frm.lbl_errors_count_threshold -text "Допустимое отклонение количества ошибок сервера, %"
    entry  $frm.ent_errors_count_threshold -textvariable errors_count_threshold
    label $frm.lbl_processes -text "Рабочие процессы:"
    label $frm.lbl_lifetime_limit -text "Период перезапуска, сек."
    entry  $frm.ent_lifetime_limit -textvariable lifetime_limit
    label $frm.lbl_max_memory_size -text "Допустимый объём памяти, КБ"
    entry  $frm.ent_max_memory_size -textvariable max_memory_size
    label $frm.lbl_max_memory_time_limit -text "Интервал превышения допустимого объёма памяти, сек."
    entry  $frm.ent_max_memory_time_limit -textvariable max_memory_time_limit
    label $frm.lbl_kill_problem_processes -justify left -anchor nw -text "Принудительно завершать проблемные процессы"
    checkbutton $frm.check_kill_problem_processes -variable kill_problem_processes -onvalue yes -offvalue no    
    
    grid $frm.lbl_host -row 0 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_host -row 0 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_port -row 1 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_port -row 1 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_name -row 2 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_name -row 2 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_secure_connect -row 3 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.cb_security_level -row 3 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_expiration_timeout -row 4 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_expiration_timeout -row 4 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_session_fault_tolerance_level -row 5 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_session_fault_tolerance_level -row 5 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_load_balancing_mode -row 6 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.cb_load_balancing_mode -row 6 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_errors_count_threshold -row 7 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_errors_count_threshold -row 7 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_processes -row 8 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.lbl_lifetime_limit -row 9 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_lifetime_limit -row 9 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_max_memory_size -row 10 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_max_memory_size -row 10 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_max_memory_time_limit -row 11 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_max_memory_time_limit -row 11 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_kill_problem_processes -row 12 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.check_kill_problem_processes -row 12 -column 1 -sticky nw -padx 5 -pady 5
    # переопределяем обработчик
    .add.frm_btn.btn_ok configure -command {
        RunCommand "" "cluster insert 
        --host=[.add.frm.ent_host get] 
        --port=[.add.frm.ent_port get] 
        --name=[.add.frm.ent_name get] 
        --expiration-timeout=$expiration_timeout 
        --lifetime-limit=$lifetime_limit 
        --max-memory-size=$max_memory_size 
        --max-memory-time-limit=$max_memory_time_limit 
        --security-level=$security_level 
        --session-fault-tolerance-level=$session_fault_tolerance_level 
        --load-balancing-mode=$load_balancing_mode 
        --errors-count-threshold=$errors_count_threshold 
        --kill-problem-processes=$kill_problem_processes 
        $auth_agent $host"
        Run::server $tree $host ""
        destroy .add
    }
    return $frm
}

Nuair a dhéantar comparáid idir cód na nósanna imeachta seo, tá an difríocht le feiceáil don tsúil nocht; díreoidh mé ar an láimhseálaí cnaipe “OK”. In Tk, is féidir airíonna na n-eilimintí grafacha a shárú le linn fhorghníomhú an chláir ag baint úsáide as an rogha chumrú. Mar shampla, an t-ordú tosaigh chun an cnaipe a thaispeáint:

ttk::button $frm_btn.btn_ok -image ok_grey_24 -command { }

Ach inár bhfoirmeacha, braitheann an t-ordú ar an bhfeidhmiúlacht riachtanach:

  .add.frm_btn.btn_ok configure -command {
        RunCommand "" "cluster insert 
        --host=[.add.frm.ent_host get] 
        --port=[.add.frm.ent_port get] 
        --name=[.add.frm.ent_name get] 
        --expiration-timeout=$expiration_timeout 
        --lifetime-limit=$lifetime_limit 
        --max-memory-size=$max_memory_size 
        --max-memory-time-limit=$max_memory_time_limit 
        --security-level=$security_level 
        --session-fault-tolerance-level=$session_fault_tolerance_level 
        --load-balancing-mode=$load_balancing_mode 
        --errors-count-threshold=$errors_count_threshold 
        --kill-problem-processes=$kill_problem_processes 
        $auth_agent $host"
        Run::server $tree $host ""
        destroy .add
    }

Sa sampla thuas, cuireann an cnaipe “clogged” tús leis an nós imeachta chun braisle a chur leis.

Anseo is fiú digression a dhéanamh i dtreo oibriú le heilimintí grafacha in Tk - le haghaidh eilimintí ionchuir sonraí éagsúla (iontráil, bosca teaglama, cnaipe seiceála, etc.) tugadh isteach paraiméadar mar athróg téacs:

entry  $frm.ent_lifetime_limit -textvariable lifetime_limit

Sainmhínítear an athróg seo san ainmspás domhanda agus tá an luach iontrála faoi láthair ann. Iad siúd. D'fhonn an téacs iontráilte a fháil ón réimse, ní gá duit ach an luach a fhreagraíonn don athróg a léamh (ar ndóigh, ar choinníoll go sainítear é agus an eilimint á cruthú).

Is é an dara modh chun an téacs a iontráladh a fháil (le haghaidh gnéithe den chineál iontrála) ná an t-ordú faigh a úsáid:

.add.frm.ent_name get

Is féidir an dá mhodh seo a fheiceáil sa chód thuas.

Má chliceáiltear ar an gcnaipe seo, sa chás seo, seolann sé an nós imeachta RunCommand leis an líne ordaithe ginte chun braisle a chur leis i dtéarmaí rac:

/opt/1C/v8.3/x86_64/rac cluster insert  --host=localhost  --port=1540  --name=dsdsds  --expiration-timeout=0  --lifetime-limit=0  --max-memory-size=0  --max-memory-time-limit=0  --security-level=0  --session-fault-tolerance-level=0  --load-balancing-mode=performance  --errors-count-threshold=0  --kill-problem-processes=no   localhost:1545

Anois táimid ag teacht ar an bpríomhordú, a rialaíonn seoladh rac leis na paraiméadair a theastaíonn uainn, a pharsáil freisin aschur na n-orduithe i liostaí agus tuairisceáin, más gá:

RunCommand

proc RunCommand {root par} {
    global dir rac_cmd cluster work_list_row_count agent_user agent_pwd cluster_user cluster_pwd
    puts "$rac_cmd $par"
    set work_list_row_count 0
    # открываем канал в неблокирующем режиме
    # $rac - команда с полным путём
    # $par - сформированные ключи запуска и опции    
    set pipe [open "|$rac_cmd $par" "r"]
    try {
        set lst ""
        set l ""
        # вывод команды добавляем в список списков
        while {[gets $pipe line]>=0} {
            #puts $line
            if {$line eq ""} {
                lappend l $lst
                set lst ""
            } else {
                lappend lst [string trim $line]
            }
        }
        close $pipe
        return $l
    } on error {result options} {
        # Запуск обработчика ошибок
        ErrorParcing $result $options
        return ""
    }
}

Tar éis na sonraí príomhfhreastalaí a iontráil, cuirfear leis an gcrann é, le haghaidh seo, sa nós imeachta Add:server thuas, tá an cód seo a leanas freagrach:

.frm_tree.tree insert {} end -id "server::$host" -text "$host" -values "$host"

Anois, trí chliceáil ar an ainm freastalaí sa chrann, faighimid liosta de na braislí arna mbainistiú ag an bhfreastalaí sin, agus trí chliceáil ar bhraisle, faigheann muid liosta de na heilimintí braisle (freastalaithe, infobases, etc.). Cuirtear é seo i bhfeidhm sa nós imeachta TreePress (comhad lib/function.tcl):

proc TreePress {tree} {
   global host server active_cluster infobase
   # определяем выделенный элемент
    set id  [$tree selection]
   # устанавливаем нужные глобальные переменные
    SetGlobalVarFromTreeItems $tree $id
   # Определяем ключ и значение, т.е. именно тип выбранного элемента
    set values [$tree item $id -values]
    set key [lindex [split $id "::"] 0]
   # и в зависимости от того что выбрали будет запущена соответствующая процедура 
   # в пространстве имён Run
    Run::$key $tree $host $values
}

Dá réir sin, seolfar Run::server don phríomhfhreastalaí (le haghaidh braisle - Rith :: braisle, le haghaidh freastalaí oibre - Rith:: work_server, etc.). Iad siúd. tá luach na hathróige $key mar chuid d'ainm na heiliminte crann atá sonraithe ag an rogha -id.

A ligean ar aird a thabhairt ar an nós imeachta

Rith::freastalaí

proc Run::server {tree host values} {
    # получаем список кластеров требуемого сервера
    set lst [RunCommand server::$host "cluster list $host"]
    if {$lst eq ""} {return}
    set l [lindex $lst 0]
    #puts $lst
    # удаляем лишнее из списка
    .frm_work.tree_work delete  [ .frm_work.tree_work children {}]
    # читаем список
    foreach cluster_list $lst {
        # Заполняем список полученными значениями
        InsertItemsWorkList $cluster_list
        # обрабатываем вывод (список) для добавления данных в дерево
        foreach i $cluster_list {
            #puts $i
            set cluster_list [split $i ":"]
            if  {[string trim [lindex $cluster_list 0]] eq "cluster"} {
                set cluster_id [string trim [lindex $cluster_list 1]]
                lappend cluster($cluster_id) $cluster_id
            }
            if  {[string trim [lindex $cluster_list 0]] eq "name"} {
                lappend  cluster($cluster_id) [string trim [lindex $cluster_list 1]]
            }
        }
    }
    # добавляем кластеры в дерево
    foreach x [array names cluster] {
        set id [lindex $cluster($x) 0]
        if { [$tree exists "cluster::$id"] == 0 } {
            $tree insert "server::$host" end -id "cluster::$id" -text "[lindex $cluster($x) 1]" -values "$id"
            # добавляем элементы в кластер
            InsertClusterItems $tree $id
        }
    }
    if { [$tree exists "agent_admins::$id"] == 0 } {
        $tree insert "server::$host" end -id "agent_admins::$id" -text "Администраторы" -values "$id"
        #InsertClusterItems $tree $id
    }
}

Próiseálann an nós imeachta seo an méid a fuarthas ón bhfreastalaí tríd an ordú RunCommand agus cuireann sé gach cineál rudaí leis an gcrann - braislí, bunghnéithe éagsúla (bunanna, freastalaithe oibre, seisiúin, agus mar sin de). Má fhéachann tú go géar, tabharfaidh tú faoi deara glao chuig an nós imeachta InsertItemsWorkList laistigh. Úsáidtear é chun gnéithe a chur le liosta grafach trí aschur fóntais an chonsóil raca a phróiseáil, a cuireadh ar ais mar liosta don athróg $lst roimhe seo. Seo liosta de na liostaí ina bhfuil péirí dúil scartha le idirstad.

Mar shampla, liosta de naisc bhraisle:

svk@svk ~]$ /opt/1C/v8.3/x86_64/rac connection list --cluster=783d2170-56c3-11e8-c586-fc75165efbb2 localhost:1545
connection     : dcf5991c-7d24-11e8-1690-fc75165efbb2
conn-id        : 0
host           : svk.home
process        : 79de2e16-56c3-11e8-c586-fc75165efbb2
infobase       : 00000000-0000-0000-0000-000000000000
application    : "JobScheduler"
connected-at   : 2018-07-01T14:49:51
session-number : 0
blocked-by-ls  : 0

connection     : b993293a-7d24-11e8-1690-fc75165efbb2
conn-id        : 0
host           : svk.home
process        : 79de2e16-56c3-11e8-c586-fc75165efbb2
infobase       : 00000000-0000-0000-0000-000000000000
application    : "JobScheduler"
connected-at   : 2018-07-01T14:48:52
session-number : 0
blocked-by-ls  : 0

I bhfoirm ghrafach beidh sé cuma rud éigin mar seo:

GUI a scríobh do 1C RAC, nó arís faoi Tcl/Tk

Roghnaíonn an nós imeachta thuas ainmneacha na n-eilimintí don cheanntásc agus sonraí chun an tábla a líonadh:

InsertItemsWorkList

proc InsertItemsWorkList {lst} {
    global work_list_row_count
    # установка чередования цвета для строки
    if [expr $work_list_row_count % 2] {
        set tag dark
    } else {
        set tag light
    }
    # разбор строк на пары ключ - значение
    foreach i $lst {
        if [regexp -nocase -all -- {(D+)(s*?|)(:)(s*?|)(.*)} $i match param v2 v3 v4 value] {
            lappend column_list [string trim $param]
            lappend value_list [string trim $value]
        }
    }
     # заполнение таблицы
    .frm_work.tree_work configure -columns $column_list -displaycolumns $column_list
    .frm_work.tree_work insert {} end  -values $value_list -tags $tag
    .frm_work.tree_work column #0 -stretch
    # установка заголовков
    foreach j $column_list {
        .frm_work.tree_work heading $j -text $j
    }
    incr work_list_row_count
}

Anseo, in ionad ordú simplí [split $str ":"], a scoilteann an teaghrán ina heilimintí deighilte le " : " agus a sheolann liosta ar ais, úsáidtear slonn rialta, ós rud é go bhfuil idirstad i roinnt eilimintí freisin.

Leis an nós imeachta InsertClusterItems (ceann amháin de roinnt cinn comhchosúla) cuireann sé liosta d'eilimintí linbh le haitheantóirí comhfhreagracha le crann na heiliminte braisle atá riachtanach
IonsáighClusterItems

proc InsertClusterItems {tree id} {
    set parent "cluster::$id"
    $tree insert $parent end -id "infobases::$id" -text "Информационные базы" -values "$id"
    $tree insert $parent end -id "servers::$id" -text "Рабочие серверы" -values "$id"
    $tree insert $parent end -id "admins::$id" -text "Администраторы" -values "$id"
    $tree insert $parent end -id "managers::$id" -text "Менеджеры кластера" -values $id
    $tree insert $parent end -id "processes::$id" -text "Рабочие процессы" -values "workprocess-all"
    $tree insert $parent end -id "sessions::$id" -text "Сеансы" -values "sessions-all"
    $tree insert $parent end -id "locks::$id" -text "Блокировки" -values "blocks-all"
    $tree insert $parent end -id "connections::$id" -text "Соединения" -values "connections-all"
    $tree insert $parent end -id "profiles::$id" -text "Профили безопасности" -values $id
}

Is féidir leat dhá rogha eile a mheas chun nós imeachta comhchosúil a chur i bhfeidhm, áit a mbeidh sé le feiceáil go soiléir conas is féidir leat orduithe athchleachtacha a bharrfheabhsú agus fáil réidh leo:

Sa nós imeachta seo, déantar suimiú agus seiceáil a réiteach go ceann:

IonsáighBaseItems

proc InsertBaseItems {tree id} {
    set parent "infobase::$id"
    if { [$tree exists "sessions::$id"] == 0 } {
        $tree insert $parent end -id "sessions::$id" -text "Сеансы" -values "$id"
    }
    if { [$tree exists "locks::$id"] == 0 } {
        $tree insert $parent end -id "locks::$id" -text "Блокировки" -values "$id"
    }
    if { [$tree exists "connections::$id"] == 0 } {
        $tree insert $parent end -id "connections::$id" -text "Соединения" -values "$id"
    }
}

Seo cur chuige níos ceart:

IonsáighProfileItems

proc InsertProfileItems {tree id} {
    set parent "profile::$id"
    set lst {
        {dir "Виртуальные каталоги"}
        {com "Разрешённые COM-классы"}
        {addin "Внешние компоненты"}
        {module "Внешние отчёты и обработки"}
        {app "Разрешённые приложения"}
        {inet "Ресурсы интернет"}
    }
    foreach i $lst {
        append item [lindex $i 0] "::$id"
        if { [$tree exists $item] == 0 } {
            $tree insert $parent end -id $item -text [lindex $i 1] -values "$id"
        }
        unset item 
    }
}

Is é an difríocht eatarthu ná úsáid lúb, ina ndéantar na horduithe arís agus arís eile a fhorghníomhú. Cén cur chuige atá le húsáid de rogha an fhorbróra.

Táimid tar éis gnéithe a chur leis agus sonraí a aisghabháil, anois tá sé in am díriú ar eagarthóireacht. Ós rud é, go bunúsach, go n-úsáidtear na paraiméadair chéanna le haghaidh eagarthóireacht agus cur leis (cé is moite den bhunachar faisnéise), úsáidtear na foirmeacha dialóige céanna. Breathnaíonn an algartam chun nósanna imeachta glaonna chun cur leis mar seo:

Cuir leis::$key->AddToplevel

Agus le haghaidh eagarthóireacht mar seo:

Cuir::$key->Cuir leis::$key->AddTopLevel

Mar shampla, déanaimis eagarthóireacht a dhéanamh ar bhraisle, i.e. Tar éis duit ainm an bhraisle sa chrann a chliceáil, brúigh an cnaipe eagarthóireachta sa bharra uirlisí (peann luaidhe) agus taispeánfar an fhoirm chomhfhreagrach ar an scáileán:

GUI a scríobh do 1C RAC, nó arís faoi Tcl/Tk
Cuir::cnuasach

proc Edit::cluster {tree host values} {
    global default lifetime_limit expiration_timeout session_fault_tolerance_level
    global max_memory_size max_memory_time_limit errors_count_threshold security_level
    global load_balancing_mode kill_problem_processes active_cluster 
    agent_user agent_pwd cluster_user cluster_pwd auth
    if {$cluster_user ne "" && $cluster_pwd ne ""} {
        set auth "--cluster-user=$cluster_user --cluster-pwd=$cluster_pwd"
    } else {
        set auth ""
    }
    # рисуем форму для кластера
    set frm [Add::cluster $tree $host $values]
    # меняем текст на метке
    $frm configure -text "Редактирование кластера"
    
    set active_cluster $values
    # получаем данные по выделенному кластеру
    set lst [RunCommand cluster::$values "cluster info --cluster=$active_cluster $host"]
    # заполняем поля
    FormFieldsDataInsert $frm $lst
    # выключаем поля, редактирование которых запрещено
    $frm.ent_host configure -state disable
    $frm.ent_port configure -state disable
    # переназначаем обработчик
    .add.frm_btn.btn_ok configure -command {
        RunCommand "" "cluster update 
        --cluster=$active_cluster $auth 
        --name=[.add.frm.ent_name get] 
        --expiration-timeout=$expiration_timeout 
        --lifetime-limit=$lifetime_limit 
        --max-memory-size=$max_memory_size 
        --max-memory-time-limit=$max_memory_time_limit 
        --security-level=$security_level 
        --session-fault-tolerance-level=$session_fault_tolerance_level 
        --load-balancing-mode=$load_balancing_mode 
        --errors-count-threshold=$errors_count_threshold 
        --kill-problem-processes=$kill_problem_processes 
        $auth $host"
        $tree delete "cluster::$active_cluster"
        Run::server $tree $host ""
        destroy .add
    }
}

Bunaithe ar na tuairimí sa chód, i bprionsabal, tá gach rud soiléir, ach amháin go bhfuil an cód láimhseálaí cnaipe sáraithe agus tá nós imeachta FormFieldsDataInsert ann a líonann na réimsí le sonraí agus a thosaíonn na hathróga:

Ionsáigh FoirmFieldsData

proc FormFieldsDataInsert {frm lst} {
    foreach i [lindex $lst 0] {
        # получаем список параметров и значений
        if [regexp -nocase -all -- {(D+)(s*?|)(:)(s*?|)(.*)} $i match param v2 v3 v4 value] {
            # меняем символы
            regsub -all -- "-" [string trim $param] "_" entry_name
            # заполняем данными
            if [winfo exists $frm.ent_$entry_name] {
                $frm.ent_$entry_name delete 0 end
                $frm.ent_$entry_name insert end [string trim $value """]
            }
            if [winfo exists $frm.cb_$entry_name] {
                global $entry_name
                set $entry_name [string trim $value """]
            }
            # для чекбоксов меняем значения
            if [winfo exists $frm.check_$entry_name] {
                global $entry_name
                if {$value eq "0"} {
                    set $entry_name no
                } elseif {$value eq "1"} {
                    set $entry_name yes
                } else {
                    set $entry_name $value
                }
            }
        }
    }
}

Sa nós imeachta seo, tá buntáiste eile ag tcl dromchla - cuirtear luachanna athróg eile in ionad ainmneacha athróg. Iad siúd. chun líonadh foirmeacha agus túsú na n-athróg a uathoibriú, comhfhreagraíonn ainmneacha na réimsí agus na n-athróg do lasca líne ordaithe an áirgiúlacht rac agus ainmneacha na bparaiméadar aschuir ordaithe le heisceacht éigin - cuirtear béim in ionad an dash. E.g sceidealta-poist-dhiúltú oireann an pháirc ent_scheduled_jobs_siúl agus athraitheach sceidealta_jobs_séan.

D’fhéadfadh foirmeacha suimithe agus eagarthóireachta a bheith difriúil i gcomhdhéanamh na réimsí, mar shampla, ag obair le bunachar faisnéise:

Slándáil faisnéise á cur leis

GUI a scríobh do 1C RAC, nó arís faoi Tcl/Tk

Slándáil faisnéise á cur in eagar

GUI a scríobh do 1C RAC, nó arís faoi Tcl/Tk

Sa nós imeachta eagarthóireachta Edit::infobase, cuirtear na réimsí riachtanacha leis an bhfoirm; tá an cód toirtiúil, mar sin ní chuirim i láthair anseo é.

De réir analaí, cuirtear nósanna imeachta le haghaidh cur leis, eagarthóireacht, scriosadh i bhfeidhm le haghaidh eilimintí eile.

Ós rud é go gciallaíonn oibriú an áirgiúlachta líon neamhtheoranta freastalaithe, braislí, bunachair faisnéise, etc., chun a chinneadh cé acu braisle lena mbaineann an freastalaí nó an córas slándála faisnéise, tugadh isteach roinnt athróg dhomhanda, a socraítear luachanna gach ceann díobh. am a chliceálann tú ar na gnéithe den chrann. Iad siúd. ritheann an nós imeachta go hathchúrsach trí na tuismitheoirí go léir agus socraítear na hathróga:

SocraighGlobalVarFromTreeItems

proc SetGlobalVarFromTreeItems {tree id} {
    global host server active_cluster infobase
    set parent [$tree parent $id]
    set values [$tree item $id -values]
    set key [lindex [split $id "::"] 0]
    switch -- $key {
        server {set host $values}
        work_server {set server $values}
        cluster {set active_cluster $values}
        infobase {set infobase $values}
    }
    if {$parent eq ""} {
        return
    } else {
        SetGlobalVarFromTreeItems $tree $parent
    }
}

Ceadaíonn an bhraisle 1C duit oibriú le nó gan údarú. Tá dhá chineál riarthóirí ann—riarthóir gníomhaire braisle agus riarthóir braisle. Dá réir sin, le haghaidh oibriú ceart, tugadh isteach 4 athróg dhomhanda eile ina raibh logáil isteach agus pasfhocal an riarthóra. Iad siúd. má tá cuntas riarthóra sa bhraisle, taispeánfar dialóg chun do logáil isteach agus do phasfhocal a chur isteach, déanfar na sonraí a shábháil mar chuimhne agus cuirfear isteach i ngach ordú don bhraisle comhfhreagrach.

Is é seo an fhreagracht as an nós imeachta láimhseála earráidí.

Earráid Páirceáil

proc ErrorParcing {err opt} {
    global cluster_user cluster_pwd agent_user agent_pwd
        switch -regexp -- $err {
        "Cluster administrator is not authenticated" {
            AuthorisationDialog "Администратор кластера"
            .auth_win.frm_btn.btn_ok configure -command {
                set cluster_user [.auth_win.frm.ent_name get]
                set cluster_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
            #RunCommand $root $par
        }
        "Central server administrator is not authenticated" {
            AuthorisationDialog "Администратор агента кластера"
            .auth_win.frm_btn.btn_ok configure -command {
                set agent_user [.auth_win.frm.ent_name get]
                set agent_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
        }
        "Администратор кластера не аутентифицирован" {
            AuthorisationDialog "Администратор кластера"
            .auth_win.frm_btn.btn_ok configure -command {
                set cluster_user [.auth_win.frm.ent_name get]
                set cluster_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
            #RunCommand $root $par
        }
        "Администратор центрального сервера не аутентифицирован" {
            AuthorisationDialog "Администратор агента кластера"
            .auth_win.frm_btn.btn_ok configure -command {
                set agent_user [.auth_win.frm.ent_name get]
                set agent_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
        }
        (.+) {
            tk_messageBox -type ok -icon error -message "$err"
        }
    }
}

Iad siúd. ag brath ar an méid a fhilleann an t-ordú, beidh an t-imoibriú dá réir sin.

Faoi láthair, tá thart ar 95 faoin gcéad den fheidhmiúlacht curtha i bhfeidhm, níl fágtha ach obair le próifílí slándála a chur i bhfeidhm agus é a thástáil =). Sin é an méid. Gabh mo leithscéal as an scéal crumpled.

Tá an cód ar fáil go traidisiúnta anseo.

Nuashonrú: Chríochnaigh mé ag obair le próifílí slándála. Anois tá an fheidhmiúlacht 100% curtha i bhfeidhm.

Nuashonrú 2: tá logánú go Béarla agus Rúisis curtha leis, tá tástáil déanta ar obair win7
GUI a scríobh do 1C RAC, nó arís faoi Tcl/Tk

Foinse: will.com

Add a comment