~epidermis/epidermis/releases

« back to all changes in this revision

Viewing changes to epidermis/handy.py

  • Committer: David D Lowe
  • Date: 2011-04-25 23:26:57 UTC
  • mfrom: (1.1.169 trunk)
  • Revision ID: daviddlowe.flimm@gmail.com-20110425232657-24sp0emj23dqehbr
0.6 release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env python
2
 
# Copyright 2008-2010 David D Lowe
3
 
# released under the GPLv3
 
2
# -*- coding: utf-8 -*-
 
3
# Copyright © David D Lowe 2008-2011
 
4
# This program is free software under the terms of GPLv2. For more 
 
5
# information, see the file named COPYING distributed with this project.
 
6
 
4
7
"""handy.py is a collection of handy functions"""
5
8
 
6
 
from __future__ import division
 
9
from __future__ import division, absolute_import
7
10
import pygtk
8
11
pygtk.require("2.0")
9
12
import sys, gtk
10
13
import os
11
14
import threading
12
 
import const
13
 
 
14
 
# create a message box, and return which button was pressed     
15
 
def message_box(message="", title="", buttons=None, pixmap=None, modal= True):
16
 
    """Display message box and return result
17
 
    Please only use this function from processes that are not running gtk.main()
18
 
    title: title of the window
19
 
    message: the message to be displayed
20
 
    buttons: a tuple containing the text of the buttons, if not specified, will 
21
 
    default to ((True, gtk.STOCK_YES),)
22
 
    default: the number (starting at 0) of the default button
23
 
    modal=Is the message dialog modal"""
24
 
    # from http://www.rexx.com/~dkuhlman/python_201/python_201.html
25
 
    # with modifications
26
 
    
27
 
        
28
 
    class MessageBox(gtk.Dialog):
29
 
        def __init__(self, message="", buttons=(), pixmap=None,
30
 
                modal=True):
31
 
            gtk.Dialog.__init__(self)
32
 
            self.connect("destroy", self.quit)
33
 
            self.connect("delete_event", self.quit)
34
 
            if modal:
35
 
                self.set_modal(True)
36
 
            hbox = gtk.HBox(spacing=5)
37
 
            hbox.set_border_width(5)
38
 
            self.vbox.pack_start(hbox)
39
 
            hbox.show()
40
 
            if pixmap:
41
 
                self.realize()
42
 
                #pixmap = Pixmap(self, pixmap)
43
 
                im = gtk.Image()
44
 
                im.set_from_stock(pixmap, gtk.ICON_SIZE_DIALOG)
45
 
                hbox.pack_start(im, expand=False)
46
 
                im.show()
47
 
            label = gtk.Label(message)
48
 
            hbox.pack_start(label)
49
 
            label.show()
50
 
            for isStock, text in buttons:
51
 
                b = gtk.Button(text)
52
 
                b.set_flags(gtk.CAN_DEFAULT)
53
 
                b.set_label(text)
54
 
                if isStock:
55
 
                    b.set_use_stock(True)
56
 
                b.connect("clicked", self.click)
57
 
                self.action_area.pack_start(b)
58
 
                b.show()
59
 
            self.ret = None
60
 
        def quit(self, *args):
61
 
            self.hide()
62
 
            self.destroy()
63
 
            gtk.main_quit()
64
 
        def click(self, button):
65
 
            self.ret = button.get_label()
66
 
            self.quit()
67
 
    
68
 
    if buttons is None:
69
 
        buttons = ((True, gtk.STOCK_OK),)
70
 
    
71
 
    win = MessageBox(message, buttons, pixmap=pixmap, modal=modal)
72
 
    win.set_title(title)
73
 
    win.set_skip_taskbar_hint(False)
74
 
    win.show()
75
 
    gtk.gdk.threads_enter()
76
 
    gtk.main()
77
 
    gtk.gdk.threads_leave()
78
 
    return win.ret
79
 
 
80
 
def show_error(text, terminalText=None):
81
 
    """displays an error alert box using message_box and prints to sys.stderr
82
 
    For use in threads other than gtk.main"""
83
 
 
84
 
    require_main_thread()
85
 
    if terminalText is None:
86
 
        terminalText = text
87
 
    print >> sys.stderr, terminalText
88
 
    message_box(text, title="Error", pixmap=gtk.STOCK_DIALOG_ERROR, buttons=((True, gtk.STOCK_OK),))
89
 
 
 
15
from . import const
90
16
 
91
17
def require_main_thread():
92
 
    """Raises a RequireThreadTypeException if the current thread is not named
93
 
    "MainThread" """
 
18
    """Raise a RequireThreadTypeException if the current thread is not named
 
19
    "MainThread"
 
20
    
 
21
    """
94
22
    if threading.currentThread().getName() not in ("MainThread", const.GTK_LOOP_THREAD_NAME):
95
 
        import ep_exceptions
 
23
        from . import ep_exceptions
96
24
        raise ep_exceptions.RequireThreadTypeException()
97
25
 
98
26
def require_non_main_thread():
99
 
    """Raises a RequireThreadTypeException if the current thread is named
100
 
    "MainThread" """
 
27
    """Raise a RequireThreadTypeException if the current thread is named
 
28
    "MainThread"
 
29
    
 
30
    """
101
31
    if threading.currentThread().getName() == "MainThread":
102
 
        import ep_exceptions
 
32
        from . import ep_exceptions
103
33
        raise ep_exceptions.RequireThreadTypeException()
104
34
 
105
35
def determine_path ():
106
 
    """returns the path of this .py file (just the directory)
107
 
    Borrowed from wxglade.py"""
 
36
    """Return the path of this .py file (just the directory)
 
37
    Borrowed from wxglade.py
 
38
    
 
39
    """
108
40
    try:
109
41
        root = __file__
110
42
    except Exception, ee:
123
55
        return os.path.join(const.PAR_DIR, "data", filename)
124
56
 
125
57
def get_first_text(thexml):
126
 
    """Get text of XML node (ignores comments)"""
 
58
    """Return text of XML node (ignores comments)"""
127
59
    import xml.dom
128
60
    for el in thexml.childNodes:
129
61
        if el.nodeType == xml.dom.Node.TEXT_NODE:
130
62
            return el.data
131
 
    import ep_exceptions
 
63
    from . import ep_exceptions
132
64
    ee = ep_exceptions.NoFirstTextError(thexml.tagName)
133
65
    raise ee
134
66
 
135
67
def bytes_in_str(bytes):
136
 
    """Returns the number of bytes in a human-readable string format"""
 
68
    """Return the number of bytes in a human-readable string format"""
137
69
    if bytes > 1073741824:
138
70
        return str(round(bytes / 1073741824, 2)) + "GB"
139
71
    elif bytes > 1048576:
143
75
    else:
144
76
        return str(bytes) + "B"
145
77
 
146
 
def ignore(*args):
147
 
    pass
148
 
 
149
 
def main():
150
 
    print "This file should not be run"
151
 
    print determine_path()
152
 
 
153
 
if __name__ == "__main__":
154
 
    main()
 
78
def abstract():
 
79
    """Raise NotImplementedError exception to indicate that the method
 
80
    in which abstract() is called is abstract.
 
81
    
 
82
    """
 
83
    import inspect
 
84
    caller = inspect.getouterframes(inspect.currentframe())[1][3]
 
85
    raise NotImplementedError(caller + ' must be implemented in subclass')