~iferca/yape/trunk

« back to all changes in this revision

Viewing changes to localgtk.py

  • Committer: Israel Fernández Cabrera
  • Date: 2008-10-03 21:12:17 UTC
  • Revision ID: iferca@gmail.com-20081003211217-uu1df2ucq3wd67nd
YaPe project moved to the new YaPe project structure. Old one will work fine but it was not suitable for the next development phases

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
 
3
 
__license__ = "GPL V.2 or (at your option) any later version"
4
 
__copyright__ = "2007, Israel Fernández Cabrera"
5
 
__author__ = "Israel Fernández Cabrera <iferca@gmail.com>"
6
 
 
7
 
import gtk
8
 
import gtk.glade
9
 
import os
10
 
import errors
11
 
from settings.config import Config
12
 
from signalhandler import SignalConnector
13
 
 
14
 
 
15
 
class GladeInterface(object):
16
 
    """GladeInterface(gladeFilename)
17
 
    
18
 
    Abstraction to manipulate glade files in a confortable way.
19
 
    """
20
 
    def __init__(self, gladeFilename):
21
 
        self._gladeFilename = gladeFilename
22
 
        self._widgets = loadGlade(gladeFilename)
23
 
        self.__realizeWidgets()
24
 
 
25
 
    def setIcontoDialog(self, dialog):
26
 
        setWindowIcon(dialog, "yape.svg")
27
 
 
28
 
    def getWidgetTree(self):
29
 
        """getWidgetTree()
30
 
        
31
 
        Return the underlaying glade.XML object.
32
 
        """
33
 
        return self._widgets
34
 
 
35
 
    def signalAutoConnect(self, signalMap):
36
 
        """signalAutoConnect(signalMap)
37
 
        
38
 
        Given a dictionary that relates signals (as keys) with methods (as values)
39
 
        made the needed connection as a batch process.
40
 
        """
41
 
        self._widgets.signal_autoconnect(signalMap)
42
 
 
43
 
    def __realizeWidgets(self):
44
 
        """
45
 
        Add widgets references to the class instance. The attribute nemes will be
46
 
        the same in the Glade file.
47
 
        """
48
 
        widgets = [(w.get_name(), w) for w in self._widgets.get_widget_prefix("_")]
49
 
        for name, widget in widgets:
50
 
            setattr(self, name, widget)
51
 
 
52
 
    def realizeWidgets(self, widgets):
53
 
        """realizeWidgets(widgets)
54
 
        
55
 
        widgets is a dictionary that relates the glade widget's names (as keys) with
56
 
        the desired attribute names. The goal of the «attribute names» is to be added
57
 
        as instance attributes containing as value the actual widget (identified by its name in 
58
 
        the glade file).
59
 
        """
60
 
        for widgetName, memberName in widgets.iteritems():
61
 
            widget = self.getWidget(widgetName)
62
 
            setattr(self, memberName, widget)
63
 
 
64
 
    def getWidget(self, widgetName):
65
 
        """getWidget(widgetName)
66
 
        
67
 
        Returns the widget identified by «widgetName». If no widget can be found
68
 
        raises a errors.GladeWidgetNotFoundException exception.
69
 
        """
70
 
        widget = self._widgets.get_widget(widgetName)
71
 
        if not widget:
72
 
            raise errors.GladeWidgetNotFoundException("Widget %s not found in glade file %s" % (widgetName, self._gladeFilename))
73
 
        return widget
74
 
 
75
 
class SaveDialog(GladeInterface):
76
 
    def __init__(self, title=None, primaryMessage=None, secondaryMessage=None):
77
 
        super(SaveDialog, self).__init__("savemessagebox.glade")
78
 
        widgets = {"Dialog": "_dialog", "Primary": "_primaryMessage",
79
 
        "Secondary": "_secondaryMessage"}
80
 
        self.realizeWidgets(widgets)
81
 
        self.setIcontoDialog(self._dialog)
82
 
        if primaryMessage:
83
 
            self._primaryMessage.set_markup("<b>%s</b>" % primaryMessage)
84
 
        if secondaryMessage:
85
 
            self._secondaryMessage.set_label(secondaryMessage)
86
 
 
87
 
    def close(self):
88
 
        self._dialog.hide()
89
 
        self._dialog.destroy()
90
 
 
91
 
    def run(self):
92
 
        return self._dialog.run()
93
 
 
94
 
class AskData(GladeInterface):
95
 
    def __init__(self):
96
 
        super(AskData, self).__init__("askdata.glade")
97
 
        widgets = {"AskDataDialog": "_dialog", "Description": "_description",
98
 
        "Label": "_label", "Entry": "_entry", "ApplyButton": "_apply"}
99
 
        self.realizeWidgets(widgets)
100
 
        signals = {"on_Entry_changed": self._onEntryChanged,
101
 
        "on_Entry_activate": self._onEntryActivate}
102
 
        self.signalAutoConnect(signals)
103
 
 
104
 
    def _onEntryActivate(self, widget):
105
 
        if self._entry.get_text():
106
 
            self._dialog.response(2)
107
 
 
108
 
    def _onEntryChanged(self, widget):
