* Added command line tool example similar to 'sopranocmd'
[kdebindings.git] / ruby / qtruby / README
blob521a5bf571b8d9778259fe0266955371ace8dfc9
1 /***************************************************************************
2  *      (C) 2003-2007 Richard Dale All rights reserved.                        *
3  *                                                                         *
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.                       *
8  *                                                                         *
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
18 >> Python?
19 >> 
20 >> Ruby smells better than Python. Also, it has cuter girls.
21 >> 
22 >> Python sometimes tastes better if you prepare it right.
23
24 > I hadn't noticed the odor thing. It does have a faintly floral aroma
25 > doesn't it.
26
27 > Of course it is no surprise that you can get more and cuter girls with
28 > Rubies than you can with Pythons.
29
30 > Scott
32 So there you have it! :)
34 Here is 'Hello World' in QtRuby:
36 #!/usr/bin/ruby -w
38 require 'Qt'
40 a = Qt::Application.new(ARGV)
41 hello = Qt::PushButton.new("Hello World!")
42 hello.resize(100, 30)
43 hello.show
44 a.exec
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
54                 such as bitBlt() etc
55                 
56         - Virtual methods
57                 All virtual methods can be overriden, not just event handlers
58                 
59         - Properties 
60                 'fooBar = 5' is a synonym for 'setFooBar(5)'
61                 
62         - Predicates
63                 'if foo?' is a synonym for 'if isFoo()' or 'if hasFoo()'
64                 
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:
69                 
70                 create_standard_status_bar_action()
71                 
72                 createStandardStatusBarAction()
73                 
74         - Operator overloading
75                 The full range of Qt operator methods is available, for example:
76                 
77                         p1 = Qt::Point.new(5,5)   => (5, 5)
78                         p2 = Qt::Point.new(20,20) => (20, 20)
79                         p1 + p2                   => (25, 25)
80                         
81         - Declare signals and slots
82                 Signals and slots are declared as list of strings like this:
83                 
84                         slots 'setColor(QColor)', 'slotLoad(const QString&)'..
85                         signals 'clicked()'..
86                         
87                 If the slots or signal have no arguments they can also be declared as
88                         Symbols:
90                         slots :click, :toggle
91                         signals :clicked
93                 Currently C++ type signatures must be used, a future version of QtRuby
94                         will allow ruby type signatures instead.
95                 
96                 Connect slots and signals like this:
97                                         
98                         Qt::Object.connect( @_colormenu, SIGNAL( "activated( int )" ),
99                                                                 self, SLOT( "slotColorMenu( int )" ) )
100         
101                 And emit signals like this:
102                 
103                         emit colorChanged( black )
105         - Constructors
106                 You can call constructors in the conventional style:
107                 
108                     quit = Qt::PushButton.new("Quit", self, "quit")
109                         
110                 Or you can pass a block if you prefer:
111                 
112                         w = MyWidget.new { setCaption("foobar") }
113                         
114                 The block will be called in the context of the newly created instance.
115                 
116                 Ordinary arguments can be provided as well as a block at the end:
117                         
118                         w = MyWidget.new(nil) { setCaption("foobar") }
119                         
120                 They are run in the context of the new instance.
121                 
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:
124                         
125                         w = MyWidget.new { |theWidget| theWidget.setCaption "foobar" }
126                         
127         - Garbage Collection
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:
132                 
133                         item2.dispose
134                         if item2.isDisposed
135                                 puts "item2 is disposed"
136                         end
137                         
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()':
142                 
143                         # static Ptr findByFileContent( const QString &fileName, int *accuracy=0 );
145                         acc = Qt::Integer.new(0)
146                 fc = KDE::MimeType.findByFileContent("mimetype.rb", acc)
147                 
148                 It supports the arithmetic operators, and so expressions such as 'acc + 3' will work.
149         
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
152                 used like this:
153                 
154                         # QFont getFont(bool * ok, const QFont&initial, QWidget* parent = 0, const char *name = 0);             
155                 
156                         ok = Qt::Boolean.new
157                         font = Qt::FontDialog.getFont(ok, Qt::Font.new("Helvetica [Cronyx]", 10), self)
158                         if !ok.nil? 
159                         # font is set to the font the user selected
160                         else 
161                         # the user canceled the dialog
162                         end
163                 
164                 Use 'nil?' to test the value returned in the Boolean
166         - Debugging
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:
169                 
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:
175                 
176                         classname    == QApplication
177                         :: method == loadLibrary$
178                         -> methodIds == []
179                         candidate list:
180                         Possible prototypes:
181                                 static QWidget* QApplication::widgetAt(int, int, bool)
182                                         ...
183                 
184                 Here, the list of candidate methods 'methodIds' is empty
185                 
186                 Another debugging mechanism allows various trace 'channels' to be switched on.
187                 
188                 You can trace virtual method callbacks:
189                     Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_VIRTUAL)
190                         
191                 Or trace QtRuby garbage collection:
192                     Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_GC)
193                 
194         - String i18n 
195         
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.
200         
201         - Qt Designer
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:
206                 
207                 $ rbuic4 mainwindowbase.ui -x -o mainwindowbase.rb
208                 
209                 Will add this to the end of the generated code:
211                         if $0 == __FILE__
212                                 a = Qt::Application.new(ARGV)
213                                 u = Ui_MainWindowBase.new
214                                 w = Qt::MainWindow.new
215                                 u.setupUi(w)
216                                 w.show
217                                 a.exec
218                         end
219                         
220                 Then you can test the example code straight away:
221                         
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,
226                 for example:
227                 
228                         require 'Qt'
229                         ...
231                         loader = Qt::UiLoader.new
232                         
233                         file = Qt::File.new(":/forms/calculatorform.ui")
234                         file.open(Qt::File::ReadOnly)
235                         formWidget = loader.load(file, self)
236                         file.close
237                         
238                         @ui_inputSpinBox1 = findChild(Qt::SpinBox, "inputSpinBox1")
239                         @ui_inputSpinBox2 = findChild(Qt::SpinBox, "inputSpinBox2")
240                         @ui_outputWidget = findChild(Qt::Label, "outputWidget")
241                         
242                         Qt::MetaObject.connectSlotsByName(self)
243                         
244                         self.layout = Qt::VBoxLayout.new do |l|
245                                 l.addWidget(formWidget)
246                         end
248         - API reference
249                 Use the bin/rbqtapi tool to discover which methods are available in
250                 the QtRuby api.
251                         
252         - Example programs
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
262 Have Fun!
264 -- Richard