Ruby + Qt4, a simple text editor, part 2
Continuation of porting examples from Python + Qt4 to Ruby + Qt4
Part 2.
Now we will consider the following question: when a file is not selected or no changes are made to the text, the save button should be inactive.
The “enabled” property in Qt Disigner is responsible for the activity, or this property can be set from the ruby code using the setEnabled method.
Set the enabled property for the b_save button to false (uncheck) and regenerate the editor.rb form.

To find out that the text has changed, we will use the textChanged () signal for textEdit.
Let's change the start.rb code to the following:
Copy Source | Copy HTML- require 'Qt4'
- require 'editor.rb'
-
- class StartQT4 < Qt::MainWindow
-
- slots 'file_dialog()', 'file_save()', 'enable_save()'
-
- def initialize parent=nil
- super
- @ui = Ui_Notepad.new
- @ui.setupUi self
- Qt::Object.connect(@ui.b_open, SIGNAL('clicked()'), self, SLOT('file_dialog()'))
- Qt::Object.connect(@ui.b_save, SIGNAL('clicked()'), self, SLOT('file_save()'))
- Qt::Object.connect(@ui.editor_window, SIGNAL('textChanged()'), self, SLOT('enable_save()'))
- end
-
- def file_dialog
- f = Qt::FileDialog
- if @filename = f.getOpenFileName
- text = File.new(@filename).read
- @ui.editor_window.setText text
- #Вставка текста в форму деактивирует кнопку и
- #начинает "слежку" за изменением текст textChanged()
- @ui.b_save.setEnabled false
- end
- end
-
- def enable_save
- @ui.b_save.setEnabled true
- end
-
- def file_save
- if @filename
- f = File.new @filename, 'w'
- f.puts @ui.editor_window.toPlainText
- f.close
- end
- end
- end
-
- if $0 == __FILE__
- app = Qt::Application.new(ARGV)
- myapp = StartQT4.new
- myapp.show
- app.exec
- end
What has been added. We have added a slot that is called when text is changed in textEdit and activates the button:
Copy Source | Copy HTML- Qt::Object.connect(@ui.editor_window, SIGNAL('textChanged()'), self, SLOT('enable_save()'))
Copy Source | Copy HTML- def enable_save
- @ui.b_save.setEnabled true
- end
In the file_dialog method, when we add text to textEdit from a file, we deactivate the button:
Copy Source | Copy HTML- @ui.b_save.setEnabled false
Now when we open a file, the changes in the current open file are not saved. You need to make a dialog box (message box), which will ask about the changes - "save", "do not save" or "cancel". For these purposes we will use MessageBox.
The message box call is as follows
Copy Source | Copy HTML- message = Qt::MessageBox.new
- message.exec

You need to configure this window. We will add buttons and some text. But how do we do this? We need to edit the file_dialog method, and if changes have been made, show the message. How do we know if there have been changes? If the “save” button is active (@ ui.b_save.idEnabled) - then we have unsaved changes. And so, make the changes:
Copy Source | Copy HTML- require 'Qt4'
- require 'editor.rb'
-
- class StartQT4 < Qt::MainWindow
-
- slots 'file_dialog()', 'file_save()', 'enable_save()'
-
- def initialize parent=nil
- super
- @ui = Ui_Notepad.new
- @ui.setupUi self
- Qt::Object.connect(@ui.b_open, SIGNAL('clicked()'), self, SLOT('file_dialog()'))
- Qt::Object.connect(@ui.b_save, SIGNAL('clicked()'), self, SLOT('file_save()'))
- Qt::Object.connect(@ui.editor_window, SIGNAL('textChanged()'), self, SLOT('enable_save()'))
- end
-
- def file_dialog
- response = false
- # Текст кнопок:
- save = 'Сохранить'
- discard = 'Не сохранять'
- cancel = 'Отменить'
- #Если были изменения вызываем message_box
- if @ui.b_save.isEnabled && @filename
- message = Qt::MessageBox.new
- message.setText 'Что следует сделать с несохраненными изменениями ?'
- message.setWindowTitle('Блокнот')
- message.setIcon(Qt::MessageBox.Question)
- message.addButton(save,Qt::MessageBox.AcceptRole)
- message.addButton(discard,Qt::MessageBox.DestructiveRole)
- message.addButton(cancel,Qt::MessageBox.RejectRole)
- message.setDetailedText('Несохраненные изменения в файле: ' + @filename.to_s)
- message.exec
- response = message.clickedButton.text
- #Сохраняем файл
- if response == save
- file_save
- @ui.b_save.setEnabled false
- end
- #Не сохранять
- if response == discard
- @ui.b_save.setEnabled false
- end
- end
- #Если мы не хотим сохранять изменения
- unless response == cancel
- f = Qt::FileDialog
- if @filename = f.getOpenFileName
- text = File.new(@filename).read
- @ui.editor_window.setText text
- @ui.b_save.setEnabled false
- end
- end
- end
-
- def enable_save
- @ui.b_save.setEnabled true
- end
-
- def file_save
- if @filename
- f = File.new @filename, 'w'
- f.puts @ui.editor_window.toPlainText
- f.close
- end
- end
- end
-
- if $0 == __FILE__
- app = Qt::Application.new(ARGV)
- myapp = StartQT4.new
- myapp.show
- app.exec
- end
Changes made to lines 18-46.
We create a new instance of the Qt :: MessageBox class, assign the message text (setText), the window title setWindowTitle, the icon (setIcon), set 3 buttons (“save”, “do not save” and “cancel”) . As the second argument, we set the types of buttons (role). Information on these types can be found in the QT documentation. setDetailedText sets the detailed message output when the "show details" button is clicked. And in the end, we call the exec method. message.clickedButton - Returns a pushButton type of the pressed button. In the example, we simply operate with the text of this button.
The dialog box looks something like this:

The source codes for the example can be downloaded on the page:
Previous example: narod.ru/disk/6746280000/ruby_qt_simple_editor_1.zip.html
Current example: narod.ru/disk/6746302000/ruby_qt_simple_editor_2.zip.html
Porting the following example to ruby: www.rkblog.rk.edu.pl/w/p/extending-pyqt4-text-editor