1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
| require 'gtk3'
require 'sqlite3'
# Create or open an SQLite3 database
db = SQLite3::Database.new "test.db"
# Create a simple table if it doesn't already exist
db.execute <<-SQL
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT,
email TEXT
);
SQL
# GTK Application
class CrudApp
def initialize
@builder = Gtk::Builder.new
create_window
setup_signals
@db = SQLite3::Database.new "test.db"
refresh_users_list
end
def create_window
@window = Gtk::Window.new("Ruby SQLite CRUD App with Search")
@window.set_size_request(400, 400)
@window.signal_connect("destroy") { Gtk.main_quit }
# Create a vertical box layout
vbox = Gtk::Box.new(:vertical, 10)
vbox.margin = 20
# Entry field for search
@search_entry = Gtk::Entry.new
@search_entry.placeholder_text = "Search users by name or email"
@search_entry.signal_connect("changed") { search_users } # Trigger search on input change
vbox.pack_start(@search_entry, expand: false, fill: true, padding: 5)
# Entry fields for name and email
@name_entry = Gtk::Entry.new
@name_entry.placeholder_text = "Enter name"
vbox.pack_start(@name_entry, expand: false, fill: true, padding: 5)
@email_entry = Gtk::Entry.new
@email_entry.placeholder_text = "Enter email"
vbox.pack_start(@email_entry, expand: false, fill: true, padding: 5)
# Buttons for CRUD operations
hbox = Gtk::Box.new(:horizontal, 10)
add_button = Gtk::Button.new(label: "Add")
add_button.signal_connect("clicked") { add_user }
hbox.pack_start(add_button, expand: true, fill: true, padding: 5)
update_button = Gtk::Button.new(label: "Update")
update_button.signal_connect("clicked") { update_user }
hbox.pack_start(update_button, expand: true, fill: true, padding: 5)
delete_button = Gtk::Button.new(label: "Delete")
delete_button.signal_connect("clicked") { delete_user }
hbox.pack_start(delete_button, expand: true, fill: true, padding: 5)
vbox.pack_start(hbox, expand: false, fill: true, padding: 5)
# Create a grid to hold the column labels and user list
grid = Gtk::Grid.new
grid.row_spacing = 10
grid.column_spacing = 20
# Column labels
name_label = Gtk::Label.new("Name")
email_label = Gtk::Label.new("Email")
name_label.set_xalign(0) # Align labels to the left
email_label.set_xalign(0)
# Add column labels to the grid
grid.attach(name_label, 0, 0, 1, 1)
grid.attach(email_label, 1, 0, 1, 1)
# Listbox for displaying users
@listbox = Gtk::ListBox.new
grid.attach(@listbox, 0, 1, 2, 1) # Listbox spans across both columns
vbox.pack_start(grid, expand: true, fill: true, padding: 5)
# Add the layout to the window
@window.add(vbox)
@window.show_all
end
def setup_signals
@window.signal_connect("destroy") { Gtk.main_quit }
end
def add_user
name = @name_entry.text
email = @email_entry.text
if name.empty? || email.empty?
show_message("Name and Email cannot be empty!")
return
end
@db.execute("INSERT INTO users (name, email) VALUES (?, ?)", [name, email])
refresh_users_list
clear_entries
end
def update_user
selected_row = @listbox.selected_row
return unless selected_row
user_id = selected_row.instance_variable_get(:@user_id)
name = @name_entry.text
email = @email_entry.text
if name.empty? || email.empty?
show_message("Name and Email cannot be empty!")
return
end
@db.execute("UPDATE users SET name = ?, email = ? WHERE id = ?", [name, email, user_id])
refresh_users_list
clear_entries
end
def delete_user
selected_row = @listbox.selected_row
return unless selected_row
user_id = selected_row.instance_variable_get(:@user_id)
@db.execute("DELETE FROM users WHERE id = ?", [user_id])
refresh_users_list
clear_entries
end
def search_users
search_query = @search_entry.text.downcase
return refresh_users_list if search_query.empty? # Reset list if search is empty
@listbox.each { |child| @listbox.remove(child) } # Clear current list
# Query the database for matching users based on search query (name or email)
@db.execute("SELECT * FROM users WHERE LOWER(name) LIKE ? OR LOWER(email) LIKE ?", ["%#{search_query}%", "%#{search_query}%"]) do |row|
list_row = Gtk::ListBoxRow.new
list_row.instance_variable_set(:@user_id, row[0]) # Save user id for update/delete actions
row_box = Gtk::Box.new(:horizontal, 20)
name_label = Gtk::Label.new(row[1])
name_label.set_xalign(0)
email_label = Gtk::Label.new(row[2])
email_label.set_xalign(0)
row_box.pack_start(name_label, expand: true, fill: true, padding: 10)
row_box.pack_start(email_label, expand: true, fill: true, padding: 10)
list_row.add(row_box)
@listbox.add(list_row)
end
@listbox.show_all
end
def refresh_users_list
@listbox.each { |child| @listbox.remove(child) } # Clear current list
@db.execute("SELECT * FROM users") do |row|
list_row = Gtk::ListBoxRow.new
list_row.instance_variable_set(:@user_id, row[0]) # Save user id for update/delete actions
row_box = Gtk::Box.new(:horizontal, 20)
name_label = Gtk::Label.new(row[1])
name_label.set_xalign(0)
email_label = Gtk::Label.new(row[2])
email_label.set_xalign(0)
row_box.pack_start(name_label, expand: true, fill: true, padding: 10)
row_box.pack_start(email_label, expand: true, fill: true, padding: 10)
list_row.add(row_box)
@listbox.add(list_row)
end
@listbox.show_all
end
def clear_entries
@name_entry.text = ''
@email_entry.text = ''
end
def show_message(message)
dialog = Gtk::MessageDialog.new(
parent: @window,
flags: :destroy_with_parent,
type: :info,
buttons_type: :close,
message: message
)
dialog.run
dialog.destroy
end
end
# Run the application
app = CrudApp.new
Gtk.main
|