Friday, September 24, 2010

GTK Programming in Ruby (5) - Adding Toolbar, using UIManager

1. Main program showing a window with a toolbar.
#
# toolbar01.rb
#
require 'gtk2'
require 'ui_module.rb'

class App < Gtk::Window
 
 include UIModule # 'ui_module.rb'
 
 def initialize
  super
  window_settings('Toolbar using UIManager', 700, 500, Gtk::Window::POS_CENTER)
  ui_initialize # 'ui_module.rb'
  vbox = layout_settings(ui_create_menu,ui_create_toolbar) # 'ui_module.rb'
  event_settings
  self.show_all
 end
  
 def window_settings(title, width, height, position)
  self.set_title title
  self.set_default_size width, height
    self.set_window_position position
 end

 def layout_settings(menubar,toolbar)
  vbox = Gtk::VBox.new false, 4
  vbox.pack_start menubar, false, false, 0
  vbox.pack_start toolbar, false, false, 0
  self.add vbox
  return vbox
 end
 
 def event_settings
  self.signal_connect "destroy" do
   app_quit
  end
 end   
 
 def app_quit
  Gtk.main_quit 
 end
 
end

Gtk.init
 window = App.new
Gtk.main


2. Define Menu and Tool bar structure in a separate file.

menu_toolbar.ui

<ui>
  <menubar name="MenuBar">
    <menu name="FileMenu" action="File">
   <menuitem name="FileNew" action="New"/>
      <menuitem name="FileOpen" action="Open"/>
      <separator/>
      <menuitem name="FileSave" action="Save"/>
      <menuitem name="FileSaveAs" action="SaveAs"/>
      <menuitem name="FileRevert" action="Revert"/>
      <separator/>
      <menuitem name="FilePageSetup" action="PageSetup"/>
      <menuitem name="FilePreview" action="Preview"/> 
      <menuitem name="FilePrint" action="Print"/> 
      <separator/>      
      <menuitem name="FileQuit" action="Quit"/>
    </menu>
    <menu name="EditMenu" action="Edit">
   <menuitem name="EditUndo" action="Undo"/>
   <menuitem name="EditRedo" action="Redo"/>
   <separator/>  
      <menuitem name="EditCut" action="Cut"/>
      <menuitem name="EditCopy" action="Copy"/>
      <menuitem name="EditPaste" action="Paste"/>
      <menuitem name="EditClear" action="Clear"/>
      <separator/>
      <menuitem name="EditSelectAll" action="SelectAll"/>
      <menuitem name="EditDeselect" action="Deselect"/>
      <separator/>
      <menuitem name="EditPreferences" action="Preferences"/>
    </menu>
    <menu name="HelpMenu" action="Help">
      <menuitem name="HelpContents" action="Contents"/>
      <menuitem name="HelpAbout" action="About"/>
    </menu>
  </menubar>
  <toolbar name="ToolBar">
   <toolitem name="FileNew" action="New"/>
      <toolitem name="FileOpen" action="Open"/>
      <toolitem name="FileSave" action="Save"/>
      <toolitem name="FileSaveAs" action="SaveAs"/>
      <toolitem name="FileRevert" action="Revert"/>
      <toolitem name="FilePreview" action="Preview"/> 
      <toolitem name="FilePrint" action="Print"/> 
      <separator/>  
   <toolitem name="EditUndo" action="Undo"/>
   <toolitem name="EditRedo" action="Redo"/>
      <toolitem name="EditCut" action="Cut"/>
      <toolitem name="EditCopy" action="Copy"/>
      <toolitem name="EditPaste" action="Paste"/>
      <toolitem name="EditClear" action="Clear"/>
      <toolitem name="EditSelectAll" action="SelectAll"/>
      <toolitem name="EditPreferences" action="Preferences"/>
   <separator/>
      <toolitem name="HelpContents" action="Contents"/>
      <toolitem name="HelpAbout" action="About"/>
      <separator/>
      <toolitem name="FileQuit" action="Quit"/>
  </toolbar>
</ui>


3. UI manager handler.

#
# ui_module.rb
#

module UIModule

 def ui_initialize
 
  # callback procs! 
  new       = Proc.new { puts "new" }
  open      = Proc.new { puts "open" }
  save      = Proc.new { puts "save" }
  saveas    = Proc.new { puts "saveas" }entries
  revert    = Proc.new { puts "revert" }
  pagesetup = Proc.new { puts "pagesetup" }
  preview   = Proc.new { puts "preview" }
  print     = Proc.new { puts "print" }
  quit    = Proc.new { app_quit }
  undo      = Proc.new { puts "undo" }
  redochg   = Proc.new { puts "redo" }
  cut       = Proc.new { puts "cut" }
  copy      = Proc.new { puts "copy" }
  paste     = Proc.new { puts "paste" }
  clear     = Proc.new { puts "clear" }
  selectall = Proc.new { puts "selectall" }
  deselect  = Proc.new { puts "deselect" }
  preferences = Proc.new { puts "preferences" }
  help      = Proc.new { puts "help" }
  about     = Proc.new { puts "about" }

  # menu items: name, stock_id, label, accelerator, tool-tip, callback
  entries = [
   ["File", nil, "_File", nil, nil, nil ],
    ["New",      Gtk::Stock::NEW,  nil, nil, "Create New",   new],
    ["Open",      Gtk::Stock::OPEN,  nil, nil, "Open a file",   open],
    ["Save",      Gtk::Stock::SAVE,  nil, nil, "Save the doc.", save],
    ["SaveAs",    Gtk::Stock::SAVE_AS,  nil, nil, "Save the doc. as", saveas],
    ["Revert",    Gtk::Stock::REVERT_TO_SAVED,  nil, nil, "Revert to saved", revert],
    ["PageSetup", nil,"Page Setup", nil, "Page setup", pagesetup],
    ["Preview",    Gtk::Stock::PRINT_PREVIEW,  nil, nil, "Print Preview", preview],
    ["Print",      Gtk::Stock::PRINT,  nil, nil, "Save the doc.", save],
    ["Quit",      Gtk::Stock::QUIT,  nil, nil, "Quit the app.", quit],
   ["Edit", nil, "_Edit", nil, nil, nil],
    ["Undo",       Gtk::Stock::UNDO,    nil, nil, "Undo Change",  undo],
    ["Redo",       Gtk::Stock::REDO,    nil, nil, "Redo Change",  redochg],
    ["Cut",       Gtk::Stock::CUT,    nil, nil, "Cut the sel.",  cut],
    ["Copy",      Gtk::Stock::COPY,   nil, nil, "Copy the sel.", copy],
    ["Paste",     Gtk::Stock::PASTE,  nil, nil, "Paste text",    paste],
    ["Clear",     Gtk::Stock::CLEAR,  nil, nil, "Clear text",    clear],
    ["SelectAll", Gtk::Stock::SELECT_ALL, nil, nil, "Sel all",  selectall],
    ["Deselect",  nil, "_Deselect", "d", "Deselect all",   deselect],
    ["Preferences",Gtk::Stock::PREFERENCES,  nil, nil, "Preferences", preferences],
   ["Help", nil, "_Help", nil, nil, nil],
    ["Contents",  Gtk::Stock::HELP,  nil, nil, "Get help",      help],
    ["About",     Gtk::Stock::ABOUT, nil, nil, "More info ...", about]
   ]
  
  # create an action group with entries defined above
  group = Gtk::ActionGroup.new("ActionGroup")
  group.add_actions(entries)
  
  # create ui manager object and add action group
  @ui_mgr = Gtk::UIManager.new
   @ui_mgr.insert_action_group group,0
   self.add_accel_group @ui_mgr.accel_group
   
 end
 
 # create menubar using ui manager
 def ui_create_menu   
  return ui_get_widget("menu_toolbar.ui", "/MenuBar") 
 end
 
 # create toolbar using ui manager
 def ui_create_toolbar
   return ui_get_widget("menu_toolbar.ui", "/ToolBar") 
 end

 # utility function to create a widget using ui manager
 def ui_get_widget(uifile, name)
  @ui_mgr.add_ui uifile
   widget = @ui_mgr.get_widget name   
   return widget
 end 
 
