1
# -*- coding: utf-8 -*-
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>"
11
from settings.config import Config
12
from signalhandler import SignalConnector
15
class GladeInterface(object):
16
"""GladeInterface(gladeFilename)
18
Abstraction to manipulate glade files in a confortable way.
20
def __init__(self, gladeFilename):
21
self._gladeFilename = gladeFilename
22
self._widgets = loadGlade(gladeFilename)
23
self.__realizeWidgets()
25
def setIcontoDialog(self, dialog):
26
setWindowIcon(dialog, "yape.svg")
28
def getWidgetTree(self):
31
Return the underlaying glade.XML object.
35
def signalAutoConnect(self, signalMap):
36
"""signalAutoConnect(signalMap)
38
Given a dictionary that relates signals (as keys) with methods (as values)
39
made the needed connection as a batch process.
41
self._widgets.signal_autoconnect(signalMap)
43
def __realizeWidgets(self):
45
Add widgets references to the class instance. The attribute nemes will be
46
the same in the Glade file.
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)
52
def realizeWidgets(self, widgets):
53
"""realizeWidgets(widgets)
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
60
for widgetName, memberName in widgets.iteritems():
61
widget = self.getWidget(widgetName)
62
setattr(self, memberName, widget)
64
def getWidget(self, widgetName):
65
"""getWidget(widgetName)
67
Returns the widget identified by «widgetName». If no widget can be found
68
raises a errors.GladeWidgetNotFoundException exception.
70
widget = self._widgets.get_widget(widgetName)
72
raise errors.GladeWidgetNotFoundException("Widget %s not found in glade file %s" % (widgetName, self._gladeFilename))
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)
83
self._primaryMessage.set_markup("<b>%s</b>" % primaryMessage)
85
self._secondaryMessage.set_label(secondaryMessage)
89
self._dialog.destroy()
92
return self._dialog.run()
94
class AskData(GladeInterface):
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)
104
def _onEntryActivate(self, widget):
105
if self._entry.get_text():
106
self._dialog.response(2)
108
def _onEntryChanged(self, widget):
109
self._apply.set_sensitive(bool(self._entry.get_text()))
112
return self._entry.get_text()
114
def setText(self, text):
115
self._entry.set_text(text)
117
def setTitle(self, title):
118
self._dialog.set_title(title)
120
def setDescription(self, description):
121
self._description.set_label(description)
123
def setLabel(self, label):
124
self._label.set_label(label)
127
return self._dialog.run()
131
self._dialog.destroy()
134
class YTreeViewColumn(object):
135
def __init__(self, title = ""):
137
self._descriptor = []
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)
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)
150
def getTitle(self): return self._title
153
for content in self._descriptor:
157
class YTreeView(gtk.TreeView):
159
super(YTreeView, self).__init__()
162
def getSelectedValue(self, column):
163
selection = self.get_selection()
164
model, selected = selection.get_selected_rows()
167
return model.get_value(model.get_iter(path), column)
170
def addColumn(self, column):
171
col = self._addNewColumn(column.getTitle())
172
for content in column.content():
173
self._appendContentToColumn(col, content)
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"])
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)
197
def _addStockRendererToColumn(self, column):
198
renderer = gtk.CellRendererPixbuf()
199
column.pack_start(renderer, False)
200
column.add_attribute(renderer, "stock_id", self._position)
204
def _addPixbufRendererToColumn(self, column):
205
renderer = gtk.CellRendererPixbuf()
206
column.pack_start(renderer, False)
207
column.add_attribute(renderer, "pixbuf", self._position)
211
def _addTextRendererToColumn(self, column):
212
renderer = gtk.CellRendererText()
213
column.pack_start(renderer, False)
214
column.add_attribute(renderer, "text", self._position)
218
def _addNewColumn(self, title):
219
column = gtk.TreeViewColumn(title)
220
self.append_column(column)
224
class TabLabelWidget(gtk.EventBox):
225
def __init__(self, text, closeCallback=None, widget=None, popup=None):
226
super(TabLabelWidget, self).__init__()
228
self._widget = widget
230
self.connect('button-press-event', self._onTabClick)
231
container = gtk.HBox()
233
label.set_markup(text)
234
container.pack_start(label, True, True, padding = 5)
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)
244
def _onTabClick(self, widget, event):
245
if event.button != 3:
247
sc = SignalConnector.getInstance()
248
sc.notifyObservers("TabMenuPopup", widget=self._widget)
250
self._popup.popup(None, None, None, event.button, event.time)
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)
264
def createLabel(self, text):
265
label = gtk.Label(text)
269
class RTabLabelWidget(LTabLabelWidget):
270
def __init__(self, text, closeCallback = None):
271
super(RTabLabelWidget, self).__init__(text, closeCallback)
273
def createLabel(self, text):
274
label = gtk.Label(text)
279
class ColorDialog(gtk.ColorSelectionDialog):
280
def __init__(self, caption):
281
super(ColorDialog, self).__init__(caption)
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])
290
def registerIconsets(iconInfo):
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()
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)
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)
323
def loadGlade(gladeFileName):
326
path = os.path.join(config.getConfig("installation_path"), "glade");
327
return gtk.glade.XML(os.path.join(path, gladeFileName))
329
raise errors.ErrorLoadingGladeFile(e.message)