# Copyright (C) 2007 daelstorm. All rights reserved. # # This program 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, either version 3 of the License, or # (at your option) any later version. # # This program 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 this program. If not, see . # # Original copyright below # Copyright (c) 2003-2004 Hyriand. All rights reserved. import gtk import gobject import time import sys, os from pynicotine import slskmessages from utils import InitialiseColumns, PopupMenu, InputDialog, Humanize, HumanSpeed, PressHeader, showCountryTooltip from pynicotine.utils import _ class UserList: def __init__(self, frame): self.frame = frame self.wTree = gtk.glade.XML(os.path.join(os.path.dirname(os.path.realpath(__file__)), "buddylist.glade" ), None, 'nicotine' ) widgets = self.wTree.get_widget_prefix("") for i in widgets: name = gtk.glade.get_widget_name(i) self.__dict__[name] = i #print name, i self.TempWindow.remove(self.userlistvbox) self.TempWindow.destroy() self.wTree.signal_autoconnect(self) TARGETS = [('text/plain', 0, 1)] self.UserList.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, TARGETS, gtk.gdk.ACTION_COPY) self.UserList.enable_model_drag_dest(TARGETS, gtk.gdk.ACTION_COPY) self.UserList.connect("drag_data_get", self.buddylist_drag_data_get_data) self.UserList.connect("drag_data_received", self.DragUserToBuddylist) self.userlist = [] self.usersmodel = gtk.ListStore(gtk.gdk.Pixbuf, gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_STRING) statusiconwidth = self.frame.images["offline"].get_width()+4 self.cols = cols = InitialiseColumns(self.UserList, [_("Status"), statusiconwidth, "pixbuf"], [_("Country"), 25, "pixbuf"], [_("User"), 120, "text", self.CellDataFunc], [_("Speed"), 0, "number", self.CellDataFunc], [_("Files"), 0, "number", self.CellDataFunc], [_("Trusted"), 0, "toggle"], [_("Notify"), 0, "toggle"], [_("Privileged"), 0, "toggle"], [_("Last seen"), 160, "text", self.CellDataFunc], [_("Comments"), -1, "edit", self.CellDataFunc], ) self.col_status, self.col_country, self.col_user, self.col_speed, self.col_files, self.col_trusted, self.col_notify, self.col_privileged, self.col_last, self.col_comments = cols self.col_status.set_sort_column_id(10) self.col_country.set_sort_column_id(14) self.col_user.set_sort_column_id(2) self.col_speed.set_sort_column_id(11) self.col_files.set_sort_column_id(12) self.col_trusted.set_sort_column_id(5) self.col_notify.set_sort_column_id(6) self.col_privileged.set_sort_column_id(7) self.col_last.set_sort_column_id(13) self.col_comments.set_sort_column_id(9) self.col_status.get_widget().hide() self.col_country.get_widget().hide() config = self.frame.np.config.sections for i in range (10): parent = cols[i].get_widget().get_ancestor(gtk.Button) if parent: parent.connect('button_press_event', PressHeader) # Read Show / Hide column settings from last session cols[i].set_visible(config["columns"]["userlist"][i]) if config["columns"]["hideflags"]: cols[1].set_visible(0) config["columns"]["userlist"][1] = 0 for render in self.col_trusted.get_cell_renderers(): render.connect('toggled', self.cell_toggle_callback, self.UserList, 5) for render in self.col_notify.get_cell_renderers(): render.connect('toggled', self.cell_toggle_callback, self.UserList, 6) for render in self.col_privileged.get_cell_renderers(): render.connect('toggled', self.cell_toggle_callback, self.UserList, 7) renderers = self.col_comments.get_cell_renderers() for render in renderers: render.connect('edited', self.cell_edited_callback, self.UserList, 9) self.UserList.set_model(self.usersmodel) self.UserList.set_property("rules-hint", True) self.privileged = [] self.notify = [] self.trusted = [] for user in self.frame.np.config.sections["server"]["userlist"]: notify = user[2] privileged = user[3] if len(user) > 4: trusted = user[4] else: trusted = 0; if len(user) > 5: last_seen = user[5] try: time_from_epoch = time.mktime(time.strptime(last_seen, "%m/%d/%Y %H:%M:%S")) except: if last_seen == '': time_from_epoch = sys.maxint else: time_from_epoch = 0 else: last_seen = _("Never seen") user += [last_seen] time_from_epoch = 0 if len(user) > 6: flag = user[6] else: user += [None] flag = None row = [self.frame.GetStatusImage(0), self.frame.GetFlagImage(flag), user[0], "0", "0", trusted, notify, privileged, last_seen, user[1], 0, 0, 0, int(time_from_epoch), flag] if len(user) > 2: if user[2]: self.notify.append(user[0]) if user[3]: self.privileged.append(user[0]) if trusted: self.trusted.append(user[0]) iter = self.usersmodel.append(row) self.userlist.append([user[0], user[1], last_seen, iter, flag]) self.usersmodel.set_sort_column_id(2, gtk.SORT_ASCENDING) self.Popup_Menu_PrivateRooms = PopupMenu(self.frame) self.popup_menu = popup = PopupMenu(frame) popup.setup( ("#" + _("Send _message"), popup.OnSendMessage, gtk.STOCK_EDIT), ("", None), ("#" + _("Show IP a_ddress"), popup.OnShowIPaddress, gtk.STOCK_NETWORK), ("#" + _("Get user i_nfo"), popup.OnGetUserInfo, gtk.STOCK_DIALOG_INFO), ("#" + _("Brow_se files"), popup.OnBrowseUser, gtk.STOCK_HARDDISK), ("#" + _("Gi_ve privileges"), popup.OnGivePrivileges, gtk.STOCK_JUMP_TO), ("$" + _("_Ban this user"), popup.OnBanUser), ("$" + _("_Ignore this user"), popup.OnIgnoreUser), ("", None), ("$" + _("_Online notify"), self.OnNotify), ("$" + _("_Privileged"), self.OnPrivileged), ("$" + _("_Trusted"), self.OnTrusted), ("", None), ("#" + _("Edit _comments"), self.OnEditComments, gtk.STOCK_EDIT), ("#" + _("_Remove"), self.OnRemoveUser, gtk.STOCK_CANCEL), (1, _("Private rooms"), self.Popup_Menu_PrivateRooms, popup.OnPrivateRooms), ) items = self.popup_menu.get_children() self.Menu_SendMessage = items[0] self.Menu_ShowIPaddress = items[2] self.Menu_GetUserInfo = items[3] self.Menu_BrowseUser = items[4] self.Menu_GivePrivileges = items[5] self.Menu_BanUser = items[6] self.Menu_IgnoreUser = items[7] self.Menu_OnNotify = items[9] self.Menu_OnPrivileged = items[10] self.Menu_Trusted = items[11] self.Menu_EditComments = items[13] self.Menu_RemoveUser = items[14] self.Menu_PrivateRooms = items[15] self.UserList.connect("button_press_event", self.OnPopupMenu) def OnTooltip(self, widget, x, y, keyboard_mode, tooltip): return showCountryTooltip(widget, x, y, tooltip, 14, 'flag_') def OnMoveList(self, widget): tab = always = chatrooms = False if self.frame.buddylist_in_tab.get_active(): tab = True if self.frame.buddylist_always_visible.get_active(): always = True if self.frame.buddylist_in_chatrooms1.get_active(): chatrooms = True if tab: self.frame.buddylist_in_chatrooms1.set_active(True) self.frame.OnChatRooms(None) if always: self.frame.buddylist_in_tab.set_active(True) if chatrooms: self.frame.buddylist_always_visible.set_active(True) def OnAddUser(self, widget): text = widget.get_text() if not text: return widget.set_text("") self.AddToList(text) def UpdateColours(self): self.frame.SetTextBG(self.AddUserEntry) def buddylist_drag_data_get_data(self, treeview, context, selection, target_id, etime): treeselection = treeview.get_selection() model, iter = treeselection.get_selected() status, flag, user, speed, files, trusted, notify, privileged, lastseen, comments = model.get(iter, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) #data = (status, flag, user, speed, files, trusted, notify, privileged, lastseen, comments) selection.set(selection.target, 8, user) def DragUserToBuddylist(self, treeview, context, x, y, selection, info, etime): model = treeview.get_model() user = selection.data if user: self.AddToList(user) def OnSettingsBanIgnore(self, widget): self.frame.OnSettingsBanIgnore(widget) def CellDataFunc(self, column, cellrenderer, model, iter): colour = self.frame.np.config.sections["ui"]["search"] if colour == "": colour = None cellrenderer.set_property("foreground", colour) def cell_toggle_callback(self, widget, index, treeview, pos): iter = self.usersmodel.get_iter(index) user = self.usersmodel.get_value(iter, 2) value = self.usersmodel.get_value(iter, pos) self.usersmodel.set(iter, pos, not value) toggle = not value if pos == 5: if toggle: if user not in self.trusted: self.trusted.append(user) else: if user in self.trusted: self.trusted.remove(user) elif pos == 6: if toggle: if user not in self.notify: self.notify.append(user) else: if user in self.notify: self.notify.remove(user) elif pos == 7: if toggle: if user not in self.privileged: self.privileged.append(user) else: if user in self.privileged: self.privileged.remove(user) self.SaveUserList() def cell_edited_callback(self, widget, index, value, treeview, pos): store = treeview.get_model() iter = store.get_iter(index) if pos == 9: self.SetComment(iter, store, value) def SetLastSeen(self, user, online =False): last_seen = "" time_from_epoch = sys.maxint if not online: last_seen = time.strftime("%m/%d/%Y %H:%M:%S") time_from_epoch = time.mktime(time.strptime(last_seen, "%m/%d/%Y %H:%M:%S")) for i in self.userlist: if i[0] == user: i[2] = last_seen self.usersmodel.set(i[3], 8, last_seen) self.usersmodel.set(i[3], 13, int(time_from_epoch)) break if not online: self.SaveUserList() def SetComment(self, iter, store, comments=None): user = store.get_value(iter, 2) if comments is not None: for i in self.userlist: if i[0] == user: i[1] = comments self.usersmodel.set(iter, 9, comments) break self.SaveUserList() def ConnClose(self): for user in self.userlist: self.usersmodel.set(user[3], 0, self.frame.GetStatusImage(0), 3, "0", 4, "0", 10, 0, 11, 0, 12, 0) for user in self.userlist: if self.usersmodel.get(user[3], 8)[0] is "": self.SetLastSeen(user[0]) def OnPopupMenu(self, widget, event): items = self.popup_menu.get_children() d = self.UserList.get_path_at_pos(int(event.x), int(event.y)) if d: path, column, x, y = d user = self.UserList.get_model().get_value(self.UserList.get_model().get_iter(path), 2) if event.button != 3: if event.type == gtk.gdk._2BUTTON_PRESS: self.frame.privatechats.SendMessage(user, None, 1) self.frame.ChangeMainPage(None, "private") return self.popup_menu.set_user(user) items = self.popup_menu.get_children() me = (self.popup_menu.user == None or self.popup_menu.user == self.frame.np.config.sections["server"]["login"]) #self.Menu_SendMessage #self.Menu_ShowIPaddress #self.Menu_GetUserInfo #self.Menu_BrowseUser #self.Menu_GivePrivileges self.Menu_BanUser.set_active(user in self.frame.np.config.sections["server"]["banlist"]) self.Menu_IgnoreUser.set_active(user in self.frame.np.config.sections["server"]["ignorelist"]) self.Menu_OnNotify.set_active(user in self.notify) self.Menu_OnPrivileged.set_active(user in self.privileged) self.Menu_Trusted.set_active(user in self.trusted) #self.Menu_EditComments #self.Menu_RemoveUser self.Menu_PrivateRooms.set_sensitive(not me) # Private rooms self.popup_menu.popup(None, None, None, event.button, event.time) def GetIter(self, user): iters = [i[3] for i in self.userlist if i[0] == user] if iters: return iters[0] else: return None def GetUserStatus(self, msg): iter = self.GetIter(msg.user) if iter is None: return if msg.status == int(self.usersmodel.get_value(iter, 10)): return if msg.user in self.notify: status = [_("User %s is offline"), _("User %s is away"), _("User %s is online")][msg.status] self.frame.logMessage(status % msg.user) self.frame.NewNotification(status % msg.user) img = self.frame.GetStatusImage(msg.status) self.usersmodel.set(iter, 0, img, 10, msg.status) if msg.status: # online self.SetLastSeen(msg.user, online=True) elif self.usersmodel.get(iter, 8)[0] is "": # disconnected self.SetLastSeen(msg.user) def GetUserStats(self, msg): iter = self.GetIter(msg.user) if iter is None: return hspeed = HumanSpeed(msg.avgspeed) hfiles = Humanize(msg.files) self.usersmodel.set(iter, 3, hspeed, 4, hfiles, 11, msg.avgspeed, 12, msg.files) if msg.country is not None: flag = "flag_"+msg.country self.usersmodel.set(iter, 1, self.frame.GetFlagImage(flag), 14, flag) for i in self.userlist: if i[0] == msg.user: i[4] = flag break def SetUserFlag(self, user, flag): iter = self.GetIter(user) if iter is None: return if user not in [i[0] for i in self.userlist]: return self.usersmodel.set(iter, 1, self.frame.GetFlagImage(flag), 14, flag) for i in self.userlist: if i[0] == user: i[4] = flag def AddToList(self, user): if user in [i[0] for i in self.userlist]: return row = [self.frame.GetStatusImage(0), None, user, "0", "0", False, False, False, _("Never seen"), "", 0, 0, 0, 0, ""] iter = self.usersmodel.append(row) self.userlist.append([user, "", _("Never seen"), iter, self.frame.GetUserFlag(user)]) self.SaveUserList() self.frame.np.queue.put(slskmessages.AddUser(user)) self.frame.np.queue.put(slskmessages.GetPeerAddress(user)) for widget in self.frame.BuddiesComboEntries: gobject.idle_add(widget.Append, user) if self.frame.np.config.sections["words"]["buddies"]: gobject.idle_add(self.frame.chatrooms.roomsctrl.UpdateCompletions) gobject.idle_add(self.frame.privatechats.UpdateCompletions) def OnEditComments(self, widget): user = self.popup_menu.get_user() for i in self.userlist: if i[0] == user: comments = i[1] break else: comments = "" comments = InputDialog(self.frame.MainWindow, _("Edit comments")+"...", _("Comments")+":", comments) if comments is not None: for i in self.userlist: if i[0] == user: i[1] = comments self.usersmodel.set(i[3], 9, comments) break self.SaveUserList() def SaveUserList(self): l = [] for i in self.userlist: user, comment, seen, iter, flag = i l.append([user, comment, (user in self.notify), (user in self.privileged), (user in self.trusted), seen, flag]) self.frame.np.config.sections["server"]["userlist"] = l self.frame.np.config.writeConfiguration() def saveColumns(self): columns = [] for column in self.UserList.get_columns(): columns.append(column.get_visible()) self.frame.np.config.sections["columns"]["userlist"] = columns def RemoveFromList(self, user): if user in self.notify: self.notify.remove(user) if user in self.privileged: self.privileged.remove(user) if user in self.trusted: self.trusted.remove(user) for i in self.userlist: if i[0] == user: self.userlist.remove(i) self.usersmodel.remove(i[3]) break self.SaveUserList() for widget in self.frame.BuddiesComboEntries: gobject.idle_add(widget.Remove, user) if self.frame.np.config.sections["words"]["buddies"]: gobject.idle_add(self.frame.chatrooms.roomsctrl.UpdateCompletions) gobject.idle_add(self.frame.privatechats.UpdateCompletions) def OnRemoveUser(self, widget): self.RemoveFromList(self.popup_menu.get_user()) def OnNotify(self, widget): user = self.popup_menu.get_user() if not widget.get_active(): if user in self.notify: self.notify.remove(user) else: if not user in self.notify: self.notify.append(user) self.SaveUserList() def OnPrivileged(self, widget): user = self.popup_menu.get_user() if not widget.get_active(): if user in self.privileged: self.privileged.remove(user) else: if not user in self.privileged: self.privileged.append(user) self.SaveUserList() def OnTrusted(self, widget): user = self.popup_menu.get_user() if not widget.get_active(): if user in self.trusted: self.trusted.remove(user) else: if not user in self.trusted: self.trusted.append(user) for i in self.userlist: if i[0] == user: self.usersmodel.set(i[3], 5, (user in self.trusted)) self.SaveUserList()