Class: Nametrainer::GUI

Inherits:
Qt::Widget
  • Object
show all
Defined in:
lib/nametrainer/gui.rb

Overview

Class for the application window.

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ GUI

Initializes the application window. You can specify a collection that is loaded at startup.

collection_dir - path to collection



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
# File 'lib/nametrainer/gui.rb', line 12

def initialize(options)
  super()

  set_window_title 'Name Trainer'
  resize 600, 500

  # the common variables
  @collection_dir = nil
  @collection = nil
  @person = nil
  @statistics = Nametrainer::Statistics.new

  # the common widgets
  @collection_label = Qt::Label.new '<i>No collection loaded</i>'
  @image_label = Qt::Label.new
  @image = Qt::Pixmap.new
  @name_label = Qt::Label.new
  @statistics_label = Qt::Label.new @statistics.to_s
  @ordered_checkbox = Qt::CheckBox.new 'Non-random order'
  @display_checkbox = Qt::CheckBox.new "Display name at once"

  if options[:learning_mode]
    @ordered_checkbox.set_checked true
    @display_checkbox.set_checked true
  end

  init_gui
  show

  collection_dir = options[:collection]
  init_collection File.expand_path(collection_dir)  if collection_dir
end

Instance Method Details

#choose_personObject

Chooses and displays the next person, erases the displayed name, and enables the Display Name button. “Next” means a random sample or, if the Non-random order checkbox is checked, the successor of the current person in the collection array.



239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/nametrainer/gui.rb', line 239

def choose_person
  @name_label.set_text ''
  if @ordered_checkbox.is_checked
    @person = @collection.successor(@person)
  else
    @person = @collection.sample
  end
  @image.load @person.image or @image = Qt::Pixmap.new  # delete image when load fails
  show_image
  enable_buttons
  display_name  if @display_checkbox.is_checked
end

#correct_answerObject

Called when Correct button is clicked.



192
193
194
# File 'lib/nametrainer/gui.rb', line 192

def correct_answer
  handle_answer(:correct)
end

#disable_buttonsObject

Disables the buttons that are only needed when a collection is loaded.



156
157
158
159
160
# File 'lib/nametrainer/gui.rb', line 156

def disable_buttons
  @correct.set_enabled false
  @wrong.set_enabled false
  @show.set_enabled false
end

#display_nameObject

Displays the name of the shown person and disables the Display Name button.



180
181
182
183
184
185
186
187
188
189
# File 'lib/nametrainer/gui.rb', line 180

def display_name
  # convert name string from utf-8 to latin1 (for QLabel)
  if RUBY_VERSION < '1.9'
    name_latin1 = Iconv.conv('LATIN1', 'UTF-8', @person.name)
  else
    name_latin1 = @person.name.encode('ISO-8859-1', 'UTF-8')
  end
  @name_label.set_text name_latin1
  @show.set_enabled false
end

#enable_buttonsObject

Enables the buttons that are only needed when a collection is loaded.



163
164
165
166
167
# File 'lib/nametrainer/gui.rb', line 163

def enable_buttons
  @correct.set_enabled true
  @wrong.set_enabled true
  @show.set_enabled true
end

#handle_answer(answer) ⇒ Object

Handles correct and wrong answers, and chooses the next person.

answer - :correct or :wrong



204
205
206
207
208
# File 'lib/nametrainer/gui.rb', line 204

def handle_answer(answer)
  update_statistics(answer)
  update_scores(answer)
  choose_person
end

#init_collection(collection_dir) ⇒ Object

Tries to load a collection (does not change anything if load fails).

collection_dir - path to collection



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/nametrainer/gui.rb', line 136

def init_collection(collection_dir)
  args = {
    :directory  => collection_dir,
    :extensions => Nametrainer::FILE_EXTENSIONS
  }
  collection = Nametrainer::CollectionLoader.load(args)
  if collection.nil? or collection.empty?
    Qt::MessageBox.warning self, 'Error', Nametrainer.collection_empty_message
    return
  end
  @collection_dir = collection_dir
  @collection = collection
  @collection_label.set_text "Collection: #{File.basename(@collection_dir)}"
  @statistics.reset
  @statistics_label.set_text @statistics.to_s
  @person = nil
  choose_person
end

#init_guiObject

Initializes the GUI layout and functions.



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
# File 'lib/nametrainer/gui.rb', line 46

