rbcurse 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/CHANGELOG +33 -0
  2. data/README.markdown +7 -1
  3. data/TODO2.txt +21 -15
  4. data/VERSION +1 -1
  5. data/examples/abasiclist.rb +2 -2
  6. data/examples/alpmenu.rb +1 -1
  7. data/examples/app.rb +0 -1
  8. data/examples/appdirtree.rb +4 -2
  9. data/examples/appemail.rb +7 -3
  10. data/examples/appemaillb.rb +1 -1
  11. data/examples/appgcompose.rb +2 -2
  12. data/examples/appgmail.rb +1 -1
  13. data/examples/appmethods.rb +20 -2
  14. data/examples/atree.rb +9 -1
  15. data/examples/dbdemo.rb +460 -0
  16. data/examples/dirtree.rb +1 -1
  17. data/examples/menu1.rb +37 -5
  18. data/examples/multispl.rb +1 -1
  19. data/examples/rfe.rb +9 -2
  20. data/examples/splitp.rb +1 -1
  21. data/examples/sqlc.rb +6 -10
  22. data/examples/sqlm.rb +2 -20
  23. data/examples/sqlt.rb +408 -0
  24. data/examples/term2.rb +1 -1
  25. data/examples/test2.rb +169 -97
  26. data/examples/testapp.rb +1 -1
  27. data/examples/testapp2.rb +1 -1
  28. data/examples/testkeypress.rb +4 -2
  29. data/examples/testtable.rb +6 -0
  30. data/examples/testtpane.rb +35 -23
  31. data/examples/testvimsplit.rb +3 -2
  32. data/lib/rbcurse.rb +1 -1
  33. data/lib/rbcurse/action.rb +8 -0
  34. data/lib/rbcurse/app.rb +39 -23
  35. data/lib/rbcurse/extras/bottomline.rb +101 -13
  36. data/lib/rbcurse/extras/directorylist.rb +14 -5
  37. data/lib/rbcurse/extras/divider.rb +1 -1
  38. data/lib/rbcurse/extras/listselectable.rb +42 -8
  39. data/lib/rbcurse/extras/masterdetail.rb +2 -2
  40. data/lib/rbcurse/extras/scrollbar.rb +11 -2
  41. data/lib/rbcurse/extras/statusline.rb +56 -0
  42. data/lib/rbcurse/extras/stdscrwindow.rb +11 -0
  43. data/lib/rbcurse/extras/tabular.rb +2 -1
  44. data/lib/rbcurse/extras/tabularwidget.rb +60 -17
  45. data/lib/rbcurse/extras/viewer.rb +16 -4
  46. data/lib/rbcurse/keylabelprinter.rb +34 -4
  47. data/lib/rbcurse/listeditable.rb +5 -1
  48. data/lib/rbcurse/listkeys.rb +1 -1
  49. data/lib/rbcurse/listscrollable.rb +15 -8
  50. data/lib/rbcurse/rbasiclistbox.rb +44 -23
  51. data/lib/rbcurse/rcommandwindow.rb +8 -14
  52. data/lib/rbcurse/rdialogs.rb +187 -2
  53. data/lib/rbcurse/rlistbox.rb +38 -19
  54. data/lib/rbcurse/rmenu.rb +313 -93
  55. data/lib/rbcurse/rmessagebox.rb +3 -2
  56. data/lib/rbcurse/rmulticontainer.rb +5 -3
  57. data/lib/rbcurse/rmultisplit.rb +2 -11
  58. data/lib/rbcurse/rmultitextview.rb +4 -5
  59. data/lib/rbcurse/rtabbedpane.rb +223 -69
  60. data/lib/rbcurse/rtable.rb +6 -10
  61. data/lib/rbcurse/rtextarea.rb +57 -36
  62. data/lib/rbcurse/rtextview.rb +12 -15
  63. data/lib/rbcurse/rtree.rb +79 -22
  64. data/lib/rbcurse/rvimsplit.rb +16 -25
  65. data/lib/rbcurse/rwidget.rb +376 -523
  66. data/lib/rbcurse/tree/treecellrenderer.rb +24 -11
  67. data/lib/rbcurse/tree/treemodel.rb +1 -1
  68. data/lib/ver/window.rb +130 -66
  69. metadata +5 -3
  70. data/examples/term.rb +0 -48
