Showing posts with label usb-creator. Show all posts
Showing posts with label usb-creator. Show all posts

Tuesday, July 7, 2009

usb-creator-kde - available for testing

So, I meant to post this up a couple of weeks ago... better late than never.

I have posted an early beta copy of usb-creator package in my PPA. It contains packages for both the gtk and kde front-ends and a common package, which contains the back-end, and some other common bits.

If you are interested in trialing the beta, feel free to download the debs or add my PPA to your sources.list (if you add it to your list, please read the warning on my PPA page).

To get the files, navigate here.

Here are some screenshots showing the kde front-end in action. Enjoy!







Wednesday, June 17, 2009

usb-creator-kde - in action and with icons...

Here's a new screenshot showing usb-creator-kde with media detected and some icon bling (icons subject to change).

Basically, I updated the ui elements from QPushButton to KPushButton and assigned icons as KIcons based on appropriate icon/button functions. So they should change with the icon theme - yay.

Anyway, here it is...


usb-creator-kde - adventures in gobject land

I'll first start out with a disclaimer: I am not fluent in Qt nor Gtk programming. What I know or have learned is through the internet, various books and reading others code. So, what I describe below may not be the best way to achieve the end result, but it appears to work and allow for minimal interference with an existing application backend.

Now that that's out of the way, I'll proceed with the discussion: porting gobject calls to Qt so that I can get a usable KDE/Qt frontend for usb-creator-kde.

For the gtk client (usb-creator), the backend currently implements timers, callbacks, and process watchers via gobject. Similar mechanisms exist for Qt. The current backend is unsuitable for general use by both a gtk and Qt frontend as gobject and Qt seem to tromp all over one another, and cause the frontend to crash. TO get around this, we need to move the gobect calls to the gtk frontend, and implement wrappers that the backend can call from the frontend. Once we have wrappers in place, we can then re-implement the wrappers in our desired frontend (e.g. PyKDE).

Here's an example of some code from the backend:

self.timeouts[udi] = gobject.timeout_add(UPDATE_FREE_INTERVAL, self.update_free, udi)
And from the PyGtk manual:

timeout_add
int timeout_add(int interval, callback callback [, mixed user_data1, ... ]);

Registers a function to be called periodically. The function will be called repeatedly after interval milliseconds until it returns false (or nothing) at which point the timeout is destroyed and will not be called again.

So to keep the timeout alive, your callback function needs to return true;
Unfortunately, there is no single call in Qt that provides this mechanism (none that I know of). So, to implement this, I needed to write a couple of functions, using unnamed arguments lists, lambda notation, etc.

First off, we need a generic timer callback function that will call our passed function, test the return value, and stop the timer if the return value is not True. I also want this function to be private to my frontend class. Here what it looks like:

def __timeout_callback(self, func, *args):
'''Private callback wrapper used by add_timeout'''

timer = self.sender()
active = func(*args)
if not active:
timer.stop()
So, func is the passed calback function to execute, followed by a list of optional arguments *args. The sender will be a timer object, which we get from self.sender, assuming that the parent is some QObject or derivation thereof (in my case, the frontend class KdeFrontend is derived from QObject).

Ok, that allows us to have an arbitrary function with any number of arguments, and have it stop a timer when appropriate. We now need to implement the public wrapper that will use this private callback. Here is the code for that:

def add_timeout(self, interval, func, *args):
'''Add a new timer for function 'func' with optional arguments. Mirrors a
similar gobject call timeout_add.'''

timer = QTimer()
QObject.connect(timer,
SIGNAL("timeout()"),
lambda: self.__timeout_callback(func, *args))
timer.start(interval)

return timer
The add_timeout function takes the same parameters as the gobject.timeout_add function. Inside, we setup a new timer, connect it to our private callback, start the timer and return a reference to it. The magic is in how we connect the passed function func. Notice that we use lambda to call our private callback, passing along the func and *args. Normally, you do not pass a function with variable parameters to Qt connect statements, but in our case, we absolutely are required to do so. This is where using lambda comes in handy.

So, there you have it. A way to implement gobject.timeout_add using Qt. While everyday use of this is not likely, it will certainly help in porting applications from PyGtk to PyQt. I hope someone out there finds this useful. I know I searched for an easy way to do this, and never found anything. After lots of trial and error and asking lots of questions to my fellow developers, I was able to come up with the above.

Cheers.

Tuesday, June 16, 2009

usb-creator-kde - update and screenie

The creator is steadily moving along. Right now the main stumbling blocks are gobject calls in the backend and the use of a DBusGMainLoop in the backend.

Together, these constitute a non-working backend for PyKDE/PyQt. KCrash has become a nightmare.

In order to get around this, we need to pull out the gobject and DBusGMainLoop and move them somewhere related to the frontend. At that point I can re-implement the bits I require as PyKDE/PyQt code, while maintaining a common backend code base.

I've taken the first step, and moved DBusGMainLoop to the gtk frontend via a wrapper. I have re-implemented similar functionality via the same wrapper in the kde frontend using DBusQtMainLoop.

Next on the list is to rip out the gobject calls... I suspect a couple of days before I get that all figured out... (unless I get a real dose of inspiration).

Anyway, here's the screenshot as promised, so you know it's not all pie-in-the-sky :)