diff options
author | Alastair Tse <liquidx@gentoo.org> | 2003-04-30 23:28:03 +0000 |
---|---|---|
committer | Alastair Tse <liquidx@gentoo.org> | 2003-04-30 23:28:03 +0000 |
commit | 13947d655744571c197d370c9d7edf09d56a534a (patch) | |
tree | 05e76c0e8b230dba7c35d5abc1f6f61440f23387 /net-p2p | |
parent | Escaping double quotes doesn't seem to work with configure... (diff) | |
download | gentoo-2-13947d655744571c197d370c9d7edf09d56a534a.tar.gz gentoo-2-13947d655744571c197d370c9d7edf09d56a534a.tar.bz2 gentoo-2-13947d655744571c197d370c9d7edf09d56a534a.zip |
cleanup as old versions don't work with new soulseek protocol. 1.1.x marked stable x86
Diffstat (limited to 'net-p2p')
-rw-r--r-- | net-p2p/pysoulseek/ChangeLog | 7 | ||||
-rw-r--r-- | net-p2p/pysoulseek/Manifest | 15 | ||||
-rw-r--r-- | net-p2p/pysoulseek/files/digest-pysoulseek-1.0.0-r1 | 1 | ||||
-rw-r--r-- | net-p2p/pysoulseek/files/digest-pysoulseek-1.0.3.12.7 | 2 | ||||
-rw-r--r-- | net-p2p/pysoulseek/files/digest-pysoulseek-1.0.4.13 | 2 | ||||
-rw-r--r-- | net-p2p/pysoulseek/files/digest-pysoulseek-1.1.0_pre5 | 2 | ||||
-rw-r--r-- | net-p2p/pysoulseek/files/digest-pysoulseek-1.1.2.1.7 | 2 | ||||
-rw-r--r-- | net-p2p/pysoulseek/files/pysoulseek-1.0.0-hyriand-11.patch | 2566 | ||||
-rw-r--r-- | net-p2p/pysoulseek/pysoulseek-1.0.0-r1.ebuild | 34 | ||||
-rw-r--r-- | net-p2p/pysoulseek/pysoulseek-1.0.3.12.7.ebuild | 42 | ||||
-rw-r--r-- | net-p2p/pysoulseek/pysoulseek-1.1.0_pre5.ebuild | 43 | ||||
-rw-r--r-- | net-p2p/pysoulseek/pysoulseek-1.1.1.1.6.ebuild | 4 | ||||
-rw-r--r-- | net-p2p/pysoulseek/pysoulseek-1.1.2.1.7.ebuild (renamed from net-p2p/pysoulseek/pysoulseek-1.0.4.13.ebuild) | 7 |
13 files changed, 17 insertions, 2710 deletions
diff --git a/net-p2p/pysoulseek/ChangeLog b/net-p2p/pysoulseek/ChangeLog index 496beb7e4282..7270484112d2 100644 --- a/net-p2p/pysoulseek/ChangeLog +++ b/net-p2p/pysoulseek/ChangeLog @@ -1,6 +1,11 @@ # ChangeLog for net-p2p/pysoulseek # Copyright 2002-2003 Gentoo Technologies, Inc.; Distributed under the GPL v2 -# $Header: /var/cvsroot/gentoo-x86/net-p2p/pysoulseek/ChangeLog,v 1.16 2003/04/29 08:55:38 liquidx Exp $ +# $Header: /var/cvsroot/gentoo-x86/net-p2p/pysoulseek/ChangeLog,v 1.17 2003/04/30 23:27:55 liquidx Exp $ + +*pysoulseek-1.1.2.1.7 (01 May 2003) + + 01 May 2003; Alastair Tse <liquidx@gentoo.org> pysoulseek-1.1.2.1.7.ebuild: + version bump *pysoulseek-1.1.1.1.6 (29 Apr 2003) diff --git a/net-p2p/pysoulseek/Manifest b/net-p2p/pysoulseek/Manifest index f9655d696220..33d2e332ac75 100644 --- a/net-p2p/pysoulseek/Manifest +++ b/net-p2p/pysoulseek/Manifest @@ -1,12 +1,5 @@ -MD5 a746ca2011986a17b29848e2bcfe8a34 ChangeLog 2269 -MD5 ab49b3eed4e92f234123c6b901f57c62 pysoulseek-1.0.4.13.ebuild 1060 -MD5 15fe4dbf978bd3b7250df41cd8e1f196 pysoulseek-1.0.3.12.7.ebuild 1139 -MD5 c1d5b531d6fae30dbed742605b3ac651 pysoulseek-1.1.1.1.6.ebuild 944 -MD5 d09d850b9f48b9594c0354958f47128d pysoulseek-1.0.0-r1.ebuild 965 -MD5 0804c63462a0dc5d4592318935ea01f7 pysoulseek-1.1.0_pre5.ebuild 1190 -MD5 104052335da24af93d4d3446e1552d46 files/digest-pysoulseek-1.0.4.13 136 -MD5 f4819ad7fcbdee697b8de57b92eac3ab files/digest-pysoulseek-1.1.0_pre5 145 +MD5 990c1e82c2f172c081e11068a9875bcc ChangeLog 2400 +MD5 74ff71f03cf3eb29d84bf9585a0c6d71 pysoulseek-1.1.2.1.7.ebuild 944 +MD5 f48cc2d420f543654890c7931a5b2f98 pysoulseek-1.1.1.1.6.ebuild 943 MD5 003e381c9f868835bd6559167f9b3642 files/digest-pysoulseek-1.1.1.1.6 137 -MD5 2772f95fa7f417637dd9e7c39eb2e06e files/digest-pysoulseek-1.0.0-r1 63 -MD5 90ec4d5e925b4c78a17a16e896c089dd files/pysoulseek-1.0.0-hyriand-11.patch 120499 -MD5 0920e4f30348b6442ffa8a3a85f6dd80 files/digest-pysoulseek-1.0.3.12.7 138 +MD5 062e856f00b7f12024443bddfaadb9e1 files/digest-pysoulseek-1.1.2.1.7 137 diff --git a/net-p2p/pysoulseek/files/digest-pysoulseek-1.0.0-r1 b/net-p2p/pysoulseek/files/digest-pysoulseek-1.0.0-r1 deleted file mode 100644 index 989f97390abe..000000000000 --- a/net-p2p/pysoulseek/files/digest-pysoulseek-1.0.0-r1 +++ /dev/null @@ -1 +0,0 @@ -MD5 9c60085d1121bfeee5fc7b591d07aa68 pyslsk-1.0.0.tar.gz 89270 diff --git a/net-p2p/pysoulseek/files/digest-pysoulseek-1.0.3.12.7 b/net-p2p/pysoulseek/files/digest-pysoulseek-1.0.3.12.7 deleted file mode 100644 index 09302450d3a9..000000000000 --- a/net-p2p/pysoulseek/files/digest-pysoulseek-1.0.3.12.7 +++ /dev/null @@ -1,2 +0,0 @@ -MD5 7afb37f9696e284420b66f384b33e49e pyslsk-1.0.3.tar.gz 90807 -MD5 2b5cd10b5a9d42a5eb8d81340b22555e pyslsk-1.0.3-hyriand-12.7.patch 96963 diff --git a/net-p2p/pysoulseek/files/digest-pysoulseek-1.0.4.13 b/net-p2p/pysoulseek/files/digest-pysoulseek-1.0.4.13 deleted file mode 100644 index 0022334df41f..000000000000 --- a/net-p2p/pysoulseek/files/digest-pysoulseek-1.0.4.13 +++ /dev/null @@ -1,2 +0,0 @@ -MD5 6ffee23b618a04152718ba43f4cf90a2 pyslsk-1.0.4.tar.gz 92802 -MD5 53b6de78551388d2b08cbd545d3d8f92 pyslsk-1.0.4-hyriand-13.patch 60748 diff --git a/net-p2p/pysoulseek/files/digest-pysoulseek-1.1.0_pre5 b/net-p2p/pysoulseek/files/digest-pysoulseek-1.1.0_pre5 deleted file mode 100644 index 76b30b7feeea..000000000000 --- a/net-p2p/pysoulseek/files/digest-pysoulseek-1.1.0_pre5 +++ /dev/null @@ -1,2 +0,0 @@ -MD5 ce235d31be19348ad6e8760403172d67 pyslsk-1.1.0pre5.tar.gz 92985 -MD5 3abe6669949cf77ddf31102f60733ed9 pyslsk-1.1.0pre5-hyriand-1.4.patch 57565 diff --git a/net-p2p/pysoulseek/files/digest-pysoulseek-1.1.2.1.7 b/net-p2p/pysoulseek/files/digest-pysoulseek-1.1.2.1.7 new file mode 100644 index 000000000000..bdde84e1aeda --- /dev/null +++ b/net-p2p/pysoulseek/files/digest-pysoulseek-1.1.2.1.7 @@ -0,0 +1,2 @@ +MD5 d2bf40f6c98bb5ee34fe041231049818 pyslsk-1.1.2.tar.gz 93647 +MD5 e3a9cd542a20046b43cc3064852c64a0 pyslsk-1.1.2-hyriand-1.7.patch 55617 diff --git a/net-p2p/pysoulseek/files/pysoulseek-1.0.0-hyriand-11.patch b/net-p2p/pysoulseek/files/pysoulseek-1.0.0-hyriand-11.patch deleted file mode 100644 index eb6cceaa9c9a..000000000000 --- a/net-p2p/pysoulseek/files/pysoulseek-1.0.0-hyriand-11.patch +++ /dev/null @@ -1,2566 +0,0 @@ -diff -rNu3 pyslsk-1.0.0/encode_bitmaps.py slsk-tmp/encode_bitmaps.py ---- pyslsk-1.0.0/encode_bitmaps.py 2002-09-29 15:42:51.000000000 +0200 -+++ slsk-tmp/encode_bitmaps.py 2003-03-12 21:31:31.000000000 +0100 -@@ -12,7 +12,7 @@ - "-a -n Offline img/offline.gif pysoulseek/wxgui/images.py", - "-a -n Down img/sm_down.png pysoulseek/wxgui/images.py", - "-a -n Up img/sm_up.png pysoulseek/wxgui/images.py", -- -+ "-a -n Yellow img/active2.gif pysoulseek/wxgui/images.py", - ] - - -diff -rNu3 pyslsk-1.0.0/pysoulseek/config.py slsk-tmp/pysoulseek/config.py ---- pyslsk-1.0.0/pysoulseek/config.py 2003-03-12 18:17:38.000000000 +0100 -+++ slsk-tmp/pysoulseek/config.py 2003-03-12 21:33:16.000000000 +0100 -@@ -32,20 +32,29 @@ - "transfers":{"downloaddir":None,"sharedownloaddir":1,"shared":None, \ - "uploadbandwidth":100,"uselimit":0,"uploadlimit":100,"limitby":1, - "usecustomban":0,"customban":"don't bother to retry", -- "downloads":[],"sharedfiles":{}, \ -+ "downloads":[],"sharedfiles":{},"preferfriends":0, \ -+ "useupslots":0,"uploadslots":2, \ - "sharedfilesstreams":{},"sharedindex":{}},"userinfo":{"descr":"''", \ -- "pic":""},"logging":{"logsdir":os.path.expanduser("~"),"privatechat":0,"chatrooms":0},"searches":{"maxresults":50}} -+ "pic":""},"logging":{"logsdir":os.path.expanduser("~"),"privatechat":0,"chatrooms":0},"searches":{"maxresults":50}, -+ "ui":{"chatme":"FOREST GREEN", "chatremote":"","chatlocal":"BLUE", \ -+ "chathilite":"", "search":"","searchq":"GREY", "decimalsep":","}} - try: - f = open(filename+".shares") - self.sharesdb = cPickle.load(f) - f.close() - except: - self.sharesdb = None -- -+ try: -+ f = open(filename+".alias") -+ self.aliases = cPickle.load(f) -+ f.close() -+ except: -+ self.aliases = {} -+ - def needConfig(self): - for i in self.sections.keys(): - for j in self.sections[i].keys(): -- if self.sections[i][j] is None or self.sections[i][j] == '' and i != "userinfo": -+ if self.sections[i][j] is None or self.sections[i][j] == '' and i not in ("userinfo","ui"): - return 1 - return 0 - -@@ -57,7 +66,7 @@ - print "Bogus config section:",i - elif j not in self.sections[i].keys(): - print "Bogus config option",j,"section",i -- elif j in ['server','shared','uploadbandwidth','uselimit',"usecustomban",'uploadlimit','limitby','downloads','sharedfiles','sharedownloaddir','userlist','banlist','autojoin','sharedfilesstreams','privatechat','chatrooms','maxresults']: -+ elif j in ['server','shared','uploadbandwidth','uselimit',"usecustomban",'uploadlimit','limitby','downloads','sharedfiles','sharedownloaddir','userlist','banlist','autojoin','sharedfilesstreams','privatechat','chatrooms','maxresults','preferfriends','useupslots','uploadslots']: - try: - self.sections[i][j] = eval(val) - except: -@@ -95,9 +104,40 @@ - except: - pass - -+ def writeAliases(self): -+ f = open(self.filename+".alias","w") -+ cPickle.dump(self.aliases, f, 1) -+ f.close() -+ - def writeShares(self): - sharesdb = [self.sections["transfers"]["sharedfiles"],self.sections["transfers"]["sharedfilesstreams"],self.sections["transfers"]["sharedindex"]] - f = open(self.filename + ".shares","w") -- cPickle.dump(sharesdb, f) -+ cPickle.dump(sharesdb, f, 1) - f.close() - -+ def AddAlias(self, rest): -+ if rest: -+ args = rest.split(" ", 1) -+ if len(args) == 2: -+ if args[0] in ("alias", "unalias"): -+ return "I will not alias that!\n" -+ self.aliases[args[0]] = args[1] -+ self.writeAliases() -+ if self.aliases.has_key(args[0]): -+ return "Alias %s: %s\n" % (args[0], self.aliases[args[0]]) -+ else: -+ return "No such alias (%s)\n" % rest -+ else: -+ m = "\nAliases:\n" -+ for i in self.aliases.keys(): -+ m = m + "%s: %s\n" % (i, self.aliases[i]) -+ return m+"\n" -+ -+ def Unalias(self, rest): -+ if rest and self.aliases.has_key(rest): -+ x = self.aliases[rest] -+ del self.aliases[rest] -+ self.writeAliases() -+ return "Removed alias %s: %s\n" % (rest, x) -+ else: -+ return "No such alias (%s)\n" % rest -Files pyslsk-1.0.0/pysoulseek/config.pyc and slsk-tmp/pysoulseek/config.pyc differ -Files pyslsk-1.0.0/pysoulseek/__init__.pyc and slsk-tmp/pysoulseek/__init__.pyc differ -Files pyslsk-1.0.0/pysoulseek/mp3.pyc and slsk-tmp/pysoulseek/mp3.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/pysoulseek.py slsk-tmp/pysoulseek/pysoulseek.py ---- pyslsk-1.0.0/pysoulseek/pysoulseek.py 2003-03-12 19:58:00.000000000 +0100 -+++ slsk-tmp/pysoulseek/pysoulseek.py 2003-03-14 22:02:58.000000000 +0100 -@@ -5,6 +5,7 @@ - """ - - import time -+import socket - import slskproto - import slskmessages - from slskmessages import newId -@@ -101,6 +102,7 @@ - slskmessages.PeerTransfer:self.PeerTransfer, - slskmessages.SharedFileList:self.SharedFileList, - slskmessages.GetSharedFileList:self.GetSharedFileList, -+ slskmessages.FileSearchRequest:self.FileSearchRequest, - slskmessages.FileSearchResult:self.FileSearchResult, - slskmessages.ConnectToPeer:self.ConnectToPeer, - slskmessages.GetUserStatus:self.GetUserStatus, -@@ -576,9 +578,15 @@ - pic = None - descr = eval(self.config.sections["userinfo"]["descr"]) - if self.transfers is not None: -- totalupl = self.transfers.getTotalUploadsAllowed() - queuesize = self.transfers.getUploadQueueSizes()[0] -- slotsavail = not self.transfers.bandwidthLimitReached() -+ if self.config.sections["transfers"]["useupslots"]: -+ totalupl = self.config.sections["transfers"]["uploadslots"] -+ slotsavail = totalupl - self.transfers.activeUploads() -+ if slotsavail < 0: -+ slotsavail = 0 -+ else: -+ totalupl = self.transfers.getTotalUploadsAllowed() -+ slotsavail = not self.transfers.bandwidthLimitReached() - self.queue.put(slskmessages.UserInfoReply(msg.conn.conn,descr,pic,totalupl, queuesize,slotsavail)) - - self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) -@@ -760,6 +768,12 @@ - def FileSearch(self, msg): - self.logMessage("%s %s" %(msg.__class__, vars(msg))) - -+ def FileSearchRequest(self, msg): -+ for i in self.peerconns: -+ if i.conn == msg.conn.conn: -+ msg.user = i.username -+ self.SearchRequest(msg) -+ - def SearchRequest(self, msg): - maxresults = self.config.sections["searches"]["maxresults"] - index = self.config.sections["transfers"]["sharedindex"] -@@ -791,7 +805,13 @@ - results.remove(i) - - queuesizes = self.transfers.getUploadQueueSizes() -- slotsavail = not self.transfers.bandwidthLimitReached() -+ if self.config.sections["transfers"]["useupslots"]: -+ totalupl = self.config.sections["transfers"]["uploadslots"] -+ slotsavail = totalupl - self.transfers.activeUploads() -+ if slotsavail < 0: -+ slotsavail = 0 -+ else: -+ slotsavail = not self.transfers.bandwidthLimitReached() - if len(resultsogg) > 0: - message = slskmessages.FileSearchResult(None, msg.user, msg.searchid,resultsogg,slotsavail, self.speed, queuesizes[1]) - self.ProcessRequestToPeer(msg.user, message) -Files pyslsk-1.0.0/pysoulseek/pysoulseek.pyc and slsk-tmp/pysoulseek/pysoulseek.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/slskmessages.py slsk-tmp/pysoulseek/slskmessages.py ---- pyslsk-1.0.0/pysoulseek/slskmessages.py 2003-03-12 19:30:16.000000000 +0100 -+++ slsk-tmp/pysoulseek/slskmessages.py 2003-03-14 23:51:46.000000000 +0100 -@@ -738,6 +738,21 @@ - def makeNetworkMessage(self):
- return ""
-
-+class FileSearchRequest(PeerMessage):
-+ """ We send this to the peer when we search for something."""
-+ """ Peer sends this to tell us he is searching for something."""
-+ def __init__(self, conn, requestid = None, text = None):
-+ self.conn = conn -+ self.requestid = requestid
-+ self.text = text
-+
-+ def makeNetworkMessage(self):
-+ return self.packObject(self.requestid)+self.packObject(self.text)
-+
-+ def parseNetworkMessage(self,message):
-+ len, self.searchid = self.getObject(message,types.IntType)
-+ len, self.searchterm = self.getObject(message,types.StringType, len)
-+
- class FileSearchResult(PeerMessage):
- """ Peer sends this when it has a file search match."""
- def __init__(self,conn, user = None, token = None, list = None, freeulslots = None, ulspeed = None, inqueue = None):
-Files pyslsk-1.0.0/pysoulseek/slskmessages.pyc and slsk-tmp/pysoulseek/slskmessages.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/slskproto.py slsk-tmp/pysoulseek/slskproto.py ---- pyslsk-1.0.0/pysoulseek/slskproto.py 2003-03-12 19:29:47.000000000 +0100 -+++ slsk-tmp/pysoulseek/slskproto.py 2003-03-14 21:18:16.000000000 +0100 -@@ -79,7 +79,7 @@ - Msg83:83,Msg84:84,Msg85:85,Msg86:86,Msg87:87,Msg88:88, - Msg89:89,Msg90:90, - AddToPrivileged:91,CheckPrivileges:92,CantConnectToPeer:1001} -- peercodes = {GetSharedFileList:4, SharedFileList:5, FileSearchResult:9, -+ peercodes = {GetSharedFileList:4, SharedFileList:5, FileSearchRequest:8, FileSearchResult:9, - UserInfoRequest:15,UserInfoReply:16, FolderContentsRequest:36, - FolderContentsResponse:37, TransferRequest:40, - TransferResponse:41,PlaceholdUpload:42,QueueUpload:43, -Files pyslsk-1.0.0/pysoulseek/slskproto.pyc and slsk-tmp/pysoulseek/slskproto.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/transfers.py slsk-tmp/pysoulseek/transfers.py ---- pyslsk-1.0.0/pysoulseek/transfers.py 2003-03-11 16:00:34.000000000 +0100 -+++ slsk-tmp/pysoulseek/transfers.py 2003-03-12 21:40:48.000000000 +0100 -@@ -332,15 +332,28 @@ - return 1 - return 0 - -+ def activeUploads(self): -+ uploads = 0 -+ for i in self.uploads: -+ if i.conn is not None and i.speed is not None: -+ uploads = uploads + 1 -+ return uploads -+ - def bandwidthLimitReached(self): - maxbandwidth = self.eventprocessor.config.sections["transfers"]["uploadbandwidth"] -- bandwidth = 0 -+ maxslots = self.eventprocessor.config.sections["transfers"]["uploadslots"] -+ useupslots = self.eventprocessor.config.sections["transfers"]["useupslots"] -+ bandwidth = uploads = 0 - curtime = time.time() - for i in self.uploads: - if i.conn is not None and i.speed is not None: - bandwidth = bandwidth + i.speed -+ uploads = uploads + 1 - # self.eventprocessor.logMessage("%i %i " %(bandwidth, maxbandwidth),1) -- if bandwidth > maxbandwidth: -+ if useupslots: -+ if uploads >= maxslots: -+ return 1 -+ elif bandwidth > maxbandwidth: - return 1 - return 0 - -@@ -600,9 +613,16 @@ - transfercandidate = None - list = [i for i in self.uploads if not self.userTransfers(i.user) and i.status == "Queued"] - listogg = [i for i in list if i.filename[-4:].lower() == ".ogg"] -+ if self.eventprocessor.config.sections["transfers"]["preferfriends"]: -+ userlist = [i[0] for i in self.eventprocessor.frame.userlist] -+ listfriends = [i for i in list if i.user in userlist] -+ else: -+ listfriends = [] - listprivileged = [i for i in list if i.user in self.privilegedusers] - if len(listogg) > 0: - list = listogg -+ if len(listfriends) > 0: -+ list = listfriends - if len(listprivileged) > 0: - list = listprivileged - if len(list) == 0: -@@ -620,16 +640,22 @@ - if i.conn is msg.conn.conn: - user = i.username - -+ userlist = [i[0] for i in self.eventprocessor.frame.userlist] - list = {user:time.time()} - listogg = {user:time.time()} -+ listfriend = {user:time.time()} - listpriv = {user:time.time()} - countogg = 0 -+ countfriend = 0 - countpriv = 0 - for i in self.uploads: - if i.status == "Queued": - if i.user in self.privilegedusers: - listpriv[i.user] = i.timequeued - countpriv += 1 -+ elif i.user in userlist: -+ listfriend[i.user] = i.timequeued -+ countfriend += 1 - elif i.filename[-4:].lower() == ".ogg": - listogg[i.user] = i.timequeued - countogg += 1 -@@ -639,11 +665,14 @@ - place = 0 - if user in self.privilegedusers: - list = listpriv -+ elif user in userlist: -+ list = listfriend -+ place = place + countpriv - elif msg.file[-4:].lower() == ".ogg": - list = listogg -- place = place + countpriv -+ place = place + countpriv + countfriend - else: -- place = place + countpriv + countogg -+ place = place + countpriv + countfriend + countogg - for i in list.keys(): - if list[i] < list[user]: - place = place + 1 -Files pyslsk-1.0.0/pysoulseek/transfers.pyc and slsk-tmp/pysoulseek/transfers.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/utils.py slsk-tmp/pysoulseek/utils.py ---- pyslsk-1.0.0/pysoulseek/utils.py 2003-03-02 17:43:23.000000000 +0100 -+++ slsk-tmp/pysoulseek/utils.py 2003-03-13 00:26:31.000000000 +0100 -@@ -5,8 +5,8 @@ - """ - - import string --import os.path - import os,stat -+import os.path - import mp3 - - def getServerList(url): -@@ -28,19 +28,28 @@ - except: - return [] - --def getFilesList(dirs): -+def getFilesList(dirs, oldshares): - """ Get a list of files in dirs and subdirs with their filelength and - (if mp3) bitrate and track length in seconds """ - list = {} - for i in dirs: -- dircontents = getDirContents(i) -+ dircontents = getDirContents(i, oldshares) - for j in dircontents.keys(): - list[j] = dircontents[j] - return list - --def getDirContents(dir): -+def getDirContents(dir, oldshares): - """ Same as getFilesList, but only for one dir """ - dir = dir.replace("//","/") -+ -+ olddir = {} -+ if oldshares.has_key(dir): -+ for i in oldshares[dir]: -+ if len(i) == 5: -+ olddir[i[0]] = i -+ else: -+ break -+ - list = {dir:[]} - try: - contents = os.listdir(dir) -@@ -50,23 +59,30 @@ - for f in contents: - pathname = os.path.join(dir, f) - try: -- mode = os.stat(pathname)[stat.ST_MODE] -+ pathstat = os.stat(pathname) -+ mode = pathstat[stat.ST_MODE] -+ mtime = pathstat[stat.ST_MTIME] - except OSError, errtuple: - print errtuple - continue - else: - if stat.S_ISDIR(mode): - # It's a directory, recurse into it -- dircontents = getDirContents(pathname) -+ dircontents = getDirContents(pathname, oldshares) - for j in dircontents.keys(): - list[j] = dircontents[j] - elif stat.S_ISREG(mode): - # It's a file, check if it is mp3 -- list[dir].append(getFileInfo(f,pathname)) -+ if olddir.has_key(f) and olddir[f][4] == mtime: -+ list[dir].append(olddir[f]) -+ else: -+ list[dir].append(getFileInfo(f,pathname)) - return list - - def getFileInfo(name, pathname): -- size = os.stat(pathname)[stat.ST_SIZE] -+ filestat = os.stat(pathname) -+ size = filestat[stat.ST_SIZE] -+ mtime = filestat[stat.ST_MTIME] - if name[-4:] == ".mp3" or name[-4:] == ".MP3": - mp3info=mp3.detect_mp3(pathname) - if mp3info: -@@ -74,20 +90,20 @@ - bitrateinfo = (mp3info["vbrrate"],1) - else: - bitrateinfo = (mp3info["bitrate"],0) -- fileinfo = (name,size,bitrateinfo,mp3info["time"]) -+ fileinfo = (name,size,bitrateinfo,mp3info["time"],mtime) - else: -- fileinfo = (name,size,None,None) -+ fileinfo = (name,size,None,None,mtime) - elif name[-4:] == ".ogg" or name[-4:] == ".OGG": - try: - import ogg.vorbis - vf = ogg.vorbis.VorbisFile(pathname) - time = int(vf.time_total(0)) - bitrate = vf.bitrate(0)/1000 -- fileinfo = (name,size, (bitrate,0), time) -+ fileinfo = (name,size, (bitrate,0), time, mtime) - except: -- fileinfo = (name,size,None,None) -+ fileinfo = (name,size,None,None,mtime) - else: -- fileinfo = (name,size,None,None) -+ fileinfo = (name,size,None,None,mtime) - return fileinfo - - -@@ -141,3 +157,96 @@ - d[x] = x - return d.values() - -+def Humanize(number,fashion): -+ if fashion == "" or fashion == "<none>": -+ return str(number) -+ elif fashion == "<space>": -+ fashion = " " -+ number = str(number) -+ ret = "" -+ while number[-3:]: -+ part, number = number[-3:], number[:-3] -+ ret = "%s%s%s" % (part, fashion, ret) -+ return ret[:-1] -+ -+def expand_alias(aliases, cmd): -+ def getpart(line): -+ if line[0] != "(": -+ return "" -+ ix = 1 -+ ret = "" -+ level = 0 -+ while ix < len(line): -+ if line[ix] == "(": -+ level = level + 1 -+ if line[ix] == ")": -+ if level == 0: -+ return ret -+ else: -+ level = level - 1 -+ ret = ret + line[ix] -+ ix = ix + 1 -+ return "" -+ -+ if not cmd: -+ return None -+ if cmd[0] != "/": -+ return None -+ cmd = cmd[1:].split(" ") -+ if not aliases.has_key(cmd[0]): -+ return None -+ alias = aliases[cmd[0]] -+ ret = "" -+ i = 0 -+ while i < len(alias): -+ if alias[i:i+2] == "$(": -+ arg=getpart(alias[i+1:]) -+ if not arg: -+ ret = ret + "$" -+ i = i + 1 -+ continue -+ i = i + len(arg) + 3 -+ args = arg.split("=",1) -+ if len(args) > 1: -+ default = args[1] -+ else: -+ default = "" -+ args = args[0].split(":") -+ if len(args) == 1: -+ first = last = int(args[0]) -+ else: -+ if args[0]: -+ first = int(args[0]) -+ else: -+ first = 1 -+ if args[1]: -+ last = int(args[1]) -+ else: -+ last = len(cmd) -+ v = string.join(cmd[first:last+1]) -+ if not v: v = default -+ ret = ret + v -+ elif alias[i:i+2] == "|(": -+ arg = getpart(alias[i+1:]) -+ if not arg: -+ ret = ret + "|" -+ i = i + 1 -+ continue -+ i = i + len(arg) + 3 -+ for j in range(len(cmd)-1, -1, -1): -+ arg = arg.replace("$%i" % j, cmd[j]) -+ arg = arg.replace("$@", string.join(cmd[1:], " ")) -+ stdin, stdout = os.popen2(arg) -+ v = stdout.read().split("\n") -+ r = "" -+ for l in v: -+ l = l.strip() -+ if l: -+ r = r + l + "\n" -+ ret = ret + r.strip() -+ stdin.close() -+ stdout.close() -+ else: -+ ret = ret + alias[i] -+ i = i + 1 -+ return ret -Files pyslsk-1.0.0/pysoulseek/utils.pyc and slsk-tmp/pysoulseek/utils.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/about.py slsk-tmp/pysoulseek/wxgui/about.py ---- pyslsk-1.0.0/pysoulseek/wxgui/about.py 2003-03-11 12:14:37.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/about.py 2003-03-15 00:48:29.000000000 +0100 -@@ -7,7 +7,7 @@ - from wxPython.wx import * - import images - --version = "1.0.0" -+version = "1.0.0-hyriand-11" - - class About(wxDialog): - def __init__(self, parent, id, title): -@@ -59,6 +59,9 @@ - "/whois /w user", "Request user info for user 'user'", - "/ip user", "Show IP for user 'user'", - "", "", -+ "/alias /al [command [definition]]", "Add a new alias", -+ "/unalias /un command", "Remove an alias", -+ "", "", - "/ban user", "Add user 'user' to your ban list", - "/unban user", "Remove user 'user' from your ban list", - "", "", -@@ -66,6 +69,7 @@ - "/pm user", "Open private to user 'user'", - "", "", - "/search /s query", "Start a new search for 'query'", -+ "/usearch /us user query", "Search a user's shares for 'query'", - "/away /a", "Toggles your away status", - "/quit /q", "Quit PySoulSeek", - ] -@@ -78,10 +82,14 @@ - "/whois /w [user]", "Request user info for user 'user'", - "/ip [user]", "Show IP for user 'user'", - "", "", -+ "/alias /al [command [definition]]", "Add a new alias", -+ "/unalias /un command", "Remove an alias", -+ "", "", - "/ban [user]", "Add user 'user' to your ban list", - "/unban [user]", "Remove user 'user' from your ban list", - "", "", - "/search /s query", "Start a new search for 'query'", -+ "/usearch /us query", "Search a user's shares for 'query'", - "/away /a", "Toggles your away status", - "/quit /q", "Quit PySoulSeek", - ] -@@ -99,3 +107,49 @@ - self.SetSizer(mainsizer) - self.SetAutoLayout(True) - mainsizer.Fit(self) -+ -+class AboutFilters(wxDialog): -+ def __init__(self, parent, id, title): -+ -+ wxDialog.__init__(self,parent,id,title) -+ -+ sizer = wxStaticBoxSizer(wxStaticBox(self,-1,""),wxHORIZONTAL) -+ -+ mainsizer = wxBoxSizer(wxVERTICAL) -+ -+ ok = wxButton(self, wxID_OK, "OK") -+ ok.SetDefault() -+ -+ sizer.Add(wxStaticText(self,-1,"""Search filtering -+ -+You can use this to refine which results are displayed. The full results -+from the server are always available if you clear all the search terms. -+ -+You can filter by: -+ -+Included text: Files are shown if they contain this text. Case is insensitive, -+but word order is important. "Spears Brittany" will not show any "Brittany Spears" -+ -+Excluded text: As above, but files will not be displayed if the text matches -+ -+Size: Shows results based on size. use > and < to find files larger or smaller. -+Files exactly the same as this term will always match. Use = to specify an exact -+match. Use k or m to specify kilo or megabytes. >10M will find files larger than -+10 megabytes. <4000k will find files smaller than 4000k. -+ -+Bitrate: Find files based on bitrate. Use < and > to find lower or higher. >192 -+finds 192 and higher, <192 finds 192 or lower. =192 only finds 192. for VBR, the -+average bitrate is used. -+ -+Free slot: Show only those results from users which have at least one upload slot -+free. -+ -+To set the filter, press Enter. This will apply to any existing results, and any -+more that are returned. To filter in a different way, just set the relevant terms. -+You do not need to do another search to apply a different filter.""",style=wxALIGN_CENTRE), flag = wxALL, border = 5) -+ -+ mainsizer.Add(sizer, flag=wxALL,border = 5) -+ mainsizer.Add(ok, flag = wxALL|wxALIGN_CENTER,border = 10) -+ self.SetSizer(mainsizer) -+ self.SetAutoLayout(True) -+ mainsizer.Fit(self) -Files pyslsk-1.0.0/pysoulseek/wxgui/about.pyc and slsk-tmp/pysoulseek/wxgui/about.pyc differ -Files pyslsk-1.0.0/pysoulseek/wxgui/buttonsplitter.pyc and slsk-tmp/pysoulseek/wxgui/buttonsplitter.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/chat.py slsk-tmp/pysoulseek/wxgui/chat.py ---- pyslsk-1.0.0/pysoulseek/wxgui/chat.py 2003-03-12 20:28:29.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/chat.py 2003-03-14 22:46:55.000000000 +0100 -@@ -15,7 +15,8 @@ - import string - from sortablelist import sortableListCtrl - from wxPython.wx import * --import locale -+import random -+from pysoulseek.utils import Humanize,expand_alias - - - def GetCompletion(part, list): -@@ -247,7 +248,10 @@ - def SayChatRoom(self,msg,text): - self.CreateRoomWindow(msg.room) - self.joinedrooms[msg.room].SayChatRoom(msg,text) -- self.frame.OnPageUpdated(self.parent) -+ if text.find(self.frame.np.config.sections["server"]["login"])>=0: -+ self.frame.OnPageUpdated(self.parent, True) -+ else: -+ self.frame.OnPageUpdated(self.parent) - - def UserLeftRoom(self,msg): - self.CreateRoomWindow(msg.room) -@@ -374,15 +378,15 @@ - sendmessageID=wxNewId() - self.menu.Append(sendmessageID, 'Send Message') - EVT_MENU(self,sendmessageID, self.OnSendMessage) -- showipID=wxNewId() -- self.menu.Append(showipID, 'Show IP address') -- EVT_MENU(self,showipID, self.OnShowIp) - getinfoID=wxNewId() - self.menu.Append(getinfoID, 'Get User Info') - EVT_MENU(self,getinfoID, self.OnGetInfo) - browseID=wxNewId() - self.menu.Append(browseID, 'Browse Files') - EVT_MENU(self,browseID, self.OnBrowse) -+ showipID=wxNewId() -+ self.menu.Append(showipID, 'Show IP address') -+ EVT_MENU(self,showipID, self.OnShowIp) - addtolistID=wxNewId() - self.menu.Append(addtolistID, 'Add to User List') - EVT_MENU(self,addtolistID, self.OnAddToList) -@@ -431,12 +435,12 @@ - return username - elif col == 1: - if not sort: -- return locale.format("%s",self.parent.users[username].avgspeed,1) -+ return Humanize(self.parent.users[username].avgspeed,self.parent.frame.np.config.sections["ui"]["decimalsep"]) - else: - return self.parent.users[username].avgspeed - elif col == 2: - if not sort: -- return locale.format("%s",self.parent.users[username].files,1) -+ return Humanize(self.parent.users[username].files,self.parent.frame.np.config.sections["ui"]["decimalsep"]) - else: - return self.parent.users[username].files - else: -@@ -533,13 +537,20 @@ - text = self.frame.np.encode(self.mychatphrase.GetLineText(0)) - if len(text) == 0: - return -+ result = expand_alias(self.frame.np.config.aliases, text) -+ if result is not None: -+ text = result - s = text.split(" ", 1) - cmd = s[0] - if len(s) > 1: - rest = s[1] - else: - rest = "" -- if cmd in ("/join", "/j"): -+ if cmd in ("/alias", "/al"): -+ self.chat.AppendText(self.frame.np.config.AddAlias(rest)) -+ elif cmd in ("/unalias", "/un"): -+ self.chat.AppendText(self.frame.np.config.Unalias(rest)) -+ elif cmd in ("/join", "/j"): - if rest: - self.queue.put(slskmessages.JoinRoom(rest)) - elif cmd in ("/leave", "/part", "/l", "/p"): -@@ -581,12 +592,17 @@ - elif cmd in ("/search", "/s"): - if rest: - self.frame.np.search.DoSearch(rest) -+ elif cmd in ("/usearch", "/us"): -+ if rest: -+ l = rest.split(" ", 1) -+ if len(l) == 2: -+ self.frame.np.search.DoSearch(l[1], l[0]) - elif cmd == "/slap": - import random - if rest: -- msg = "/me slaps %s with a %s" % (rest, random.choice("a large trout", "a dictionary", "a rubber duck", "a copy of Windows XP", "a glove", "an empty bottle", "a lawsuit", "a ddos", "google", "a herring")) -+ msg = "/me slaps %s with a %s" % (rest, random.choice(("a large trout", "a dictionary", "a rubber duck", "a copy of Windows XP", "a glove", "an empty bottle", "a lawsuit", "a ddos", "google", "a herring"))) - self.queue.put(slskmessages.SayChatroom(self.room, msg)) -- elif cmd[0] == "/" and cmd != "/me": -+ elif len(cmd) > 0 and cmd[0] == "/" and cmd != "/me": - wxLogMessage("Command %s is not recognized" %(text)) - else: - self.queue.put(slskmessages.SayChatroom(self.room, text)) -@@ -655,15 +671,18 @@ - - if text[:4] == "/me ": - str = "%s * %s %s\n" %(time.strftime("%X"),msg.user,text[4:]) -- color = "FOREST GREEN" -+ color = self.frame.np.config.sections["ui"]["chatme"] - else: - str = "%s [%s] %s\n" %(time.strftime("%X"),msg.user,text) - if msg.user == self.frame.np.config.sections["server"]["login"]: -- color = wxBLUE -+ color = self.frame.np.config.sections["ui"]["chatlocal"] -+ elif text.upper().find(self.frame.np.config.sections["server"]["login"].upper()) >= 0: -+ color = self.frame.np.config.sections["ui"]["chathilite"] -+ self.parent.OnPageUpdated(self, True) - else: -- color = None -+ color = self.frame.np.config.sections["ui"]["chatremote"] - -- if color is not None: -+ if color is not None and color != "": - self.chat.SetDefaultStyle(wxTextAttr(color)) - self.chat.AppendUserText(self.frame.np.decode(str,wxUSE_UNICODE),msg.user,color) - self.chat.SetDefaultStyle(wxTextAttr()) -@@ -723,9 +742,14 @@ - timestamp = self.np.encode(time.strftime("%c",time.localtime())) - if text[:4] == "/me ": - str = "%s * %s %s\n" %(timestamp,msg.user,text[4:]) -- color = "FOREST GREEN" -+ color = self.np.config.sections["ui"]["chatme"] - else: - str = "%s [%s] %s\n" %(timestamp,msg.user,text) -+ if text.upper().find(self.np.config.sections["server"]["login"].upper()) >= 0: -+ color = self.np.config.sections["ui"]["chathilite"] -+ else: -+ color = self.np.config.sections["ui"]["chatremote"] -+ if color == "": - color = None - self.users[msg.user].AddText(self.np.decode(str,wxUSE_UNICODE),color) - self.np.frame.OnPageUpdated(self) -@@ -819,10 +843,12 @@ - timestamp = self.parent.np.encode(time.strftime("%c",time.localtime())) - if text[:4] == "/me ": - str = "%s * %s %s\n" %(timestamp,username,text[4:]) -- color = "FOREST GREEN" -+ color = self.parent.np.config.sections["ui"]["chatme"] - else: - str = "%s %s\n" %(timestamp,text) -- color = wxBLUE -+ color = self.parent.np.config.sections["ui"]["chatlocal"] -+ if color == "": -+ color = None - - if len(text) > 0: - self.AddText(self.parent.np.decode(str, wxUSE_UNICODE), color) -@@ -833,6 +859,9 @@ - def OnEnter(self, event): - """ Sends our chat phrase and updates the window.""" - text = self.parent.np.encode(self.mychatphrase.GetLineText(0)) -+ result = expand_alias(self.parent.np.config.aliases, text) -+ if result is not None: -+ text = result - s = text.split(" ", 1) - cmd = s[0] - if len(s) > 1: -@@ -844,7 +873,11 @@ - truerest = "" - else: - truerest = rest -- if cmd in ("/away", "/a"): -+ if cmd in ("/alias", "/al"): -+ self.chat.AppendText(self.parent.np.config.AddAlias(truerest)) -+ elif cmd in ("/unalias", "/un"): -+ self.chat.AppendText(self.parent.np.config.Unalias(truerest)) -+ elif cmd in ("/away", "/a"): - self.parent.np.frame.OnAway(event) - elif cmd in ("/quit", "/q"): - self.parent.np.frame.Close() -@@ -867,7 +900,10 @@ - elif cmd in ("/search", "/s"): - if truerest: - self.parent.np.search.DoSearch(truerest) -- elif cmd[0] == "/" and cmd != "/me": -+ elif cmd in ("/usearch", "/us"): -+ if truerest: -+ self.parent.np.search.DoSearch(truerest, self.user) -+ elif len(cmd) > 0 and cmd[0] == "/" and cmd != "/me": - wxLogMessage("Command %s is not recognized" %(text)) - else: - self.SendMessage(text) -Files pyslsk-1.0.0/pysoulseek/wxgui/chat.pyc and slsk-tmp/pysoulseek/wxgui/chat.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/configwindow.py slsk-tmp/pysoulseek/wxgui/configwindow.py ---- pyslsk-1.0.0/pysoulseek/wxgui/configwindow.py 2003-03-12 03:11:16.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/configwindow.py 2003-03-12 21:44:20.000000000 +0100 -@@ -10,6 +10,7 @@ - import os,stat - from pysoulseek import mp3 - from pysoulseek import utils -+import time - - from wxPython.wx import * - -@@ -116,6 +117,46 @@ - self._list.sort() - self.listbox.Set(self._list) - -+class ColourPicker: -+ def __init__(self, parent, id, title): -+ self.button = wxButton(parent, -1, title) -+ self.textctrl = wxTextCtrl(parent, -1, size=wxSize(125,25), style=wxTE_READONLY|wxTE_RICH|wxTE_MULTILINE) -+ self.button2 = wxButton(parent, -1, "Default") -+ self.parent = parent -+ self._value = "" -+ EVT_BUTTON(parent, self.button.GetId(), self.OnClick) -+ EVT_BUTTON(parent, self.button2.GetId(), self.OnClear) -+ -+ def OnClick(self, event): -+ colour = wxColourData() -+ colour.SetColour(self.textctrl.GetValue()) -+ dlg = wxColourDialog(self.parent, colour) -+ if dlg.ShowModal() == wxID_OK: -+ colour = dlg.GetColourData().GetColour() -+ if colour: -+ colourname = wxTheColourDatabase.FindName(colour) -+ if colourname: -+ self.SetValue(colourname) -+ else: -+ self.SetValue("#%2x%2x%2x" % (colour.Red(),colour.Green(),colour.Blue())) -+ else: -+ self.SetValue("") -+ dlg.Destroy() -+ -+ def OnClear(self,event): -+ self.SetValue("") -+ -+ def GetValue(self): -+ return self._value -+ -+ def SetValue(self, value): -+ self._value = value -+ self.textctrl.Clear() -+ style = self.textctrl.GetDefaultStyle() -+ self.textctrl.SetDefaultStyle(wxTextAttr(value)) -+ self.textctrl.AppendText(value.capitalize()) -+ self.textctrl.SetDefaultStyle(style) -+ - class ConfigWindow(wxDialog): - """ - This class defines a settings window that the main application should -@@ -135,10 +176,12 @@ - serverpanel = wxPanel(nb, -1) - transferspanel = wxPanel(nb, -1) - userinfopanel = wxPanel(nb, -1) -+ uipanel = wxPanel(nb, -1) - miscpanel = wxPanel(nb, -1) - nb.AddPage(serverpanel,"Server") - nb.AddPage(transferspanel,"Transfers") - nb.AddPage(userinfopanel,"Personal info") -+ nb.AddPage(uipanel,"Interface") - nb.AddPage(miscpanel,"Miscellaneous") - - self.serverctrl = wxTextCtrl(serverpanel,-1,size=wxSize(250, 25)) -@@ -165,7 +208,10 @@ - - self.downloaddirctrl = wxTextCtrl(transferspanel,-1,size=wxSize(250, 25)) - self.uploaddirsctrl = wxListBox(transferspanel, -1, size=wxSize(250,100)) -+ self.upload_use_width = wxRadioButton(transferspanel,-1,"upload speed exceeds ",style=wxRB_GROUP) -+ self.upload_use_slots = wxRadioButton(transferspanel,-1,"number of uploads exceeds ") - self.uploadbandwidth = wxTextCtrl(transferspanel,-1,size=wxSize(30, 25)) -+ self.upslots = wxTextCtrl(transferspanel,-1,size=wxSize(30,25)) - self.downloaddirchoose = wxButton(transferspanel, -1, "Choose...") - self.sharedownloadctrl = wxCheckBox(transferspanel, -1, "Share download directory") - self.uploaddiradd = wxButton(transferspanel, -1, "Add...") -@@ -175,6 +221,7 @@ - self.uploadlimit = wxTextCtrl(transferspanel, -1, size=wxSize(30,25)) - self.limittransfer = wxRadioButton(transferspanel, -1, "per transfer", style=wxRB_GROUP) - self.limittotal = wxRadioButton(transferspanel, -1, "total for all transfers") -+ self.preferfriends = wxCheckBox(transferspanel, -1, "Let users in my list download first") - - EVT_BUTTON(self,self.downloaddirchoose.GetId(),self.OnDownloadChoose) - EVT_BUTTON(self,self.uploaddiradd.GetId(),self.OnUploadAdd) -@@ -182,6 +229,8 @@ - EVT_BUTTON(self,self.uploaddirrescan.GetId(),self.OnUploadRescan) - EVT_CHECKBOX(self,self.sharedownloadctrl.GetId(),self.OnShareDownload) - EVT_CHECKBOX(self,self.useuploadlimit.GetId(),self.OnUseUploadLimit) -+ EVT_RADIOBUTTON(self,self.upload_use_width.GetId(),self.OnUploadChoose) -+ EVT_RADIOBUTTON(self,self.upload_use_slots.GetId(),self.OnUploadChoose) - - downloadsizer = wxBoxSizer(wxHORIZONTAL) - downloadsizer.Add(self.downloaddirctrl) -@@ -197,9 +246,14 @@ - uploadsizer.Add(uploadbuttonssizer) - - bandwidthsizer = wxBoxSizer(wxHORIZONTAL) -+ bandwidthsizer.Add(self.upload_use_width) - bandwidthsizer.Add(self.uploadbandwidth, flag=wxLEFT, border=10) - bandwidthsizer.Add(wxStaticText(transferspanel, -1, " KBytes/sec"),flag=wxALIGN_CENTER) - -+ upslotssizer = wxBoxSizer(wxHORIZONTAL) -+ upslotssizer.Add(self.upload_use_slots) -+ upslotssizer.Add(self.upslots) -+ - limitsizer = wxFlexGridSizer(cols=3, rows=2) - limitsizer.Add(self.uploadlimit, flag=wxLEFT, border = 10) - limitsizer.Add(wxStaticText(transferspanel, -1, " KBytes/sec "), flag=wxALIGN_CENTER) -@@ -214,10 +268,12 @@ - transferssizer.Add(self.sharedownloadctrl,flag=wxLEFT|wxTOP, border = 10) - transferssizer.Add(wxStaticText(transferspanel, -1, "Shared directories:"),flag=wxTOP|wxLEFT, border = 10) - transferssizer.Add(uploadsizer, flag=wxLEFT|wxRIGHT, border = 10) -- transferssizer.Add(wxStaticText(transferspanel, -1, "Locally queue uploads if total upload speed exceeds:"),flag=wxTOP|wxLEFT, border = 10) -- transferssizer.Add(bandwidthsizer,flag=wxLEFT|wxBOTTOM, border = 10) -+ transferssizer.Add(wxStaticText(transferspanel, -1, "Locally queue uploads if:"),flag=wxTOP|wxLEFT, border = 10) -+ transferssizer.Add(bandwidthsizer,flag=wxLEFT, border = 10) -+ transferssizer.Add(upslotssizer,flag=wxBOTTOM|wxLEFT, border = 10) - transferssizer.Add(self.useuploadlimit, flag=wxLEFT, border = 10) - transferssizer.Add(limitsizer, flag=wxLEFT|wxBOTTOM, border = 10) -+ transferssizer.Add(self.preferfriends, flag=wxLEFT|wxBOTTOM, border = 10) - - self.descr = wxTextCtrl(userinfopanel,-1,size=wxSize(250,100),style = wxTE_MULTILINE|wxTE_RICH) - self.pic = wxTextCtrl(userinfopanel,-1,size=wxSize(250, 25)) -@@ -234,6 +290,33 @@ - userinfosizer.Add(wxStaticText(userinfopanel, -1, "Picture:"),flag=wxTOP|wxLEFT, border = 10) - userinfosizer.Add(picsizer,flag=wxLEFT|wxBOTTOM, border = 10) - -+ self.colourchatremote = ColourPicker(uipanel, -1, "Remote text:") -+ self.colourchatlocal = ColourPicker(uipanel, -1, "Local text:") -+ self.colourchatme = ColourPicker(uipanel, -1, "/me text:") -+ self.colourhighlight = ColourPicker(uipanel, -1, "Highlight colour:") -+ self.coloursearchnoqueue = ColourPicker(uipanel, -1, "Without queue:") -+ self.coloursearchqueue = ColourPicker(uipanel, -1, "With queue:") -+ self.decimalsep = wxComboBox(uipanel, -1, style=wxCB_DROPDOWN|wxCB_READONLY, choices = ["<none>", ",", ".", "<space>"]) -+ -+ uisizer=wxStaticBoxSizer(wxStaticBox(uipanel,-1,"Colours:"),wxVERTICAL) -+ uisizer.Add(wxStaticText(uipanel,-1,"Chat colours:"), flag=wxLEFT|wxTOP, border = 10) -+ chatcoloursgrid = wxFlexGridSizer(cols=3, vgap=2, hgap=5) -+ for i in self.colourchatremote, self.colourchatlocal, self.colourchatme, self.colourhighlight: -+ chatcoloursgrid.Add(i.button, flag=wxEXPAND) -+ chatcoloursgrid.Add(i.textctrl) -+ chatcoloursgrid.Add(i.button2) -+ uisizer.Add(chatcoloursgrid, flag=wxEXPAND|wxLEFT, border=15) -+ uisizer.Add(wxStaticText(uipanel,-1,"Search result colours:"),flag=wxLEFT|wxTOP, border=10) -+ searchcoloursgrid = wxFlexGridSizer(cols=3,vgap=2,hgap=5) -+ for i in self.coloursearchnoqueue, self.coloursearchqueue: -+ searchcoloursgrid.Add(i.button, flag=wxEXPAND) -+ searchcoloursgrid.Add(i.textctrl) -+ searchcoloursgrid.Add(i.button2) -+ uisizer.Add(searchcoloursgrid, flag=wxEXPAND|wxLEFT, border=15) -+ decimalsepsizer = wxBoxSizer(wxHORIZONTAL) -+ decimalsepsizer.Add(wxStaticText(uipanel, -1, "Decimal separator:"), flag=wxALIGN_CENTER|wxRIGHT, border = 5) -+ decimalsepsizer.Add(self.decimalsep) -+ uisizer.Add(decimalsepsizer, flag=wxTOP|wxLEFT, border=10) - - self.logsdirctrl = wxTextCtrl(miscpanel,-1,size=wxSize(250, 25)) - self.logsdirchoose = wxButton(miscpanel, -1, "Choose...") -@@ -271,6 +354,8 @@ - transferspanel.SetAutoLayout(True) - userinfopanel.SetSizer(userinfosizer) - userinfopanel.SetAutoLayout(True) -+ uipanel.SetSizer(uisizer) -+ uipanel.SetAutoLayout(true) - miscpanel.SetSizer(miscsizer) - miscpanel.SetAutoLayout(True) - -@@ -345,7 +430,7 @@ - shared.append(self.encode(self.uploaddirsctrl.GetString(i))) - if self.sharedownloadctrl.GetValue(): - shared.append(self.encode(self.downloaddirctrl.GetValue())) -- self.sharedfiles = utils.getFilesList(shared) -+ self.sharedfiles = utils.getFilesList(shared, self.sharedfiles) - self.sharedfilesstreams = utils.getFilesStreams(self.sharedfiles) - self.sharedindex = utils.getFilesIndex(shared,self.sharedfiles) - -@@ -365,12 +450,21 @@ - if dir is not None: - self.logsdirctrl.SetValue(dir) - -+ def OnUploadChoose(self,event): -+ if self.upload_use_width.GetValue(): -+ self.upslots.Enable(false) -+ self.uploadbandwidth.Enable(true) -+ else: -+ self.upslots.Enable(true) -+ self.uploadbandwidth.Enable(false) -+ - def SetSettings(self, config): - server = config.sections["server"] - transfers = config.sections["transfers"] - userinfo = config.sections["userinfo"] - logging = config.sections["logging"] - searches = config.sections["searches"] -+ ui = config.sections["ui"] - if server["server"] is not None: - self.serverctrl.SetValue(string.join([str(i) for i in server["server"]],":")) - if server["login"] is not None: -@@ -408,6 +502,16 @@ - self.usecustomban.SetValue(transfers["usecustomban"]) - if transfers["customban"] is not None: - self.customban.SetValue(transfers["customban"]) -+ if transfers["preferfriends"] is not None: -+ self.preferfriends.SetValue(transfers["preferfriends"]) -+ if transfers["uploadslots"] is not None: -+ self.upslots.SetValue(str(transfers["uploadslots"])) -+ if transfers["useupslots"] is not None: -+ if transfers["useupslots"]: -+ self.upload_use_slots.SetValue(true); -+ else: -+ self.upload_use_width.SetValue(true); -+ self.OnUploadChoose(None) - if userinfo["descr"] is not None: - self.descr.SetValue(eval(userinfo["descr"])) - if userinfo["pic"] is not None: -@@ -420,6 +524,20 @@ - self.loggingchatctrl.SetValue(logging["chatrooms"]) - if searches["maxresults"] is not None: - self.maxresults.SetValue(str(searches["maxresults"])) -+ if ui["chatremote"] is not None: -+ self.colourchatremote.SetValue(ui["chatremote"]) -+ if ui["chatlocal"] is not None: -+ self.colourchatlocal.SetValue(ui["chatlocal"]) -+ if ui["chatme"] is not None: -+ self.colourchatme.SetValue(ui["chatme"]) -+ if ui["chatme"] is not None: -+ self.colourhighlight.SetValue(ui["chathilite"]) -+ if ui["search"] is not None: -+ self.coloursearchnoqueue.SetValue(ui["search"]) -+ if ui["searchq"] is not None: -+ self.coloursearchqueue.SetValue(ui["searchq"]) -+ if ui["decimalsep"] is not None: -+ self.decimalsep.SetValue(ui["decimalsep"]) - - def encode(self, str): - import locale,types -@@ -455,6 +573,11 @@ - except: - uploadlimit = None - try: -+ uploadslots = int(self.encode(self.upslots.GetValue())) -+ except: -+ uploadslots = None -+ useupslots = self.encode(self.upload_use_slots.GetValue()) -+ try: - maxresults = int(self.encode(self.maxresults.GetValue())) - except: - maxresults = None -@@ -475,11 +598,21 @@ - "usecustomban":self.encode(self.usecustomban.GetValue()), \ - "customban":self.encode(self.customban.GetValue()), \ - "uploadlimit":uploadlimit, \ -+ "uploadslots":uploadslots, \ -+ "useupslots":useupslots, \ - "limitby":self.encode(self.limittotal.GetValue()), \ -+ "preferfriends":self.encode(self.preferfriends.GetValue()), \ - "sharedownloaddir":self.encode(self.sharedownloadctrl.GetValue())},"userinfo": \ - {"descr":self.encode(self.descr.GetValue()).__repr__(), \ - "pic":self.encode(self.pic.GetValue())},"logging":{ \ - "logsdir":self.encode(self.logsdirctrl.GetValue()), \ - "privatechat":self.encode(self.loggingprivatectrl.GetValue()), \ - "chatrooms":self.encode(self.loggingchatctrl.GetValue())}, -- "searches":{"maxresults":maxresults}} -+ "searches":{"maxresults":maxresults}, \ -+ "ui":{"chatremote":self.encode(self.colourchatremote.GetValue()), \ -+ "chatlocal":self.encode(self.colourchatlocal.GetValue()), \ -+ "chatme":self.encode(self.colourchatme.GetValue()), \ -+ "chathilite":self.encode(self.colourhighlight.GetValue()), \ -+ "search":self.encode(self.coloursearchnoqueue.GetValue()), \ -+ "searchq":self.encode(self.coloursearchqueue.GetValue()), -+ "decimalsep":self.encode(self.decimalsep.GetValue())}} -Files pyslsk-1.0.0/pysoulseek/wxgui/configwindow.pyc and slsk-tmp/pysoulseek/wxgui/configwindow.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/frame.py slsk-tmp/pysoulseek/wxgui/frame.py ---- pyslsk-1.0.0/pysoulseek/wxgui/frame.py 2003-03-10 17:42:25.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/frame.py 2003-03-15 00:42:13.000000000 +0100 -@@ -21,6 +21,7 @@ - import buttonsplitter - from wxPython.wx import * - from configwindow import * -+from types import StringType - - class NetworkEvent(wxPyEvent): - """ -@@ -123,6 +124,9 @@ - aboutPrivateID = wxNewId() - helpmenu.Append(aboutPrivateID, '&Private chat commands', 'About private chat commands') - EVT_MENU(self,aboutPrivateID, self.OnAboutPrivateCommands) -+ aboutFiltersID = wxNewId() -+ helpmenu.Append(aboutFiltersID, '&Search filters', 'About search filtering') -+ EVT_MENU(self,aboutFiltersID, self.OnAboutFilters) - helpmenu.AppendSeparator() - aboutID = wxNewId() - helpmenu.Append(aboutID, '&About', 'About PySoulSeek') -@@ -295,6 +299,9 @@ - def OnAboutPrivateCommands(self, event): - about.AboutCommands(self, -1, "About Chat Commands", True).ShowModal() - -+ def OnAboutFilters(self, event): -+ about.AboutFilters(self, -1, "About Search Filters").ShowModal() -+ - def ConnectError(self,msg): - self.mainmenu.Enable(self.connectID,1) - self.mainmenu.Enable(self.disconnectID,0) -@@ -373,8 +380,8 @@ - break - - -- def OnPageUpdated(self, pageobj): -- self.nb.OnPageUpdated(pageobj) -+ def OnPageUpdated(self, pageobj, hilite=False): -+ self.nb.OnPageUpdated(pageobj, hilite) - - def callback(self,msgs): - """ Callback function called by networking thread.""" -Files pyslsk-1.0.0/pysoulseek/wxgui/frame.pyc and slsk-tmp/pysoulseek/wxgui/frame.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/images.py slsk-tmp/pysoulseek/wxgui/images.py ---- pyslsk-1.0.0/pysoulseek/wxgui/images.py 2003-02-20 14:08:48.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/images.py 2003-03-12 21:31:36.000000000 +0100 -@@ -1,5 +1,5 @@ - #---------------------------------------------------------------------- --# This file was generated by ./encode_bitmaps.py -+# This file was generated by encode_bitmaps.py - # - from wxPython.wx import wxImageFromStream, wxBitmapFromImage - from wxPython.wx import wxEmptyIcon -@@ -8,150 +8,289 @@ - - def getBirdData(): - return zlib.decompress( --"x\xda\x01'\x0e\xd8\xf1\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00@\x00\ -+'x\xda\x01~\x1c\x81\xe3\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00@\x00\ - \x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\ --\x08d\x88\x00\x00\r\xdeIDATx\x9c\xe5[+p#\xc7\x16=I5\xb8@\xa0\x81\xc1\x00\x83\ --\x01\x06\x03\x02\x06\x18\x0c0\x10\x08\x10X \xb0@\xe0\x01\x83\x05\x06\x0f\x18\ --\x1a\x04,\x080\x0c\\\x10`\xb0@`\x81\xc1\x02\x83\x05\x06\x0f\x08,\x100\x18\ --\xb0`\x80\xc1\x00\x83\x01\x06\x17LU\x1e\xe8\xdf\xed\x9e\x96,o\x92\xaa\xd4{\ --\xb7J\xf6h>\xdd\xf7{\xeeG\xd2\x0f\x00\xfe\xc0\xff1)\xf3\x97\xcc\xbb\x91\xc5%\ --\nw\x8c\xc9\xff\x1c\x8d\xd1\x8a\xf19\xb7\xc7\xc8\xf9u\xe4}\x87q\x1c\x9e;d\ --\x1d%\xafqt\xee\x07X\x0f\xd0E\x89\xa2(\x02\xb3d\x14@\x8a\xec&\xe6?9eM6\xd9q\ --\xfe@rO{\x13x\xa5s\xf6~O\xc9u\x1e\xa3Ub\xa5\x8c\x0c\x8c\x8c\xfe\xb1G\xff\xd8\ --\x01`\xe7\x01\x80.\n\x94?\xd5\xa0\x99\x06\x91Q\x80\x11\xde\xfe'2Lz\x85\x08e\ --\x08\xe1I\x99\xedI\xb2\xa1\x00\xb2\x02\xf1\x18\xde\xbb\xfb\"\x01$\xd3R\xb81\ --\xb6\\\xb8\x8f#!\xd9\xdd'\xae\xf1h\xef\x19\x19426\x9b{\xab\x80 \x8a\xf9;\xd3\ --\x00i`F\xc1\x0b\xac\x12\x00\x02+\xe9\x11\x00\x0b\xef\xf0\x16t\xd7<C\xd6\x99x\ --0\xe7(\xac\x85\x91\xc1\xd6\xb3\"\xa1\xad\x12\xa3\xd0L<\x8c\xe1\xc2\x89\x12O!\ --q\x873\x03\x81\x15\x83F2\xca\x10k)\xb7\x01)\xf2\x96\x07\xe9`u+<\x12\xe1\x91X\ --\xdfo\x9f`\x04)\x86&\xa0i\x1a\x00\xc0\xc0\xc0\xb6\xed\xc0\xcf\xec\xbd\x89\ --\xd9pB L\x1c>\x13\xe7\xecB\x12\xc2\xdaJ\n\x9e\xf1\xad\x11V\t\x88\xae\xfd\x18\ --8%\xef\xfeq\x08X\xe6\xc8\x1d\x93g\xdc\x85\x00\xa9\xf0\n\xd7\xc9\xdb\xe3\xf6\ --\xe3\x1a\xf3\x93\x12\xf3\xaa\xc4\xf6\xeb\xc6Z\x8bA\x8a\xa3\xe7\xbdU\xdd\x9e\ --\xfe8x\xa1;o\xde\xb9\xb0\x8c_\x04\xf2\xf7\x00\xf0\xbc\x12(\xbe7\xfc3\xc2\x92\ --\"0i\x1f\xf7D\xc1\xca\x91\xf5\x11\x94A\xd9\xcc \x04\x03P\x1ekl,\x005U\tm\xc1\ --\x96a<\xa2\xfd\xd6c\x18\x06\xb3_\x04Z\xc1\xa3\xd8e\x90\xc8\xb2\x0c\xef7\xf69\ --V\xd63F\x02\xd4\x14@)\xf1\x8c\xc0\xbaty\xd2\x89\xe6\x85%@\xb1\xc0\xf2\xba\ --\x8d:\xc3<\x1b\x05\xd8\xff\xee\xdc\xa2\xae\xa2\xf5~\xfbt\x07\x1em\xe8IW\x96)\ --\xd3\xed#A\xd1\xc7\xbftw\x16k8\xe5 \x80\xa6\x9a\xae\xeb\xb3\x80\xf3\x80\x00|\ --\xb0\xc8/\xdc\xc6\x81\xa5\xf26\x8e\xb5k7\xd6D\xa8OJh\x82\t\xf0\xa1\xf3\x0cEq\ --\x0b\xa0>)\x00]\x80\x01l\x1ez\xf03\x92\x98N\x05\x0b\xca\xf4<\t\x00$\xc56\xd3\ --\xb8\xf3\xc1\x13\xc8\x03m\xacG\x7fD32.4#\xeb~$\x16\xf6b\xda8\x8bD\x0fG#c}s\ --\x83\xcb\xf5\x07`\x1c\xa2\xbb\xe2\x82\xc4\x081\xafk\xeb\t\xb7 \xe8\x90*\xa3B\ --\x8c<^D\x1e\x01!,\x84\x12\xd2\xf3\xa3\xc4\x8a\xd8\x83\xe3\x10P\x1ad1 \xb8|\ --\x82\xfeB\t\xb1p\xae\xd2#_p8!\xa3\xeb)\xf1\x00\x10\xa1:.@G\x05\x86\x11h\xbf\ --\r\x18\x9e\xad\xf5F\x18\x0b\x8eq\xa8\xc1*ij\xf1\xcc\xf9([\xc4\xdb\xff(\xdf\ --\x90s\x7f\x84\x02(\xa0\xbfS\x12\x19\xe3L\x10\x1a\xf6\x19\x80\x99\xd1,\x16X.\ --\x97R\xd2\x0cX\xbaK\x06\x1b\xe6'%\xfao\x9dO\xcb^\xe0\x04\xb9\xa5\xc7\xf9\xd8\ --\x06\x10c\x14E\xd9\"d\x16\x82\xacf\x13\x0f\x08\x18@\xb9\rS\x14\xce\x08\xc4 ,\ --\x96K\xe0y\xc0\xf6\xcbm`h\xdc\xa1\x80\xa4\x08b\x1e\x00\xa5\x03OQ\xde\xce\xac\ --\xe1=\x83\x83\x85\x1d8\xcaL0)\x98\x0c\x19\x0fp\xe5\xa9(\x7f\xa5'\xb8W\\\x17\ --\xc0\xe7\xe4P\x1a\x9b\xf8\xd5\xc7\x15\x8a\xaaA\x0f\x8d\xe6\xcd\x12\xcb\xb7+\ --\xf8}\x12\xea\xba\x1e\xddc\xef\xafir.k2\nE\x1e \x95\x1f\x0cE>\xf7KC!\x18L\ --\x1a\xd3\xc9%o\x81/\x12\x8c{\xfb\"\"JwV\xc8D\x80\xb4\x02$\n\x1b,\xde\x9e\x03\ --O\x1d\xfao\xdb\xa9\xe4r]\xd1\xf8\x94\xc7\x1a\xa5.\xc0#\xb0m\x07SJ\x8f\xa6\ --\x94\x8db8M\x8fv\x1d\x12\xeb\xf1(\xd6w<\x8e\xec\xcb\xf5XD\x17\xebp\n`+`\x0e\ --\xf0v\x08#\x9b\x12\x00\xc5q\t*4\xba\xae\xdd\t\x82\xa5\xeb@-\xcd\xab\nP\x84\ --\x9b\xfbm\x08\x01\x05\x80)\x08g\x8b\xdd\xc0\x8fQ8\x8fl\r\xc9V\x19\x1c\x9a/\ --\x98\x8cl*B/\xb4ok\x82\x86\x88\xa05\xa1<2\x1bv\xbd\x01\xb5a4\xd6\xe5Q<\xa1Dn\ --M\x15\xe3\x18w\xa1sh\xcf\xef3\x89\xac7l\xc8\xb9\x0e2\xad\x07\xec~\x9a\xcc\ --\xfb\xaem1\x9f7(\x8e4\xd86\\Z\x13\xee\xef7\xe0A\xaa\x8eE\x16P\xc6\x8d4\x18\ --\x9b\xcfk,NJ\xcc\xcb\x12\xf7\xb77`\x1e\x82\x8b{4\x85\x8f\xd1\xe8\x85p\x1e\ --\xf6\x98w\x01\xe0^r\xfd\x82\xb0\xb7\xc5\x1e\xaf|\xb1\x97)\x87\x19\x18\x07l\ --\xbf\xde\xe1|\xd1`Q\x97X\x9eVX5\x15\xf8i\xf0kHR2\xb6\xc9\x95\xb3\x0e-G\xc6\ --\xfc\xb4BY\x15\xe8z\xd3e\xf1\xe8\xf0\x81\xe2\xde=\xac\xe8\x89l\xe5\xd7\xf5\ --\xbdS\xc5\xc1\xc2\x97\x85\x06\xcf4\x18@\xf7\xc8\x18\\\x85hs\xbc\x8c\xeb\xf6a\ --\x83\xe5\x9b\x85\xe1\xfby\x00\x9f\xd6\xd8~^G\xde\x14\xf71\x12\x04}\x1a\t\xd5\ --\x92T\xc0\xf9\x9b\x05@\x1a\x17\xbf^\xa3>\x9bC+\x8a\xfa\xec8\x88\x822\xfd\xb9\ --\xd1l\xd8,\x16\xd0\x04\xdc}ZO\xe5U\xc0\xc5\xe5\x15\xba\xae\xc3\xdd\xada|^\ --\x95\x00i\xdcl\xb6F\xe9Q\x9c\xc3\xf7\x1a\xe0\x01\xed\xd7\r\x96\xef/\xed\xa6C\ --\xc2\x8dP\x16\x91\xed\xbd\xa3\xad\x11\x152\x13\x94\xb5\x8b\xd4'%\xea\xb2\xf0\ --\xe8\xda\x0f\xc00\xc2\xf7\xe7\x94 \xaeT\xccru\x0e~\xdc\xa2ks\xd9\xc0\xec\xdd\ --4s@m\x84\xfa\x000\xa3\x7f\xec@G\xa5\xe7\x9b\x00t\xdf\xb6\x987\r\x8a\x19\xc0\ --\xcf\xc0\xbc\xa9\xb0\xb9e\xb8\xb0\x89h\x04@\x84a\x18\xb28\x14`F\x85\xbdC\xe7\ --d\xdf=3.\x96\x0b\x91W\t\x97\xd7\xbf\xa1>\x9b{\xe5y\xc0\x12!\xe0\xa6:\xba(\ --\xa0\x8b9\xda\xb6\xc54\x14\xac'\xcd\x08\x98i\xac.\xafP\x14\x05\xf8i@\xd7\xf7\ --\xe8\xbeu\xa8H\x9b>\x01\x00\x14c\xf3\xe5\x16\x1f.\xcf\xcd\xb3n\xdc\x95)r\x00\ --\xe0\xf2\xfd56\x0f-\xee\xbe\xdc\xa3\xac\xea\xb8\x96@\n\t\xf6]\xf7\xd8\x85\ --\xb4\xb5c>\xd7\xd4\x15\xcaB\xc7!`\x95\xc6\xb0M \xc7\x1e\x97\xf6\xe2\x92\xaa\ --\xb2ByR\x81\x99\xfd`s\xb3\xd9\xa29\x9b\x9bA\rl^\xe7\x01\x8b\xa6\xc6\xf6\xf6&\ --\xe1)]\xd1\x18\xaa\x9e/\x80\xa3\xca\xb4\xf8\xe3TI*s\x04f\x84\x98]\x8b\x98\ --\x15\x13\xd7\xd5Y\xb3\xa3\xb45\x1b_\x7f\\\xa38\xa9\x8c\xc8D\xc03\xfb\xeaq\ --\xc2\xec\xc8h\xaa\xc20m\x1e\xc0\xfa\xcb=\x86\xbe\xc7\xb2.3\x02\xbe\x00\xa6\ --\x8ap\xf9\xcb{l\xb6\x1d\xee7[TU\x83\x81]\xaa\xdf\xeb\x01\x06\x03\x96oW\xc0\ --\xd0\xa3{\xd8\xe0\x0e\x19\xd0rL\xec\xc9\xed\xd5q\x01\xad\xb5I[6\x0e\xcb\xb2|\ --\xa1\x1e\x08k\x96Ea<\xec\xa5\xb1\xf8\x84Lrl~^\x82\x8a\x0e\xacB\xed\x02 \x93\ --\x06\xc5\x91c\xb6(K\xd0h+\xb8W\x93\x11b\xd9$\x1e\xe2\x059D 3:{}\xed@\xb8\xfa\ --\xf5\x1a\xf7_[\xdc\xfdg\x8b\xaa\xae\xc1\x8c\xcc\x80$<1\xdd\x82\x08\x033\xb4\ --\"\xb4]\xbf\xb3\x84\xddI.L\x9c\xab\xbf\xda\x82\x083\x80W=jc\xfel\x01\x1c\xd7\ --\x00i3j\xf3YM\x80\xbd\xa0P\x1e\xb8,02\xb4&\x03F`4\xcb%\xb4\"\xdc\xado^)\xc4w\ --\x08\x0e\x08\xd0}\xc53\x8a\x0c\xdao[\xdc\x7fmQ\xd5\x8dI\xd1\x92\x0f9k\xcc\ --\x8e\xc4\x1c\x11\xf9\x0f0\x96\xe7\xe7\xa0a\xc0\xed\xc7\x9bx\x81\x7f\x12Y\xd0\ --m\xe6\x0bPY\x03\xb3\xc2N\x861\x1d\x86\xe6\x1e\xcf\x9e\xb5\x8d\x87\xc9\xdf\ --\x05x\xa6\xbf\xdf\x13\xfeV\n1\x7f\xbfiQ\x9d6`X\xd0\x13\xa5r4c\xdc\x89\x01\ --\xb6\x04f\x15\xe6\xb743\x8b\xad..\xc0\x8f=\xee?\xad_\x8f\t\x7f\x1b\x19A\xaa\ --\xb3\x05\xa8j\x00\xa5\xad\xe5\xa3B\x1c\xbb>\x1fp\x14c\x80\xe8\xf4\xfc\x12\n(\ --\xca\x028*\xc0\x9fo1\x7f\xbb\x04!\xa9\x0fr\xab\xbe&\x86\x0f%E\xb8z\x7f\x8d\ --\xfe\xc9\x0cJ\xba\xbe\xc7\xfd\xd7\x16\xf5\xd9\xdc\x16\\\xd3\xb6\xdbf\x7f\xec\ --BT%\xfe\":\x16\x13\x96a\x04\xf4\x0cX^\x9c\x03}\x8f\xfb\xcfw\xa2\xa4\xb4\xc3\ --\x072\xc0\t\xe0\xaf\x17^\x8c\xe7\xeb\x9f\x17\xe8\x9f\xcc\xd4\xb8\x02\x01G\ --\xb6\x80\x8a&K\xf0\x9e\xeaC 2J:\x12\x13\xef\x08\xb6\xb9\xb1\xef\x9d\x17\xf0\ --\xe8&<%\xfa\xf5\x1a\xe5i\x83\xc2\x16:}\xd7\xa1}h_\xd5\xf0\x1e.\xbcy\xd5\xcd\ --\x1c=\x03\xdd\xd3\x80\xe2\xb8\n\xa5\xb1r\x8a\x7fI\t\xa6\x8d&\xb1&\xc6D\x01N\ --\xf8\xc997c\xb3\x0f\x95\xa7\r\xf4Q\x01b\xf6\x1f7\xb7\x0f\xadh\x93\xffzZ\xbd\ --\xbb\xc0\xe6\xa1E\xff\xc4\xa0c\xf8\xaa\x95\xbd\xf7\x05\x85\xd1\x18x\xcd\x91,\ --\x86\x8d\xb8i\xaeL\x1f\x90}\x82\x02\x96\xe7+\xd3\xfe\x8e\x00\x8d\x8c\xeb_\ --\xde\x1b\x8f8\xd2\xd1P\xb2\xef:\xb4\xdbm\xd8\xe9\x90\xd0\xb0{\xd5\xcd\x1cZk0\ --\x08\xddc\x0f\xd2\x05\x96\xab\xc6\x94\xb6V\x04_[\xe6Z\xf1\xc8\xdd3m\xb2=\x9f\ --M\x83\x949N\x1bX\x17&<\x02\xe5i\r:\xd2\xa6\x8br\xb3\x01\x0e\x9e\xf1=\xf5\xfc\ --\xf9\xc5%6\x0f[0\x03\xc5O5\xba\xa7\x01u)\xa69\xa3\x80\xb6\xd4\xf5\x1d\t\x1ew\ --\x01\xe1D\x01\xb9n}\x17\xb12\xee\xb7x\xbb\x8c&6Z\x99\xee\xef\xfa\xea\nU]\x83\ --F\xc6v\xbbg4.\xa8>\x9b\xa3\x7f\x06x\xa6\xb1zw\tV\xc0\xc0\x0c\"\r\x1e\x11\x1a\ --\x1b\x07\xd2;\x94\x10\xd9\xddaZ~ \x12\xd4@\xfek%Se\xa4\xc1\xe1\x15\xa3\xc2\ --\xe8\xdcu}\x03\x1b\xc5T\xa7\x8d\xf9\xa0\xe3y0\nx)\x0c\x14au~\x81\xf6\xb1G\ --\xcf\x8c\xc2\x81\xf0L\x9b\xa6F\xf0*\xdd]\xe2\xd4\xfe0\x9b\x86\xb8\x8a\x16K\ --\x84\xcf?2=/'\xc6\x0c\x80m%\xb9\xf8\xd7\n\x1a+|\xb8\xbe\xb6\xad\xe6n\x7f\xaa\ --\xe7sS\xbf\xcf4\x96\xef\x96\xe6X\nD\x16\xdcr\xad\xed\x98x\xae\x18\xf4\xfa\ --\xb9\xa4o\xd0d%Hy\x0c\xf8\xd3d\x99\x1c\x9e\x07_#\xec\xfd\x0e\x9f\"\xac\xde]`\ --\xfb\xad\xc7\xa0\xc8W\xa3\xfe\xba[3;\xaf\xcc\xacwp\x1d2\x01A\xf6c\xab?\x93\ --\xd0\xc8\x02\xe1\xfa\xf7\x1bp\xdf\x83\x9fz\xf8\x19\x7f\xc2\\\xdd\x04\xcb\xaf\ --\xfe\xbd\xb0(/\xc07\xb9\x7f\x92\xaa\x13\xc5\xbc\x96\xef\xbd\x1e\xb0{\x82\x17\ --(\x9b\\\x9e\x06\x93\t\x86\x01\xb7\xbf\x7f\xf0\xd9!\x15\xc6Y\xbe\xed{\x0c\n`\ --\xdb\x89\xfa\xcf\x1e\x1c\x87I8\xe42\xd3\x84\xdf\x14$\xf7f\x01_\xff\x1f\"r\ --\xb2\xa9c\x8e\xc3\xa6\xb7\xeb5\xfa\xb6\x03\x86!\xc4}R\xa1U\xa7\xb5\xb1\xb6\ --\xd6X\xbd]b\x80\xb0\xac[o\x14\x16Os|.\xf5\x89\xf2=\xca\x16\x8e2\xb3\x86\x00\ --\x17B[\xafR\x832\x16\xd7.\r2\x83\xfb\x1ew770\x1fR \x02\x1dw|qy\x85\xedc\x07\ --\xcc(vi\x85\xe97\xcfv\x08?\x01>W\xb1\xe6\xc2f7\xfb\xdfAv#\x97[\xd7\x9fn\xd1?\ --\xb4\xd0v\xb5\xa171/W\xafO\x1b\xe8\xa2\x04\x03\xe8{\x03v\xe7\x17\x17`\x02\ --\x06\xbb\x8e\xfc04\x12\xc0u\xa7\x19\x8b\xbfT\xf6\x02n\xcd\x03\x07\"\xbbr\xbf\ --|\xdc\x95\xbb<\x18\x0b\x1b\x8b\x7f\x083\xc0\x0cC\xab\x8b\x0b\xdf\xc62\x00:\ --\xd2\xa6\xc8qB\t\xf7\xf5\xfbe*\xbb\x14\xf4r\xe1\x91\xb7\xf8>\x0c\xc8\x94\xaa\ --i\x18D\xe1a7\xb9\xfdt\x8b\xf6a\x0b\xe2\xcc\x88<J_\x84\xb2\xaa0\xafj0\x85\n\ --\x8d\x91X\xdd\t\x9f\x9aE\n\xba\x0b\x0f\x10\xce\xcb\xe7\xe5t\xc8\x9f\xcb\xb09\ --\x152C\x12\x99\t@\xfb\xad\xc5\xdd\xc7\xb5\x00\xba\x04\xf0\xdc\x0e\xca~JD\x88\ --s<v\xb8\xbc\x14bG\x8d?\x1dy\x89\xf3/\xd5\x01S\x10\xdcM9\xc7\x91\rF\xf9S\x8d\ --\xe2\xa8\x80\xc9\xf3\xa6\xff\xee\x1f\xcd|\x00p\xb5=\xa3\x1f\x06\x94\x07\xae\ --\x1f1)\xddzg\xc7\x97P\x922Y\xc1\x18I~}\xcf\xee\xba\x13\x03\xd2\x8e0b\xd2.\ --\xbe|\xb3@{R\x82\xc4\x1d\xcc\x8cv\xb3\xf1\nX\xaeV\x18\x14\xc2\x8f1\x12\xdaY\ --\xb4d\x04\xdc\x95\xff_\xa4\x89\xa2B\xc8\xca\x04\xb5\x97&E\x06\x80\xfa\xacA}\ --\xd6\x84s\xd6RW]\x87\xd2~\x03\x14G\x1a\xcb\xc5\xc2\x0fT\xf2]\xf9\x8e\xfd\x9c\ --{'1\x9ev\x80i\x85\x19U\x91R\xf8\x11\xe1\xc7\x13\xb1({\x84\xddG\x12\xb1\x05\ --\xc3\xf37\x0b\xd4?U\x80\"\x14e\t\xd0\xfe\xcc\xb2\xd7\xb2\xa9\xdb[A^[\xf3\xbb\ --\xcf\x08(y\xe6/k\x86$@\xce\xe7s\xb7\xed\xd4\x8a\xaf\xa5\x9c\x909\xe1sY\xc2\ --\xf1\xe0\xd2\xf3\xc8\xe1'5\x96\xa2\xaf\xcaJ\"\x1c\xee\t\x93\xfb\x94pQ \xfe\ --\xf1\xc2\x9e\xe7\xb2\xf7\xecS\x9c\xab\x1f2\xcf\xf2\x18\x9f\x0f\x8a\xf0\xef\ --\x00\xa4\xdf\x15VS\xc1_\x9a\x0b\xece.\xa1?\xa3\x04\xaf\x88\\\x89\x0c!\x92\ --\x152\xfa\xa1\xc5\xe4\xb5\x97\xcd<\xfd=\xb3\xde\xc3\xf79tL\xe7\xefq\xd6v/7\ --\xc1\xe68\x0cv\x86\x80$J^\xc0wx\xc4\x01\xf4\xa2`\xa9\x17\xe4\xcc'2M\x98\x1a\ --\xdb\xba\x93\xed\x97\xb1\xc5\xf7\x16\xe3%\xf64$\x92\xf6)\xe1\xc5>b\xc7\xbd\ --\xb9\nt\xf2\xdc\x0e$\x87\xbd\x06\xd8Y\xc2\xe8\xfe[\x81y0]*\xdb\xf6<\x17\x02\ --\x04\x98\x8bD\xfb\x81\xe7\x05\xca\x16MJV\x8f,\xee\xa5Xa\xae\xc9r\xe7<\xaa\ --\x87\xbb\\\x1e\x8f]\xdc\n5\x12\x88\xad\xc5\xd9\xca3Z\x05<\xbb\xff\xbd\xf5\ --\x02\x00\x8a\xa0\xdc\xa6\xf7_\xee\xf3S\x9b\x94\xe4\x0f\x14\xf7*\xca~\xc15\ --\xfa^o\xac\x00g\xf3W\xe1\x8bS\x90\x1fn8\x8bR\xb8\xe6\x940\"\x08\xcb\x83\xc7\ --\x00\xf7\xb3Y\x80\xeco\x87\xd3\xae\xea\x1fM\x07\xa2O\xfa\xb1x\xa4|\xf2\x9e\ --\xf5\x03)\xfcq\xd8L\xfd\x7f\x93\xfe\x0b\x0bS\xa9=J\x9e\xec\xb4\x00\x00\x00\ --\x00IEND\xaeB`\x82\x88\x05\xbc\xdc" ) -+\x08d\x88\x00\x00\x1c5IDATx\x9c\x8d\x9b{\xb0eWq\xde\x7f\xddk\xed}\xce\xbds\ -+\x19\x8d\x06i\xf4FHHc!L$!!\x10\x8c\x80\xf0\xb0\x11\xc2\x10 @\x01\x81\xaa\x84\ -+\x10\xe1\x98r\xe2\x84\xbc\\\xce\xcb\t\x15\xdb\xa9\xa4*\xe5J\x95S\x15\x13cl\ -+\x10\x81\x80A`W\xe2` \x01\x02\xc2\x06$\x01\x12`$\xac\x91\xd0\xa0\xe70\x8f{\ -+\xcf9{\xad\xee\xfc\xd1k\x9fs\xeeHJ\xe5TM\xdd9\xaf}\xd6\xea\xd5\xfd\xf5\xd7_\ -+\xf7\x16\xd1\xde\xdd\x1d0\x00\xd4\xe3/(\x00.\xbb\x9f#\t\xb7\xf15@|\xd7\xfb"\ -+\x82\xbb\xa3\xaa`\x8e\x8a\xe3\xee\x98+(\xa8\x03\x18Fm\xdf\xef\xda\xef\xc6Ss_\ -+]Z\x04#\x9e\'Q\xdc\x1d\x97\xdd?km\xbd\x82\xb4\xbf\x86\x88\xb4\xb5\x13\xdfq_\ -+\xaeO\xb5]\xd7\n"\x82 \x9d\xa7\x94p\x15\xac\xb6E\xb9\xc4?i\xdfp\x07I\xab\xbf\ -+\xb2\\!\x8c\xc6X\xael|\x13p\xc0k\xbc\xa6)>+\xb4\xeb\xb4\x1dH\x18\x8a\xe5\xbe\ -+%\xdesY3\xee\xdac\xd7\xf5}\xb5>\x80Zv\xbf?\x1e\x9e\x08X\\O\xbc\x02NR\xa8u \ -+\xabBu\xe3\xcc3\xce\xe5\x8c\xb3\xcf\x01\xc9x\xca\xf4\xfd\x144\x93\xbb\x1eI\ -+\x8aHBU\xc9\xa9\x8fk\x89 \x92\xc0\x15\x10T\xb5\xbd\xb6Z\x80\xcb\xe8W\x8f\x7f\ -+4\xffZ\xee\xb1\xf9\x17\x86`V\x11\x0b\xdb\xb8\xd7\xb6W_z\x965\xa3\xc7k\xab\ -+\xf7q\xc7\xcc\xf0Z\x96\x06\x18\xea0^\x18\xa9\x95l\x0b\x1e\xb8\xef/8r\xdf\x0f\ -+I\x92\xc9\xa3\x85\xf6\x1f8\x87K/\xbf\x92\x8d\xbd\xfb\xd0~\x83~\xbaE\xea{\xba\ -+n\x82\xe6\x9e\xdcMH)\x93s\xc656\x9c\xb4C\xb5\x07I$QP\tW];DS\x01)$\x0f\xd7\ -+\xac\x06\xae\x89d\xb1h\x19W7\x9adt\xd9j\xb8\xd7xN\xc5\xab\xc5\xeb\x1a!\xe6\ -+\xd503\xccJ\x84\x98\x19\xe2F\xad5\xbeg\xf1\xfdZ\x07j\xadX\xa9P\n]\xd9\xe6\ -+\xd6/}\x8e\x1f\xdd\xf7C\xc0\xc9n\x05IS\x10ec\xebt\x98\xec%\xedy\n\xf4\x1b0\ -+\x99bi\x82\xe4\t\x9ezjN\x90\x12\x92\x144\xe3\x9aI)\xe3\x92"\xc6\x93\xe2\xa2\ -+\x98DLW*\xd5\x0b\xd3\x0e\x18NP\xcd\xb0\xe9\x16\x95\x0c\x08\xc3PH\xa2\xcbS\ -+\x1d7\x02\xe0\xc9\x81\xf1T\x0b\x96l\x97\x81Lc\xe3b\xed\xd4\xad\xc4\xff\xd50\ -+\xaf\xcd@\x85*s\\\x8c*\x15\x95\x05&\x02\xfd&\xe6\x82J\n\x0fp34O\xc9\x1b[\xb0\ -+\xb9\x85L\xb7\xd0~\x83\xd4OIy\x82\xa6\t\x9a;\x92v\x90@R\x86\xd4\x81$LS\x03\ -+\xab\x08\x81"\xab3\x85J/\xca\xe6D8\xf4\x82+\x10\x81\x87v\xe0\x9b\xdf\xf9s\ -+\xe6\xdb;\xa4\xae\x03M,\x06\xc3TI)QJ\x18B\xbd\xb9\xbf{\x18X\xac\x81W3\x94t\ -+\x888\xb5\x94p7\xedp\xa0\x96\x05f\x05\xb0\xf0>\x03\x93\x8a{\xc12\xb8/"\xb6$\ -+\xe1^G\xe8\x86n\xd2\xb3\xb1\xf5\x14\xba\xc9&\xfdt\x0f\xb9\x9f\xd2\xf7\x13r\ -+\xee\xe9R\xa6\xeb:r\xa7\xe4\xdc\x93s&\xa5D\xce\x19UE5\x93\x92\xa0\n\xa9SR\ -+\xa7\xe4\xacL\x922\xa1\xf2\xe9\x0f\x7f\x80C\xcf8\x8f\x17\x1e\xbc\x90;\xff\ -+\xf4\xff\x90\xebIzf\xf4y iE\xb4\x92\xb3bT4\x0b\xa9S$\xcb\xf2\xfa\xf1\x9b}\ -+\xfb\x9d\xf8\xdd>e\x12\x89\xac\x89\x94\xc2x\xaaJ\xa7\x89>erJt)\x91\x05\xb2\ -+\x80v\xf1]m!\x1c\x00id\x91\x84\xa3h\x9e\xd0\xf5\x1b\xe8d\x0b\xe97\xc8\xa9\ -+\xa7\xeb\xa7\xa8d4gr\xea\x91\x9c\x10I\x88*\x92;\x10\xc5]@\x12"\x0ebaQ\x89x\ -+\xec)lf\xb8\xe8\xbc3\xf8b\x9dA\xa9\\\xfdS\x17\xb0\xef\xecs\x01\xa1"<\xba\x03\ -+w\xfe\xf9a\x1e=~\x92\xac\x1dq\xe8\x8e\x88\xb6\x13\x1a\xcf\xc8\xc0\x1d%^7\x94\ -+$\x15\x17\xc7]\x1a\x068\x96\x13R\x03Y\xdd\x1cK\x19\x11%\x9b\xe0n(\xdd.0\xce\ -+\x8e\x02J\xdfM\xe9\xbbMJ\xb7A\x9an!\x9a\xd1.,\x8f\n\xa2\x1d\xa4LJ]\x80\\R\ -+\x0c\x05\xcfa\x14q\x94\x82\xc8@\xaf\xe0eF/\x03b\x03]\xaaa\xf1a\x87\x9f\xb9\ -+\xea\xd2\xa5\x0b\x927\xf8\xcd\x8f\xff!\x8b\xda\xd3\xf5\x13\x165\x914\x91$S\ -+\xeb\x80\xa18c\x1e\x97\x95A\\P\x0c\x17AE0\x8f\x9c\x8e\x19B\xc6\x04\xa8\x86\ -+\x8a\x90\x89\x10(^Q\xed\xf0\xe2\xa4\xd4R\xba;\xd9q\x10%\xe5)\xddd\x82N\xf7 \ -+\xdd\x14I\x1d\xb9\x1f\xe3>\xdc\x07\tw\x17U*N\x92\x84\x93\x97\xa9OD\xe8\xc5\ -+\xd8;Q~\xfa\x92g\xb2\x7f\x8f`\xb3\x19<z/P\xc9\xaa\xb8-\xe2dD\x01\xe3\x8ag\ -+\x9c\x87\x9ev\x16\'U\xf8\xfa\x1d\xf7\xb1s\xa2Rk\x05M\x08\t\xc7\x10\xaf\x88@\ -+\xb21\xbd8BA\xdc\xc3\x085\xbc\xce\xb4\x91\x1b\x03<(\x94\xb8#.\x88\n\xeau\x95\ -+\xbaM\x10\x87\x8cy0\xb4\x9c\xe866\xa1\x9f\x9266\xc1\x15\xcd=\x9a\x12\x82\x92\ -+r\x86\xc6\x05L\x94,\x12\x0bt\x07M\xb8(\x99\x84\x96m>\xfa\xbb\xff\x85\xf7|\ -+\xf8?A\xddn\x0b\xb6`\x98*\xd8\xda&\xa8s^t\xc5\xe50\xd9\xe2?~\xe4\x93t\xb2IM\ -+\x99\x99)\x9e\xa6\x98\x0bNA\x97\'\xee\x88\x1b\x8e\xb7\xac\xd9\x00\x11k\xfc)\ -+\xa1\x1e\xd9\xc3\x1d\xbcy(h\\\xc3+)\xf5\xbb\xb8\xca\x92\x07\xc4\x89o\xc2t\ -+\x13\xf24\xf2|\xee\x10\x11R\xea\xd0\x94p\x8d\r\xab\xa4]\xa4\xc75\xe1\x92\x11\ -+[0I\x13l1\x83:\x90l\x1e\xf1j\x86\xa4\x0e\xf3\x95;+\x8e`\xd8\xe2$\x8e\xf1\xcc\ -+\xf3\xcf`\xe3\xc0\x05\x1c]\xc0]w?\xca#\xc7\x16\xb8$\x12\x82S\x83\xe2z\x05\ -+\x14\xb1\x16\xe3.@E4\x07F\x188\x8e\xaac\x8da\x84\x07\rA\xcd=\xf8\xcb.\x0c\ -+\x08\xca\xeeHJ\xf4\xd3=X\xb7\x81\xa7\x9e\xd4\x90\x9e\xd4\xe2U\x83\r&m1\x06K#\ -+8B\x15E\xb4C<\xb33T\x0e\xfd\xcc+9\xb0\x01\x9f\xfc\xf8Gb\xf1\x18"\xe0"\r\xccF\ -+\xde>P\x17\xf0\xd2\xe7<\x1b\xfa\xbd\xfc\xd6\xa7?K\xf1M&\x93)en\xa8\x06\x0e\ -+\x18 &\xe0\x15\xd7\xd8\xbc\x8b4\x10nP\xa9}\x10!@)\xabt\x9c\xba\x16r\x05\xed{\ -+R?\x01\x14G\xc9>\xf2h\xed\xd1\xae\'M6\xb04%w\xe1\xee.\xa0\x12q\x1e\x1e hj\ -+\xc8\x9c\xb4\xf1{A\xd1@az^\xf1s\xaf\xa7?\xf9\x10\xb7~\xf6\xd3T2]\x97\xa8\xa5\ -+\x84A\xdb\xb2\x02\xe5\xc3\x88J\x05\n\xd5f\xd8p\x02\xc9\x19qe\xd2ux\x01!\x83\ -+\x18\x9e\xea\x12\xdc\xdc#\x03U\x1a\xd5\xf7\x8a:\x88\x18hnL\xb44o\x08L\x90\ -+\xa4\x8c5X\xd4$c\x08\xb8\xa0\xa9\xa3\xeb7\xa9\xdd\x06E{\xc8\x82\x8a\xe2\x1a\ -+\x9c_P4\xe9\x92\x8e\xaaj\x10X\x8d\xf3U\x0fD\x9e-\x943/\xbc\x8c\r\x9e\xc1\xc3\ -+\x7f\xfc9^x\xc3\x1b9\xb0\xa5|\xf2\xa3\x1ff\x18\xe6A\x95\x11\x8a\x83#\xdc\x7f\ -+\xef\x8f\x10I\x9c\x7f\xfe\x05\x90*[\xd3\xcc\xbc\xcc\x10\x87N\x14\xeb:\xaa\ -+\xb5\x90\x17Z|;0\xba}Pci\xfc;a-%*\xae\t+\xdej\xba\x84x\x0e\x10\x97\xd4<`\x89\ -+\x01\tI\t\xed{\xb4\xcbt\xb9\xa3O\xb5\x15V\x82\x01)g\x0c\x1f\x13S\xb8\xb2@m\ -+\xa0\xa3"\xb8@\x9eLq&\x14*\xafz\xd3;\xa9\x8f\xdc\xcd\x03\xdf\xfd:fN\x972\xd5\ -+\xdbU\xdc\x11\x12\xaa\x99Zk\x18\xb2\xcc\xb8\xf8\x9c3\xb8t\xdf\xd9\x1c3\xe1\ -+\xb6;\x1fb6\x08\x1a\xdb\x02\xab \xb5\x85]\x84\x81\xea\x8a\x17`58\n\x16\x86\ -+\xaa@\x1aq\xa1\x15\xcc\xd5\x97!\x1c<\xc0\xc3\x17\xba\xc9F\xd0C1\xba\xce\x98\ -+\xb0\x00\xa0JO\xee2\x95\x8a\xb8\x93d,r\xa04\xde\x1eu\xb5\x839\xf1?an\xc2\x19\ -+\xe7_\xc8\xd69\xa7s\xf8\x07w\xa2\xfd\x04\x1f\xb6\x11I\x98[\x03#\xe7\xdcs\xcf\ -+\xa6!\x1a"\x89C\x97\x1d\x84\xbc\xc9\x07\xfe\xd77I\xa9#\x990 P\x05\xd5\x0c\ -+\x94(\x8e<\xe1\x1eP\xa7I\xc3\xfb\xca\tzUT\xa0\xda\x02W\xa3\x96J\xea\x14\x17\ -+\xa7\xeeT\xfa\x14\x94=N7\x11\xc1"\x16\x1b\xef\x954\xc9\xec;m\xca\x85\x07\xf6\ -+\xd0\'\xb8\xe7\xc8\x9c\x93\x8b\xc2\xf1\xc1\x99L\xa6X-8\xc2\xc0\x10\xcc\xd0\ -+\xad\xc5^\xc4\xb7\x12Y\xce\x10\x9c\x84iO\xea7\xc2\x15\xd7\x04\x8d\xd8se\xbd\ -+\x10\xc6A\xeb\x02\xcb\x13(\x0b\xba\xdc\xb33\x14T\x13\xf4\x1dX\xa5:\x88dp%\ -+\x89cu\x1e8\xe4\xce\x9eiB\xca\x8c{\xbe\xf7m^\xf1\x92\x17p\xe0\x8c}\xcc\x87\ -+\xca\x02a\xcf\xde\xd3\xf8\xd2\xff\xfe\n\xf3\xc7\x16ki\xb0\xa2!\xc5T\x92V\xfa\ -+\\\xd9\x90\x1d\xbe\xf0\x99\x8f\xf2\xd2K\x9e\xce\xa1\xa7\x9f\xcf\xe7?\xf5\xfb\ -+\xd4\x93\x0f\xb2\xd9y\xe4\xe4,\x90\x84\x9c\x95\xac\xce4+\x93,tbt\xc9\xc9\x1a\ -+5ANNNB\x02\xe6e\x0e\xda\xd2\x92\xfb\xda\xdf CQ\xf6J\xab\xf2F{,H\x0c\xe4T\xa9\ -+\xb6\x13\xe9,e\xa4\xeb\xf1\x94\x91\x14uB\x12\x98d\xa7\xf7\x19]9A_~\xc2\x9d_\ -+\xfb\x1co{\xc5\x0bx\xc5\xb3/\xe2\xd5\xd7\\\xc6\xeb\x9fw\x05;\x8f\x1d\r\xedA3\ -+H^\xe2`\xa6\x01\x82\xa83I\x80T\xb6z\x83\xc51\xf0\x05/\xbe\xea \x97^\xf64\xbe\ -+\xff\xe3\x13\xecx\r@RA%G\xbaq\x0f\x12\xd22\x03\xde\xe4)\x07\xb5P\x82\xee{\ -+\xe0\xc1V>\'\xbc\xa9NK!M\xc3\x95c\x1d\x8d 1p\xf19\xfb){\xf6\xb3\x93\x84\x1f\ -+\x1c\xde\xe1\'\xc7\x8cRJ\x93\xda\n*\x86H\xa1\xeb\x8c\xef\xdd\xf1\r^\xfb\xaa\ -+\x97\xb3\x99\xa1l?\xca\xb1\xe7>\x9b\xaf\xde\xf2!\xa8\x0br\xd7Q\x86\x05}j^\ -+\xa6i\x95\x8aE\xc8R3\xaeJ\'\x13:M\xb8:S\x11(\x0b\xa83\xde\xf1\xda\x1b\xa0\ -+\xdf\xe2=\xff\xea\xdf\xf3\x9cC/a:\x992\x90\xa8\x02\x05eh\x8e?n\xc8\xd3\xa8\ -+\xef)CM\xa8w\xccS\xc7\xa1W\xbe\x9a\xfd\xbdq\xcb\xc7n\x0e\x99\x0cm\x08%\x90\ -+\x13\xbf\xf0w\xdf\xcb\xbd\xf7\xfe\x90[>\xfe\x11(\xdb\\\x7f\xd9\xd3`\xb2\x8f\ -+\x0f}\xe5v\x86\x85\xd0\xe7\tY2\xb5l\x93\xb5\xe0\xc3\x9cir\x98\x1f\xe7\xbb\ -+\x7f\xf6\x05~\xee\x9f\xff"P`q\x12l\x0e>\xb4\xfa\x80\x90\xc3\xac2\x99LX\xec\ -+\xcc"\\\xc5I\xee\x8d\x07\x88D\xba\xcb\t\x15\x0f|\xf0`_J\xc1|\xc6s\x0e\x9e\ -+\xcf\x95\x17\x9d\x83\'\xd8\xa9p\xe4\xd8\xc0\xf1\xc1\x98W0\ti\xca\x9b j#Kt\ -+\xa7v\x997\xbc\xf5\x1d\x9c<|\'\x0f\xdc\xf5\x8dP\x8f\xdc0\x04\x11G4\xe1\xaa\\\ -+\xfb\xc2\xeb\xf1\xc9\x14\xb4oZ`\x82a\xce\x8f\xef?\xcc\xf4\xa9\x17\xb23/\xa8C\ -+\xaf\x85{\xbe\xf7-^z\xdd5\xec\xdf\x9c0lOx\xf8\xb9\xcf\xe2\x8b\x7f\xf0A\xb2-\ -+\x18\xeaN\xabL=\xd2mu\x98n\xf2\xe8\xb1\xe3\x14\xf3F\xdeB\xae\xaaQ\xc9\x0c\ -+\xa1\xccjEz\xa5za\xde\\\x05\x04\xac\xe0;\xdb\xfc\x8d\xd7\xbd*\xaa\xb8\x94!o\ -+\xf0K\xbf\xf6\x1f\xb8\xf2\xd0\x8b\xd8\xc8\x93\xd0\x08U\xa8.T\x82\x88\x98+U\ -+\x9d\xe2\xca\xbes\xce\xe7\xe9\x07\xf6s\xcf]\xdf\nq\x83\x01\xc5\x82g`@&o\xec\ -+\xc57\xf7\xf1\xd6_\xfcG\x9c\x7f\xee9\x1c{\xe41~x\xe4!\xee\xbe\xfbn\x9e1\xddG\ -+\xaf[\x889\x89\x19\xb7\xfe\xc9\xa7\xf8\xcd\xbf\xf7\x0e\xa8\x0b\xb0\x01\xca\ -+\x9c\xbeK\xd42oi\xba\xd1d\xc9\xfc\xd2\xbfx\x1f_\xb9\xfd\xfb\xfc\xd1\xff\xfc<\ -+\x17\x1f|\x16IWY\xc0L\xc8\xd2@\x88$h\xaf\x88w\xfc\xf0\xf0a\xe8&\xf8|F\xad5\ -+\xd8\xd5\xd0h\xa9%lXp\xe8\xca\xcb\xb8\xe0\xec\xfdx\n\xb6X\x89\x1a~aNu\xe1\ -+\xf8\xdc96+l\xcf\r\xab%\xa44\xed\x97\xa8?\xaa\x80\xda\xf2\xfb\xc1g\\\xcc\xc5\ -+\x07\x0frbg{\xa9\n}\xf9\xab\xb7r\xdd\xf5\x87\xd8\xd8:\r\xa5\xc7\x86\x81a\x06\ -+\xafx\xfe\x15|\xf5\x0f~\x07\xca,6\xec\x05/\x89$Nq\xc3=\x81v\x90\xa6\\\xf3\ -+\xa2\x9f\x85\xfd\x97 \x1b\xfb\xa8%0K[\xda\x05!+\x89\xaa\xda\xea\xfb\xa8\xa0\ -+\xb6\x17\x95\xeb~\xf6F\xce\xd8\x14n\xb9\xf9\xf7q\xab\x88h\x94\xa9\xb5\x82(o8\ -+tMx\xc4(K\xb7\xaa\x90\xd4C\xbf\xc1\xbf\xfb\xe0G8\xe7\xe2\x9fb\xaa\xcad\xa2\ -+\xb0=c\xdawk\x12y\xa5\x985R\xe5<\xf7\xe0\x05\xb1\xe8\xbe\x03\xcd|\xe2\x8f\ -+\xbf\xc0\xd1\x07\x8fp\xe3U\x07#\xcd-\xd3C\x8dS\xa7\x82\x1b\x16b\x1cV\x0b*\ -+\x8aj\x8fi\xcf{\xff\xd9\xaf\xf2\xe5\xdb\xbe\xc7\xe7\xbfr\x07\xcf\xb8\xfc9\ -+\x9c\xd8\x19\x10w\xb2\x97U\x1e\xc6\xc9\xea\xc1\xe6D\x04\xcd\t\xb4\xe75\x7f\ -+\xf5\x8d\xd8c\x0fp\xf8\xdb\x7f\x06\xfe\xa1\x06\xd9\xb5\xd5p\x04#k\xa4Z\xc4\ -+\x97\xa9M4#^1\x81\xcb\xcf;\xc0\xbe\xfd[\xe8tB\xad\x05&\xce\xc1\x8b.\x00+AU\ -+\x1bl:4P\xf40\xeeP!u<\xed\xec38\xff\xc0>\x18v\xc0\xd6\x17=>\xc6\x86\xc8\xb8\ -+\x95Dq\xc5\xb5\x03\x9d\xf0\xfc\x97\xbd\x9a\xee\xec\xbb)\xdd\x16\x8b*T2\xca\ -+\xb0\xab\x14\x06\xc8u\\\x88\x80\xf4\x99Y\x85\xb3\x9f~1\x93s\x0fp\xff=\xdfo\ -+\x95V\xe3\xdb\xb4Z\x1c]6 \\|\xacFp\x8b4\xa5u\xc6\r/xn\x9c(5@\xad\x14\x04o\ -+\x9d\'_.}\x14\xc6\x85(\xaa\x12\x15s\xb8\xfa\xb2\x8b\x90\x94\xda\xe6\x9f\xac\ -+\xbb\xd0\x96\xd1\xb2\x8eK\xc7/\xff\xeb\x7f\xcb\x17\xfe\xf4[\xfc\x8f/~\x9dg^y\ -+-\'v\x06\x06\'$\xbc\xea\xc1%\x96F\x10\xb2\x8f\x05\x86:\xa2J\xee&\x9c\x98\xef\ -+\x90\xba\t\xdf;\xfc#\xd0\x1e\xb3X\xb8*`\xe1v\xd2\xc8\x84\xefZ\x8cPm@\xcc\x10\ -+5\xd4\x07j\x1d\xc0*\xba\xd4\x0f\xea\xf2;\xc6\xa8\xfd5\x0frPq\xea\xb0 \xa5\ -+\x0e+\xc3\xffs\xf3\xe3\xc9\x19)\x80\xbc\xdb\xe2\x8aC\xaf \x9f\xf7l|z\x1a\'\ -+\x87\x84e\x8d\x8d\xe3\x88\xc9\xe3\x9a7\xd9\x9b\x19sV\xa4\x83R\xe6\xec\xd9\ -+\xbb\xc9b>\xe3\x98\x19\xd7\xbd\xf6u\x1c\xe8\x13\xb7|\xe4\xc3\xe0\x05Qo\x82NK\ -+)>\xba \xcbM\xb8\x170\xa3JS_\xdd\xb1V\xfa\xc6\xf7\xc2\xfa\xac\xbd6\xfaD)5*\ -+\xd52\x9cb\xde\'y\xa4\x1e\xa4\xe3\x1f\xfe\xeao\xf0\xa5o\xdc\xc5\xe7\xbe\xf6\ -+\x1d.\xbb\xea:N.\xa0 q\x1d\xb5\xd6\xa2\x0b\xba>\xf6\x1e\x04o\xd5 \x84\xa2\ -+\xab\x90\xa7\x99\x1d\xafL6z\xde\xf8\xd7\xdf\x81>\xfa\x08\xb7\xfc\xde\x07\xb0\ -+\xd4\xa3\xaeX\x99ASs \xedZ\xcbR[h\xe7\xbbd\x85k\x16\x17\x91\x08\x1b@e\xd5\ -+\xe6\x8aox\x93\xbf\xa2\x056\x82\xe4\x93?2\xa6}\xa0\xfdK^\xc9\xf4\xc2+\x91=gR\ -+t\x13K\x86\xd7\x1amN-\x01\xfaM\xba\xdbu\x05!\xe28\xe1\x01h\xe2\xf4\xd3L-\x85\ -+\xd3\xcf9\x8b\x8d\xb3\xceb\xd8:\x9d\x17\xff\x95\xd7\xb1/+\x9f\xbc\xf9\x83(\ -+\xad\x15E]\xb9\xefZG\xb6\tr\xcd(c\x8c7yJ\x04\x19y\xff\xae\xcd\x8d\xddh\xc1\ -+\xdc\xb0S=\x7f\x85v\xab\xcfk\xe6\x1f\xbf\xef\xd7\xf9\xfc\xadw\xf0\'_\xbd\x9d\ -+\x9f\xbe\xe6zvj\xc7\xbc\xc6BD$\x14\xad\x1a\r]m\x9a\xa6\xaa6\xb2e\xeb\x1e\x10\ -+\xa5\xaev\xca\xdc\x0bY\x9d\xb4\xb5A\x99\x1boy\xf7M\xcc\xee\xbf\x9f\xff\xfe\ -+\xb1\x9bA;\xcc\x86\xd5\x82\xc6\xb557\xa6\x91\x8c\xb0\x83\xaf\x14\xe3\x06T\ -+\xa33\xe8\x08\xa9\xbeB\x04\x9aN\xe0\xcd\\"\xa0\xdeZ\xe4\xaeMN\x17F\x06\x81\ -+\xf6\\q\xe8\xe5\x9cv\xf0\xf9\xd4\xbc\x97\x85\xf4\xd4<\xc1k4=\x92I\xab]<\x0c\ -+\xaa\xf2\xf8,\x10\x174\xfa\x9c\xc8\x1dH\xe7\xa1\x04\xd7Juc\xc8\xc6\xfe\xa7\ -+\x9fGw\xd6\x99\xcc?\xfdI\xfe\xf2\x9b\xde\xcc\xa6W>\xf3_oF\xcdB.l\xe5pu\x8f\ -+\xbe\xbf\n^\xdb&}w\xf13b\xdax\xc0\xd2\xf4\x85\xf8\x90\xed\n\x177GEI\x08&\x19\ -+\xd7\x9e\x7f\xf2/\xdf\xc7\x03\x0f\x1f\xa5\x98\xf3\x83\x1f=\xc4g\xbf\xf6\x1d\ -+\xae>\xf42N\xee\x00i\x03\x8a\xa3\x9a1\x1bB\xfd\xf6&\xda\xaa\xa3>R/m\x0b\xd0U\ -+- \xea\xa8\x1a\xa4\x06\\*Ts\xf2\xa4\xe7\xc4|\xc1\xd6F\xcf\x9bn\xfa[,\x8e\x1c\ -+\xe1K\x7f\xf4\x99@\xdd\x14r\xe5`\x03{\xfa\x0e_,\xb0&Q\x05\xc0\xad\xf5\xee\ -+\x9f\xe4\xb1\xae\x0f,G\x03X\x85\x10\x12}\xcbj\n\xa9\xe7\xda\x97\xdf\xc0\x91G\ -+Op\xf4\xd86\x97\xe8\x84\xfe\xf4\xb3\x18t\x8at0T\tbf\x86H\xc2\xbd,\x1b\xaf\ -+\xaaM\x0f\x1c\xb3\x80*bBn]\x84(LD\xc8\x02\x9e\x13\xc9\x01\x0b\xcd]7:f\xd59\ -+\xfd\xc2\xf3\xd9:\xef\x1cn\xbe\xf9f.y\xde\x0b8w\xdf>&\x9d\xf0\xe3\xc3\xf7r\ -+\xd7mw\x90$\xe32,\xf7,\xed\xa4\xd7M\xf08s\x9c\x12\xeb\xd2\xdcBF\xe3\xa4DI\ -+\x89k\x0e\xbd\x84\x87\xe6\xc6\x0f\x1e\xfe\tg^p)\xe9\\\x98\x17\xc5\xd3\x84\ -+\xc5P\x10\x9d\x84\xa7X\xeb\x07@\xeb"\xb5F\xab\x06\xb0\xa6\x94B\x9b\x88$\xb4\ -+\xc2\x00q\xd0\x14\x9e0>\x17\x15\x14\x18\x86\x01\xed{\x8a\xc2L\x13\x97>\xefy<\ -+\xf5\x8c3\xe9\x86\x81a~\x12\x9fL\xb8\xfd\xf6o\xa3\xee\xb8\xe4\xa6\xe3\x8f\ -+\xa7\xf9\xff\xf7\xd0uPA\x97\xba~\xf5\x04$\xde\xf2\xae\x9f\xe7\xcb\xb7\xdd\ -+\xc9}\x8f\x9ed\xcf\xd3:j\xce\xd4\xa4\xd4\x02\xfd\xa4g>\xb3\xc88J\x13H\x05\ -+\x13%\x99c\xb2\x1b\xa8\xc7\xde\x80\xbb\xb7\xceP\x1bY\xc9\x9aPZ\xcb(\x8c\x84\ -+\xb8\xd3\xe5L\x01\xaa\xc0Nrn|\xfb[\x98\x9a\x93k\xa5/\x85_\xff\x95_\xe1\xa2\ -+\xab\x9f\xcb\x05g\x9d\x85&Gj\xa1\x138r\xf8>\xee\xf8\xc6\xd7[\x89-m\xa0\xe1Tx\ -+o\xd5Y\x9b\xf5I]\xcf\xe0p\xed\x0b_\xcc\xe6\xde}\x98&\xee\xbe\xef\x08\xfdi\ -+\x07x\xfd\xdb\xaecG\xa6,\xb4\xa3z\xe8\xfaH\xb0gM\x81\x19\xe2\x82&\xa8M0\x15\ -+\x0b\xc3\xacf\x85\x9a!Z\xaf#\x8f\n\xeb\xfaI\xa4V/\x8bG\xb7\xd7%ZSh\xa0\xf4\ -+\x1c\xa7\x08\xf4\x08\'\x87\xcaEW_\xcd\xc6\xe9O\xc5\xe7\xf3\xa8\x87\xdc\xe0\ -+\xe4\x1c\xcf\x13n\xbf\xfdv\xbc.H)=\xc1\xe6W\x8f\x18h\x12\xcc\x01\xedx\xfb\ -+\xbb\xdf\xc3Wo\xfb\x16\xdb\x8b\x81\x03\xcf\xba\x86\xbb\x1fz\x94\xa7\\\xf4,\ -+\xaa\xf4K\x10\x13$0S\xc0DZ\x8d\xe5\xab\xd4\xbb\xd4%\xd6\xfe\x7f\xca#\x8b\x04\ -+\x90\xa9\xb70\xa0\xa5,\tD\xae\x8d\xb9\xe9X\n\tm\xea\xcb\x18TH\x1bS^\xfe\xc6\ -+\xd71\xd1\x1c1o\x85\xcd\xdc#\xc7v\xf8\x8d_\xfee.\xbf\xf2*\xfa\xb2\xe0\xf6\ -+\xdb\xbe\xf1\xe4\x9bo\xa5)\x9a\xb8\xea\xd0\x8bxd{`\xbe\xb1\x977\xdd\xf4\x1e\ -+\x16\x9286\x9b\xa3\xd3\xa70/F\xf5\xc0\x07\x15\x02\xe2\x8d\x18\xd9\x11p\x13L\ -+\xc2\xe5G\x86i\xeaM\x16\xd7\'6@3U;\xfd\xc8\x9f"\xdazwP\xdcP\x8f\xd9\x9f4N\ -+\x7f\x88 I\x969\xbb\x92q\x11\x8a\x19\xdau\xcc\x87\xc2\x9e\x8d)\x07\xaf\xbe\ -+\x86\xad\xe9\x04\x8e?\xc67o\xbf\x8dIN\xcc\xe7\xf3\'\xb6B+\xa5\xdf\xfc\xce\ -+\x9b\xb8\xeb\xde\x1f\xf3\xd0\xa2rN\xea\x98\x9b\xc3\xde}\xcc\xe6\x95\x9a\xa2\ -+\xb3\xeb\xce\x8a\x8cIp\x0b\x1b\xe7r\xdc\x11\x8f\xd0\xf0\xa5w\x87\xf8\xbaR\ -+\xa0Y\xf2\x98\x1c}\x8d\xe0\xf7"\x12\xdd\x18\x844r\xf6S\xe4\xee\x98\xd4\x92\ -+\xa5\xf4\xadX\x80\xa7+\x9a\x95\xc1\r\xeb\x82\x8d\xbd\xeamoe\x1f\xceo\xfd\xda\ -+\xbf\x81\xaeg\xb1X\xc4\xc4\x99[45\x08\xb74\xc9\\\xf3\xa2\x97pt\x00\xb6\xf6\ -+\xf3\xba\xbf\xf9\x1a\x8eUgH)\xa4\x00w\xe8\x84d\x89Z\xc6\xd3\x8dT\xad\x12\xc8\ -+/\x1e\x1d\xe1$\x8ai\x13~k\x94\xc9\xa1\xdbj\x0c{,;C\xb1\xdf\x15\x13\xc4hR\x1a\ -+M/o-\x8eq\xfb,\xbf4r|\x8d~Mk\x8c\xc8\xb2T\x8eI\xad\xcc\xf1\xe3\xc7\xa9e`\xb2\ -+\xb9\x11*\xb1\x08fka$\x8ak\x86\xae\xe7-\xef\xba\x89\xaf\xff\xe0^\x8e\xe7\xcc\ -+,%\x8a\x84\x02\xe1:\xe2\x11\xadb\xf5\xc6\x97dy\x8cmI\r\xdcV\\*\xd6\x1a\xde\ -+\x80FOb\xbd+\x14Y`\xfd!\x86\x88\x93E\xc9(N]/\xb8\x9f\xe0\xd1~\x80\xd6-r\x107\ -+6SbZ\xe0\xfd\xef\xff\x1d\xb6\x1f\xb8\x97\xc5\xc3\x0f\x91ZfX\xe0K\x9e\xe0\xa2\ -+\\\xf5\x82\xeby\xac\x1a\xf3\xa7\xec\xe5\x8d?\x7f\x13\x8b~\xc2\xb69Z\xc3\xc8\ -+\xb5\xb2\xec\x02GA\xd3\xdc\xba=/6\xb2oi\xa1\x11\xcb5V\xaf\x8f\x07\xf8\xe4\ -+\x18\xb0v\xba\xd2N*Z\x9e++\x9f\xb2\xedh\xa9\x8f\x05P[\x84Z\xbc9{\xe41\xf2 \ -+\xd8\xd1\xc7\xf8\xc4\x7f\xfemX\x9cd\xa2\xa9Ik\xa3`\x99@\x13o~\xd7\xbb\xb9\ -+\xeb\xc8\x11\x8e\xe7\xc4b\xa3\xe3\xa4\xc7\x10\xad\x9a\xc7\xa8\xadjd\x86\xe5\ -+\xa9z `\xd42$\x19\xb9T\x03k\x951\xab/\xbb\xcf"\xf6\x84\x9b\x07\xc8\xde\x8a\ -+\x97\x94\x12\xb9\xf5\xd9\xc7x\x1f\xa1\xe3\xf1\x0f\x8b\xb1\x13@\x86B\x9736\ -+\x1f\x98\xa6L\xa9\x85\xffv\xf3\x87y\xf8\xce\xbb\xb1\xa3\x8f\xc1|\x07qcXNy:\ -+\xdao\xf0\xac\xe7\\\xcdv\xee\xb0\xbd{y\xdb\x1b^\xcf1\x8c\x99\xd2(*$$\xe4?o\ -+\x14A\x9a\xec\xa8\xb4\x06gx\x82\xc6\x082\xc5b\xe3fkz\x83y\xc8\x96\xaeT\x11\ -+\xac\x85^Pu\x03[V\x83\x91\xdfGP\x1aS\x9e2Vuk\xa7\xafq\x1c"\x82\x1bt)s\xec\ -+\xa1\x879m\xb2\x89\xd4\x19\xba\xd8f\xf6\xc0\x11>\xf5\xbb\xef\x87\xd9\x0e\x8a\ -+\x93rfpp\xcd\xb8\x04\x89y\xe7\xdf\xf9\xfb|\xeb\xbe\xc3\xd8\xd6&\xb3,\x14FI\ -+\xdd\x97,\xb4\xd9:\x0e\x7f\xac\x93\x9a\xab\xc5\xdc\xcf\xc8\x9f<>\xdf\xb0\xa1\ -+\xb6~\xa7(\x88+\xa2O\xce?\xf2\xb8;\xa5\x95\xafM\xfb\x93\xe6v\x82\xb3\xcb{\ -+\x1cJ\x1bv\xc8\x08\x94\xca\x1f~\xec\xe3\xfc\xe8;\xdfe\x8f\nI\x9d\xc7~|\x84T\ -+\x07\x90\xc8\x18\x8er\xe5\xf3\xae\xe5\xf4\xb3\xce\xc7L8\xfc\xe0\xc3lwS\xfe\ -+\xda\xdf\xfe\x05vzaG\x0c\xb5\xcaD\x13\xd5\x9b>\xa9\xb4R\xb6\xfdlkS8\xc1\xf5\ -+\x97\xd3\xe54\xec\x91\xb5\xfai\xd9\xbao\xc1a\xad\xc0[\xf7\xe7V\x85\xee\xaa\ -+\x05\xc4\x89\\/\x91^\xd2\xda\xe9\xaf\xa3g\x9f2b\xce\xce\xd1\xa3tfl\x1f9\xc2-\ -+\xef\xffm(\x15|hU\xdd\xd0b8Qp\xde\xfe\xae\x9b\xb8\xef\xd1\xa3\xcc\x8bp\x89(\ -+\xf9\xa9\xfb\x98w\xc2\x8e\x97U\'\xc9\nI3.\xca\x80\xe3c<\x8b\x07\x98\x8f\xb2\ -+\x00\xb2\x1c0\x1f\xc54\xb7\xf0\x02\x19?OT\x80\xb5\xee\xae\x03v=\xdc\xc9\x82\ -+\xe05N\xbcW\t\x94f\x1cb\x92%\xde\xe0\xe3\xc4\xb9!\xe6LL\xf8\xc4\xc7>\xce=\ -+\xb7}\x13\x9d\xed@\x19H8\xb5\x0ehn\xee)P\xcd\xa0\xcb\\t\xf9\xe5\xbc\xf0\x99\ -+\xcfb\xd1w\xcc\x80\xaa\xb0h\x1d_F\xcf\x96\xd6\xe9\x16\xd0\x1c\x9b\xaf\xa5\ -+\x11>!\xdc:\xb5\xde\xcfJD\x88\x10Im\x91\x8d\xab\x90b\x84\xc6j\x9b?\xf6(\x7f\ -+\xa3bl?\xc2\xc8\x03<\x88D\xb4+\xa5q\xa6\x95\xe09\xfe\xd4h\x94,\xc24\x0b\xf7|\ -+\xf7\xfb|\xf2\xf7>\x04\xf3\x19\xa8\x86\x02\xac1\x83\x9b$a\xe2T\x8d^\xc3\xd1\ -+\xf9\xc0\x99]b;9\xc3R>k\xfa\xe0\x9a(\xd0\n\xb9\xe5\xc9J\r\xaa+\x1e\xb3\xbf\ -+\xea\xe1\rc\x86\x8e9\xe5\xf8\xbf\xa9C\x95\x15\xb5>\xe5\xb4\xdd\xbdYs\x05jy\ -+\xac\xa8\xc2\xcf\x035\xc7\xe4\x97ZEX\x1b \xd2@Q\xd5\xa9\x05\x90\xc4\xa5W\\\ -+\xc3\xd9O\xdd\x1f\xfcA\x05\xb5\x81\x07\xef;\xcc\x9d\xb7\xdd\x81\x88p\xcd\xf5\ -+/\xe6\xc8\xf6\x0eG\x8e\x1e\xe5\xe9\xed\x98G\x82\x1a\xe9TZse\x8d\xd48\xcb\x18\ -+\x17\xf5\xf6\xb9\x06\x06\xd5\x96\x85\xcdn\x11v\xf5X/\xf0\x92\x80I\xb4\xdf\ -+\xac\x0e\xd1\xeb\xf4\xdaTb\xdf]\x0b\x88\x84\x8bTdU\x0e\xef\xf2\x01\x8f"\xa4\ -+\x18f\xc2\r\xafy5\x97]ri\xbbG F\xd6\xebl\x9b;n\xfd\x1aw\xdc\xf1\x1d\xdc\xe15\ -+oy\x1b\'\x93\xb2\xff\xac\xb3\x190\x90(\x9ab4\xda\x1bMM\x80\x85d%\xa3p3J\xe8\ -+\x91\xc7\x97\xcbl\x84g\x94\xe7C\xc8\x89\xb0\x18\xff>\xce >\x02|H\xe22\x02\ -+\x88\x8c\xcdQ\xf3V\xec\x84T\x99DIkn)b\x8d\x19\xc6\xf1h\x8a\x05^{\xe8\xf9<\ -+\xf7\x85\xd7\x85i\x14\xc4\x8c\xec\xc6?}\xef?\xe0\xa2+\xaf\xc2R"\xed?\x8d\xd7\ -+\xdcx#C\x82\x92\x84ad0\xc4)\xa7\x96\xfe\xc2\xed\xc7\x1a\x81`|\xad\x85-\xa2\ -+\xa85| 2\x8b-\x19 K\x11\xc7\xc7Z\x05]r\x027\xc7\xdd\xe2\xdaVb\x06\xd9[\xb7\ -+\xc9G\x1e \xb6\xb6\xd9\x91\r\xb2D`edc+\x9d\xde%\x04\x92*\xab\xa9L\x11e>\x14^\ -+t\xe3\r\\\xfe\x97\xae\x00\xcd\x1c\xb8\xf8Bl\x1a@\xeb\xad\x91),/\xceXE@S\x85$\ -+>\xb5\xcb\x9d=\x8e1\xd2\x9b\x8f_%\xc6\x8dW\xbc\xe4I\xc8^\xdc\xe4\xd5\xee0)e\ -+\xec3F8\xaf\xd2\xe0\x9a|\x9dD\x02\x14\xdb\x8f\xbb4\xd7\x1f\x97*-\x01I\x84\ -+\x85\xa0K\xe6H\xce\xbc\xf8e/G\xcc\x19\x1cj\x16\xe6eh\xf3<\xb2d\x97\xc1\xe4VU\ -+(\xad\xb3\xdf&\x90\xa3\x10\x1a\x11}$^\xac6\xedk\x9b\x96&\xea\xcarl.<\xc5\xa9\ -+T\xabq[M-X\x19\xa8e\x881\x1d\xf36,=Z\xc9\xeb\x92\xfd!!$\x06\x00\xb2\xfb\xe6\ -+\xad\xd6\r\xf65s+\x11B4#\x999\x839\xde)\xe6N\xce\xf13c\xfd\xce2\xf6i\xcc\xd3\ -+W\x8cs\xac\xec\x88\x9e\x86K\xa42\x1f\xd9\x9e\xcb\xd2\x0b\x97\x9b\x97\xb5\x03\ -+\x1c\xcb\x84\xa8\xa3\xe3`<\xee\x10s+X\x1d\xa2\xc8\xd3`\xb2y\xac*Rk\x8cd\x95f\ -+\xddq?-\xcd\xb0ba\xe3{\xeb\xee;\x9e\x964\xce-9\x0c\x19e\xb3\x84\xb0"i\x8d\ -+\x8b5\x15:\xa2\x13\xc3I\xe2D\xa3<N\xd8\x83\xf3\x858\xab\x8eU\xa1\x8e\xe3\x08\ -+\x12\xf2\xd7\x08\xd0q\xffP\x1b%\xb0\x10>\x8bW\xbcT\xea\x10\x1b\xa7\xcc\x19\ -+\x86\x9dH\xd7\xad/\xb5\x14c\xd7]\xbfm\x89\xd5\xcd\nk4\xd3W\x7f\xc7\x1e\xce\ -+\xe8\x0b\xcb\xcd\x8f\xe9n\xcc\xf7\x10\xd4j\xd7\x88\\s\xe56.\xb7\xfa\x9d\xd5\ -+\xe6\x97\xa5v\x9b?\xaam&!nkla\xb1\x16\xf7\xeb\xe9o\xa8\xde\x8cax\x1d(\x8b9e\ -+\x98Q\x163|\xbc\x95\x8eQ\x11Z\x1e\x8a.w\xb8,\x86e\xb5\xc1\xd1\xc7Z\x97\xa9\t\ -+h\xab\x11\xf8\xe5eF\xff\x1e\x8d\xb2\x16\xc7\xe6\xb6\x94\x18\x82\x8c%\nF\x950\ -+|u\x1a\xa8\xb6\x82\\h\xe4\xca\xa1K\xd4\x12\xa8\xe3\xd2\xea\x03\x1b\xcd\x16k1\ -+\x81R\x9d\xeaQK\x98Y\xb8\x7f]P\xe63\x16\xb3\x1d\x86a\x08\x00\x1e\xef\x1a\xc3\ -+\x1b\x88\xb9\xd1\x99\xb6j\xebI\xf8\xf3\xba\xbd$\xa6K\x02\x13|<\xd4e\xbb{\xbc\ -+\xf9t|?\xee5\x88\xf4\x94\x9b\x91\x8b\xc7\xc8\xcd\x18\x1c\xd5ey\xcbk\xf5\x15\ -+\x1f07Ju\xb2\x83\x99b8\xd5\xac\xdd\x8f\xe1\xa8\x85\xf1\xa4\x121R\x812\xa7.N\ -+\xe0\xf3\xe3\xd8\xec\x18e\xe78ev\x1c/\x8b\xe5A\xe5q\xb6wC3\xbe=\xa7\xdf\x9c\ -+\x90\xad\r\x1c\xef\xea\xfc\xae\xdc1\x1e\xdahh\x93\xc5\x08\xcem\xb40\xc01wJ\ -+\x1bNN.m\x80i\x9c\xe2r\\\x95\xea\x89J\t\xfe\xafJ)\x85\xeakq-\x12\x03\xd6\x1e\ -+\xac\xb1V\xa7\x16\xa7,*VB\xcd\xae\x831\x0c\x8e\x9bR\x160\x9f\x17\x86yaX,\xd0\ -+\xc5ql\xe7(\xf3\x13\x0f\xe3;GY\x1c\x7f\x842;\t^\xa3\xa2\xeds\xc7`\xce\xe7?\ -+\xfbYH\xca\xcePZ\\5\xf6\xb5\x0c\x91\xc7\x1b x\xbb\xef\xbaS\xb4\x8cz\x9dX\xb8\ -+~Z\x89N\xeb7F\x8e\xe1T\x90]=\xfb%>\xf8\x98\xf3\xdbtw\xeb\x12{\x8d\xf2\xd6]"\ -+\xd5\x0e\x05\xdas\xb7D\xad\x86\x0f\xc2b\x11\xc07\xcc\xb7\xa9\xc3\x82:\xdf\ -+\xa6\x0e;\xd4\x9d\xe3<x\xff_,e,\xe9U\xdc4a\x1e\x9a\xfa2\xf0\xc7\x82a\xc9\x82\ -+\xdb"G\x92>>\x1f\xef@\x18a\xe0\xd4\xb0\x89\xf4\xb0k\xd3\xbb\x1e\xba{\xc8b\ -+\xf5\xbd\xb5\xdf^\x97\xb4\x97\xa8\xb7>\xe8\xa0k\xebiypy\xf3u\xfbg#\xff\x0f\ -+\xc9/\x89PJ!\xe7\x9c\x1bQ\xc9\x98\xd5\xd5b\xc7\xf8\xe3\x94\r\x8f\xac\xd1G\ -+\xa1q7\xf7\xf6S\xf6w\xca\xdbkvh}\x05\xa9O\xf8\xb9\xe5\xe8\xcd\xa9\xd7_\xe2\ -+\xc2*\xcb\x84:\xb5*\x90B\xa5f\t\x8c\xc8H\xb3\x9c,\x89ZK\xe8\xde"\xfc_\xce\ -+\xbc\x05\xfcSMC%\x00\x00\x00\x00IEND\xaeB`\x82\xb3\x8d;\x80' ) - - def getBirdBitmap(): - return wxBitmapFromImage(getBirdImage()) -@@ -169,15 +308,15 @@ - def getAwayData(): - return zlib.decompress( - 'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x02 \xcc\xc1\ --\x06$\xe5?\xffO\x04R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xcf\xf1tq\x0c\xa9\ --\x98\x93," \x90\xb0\x80\xc5 Q\xf8\xcf\x87\x87G\xff\xf3\xcb\xc7\xfdqOOf\xee\ --\xd9\x11\xd3\xb0\xc6\xd3\xc1\xa1i\xa2\x8a\xf8\x04\xa6\x02\xa9\x86\x1cm;}\x81\ --\xa7L\x9b\xf6|x\xcc\x9f\x17\xcd)\xa5\xa0\xf0\xe1\x91=;w\x93\xff$q\x11\x91\r\ --\xda\xc7R9\xb8w5\xb4\xf0,[$__p\xb3\xff(C\xceI\xa6\xb4\x03\xfd\xfa"\x12\x1f\ --\x1eq~\x9bq\x80\xa3Y\xd4[E\x82\x95E\x81\xcd\xf3\x84\x83\x81\xde\xd9\x88\xd8\ --\x867]\xb2\xd1\x05\xd9G^6q\n\xc7\xfd\x99.\xd0\xb8\xa3eB\x1a\x1b\x9b\xcd\xcc\ --\xce\x08\x06\x86\xd3\x9b\xac\xff\xe90\x1b\x96\x03\xdd\xc9\xe0\xe9\xea\xe7\ --\xb2\xce)\xa1\t\x00\xd0\xb5LC' ) -+\x06$\xe5?\xffO\x04R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xcf\xf0tq\x0c\xa9\ -+\x98\xb34\xf8 o\x83\x01\xc7\x92c\x8c/X\xca\x8c\xc3\x8bX\xdd\x0bZ\xfa\x1e\xb1\ -+\\\xe0\xfc\x90\xe8#\xc5\xbdv\xeb\xf7E,}\xbb\x1dd\x95\x0eq\xa8\xe9\x9e\xf49\ -+\xe4\xf3\xa9\xcf\xd4\xc2\xdb\xf1^\xcb\x8b\xd8\xe9Mr3X~^\x99\xd5\xea\xcfU\x17\ -+)\xb0q\xb9\x19\xa7\x80g\x8c\xd9\xe6\xd3N\x1cU\x1b]\x8d\xf6\x0b\x9f\x0e\x12\ -+\xf3<\xea\xe3\xb8`\xeeQ\xe7\t\x97\x18\x0eV\xbe\x9a\x1d\xa0_\x18\xeb9\x83q\ -+\xc6\xfb\xf2\x9eoR\xdc\xac;\xbb\x1eo\x90\x96\x17\x89\xbea&\xf4\x9e\xf1\xdb\ -+\xde\xbb<\x01?}\xe2\x0b\x19C\xb6;D\x9f0\x8e\xb7\x00\xba\x91\xc1\xd3\xd5\xcfe\ -+\x9dSB\x13\x00`\xd1Pt' ) - - def getAwayBitmap(): - return wxBitmapFromImage(getAwayImage()) -@@ -189,21 +328,19 @@ - #---------------------------------------------------------------------- - def getOnlineData(): - return zlib.decompress( --'x\xda\x01a\x01\x9e\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\ -+'x\xda\x01@\x01\xbf\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\ - \x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\ --\x08\x08\x08|\x08d\x88\x00\x00\x01\x18IDATx\x9c\x8d\x92\xadr\x021\x14\x85O\ --\x98\x15\x11\x88##\xf7\x11\x90\x08\x04\xb2\xa2\x0fPQ\x81@ \xfa\x10<\x02\xa2\ --\x02Q\x81\xacDT\xf4\x01**\x11\x15\x95\x08DdD\xc5\x8a\x9dI\xc5M\xda\r{\x1783\ --\x99\xfc\xdc\xdco\xee=\x89!\tM\xa4\x8f!8\xa3\x06;2\x1a\x80\xf4\xd1\x8e\xff\ --\xf7\xfe4\x0c\x1ai\x87!8c+\x80\x94qI*@\xaa\x00l\x05|\x7f93\x99\xf88\x08\x98\ --\xce\xf4\xa0\x1d\xcb\x98\xce\xa4\x1d\rR\xd7>\x8eH\xe0\xee\xbe\x1f\xfc\xfc\ --\x906l%\xeb\xc3\xa1\xf4\xa1\xae%\xc7\x90\xc4\xc3\xa3l\x9a\x1f\t\xee\xf7r9\ --\x83\xdf\xdf\x9c\x99\xcf}lZ\xb9\x93\xe7\xe3\xd1\x19C\x12\xab\xa7\x12\xd0\xb4\ --e5!\x94\x89M+\xde\x00\xc9\xc4\xed\xf3\xf5\xf7\xee*\'\xff\x012\x84L\xe6\xa5\ --\xde\xb3\xba\xebs/\xd4\x8f\x04\x00\x8b\x85\xf4\x9c[\xcb\xbe\x9c\xab\xd2\x0e\ --\x01\xa9\x04\xc9\x93\xd7\x81\xe4\xa2\x85\x1e \xa1w\xbb\xcb\xfe\xa8\x80\xf5Z^\ --\xe5Z\xb2\n\xd8\xbe\xc8\xcf\xdbln{\x99\x1e`\xb5\x94\x1fx\xab~\x01\xf4=f\x9f\ --\x11\xb7S\x87\x00\x00\x00\x00IEND\xaeB`\x82T\xf1\x96\x10' ) -+\x08\x08\x08|\x08d\x88\x00\x00\x00\xf7IDATx\x9c\x8d\x92a\x11\xc20\x0c\x85\ -+\x13\x0c\xec\xd5\xc1$\xe0`8@\x02\xa0\x00\x0bH\x00\x05 \x01$\xe0\x00\x1c\x80\ -+\x82\x16\x05\xe1\xc7#\xb0\x8dl\xf0\xeezk\x97\xe6\xbb\xe45\n@"\x01\xd9JI\x1a\ -+\x06[\xd2\x08\x00d\xab\xaa\xcf\xf9~\x1f\x06M\xa2\x9f\xa5$U\x15\x01\xb8\xc6\ -+\x14\x02X\x85\x88\xaa\xc8\xf5\x9at:\xcd6\x08h\x9a8XU\\M\xc3v"H]g\x9b\x00"\ -+\xf3\xf9w\xf0|f\x1b\xaa\xdc_.]\x1f\xea\x9a9\n@\x16\x0b\x1e\x1e\x0f\x06\x8fG^\ -+v\xf0\xe9\x94t6\xcbf\xc6;\xfe\xbd\xdd\x92*\x00Y\xaf\xbb\x00\xeb\xd5SJ7\xd1\ -+\x8c\xde\x88\xbcL\xdc\xed~\xbfw[\x9e\xfc\x068\x04\xa0q\xde\xbb\xab\xbd\xef{\ -+\x11\x0e\x92\x88\xc8r\xc9\x9e\xbd5\xf7\xa5\xaf\xc19hW2\x94<\n\xf0\xb2\x0f\ -+\x87q\x7fB\xc0f\xc3W\xf9\x95\x1c\x02\xf6{N\xdev\xfb\xdf\xcb|\x01V+N\xe0\xbfz\ -+\x02c\xcceV\x80\xefu4\x00\x00\x00\x00IEND\xaeB`\x82\xfa\xa9\x7f\xb3' ) - - def getOnlineBitmap(): - return wxBitmapFromImage(getOnlineImage()) -@@ -215,13 +352,13 @@ - #---------------------------------------------------------------------- - def getOfflineData(): - return zlib.decompress( --"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x02 \xcc\xc1\ -+'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x02 \xcc\xc1\ - \x06$\xe5?\xffO\x04R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xa7{\xba8\x86T\xcc\ --I\x16\x11\x10HX\xc0b\x90(|\xe6\xc7\x87\x87\xf5\xc7\xda\xf9\xff_\xbcy\x83AYO\ --\\!{\x96\xa2\xc2\x01\x8fI\xdc\x1e\x8c\x16\xbc\x0e\xdbD\xe7\x8bw\x141F\xc6\ -+I\x16\x11\x10HX\xc0b\x90(|\xe6\xff\x87\x87\xf5\xff\xda\xf9\xff_\xbcy\x83AYO\ -+\\!{\x96\x86\xc2\x01\x8fI\xdc\x1e\x8c\x16\xbc\x0e\xdbD\xe7\x8bw\x141F\xc6\ - \x1dH\xd7vd\xbe`:\xf9\tkLWa\xe7e=\xb1\x15y\x0c\xebf\x1c0`\x98\xedTs\xf1\x84S\ --\xdf\xda\x8aX\x06\xee\xdc$\x93d\xd3\x86\x88^\x03\x06\x86\x86\rza\x99\xf9'~\ --\x01\xadd\xf0t\xf5sY\xe7\x94\xd0\x04\x00\xc0q7\xbe" ) -+\xdf\xda\x8aX\x06\xee\xdc$\x93d\xd3\x86\x88^\x03\x06\x06\xd6Gz\xd9\xdb\xd7\ -+\xfd\n\x06Z\xc9\xe0\xe9\xea\xe7\xb2\xce)\xa1\t\x00\xda`7\xe8' ) - - def getOfflineBitmap(): - return wxBitmapFromImage(getOfflineImage()) -@@ -264,3 +401,28 @@ - stream = cStringIO.StringIO(getUpData()) - return wxImageFromStream(stream) - -+#---------------------------------------------------------------------- -+def getYellowData(): -+ return zlib.decompress( -+'x\xda\x01Z\x01\xa5\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\ -+\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\ -+\x08\x08\x08|\x08d\x88\x00\x00\x01\x11IDATx\x9c\x95\x92\xbfN\x02A\x10\xc6\ -+\xbf!\xac\t\x85q\x07\x1a\x1aJ\x13{\x1bihllh\xb0\xd3{\x07\x9e\x81G\xe0\x1d\ -+\xb4\xa4"!6\xd4^cCe\xc2\x0b\xd0xcabrW\x8c\x05\xdcqd\xe7\x8es\x9a\xcd\xce\x97\ -+\xef\xb7\xf3g\xc9{\x0f+d\xd1Q~\xfc%S,\x05Y\x00Yt\x14\x17W\xc5\x9d\xc7\xbbJP\ -+\xcbJ\x16/;\x8f\x9f\xec\xb2\xb6\x02\x13\x90\x9b\x01`0\xd9\x92\xbc\xddh%@\xd6\ -+C[t\x0c8\x86\xac\x87\n\xc7\xb0 \xb2\xec+\xe9\xe6I\x01\x80G\xab\xa0\xcf\x1c\ -+\xce\xf7\xef\xa1\xb6\xec+\x00\xb4y\xb4"\x89#\x958R\xa4\tN`\x8e\x03\x182\xd9\ -+\'\xb2o\xf0xG\xe4\xbd\x87|L\x0f\xe2\x97\xddh\x9a\x94\x8c\xfb\x93\x1f>\t8\x0c\ -+\x91o\xe7g\xf7]\x8e\xdc\\\x00\n\x88\xeb\x01\xae\xd7\xd8\x0cT|$\x00\x908:N=M\ -+\xcc!\x9fT\x10D\xa9\x92*s= 7\xdf\xbd\xd4\xce\xc7\x04\xc8f\xa6M\xcc&@\xb6\xaf\ -+\x8av\xb7\xf1f\x02\x00_?\xffk\xa5\x7f\xd3\x0fZ\x88\xbc\xbf\xaa\xee\x00\x00\ -+\x00\x00IEND\xaeB`\x82H\xf3\x8b\xc6' ) -+ -+def getYellowBitmap(): -+ return wxBitmapFromImage(getYellowImage()) -+ -+def getYellowImage(): -+ stream = cStringIO.StringIO(getYellowData()) -+ return wxImageFromStream(stream) -+ -Files pyslsk-1.0.0/pysoulseek/wxgui/images.pyc and slsk-tmp/pysoulseek/wxgui/images.pyc differ -Files pyslsk-1.0.0/pysoulseek/wxgui/__init__.pyc and slsk-tmp/pysoulseek/wxgui/__init__.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/notebook.py slsk-tmp/pysoulseek/wxgui/notebook.py ---- pyslsk-1.0.0/pysoulseek/wxgui/notebook.py 2003-03-02 17:44:25.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/notebook.py 2003-03-12 21:31:36.000000000 +0100 -@@ -15,31 +15,40 @@ - - self.imglist = wxImageList(18,18) - self.offline = self.imglist.Add(images.getOnlineBitmap()) -+ self.yellow = self.imglist.Add(images.getYellowBitmap()) - self.AssignImageList(self.imglist) - self.pages = [] -+ self.hilites = {} - self.page = 0 - - def OnPageChanged(self, event): -+ self.hilites[self.pages[self.page]] = 0 - self.page = event.GetSelection() -+ self.hilites[self.pages[self.page]] = 0 - self.SetPageImage(self.page,-1) - - def AddPage(self, page, title): - wxNotebook.AddPage(self, page, title) -+ self.hilites[page] = 0 - self.pages.append(page) - - def DeleteAllPages(self): - wxNotebook.DeleteAllPages(self) - self.pages = [] -+ self.hilites = {} - self.page = 0 - - def DeletePage(self, index): - wxNotebook.DeletePage(self, index) -+ del self.hilites[self.pages[index]] - del self.pages[index] - self.page = self.GetSelection() - if index <= self.GetSelection(): - self.page = self.page - 1 - -- def OnPageUpdated(self, pageobj): -+ def OnPageUpdated(self, pageobj, hilite=False): -+ if hilite: -+ self.hilites[pageobj] = 1 - if self.pages[self.page] != pageobj: -- self.SetPageImage(self.pages.index(pageobj),0) -+ self.SetPageImage(self.pages.index(pageobj),self.hilites[pageobj]) - -Files pyslsk-1.0.0/pysoulseek/wxgui/notebook.pyc and slsk-tmp/pysoulseek/wxgui/notebook.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/search.py slsk-tmp/pysoulseek/wxgui/search.py ---- pyslsk-1.0.0/pysoulseek/wxgui/search.py 2003-03-12 18:59:56.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/search.py 2003-03-14 22:04:23.000000000 +0100 -@@ -16,7 +16,7 @@ - import notebook - from sortablelist import sortableListCtrl - from wxPython.wx import * --import locale -+from pysoulseek.utils import Humanize - - class SearchWindow(wxPanel): - """ A search window with notebook that contains search results. -@@ -54,12 +54,16 @@ - self.DoSearch(self.frame.np.encode(self.search.GetLineText(0))) - self.search.Clear() - -- def DoSearch(self, text): -+ def DoSearch(self, text, user = None): - requestid = wxNewId() - tab, list = self.MakeSearchTab() - self.searches[requestid] = (list,text) -- self.resultsnb.AddPage(tab,text) -- self.queue.put(slskmessages.FileSearch(requestid,text)) -+ if user is None: -+ self.resultsnb.AddPage(tab,text) -+ self.queue.put(slskmessages.FileSearch(requestid,text)) -+ else: -+ self.resultsnb.AddPage(tab,"[%s] %s" % (user, text)) -+ self.processrequest(user, slskmessages.FileSearchRequest(None,requestid,text)) - - def ShowResult(self, msg, username): - """ Show search result.""" -@@ -69,17 +73,42 @@ - tab, list = self.MakeSearchTab() - self.searches[msg.token] = (list, text) - self.resultsnb.AddPage(tab,text) -- self.searches[msg.token][0].AddResult(msg, username) -- self.onupdate(self) -- self.resultsnb.OnPageUpdated(self.searches[msg.token][0].parent) -+ results = self.searches[msg.token][0].AddResult(msg, username) -+ if results: -+ self.onupdate(self) -+ self.resultsnb.OnPageUpdated(self.searches[msg.token][0].parent) - - def MakeSearchTab(self): - """ Create a result window, which is a notebook tab. """ - panel = wxPanel(self.resultsnb, -1) -+ filterinstr = wxStaticText(panel, -1, label = " Filter In: ") -+ filterin = wxTextCtrl(panel, -1, value = "", style = wxTE_PROCESS_ENTER) -+ filteroutstr = wxStaticText(panel, -1, label = " Filter Out: ") -+ filterout = wxTextCtrl(panel, -1, value = "", style = wxTE_PROCESS_ENTER) -+ filtersizestr = wxStaticText(panel, -1, label = " Size: ") -+ filtersize = wxTextCtrl(panel, -1, value = "", style = wxTE_PROCESS_ENTER) -+ filterbrstr = wxStaticText(panel, -1, label = " Bitrate: ") -+ filterbr = wxTextCtrl(panel, -1, value = "", size = wxSize(45,20), style = wxTE_PROCESS_ENTER) -+ filterfree = wxCheckBox(panel, -1, label = "free slot") - close = wxButton(panel, -1, "Close") - closeignore = wxButton(panel, -1, "Close and ignore") -+ panel.filterin = filterin -+ panel.filterout = filterout -+ panel.filtersize = filtersize -+ panel.filterbr = filterbr -+ panel.filterfree = filterfree - list = SearchList(panel, -1, self.processrequest, self.privatechat, self.info, self.browse, self.transfers,self.frame) - sizerh = wxBoxSizer(wxHORIZONTAL) -+ sizerh.Add(filterinstr, flag = wxALIGN_CENTER) -+ sizerh.Add(filterin) -+ sizerh.Add(filteroutstr, flag = wxALIGN_CENTER) -+ sizerh.Add(filterout) -+ sizerh.Add(filtersizestr, flag = wxALIGN_CENTER) -+ sizerh.Add(filtersize) -+ sizerh.Add(filterbrstr, flag = wxALIGN_CENTER) -+ sizerh.Add(filterbr) -+ sizerh.Add(filterfree, flag = wxALIGN_CENTER|wxLEFT, border=5) -+ - sizerh.Add(60,10,1,wxEXPAND) - sizerh.Add(closeignore) - sizerh.Add(close) -@@ -90,6 +119,12 @@ - panel.SetAutoLayout(True) - EVT_BUTTON(self, close.GetId(), self.OnClose) - EVT_BUTTON(self, closeignore.GetId(), self.OnCloseIgnore) -+ EVT_TEXT_ENTER(self, filterin.GetId(), list.OnRefilter) -+ EVT_TEXT_ENTER(self, filterout.GetId(), list.OnRefilter) -+ EVT_TEXT_ENTER(self, filtersize.GetId(), list.OnRefilter) -+ EVT_TEXT_ENTER(self, filterbr.GetId(), list.OnRefilter) -+ EVT_CHECKBOX(self, filterfree.GetId(), list.OnRefilter) -+ - return panel,list - - def Close(self, ignore): -@@ -141,6 +176,9 @@ - self.frame = frame - - self.results = [] -+ self.results_visible = [] -+ -+ self.UpdateColours() - - self.menu = wxMenu() - downloadID=wxNewId() -@@ -172,12 +210,16 @@ - EVT_RIGHT_UP(self,self.OnRightUp) - - -+ def UpdateColours(self): -+ self.normal.SetTextColour(self.frame.np.config.sections["ui"]["search"]) -+ self.grey.SetTextColour(self.frame.np.config.sections["ui"]["searchq"]) -+ - def OnRightUp(self,event): - """ Pops up a menu on a right-click in users list.""" - pt = event.GetPosition() - item, flags = self.HitTest(pt) - self.id = item -- self.selecteduser = self.results[self.id][1] -+ self.selecteduser = self.results_visible[self.id][1] - if item >= 0: - self.SetItemState(item,wxLIST_STATE_FOCUSED,wxLIST_STATE_FOCUSED) - self.PopupMenu(self.menu, pt) -@@ -201,6 +243,11 @@ - def OnShowIP(self, event): - self.frame.np.queue.put(slskmessages.GetPeerAddress(self.selecteduser)) - -+ def OnBanUser(self, event): -+ self.frame.BanUser(self.selecteduser) -+ -+ def OnShowIP(self, event): -+ self.frame.np.queue.put(slskmessages.GetPeerAddress(self.selecteduser)) - - def OnDownload(self, event): - item = -1 -@@ -208,20 +255,78 @@ - item = self.GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED) - if item == -1: - break -- self.transfers.getFile(self.results[item][1],self.results[item][6]+self.results[item][0]) -+ self.transfers.getFile(self.results_visible[item][1],self.results_visible[item][6]+self.results_visible[item][0]) - - def OnDownloadFolder(self,event): -- self.processrequest(self.selecteduser, slskmessages.FolderContentsRequest(None,self.results[self.id][6])) -+ self.processrequest(self.selecteduser, slskmessages.FolderContentsRequest(None,self.results_visible[self.id][6])) - -+ def checkDigit(self, filter, value, factorize = True): -+ op = ">=" -+ if filter[:1] in (">", "<", "="): -+ op, filter = filter[:1]+"=", filter[1:] -+ -+ if not filter: -+ return True -+ -+ factor = 1 -+ if factorize: -+ if filter.lower()[-1] == "g": -+ factor = 1024*1024*1024 -+ filter = filter[:-1] -+ elif filter.lower()[-1] == "m": -+ factor = 1024*1024 -+ filter = filter[:-1] -+ elif filter.lower()[-1] == "k": -+ factor = 1024 -+ filter = filter[:-1] -+ -+ if not filter: -+ return True -+ -+ if not filter.isdigit(): -+ return True -+ -+ filter = long(filter) * factor -+ -+ if eval(str(value)+op+str(filter)): -+ return True -+ -+ return False -+ -+ def checkFilter(self, name, size, br, free): -+ filterin = self.parent.filterin.GetLineText(0) -+ filterout = self.parent.filterout.GetLineText(0) -+ filtersize = self.parent.filtersize.GetLineText(0).replace(" ", "") -+ filterbr = self.parent.filterbr.GetLineText(0).replace(" ", "") -+ shown = True -+ -+ if self.parent.filterfree.GetValue() and not free: -+ shown = False -+ -+ if name.replace("_", " ").lower().find(filterin) == -1: -+ shown = False -+ -+ if shown and filterout and name.replace("_"," ").lower().find(filterout) >= 0: -+ shown = False -+ -+ if shown and filtersize and not self.checkDigit(filtersize, size): -+ shown = False -+ -+ if shown and filterbr and not self.checkDigit(filterbr, br, False): -+ shown = False -+ -+ return shown -+ - def AddResult(self, msg, username): - """ Add a result to the list.""" -- import string -+ results = 0 - for i in msg.list: -- s = string.split(i[1],'\\') -+ s = i[1].split("\\") - name = s[-1] - dir = i[1][:-len(name)] - user = username - size = i[2] -+ br = 0 - - if i[3] == 'mp3' and len(i[4]) == 3: - attrs = i[4] -@@ -236,22 +341,29 @@ - attributes = "" - else: - attributes = str(i[4]) -- self.results.append([name,user,size,msg.ulspeed,msg.inqueue,attributes,dir,msg.freeulslots]) -- self.SetItemCount(len(self.results)) -+ -+ self.results.append([name,user,size,msg.ulspeed,msg.inqueue,attributes,dir,msg.freeulslots,br]) -+ -+ if self.checkFilter(name, size, br, msg.freeulslots): -+ self.results_visible.append([name,user,size,msg.ulspeed,msg.inqueue,attributes,dir,msg.freeulslots,br]) -+ results += 1 -+ -+ self.SetItemCount(len(self.results_visible)) -+ return results - - def OnGetItemText(self, item, col): - import types -- text = self.results[item][col] -+ text = self.results_visible[item][col] - if type(text) == types.StringType: - if len(text) > 0: - return self.frame.np.decode(text,wxUSE_UNICODE) - else: - return '' - else: -- return locale.format("%s",text,1) -+ return Humanize(text,self.frame.np.config.sections["ui"]["decimalsep"]) - - def OnGetItemAttr(self, item): -- if self.results[item][7] == 0: -+ if self.results_visible[item][7] == 0: - return self.grey - else: - return self.normal -@@ -259,9 +371,17 @@ - def OnGetItemImage(self, item): - return -1 - -+ def refilter(self): -+ self.results_visible = [i for i in self.results if self.checkFilter(i[0], i[2], i[8], i[7])] -+ self.SetItemCount(len(self.results_visible)) -+ -+ def OnRefilter(self, event): -+ self.refilter() -+ - def SortList(self, col, order): -+ self.refilter() - if order == 0: -- self.results.sort(lambda x,y: self.cmp(x[col],y[col])) -+ self.results_visible.sort(lambda x,y: self.cmp(x[col],y[col])) - else: -- self.results.sort(lambda y,x: self.cmp(x[col],y[col])) -+ self.results_visible.sort(lambda y,x: self.cmp(x[col],y[col])) - -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/search.py~ slsk-tmp/pysoulseek/wxgui/search.py~ ---- pyslsk-1.0.0/pysoulseek/wxgui/search.py~ 1970-01-01 01:00:00.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/search.py~ 2003-03-12 21:46:18.000000000 +0100 -@@ -0,0 +1,279 @@ -+# Copyright (c) 2001-2003 Alexander Kanavin. All rights reserved. -+ -+""" -+This module contains GUI classes for displaying search results. -+""" -+ -+import time -+from pysoulseek import slskproto -+from pysoulseek import slskmessages -+import Queue -+import threading -+import images -+import about -+import userinfobrowse -+import search -+import notebook -+from sortablelist import sortableListCtrl -+from wxPython.wx import * -+from pysoulseek.utils import Humanize -+ -+class SearchWindow(wxPanel): -+ """ A search window with notebook that contains search results. -+ searches contains pointers to windows that display them.""" -+ def __init__(self, parent, id, queue, processrequest, privatechat, info, browse, transfers, onupdate,frame): -+ wxPanel.__init__(self, parent, id) -+ self.queue = queue -+ self.processrequest = processrequest -+ self.privatechat = privatechat -+ self.info = info -+ self.browse = browse -+ self.transfers = transfers -+ self.onupdate = onupdate -+ self.frame = frame -+ self.search = wxTextCtrl(self,-1, style = wxTE_PROCESS_ENTER) -+ self.searchbutton = wxButton(self, -1, "Search") -+ self.resultsnb = notebook.IconNotebook(self, -1, style = wxCLIP_CHILDREN) -+ sizerh = wxBoxSizer(wxHORIZONTAL) -+ sizerh.Add(self.search,1,wxEXPAND) -+ sizerh.Add(self.searchbutton,0,wxEXPAND) -+ sizerv = wxBoxSizer(wxVERTICAL) -+ sizerv.Add(sizerh,0,wxEXPAND) -+ sizerv.Add(self.resultsnb,1,wxEXPAND) -+ -+ self.SetSizer(sizerv) -+ self.SetAutoLayout(True) -+ -+ EVT_BUTTON(self, self.searchbutton.GetId(), self.OnSearch) -+ EVT_TEXT_ENTER(self,self.search.GetId(), self.OnSearch) -+ -+ self.searches = {} -+ -+ def OnSearch(self, event): -+ """ Process search request""" -+ self.DoSearch(self.frame.np.encode(self.search.GetLineText(0))) -+ self.search.Clear() -+ -+ def DoSearch(self, text): -+ requestid = wxNewId() -+ tab, list = self.MakeSearchTab() -+ self.searches[requestid] = (list,text) -+ self.resultsnb.AddPage(tab,text) -+ self.queue.put(slskmessages.FileSearch(requestid,text)) -+ -+ def ShowResult(self, msg, username): -+ """ Show search result.""" -+ if self.searches.has_key(msg.token): -+ if self.searches[msg.token][0] is None: -+ text = self.searches[msg.token][1] -+ tab, list = self.MakeSearchTab() -+ self.searches[msg.token] = (list, text) -+ self.resultsnb.AddPage(tab,text) -+ self.searches[msg.token][0].AddResult(msg, username) -+ self.onupdate(self) -+ self.resultsnb.OnPageUpdated(self.searches[msg.token][0].parent) -+ -+ def MakeSearchTab(self): -+ """ Create a result window, which is a notebook tab. """ -+ panel = wxPanel(self.resultsnb, -1) -+ close = wxButton(panel, -1, "Close") -+ closeignore = wxButton(panel, -1, "Close and ignore") -+ list = SearchList(panel, -1, self.processrequest, self.privatechat, self.info, self.browse, self.transfers,self.frame) -+ sizerh = wxBoxSizer(wxHORIZONTAL) -+ sizerh.Add(60,10,1,wxEXPAND) -+ sizerh.Add(closeignore) -+ sizerh.Add(close) -+ sizerv = wxBoxSizer(wxVERTICAL) -+ sizerv.Add(sizerh,0,wxEXPAND) -+ sizerv.Add(list,1,wxEXPAND) -+ panel.SetSizer(sizerv) -+ panel.SetAutoLayout(True) -+ EVT_BUTTON(self, close.GetId(), self.OnClose) -+ EVT_BUTTON(self, closeignore.GetId(), self.OnCloseIgnore) -+ return panel,list -+ -+ def Close(self, ignore): -+ """ Close the search results window.""" -+ selectednum = self.resultsnb.GetSelection() -+ selected = self.resultsnb.GetPage(selectednum) -+ for i in self.searches.keys(): -+ if self.searches[i][0] is not None and self.searches[i][0].GetParent() == selected: -+ self.searches[i] = (None,self.searches[i][1]) -+ if ignore: -+ del self.searches[i] -+ -+ parent = self.resultsnb -+ self.resultsnb.DeletePage(selectednum) -+ if parent.GetPageCount() > 0: -+ parent.SetSelection(0) -+ -+ def OnClose(self, event): -+ self.Close(0) -+ -+ def OnCloseIgnore(self, event): -+ self.Close(1) -+ -+class SearchList(sortableListCtrl): -+ """ List of search results.""" -+ def __init__(self, parent, id, processrequest, privatechat, info, browse, transfers,frame,style = wxLC_REPORT|wxLC_VIRTUAL|wxLC_VRULES|wxSUNKEN_BORDER): -+ sortableListCtrl.__init__(self,parent,id,style = style) -+ self.InsertColumn(0,"Filename", width=250) -+ self.InsertColumn(1,"User", width = 100) -+ self.InsertColumn(2,"Size",width=100,format=wxLIST_FORMAT_RIGHT) -+ self.InsertColumn(3,"Speed",width=50,format=wxLIST_FORMAT_RIGHT) -+ self.InsertColumn(4,"In queue",width=50,format=wxLIST_FORMAT_RIGHT) -+ self.InsertColumn(5,"Attributes",width=150) -+ self.InsertColumn(6,"Directory",width=500) -+ self.SetItemCount(0) -+ -+ self.normal = wxListItemAttr() -+ self.grey = wxListItemAttr() -+ self.grey.SetTextColour("grey") -+ self.red = wxListItemAttr() -+ self.red.SetTextColour("red") -+ -+ self.parent = parent -+ self.processrequest = processrequest -+ self.privatechat = privatechat -+ self.info = info -+ self.browse = browse -+ self.transfers = transfers -+ self.frame = frame -+ -+ self.results = [] -+ -+ self.UpdateColours() -+ -+ self.menu = wxMenu() -+ downloadID=wxNewId() -+ self.menu.Append(downloadID, 'Download File(s)') -+ EVT_MENU(self,downloadID, self.OnDownload) -+ downloadfolderID=wxNewId() -+ self.menu.Append(downloadfolderID, 'Download Containing Folder') -+ EVT_MENU(self,downloadfolderID, self.OnDownloadFolder) -+ self.menu.AppendSeparator() -+ sendmessageID=wxNewId() -+ self.menu.Append(sendmessageID, 'Send Message') -+ EVT_MENU(self,sendmessageID, self.OnSendMessage) -+ getinfoID=wxNewId() -+ self.menu.Append(getinfoID, 'Get User Info') -+ EVT_MENU(self,getinfoID, self.OnGetInfo) -+ browseID=wxNewId() -+ self.menu.Append(browseID, 'Browse Files') -+ EVT_MENU(self,browseID, self.OnBrowse) -+ showIpID=wxNewId() -+ self.menu.Append(showIpID, "Show IP") -+ EVT_MENU(self,showIpID, self.OnShowIP) -+ addtolistID=wxNewId() -+ self.menu.Append(addtolistID, 'Add to User List') -+ EVT_MENU(self,addtolistID, self.OnAddToList) -+ banuserID=wxNewId() -+ self.menu.Append(banuserID, 'Ban this User') -+ EVT_MENU(self,banuserID, self.OnBanUser) -+ -+ EVT_RIGHT_UP(self,self.OnRightUp) -+ -+ -+ def UpdateColours(self): -+ self.normal.SetTextColour(self.frame.np.config.sections["ui"]["search"]) -+ self.grey.SetTextColour(self.frame.np.config.sections["ui"]["searchq"]) -+ -+ def OnRightUp(self,event): -+ """ Pops up a menu on a right-click in users list.""" -+ pt = event.GetPosition() -+ item, flags = self.HitTest(pt) -+ self.id = item -+ self.selecteduser = self.results[self.id][1] -+ if item >= 0: -+ self.SetItemState(item,wxLIST_STATE_FOCUSED,wxLIST_STATE_FOCUSED) -+ self.PopupMenu(self.menu, pt) -+ -+ """ Handlers for the menu items""" -+ def OnSendMessage(self, event): -+ self.privatechat.SendMessage(self.selecteduser) -+ -+ def OnGetInfo(self, event): -+ self.processrequest(self.selecteduser, slskmessages.UserInfoRequest(None), self.info) -+ -+ def OnBrowse(self, event): -+ self.processrequest(self.selecteduser, slskmessages.GetSharedFileList(None), self.browse) -+ -+ def OnAddToList(self, event): -+ self.frame.AddToList(self.selecteduser) -+ -+ def OnBanUser(self, event): -+ self.frame.BanUser(self.selecteduser) -+ -+ def OnShowIP(self, event): -+ self.frame.np.queue.put(slskmessages.GetPeerAddress(self.selecteduser)) -+ -+ -+ def OnBanUser(self, event): -+ self.frame.BanUser(self.selecteduser) -+ -+ def OnShowIP(self, event): -+ self.frame.np.queue.put(slskmessages.GetPeerAddress(self.selecteduser)) -+ -+ def OnDownload(self, event): -+ item = -1 -+ while 1: -+ item = self.GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED) -+ if item == -1: -+ break -+ self.transfers.getFile(self.results[item][1],self.results[item][6]+self.results[item][0]) -+ -+ def OnDownloadFolder(self,event): -+ self.processrequest(self.selecteduser, slskmessages.FolderContentsRequest(None,self.results[self.id][6])) -+ -+ def AddResult(self, msg, username): -+ """ Add a result to the list.""" -+ import string -+ for i in msg.list: -+ s = string.split(i[1],'\\') -+ name = s[-1] -+ dir = i[1][:-len(name)] -+ user = username -+ size = i[2] -+ -+ if i[3] == 'mp3' and len(i[4]) == 3: -+ attrs = i[4] -+ if attrs[2] == 1: -+ brs = 'VBR' -+ else: -+ brs = 'Bitrate' -+ br = attrs[0] -+ length = '%i:%02i' %(attrs[1] / 60, attrs[1] % 60) -+ attributes = '%s: %i, Length: %s' %(brs,br,length) -+ elif i[3] == '': -+ attributes = "" -+ else: -+ attributes = str(i[4]) -+ self.results.append([name,user,size,msg.ulspeed,msg.inqueue,attributes,dir,msg.freeulslots]) -+ self.SetItemCount(len(self.results)) -+ -+ def OnGetItemText(self, item, col): -+ import types -+ text = self.results[item][col] -+ if type(text) == types.StringType: -+ if len(text) > 0: -+ return self.frame.np.decode(text,wxUSE_UNICODE) -+ else: -+ return '' -+ else: -+ return Humanize(text,self.frame.np.config.sections["ui"]["decimalsep"]) -+ -+ def OnGetItemAttr(self, item): -+ if self.results[item][7] == 0: -+ return self.grey -+ else: -+ return self.normal -+ -+ def OnGetItemImage(self, item): -+ return -1 -+ -+ def SortList(self, col, order): -+ if order == 0: -+ self.results.sort(lambda x,y: self.cmp(x[col],y[col])) -+ else: -+ self.results.sort(lambda y,x: self.cmp(x[col],y[col])) -+ -Files pyslsk-1.0.0/pysoulseek/wxgui/search.pyc and slsk-tmp/pysoulseek/wxgui/search.pyc differ -Files pyslsk-1.0.0/pysoulseek/wxgui/sortablelist.pyc and slsk-tmp/pysoulseek/wxgui/sortablelist.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/transfers.py slsk-tmp/pysoulseek/wxgui/transfers.py ---- pyslsk-1.0.0/pysoulseek/wxgui/transfers.py 2003-03-12 19:03:40.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/transfers.py 2003-03-12 21:47:39.000000000 +0100 -@@ -10,7 +10,7 @@ - import string - import time - from sortablelist import sortableListCtrl --import locale -+from types import StringType - - class TransfersList(sortableListCtrl): - """ This is a list control for transfers. Gets transfer data from transfer -@@ -30,6 +30,26 @@ - self.update(None) - - -+ def Humanize(self, size): -+ if size is None: -+ return None -+ priv = "" -+ if type(size) is StringType and size[-13:] == " (privileged)": -+ size, priv = size[:-13], size[-13:] -+ try: -+ s = int(size) -+ if s > 1024*1024*1024: -+ r = "%.2f GB" % ((float(s) / (1024.0*1024.0*1024.0))) -+ elif s > 1024*1024: -+ r = "%.2f MB" % ((float(s) / (1024.0*1024.0))) -+ elif s > 1024: -+ r = "%.2f KB" % ((float(s) / 1024.0)) -+ else: -+ r = str(size) -+ return r + priv -+ except: -+ return size + priv -+ - def update(self, item): - if item is not None: - if item in self.list: -@@ -53,9 +73,9 @@ - if col == 1: - return item.user - if col == 2: -- return item.status -+ return self.Humanize(item.status) - if col == 3: -- return locale.format("%s",item.size,1) -+ return self.Humanize(item.size) - if col == 4: - if item.speed is not None: - return "%.1f" %(item.speed) -@@ -105,15 +125,15 @@ - sendmessageID=wxNewId() - self.menu.Append(sendmessageID, 'Send Message') - EVT_MENU(self,sendmessageID, self.OnSendMessage) -- getaddrID=wxNewId() -- self.menu.Append(getaddrID, 'Show IP address') -- EVT_MENU(self,getaddrID, self.OnGetAddr) - getinfoID=wxNewId() - self.menu.Append(getinfoID, 'Get User Info') - EVT_MENU(self,getinfoID, self.OnGetInfo) - browseID=wxNewId() - self.menu.Append(browseID, 'Browse Files') - EVT_MENU(self,browseID, self.OnBrowse) -+ getaddrID=wxNewId() -+ self.menu.Append(getaddrID, 'Show IP address') -+ EVT_MENU(self,getaddrID, self.OnGetAddr) - addtolistID=wxNewId() - self.menu.Append(addtolistID, 'Add to User List') - EVT_MENU(self,addtolistID, self.OnAddToList) -Files pyslsk-1.0.0/pysoulseek/wxgui/transfers.pyc and slsk-tmp/pysoulseek/wxgui/transfers.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/userinfobrowse.py slsk-tmp/pysoulseek/wxgui/userinfobrowse.py ---- pyslsk-1.0.0/pysoulseek/wxgui/userinfobrowse.py 2003-03-12 19:24:40.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/userinfobrowse.py 2003-03-13 00:18:04.000000000 +0100 -@@ -16,7 +16,8 @@ - import notebook - from sortablelist import sortableListCtrl - from wxPython.wx import * --import locale -+from pysoulseek.utils import Humanize -+import string - - class UserNotebook(notebook.IconNotebook): - """ This is a notebook with user's information. Used to show either -@@ -86,16 +87,15 @@ - self.image = None - - buttonsizer = wxBoxSizer(wxVERTICAL) -+ buttonsizer.Add(self.chat, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, border=10) -+ buttonsizer.Add(self.browse,0,wxEXPAND|wxTOP|wxLEFT|wxRIGHT, border=10) -+ buttonsizer.Add(self.getip, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, border=10) -+ buttonsizer.Add(self.addtolist,0,wxEXPAND|wxTOP|wxLEFT|wxRIGHT, border=10) -+ buttonsizer.Add(self.ban,0,wxEXPAND|wxTOP|wxLEFT|wxRIGHT, border=10) -+ buttonsizer.Add(self.savepic,0,wxEXPAND|wxTOP|wxLEFT|wxRIGHT, border=10) - buttonsizer.Add(0,0,1,wxEXPAND) -- buttonsizer.Add(self.chat, 0, wxEXPAND, border=10) -- buttonsizer.Add(self.browse,0,wxEXPAND, border=10) -- buttonsizer.Add(self.addtolist,0,wxEXPAND, border=10) -- buttonsizer.Add(self.getip, 0, wxEXPAND, border=10) -- buttonsizer.Add(self.ban,0,wxEXPAND, border=10) -- buttonsizer.Add(self.savepic,0,wxEXPAND, border=10) -- buttonsizer.Add(self.refresh,0,wxEXPAND, border=10) -- buttonsizer.Add(10,10,0,wxEXPAND) -- buttonsizer.Add(self.close,0,wxEXPAND, border=10) -+ buttonsizer.Add(self.refresh,0,wxEXPAND|wxLEFT|wxRIGHT, border=10) -+ buttonsizer.Add(self.close,0,wxEXPAND|wxALL, border=10) - - sizerv = wxBoxSizer(wxVERTICAL) - sizerv.Add(wxStaticText(self,-1, "Self-description:")) -@@ -184,9 +184,15 @@ - def OnBan(self, event): - self.frame.BanUser(self.user) - -+ def OnChat(self, event): -+ self.frame.np.privatechat.SendMessage(self.user) -+ - def OnBrowse(self, event): - self.frame.np.ProcessRequestToPeer(self.user, slskmessages.GetSharedFileList(None), self.frame.np.userbrowse) - -+ def OnBan(self, event): -+ self.frame.BanUser(self.user) -+ - def OnClose(self, event): - """ Closes the window""" - del self.parent.users[self.user] -@@ -202,9 +208,15 @@ - self.frame.np.ProcessRequestToPeer(self.user, slskmessages.UserInfoRequest(None), self.frame.np.userinfo) - - -+ def OnShowIp(self, event): -+ self.frame.np.queue.put(slskmessages.GetPeerAddress(self.user)) -+ -+ def OnRefresh(self, event): -+ self.frame.np.ProcessRequestToPeer(self.user, slskmessages.UserInfoRequest(None), self.frame.np.userinfo) -+ - class FileListCtrl(sortableListCtrl): - """ This is a list of a user's files in a particular directory""" -- def __init__(self, parent, id, style = wxLC_REPORT|wxLC_VIRTUAL|wxSUNKEN_BORDER|wxLC_VRULES): -+ def __init__(self, parent, id, frame, style = wxLC_REPORT|wxLC_VIRTUAL|wxSUNKEN_BORDER|wxLC_VRULES): - sortableListCtrl.__init__(self,parent,id,style = style) - self.InsertColumn(0,"Filename", width=200) - self.InsertColumn(1,"Size",width=100,format=wxLIST_FORMAT_RIGHT) -@@ -214,6 +226,8 @@ - self.dir = None - - self.parent = parent -+ self.frame = frame -+ self.curtreeitem = None - - def SetFileList(self, list): - """ Actually sets the list.""" -@@ -237,7 +251,7 @@ - return item[1] - if col == 1: - if not sort: -- return locale.format("%s", item[2], 1) -+ return Humanize(item[2],self.frame.np.config.sections["ui"]["decimalsep"]) - else: - return item[2] - if col == 2: -@@ -290,7 +304,7 @@ - self.refresh = wxButton(self, -1, "Refresh") - splitter = wxSplitterWindow(self,-1,style=wxNO_3D|wxSP_3DSASH) - self.tree = DirTreeCtrl(splitter, -1) -- self.listctrl = FileListCtrl(splitter,-1) -+ self.listctrl = FileListCtrl(splitter,-1,frame) - - sizerlowh = wxBoxSizer(wxHORIZONTAL) - sizerlowh.Add(self.gauge,0,wxEXPAND) -@@ -339,6 +353,9 @@ - downloaddirID=wxNewId() - self.treemenu.Append(downloaddirID, 'Download Directory') - EVT_MENU(self.tree,downloaddirID, self.OnDownloadDir) -+ recdownloaddirID=wxNewId() -+ self.treemenu.Append(recdownloaddirID, 'Recursively Download Dir') -+ EVT_MENU(self.tree,recdownloaddirID, self.OnRecDownloadDir) - downloadfileID=wxNewId() - self.listmenu.Append(downloadfileID, 'Download File(s)') - EVT_MENU(self.listctrl,downloadfileID, self.OnDownloadFile) -@@ -348,14 +365,14 @@ - self.treemenu.Append(sendmessageID, 'Send Message') - self.listmenu.Append(sendmessageID, 'Send Message') - EVT_MENU(self,sendmessageID, self.OnSendMessage) -- showIp=wxNewId() -- self.treemenu.Append(showIp, 'Show IP') -- self.listmenu.Append(showIp, 'Show IP') -- EVT_MENU(self,showIp, self.OnShowIp) - getinfoID=wxNewId() - self.treemenu.Append(getinfoID, 'Get User Info') - self.listmenu.Append(getinfoID, 'Get User Info') - EVT_MENU(self,getinfoID, self.OnGetInfo) -+ showIp=wxNewId() -+ self.treemenu.Append(showIp, 'Show IP') -+ self.listmenu.Append(showIp, 'Show IP') -+ EVT_MENU(self,showIp, self.OnShowIp) - addtolistID=wxNewId() - self.treemenu.Append(addtolistID, 'Add to User List') - self.listmenu.Append(addtolistID, 'Add to User List') -@@ -428,7 +445,8 @@ - - def OnTreeSelChanged(self, event): - """ On selection of a tree item, display the filelist""" -- self.listctrl.SetFileList(self.tree.GetPyData(event.GetItem())) -+ self.curtreeitem = event.GetItem() -+ self.listctrl.SetFileList(self.tree.GetPyData(self.curtreeitem)) - - def OnDownloadDir(self,event): - """ Get every file in the directory """ -@@ -466,6 +484,12 @@ - def OnShowIp(self, event): - self.frame.np.queue.put(slskmessages.GetPeerAddress(self.user)) - -+ def OnRefresh(self, event): -+ self.frame.np.ProcessRequestToPeer(self.user, slskmessages.GetSharedFileList(None), self.frame.np.userbrowse) -+ -+ def OnShowIp(self, event): -+ self.frame.np.queue.put(slskmessages.GetPeerAddress(self.user)) -+ - def OnSearch(self,event): - """ Process search request""" - text = self.search.GetLineText(0) -@@ -506,3 +530,21 @@ - list.extend(self.FindNodes(node[i][1],text)) - return list - -+ def OnRecDownloadDir(self,event): -+ """ Download directory recursively """ -+ self.RecDownloadDir(self.curtreeitem) -+ -+ def RecDownloadDir(self,item, path = ""): -+ """ Download directory recursively """ -+ import os -+ (dir, flist) = self.tree.GetPyData(item) -+ ldir = string.split(dir,'\\')[-1] # local directory -+ ldir = os.path.join(path,ldir) -+ for i in flist: # Get the files in this dir -+ self.transfers.getFile(self.user, dir+'\\'+i[1], ldir) -+ -+ if self.tree.ItemHasChildren(item): # Get the other dirs -+ i, cookie = self.tree.GetFirstChild(item, 0) -+ while i.IsOk(): -+ self.RecDownloadDir(i, ldir) -+ i, cookie = self.tree.GetNextChild(item, cookie) -Files pyslsk-1.0.0/pysoulseek/wxgui/userinfobrowse.pyc and slsk-tmp/pysoulseek/wxgui/userinfobrowse.pyc differ -diff -rNu3 pyslsk-1.0.0/pysoulseek/wxgui/userlist.py slsk-tmp/pysoulseek/wxgui/userlist.py ---- pyslsk-1.0.0/pysoulseek/wxgui/userlist.py 2003-03-12 19:04:53.000000000 +0100 -+++ slsk-tmp/pysoulseek/wxgui/userlist.py 2003-03-12 21:55:17.000000000 +0100 -@@ -64,25 +64,25 @@ - self.SetItemCount(len(self.parent.frame.userlist)) - - self.menu = wxMenu() -+ removeID=wxNewId() -+ self.menu.Append(removeID, 'Remove') -+ EVT_MENU(self,removeID,self.OnRemove) -+ self.menu.AppendSeparator() - sendmessageID=wxNewId() - self.menu.Append(sendmessageID, 'Send Message') - EVT_MENU(self,sendmessageID, self.OnSendMessage) -- showipID=wxNewId() -- self.menu.Append(showipID, 'Show IP address') -- EVT_MENU(self,showipID, self.OnShowIp) - getinfoID=wxNewId() - self.menu.Append(getinfoID, 'Get User Info') - EVT_MENU(self,getinfoID, self.OnGetInfo) - browseID=wxNewId() - self.menu.Append(browseID, 'Browse Files') - EVT_MENU(self,browseID, self.OnBrowse) -+ showipID=wxNewId() -+ self.menu.Append(showipID, 'Show IP address') -+ EVT_MENU(self,showipID, self.OnShowIp) - banuserID=wxNewId() - self.menu.Append(banuserID, 'Ban this User') - EVT_MENU(self,banuserID, self.OnBanUser) -- self.menu.AppendSeparator() -- removeID=wxNewId() -- self.menu.Append(removeID, 'Remove') -- EVT_MENU(self,removeID,self.OnRemove) - - EVT_RIGHT_UP(self,self.OnRightUp) - -@@ -121,6 +121,9 @@ - def OnBanUser(self,event): - self.parent.frame.BanUser(self.focuseduser) - -+ def OnBanUser(self,event): -+ self.parent.frame.BanUser(self.focuseduser) -+ - def OnGetItemText(self, item, col): - user = self.parent.frame.userlist[item] - return self.GetColumnValue(user,col) -Files pyslsk-1.0.0/pysoulseek/wxgui/userlist.pyc and slsk-tmp/pysoulseek/wxgui/userlist.pyc differ -diff -rNu3 pyslsk-1.0.0/TODO.hyriand slsk-tmp/TODO.hyriand ---- pyslsk-1.0.0/TODO.hyriand 1970-01-01 01:00:00.000000000 +0100 -+++ slsk-tmp/TODO.hyriand 2003-03-12 21:31:36.000000000 +0100 -@@ -0,0 +1,6 @@ -+ - Keyboard shortcuts (tabs/etc) -+ -+ - Omni-present birdies? (to reduce flicker) -+ - Wishlist? -+ - Search filtering? -+ - wxHTML chat? diff --git a/net-p2p/pysoulseek/pysoulseek-1.0.0-r1.ebuild b/net-p2p/pysoulseek/pysoulseek-1.0.0-r1.ebuild deleted file mode 100644 index 5cabbbc42b61..000000000000 --- a/net-p2p/pysoulseek/pysoulseek-1.0.0-r1.ebuild +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 1999-2003 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/net-p2p/pysoulseek/pysoulseek-1.0.0-r1.ebuild,v 1.3 2003/03/16 17:31:00 liquidx Exp $ - -IUSE="oggvorbis" - -inherit eutils - -MY_PN="${PN/soulseek/slsk}" -MY_P="${MY_PN}-${PV}" -DESCRIPTION="client for SoulSeek filesharing" -HOMEPAGE="http://www.sensi.org/~ak/pyslsk/" -SRC_URI="http://www.sensi.org/~ak/pyslsk/${MY_P}.tar.gz" - -LICENSE="GPL-2" -SLOT="0" -KEYWORDS="x86 ~ppc ~sparc" - -DEPEND=">=dev-lang/python-2.1 - >=dev-python/wxPython-2.4.0.1 - ~x11-libs/wxGTK-2.4.0 - oggvorbis? ( media-libs/pyvorbis media-libs/pyogg )" - -S="${WORKDIR}/${MY_P}" - -src_compile() { - epatch ${FILESDIR}/${P}-hyriand-11.patch - python setup.py build || die "compile failed" -} - -src_install() { - python setup.py install --prefix=/usr --root=${D} || die "install failed" - dodoc CHANGELOG KNOWN_BUGS MAINTAINERS MANIFEST PKG-INFO README TODO VERSION -} diff --git a/net-p2p/pysoulseek/pysoulseek-1.0.3.12.7.ebuild b/net-p2p/pysoulseek/pysoulseek-1.0.3.12.7.ebuild deleted file mode 100644 index 752385a3115e..000000000000 --- a/net-p2p/pysoulseek/pysoulseek-1.0.3.12.7.ebuild +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 1999-2003 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/net-p2p/pysoulseek/pysoulseek-1.0.3.12.7.ebuild,v 1.3 2003/03/26 01:45:41 liquidx Exp $ - -IUSE="oggvorbis" - -inherit eutils - -MY_PN="${PN/soulseek/slsk}" - -# Main pysoulseek Package-Version -MY_P=${MY_PN}-${PV%.*.*} - -# Hyriand Patch Version -MY_HV=${PV#*.*.*.} - -DESCRIPTION="client for SoulSeek filesharing" -HOMEPAGE="http://www.sensi.org/~ak/pyslsk/" -SRC_URI="http://www.sensi.org/~ak/pyslsk/${MY_P}.tar.gz http://thegraveyard.org/pyslsk/${MY_P}-hyriand-${MY_HV}.patch" - -LICENSE="GPL-2" -SLOT="0" -KEYWORDS="x86 ~ppc ~sparc" - -DEPEND=">=dev-lang/python-2.1 - >=dev-python/wxPython-2.4.0.1 - ~x11-libs/wxGTK-2.4.0 - oggvorbis? ( media-libs/pyvorbis media-libs/pyogg )" - -RDEPEND=${DEPEND} - -S="${WORKDIR}/${MY_P}" - -src_compile() { - epatch ${DISTDIR}/${MY_P}-hyriand-${MY_HV}.patch - python setup.py build || die "compile failed" -} - -src_install() { - python setup.py install --prefix=/usr --root=${D} || die "install failed" - dodoc CHANGELOG KNOWN_BUGS MAINTAINERS MANIFEST PKG-INFO README TODO VERSION -} diff --git a/net-p2p/pysoulseek/pysoulseek-1.1.0_pre5.ebuild b/net-p2p/pysoulseek/pysoulseek-1.1.0_pre5.ebuild deleted file mode 100644 index 2356b1362822..000000000000 --- a/net-p2p/pysoulseek/pysoulseek-1.1.0_pre5.ebuild +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 1999-2003 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/net-p2p/pysoulseek/pysoulseek-1.1.0_pre5.ebuild,v 1.1 2003/04/19 14:17:32 liquidx Exp $ - -IUSE="oggvorbis" - -inherit eutils distutils - -MY_PN="${PN/soulseek/slsk}" - -# Hyriand Patch Version (skip first 3 version numbers) -# - disabled beacuse of _pre prefix -#MY_HV=${PV#*.*.*.} -MY_HV="1.4" - -# Main pysoulseek Package-Version (remove trailing MY_HV) -# - disabled because of _pre, stripping _ from versioning -#MY_P=${MY_PN}-${PV%.${MY_HV}} -MY_P=${MY_PN}-${PV/_/} - -DESCRIPTION="client for SoulSeek filesharing" -HOMEPAGE="http://www.sensi.org/~ak/pyslsk/ - http://thegraveyard.org/pyslsk/index.html" -SRC_URI="http://www.sensi.org/~ak/pyslsk/${MY_P}.tar.gz - http://thegraveyard.org/pyslsk/${MY_P}-hyriand-${MY_HV}.patch" - -LICENSE="GPL-2" -SLOT="0" -KEYWORDS="~x86 ~ppc ~sparc" - -DEPEND=">=dev-lang/python-2.1 - >=dev-python/wxPython-2.4.0.1 - ~x11-libs/wxGTK-2.4.0 - oggvorbis? ( media-libs/pyvorbis media-libs/pyogg )" - -RDEPEND=${DEPEND} - -S="${WORKDIR}/${MY_P}" - -src_unpack() { - unpack ${MY_P}.tar.gz - epatch ${DISTDIR}/${MY_P}-hyriand-${MY_HV}.patch -} diff --git a/net-p2p/pysoulseek/pysoulseek-1.1.1.1.6.ebuild b/net-p2p/pysoulseek/pysoulseek-1.1.1.1.6.ebuild index 438283f0a838..880d5fc9fe97 100644 --- a/net-p2p/pysoulseek/pysoulseek-1.1.1.1.6.ebuild +++ b/net-p2p/pysoulseek/pysoulseek-1.1.1.1.6.ebuild @@ -1,6 +1,6 @@ # Copyright 1999-2003 Gentoo Technologies, Inc. # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/net-p2p/pysoulseek/pysoulseek-1.1.1.1.6.ebuild,v 1.1 2003/04/29 08:55:39 liquidx Exp $ +# $Header: /var/cvsroot/gentoo-x86/net-p2p/pysoulseek/pysoulseek-1.1.1.1.6.ebuild,v 1.2 2003/04/30 23:27:55 liquidx Exp $ IUSE="oggvorbis" @@ -19,7 +19,7 @@ SRC_URI="http://www.sensi.org/~ak/pyslsk/${MY_P}.tar.gz LICENSE="GPL-2" SLOT="0" -KEYWORDS="~x86 ~ppc ~sparc" +KEYWORDS="x86 ~ppc ~sparc" DEPEND=">=dev-lang/python-2.1 >=dev-python/wxPython-2.4.0.1 diff --git a/net-p2p/pysoulseek/pysoulseek-1.0.4.13.ebuild b/net-p2p/pysoulseek/pysoulseek-1.1.2.1.7.ebuild index d4daddf204a8..e8490e64f44a 100644 --- a/net-p2p/pysoulseek/pysoulseek-1.0.4.13.ebuild +++ b/net-p2p/pysoulseek/pysoulseek-1.1.2.1.7.ebuild @@ -1,6 +1,6 @@ # Copyright 1999-2003 Gentoo Technologies, Inc. # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/net-p2p/pysoulseek/pysoulseek-1.0.4.13.ebuild,v 1.1 2003/03/28 23:34:59 liquidx Exp $ +# $Header: /var/cvsroot/gentoo-x86/net-p2p/pysoulseek/pysoulseek-1.1.2.1.7.ebuild,v 1.1 2003/04/30 23:27:55 liquidx Exp $ IUSE="oggvorbis" @@ -8,13 +8,12 @@ inherit eutils distutils MY_PN="${PN/soulseek/slsk}" -# Hyriand Patch Version (skip first 3 version numbers) MY_HV=${PV#*.*.*.} -# Main pysoulseek Package-Version (remove trailing MY_HV) MY_P=${MY_PN}-${PV%.${MY_HV}} DESCRIPTION="client for SoulSeek filesharing" -HOMEPAGE="http://www.sensi.org/~ak/pyslsk/ http://thegraveyard.org/pyslsk/index-1.0.0.html" +HOMEPAGE="http://www.sensi.org/~ak/pyslsk/ + http://thegraveyard.org/pyslsk/index.html" SRC_URI="http://www.sensi.org/~ak/pyslsk/${MY_P}.tar.gz http://thegraveyard.org/pyslsk/${MY_P}-hyriand-${MY_HV}.patch" |