ssh-hull 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|