109
 
        self._apply.set_sensitive(bool(self._entry.get_text()))
110
 
 
111
 
    def getText(self):
112
 
        return self._entry.get_text()
113
 
 
114
 
    def setText(self, text):
115
 
        self._entry.set_text(text)
116
 
 
117
 
    def setTitle(self, title):
118
 
        self._dialog.set_title(title)
119
 
 
120
 
    def setDescription(self, description):
121
 
        self._description.set_label(description)
122
 
 
123
 
    def setLabel(self, label):
124
 
        self._label.set_label(label)
125
 
 
126
 
    def run(self):
127
 
        return self._dialog.run()
128
 
 
129
 
    def close(self):
130
 
        self._dialog.hide()
131
 
        self._dialog.destroy()
132
 
 
133
 
 
134
 
class YTreeViewColumn(object):
135
 
    def __init__(self, title = ""):
136
 
        self._title = title
137
 
        self._descriptor = []
138
 
 
139
 
    def addContent(self, colType, visible = True, resizable = False, reorderable = False, extraArgs=None):
140
 
        if colType not in ["text", "pixbuf", "stock", "bool"]:
141
 
            raise AttributeError("Invalid column type, must be in ['text', 'pixbuf', 'stock'] and got %s" % colType)
142
 
        textDescriptor = {}
143
 
        textDescriptor["type"] = colType
144
 
        textDescriptor["visible"] = visible
145
 
        textDescriptor["resizable"] = resizable
146
 
        textDescriptor["reorderable"] = reorderable
147
 
        textDescriptor["extra"] = extraArgs
148
 
        self._descriptor.append(textDescriptor)
149
 
 
150
 
    def getTitle(self): return self._title
151
 
 
152
 
    def content(self):
153
 
        for content in self._descriptor:
154
 
            yield content
155
 
 
156
 
 
157
 
class YTreeView(gtk.TreeView):
158
 
    def __init__(self):
159
 
        super(YTreeView, self).__init__()
160
 
        self._position = 0
161
 
 
162
 
    def getSelectedValue(self, column):
163
 
        selection = self.get_selection()
164
 
        model, selected = selection.get_selected_rows()
165
 
        if selected:
166
 
            path = selected[0]
167
 
            return model.get_value(model.get_iter(path), column)
168
 
        return None
169
 
 
170
 
    def addColumn(self, column):
171
 
        col = self._addNewColumn(column.getTitle())
172
 
        for content in column.content():
173
 
            self._appendContentToColumn(col, content)
174
 
 
175
 
    def _appendContentToColumn(self, column, content):
176
 
        column.set_visible(content["visible"])
177
 
        column.set_resizable(content["resizable"])
178
 
        column.set_reorderable(content["reorderable"])
179
 
        if content["type"] == "text":
180
 
            column = self._addTextRendererToColumn(column)
181
 
        if content["type"] == "pixbuf":
182
 
            column = self._addPixbufRendererToColumn(column)
183
 
        if content["type"] == "stock":
184
 
            column = self._addStockRendererToColumn(column)
185
 
        if content["type"] == "bool":
186
 
            column = self._addToggleRendererToColumn(column, content["extra"])
187
 
 
188
 
    def _addToggleRendererToColumn(self, column, callback):
189
 
        renderer = gtk.CellRendererToggle()
190
 
        column.pack_start(renderer, False)
191
 
        renderer.set_property('activatable', True)
192
 
        renderer.connect('toggled', callback)
193
 
        column.add_attribute(renderer, "active", self._position)
194
 
        self._position += 1
195
 
        return column
196
 
 
197
 
    def _addStockRendererToColumn(self, column):
198
 
        renderer = gtk.CellRendererPixbuf()
199
 
        column.pack_start(renderer, False)
200
 
        column.add_attribute(renderer, "stock_id", self._position)
201
 
        self._position += 1
202
 
        return column
203
 
 
204
 
    def _addPixbufRendererToColumn(self, column):
205
 
        renderer = gtk.CellRendererPixbuf()
206
 
        column.pack_start(renderer, False)
207
 
        column.add_attribute(renderer, "pixbuf", self._position)
208
 
        self._position += 1
209
 
        return column
210
 
        
211
 
    def _addTextRendererToColumn(self, column):
212
 
        renderer = gtk.CellRendererText()
213
 
        column.pack_start(renderer, False)
214
 
        column.add_attribute(renderer, "text", self._position)
215
 
        self._position += 1
216
 
        return column
217
 
 
218
 
    def _addNewColumn(self, title):
219
 
        column = gtk.TreeViewColumn(title)
220
 
        self.append_column(column)
221
 
        return column
222
 
 
223
 
 
224
 
class TabLabelWidget(gtk.EventBox):
225
 
    def __init__(self, text, closeCallback=None, widget=None, popup=None):
226
 
        super(TabLabelWidget, self).__init__()
227
 
        self._popup = popup
228
 
        self._widget = widget
229
 
        if self._popup:
230
 
            self.connect('button-press-event', self._onTabClick)
231
 
        container = gtk.HBox()
232
 
        label = gtk.Label()
233
 
        label.set_markup(text)
