438 lines
16 KiB
Python
438 lines
16 KiB
Python
# This file is part of Gajim.
|
|
#
|
|
# Gajim is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published
|
|
# by the Free Software Foundation; version 3 only.
|
|
#
|
|
# Gajim is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
from gi.repository import Gtk
|
|
from gi.repository import Gdk
|
|
|
|
from gajim import gui_menu_builder
|
|
from gajim.common import app
|
|
from gajim.common import helpers
|
|
from gajim.common.i18n import Q_
|
|
from gajim.gtk import ErrorDialog
|
|
from gajim.gtk.util import get_builder
|
|
|
|
|
|
class ManageBookmarksWindow:
|
|
def __init__(self):
|
|
self.xml = get_builder('manage_bookmarks_window.ui')
|
|
self.window = self.xml.get_object('manage_bookmarks_window')
|
|
self.window.set_transient_for(app.interface.roster.window)
|
|
|
|
self.ignore_events = False
|
|
|
|
# Account-JID, RoomName, Room-JID, Autojoin, Minimize, Password, Nick,
|
|
# Show_Status
|
|
self.treestore = Gtk.TreeStore(str, str, str, bool, bool, str,
|
|
str, str, str)
|
|
self.treestore.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
|
|
|
# Store bookmarks in treeview.
|
|
for account, account_label in app.get_enabled_accounts_with_labels(
|
|
connected_only=True, private_storage_only=True):
|
|
iter_ = self.treestore.append(None, [
|
|
None, account, None, None,
|
|
None, None, None, None, account_label])
|
|
|
|
con = app.connections[account]
|
|
bookmarks = con.get_module('Bookmarks').bookmarks
|
|
for jid, bookmark in bookmarks.items():
|
|
if not bookmark['name']:
|
|
# No name was given for this bookmark.
|
|
# Use the first part of JID instead...
|
|
name = jid.split("@")[0]
|
|
bookmark['name'] = name
|
|
|
|
# make '1', '0', 'true', 'false' (or other) to True/False
|
|
autojoin = helpers.from_xs_boolean_to_python_boolean(
|
|
bookmark['autojoin'])
|
|
|
|
minimize = helpers.from_xs_boolean_to_python_boolean(
|
|
bookmark['minimize'])
|
|
|
|
print_status = bookmark.get('print_status', '')
|
|
if print_status not in ('', 'all', 'in_and_out', 'none'):
|
|
print_status = ''
|
|
self.treestore.append(iter_, [account,
|
|
bookmark['name'],
|
|
jid,
|
|
autojoin,
|
|
minimize,
|
|
bookmark['password'],
|
|
bookmark['nick'],
|
|
print_status,
|
|
bookmark['name']])
|
|
|
|
self.print_status_combobox = self.xml.get_object(
|
|
'print_status_combobox')
|
|
model = Gtk.ListStore(str, str)
|
|
|
|
self.option_list = {
|
|
'': _('Default'), 'all': Q_('?print_status:All'),
|
|
'in_and_out': _('Enter and leave only'),
|
|
'none': Q_('?print_status:None')}
|
|
for opt, label in sorted(self.option_list.items()):
|
|
model.append([label, opt])
|
|
|
|
self.print_status_combobox.set_model(model)
|
|
self.print_status_combobox.set_active(1)
|
|
|
|
self.view = self.xml.get_object('bookmarks_treeview')
|
|
self.view.set_model(self.treestore)
|
|
self.view.expand_all()
|
|
|
|
renderer = Gtk.CellRendererText()
|
|
column = Gtk.TreeViewColumn('Bookmarks', renderer, text=8)
|
|
self.view.append_column(column)
|
|
|
|
self.selection = self.view.get_selection()
|
|
self.selection.connect('changed', self.bookmark_selected)
|
|
|
|
# Prepare input fields
|
|
self.title_entry = self.xml.get_object('title_entry')
|
|
self.title_entry.connect('changed', self.on_title_entry_changed)
|
|
self.nick_entry = self.xml.get_object('nick_entry')
|
|
self.nick_entry.connect('changed', self.on_nick_entry_changed)
|
|
self.server_entry = self.xml.get_object('server_entry')
|
|
self.server_entry.connect(
|
|
'focus-out-event', self.on_server_entry_focus_out)
|
|
self.room_entry = self.xml.get_object('room_entry')
|
|
self.room_entry_changed_id = self.room_entry.connect(
|
|
'changed', self.on_room_entry_changed)
|
|
self.pass_entry = self.xml.get_object('pass_entry')
|
|
self.pass_entry.connect('changed', self.on_pass_entry_changed)
|
|
self.autojoin_checkbutton = self.xml.get_object('autojoin_checkbutton')
|
|
self.minimize_checkbutton = self.xml.get_object('minimize_checkbutton')
|
|
self.settings_box = self.xml.get_object('settings_box')
|
|
self.remove_bookmark_button = self.xml.get_object(
|
|
'remove_bookmark_button')
|
|
|
|
self.xml.connect_signals(self)
|
|
self.window.show_all()
|
|
# select root iter
|
|
first_iter = self.treestore.get_iter_first()
|
|
if first_iter:
|
|
self.selection.select_iter(first_iter)
|
|
|
|
def on_key_press_event(self, widget, event):
|
|
if event.keyval == Gdk.KEY_Escape:
|
|
self.window.destroy()
|
|
|
|
def on_add_bookmark_button_clicked(self, widget):
|
|
"""
|
|
Add a new bookmark
|
|
"""
|
|
# Get the account that is currently used
|
|
# (the parent of the currently selected item)
|
|
(model, iter_) = self.selection.get_selected()
|
|
if not iter_: # Nothing selected, do nothing
|
|
return
|
|
|
|
parent = model.iter_parent(iter_)
|
|
|
|
if parent:
|
|
# We got a bookmark selected, so we add_to the parent
|
|
add_to = parent
|
|
else:
|
|
# No parent, so we got an account -> add to this.
|
|
add_to = iter_
|
|
|
|
account = model[add_to][1]
|
|
nick = app.nicks[account]
|
|
label = _('New Group Chat')
|
|
iter_ = self.treestore.append(add_to, [
|
|
account, label, '@', False, False, '', nick, 'in_and_out', label])
|
|
|
|
self.view.expand_row(model.get_path(add_to), True)
|
|
self.view.set_cursor(model.get_path(iter_))
|
|
|
|
def on_remove_bookmark_button_clicked(self, widget):
|
|
"""
|
|
Remove selected bookmark
|
|
"""
|
|
(model, iter_) = self.selection.get_selected()
|
|
if not iter_: # Nothing selected
|
|
return
|
|
|
|
if not model.iter_parent(iter_):
|
|
# Don't remove account iters
|
|
return
|
|
|
|
self.ignore_events = True
|
|
model.remove(iter_)
|
|
self.selection.unselect_all()
|
|
self.clear_fields()
|
|
self.set_sensitive_all(False)
|
|
self.ignore_events = False
|
|
|
|
def check_valid_bookmark(self):
|
|
"""
|
|
Check if all necessary fields are entered correctly
|
|
"""
|
|
(model, iter_) = self.selection.get_selected()
|
|
|
|
if not model.iter_parent(iter_):
|
|
# Account data can't be changed
|
|
return
|
|
|
|
server = self.server_entry.get_text()
|
|
room = self.room_entry.get_text()
|
|
|
|
if server == '' or room == '':
|
|
ErrorDialog(
|
|
_('This bookmark has invalid data'),
|
|
_('Please be sure to fill out server and room fields '
|
|
'or remove this bookmark.'))
|
|
return False
|
|
|
|
return True
|
|
|
|
def on_ok_button_clicked(self, widget):
|
|
"""
|
|
Parse the treestore data into our new bookmarks array, then send the
|
|
new bookmarks to the server.
|
|
"""
|
|
|
|
(model, iter_) = self.selection.get_selected()
|
|
if iter_ and model.iter_parent(iter_):
|
|
# bookmark selected, check it
|
|
if not self.check_valid_bookmark():
|
|
return
|
|
|
|
for account in self.treestore:
|
|
acct = account[1]
|
|
con = app.connections[acct]
|
|
con.get_module('Bookmarks').bookmarks = {}
|
|
|
|
for bm in account.iterchildren():
|
|
# Convert True/False/None to '1' or '0'
|
|
autojoin = str(int(bm[3]))
|
|
minimize = str(int(bm[4]))
|
|
name = bm[1]
|
|
jid = bm[2]
|
|
pw = bm[5]
|
|
nick = bm[6]
|
|
|
|
# create the bookmark-dict
|
|
bmdict = {
|
|
'name': name,
|
|
'autojoin': autojoin,
|
|
'minimize': minimize,
|
|
'password': pw,
|
|
'nick': nick,
|
|
'print_status': bm[7]}
|
|
|
|
con.get_module('Bookmarks').bookmarks[jid] = bmdict
|
|
|
|
con.get_module('Bookmarks').store_bookmarks()
|
|
gui_menu_builder.build_bookmark_menu(acct)
|
|
self.window.destroy()
|
|
|
|
def on_cancel_button_clicked(self, widget):
|
|
self.window.destroy()
|
|
|
|
def bookmark_selected(self, selection):
|
|
"""
|
|
Fill in the bookmark's data into the fields.
|
|
"""
|
|
(model, iter_) = selection.get_selected()
|
|
|
|
if not iter_:
|
|
# After removing the last bookmark for one account
|
|
# this will be None, so we will just:
|
|
return
|
|
|
|
if model.iter_parent(iter_):
|
|
# make the fields sensitive
|
|
self.set_sensitive_all(True)
|
|
else:
|
|
# Top-level has no data (it's the account fields)
|
|
# clear fields & make them insensitive
|
|
self.clear_fields()
|
|
self.set_sensitive_all(False)
|
|
return
|
|
|
|
# Fill in the data for childs
|
|
self.title_entry.set_text(model[iter_][1])
|
|
room_jid = model[iter_][2]
|
|
room_jid_s = room_jid.split('@')
|
|
if len(room_jid_s) == 1:
|
|
room = ''
|
|
server = room_jid
|
|
else:
|
|
(room, server) = room_jid_s
|
|
self.room_entry.handler_block(self.room_entry_changed_id)
|
|
self.room_entry.set_text(room)
|
|
self.room_entry.handler_unblock(self.room_entry_changed_id)
|
|
self.server_entry.set_text(server)
|
|
|
|
self.autojoin_checkbutton.set_active(model[iter_][3])
|
|
self.minimize_checkbutton.set_active(model[iter_][4])
|
|
# sensitive only if auto join is checked
|
|
self.minimize_checkbutton.set_sensitive(model[iter_][3])
|
|
|
|
if model[iter_][5] is not None:
|
|
password = model[iter_][5]
|
|
else:
|
|
password = None
|
|
|
|
if password:
|
|
self.pass_entry.set_text(password)
|
|
else:
|
|
self.pass_entry.set_text('')
|
|
nick = model[iter_][6]
|
|
if nick:
|
|
self.nick_entry.set_text(nick)
|
|
else:
|
|
self.nick_entry.set_text('')
|
|
|
|
print_status = model[iter_][7]
|
|
opts = sorted(self.option_list.keys())
|
|
self.print_status_combobox.set_active(opts.index(print_status))
|
|
|
|
def on_title_entry_changed(self, widget):
|
|
if self.ignore_events:
|
|
return
|
|
(model, iter_) = self.selection.get_selected()
|
|
if iter_: # After removing a bookmark, we got nothing selected
|
|
if model.iter_parent(iter_):
|
|
# Don't clear the title field for account nodes
|
|
model[iter_][1] = self.title_entry.get_text()
|
|
|
|
def on_nick_entry_changed(self, widget):
|
|
if self.ignore_events:
|
|
return
|
|
(model, iter_) = self.selection.get_selected()
|
|
if iter_:
|
|
nick = self.nick_entry.get_text()
|
|
try:
|
|
nick = helpers.parse_resource(nick)
|
|
except helpers.InvalidFormat:
|
|
ErrorDialog(
|
|
_('Invalid nickname'),
|
|
_('Character not allowed'),
|
|
transient_for=self.window)
|
|
self.nick_entry.set_text(model[iter_][6])
|
|
return True
|
|
model[iter_][6] = nick
|
|
|
|
def on_server_entry_focus_out(self, widget, event):
|
|
if self.ignore_events:
|
|
return
|
|
(model, iter_) = self.selection.get_selected()
|
|
if not iter_:
|
|
return
|
|
server = widget.get_text()
|
|
if not server:
|
|
return
|
|
if '@' in server:
|
|
ErrorDialog(
|
|
_('Invalid server'),
|
|
_('Character not allowed'),
|
|
transient_for=self.window)
|
|
widget.set_text(server.replace('@', ''))
|
|
|
|
room = self.room_entry.get_text().strip()
|
|
if not room:
|
|
return
|
|
room_jid = room + '@' + server.strip()
|
|
try:
|
|
room_jid = helpers.parse_jid(room_jid)
|
|
except helpers.InvalidFormat as e:
|
|
ErrorDialog(
|
|
_('Invalid server'),
|
|
_('Character not allowed'),
|
|
transient_for=self.window)
|
|
self.server_entry.set_text(model[iter_][2].split('@')[1])
|
|
return True
|
|
model[iter_][2] = room_jid
|
|
|
|
def on_room_entry_changed(self, widget):
|
|
if self.ignore_events:
|
|
return
|
|
(model, iter_) = self.selection.get_selected()
|
|
if not iter_:
|
|
return
|
|
room = widget.get_text()
|
|
if not room:
|
|
return
|
|
if '@' in room:
|
|
room, server = room.split('@', 1)
|
|
widget.set_text(room)
|
|
if server:
|
|
self.server_entry.set_text(server)
|
|
self.server_entry.grab_focus()
|
|
server = self.server_entry.get_text().strip()
|
|
if not server:
|
|
return
|
|
room_jid = room.strip() + '@' + server
|
|
try:
|
|
room_jid = helpers.parse_jid(room_jid)
|
|
except helpers.InvalidFormat:
|
|
ErrorDialog(
|
|
_('Invalid room'),
|
|
_('Character not allowed'),
|
|
transient_for=self.window)
|
|
return True
|
|
model[iter_][2] = room_jid
|
|
|
|
def on_pass_entry_changed(self, widget):
|
|
if self.ignore_events:
|
|
return
|
|
(model, iter_) = self.selection.get_selected()
|
|
if iter_:
|
|
model[iter_][5] = self.pass_entry.get_text()
|
|
|
|
def on_autojoin_checkbutton_toggled(self, widget, *args):
|
|
if self.ignore_events:
|
|
return
|
|
(model, iter_) = self.selection.get_selected()
|
|
if iter_:
|
|
model[iter_][3] = self.autojoin_checkbutton.get_active()
|
|
self.minimize_checkbutton.set_sensitive(model[iter_][3])
|
|
|
|
def on_minimize_checkbutton_toggled(self, widget, *args):
|
|
if self.ignore_events:
|
|
return
|
|
(model, iter_) = self.selection.get_selected()
|
|
if iter_:
|
|
model[iter_][4] = self.minimize_checkbutton.get_active()
|
|
|
|
def on_print_status_combobox_changed(self, widget):
|
|
if self.ignore_events:
|
|
return
|
|
active = widget.get_active()
|
|
model = widget.get_model()
|
|
print_status = model[active][1]
|
|
(model2, iter_) = self.selection.get_selected()
|
|
if iter_:
|
|
model2[iter_][7] = print_status
|
|
|
|
def clear_fields(self):
|
|
widgets = [
|
|
self.title_entry, self.nick_entry, self.room_entry,
|
|
self.server_entry, self.pass_entry]
|
|
for field in widgets:
|
|
field.set_text('')
|
|
self.autojoin_checkbutton.set_active(False)
|
|
self.minimize_checkbutton.set_active(False)
|
|
self.print_status_combobox.set_active(1)
|
|
|
|
def set_sensitive_all(self, sensitive):
|
|
widgets = [
|
|
self.title_entry, self.nick_entry, self.room_entry,
|
|
self.server_entry, self.pass_entry, self.settings_box,
|
|
self.remove_bookmark_button]
|
|
for field in widgets:
|
|
field.set_sensitive(sensitive)
|