2
# Copyright (C) 2010 Canonical Ltd
4
# This program is free software: you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License version 2 as
6
# published by the Free Software Foundation.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
# Copyright (C) 2010 Ken VanDine <ken.vandine@canonical.com>
18
# Accounts interface for Gwibber
27
from gettext import lgettext as _
28
if hasattr(gettext, 'bind_textdomain_codeset'):
29
gettext.bind_textdomain_codeset('gwibber','UTF-8')
30
gettext.textdomain('gwibber')
32
import gtk, pango, gconf, os, json, uuid
33
from gwibber.lib import GwibberPublic
35
from microblog.util import resources
37
for p in resources.get_plugin_dirs()[0]:
38
print "Loading plugin for %s" % p
39
globals()[p] = __import__("%s.gtk.%s" % (p,p), fromlist='*')
41
from dbus.mainloop.glib import DBusGMainLoop
42
DBusGMainLoop(set_as_default=True)
44
class GwibberAccountManager(object):
45
def __init__(self, selected_account=None, condition=None, message=None):
46
self.selected_account = selected_account
47
self.condition = condition
48
self.message = message
49
self.gwibber = GwibberPublic()
50
self.services = json.loads(self.gwibber.GetServices())
51
self.ui = gtk.Builder()
52
self.ui.set_translation_domain("gwibber")
53
self.ui.add_from_file(resources.get_ui_asset("gwibber-accounts-dialog.ui"))
54
self.ui.connect_signals(self)
56
dialog = self.ui.get_object("accounts_dialog")
57
dialog.resize(640,400)
58
dialog.set_icon_from_file(resources.get_ui_asset("gwibber.svg"))
60
if hasattr(gtk, "InfoBar"):
61
self.alignment_infobar = self.ui.get_object("alignment_infobar")
62
self.infobar = gtk.InfoBar()
63
self.alignment_infobar.add(self.infobar)
66
# Hide the help button until we have help :)
67
button_help = self.ui.get_object("button_help")
70
# This should check for configured accounts, and if there are any hide this
71
self.ui.get_object('frame_new_account').hide()
72
self.ui.get_object('vbox_save').hide()
73
self.ui.get_object('vbox_create').hide()
75
self.setup_account_tree()
76
self.populate_account_tree()
79
def setup_account_tree(self):
80
# Protocol title, Icon, Protocol Properties
81
self.service_store = gtk.ListStore(str, gtk.gdk.Pixbuf, str)
82
for name, props in self.services.items():
83
icon = self.get_icon(name)
85
self.service_store.append((props["name"], icon, name))
87
service_combo = self.ui.get_object("protocol_combobox")
88
service_combo.set_model(self.service_store)
90
celltxt = gtk.CellRendererText()
91
cellimg = gtk.CellRendererPixbuf()
93
service_combo.pack_start(cellimg, False)
94
service_combo.pack_start(celltxt, False)
95
service_combo.add_attribute(cellimg, "pixbuf", 1)
96
service_combo.add_attribute(celltxt, "text", 0)
97
service_combo.set_active(0)
99
# Store: Account name, Icon, Protocol properties, Color
100
self.account_store = gtk.TreeStore(str, gtk.gdk.Pixbuf, object, str)
102
icon_column = gtk.TreeViewColumn('Icon')
103
name_column = gtk.TreeViewColumn('Account')
105
celltxt = gtk.CellRendererText()
106
cellimg = gtk.CellRendererPixbuf()
108
icon_column.pack_start(cellimg, False)
109
icon_column.add_attribute(cellimg, 'pixbuf', 1)
110
icon_column.add_attribute(cellimg, 'cell-background', 3)
112
name_column.pack_start(celltxt, True)
113
name_column.add_attribute(celltxt, 'text', 0)
114
name_column.add_attribute(celltxt, 'cell-background', 3)
116
self.account_tree = self.ui.get_object("accounts_tree")
117
self.account_tree.append_column(icon_column)
118
self.account_tree.append_column(name_column)
119
self.account_tree.set_model(self.account_store)
121
def select_account(self):
122
if not self.selected_account:
123
if len(self.account_store):
124
self.account_tree.set_cursor(0)
125
else: self.add_account()
127
for i in self.account_store:
128
if i[2]["id"] == self.selected_account:
129
self.account_tree.set_cursor(i.path)
130
#self.selected_account = None
133
def get_icon(self, name):
134
icf = util.get_service_icon(name)
136
if os.path.exists(icf):
137
return gtk.gdk.pixbuf_new_from_file(icf)
138
#return gtk.gdk.pixbuf_new_from_file(resources.get_ui_asset("gwibber.png"))
141
def get_from_keyring(self, acctid, name):
142
item = {"id": str("%s/%s" % (acctid, name))}
144
return gnomekeyring.find_items_sync(gnomekeyring.ITEM_GENERIC_SECRET, item)[0].secret
145
except gnomekeyring.NoMatchError:
148
def put_in_keyring(self, acctid, name, value):
149
id = "%s/%s" % (acctid, name)
150
return gnomekeyring.item_create_sync(
151
gnomekeyring.get_default_keyring_sync(),
152
gnomekeyring.ITEM_GENERIC_SECRET,
153
"Gwibber preference: %s" % id,
154
{"id": str(id)}, str(value), True)
156
def populate_account_tree(self):
157
self.account_store.clear()
158
accounts = json.loads(self.gwibber.GetAccounts())
159
for account in accounts:
161
icon = self.get_icon(account["service"])
162
if account.has_key("site_display_name"):
163
name = account["site_display_name"]
165
name = "%s (%s)" % (self.services[account["service"]]["name"], account["username"])
166
private_fields = [f.split(":")[-1] for f in self.services[account["service"]]["config"] if ":" in f]
168
for f in private_fields:
169
if not account.has_key(f): account[f] = ":KEYRING:MISSING"
170
if account[f].startswith(":KEYRING:"):
171
value = self.get_from_keyring(account["id"], f)
174
self.account_store.append(None, [name, icon, account, color])
178
def verify_account(self, account):
179
for field in self.services[account["service"]]["config"]:
180
if field.split(":")[-1] not in account:
181
print "Couldn't find field:", field.split(":")[-1]
185
def on_edit_account(self, widget, data=None):
186
self.on_edit_account_save()
187
#self.ui.get_object('vbox_save').show()
188
#self.ui.get_object('vbox_create').hide()
190
def on_edit_account_cancel(self, widget):
191
#self.ui.get_object('vbox_save').hide()
192
#self.ui.get_object('vbox_create').hide()
193
self.select_account()
195
def on_account_delete(self, widget):
196
if not hasattr(self, 'account'):
199
if "id" in self.account:
201
private_fields = [f.split(":")[-1] for f in self.services[self.account["service"]]["config"] if ":" in f]
202
for f in private_fields:
203
if self.account[f].startswith(":KEYRING:"):
204
keyring_id = int(self.account[f].split(":")[-1])
205
gnomekeyring.item_delete_sync(gnomekeyring.get_default_keyring_sync(), keyring_id)
208
self.gwibber.accounts.Delete(self.account["id"])
209
self.populate_account_tree()
210
self.select_account()
212
def on_edit_account_save(self, widget=None):
215
service = self.services[self.account["service"]]
216
is_new = "id" not in self.account
218
if is_new: self.account["id"] = uuid.uuid1().hex
220
for config in service["config"]:
221
is_private = config.startswith("private:")
222
config = config.replace("private:", "")
223
widget = self.account_widget.ui.get_object(config)
227
for p in ["text", "active", "color"]:
228
if widget and hasattr(widget.props, p):
229
value = getattr(widget.props, p)
230
self.account[config] = value
232
if is_private and self.account.has_key(config):
233
if not self.account[config].startswith(":KEYRING:"):
234
self.account[config] = ":KEYRING:%s" % self.put_in_keyring(
235
self.account["id"], config, self.account[config])
238
if isinstance(value, gtk.gdk.Color):
239
value = gtk.color_selection_palette_to_string(
240
gtk.color_selection_palette_from_string(value.to_string()))
241
self.account[config] = value
243
if not self.verify_account(self.account): return False
245
fn = "Create" if is_new else "Update"
246
getattr(self.gwibber.accounts, fn)(json.dumps(self.account))
248
self.ui.get_object('vbox_save').hide()
249
self.ui.get_object('vbox_create').hide()
251
# if we just fixed a failure case, hide the infobar
252
if self.account["id"] == self.selected_account:
253
if hasattr(gtk, "InfoBar"):
255
self.selected_account = None
257
self.populate_account_tree()
259
# Set the autostart gconf key so we get loaded on login
260
gc = gconf.client_get_default()
261
if gc.get("/apps/gwibber/preferences/autostart") is None:
262
gc.set_bool("/apps/gwibber/preferences/autostart", True)
266
def on_button_add_activate(self, widget=None, data=None):
269
def add_account(self):
270
# Populate protocols combobox
271
self.ui.get_object('frame_new_account').show()
272
self.ui.get_object('vbox_details').hide()
273
self.ui.get_object('vbox_account').hide()
274
self.ui.get_object('vbox_save').hide()
275
self.ui.get_object('vbox_create').hide()
277
def on_button_create_clicked(self, widget, data=None):
278
model = widget.get_model()
279
iter = widget.get_active_iter()
280
icon = model.get_value(iter, 1)
281
service = model.get_value(iter, 2)
282
self.account_show(service, icon)
284
def account_show(self, service_id, icon=None, account=None, condition=None, message=None):
285
if hasattr(gtk, "InfoBar"):
286
if condition == "error":
287
self.infobar.set_message_type(gtk.MESSAGE_ERROR)
288
if condition == "info":
289
self.infobar.set_message_type(gtk.MESSAGE_INFO)
290
if message and condition:
291
if hasattr(self, "infobar_content_area"):
292
for child in self.infobar_content_area.get_children(): child.destroy()
293
self.infobar_content_area = self.infobar.get_content_area()
294
message_label = gtk.Label(message)
295
message_label.set_use_markup(True)
296
message_label.set_ellipsize(pango.ELLIPSIZE_END)
297
self.infobar_content_area.add(message_label)
298
self.infobar.show_all()
302
vbox_account = self.ui.get_object('vbox_account')
303
for child in vbox_account.get_children(): child.destroy()
305
self.ui.get_object('vbox_details').show()
306
self.ui.get_object('vbox_account').show()
307
self.ui.get_object('frame_new_account').hide()
309
service = self.services[service_id]
310
self.ui.get_object('label_name').set_label(service["name"])
313
self.ui.get_object('image_type').set_from_pixbuf(icon)
315
if service_id in globals():
317
account = {"service": service_id}
322
aw = globals()[service_id].AccountWidget(account, self)
324
vbox_account.pack_start(aw, False, False)
327
if "color" not in account:
328
account["color"] = service["color"]
330
for config in service["config"]:
331
is_private = config.startswith("private:")
332
config = config.replace("private:", "")
334
if config in account:
335
value = account[config]
336
widget = aw.ui.get_object(config)
338
if isinstance(widget, gtk.Entry):
339
if is_private and account[config].startswith(":KEYRING:"):
340
value = self.get_from_keyring(account["id"], config)
342
widget.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("pink"))
344
widget.set_text(value)
345
widget.connect("changed", self.on_edit_account)
347
elif isinstance(widget, gtk.CheckButton):
348
widget.set_active(value)
349
widget.connect("toggled", self.on_edit_account)
351
elif isinstance(widget, gtk.ColorButton):
352
widget.set_color(gtk.color_selection_palette_from_string(value)[0])
353
widget.connect("color-set", self.on_edit_account)
355
self.account = account
356
self.account_widget = aw
358
self.ui.get_object('vbox_create').hide()
360
def on_accounts_dialog_destroy(self, widget, data=None):
363
def on_accounts_tree_row_activated(self, widget, data=None):
364
self.ui.get_object('vbox_save').hide()
365
self.ui.get_object('vbox_create').hide()
367
model, rows = widget.get_selection().get_selected_rows()
370
iter = model.get_iter(rows[0][0])
371
icon = model.get_value(iter, 1)
372
acct = model.get_value(iter, 2)
373
if self.selected_account == acct["id"] and self.condition:
374
self.account_show(acct["service"], icon, acct, self.condition, self.message)
376
self.account_show(acct["service"], icon, acct)
378
def on_button_close_clicked(self, widget, data=None):