end

4. Run it.
$ ruby toolbar01.rb

5. Result.

Wednesday, September 15, 2010

GTK Programming in Ruby (4) - Adding Menubar, using UIManager

1. Create a ui file (xml format) to define its menu structure.
File Name: menu03.ui
<ui>
  <menubar name="MenuBar">
    <menu name="FileMenu" action="File">
   <menuitem name="FileNew" action="New"/>
      <menuitem name="FileOpen" action="Open"/>
      <separator/>
      <menuitem name="FileSave" action="Save"/>
      <menuitem name="FileSaveAs" action="SaveAs"/>
      <menuitem name="FileRevert" action="Revert"/>
      <separator/>
      <menuitem name="FilePageSetup" action="PageSetup"/>
      <menuitem name="FilePreview" action="Preview"/> 
      <menuitem name="FilePrint" action="Print"/> 
      <separator/>      
      <menuitem name="FileQuit" action="Quit"/>
    </menu>
    <menu name="EditMenu" action="Edit">
   <menuitem name="EditUndo" action="Undo"/>
   <menuitem name="EditRedo" action="Redo"/>
   <separator/>  
      <menuitem name="EditCut" action="Cut"/>
      <menuitem name="EditCopy" action="Copy"/>
      <menuitem name="EditPaste" action="Paste"/>
      <menuitem name="EditClear" action="Clear"/>
      <separator/>
      <menuitem name="EditSelectAll" action="SelectAll"/>
      <menuitem name="EditDeselect" action="Deselect"/>
      <separator/>
      <menuitem name="EditPreferences" action="Preferences"/>
    </menu>
    <menu name="HelpMenu" action="Help">
      <menuitem name="HelpContents" action="Contents"/>
      <menuitem name="HelpAbout" action="About"/>
    </menu>
  </menubar>
</ui>

2. Use it in the program to create menu.
#!/usr/bin/ruby
#
# menu03.rb
# using UIManager
# requires menu03.ui

require 'gtk2'

