Archive for the ‘QT/KDE’ Category
Qt4 Ruby and Metaprogramming 0.1 – Wiring up slots automatically
In my attempts to learn Qt 4 and QtRuby, it’s pretty obvious that there’s a huge potential for doing Rails-like things, such as declaration by convention. To this end, here’s an example of what you can do with the code I’m writing: this loads a UI file and wires something up to the Open action:
class ActionOpenHandler < Qt::Object
slots "on_activated()"
def initialize(main = nil)
super
@main = main
end
def on_activated
path = nil
Qt::FileDialog.new do |fd|
path = fd.get_open_file_name()
end
return unless path
text = nil; File.open(path, ‘r’) {|f| text = f.read}
@main.findChild(Qt::TextEdit, "textBrowser").text = text
end
end
a = Qt::Application.new(ARGV)
QtSuperLoader.new.initialize_and_hook("./main.ui").show
a.exec
Next, I’m seeking to replace the ugly line "@main.findChild(Qt::TextEdit, "textBrowser").text = text" with the more palatable "@main.text_browser.text = text". However, this is a bit more tricky, because findChild creates strongly-typed objects – there may be some trickery to get around it though involving QMetaObject.
Here’s the files, including the code that supports it all: qttest.rb and Translator.ui
Don’t worry, I haven’t forgotten QtRuby on Win32!
I was planning on posting the same kind of tutorial for Win32 for using QtRuby, but I’m currently stuck as to how to get it to build. After fighting with random build glitches for three hours or so (making progress, slowly), I’m currently stuck here:
C:/MinGW/bin/g++.exe -IC:/Qt/4.3.0/include/QtDBus -IC:/Qt/4.3.0/include/QtTest
-IC:/Qt/4.3.0/include/QtUiTools -IC:/Qt/4.3.0/include/QtScript -IC:/Qt/4.3.0/in
clude/QtSvg -IC:/Qt/4.3.0/include/QtXml -IC:/Qt/4.3.0/include/QtSql -IC:/Qt/4.3.
0/include/QtOpenGL -IC:/Qt/4.3.0/include/QtNetwork -IC:/Qt/4.3.0/include/QtDesig
ner -IC:/Qt/4.3.0/include/QtDesigner -IC:/Qt/4.3.0/include/QtAssistant -IC:/Qt/4
.3.0/include/Qt3Support -IC:/Qt/4.3.0/include/QtGui -IC:/Qt/4.3.0/include/QtCore
-IC:\Qt\4.3.0\mkspecs/default -IC:/Qt/4.3.0/include/Qt -IC:/Qt/4.3.0/include C
:/Qt/4.3.0/lib/libQtCore4.a C:/Qt/4.3.0/lib/libQtNetwork4.a C:/Qt/4.3.0/lib/libQ
tSql4.a C:/Qt/4.3.0/lib/libQtXml4.a C:/Qt/4.3.0/lib/libQtGui4.a C:/Qt/4.3.0/lib/
libQtUiTools.a C:/Qt/4.3.0/lib/libQtSvg4.a C:/Qt/4.3.0/lib/libQtOpenGL4.a C:/Qt/
4.3.0/lib/libQt3Support4.a -o C:\Users\paulbe\AppData\Local\Temp/3428-qtguess C
:\Users\paulbe\AppData\Local\Temp/3428-qtguess.cpp
Compiler output:
C:\Users\paulbe\AppData\Local\Temp/3428-qtguess.cpp:8:2: warning: no newline at
end of file
C:\Users\paulbe\AppData\Local\Temp/ccMxaaaa.o(.text+0×147):3428-qtguess.cpp:
undefined reference to `_imp___ZN12QApplicationC1ERiPPci‘
C:\Users\paulbe\AppData\Local\Temp/ccMxaaaa.o(.text+0×154):3428-qtguess.cpp:
undefined reference to `QApplication::~QApplication()’
collect2: ld returned 1 exit status
Thoughts? It looks like I’ve got some sort of compiler mismatch (one library compiled with MSVC and one compiled with MinGW, probably). I have no idea where though, I’m 85% sure that Qt is compiled with MinGW
Update: Alright, the new plan is to compile everything from scratch, and see if I can get some better results.
Update 2: It’s definitely the compiler difference:
{ Snip! }
SYMBOL TABLE:
[ 0](sec 1)(fl 0×00)(ty 0)(scl 3) (nx 0) 0×00000000 .text
[ 1](sec 2)(fl 0×00)(ty 0)(scl 3) (nx 0) 0×00000000 .idata$7
[ 2](sec 3)(fl 0×00)(ty 0)(scl 3) (nx 0) 0×00000000 .idata$5
[ 3](sec 4)(fl 0×00)(ty 0)(scl 3) (nx 0) 0×00000000 .idata$4
[ 4](sec 5)(fl 0×00)(ty 0)(scl 3) (nx 0) 0×00000000 .idata$6
[ 5](sec 1)(fl 0×00)(ty 0)(scl 2) (nx 0) 0×00000000 __ZN12QApplicationC2ERiPPci
[ 6](sec 3)(fl 0×00)(ty 0)(scl 2) (nx 0) 0×00000000 __imp___ZN12QApplicationC2ERiPPci
[ 7](sec 0)(fl 0×00)(ty 0)(scl 2) (nx 0) 0×00000000 __head_QtGui4_dll
The compiler’s looking for __imp___ZN12QApplicationC1ERiPPci, but the precompiled library has C2. I don’t understand why Qt’s distributing a busted library – this would break even their samples in straight C++ – it’s possible that Mingw updated behind their back though.
Cross-platform UI with Qt4 and Ruby – Mac/Linux HOWTO
Today I’ve spent the day working on figuring out how to make UIs using Ruby and Qt4. If you haven’t heard of it, Qt4 is an awesome UI framework written in C++. Since C++ is way too much work, some great KDE devs wrote a bindings generator for Qt4 called qt4-qtruby. While this package is fairly “linuxy”, it’s pretty easy to build it on Mac OS X too, making it possible to write GUI programs for OS X without having to delve into RubyCocoa which has too much hackiness (in my opinion), or even worse, Objective C. Furthermore, your code that you write on OS X will look great on Windows and Linux too!
Starting from scratch
First, install Ruby. If you’re using Linux, you’ll probably use the package manager to install Ruby and the Ruby development libraries! (Ubuntu will run sudo apt-get install ruby irb ruby-dev) OS X Tiger ships with Ruby by default, but you’ll want to install an updated version, via the Ruby one-click installer, then disable the old Ruby by using the following command:
touch ~/.bashrc && echo ‘export PATH="/usr/local/bin:$PATH"’ >> ~/.bashrc
sudo mv /usr/lib/libruby.1.dylib /usr/lib/_libruby.1.dylib
Installing Qt4 and QtRuby
First, install Qt4 by using your package manager on Linux (in Ubuntu, use the -kdecopy packages, they are more up to date), or by downloading the DMG from the Qt/Mac Open Source Edition Download page. You’ll also need MacPorts (and by proxy, the XCode tools). Also, download the Qt4 Ruby bindings source code from Rubyforge and save it to the Desktop.
Here’s the cool thing about QtRuby, and the advantage of building it from source: the build framework for QtRuby scans through whatever version of Qt you have installed, and dynamically builds the bindings. This means, there’s no waiting for new Qt features to be available in Ruby, it’s always up-to-date! Which is quite handy, because it seems like every minor version of Qt has new cool stuff.
Next, we have to do a bit of hackery – unfortunately, there’s no easy way to install QtRuby but it’s not so hard. Here’s what you’ll run:
sudo port install cmake ## CMake is a cool build system
tar -xzvf qt4-qtruby-1.4.9.tgz && cd ./qt4-qtruby-1.4.9
cmake .
make && sudo make install
Try it out!
Once you’ve got it built, try this sample code to see some of the new features in Qt 4.3 – this code will run a natively-styled wizard in Windows, Mac, and Linux without any changes! Unfortunately, this code isn’t very elegant or Ruby-like, but it’s a base that someone could write a really elegant UI framework over like RoR.
a = Qt::Application.new(ARGV)
def create_intro_page
page = Qt::WizardPage.new do |p|
p.title = "Introduction"
end
label = Qt::Label.new("This is a wizard!")
label.word_wrap = true
layout = Qt::VBoxLayout.new do |v|
v.add_widget(label)
end
page.layout = layout
page
end
wiz = Qt::Wizard.new do |x|
x.add_page(create_intro_page())
x.set_window_title("Test Wizard")
x.show
end
a.exec
![]() On Mac OS X |
![]() On Linux |
In summary:
- Install a Ruby that doesn’t suck, and hack your environment so it works right
- Install Qt and MacPorts
- Build QtRuby and install it
- Make UIs for all 3 platforms without hating your life
Autotorrent 0.5.1 – This one is actually useful
After reading the feedback on kde-apps.org as well as discovering how awesome KTorrent is, I’ve added some features to Autotorrent that should make it much more useful for people. First, I added support for other torrent programs, and I was able to make the KTorrent support really nice using DCOP. Basically, it means that once you have a default directory set up, Autotorrent can silently add torrents without popping up the “OMG DO YOU WANT TO SAVE THIS?!” dialog.

