rkumar-rbcurse 0.1.1 → 0.1.2

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