ssh-hull 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +44 -0
- data/.gitignore +27 -0
- data/.rubocop.yml +62 -0
- data/.tool-versions +1 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +142 -0
- data/LICENSE +19 -0
- data/README.md +12 -0
- data/Rakefile +7 -0
- data/bin/bundle +114 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/bomb +12 -0
- data/config/locales/en.yml +71 -0
- data/config/locales/fr.yml +71 -0
- data/exe/ssh-hull +12 -0
- data/exe/ssh-tunnel +1 -0
- data/lib/ssh-hull/cli.rb +113 -0
- data/lib/ssh-hull/logger.rb +6 -0
- data/lib/ssh-hull/ui/application.rb +47 -0
- data/lib/ssh-hull/ui/forms/application_form.rb +69 -0
- data/lib/ssh-hull/ui/forms/host_form.rb +27 -0
- data/lib/ssh-hull/ui/forms/tunnel_form.rb +31 -0
- data/lib/ssh-hull/ui/helpers/application_window_helper.rb +233 -0
- data/lib/ssh-hull/ui/helpers/common/form_helper.rb +169 -0
- data/lib/ssh-hull/ui/helpers/common/minimize_helper.rb +46 -0
- data/lib/ssh-hull/ui/helpers/common/modal_helper.rb +43 -0
- data/lib/ssh-hull/ui/helpers/common/toolbar_helper.rb +106 -0
- data/lib/ssh-hull/ui/helpers/common/translation_helper.rb +18 -0
- data/lib/ssh-hull/ui/helpers/common/tree_view_helper.rb +40 -0
- data/lib/ssh-hull/ui/helpers/host_window_helper.rb +230 -0
- data/lib/ssh-hull/ui/helpers/tunnel_window_helper.rb +96 -0
- data/lib/ssh-hull/ui/models/config.rb +82 -0
- data/lib/ssh-hull/ui/models/host.rb +90 -0
- data/lib/ssh-hull/ui/models/tunnel.rb +118 -0
- data/lib/ssh-hull/ui/status_icon.rb +45 -0
- data/lib/ssh-hull/ui/windows/about_window.rb +32 -0
- data/lib/ssh-hull/ui/windows/application_window.rb +42 -0
- data/lib/ssh-hull/ui/windows/hosts/delete_window.rb +56 -0
- data/lib/ssh-hull/ui/windows/hosts/edit_window.rb +39 -0
- data/lib/ssh-hull/ui/windows/hosts/new_window.rb +45 -0
- data/lib/ssh-hull/ui/windows/tunnels/delete_window.rb +57 -0
- data/lib/ssh-hull/ui/windows/tunnels/edit_window.rb +39 -0
- data/lib/ssh-hull/ui/windows/tunnels/new_window.rb +45 -0
- data/lib/ssh-hull/version.rb +17 -0
- data/lib/ssh-tunnel.rb +94 -0
- data/resources/gresources.xml +13 -0
- data/resources/ui/about_window.glade +48 -0
- data/resources/ui/application_window.glade +196 -0
- data/resources/ui/hosts/delete_window.glade +74 -0
- data/resources/ui/hosts/edit_window.glade +331 -0
- data/resources/ui/hosts/new_window.glade +328 -0
- data/resources/ui/tunnels/delete_window.glade +73 -0
- data/resources/ui/tunnels/edit_window.glade +305 -0
- data/resources/ui/tunnels/new_window.glade +305 -0
- data/snap/snapcraft.yaml +48 -0
- data/spec/factories/host.rb +22 -0
- data/spec/factories/tunnel.rb +16 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/ssh_tunnel/ui/forms/host_form_spec.rb +103 -0
- data/spec/ssh_tunnel/ui/forms/tunnel_form_spec.rb +132 -0
- data/spec/ssh_tunnel/ui/models/host_spec.rb +116 -0
- data/spec/ssh_tunnel/ui/models/tunnel_spec.rb +43 -0
- data/spec/ssh_tunnel_spec.rb +45 -0
- data/ssh-hull.gemspec +38 -0
- metadata +320 -0
@@ -0,0 +1,169 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SSHTunnel
|
4
|
+
module UI
|
5
|
+
module Helpers
|
6
|
+
module Common
|
7
|
+
module FormHelper
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
def bind_menu_entries(entries)
|
11
|
+
entries.each do |f|
|
12
|
+
bind_template_child "menu_#{f}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def bind_buttons(buttons)
|
18
|
+
buttons.each do |f|
|
19
|
+
bind_template_child "button_#{f}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def bind_form_fields(fields)
|
25
|
+
fields.each do |f|
|
26
|
+
bind_template_child "label_#{f}"
|
27
|
+
bind_template_child "input_#{f}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
module InstanceMethods
|
34
|
+
|
35
|
+
def params
|
36
|
+
params = {}
|
37
|
+
form_fields.each do |field_name, opts|
|
38
|
+
# get input value
|
39
|
+
input = "input_#{field_name}"
|
40
|
+
field = __send__(input)
|
41
|
+
getter = getter_for(opts[:type])
|
42
|
+
value = field.__send__(getter)
|
43
|
+
params[field_name] = value
|
44
|
+
end
|
45
|
+
params
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def bind_submit_button
|
50
|
+
button_submit.label = t('button.submit')
|
51
|
+
button_submit.signal_connect :clicked do
|
52
|
+
submit_form(params)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def submit_form(params)
|
58
|
+
form = form_object
|
59
|
+
form.submit(params)
|
60
|
+
if form.valid?
|
61
|
+
form.save
|
62
|
+
save_and_reload_view
|
63
|
+
else
|
64
|
+
render_form_errors(form.errors)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def form_object
|
70
|
+
raise NotImplementedError
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def save_and_reload_view
|
75
|
+
raise NotImplementedError
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def render_form_errors(errors)
|
80
|
+
form_fields.each do |field_name, _method|
|
81
|
+
has_errors = errors.of_kind?(field_name, :blank) || errors.of_kind?(field_name, :inclusion)
|
82
|
+
input = "input_#{field_name}"
|
83
|
+
field = __send__(input)
|
84
|
+
color = has_errors ? red : white
|
85
|
+
field.override_background_color(:normal, color)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def red
|
91
|
+
Gdk::RGBA.new(255, 0, 0)
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def white
|
96
|
+
Gdk::RGBA.new(255, 255, 255)
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def restore_form_values(model)
|
101
|
+
form_fields.each do |field_name, opts|
|
102
|
+
restore_form_value(model, field_name, opts)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def restore_form_value(model, field_name, opts)
|
108
|
+
# get model value
|
109
|
+
value = model.__send__(field_name)
|
110
|
+
|
111
|
+
# set input form
|
112
|
+
input = "input_#{field_name}"
|
113
|
+
field = __send__(input)
|
114
|
+
setter = setter_for(opts[:type])
|
115
|
+
|
116
|
+
if opts[:type] == :file && value.nil?
|
117
|
+
field.unselect_all
|
118
|
+
else
|
119
|
+
field.__send__(setter, value)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
INPUT_TYPES = {
|
125
|
+
text: {
|
126
|
+
getter: :text,
|
127
|
+
setter: :text=,
|
128
|
+
},
|
129
|
+
select: {
|
130
|
+
getter: :active_id,
|
131
|
+
setter: :active_id=,
|
132
|
+
},
|
133
|
+
file: {
|
134
|
+
getter: :filename,
|
135
|
+
setter: :filename=,
|
136
|
+
},
|
137
|
+
checkbox: {
|
138
|
+
getter: :active?,
|
139
|
+
setter: :active=,
|
140
|
+
},
|
141
|
+
}.freeze
|
142
|
+
private_constant :INPUT_TYPES
|
143
|
+
|
144
|
+
|
145
|
+
def setter_for(input_type)
|
146
|
+
INPUT_TYPES.dig(input_type, :setter)
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
def getter_for(input_type)
|
151
|
+
INPUT_TYPES.dig(input_type, :getter)
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
def set_input_labels(scope:)
|
156
|
+
form_fields.each do |field_name, _method|
|
157
|
+
label = "label_#{field_name}"
|
158
|
+
field = __send__(label)
|
159
|
+
value = t("form.#{scope}.#{field_name}")
|
160
|
+
field.text = value
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SSHTunnel
|
4
|
+
module UI
|
5
|
+
module Helpers
|
6
|
+
module Common
|
7
|
+
module MinimizeHelper
|
8
|
+
|
9
|
+
def initialize(*)
|
10
|
+
super
|
11
|
+
|
12
|
+
# Set instance variables
|
13
|
+
@minimized = false
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def minimized?
|
18
|
+
@minimized
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def minimize!
|
23
|
+
@minimized = true
|
24
|
+
hide
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def maximize!
|
29
|
+
@minimized = false
|
30
|
+
show
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def toggle!
|
35
|
+
if minimized?
|
36
|
+
maximize!
|
37
|
+
else
|
38
|
+
minimize!
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SSHTunnel
|
4
|
+
module UI
|
5
|
+
module Helpers
|
6
|
+
module Common
|
7
|
+
module ModalHelper
|
8
|
+
|
9
|
+
def initialize(application, window, *)
|
10
|
+
super application: application
|
11
|
+
|
12
|
+
# Set instance variables
|
13
|
+
@application = application
|
14
|
+
@window = window
|
15
|
+
|
16
|
+
# Bind listeners
|
17
|
+
bind_submit_button
|
18
|
+
bind_cancel_button
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def bind_cancel_button
|
25
|
+
# Not all modals have a cancel button
|
26
|
+
if respond_to?(:button_cancel)
|
27
|
+
button_cancel.label = t('button.cancel')
|
28
|
+
button_cancel.signal_connect :clicked do
|
29
|
+
close
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Bind escape key stroke
|
34
|
+
signal_connect :key_press_event do |_widget, event|
|
35
|
+
event.keyval == 65_307 ? close : false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SSHTunnel
|
4
|
+
module UI
|
5
|
+
module Helpers
|
6
|
+
module Common
|
7
|
+
module ToolbarHelper
|
8
|
+
|
9
|
+
def initialize(*)
|
10
|
+
super
|
11
|
+
|
12
|
+
# Bind listeners
|
13
|
+
bind_menu_entries
|
14
|
+
bind_toolbar_buttons
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
|
21
|
+
def bind_menu_entries
|
22
|
+
signal_connect :destroy do
|
23
|
+
@application.quit
|
24
|
+
end
|
25
|
+
|
26
|
+
menu_quit.label = t('menu.quit')
|
27
|
+
menu_quit.signal_connect :activate do
|
28
|
+
@application.quit
|
29
|
+
end
|
30
|
+
|
31
|
+
menu_about.label = t('menu.about')
|
32
|
+
menu_about.signal_connect :activate do
|
33
|
+
window = SSHTunnel::UI::Windows::AboutWindow.new(@application)
|
34
|
+
window.present
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def bind_toolbar_buttons
|
40
|
+
bind_toolbar_button_add
|
41
|
+
bind_toolbar_button_edit
|
42
|
+
bind_toolbar_button_remove
|
43
|
+
bind_toolbar_button_start
|
44
|
+
bind_toolbar_button_stop
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def bind_toolbar_button_add
|
49
|
+
button_add.tooltip_text = t('tooltip.host.add')
|
50
|
+
button_add.signal_connect :clicked do
|
51
|
+
with_new_host_model do |object|
|
52
|
+
window = SSHTunnel::UI::Windows::Hosts::NewWindow.new(@application, self, object)
|
53
|
+
window.present
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def bind_toolbar_button_edit
|
60
|
+
button_edit.tooltip_text = t('tooltip.host.edit')
|
61
|
+
button_edit.signal_connect :clicked do
|
62
|
+
with_host_model do |object|
|
63
|
+
window = SSHTunnel::UI::Windows::Hosts::EditWindow.new(@application, self, object)
|
64
|
+
window.present
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def bind_toolbar_button_remove
|
71
|
+
button_remove.tooltip_text = t('tooltip.host.remove')
|
72
|
+
button_remove.signal_connect :clicked do
|
73
|
+
with_host_model do |object|
|
74
|
+
window = SSHTunnel::UI::Windows::Hosts::DeleteWindow.new(@application, self, object)
|
75
|
+
window.present
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def bind_toolbar_button_start
|
82
|
+
button_start.tooltip_text = t('tooltip.tunnel.start')
|
83
|
+
button_start.signal_connect :clicked do
|
84
|
+
with_host_model do |object|
|
85
|
+
object.start_tunnels!
|
86
|
+
reload_hosts_treeview
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def bind_toolbar_button_stop
|
93
|
+
button_stop.tooltip_text = t('tooltip.tunnel.stop')
|
94
|
+
button_stop.signal_connect :clicked do
|
95
|
+
with_host_model do |object|
|
96
|
+
object.stop_tunnels!
|
97
|
+
reload_hosts_treeview
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SSHTunnel
|
4
|
+
module UI
|
5
|
+
module Helpers
|
6
|
+
module Common
|
7
|
+
module TranslationHelper
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
ruby2_keywords def t(*args)
|
11
|
+
I18n.t(*args)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SSHTunnel
|
4
|
+
module UI
|
5
|
+
module Helpers
|
6
|
+
module Common
|
7
|
+
module TreeViewHelper
|
8
|
+
|
9
|
+
def add_text_column(treeview, label, attributes)
|
10
|
+
renderer = Gtk::CellRendererText.new
|
11
|
+
add_column(treeview, renderer, label, attributes)
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def add_image_column(treeview, label, attributes)
|
16
|
+
renderer = Gtk::CellRendererPixbuf.new
|
17
|
+
add_column(treeview, renderer, label, attributes)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def add_column(treeview, renderer, label, attributes)
|
22
|
+
visible = attributes.delete(:visible) { true }
|
23
|
+
sortable = attributes.delete(:sortable) { true }
|
24
|
+
|
25
|
+
column = Gtk::TreeViewColumn.new(label, renderer, attributes)
|
26
|
+
column.visible = visible
|
27
|
+
|
28
|
+
if sortable
|
29
|
+
column.clickable = true
|
30
|
+
column.sort_column_id = attributes[:text] if attributes[:text]
|
31
|
+
end
|
32
|
+
|
33
|
+
treeview.append_column(column)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SSHTunnel
|
4
|
+
module UI
|
5
|
+
module Helpers
|
6
|
+
module HostWindowHelper
|
7
|
+
|
8
|
+
include SSHTunnel::UI::Helpers::Common::ModalHelper
|
9
|
+
include SSHTunnel::UI::Helpers::Common::TranslationHelper
|
10
|
+
include SSHTunnel::UI::Helpers::Common::TreeViewHelper
|
11
|
+
include SSHTunnel::UI::Helpers::Common::FormHelper::InstanceMethods
|
12
|
+
|
13
|
+
def self.included(base)
|
14
|
+
base.extend(ClassMethods)
|
15
|
+
base.extend(SSHTunnel::UI::Helpers::Common::FormHelper::ClassMethods)
|
16
|
+
end
|
17
|
+
|
18
|
+
FORM_BUTTONS = %w[submit cancel add edit remove reset_identity_file].freeze
|
19
|
+
FORM_FIELDS = {
|
20
|
+
name: {
|
21
|
+
type: :text,
|
22
|
+
},
|
23
|
+
user: {
|
24
|
+
type: :text,
|
25
|
+
},
|
26
|
+
host: {
|
27
|
+
type: :text,
|
28
|
+
},
|
29
|
+
port: {
|
30
|
+
type: :text,
|
31
|
+
},
|
32
|
+
identity_file: {
|
33
|
+
type: :file,
|
34
|
+
},
|
35
|
+
}.freeze
|
36
|
+
|
37
|
+
|
38
|
+
module ClassMethods
|
39
|
+
|
40
|
+
def init
|
41
|
+
bind_buttons(FORM_BUTTONS)
|
42
|
+
bind_form_fields(FORM_FIELDS.keys)
|
43
|
+
bind_template_child 'tunnels_scrolled_window'
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def initialize(application, window, host)
|
50
|
+
super
|
51
|
+
|
52
|
+
# Set instance variables
|
53
|
+
@host = host
|
54
|
+
|
55
|
+
# Bind listeners
|
56
|
+
set_input_labels(scope: :host)
|
57
|
+
bind_host_buttons
|
58
|
+
bind_tunnels_buttons
|
59
|
+
|
60
|
+
# Load tunnels treeview
|
61
|
+
load_tunnels_treeview(@host)
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def load_tunnels_treeview(host)
|
66
|
+
# create treeview
|
67
|
+
treeview_model = create_tunnels_treeview_model(host.tunnels)
|
68
|
+
@tunnels_treeview = create_tunnels_treeview(treeview_model)
|
69
|
+
|
70
|
+
# Render treeview
|
71
|
+
tunnels_scrolled_window.add(@tunnels_treeview)
|
72
|
+
@tunnels_treeview.show
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
def reload_tunnels_treeview(host)
|
77
|
+
@tunnels_treeview.destroy
|
78
|
+
load_tunnels_treeview(host)
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
|
85
|
+
TUNNEL_UUID_COLUMN = 0
|
86
|
+
TUNNEL_NAME_COLUMN = 1
|
87
|
+
TUNNEL_TYPE_COLUMN = 2
|
88
|
+
TUNNEL_LOCAL_HOST_COLUMN = 3
|
89
|
+
TUNNEL_LOCAL_PORT_COLUMN = 4
|
90
|
+
TUNNEL_REMOTE_HOST_COLUMN = 5
|
91
|
+
TUNNEL_REMOTE_PORT_COLUMN = 6
|
92
|
+
TUNNEL_AUTO_START_COLUMN = 7
|
93
|
+
|
94
|
+
|
95
|
+
def create_tunnels_treeview_model(tunnels)
|
96
|
+
model = Gtk::ListStore.new(String, String, String, String, String, String, String, String)
|
97
|
+
|
98
|
+
tunnels.each do |tunnel|
|
99
|
+
iter = model.append
|
100
|
+
iter.set_values([tunnel.uuid, tunnel.name, tunnel.type, tunnel.local_host, tunnel.local_port, tunnel.remote_host, tunnel.remote_port, tunnel.auto_start?.to_s])
|
101
|
+
end
|
102
|
+
|
103
|
+
model
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def create_tunnels_treeview(model)
|
108
|
+
treeview = Gtk::TreeView.new(model)
|
109
|
+
|
110
|
+
# edit tunnel on double-click
|
111
|
+
tunnels_treeview_bind_double_click(treeview)
|
112
|
+
|
113
|
+
# add columns to the tree view
|
114
|
+
tunnels_treeview_add_columns(treeview)
|
115
|
+
|
116
|
+
treeview
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
def tunnels_treeview_bind_double_click(treeview)
|
121
|
+
treeview.signal_connect :row_activated do |_widget, path|
|
122
|
+
if path.to_s.include?(':')
|
123
|
+
false
|
124
|
+
else
|
125
|
+
with_tunnel_model do |object|
|
126
|
+
window = SSHTunnel::UI::Windows::Tunnels::EditWindow.new(application, self, object)
|
127
|
+
window.present
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
def tunnels_treeview_add_columns(treeview)
|
135
|
+
add_text_column treeview, t('view.tunnel.uuid'), text: TUNNEL_UUID_COLUMN, visible: false
|
136
|
+
add_text_column treeview, t('view.tunnel.name'), text: TUNNEL_NAME_COLUMN
|
137
|
+
add_text_column treeview, t('view.tunnel.type'), text: TUNNEL_TYPE_COLUMN
|
138
|
+
add_text_column treeview, t('view.tunnel.local_host'), text: TUNNEL_LOCAL_HOST_COLUMN
|
139
|
+
add_text_column treeview, t('view.tunnel.local_port'), text: TUNNEL_LOCAL_PORT_COLUMN
|
140
|
+
add_text_column treeview, t('view.tunnel.remote_host'), text: TUNNEL_REMOTE_HOST_COLUMN
|
141
|
+
add_text_column treeview, t('view.tunnel.remote_port'), text: TUNNEL_REMOTE_PORT_COLUMN
|
142
|
+
add_text_column treeview, t('view.tunnel.auto_start'), text: TUNNEL_AUTO_START_COLUMN
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
def bind_host_buttons
|
147
|
+
button_reset_identity_file.label = t('button.reset')
|
148
|
+
button_reset_identity_file.tooltip_text = t('tooltip.host.reset_identity_file')
|
149
|
+
button_reset_identity_file.signal_connect :clicked do
|
150
|
+
input_identity_file.unselect_all
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
# rubocop:disable Metrics/MethodLength
|
156
|
+
def bind_tunnels_buttons
|
157
|
+
button_add.label = t('button.add')
|
158
|
+
button_add.tooltip_text = t('tooltip.tunnel.add')
|
159
|
+
button_add.signal_connect :clicked do
|
160
|
+
with_new_tunnel_model do |object|
|
161
|
+
window = SSHTunnel::UI::Windows::Tunnels::NewWindow.new(application, self, object)
|
162
|
+
window.present
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
button_edit.label = t('button.edit')
|
167
|
+
button_edit.tooltip_text = t('tooltip.tunnel.edit')
|
168
|
+
button_edit.signal_connect :clicked do
|
169
|
+
with_tunnel_model do |object|
|
170
|
+
window = SSHTunnel::UI::Windows::Tunnels::EditWindow.new(application, self, object)
|
171
|
+
window.present
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
button_remove.label = t('button.remove')
|
176
|
+
button_remove.tooltip_text = t('tooltip.tunnel.remove')
|
177
|
+
button_remove.signal_connect :clicked do
|
178
|
+
with_tunnel_model do |object|
|
179
|
+
window = SSHTunnel::UI::Windows::Tunnels::DeleteWindow.new(application, self, object)
|
180
|
+
window.present
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
# rubocop:enable Metrics/MethodLength
|
185
|
+
|
186
|
+
|
187
|
+
def all_tunnels
|
188
|
+
@host.tunnels
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
def find_tunnel_model
|
193
|
+
return nil if @tunnels_treeview.selection.selected.blank?
|
194
|
+
|
195
|
+
uuid = @tunnels_treeview.selection.selected.get_value(TUNNEL_UUID_COLUMN)
|
196
|
+
all_tunnels.find { |t| t.uuid == uuid }
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
def with_tunnel_model
|
201
|
+
object = find_tunnel_model
|
202
|
+
yield object if object
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
def with_new_tunnel_model
|
207
|
+
yield SSHTunnel::UI::Models::Tunnel.new(parent: @host)
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
def form_fields
|
212
|
+
FORM_FIELDS
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
def form_object
|
217
|
+
SSHTunnel::UI::Forms::HostForm.new(@host)
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
def save_and_reload_view
|
222
|
+
@application.config.save!
|
223
|
+
close
|
224
|
+
@window.reload_hosts_treeview
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|