This dialog isn’t very pretty but that’s alright
Next, after learning some basic QtRuby, I managed to make a decent configuration dialog. It’s not very well spaced and it was a giant pain-in-the-ass to get what I wanted done, probably because I’m used to the GTK+ way of doing things, particularly when it comes to signals and slots. I’m totally biased, but I think the Qt way just involves a lot of extra declarations and isn’t nearly as Ruby-like as Ruby-GNOME2
Update: PS here’s where you can download Autotorrent. Oops.
Porting apps to KDE4 – part 1
After reading all the awesome things about the new cool things in QT4, especially the graphics stuff, I decided to check it out. And what better way to learn a new technology than to contribute something to the community! So after Emailing the original author and making sure he wasn’t working on it himself, I started to work to port Filelight, a handy utility that lets you view your disk usage visually in a way that’s very easy to get useful information out of. The other thing that is exciting about KDE4 is apps “by default” work with Windows too, so in the near future we’ll see a flood of awesome new open source programs for Windows.
The first thing you should do when porting a KDE app is get your environment set up. I did this by going to the building from SVN guide and following the instructions. Some notes:
- The guide says to create a separate user, but I think that’s overkill and somewhat annoying. What I did instead was create a script called kde_dev.sh that has the entries that they put into your .bashrc
- Ubuntu Edgy (and most other distros) have a version of D-Bus that’s up to date enough, don’t bother compiling your own (it’ll give you massive headaches trying to get it to cooperate with your system’s D-Bus anyways)
- Originally, I tried to use the Ubuntu KDE4 stuff that’s in Synaptic but unfortunately something’s glitched with building projects, cmake will always give you weird errors
Next, since Filelight uses Autotools, I could use the handy am2cmake script to create all of the CMakeFiles.txt entries automagically. It’s kind of cheating, but on the other hand, why should I have to look up a bunch of obscure commands unless I have to? I think I can get the Zeitgeist of cmake by reading the generated files. I also had to create a dummy ConfigureChecks.cmake which I’ll have to redo manually using the configure.ac file
After that, I read the Qt 4 Porting Guide and proceeded to cheat even more and use the qt3to4 utility to convert most of the code to Qt 4. However, after I get it to build correctly I’m going to go back and do a proper port, removing all of the old Qt3′isms.

