rbcurse 1.3.0 → 1.4.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.
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