Entries in the Category “tips”

Two small pygtk recipes : autohide and notebook window creation

written by nicoe, on Feb 11, 2011 2:23:00 PM.

Here are two small python + GTk recipes that might comes handy when people are searching for howtos about autohide and window creation from notebook drag and drop.

Auto-hiding part of a window with pygtk

First you create a gtk.Paned widget wich will hold the main screen and the widgets that will be hidden automatically. Then in the left part of pane window the trick is to use an EventBox around your VBox so that you can listen for the enter-notify-event and leave-notify-event signals.

import gtk

def toggle_max(widget, event):
    pane.set_position(65)

def toggle_min(widget, event):
    pane.set_position(15)

window = gtk.Window()
pane = gtk.HPaned()
eventbox = gtk.EventBox()
vbox = gtk.VBox()
eventbox.add(vbox)
entry1 = gtk.Entry()
vbox.pack_start(entry1)
entry2 = gtk.Entry()
pane.add1(eventbox)
pane.add2(entry2)

eventbox.connect('enter-notify-event', toggle_max)
eventbox.connect('leave-notify-event', toggle_min)

window.add(pane)
window.show_all()

gtk.main()

Notebook window creation

One very neat feature I discovered with chromium is the creation of another window once you drag and drop a tab in your root window. Since I am thinking about integrating this feature in the tryton client, I give it a shot in a very small script. The tricky part was debugging the create_window_from_tab function, kudos go to Juhaz from #pygtk who helped me with this.

import gtk

def check_pages(notebook, child, page_num):
    page_nbr = notebook.get_n_pages()
    if page_nbr == 0:
        parent_win = notebook.get_parent_window()
        parent_win.destroy()

def create_window_from_tab(notebook, page, drop_x, drop_y):
    window = gtk.Window()
    nb = gtk.Notebook()
    nb.set_group_id(42)
    nb.connect('create-window', create_window_from_tab)
    nb.connect('page-removed', check_pages)
    window.add(nb)
    window.show_all()
    window.maximize()
    return nb

dialog = gtk.Window()
image_tab1 = gtk.Image()
image_tab1.set_from_stock(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_BUTTON)
label_tab1 = gtk.Label('Tab 1')
image_tab2 = gtk.Image()
image_tab2.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_BUTTON)
label_tab2 = gtk.Label('Tab 2')
image_tab3 = gtk.Image()
image_tab3.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_BUTTON)
label_tab3 = gtk.Label('Tab 3')

notebook = gtk.Notebook()
notebook.set_group_id(42)
notebook.append_page(image_tab1, label_tab1)
notebook.set_tab_detachable(image_tab1, True)
notebook.append_page(image_tab2, label_tab2)
notebook.set_tab_detachable(image_tab2, True)
notebook.append_page(image_tab3, label_tab3)
notebook.set_tab_detachable(image_tab3, True)
notebook.connect('create-window', create_window_from_tab)
notebook.connect('page-removed', check_pages)

dialog.add(notebook)
dialog.show_all()

gtk.main()

One vim server per desktop

written by nicoe, on Jan 27, 2011 9:14:00 PM.

I usually organize my desktop 'semantically'. The first desktop is where I do my main development, the second one is where I test those developments, the third one is used for my tests in bpython or when I need to write some little examples. The last desktops is where I have my luakit windows and the next to last one is where I have my gajim, xchat and mutt windows. The five other desktops are usually empty but are there in case of need.

And here is what my typical desktop looks like:

/static/nicoe/thumb_desktop_20110127.png

One thing that annoy the hell out of me is the fact that I cannot open a specific file in my already running vim from one of the command line. So today, I finally stop complaining about that and I read about the remote option of vim.

So here is my script that will create a server per desktop and if a server is already running on this desktop than it will connect to it and open the file into it.

#!/bin/sh
if test -n "$DISPLAY"; then
    desktop="SERVER$(wmctrl -d | grep '\*' | cut -f 1 -d ' ')"
    vim --serverlist | grep $desktop
    if [ $? -eq 1 ]
    then
        urxvtcd +sb -geometry 80x57 -e vim --servername $desktop $* >> /dev/null &
    else
        vim --servername $desktop --remote $*
    fi
else
    vim $*
fi

The trickier part was finding the wmctrl tool which is a nice utility to interact through the command line with EWMH/NetWM compatible X Window managers (and thus with my the greatest WM of all time : openbox ;)).

Inheritance-aware dictionnary

written by nicoe, on Nov 14, 2008 11:21:00 AM.

In our framework we are using a dictionnary that stores the views available for a model. But what happens if you still want to provide a view for a subclass of a model ?

Of course there is still the default view created through introspection but they are only good-looking for very simple models. Thus, in this case, we decided to provide the view from the inherited parent.

Here is the code for an inheritance-aware dictionnary class.

class ClassDict(dict):
   """A dictionnary subclass that uses classes as keys
   >>> class A(object): pass
   >>> class B(object): pass
   >>> class C(B): pass
   >>> class D(A, C): pass
   >>> class E(D, B): pass
   >>> a = A(); b = B(); c = C(); d = D(); e = E()
   >>> test = ClassDict()
   >>> test[A] = 'A'
   >>> test[D]
   'A'
   >>> try:
   ...    test[b]
   ... except KeyError:
   ...    print 'Yep'
   Yep
   >>> test[B] = 'B'
   >>> test[E]
   'A'
   >>> test[C]
   'B'
   >>> test[c]
   'B'
   >>> del test[A]
   >>> test[d]
   'B'
   """
   def __getitem__(self, key):
       if not isinstance(key, type):
           key = key.__class__
       found = False
       for class_key in key.__mro__:
           try:
               val = super(ClassDict, self).__getitem__(class_key)
               found = True
               break
           except KeyError:
               pass
       if found:
           return val
       raise KeyError
   def __setitem__(self, key, value):
       if not isinstance(key, type):
           key = key.__class__
       super(ClassDict, self).__setitem__(key, value)

This kind of dictionnary will only accept new-style classes, moreover if you use an instance as a key, it will use as the key the class of this instance.

Note to myself

written by nicoe, on Jul 9, 2008 4:42:00 PM.

How to display numbers and monetary value in a locale aware way

>>> import locale
>>> locale.setlocale(locale.LC_ALL, '')
>>> locale.currency(6512.345)
'6512,35 \xe2\x82\xac'
>>> print locale.currency(6512.345)
6512,35 €
>>> print locale.currency(6512.345, grouping=True)
6.512,35 €
>>> print locale.currency(6512.345, grouping=True, international=True)
6.512,35 EUR
>>> locale.format('%#2.3f', 6512.345, True, False)
'6.512,345'

More info in the python documentation for the locale module