Skip to content

Instantly share code, notes, and snippets.

@jdudek
Created December 2, 2011 06:55
Show Gist options
  • Save jdudek/1422121 to your computer and use it in GitHub Desktop.
Save jdudek/1422121 to your computer and use it in GitHub Desktop.
require 'gtk2'
require 'rubygems'
require 'dbi'
class Person
DB_FILE = 'db.sqlite'
@@db = nil
@@instances = []
def self.db
if !@@db
@@db = DBI.connect("DBI:SQLite3:#{DB_FILE}");
end
return @@db
end
def self.close
@@db.disconnect if @@db
@@db = nil
@@instances = []
end
def self.create_schema
self.db.do('
CREATE TABLE person (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`first_name` VARCHAR(255),
`last_name` VARCHAR(255),
`email` VARCHAR(255),
`address` VARCHAR(255),
`phone` VARCHAR(255),
`jabberid` VARCHAR(255)
)
');
end
def self.find(id)
id = id.to_s.to_i
if !@@instances[id]
row = self.db.select_one("SELECT * FROM `person` WHERE `id` = #{id}")
if row
@@instances[id] = Person.new
@@instances[id].hydrate row
end
end
return @@instances[id]
end
def self.find_all(str = nil)
if str
where = "WHERE `first_name` LIKE '%#{str}%' OR `last_name` LIKE '%#{str}%'"
else
where = ""
end
results = []
self.db.execute("SELECT * FROM `person` #{where}").each do |row|
id = row['id'].to_s.to_i
if !@@instances[id]
@@instances[id] = Person.new
@@instances[id].hydrate(row)
end
results.push(@@instances[id])
end
return results
end
def self.delete(p)
if !p.is_a? Person
p = Person.find p
end
self.db.do("DELETE FROM `person` WHERE `id` = #{p.id}") if !p.is_new
@@instances[p.id] = nil
end
attr_reader :id, :is_new
attr_reader :first_name, :last_name, :email, :address, :phone, :jabberid
attr_writer :first_name, :last_name, :email, :address, :phone, :jabberid
def initialize
@is_new = true
end
def hydrate(v)
raise RuntimeError "Object already hydrated" if !@is_new
@id = v["id"].to_s.to_i
@first_name = v["first_name"]
@last_name = v["last_name"]
@email = v["email"]
@address = v["address"]
@phone = v["phone"]
@jabberid = v["jabberid"]
@is_new = false
end
def save
if @is_new
Person.db.do("
INSERT INTO `person`
(`first_name`, `last_name`, `email`, `address`, `phone`, `jabberid`)
VALUES (
'#{@first_name}', '#{@last_name}', '#{@email}', '#{@address}',
'#{@phone}', '#{@jabberid}'
)
")
@is_new = false
@id = Person.db.select_one("SELECT last_insert_rowid()").to_s.to_i
else
Person.db.do("
UPDATE `person`
SET
`first_name` = '#{@first_name}',
`last_name` = '#{@last_name}',
`email` = '#{@email}',
`address` = '#{@address}',
`phone` = '#{@phone}',
`jabberid` = '#{@jabberid}'
WHERE `id` = #{@id}
")
end
end
def to_s
"(#{self.id}) #{self.last_name}, #{self.first_name}, #{self.email}, " +
"#{self.address}, #{self.phone}, jid:#{self.jabberid}"
end
def to_a
[ @id.to_i, @first_name, @last_name, @email, @address, @phone, @jabberid ]
end
end
class AddressBookApp
def initialize
self.create_window
Gtk.main
end
def create_window
@win = Gtk::Window.new
@win.window_position = Gtk::Window::POS_CENTER
@win.set_default_size(300, 300)
@win.title = "Address Book"
@win.signal_connect("delete_event") { Gtk.main_quit }
@btn_add = Gtk::Button.new(Gtk::Stock::ADD)
@btn_del = Gtk::Button.new(Gtk::Stock::REMOVE)
@btn_quit = Gtk::Button.new(Gtk::Stock::QUIT)
@btn_quit.signal_connect("clicked") { Gtk.main_quit }
box_btns = Gtk::HBox.new
box_btns.pack_start(@btn_add, false)
box_btns.pack_start(@btn_del, false)
box_btns.pack_end(@btn_quit, false)
@status = Gtk::Statusbar.new
self.create_list
box_main = Gtk::VBox.new
box_main.pack_start(@list_view, true)
box_main.pack_end(@status, false)
box_main.pack_end(box_btns, false)
@win.add(box_main)
@win.show_all
end
def create_list
@list_store = Gtk::ListStore.new(
Integer, String, String, String, String, String, String)
@list_view = Gtk::TreeView.new(@list_store)
fields = [ "First name", "Last name", "Email", "Address",
"Phone", "JabberID" ]
fields.each_index do |i|
renderer = Gtk::CellRendererText.new
@list_view.append_column(
Gtk::TreeViewColumn.new(fields[i], renderer, :text => i+1))
renderer.editable = true
renderer.signal_connect("edited") do |r, path, text|
@list_store.set_value(@list_store.get_iter(path), i+1, text)
end
end
#@list_view.headers_clickable = true
#@list_store.set_sort_column_id(2)
@list_view.selection.mode = Gtk::SELECTION_MULTIPLE
@list_view.selection.signal_connect("changed") do |sel|
if sel.count_selected_rows < 1
@btn_del.sensitive = false
else
@btn_del.sensitive = true
end
end
@btn_del.sensitive = false
Person.find_all.each do |p|
elem = @list_store.append
p.to_a.each_index { |i| elem[i] = p.to_a[i] }
end
#@list_view.selection.select_path(Gtk::TreePath.new "0")
@list_store.signal_connect("row-changed") do |store, path, iter|
p = Person.find(iter[0])
p.first_name = iter[1]
p.last_name = iter[2]
p.email = iter[3]
p.address = iter[4]
p.phone = iter[5]
p.jabberid = iter[6]
p.save
end
@list_store.signal_connect("row-inserted") do |store, path, iter|
p = Person.new
p.save
iter[0] = p.id
end
@list_store.signal_connect("row-deleted") do |store, path|
# ustaw zaznaczenie
@list_view.set_cursor(path, nil, false) if @list_store.get_iter(path)
if !@list_view.selection.path_is_selected? path
path.prev!
@list_view.set_cursor(path, nil, false) if @list_store.get_iter(path)
end
end
@btn_add.signal_connect("clicked") do
elem = @list_store.append
@list_view.set_cursor(elem.path, @list_view.get_column(0), true)
end
@btn_del.signal_connect("clicked") do
to_remove = []
@list_view.selection.selected_each do |model, path, iter|
to_remove.push(Gtk::TreeRowReference.new(model, path))
end
to_remove.each do |ref|
iter = @list_store.get_iter(ref.path)
Person.delete(iter[0])
@list_store.remove(iter)
end
end
end
end
AddressBookApp.new
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment