rkumar-rbcurse 0.1.1 → 0.1.2

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/CHANGELOG CHANGED
@@ -1,3 +1,43 @@
1
+ ** 2009-02-17 12:10 **
2
+ ## added table markers for data and columns before and after on border ##
3
+
4
+ also added putting space in intercell area, but today i am not getting any
5
+ junk there anywaym while scrolling etc.
6
+
7
+ * * *
8
+ ** 2009-02-16 22:10 **
9
+ ## added edit_length to TableColumn ##
10
+
11
+ This is max editable length of editor component in tables.
12
+
13
+ * * *
14
+ ** 2009-02-13 13:48 **
15
+ ## added button_type to tabbed pane ##
16
+
17
+ Now buttons at bottom of tabbed pane. Will return selected_index
18
+ to caller.
19
+ Uploaded to github, will be included in 0.1.2.
20
+
21
+ * * *
22
+ ** 2009-02-12 22:48 **
23
+ ## Code to stop table from printing a column if exceeding bounds ##
24
+
25
+ Uploaded to github, will be included in 0.1.2.
26
+
27
+ EXPERIMENTAL CODE: Affects only tables. Now table will not print a column or header
28
+ if columns width causes it to exceed width of table.
29
+
30
+ This means if you have a single column which is wider than table
31
+ then it wont print. In Listboxes we always truncate data and pass to
32
+ renderer. We could do that here, but it could get messy.
33
+
34
+ * * *
35
+ **2009-02-12 **
36
+ ## Missed one parameter in Table's repaint, and some Table Cell Renderers
37
+
38
+ Fixed and uploaded as 0.1.1
39
+
40
+ * * *
1
41
  **2009-02-11 00:57**
2
42
  ## Path changes in order to make first gem ##
3
43
 
@@ -0,0 +1,13 @@
1
+ === 0.1.1 / 2009-02-12
2
+
3
+ * Bugfix
4
+
5
+ * Parameter added to table cell renderer's repaint got missed in one
6
+ * or 2 classes. Only affects Tables.
7
+
8
+ === 0.1.0 / 2009-02-11
9
+
10
+ * 1 major enhancement
11
+
12
+ * Birthday!
13
+
data/README.txt CHANGED
@@ -13,13 +13,19 @@
13
13
 
14
14
  * rfe.rb is a ruby file explorer
15
15
 
