rediscover 0.0.1

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.
data/bin/rediscover ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.dirname(__FILE__) + '/../lib/')
4
+ require 'rediscover'
5
+
6
+ Rediscover::App.new.main_loop()
@@ -0,0 +1,57 @@
1
+ require 'logger'
2
+ require 'forwardable'
3
+ require 'rediscover/exception_handler'
4
+ require 'rediscover/icon'
5
+ require 'rediscover/frame/connect'
6
+ require 'rediscover/frame/main'
7
+ require 'rediscover/dialog/error'
8
+ require 'rediscover/dialog/confirm'
9
+
10
+ module Rediscover
11
+ class App < Wx::App
12
+
13
+ DEFAULTS = {
14
+ :host => 'localhost',
15
+ :port => 6379
16
+ }
17
+
18
+ attr_reader :logger, :host, :port, :redis
19
+
20
+ def on_init
21
+ @logger = Logger.new(STDOUT)
22
+ ExceptionHandler.set_logger(@logger)
23
+ @host = DEFAULTS[:host]
24
+ @port = DEFAULTS[:port]
25
+
26
+ display_connect
27
+ end
28
+
29
+ def display_connect
30
+ @connect_frame = Frame::Connect.new
31
+ end
32
+
33
+ def display_main
34
+ @main_frame = Frame::Main.new
35
+ end
36
+
37
+ def connect(host, port)
38
+ begin
39
+ @redis = Redis.new(:host => host, :port => port)
40
+ @redis.connect_to_server # connection errors will be rescued by Frame::Connect
41
+ @host, @port = host, port
42
+ @connect_frame.close
43
+ rescue => e
44
+ logger.error(e)
45
+ @conn_refused_dlg = Dialog::Error.new(@connect_frame,
46
+ "Can't connect to server.",
47
+ 'Unable to Connect')
48
+ @conn_refused_dlg.show_modal
49
+ return
50
+ end
51
+
52
+ @logger.info(@redis.to_s)
53
+ display_main
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,12 @@
1
+ module Rediscover
2
+ module Dialog
3
+ class Confirm < Wx::MessageDialog
4
+ include Wx
5
+
6
+ def initialize(window, message, caption)
7
+ super(window, message, caption, YES_NO|ICON_QUESTION)
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Rediscover
2
+ module Dialog
3
+ class Error < Wx::MessageDialog
4
+ include Wx
5
+
6
+ def initialize(window, message, caption)
7
+ super(window, message, caption, OK|ICON_ERROR)
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ module Rediscover
2
+ class ExceptionHandler
3
+
4
+ def self.set_logger(logger)
5
+ @@logger = logger
6
+ end
7
+
8
+ def self.modal(window, exception)
9
+ self.log(exception)
10
+ dlg = Rediscover::Dialog::Error.new(window,
11
+ 'An error occurred: ' + exception.to_s,
12
+ 'Error')
13
+ dlg.show_modal
14
+ end
15
+
16
+ def self.log(exception)
17
+ @@logger.error(exception)
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ module Rediscover
2
+ module Frame
3
+
4
+ class Connect < Wx::Frame
5
+ include Wx
6
+
7
+ def initialize
8
+ @app = get_app
9
+ super(nil, -1, 'Connect to Redis')
10
+
11
+ set_icon(Rediscover::Icon.new('server_connect'))
12
+
13
+ setup_panel
14
+ show
15
+ end
16
+
17
+ def setup_panel
18
+ @panel = Wx::Panel.new(self)
19
+ @host_label = StaticText.new(@panel, :label => 'Host')
20
+ @host_textbox = TextCtrl.new(@panel, :value => @app.host)
21
+ @port_label = StaticText.new(@panel, :label => 'Port')
22
+ @port_textbox = TextCtrl.new(@panel, :value => @app.port.to_s)
23
+ @connect_button = Button.new(@panel, :label => 'Connect')
24
+
25
+ evt_button @connect_button, :connect_button_evt
26
+
27
+ @panel_sizer = BoxSizer.new(VERTICAL)
28
+ @panel.set_sizer(@panel_sizer)
29
+ @panel_sizer.add(@host_label, 0, GROW|ALL, 2)
30
+ @panel_sizer.add(@host_textbox, 0, GROW|ALL, 2)
31
+ @panel_sizer.add(@port_label, 0, GROW|ALL, 2)
32
+ @panel_sizer.add(@port_textbox, 0, GROW|ALL, 2)
33
+ @panel_sizer.add(@connect_button, 0, GROW|ALL, 2)
34
+ end
35
+
36
+ def connect_button_evt
37
+ host = @host_textbox.get_value
38
+ port = @port_textbox.get_value.to_i
39
+ @app.connect(host, port)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,56 @@
1
+ module Rediscover
2
+ module Frame
3
+ class CreateKey < Wx::Frame
4
+ include Wx
5
+
6
+ def initialize(window)
7
+ @redis = get_app.redis
8
+ super(window, -1, 'Create a Key')
9
+
10
+ set_icon(Rediscover::Icon.new('key_add'))
11
+
12
+ setup_panel
13
+ show
14
+ end
15
+
16
+ def setup_panel
17
+ @panel = Wx::Panel.new(self)
18
+ @key_label = StaticText.new(@panel, :label => 'Key')
19
+ @key_textbox = TextCtrl.new(@panel)
20
+ @value_label = StaticText.new(@panel, :label => 'Value')
21
+ @value_textbox = TextCtrl.new(@panel)
22
+ @create_button = Button.new(@panel, :label => 'Create')
23
+
24
+ evt_button @create_button, :create_evt
25
+
26
+ @panel_sizer = BoxSizer.new(VERTICAL)
27
+ @panel.set_sizer(@panel_sizer)
28
+ @panel_sizer.add(@key_label, 0, GROW|ALL, 2)
29
+ @panel_sizer.add(@key_textbox, 0, GROW|ALL, 2)
30
+ @panel_sizer.add(@value_label, 0, GROW|ALL, 2)
31
+ @panel_sizer.add(@value_textbox, 0, GROW|ALL, 2)
32
+ @panel_sizer.add(@create_button, 0, GROW|ALL, 2)
33
+ end
34
+
35
+ def on_create(&block)
36
+ @on_create_block = block
37
+ end
38
+
39
+ def create_evt
40
+ key = @key_textbox.get_value
41
+ value = @value_textbox.get_value
42
+
43
+ begin
44
+ @redis[key] = value
45
+ rescue => e
46
+ ExceptionHandler.modal(self, e)
47
+ return
48
+ end
49
+
50
+ @on_create_block.call() if @on_create_block
51
+ close
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,59 @@
1
+ require 'rediscover/panel/server'
2
+ require 'rediscover/panel/browser'
3
+ require 'rediscover/panel/key_list'
4
+ require 'rediscover/key_viewer'
5
+ require 'rediscover/set_element_list'
6
+ require 'rediscover/sorted_set_element_list'
7
+ require 'rediscover/list_element_list'
8
+ require 'rediscover/panel/string_view'
9
+ require 'rediscover/panel/set_view'
10
+ require 'rediscover/panel/sorted_set_view'
11
+ require 'rediscover/panel/list_view'
12
+ require 'rediscover/frame/create_key'
13
+
14
+ module Rediscover
15
+ module Frame
16
+ class Main < Wx::Frame
17
+ include Wx
18
+
19
+ WINDOW_WIDTH = 600
20
+ WINDOW_HEIGHT = 400
21
+
22
+ def initialize
23
+ super(nil, -1, 'Rediscover', DEFAULT_POSITION, Size.new(WINDOW_WIDTH, WINDOW_HEIGHT))
24
+
25
+ @redis = get_app.redis
26
+ @logger = get_app.logger
27
+
28
+ set_icon(Rediscover::Icon.new('application'))
29
+
30
+ setup_status_bar
31
+ setup_notebook
32
+ show
33
+ end
34
+
35
+ def setup_notebook
36
+ @notebook = Notebook.new(self)
37
+
38
+ @server_page = Panel::Server.new(@notebook)
39
+ @browser_page = Panel::Browser.new(@notebook)
40
+ @browser_page.on_status_change { |status| update_status_bar(status) }
41
+
42
+ @notebook.add_page(@server_page, 'Server Info', false)
43
+ @notebook.add_page(@browser_page, 'Key Browser', true)
44
+ end
45
+
46
+ def setup_status_bar
47
+ @status_bar = create_status_bar(2)
48
+ @status_bar.set_status_widths([-3, -1]) # set fields to variable widths
49
+ update_status_bar
50
+ end
51
+
52
+ def update_status_bar(status = nil)
53
+ @status_bar.set_status_text(@redis.to_s, 0) # connection info in left field
54
+ @status_bar.set_status_text(status, 1) if status # key count in right field
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,12 @@
1
+ module Rediscover
2
+ class Icon < Wx::Icon
3
+
4
+ @@icon_dir = File.join( File.dirname(__FILE__), 'icons')
5
+
6
+ def initialize(icon_name)
7
+ icon_file = File.join(@@icon_dir, "#{icon_name}.png")
8
+ super(icon_file, Wx::BITMAP_TYPE_PNG)
9
+ end
10
+
11
+ end
12
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,117 @@
1
+ module Rediscover
2
+ class KeyListCtrl < Wx::ListCtrl
3
+ include Wx
4
+
5
+ COLS = %w(Key Value Type TTL)
6
+
7
+ def initialize(window)
8
+ @redis = get_app.redis
9
+ @logger = get_app.logger
10
+
11
+ super(window, :style => LC_REPORT|LC_VIRTUAL)
12
+
13
+ i = 0
14
+ COLS.each do |name|
15
+ insert_column(i += 1, name)
16
+ end
17
+ set_column_width(0, 200)
18
+ set_column_width(1, 200)
19
+
20
+ evt_list_item_right_click self, :list_item_right_click_evt
21
+ end
22
+
23
+ def size
24
+ @keys.size
25
+ end
26
+
27
+ def on_get_keys(&block)
28
+ @on_get_keys_block = block
29
+ end
30
+
31
+ def update
32
+ @keys = @on_get_keys_block.call()
33
+ @logger.debug("KeyListCtrl loaded #{size} keys")
34
+ delete_all_items
35
+ set_item_count(size)
36
+ do_on_status_change
37
+ end
38
+
39
+ def delete(selections)
40
+ selections.each do |index|
41
+ key = @keys[index]
42
+ @redis.delete(key)
43
+ end
44
+ update
45
+ end
46
+
47
+ def on_get_item_text(item, column)
48
+ text = case column
49
+ when COLS.index('Key') then @keys[item]
50
+ when COLS.index('Value') then get_item_value(item)
51
+ when COLS.index('Type') then get_item_type(item)
52
+ when COLS.index('TTL') then @redis.ttl(@keys[item]).to_s
53
+ end
54
+
55
+ return text || ''
56
+ end
57
+
58
+ def get_item_type(item)
59
+ @redis.type?(@keys[item])
60
+ end
61
+
62
+ def get_item_value(item)
63
+ case get_item_type(item)
64
+ when 'string' then return @redis[@keys[item]]
65
+ when 'list' then return "#{@redis.list_length(@keys[item])} element(s)"
66
+ when 'set' then return "#{@redis.set_count(@keys[item])} element(s)"
67
+ when 'zset' then return "#{@redis.zset_count(@keys[item])} element(s)"
68
+ end
69
+ end
70
+
71
+ def list_item_right_click_evt(event)
72
+ menu = get_ctx_menu_for_selections(get_selections)
73
+ popup_menu(menu, event.get_point) if menu
74
+ end
75
+
76
+ def get_ctx_menu_for_selections(selections)
77
+ return nil if selections.empty?
78
+ @ctx_menu = Menu.new
79
+
80
+ if selections.size == 1 && @redis.type?(@keys[*selections]) != 'none'
81
+ @ctx_edit_item = MenuItem.new(@ctx_menu, -1, 'Edit')
82
+ evt_menu(@ctx_edit_item) { do_on_edit(*selections) }
83
+ end
84
+
85
+ # delete menu item
86
+ @ctx_delete_item = MenuItem.new(@ctx_menu, -1, 'Delete')
87
+ evt_menu(@ctx_delete_item) do
88
+ if ID_YES == Dialog::Confirm.new(self, 'Really delete selected key(s)?', 'Really delete?').show_modal
89
+ delete(selections)
90
+ end
91
+ end
92
+
93
+ @ctx_menu.append_item(@ctx_edit_item) if @ctx_edit_item
94
+ @ctx_menu.append_item(@ctx_delete_item)
95
+ @ctx_menu
96
+ end
97
+
98
+ def on_edit(&block)
99
+ @on_edit_block = block
100
+ end
101
+
102
+ def do_on_edit(selection)
103
+ key = @keys[selection]
104
+ @on_edit_block.call(key, @redis.type?(key), selection)
105
+ end
106
+
107
+ def on_status_change(&block)
108
+ @on_status_change_block = block
109
+ do_on_status_change
110
+ end
111
+
112
+ def do_on_status_change
113
+ @on_status_change_block.call("#{size} keys") if @on_status_change_block
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,17 @@
1
+ module KeyViewer
2
+ def on_save(&block)
3
+ @on_save_block = block
4
+ end
5
+
6
+ def do_on_save
7
+ @on_save_block.call() if @on_save_block
8
+ end
9
+
10
+ def on_close(&block)
11
+ @on_close_block = block
12
+ end
13
+
14
+ def do_on_close
15
+ @on_close_block.call() if @on_close_block
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ module Rediscover
2
+ class ListElementList < Wx::ListCtrl
3
+ include Wx
4
+
5
+ def initialize(parent, key, elements)
6
+ @parent, @key = parent, key
7
+ @redis = get_app.redis
8
+ @logger = get_app.logger
9
+
10
+ super(parent, :style => LC_REPORT)
11
+
12
+ setup
13
+ set_elements(elements)
14
+ end
15
+
16
+ def setup
17
+ insert_column(0, 'Elements')
18
+ set_column_width(LIST_AUTOSIZE, -1)
19
+ end
20
+
21
+ def set_elements(elements)
22
+ delete_all_items
23
+ i = 0
24
+ elements.each { |element| insert_item(i, element); i += 1 }
25
+ @elements = elements
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,44 @@
1
+ module Rediscover
2
+ module Panel
3
+ class Browser < Wx::SplitterWindow
4
+ include Wx
5
+
6
+ def initialize(parent)
7
+ @parent = parent
8
+ super(@parent, -1)
9
+
10
+ @redis = get_app.redis
11
+ @logger = get_app.logger
12
+
13
+ @key_list_panel = Panel::KeyList.new(self)
14
+ @key_list_panel.on_edit { |key, type, item| edit(key, type, item)}
15
+
16
+ init(@key_list_panel) # just show the key list initially
17
+ end
18
+
19
+ def edit(key, type, item)
20
+ unsplit(@view_panel) if @view_panel
21
+
22
+ @view_panel = get_view_panel(key, type)
23
+ @view_panel.on_save { @key_list_panel.refresh(item) }
24
+ @view_panel.on_close { unsplit(@view_panel) }
25
+
26
+ split_horizontally(@key_list_panel, @view_panel)
27
+ end
28
+
29
+ def get_view_panel(key, type)
30
+ case type
31
+ when 'string' then return Panel::StringView.new(self, key)
32
+ when 'set' then return Panel::SetView.new(self, key)
33
+ when 'zset' then return Panel::SortedSetView.new(self, key)
34
+ when 'list' then return Panel::ListView.new(self, key)
35
+ end
36
+ end
37
+
38
+ def on_status_change(&block)
39
+ @key_list_panel.on_status_change { |status| block.call(status) }
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,89 @@
1
+ require 'rediscover/key_list_ctrl'
2
+
3
+ module Rediscover
4
+ module Panel
5
+ class KeyList < Wx::Panel
6
+ include Wx
7
+ extend Forwardable
8
+
9
+ def_delegators :@key_list, :on_edit
10
+
11
+ def initialize(parent)
12
+ @parent = parent
13
+ super(@parent, -1, :style => SUNKEN_BORDER)
14
+
15
+ @redis = get_app.redis
16
+ @logger = get_app.logger
17
+ @key_pattern = '*'
18
+
19
+ setup_sizer
20
+ setup_tool_bar
21
+ setup_key_browser
22
+ setup_key_shortcuts
23
+ end
24
+
25
+ def setup_sizer
26
+ @sizer = BoxSizer.new(VERTICAL)
27
+ set_sizer(@sizer)
28
+ end
29
+
30
+ def setup_tool_bar
31
+ @tool_bar_sizer = BoxSizer.new(HORIZONTAL)
32
+ @sizer.add_item(@tool_bar_sizer)
33
+
34
+ @add_button = Button.new(self, ID_ADD)
35
+ evt_button(@add_button) do
36
+ create_key_frame = Rediscover::Frame::CreateKey.new(self)
37
+ create_key_frame.on_create { refresh }
38
+ end
39
+
40
+ @refresh_button = Button.new(self, ID_REFRESH)
41
+ evt_button @refresh_button, :refresh
42
+
43
+ # filter input and button
44
+ @filter_textbox = TextCtrl.new(self,
45
+ :style => TE_PROCESS_ENTER,
46
+ :size => Size.new(200, -1))
47
+ evt_text_enter @filter_textbox, :filter # filter when enter is pressed in the textbox
48
+ @filter_button = Button.new(self, :label => 'Filter')
49
+ evt_button @filter_button, :filter # filter when button is pressed
50
+
51
+ # add elements to tool bar
52
+ @tool_bar_sizer.add_item(@add_button, :flag => ALL, :border => 1)
53
+ @tool_bar_sizer.add_item(@refresh_button, :flag => ALL, :border => 1)
54
+ @tool_bar_sizer.add_item(@filter_textbox, :flag => ALL, :border => 1)
55
+ @tool_bar_sizer.add_item(@filter_button, :flag => ALL, :border => 1)
56
+ end
57
+
58
+ def setup_key_shortcuts
59
+ evt_key_up { |event| refresh if event.get_key_code == K_F5 }
60
+ end
61
+
62
+ def setup_key_browser
63
+ @key_list = KeyListCtrl.new(self)
64
+ @sizer.add(@key_list, 1, EXPAND)
65
+ @key_list.on_get_keys { @redis.keys(@key_pattern).sort }
66
+ @key_list.update
67
+ end
68
+
69
+ def refresh(item = nil)
70
+ if(item)
71
+ @key_list.refresh_item(item)
72
+ else
73
+ @key_list.update
74
+ end
75
+ end
76
+
77
+ def filter
78
+ @key_pattern = @filter_textbox.get_value.strip
79
+ @key_pattern = '*' if @key_pattern.nil? or @key_pattern == ''
80
+ refresh
81
+ end
82
+
83
+ def on_status_change(&block)
84
+ @key_list.on_status_change { |status| block.call(status) }
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,72 @@
1
+ module Rediscover
2
+ module Panel
3
+ class ListView < Wx::Panel
4
+ include Wx
5
+ include KeyViewer
6
+
7
+ def initialize(parent, key)
8
+ @parent, @key = parent, key
9
+ @redis = get_app.redis
10
+ @logger = get_app.logger
11
+
12
+ super(@parent, -1, :style => SUNKEN_BORDER)
13
+
14
+ setup
15
+ end
16
+
17
+ def setup
18
+ members = @redis.lrange(@key, 0, -1)
19
+
20
+ @sizer = BoxSizer.new(VERTICAL)
21
+ set_sizer(@sizer)
22
+
23
+ @key_label = StaticText.new(self, :label => "Key: #{@key}")
24
+
25
+ @element_list = ListElementList.new(self, @key, members)
26
+
27
+ @button_sizer = BoxSizer.new(HORIZONTAL)
28
+
29
+ @lpush_button = Button.new(self, :label => 'Left Push')
30
+ evt_button(@lpush_button) { push(:lpush) }
31
+
32
+ @rpush_button = Button.new(self, :label => 'Right Push')
33
+ evt_button(@rpush_button) { push(:rpush) }
34
+
35
+ @lpop_button = Button.new(self, :label => 'Left Pop')
36
+ evt_button(@lpop_button) { pop(:lpop) }
37
+
38
+ @rpop_button = Button.new(self, :label => 'Right Pop')
39
+ evt_button(@rpop_button) { pop(:rpop) }
40
+
41
+ @close_button = Button.new(self, :label => 'Close')
42
+ evt_button @close_button, :do_on_close
43
+
44
+ @sizer.add_item(@key_label, :flag => ALL, :border => 2)
45
+ @sizer.add_item(@element_list, :proportion => 1, :flag => EXPAND|ALL, :border => 2)
46
+ @sizer.add_item(@button_sizer)
47
+
48
+ @button_sizer.add_item(@lpush_button, :flag => ALL, :border => 2)
49
+ @button_sizer.add_item(@rpush_button, :flag => ALL, :border => 2)
50
+ @button_sizer.add_item(@lpop_button, :flag => ALL, :border => 2)
51
+ @button_sizer.add_item(@rpop_button, :flag => ALL, :border => 2)
52
+ @button_sizer.add_item(@close_button, :flag => ALL, :border => 2)
53
+ end
54
+
55
+ def pop(dir = :lpop)
56
+ @redis.send(dir, @key)
57
+ @element_list.set_elements(@redis.lrange(@key, 0, -1))
58
+ do_on_save
59
+ end
60
+
61
+ def push(dir = :lpush)
62
+ @add_dlg = TextEntryDialog.new(self, 'Enter a new element:', 'Add Element')
63
+ if @add_dlg.show_modal == ID_OK
64
+ @redis.send(dir, @key, @add_dlg.get_value)
65
+ @element_list.set_elements(@redis.lrange(@key, 0, -1))
66
+ do_on_save
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,42 @@
1
+ module Rediscover
2
+ module Panel
3
+ class Server < Wx::Panel
4
+ include Wx
5
+
6
+ REFRESH_INTERVAL = 5000
7
+
8
+ def initialize(parent)
9
+ @parent = parent
10
+ super(@parent, -1)
11
+
12
+ @redis = get_app.redis
13
+ @logger = get_app.logger
14
+
15
+ setup_sizer
16
+ setup_server_info
17
+ end
18
+
19
+ def setup_sizer
20
+ @sizer = BoxSizer.new(VERTICAL)
21
+ set_sizer(@sizer)
22
+ end
23
+
24
+ def setup_server_info
25
+ @server_info_text = StaticText.new(self, :label => get_info)
26
+ @sizer.add_item(@server_info_text)
27
+ timer = Timer.new(self)
28
+ evt_timer(timer.id) { refresh }
29
+ timer.start(REFRESH_INTERVAL)
30
+ end
31
+
32
+ def get_info
33
+ @redis.info.map { |key, value| "#{key}: #{value}" }.sort.join("\n")
34
+ end
35
+
36
+ def refresh
37
+ @server_info_text.set_label(get_info)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,55 @@
1
+ module Rediscover
2
+ module Panel
3
+ class SetView < Wx::Panel
4
+ include Wx
5
+ include KeyViewer
6
+
7
+ def initialize(parent, key)
8
+ @parent, @key = parent, key
9
+ @redis = get_app.redis
10
+ @logger = get_app.logger
11
+
12
+ super(@parent, -1, :style => SUNKEN_BORDER)
13
+
14
+ setup
15
+ end
16
+
17
+ def setup
18
+ members = @redis.smembers(@key)
19
+
20
+ @sizer = BoxSizer.new(VERTICAL)
21
+ set_sizer(@sizer)
22
+
23
+ @key_label = StaticText.new(self, :label => "Key: #{@key}")
24
+
25
+ @element_list = SetElementList.new(self, @key, members)
26
+ @element_list.on_save { do_on_save }
27
+
28
+ @button_sizer = BoxSizer.new(HORIZONTAL)
29
+
30
+ @add_button = Button.new(self, :label => 'Add Element')
31
+ evt_button @add_button, :add
32
+
33
+ @close_button = Button.new(self, :label => 'Close')
34
+ evt_button @close_button, :do_on_close
35
+
36
+ @sizer.add_item(@key_label, :flag => ALL, :border => 2)
37
+ @sizer.add_item(@element_list, :proportion => 1, :flag => EXPAND|ALL, :border => 2)
38
+ @sizer.add_item(@button_sizer)
39
+
40
+ @button_sizer.add_item(@add_button, :flag => ALL, :border => 2)
41
+ @button_sizer.add_item(@close_button, :flag => ALL, :border => 2)
42
+ end
43
+
44
+ def add
45
+ @add_dlg = TextEntryDialog.new(self, 'Enter a new element:', 'Add Element')
46
+ if @add_dlg.show_modal == ID_OK
47
+ @redis.sadd(@key, @add_dlg.get_value)
48
+ @element_list.set_elements(@redis.smembers(@key))
49
+ do_on_save
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,55 @@
1
+ module Rediscover
2
+ module Panel
3
+ class SortedSetView < Wx::Panel
4
+ include Wx
5
+ include KeyViewer
6
+
7
+ def initialize(parent, key)
8
+ @parent, @key = parent, key
9
+ @redis = get_app.redis
10
+ @logger = get_app.logger
11
+
12
+ super(@parent, -1, :style => SUNKEN_BORDER)
13
+
14
+ setup
15
+ end
16
+
17
+ def setup
18
+ members = @redis.zrange(@key, 0, -1)
19
+
20
+ @sizer = BoxSizer.new(VERTICAL)
21
+ set_sizer(@sizer)
22
+
23
+ @key_label = StaticText.new(self, :label => "Key: #{@key}")
24
+
25
+ @element_list = SortedSetElementList.new(self, @key, members)
26
+ @element_list.on_save { do_on_save }
27
+
28
+ @button_sizer = BoxSizer.new(HORIZONTAL)
29
+
30
+ @add_button = Button.new(self, :label => 'Add Element')
31
+ evt_button @add_button, :add
32
+
33
+ @close_button = Button.new(self, :label => 'Close')
34
+ evt_button @close_button, :do_on_close
35
+
36
+ @sizer.add_item(@key_label, :flag => ALL, :border => 2)
37
+ @sizer.add_item(@element_list, :proportion => 1, :flag => EXPAND|ALL, :border => 2)
38
+ @sizer.add_item(@button_sizer)
39
+
40
+ @button_sizer.add_item(@add_button, :flag => ALL, :border => 2)
41
+ @button_sizer.add_item(@close_button, :flag => ALL, :border => 2)
42
+ end
43
+
44
+ def add
45
+ @add_dlg = TextEntryDialog.new(self, 'Enter a new element:', 'Add Element')
46
+ if @add_dlg.show_modal == ID_OK
47
+ @redis.zadd(@key, 0, @add_dlg.get_value) # TODO get a priority score
48
+ @element_list.set_elements(@redis.zrange(@key, 0, -1))
49
+ do_on_save
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,50 @@
1
+ module Rediscover
2
+ module Panel
3
+ class StringView < Wx::Panel
4
+ include Wx
5
+ include KeyViewer
6
+
7
+ def initialize(parent, key)
8
+ @parent = parent
9
+ super(@parent, -1, :style => SUNKEN_BORDER)
10
+
11
+ @key = key
12
+ @redis = get_app.redis
13
+
14
+ setup
15
+ end
16
+
17
+ def setup
18
+ value = @redis[@key]
19
+
20
+ @sizer = BoxSizer.new(VERTICAL)
21
+ set_sizer(@sizer)
22
+
23
+ @key_label = StaticText.new(self, :label => "Key: #{@key}")
24
+
25
+ @value_textbox = TextCtrl.new(self, :value => value, :style => TE_MULTILINE|TE_DONTWRAP)
26
+
27
+ @button_sizer = BoxSizer.new(HORIZONTAL)
28
+
29
+ @save_button = Button.new(self, :label => 'Save')
30
+ evt_button @save_button, :save
31
+
32
+ @close_button = Button.new(self, :label => 'Close')
33
+ evt_button @close_button, :do_on_close
34
+
35
+ @sizer.add_item(@key_label, :flag => ALL, :border => 2)
36
+ @sizer.add_item(@value_textbox, :proportion => 1, :flag => EXPAND|ALL, :border => 2)
37
+ @sizer.add_item(@button_sizer)
38
+
39
+ @button_sizer.add_item(@save_button, :flag => ALL, :border => 2)
40
+ @button_sizer.add_item(@close_button, :flag => ALL, :border => 2)
41
+ end
42
+
43
+ def save
44
+ @redis[@key] = @value_textbox.get_value
45
+ do_on_save
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,70 @@
1
+ module Rediscover
2
+ class SetElementList < Wx::ListCtrl
3
+ include Wx
4
+
5
+ def initialize(parent, key, elements)
6
+ @parent, @key = parent, key
7
+ @redis = get_app.redis
8
+ @logger = get_app.logger
9
+
10
+ super(parent, :style => LC_REPORT)
11
+
12
+ setup
13
+ set_elements(elements)
14
+ end
15
+
16
+ def setup
17
+ insert_column(0, 'Elements')
18
+ set_column_width(LIST_AUTOSIZE, -1)
19
+ evt_list_item_right_click self, :list_item_right_click_evt
20
+ end
21
+
22
+ def set_elements(elements)
23
+ delete_all_items
24
+ i = 0
25
+ elements.each { |element| insert_item(i, element); i += 1 }
26
+ @elements = elements
27
+ end
28
+
29
+ def delete(selections)
30
+ delete_elements = selections.map { |index| @elements[index] }
31
+ delete_elements.each do |element|
32
+ @elements.delete(element)
33
+ @redis.srem(@key, element)
34
+ delete_item(find_item(0, element))
35
+ end
36
+ update
37
+ do_on_save
38
+ end
39
+
40
+ def list_item_right_click_evt(event)
41
+ menu = get_ctx_menu_for_selections(get_selections)
42
+ popup_menu(menu, event.get_point) if menu
43
+ end
44
+
45
+ def get_ctx_menu_for_selections(selections)
46
+ return nil if selections.empty?
47
+ @ctx_menu = Menu.new
48
+
49
+ # delete menu item
50
+ @ctx_delete_item = MenuItem.new(@ctx_menu, -1, 'Delete')
51
+ evt_menu(@ctx_delete_item) do
52
+ if ID_YES == Dialog::Confirm.new(self, 'Really delete selected element(s)?', 'Really delete?').show_modal
53
+ delete(selections)
54
+ end
55
+ end
56
+
57
+ @ctx_menu.append_item(@ctx_delete_item)
58
+ @ctx_menu
59
+ end
60
+
61
+ def on_save(&block)
62
+ @on_save_block = block
63
+ end
64
+
65
+ def do_on_save
66
+ @on_save_block.call() if @on_save_block
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,70 @@
1
+ module Rediscover
2
+ class SortedSetElementList < Wx::ListCtrl
3
+ include Wx
4
+
5
+ def initialize(parent, key, elements)
6
+ @parent, @key = parent, key
7
+ @redis = get_app.redis
8
+ @logger = get_app.logger
9
+
10
+ super(parent, :style => LC_REPORT)
11
+
12
+ setup
13
+ set_elements(elements)
14
+ end
15
+
16
+ def setup
17
+ insert_column(0, 'Elements')
18
+ set_column_width(LIST_AUTOSIZE, -1)
19
+ evt_list_item_right_click self, :list_item_right_click_evt
20
+ end
21
+
22
+ def set_elements(elements)
23
+ delete_all_items
24
+ i = 0
25
+ elements.each { |element| insert_item(i, element); i += 1 }
26
+ @elements = elements
27
+ end
28
+
29
+ def delete(selections)
30
+ delete_elements = selections.map { |index| @elements[index] }
31
+ delete_elements.each do |element|
32
+ @elements.delete(element)
33
+ @redis.zrem(@key, element)
34
+ delete_item(find_item(0, element))
35
+ end
36
+ update
37
+ do_on_save
38
+ end
39
+
40
+ def list_item_right_click_evt(event)
41
+ menu = get_ctx_menu_for_selections(get_selections)
42
+ popup_menu(menu, event.get_point) if menu
43
+ end
44
+
45
+ def get_ctx_menu_for_selections(selections)
46
+ return nil if selections.empty?
47
+ @ctx_menu = Menu.new
48
+
49
+ # delete menu item
50
+ @ctx_delete_item = MenuItem.new(@ctx_menu, -1, 'Delete')
51
+ evt_menu(@ctx_delete_item) do
52
+ if ID_YES == Dialog::Confirm.new(self, 'Really delete selected element(s)?', 'Really delete?').show_modal
53
+ delete(selections)
54
+ end
55
+ end
56
+
57
+ @ctx_menu.append_item(@ctx_delete_item)
58
+ @ctx_menu
59
+ end
60
+
61
+ def on_save(&block)
62
+ @on_save_block = block
63
+ end
64
+
65
+ def do_on_save
66
+ @on_save_block.call() if @on_save_block
67
+ end
68
+
69
+ end
70
+ end
data/lib/rediscover.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'wx'
3
+ require 'redis'
4
+ require 'rediscover/app'
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rediscover
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Chris Kite
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-03-07 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: wxruby
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.0.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: redis
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.2
34
+ version:
35
+ description:
36
+ email:
37
+ executables:
38
+ - rediscover
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - lib/rediscover.rb
45
+ - lib/rediscover/key_list_ctrl.rb
46
+ - lib/rediscover/sorted_set_element_list.rb
47
+ - lib/rediscover/set_element_list.rb
48
+ - lib/rediscover/key_viewer.rb
49
+ - lib/rediscover/dialog/confirm.rb
50
+ - lib/rediscover/dialog/error.rb
51
+ - lib/rediscover/icon.rb
52
+ - lib/rediscover/panel/browser.rb
53
+ - lib/rediscover/panel/server.rb
54
+ - lib/rediscover/panel/list_view.rb
55
+ - lib/rediscover/panel/sorted_set_view.rb
56
+ - lib/rediscover/panel/string_view.rb
57
+ - lib/rediscover/panel/set_view.rb
58
+ - lib/rediscover/panel/key_list.rb
59
+ - lib/rediscover/frame/main.rb
60
+ - lib/rediscover/frame/create_key.rb
61
+ - lib/rediscover/frame/connect.rb
62
+ - lib/rediscover/exception_handler.rb
63
+ - lib/rediscover/list_element_list.rb
64
+ - lib/rediscover/icons/server_connect.png
65
+ - lib/rediscover/icons/refresh.png
66
+ - lib/rediscover/icons/key_add.png
67
+ - lib/rediscover/icons/application.png
68
+ - lib/rediscover/icons/add.png
69
+ - lib/rediscover/app.rb
70
+ - bin/rediscover
71
+ has_rdoc: true
72
+ homepage: http://github.com/chriskite/rediscover
73
+ licenses: []
74
+
75
+ post_install_message:
76
+ rdoc_options: []
77
+
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: "0"
85
+ version:
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "0"
91
+ version:
92
+ requirements: []
93
+
94
+ rubyforge_project:
95
+ rubygems_version: 1.3.5
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: Redis GUI
99
+ test_files: []
100
+