HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

GtkInfobars for a GTK+ application

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
gtkforapplicationgtkinfobars

Problem

I instantiate GtkInfobars a lot in my GTK+ application in order to communicate with the user. There are various types of infobars, depending on the message. Basically, any infobar could be a combination of the 4 different infobar message types and 5 different icons (which are painted on the left side of the infobar).

Initially, I would call my custom infobar function like this:

infobar("Message. Woo.", type=gtk.MESSAGE_INFO, icon=gtk.STOCK_DIALOG_WARNING, timeout=5)


After a while I decided I wanted to simplify all the creation calls... so I modified my infobar function so that I could do this:

infobar("Message. Woo.", type=(1,3), timeout=3)


I feel like the second way is better and that it's worth the code obfuscation, but I suspect not everyone will agree with me.

```
def infobar(self, msg=None, type=(1,1), timeout=3, vbox=None):
"""Popup a new auto-hiding InfoBar."""

# List of possible infobar message types
msgtypes = [0,
gtk.MESSAGE_INFO, # 1
gtk.MESSAGE_QUESTION, # 2
gtk.MESSAGE_WARNING, # 3
gtk.MESSAGE_ERROR] # 4

# List of possible images to show in infobar
imgtypes = [gtk.STOCK_APPLY, # 0
gtk.STOCK_DIALOG_INFO, # 1
gtk.STOCK_DIALOG_QUESTION, # 2
gtk.STOCK_DIALOG_WARNING, # 3
gtk.STOCK_DIALOG_ERROR] # 4

ibar = gtk.InfoBar()
ibar.set_message_type (msgtypes[type[0]])
if vbox:
# If specific vbox requested: assume ibar for filemode, add cancel button
ibar.add_button (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
ibar.connect ('response', self.cleanup_filemode)
else:
# If no specific vbox requested: do normal ibar at the top of message area
vbox = self.vbox_ibar
ibar.add_button (gtk.STOCK_OK, gtk.RESPONSE_OK)
ibar.connect ('response', lambda *args: ibar

Solution

I'd move all of those message into an external resource file something like:


    Error. Could not open file:{filename}


Then I'd simply pop the message using:

self.infobar('file.open.fail', filename = filename)


That should cleanup the calls to infobar, and make it easier to do things like provide strings for a different language.

EDIT:

Quick hack of an implementation

from xml.etree.ElementTree import XML, tostring

# of course, you'd want to load this from an external file
message_file = XML("""

    
        Error. Could not open file:{filename}
    
    
        File opened!
    

""")

messages = {}
for message in message_file.findall("message"):
    messages[message.attrib['id']] = message

def message(id, **kwargs):
    message_detail = messages[id]
    text = ''.join( tostring(node) for node in message_detail)
    return text.strip().format(**kwargs)

print message('file.open.fail', filename = 'file.txt')
print message('file.open.good', filename = 'file.txt')


Doesn't try to handle type/icon/delay. You'll probably also want to consider how you want to do whitespace.

Code Snippets

<message id="file.open.fail" type="warning" icon="error" delay="5">
    <b>Error. Could not open file:<i><tt><small>{filename}</small></tt></i></b>
</message>
self.infobar('file.open.fail', filename = filename)
from xml.etree.ElementTree import XML, tostring

# of course, you'd want to load this from an external file
message_file = XML("""
<messages>
    <message id="file.open.fail" type="warning" icon="error" delay="5">
        <b>Error. Could not open file:<i><tt><small>{filename}</small></tt></i></b>
    </message>
    <message id="file.open.good" type="warning" icon="error" delay="5">
        <b>File opened!</b>
    </message>
</messages>
""")

messages = {}
for message in message_file.findall("message"):
    messages[message.attrib['id']] = message

def message(id, **kwargs):
    message_detail = messages[id]
    text = ''.join( tostring(node) for node in message_detail)
    return text.strip().format(**kwargs)

print message('file.open.fail', filename = 'file.txt')
print message('file.open.good', filename = 'file.txt')

Context

StackExchange Code Review Q#9471, answer score: 4

Revisions (0)

No revisions yet.