Ils seront nôtres.
On a fait notre choix :
Plus qu'à choisir les couleurs maintenant.
On a fait notre choix :
Plus qu'à choisir les couleurs maintenant.
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.
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()
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()
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:
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 ;)).
Last week I learned about aeroolib a not so friendly fork of relatorio. It left me wondering about how to handle such a situation. Granted relatorio suffered from a lack of attention since I started to work for PCSol, but since I left, I intend to push for a greater integration of it into tryton.
I was disappointed because I never heard of this company using relatorio and all of a sudden they announce that they forked our project and added some nice features. The guy behind this company had posted 2 bugs (one of them after having talk with him in great length on IRC) and never posted any message on our mailing list. One thing amongst other that really got on my nerves was that the new project fixed a (so called) security breach, and they did not warn us about that issue ! And eventhough they did grant us the copyright on our work (they had too, that's why I choose the GPL when writing this piece of software after all) I felt that the collaboration should have been better.
But next time you intend to fork project do it right:
Those little advices will ease our work and yours. A fork, even an unfriendly one, might be mutually beneficient.
This first of January I will start working with Cédric Krier and Bertrand Chenal from b2ck. I will work with Cédric on a Tryton project in Holland. This project is really interesting and will bring a lot of improvements to the tryton client and server. I am really happy with this turn in my life since it will allow me to work on more interesting problems in a better and more thought-challenging environment.
The first development I am working on is a functionality that will propagate constraints from domain to the opened tabs in the tryton client. To make things clearer an example is probably necessary. With tryton (or openerp) you can set a constraint on fields or views by setting what is called a domain. So to ensure some business rules are enforced we sometimes need to inverse the domain so that people creating object won't be able to violate the rules we defined with the domain.
So what I needed was a module that could do this (taken from my tests):
>>> domain = ['OR', ('x', '=', 3), ('y', '>', 5), ('z', '=', 'abc')]
>>> inversion(domain, 'x')
[('x', '=', 3)]
>>> inversion(domain, 'x', {'y': 4})
[('x', '=', 3)]
>>> inversion(domain, 'x', {'y': 7})
True
The last result stating that there is no constraint on the x fields since the domain constraint is already met by the y value in the context.
Another focus point will be the creation of a connection manager inspired by the one used by gajim. This will prove a nice UI addition for less technical users.
At work we have a project to realize a pygtk POS interface for OpenERP. It is getting closer and closer everyday and after much hagglings to create the right UI, I had to connect it to the underlying server. Using the so called netrpc protocol out of the box is not really the most pythonic you can get.
So I came up with those classes that made me fells just like home when I needed to work with the OpenERP objects.
class MetaOEObject(type):
def __init__(cls, name, bases, dict):
super(MetaOEObject, cls).__init__(name, bases, dict)
cls.proxy = Config.client.create_proxy(Config.database,
dict['dotted_name'])
cls.fields = cls.proxy.fields_get()
OEObject.proxies[dict['dotted_name']] = cls
class OEObject(object):
proxies = {}
def __init__(self, id=None):
self.id = id
if id is not None:
self.value = self.proxy.read(id)
@classmethod
def select(cls, condition):
ids = cls.proxy.search(condition)
return [cls(id) for id in ids]
def __getattr__(self, name):
if name not in self.fields:
raise AttributeError
elif self.fields[name]['type'] == 'many2one':
oeobj = OEObject.proxies[self.fields[name]['relation']]
if self.value[name]:
return oeobj(self.value[name][0])
else:
return None
elif self.fields[name]['type'] == 'one2many':
oeobj = OEObject.proxies[self.fields[name]['relation']]
return [oeobj(id) for ids in self.value[name]]
elif self.fields[name]['type'] == 'binary':
if not self.value[name]:
return None
filename = os.tempnam()
fd = open(filename, 'w')
fd.write(base64.b64decode(self.value[name]))
fd.flush()
return filename
return self.value[name]
def __str__(self):
print self.dotted_name, self.id
return '<%s (%d)>' % (self.dotted_name, self.id)
class Category(OEObject):
__metaclass__ = MetaOEObject
dotted_name = 'product.category'
class Product(OEObject):
__metaclass__ = MetaOEObject
dotted_name = 'product.product'
Those kind of classes makes use of metaclasses so that proxy and fields are class-attributes which seems nicer to me. It allows me write pieces of code like this
for category in Category.select([('parent_id', '=', None)]):
page = self.create_category_page(category, notebook)
for product in Product.select([('categ_id', '=', category.id)]):
page.add_product(product)
Which populates a GtkIconView into a notebook used to display products sorted by categories.
J'ai enfin décidé d'utiliser les propriétés de lecteur MP3 de mon Nokia. Le déclic ce fut l'importation des 45 CDs achetés lors la (triste) liquidation de Caroline Musique. Il faut que je trouve du temps pour écouter tout ça ! Temps tout trouvé puisque je passe vingt cinq minutes dans le bus tous les matins.
libmtp est bien faite et détecte mon téléphone malheureusement soit elle, soit rhythmbox est incapable de transférer les fichiers musicaux correctement puisqu'ils ne respectent pas la hiérarchie Artiste/Album. Tant pis, je l'utilise alors en mass-storage et j'ajoute le fichier .is_audio_player suivant permettant à rhythmbox de correctement transcoder mes précieux flac en mp3 parfaitement compréhensibles par mon GSM.
audio_folders=Music/ folder_depth=2 output_formats=audio/mpeg
Avec la sortie de la nouvelle version du bureau GNOME arrive la fonctionnalité que j'attendais vraiment : le passage à WebKit d'epiphany.
WebKit c'est un moteur de rendu Web. WebKit c'est aussi un troll (mourrant) sur l'implication d'Apple dans le logiciel libre car ce moteur est basé sur KHTML et la collaboration entre l'équipe de KDE et celle de la Pomme n'a pas toujours été parfaite.
Mais WebKit c'est surtout une bibliothèque ultra-rapide, j'ai l'impression de revivre et que le net va 5× plus vite depuis que je l'utilise.
Et le voila, cet hymne qu'on attendait depuis si longtemps. Il va retentir dans le stade à l'affiche de FIFA 2010. Le tirage avait lieu hier, et on est maintenant fixé sur les adversaires du Standard :
Toutes les équipes jouent en rouge et blanc, ce sera l'occasion de voir nos joueurs avec le maillot brun. C'est pas plus mal. Et l'un dans l'autre, le tirage est relativement abordable. Ça pourrait le faire.
Demain rendez-vous à Sclessin pour choper des places pour les trois matches.
EDIT: C'est fait j'ai mes places ! 20 minutes de file, seulement 5 personnes devant moi, le rêve du à une communication très approximative du Standard.