16
+ * sqlc.rb is a ruby sql client demo (using testd.db at
17
+ http://www.benegal.org/files/screen/testd.db)
18
+
16
19
  * testtodo.rb is a test TODO application
17
20
 
18
- * Screenshots on http://github.com/rkumar/rbcurse/wikis/screenshots
19
- (OLD)
20
- and http://www.benegal.org/files/screen/?M=D (new)
21
+ * Screenshots on
22
+ http://www.benegal.org/files/screen/?M=D (new)
21
23
  and on blog, http://totalrecall.wordpress.com
24
+ and http://github.com/rkumar/rbcurse/wikis/screenshots (old)
25
+
26
+ * Todo (for 0.1.2): http://rubyforge.org/pm/task.php?group_id=7775&group_project_id=13812&func=browse
22
27
 
28
+ * Next Major Release: http://rubyforge.org/pm/task.php?group_project_id=13813&group_id=7775&func=browse
23
29
 
24
30
  == DESCRIPTION:
25
31
 
@@ -127,7 +133,7 @@ code below. See test programs for latest, working code.
127
133
  end
128
134
  field.insert 5, "hello ruby", "so long python", "farewell java", "RIP .Net"
129
135
 
130
- === create a textarea for entry (this can be buggy at present)
136
+ === create a textarea for entry
131
137
 
132
138
  texta = TextArea.new @form do
133
139
  name "mytext"
@@ -287,21 +293,16 @@ code below. See test programs for latest, working code.
287
293
 
288
294
  (following is provided with source)
289
295
 
290
- * uses the window class created by "manveru" (michael) - this can be
291
- removed if not needed. (lib/ver/window)
296
+ * uses the window class created by "manveru" (michael)
292
297
  It is provided with this package, and has some alterations from the
293
298
  original. I have added a method getchar() which traps and returns
294
299
  ALT/META, META+CTRL, META+SHIFT+CONTROL, ALT+Fn etc.
295
300
 
296
- So basically do not remove it unless you have very different
297
- requirements.
298
301
 
299
302
  == INSTALL:
300
303
 
301
- * currently, just unzip/untar in a folder. Please change the path in
302
- the top line of the test programs.
303
-
304
- (Please advice me how i can improve installation procedure)
304
+ sudo gem install ncurses-ruby
305
+ sudo gem install rbcurse
305
306
 
306
307
  == LICENSE:
307
308
 
@@ -13,9 +13,14 @@ require 'fileutils'
13
13
  #$LOAD_PATH << "/Users/rahul/work/projects/rbcurse/"
14
14
 
15
15
  # TODO
16
- # operations on selected files: move, delete, zip
16
+ # operations on selected files: move, delete, zip, copy
17
+ # - delete should move to Trash if exists - DONE
18
+ # global - don't ask confirm
19
+ # Select based on pattern.
17
20
  # This class represents the finder pane. There are 2
18
21
  # on this sample app
22
+ # NOTE: rfe_renderer uses entries so you may need to sync it with list_data_model
23
+ # actually, renderer should refer back to list data model!
19
24
  class FileExplorer
20
25
  include FileUtils
21
26
  attr_reader :wdir
@@ -34,6 +39,8 @@ class FileExplorer
34
39
  @wdir = @dir.path
35
40
  @filter_pattern = '*'
36
41
  @prev_dirs=[]
42
+ @inside_block = false
43
+
37
44
  end
38
45
  def title str
39
46
  @list.title = str
@@ -234,19 +241,41 @@ class FileExplorer
234
241
  def current_index
235
242
  @list.current_index
236
243
  end
237
- def filename
244
+ def filename ix=current_index()
238
245
  #@entries[@list.current_index]
239
- list_data()[current_index()]
246
+ list_data()[ix]
240
247
  end
241
- def filepath
242
- f = filename()
248
+ def filepath ix=current_index()
249
+ f = filename(ix)
243
250
  if f[0,1]=='/'
244
251
  f
245
252
  else
246
- cur_dir() + "/" + filename()
253
+ cur_dir() + "/" + f
254
+ end
255
+ end
256
+ # delete the item at position i
257
+ def delete_at i=@list.current_index
258
+ ret = @list.list_data_model.delete_at i
259
+ ret = @entries.delete_at i
260
+ end
261
+ def delete obj
262
+ ret = @list.list_data_model.delete obj
263
+ ret = @entries.delete_at obj
264
+ end
265
+ def insert_at obj, ix = @list.current_index
266
+ @list.list_data_model.insert ix, f
267
+ @entries.insert ix, obj
268
+ end
269
+ def remove_selected_rows
270
+ rows = @list.selected_rows
271
+ rows=rows.sort! {|x,y| y <=> x }
272
+ rows.each do |i|
273
+ ret = @list.list_data_model.delete_at i
274
+ ret = @entries.delete_at i
247
275
  end
248
276
  end
249
277
 
278
+ # ADD
250
279
  end
251
280
  class RFe
252
281
  attr_reader :status_row
@@ -258,6 +287,9 @@ class RFe
258
287
  colb = Ncurses.COLS/2
259
288
  ht = Ncurses.LINES - 7
260
289
  wid = Ncurses.COLS/2 - 0
290
+ @trash_path = File.expand_path("~/.Trash")
291
+ @trash_exists = File.directory? @trash_path
292
+ $log.debug " trash_path #{@trash_path}, #{@trash_exists}"
261
293
  @lista = FileExplorer.new @form, self, row=2, col=1, ht, wid
262
294
  @listb = FileExplorer.new @form, self, row=2, col=colb, ht, wid
263
295
 
@@ -280,33 +312,116 @@ class RFe
280
312
  File.open(@config_name, "w") { | f | YAML.dump( @config, f )}
281
313
  end
282
314
  def move
283
- fp = @current_list.filepath
315
+ fp = @current_list.filepath #.gsub(' ',"\ ")
284
316
  fn = @current_list.filename
285
317
  $log.debug " FP #{fp}"
286
318
  other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
287
319
  other_dir = other_list.cur_dir
288
320
  $log.debug " OL #{other_list.cur_dir}"
289
- str= "move #{fn} to #{other_list.cur_dir}"
290
- $log.debug " MOVE #{fp}"
291
- #confirm "#{str}"
292
- mb = RubyCurses::MessageBox.new do
293
- title "Move"
294
- message "Move #{fn} to"
295
- type :input
296
- width 60
297
- default_value other_dir
298
- button_type :ok_cancel
299
- default_button 0
300
- end
321
+ if @current_list.list.selected_row_count == 0
322
+ str= "#{fn}"
323
+ else
324
+ str= "#{@current_list.list.selected_row_count} files "
325
+ end
326
+ mb = RubyCurses::MessageBox.new do
327
+ title "Move"
328
+ message "Move #{str} to"
329
+ type :input
330
+ width 80
331
+ default_value other_dir
332
+ button_type :ok_cancel
333
+ default_button 0
334
+ end
301
335
  #confirm "selected :#{mb.input_value}, #{mb.selected_index}"
302
336
  if mb.selected_index == 0
303
- # need to redraw directories
304
- FileUtils.move(fp, mb.input_value)
305
- @current_list.list.list_data_model.delete_at @current_list.list.current_index # ???
337
+ if @current_list.list.selected_row_count == 0
338
+ FileUtils.move(fp, mb.input_value)
339
+ #ret = @current_list.list.list().delete_at @current_list.list.current_index # ???
340
+ # @current_list.entries.delete_at @current_list.current_index
341
+ @current_list.delete_at
342
+ else
343
+ each_selected_row do |f|
344
+ FileUtils.move(f, mb.input_value)
345
+ end
346
+ @current_list.remove_selected_rows
347
+ @current_list.list.clear_selection
348
+ end
306
349
  other_list.rescan
307
350
  end
308
351
  end
352
+ def each_selected_row #title, message, default_value
353
+ rows = @current_list.list.selected_rows
354
+ rows = rows.dup
355
+ rows.each do |i|
356
+ fp = @current_list.filepath i
357
+ #$log.debug " moving #{i}: #{fp}"
358
+ #FileUtils.move(fp, mb.input_value)
359
+ yield fp
360
+ end
361
+ end
309
362
  def copy
363
+ fp = @current_list.filepath #.gsub(' ',"\ ")
364
+ fn = @current_list.filename
365
+ $log.debug " FP #{fp}"
366
+ other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
367
+ other_dir = other_list.cur_dir
368
+ $log.debug " OL #{other_list.cur_dir}"
369
+ if @current_list.list.selected_row_count == 0
370
+ str= "#{fn}"
371
+ else
372
+ str= "#{@current_list.list.selected_row_count} files "
373
+ end
374
+ mb = RubyCurses::MessageBox.new do
375
+ title "Copy"
376
+ message "Copy #{str} to"
377
+ type :input
378
+ width 80
379
+ default_value other_dir
380
+ button_type :ok_cancel
381
+ default_button 0
382
+ end
383
+ if mb.selected_index == 0
384
+ if @current_list.list.selected_row_count == 0
385
+ FileUtils.copy(fp, mb.input_value)
386
+ else
387
+ each_selected_row do |f|
388
+ FileUtils.copy(f, mb.input_value)
389
+ end
390
+ @current_list.list.clear_selection
391
+ end
392
+ other_list.rescan
393
+ end
394
+ end
395
+ def delete
396
+ fp = @current_list.filepath #.gsub(' ',"\ ")
397
+ fn = @current_list.filename
398
+ if @current_list.list.selected_row_count == 0
399
+ str= "#{fn}"
400
+ else
401
+ str= "#{@current_list.list.selected_row_count} files "
402
+ end
403
+ if confirm("delete #{str}")==:YES
404
+ if @current_list.list.selected_row_count == 0
405
+ if @trash_exists
406
+ FileUtils.mv fp, @trash_path
407
+ else
408
+ FileUtils.rm fp
409
+ end
410
+ ret=@current_list.delete_at
411
+ else
412
+ each_selected_row do |f|
413
+ if @trash_exists
414
+ FileUtils.mv f, @trash_path
415
+ else
416
+ FileUtils.rm f
417
+ end
418
+ end
419
+ @current_list.remove_selected_rows
420
+ @current_list.list.clear_selection
421
+ end
422
+ end
423
+ end
424
+ def copy1
310
425
  fp = @current_list.filepath
311
426
  fn = @current_list.filename
312
427
  $log.debug " FP #{fp}"
@@ -392,22 +507,11 @@ class RFe
392
507
  other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
393
508
  case c
394
509
  when 'c'
395
- # str= "copy #{fn} to #{other_list.cur_dir}"
396
510
  copy
397
511
  when 'm'
398
- str= "move #{fn} to #{other_list.cur_dir}"
399
512
  move
400
- #if confirm("#{str}")==:YES
401
- #$log.debug " MOVE #{str}"
402
- #end
403
513
  when 'd'
404
- str= "delete #{fn} "
405
- if confirm("#{str}")==:YES
406
- $log.debug " delete #{fp}"
407
- FileUtils.rm fp
408
- ret=@current_list.list.list_data_model.delete_at @current_list.list.current_index # ???
409
- $log.debug " DEL RET #{ret},#{@current_list.list.current_index}"
410
- end
514
+ delete
411
515
  when 'u'
412
516
  str= "move #{fn} to #{other_list.cur_dir}"
413
517
  if confirm("#{str}")==:YES
@@ -475,6 +579,14 @@ class RFe
475
579
  str= "edit #{fp}"
476
580
  #if confirm("#{str}")==:YES
477
581
  edit fp
582
+ when 'm'
583
+ f = get_string("Enter a directory to create", 20 )
584
+ if f != ""
585
+ FileUtils.mkdir f
586
+ @current_list.list.list_data_model.insert @current_list.list.current_index, f # ???
587
+ @current_list.entries.insert @current_list.list.current_index, f # ???
588
+ end
589
+
478
590
  when 'x'
479
591
  str= "exec #{fp}"
480
592
  exec_popup fp
@@ -508,6 +620,9 @@ class RFe
508
620
  @lista.draw_screen lasta
509
621
  @listb.draw_screen lastb
510
622
 
623
+ # @form.bind_key(?\M-x){
624
+ # @current_list.mark_block
625
+ # }
511
626
  @form.bind_key(?@){
512
627
  @current_list.change_dir File.expand_path("~/")
513
628
  }
@@ -653,6 +768,7 @@ def get_key_labels categ=nil
653
768
  ['t', 'tree'], ['p', 'Previous'],
654
769
  ['b', 'Bookmark'], ['u', 'Unbookmark'],
655
770
  ['l', 'List'], ['s', 'Save'],
771
+ ['m', 'mkdir'], nil,
656
772
  ['C-c', 'Cancel']
657
773
  ]
