1 /***************************************************************************
2 * (C) 2003-2007 Richard Dale All rights reserved. *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as *
6 * published by the Free Software Foundation; either version 2 of the *
7 * License, or (at your option) any later version. *
9 ***************************************************************************/
11 Here is a Ruby SMOKE adaptor for Qt
13 Why ruby? From the rubytalk list
15 On 8/28/03 8:56 PM, "Scott Thompson" wrote:
17 >> : Can anyone give me a good reason why I would want to use Ruby over
20 >> Ruby smells better than Python. Also, it has cuter girls.
22 >> Python sometimes tastes better if you prepare it right.
24 > I hadn't noticed the odor thing. It does have a faintly floral aroma
27 > Of course it is no surprise that you can get more and cuter girls with
28 > Rubies than you can with Pythons.
32 So there you have it! :)
34 Here is 'Hello World' in QtRuby:
40 a = Qt::Application.new(ARGV)
41 hello = Qt::PushButton.new("Hello World!")
46 Ruby 1.8 is unfortunately implicitly required as with 1.6.x it is not possible to:
48 Make dynamic constants available (thus forcing syntax such as Qt.RichText rather than Qt::RichText)<br>
49 Call super in the initialize method thus making subclassing of non trivial classes impossible
51 QtRuby features a very complete coverage of the Qt api:
53 - You can call all Qt public and protected methods, and all friend methods
57 All virtual methods can be overriden, not just event handlers
60 'fooBar = 5' is a synonym for 'setFooBar(5)'
63 'if foo?' is a synonym for 'if isFoo()' or 'if hasFoo()'
65 - Use underscore naming for method names instead of camel case if you
66 prefer. Any underscores in method names are removed, and the following
67 character is capitalised. For example, you can use either of these two
68 forms to call the same method:
70 create_standard_status_bar_action()
72 createStandardStatusBarAction()
74 - Operator overloading
75 The full range of Qt operator methods is available, for example:
77 p1 = Qt::Point.new(5,5) => (5, 5)
78 p2 = Qt::Point.new(20,20) => (20, 20)
81 - Declare signals and slots
82 Signals and slots are declared as list of strings like this:
84 slots 'setColor(QColor)', 'slotLoad(const QString&)'..
87 If the slots or signal have no arguments they can also be declared as
93 Currently C++ type signatures must be used, a future version of QtRuby
94 will allow ruby type signatures instead.
96 Connect slots and signals like this:
98 Qt::Object.connect( @_colormenu, SIGNAL( "activated( int )" ),
99 self, SLOT( "slotColorMenu( int )" ) )
101 And emit signals like this:
103 emit colorChanged( black )
106 You can call constructors in the conventional style:
108 quit = Qt::PushButton.new("Quit", self, "quit")
110 Or you can pass a block if you prefer:
112 w = MyWidget.new { setCaption("foobar") }
114 The block will be called in the context of the newly created instance.
116 Ordinary arguments can be provided as well as a block at the end:
118 w = MyWidget.new(nil) { setCaption("foobar") }
120 They are run in the context of the new instance.
122 And there's more! You can also pass an arg to the block, and it will
123 be run in the context of the arg:
125 w = MyWidget.new { |theWidget| theWidget.setCaption "foobar" }
128 When a ruby instance is garbage collected, the underlying C++ instance will only be
129 deleted if it isn't 'owned' by a parent object. Normally this will 'just work', but
130 there are occasions when you need to delete the C++ ahead of garbage collection, and
131 whether or not it has a parent. Use the dispose() and isDisposed() methods like this:
135 puts "item2 is disposed"
138 - C++ 'int*' and 'int&' argument types
139 Ruby passes numeric values by value, and so they can't be changed when passed to a
140 method. The Qt::Integer class provides a mutable numeric type which does get updated
141 when passed as an argument. For example, this C++ method 'findByFileContent()':
143 # static Ptr findByFileContent( const QString &fileName, int *accuracy=0 );
145 acc = Qt::Integer.new(0)
146 fc = KDE::MimeType.findByFileContent("mimetype.rb", acc)
148 It supports the arithmetic operators, and so expressions such as 'acc + 3' will work.
150 - C++ 'bool*' and 'bool&' argument types
151 There is a similar problem for bool arg types, and the mutable Qt::Boolean class can be
154 # QFont getFont(bool * ok, const QFont&initial, QWidget* parent = 0, const char *name = 0);
157 font = Qt::FontDialog.getFont(ok, Qt::Font.new("Helvetica [Cronyx]", 10), self)
159 # font is set to the font the user selected
161 # the user canceled the dialog
164 Use 'nil?' to test the value returned in the Boolean
167 If a method call can't be matched in the Smoke library giving a 'method_missing'
168 error, you can turn on debugging to trace the matching process:
170 a = Qt::Application.new(ARGV)
171 Qt.debug_level = Qt::DebugLevel::High
172 a.loadLibrary("foo") # Non existent method
174 Will give the following output:
176 classname == QApplication
177 :: method == loadLibrary$
181 static QWidget* QApplication::widgetAt(int, int, bool)
184 Here, the list of candidate methods 'methodIds' is empty
186 Another debugging mechanism allows various trace 'channels' to be switched on.
188 You can trace virtual method callbacks:
189 Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_VIRTUAL)
191 Or trace QtRuby garbage collection:
192 Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_GC)
196 QtRuby supports $KCODE values of 'u', 'e' and
197 's' or the corresponding '-K' options from the command line. Qt Designer
198 .ui files have UTF-8 strings so if you use any 8 bit UTF-8 characters, you
199 will need to set $KCODE='u' or use the -Ku command line option.
202 A 'rbuic4' tool is included in tools/rbuic to compile
203 .ui files into ruby code. As described above, Qt Designer uses UTF-8.
204 In addition to the options in the original uic C++ utility an '-x' flag
205 has been added. This will generate a top level stub in the code:
207 $ rbuic4 mainwindowbase.ui -x -o mainwindowbase.rb
209 Will add this to the end of the generated code:
212 a = Qt::Application.new(ARGV)
213 u = Ui_MainWindowBase.new
214 w = Qt::MainWindow.new
220 Then you can test the example code straight away:
222 $ ruby mainwindowbase.rb
224 - Loading .ui files at runtime with Qt::UiLoader
225 You can load a Qt Designer .ui file at runtime with Qt::UiLoader,
231 loader = Qt::UiLoader.new
233 file = Qt::File.new(":/forms/calculatorform.ui")
234 file.open(Qt::File::ReadOnly)
235 formWidget = loader.load(file, self)
238 @ui_inputSpinBox1 = findChild(Qt::SpinBox, "inputSpinBox1")
239 @ui_inputSpinBox2 = findChild(Qt::SpinBox, "inputSpinBox2")
240 @ui_outputWidget = findChild(Qt::Label, "outputWidget")
242 Qt::MetaObject.connectSlotsByName(self)
244 self.layout = Qt::VBoxLayout.new do |l|
245 l.addWidget(formWidget)
249 Use the bin/rbqtapi tool to discover which methods are available in
253 The best way to start programming QtRuby is to look at some existing
254 code and start messing with it..
255 The are various samples under qtruby/examples.
257 - Optional QScintilla text editing widget support
258 Great for building your own ruby IDE..
260 - Optional Qwt scientific plotting library support