class App < Gtk::Window
 
 def initialize
  super
  window_settings('Menubar using UIManager', 400, 300, Gtk::Window::POS_CENTER)
  mb = menu_settings
  vbox = layout_settings(mb)
  event_settings
  self.show_all
 end
  
 def window_settings(title, width, height, position)
  self.set_title title
  self.set_default_size width, height
    self.set_window_position position
 end

 def layout_settings(menubar)
  vbox = Gtk::VBox.new false, 3
  vbox.pack_start menubar, false, false, 0
  self.add vbox
  return vbox
 end
 
 def menu_settings    
 
  # callback procs! 
  new      = Proc.new { puts "new" }
  open      = Proc.new { puts "open" }
  save      = Proc.new { puts "save" }
  saveas    = Proc.new { puts "saveas" }
  revert    = Proc.new { puts "revert" }
  pagesetup = Proc.new { puts "pagesetup" }
  preview   = Proc.new { puts "preview" }
  print     = Proc.new { puts "print" }
  quit    = Proc.new { app_quit }
  undo      = Proc.new { puts "undo" }
  redochg   = Proc.new { puts "redo" }
  cut       = Proc.new { puts "cut" }
  copy      = Proc.new { puts "copy" }
  paste     = Proc.new { puts "paste" }
  clear     = Proc.new { puts "clear" }
  selectall = Proc.new { puts "selectall" }
  deselect  = Proc.new { puts "deselect" }
  preferences = Proc.new { puts "preferences" }
  help      = Proc.new { puts "help" }
  about     = Proc.new { puts "about" }

  # menu items: name, stock_id, label, accelerator, tool-tip, callback
  entries = [
   ["File", nil, "_File", nil, nil, nil ],
    ["New",      Gtk::Stock::NEW,  nil, nil, "Create New",   new],
    ["Open",      Gtk::Stock::OPEN,  nil, nil, "Open a file",   open],
    ["Save",      Gtk::Stock::SAVE,  nil, nil, "Save the doc.", save],
    ["SaveAs",    Gtk::Stock::SAVE_AS,  nil, nil, "Save the doc. as", saveas],
    ["Revert",    Gtk::Stock::REVERT_TO_SAVED,  nil, nil, "Revert to saved", revert],
    ["PageSetup", nil,"Page Setup", nil, "Page setup", pagesetup],
    ["Preview",    Gtk::Stock::PRINT_PREVIEW,  nil, nil, "Print Preview", preview],
    ["Print",      Gtk::Stock::PRINT,  nil, nil, "Save the doc.", save],
    ["Quit",      Gtk::Stock::QUIT,  nil, nil, "Quit the app.", quit],
   ["Edit", nil, "_Edit", nil, nil, nil],
    ["Undo",       Gtk::Stock::UNDO,    nil, nil, "Undo Change",  undo],
    ["Redo",       Gtk::Stock::REDO,    nil, nil, "Redo Change",  redochg],
    ["Cut",       Gtk::Stock::CUT,    nil, nil, "Cut the sel.",  cut],
    ["Copy",      Gtk::Stock::COPY,   nil, nil, "Copy the sel.", copy],
    ["Paste",     Gtk::Stock::PASTE,  nil, nil, "Paste text",    paste],
    ["Clear",     Gtk::Stock::CLEAR,  nil, nil, "Clear text",    clear],
    ["SelectAll", Gtk::Stock::SELECT_ALL, nil, nil, "Sel all",  selectall],
    ["Deselect",  nil, "_Deselect", "d", "Deselect all",   deselect],
    ["Preferences",Gtk::Stock::PREFERENCES,  nil, nil, "Preferences", preferences],
   ["Help", nil, "_Help", nil, nil, nil],
    ["Contents",  Gtk::Stock::HELP,  nil, nil, "Get help",      help],
    ["About",     Gtk::Stock::ABOUT, nil, nil, "More info ...", about]
  ]
    
  return create_menu(entries,"menu03.ui")
  
 end
 
 def event_settings
  self.signal_connect "destroy" do
   app_quit
  end
 end   
 
 def create_menu(entries, menu_ui)
  
  group = Gtk::ActionGroup.new("MenuActionGroup")
  group.add_actions(entries)
  
  ui = Gtk::UIManager.new
   ui.insert_action_group group,0
   ui.add_ui menu_ui
   
   menubar = ui.get_widget "/MenuBar"
   
  self.add_accel_group ui.accel_group
   
   return menubar
 end
 
 def app_quit
  Gtk.main_quit 
 end
 
end

Gtk.init
 window = App.new
Gtk.main

3. Run it:
$ ruby menu03.rb 

4. Results:
a. File menu

b. Edit menu

5, Issues.
a.Again, it automatically translate (into Japanese). How do I suppress, or display in another language such as German or Chinese?
b. Is there a stock item for Page Setup?

6. Reference:
a. http://ruby-gnome2.sourceforge.jp/hiki.cgi?tut-gtk2-mnstbs-dynmc
b. http://zetcode.com/tutorials/rubygtktutorial/menustoolbars/

Sunday, September 12, 2010

Installed Simple Backup (sbackup)

Just installed backup software on my Ubuntu PC.

1. Open Synapitc.
2. Search and Install sbackup.
3. Administration > Backup

I am using a default settings for now.

Saturday, September 11, 2010

Installing rbbr - ruby class browser

Installed rbbr.

1. Open Synaptic
2. Search and Install rbbr

Launch it.

$ rbbr


It opens a browser like this:

GTK Programming in Ruby (3) - Adding Menubar, using Stock items

#!/usr/bin/ruby
#
# menu02.rb
# using Stock Menu Items

require 'gtk2'

