patternpythonMinor
GtkInfobars for a GTK+ application
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
After a while I decided I wanted to simplify all the creation calls... so I modified my
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
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:
Then I'd simply pop the message using:
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
Doesn't try to handle type/icon/delay. You'll probably also want to consider how you want to do whitespace.
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.