234
 
        container.pack_start(label, True, True, padding = 5)
235
 
        if closeCallback:
236
 
            self.closeButton = gtk.Button()
237
 
            self.closeButton.set_relief(gtk.RELIEF_NONE)
238
 
            self.closeButton.connect("clicked", closeCallback, self._widget)
239
 
            self.closeButton.set_image(gtk.image_new_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU))
240
 
            container.pack_start(self.closeButton, False, False)
241
 
        self.add(container)
242
 
        self.show_all()
243
 
 
244
 
    def _onTabClick(self, widget, event):
245
 
        if event.button != 3:
246
 
            return False
247
 
        sc = SignalConnector.getInstance()
248
 
        sc.notifyObservers("TabMenuPopup", widget=self._widget)
249
 
        if self._popup:
250
 
            self._popup.popup(None, None, None, event.button, event.time)
251
 
 
252
 
class LTabLabelWidget(gtk.VBox):
253
 
    def __init__(self, text, closeCallback = None):
254
 
        super(LTabLabelWidget, self).__init__()
255
 
        self.pack_start(self.createLabel(text), False, False, padding = 5)
256
 
        if (closeCallback is not None):
257
 
            closeButton = gtk.Button()
258
 
            closeButton.set_relief(gtk.RELIEF_NONE)
259
 
            closeButton.connect("clicked", closeCallback)
260
 
            closeButton.set_image(gtk.image_new_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU))
261
 
            self.pack_start(closeButton)
262
 
        self.show_all()
263
 
 
264
 
    def createLabel(self, text):
265
 
        label = gtk.Label(text)
266
 
        label.set_angle(90)
267
 
        return label
268
 
 
269
 
class RTabLabelWidget(LTabLabelWidget):
270
 
    def __init__(self, text, closeCallback = None):
271
 
        super(RTabLabelWidget, self).__init__(text, closeCallback)
272
 
 
273
 
    def createLabel(self, text):
274
 
        label = gtk.Label(text)
275
 
        label.set_angle(270)
276
 
        return label
277
 
 
278
 
 
279
 
class ColorDialog(gtk.ColorSelectionDialog):
280
 
    def __init__(self, caption):
281
 
        super(ColorDialog, self).__init__(caption)
282
 
 
283
 
    
284
 
    def getColorAsString(self):
285
 
        color = self.colorsel.get_current_color()
286
 
        colorString = color.to_string()
287
 
        result = "#%s%s%s" % (colorString[1:3], colorString[5:7], colorString[9:11])
288
 
        return result
289
 
 
290
 
def registerIconsets(iconInfo):
291
 
    """
292
 
    From the pyGTK FAQ
293
 
    """
294
 
    iconFactory = gtk.IconFactory()
295
 
    stockIds = gtk.stock_list_ids()
296
 
    for stockId, file in iconInfo:
297
 
        if stockId not in stockIds:
298
 
            imagePath = os.path.join(os.path.dirname(__file__), "images")
299
 
            pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(imagePath, file))
300
 
            iconset = gtk.IconSet(pixbuf)
301
 
            iconFactory.add(stockId, iconset)
302
 
    iconFactory.add_default()
303
 
 
304
 
def registerCustomIcons():
305
 
    iconList = [('class', 'class.svg'), ('import', 'import.svg'), ('function', 'function.svg'),
306
 
    ('import-section', 'import-section.svg'), ('python-file', 'mime-text-x-python.svg'),
307
 
    ('private-method', 'private-method.svg'), ('public-method', 'public-method.svg'),
308
 
    ('special-method', 'special-method.svg'), ('run-current-script', 'run-current-script.svg'),
309
 
    ('variable', 'variable.svg'), ('open-project', 'project.svg'), ('new-project', 'project-new.svg'),
310
 
    ('new-django-app', 'new-django-app.svg'), ('django-validate-model', 'django-validate-model.svg'),
311
 
    ('django-sync-db', 'django-sync-db.svg'), ('django-web-server', 'django-web-server.svg'),
312
 
    ('django-shell', 'django-shell.svg'), ('django-db-shell', 'django-db-shell.svg'),
313
 
    ('css-file', 'gnome-mime-text-css.svg'), ('css-selector', 'css-selector.svg'),
314
 
    ('task-important', 'task-important.svg'), ('task-generic', 'task-generic.svg'),
315
 
    ('task-med', 'task-med.svg'), ('task-bug', 'task-bug.svg'), ('calendar', 'calendar.svg')]
316
 
    registerIconsets(iconList)
317
 
 
318
 
def setWindowIcon(window, icon="yape.svg"):
319
 
    imagePath = os.path.join(os.path.dirname(__file__), "images")
320
 
    pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(imagePath, icon))
321
 
    window.set_icon(pixbuf)
322
 
 
323
 
def loadGlade(gladeFileName):
324
 
    try:
325
 
        config = Config()
326
 
        path = os.path.join(config.getConfig("installation_path"), "glade");
327
 
        return gtk.glade.XML(os.path.join(path, gladeFileName))
328
 
    except Exception, e:
329
 
        raise errors.ErrorLoadingGladeFile(e.message)
330