data/examples/dirtree.rb CHANGED
@@ -11,7 +11,7 @@ def _directories wd
11
11
  return ent
12
12
  end
13
13
  App.new do
14
- header = app_header "rbcurse 1.2.0", :text_center => "Yet Another File Manager", :text_right =>"Directory Lister", :color => :black, :bgcolor => :white#, :attr => Ncurses::A_BLINK
14
+ header = app_header "rbcurse #{Rbcurse::VERSION}", :text_center => "Yet Another File Manager", :text_right =>"Directory Lister", :color => :black, :bgcolor => :white#, :attr => Ncurses::A_BLINK
15
15
  message "Press Enter to expand/collapse"
16
16
 
17
17
  pwd = Dir.getwd
data/examples/menu1.rb CHANGED
@@ -4,7 +4,9 @@ require 'rbcurse/app'
4
4
  App.new do
5
5
  #title "Demo of Menu - rbcurse"
6
6
  #subtitle "Hit F1 to quit, F2 for menubar toggle"
7
- header = app_header "rbcurse 1.2.0", :text_center => "Menubar Demo", :text_right =>"enabled"
7
+ header = app_header "rbcurse #{Rbcurse::VERSION}", :text_center => "Menubar Demo", :text_right =>"enabled"
8
+ form = @form
9
+ mylabel = "a field"
8
10
 
9
11
  # TODO accelerators and
10
12
  # getting a handle for later use
@@ -12,13 +14,36 @@ require 'rbcurse/app'
12
14
  #@toggle_key=KEY_F2
13
15
  menu "File" do
14
16
  item "Open", "O" do
15
- command do
17
+ accelerator "Ctrl-O"
18
+ command do
16
19
  alert "HA!! you wanted to open a file?"
17
20
  end
18
21
  end
22
+ menu "QuickOpen" do
23
+ item_list do
24
+ Dir.glob("*.rb")
25
+ end
26
+ command do |menuitem, text|
27
+ #alert " We gots #{text} "
28
+ fld = form.by_name[mylabel]
29
+ fld.text =text
30
+ end
31
+ end
32
+ menu "Close" do
33
+ item_list do
34
+ Dir.glob("t*.rb")
35
+ end
36
+ end
19
37
  item "New", "N"
20
38
  separator
21
- item "Close", "C"
39
+ item "Exit", "x" do
40
+ command do
41
+ throw(:close)
42
+ end
43
+ end
44
+ item "Cancel Menu" do
45
+ accelerator "Ctrl-g"
46
+ end
22
47
 
23
48
  end # menu
24
49
  menu "Window" do
@@ -31,13 +56,20 @@ require 'rbcurse/app'
31
56
  alert "You clickses on Less"
32
57
  end
33
58
  end
59
+ menu "Size" do
60
+ item "Zoom", "Z"
61
+ item "Maximize", "X"
62
+ item "Minimize", "N"
63
+ end
34
64
  end
35
65
  end
36
66
  end # menubar
37
67
  mb.toggle_key = FFI::NCurses::KEY_F2
68
+ mb.color = :white
69
+ mb.bgcolor = :blue
38
70
  @form.set_menu_bar mb
39
71
  stack :margin_top => 10, :margin => 5 do
40
- field "a field", :attr => 'reverse', :block_event => :CHANGE do |e|
72
+ field mylabel, :attr => 'reverse', :block_event => :CHANGE do |e|
41
73
  message e.to_s
42
74
 
43
75
  case e.text
@@ -53,7 +85,7 @@ require 'rbcurse/app'
53
85
  end
54
86
  @adock = nil
