Wednesday 15 June 2011

Screw you launchpad

I've moved my code hosting to http://code.google.com/p/openmolar/, switching from bzr to hg.

Why?
https://bugs.launchpad.net/launchpad/+bug/220082

I'm absolutely bloody furious.

However, I feel this move was absolutely necessary.
Launchpad is falling behind other code hosting sites from a my perspective as a coder. Only time will tell if I am right.


p.s. as a dentist.. should i really be using hg?

Monday 13 June 2011

PyQt QSysTrayIcon Example

Following A question in #pyqt on irc.freenode.net, I had a play with QSysTrayIcon.

"Hugo__" wanted a tray icon in Gnome which showed a different menu for left and right clicking.

Here's one way to achieve such with PyQt4.

Note - I use QtGui.QIcon.fromTheme here.. and do NOT supply a fallback icon.
Hence, the icons will only show on freedesktop standards compliant environments (gnome, KDE etc..)

see
http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
for details.







#! /usr/bin/env python
from PyQt4 import QtGui, QtCore

class RightClickMenu(QtGui.QMenu):
    def __init__(self, parent=None):
        QtGui.QMenu.__init__(self, "Edit", parent)

        icon = QtGui.QIcon.fromTheme("edit-cut")
        self.addAction(QtGui.QAction(icon, "&Cut", self))

        icon = QtGui.QIcon.fromTheme("edit-copy")
        self.addAction(QtGui.QAction(icon, "Copy (&X)", self))

        icon = QtGui.QIcon.fromTheme("edit-paste")
        self.addAction(QtGui.QAction(icon, "&Paste", self))
    
class LeftClickMenu(QtGui.QMenu):
    def __init__(self, parent=None):
        QtGui.QMenu.__init__(self, "File", parent)

        icon = QtGui.QIcon.fromTheme("document-new")
        self.addAction(QtGui.QAction(icon, "&New", self))

        icon = QtGui.QIcon.fromTheme("document-open")
        self.addAction(QtGui.QAction(icon, "&Open", self))

        icon = QtGui.QIcon.fromTheme("document-save")
        self.addAction(QtGui.QAction(icon, "&Save", self))


class SystemTrayIcon(QtGui.QSystemTrayIcon):
    def __init__(self, parent=None):
        QtGui.QSystemTrayIcon.__init__(self, parent)
        self.setIcon(QtGui.QIcon.fromTheme("document-save"))

        self.right_menu = RightClickMenu()
        self.setContextMenu(self.right_menu)

        self.left_menu = LeftClickMenu()
    
        self.activated.connect(self.click_trap)

    def click_trap(self, value):
        if value == self.Trigger: #left click!
            self.left_menu.exec_(QtGui.QCursor.pos())

    def welcome(self):
        self.showMessage("Hello", "I should be aware of both buttons")
        
    def show(self):
        QtGui.QSystemTrayIcon.show(self)
        QtCore.QTimer.singleShot(100, self.welcome)

if __name__ == "__main__":
    app = QtGui.QApplication([])

    tray = SystemTrayIcon()
    tray.show()
    
    #set the exec loop going
    app.exec_()

Making PyQt experimentation easier

Over the past few months, I've encountered the same issue. namely, I want to do *SOMETHING* with the openmolar project be it:
  1. document with sphinx
  2. write unittests (I know... I should have written them 1st..)
  3. make a deb or rpm
  4. make a windows executable
  5. convert to python 3 with 2to3 etc..

Rather than risk breaking my main codebase however, I believe it always helps to attempt this stuff with a smaller application first I think. So I've written one. It is trivial enough to keep the codebase simple, but complex enough to be realistic.

It raises dialogs, stores data, etc.

I've tried to follow a lot of my coding style choices (which you may hate), but on checking the modules with pylint, most get a 10/10, only decreasing when PyQt4 own naming conventions dictate.

anyways, to cut to the chase.. the code is here is anyone wants a play. This is in the public domain, so do with it as you wish.
download it from my dropbox account http://dl.dropbox.com/u/1989100/example_pyqt_app.tar.bz2

My current focus is writing unittests (something I am ashamed to admit I have never done before), and it is proving VERY interesting.

for example. dialogs are interesting, in that the exec_ function needs to be called to ensure correct code coverage. Calling that during a test run causes a pause in the procedings.. not good.

So what is the best way to call accept() or reject() on such a dialog?
I am experimenting with installEventFilter into QApplication itself, and accepting the dialog when the focus event is encountered seems to be working really well.

Tuesday 7 June 2011

Python Class - Am I a subclass?

Problem...
in #python on freenode, a question was asked about identifying a subclass during the __init__ method.
I came up with this example. 
class Example(object):
    def __init__(self):
        if self.__class__ != Example.mro()[0]:
            print "I am an instance of a subclass of Example"
        else:
            print "I am an instance of Example"

class ExampleDeritive(Example):
    ''' the most basic of subclasses! '''
    pass


>>> Example()
I am an instance of Example

>>> ExampleDeritive()
I am an instance of a subclass of Example