658
774
  end
@@ -19,12 +19,14 @@ module RubyCurses
19
19
  @bgcolor = @orig_bgcolor
20
20
  @color = @orig_color
21
21
  @row_attr = @orig_attr
22
+ # XXX ouch, when we delete from list, must delete from here too.
22
23
  value = @parent.entries[row_index]
23
24
  if value[0,1]=="/"
24
25
  path = value.dup
25
26
  else
26
27
  path = @parent.cur_dir()+"/"+value
27
28
  end
29
+ begin
28
30
  stat = File.stat(path)
29
31
  if File.directory? path
30
32
  @row_attr = Ncurses::A_BOLD
@@ -33,6 +35,10 @@ module RubyCurses
33
35
  value = format_string(value, path, stat)
34
36
  super
35
37
 
38
+ rescue => err
39
+ $log.debug " rfe_renderer: #{err}"
40
+ end
41
+
36
42
  end
37
43
  GIGA_SIZE = 1073741824.0
38
44
  MEGA_SIZE = 1048576.0
@@ -0,0 +1,419 @@
1
+ require 'rubygems'
2
+ require 'ncurses'
3
+ require 'logger'
4
+ require 'sqlite3'
5
+ require 'rbcurse'
6
+ require 'rbcurse/rcombo'
7
+ require 'rbcurse/rtextarea'
8
+ require 'rbcurse/rtable'
9
+ #require 'rbcurse/table/tablecellrenderer'
10
+ require 'rbcurse/comboboxcellrenderer'
11
+ require 'rbcurse/keylabelprinter'
12
+ require 'rbcurse/applicationheader'
13
+ require 'rbcurse/action'
14
+
15
+ # pls get testd.db from
16
+ # http://www.benegal.org/files/screen/testd.db
17
+ # or put some other sqlite3 db name there.
18
+
19
+ ## must give me @content, @columns, @datatypes (opt)
20
+ class Datasource
21
+ # attr_reader :field_length # specified by user, length of row in display table
22
+ attr_accessor :columns # names of columns in array
23
+ attr_accessor :datatypes # array of datatyps of columns required to align: int, real, float, smallint
24
+ attr_accessor :content # 2 dim data
25
+ attr_accessor :user_columns # columnnames provided by user, overrides what is generated for display
26
+ # attr_reader :sqlstring # specified by user
27
+
28
+ # constructor
29
+ def initialize(config={}, &block)
30
+ @content = []
31
+ @columns = nil # actual db columnnames -- needed to figure out datatypes
32
+ @user_columns = nil # user specified db columnnames, overrides what may be provided
33
+ @datatypes = nil
34
+ # @rows = nil
35
+ # @sqlstring = nil
36
+ # @command = nil
37
+
38
+ instance_eval(&block) if block_given?
39
+ end
40
+ def connect dbname
41
+ @db = SQLite3::Database.new(dbname)
42
+ end
43
+ # get columns and datatypes, prefetch
44
+ def get_data command
45
+ @columns, *rows = @db.execute2(command)
46
+ @content = rows
47
+ return nil if @content.nil? or @content[0].nil?
48
+ @datatypes = @content[0].types #if @datatypes.nil?
49
+ @command = command
50
+ return @content
51
+ end
52
+ def get_metadata table
53
+ get_data "select * from #{table} limit 1"
54
+ return @columns
55
+ end
56
+ ##
57
+ # returns columns_widths, and updates that variable
58
+ def estimate_column_widths tablewidth, columns
59
+ colwidths = {}
60
+ min_column_width = (tablewidth/columns.length) -1
61
+ $log.debug("min: #{min_column_width}, #{tablewidth}")
62
+ @content.each_with_index do |row, cix|
63
+ break if cix >= 20
64
+ row.each_index do |ix|
65
+ col = row[ix]
66
+ colwidths[ix] ||= 0
67
+ colwidths[ix] = [colwidths[ix], col.length].max
68
+ end
69
+ end
70
+ total = 0
71
+ colwidths.each_pair do |k,v|
72
+ name = columns[k.to_i]
73
+ colwidths[name] = v
74
+ total += v
75
+ end
76
+ colwidths["__TOTAL__"] = total
77
+ column_widths = colwidths
78
+ @max_data_widths = column_widths.dup
79
+
80
+ columns.each_with_index do | col, i|
81
+ if @datatypes[i].match(/(real|int)/) != nil
82
+ wid = column_widths[i]
83
+ # cw = [column_widths[i], [8,min_column_width].min].max
84
+ $log.debug("XXX #{wid}. #{columns[i].length}")
85
+ cw = [wid, columns[i].length].max
86
+ $log.debug("int #{col} #{column_widths[i]}, #{cw}")
87
+ elsif @datatypes[i].match(/(date)/) != nil
88
+ cw = [column_widths[i], [12,min_column_width].min].max
89
+ #cw = [12,min_column_width].min
90
+ $log.debug("date #{col} #{column_widths[i]}, #{cw}")
91
+ else
92
+ cw = [column_widths[i], min_column_width].max
93
+ if column_widths[i] <= col.length and col.length <= min_column_width
94
+ cw = col.length
95
+ end
96
+ $log.debug("else #{col} #{column_widths[i]}, #{col.length} #{cw}")
97
+ end
98
+ column_widths[i] = cw
99
+ total += cw
100
+ end
101
+ column_widths["__TOTAL__"] = total
102
+ $log.debug("Estimated col widths: #{column_widths.inspect}")
103
+ @column_widths = column_widths
104
+ return column_widths
105
+ end
106
+
107
+ # added to enable query form to allow movement into table only if
108
+ # there is data 2008-10-08 17:46
109
+ # returns number of rows fetched
110
+ def data_length
111
+ return @content.length
112
+ end
113
+
114
+ end
115
+ def get_key_labels
116
+ key_labels = [
117
+ ['C-q', 'Exit'], nil,
118
+ ['M-s', 'Save'], ['M-m', 'Move']
119
+ ]
120
+ return key_labels
121
+ end
122
+ def get_key_labels_table
123
+ key_labels = [
124
+ ['M-n','NewRow'], ['M-d','DelRow'],
125
+ ['C-x','Select'], nil,
126
+ ['M-0', 'Top'], ['M-9', 'End'],
127
+ ['C-p', 'PgUp'], ['C-n', 'PgDn'],
128
+ ['M-Tab','Nxt Fld'], ['Tab','Nxt Col'],
129
+ ['+','Widen'], ['-','Narrow']
130
+ ]
131
+ return key_labels
132
+ end
133
+ class Sqlc
134
+ def initialize
135
+ @window = VER::Window.root_window
136
+ @form = Form.new @window
137
+
138
+ #@todo = Sql.new "todo.yml"
139
+ #@todo.load
140
+ @db = Datasource.new
141
+ @db.connect "testd.db"
142
+ end
143
+ def run
144
+ title = "rbcurse"
145
+ @header = ApplicationHeader.new @form, title, {:text2=>"Demo", :text_center=>"SQL Client"}
146
+ status_row = RubyCurses::Label.new @form, {'text' => "", :row => Ncurses.LINES-4, :col => 0, :display_length=>60}
147
+ @status_row = status_row
148
+ # setting ENTER across all objects on a form
149
+ @form.bind(:ENTER) {|f| status_row.text = f.help_text unless f.help_text.nil? }
150
+ r = 1; c = 1;
151
+ @data = [ ["No data"] ]
152
+ data = @data
153
+ colnames = %w[ Result ]
154
+
155
+ ta_ht = 5
156
+ t_width = 78
157
+ sqlarea = TextArea.new @form do
158
+ name "sqlarea"
159
+ row r
160
+ col c
161
+ width t_width
162
+ height ta_ht
163
+ title "Sql Query"
164
+ title_attrib (Ncurses::A_REVERSE | Ncurses::A_BOLD)
165
+ help_text "Enter query and press Run or Meta-r"
166
+ end
167
+ sqlarea << "select * from contacts"
168
+ buttrow = r+ta_ht+1 #Ncurses.LINES-4
169
+ #create_table_actions atable, todo, data, categ.getvalue
170
+ #save_cmd = @save_cmd
171
+ b_run = Button.new @form do
172
+ text "&Run"
173
+ row buttrow
174
+ col c
175
+ help_text "Run query"
176
+ end
177
+ ## We use Action to create a button: to test out ampersand with MI and Button
178
+ #clear_act = @clear_act
179
+ b_clear = Button.new @form do
180
+ #action new_act
181
+ text "&Clear"
182
+ row buttrow
183
+ col c+10
184
+ help_text "Clear query entry box "
185
+ #bind(:ENTER) { status_row.text "New button adds a new row below current " }
186
+ end
187
+ b_clear.command {
188
+ sqlarea.remove_all
189
+ sqlarea.focus
190
+ }
191
+
192
+ # using ampersand to set mnemonic
193
+ =begin
194
+ b_delrow = Button.new @form do
195
+ text "&Delete"
196
+ row buttrow
197
+ col c+25
198
+ #bind(:ENTER) { status_row.text "Deletes focussed row" }
199
+ help_text ""
200
+ end
201
+ b_delrow.command {
202
+ #@del_cmd.call
203
+ }
204
+ =end
205
+ Button.button_layout [b_run, b_clear], buttrow, startcol=5, cols=Ncurses.COLS-1, gap=5
206
+
207
+ table_ht = 15
208
+ atable = Table.new @form do
209
+ name "tasktable"
210
+ row buttrow+1
211
+ col c
212
+ width t_width
213
+ height table_ht
214
+ #title "A Table"
215
+ #title_attrib (Ncurses::A_REVERSE | Ncurses::A_BOLD)
216
+ #set_data data, colnames
217
+ #cell_editing_allowed true
218
+ #editing_policy :EDITING_AUTO
219
+ help_text "M-Tab for next field"
220
+ end
221
+ @atable = atable
222
+ @data = data
223
+ #atable.table_model.data = data
224
+
225
+ tcm = atable.get_table_column_model
226
+ b_run.command {
227
+ query = sqlarea.get_text
228
+ run_query query
229
+ }
230
+ #
231
+ ## key bindings fo atable
232
+ # column widths
233
+ app = self
234
+ atable.configure() do
235
+ #bind_key(330) { atable.remove_column(tcm.column(atable.focussed_col)) rescue "" }
236
+ bind_key(?+) {
237
+ acolumn = atable.column atable.focussed_col()
238
+ w = acolumn.width + 1
239
+ acolumn.width w
240
+ #atable.table_structure_changed
241
+ }
242
+ bind_key(?-) {
243
+ acolumn = atable.column atable.focussed_col()
244
+ w = acolumn.width - 1
245
+ if w > 3
246
+ acolumn.width w
247
+ #atable.table_structure_changed
248
+ end
249
+ }
250
+ bind_key(?>) {
251
+ colcount = tcm.column_count-1
252
+ #atable.move_column sel_col.value, sel_col.value+1 unless sel_col.value == colcount
253
+ col = atable.focussed_col
254
+ atable.move_column col, col+1 unless col == colcount
255
+ }
256
+ bind_key(?<) {
257
+ col = atable.focussed_col
258
+ atable.move_column col, col-1 unless col == 0
259
+ #atable.move_column sel_col.value, sel_col.value-1 unless sel_col.value == 0
260
+ }
261
+ bind_key(?\M-h, app) {|tab,td| $log.debug " BIND... #{tab.class}, #{td.class}"; app.make_popup atable}
262
+ end
263
+ #keylabel = RubyCurses::Label.new @form, {'text' => "", "row" => r+table_ht+3, "col" => c, "color" => "yellow", "bgcolor"=>"blue", "display_length"=>60, "height"=>2}
264
+ #eventlabel = RubyCurses::Label.new @form, {'text' => "Events:", "row" => r+table_ht+6, "col" => c, "color" => "white", "bgcolor"=>"blue", "display_length"=>60, "height"=>2}
265
+
266
+ # report some events
267
+ #atable.table_model.bind(:TABLE_MODEL_EVENT){|e| #eventlabel.text = "Event: #{e}"}
268
+ #atable.get_table_column_model.bind(:TABLE_COLUMN_MODEL_EVENT){|e| eventlabel.text = "Event: #{e}"}
269
+ atable.bind(:TABLE_TRAVERSAL_EVENT){|e| @header.text_right "Row #{e.newrow+1} of #{atable.row_count}" }
270
+
271
+ tablist_ht = 6
272
+ mylist = @db.get_data "select name from sqlite_master"
273
+ $listdata = Variable.new mylist
274
+ tablelist = Listbox.new @form do
275
+ name "tablelist"
276
+ row 1
277
+ col t_width+2
278
+ width 20
279
+ height tablist_ht
280
+ # list mylist
281
+ list_variable $listdata
282
+ #selection_mode :SINGLE
283
+ #show_selector true
284
+ title "Tables"
285
+ title_attrib 'reverse'
286
+ end
287
+ #tablelist.bind(:PRESS) { |alist| @status_row.text = "Selected #{alist.current_index}" }
288
+ tablelist.list_selection_model().bind(:LIST_SELECTION_EVENT,tablelist) { |lsm, alist| @status_row.text = "Selected #{alist.current_index}" }
289
+
290
+ collist = []
291
+ $coldata = Variable.new collist
292
+ columnlist = Listbox.new @form do
293
+ name "columnlist"
294
+ row tablist_ht+2
295
+ col t_width+2
296
+ width 20
297
+ height 15
298
+ # list mylist
299
+ list_variable $coldata
300
+ #selection_mode :SINGLE
301
+ #show_selector true
302
+ title "Columns"
303
+ title_attrib 'reverse'
304
+ end
305
+ tablelist.bind_key(32) {
306
+ @status_row.text = "Selected #{tablelist.get_content()[tablelist.current_index]}"
307
+ table = "#{tablelist.get_content()[tablelist.current_index]}"
308
+ columnlist.list_data_model.remove_all
309
+ columnlist.list_data_model.insert 0, *@db.get_metadata(table)
310
+ }
311
+ tablelist.bind_key(13) {
312
+ @status_row.text = "Selected #{tablelist.get_content()[tablelist.current_index]}"
313
+ table = "#{tablelist.get_content()[tablelist.current_index]}"
314
+ run_query "select * from #{table}"
315
+ }
316
+
317
+
318
+ @form.repaint
319
+ @window.wrefresh
320
+ Ncurses::Panel.update_panels
321
+ begin
322
+ while((ch = @window.getchar()) != ?\C-q )
323
+ #colcount = tcm.column_count-1
324
+ s = keycode_tos ch
325
+ #status_row.text = "Pressed #{ch} , #{s}"
326
+ @form.handle_key(ch)
327
+
328
+ @form.repaint
329
+ @window.wrefresh
330
+ end
331
+ ensure
332
+ @window.destroy if !@window.nil?
333
+ end
334
+ end
335
+ def run_query sql
336
+ #query = sqlarea.get_text
337
+ query = sql
338
+ begin
339
+ @content = @db.get_data query
340
+ if @content.nil?
341
+ @status_row.text = "0 rows retrieved"
342
+ return
343
+ end
344
+ #cw = @db.estimate_column_widths @atable.width, @db.columns
345
+ @atable.set_data @content, @db.columns
346
+ cw = @atable.estimate_column_widths @db.columns, @db.datatypes
347
+ @atable.set_column_widths cw
348
+ rescue => exc
349
+ alert exc.to_s
350
+ return
351
+ end
352
+ @status_row.text = "#{@content.size} rows retrieved"
353
+ @atable.repaint
354
+ end
355
+ def create_table_actions atable, todo, data, categ
356
+ #@new_act = Action.new("New Row", "mnemonic"=>"N") {
357
+ @new_act = Action.new("&New Row") {
358
+ mod = nil
359
+ cc = atable.get_table_column_model.column_count
360
+ if atable.row_count < 1
361
+ frow = 0
362
+ else
363
+ frow = atable.focussed_row
364
+ #frow += 1 # why ?
365
+ mod = atable.get_value_at(frow,0) unless frow.nil?
366
+ end
367
+ tmp = [mod, 5, "", "TODO", Time.now]
368
+ tm = atable.table_model
369
+ tm.insert frow, tmp
370
+ atable.set_focus_on frow
371
+ @status_row.text = "Added a row. Please press Save before changing Category."
372
+ alert("Added a row before current one. Use C-k to clear task.")
373
+ }
374
+ @new_act.accelerator "Alt-N"
375
+ @save_cmd = lambda {
376
+ todo.set_tasks_for_category categ, data
377
+ todo.dump
378
+ alert("Rewritten yaml file")
379
+ }
380
+ @del_cmd = lambda {
381
+ row = atable.focussed_row
382
+ if !row.nil?
383
+ if confirm("Do your really want to delete row #{row+1}?")== :YES
384
+ tm = atable.table_model
385
+ tm.delete_at row
386
+ else
387
+ @status_row.text = "Delete cancelled"
388
+ end
389
+ end
390
+ }
391
+
392
+ end
393
+ end
394
+ if $0 == __FILE__
395
+ include RubyCurses
396
+ include RubyCurses::Utils
397
+
398
+ begin
399
+ # Initialize curses
400
+ VER::start_ncurses # this is initializing colors via ColorMap.setup
401
+ $log = Logger.new("view.log")
402
+ $log.level = Logger::DEBUG
403
+
404
+ colors = Ncurses.COLORS
405
+ $log.debug "START #{colors} colors ---------"
406
+
407
+ catch(:close) do
408
+ t = Sqlc.new
409
+ t.run
410
+ end
411
+ rescue => ex
412
+ ensure
413
+ VER::stop_ncurses
414
+ p ex if ex
415
+ p(ex.backtrace.join("\n")) if ex
416
+ $log.debug( ex) if ex
417
+ $log.debug(ex.backtrace.join("\n")) if ex
418
+ end
419
+ end