def init_gui
  name_fontsize = 24
  name_font = Qt::Font.new { setPointSize name_fontsize }
  @name_label.set_font name_font
  @image_label.set_size_policy Qt::SizePolicy::Ignored, Qt::SizePolicy::Ignored

  # create buttons
  @show = Qt::PushButton.new '&Display Name', self do
    #set_tool_tip 'S'
    set_shortcut Qt::KeySequence.new(Qt::Key_D.to_i)
  end
  @correct = Qt::PushButton.new 'Correct', self do
    #set_tool_tip 'F'
    set_shortcut Qt::KeySequence.new(Qt::Key_S.to_i)
  end
  @wrong = Qt::PushButton.new 'Wrong', self do
    #set_tool_tip 'D'
    set_shortcut Qt::KeySequence.new(Qt::Key_F.to_i)
  end
  load_collection = Qt::PushButton.new '&Load Collection', self do
    #set_tool_tip 'L'
    set_shortcut Qt::KeySequence.new(Qt::Key_L.to_i)
  end
  help = Qt::PushButton.new '&Help', self do
    #set_tool_tip 'H'
    set_shortcut Qt::KeySequence.new(Qt::Key_H.to_i)
  end
  quit = Qt::PushButton.new 'Quit', self do
    #set_tool_tip 'Ctrl+W'
    set_shortcut Qt::KeySequence.new(Qt::CTRL.to_i + Qt::Key_W.to_i)
  end

  # Connect the buttons to slots.
  connect load_collection, SIGNAL(:clicked), self, SLOT(:load_collection)
  connect quit, SIGNAL(:clicked), self, SLOT(:quit)
  connect help, SIGNAL(:clicked), self, SLOT(:show_help)
  connect @correct, SIGNAL(:clicked), self, SLOT(:correct_answer)
  connect @wrong, SIGNAL(:clicked), self, SLOT(:wrong_answer)
  connect @show, SIGNAL(:clicked), self, SLOT(:display_name)

  # Start with buttons disabled.
  disable_buttons

  # Create the layout.
  vbox = Qt::VBoxLayout.new self
  mainbox = Qt::HBoxLayout.new

  vbox.add_widget @collection_label

  left = Qt::VBoxLayout.new
  left.add_widget @image_label, 1
  left.add_widget @name_label

  answer_buttons = Qt::HBoxLayout.new
  answer_buttons.add_widget @correct
  answer_buttons.add_widget @wrong

  right = Qt::VBoxLayout.new
  right.add_widget @show
  right.add_layout answer_buttons
  right.add_stretch 1
  right.add_widget Qt::Label.new 'Statistics:'
  right.add_widget @statistics_label
  right.add_stretch 1
  right.add_widget @ordered_checkbox
  right.add_widget @display_checkbox
  right.add_stretch 1
  right.add_widget load_collection
  right.add_widget help
  right.add_widget quit

  mainbox.add_layout left, 1
  mainbox.add_layout right

  vbox.add_layout mainbox

  set_layout vbox
end

#load_collectionObject

Opens a file dialog and tries to load a collection.



128
129
130
131
# File 'lib/nametrainer/gui.rb', line 128

def load_collection
  collection_dir = Qt::FileDialog.get_existing_directory self, 'Load Collection'
  init_collection File.expand_path(collection_dir)  if collection_dir
end

#quitObject

Quits application.



170
171
172
# File 'lib/nametrainer/gui.rb', line 170

def quit
  Qt::Application.instance.quit
end

#resizeEvent(event) ⇒ Object

Repaints the image when the application window is resized.



253
254
255
256
257
# File 'lib/nametrainer/gui.rb', line 253

def resizeEvent(event)
  return  if (@image.nil? || @image.null?)
  scaledSize = @image.size.scale(@image_label.size, Qt::KeepAspectRatio)
  show_image  if scaledSize != @image_label.pixmap.size
end

#show_helpObject

Shows the help window.



175
176
177
# File 'lib/nametrainer/gui.rb', line 175

def show_help
  Qt::MessageBox.about self, 'Help', Nametrainer.help_message
end

#show_imageObject

Displays the image, scaled as large as possible.



227
228
229
230
231
232
233
# File 'lib/nametrainer/gui.rb', line 227

def show_image
  if @image.null?
    @image_label.set_text "<i>Unable to display `#{File.basename(@person.image)}'.</i>"
  else
    @image_label.set_pixmap @image.scaled(@image_label.size, Qt::KeepAspectRatio)
  end
end

#update_scores(answer) ⇒ Object

Increases the score for correctly recognized persons.



222
223
224
# File 'lib/nametrainer/gui.rb', line 222

def update_scores(answer)
  @person.increase_score  if answer == :correct
end

#update_statistics(answer) ⇒ Object

Updates the statistics depending on answer.



211
212
213
214
215
216
217
218
219
# File 'lib/nametrainer/gui.rb', line 211

def update_statistics(answer)
  case answer
  when :correct
    @statistics.correct += 1
  when :wrong
    @statistics.wrong += 1
  end
  @statistics_label.set_text @statistics.to_s
end

#wrong_answerObject

Called when Wrong button is clicked.



197
198
199
# File 'lib/nametrainer/gui.rb', line 197

def wrong_answer
  handle_answer(:wrong)
end