class App < Gtk::Window
 
 def initialize
  super
  window_settings('Window with Menu', 400, 300)
  mb = menu_settings
  vbox = layout_settings(mb)
  event_settings
  show_all
 end
 
 def window_settings(title, width, height)
  set_title title
  set_default_size width, height
    set_window_position Gtk::Window::POS_CENTER
 end

 def layout_settings(menubar)
  vbox = Gtk::VBox.new false, 3
  vbox.pack_start menubar, false, false, 0
  add vbox
  return vbox
 end
 
 def menu_settings   
 
  # create keyboard accelerator group (keyboard shot cut)
  @keyaccgrp = Gtk::AccelGroup.new
    add_accel_group @keyaccgrp
   
  # menu bar
  menubar = Gtk::MenuBar.new
      
  # menus
  filemenu = new_menu(menubar, 'File')
  editmenu = new_menu(menubar, 'Edit')
  helpmenu = new_menu(menubar, 'Help')
  
  # file menu items
  quitmenuitem = new_menu_item (filemenu, Gtk::Stock::QUIT, 'Q').signal_connect "activate" do
   app_quit
  end     

  # edit menu items
  copymenuitem = new_menu_item (editmenu, Gtk::Stock::COPY, 'C')
  cutmenuitem = new_menu_item (editmenu, Gtk::Stock::CUT, 'X')
  pastemenuitem = new_menu_item (editmenu, Gtk::Stock::PASTE, 'V')
 
  return menubar
  
 end
 
 def event_settings
  signal_connect "destroy" do
   app_quit
  end   
 end  
 
 def new_menu(menubar,title)
  menu = Gtk::Menu.new
  item = Gtk::MenuItem.new title
  item.set_submenu menu
  menubar.append item
  return menu 
 end
 
 def new_menu_item(menu, stock, char)
  item = Gtk::ImageMenuItem.new stock, @keyaccgrp
    key, mod = Gtk::Accelerator.parse char
    item.add_accelerator("activate", @keyaccgrp, key, mod, Gtk::ACCEL_VISIBLE)  
  menu.append item
  return item
 end
 
 def app_quit
  Gtk.main_quit
 end
 
end

Gtk.init
 window = App.new
Gtk.main




The result:

Issues:
1. I did not expect automatic translation (to Japanese). How do I suppress?
2. How do I add accelerator to Menu bar items such as "File"? Using underscore ("_File") does not work.

Friday, September 10, 2010

GTK Programming in Ruby (2) - Adding Menubar

# menu01.rb

require 'gtk2'

class App < Gtk::Window

 def initialize
  super
  window_settings('Window with Menu', 400, 300)
  menu_settings
  event_settings
  show_all
 end
    
 def window_settings(title, width, height)
  set_title title
  set_default_size width, height
    set_window_position Gtk::Window::POS_CENTER
 end

 def menu_settings    
 
  # menu bar
  menubar = Gtk::MenuBar.new
  
  # file menu
  filemenu = Gtk::Menu.new
  filemenuitem = Gtk::MenuItem.new "File"
  filemenuitem.set_submenu filemenu
  
  # file | quit menu item
  exitmenuitem = Gtk::MenuItem.new "Quit"
  exitmenuitem.signal_connect "activate" do
    quit
  end
  filemenu.append exitmenuitem

  # edit menu
  editmenu = Gtk::Menu.new
  editmenuitem = Gtk::MenuItem.new "Edit"
  editmenuitem.set_submenu editmenu
  
  # help menu
  helpmenu = Gtk::Menu.new
  helpmenuitem = Gtk::MenuItem.new "Help"
  helpmenuitem.set_submenu helpmenu

  # append all menu(item)s to menubar
  menubar.append filemenuitem
  menubar.append editmenuitem
  menubar.append helpmenuitem
  
  # place the menu bar in the window
  vbox = Gtk::VBox.new false, 2
  vbox.pack_start menubar, false, false, 0
  add vbox
  
 end
 
 def event_settings
  signal_connect "destroy" do 
   quit
  end    
 end   
 
 def quit
  Gtk.main_quit 
 end
 
end

Gtk.init
 window = App.new
Gtk.main

Run it:
$ ruby menu01.rb

The result is:

Monday, September 6, 2010

Testing sequel to access PostgreSQL

# seq01pg.rb

require 'rubygems'
require 'sequel'

class SequelTest

  def initialize
    
    @db =  Sequel.postgres('mydb', :host=>'localhost', :user=>'socrateos', :password=>'secret')
    
    unless(@db.table_exists?(:table1))
      @db.create_table :table1 do
        primary_key :id
        String :title
      end
    end
  
    unless(record_exists?(:table1, :title, 'test1'))
      @db[:table1].insert(:id => 1, :title => 'test1')
    end
  
    unless(record_exists?(:table1, :title, 'test2'))
      @db[:table1].insert(:id => 2, :title => 'test2')
    end
 
    unless(record_exists?(:table1, :title, 'test3'))
      @db[:table1].insert(:id => 3, :title => 'test3')
    end
  
  end

  def record_exists?(table, field, value)
    rows = @db[table].where(field => value)
    return (rows.count>0)
  end
  
  def show_all
    p "Database type:" + @db.database_type.to_s
    @db.fetch('select * from table1') do |row|
      p row
    end
  end
 
end

app = SequelTest.new
app.show_all


Run it:
$ ruby seq01pg.rb 
"Database type:postgres"
{:title=>"test1", :id=>1}
{:title=>"test2", :id=>2}
{:title=>"test3", :id=>3}

Saturday, September 4, 2010

Testing sequel to access SQLite

require 'rubygems'
require 'sequel'

class SequelTest

  def initialize
    # @db = Sequle.connect("sqlite:test2.db") # this does not create database
    @db = Sequel.sqlite("test2.db")
    unless(@db.table_exists?(:table1))
      @db.create_table :table1 do
        primary_key :id
        String :title
      end
    end
  
    unless(record_exists?(:table1, :title, 'test1'))
      @db[:table1].insert(:title => 'test1')
    end
  
    unless(record_exists?(:table1, :title, 'test2'))
      @db[:table1].insert(:title => 'test2')
    end
  
    unless(record_exists?(:table1, :title, 'test3'))
      @db[:table1].insert(:title => 'test3')
    end
  
  end

  def record_exists?(table, field, value)
    rows = @db[table].where(field => value)
    return (rows.count>0)
  end
  
  def show_all
    p "Database type:" + @db.database_type.to_s
    @db.fetch('select * from table1') do |row|
      p row
    end
  end

end

app = SequelTest.new
app.show_all

$ ruby seq01sq.rb 
"Database type:sqlite"
{:title=>"test1", :id=>1}
{:title=>"test2", :id=>2}
{:title=>"test3", :id=>3}

Wednesday, September 1, 2010

Testing pg (postgresql-ruby)

# pgsql01.rb

require 'pg'

class PgSQLTest

  def initialize
    @db = PGconn.connect( nil, 5432, nil, nil, 'mydb', nil, nil ) 
    puts "dbname: " + @db.db + ", user: "+@db.user
    @db.exec("create table test (id INTEGER PRIMARY KEY, title TEXT)") \
       unless(table_exists("test"))
    @db.exec("insert into test (id, title) values(1, 'test1')") \
       unless(record_exists("test", "test1"))
    @db.exec("insert into test (id, title) values(2, 'test2')") \
       unless(record_exists("test", "test2"))
  end
 
  def exit
    @db.close if(@db)
  end
 
  def table_exists(name)
    rows = @db.exec("SELECT 1 FROM pg_catalog.pg_class \
       WHERE relkind = 'r' AND relname = '"+name+"' \
       AND pg_catalog.pg_table_is_visible(oid) LIMIT 1")
    return (rows.count>0)
  end
 
  def record_exists(table_name, title)
    rows = @db.exec("select id from "+table_name+" where title='"+title+"'")
    return (rows.count>0)
  end
 
  def show_all
    rows = @db.exec('select * from test')
    for col in rows.fields
      printf("%-15s", col)
    end 
    printf("\n---------------------\n")
    r = 0
    rows.each do |row|
      c = 0
      row.each do |col|
        printf("%-15s", rows.getvalue(r,c))
        c = c + 1
      end
      r = r + 1
      printf("\n")
    end
  end 

end

app = PgSQLTest.new
app.show_all
app.exit

Run it.
ruby pgsql01.rb
dbname: mydb, user: socrateos
id             title          
---------------------
1              test1          
2              test2