Back to Home

Ruby + Qt4, a simple text editor, part 2

ruby · Qt4

Ruby + Qt4, a simple text editor, part 2

    In a previous post ( f3ex.habrahabr.ru/blog/54673 ) I wrote how to write “simple text editor” using ruby ​​and Qt4.
    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.

    image



    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
    1. require 'Qt4'
    2. require 'editor.rb'
    3.  
    4. class StartQT4 < Qt::MainWindow
    5.  
    6.   slots 'file_dialog()', 'file_save()', 'enable_save()'
    7.  
    8.   def initialize parent=nil
    9.     super
    10.     @ui = Ui_Notepad.new
    11.     @ui.setupUi self
    12.     Qt::Object.connect(@ui.b_open, SIGNAL('clicked()'), self, SLOT('file_dialog()'))
    13.     Qt::Object.connect(@ui.b_save, SIGNAL('clicked()'), self, SLOT('file_save()'))
    14.     Qt::Object.connect(@ui.editor_window, SIGNAL('textChanged()'), self, SLOT('enable_save()'))
    15.   end
    16.  
    17.   def file_dialog
    18.     f = Qt::FileDialog
    19.     if @filename = f.getOpenFileName
    20.       text = File.new(@filename).read
    21.       @ui.editor_window.setText text
    22.       #Вставка текста в форму деактивирует кнопку и
    23.       #начинает "слежку" за изменением текст textChanged()
    24.       @ui.b_save.setEnabled false
    25.     end
    26.   end
    27.  
    28.   def enable_save
    29.     @ui.b_save.setEnabled true
    30.   end
    31.  
    32.   def file_save
    33.     if @filename
    34.       f = File.new @filename, 'w'
    35.       f.puts @ui.editor_window.toPlainText
    36.       f.close
    37.     end
    38.   end
    39. end
    40.  
    41. if $0 == __FILE__
    42.     app = Qt::Application.new(ARGV)
    43.     myapp = StartQT4.new
    44.     myapp.show
    45.     app.exec
    46. 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
    1. Qt::Object.connect(@ui.editor_window, SIGNAL('textChanged()'), self, SLOT('enable_save()'))


    Copy Source | Copy HTML
    1. def enable_save
    2.   @ui.b_save.setEnabled true
    3. end


    In the file_dialog method, when we add text to textEdit from a file, we deactivate the button:
    Copy Source | Copy HTML
    1. @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
    1. message = Qt::MessageBox.new
    2. message.exec


    image

    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
    1. require 'Qt4'
    2. require 'editor.rb'
    3.  
    4. class StartQT4 < Qt::MainWindow
    5.  
    6.   slots 'file_dialog()', 'file_save()', 'enable_save()'
    7.  
    8.   def initialize parent=nil
    9.     super
    10.     @ui = Ui_Notepad.new
    11.     @ui.setupUi self
    12.     Qt::Object.connect(@ui.b_open, SIGNAL('clicked()'), self, SLOT('file_dialog()'))
    13.     Qt::Object.connect(@ui.b_save, SIGNAL('clicked()'), self, SLOT('file_save()'))
    14.     Qt::Object.connect(@ui.editor_window, SIGNAL('textChanged()'), self, SLOT('enable_save()'))
    15.   end
    16.  
    17.   def file_dialog
    18.     response = false
    19.     # Текст кнопок:                                                                            
    20.     save = 'Сохранить'
    21.     discard = 'Не сохранять'
    22.     cancel = 'Отменить'
    23.     #Если были изменения вызываем message_box                                                  
    24.     if @ui.b_save.isEnabled && @filename
    25.       message = Qt::MessageBox.new
    26.       message.setText 'Что следует сделать с несохраненными изменениями ?'
    27.       message.setWindowTitle('Блокнот')
    28.       message.setIcon(Qt::MessageBox.Question)
    29.       message.addButton(save,Qt::MessageBox.AcceptRole)
    30.       message.addButton(discard,Qt::MessageBox.DestructiveRole)
    31.       message.addButton(cancel,Qt::MessageBox.RejectRole)
    32.       message.setDetailedText('Несохраненные изменения в файле: ' + @filename.to_s)
    33.       message.exec
    34.       response = message.clickedButton.text
    35.       #Сохраняем файл                                                                          
    36.       if response == save
    37.         file_save
    38.         @ui.b_save.setEnabled false
    39.       end
    40.       #Не сохранять
    41.       if response == discard
    42.         @ui.b_save.setEnabled false
    43.       end
    44.     end
    45.     #Если мы не хотим сохранять изменения
    46.     unless response == cancel
    47.       f = Qt::FileDialog
    48.       if @filename = f.getOpenFileName
    49.         text = File.new(@filename).read
    50.         @ui.editor_window.setText text
    51.         @ui.b_save.setEnabled false
    52.       end
    53.     end
    54.   end
    55.  
    56.   def enable_save
    57.     @ui.b_save.setEnabled true
    58.   end
    59.  
    60.   def file_save
    61.     if @filename
    62.       f = File.new @filename, 'w'
    63.       f.puts @ui.editor_window.toPlainText
    64.       f.close
    65.     end
    66.   end
    67. end
    68.  
    69. if $0 == __FILE__
    70.     app = Qt::Application.new(ARGV)
    71.     myapp = StartQT4.new
    72.     myapp.show
    73.     app.exec
    74. 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:

    image

    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

    Read Next