# -*- coding: utf-8 -*-
# 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 os
import gtk, gtk.glade
from tempfile import gettempdir
from pynicotine.pynicotine import NetworkEventProcessor
from pynicotine import slskmessages
from pynicotine import slskproto
from pynicotine.utils import version
import time
try:
import gtkmozembed
except ImportError:
gtkmozembed = None
import gobject
import thread
import urllib
import signal
import re
try:
import webbrowser
except ImportError:
webbrowser = None
from privatechat import PrivateChats
from chatrooms import ChatRooms
from userinfo import UserTabs, UserInfo
from search import Searches
from downloads import Downloads
from uploads import Uploads
from userlist import UserList
from userbrowse import UserBrowse
from settingswindow import SettingsWindow
from fastconfigure import FastConfigureAssistant
from about import *
from checklatest import checklatest
from pynicotine.config import *
import utils, pynicotine.utils
from utils import AppendLine, ImageLabel, IconNotebook, ScrollBottom, PopupMenu, Humanize, HumanSpeed, HumanSize, popupWarning, OpenUri
import translux
from dirchooser import ChooseFile, SaveFile
from pynicotine.utils import _, ChangeTranslation, executeCommand
import nowplaying
from pynicotine import pluginsystem
from pynicotine.logfacility import log
from entrydialog import *
import pynicotine.upnp as upnp
SEXY=True
try:
import sexy
except ImportError:
SEXY=False
# LibSexy is deprecated, we should try to find a replacement
#msg = _("Note: Python Bindings for libsexy were not found. To enable spell checking, get them from http://www.chipx86.com/wiki/Libsexy or your distribution's package manager. Look for sexy-python or python-sexy.")
#log.addwarning(msg)
class roomlist:
def __init__(self, frame):
self.frame = frame
#self.tooltips = self.frame.tooltips
self.wTree = gtk.glade.XML(os.path.join(os.path.dirname(os.path.realpath(__file__)), "roomlist.glade" ), None, 'nicotine' )
widgets = self.wTree.get_widget_prefix("")
for i in widgets:
name = gtk.glade.get_widget_name(i)
self.__dict__[name] = i
self.RoomList.remove(self.vbox2)
self.RoomList.destroy()
# self.RoomsList is the TreeView
self.wTree.signal_autoconnect(self)
self.search_iter = None
self.query = ""
self.room_model = self.RoomsList.get_model()
self.FindRoom.connect("clicked", self.OnSearchRoom)
def OnCreateRoom(self, widget):
room = widget.get_text()
if not room:
return
self.frame.np.queue.put(slskmessages.JoinRoom(room))
widget.set_text("")
def OnSearchRoom(self, widget):
if self.room_model is not self.RoomsList.get_model():
self.room_model = self.RoomsList.get_model()
self.search_iter = self.room_model.get_iter_root()
room = self.SearchRooms.get_text().lower()
if not room:
return
if self.query == room:
if self.search_iter is None:
self.search_iter = self.room_model.get_iter_root()
else:
self.search_iter = self.room_model.iter_next(self.search_iter)
else:
self.search_iter = self.room_model.get_iter_root()
self.query = room
while self.search_iter:
room_match, size = self.room_model.get(self.search_iter, 0, 1)
if self.query in room_match.lower():
path = self.room_model.get_path(self.search_iter)
self.RoomsList.set_cursor(path)
#print room_match
break
self.search_iter = self.room_model.iter_next(self.search_iter)
class BuddiesComboBoxEntry(gtk.ComboBoxEntry):
def __init__(self, frame):
self.frame = frame
gtk.ComboBoxEntry.__init__(self)
self.items = {}
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
self.set_text_column(0)
self.store.set_default_sort_func(lambda *args: -1)
self.store.set_sort_column_id(-1, gtk.SORT_ASCENDING)
self.show()
def Fill(self):
self.items.clear()
self.store.clear()
self.items[""] = self.store.append([""])
for user in self.frame.np.config.sections["server"]["userlist"]:
self.items[user[0]] = self.store.append([user[0]])
self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
def Append(self, item):
if item in self.items:
return
self.items[item] = self.get_model().append([item])
def Remove(self, item):
if item in self.items:
self.get_model().remove(self.items[item] )
del self.items[item]
class BrowserWindow(gtk.VBox):
"""
An HTML browser
"""
def __init__(self, frame, url, nostyles=False):
"""
Initializes the window
"""
gtk.VBox.__init__(self)
self.set_border_width(5)
self.set_spacing(3)
self.nostyles = nostyles
self.action_count = 0
self.frame = frame
if not nostyles:
top = gtk.HBox()
top.set_spacing(3)
self.back = gtk.Button()
image = gtk.Image()
image.set_from_stock('gtk-go-back', gtk.ICON_SIZE_SMALL_TOOLBAR)
self.back.set_image(image)
self.back.set_sensitive(False)
self.back.connect('clicked', self.on_back)
top.pack_start(self.back, False, False)
self.next = gtk.Button()
image = gtk.Image()
image.set_from_stock('gtk-go-forward', gtk.ICON_SIZE_SMALL_TOOLBAR)
self.next.set_image(image)
self.next.connect('clicked', self.on_next)
self.next.set_sensitive(False)
top.pack_start(self.next, False, False)
w = gtk.Button(_("Open Browser"))
w.connect('clicked', self.on_open_browser)
top.pack_start(w, False, False)
self.entry = gtk.Entry()
self.entry.connect('activate', self.entry_activate)
top.pack_start(self.entry, True, True)
self.pack_start(top, False, True)
try:
gtkmozembed.set_profile_path(gettempdir(), "nicotine+mozembed")
self.view = gtkmozembed.MozEmbed()
except Exception, e:
log.addwarning(_('Embedded Mozilla webrowser failed to load: %s(error)') % {'error':e})
return
else:
self.pack_start(self.view, True, True)
if not nostyles:
self.view.connect('location', self.on_location_change)
self.show_all()
self.finish()
repeat=True
self.view.set_data('
' + _('Loading requested'
' information...') + '', '')
self.view.connect('net-stop', self.on_net_stop)
self.cache_dir = gettempdir()
self.server = ''
if url:
self.load_url(url, self.action_count, False)
def finish(self, repeat=True):
"""
Waits for current pending gtk events to finish
"""
while gtk.events_pending():
gtk.main_iteration()
if not repeat: break
def shutdown(self):
self.view.stop_load()
self.view.is_realize = False
self.finish()
def on_net_stop(self, *args):
"""
Called when mozilla is done loading the page
"""
self.view.stopped = True
def set_text(self, text):
"""
Sets the text of the browser window
"""
self.view.set_data(text, '')
def entry_activate(self, *e):
"""
Called when the user presses enter in the address bar
"""
url = unicode(self.entry.get_text(), 'utf-8')
self.load_url(url, self.action_count)
def on_location_change(self, mozembed):
# Only called when not self.nostyles
self.entry.set_text(mozembed.get_location())
self.back.set_sensitive(self.view.can_go_back())
self.next.set_sensitive(self.view.can_go_forward())
def on_next(self, widget):
"""
Goes to the next entry in history
"""
self.view.go_forward()
def on_back(self, widget):
"""
Goes to the previous entry in history
"""
self.view.go_back()
def on_open_browser(self, button):
"""
Opens the current URL in a new browser window (if possible).
"""
# This method is rarely used, so we only do the import when we need to.
# "new=1" is to request new window.
webbrowser.open(self.view.get_location(), new=1)
def load_url(self, url, action_count, history=False):
"""
Loads a URL, either from the cache, or from the website specified
"""
self.view.load_url(url)
if not self.nostyles:
if self.view.can_go_back(): self.back.set_sensitive(True)
if not self.view.can_go_forward(): self.next.set_sensitive(False)
self.entry.set_sensitive(True)
self.entry.set_text(url)
class NicotineFrame:
def __init__(self, config, plugindir, use_trayicon, try_rgba, start_hidden=False, WebBrowser=True, bindip=None):
self.clip_data = ""
self.configfile = config
self.transfermsgs = {}
self.transfermsgspostedtime = 0
self.manualdisconnect = 0
self.away = 0
self.exiting = 0
self.startup = True
self.current_tab = 0
self.rescanning = 0
self.brescanning = 0
self.needrescan = 0
self.autoaway = False
self.awaytimer = None
self.SEXY = SEXY
self.chatrooms = None
self.bindip = bindip
self.got_focus = False
try:
import pynotify
pynotify.init("Nicotine+")
self.pynotify = pynotify
self.pynotifyBox = None
from xml.dom.minidom import getDOMImplementation
self.xmldocument = getDOMImplementation().createDocument(None, None, None)
except ImportError:
self.pynotify = None
self.np = NetworkEventProcessor(self, self.callback, self.logMessage, self.SetStatusText, self.bindip, config)
config = self.np.config.sections
self.temp_modes_order = config["ui"]["modes_order"]
utils.DECIMALSEP = config["ui"]["decimalsep"]
utils.CATCH_URLS = config["urls"]["urlcatching"]
utils.HUMANIZE_URLS = config["urls"]["humanizeurls"]
utils.PROTOCOL_HANDLERS = config["urls"]["protocols"].copy()
utils.PROTOCOL_HANDLERS["slsk"] = self.OnSoulSeek
utils.USERNAMEHOTSPOTS = config["ui"]["usernamehotspots"]
utils.NICOTINE = self
pynicotine.utils.log = self.logMessage
self.LoadIcons()
self.ChangeTranslation = ChangeTranslation
if self.np.config.sections["language"]["setlanguage"]:
trerror = self.ChangeTranslation(self.np.config.sections["language"]["language"])
if trerror:
log.add(' '.join(['TError:', trerror]))
self.BuddiesComboEntries = []
self.accel_group = gtk.AccelGroup()
#self.tooltips = gtk.Tooltips()
#self.tooltips.enable()
self.roomlist = roomlist(self)
# Import glade widgets
gtk.glade.set_custom_handler(self.get_custom_widget)
self.wTree = gtk.glade.XML(os.path.join(os.path.dirname(os.path.realpath(__file__)), "mainwindow.glade" ), None, 'nicotine' )
widgets = self.wTree.get_widget_prefix("")
for i in widgets:
name = gtk.glade.get_widget_name(i)
self.__dict__[name] = i
# Create Search combo ListStores
self.SearchEntryCombo_List = gtk.ListStore(gobject.TYPE_STRING)
self.SearchEntryCombo.set_model(self.SearchEntryCombo_List)
self.SearchEntryCombo.set_text_column(0)
self.SearchEntry = self.SearchEntryCombo.child
self.SearchEntry.connect("activate", self.OnSearch)
self.RoomSearchCombo_List = gtk.ListStore(gobject.TYPE_STRING)
self.RoomSearchCombo.set_model(self.RoomSearchCombo_List)
self.RoomSearchCombo.set_text_column(0)
self.SearchMethod_List = gtk.ListStore(gobject.TYPE_STRING)
for i in [_("")]:
self.SearchMethod_List.append([i])
self.SearchMethod.set_model(self.SearchMethod_List)
self.MainWindow.set_title(_("Nicotine+") + " " + version)
self.MainWindow.set_icon(self.images["n"])
self.MainWindow.selection_add_target("PRIMARY", "STRING", 1)
self.MainWindow.set_geometry_hints(None, min_width=500, min_height=460)
self.MainWindow.connect("focus_in_event", self.OnFocusIn)
self.MainWindow.connect("focus_out_event", self.OnFocusOut)
self.MainWindow.connect("configure_event", self.OnWindowChange)
self.MainWindow.add_accel_group(self.accel_group)
self.wTree.signal_autoconnect(self)
# Enabling RGBA if possible, you need up-to-date Murrine Engine for it from what I've heard
RGBA = False
if try_rgba:
gtk_screen = self.MainWindow.get_screen()
colormap = gtk_screen.get_rgba_colormap()
if colormap:
if self.MainWindow.is_composited():
RGBA = True
log.add('Enabling RGBA')
gtk_screen.set_default_colormap(colormap)
else:
log.add('Your X can handle RGBA, but your window manager cannot. Not enabling transparancy.')
else:
log.add('Your X cannot handle RGBA, not enabling transparency')
width = self.np.config.sections["ui"]["width"]
height = self.np.config.sections["ui"]["height"]
self.MainWindow.resize(width, height)
xpos = self.np.config.sections["ui"]["xposition"]
ypos = self.np.config.sections["ui"]["yposition"]
# According to the pygtk doc this will be ignored my many window managers since the move takes place before we do a show()
if min(xpos, ypos) < 0:
self.MainWindow.set_position(gtk.WIN_POS_CENTER)
else:
self.MainWindow.move(xpos, ypos)
self.MainWindow.show()
self.is_mapped = True
if start_hidden:
self.MainWindow.unmap()
self.is_mapped = False
self.minimized = False
self.HiddenTabs = {}
self.clip = gtk.Clipboard(display=gtk.gdk.display_get_default(), selection="CLIPBOARD")
self.logpopupmenu = PopupMenu(self).setup(
("#" + _("Find"), self.OnFindLogWindow, gtk.STOCK_FIND),
("", None),
("#" + _("Copy"), self.OnCopyLogWindow, gtk.STOCK_COPY),
("#" + _("Copy All"), self.OnCopyAllLogWindow, gtk.STOCK_COPY),
("", None),
("#" + _("Clear log"), self.OnClearLogWindow, gtk.STOCK_CLEAR)
)
# for iterating buddy changes to the combos
self.CreateRecommendationsWidgets()
self.status_context_id = self.Statusbar.get_context_id("")
self.socket_context_id = self.SocketStatus.get_context_id("")
self.user_context_id = self.UserStatus.get_context_id("")
self.down_context_id = self.DownStatus.get_context_id("")
self.up_context_id = self.UpStatus.get_context_id("")
self.MainWindow.connect("delete-event", self.on_delete_event)
self.MainWindow.connect('window-state-event', self.window_state_event_cb)
self.MainWindow.connect("destroy", self.OnDestroy)
self.MainWindow.connect("key_press_event", self.OnKeyPress)
self.MainWindow.connect("motion-notify-event", self.OnButtonPress)
gobject.signal_new("network_event", gtk.Window, gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("network_event_lo", gtk.Window, gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
self.MainWindow.connect("network_event", self.OnNetworkEvent)
self.MainWindow.connect("network_event_lo", self.OnNetworkEvent)
self.MainNotebook.connect("page-removed", self.OnPageRemoved)
self.MainNotebook.connect("page-reordered", self.OnPageReordered)
self.MainNotebook.connect("page-added", self.OnPageAdded)
#if sys.platform.startswith("win"):
#self.now_playing1.set_sensitive(False)
for thing in config["interests"]["likes"]:
self.likes[thing] = self.likeslist.append([thing])
for thing in config["interests"]["dislikes"]:
self.dislikes[thing] = self.dislikeslist.append([thing])
for w in self.ChatNotebook, self.PrivatechatNotebook, self.UserInfoNotebook, self.UserBrowseNotebook, self.SearchNotebook:
w.set_tab_closers(config["ui"]["tabclosers"])
w.set_reorderable(config["ui"]["tab_reorderable"])
w.show_images(config["ui"]["tab_icons"])
try:
for tab in self.MainNotebook.get_children():
self.MainNotebook.set_tab_reorderable(tab, config["ui"]["tab_reorderable"])
except:
# Old gtk
pass
self.SetTranslatableTabNames()
for label_tab in [self.ChatTabLabel, self.PrivateChatTabLabel, self.SearchTabLabel, self.UserInfoTabLabel, self.DownloadsTabLabel, self.UploadsTabLabel, self.UserBrowseTabLabel, self.InterestsTabLabel]:
if type(label_tab) is ImageLabel:
label_tab.show_image(config["ui"]["tab_icons"])
label_tab.set_angle(config["ui"]["labelmain"])
elif type(label_tab) is gtk.EventBox:
label_tab.child.show_image(config["ui"]["tab_icons"])
label_tab.child.set_angle(config["ui"]["labelmain"])
self.translux = None
self.TransparentTint()
self.LogScrolledWindow = gtk.ScrolledWindow()
self.LogScrolledWindow.set_shadow_type(gtk.SHADOW_IN)
self.LogScrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.LogScrolledWindow.show()
self.LogWindow = gtk.TextView()
self.LogWindow.set_wrap_mode(gtk.WRAP_WORD)
self.LogWindow.set_cursor_visible(False)
self.LogWindow.set_editable(False)
self.LogScrolledWindow.add(self.LogWindow)
self.LogWindow.connect("button-press-event", self.OnPopupLogMenu)
self.debugLogBox.pack_start(self.LogScrolledWindow)
self.debugWarnings.set_active((1 in config["logging"]["debugmodes"]))
self.debugSearches.set_active((2 in config["logging"]["debugmodes"]))
self.debugConnections.set_active((3 in config["logging"]["debugmodes"]))
self.debugMessages.set_active((4 in config["logging"]["debugmodes"]))
self.debugTransfers.set_active((5 in config["logging"]["debugmodes"]))
self.debugStatistics.set_active((6 in config["logging"]["debugmodes"]))
self.debugButtonsBox.hide()
if self.translux:
self.LogScrolledWindow.get_vadjustment().connect("value-changed", lambda *args: self.LogWindow.queue_draw())
self.translux.subscribe(self.LogWindow, lambda: self.LogWindow.get_window(gtk.TEXT_WINDOW_TEXT))
if config["logging"]["logcollapsed"]:
self.show_log_window1.set_active(False)
else:
#self.vpaned1.pack2(self.LogScrolledWindow, False, True)
self.show_log_window1.set_active(True)
self.LogWindow.show()
self.OnShowLog(self.show_log_window1)
self.extravbox = gtk.VBox() # Web browser vbox
for l in [self.ChatTabLabel, self.PrivateChatTabLabel, self.DownloadsTabLabel, self.UploadsTabLabel, self.SearchTabLabel, self.UserInfoTabLabel, self.UserBrowseTabLabel, self.InterestsTabLabel]:
if type(l) is ImageLabel:
l.set_text_color(0)
elif type(l) is gtk.EventBox:
l.child.set_text_color(0)
self.show_tickers1.set_active(not config["ticker"]["hide"])
self.show_debug_info1.set_active(self.np.config.sections["logging"]["debug"])
self.settingswindow = SettingsWindow(self)
self.settingswindow.SettingsWindow.connect("settings-closed", self.OnSettingsClosed)
self.fastconfigure = FastConfigureAssistant(self)
self.chatrooms = self.ChatNotebook
self.chatrooms.show()
self.Searches = self.SearchNotebook
self.Searches.LoadConfig()
self.downloads = Downloads(self)
self.uploads = Uploads(self)
self.userlist = UserList(self)
self.UpdateColours(1)
self.privatechats = self.PrivatechatNotebook
self.privatechats.show()
self.userinfo = self.UserInfoNotebook
self.userinfo.show()
self.userbrowse = self.UserBrowseNotebook
self.userbrowse.show()
self.userinfo.SetTabLabel(self.UserInfoTabLabel)
self.userbrowse.SetTabLabel(self.UserBrowseTabLabel)
self.sUserinfoButton.connect("clicked", self.OnGetUserInfo)
self.UserInfoCombo.child.connect("activate", self.OnGetUserInfo)
self.sPrivateChatButton.connect("clicked", self.OnGetPrivateChat)
self.UserPrivateCombo.child.connect("activate", self.OnGetPrivateChat)
self.sSharesButton.connect("clicked", self.OnGetShares)
self.UserBrowseCombo.child.connect("activate", self.OnGetShares)
if config["ui"]["roomlistcollapsed"]:
self.show_room_list1.set_active(False)
else:
self.vpaned3.pack2(self.roomlist.vbox2,True, True)
self.show_room_list1.set_active(True)
buddylist = config["ui"]["buddylistinchatrooms"]
if buddylist == 1:
self.buddylist_in_chatrooms1.set_active(True)
elif buddylist == 2:
self.buddylist_always_visible.set_active(True)
elif buddylist == 0:
self.buddylist_in_tab.set_active(True)
if config["columns"]["hideflags"]:
self.ShowFlags.set_active(False)
else:
self.ShowFlags.set_active(True)
self.SetUserStatus(_("Offline"))
self.Notifications = Notifications(self)
self.TrayApp = TrayApp(self)
self.UpdateBandwidth()
self.UpdateTransferButtons()
# Search Methods
self.searchroomslist = {}
self.searchmethods = {}
self.RoomSearchCombo.set_size_request(150, -1)
self.UserSearchCombo.set_size_request(120, -1)
self.UserSearchCombo.set_sensitive(False)
thread.start_new_thread(self.BuddiesCombosFill, ("",))
self.SearchMethod_List.clear()
# Space after Joined Rooms is important, so it doesn't conflict
# with any possible real room, but if it's not translated with the space
# nothing awful will happen
self.searchroomslist[_("Joined Rooms ")] = self.RoomSearchCombo_List.append([_("Joined Rooms ")])
self.RoomSearchCombo.set_active_iter(self.searchroomslist[_("Joined Rooms ")])
for method in [_("Global"), _("Buddies"), _("Rooms"), _("User")]:
self.searchmethods[method] = self.SearchMethod_List.append([method])
self.SearchMethod.set_active_iter(self.searchmethods[_("Global")])
self.SearchMethod.connect("changed", self.OnSearchMethod)
self.UserSearchCombo.hide()
self.RoomSearchCombo.hide()
###
self.disconnect1.set_sensitive(0)
self.awayreturn1.set_sensitive(0)
self.check_privileges1.set_sensitive(0)
self.gstreamer = gstreamer()
self.pluginhandler = pluginsystem.PluginHandler(self, plugindir)
self.ShowChatButtons.set_active(not config["ui"]["chat_hidebuttons"])
if config["transfers"]["rescanonstartup"]:
self.BothRescan()
img = gtk.Image()
img.set_from_pixbuf(self.images["away2"])
self.awayreturn1.set_image(img)
img = gtk.Image()
img.set_from_pixbuf(self.images["bug"])
self.report_bug.set_image(img)
img = gtk.Image()
img.set_from_pixbuf(self.images["money"])
self.check_privileges1.set_image(img)
self.now = nowplaying.NowPlaying(self)
self.SetTabPositions()
ConfigUnset = self.np.config.needConfig()
if ConfigUnset:
if ConfigUnset > 1:
self.connect1.set_sensitive(False)
self.rescan1.set_sensitive(True)
# Display FastConfigure
self.OnFastConfigure(None)
else:
# Connect anyway
#self.OnConnect(-1)
self.OnFirstConnect(-1)
else:
#self.OnConnect(-1)
self.OnFirstConnect(-1)
self.UpdateDownloadFilters()
if use_trayicon and config["ui"]["trayicon"]:
if RGBA:
log.add('X11/GTK RGBA Bug workaround: Setting default colormap to RGB')
gtk_screen.set_default_colormap(gtk_screen.get_rgb_colormap())
self.TrayApp.Create(True)
if RGBA:
log.add('X11/GTK RGBA Bug workaround: Restoring RGBA as default colormap.')
gtk_screen.set_default_colormap(colormap)
#self.SetAllToolTips()
self.WebBrowserTabLabel = gtk.Label("Browser")
self.WebBrowserTabLabel.set_property("xalign", 0)
if WebBrowser and config["ui"]["mozembed"] and gtkmozembed is not None:
self.extravbox.show()
self.browser = BrowserWindow(self, "http://nicotine-plus.org")
self.extravbox.pack_start(self.browser, True, True)
self.extravbox.show_all()
self.MainNotebook.append_page(self.extravbox, self.WebBrowserTabLabel)
self.MainNotebook.set_tab_reorderable(self.extravbox, self.np.config.sections["ui"]["tab_reorderable"])
else:
self.browser = None
self.SetMainTabsVisibility()
self.startup=False
for (timestamp, level, msg) in log.history:
self.updateLog(msg, level)
log.addlistener(self.logCallback)
def SetTranslatableTabNames(self):
# Custom widgets, such as these tab labels aren't translated
labels = {self.ChatTabLabel: _("Chat rooms"), self.PrivateChatTabLabel: _("Private chat"), self.SearchTabLabel: _("Search files"), self.UserInfoTabLabel: _("User info"), self.DownloadsTabLabel:_("Downloads") , self.UploadsTabLabel: _("Uploads"), self.UserBrowseTabLabel:_("User browse") , self.InterestsTabLabel: _("Interests")}
for label_tab, string in labels.items():
if type(label_tab) is ImageLabel:
label_tab.set_text(string)
elif type(label_tab) is gtk.EventBox:
label_tab.child.set_text(string)
def AddDebugLevel(self, debugLevel):
if debugLevel not in self.np.config.sections["logging"]["debugmodes"]:
self.np.config.sections["logging"]["debugmodes"].append(debugLevel)
def RemoveDebugLevel(self, debugLevel):
if debugLevel in self.np.config.sections["logging"]["debugmodes"]:
self.np.config.sections["logging"]["debugmodes"].remove(debugLevel)
def OnDebugWarnings(self, widget):
if self.startup: return
if widget.get_active():
self.AddDebugLevel(1)
else:
self.RemoveDebugLevel(1)
def OnDebugSearches(self, widget):
if self.startup: return
if widget.get_active():
self.AddDebugLevel(2)
else:
self.RemoveDebugLevel(2)
def OnDebugConnections(self, widget):
if self.startup: return
if widget.get_active():
self.AddDebugLevel(3)
else:
self.RemoveDebugLevel(3)
def OnDebugMessages(self, widget):
if self.startup: return
if widget.get_active():
self.AddDebugLevel(4)
else:
self.RemoveDebugLevel(4)
def OnDebugTransfers(self, widget):
if self.startup: return
if widget.get_active():
self.AddDebugLevel(5)
else:
self.RemoveDebugLevel(5)
def OnDebugStatistics(self, widget):
if self.startup: return
if widget.get_active():
self.AddDebugLevel(6)
else:
self.RemoveDebugLevel(6)
def on_delete_event(self, widget, event):
if not self.np.config.sections["ui"]["exitdialog"]:
return False
if self.TrayApp.HAVE_TRAYICON and self.np.config.sections["ui"]["exitdialog"] == 2:
if self.is_mapped:
self.MainWindow.unmap()
self.is_mapped = False
return True
if self.TrayApp.HAVE_TRAYICON:
option = QuitBox(self, title=_('Close Nicotine-Plus?'), message=_('Are you sure you wish to exit Nicotine-Plus at this time?'), tray=True, status="question", third=_("Send to tray") )
else:
option = QuitBox(self, title=_('Close Nicotine-Plus?'), message=_('Are you sure you wish to exit Nicotine-Plus at this time?'), tray=False, status="question" )
return True
def window_state_event_cb(self, window, event):
if event.changed_mask and gtk.gdk.WINDOW_STATE_ICONIFIED:
if event.new_window_state and gtk.gdk.WINDOW_STATE_ICONIFIED:
self.minimized = 1
else:
self.minimized = 0
def similar_users_drag_data_get_data(self, treeview, context, selection, target_id, etime):
treeselection = treeview.get_selection()
model, iter = treeselection.get_selected()
user = model.get_value(iter, 1)
#data = (status, flag, user, speed, files, trusted, notify, privileged, lastseen, comments)
selection.set(selection.target, 8, user)
def NewNotification(self, message, title="Nicotine+"):
if self.pynotify is None:
return
xmlmessage = self.xmldocument.createTextNode(message).toxml()
if self.pynotifyBox is None:
self.pynotifyBox = self.pynotify.Notification(title, xmlmessage)
self.pynotifyBox.set_icon_from_pixbuf(self.images["notify"])
try: n.attach_to_status_icon(self.TrayApp.trayicon_module)
except:
try: n.attach_to_widget(self.TrayApp.trayicon_module)
except: pass
else:
self.pynotifyBox.update(title, xmlmessage)
try:
self.pynotifyBox.show()
except gobject.GError, error:
self.logMessage(_("Notification Error: %s") % str(error))
def LoadIcons(self):
self.images = {}
self.icons = {}
self.flag_images = {}
self.flag_users = {}
scale = None
def loadStatic(name):
loader = gtk.gdk.PixbufLoader()
try:
data = getattr(imagedata, "%s_vector" % (name,))
loader.write(data, len(data))
except (gobject.GError, AttributeError):
try:
# If we reuse the loader for the PNG we get an GtkWarning about a failing assertion
# If we let the loader go out of scope we get a GtkWarning about not finalizing the loader
# If we close the loader it throws an exception on invalid data...
loader.close()
except gobject.GError, e:
# always happens -_-
pass
loader = gtk.gdk.PixbufLoader()
data = getattr(imagedata, "%s" % (name,))
loader.write(data, len(data))
loader.close()
pixbuf = loader.get_pixbuf()
if scale:
w, h = pixbuf.get_width(), pixbuf.get_height()
if w == h:
pixbuf = pixbuf.scale_simple(scale,scale,gtk.gdk.INTERP_BILINEAR)
return pixbuf
names = ["empty", "away", "online", "offline", "hilite", "hilite2", "hilite3", "connect", "disconnect", "away2", "n", "nicotinen", "notify", "bug", "money", "plugin" ]
if "icontheme" in self.np.config.sections["ui"]:
extensions = ["jpg", "jpeg", "bmp", "png", "svg"]
for name in names:
path = None
exts = extensions[:]
loaded = False
while not path or (exts and not loaded):
path = os.path.expanduser(os.path.join(self.np.config.sections["ui"]["icontheme"], "%s.%s" % (name, exts.pop())))
if os.path.exists(path):
data = open(path, 'rb')
s = data.read()
data.close()
loader = gtk.gdk.PixbufLoader()
try:
loader.write(s, len(s))
loader.close()
pixbuf = loader.get_pixbuf()
if scale:
w, h = pixbuf.get_width(), pixbuf.get_height()
if w == h:
pixbuf = pixbuf.scale_simple(scale,scale,gtk.gdk.INTERP_BILINEAR)
self.images[name] = pixbuf
loaded = True
except gobject.GError:
pass
del loader
del s
if not name in self.images:
self.images[name] = loadStatic(name)
else:
for name in names:
self.images[name] = loadStatic(name)
def SaveColumns(self):
for i in [self.userlist, self.chatrooms.roomsctrl, self.downloads, self.uploads, self.Searches]:
i.saveColumns()
self.np.config.writeConfiguration()
def OnSearchMethod(self, widget):
act = False
if self.SearchMethod.get_active_text() == _("User"):
self.UserSearchCombo.show()
act = True
else:
self.UserSearchCombo.hide()
self.UserSearchCombo.set_sensitive(act)
act = False
if self.SearchMethod.get_active_text() == _("Rooms"):
act = True
self.RoomSearchCombo.show()
else:
self.RoomSearchCombo.hide()
self.RoomSearchCombo.set_sensitive(act)
def CreateRecommendationsWidgets(self):
self.likes = {}
self.likeslist = gtk.ListStore(gobject.TYPE_STRING)
self.likeslist.set_sort_column_id(0, gtk.SORT_ASCENDING)
cols = utils.InitialiseColumns(self.LikesList, [_("I like")+":", 0, "text", self.CellDataFunc])
cols[0].set_sort_column_id(0)
self.LikesList.set_model(self.likeslist)
self.RecommendationsList.set_property("rules-hint", True)
self.RecommendationUsersList.set_property("rules-hint", True)
self.RecommendationUsersList.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, [('text/plain', 0, 2)], gtk.gdk.ACTION_COPY)
self.RecommendationUsersList.connect("drag_data_get", self.similar_users_drag_data_get_data)
self.til_popup_menu = popup = utils.PopupMenu(self)
popup.setup(
("#" + _("_Remove this item"), self.OnRemoveThingILike, gtk.STOCK_CANCEL),
("#" + _("Re_commendations for this item"), self.OnRecommendItem, gtk.STOCK_INDEX),
("", None),
("#" + _("_Search for this item"), self.OnRecommendSearch, gtk.STOCK_FIND),
)
self.LikesList.connect("button_press_event", self.OnPopupTILMenu)
self.dislikes = {}
self.dislikeslist = gtk.ListStore(gobject.TYPE_STRING)
self.dislikeslist.set_sort_column_id(0, gtk.SORT_ASCENDING)
cols = utils.InitialiseColumns(self.DislikesList, [_("I dislike")+":", 0, "text", self.CellDataFunc])
cols[0].set_sort_column_id(0)
self.DislikesList.set_model(self.dislikeslist)
self.tidl_popup_menu = popup = utils.PopupMenu(self)
popup.setup(("#" + _("_Remove this item"), self.OnRemoveThingIDislike, gtk.STOCK_CANCEL),
("", None),
("#" + _("_Search for this item"), self.OnRecommendSearch, gtk.STOCK_FIND),)
self.DislikesList.connect("button_press_event", self.OnPopupTIDLMenu)
cols = utils.InitialiseColumns(self.RecommendationsList,
[_("Item"), 0, "text", self.CellDataFunc],
[_("Rating"), 75, "text", self.CellDataFunc])
cols[0].set_sort_column_id(0)
cols[1].set_sort_column_id(2)
self.recommendationslist = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_INT)
self.RecommendationsList.set_model(self.recommendationslist)
self.r_popup_menu = popup = utils.PopupMenu(self)
popup.setup(
("$" + _("I _like this"), self.OnLikeRecommendation),
("$" + _("I _don't like this"), self.OnDislikeRecommendation),
("#" + _("_Recommendations for this item"), self.OnRecommendRecommendation, gtk.STOCK_INDEX),
("", None),
("#" + _("_Search for this item"), self.OnRecommendSearch, gtk.STOCK_FIND),
)
self.RecommendationsList.connect("button_press_event", self.OnPopupRMenu)
cols = utils.InitialiseColumns(self.UnrecommendationsList,
[_("Item"), 0, "text", self.CellDataFunc],
[_("Rating"), 75, "text", self.CellDataFunc])
cols[0].set_sort_column_id(0)
cols[1].set_sort_column_id(2)
self.unrecommendationslist = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_INT)
self.UnrecommendationsList.set_model(self.unrecommendationslist)
self.ur_popup_menu = popup = utils.PopupMenu(self)
popup.setup(
("$" + _("I _like this"), self.OnLikeRecommendation),
("$" + _("I _don't like this"), self.OnDislikeRecommendation),
("#" + _("_Recommendations for this item"), self.OnRecommendRecommendation, gtk.STOCK_INDEX),
("", None),
("#" + _("_Search for this item"), self.OnRecommendSearch, gtk.STOCK_FIND),
)
self.UnrecommendationsList.connect("button_press_event", self.OnPopupUnRecMenu)
self.RecommendationsExpander.connect("activate", self.RecommendationsExpanderStatus)
self.UnrecommendationsExpander.connect("activate", self.RecommendationsExpanderStatus)
statusiconwidth = self.images["offline"].get_width()+4
cols = utils.InitialiseColumns(self.RecommendationUsersList,
["", statusiconwidth, "pixbuf"],
[_("User"), 100, "text", self.CellDataFunc],
[_("Speed"), 0, "text", self.CellDataFunc],
[_("Files"), 0, "text", self.CellDataFunc],
)
cols[0].set_sort_column_id(4)
cols[1].set_sort_column_id(1)
cols[2].set_sort_column_id(5)
cols[3].set_sort_column_id(6)
self.recommendationusers = {}
self.recommendationuserslist = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT)
self.RecommendationUsersList.set_model(self.recommendationuserslist)
self.recommendationuserslist.set_sort_column_id(1, gtk.SORT_ASCENDING)
self.ru_popup_menu = popup = utils.PopupMenu(self)
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),
("", None),
("$" + _("_Add user to list"), popup.OnAddToList),
("$" + _("_Ban this user"), popup.OnBanUser),
("$" + _("_Ignore this user"), popup.OnIgnoreUser),
)
self.RecommendationUsersList.connect("button_press_event", self.OnPopupRUMenu)
def download_large_folder(self, username, folder, files, numfiles, msg):
FolderDownload(self, title=_('Nicotine+')+': Download %(num)i files?' %{'num':numfiles}, message=_("Are you sure you wish to download %(num)i files from %(user)s's directory %(folder)s?") %{'num': numfiles, 'user':username, 'folder':folder } , modal=True, data=msg, callback=self.folder_download_response )
def folder_download_response(self, dialog, response, data):
if response == gtk.RESPONSE_CANCEL:
dialog.destroy()
return
elif response == gtk.RESPONSE_OK:
dialog.destroy()
self.np.transfers.FolderContentsResponse(data)
def on_quit_response(self, dialog, response):
checkbox = dialog.checkbox.get_active()
dialog.destroy()
if response == gtk.RESPONSE_OK:
if checkbox:
self.np.config.sections["ui"]["exitdialog"] = 0
if self.TrayApp.trayicon:
if sys.platform == "win32":
self.TrayApp.trayicon.hide_icon()
else:
self.TrayApp.destroy_trayicon()
self.MainWindow.destroy()
if self.browser is not None:
self.browser.shutdown()
#sys.exit()
#gtk.gdk.threads_leave()
gtk.main_quit()
elif response == gtk.RESPONSE_CANCEL:
pass
elif response == gtk.RESPONSE_REJECT:
if checkbox:
self.np.config.sections["ui"]["exitdialog"] = 2
if self.is_mapped:
self.MainWindow.unmap()
self.is_mapped = False
def on_clear_response(self, dialog, response, direction):
dialog.destroy()
if response == gtk.RESPONSE_OK:
if direction == "down":
self.downloads.ClearTransfers(["Queued"])
elif direction == "up":
self.uploads.ClearTransfers(["Queued"])
def onOpenRoomList(self, dialog, response):
dialog.destroy()
if response == gtk.RESPONSE_OK:
self.show_room_list1.set_active(True)
def OnGetUserInfo(self, widget):
text = self.UserInfoCombo.child.get_text()
if not text:
return
self.LocalUserInfoRequest(text)
self.UserInfoCombo.child.set_text("")
def OnGetShares(self, widget):
text = self.UserBrowseCombo.child.get_text()
if not text:
return
self.BrowseUser(text)
self.UserBrowseCombo.child.set_text("")
def OnLoadFromDisk(self, widget):
configdir, config = os.path.split(self.np.config.filename)
sharesdir = os.path.abspath(configdir+os.sep+"usershares"+os.sep)
try:
if not os.path.exists(sharesdir):
os.mkdir(sharesdir)
except Exception, msg:
log.addwarning(_("Can't create directory '%(folder)s', reported error: %(error)s") % {'folder':sharesdir, 'error':msg})
shares = ChooseFile(self.MainWindow.get_toplevel(), sharesdir, multiple = True)
if shares is None:
return
for share in shares:
try:
import cPickle as mypickle
import bz2
sharefile = bz2.BZ2File(share)
mylist = mypickle.load(sharefile)
sharefile.close()
if not isinstance(mylist, (list, dict)):
raise TypeError, "Bad data in file %(sharesdb)s" % {'sharesdb':share}
username = share.split(os.sep)[-1]
self.userbrowse.InitWindow(username, None)
if username in self.userbrowse.users:
self.userbrowse.users[username].LoadShares(mylist)
except Exception, msg:
log.addwarning(_("Loading Shares from disk failed: %(error)s") % {'error':msg})
def OnNowPlayingConfigure(self, widget):
self.now.NowPlaying.show()
self.now.NowPlaying.deiconify()
def OnGetPrivateChat(self, widget):
text = self.UserPrivateCombo.child.get_text()
if not text:
return
self.privatechats.SendMessage(text, None, 1)
self.UserPrivateCombo.child.set_text("")
def OnOpenPrivateChat(self, widget, prefix = ""):
# popup
users = []
for entry in self.np.config.sections["server"]["userlist"]:
users.append(entry[0])
users.sort()
user = input_box(self, title=_('Nicotine+:')+" "+_("Start Message"),
message=_('Enter the User who you wish to send a private message:'),
default_text='', droplist=users)
if user is not None:
self.privatechats.SendMessage(user, None, 1)
self.ChangeMainPage(None, "chatrooms")
def OnGetAUsersInfo(self, widget, prefix = ""):
# popup
users = []
for entry in self.np.config.sections["server"]["userlist"]:
users.append(entry[0])
users.sort()
user = input_box(self, title=_('Nicotine+: Get User Info'),
message=_('Enter the User whose User Info you wish to recieve:'),
default_text='', droplist=users)
if user is None:
pass
else:
self.LocalUserInfoRequest(user)
def OnGetAUsersIP(self, widget, prefix = ""):
users = []
for entry in self.np.config.sections["server"]["userlist"]:
users.append(entry[0])
users.sort()
user = input_box(self, title=_("Nicotine+: Get A User's IP"),
message=_('Enter the User whose IP Address you wish to recieve:'),
default_text='', droplist=users)
if user is None:
pass
else:
self.np.queue.put(slskmessages.GetPeerAddress(user))
def OnGetAUsersShares(self, widget, prefix = ""):
users = []
for entry in self.np.config.sections["server"]["userlist"]:
users.append(entry[0])
users.sort()
user = input_box(self, title=_("Nicotine+: Get A User's Shares List"),
message=_('Enter the User whose Shares List you wish to recieve:'),
default_text='', droplist=users)
if user is None:
pass
else:
self.BrowseUser(user)
def button_press(self, widget, event):
try:
if event.type == gtk.gdk.BUTTON_PRESS:
widget.popup(None, None, None, event.button, event.time)
# Tell calling code that we have handled this event the buck
# stops here.
return True
# Tell calling code that we have not handled this event pass it on.
return False
except Exception,e:
log.addwarning(_("button_press error, %(error)s") % {'error':e})
def get_custom_widget(self, widget, string0, id, string1, string2, int1, int2):
ui = self.np.config.sections["ui"]
if id == "ChatNotebook":
return ChatRooms(self)
elif id == "SearchNotebook":
return Searches(self)
#IconNotebook(self.images, ui["labelsearch"], ui["tabclosers"])
elif id == "PrivatechatNotebook":
return PrivateChats(self)
elif id == "UserInfoNotebook":
notebook = UserTabs(self, UserInfo)
return notebook
elif id == "UserBrowseNotebook":
notebook = UserTabs(self, UserBrowse)
return notebook
elif id in ("UserSearchCombo", "UserPrivateCombo", "UserInfoCombo", "UserBrowseCombo"):
comboentry = BuddiesComboBoxEntry(self)
self.BuddiesComboEntries.append(comboentry)
return comboentry
elif string1 == "ImageLabel":
return ImageLabel(string2, self.images["empty"])
elif "TabLabel" in id:
label_tab = ImageLabel(string2, self.images["empty"])
eventbox = gtk.EventBox()
eventbox.set_visible_window(False)
label_tab.show()
eventbox.add(label_tab)
eventbox.show()
eventbox.set_events(gtk.gdk.BUTTON_PRESS_MASK)
eventbox.connect('button_press_event', self.on_tab_click, id+"Menu", string1)
self.__dict__[id+"Menu"] = popup = utils.PopupMenu(self)
popup.setup(
("#" + _("Hide %(tab)s" % {"tab":string2}), self.HideTab, gtk.STOCK_REMOVE, [eventbox, string1]),
)
popup.set_user(string1)
return eventbox
else:
return gtk.Label(_("(custom widget: %s)") % id)
def OnPageRemoved(self, MainNotebook, child, page_num):
name = self.MatchMainNotebox(child)
self.np.config.sections["ui"]["modes_visible"][name] = 0
self.OnPageReordered(MainNotebook, child, page_num)
def OnPageAdded(self, MainNotebook, child, page_num):
name = self.MatchMainNotebox(child)
self.np.config.sections["ui"]["modes_visible"][name] = 1
self.OnPageReordered(MainNotebook, child, page_num)
def OnPageReordered(self, MainNotebook, child, page_num):
if self.exiting:
return
tabs = []
for children in self.MainNotebook.get_children():
tabs.append(self.MatchMainNotebox(children))
self.np.config.sections["ui"]["modes_order"] = tabs
#self.np.config.writeConfig()
def SetMainTabsVisibility(self):
tabs = self.temp_modes_order
#print type(tabs)
order = 0
for name in tabs:
#print name
tab = self.MatchMainNamePage(name)
#print tab
self.MainNotebook.reorder_child(tab, order)
order += 1
visible = self.np.config.sections["ui"]["modes_visible"]
for name in visible:
tab = self.MatchMainNamePage(name)
if tab is None:
continue
eventbox = self.MainNotebook.get_tab_label(tab)
if not visible[name]:
if tab not in self.MainNotebook.get_children():
return
if tab in self.HiddenTabs:
return
self.HiddenTabs[tab] = eventbox
num = self.MainNotebook.page_num(tab )
self.MainNotebook.remove_page(num)
def HideTab(self, widget, lista):
eventbox, child = lista
tab = self.__dict__[child]
if tab not in self.MainNotebook.get_children():
return
if tab in self.HiddenTabs:
return
#print child, eventbox
#print self.__dict__[child], eventbox
self.HiddenTabs[tab] = eventbox
num = self.MainNotebook.page_num(tab )
#print self.MainNotebook.get_tab_label(self.__dict__[child]), eventbox
self.MainNotebook.remove_page(num)
def ShowTab(self, widget, lista):
name, child = lista
if child in self.MainNotebook.get_children():
return
if child not in self.HiddenTabs:
return
eventbox = self.HiddenTabs[child]
self.MainNotebook.append_page(child, eventbox)
self.MainNotebook.set_tab_reorderable(child, self.np.config.sections["ui"]["tab_reorderable"])
del self.HiddenTabs[child]
def on_tab_click(self, widget, event, id, child):
#print widget, event, id, child
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
self.__dict__[id].popup(None, None, None, event.button, event.time)
#if event.type == gtk.gdk.BUTTON_PRESS:
#widget.popup(None, None, None, event.button, event.time)
pass
def BuddiesCombosFill(self, nothing):
for widget in self.BuddiesComboEntries:
gobject.idle_add(widget.Fill)
def OnAutoAway(self):
if not self.away:
self.autoaway = True
self.OnAway(None)
return False
def OnButtonPress(self, widget, event):
if self.autoaway:
self.OnAway(None)
self.autoaway = False
if self.awaytimer is not None:
gobject.source_remove(self.awaytimer)
autoaway = self.np.config.sections["server"]["autoaway"]
if autoaway > 0:
self.awaytimer = gobject.timeout_add(1000*60*autoaway, self.OnAutoAway)
else:
self.awaytimer = None
def OnKeyPress(self, widget, event):
self.OnButtonPress(None, None)
if event.state & (gtk.gdk.MOD1_MASK|gtk.gdk.CONTROL_MASK) != gtk.gdk.MOD1_MASK:
return False
for i in range(1, 10):
if event.keyval == gtk.gdk.keyval_from_name(str(i)):
self.MainNotebook.set_current_page(i-1)
widget.emit_stop_by_name("key_press_event")
return True
return False
def emit_network_event(self, msgs):
lo = [msg for msg in msgs if msg.__class__ is slskmessages.FileSearchResult]
hi = [msg for msg in msgs if msg.__class__ is not slskmessages.FileSearchResult]
if hi:
self.MainWindow.emit("network_event", hi)
if lo:
self.MainWindow.emit("network_event_lo", lo)
return False
## Recieved a network event via emit_network_event
## with at least one, but possibly more messages
## call the appropriate event class for these message
# @param self NicotineFrame (Class)
# @param widget the main window
# @param msgs a list of messages
def OnNetworkEvent(self, widget, msgs):
for i in msgs:
if i.__class__ in self.np.events:
self.np.events[i.__class__](i)
else:
self.logMessage("No handler for class %s %s" % (i.__class__, vars(i)))
def callback(self, msgs):
#gtk.gdk.threads_enter()
if len(msgs) > 0:
gobject.idle_add(self.emit_network_event, msgs[:])
#gtk.gdk.threads_leave()
def networkcallback(self,msgs):
#gtk.gdk.threads_enter()
curtime = time.time()
for i in msgs[:]:
if i.__class__ is slskmessages.DownloadFile or i.__class__ is slskmessages.UploadFile:
self.transfermsgs[i.conn] = i
msgs.remove(i)
if i.__class__ is slskmessages.ConnClose:
msgs = self.postTransferMsgs(msgs,curtime)
if curtime-self.transfermsgspostedtime > 1.0:
msgs = self.postTransferMsgs(msgs,curtime)
if len(msgs) > 0:
gobject.idle_add(self.emit_network_event, msgs[:])
#gtk.gdk.threads_leave()
def postTransferMsgs(self,msgs,curtime):
trmsgs = []
for (key, value) in self.transfermsgs.iteritems():
trmsgs.append(value)
msgs = trmsgs+msgs
self.transfermsgs = {}
self.transfermsgspostedtime = curtime
return msgs
def CellDataFunc(self, column, cellrenderer, model, iter):
colour = self.np.config.sections["ui"]["search"]
if colour == "":
colour = None
cellrenderer.set_property("foreground", colour)
def changecolour(self, tag, colour):
if colour in self.frame.np.config.sections["ui"]:
color = self.frame.np.config.sections["ui"][colour]
else:
color = None
font = self.frame.np.config.sections["ui"]["chatfont"]
if color:
if color == "":
color = None
tag.set_property("foreground", color)
tag.set_property("font", font)
else:
tag.set_property("font", font)
def ChangeListFont(self, listview, font):
if font == "":
font = 'default font'
for c in listview.get_columns():
for r in c.get_cell_renderers():
if type(r) in (gtk.CellRendererText, gtk.CellRendererCombo):
r.set_property("font", font)
def UpdateColours(self, first=0):
color = self.np.config.sections["ui"]["chatremote"]
font = self.np.config.sections["ui"]["chatfont"]
if color == "":
map = self.LogWindow.get_style().copy()
colour = map.text[gtk.STATE_NORMAL]
else:
colour = gtk.gdk.color_parse(color)
if font == "":
font = None
if first:
self.tag_log = self.LogWindow.get_buffer().create_tag()
self.tag_log.set_property("font", font)
self.tag_log.set_property("foreground-gdk", colour)
self.SetTextBG(self.LogWindow)
self.SetTextBG(self.userlist.UserList)
#self.ChangeListFont( self.UserList, self.frame.np.config.sections["ui"]["listfont"])
for listview in [self.userlist.UserList, self.RecommendationsList, self.UnrecommendationsList, self.RecommendationUsersList, self.LikesList, self.DislikesList, self.roomlist.RoomsList]:
self.ChangeListFont(listview, self.np.config.sections["ui"]["listfont"])
self.SetTextBG(self.RecommendationsList)
self.SetTextBG(self.UnrecommendationsList)
self.SetTextBG(self.RecommendationUsersList)
self.SetTextBG(self.LikesList)
self.SetTextBG(self.DislikesList)
self.SetTextBG(self.UserPrivateCombo.child)
self.SetTextBG(self.UserInfoCombo.child)
self.SetTextBG(self.UserBrowseCombo.child)
self.SetTextBG(self.SearchEntry)
def SetTextBG(self, widget, bgcolor="", fgcolor=""):
if bgcolor == "" and self.np.config.sections["ui"]["textbg"] == "":
colour = None
else:
if bgcolor == "":
bgcolor = self.np.config.sections["ui"]["textbg"]
colour = gtk.gdk.color_parse(bgcolor)
widget.modify_base(gtk.STATE_NORMAL, colour)
widget.modify_bg(gtk.STATE_NORMAL, colour)
widgetlist = [gtk.Entry, gtk.SpinButton]
if SEXY:
widgetlist.append(sexy.SpellEntry)
if type(widget) in widgetlist:
if fgcolor != "":
colour = gtk.gdk.color_parse(fgcolor)
elif fgcolor == "" and self.np.config.sections["ui"]["inputcolor"] == "":
colour = None
elif fgcolor == "" and self.np.config.sections["ui"]["inputcolor"] != "":
fgcolor = self.np.config.sections["ui"]["inputcolor"]
colour = gtk.gdk.color_parse(fgcolor)
widget.modify_text(gtk.STATE_NORMAL, colour)
widget.modify_fg(gtk.STATE_NORMAL, colour)
if type(widget) is gtk.TreeView:
colour = self.np.config.sections["ui"]["search"]
if colour == "":
colour = None
for c in widget.get_columns():
for r in c.get_cell_renderers():
if type(r) in (gtk.CellRendererText, gtk.CellRendererCombo):
r.set_property("foreground", colour)
def PopupMessage(self, popup):
self.logMessage(_(popup.title) + ": " + _(popup.message))
dialog = gtk.MessageDialog(type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_OK, message_format=popup.title)
dialog.format_secondary_text(popup.message)
dialog.connect('response', lambda dialog, response: dialog.destroy())
dialog.show()
def PopupMessage2(self, title, message):
dialog = gtk.MessageDialog(type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_OK, message_format=title)
dialog.set_title("Nicotine+: " +title)
dialog.format_secondary_text(message)
dialog.connect('response', lambda dialog, response: dialog.destroy())
dialog.show()
def logCallback(self, timestamp, level, msg):
gobject.idle_add(self.updateLog, msg, level, priority=gobject.PRIORITY_DEFAULT)
def logMessage(self, msg, debugLevel = 0):
log.add(msg, debugLevel)
def updateLog(self, msg, debugLevel = None):
'''For information about debug levels see
pydoc pynicotine.logfacility.logger.add
'''
if self.np.config.sections["logging"]["debug"]:
if debugLevel in (None, 0) or debugLevel in self.np.config.sections["logging"]["debugmodes"]:
AppendLine(self.LogWindow, msg, self.tag_log, scroll=True)
if self.np.config.sections["logging"]["logcollapsed"]:
self.SetStatusText(msg)
else:
if debugLevel in (None, 0, 1):
try:
AppendLine(self.LogWindow, msg, self.tag_log, scroll=True)
if self.np.config.sections["logging"]["logcollapsed"]:
self.SetStatusText(msg)
except Exception, e:
print e
return False
def ScrollBottom(self, widget):
va = widget.get_vadjustment()
va.set_value(va.upper - va.page_size)
widget.set_vadjustment(va)
return False
def SetStatusText(self, msg):
self.Statusbar.pop(self.status_context_id)
self.Statusbar.push(self.status_context_id, str(msg))
def OnWindowChange(self, widget, blag):
(width, height) = self.MainWindow.get_size()
self.np.config.sections["ui"]["height"] = height
self.np.config.sections["ui"]["width"] = width
(xpos, ypos) = self.MainWindow.get_position()
self.np.config.sections["ui"]["xposition"] = xpos
self.np.config.sections["ui"]["yposition"] = ypos
def OnDestroy(self, widget):
self.np.config.sections["privatechat"]["users"] = list(self.privatechats.users.keys())
self.np.protothread.abort()
self.np.StopTimers()
if not self.manualdisconnect:
self.OnDisconnect(None)
self.np.config.writeConfig()
if self.TrayApp.trayicon:
if sys.platform == "win32":
self.TrayApp.trayicon.hide_icon()
else:
self.TrayApp.destroy_trayicon()
if self.browser is not None:
self.browser.shutdown()
gtk.gdk.threads_leave()
#sys.exit()
#import time
#time.sleep(4)
gtk.main_quit()
#gtk.gdk.threads_leave()
if sys.platform.startswith("win"):
# Hack. main_quit works on Linux but not on Windows, needs to be resolved properly.
sys.exit()
def OnFirstConnect(self, widget):
if not self.np.config.sections["server"]["upnp"]:
self.OnConnect(-1)
return
thread.start_new_thread(self.Fixportmapping, ())
def Fixportmapping(self):
if not upnp.upnppossible:
log.add(_('Not using UPnP to fix portmapping due to errors: %(errors)s') % {'errors':'\n'.join(upnp.miniupnpc_errors)})
self.OnConnect(-1)
return
log.add(_("Figuring out UPnP..."))
time.sleep(0.5) # Wait for the GUI to come alive
print "Fixing ports..."
internalport = self.np.protothread._p.getsockname()[1] # Internal LAN port
externalport = internalport # External LAN port
try:
mapping = upnp.fixportmapping(self.np.protothread._p.getsockname()[1])
if not mapping:
log.add('Failed to automate port forwarding, sorry.')
else:
(externalip, externalport) = mapping
log.add('Managed to forward port %s, your external IP is %s.' % (externalport, externalip))
self.networkcallback([slskmessages.IncPort(externalport)])
except Exception, e:
log.add('UPNP Exception (should never happen): %s' % (e,))
print "Done fixing ports"
self.OnConnect(-1)
def OnConnect(self, widget):
self.TrayApp.tray_status["status"] = "connect"
self.TrayApp.SetImage()
if self.np.serverconn is not None:
return
if widget != -1:
while not self.np.queue.empty():
self.np.queue.get(0)
self.SetUserStatus("...")
server = self.np.config.sections["server"]["server"]
self.SetStatusText(_("Connecting to %(host)s:%(port)s") %{'host':server[0],'port':server[1]} )
self.np.queue.put(slskmessages.ServerConn(None, server))
if self.np.servertimer is not None:
self.np.servertimer.cancel()
self.np.servertimer = None
def OnDisconnect(self, event):
self.disconnect1.set_sensitive(0)
self.manualdisconnect = 1
self.np.queue.put(slskmessages.ConnClose(self.np.serverconn))
def FetchUserListStatus(self):
for user in self.userlist.userlist:
self.np.queue.put(slskmessages.AddUser(user[0]))
return False
def ConnClose(self, conn, addr):
if self.awaytimer is not None:
gobject.source_remove(self.awaytimer)
self.awaytimer = None
if self.autoaway:
self.autoaway = self.away = False
self.SetWidgetOnlineStatus(False)
self.SetUserStatus(_("Offline"))
self.TrayApp.tray_status["status"] = "disconnect"
self.TrayApp.SetImage()
self.Searches.interval = 0
self.chatrooms.ConnClose()
self.privatechats.ConnClose()
self.Searches.ConnClose()
self.uploads.ConnClose()
self.downloads.ConnClose()
self.userlist.ConnClose()
self.userinfo.ConnClose()
self.userbrowse.ConnClose()
#self.pluginhandler.ServerDisconnectNotification()
def SetWidgetOnlineStatus(self, status):
self.connect1.set_sensitive(not status)
self.disconnect1.set_sensitive(status)
self.awayreturn1.set_sensitive(status)
self.check_privileges1.set_sensitive(status)
self.roomlist.CreateRoomEntry.set_sensitive(status)
self.roomlist.RoomsList.set_sensitive(status)
self.roomlist.SearchRooms.set_sensitive(status)
self.roomlist.FindRoom.set_sensitive(status)
self.UserPrivateCombo.set_sensitive(status)
self.sPrivateChatButton.set_sensitive(status)
self.UserBrowseCombo.set_sensitive(status)
self.sSharesButton.set_sensitive(status)
self.UserInfoCombo.set_sensitive(status)
self.sUserinfoButton.set_sensitive(status)
self.UserSearchCombo.set_sensitive(status)
self.SearchEntryCombo.set_sensitive(status)
self.SearchButton.set_sensitive(status)
self.SimilarUsersButton.set_sensitive(status)
self.GlobalRecommendationsButton.set_sensitive(status)
self.RecommendationsButton.set_sensitive(status)
self.DownloadButtons.set_sensitive(status)
self.UploadButtons.set_sensitive(status)
def ConnectError(self, conn):
self.SetWidgetOnlineStatus(False)
self.SetUserStatus(_("Offline"))
self.TrayApp.tray_status["status"] = "disconnect"
self.TrayApp.SetImage()
self.uploads.ConnClose()
self.downloads.ConnClose()
#self.pluginhandler.ServerDisconnectNotification()
def SetUserStatus(self, status):
self.UserStatus.pop(self.user_context_id)
self.UserStatus.push(self.user_context_id, status)
def SetSocketStatus(self, status):
self.SocketStatus.pop(self.socket_context_id)
self.SocketStatus.push(self.socket_context_id, _("%s/%s Connections") % (status, slskproto.MAXFILELIMIT))
def InitInterface(self, msg):
if self.away == 0:
self.SetUserStatus(_("Online"))
self.TrayApp.tray_status["status"] = "connect"
self.TrayApp.SetImage()
autoaway = self.np.config.sections["server"]["autoaway"]
if autoaway > 0:
self.awaytimer = gobject.timeout_add(1000*60*autoaway, self.OnAutoAway)
else:
self.awaytimer = None
else:
self.SetUserStatus(_("Away"))
self.TrayApp.tray_status["status"] = "away2"
self.TrayApp.SetImage()
self.SetWidgetOnlineStatus(True)
self.uploads.InitInterface(self.np.transfers.uploads)
self.downloads.InitInterface(self.np.transfers.downloads)
gobject.idle_add(self.FetchUserListStatus)
AppendLine(self.LogWindow, self.np.decode(msg.banner), self.tag_log)
#self.pluginhandler.ServerConnectNotification()
return self.privatechats, self.chatrooms, self.userinfo, self.userbrowse, self.Searches, self.downloads, self.uploads, self.userlist
def GetStatusImage(self, status):
if status == 1:
return self.images["away"]
elif status == 2:
return self.images["online"]
else:
return self.images["offline"]
def HasUserFlag(self, user, flag):
if flag not in self.flag_images:
self.GetFlagImage(flag)
if flag not in self.flag_images:
return
self.flag_users[user] = flag
self.chatrooms.roomsctrl.SetUserFlag(user, flag)
self.userlist.SetUserFlag(user, flag)
def GetUserFlag(self, user):
if user not in self.flag_users:
for i in self.np.config.sections["server"]["userlist"]:
if user == i[0] and i[6] is not None:
return i[6]
return None
else:
return self.flag_users[user]
def GetFlagImage(self, flag):
if flag is None: return
if flag not in self.flag_images:
if hasattr(imagedata, flag):
img = None
try:
loader = gtk.gdk.PixbufLoader("png")
data = getattr(imagedata, flag)
loader.write(data, len(data))
loader.close()
img = loader.get_pixbuf()
except Exception, e:
log.addwarning(_("Error loading image for %(flag)s: %(error)s") % {'flag':flag, 'error':e})
self.flag_images[flag] = img
return img
else:
return None
else:
return self.flag_images[flag]
def OnShowDebug(self, widget):
if not self.startup:
self.np.config.sections["logging"]["debug"] = self.show_debug_info1.get_active()
if self.show_debug_info1.get_active():
self.debugButtonsBox.show()
else:
self.debugButtonsBox.hide()
def OnAway(self, widget):
self.away = (self.away+1) % 2
if self.away == 0:
self.SetUserStatus(_("Online"))
self.TrayApp.tray_status["status"] = "connect"
self.TrayApp.SetImage()
else:
self.SetUserStatus(_("Away"))
self.TrayApp.tray_status["status"] = "away2"
self.TrayApp.SetImage()
self.np.queue.put(slskmessages.SetStatus(self.away and 1 or 2))
self.privatechats.UpdateColours()
def OnExit(self, widget):
self.exiting = 1
if sys.platform == "win32" and self.TrayApp.trayicon:
self.TrayApp.trayicon.hide_icon()
self.MainWindow.destroy()
def OnSearch(self, widget):
self.Searches.OnSearch()
def OnClearSearchHistory(self, widget):
self.Searches.OnClearSearchHistory()
def ChatRequestIcon(self, status = 0, widget=None):
if status == 1 and not self.got_focus:
self.MainWindow.set_icon(self.images["hilite2"])
if self.MainNotebook.get_current_page() == self.MainNotebook.page_num(self.hpaned1):
return
tablabel = self.GetTabLabel(self.ChatTabLabel)
if not tablabel:
return
if status == 0:
if tablabel.get_image() == self.images["hilite"]:
return
tablabel.set_image(status == 1 and self.images["hilite"] or self.images["hilite3"])
tablabel.set_text_color(status+1)
def GetTabLabel(self, TabLabel):
tablabel = None
if type(TabLabel) is ImageLabel:
tablabel = TabLabel
elif type(TabLabel) is gtk.EventBox:
tablabel = TabLabel.child
return tablabel
def RequestIcon(self, TabLabel, widget=None):
if TabLabel == self.PrivateChatTabLabel and not self.got_focus:
self.MainWindow.set_icon(self.images["hilite2"])
tablabel = self.GetTabLabel(TabLabel)
if not tablabel:
return
if self.current_tab != TabLabel:
tablabel.set_image(self.images["hilite"])
tablabel.set_text_color(2)
def OnSwitchPage(self, notebook, page, page_nr):
tabLabels = []
tabs = self.MainNotebook.get_children()
for i in tabs:
tabLabels.append(self.MainNotebook.get_tab_label(i))
#tabLabels = [self.ChatTabLabel, self.PrivateChatTabLabel, self.DownloadsTabLabel, self.UploadsTabLabel, self.SearchTabLabel, self.UserInfoTabLabel, self.UserBrowseTabLabel, self.InterestsTabLabel]
#if "BuddiesTabLabel" in self.__dict__:
#tabLabels.append(self.BuddiesTabLabel)
l = tabLabels[page_nr]
#n = [self.ChatNotebook, self.PrivatechatNotebook, None, None, self.SearchNotebook, self.UserInfoNotebook, self.UserBrowseNotebook, None, None][page_nr]
compare = {self.ChatTabLabel: self.ChatNotebook, self.PrivateChatTabLabel: self.PrivatechatNotebook, self.DownloadsTabLabel: None, self.UploadsTabLabel: None, self.SearchTabLabel: self.SearchNotebook, self.UserInfoTabLabel: self.UserInfoNotebook, self.UserBrowseTabLabel: self.UserBrowseNotebook, self.InterestsTabLabel: None, self.WebBrowserTabLabel: self.extravbox}
if "BuddiesTabLabel" in self.__dict__:
compare[self.BuddiesTabLabel] = None
n = compare[l]
self.current_tab = l
if l is not None:
if type(l) is ImageLabel:
l.set_image(self.images["empty"])
l.set_text_color(0)
elif type(l) is gtk.EventBox:
l.child.set_image(self.images["empty"])
l.child.set_text_color(0)
if n is not None and type(n) not in [gtk.HPaned, gtk.VBox]:
n.popup_disable()
n.popup_enable()
if n.get_current_page() != -1:
n.dismiss_icon(n, None, n.get_current_page())
if page_nr == self.MainNotebook.page_num(self.hpaned1):
if self.chatrooms:
p = n.get_current_page()
self.chatrooms.roomsctrl.OnSwitchPage(n, None, p, 1)
elif page_nr == self.MainNotebook.page_num(self.privatevbox):
p = n.get_current_page()
if "privatechats" in self.__dict__:
self.privatechats.OnSwitchPage(n, None, p, 1)
elif page_nr == self.MainNotebook.page_num(self.vboxuploads):
self.uploads._update()
elif page_nr == self.MainNotebook.page_num(self.vboxdownloads):
self.downloads._update()
def UpdateBandwidth(self):
def _calc(l):
bandwidth = 0.0
users = 0
l = [i for i in l if i.conn is not None]
for i in l:
if i.speed is not None:
bandwidth = bandwidth + i.speed
return len(l),bandwidth
def _num_users(l):
users = []
for i in l:
if i.user not in users:
users.append(i.user)
return len(users), len(l)
if self.np.transfers is not None:
usersdown, down = _calc(self.np.transfers.downloads)
usersup, up = _calc(self.np.transfers.uploads)
total_usersdown, filesdown = _num_users(self.np.transfers.downloads)
total_usersup, filesup = _num_users(self.np.transfers.uploads)
else:
down = up = 0.0
filesup = filesdown = total_usersdown = total_usersup = usersdown = usersup = 0
self.DownloadUsers.set_text(_("Users: %s") % total_usersdown)
self.UploadUsers.set_text(_("Users: %s") % total_usersup)
self.DownloadFiles.set_text(_("Files: %s") % filesdown)
self.UploadFiles.set_text(_("Files: %s") % filesup)
self.DownStatus.pop(self.down_context_id)
self.UpStatus.pop(self.up_context_id)
self.DownStatus.push(self.down_context_id, _("Down: %(num)i users, %(speed).1f KB/s") % {'num':usersdown, 'speed':down})
self.UpStatus.push(self.up_context_id, _("Up: %(num)i users, %(speed).1f KB/s") % {'num':usersup,'speed':up})
self.TrayApp.SetToolTip(_("Nicotine+ Transfers: %(speeddown).1f KB/s Down, %(speedup).1f KB/s Up") % {'speeddown':down,'speedup':up})
def BanUser(self, user):
if self.np.transfers is not None:
self.np.transfers.BanUser(user)
def UserIpIsBlocked(self, user):
for ip, username in self.np.config.sections["server"]["ipblocklist"].items():
if user == username:
return True
return False
def BlockedUserIp(self, user):
for ip, username in self.np.config.sections["server"]["ipblocklist"].items():
if user == username:
return ip
return None
def UserIpIsIgnored(self, user):
for ip, username in self.np.config.sections["server"]["ipignorelist"].items():
if user == username:
return True
return False
def IgnoredUserIp(self, user):
for ip, username in self.np.config.sections["server"]["ipignorelist"].items():
if user == username:
return ip
return None
def IgnoreIP(self, ip):
if ip is None or ip == "" or ip.count(".") != 3:
return
ipignorelist = self.np.config.sections["server"]["ipignorelist"]
if ip not in ipignorelist:
ipignorelist[ip] = ""
self.np.config.writeConfiguration()
self.settingswindow.pages["Ignore List"].SetSettings(self.np.config.sections)
def OnIgnoreIP(self, user):
if user not in self.np.users or type(self.np.users[user].addr) is not tuple:
if user not in self.np.ipignore_requested:
self.np.ipignore_requested[user] = 0
self.np.queue.put(slskmessages.GetPeerAddress(user))
return
ipignorelist = self.np.config.sections["server"]["ipignorelist"]
ip, port = self.np.users[user].addr
if ip not in ipignorelist or self.np.config.sections["server"]["ipignorelist"][ip] != user:
self.np.config.sections["server"]["ipignorelist"][ip] = user
self.np.config.writeConfiguration()
self.settingswindow.pages["Ignore List"].SetSettings(self.np.config.sections)
def OnUnIgnoreIP(self, user):
ipignorelist = self.np.config.sections["server"]["ipignorelist"]
if self.UserIpIsIgnored(user):
ip = self.IgnoredUserIp(user)
if ip is not None:
del ipignorelist[ip]
self.np.config.writeConfiguration()
self.settingswindow.pages["Ignore List"].SetSettings(self.np.config.sections)
return True
if user not in self.np.users:
if user not in self.np.ipignore_requested:
self.np.ipignore_requested[user] = 1
self.np.queue.put(slskmessages.GetPeerAddress(user))
return
if not type(self.np.users[user].addr) is tuple:
return
ip, port = self.np.users[user].addr
if ip in ipignorelist:
del ipignorelist[ip]
self.np.config.writeConfiguration()
self.settingswindow.pages["Ignore List"].SetSettings(self.np.config.sections)
def OnBlockUser(self, user):
if user not in self.np.users or type(self.np.users[user].addr) is not tuple:
if user not in self.np.ipblock_requested:
self.np.ipblock_requested[user] = 0
self.np.queue.put(slskmessages.GetPeerAddress(user))
return
ip, port = self.np.users[user].addr
if ip not in self.np.config.sections["server"]["ipblocklist"] or self.np.config.sections["server"]["ipblocklist"][ip] != user:
self.np.config.sections["server"]["ipblocklist"][ip] = user
self.np.config.writeConfiguration()
self.settingswindow.pages["Ban List"].SetSettings(self.np.config.sections)
def OnUnBlockUser(self, user):
if self.UserIpIsBlocked(user):
ip = self.BlockedUserIp(user)
if ip is not None:
del self.np.config.sections["server"]["ipblocklist"][ip]
self.np.config.writeConfiguration()
self.settingswindow.pages["Ban List"].SetSettings(self.np.config.sections)
return True
if user not in self.np.users:
if user not in self.np.ipblock_requested:
self.np.ipblock_requested[user] = 1
self.np.queue.put(slskmessages.GetPeerAddress(user))
return
if not type(self.np.users[user].addr) is tuple:
return
ip, port = self.np.users[user].addr
if ip in self.np.config.sections["server"]["ipblocklist"]:
del self.np.config.sections["server"]["ipblocklist"][ip]
self.np.config.writeConfiguration()
self.settingswindow.pages["Ban List"].SetSettings(self.np.config.sections)
def UnbanUser(self, user):
if user in self.np.config.sections["server"]["banlist"]:
self.np.config.sections["server"]["banlist"].remove(user)
self.np.config.writeConfiguration()
def IgnoreUser(self, user):
if user not in self.np.config.sections["server"]["ignorelist"]:
self.np.config.sections["server"]["ignorelist"].append(user)
self.np.config.writeConfiguration()
def UnignoreUser(self, user):
if user in self.np.config.sections["server"]["ignorelist"]:
self.np.config.sections["server"]["ignorelist"].remove(user)
self.np.config.writeConfiguration()
def BothRescan(self):
self.OnRescan()
if self.np.config.sections["transfers"]["enablebuddyshares"]:
self.OnBuddyRescan()
def OnRescan(self, widget = None, rebuild = False):
if self.rescanning:
return
self.rescanning = 1
self.rescan1.set_sensitive(False)
self.rebuild1.set_sensitive(False)
self.logMessage(_("Rescanning started"))
shared = self.np.config.sections["transfers"]["shared"][:]
if self.np.config.sections["transfers"]["sharedownloaddir"]:
shared.append((_('Downloaded'), self.np.config.sections["transfers"]["downloaddir"]))
cleanedshares = []
for combo in shared:
if combo not in cleanedshares:
cleanedshares.append(combo)
msg = slskmessages.RescanShares(cleanedshares, lambda: None)
thread.start_new_thread(self.np.shares.RescanShares, (msg, rebuild))
def OnRebuild(self, widget = None):
self.OnRescan(widget, rebuild=True)
def OnBuddyRescan(self, widget = None, rebuild = False):
if self.brescanning:
return
self.brescanning = 1
self.rescan_buddy.set_sensitive(False)
self.rebuild_buddy.set_sensitive(False)
self.logMessage(_("Rescanning Buddy Shares started"))
shared = self.np.config.sections["transfers"]["buddyshared"][:] + self.np.config.sections["transfers"]["shared"][:]
if self.np.config.sections["transfers"]["sharedownloaddir"]:
shared.append(self.np.config.sections["transfers"]["downloaddir"])
cleanedshares = []
for i in shared:
if i not in cleanedshares:
cleanedshares.append(i)
msg = slskmessages.RescanBuddyShares(cleanedshares, lambda: None)
thread.start_new_thread(self.np.shares.RescanBuddyShares, (msg, rebuild))
def OnBuddyRebuild(self, widget = None):
self.OnBuddyRescan(widget, rebuild=True)
def _BuddyRescanFinished(self, data):
self.np.config.setBuddyShares(*data)
self.np.config.writeShares()
self.rescan_buddy.set_sensitive(True)
self.rebuild_buddy.set_sensitive(True)
if self.np.transfers is not None:
self.np.shares.sendNumSharedFoldersFiles()
self.brescanning = 0
self.logMessage(_("Rescanning Buddy Shares finished"))
self.BuddySharesProgress.hide()
self.np.shares.CompressShares("buddy")
def _RescanFinished(self, data):
self.np.config.setShares(*data)
self.np.config.writeShares()
self.rescan1.set_sensitive(True)
self.rebuild1.set_sensitive(True)
if self.np.transfers is not None:
self.np.shares.sendNumSharedFoldersFiles()
self.rescanning = 0
self.logMessage(_("Rescanning finished"))
self.SharesProgress.hide()
self.np.shares.CompressShares("normal")
def RescanFinished(self, data, type):
if type == "buddy":
gobject.idle_add(self._BuddyRescanFinished, data)
elif type == "normal":
gobject.idle_add(self._RescanFinished, data)
def OnSettingsShares(self, widget):
self.OnSettings(widget, 'Shares')
def OnSettingsSearches(self, widget):
self.OnSettings(widget, 'Searches')
def OnSettingsDownloads(self, widget):
self.OnSettings(widget, 'Downloads')
self.settingswindow.pages["Downloads"].DownloadFilters.set_expanded(True)
def OnSettingsUploads(self, widget):
self.OnSettings(widget, 'Transfers')
self.settingswindow.pages["Transfers"].Uploads.set_expanded(True)
def OnSettingsUserinfo(self, widget):
self.OnSettings(widget, 'User info')
def OnSettingsLogging(self, widget):
self.OnSettings(widget, 'Logging')
def OnSettingsIgnore(self, widget):
self.OnSettings(widget, 'Ingore List')
def OnSettingsBanIgnore(self, widget):
self.OnSettings(widget, 'Ban List')
def OnFastConfigure(self, widget):
if not self.settingswindow.SettingsWindow.get_property("visible"):
self.fastconfigure.show()
def OnSettings(self, widget, page=None):
if not self.fastconfigure.window.get_property("visible"):
self.settingswindow.SetSettings(self.np.config.sections)
if page:
self.settingswindow.SwitchToPage(page)
self.settingswindow.SettingsWindow.show()
self.settingswindow.SettingsWindow.deiconify()
def OnSettingsClosed(self, widget, msg):
if msg == "cancel":
self.settingswindow.SettingsWindow.hide()
return
output = self.settingswindow.GetSettings()
if type(output) is not tuple:
return
if msg == "ok":
self.settingswindow.SettingsWindow.hide()
needrescan, needcolors, needcompletion, config = output
for (key, data) in config.items():
self.np.config.sections[key].update(data)
config = self.np.config.sections
# Write utils.py options
utils.DECIMALSEP = config["ui"]["decimalsep"]
utils.CATCH_URLS = config["urls"]["urlcatching"]
utils.HUMANIZE_URLS = config["urls"]["humanizeurls"]
utils.PROTOCOL_HANDLERS = config["urls"]["protocols"].copy()
utils.PROTOCOL_HANDLERS["slsk"] = self.OnSoulSeek
utils.USERNAMEHOTSPOTS = config["ui"]["usernamehotspots"]
uselimit = config["transfers"]["uselimit"]
uploadlimit = config["transfers"]["uploadlimit"]
limitby = config["transfers"]["limitby"]
if config["transfers"]["geoblock"]:
panic = config["transfers"]["geopanic"]
cc = config["transfers"]["geoblockcc"]
self.np.queue.put(slskmessages.SetGeoBlock([panic, cc]))
else:
self.np.queue.put(slskmessages.SetGeoBlock(None))
self.np.queue.put(slskmessages.SetUploadLimit(uselimit,uploadlimit,limitby))
self.np.queue.put(slskmessages.SetDownloadLimit(config["transfers"]["downloadlimit"]))
self.np.ToggleRespondDistributed(None, settings=True)
# Modify GUI
self.UpdateDownloadFilters()
self.TransparentTint(1)
self.np.config.writeConfiguration()
if not config["ui"]["trayicon"] and self.TrayApp.HAVE_TRAYICON:
self.TrayApp.destroy_trayicon()
elif config["ui"]["trayicon"] and not self.TrayApp.HAVE_TRAYICON:
if self.TrayApp.trayicon_module == None and not self.TrayApp.TRAYICON_CREATED:
self.TrayApp.Load()
else:
self.TrayApp.HAVE_TRAYICON = True
self.TrayApp.Draw()
if self.np.config.sections["language"]["setlanguage"]:
self.ChangeTranslation(config["language"]["language"])
if needcompletion:
self.chatrooms.roomsctrl.UpdateCompletions()
self.privatechats.UpdateCompletions()
if needcolors:
self.chatrooms.roomsctrl.UpdateColours()
self.privatechats.UpdateColours()
self.Searches.UpdateColours()
self.downloads.UpdateColours()
self.uploads.UpdateColours()
self.userinfo.UpdateColours()
self.userbrowse.UpdateColours()
self.settingswindow.UpdateColours()
self.userlist.UpdateColours()
self.UpdateColours()
self.OnShowChatButtons()
for w in [self.ChatNotebook, self.PrivatechatNotebook, self.UserInfoNotebook, self.UserBrowseNotebook, self.SearchNotebook]:
w.set_tab_closers(config["ui"]["tabclosers"])
w.set_reorderable(config["ui"]["tab_reorderable"])
w.show_images(config["ui"]["tab_icons"])
w.set_text_colors(None)
try:
for tab in self.MainNotebook.get_children():
self.MainNotebook.set_tab_reorderable(tab, config["ui"]["tab_reorderable"])
except:
# Old gtk
pass
tabLabels = [self.ChatTabLabel, self.PrivateChatTabLabel, self.DownloadsTabLabel, self.UploadsTabLabel, self.SearchTabLabel, self.UserInfoTabLabel, self.UserBrowseTabLabel, self.InterestsTabLabel]
if "BuddiesTabLabel" in self.__dict__:
tabLabels.append(self.BuddiesTabLabel)
for label_tab in tabLabels:
if type(label_tab) is ImageLabel:
label_tab.show_image(config["ui"]["tab_icons"])
label_tab.set_text_color(None)
elif type(label_tab) is gtk.EventBox:
label_tab.child.show_image(config["ui"]["tab_icons"])
label_tab.child.set_text_color(None)
self.SetTabPositions()
if self.np.transfers is not None:
self.np.transfers.checkUploadQueue()
self.UpdateTransferButtons()
if needrescan:
self.needrescan = 1
if msg == "ok" and self.needrescan:
self.needrescan = 0
self.BothRescan()
ConfigUnset = self.np.config.needConfig()
if ConfigUnset > 1:
if self.np.transfers is not None:
self.connect1.set_sensitive(0)
#self.OnSettings(None)
self.OnFastConfigure(None)
else:
if self.np.transfers is None:
self.connect1.set_sensitive(1)
#self.SetAllToolTips()
self.pluginhandler.check_enabled()
def OnChangePassword(self, password):
self.np.queue.put(slskmessages.ChangePassword(password))
def OnBackupConfig(self, widget=None):
response = SaveFile(self.MainWindow.get_toplevel(), os.path.dirname(self.np.config.filename), title="Pick a filename for config backup, or cancel to use a timestamp")
if response:
error, message = self.np.config.writeConfigBackup(response[0])
else:
error, message = self.np.config.writeConfigBackup()
if error:
self.logMessage("Error backing up config: %s" % message)
else:
self.logMessage("Config backed up to: %s" % message)
def SetAllToolTips(self):
act = self.np.config.sections["ui"]["tooltips"]
self.logMessage("I dont konw what to do with SetAllToolTips")
#for tips in [self.tooltips, self.roomlist.tooltips] + [page.tooltips for page in self.settingswindow.pages.values()] + [room.tooltips for room in self.chatrooms.roomsctrl.joinedrooms.values()] + [private.tooltips for private in self.privatechats.users.values()] + [user.tooltips for user in self.userinfo.users.values()] + [user.tooltips for user in self.userbrowse.users.values()] + [data[2].tooltips for data in self.Searches.searches.values() if data[2] is not None]:
# if act:
# tips.enable()
# else:
# tips.disable()
def AutoReplace(self, message):
if self.np.config.sections["words"]["replacewords"]:
autoreplaced = self.np.config.sections["words"]["autoreplaced"]
for word, replacement in autoreplaced.items():
message = message.replace(word, replacement)
return message
def CensorChat(self, message):
if self.np.config.sections["words"]["censorwords"]:
filler = self.np.config.sections["words"]["censorfill"]
censored = self.np.config.sections["words"]["censored"]
for word in censored:
message = message.replace(word, filler * len(word))
return message
def getTabPosition(self, string):
if string in ("Top", "top", _("Top")):
position = gtk.POS_TOP
elif string in ("Bottom", "bottom", _("Bottom")):
position = gtk.POS_BOTTOM
elif string in ("Left", "left", _("Left")):
position = gtk.POS_LEFT
elif string in ("Right", "right", _("Right")):
position = gtk.POS_RIGHT
else:
position = gtk.POS_TOP
return position
def SetTabPositions(self):
ui = self.np.config.sections["ui"]
self.ChatNotebook.set_tab_pos(self.getTabPosition(ui["tabrooms"]))
self.ChatNotebook.set_tab_angle(ui["labelrooms"])
self.MainNotebook.set_tab_pos(self.getTabPosition(ui["tabmain"]))
for label_tab in[self.ChatTabLabel, self.PrivateChatTabLabel, self.SearchTabLabel, self.UserInfoTabLabel, self.DownloadsTabLabel, self.UploadsTabLabel, self.UserBrowseTabLabel, self.InterestsTabLabel]:
if type(label_tab) is ImageLabel:
label_tab.set_angle(ui["labelmain"])
elif type(label_tab) is gtk.EventBox:
label_tab.child.set_angle(ui["labelmain"])
if "BuddiesTabLabel" in self.__dict__:
self.BuddiesTabLabel.set_angle(ui["labelmain"])
self.PrivatechatNotebook.set_tab_pos(self.getTabPosition(ui["tabprivate"]))
self.PrivatechatNotebook.set_tab_angle(ui["labelprivate"])
self.UserInfoNotebook.set_tab_pos(self.getTabPosition(ui["tabinfo"]))
self.UserInfoNotebook.set_tab_angle(ui["labelinfo"])
self.UserBrowseNotebook.set_tab_pos(self.getTabPosition(ui["tabbrowse"]))
self.UserBrowseNotebook.set_tab_angle(ui["labelbrowse"])
self.SearchNotebook.set_tab_pos(self.getTabPosition(ui["tabsearch"]))
self.SearchNotebook.set_tab_angle(ui["labelsearch"])
def TransparentTint(self, update=None):
if not self.np.config.sections["ui"]["enabletrans"]:
if self.translux:
self.translux.disable()
return
filter =""
tint = None
ttint = self.np.config.sections["ui"]["transtint"]
if ttint == "" or ttint[0] != "#":
return
ttint = ttint[1:]
if len(ttint) != 6:
return
try:
alpha = "%02X" % self.np.config.sections["ui"]["transalpha"]
tint = long(ttint+alpha, 16)
if update and self.translux:
self.translux.changeTint(tint)
if self.LogWindow not in self.translux.subscribers:
self.translux.subscribe(self.LogWindow, lambda: self.LogWindow.get_window(gtk.TEXT_WINDOW_TEXT))
except Exception, e:
log.addwarning(_('Translux error: %(error)s') % {'error':e})
if self.translux is None and tint is not None:
self.translux = translux.Translux(self.MainWindow, tint)
def CreateIconButton(self, icon, icontype, callback, label=None):
button = gtk.Button()
button.connect_object("clicked", callback, "")
button.show()
Alignment = gtk.Alignment(0.5, 0.5, 0, 0)
Alignment.show()
Hbox = gtk.HBox(False, 2)
Hbox.show()
Hbox.set_spacing(2)
image = gtk.Image()
image.set_padding(0, 0)
if icontype == "stock":
image.set_from_stock(icon, 4)
else:
image.set_from_pixbuf(icon)
image.show()
Hbox.pack_start(image, False, False, 0)
Alignment.add(Hbox)
if label:
Label = gtk.Label(label)
Label.set_padding(0, 0)
Label.show()
Hbox.pack_start(Label, False, False, 0)
button.add(Alignment)
return button
def UpdateDownloadFilters(self):
proccessedfilters = []
outfilter = "(\\\\("
failed = {}
df = self.np.config.sections["transfers"]["downloadfilters"]
df.sort()
# Get Filters from config file and check their escaped status
# Test if they are valid regular expressions and save error messages
for item in df :
filter, escaped = item
if escaped:
dfilter = re.escape(filter)
dfilter = dfilter.replace("\*", ".*")
else:
dfilter = filter
try:
re.compile("("+dfilter+")")
outfilter += dfilter
proccessedfilters.append(dfilter)
except Exception, e:
failed[dfilter] = e
proccessedfilters.append(dfilter)
if item is not df[-1]:
outfilter += "|"
# Crop trailing pipes
while outfilter[-1] == "|":
outfilter = outfilter [:-1]
outfilter += ")$)"
try:
re.compile(outfilter)
self.np.config.sections["transfers"]["downloadregexp"] = outfilter
# Send error messages for each failed filter to log window
if len(failed.keys()) >= 1:
errors = ""
for filter, error in failed.items():
errors += "Filter: %s Error: %s " % (filter, error)
error = _("Error: %(num)d Download filters failed! %(error)s " %{'num':len(failed.keys()), 'error':errors} )
self.logMessage(error)
except Exception, e:
# Strange that individual filters _and_ the composite filter both fail
self.logMessage(_("Error: Download Filter failed! Verify your filters. Reason: %s" % e))
self.np.config.sections["transfers"]["downloadregexp"] = ""
def UpdateTransferButtons(self):
if self.np.config.sections["transfers"]["enabletransferbuttons"]:
self.DownloadButtons.show()
self.UploadButtons.show()
else:
self.UploadButtons.hide()
self.DownloadButtons.hide()
def OnNicotineGuide(self, widget):
paths = []
file = "NicotinePlusGuide.html"
path1 = os.getcwd()
path1split = path1.rsplit(os.sep, 1)
if path1split[1] == "doc":
paths.append(path1split[0])
else:
paths.append(path1)
path2 = "%s/share/nicotine/documentation" % sys.prefix
paths.append(path2)
winpath = "C:\Program Files\Nicotine+"
paths.append(winpath)
for path in paths:
#
if os.path.exists(os.sep.join([path, "doc", file])):
url = "file:%s/%s/%s" % (urllib.pathname2url(path).replace("|", ":") ,"doc", file)
OpenUri(url)
return
if os.path.exists(os.sep.join([path, file])):
url = "file:%s/%s" % (urllib.pathname2url(path).replace("|", ":"), file)
OpenUri(url)
return
else:
popupWarning(None, _("Cannot Find Guide"), _("The Nicotine Offline Guide ( NicotinePlusGuide.html ) was not found in either the following directories:\n\n%(pwd)s\nand\n%(prefix)s/share/nicotine/documentation/\n\nEither install Nicotine-Plus, or start from inside the Nicotine-Plus source directory." % {'pwd':path1, 'prefix':sys.prefix } ) )
def OnOnlineNicotineGuide(self, widget):
url = "http://nicotine-plus.sourceforge.net/NicotinePlusGuide/"
OpenUri(url)
def OnSourceForgeProject(self, widget):
url = "http://sourceforge.net/projects/nicotine-plus/"
OpenUri(url)
def OnTrac(self, widget):
url = "http://nicotine-plus.org/"
OpenUri(url)
def OnCheckLatest(self, widget):
checklatest(self.MainWindow)
def OnReportBug(self, widget):
url = 'http://www.nicotine-plus.org/newticket?reporter=%s&keywords=%s' % (self.np.config.sections["server"]["login"], version)
if "svn" in version:
url += "&version=SVN"
else:
url += "&version=%s" % version
OpenUri(url)
def OnAbout(self, widget):
dlg = AboutDialog(self.MainWindow, self)
dlg.run()
dlg.destroy()
def OnAboutChatroomCommands(self, widget, parent=None):
if parent is None:
parent = self.MainWindow
dlg = AboutRoomsDialog(parent)
dlg.run()
dlg.destroy()
def OnAboutPrivateChatCommands(self, widget):
dlg = AboutPrivateDialog(self.MainWindow)
dlg.run()
dlg.destroy()
def OnAboutDependencies(self, widget):
dlg = AboutDependenciesDialog(self.MainWindow)
dlg.run()
dlg.destroy()
def OnAboutFilters(self, widget):
dlg = AboutFiltersDialog(self.MainWindow)
dlg.run()
dlg.destroy()
def OnShowChatButtons(self, widget=None):
if widget is not None:
show = widget.get_active()
self.np.config.sections["ui"]["chat_hidebuttons"] = (not show)
if self.chatrooms is None:
return
for room in self.chatrooms.roomsctrl.joinedrooms.values():
room.OnShowChatButtons(not self.np.config.sections["ui"]["chat_hidebuttons"])
self.np.config.writeConfiguration()
def OnShowLog(self, widget):
show = widget.get_active()
self.np.config.sections["logging"]["logcollapsed"] = (not show)
if not show:
if self.debugLogBox in self.vpaned1.get_children():
self.vpaned1.remove(self.debugLogBox)
else:
if not self.debugLogBox in self.vpaned1.get_children():
self.vpaned1.pack2(self.debugLogBox, False, True)
ScrollBottom(self.LogScrolledWindow)
self.np.config.writeConfiguration()
def OnShowFlags(self, widget):
if self.chatrooms is None:
return
show = widget.get_active()
self.np.config.sections["columns"]["hideflags"] = (not show)
for room in self.chatrooms.roomsctrl.joinedrooms:
self.chatrooms.roomsctrl.joinedrooms[room].cols[1].set_visible(show)
self.np.config.sections["columns"]["chatrooms"][room][1] = int(show)
self.userlist.cols[1].set_visible(show)
self.np.config.sections["columns"]["userlist"][1] = int(show)
self.np.config.writeConfiguration()
def OnShowRoomList(self, widget):
show = widget.get_active()
self.np.config.sections["ui"]["roomlistcollapsed"] = (not show)
if not show:
if self.roomlist.vbox2 in self.vpaned3.get_children():
self.vpaned3.remove(self.roomlist.vbox2)
#try:
if self.userlist.userlistvbox not in self.vpaned3.get_children():
self.vpaned3.hide()
#except AttributeError:
#pass # Happens when the roomlist is hidden on startup
else:
if not self.roomlist.vbox2 in self.vpaned3.get_children():
self.vpaned3.pack2(self.roomlist.vbox2, True, True)
self.vpaned3.show()
self.np.config.writeConfiguration()
def OnToggleBuddyList(self, widget):
tab = always = chatrooms = False
if self.buddylist_in_tab.get_active():
tab = True
if self.buddylist_always_visible.get_active():
always = True
if self.buddylist_in_chatrooms1.get_active():
chatrooms = True
if self.userlist.userlistvbox in self.MainNotebook.get_children():
if tab:
return
self.MainNotebook.remove_page(self.MainNotebook.page_num(self.userlist.userlistvbox))
if self.userlist.userlistvbox in self.vpanedm.get_children():
if always:
return
self.vpanedm.remove(self.userlist.userlistvbox)
if self.userlist.userlistvbox in self.vpaned3.get_children():
if chatrooms:
return
self.vpaned3.remove(self.userlist.userlistvbox)
if not self.show_room_list1.get_active():
#
if not chatrooms:
self.vpaned3.hide()
if tab:
self.BuddiesTabLabel = ImageLabel(_("Buddy list"), self.images["empty"])
self.BuddiesTabLabel.show()
if self.userlist.userlistvbox not in self.MainNotebook.get_children():
self.MainNotebook.append_page(self.userlist.userlistvbox, self.BuddiesTabLabel)
if self.userlist.userlistvbox in self.MainNotebook.get_children():
self.MainNotebook.set_tab_reorderable(self.userlist.userlistvbox, self.np.config.sections["ui"]["tab_reorderable"])
self.userlist.BuddiesLabel.hide()
self.np.config.sections["ui"]["buddylistinchatrooms"] = 0
if chatrooms:
self.vpaned3.show()
if self.userlist.userlistvbox not in self.vpaned3.get_children():
self.vpaned3.pack1(self.userlist.userlistvbox, True, True)
self.userlist.BuddiesLabel.show()
self.np.config.sections["ui"]["buddylistinchatrooms"] = 1
if always:
self.vpanedm.show()
if self.userlist.userlistvbox not in self.vpanedm.get_children():
self.vpanedm.pack2(self.userlist.userlistvbox, True, True)
self.userlist.BuddiesLabel.show()
self.np.config.sections["ui"]["buddylistinchatrooms"] = 2
else:
self.vpanedm.hide()
self.np.config.writeConfiguration()
def OnCheckPrivileges(self, widget):
self.np.queue.put(slskmessages.CheckPrivileges())
def OnSoulSeek(self, url):
try:
user, file = urllib.url2pathname(url[7:]).split("/", 1)
if file[-1] == "/":
self.np.ProcessRequestToPeer(user, slskmessages.FolderContentsRequest(None, file[:-1].replace("/","\\")))
else:
self.np.transfers.getFile(user, file.replace("/","\\"), "")
except:
self.logMessage(_("Invalid SoulSeek meta-url: %s") % url)
def SetClipboardURL(self, user, path):
self.clip.set_text( "slsk://" + urllib.pathname2url("%s/%s" % (user, path.replace("\\", "/"))) )
self.clip_data = "slsk://" + urllib.pathname2url("%s/%s" % (user, path.replace("\\", "/")))
self.MainWindow.selection_owner_set("PRIMARY", 0L)
def OnSelectionGet(self, widget, data, info, timestamp):
data.set_text(self.clip_data, -1)
def LocalUserInfoRequest(self, user):
# Hack for local userinfo requests, for extra security
if user == self.np.config.sections["server"]["login"]:
try:
if self.np.config.sections["userinfo"]["pic"] != "":
if sys.platform == "win32":
userpic = u"%s" % self.np.config.sections["userinfo"]["pic"]
else:
userpic = self.np.config.sections["userinfo"]["pic"]
if os.path.exists(userpic):
has_pic = True
f=open(userpic,'rb')
pic = f.read()
f.close()
else:
has_pic = False
pic = None
else:
has_pic = False
pic = None
except:
pic = None
descr = self.np.encode(eval(self.np.config.sections["userinfo"]["descr"], {}))
if self.np.transfers is not None:
totalupl = self.np.transfers.getTotalUploadsAllowed()
queuesize = self.np.transfers.getUploadQueueSizes()[0]
slotsavail = self.np.transfers.allowNewUploads()
ua = self.np.config.sections["transfers"]["remotedownloads"]
if ua:
uploadallowed = self.np.config.sections["transfers"]["uploadallowed"]
else:
uploadallowed = ua
self.userinfo.ShowLocalInfo(user, descr, has_pic, pic, totalupl, queuesize, slotsavail, uploadallowed)
else:
self.np.ProcessRequestToPeer(user, slskmessages.UserInfoRequest(None), self.userinfo)
# Here we go, ugly hack for getting your own shares
def BrowseUser(self, user):
login = self.np.config.sections["server"]["login"]
if user is None or user == login:
user = login
if user in [i[0] for i in self.np.config.sections["server"]["userlist"]] and self.np.config.sections["transfers"]["enablebuddyshares"]:
m = slskmessages.SharedFileList(None, self.np.config.sections["transfers"]["bsharedfilesstreams"])
else:
m = slskmessages.SharedFileList(None, self.np.config.sections["transfers"]["sharedfilesstreams"])
m.parseNetworkMessage(m.makeNetworkMessage(nozlib=1), nozlib=1)
self.userbrowse.ShowInfo(login, m)
else:
self.np.ProcessRequestToPeer(user, slskmessages.GetSharedFileList(None), self.userbrowse)
def OnBrowseMyShares(self, widget):
self.BrowseUser(None)
def PrivateRoomRemoveUser(self, room, user):
self.np.queue.put(slskmessages.PrivateRoomRemoveUser(room, user))
def PrivateRoomAddUser(self, room, user):
self.np.queue.put(slskmessages.PrivateRoomAddUser(room, user))
def PrivateRoomAddOperator(self, room, user):
self.np.queue.put(slskmessages.PrivateRoomAddOperator(room, user))
def PrivateRoomRemoveOperator(self, room, user):
self.np.queue.put(slskmessages.PrivateRoomRemoveOperator(room, user))
def OnFocusIn(self, widget, event):
self.MainWindow.set_icon(self.images["n"])
self.got_focus = True
if self.MainWindow.get_urgency_hint():
self.MainWindow.set_urgency_hint(False)
def OnFocusOut(self, widget, event):
self.got_focus = False
def EntryCompletionFindMatch(self, completion, entry_text, iter, widget):
model = completion.get_model()
item_text = model.get_value(iter, 0)
ix = widget.get_position()
config = self.np.config.sections["words"]
if entry_text == None or entry_text == "" or entry_text.isspace() or item_text is None:
return False
# Get word to the left of current position
if " " in entry_text:
split_key = entry_text[:ix].split(" ")[-1]
else:
split_key = entry_text
if split_key.isspace() or split_key == "" or len(split_key) < config["characters"]:
return False
# case-insensitive matching
if item_text.lower().startswith(split_key) and item_text.lower() != split_key:
return True
return False
#
def EntryCompletionFoundMatch(self, completion, model, iter, widget):
current_text = widget.get_text()
ix = widget.get_position()
# if more than a word has been typed, we throw away the
# one to the left of our current position because we want
# to replace it with the matching word
if " " in current_text:
prefix = " ".join(current_text[:ix].split(" ")[:-1])
suffix = " ".join(current_text[ix:].split(" "))
# add the matching word
new_text = "%s %s%s" % (prefix, model[iter][0], suffix)
# set back the whole text
widget.set_text(new_text)
# move the cursor at the end
widget.set_position(len(prefix) + len(model[iter][0]) + 1)
else:
new_text = "%s" % (model[iter][0])
widget.set_text(new_text)
widget.set_position(-1)
# stop the event propagation
return True
def OnPopupLogMenu(self, widget, event):
if event.button != 3:
return False
widget.emit_stop_by_name("button-press-event")
self.logpopupmenu.popup(None, None, None, event.button, event.time)
return True
def OnFindLogWindow(self, widget):
self.OnFindTextview(None, self.LogWindow)
def OnFindTextview(self, widget, textview, repeat=False):
if "FindDialog" not in self.__dict__:
self.FindDialog = FindDialog(self, _('Enter the string to search for:'), "", textview=textview, modal=False)
self.FindDialog.set_title(_('Nicotine+: Find string'))
self.FindDialog.set_icon(self.images["n"])
self.FindDialog.set_default_size(300, 100)
self.FindDialog.show()
self.FindDialog.set_transient_for(self.MainWindow)
self.FindDialog.connect("find-click", self.OnFindClicked)
return
if textview is not self.FindDialog.textview:
repeat = False
self.FindDialog.textview = textview
self.FindDialog.currentPosition = None
self.FindDialog.nextPosition = None
self.FindDialog.show()
self.FindDialog.deiconify()
if repeat:
self.OnFindClicked(widget, self.FindDialog.lastdirection)
else:
self.FindDialog.entry.set_text("")
def OnFindClicked(self, widget, direction):
if self.FindDialog.textview is None:
return
self.FindDialog.lastdirection = direction
textview = self.FindDialog.textview
buffer = textview.get_buffer()
start, end = buffer.get_bounds()
query = self.FindDialog.entry.get_text()
textview.emit("select-all", False)
if self.FindDialog.currentPosition is None:
self.FindDialog.currentPosition = buffer.create_mark(None, start, False)
self.FindDialog.nextPosition = buffer.create_mark(None, start, False)
second = 0
if direction == "next":
current = buffer.get_mark("insert")
iter = buffer.get_iter_at_mark(current)
match1 = iter.forward_search(query, gtk.TEXT_SEARCH_TEXT_ONLY, limit=None)
if match1 is not None and len(match1) == 2:
match_start, match_end = match1
buffer.place_cursor(match_end)
buffer.select_range( match_end, match_start)
textview.scroll_to_iter(match_start, 0)
else:
iter = start
match1 = iter.forward_search(query, gtk.TEXT_SEARCH_TEXT_ONLY, limit=None)
if match1 is not None and len(match1) == 2:
match_start, match_end = match1
buffer.place_cursor(match_end)
buffer.select_range( match_end, match_start)
textview.scroll_to_iter(match_start, 0)
elif direction == "previous":
current = buffer.get_mark("insert")
iter = buffer.get_iter_at_mark(current)
match1 = iter.backward_search(query, gtk.TEXT_SEARCH_TEXT_ONLY, limit=None)
if match1 is not None and len(match1) == 2:
match_start, match_end = match1
buffer.place_cursor(match_start)
buffer.select_range(match_start, match_end)
textview.scroll_to_iter(match_start, 0)
return
def OnCopyLogWindow(self, widget):
bound = self.LogWindow.get_buffer().get_selection_bounds()
if bound is not None and len(bound) == 2:
start, end = bound
log = self.LogWindow.get_buffer().get_text(start, end)
self.clip.set_text(log)
def OnCopyAllLogWindow(self, widget):
start, end = self.LogWindow.get_buffer().get_bounds()
log = self.LogWindow.get_buffer().get_text(start, end)
self.clip.set_text(log)
def OnClearLogWindow(self, widget):
self.LogWindow.get_buffer().set_text("")
def OnAddThingILike(self, widget):
thing = utils.InputDialog(self.MainWindow, _("Add thing I like"), _("I like")+":")
if thing and thing.lower() not in self.np.config.sections["interests"]["likes"]:
thing = thing.lower()
self.np.config.sections["interests"]["likes"].append(thing)
self.likes[thing] = self.likeslist.append([thing])
self.np.config.writeConfiguration()
self.np.queue.put(slskmessages.AddThingILike(self.np.encode(thing)))
def OnAddThingIDislike(self, widget):
thing = utils.InputDialog(self.MainWindow, _("Add thing I don't like"), _("I don't like")+":")
if thing and thing.lower() not in self.np.config.sections["interests"]["dislikes"]:
thing = thing.lower()
self.np.config.sections["interests"]["dislikes"].append(thing)
self.dislikes[thing] = self.dislikeslist.append([thing])
self.np.config.writeConfiguration()
self.np.queue.put(slskmessages.AddThingIHate(self.np.encode(thing)))
def SetRecommendations(self, title, recom):
self.recommendationslist.clear()
for (thing, rating) in recom.iteritems():
thing = self.np.decode(thing)
self.recommendationslist.append([thing, Humanize(rating), rating])
self.recommendationslist.set_sort_column_id(2, gtk.SORT_DESCENDING)
def SetUnrecommendations(self, title, recom):
self.unrecommendationslist.clear()
for (thing, rating) in recom.iteritems():
thing = self.np.decode(thing)
self.unrecommendationslist.append([thing, Humanize(rating), rating])
self.unrecommendationslist.set_sort_column_id(2, gtk.SORT_ASCENDING)
def GlobalRecommendations(self, msg):
self.SetRecommendations("Global recommendations", msg.recommendations)
self.SetUnrecommendations("Unrecommendations", msg.unrecommendations)
def Recommendations(self, msg):
self.SetRecommendations("Recommendations", msg.recommendations)
self.SetUnrecommendations("Unrecommendations", msg.unrecommendations)
def ItemRecommendations(self, msg):
self.SetRecommendations(_("Recommendations for %s") % msg.thing, msg.recommendations)
self.SetUnrecommendations("Unrecommendations", msg.unrecommendations)
def OnGlobalRecommendationsClicked(self, widget):
self.np.queue.put(slskmessages.GlobalRecommendations())
def OnRecommendationsClicked(self, widget):
self.np.queue.put(slskmessages.Recommendations())
def OnSimilarUsersClicked(self, widget):
self.np.queue.put(slskmessages.SimilarUsers())
def SimilarUsers(self, msg):
self.recommendationuserslist.clear()
self.recommendationusers = {}
for user in msg.users.keys():
iter = self.recommendationuserslist.append([self.images["offline"], user, "0", "0", 0, 0, 0])
self.recommendationusers[user] = iter
self.np.queue.put(slskmessages.AddUser(user))
def ItemSimilarUsers(self, msg):
self.recommendationuserslist.clear()
self.recommendationusers = {}
for user in msg.users:
iter = self.recommendationuserslist.append([self.images["offline"], user, "0", "0", 0, 0, 0])
self.recommendationusers[user] = iter
self.np.queue.put(slskmessages.AddUser(user))
def GetUserStatus(self, msg):
if msg.user not in self.recommendationusers:
return
img = self.GetStatusImage(msg.status)
self.recommendationuserslist.set(self.recommendationusers[msg.user], 0, img, 4, msg.status)
def GetUserStats(self, msg):
if msg.user not in self.recommendationusers:
return
self.recommendationuserslist.set(self.recommendationusers[msg.user], 2, HumanSpeed(msg.avgspeed), 3, Humanize(msg.files), 5, msg.avgspeed, 6, msg.files)
def OnPopupRUMenu(self, widget, event):
items = self.ru_popup_menu.get_children()
d = self.RecommendationUsersList.get_path_at_pos(int(event.x), int(event.y))
if not d:
return
path, column, x, y = d
user = self.recommendationuserslist.get_value(self.recommendationuserslist.get_iter(path), 1)
if event.button != 3:
if event.type == gtk.gdk._2BUTTON_PRESS:
self.privatechats.SendMessage(user)
self.ChangeMainPage(None, "private")
return
self.ru_popup_menu.set_user(user)
items[7].set_active(user in [i[0] for i in self.np.config.sections["server"]["userlist"]])
items[8].set_active(user in self.np.config.sections["server"]["banlist"])
items[9].set_active(user in self.np.config.sections["server"]["ignorelist"])
self.ru_popup_menu.popup(None, None, None, event.button, event.time)
def OnRemoveThingILike(self, widget):
thing = self.til_popup_menu.get_user()
if thing not in self.np.config.sections["interests"]["likes"]:
return
self.likeslist.remove(self.likes[thing])
del self.likes[thing]
self.np.config.sections["interests"]["likes"].remove(thing)
self.np.config.writeConfiguration()
self.np.queue.put(slskmessages.RemoveThingILike(self.np.encode(thing)))
def OnRecommendItem(self, widget):
thing = self.til_popup_menu.get_user()
self.np.queue.put(slskmessages.ItemRecommendations(self.np.encode(thing)))
self.np.queue.put(slskmessages.ItemSimilarUsers(self.np.encode(thing)))
def OnPopupTILMenu(self, widget, event):
if event.button != 3:
return
d = self.LikesList.get_path_at_pos(int(event.x), int(event.y))
if not d:
return
path, column, x, y = d
iter = self.likeslist.get_iter(path)
thing = self.likeslist.get_value(iter, 0)
self.til_popup_menu.set_user(thing)
self.til_popup_menu.popup(None, None, None, event.button, event.time)
def OnRemoveThingIDislike(self, widget):
thing = self.tidl_popup_menu.get_user()
if thing not in self.np.config.sections["interests"]["dislikes"]:
return
self.dislikeslist.remove(self.dislikes[thing])
del self.dislikes[thing]
self.np.config.sections["interests"]["dislikes"].remove(thing)
self.np.config.writeConfiguration()
self.np.queue.put(slskmessages.RemoveThingIHate(self.np.encode(thing)))
def OnPopupTIDLMenu(self, widget, event):
if event.button != 3:
return
d = self.DislikesList.get_path_at_pos(int(event.x), int(event.y))
if not d:
return
path, column, x, y = d
iter = self.dislikeslist.get_iter(path)
thing = self.dislikeslist.get_value(iter, 0)
self.tidl_popup_menu.set_user(thing)
self.tidl_popup_menu.popup(None, None, None, event.button, event.time)
def OnLikeRecommendation(self, widget):
thing = widget.parent.get_user()
if widget.get_active() and thing not in self.np.config.sections["interests"]["likes"]:
self.np.config.sections["interests"]["likes"].append(thing)
self.likes[thing] = self.likeslist.append([thing])
self.np.config.writeConfiguration()
self.np.queue.put(slskmessages.AddThingILike(self.np.encode(thing)))
elif not widget.get_active() and thing in self.np.config.sections["interests"]["likes"]:
self.likeslist.remove(self.likes[thing])
del self.likes[thing]
self.np.config.sections["interests"]["likes"].remove(thing)
self.np.config.writeConfiguration()
self.np.queue.put(slskmessages.RemoveThingILike(self.np.encode(thing)))
def OnDislikeRecommendation(self, widget):
thing = widget.parent.get_user()
if widget.get_active() and thing not in self.np.config.sections["interests"]["dislikes"]:
self.np.config.sections["interests"]["dislikes"].append(thing)
self.dislikes[thing] = self.dislikeslist.append([thing])
self.np.config.writeConfiguration()
self.np.queue.put(slskmessages.AddThingIHate(self.np.encode(thing)))
elif not widget.get_active() and thing in self.np.config.sections["interests"]["dislikes"]:
self.dislikeslist.remove(self.dislikes[thing])
del self.dislikes[thing]
self.np.config.sections["interests"]["dislikes"].remove(thing)
self.np.config.writeConfiguration()
self.np.queue.put(slskmessages.RemoveThingIHate(self.np.encode(thing)))
def OnRecommendRecommendation(self, widget):
thing = self.r_popup_menu.get_user()
self.np.queue.put(slskmessages.ItemRecommendations(self.np.encode(thing)))
self.np.queue.put(slskmessages.ItemSimilarUsers(self.np.encode(thing)))
def OnRecommendSearch(self, widget):
thing = widget.parent.get_user()
self.SearchEntry.set_text(thing)
self.ChangeMainPage(None, "search")
def OnPopupRMenu(self, widget, event):
if event.button != 3:
return
d = self.RecommendationsList.get_path_at_pos(int(event.x), int(event.y))
if not d:
return
path, column, x, y = d
iter = self.recommendationslist.get_iter(path)
thing = self.recommendationslist.get_value(iter, 0)
items = self.r_popup_menu.get_children()
self.r_popup_menu.set_user(thing)
items[0].set_active(thing in self.np.config.sections["interests"]["likes"])
items[1].set_active(thing in self.np.config.sections["interests"]["dislikes"])
self.r_popup_menu.popup(None, None, None, event.button, event.time)
def OnPopupUnRecMenu(self, widget, event):
if event.button != 3:
return
d = self.UnrecommendationsList.get_path_at_pos(int(event.x), int(event.y))
if not d:
return
path, column, x, y = d
iter = self.unrecommendationslist.get_iter(path)
thing = self.unrecommendationslist.get_value(iter, 0)
items = self.ur_popup_menu.get_children()
self.ur_popup_menu.set_user(thing)
items[0].set_active(thing in self.np.config.sections["interests"]["likes"])
items[1].set_active(thing in self.np.config.sections["interests"]["dislikes"])
self.ur_popup_menu.popup(None, None, None, event.button, event.time)
def OnShowTickers(self, widget):
if not self.chatrooms:
return
show = widget.get_active()
self.np.config.sections["ticker"]["hide"] = (not show)
self.np.config.writeConfiguration()
for room in self.chatrooms.roomsctrl.joinedrooms.values():
room.ShowTicker(show)
def RecommendationsExpanderStatus(self, widget):
if widget.get_property("expanded"):
self.RecommendationsVbox.set_child_packing(widget, False, True, 0, 0)
else:
self.RecommendationsVbox.set_child_packing(widget, True, True, 0, 0)
def GivePrivileges(self, user, days):
self.np.queue.put(slskmessages.GivePrivileges(user, days))
def MatchMainNotebox(self, tab):
if tab == self.hpaned1:
name = "chatrooms" # Chatrooms
elif tab == self.privatevbox :
name = "private"# Private rooms
elif tab == self.vboxdownloads:
name = "downloads" # Downloads
elif tab == self.vboxuploads:
name = "uploads" # Uploads
elif tab == self.searchvbox:
name = "search" # Searches
elif tab == self.userinfovbox:
name = "userinfo"# Userinfo
elif tab == self.userbrowsevbox:
name = "userbrowse"# User browse
elif tab == self.interests:
name = "interests" # Interests
elif tab == self.userlist.userlistvbox:
name = "userlist" # Buddy list
elif tab == self.extravbox:
name = "extra" # Buddy list
else:
#this should never happen, unless you've renamed a widget
return
return name
def MatchMainNamePage(self, tab):
if tab == "chatrooms":
child = self.hpaned1 # Chatrooms
elif tab == "private":
child = self.privatevbox # Private rooms
elif tab == "downloads":
child = self.vboxdownloads # Downloads
elif tab == "uploads":
child = self.vboxuploads # Uploads
elif tab == "search":
child = self.searchvbox # Searches
elif tab == "userinfo":
child = self.userinfovbox # Userinfo
elif tab == "userbrowse":
child = self.userbrowsevbox # User browse
elif tab == "interests":
child = self.interests # Interests
elif tab == "userlist":
child = self.userlist.userlistvbox # Buddy list
elif tab == "extra":
child = self.extravbox
else:
#this should never happen, unless you've renamed a widget
return
return child
def ChangeMainPage(self, widget, tab):
page_num = self.MainNotebook.page_num
if tab == "chatrooms":
child = self.hpaned1 # Chatrooms
elif tab == "private":
child = self.privatevbox # Private rooms
elif tab == "downloads":
child = self.vboxdownloads # Downloads
elif tab == "uploads":
child = self.vboxuploads # Uploads
elif tab == "search":
child = self.searchvbox # Searches
elif tab == "userinfo":
child = self.userinfovbox # Userinfo
elif tab == "userbrowse":
child = self.userbrowsevbox # User browse
elif tab == "interests":
child = self.interests # Interests
elif tab == "userlist":
child = self.userlist.userlistvbox # Buddy list
elif tab == "extra":
child = self.extravbox
else:
#this should never happen, unless you've renamed a widget
return
if child in self.MainNotebook.get_children():
self.MainNotebook.set_current_page(page_num(child))
else:
self.ShowTab(widget, [tab, child])
def OnChatRooms(self, widget):
self.ChangeMainPage(widget, "chatrooms")
def OnPrivateChat(self, widget):
self.ChangeMainPage(widget, "private")
def OnDownloads(self, widget):
self.ChangeMainPage(widget, "downloads")
def OnUploads(self, widget):
self.ChangeMainPage(widget, "uploads")
def OnSearchFiles(self, widget):
self.ChangeMainPage(widget, "search")
def OnUserInfo(self, widget):
self.ChangeMainPage(widget, "userinfo")
def OnUserBrowse(self, widget):
self.ChangeMainPage(widget, "userbrowse")
def OnInterests(self, widget):
self.ChangeMainPage(widget, "interests")
def OnUserList(self, widget):
self.ChangeMainPage(widget, "userlist")
class Notifications:
def __init__(self, frame):
self.frame = frame
self.tts = []
self.tts_playing = False
self.continue_playing = False
def Add(self, location, user, room=None, tab=True):
hilites = self.frame.TrayApp.tray_status["hilites"]
if location == "rooms" and room != None and user != None:
if room not in hilites["rooms"]:
hilites["rooms"].append(room)
self.sound("room_nick", user, place=room)
self.frame.TrayApp.SetImage()
elif location == "private":
if user in hilites[location]:
hilites[location].remove(user)
hilites[location].append(user)
elif user not in hilites[location]:
hilites[location].append(user)
self.sound(location, user)
self.frame.TrayApp.SetImage()
if tab and self.frame.np.config.sections["ui"]["urgencyhint"] and not self.frame.got_focus:
self.frame.MainWindow.set_urgency_hint(True)
self.SetTitle(user)
def ClearPage(self, notebook, item):
(page, label, window, focused) = item
#print notebook, page, label, window, focused
location=None
if notebook is self.frame.ChatNotebook:
location = "rooms"
self.Clear(location, room=label)
elif notebook is self.frame.PrivatechatNotebook:
location = "private"
self.Clear(location, user=label)
def Clear(self, location, user=None, room=None):
if location == "rooms" and room != None:
if room in self.frame.TrayApp.tray_status["hilites"]["rooms"]:
self.frame.TrayApp.tray_status["hilites"]["rooms"].remove(room)
self.SetTitle(room)
elif location == "private":
if user in self.frame.TrayApp.tray_status["hilites"]["private"]:
self.frame.TrayApp.tray_status["hilites"]["private"].remove(user)
self.SetTitle(user)
self.frame.TrayApp.SetImage()
def SetTitle(self, user=None):
if self.frame.TrayApp.tray_status["hilites"]["rooms"] == [] and self.frame.TrayApp.tray_status["hilites"]["private"] == []:
# Reset Title
if self.frame.MainWindow.get_title() != _("Nicotine+") + " " + version:
self.frame.MainWindow.set_title(_("Nicotine+") + " " + version)
else:
# Private Chats have a higher priority
if len(self.frame.TrayApp.tray_status["hilites"]["private"]) > 0:
user = self.frame.TrayApp.tray_status["hilites"]["private"][-1]
self.frame.MainWindow.set_title(_("Nicotine+") + " " + version+ " :: " + _("Private Message from %(user)s" % {'user':user} ) )
# Allow for the possibility the username is not available
elif len(self.frame.TrayApp.tray_status["hilites"]["rooms"]) > 0:
room = self.frame.TrayApp.tray_status["hilites"]["rooms"][-1]
if user == None:
self.frame.MainWindow.set_title(_("Nicotine+") + " " + version+ " :: " + _("You've been mentioned in the %(room)s room" % {'room':room} ) )
else:
self.frame.MainWindow.set_title(_("Nicotine+") + " " + version+ " :: " + _("%(user)s mentioned you in the %(room)s room" % {'user':user, 'room':room } ) )
def new_tts(self, message):
if not self.frame.np.config.sections["ui"]["speechenabled"]:
return
if message not in self.tts:
self.tts.append(message)
thread.start_new_thread(self.play_tts, ())
def play_tts(self):
if self.tts_playing:
self.continue_playing = True
return
for message in self.tts[:]:
self.tts_player(message)
if message in self.tts:
self.tts.remove(message)
self.tts_playing = False
if self.continue_playing:
self.continue_playing = False
self.play_tts()
def tts_clean(self, message):
for i in ["_", "[", "]", "(", ")"]:
message = message.replace(i, " ")
return message
def tts_player(self, message):
self.tts_playing = True
executeCommand(self.frame.np.config.sections["ui"]["speechcommand"], message)
def sound(self, message, user, place=None):
if sys.platform == "win32":
return
if self.frame.np.config.sections["ui"]["speechenabled"]:
if message == "room_nick" and place is not None:
self.new_tts(_("%(myusername)s, the user, %(username)s has mentioned your name in the room, %(place)s.") %{ "myusername": self.frame.np.config.sections[ "server"]["login"], "username": user, "place": place} )
elif message == "private":
self.new_tts("%(myusername)s, you have recieved a private message from %(username)s." % {"myusername":self.frame.np.config.sections["server"]["login"], "username":user } )
return
if "soundenabled" not in self.frame.np.config.sections["ui"] or not self.frame.np.config.sections["ui"]["soundenabled"]:
return
if "soundcommand" not in self.frame.np.config.sections["ui"]:
return
command = self.frame.np.config.sections["ui"]["soundcommand"]
path = None
exists = 0
if message == "private":
soundtitle = "private"
elif message == "room_nick":
soundtitle = "room_nick"
if "soundtheme" in self.frame.np.config.sections["ui"]:
path = os.path.expanduser(os.path.join(self.frame.np.config.sections["ui"]["soundtheme"], "%s.ogg" % soundtitle))
if os.path.exists(path): exists = 1
else: path = None
if not exists:
path = "%s/share/nicotine/sounds/default/%s.ogg" %(sys.prefix, soundtitle)
if os.path.exists(path): exists = 1
else: path = None
if not exists:
path = "sounds/default/%s.ogg" % soundtitle
if os.path.exists(path): exists = 1
else: path = None
if path != None and exists:
if command == "Gstreamer (gst-python)":
if self.frame.gstreamer.player is None:
return
self.frame.gstreamer.play(path)
else:
os.system("%s %s &" % ( command, path))
class TrayApp:
def __init__(self, frame):
self.frame = frame
self.current_image = None
self.pygtkicon = False
if gtk.pygtk_version[0] >= 2 and gtk.pygtk_version[1] >= 10:
self.pygtkicon = True
self.trayicon = None
self.trayicon_module = None
self.TRAYICON_CREATED = 0
self.TRAYICON_FAILED = 0
self.CREATE_TRAYICON = 0
self.HAVE_TRAYICON = False
self.tray_status = {"hilites" : { "rooms": [], "private": [] }, "status": "disconnect", "last": "disconnect"}
self.CreateMenu()
def HideUnhideWindow(self, widget):
if self.frame.is_mapped:
self.frame.MainWindow.unmap()
self.frame.is_mapped = False
else:
self.frame.MainWindow.map()
# weird, but this allows us to easily a minimized nicotine from one
# desktop to another by clicking on the tray icon
if self.frame.minimized:
self.frame.MainWindow.present()
self.frame.MainWindow.grab_focus()
self.frame.is_mapped = True
self.frame.chatrooms.roomsctrl.ClearNotifications()
self.frame.privatechats.ClearNotifications()
def Create(self, create=False):
if create:
self.HAVE_TRAYICON = self.CREATE_TRAYICON = True
if self.CREATE_TRAYICON:
self.Load()
if self.HAVE_TRAYICON:
self.Draw()
def Load(self):
if self.TRAYICON_FAILED:
return
# PyGTK >= 2.10
if self.pygtkicon:
trayicon = gtk.StatusIcon()
self.trayicon_module = trayicon
self.HAVE_TRAYICON = True
self.TRAYICON_FAILED = False
else:
if sys.platform == "win32":
return
try:
from pynicotine import trayicon
self.trayicon_module = trayicon
self.HAVE_TRAYICON = True
self.TRAYICON_FAILED = False
except ImportError, error:
self.TRAYICON_FAILED = True
self.HAVE_TRAYICON = False
log.add(_("Note: Trayicon Python module was not found in the pynicotine directory: %s") % error)
def destroy_trayicon(self):
if not self.TRAYICON_CREATED:
return
self.TRAYICON_CREATED = 0
self.HAVE_TRAYICON = False
self.current_image = None
if self.pygtkicon:
self.trayicon_module.set_visible(False)
self.trayicon_module = None
else:
if sys.platform != "win32":
self.eventbox.destroy()
self.trayicon.destroy()
else:
self.tray_status["last"] = ""
self.trayicon.hide_icon()
self.tray_popup_menu.destroy()
def Draw(self):
if not self.HAVE_TRAYICON or self.trayicon_module == None or self.TRAYICON_CREATED:
return
self.TRAYICON_CREATED = 1
if self.pygtkicon:
self.trayicon_module.set_visible(True)
self.trayicon_module.connect("popup-menu", self.OnStatusIconPopup)
self.trayicon_module.connect("activate", self.OnStatusIconClicked)
else:
if sys.platform == "win32":
if not self.trayicon:
self.trayicon = self.trayicon_module.TrayIcon("Nicotine", self.frame)
self.trayicon.show_icon()
else:
self.trayicon = self.trayicon_module.TrayIcon("Nicotine")
self.eventbox = gtk.EventBox()
self.trayicon.add(self.eventbox)
self.eventbox.connect("button-press-event", self.OnTrayiconClicked)
self.trayicon.show_all()
self.SetImage(self.tray_status["status"])
def SetImage(self, status=None):
# Abort if Trayicon module wasn't loaded
if not self.HAVE_TRAYICON or self.trayicon_module == None or not self.TRAYICON_CREATED:
return
try:
if status != None:
self.tray_status["status"] = status
# Check for hilites, and display hilite icon if there is a room or private hilite
if self.tray_status["hilites"]["rooms"] == [] and self.tray_status["hilites"]["private"] == []:
# If there is no hilite, display the status
icon = self.tray_status["status"]
self.trayicon_module.set_blinking(False)
else:
icon = "hilite2"
self.trayicon_module.set_blinking(True)
if icon != self.tray_status["last"]:
self.tray_status["last"] = icon
if self.pygtkicon:
self.trayicon_module.set_from_pixbuf(self.frame.images[icon])
else:
if sys.platform == "win32":
# For Win32 Systray
self.trayicon.set_img(icon)
else:
# For trayicon.so module X11 Systray
self.eventbox.hide()
if self.current_image != None:
self.eventbox.remove(self.current_image)
img = gtk.Image()
img.set_from_pixbuf(self.frame.images[icon])
img.show()
self.current_image = img
self.eventbox.add(self.current_image)
self.eventbox.show()
except Exception,e:
log.addwarning(_("ERROR: SetImage, %(error)s") % {'error':e})
def CreateMenu(self):
try:
self.tray_popup_menu_server = popup0 = PopupMenu(self)
popup0.setup(
("#" + _("Connect"), self.frame.OnConnect, gtk.STOCK_CONNECT),
("#" + _("Disconnect"), self.frame.OnDisconnect, gtk.STOCK_DISCONNECT),
)
self.tray_popup_menu = popup = PopupMenu(self)
popup.setup(
("#" + _("Hide / Unhide Nicotine"), self.HideUnhideWindow, gtk.STOCK_GOTO_BOTTOM),
(1, _("Server"), self.tray_popup_menu_server, self.OnPopupServer),
("#" + _("Settings"), self.frame.OnSettings, gtk.STOCK_PREFERENCES),
("#" + _("Send Message"), self.frame.OnOpenPrivateChat, gtk.STOCK_EDIT),
("#" + _("Lookup a User's IP"), self.frame.OnGetAUsersIP, gtk.STOCK_NETWORK),
("#" + _("Lookup a User's Info"), self.frame.OnGetAUsersInfo, gtk.STOCK_DIALOG_INFO),
("#" + _("Lookup a User's Shares"), self.frame.OnGetAUsersShares, gtk.STOCK_HARDDISK),
("%" + _("Toggle Away"), self.frame.OnAway, self.frame.images["away2"] ),
("#" + _("Quit"), self.frame.OnExit, gtk.STOCK_QUIT),
)
except Exception,e:
log.addwarning(_('ERROR: tray menu, %(error)s') % {'error':e})
def OnPopupServer(self, widget):
items = self.tray_popup_menu_server.get_children()
if self.tray_status["status"] == "disconnect":
items[0].set_sensitive(True)
items[1].set_sensitive(False)
else:
items[0].set_sensitive(False)
items[1].set_sensitive(True)
return
def OnStatusIconClicked(self, status_icon):
self.HideUnhideWindow(None)
def OnStatusIconPopup(self, status_icon, button, activate_time):
if button == 3:
self.tray_popup_menu.popup(None, None, None, button, activate_time)
if sys.platform == 'darwin':
if self.tray_popup_menu.get_property("visible") == False:
self.tray_popup_menu.popup(None, None, None, button, activate_time)
else:
self.tray_popup_menu.popdown()
def OnTrayiconClicked(self, obj, event):
(w, h) = self.trayicon.get_size()
if event.x < 0 or event.y < 0 or event.x >= w or event.y >= h:
return
if event.button == 1:
self.HideUnhideWindow(None)
else:
items = self.tray_popup_menu.get_children()
if self.tray_status["status"] == "disconnect":
act = False
else:
act = True
items[3].set_sensitive(act)
items[4].set_sensitive(act)
items[5].set_sensitive(act)
items[6].set_sensitive(act)
items[7].set_sensitive(act)
if event.type == gtk.gdk.BUTTON_PRESS:
self.tray_popup_menu.popup(None, None, None, event.button, event.time)
return True
return False
def SetToolTip(self, string):
if self.pygtkicon and self.trayicon_module is not None:
self.trayicon_module.set_tooltip(string)
class gstreamer:
def __init__(self):
self.player = None
try:
import pygst
pygst.require("0.10")
import gst
except Exception, error:
#print _("WARNING: Gstreamer-python module failed to load:"), error
return
self.gst = gst
try:
self.player = gst.element_factory_make("playbin", "player")
fakesink = gst.element_factory_make('fakesink', "my-fakesink")
self.player.set_property("video-sink", fakesink)
except Exception, error:
log.addwarning(_("ERROR: Gstreamer-python could not play: %(error)s") % {'error':error})
self.gst = self.player = None
return
self.bus = self.player.get_bus()
self.bus.add_signal_watch()
self.bus.connect('message', self.on_gst_message)
def play(self, path):
self.player.set_property('uri', "file://" + path)
self.player.set_state(self.gst.STATE_PLAYING)
def on_gst_message(self, bus, message):
t = message.type
if t == self.gst.MESSAGE_EOS:
self.player.set_state(self.gst.STATE_NULL)
elif t == self.gst.MESSAGE_ERROR:
self.player.set_state(self.gst.STATE_NULL)
class MainApp:
def __init__(self, config, plugindir, trayicon, rgbamode, start_hidden, WebBrowser, bindip):
self.frame = NicotineFrame(config, plugindir, trayicon, rgbamode, start_hidden, WebBrowser, bindip)
def MainLoop(self):
signal.signal(signal.SIGINT, signal.SIG_IGN)
self.frame.MainWindow.show()
gtk.gdk.threads_init()
gtk.gdk.threads_enter() # Without this N+ hangs on XP (Vista and Linux don't have that problem)
gtk.main()
gtk.gdk.threads_leave()