55
87
  keyarray = [
56
- ["F1" , "Exit"], nil,
88
+ ["F10" , "Exit"], nil,
57
89
  ["F2", "Menu"], nil,
58
90
  ["M-e", "Disable"], ["M-x", "XXXX"],
59
91
  ["C-?", "Help"], nil
data/examples/multispl.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rbcurse/app'
2
2
 
3
3
  App.new do
4
- header = app_header "rbcurse 1.2.0", :text_center => "MultiSplit Demo", :text_right =>"ColumnBrowse pattern"
4
+ header = app_header "rbcurse #{Rbcurse::VERSION}", :text_center => "MultiSplit Demo", :text_right =>"ColumnBrowse pattern"
5
5
  message_row(27)
6
6
  message "<TAB> and <BTAB> "
7
7
  oo = :HORIZONTAL_SPLIT
data/examples/rfe.rb CHANGED
@@ -468,15 +468,20 @@ class RFe
468
468
  end
469
469
  end
470
470
  ## TODO : make this separate and callable with its own keylabels
471
- def view content=nil
471
+ def view content=nil # can throw IO errors
472
472
  require 'rbcurse/rtextview'
473
473
  wt = 0
474
474
  wl = 0
475
475
  wh = Ncurses.LINES-wt
476
476
  ww = Ncurses.COLS-wl
477
477
  if content.nil?
478
+ begin
478
479
  fp = @current_list.filepath
479
480
  content = get_contents(fp)
481
+ rescue => err
482
+ alert err.to_s
483
+ return
484
+ end
480
485
  else
481
486
  fp=""
482
487
  end
@@ -506,6 +511,8 @@ class RFe
506
511
  @v_form.repaint
507
512
  ##@v_window.wrefresh
508
513
  end
514
+ rescue => err
515
+ alert err.to_s
509
516
  ensure
510
517
  @v_window.destroy if !@v_window.nil?
511
518
  end
@@ -544,7 +551,7 @@ class RFe
544
551
  str= "view #{fp}"
545
552
  #if confirm("#{str}")==:YES
546
553
  $log.debug " VIEW #{fp}"
547
- view
554
+ view
548
555
  #end
549
556
  when 'r'
550
557
  str= "ruby #{fn}"
data/examples/splitp.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rbcurse/app'
2
2
 
3
3
  App.new do
4
- header = app_header "rbcurse 1.2.0", :text_center => "Splitpane Demo", :text_right =>""
4
+ header = app_header "rbcurse #{Rbcurse::VERSION}", :text_center => "Splitpane Demo", :text_right =>""
5
5
  message_row(27)
6
6
  message "<TAB> between outer panes, Alt-W between inner tabs, Alt-TAb to exit Splitpane"
7
7
 
data/examples/sqlc.rb CHANGED
@@ -1,13 +1,14 @@
1
1
  ## rkumar, 2009
2
- #DEPRECATED. See sqlm.rb
2
+ #DEPRECATED. See sqlm.rb or sqlt.rb in which i use a TabularWidget instead of Table.
3
3
  #AVOID USING TabbedPane till its rewritten 1.3.2 or so.
4
- #You will have to press a downarrow or any key if the pane goes blank.
4
+
5
5
  #
6
6
  ############ WARNING ##############################################################
7
7
  # TabbedPanes seem to have stopped displaying at some points
8
8
  # after moving to FFI-Ncurses. And i've not been able to locate the point.
9
9
  # This is one subtle difference between ncurses and ffi-ncurses.
10
10
  # So i will scrap this and do a fresh clean rewrite of TabbedPane class.
11
+ # OKAY I've got them fixed.
11
12
  #
12
13
  ###################################################################################
13
14
  # Sample demo of various widgets and their interaction.
@@ -17,11 +18,9 @@
17
18
  # Please see bind_key statements in this app for some key bindings in table.
18
19
  # There are also key bindings in tabbedpanes and textarea's that will help alot.
19
20
  # This demo uses a tabbedpane so we can have the results of many sql statements and not
20
- # need to keep reissuing. The tabbed pane SUCKS, if you get in when not populated
21
- # you GET STUCK so press Alt-C to get out.
21
+ # need to keep reissuing. Its better to use a multitextview or multicontainer
22
+ # than a tabbedpane for such use.
22
23
  #
23
- require 'rubygems'
24
- #require 'ncurses' # FFI
25
24
  require 'logger'
26
25
  require 'sqlite3'
27
26
  require 'rbcurse'
@@ -168,7 +167,7 @@ class Sqlc
168
167
  end
169
168
  def run
170
169
  title = "rbcurse"
171
- @header = ApplicationHeader.new @form, title, {:text2=>"Demo", :text_center=>"SQL Client ***DEPRECATED use sqlm.rb ******"}
170
+ @header = ApplicationHeader.new @form, title, {:text2=>"Demo", :text_center=>"SQL Client using TabbedPane and Table (see sqlm.rb instead) "}
172
171
  status_row = RubyCurses::Label.new @form, {'text' => "", :row => Ncurses.LINES-4, :col => 0, :display_length=>70}
173
172
  @status_row = status_row
174
173
  # setting ENTER across all objects on a form
@@ -405,9 +404,6 @@ class Sqlc
405
404
  table_ht = 15
406
405
  atable = Table.new do
407
406
  name "sqltable#{counter}"
408
- #cell_editing_allowed true
409
- #editing_policy :EDITING_AUTO
410
- #help_text "M-Tab for next field, M-8 amd M-7 for horiz scroll, + to resize, C-q quit"
411
407
  help_text "M-Tab for next field, C-q quit"
412
408
  end
413
409
  atable.bind(:TABLE_TRAVERSAL_EVENT){|e| @header.text_right "Row #{e.newrow+1} of #{atable.row_count}" }
data/examples/sqlm.rb CHANGED
@@ -125,24 +125,6 @@ class Datasource
125
125
  end
126
126
 
127
127
  end
128
- def get_key_labels
129
- key_labels = [
130
- ['C-q', 'Exit'], nil,
131
- ['M-s', 'Save'], ['M-m', 'Move']
132
- ]
133
- return key_labels
134
- end
135
- def get_key_labels_table
136
- key_labels = [
137
- ['M-n','NewRow'], ['M-d','DelRow'],
138
- ['C-x','Select'], nil,
139
- ['M-0', 'Top'], ['M-9', 'End'],
140
- ['C-p', 'PgUp'], ['C-n', 'PgDn'],
141
- ['M-Tab','Nxt Fld'], ['Tab','Nxt Col'],
142
- ['+','Widen'], ['-','Narrow']
143
- ]
144
- return key_labels
145
- end
146
128
  class Sqlc
147
129
  def initialize
148
130
  @window = VER::Window.root_window
@@ -175,7 +157,7 @@ class Sqlc
175
157
  height ta_ht
176
158
  title "Sql Query"
177
159
  title_attrib (Ncurses::A_REVERSE | Ncurses::A_BOLD)
178
- help_text "Enter query and press Run or Meta-r"
160
+ help_text "Enter query and press Run or Meta-r. Ctrl-q to quit"
179
161
  end
180
162
  sqlarea << "select * from contacts"
181
163
  buttrow = r+ta_ht+1 #Ncurses.LINES-4
@@ -352,7 +334,7 @@ class Sqlc
352
334
  while((ch = @window.getchar()) != ?\C-q.getbyte(0) )
353
335
  break if ch == KEY_F1
354
336
  s = keycode_tos ch
355
- status_row.text = "Pressed #{ch}, #{s}. C-q to quit, Alt-Tab to exit table, Alt-: for buffers "
337
+ status_row.text = "C-q to quit, Alt-Tab to exit table, Alt-: for buffers. Alt-N/P next/previous "
356
338
  @form.handle_key(ch)
357
339
 
358
340
  @form.repaint
data/examples/sqlt.rb ADDED
@@ -0,0 +1,408 @@
1
+ ## rkumar, 2009
2
+ #AVOID USING TabbedPane till its rewritten 1.3.2 or so.
3
+ #You will have to press a downarrow or any key if the pane goes blank.
4
+ #
5
+ # Sample demo of various widgets and their interaction.
6
+ # This is a simple sql client which allows table / column selection, construction
7
+ # of SQL queries, and multiple resultsets.
8
+ # Use C-q to quit, Alt-Tab to move out of Table to next field.
9
+ # Please see bind_key statements in this app for some key bindings in table.
10
+ # There are also key bindings in tabbedpanes and textarea's that will help alot.
11
+ # This demo uses a tabbedpane so we can have the results of many sql statements and not
12
+ # need to keep reissuing. The tabbed pane SUCKS, if you get in when not populated
13
+ # you GET STUCK so press Alt-C to get out.
14
+ #
15
+ require 'logger'
16
+ require 'sqlite3'
17
+ require 'rbcurse'
18
+ require 'rbcurse/rcombo'
19
+ require 'rbcurse/rtextarea'
20
+ require 'rbcurse/rtable'
21
+ #require 'rbcurse/table/tablecellrenderer'
22
+ #require 'rbcurse/comboboxcellrenderer'
23
+ #require 'rbcurse/keylabelprinter'
24
+ require 'rbcurse/applicationheader'
25
+ require 'rbcurse/action' # not used here
26
+ require 'rbcurse/rtabbedpane'
27
+ require 'rbcurse/extras/tabularwidget'
28
+
29
+ # pls get testd.db from
30
+ # http://www.benegal.org/files/screen/testd.db
31
+ # or put some other sqlite3 db name there.
32
+ # or create using sqlite3 testd.db < data.txt
33
+
34
+ ## must give me @content, @columns, @datatypes (opt)
35
+ class Datasource
36
+ # attr_reader :field_length # specified by user, length of row in display table
37
+ attr_accessor :columns # names of columns in array
38
+ attr_accessor :datatypes # array of datatyps of columns required to align: int, real, float, smallint
39
+ attr_accessor :content # 2 dim data
40
+ attr_accessor :user_columns # columnnames provided by user, overrides what is generated for display
41
+ # attr_reader :sqlstring # specified by user
42
+
43
+ # constructor
44
+ def initialize(config={}, &block)
45
+ @content = []
46
+ @columns = nil # actual db columnnames -- needed to figure out datatypes
47
+ @user_columns = nil # user specified db columnnames, overrides what may be provided
48
+ @datatypes = nil
49
+ # @rows = nil
50
+ # @sqlstring = nil
51
+ # @command = nil
52
+
53
+ instance_eval(&block) if block_given?
54
+ end
55
+ def connect dbname
56
+ raise " #{dbname} does not exist. Please fetch from http://www.benegal.org/files/screen/testd.db" if !File.exists?(dbname)
57
+ @db = SQLite3::Database.new(dbname)
58
+ end
59
+ # get columns and datatypes, prefetch
60
+ def get_data command
61
+ @columns, *rows = @db.execute2(command)
62
+ $log.debug "XXX COLUMNS #{command} : #{@columns.count}: #{@columns} "
63
+ @content = rows
64
+ return nil if @content.nil? or @content[0].nil?
65
+ @datatypes = @content[0].types #if @datatypes.nil?
66
+ @command = command
67
+ return @content
68
+ end
69
+ def get_metadata table
70
+ get_data "select * from #{table} limit 1"
71
+ return @columns
72
+ end
73
+ ##
74
+ # returns columns_widths, and updates that variable
75
+ def estimate_column_widths tablewidth, columns
76
+ colwidths = {}
77
+ min_column_width = (tablewidth/columns.length) -1
78
+ $log.debug("min: #{min_column_width}, #{tablewidth}")
79
+ @content.each_with_index do |row, cix|
80
+ break if cix >= 20
81
+ row.each_index do |ix|
82
+ col = row[ix]
83
+ colwidths[ix] ||= 0
84
+ colwidths[ix] = [colwidths[ix], col.length].max
85
+ end
86
+ end
87
+ total = 0
88
+ colwidths.each_pair do |k,v|
89
+ name = columns[k.to_i]
90
+ colwidths[name] = v
91
+ total += v
92
+ end
93
+ colwidths["__TOTAL__"] = total
94
+ column_widths = colwidths
95
+ @max_data_widths = column_widths.dup
96
+
97
+ columns.each_with_index do | col, i|
98
+ if @datatypes[i].match(/(real|int)/) != nil
99
+ wid = column_widths[i]
100
+ # cw = [column_widths[i], [8,min_column_width].min].max
101
+ $log.debug("XXX #{wid}. #{columns[i].length}")
102
+ cw = [wid, columns[i].length].max
103
+ $log.debug("int #{col} #{column_widths[i]}, #{cw}")
104
+ elsif @datatypes[i].match(/(date)/) != nil
105
+ cw = [column_widths[i], [12,min_column_width].min].max
106
+ #cw = [12,min_column_width].min
107
+ $log.debug("date #{col} #{column_widths[i]}, #{cw}")
108
+ else
109
+ cw = [column_widths[i], min_column_width].max
110
+ if column_widths[i] <= col.length and col.length <= min_column_width
111
+ cw = col.length
112
+ end
113
+ $log.debug("else #{col} #{column_widths[i]}, #{col.length} #{cw}")
114
+ end
115
+ column_widths[i] = cw
116
+ total += cw
117
+ end
118
+ column_widths["__TOTAL__"] = total
119
+ $log.debug("Estimated col widths: #{column_widths.inspect}")
120
+ @column_widths = column_widths
121
+ return column_widths
122
+ end
123
+
124
+ # added to enable query form to allow movement into table only if
125
+ # there is data 2008-10-08 17:46
126
+ # returns number of rows fetched
127
+ def data_length
128
+ return @content.length
129
+ end
130
+
131
+ end
132
+ def get_key_labels
133
+ key_labels = [
134
+ ['C-q', 'Exit'], nil,
135
+ ['M-s', 'Save'], ['M-m', 'Move']
136
+ ]
137
+ return key_labels
138
+ end
139
+ def get_key_labels_table
140
+ key_labels = [
141
+ ['M-n','NewRow'], ['M-d','DelRow'],
142
+ ['C-x','Select'], nil,
143
+ ['M-0', 'Top'], ['M-9', 'End'],
144
+ ['C-p', 'PgUp'], ['C-n', 'PgDn'],
145
+ ['M-Tab','Nxt Fld'], ['Tab','Nxt Col'],
146
+ ['+','Widen'], ['-','Narrow']
147
+ ]
148
+ return key_labels
149
+ end
150
+ class Sqlc
151
+ def initialize
152
+ @window = VER::Window.root_window
153
+ $catch_alt_digits = false # we want to use Alt-1, 2 for tabs.
154
+ @form = Form.new @window
155
+ @tab_ctr = 0
156
+
157
+ @db = Datasource.new
158
+ @db.connect "testd.db"
159
+ end
160
+ def run
161
+ title = "rbcurse"
162
+ @header = ApplicationHeader.new @form, title, {:text2=>"Demo", :text_center=>"SQL Client using TabbedPane and TabularWidget (see sqlm.rb also) "}
163
+ status_row = RubyCurses::Label.new @form, {'text' => "", :row => Ncurses.LINES-4, :col => 0, :display_length=>70}
164
+ @status_row = status_row
165
+ # setting ENTER across all objects on a form
166
+ @form.bind(:ENTER) {|f| status_row.text = f.help_text unless f.help_text.nil? }
167
+ r = 1; c = 1;
168
+ @data = [ ["No data"] ]
169
+ data = @data
170
+ colnames = %w[ Result ]
171
+
172
+ ta_ht = 5
173
+ t_width = 78
174
+ sqlarea = TextArea.new @form do
175
+ name "sqlarea"
176
+ row r
177
+ col c
178
+ width t_width
179
+ height ta_ht
180
+ title "Sql Query"
181
+ title_attrib (Ncurses::A_REVERSE | Ncurses::A_BOLD)
182
+ help_text "Enter query and press Run or Meta-r"
183
+ end
184
+ sqlarea << "select * from contacts"
185
+ buttrow = r+ta_ht+1 #Ncurses.LINES-4
186
+ b_run = Button.new @form do
187
+ text "&Run"
188
+ row buttrow
189
+ col c
190
+ help_text "Run query"
191
+ end
192
+ ## We use Action to create a button: to test out ampersand with MI and Button
193
+ b_clear = Button.new @form do
194
+ #action new_act
195
+ text "&Clear"
196
+ row buttrow
197
+ col c+10
198
+ help_text "Clear query entry box "
199
+ end
200
+ b_clear.command {
201
+ sqlarea.remove_all
202
+ sqlarea.focus
203
+ }
204
+
205
+ # using ampersand to set mnemonic
206
+
207
+ b_construct = Button.new @form do
208
+ text "Constr&uct"
209
+ row buttrow
210
+ col c+25
211
+ help_text "Select a table, select columns and press this to construct an SQL"
212
+ end
213
+
214
+ Button.button_layout [b_run, b_clear, b_construct], buttrow, startcol=5, cols=Ncurses.COLS-1, gap=5
215
+
216
+ @tp = create_tabbed_pane @form, buttrow, t_width, c
217
+ @tp.show
218
+ @data = data
219
+
220
+ b_run.command {
221
+ query = sqlarea.get_text
222
+ run_query query
223
+ }
224
+ #
225
+ ## key bindings fo atable
226
+ # column widths
227
+ app = self
228
+
229
+
230
+ tablist_ht = 6
231
+ mylist = @db.get_data "select name from sqlite_master"
232
+ # mylist is an Array of SQLite3::ResultSet::ArrayWithTypesAndFields
233
+ raise "Database contains no tables! I need some tables" unless mylist
234
+ mylist.collect!{|x| x[0] } ## 1.9 hack, but will it run on 1.8 ??
235
+ $listdata = Variable.new mylist
236
+ tablelist = Listbox.new @form do
237
+ name "tablelist"
238
+ row 1
239
+ col t_width+2
240
+ width 20
241
+ height tablist_ht
242
+ # list mylist
243
+ list_variable $listdata
244
+ #selection_mode :multiple
245
+ #show_selector true
246
+ title "Tables"
247
+ title_attrib 'reverse'
248
+ help_text "Press ENTER to run * query, Space to select columns"
249
+ end
250
+ #tablelist.bind(:PRESS) { |alist| @status_row.text = "Selected #{alist.current_index}" }
251
+ tablelist.list_selection_model().bind(:LIST_SELECTION_EVENT,tablelist) { |lsm, alist| @status_row.text = "Selected #{alist.current_index}" }
252
+
253
+ collist = []
254
+ $coldata = Variable.new collist
255
+ columnlist = Listbox.new @form do
256
+ name "columnlist"
257
+ row tablist_ht+2
258
+ col t_width+2
259
+ width 20
260
+ height 15
261
+ # list mylist
262
+ list_variable $coldata
263
+ selection_mode :multiple
264
+ #show_selector true
265
+ title "Columns"
266
+ title_attrib 'reverse'
267
+ help_text "Press ENTER to append columns to sqlarea, Space to select"
268
+ end
269
+ ## pressing SPACE on a table populates column list with its columns so they can be selected
270
+ #tablelist.bind_key(32) {
271
+ # Now space trapped at listbox level, need to use event
272
+ tablelist.list_selection_model().bind(:LIST_SELECTION_EVENT,tablelist) { |lsm, alist| @status_row.text = "Selected #{alist.current_index}"
273
+ #@status_row.text = "Selected table #{tablelist.get_content()[tablelist.current_index]}"
274
+ table = "#{tablelist.get_content()[tablelist.current_index]}"
275
+ ##table = table[0] if table.class==Array ## 1.9 ???
276
+ columnlist.list_data_model.remove_all
277
+ columnlist.list_data_model.insert 0, *@db.get_metadata(table)
278
+ }
279
+ ## pressing ENTER on a table runs a query on it, no need to type and SQL
280
+
281
+ tablelist.bind(:PRESS) {
282
+ @status_row.text = "Selected #{tablelist.get_content()[tablelist.current_index]}"
283
+ table = "#{tablelist.get_content()[tablelist.current_index]}"
284
+ ##table = table[0] if table.class==Array ## 1.9 ???
285
+ run_query "select * from #{table}"
286
+ }
287
+
288
+ columnlist.bind(:PRESS) {
289
+ ## append column name to sqlarea if ENTER pressed
290
+ column = "#{columnlist.get_content()[columnlist.current_index]}"
291
+ sqlarea << "#{column},"
292
+ }
293
+ columnlist.bind_key(32) {
294
+ ## select row - later can press Construct button
295
+ columnlist.toggle_row_selection
296
+ column = "#{columnlist.get_content()[columnlist.current_index]}"
297
+ }
298
+ ## construct an SQL after selecting some columns in the column list
299
+ b_construct.command {
300
+ # current_index is wrong, we need selected_index
301
+ table = "#{tablelist.get_content()[tablelist.selected_index]}"
302
+ #table = table[0] if table.class==Array ## 1.9 ???
303
+ indexes = columnlist.selected_rows()
304
+ columns=[]
305
+ indexes.each do |i|
306
+ columns << columnlist.get_content()[i]
307
+ end
308
+ sql = "select #{columns.join(',')} from #{table}"
309
+ sqlarea << sql
310
+ }
311
+
312
+
313
+ @form.repaint
314
+ @window.wrefresh
315
+ Ncurses::Panel.update_panels
316
+ begin
317
+ while((ch = @window.getchar()) != ?\C-q.getbyte(0) )
318
+ break if ch == KEY_F1
319
+ s = keycode_tos ch
320
+ status_row.text = "Pressed #{ch} , #{s}. Press C-q to quit, Alt-Tab for exiting table "
321
+ @form.handle_key(ch)
322
+
323
+ @form.repaint
324
+ @window.wrefresh
325
+ end
326
+ ensure
327
+ @window.destroy if !@window.nil?
328
+ end
329
+ end
330
+ ## execute the query in the textarea
331
+ # @param [String] sql string
332
+ def run_query sql
333
+ #query = sqlarea.get_text
334
+ query = sql
335
+ begin
336
+ @content = @db.get_data query
337
+ if @content.nil?
338
+ @status_row.text = "0 rows retrieved"
339
+ return
340
+ end
341
+ #cw = @db.estimate_column_widths @atable.width, @db.columns
342
+ atable, newtab = create_table @tp, @tab_ctr #, buttrow, t_width, c
343
+ #atable.set_data @content, @db.columns
344
+ atable.set_content @content
345
+ atable.columns=@db.columns
346
+ #cw = atable.estimate_column_widths @db.columns, @db.datatypes
347
+ #atable.set_column_widths cw
348
+ rescue => exc
349
+ $log.debug(exc.backtrace.join("\n"))
350
+ alert exc.to_s
351
+ return
352
+ end
353
+ @status_row.text = "#{@content.size} rows retrieved"
354
+ atable.repaint
355
+ newtab.repaint
356
+ end
357
+ ## create a Table component for populating with data
358
+ def create_table tp, counter #, buttrow, t_width, c
359
+ table_ht = 15
360
+ atable = TabularWidget.new do
361
+ name "sqltable#{counter}"
362
+ help_text "M-Tab for next field, C-q quit"
363
+ end
364
+ #atable.bind(:TABLE_TRAVERSAL_EVENT){|e| @header.text_right "Row #{e.newrow+1} of #{atable.row_count}" }
365
+ @tab_ctr += 1
366
+ tab1 = tp.add_tab "Tab&#{@tab_ctr}" , atable
367
+ return atable, tab1
368
+ end
369
+ ## create the single tabbedpane for populating with resultsets
370
+ def create_tabbed_pane form, buttrow, t_width, c
371
+ tp = RubyCurses::TabbedPane.new form do
372
+ height 16
373
+ width t_width
374
+ row buttrow +1
375
+ col c
376
+ button_type :ok
377
+ end
378
+ return tp
379
+ end
380
+ end
381
+ if $0 == __FILE__
382
+ include RubyCurses
383
+ include RubyCurses::Utils
384
+
385
+ begin
386
+ # Initialize curses
387
+ VER::start_ncurses # this is initializing colors via ColorMap.setup
388
+ #$log = Logger.new("rbc13.log")
389
+ $log = Logger.new(ENV['LOGDIR'] || "" + "rbc13.log")
390
+
391
+ $log.level = Logger::DEBUG
392
+
393
+ colors = Ncurses.COLORS
394
+ $log.debug "START #{colors} colors SQLC demo "
395
+
396
+ catch(:close) do
397
+ t = Sqlc.new
398
+ t.run
399
+ end
400
+ rescue => ex
401
+ ensure
402
+ VER::stop_ncurses
403
+ p ex if ex
404
+ p(ex.backtrace.join("\n")) if ex
405
+ $log.debug( ex) if ex
406
+ $log.debug(ex.backtrace.join("\n")) if ex
407
+ end
408
+ end