diff options
-rw-r--r-- | NohGooee/BeautifulSupe.py (renamed from BitTorrent/BeautifulSupe.py) | 0 | ||||
-rw-r--r-- | NohGooee/Choker.py (renamed from BitTorrent/Choker.py) | 0 | ||||
-rw-r--r-- | NohGooee/ClientIdentifier.py (renamed from BitTorrent/ClientIdentifier.py) | 0 | ||||
-rw-r--r-- | NohGooee/Connecter.py (renamed from BitTorrent/Connecter.py) | 4 | ||||
-rw-r--r-- | NohGooee/ConvertedMetainfo.py (renamed from BitTorrent/ConvertedMetainfo.py) | 6 | ||||
-rw-r--r-- | NohGooee/CurrentRateMeasure.py (renamed from BitTorrent/CurrentRateMeasure.py) | 2 | ||||
-rw-r--r-- | NohGooee/Desktop.py (renamed from BitTorrent/Desktop.py) | 2 | ||||
-rw-r--r-- | NohGooee/Downloader.py (renamed from BitTorrent/Downloader.py) | 6 | ||||
-rw-r--r-- | NohGooee/DownloaderFeedback.py (renamed from BitTorrent/DownloaderFeedback.py) | 0 | ||||
-rw-r--r-- | NohGooee/Encoder.py (renamed from BitTorrent/Encoder.py) | 12 | ||||
-rw-r--r-- | NohGooee/GUI.py (renamed from BitTorrent/GUI.py) | 6 | ||||
-rw-r--r-- | NohGooee/GetTorrent.py (renamed from BitTorrent/GetTorrent.py) | 2 | ||||
-rw-r--r-- | NohGooee/IPC.py (renamed from BitTorrent/IPC.py) | 6 | ||||
-rw-r--r-- | NohGooee/LaunchPath.py (renamed from BitTorrent/LaunchPath.py) | 0 | ||||
-rw-r--r-- | NohGooee/NatCheck.py (renamed from BitTorrent/NatCheck.py) | 0 | ||||
-rw-r--r-- | NohGooee/NatTraversal.py (renamed from BitTorrent/NatTraversal.py) | 10 | ||||
-rw-r--r-- | NohGooee/NewVersion.py (renamed from BitTorrent/NewVersion.py) | 10 | ||||
-rw-r--r-- | NohGooee/PeerID.py (renamed from BitTorrent/PeerID.py) | 2 | ||||
-rw-r--r-- | NohGooee/PiecePicker.py (renamed from BitTorrent/PiecePicker.py) | 0 | ||||
-rw-r--r-- | NohGooee/RateLimiter.py (renamed from BitTorrent/RateLimiter.py) | 2 | ||||
-rw-r--r-- | NohGooee/RateMeasure.py (renamed from BitTorrent/RateMeasure.py) | 2 | ||||
-rw-r--r-- | NohGooee/Rerequester.py (renamed from BitTorrent/Rerequester.py) | 12 | ||||
-rw-r--r-- | NohGooee/StatusLight.py (renamed from BitTorrent/StatusLight.py) | 2 | ||||
-rw-r--r-- | NohGooee/Storage.py (renamed from BitTorrent/Storage.py) | 2 | ||||
-rw-r--r-- | NohGooee/StorageWrapper.py (renamed from BitTorrent/StorageWrapper.py) | 4 | ||||
-rw-r--r-- | NohGooee/TorrentQueue.py (renamed from BitTorrent/TorrentQueue.py) | 18 | ||||
-rw-r--r-- | NohGooee/TrayIcon.py (renamed from BitTorrent/TrayIcon.py) | 8 | ||||
-rw-r--r-- | NohGooee/Uploader.py (renamed from BitTorrent/Uploader.py) | 2 | ||||
-rw-r--r-- | NohGooee/__init__.py (renamed from BitTorrent/__init__.py) | 6 | ||||
-rw-r--r-- | NohGooee/bencode.py (renamed from BitTorrent/bencode.py) | 2 | ||||
-rw-r--r-- | NohGooee/bitfield.py (renamed from BitTorrent/bitfield.py) | 0 | ||||
-rw-r--r-- | NohGooee/btformats.py (renamed from BitTorrent/btformats.py) | 2 | ||||
-rw-r--r-- | NohGooee/configfile.py (renamed from BitTorrent/configfile.py) | 10 | ||||
-rw-r--r-- | NohGooee/defaultargs.py (renamed from BitTorrent/defaultargs.py) | 4 | ||||
-rw-r--r-- | NohGooee/defer.py (renamed from BitTorrent/defer.py) | 0 | ||||
-rw-r--r-- | NohGooee/download.py (renamed from BitTorrent/download.py) | 46 | ||||
-rw-r--r-- | NohGooee/language.py (renamed from BitTorrent/language.py) | 0 | ||||
-rw-r--r-- | NohGooee/launchmanycore.py (renamed from BitTorrent/launchmanycore.py) | 10 | ||||
-rw-r--r-- | NohGooee/makemetafile.py (renamed from BitTorrent/makemetafile.py) | 8 | ||||
-rw-r--r-- | NohGooee/parseargs.py (renamed from BitTorrent/parseargs.py) | 10 | ||||
-rw-r--r-- | NohGooee/parsedir.py (renamed from BitTorrent/parsedir.py) | 4 | ||||
-rw-r--r-- | NohGooee/platform.py (renamed from BitTorrent/platform.py) | 4 | ||||
-rw-r--r-- | NohGooee/prefs.py (renamed from BitTorrent/prefs.py) | 0 | ||||
-rw-r--r-- | NohGooee/selectpoll.py (renamed from BitTorrent/selectpoll.py) | 0 | ||||
-rw-r--r-- | NohGooee/track.py (renamed from BitTorrent/track.py) | 12 | ||||
-rw-r--r-- | NohGooee/zurllib.py (renamed from BitTorrent/zurllib.py) | 2 | ||||
l--------- | bittorrent | 1 | ||||
l--------- | bittorrent-console | 1 | ||||
-rwxr-xr-x | bittorrent-console.py | 308 | ||||
l--------- | bittorrent-curses | 1 | ||||
-rwxr-xr-x | bittorrent-curses.py | 449 | ||||
l--------- | bittorrent-tracker | 1 | ||||
-rw-r--r-- | bittorrent.desktop | 11 | ||||
-rw-r--r-- | bittorrent.png | bin | 1729 -> 0 bytes | |||
-rwxr-xr-x | bittorrent.py | 3834 | ||||
l--------- | changetracker-console | 1 | ||||
-rw-r--r-- | images/bittorrent.ico | bin | 13902 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/abort.png | bin | 3856 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/broken.png | bin | 3827 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/finished.png | bin | 3885 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/info.png | bin | 3824 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/pause.png | bin | 3137 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/paused.png | bin | 3230 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/play.png | bin | 3465 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/queued.png | bin | 4285 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/remove.png | bin | 3916 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/running.png | bin | 3472 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/status-broken.png | bin | 3179 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/status-natted.png | bin | 3286 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/status-pre-natted.png | bin | 3316 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/status-running.png | bin | 3433 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/status-starting.png | bin | 3226 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/status-stopped.png | bin | 3101 -> 0 bytes | |||
-rw-r--r-- | images/icons/default/trashcan.png | bin | 3321 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/broken.png | bin | 1046 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/finished.png | bin | 1076 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/info.png | bin | 1162 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/pause.png | bin | 450 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/paused.png | bin | 1668 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/play.png | bin | 759 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/queued.png | bin | 1650 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/remove.png | bin | 315 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/running.png | bin | 799 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/status-broken.png | bin | 821 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/status-natted.png | bin | 762 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/status-pre-natted.png | bin | 767 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/status-running.png | bin | 653 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/status-starting.png | bin | 811 -> 0 bytes | |||
-rw-r--r-- | images/icons/old/status-stopped.png | bin | 821 -> 0 bytes | |||
-rw-r--r-- | images/logo/bittorrent_32.png | bin | 4326 -> 0 bytes | |||
-rw-r--r-- | images/logo/bittorrent_96.png | bin | 19020 -> 0 bytes | |||
-rw-r--r-- | khashmir/KRateLimiter.py | 4 | ||||
-rw-r--r-- | khashmir/actions.py | 2 | ||||
-rw-r--r-- | khashmir/cache.py | 2 | ||||
-rw-r--r-- | khashmir/inserter.py | 4 | ||||
-rw-r--r-- | khashmir/khashmir.py | 10 | ||||
-rw-r--r-- | khashmir/knode.py | 2 | ||||
-rw-r--r-- | khashmir/krpc.py | 8 | ||||
-rw-r--r-- | khashmir/kstore.py | 2 | ||||
-rw-r--r-- | khashmir/ktable.py | 2 | ||||
-rw-r--r-- | khashmir/node.py | 2 | ||||
-rw-r--r-- | khashmir/test_khashmir.py | 2 | ||||
-rw-r--r-- | khashmir/test_krpc.py | 2 | ||||
-rw-r--r-- | khashmir/test_kstore.py | 2 | ||||
-rw-r--r-- | khashmir/unet.py | 4 | ||||
-rw-r--r-- | language_codes.py | 4 | ||||
l--------- | launchmany-console | 1 | ||||
l--------- | launchmany-curses | 1 | ||||
-rwxr-xr-x | launchmany-curses.py | 301 | ||||
l--------- | maketorrent | 1 | ||||
l--------- | maketorrent-console | 1 | ||||
-rwxr-xr-x | maketorrent.py | 577 | ||||
-rwxr-xr-x | nohgooee-changetracker (renamed from changetracker-console.py) | 4 | ||||
-rwxr-xr-x | nohgooee-maketorrent (renamed from maketorrent-console.py) | 12 | ||||
-rwxr-xr-x | nohgooee-seed (renamed from launchmany-console.py) | 14 | ||||
-rwxr-xr-x | nohgooee-seed.init (renamed from btseed.init) | 0 | ||||
-rwxr-xr-x | nohgooee-torrentinfo (renamed from torrentinfo-console.py) | 6 | ||||
-rwxr-xr-x | nohgooee-tracker.init (renamed from bttrack.init) | 0 | ||||
-rwxr-xr-x | nohgooee-tracker.tac (renamed from bittorrent-tracker.py) | 4 | ||||
-rw-r--r-- | redirdonate.html | 1 | ||||
-rw-r--r-- | setup.py | 6 | ||||
-rw-r--r-- | test/test_ClientIdentifier.py | 2 | ||||
l--------- | torrentinfo-console | 1 |
123 files changed, 170 insertions, 5661 deletions
diff --git a/BitTorrent/BeautifulSupe.py b/NohGooee/BeautifulSupe.py index 79072d4..79072d4 100644 --- a/BitTorrent/BeautifulSupe.py +++ b/NohGooee/BeautifulSupe.py diff --git a/BitTorrent/Choker.py b/NohGooee/Choker.py index ed3d500..ed3d500 100644 --- a/BitTorrent/Choker.py +++ b/NohGooee/Choker.py diff --git a/BitTorrent/ClientIdentifier.py b/NohGooee/ClientIdentifier.py index cec2fa5..cec2fa5 100644 --- a/BitTorrent/ClientIdentifier.py +++ b/NohGooee/ClientIdentifier.py diff --git a/BitTorrent/Connecter.py b/NohGooee/Connecter.py index 5fc3add..830fd82 100644 --- a/BitTorrent/Connecter.py +++ b/NohGooee/Connecter.py @@ -13,8 +13,8 @@ from binascii import b2a_hex from struct import pack, unpack -from BitTorrent.RawServer_magic import Handler -from BitTorrent.bitfield import Bitfield +from NohGooee.RawServer_magic import Handler +from NohGooee.bitfield import Bitfield def toint(s): return unpack("!i", s)[0] diff --git a/BitTorrent/ConvertedMetainfo.py b/NohGooee/ConvertedMetainfo.py index 0e22205..9b2459f 100644 --- a/BitTorrent/ConvertedMetainfo.py +++ b/NohGooee/ConvertedMetainfo.py @@ -14,9 +14,9 @@ import os import sys from sha import sha -from BitTorrent.bencode import bencode -from BitTorrent import btformats -from BitTorrent import BTFailure, WARNING, ERROR +from NohGooee.bencode import bencode +from NohGooee import btformats +from NohGooee import BTFailure, WARNING, ERROR WINDOWS_UNSUPPORTED_CHARS ='"*/:<>?\|' diff --git a/BitTorrent/CurrentRateMeasure.py b/NohGooee/CurrentRateMeasure.py index 3dd940f..86e16da 100644 --- a/BitTorrent/CurrentRateMeasure.py +++ b/NohGooee/CurrentRateMeasure.py @@ -10,7 +10,7 @@ # Written by Bram Cohen -from BitTorrent.platform import bttime +from NohGooee.platform import bttime class Measure(object): diff --git a/BitTorrent/Desktop.py b/NohGooee/Desktop.py index b724811..e8955c3 100644 --- a/BitTorrent/Desktop.py +++ b/NohGooee/Desktop.py @@ -13,7 +13,7 @@ import os import sys -from BitTorrent.platform import get_home_dir, get_shell_dir +from NohGooee.platform import get_home_dir, get_shell_dir if os.name == 'nt': from win32com.shell import shellcon diff --git a/BitTorrent/Downloader.py b/NohGooee/Downloader.py index accb332..ca5f973 100644 --- a/BitTorrent/Downloader.py +++ b/NohGooee/Downloader.py @@ -12,9 +12,9 @@ from random import shuffle -from BitTorrent.platform import bttime -from BitTorrent.CurrentRateMeasure import Measure -from BitTorrent.bitfield import Bitfield +from NohGooee.platform import bttime +from NohGooee.CurrentRateMeasure import Measure +from NohGooee.bitfield import Bitfield class PerIPStats(object): diff --git a/BitTorrent/DownloaderFeedback.py b/NohGooee/DownloaderFeedback.py index 6c16c90..6c16c90 100644 --- a/BitTorrent/DownloaderFeedback.py +++ b/NohGooee/DownloaderFeedback.py diff --git a/BitTorrent/Encoder.py b/NohGooee/Encoder.py index a5bd6dc..8675823 100644 --- a/BitTorrent/Encoder.py +++ b/NohGooee/Encoder.py @@ -12,12 +12,12 @@ from socket import error as socketerror -from BitTorrent import BTFailure -from BitTorrent.RawServer_magic import Handler -from BitTorrent.NatTraversal import UPNPError -from BitTorrent.Connecter import Connection -from BitTorrent.platform import is_frozen_exe -from BitTorrent.ClientIdentifier import identify_client +from NohGooee import BTFailure +from NohGooee.RawServer_magic import Handler +from NohGooee.NatTraversal import UPNPError +from NohGooee.Connecter import Connection +from NohGooee.platform import is_frozen_exe +from NohGooee.ClientIdentifier import identify_client # header, reserved, download id, my id, [length, message] diff --git a/BitTorrent/GUI.py b/NohGooee/GUI.py index 0497367..a4a677c 100644 --- a/BitTorrent/GUI.py +++ b/NohGooee/GUI.py @@ -21,8 +21,8 @@ import threading assert gtk.gtk_version >= (2, 6), _( "GTK %s or newer required") % '2.6' assert gtk.pygtk_version >= (2, 6), _("PyGTK %s or newer required") % '2.6' -from BitTorrent import app_name, FAQ_URL, languages, language_names -from BitTorrent.platform import image_root, read_language_file, write_language_file +from NohGooee import app_name, FAQ_URL, languages, language_names +from NohGooee.platform import image_root, read_language_file, write_language_file def lock_wrap(function, *args): gtk.gdk.threads_enter() @@ -451,7 +451,7 @@ class FileSelection(IconMixin, gtk.FileChooserDialog): buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) IconMixin.__init__(self) - from BitTorrent.ConvertedMetainfo import filesystem_encoding + from NohGooee.ConvertedMetainfo import filesystem_encoding self.fsenc = filesystem_encoding try: fullname.decode('utf8') diff --git a/BitTorrent/GetTorrent.py b/NohGooee/GetTorrent.py index a69651c..dcbcb50 100644 --- a/BitTorrent/GetTorrent.py +++ b/NohGooee/GetTorrent.py @@ -17,7 +17,7 @@ import os import re import zurllib from bencode import bdecode -from BitTorrent.platform import get_cache_dir +from NohGooee.platform import get_cache_dir urlpat = re.compile('^\w+://') urlpat_torrent = re.compile('^torrent://') diff --git a/BitTorrent/IPC.py b/NohGooee/IPC.py index de50434..11d910b 100644 --- a/BitTorrent/IPC.py +++ b/NohGooee/IPC.py @@ -25,9 +25,9 @@ if os.name == 'nt': from binascii import b2a_hex -from BitTorrent.RawServer_magic import RawServer, Handler -from BitTorrent.platform import get_home_dir, get_config_dir -from BitTorrent import INFO, WARNING, ERROR, CRITICAL, BTFailure, app_name +from NohGooee.RawServer_magic import RawServer, Handler +from NohGooee.platform import get_home_dir, get_config_dir +from NohGooee import INFO, WARNING, ERROR, CRITICAL, BTFailure, app_name def toint(s): return int(b2a_hex(s), 16) diff --git a/BitTorrent/LaunchPath.py b/NohGooee/LaunchPath.py index 3c78845..3c78845 100644 --- a/BitTorrent/LaunchPath.py +++ b/NohGooee/LaunchPath.py diff --git a/BitTorrent/NatCheck.py b/NohGooee/NatCheck.py index fe59a15..fe59a15 100644 --- a/BitTorrent/NatCheck.py +++ b/NohGooee/NatCheck.py diff --git a/BitTorrent/NatTraversal.py b/NohGooee/NatTraversal.py index 30eb377..a6c96e3 100644 --- a/BitTorrent/NatTraversal.py +++ b/NohGooee/NatTraversal.py @@ -26,11 +26,11 @@ except NameError: # python 2.2 pass -from BitTorrent import app_name, defer -from BitTorrent import INFO, WARNING, ERROR -from BitTorrent.platform import os_version -from BitTorrent.RawServer_magic import RawServer, Handler -from BitTorrent.BeautifulSupe import BeautifulSupe, Tag +from NohGooee import app_name, defer +from NohGooee import INFO, WARNING, ERROR +from NohGooee.platform import os_version +from NohGooee.RawServer_magic import RawServer, Handler +from NohGooee.BeautifulSupe import BeautifulSupe, Tag from urllib2 import URLError, HTTPError, Request #bleh diff --git a/BitTorrent/NewVersion.py b/NohGooee/NewVersion.py index 25445ae..96ed2f5 100644 --- a/BitTorrent/NewVersion.py +++ b/NohGooee/NewVersion.py @@ -19,11 +19,11 @@ from sha import sha DEBUG = False -from BitTorrent import ERROR, WARNING, BTFailure, version, app_name -from BitTorrent import GetTorrent -from BitTorrent.bencode import bdecode, bencode -from BitTorrent.platform import os_version, spawn, get_temp_dir, doc_root, is_frozen_exe, osx -from BitTorrent.ConvertedMetainfo import ConvertedMetainfo +from NohGooee import ERROR, WARNING, BTFailure, version, app_name +from NohGooee import GetTorrent +from NohGooee.bencode import bdecode, bencode +from NohGooee.platform import os_version, spawn, get_temp_dir, doc_root, is_frozen_exe, osx +from NohGooee.ConvertedMetainfo import ConvertedMetainfo if osx: from Foundation import NSAutoreleasePool diff --git a/BitTorrent/PeerID.py b/NohGooee/PeerID.py index 9dc9285..d116abe 100644 --- a/BitTorrent/PeerID.py +++ b/NohGooee/PeerID.py @@ -19,7 +19,7 @@ except AttributeError: def getpid(): return 1 -from BitTorrent import version +from NohGooee import version def make_id(): myid = 'M' + version.split()[0].replace('.', '-') diff --git a/BitTorrent/PiecePicker.py b/NohGooee/PiecePicker.py index e22b13a..e22b13a 100644 --- a/BitTorrent/PiecePicker.py +++ b/NohGooee/PiecePicker.py diff --git a/BitTorrent/RateLimiter.py b/NohGooee/RateLimiter.py index d58f2c4..12d3205 100644 --- a/BitTorrent/RateLimiter.py +++ b/NohGooee/RateLimiter.py @@ -10,7 +10,7 @@ # Written by Uoti Urpala and Andrew Loewenstern -from BitTorrent.platform import bttime +from NohGooee.platform import bttime def minctx(a,b): A = B = 0 diff --git a/BitTorrent/RateMeasure.py b/NohGooee/RateMeasure.py index b609330..e5101ff 100644 --- a/BitTorrent/RateMeasure.py +++ b/NohGooee/RateMeasure.py @@ -10,7 +10,7 @@ # Written by Bram Cohen -from BitTorrent.platform import bttime +from NohGooee.platform import bttime class RateMeasure(object): diff --git a/BitTorrent/Rerequester.py b/NohGooee/Rerequester.py index 93d9472..b899ca9 100644 --- a/BitTorrent/Rerequester.py +++ b/NohGooee/Rerequester.py @@ -15,12 +15,12 @@ from socket import error, gethostbyname from random import random, randrange from binascii import b2a_hex -from BitTorrent import version -from BitTorrent.platform import bttime -from BitTorrent.zurllib import urlopen, quote, Request -from BitTorrent.btformats import check_peers -from BitTorrent.bencode import bencode, bdecode -from BitTorrent import BTFailure, INFO, WARNING, ERROR, CRITICAL +from NohGooee import version +from NohGooee.platform import bttime +from NohGooee.zurllib import urlopen, quote, Request +from NohGooee.btformats import check_peers +from NohGooee.bencode import bencode, bdecode +from NohGooee import BTFailure, INFO, WARNING, ERROR, CRITICAL class Rerequester(object): diff --git a/BitTorrent/StatusLight.py b/NohGooee/StatusLight.py index 11cbf14..e1668e4 100644 --- a/BitTorrent/StatusLight.py +++ b/NohGooee/StatusLight.py @@ -1,4 +1,4 @@ -from BitTorrent.platform import bttime +from NohGooee.platform import bttime class StatusLight(object): diff --git a/BitTorrent/Storage.py b/NohGooee/Storage.py index 8f1d6fb..7a766bd 100644 --- a/BitTorrent/Storage.py +++ b/NohGooee/Storage.py @@ -14,7 +14,7 @@ import os from bisect import bisect_right from array import array -from BitTorrent import BTFailure, app_name +from NohGooee import BTFailure, app_name class FilePool(object): diff --git a/BitTorrent/StorageWrapper.py b/NohGooee/StorageWrapper.py index ac14fdd..7955f95 100644 --- a/BitTorrent/StorageWrapper.py +++ b/NohGooee/StorageWrapper.py @@ -16,8 +16,8 @@ from sha import sha from array import array from binascii import b2a_hex -from BitTorrent.bitfield import Bitfield -from BitTorrent import BTFailure, INFO, WARNING, ERROR, CRITICAL +from NohGooee.bitfield import Bitfield +from NohGooee import BTFailure, INFO, WARNING, ERROR, CRITICAL def toint(s): return int(b2a_hex(s), 16) diff --git a/BitTorrent/TorrentQueue.py b/NohGooee/TorrentQueue.py index 4187a80..bf369be 100644 --- a/BitTorrent/TorrentQueue.py +++ b/NohGooee/TorrentQueue.py @@ -18,15 +18,15 @@ import threading import traceback -from BitTorrent import GetTorrent -from BitTorrent.platform import bttime -from BitTorrent.download import Feedback, Multitorrent -from BitTorrent.bencode import bdecode -from BitTorrent.ConvertedMetainfo import ConvertedMetainfo -from BitTorrent.prefs import Preferences -from BitTorrent import BTFailure, BTShutdown, INFO, WARNING, ERROR, CRITICAL -from BitTorrent import configfile -from BitTorrent import FAQ_URL +from NohGooee import GetTorrent +from NohGooee.platform import bttime +from NohGooee.download import Feedback, Multitorrent +from NohGooee.bencode import bdecode +from NohGooee.ConvertedMetainfo import ConvertedMetainfo +from NohGooee.prefs import Preferences +from NohGooee import BTFailure, BTShutdown, INFO, WARNING, ERROR, CRITICAL +from NohGooee import configfile +from NohGooee import FAQ_URL import BitTorrent diff --git a/BitTorrent/TrayIcon.py b/NohGooee/TrayIcon.py index ac7620d..d48dd2e 100644 --- a/BitTorrent/TrayIcon.py +++ b/NohGooee/TrayIcon.py @@ -1,8 +1,8 @@ import os -from BitTorrent import app_name -from BitTorrent.GUI import gtk_wrap -from BitTorrent.platform import image_root +from NohGooee import app_name +from NohGooee.GUI import gtk_wrap +from NohGooee.platform import image_root if os.name == 'nt': from systray import systray @@ -86,7 +86,7 @@ else: if __name__ == '__main__': import threading - from BitTorrent.platform import install_translation + from NohGooee.platform import install_translation install_translation() ti = TrayIcon(True) th = threading.Thread(target=ti.enable, args=()) diff --git a/BitTorrent/Uploader.py b/NohGooee/Uploader.py index d02bfa8..ce98949 100644 --- a/BitTorrent/Uploader.py +++ b/NohGooee/Uploader.py @@ -10,7 +10,7 @@ # Written by Bram Cohen -from BitTorrent.CurrentRateMeasure import Measure +from NohGooee.CurrentRateMeasure import Measure class Upload(object): diff --git a/BitTorrent/__init__.py b/NohGooee/__init__.py index cae9c77..5dc8996 100644 --- a/BitTorrent/__init__.py +++ b/NohGooee/__init__.py @@ -21,12 +21,12 @@ branch = None if os.access('.cdv', os.F_OK): branch = os.path.split(os.path.realpath(os.path.split(sys.argv[0])[0]))[1] -from BitTorrent.language import languages, language_names -from BitTorrent.platform import get_home_dir, is_frozen_exe +from NohGooee.language import languages, language_names +from NohGooee.platform import get_home_dir, is_frozen_exe if os.name == 'posix': if os.uname()[0] == "Darwin": - from BitTorrent.platform import install_translation + from NohGooee.platform import install_translation install_translation() del sys, get_home_dir, is_frozen_exe diff --git a/BitTorrent/bencode.py b/NohGooee/bencode.py index 2fcdeb8..f544286 100644 --- a/BitTorrent/bencode.py +++ b/NohGooee/bencode.py @@ -10,7 +10,7 @@ # Written by Petru Paler -from BitTorrent import BTFailure +from NohGooee import BTFailure def decode_int(x, f): f += 1 diff --git a/BitTorrent/bitfield.py b/NohGooee/bitfield.py index bede74f..bede74f 100644 --- a/BitTorrent/bitfield.py +++ b/NohGooee/bitfield.py diff --git a/BitTorrent/btformats.py b/NohGooee/btformats.py index 97e62df..632fe27 100644 --- a/BitTorrent/btformats.py +++ b/NohGooee/btformats.py @@ -12,7 +12,7 @@ import re -from BitTorrent import BTFailure +from NohGooee import BTFailure allowed_path_re = re.compile(r'^[^/\\.~][^/\\]*$') diff --git a/BitTorrent/configfile.py b/NohGooee/configfile.py index 6f4a1e3..49c4e4f 100644 --- a/BitTorrent/configfile.py +++ b/NohGooee/configfile.py @@ -22,11 +22,11 @@ except ImportError: from ConfigParser import ConfigParser as RawConfigParser from ConfigParser import MissingSectionHeaderError, ParsingError -from BitTorrent import parseargs -from BitTorrent import app_name, version, ERROR, BTFailure -from BitTorrent.platform import get_config_dir, locale_root, is_frozen_exe -from BitTorrent.defaultargs import MYTRUE -from BitTorrent.zurllib import bind_tracker_connection, set_zurllib_rawserver +from NohGooee import parseargs +from NohGooee import app_name, version, ERROR, BTFailure +from NohGooee.platform import get_config_dir, locale_root, is_frozen_exe +from NohGooee.defaultargs import MYTRUE +from NohGooee.zurllib import bind_tracker_connection, set_zurllib_rawserver MAIN_CONFIG_FILE = 'ui_config' TORRENT_CONFIG_FILE = 'torrent_config' diff --git a/BitTorrent/defaultargs.py b/NohGooee/defaultargs.py index 2c7af5c..dc9583a 100644 --- a/BitTorrent/defaultargs.py +++ b/NohGooee/defaultargs.py @@ -36,12 +36,12 @@ if os.name == 'posix': MIN_INCOMPLETE = 100 if os.name == 'nt': - from BitTorrent.platform import win_version_num + from NohGooee.platform import win_version_num # starting in XP SP2 the incomplete outgoing connection limit was set to 10 if win_version_num >= (2, 5, 1, 2, 0): MIN_INCOMPLETE = 10 -from BitTorrent import languages +from NohGooee import languages basic_options = [ ('data_dir', '', diff --git a/BitTorrent/defer.py b/NohGooee/defer.py index 4531271..4531271 100644 --- a/BitTorrent/defer.py +++ b/NohGooee/defer.py diff --git a/BitTorrent/download.py b/NohGooee/download.py index d17b685..e3248c4 100644 --- a/BitTorrent/download.py +++ b/NohGooee/download.py @@ -25,29 +25,29 @@ from cStringIO import StringIO from traceback import print_exc from math import sqrt -from BitTorrent.btformats import check_message -from BitTorrent.Choker import Choker -from BitTorrent.Storage import Storage, FilePool -from BitTorrent.StorageWrapper import StorageWrapper -from BitTorrent.Uploader import Upload -from BitTorrent.Downloader import Downloader -from BitTorrent.Encoder import Encoder, SingleportListener -from BitTorrent.zurllib import set_zurllib_rawserver, add_unsafe_thread -from BitTorrent import PeerID - -from BitTorrent.RateLimiter import MultiRateLimiter as RateLimiter -from BitTorrent.RateLimiter import RateLimitedGroup - -from BitTorrent.RawServer_magic import RawServer -from BitTorrent.NatTraversal import NatTraverser -from BitTorrent.Rerequester import Rerequester, DHTRerequester -from BitTorrent.DownloaderFeedback import DownloaderFeedback -from BitTorrent.RateMeasure import RateMeasure -from BitTorrent.CurrentRateMeasure import Measure -from BitTorrent.PiecePicker import PiecePicker -from BitTorrent.ConvertedMetainfo import set_filesystem_encoding -from BitTorrent import version -from BitTorrent import BTFailure, BTShutdown, INFO, WARNING, ERROR, CRITICAL +from NohGooee.btformats import check_message +from NohGooee.Choker import Choker +from NohGooee.Storage import Storage, FilePool +from NohGooee.StorageWrapper import StorageWrapper +from NohGooee.Uploader import Upload +from NohGooee.Downloader import Downloader +from NohGooee.Encoder import Encoder, SingleportListener +from NohGooee.zurllib import set_zurllib_rawserver, add_unsafe_thread +from NohGooee import PeerID + +from NohGooee.RateLimiter import MultiRateLimiter as RateLimiter +from NohGooee.RateLimiter import RateLimitedGroup + +from NohGooee.RawServer_magic import RawServer +from NohGooee.NatTraversal import NatTraverser +from NohGooee.Rerequester import Rerequester, DHTRerequester +from NohGooee.DownloaderFeedback import DownloaderFeedback +from NohGooee.RateMeasure import RateMeasure +from NohGooee.CurrentRateMeasure import Measure +from NohGooee.PiecePicker import PiecePicker +from NohGooee.ConvertedMetainfo import set_filesystem_encoding +from NohGooee import version +from NohGooee import BTFailure, BTShutdown, INFO, WARNING, ERROR, CRITICAL from khashmir.utkhashmir import UTKhashmir from khashmir import const diff --git a/BitTorrent/language.py b/NohGooee/language.py index f7f72ef..f7f72ef 100644 --- a/BitTorrent/language.py +++ b/NohGooee/language.py diff --git a/BitTorrent/launchmanycore.py b/NohGooee/launchmanycore.py index 955f88a..bf83fea 100644 --- a/BitTorrent/launchmanycore.py +++ b/NohGooee/launchmanycore.py @@ -15,11 +15,11 @@ import os from cStringIO import StringIO from traceback import print_exc -from BitTorrent import configfile -from BitTorrent.parsedir import parsedir -from BitTorrent.download import Multitorrent, Feedback -from BitTorrent.ConvertedMetainfo import ConvertedMetainfo -from BitTorrent import BTFailure +from NohGooee import configfile +from NohGooee.parsedir import parsedir +from NohGooee.download import Multitorrent, Feedback +from NohGooee.ConvertedMetainfo import ConvertedMetainfo +from NohGooee import BTFailure from threading import Event from time import time diff --git a/BitTorrent/makemetafile.py b/NohGooee/makemetafile.py index 798f325..ccd721d 100644 --- a/BitTorrent/makemetafile.py +++ b/NohGooee/makemetafile.py @@ -18,10 +18,10 @@ from sha import sha from time import time from threading import Event -from BitTorrent.bencode import bencode, bdecode -from BitTorrent.btformats import check_info -from BitTorrent.parseargs import parseargs, printHelp -from BitTorrent import BTFailure +from NohGooee.bencode import bencode, bdecode +from NohGooee.btformats import check_info +from NohGooee.parseargs import parseargs, printHelp +from NohGooee import BTFailure from khashmir.node import Node from khashmir.ktable import KTable diff --git a/BitTorrent/parseargs.py b/NohGooee/parseargs.py index bd38558..e2f773a 100644 --- a/BitTorrent/parseargs.py +++ b/NohGooee/parseargs.py @@ -13,10 +13,10 @@ from types import * from cStringIO import StringIO -from BitTorrent.defaultargs import MyBool, MYTRUE -from BitTorrent import BTFailure -from BitTorrent.bencode import bdecode -from BitTorrent.platform import is_frozen_exe +from NohGooee.defaultargs import MyBool, MYTRUE +from NohGooee import BTFailure +from NohGooee.bencode import bdecode +from NohGooee.platform import is_frozen_exe def makeHelp(uiname, defaults): ret = '' @@ -37,7 +37,7 @@ def makeHelp(uiname, defaults): def printHelp(uiname, defaults): if uiname in ('bittorrent','maketorrent') and is_frozen_exe: - from BitTorrent.GUI import HelpWindow + from NohGooee.GUI import HelpWindow HelpWindow(None, makeHelp(uiname, defaults)) else: print makeHelp(uiname, defaults) diff --git a/BitTorrent/parsedir.py b/NohGooee/parsedir.py index 3b86a03..2ffe1c2 100644 --- a/BitTorrent/parsedir.py +++ b/NohGooee/parsedir.py @@ -13,8 +13,8 @@ import os from sha import sha -from BitTorrent.bencode import bencode, bdecode -from BitTorrent.btformats import check_message +from NohGooee.bencode import bencode, bdecode +from NohGooee.btformats import check_message NOISY = False diff --git a/BitTorrent/platform.py b/NohGooee/platform.py index 8435397..4749fd3 100644 --- a/BitTorrent/platform.py +++ b/NohGooee/platform.py @@ -33,8 +33,8 @@ elif os.name == 'posix' and os.uname()[0] == 'Darwin': except ImportError: pass -from BitTorrent import app_name, version -from BitTorrent.language import locale_sucks +from NohGooee import app_name, version +from NohGooee.language import locale_sucks if sys.platform.startswith('win'): bttime = time.clock diff --git a/BitTorrent/prefs.py b/NohGooee/prefs.py index 37177c2..37177c2 100644 --- a/BitTorrent/prefs.py +++ b/NohGooee/prefs.py diff --git a/BitTorrent/selectpoll.py b/NohGooee/selectpoll.py index d01f1ef..d01f1ef 100644 --- a/BitTorrent/selectpoll.py +++ b/NohGooee/selectpoll.py diff --git a/BitTorrent/track.py b/NohGooee/track.py index fe4788f..ee1fe5e 100644 --- a/BitTorrent/track.py +++ b/NohGooee/track.py @@ -22,12 +22,12 @@ from twisted.web.resource import Resource from twisted.internet import reactor from twisted.python import log -from BitTorrent.parseargs import parseargs, formatDefinitions -from BitTorrent.parsedir import parsedir -from BitTorrent.NatCheck import NatCheck -from BitTorrent.bencode import bencode, bdecode, Bencached -from BitTorrent.zurllib import quote, unquote -from BitTorrent import version +from NohGooee.parseargs import parseargs, formatDefinitions +from NohGooee.parsedir import parsedir +from NohGooee.NatCheck import NatCheck +from NohGooee.bencode import bencode, bdecode, Bencached +from NohGooee.zurllib import quote, unquote +from NohGooee import version defaults = [ diff --git a/BitTorrent/zurllib.py b/NohGooee/zurllib.py index 8bbe5ba..399118f 100644 --- a/BitTorrent/zurllib.py +++ b/NohGooee/zurllib.py @@ -13,7 +13,7 @@ import sys import threading import thread -from BitTorrent import PeerID +from NohGooee import PeerID user_agent = PeerID.make_id() del PeerID diff --git a/bittorrent b/bittorrent deleted file mode 120000 index 7ca3c4e..0000000 --- a/bittorrent +++ /dev/null @@ -1 +0,0 @@ -bittorrent.py
\ No newline at end of file diff --git a/bittorrent-console b/bittorrent-console deleted file mode 120000 index 054110d..0000000 --- a/bittorrent-console +++ /dev/null @@ -1 +0,0 @@ -bittorrent-console.py
\ No newline at end of file diff --git a/bittorrent-console.py b/bittorrent-console.py deleted file mode 100755 index e5ec115..0000000 --- a/bittorrent-console.py +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/env python - -# The contents of this file are subject to the BitTorrent Open Source License -# Version 1.1 (the License). You may not copy or use this file, in either -# source code or executable form, except in compliance with the License. You -# may obtain a copy of the License at http://www.bittorrent.com/license/. -# -# Software distributed under the License is distributed on an AS IS basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. - -# Written by Bram Cohen, Uoti Urpala and John Hoffman - -from __future__ import division - -from BitTorrent.platform import install_translation -install_translation() - -import sys -import os -import threading -from time import time, strftime -from cStringIO import StringIO - -from BitTorrent.download import Feedback, Multitorrent -from BitTorrent.defaultargs import get_defaults -from BitTorrent.parseargs import printHelp -from BitTorrent.zurllib import urlopen -from BitTorrent.bencode import bdecode -from BitTorrent.ConvertedMetainfo import ConvertedMetainfo -from BitTorrent.prefs import Preferences -from BitTorrent import configfile -from BitTorrent import BTFailure -from BitTorrent import version -from BitTorrent import GetTorrent - - -def fmttime(n): - if n == 0: - return _("download complete!") - try: - n = int(n) - assert n >= 0 and n < 5184000 # 60 days - except: - return _("<unknown>") - m, s = divmod(n, 60) - h, m = divmod(m, 60) - return _("finishing in %d:%02d:%02d") % (h, m, s) - -def fmtsize(n): - s = str(n) - size = s[-3:] - while len(s) > 3: - s = s[:-3] - size = '%s,%s' % (s[-3:], size) - if n > 999: - unit = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] - i = 1 - while i + 1 < len(unit) and (n >> 10) >= 999: - i += 1 - n >>= 10 - n /= (1 << 10) - size = '%s (%.0f %s)' % (size, n, unit[i]) - return size - - -class HeadlessDisplayer(object): - - def __init__(self, doneflag): - self.doneflag = doneflag - - self.done = False - self.percentDone = '' - self.timeEst = '' - self.downRate = '---' - self.upRate = '---' - self.shareRating = '' - self.seedStatus = '' - self.peerStatus = '' - self.errors = [] - self.file = '' - self.downloadTo = '' - self.fileSize = '' - self.numpieces = 0 - - def set_torrent_values(self, name, path, size, numpieces): - self.file = name - self.downloadTo = path - self.fileSize = fmtsize(size) - self.numpieces = numpieces - - def finished(self): - self.done = True - self.downRate = '---' - self.display({'activity':_("download succeeded"), 'fractionDone':1}) - - def error(self, errormsg): - newerrmsg = strftime('[%H:%M:%S] ') + errormsg - self.errors.append(newerrmsg) - self.display({}) - - def display(self, statistics): - fractionDone = statistics.get('fractionDone') - activity = statistics.get('activity') - timeEst = statistics.get('timeEst') - downRate = statistics.get('downRate') - upRate = statistics.get('upRate') - spew = statistics.get('spew') - - print '\n\n\n\n' - if spew is not None: - self.print_spew(spew) - - if timeEst is not None: - self.timeEst = fmttime(timeEst) - elif activity is not None: - self.timeEst = activity - - if fractionDone is not None: - self.percentDone = str(int(fractionDone * 1000) / 10) - if downRate is not None: - self.downRate = '%.1f KB/s' % (downRate / (1 << 10)) - if upRate is not None: - self.upRate = '%.1f KB/s' % (upRate / (1 << 10)) - downTotal = statistics.get('downTotal') - if downTotal is not None: - upTotal = statistics['upTotal'] - if downTotal <= upTotal / 100: - self.shareRating = _("oo (%.1f MB up / %.1f MB down)") % ( - upTotal / (1<<20), downTotal / (1<<20)) - else: - self.shareRating = _("%.3f (%.1f MB up / %.1f MB down)") % ( - upTotal / downTotal, upTotal / (1<<20), downTotal / (1<<20)) - numCopies = statistics['numCopies'] - nextCopies = ', '.join(["%d:%.1f%%" % (a,int(b*1000)/10) for a,b in - zip(xrange(numCopies+1, 1000), statistics['numCopyList'])]) - if not self.done: - self.seedStatus = _("%d seen now, plus %d distributed copies " - "(%s)") % (statistics['numSeeds' ], - statistics['numCopies'], - nextCopies) - else: - self.seedStatus = _("%d distributed copies (next: %s)") % ( - statistics['numCopies'], nextCopies) - self.peerStatus = _("%d seen now") % statistics['numPeers'] - - for err in self.errors[-4:]: - print _("ERROR:\n") + err + '\n' - print _("saving: "), self.file - print _("file size: "), self.fileSize - print _("percent done: "), self.percentDone - print _("time left: "), self.timeEst - print _("download to: "), self.downloadTo - print _("download rate: "), self.downRate - print _("upload rate: "), self.upRate - print _("share rating: "), self.shareRating - print _("seed status: "), self.seedStatus - print _("peer status: "), self.peerStatus - - def print_spew(self, spew): - s = StringIO() - s.write('\n\n\n') - for c in spew: - s.write('%20s ' % c['ip']) - if c['initiation'] == 'L': - s.write('l') - else: - s.write('r') - total, rate, interested, choked = c['upload'] - s.write(' %10s %10s ' % (str(int(total/10485.76)/100), - str(int(rate)))) - if c['is_optimistic_unchoke']: - s.write('*') - else: - s.write(' ') - if interested: - s.write('i') - else: - s.write(' ') - if choked: - s.write('c') - else: - s.write(' ') - - total, rate, interested, choked, snubbed = c['download'] - s.write(' %10s %10s ' % (str(int(total/10485.76)/100), - str(int(rate)))) - if interested: - s.write('i') - else: - s.write(' ') - if choked: - s.write('c') - else: - s.write(' ') - if snubbed: - s.write('s') - else: - s.write(' ') - s.write('\n') - print s.getvalue() - - -class DL(Feedback): - - def __init__(self, metainfo, config): - self.doneflag = threading.Event() - self.metainfo = metainfo - self.config = Preferences().initWithDict(config) - - def run(self): - self.d = HeadlessDisplayer(self.doneflag) - try: - self.multitorrent = Multitorrent(self.config, self.doneflag, - self.global_error) - # raises BTFailure if bad - metainfo = ConvertedMetainfo(bdecode(self.metainfo)) - torrent_name = metainfo.name_fs - if config['save_as']: - if config['save_in']: - raise BTFailure(_("You cannot specify both --save_as and " - "--save_in")) - saveas = config['save_as'] - elif config['save_in']: - saveas = os.path.join(config['save_in'], torrent_name) - else: - saveas = torrent_name - - self.d.set_torrent_values(metainfo.name, os.path.abspath(saveas), - metainfo.total_bytes, len(metainfo.hashes)) - self.torrent = self.multitorrent.start_torrent(metainfo, - Preferences(self.config), self, saveas) - except BTFailure, e: - print str(e) - return - self.get_status() - self.multitorrent.rawserver.install_sigint_handler() - self.multitorrent.rawserver.listen_forever() - self.d.display({'activity':_("shutting down"), 'fractionDone':0}) - self.torrent.shutdown() - - def reread_config(self): - try: - newvalues = configfile.get_config(self.config, 'bittorrent-console') - except Exception, e: - self.d.error(_("Error reading config: ") + str(e)) - return - self.config.update(newvalues) - # The set_option call can potentially trigger something that kills - # the torrent (when writing this the only possibility is a change in - # max_files_open causing an IOError while closing files), and so - # the self.failed() callback can run during this loop. - for option, value in newvalues.iteritems(): - self.multitorrent.set_option(option, value) - for option, value in newvalues.iteritems(): - self.torrent.set_option(option, value) - - def get_status(self): - self.multitorrent.rawserver.add_task(self.get_status, - self.config['display_interval']) - status = self.torrent.get_status(self.config['spew']) - self.d.display(status) - - def global_error(self, level, text): - self.d.error(text) - - def error(self, torrent, level, text): - self.d.error(text) - - def failed(self, torrent, is_external): - self.doneflag.set() - - def finished(self, torrent): - self.d.finished() - - -if __name__ == '__main__': - uiname = 'bittorrent-console' - defaults = get_defaults(uiname) - - metainfo = None - if len(sys.argv) <= 1: - printHelp(uiname, defaults) - sys.exit(1) - try: - config, args = configfile.parse_configuration_and_args(defaults, - uiname, sys.argv[1:], 0, 1) - - torrentfile = None - if len(args): - torrentfile = args[0] - for opt in ('responsefile', 'url'): - if config[opt]: - print '"--%s"' % opt, _("deprecated, do not use") - torrentfile = config[opt] - if torrentfile is not None: - metainfo, errors = GetTorrent.get(torrentfile) - if errors: - raise BTFailure(_("Error reading .torrent file: ") + '\n'.join(errors)) - else: - raise BTFailure(_("you must specify a .torrent file")) - except BTFailure, e: - print str(e) - sys.exit(1) - - dl = DL(metainfo, config) - dl.run() diff --git a/bittorrent-curses b/bittorrent-curses deleted file mode 120000 index e6ea9be..0000000 --- a/bittorrent-curses +++ /dev/null @@ -1 +0,0 @@ -bittorrent-curses.py
\ No newline at end of file diff --git a/bittorrent-curses.py b/bittorrent-curses.py deleted file mode 100755 index f5d906f..0000000 --- a/bittorrent-curses.py +++ /dev/null @@ -1,449 +0,0 @@ -#!/usr/bin/env python - -# The contents of this file are subject to the BitTorrent Open Source License -# Version 1.1 (the License). You may not copy or use this file, in either -# source code or executable form, except in compliance with the License. You -# may obtain a copy of the License at http://www.bittorrent.com/license/. -# -# Software distributed under the License is distributed on an AS IS basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. - -# Original version written by Henry 'Pi' James, modified by (at least) -# John Hoffman and Uoti Urpala - -from __future__ import division - -from BitTorrent.platform import install_translation -install_translation() - -SPEW_SCROLL_RATE = 1 - -import sys -import os -import threading -from time import time, strftime - -from BitTorrent.download import Feedback, Multitorrent -from BitTorrent.defaultargs import get_defaults -from BitTorrent.parseargs import printHelp -from BitTorrent.zurllib import urlopen -from BitTorrent.bencode import bdecode -from BitTorrent.ConvertedMetainfo import ConvertedMetainfo -from BitTorrent.prefs import Preferences -from BitTorrent import configfile -from BitTorrent import BTFailure -from BitTorrent import version -from BitTorrent import GetTorrent - - -try: - curses = import_curses() - import curses.panel - from curses.wrapper import wrapper as curses_wrapper - from signal import signal, SIGWINCH -except: - print _("Textmode GUI initialization failed, cannot proceed.") - print - print _("This download interface requires the standard Python module " - "\"curses\", which is unfortunately not available for the native " - "Windows port of Python. It is however available for the Cygwin " - "port of Python, running on all Win32 systems (www.cygwin.com).") - print - print _('You may still use "bittorrent-console" to download.') - sys.exit(1) - -def fmttime(n): - if n == 0: - return _("download complete!") - try: - n = int(n) - assert n >= 0 and n < 5184000 # 60 days - except: - return _("<unknown>") - m, s = divmod(n, 60) - h, m = divmod(m, 60) - return _("finishing in %d:%02d:%02d") % (h, m, s) - -def fmtsize(n): - s = str(n) - size = s[-3:] - while len(s) > 3: - s = s[:-3] - size = '%s,%s' % (s[-3:], size) - if n > 999: - unit = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] - i = 1 - while i + 1 < len(unit) and (n >> 10) >= 999: - i += 1 - n >>= 10 - n /= (1 << 10) - size = '%s (%.0f %s)' % (size, n, unit[i]) - return size - - -class CursesDisplayer(object): - - def __init__(self, scrwin, errlist, doneflag, reread_config, ulrate): - self.scrwin = scrwin - self.errlist = errlist - self.doneflag = doneflag - - signal(SIGWINCH, self.winch_handler) - self.changeflag = threading.Event() - - self.done = False - self.reread_config = reread_config - self.ulrate = ulrate - self.activity = '' - self.status = '' - self.progress = '' - self.downRate = '---' - self.upRate = '---' - self.shareRating = '' - self.seedStatus = '' - self.peerStatus = '' - self.errors = [] - self.file = '' - self.downloadTo = '' - self.fileSize = '' - self.numpieces = 0 - self.spew_scroll_time = 0 - self.spew_scroll_pos = 0 - - self._remake_window() - curses.use_default_colors() - - def set_torrent_values(self, name, path, size, numpieces): - self.file = name - self.downloadTo = path - self.fileSize = fmtsize(size) - self.numpieces = numpieces - self._remake_window() - - def winch_handler(self, signum, stackframe): - self.changeflag.set() - curses.endwin() - self.scrwin.refresh() - self.scrwin = curses.newwin(0, 0, 0, 0) - self._remake_window() - - def _remake_window(self): - self.scrh, self.scrw = self.scrwin.getmaxyx() - self.scrpan = curses.panel.new_panel(self.scrwin) - self.labelh, self.labelw, self.labely, self.labelx = 11, 9, 1, 2 - self.labelwin = curses.newwin(self.labelh, self.labelw, - self.labely, self.labelx) - self.labelpan = curses.panel.new_panel(self.labelwin) - self.fieldh, self.fieldw, self.fieldy, self.fieldx = ( - self.labelh, self.scrw-2 - self.labelw-3, - 1, self.labelw+3) - self.fieldwin = curses.newwin(self.fieldh, self.fieldw, - self.fieldy, self.fieldx) - self.fieldwin.nodelay(1) - self.fieldpan = curses.panel.new_panel(self.fieldwin) - self.spewh, self.speww, self.spewy, self.spewx = ( - self.scrh - self.labelh - 2, self.scrw - 3, 1 + self.labelh, 2) - self.spewwin = curses.newwin(self.spewh, self.speww, - self.spewy, self.spewx) - self.spewpan = curses.panel.new_panel(self.spewwin) - try: - self.scrwin.border(ord('|'),ord('|'),ord('-'),ord('-'),ord(' '),ord(' '),ord(' '),ord(' ')) - except: - pass - self.labelwin.addstr(0, 0, _("file:")) - self.labelwin.addstr(1, 0, _("size:")) - self.labelwin.addstr(2, 0, _("dest:")) - self.labelwin.addstr(3, 0, _("progress:")) - self.labelwin.addstr(4, 0, _("status:")) - self.labelwin.addstr(5, 0, _("dl speed:")) - self.labelwin.addstr(6, 0, _("ul speed:")) - self.labelwin.addstr(7, 0, _("sharing:")) - self.labelwin.addstr(8, 0, _("seeds:")) - self.labelwin.addstr(9, 0, _("peers:")) - curses.panel.update_panels() - curses.doupdate() - self.changeflag.clear() - - - def finished(self): - self.done = True - self.downRate = '---' - self.display({'activity':_("download succeeded"), 'fractionDone':1}) - - def error(self, errormsg): - newerrmsg = strftime('[%H:%M:%S] ') + errormsg - self.errors.append(newerrmsg.split('\n')[0]) - self.errlist.append(newerrmsg) - self.display({}) - - def display(self, statistics): - fractionDone = statistics.get('fractionDone') - activity = statistics.get('activity') - timeEst = statistics.get('timeEst') - downRate = statistics.get('downRate') - upRate = statistics.get('upRate') - spew = statistics.get('spew') - - inchar = self.fieldwin.getch() - if inchar == 12: # ^L - self._remake_window() - elif inchar in (ord('q'),ord('Q')): - self.doneflag.set() - elif inchar in (ord('r'),ord('R')): - self.reread_config() - elif inchar in (ord('u'),ord('U')): - curses.echo() - self.fieldwin.nodelay(0) - s = self.fieldwin.getstr(6,10) - curses.noecho() - self.fieldwin.nodelay(1) - r = None - try: - r = int(s) - except ValueError: - pass - if r is not None: - self.ulrate(r) - - if timeEst is not None: - self.activity = fmttime(timeEst) - elif activity is not None: - self.activity = activity - if self.changeflag.isSet(): - return - - if fractionDone is not None: - blocknum = int(self.fieldw * fractionDone) - self.progress = blocknum * '#' + (self.fieldw - blocknum) * '_' - self.status = '%s (%.1f%%)' % (self.activity, fractionDone * 100) - - if downRate is not None: - self.downRate = '%.1f KB/s' % (downRate / (1 << 10)) - if upRate is not None: - self.upRate = '%.1f KB/s' % (upRate / (1 << 10)) - downTotal = statistics.get('downTotal') - if downTotal is not None: - upTotal = statistics['upTotal'] - if downTotal <= upTotal / 100: - self.shareRating = _("oo (%.1f MB up / %.1f MB down)") % ( - upTotal / (1<<20), downTotal / (1<<20)) - else: - self.shareRating = _("%.3f (%.1f MB up / %.1f MB down)") % ( - upTotal / downTotal, upTotal / (1<<20), downTotal / (1<<20)) - numCopies = statistics['numCopies'] - nextCopies = ', '.join(["%d:%.1f%%" % (a,int(b*1000)/10) for a,b in - zip(xrange(numCopies+1, 1000), statistics['numCopyList'])]) - if not self.done: - self.seedStatus = _("%d seen now, plus %d distributed copies" - "(%s)") % (statistics['numSeeds' ], - statistics['numCopies'], - nextCopies) - else: - self.seedStatus = _("%d distributed copies (next: %s)") % ( - statistics['numCopies'], nextCopies) - self.peerStatus = _("%d seen now") % statistics['numPeers'] - - self.fieldwin.erase() - self.fieldwin.addnstr(0, 0, self.file, self.fieldw, curses.A_BOLD) - self.fieldwin.addnstr(1, 0, self.fileSize, self.fieldw) - self.fieldwin.addnstr(2, 0, self.downloadTo, self.fieldw) - if self.progress: - self.fieldwin.addnstr(3, 0, self.progress, self.fieldw, curses.A_BOLD) - self.fieldwin.addnstr(4, 0, self.status, self.fieldw) - self.fieldwin.addnstr(5, 0, self.downRate, self.fieldw) - self.fieldwin.addnstr(6, 0, self.upRate, self.fieldw) - self.fieldwin.addnstr(7, 0, self.shareRating, self.fieldw) - self.fieldwin.addnstr(8, 0, self.seedStatus, self.fieldw) - self.fieldwin.addnstr(9, 0, self.peerStatus, self.fieldw) - - self.spewwin.erase() - - if not spew: - errsize = self.spewh - if self.errors: - self.spewwin.addnstr(0, 0, _("error(s):"), self.speww, curses.A_BOLD) - errsize = len(self.errors) - displaysize = min(errsize, self.spewh) - displaytop = errsize - displaysize - for i in range(displaysize): - self.spewwin.addnstr(i, self.labelw, self.errors[displaytop + i], - self.speww-self.labelw-1, curses.A_BOLD) - else: - if self.errors: - self.spewwin.addnstr(0, 0, _("error:"), self.speww, curses.A_BOLD) - self.spewwin.addnstr(0, self.labelw, self.errors[-1], - self.speww-self.labelw-1, curses.A_BOLD) - self.spewwin.addnstr(2, 0, _(" # IP Upload Download Completed Speed"), self.speww, curses.A_BOLD) - - - if self.spew_scroll_time + SPEW_SCROLL_RATE < time(): - self.spew_scroll_time = time() - if len(spew) > self.spewh-5 or self.spew_scroll_pos > 0: - self.spew_scroll_pos += 1 - if self.spew_scroll_pos > len(spew): - self.spew_scroll_pos = 0 - - for i in range(len(spew)): - spew[i]['lineno'] = i+1 - spew.append({'lineno': None}) - spew = spew[self.spew_scroll_pos:] + spew[:self.spew_scroll_pos] - - for i in range(min(self.spewh - 5, len(spew))): - if not spew[i]['lineno']: - continue - self.spewwin.addnstr(i+3, 0, '%3d' % spew[i]['lineno'], 3) - self.spewwin.addnstr(i+3, 4, spew[i]['ip'], 15) - ul = spew[i]['upload'] - if ul[1] > 100: - self.spewwin.addnstr(i+3, 20, '%6.0f KB/s' % ( - ul[1] / 1000), 11) - self.spewwin.addnstr(i+3, 32, '-----', 5) - if ul[2]: - self.spewwin.addnstr(i+3, 33, 'I', 1) - if ul[3]: - self.spewwin.addnstr(i+3, 35, 'C', 1) - dl = spew[i]['download'] - if dl[1] > 100: - self.spewwin.addnstr(i+3, 38, '%6.0f KB/s' % ( - dl[1] / 1000), 11) - self.spewwin.addnstr(i+3, 50, '-------', 7) - if dl[2]: - self.spewwin.addnstr(i+3, 51, 'I', 1) - if dl[3]: - self.spewwin.addnstr(i+3, 53, 'C', 1) - if dl[4]: - self.spewwin.addnstr(i+3, 55, 'S', 1) - self.spewwin.addnstr(i+3, 58, '%5.1f%%' % (int(spew[i]['completed']*1000)/10), 6) - if spew[i]['speed'] is not None: - self.spewwin.addnstr(i+3, 64, '%5.0f KB/s' % (spew[i]['speed']/1000), 10) - - self.spewwin.addnstr(self.spewh-1, 0, - _("downloading %d pieces, have %d fragments, " - "%d of %d pieces completed") % - (statistics['storage_active'], statistics['storage_dirty'], - statistics['storage_numcomplete'], self.numpieces), - self.speww-1) - - curses.panel.update_panels() - curses.doupdate() - - -class DL(Feedback): - - def __init__(self, metainfo, config, errlist): - self.doneflag = threading.Event() - self.metainfo = metainfo - self.config = Preferences().initWithDict(config) - self.errlist = errlist - - def run(self, scrwin): - def reread(): - self.multitorrent.rawserver.external_add_task(self.reread_config,0) - def ulrate(value): - self.multitorrent.set_option('max_upload_rate', value) - self.torrent.set_option('max_upload_rate', value) - - self.d = CursesDisplayer(scrwin, self.errlist, self.doneflag, reread, ulrate) - try: - self.multitorrent = Multitorrent(self.config, self.doneflag, - self.global_error) - # raises BTFailure if bad - metainfo = ConvertedMetainfo(bdecode(self.metainfo)) - torrent_name = metainfo.name_fs - if config['save_as']: - if config['save_in']: - raise BTFailure(_("You cannot specify both --save_as and " - "--save_in")) - saveas = config['save_as'] - elif config['save_in']: - saveas = os.path.join(config['save_in'], torrent_name) - else: - saveas = torrent_name - - self.d.set_torrent_values(metainfo.name, os.path.abspath(saveas), - metainfo.total_bytes, len(metainfo.hashes)) - self.torrent = self.multitorrent.start_torrent(metainfo, - Preferences(self.config), self, saveas) - except BTFailure, e: - errlist.append(str(e)) - return - self.get_status() - self.multitorrent.rawserver.install_sigint_handler() - self.multitorrent.rawserver.listen_forever() - self.d.display({'activity':_("shutting down"), 'fractionDone':0}) - self.torrent.shutdown() - - def reread_config(self): - try: - newvalues = configfile.get_config(self.config, 'bittorrent-curses') - except Exception, e: - self.d.error(_("Error reading config: ") + str(e)) - return - self.config.update(newvalues) - # The set_option call can potentially trigger something that kills - # the torrent (when writing this the only possibility is a change in - # max_files_open causing an IOError while closing files), and so - # the self.failed() callback can run during this loop. - for option, value in newvalues.iteritems(): - self.multitorrent.set_option(option, value) - for option, value in newvalues.iteritems(): - self.torrent.set_option(option, value) - - def get_status(self): - self.multitorrent.rawserver.add_task(self.get_status, - self.config['display_interval']) - status = self.torrent.get_status(self.config['spew']) - self.d.display(status) - - def global_error(self, level, text): - self.d.error(text) - - def error(self, torrent, level, text): - self.d.error(text) - - def failed(self, torrent, is_external): - self.doneflag.set() - - def finished(self, torrent): - self.d.finished() - - -if __name__ == '__main__': - uiname = 'bittorrent-curses' - defaults = get_defaults(uiname) - - metainfo = None - if len(sys.argv) <= 1: - printHelp(uiname, defaults) - sys.exit(1) - try: - config, args = configfile.parse_configuration_and_args(defaults, - uiname, sys.argv[1:], 0, 1) - - torrentfile = None - if len(args): - torrentfile = args[0] - for opt in ('responsefile', 'url'): - if config[opt]: - print '"--%s"' % opt, _("deprecated, do not use") - torrentfile = config[opt] - if torrentfile is not None: - metainfo, errors = GetTorrent.get(torrentfile) - if errors: - raise BTFailure(_("Error reading .torrent file: ") + '\n'.join(errors)) - else: - raise BTFailure(_("you must specify a .torrent file")) - except BTFailure, e: - print str(e) - sys.exit(1) - - errlist = [] - dl = DL(metainfo, config, errlist) - curses_wrapper(dl.run) - - if errlist: - print _("These errors occurred during execution:") - for error in errlist: - print error diff --git a/bittorrent-tracker b/bittorrent-tracker deleted file mode 120000 index c6ade35..0000000 --- a/bittorrent-tracker +++ /dev/null @@ -1 +0,0 @@ -bittorrent-tracker.py
\ No newline at end of file diff --git a/bittorrent.desktop b/bittorrent.desktop deleted file mode 100644 index df6d84c..0000000 --- a/bittorrent.desktop +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Name=BitTorrent File Transfer -Comment=Distributed download of files from the Internet -Exec=bittorrent -Icon=bittorrent.png -Terminal=false -Type=Application -StartupNotify=true -Categories=Network; -MimeType=application/x-bittorrent; diff --git a/bittorrent.png b/bittorrent.png Binary files differdeleted file mode 100644 index 52a4d49..0000000 --- a/bittorrent.png +++ /dev/null diff --git a/bittorrent.py b/bittorrent.py deleted file mode 100755 index c67f665..0000000 --- a/bittorrent.py +++ /dev/null @@ -1,3834 +0,0 @@ -#!/usr/bin/env python - -# The contents of this file are subject to the BitTorrent Open Source License -# Version 1.1 (the License). You may not copy or use this file, in either -# source code or executable form, except in compliance with the License. You -# may obtain a copy of the License at http://www.bittorrent.com/license/. -# -# Software distributed under the License is distributed on an AS IS basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. - -# Written by Uoti Urpala and Matt Chisholm - -from __future__ import division - -from BitTorrent.platform import install_translation -install_translation() - -import sys -import itertools -import math -import os -import threading -import datetime -import random -import atexit - -assert sys.version_info >= (2, 3), _("Install Python %s or greater") % '2.3' - -from BitTorrent import BTFailure, INFO, WARNING, ERROR, CRITICAL, status_dict, app_name - -from BitTorrent import configfile - -from BitTorrent.defaultargs import get_defaults -from BitTorrent.IPC import ipc_interface -from BitTorrent.prefs import Preferences -from BitTorrent.platform import doc_root, btspawn, path_wrap, os_version, is_frozen_exe, get_startup_dir, create_shortcut, remove_shortcut -from BitTorrent import zurllib - -defaults = get_defaults('bittorrent') -defaults.extend((('donated' , '', ''), # the version that the user last donated for - ('notified', '', ''), # the version that the user was last notified of - )) - - -ui_options = [ - 'max_upload_rate' , - 'minport' , - 'maxport' , - 'next_torrent_time' , - 'next_torrent_ratio' , - 'last_torrent_ratio' , - 'seed_forever' , - 'seed_last_forever' , - 'ask_for_save' , - 'save_in' , - 'open_from' , - 'ip' , - 'start_torrent_behavior', - 'upnp' , - ] - -if os.name == 'nt': - ui_options.extend( [ - 'launch_on_startup' , - 'minimize_to_tray' , - ]) - -advanced_ui_options_index = len(ui_options) - -ui_options.extend([ - 'min_uploads' , - 'max_uploads' , - 'max_initiate' , - 'max_incomplete' , - 'max_allow_in' , - 'max_files_open' , - 'forwarded_port' , - 'display_interval', - 'donated' , - 'notified' , - ]) - - -if is_frozen_exe: - ui_options.append('progressbar_hack') - defproghack = 0 - if os_version == 'XP': - # turn on progress bar hack by default for Win XP - defproghack = 1 - defaults.extend((('progressbar_hack' , defproghack, ''),)) - - -NAG_FREQUENCY = 3 -PORT_RANGE = 5 - -defconfig = dict([(name, value) for (name, value, doc) in defaults]) -del name, value, doc - -def btgui_exit(ipc): - ipc.stop() - -class global_logger(object): - def __init__(self, logger = None): - self.logger = logger - def __call__(self, severity, msg): - if self.logger: - self.logger(severity, msg) - else: - sys.stderr.write("%s: %s\n" % (status_dict[severity], msg)) - -# if it's application global, why do we pass a reference to it everywhere? -global_log_func = global_logger() - -if __name__ == '__main__': - zurllib.add_unsafe_thread() - - try: - config, args = configfile.parse_configuration_and_args(defaults, - 'bittorrent', sys.argv[1:], 0, None) - except BTFailure, e: - print str(e) - sys.exit(1) - - config = Preferences().initWithDict(config) - advanced_ui = config['advanced'] - - newtorrents = args - for opt in ('responsefile', 'url'): - if config[opt]: - print '"--%s"' % opt, _("deprecated, do not use") - newtorrents.append(config[opt]) - - ipc = ipc_interface(config, global_log_func) - - # this could be on the ipc object - ipc_master = True - try: - ipc.create() - except BTFailure: - ipc_master = False - - try: - ipc.send_command('no-op') - except BTFailure: - global_log_func(ERROR, _("Failed to communicate with another %s process " - "but one seems to be running.") + - _(" Closing all %s windows may fix the problem.") - % (app_name, app_name)) - sys.exit(1) - - # make sure we clean up the ipc when we close - atexit.register(btgui_exit, ipc) - - # it's not obvious, but 'newtorrents' is carried on to the gui - # __main__ if we're the IPC master - - if not ipc_master: - - if newtorrents: - # Not sure if anything really useful could be done if - # these send_command calls fail - for name in newtorrents: - ipc.send_command('start_torrent', name, config['save_as']) - sys.exit(0) - - try: - ipc.send_command('show_error', _("%s already running")%app_name) - except BTFailure: - global_log_func(ERROR, _("Failed to communicate with another %s process.") + - _(" Closing all %s windows may fix the problem.") - % app_name) - sys.exit(1) - - -import gtk -import pango -import gobject -import webbrowser - -assert gtk.pygtk_version >= (2, 6), _("PyGTK %s or newer required") % '2.6' - -from BitTorrent import HELP_URL, DONATE_URL, SEARCH_URL, version, branch - -from BitTorrent import TorrentQueue -from BitTorrent import LaunchPath -from BitTorrent import Desktop -from BitTorrent import ClientIdentifier -from BitTorrent import NewVersion - -from BitTorrent.parseargs import makeHelp -from BitTorrent.TorrentQueue import RUNNING, RUN_QUEUED, QUEUED, KNOWN, ASKING_LOCATION -from BitTorrent.TrayIcon import TrayIcon -from BitTorrent.StatusLight import GtkStatusLight as StatusLight -from BitTorrent.GUI import * - - -main_torrent_dnd_tip = _("drag to reorder") -torrent_menu_tip = _("right-click for menu") -torrent_tip_format = '%s:\n %s\n %s' - -rate_label = ': %s' - -speed_classes = { - ( 4, 5):_("dialup" ), - ( 6, 14):_("DSL/cable 128k up"), - ( 15, 29):_("DSL/cable 256k up"), - ( 30, 91):_("DSL 768k up" ), - ( 92, 137):_("T1" ), - ( 138, 182):_("T1/E1" ), - ( 183, 249):_("E1" ), - ( 250, 5446):_("T3" ), - (5447,18871):_("OC3" ), - } - -def find_dir(path): - if os.path.isdir(path): - return path - directory, garbage = os.path.split(path) - while directory: - if os.access(directory, os.F_OK) and os.access(directory, os.W_OK): - return directory - directory, garbage = os.path.split(directory) - if garbage == '': - break - return None - -def smart_dir(path): - path = find_dir(path) - if path is None: - path = Desktop.desktop - return path - -class MenuItem(gtk.MenuItem): - def __init__(self, label, accel_group=None, func=None): - gtk.MenuItem.__init__(self, label) - if func is not None: - self.connect("activate", func) - else: - self.set_sensitive(False) - - if accel_group is not None: - label = label.decode('utf-8') - accel_index = label.find('_') - if -1 < accel_index < len(label) - 1: - accel_char = long(ord(label[accel_index+1])) - accel_key = gtk.gdk.unicode_to_keyval(accel_char) - if accel_key != accel_char | 0x01000000: - self.add_accelerator("activate", accel_group, accel_key, - gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) - self.show() - - -def build_menu(menu_items, accel_group=None): - menu = gtk.Menu() - for label,func in menu_items: - if label == '----': - s = gtk.SeparatorMenuItem() - s.show() - menu.add(s) - else: - item = MenuItem(label, accel_group=accel_group, func=func) - item.show() - menu.add(item) - return menu - - -class Validator(gtk.Entry): - valid_chars = '1234567890' - minimum = None - maximum = None - cast = int - - def __init__(self, option_name, config, setfunc): - gtk.Entry.__init__(self) - self.option_name = option_name - self.config = config - self.setfunc = setfunc - - self.set_text(str(config[option_name])) - - self.set_size_request(self.width,-1) - - self.connect('insert-text', self.text_inserted) - self.connect('focus-out-event', self.focus_out) - - def get_value(self): - value = None - try: - value = self.cast(self.get_text()) - except ValueError: - pass - return value - - def set_value(self, value): - self.set_text(str(value)) - self.setfunc(self.option_name, value) - - def focus_out(self, entry, widget): - value = self.get_value() - - if value is None: - return - - if (self.minimum is not None) and (value < self.minimum): - value = self.minimum - if (self.maximum is not None) and (value > self.maximum): - value = self.maximum - - self.set_value(value) - - def text_inserted(self, entry, input, position, user_data): - for i in input: - if (self.valid_chars is not None) and (i not in self.valid_chars): - self.emit_stop_by_name('insert-text') - return True - return False - -class IPValidator(Validator): - valid_chars = '1234567890.' - width = 128 - cast = str - -class PortValidator(Validator): - width = 64 - minimum = 1024 - maximum = 65535 - - def add_end(self, end_name): - self.end_option_name = end_name - - def set_value(self, value): - self.set_text(str(value)) - self.setfunc(self.option_name, value) - self.setfunc(self.end_option_name, value+PORT_RANGE) - - -class PercentValidator(Validator): - width = 48 - minimum = 0 - -class MinutesValidator(Validator): - width = 48 - minimum = 1 - -class EnterUrlDialog(MessageDialog): - flags = gtk.DIALOG_DESTROY_WITH_PARENT - def __init__(self, parent): - self.entry = gtk.Entry() - self.entry.show() - self.main = parent - MessageDialog.__init__(self, parent.mainwindow, - _("Enter torrent URL"), - _("Enter the URL of a torrent file to open:"), - type=gtk.MESSAGE_QUESTION, - buttons=gtk.BUTTONS_OK_CANCEL, - yesfunc=lambda *args: parent.open_url(self.entry.get_text()), - default=gtk.RESPONSE_OK - ) - hbox = gtk.HBox() - hbox.pack_start(self.entry, padding=SPACING) - hbox.show() - self.entry.set_activates_default(True) - self.entry.set_flags(gtk.CAN_FOCUS) - self.vbox.pack_start(hbox) - self.entry.grab_focus() - - def close(self, *args): - self.destroy() - - def destroy(self): - MessageDialog.destroy(self) - self.main.window_closed('enterurl') - - -class RateSliderBox(gtk.VBox): - base = 10 - multiplier = 4 - max_exponent = 3.3 - - def __init__(self, config, torrentqueue): - gtk.VBox.__init__(self, homogeneous=False) - self.config = config - self.torrentqueue = torrentqueue - - if self.config['max_upload_rate'] < self.slider_to_rate(0): - self.config['max_upload_rate'] = self.slider_to_rate(0) - - self.speed_classes = { - ( 4, 5):_("dialup" ), - ( 6, 14):_("DSL/cable 128k up"), - ( 15, 29):_("DSL/cable 256k up"), - ( 30, 91):_("DSL 768k up" ), - ( 92, 137):_("T1" ), - ( 138, 182):_("T1/E1" ), - ( 183, 249):_("E1" ), - ( 250, 5446):_("T3" ), - (5447,18871):_("OC3" ), - } - - biggest_size = 0 - for v in self.speed_classes.values(): - width = gtk.Label(v).size_request()[0] - if width > biggest_size: - biggest_size = width - - self.rate_slider_label_box = gtk.HBox(spacing=SPACING, - homogeneous=True) - - self.rate_slider_label = gtk.Label(_("Maximum upload rate:")) - self.rate_slider_label.set_ellipsize(pango.ELLIPSIZE_START) - self.rate_slider_label.set_alignment(1, 0.5) - self.rate_slider_label_box.pack_start(self.rate_slider_label, - expand=True, fill=True) - - self.rate_slider_value = gtk.Label( - self.value_to_label(self.config['max_upload_rate'])) - self.rate_slider_value.set_alignment(0, 0.5) - self.rate_slider_value.set_size_request(biggest_size, -1) - - self.rate_slider_label_box.pack_start(self.rate_slider_value, - expand=True, fill=True) - - self.rate_slider_adj = gtk.Adjustment( - self.rate_to_slider(self.config['max_upload_rate']), 0, - self.max_exponent, 0.01, 0.1) - - self.rate_slider = gtk.HScale(self.rate_slider_adj) - self.rate_slider.set_draw_value(False) - self.rate_slider_adj.connect('value_changed', self.set_max_upload_rate) - - self.pack_start(self.rate_slider , expand=False, fill=False) - self.pack_start(self.rate_slider_label_box , expand=False, fill=False) - - if False: # this shows the legend for the slider - self.rate_slider_legend = gtk.HBox(homogeneous=True) - for i in range(int(self.max_exponent+1)): - label = gtk.Label(str(self.slider_to_rate(i))) - alabel = halign(label, i/self.max_exponent) - self.rate_slider_legend.pack_start(alabel, - expand=True, fill=True) - self.pack_start(self.rate_slider_legend, expand=False, fill=False) - - - def start(self): - self.set_max_upload_rate(self.rate_slider_adj) - - def rate_to_slider(self, value): - return math.log(value/self.multiplier, self.base) - - def slider_to_rate(self, value): - return int(round(self.base**value * self.multiplier)) - - def value_to_label(self, value): - conn_type = '' - for key, conn in self.speed_classes.items(): - min_v, max_v = key - if min_v <= value <= max_v: - conn_type = ' (%s)'%conn - break - label = str(Rate(value*1024)) + conn_type - return label - - def set_max_upload_rate(self, adj): - option = 'max_upload_rate' - value = self.slider_to_rate(adj.get_value()) - self.config[option] = value - self.torrentqueue.set_config(option, value) - self.rate_slider_value.set_text(self.value_to_label(int(value))) - - -class StopStartButton(gtk.Button): - stop_tip = _("Temporarily stop all running torrents") - start_tip = _("Resume downloading") - - def __init__(self, main): - gtk.Button.__init__(self) - self.main = main - self.connect('clicked', self.toggle) - - self.stop_image = gtk.Image() - self.stop_image.set_from_stock('bt-pause', gtk.ICON_SIZE_BUTTON) - self.stop_image.show() - - self.start_image = gtk.Image() - self.start_image.set_from_stock('bt-play', gtk.ICON_SIZE_BUTTON) - self.start_image.show() - - def toggle(self, widget): - self.set_paused(not self.main.config['pause']) - - def set_paused(self, paused): - image = self.get_child() - if paused: - if image == self.stop_image: - self.remove(self.stop_image) - if image != self.start_image: - self.add(self.start_image) - self.main.tooltips.set_tip(self, self.start_tip) - self.main.stop_queue() - else: - if image == self.start_image: - self.remove(self.start_image) - if image != self.stop_image: - self.add(self.stop_image) - self.main.tooltips.set_tip(self, self.stop_tip ) - self.main.restart_queue() - - -class VersionWindow(Window): - def __init__(self, main, newversion, download_url): - Window.__init__(self) - self.set_title(_("New %s version available")%app_name) - self.set_border_width(SPACING) - self.set_resizable(False) - self.main = main - self.newversion = newversion - self.download_url = download_url - self.connect('destroy', lambda w: self.main.window_closed('version')) - self.vbox = gtk.VBox(spacing=SPACING) - self.hbox = gtk.HBox(spacing=SPACING) - self.image = gtk.Image() - self.image.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_DIALOG) - self.hbox.pack_start(self.image) - - self.label = gtk.Label() - self.label.set_markup( - (_("A newer version of %s is available.\n") % app_name) + - (_("You are using %s, and the new version is %s.\n") % (version, newversion)) + - (_("You can always get the latest version from \n%s") % self.download_url) - ) - self.label.set_selectable(True) - self.hbox.pack_start(self.label) - self.vbox.pack_start(self.hbox) - self.bbox = gtk.HBox(spacing=SPACING) - - self.closebutton = gtk.Button(_("Download _later")) - self.closebutton.connect('clicked', self.close) - - self.newversionbutton = gtk.Button(_("Download _now")) - self.newversionbutton.connect('clicked', self.get_newversion) - - self.bbox.pack_end(self.newversionbutton, expand=False, fill=False) - self.bbox.pack_end(self.closebutton , expand=False, fill=False) - - self.checkbox = gtk.CheckButton(_("_Remind me later")) - self.checkbox.set_active(True) - self.checkbox.connect('toggled', self.remind_toggle) - - self.bbox.pack_start(self.checkbox, expand=False, fill=False) - - self.vbox.pack_start(self.bbox) - - self.add(self.vbox) - self.show_all() - - def remind_toggle(self, widget): - v = self.checkbox.get_active() - notified = '' - if v: - notified = '' - else: - notified = self.newversion - self.main.set_config('notified', str(notified)) - - def close(self, widget): - self.destroy() - - def get_newversion(self, widget): - if self.main.updater.can_install(): - if self.main.updater.torrentfile is None: - self.main.visit_url(self.download_url) - else: - self.main.start_auto_update() - else: - self.main.visit_url(self.download_url) - self.destroy() - - -class AboutWindow(object): - - def __init__(self, main, donatefunc): - self.win = Window() - self.win.set_title(_("About %s")%app_name) - self.win.set_size_request(300,400) - self.win.set_border_width(SPACING) - self.win.set_resizable(False) - self.win.connect('destroy', lambda w: main.window_closed('about')) - self.scroll = gtk.ScrolledWindow() - self.scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - self.scroll.set_shadow_type(gtk.SHADOW_IN) - - self.outervbox = gtk.VBox() - - self.outervbox.pack_start(get_logo(96), expand=False, fill=False) - - version_str = version - if int(version_str[2]) % 2: - version_str = version_str + ' ' + _("Beta") - - self.outervbox.pack_start(gtk.Label(_("Version %s")%version_str), expand=False, fill=False) - - if branch is not None: - blabel = gtk.Label('cdv client dir: %s' % branch) - self.outervbox.pack_start(blabel, expand=False, fill=False) - - self.vbox = gtk.VBox() - self.vbox.set_size_request(250, -1) - - for i, fn in enumerate(('credits', 'credits-l10n')): - if i != 0: - self.vbox.pack_start(gtk.HSeparator(), padding=SPACING, - expand=False, fill=False) - filename = os.path.join(doc_root, fn+'.txt') - l = '' - if not os.access(filename, os.F_OK|os.R_OK): - l = _("Couldn't open %s") % filename - else: - credits_f = file(filename) - l = credits_f.read() - credits_f.close() - if os.name == 'nt': - # gtk ignores blank lines on win98 - l = l.replace('\n\n', '\n\t\n') - label = gtk.Label(l.strip()) - label.set_line_wrap(True) - label.set_selectable(True) - label.set_justify(gtk.JUSTIFY_CENTER) - label.set_size_request(250,-1) - self.vbox.pack_start(label, expand=False, fill=False) - - self.scroll.add_with_viewport(self.vbox) - - self.outervbox.pack_start(self.scroll, padding=SPACING) - - self.donatebutton = gtk.Button(_("Donate")) - self.donatebutton.connect('clicked', donatefunc) - self.donatebuttonbox = gtk.HButtonBox() - self.donatebuttonbox.pack_start(self.donatebutton, - expand=False, fill=False) - self.outervbox.pack_end(self.donatebuttonbox, expand=False, fill=False) - - self.win.add(self.outervbox) - - self.win.show_all() - - def close(self, widget): - self.win.destroy() - - -class LogWindow(object): - def __init__(self, main, logbuffer, config): - self.config = config - self.main = main - self.win = Window() - self.win.set_title(_("%s Activity Log")%app_name) - self.win.set_default_size(600, 200) - self.win.set_border_width(SPACING) - - self.buffer = logbuffer - self.text = gtk.TextView(self.buffer) - self.text.set_editable(False) - self.text.set_cursor_visible(False) - self.text.set_wrap_mode(gtk.WRAP_WORD) - - self.scroll = gtk.ScrolledWindow() - self.scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - self.scroll.set_shadow_type(gtk.SHADOW_IN) - self.scroll.add(self.text) - - self.vbox = gtk.VBox(spacing=SPACING) - self.vbox.pack_start(self.scroll) - - self.buttonbox = gtk.HButtonBox() - self.buttonbox.set_spacing(SPACING) - - self.closebutton = gtk.Button(stock='gtk-close') - self.closebutton.connect('clicked', self.close) - - self.savebutton = gtk.Button(stock='gtk-save') - self.savebutton.connect('clicked', self.save_log_file_selection) - - self.clearbutton = gtk.Button(stock='gtk-clear') - self.clearbutton.connect('clicked', self.clear_log) - - self.buttonbox.pack_start(self.savebutton) - self.buttonbox.pack_start(self.closebutton) - - self.hbox2 = gtk.HBox(homogeneous=False) - - self.hbox2.pack_end(self.buttonbox, expand=False, fill=False) - - bb = gtk.HButtonBox() - bb.pack_start(self.clearbutton) - self.hbox2.pack_start(bb, expand=False, fill=True) - - self.vbox.pack_end(self.hbox2, expand=False, fill=True) - - self.win.add(self.vbox) - self.win.connect("destroy", lambda w: self.main.window_closed('log')) - self.scroll_to_end() - self.win.show_all() - - def scroll_to_end(self): - mark = self.buffer.create_mark(None, self.buffer.get_end_iter()) - self.text.scroll_mark_onscreen(mark) - - def save_log_file_selection(self, *args): - name = 'bittorrent.log' - path = smart_dir(self.config['save_in']) - fullname = os.path.join(path, name) - self.main.open_window('savefile', - title=_("Save log in:"), - fullname=fullname, - got_location_func=self.save_log, - no_location_func=lambda: self.main.window_closed('savefile')) - - - def save_log(self, saveas): - self.main.window_closed('savefile') - f = file(saveas, 'w') - f.write(self.buffer.get_text(self.buffer.get_start_iter(), - self.buffer.get_end_iter())) - save_message = self.buffer.log_text(_("log saved"), None) - f.write(save_message) - f.close() - - def clear_log(self, *args): - self.buffer.clear_log() - - def close(self, widget): - self.win.destroy() - - -class LogBuffer(gtk.TextBuffer): - - def __init__(self): - gtk.TextBuffer.__init__(self) - - tt = self.get_tag_table() - - size_tag = gtk.TextTag('small') - size_tag.set_property('size-points', 10) - tt.add(size_tag) - - info_tag = gtk.TextTag('info') - info_tag.set_property('foreground', '#00a040') - tt.add(info_tag) - - warning_tag = gtk.TextTag('warning') - warning_tag.set_property('foreground', '#a09000') - tt.add(warning_tag) - - error_tag = gtk.TextTag('error') - error_tag.set_property('foreground', '#b00000') - tt.add(error_tag) - - critical_tag = gtk.TextTag('critical') - critical_tag.set_property('foreground', '#b00000') - critical_tag.set_property('weight', pango.WEIGHT_BOLD) - tt.add(critical_tag) - - - def log_text(self, text, severity=CRITICAL): - now_str = datetime.datetime.strftime(datetime.datetime.now(), - '[%Y-%m-%d %H:%M:%S] ') - self.insert_with_tags_by_name(self.get_end_iter(), now_str, 'small') - if severity is not None: - self.insert_with_tags_by_name(self.get_end_iter(), '%s\n'%text, - 'small', status_dict[severity]) - else: - self.insert_with_tags_by_name(self.get_end_iter(), - ' -- %s -- \n'%text, 'small') - - return now_str+text+'\n' - - def clear_log(self): - self.set_text('') - self.log_text(_("log cleared"), None) - - -class CheckButton(gtk.CheckButton): - def __init__(self, label, main, option_name, initial_value, - extra_callback=None): - gtk.CheckButton.__init__(self, label) - self.main = main - self.option_name = option_name - self.option_type = type(initial_value) - self.set_active(bool(initial_value)) - self.extra_callback = extra_callback - self.connect('toggled', self.callback) - - def callback(self, *args): - self.main.config[self.option_name] = \ - self.option_type(not self.main.config[self.option_name]) - self.main.setfunc(self.option_name, self.main.config[self.option_name]) - if self.extra_callback is not None: - self.extra_callback() - - -class SettingsWindow(object): - - def __init__(self, main, config, setfunc): - self.main = main - self.setfunc = setfunc - self.config = config - self.win = Window() - self.win.connect("destroy", lambda w: main.window_closed('settings')) - self.win.set_title(_("%s Settings")%app_name) - self.win.set_border_width(SPACING) - - self.notebook = gtk.Notebook() - - self.vbox = gtk.VBox(spacing=SPACING) - self.vbox.pack_start(self.notebook, expand=False, fill=False) - - # General tab - if os.name == 'nt': - self.cb_box = gtk.VBox(spacing=SPACING) - self.cb_box.set_border_width(SPACING) - self.notebook.append_page(self.cb_box, gtk.Label(_("General"))) - - self.startup_checkbutton = CheckButton( - _("Launch BitTorrent when Windows starts"), self, - 'launch_on_startup', self.config['launch_on_startup']) - self.cb_box.pack_start(self.startup_checkbutton, expand=False, fill=False) - self.startup_checkbutton.connect('toggled', self.launch_on_startup) - - self.minimize_checkbutton = CheckButton( - _("Minimize to system tray"), self, - 'minimize_to_tray', self.config['minimize_to_tray']) - self.cb_box.pack_start(self.minimize_checkbutton, expand=False, fill=False) - - # allow the user to set the progress bar text to all black - self.progressbar_hack = CheckButton( - _("Progress bar text is always black\n(requires restart)"), - self, 'progressbar_hack', self.config['progressbar_hack']) - - self.cb_box.pack_start(self.progressbar_hack, expand=False, fill=False) - # end General tab - - # Saving tab - self.saving_box = gtk.VBox(spacing=SPACING) - self.saving_box.set_border_width(SPACING) - self.notebook.append_page(self.saving_box, gtk.Label(_("Saving"))) - - self.dl_frame = gtk.Frame(_("Save new downloads in:")) - self.saving_box.pack_start(self.dl_frame, expand=False, fill=False) - - self.dl_box = gtk.VBox(spacing=SPACING) - self.dl_box.set_border_width(SPACING) - self.dl_frame.add(self.dl_box) - self.save_in_box = gtk.HBox(spacing=SPACING) - - self.dl_save_in = gtk.Entry() - self.dl_save_in.set_editable(False) - self.set_save_in(self.config['save_in']) - self.save_in_box.pack_start(self.dl_save_in, expand=True, fill=True) - - self.dl_save_in_button = gtk.Button(_("Change...")) - self.dl_save_in_button.connect('clicked', self.get_save_in) - self.save_in_box.pack_start(self.dl_save_in_button, expand=False, fill=False) - self.dl_box.pack_start(self.save_in_box, expand=False, fill=False) - - self.dl_ask_checkbutton = CheckButton( - _("Ask where to save each new download"), self, - 'ask_for_save', self.config['ask_for_save']) - - self.dl_box.pack_start(self.dl_ask_checkbutton, expand=False, fill=False) - # end Saving tab - - # Downloading tab - self.downloading_box = gtk.VBox(spacing=SPACING) - self.downloading_box.set_border_width(SPACING) - self.notebook.append_page(self.downloading_box, gtk.Label(_("Downloading"))) - - self.dnd_frame = gtk.Frame(_("When starting a new torrent:")) - self.dnd_box = gtk.VBox(spacing=SPACING, homogeneous=True) - self.dnd_box.set_border_width(SPACING) - - self.dnd_states = ['replace','add','ask'] - self.dnd_original_state = self.config['start_torrent_behavior'] - - self.always_replace_radio = gtk.RadioButton( - group=None, - label=_("_Stop another running torrent to make room")) - self.dnd_box.pack_start(self.always_replace_radio) - self.always_replace_radio.state_name = self.dnd_states[0] - - self.always_add_radio = gtk.RadioButton( - group=self.always_replace_radio, - label=_("_Don't stop other running torrents")) - self.dnd_box.pack_start(self.always_add_radio) - self.always_add_radio.state_name = self.dnd_states[1] - - self.always_ask_radio = gtk.RadioButton( - group=self.always_replace_radio, - label=_("_Ask each time") - ) - self.dnd_box.pack_start(self.always_ask_radio) - self.always_ask_radio.state_name = self.dnd_states[2] - - self.dnd_group = self.always_replace_radio.get_group() - for r in self.dnd_group: - r.connect('toggled', self.start_torrent_behavior_changed) - - self.set_start_torrent_behavior(self.config['start_torrent_behavior']) - - self.dnd_frame.add(self.dnd_box) - self.downloading_box.pack_start(self.dnd_frame, expand=False, fill=False) - - # Seeding tab - self.seeding_box = gtk.VBox(spacing=SPACING) - self.seeding_box.set_border_width(SPACING) - self.notebook.append_page(self.seeding_box, gtk.Label(_("Seeding"))) - - def colon_split(framestr): - COLONS = (':', u'\uff1a') - for colon in COLONS: - if colon in framestr: - return framestr.split(colon) - return '', framestr - - nt_framestr = _("Seed completed torrents: until share ratio reaches [_] percent, or for [_] minutes, whichever comes first.") - nt_title, nt_rem = colon_split(nt_framestr) - nt_msg1, nt_msg2, nt_msg4 = nt_rem.split('[_]') - nt_msg3 = '' - if ',' in nt_msg2: - nt_msg2, nt_msg3 = nt_msg2.split(',') - nt_msg2 += ',' - - self.next_torrent_frame = gtk.Frame(nt_title+':') - self.next_torrent_box = gtk.VBox(spacing=SPACING, homogeneous=True) - self.next_torrent_box.set_border_width(SPACING) - - self.next_torrent_frame.add(self.next_torrent_box) - - - self.next_torrent_ratio_box = gtk.HBox() - self.next_torrent_ratio_box.pack_start(gtk.Label(nt_msg1), - fill=False, expand=False) - self.next_torrent_ratio_field = PercentValidator('next_torrent_ratio', - self.config, self.setfunc) - self.next_torrent_ratio_box.pack_start(self.next_torrent_ratio_field, - fill=False, expand=False) - self.next_torrent_ratio_box.pack_start(gtk.Label(nt_msg2), - fill=False, expand=False) - self.next_torrent_box.pack_start(self.next_torrent_ratio_box) - - - self.next_torrent_time_box = gtk.HBox() - self.next_torrent_time_box.pack_start(gtk.Label(nt_msg3), - fill=False, expand=False) - self.next_torrent_time_field = MinutesValidator('next_torrent_time', - self.config, self.setfunc) - self.next_torrent_time_box.pack_start(self.next_torrent_time_field, - fill=False, expand=False) - self.next_torrent_time_box.pack_start(gtk.Label(nt_msg4), - fill=False, expand=False) - self.next_torrent_box.pack_start(self.next_torrent_time_box) - - def seed_forever_extra(): - for field in (self.next_torrent_ratio_field, - self.next_torrent_time_field): - field.set_sensitive(not self.config['seed_forever']) - - seed_forever_extra() - self.seed_forever = CheckButton( _("Seed indefinitely"), self, - 'seed_forever', - self.config['seed_forever'], - seed_forever_extra) - self.next_torrent_box.pack_start(self.seed_forever) - # end next torrent seed behavior - - # begin last torrent seed behavior - lt_framestr = _("Seed last completed torrent: until share ratio reaches [_] percent.") - lt_title, lt_rem = colon_split(lt_framestr) - lt_msg1, lt_msg2 = lt_rem.split('[_]') - - self.seeding_box.pack_start(self.next_torrent_frame, expand=False, fill=False) - - self.last_torrent_frame = gtk.Frame(lt_title+':') - self.last_torrent_vbox = gtk.VBox(spacing=SPACING) - self.last_torrent_vbox.set_border_width(SPACING) - self.last_torrent_box = gtk.HBox() - self.last_torrent_box.pack_start(gtk.Label(lt_msg1), - expand=False, fill=False) - self.last_torrent_ratio_field = PercentValidator('last_torrent_ratio', - self.config, self.setfunc) - self.last_torrent_box.pack_start(self.last_torrent_ratio_field, - fill=False, expand=False) - self.last_torrent_box.pack_start(gtk.Label(lt_msg2), - fill=False, expand=False) - self.last_torrent_vbox.pack_start(self.last_torrent_box) - - def seed_last_forever_extra(): - self.last_torrent_ratio_field.set_sensitive( - not self.config['seed_last_forever']) - - seed_last_forever_extra() - - self.seed_last_forever = CheckButton(_("Seed indefinitely"), self, - 'seed_last_forever', - self.config['seed_last_forever'], - seed_last_forever_extra) - self.last_torrent_vbox.pack_start(self.seed_last_forever) - - self.last_torrent_frame.add(self.last_torrent_vbox) - self.seeding_box.pack_start(self.last_torrent_frame, expand=False, fill=False) - - # Network tab - self.network_box = gtk.VBox(spacing=SPACING) - self.network_box.set_border_width(SPACING) - self.notebook.append_page(self.network_box, gtk.Label(_("Network"))) - - self.port_range_frame = gtk.Frame(_("Look for available port:")) - self.port_range_box = gtk.VBox(spacing=SPACING) - self.port_range_box.set_border_width(SPACING) - - self.port_range = gtk.HBox() - self.port_range.pack_start(gtk.Label(_("starting at port: ")), - expand=False, fill=False) - self.minport_field = PortValidator('minport', self.config, self.setfunc) - self.minport_field.add_end('maxport') - self.port_range.pack_start(self.minport_field, expand=False, fill=False) - self.minport_field.settingswindow = self - self.port_range.pack_start(gtk.Label(' (1024-65535)'), - expand=False, fill=False) - self.port_range_box.pack_start(self.port_range, - expand=False, fill=False) - - self.upnp = CheckButton(_("Enable automatic port mapping")+' (_UPnP)', - self, 'upnp', self.config['upnp'], None) - self.port_range_box.pack_start(self.upnp, - expand=False, fill=False) - - self.port_range_frame.add(self.port_range_box) - self.network_box.pack_start(self.port_range_frame, expand=False, fill=False) - - self.ip_frame = gtk.Frame(_("IP to report to the tracker:")) - self.ip_box = gtk.VBox() - self.ip_box.set_border_width(SPACING) - self.ip_field = IPValidator('ip', self.config, self.setfunc) - self.ip_box.pack_start(self.ip_field, expand=False, fill=False) - label = gtk.Label(_("(Has no effect unless you are on the\nsame local network as the tracker)")) - label.set_line_wrap(True) - self.ip_box.pack_start(lalign(label), expand=False, fill=False) - self.ip_frame.add(self.ip_box) - self.network_box.pack_start(self.ip_frame, expand=False, fill=False) - - # end Network tab - - # Language tab - self.languagechooser = LanguageChooser() - self.notebook.append_page(self.languagechooser, gtk.Label("Language")) - # end Language tab - - # Advanced tab - if advanced_ui: - self.advanced_box = gtk.VBox(spacing=SPACING) - self.advanced_box.set_border_width(SPACING) - hint = gtk.Label(_("WARNING: Changing these settings can\nprevent %s from functioning correctly.")%app_name) - self.advanced_box.pack_start(lalign(hint), expand=False, fill=False) - self.store = gtk.ListStore(*[gobject.TYPE_STRING] * 2) - for option in ui_options[advanced_ui_options_index:]: - self.store.append((option, str(self.config[option]))) - - self.treeview = gtk.TreeView(self.store) - r = gtk.CellRendererText() - column = gtk.TreeViewColumn(_("Option"), r, text=0) - self.treeview.append_column(column) - r = gtk.CellRendererText() - r.set_property('editable', True) - r.connect('edited', self.store_value_edited) - column = gtk.TreeViewColumn(_("Value"), r, text=1) - self.treeview.append_column(column) - self.advanced_frame = gtk.Frame() - self.advanced_frame.set_shadow_type(gtk.SHADOW_IN) - self.advanced_frame.add(self.treeview) - - self.advanced_box.pack_start(self.advanced_frame, expand=False, fill=False) - self.notebook.append_page(self.advanced_box, gtk.Label(_("Advanced"))) - - - self.win.add(self.vbox) - self.win.show_all() - - - def get_save_in(self, widget=None): - self.file_selection = self.main.open_window('choosefolder', - title=_("Choose default download directory"), - fullname=self.config['save_in'], - got_location_func=self.set_save_in, - no_location_func=lambda: self.main.window_closed('choosefolder')) - - def set_save_in(self, save_location): - self.main.window_closed('choosefolder') - if os.path.isdir(save_location): - if save_location[-1] != os.sep: - save_location += os.sep - self.config['save_in'] = save_location - save_in = path_wrap(self.config['save_in']) - self.dl_save_in.set_text(save_in) - self.setfunc('save_in', self.config['save_in']) - - def launch_on_startup(self, *args): - dst = os.path.join(get_startup_dir(), app_name) - if self.config['launch_on_startup']: - src = os.path.abspath(sys.argv[0]) - create_shortcut(src, dst, "--start_minimized") - else: - try: - remove_shortcut(dst) - except Exception, e: - self.main.global_error(WARNING, _("Failed to remove shortcut: %s") % str(e)) - - def set_start_torrent_behavior(self, state_name): - if state_name in self.dnd_states: - for r in self.dnd_group: - if r.state_name == state_name: - r.set_active(True) - else: - r.set_active(False) - else: - self.always_replace_radio.set_active(True) - - def start_torrent_behavior_changed(self, radiobutton): - if radiobutton.get_active(): - self.setfunc('start_torrent_behavior', radiobutton.state_name) - - def store_value_edited(self, cell, row, new_text): - it = self.store.get_iter_from_string(row) - option = ui_options[int(row)+advanced_ui_options_index] - t = type(defconfig[option]) - try: - if t is type(None) or t is str: - value = new_text - elif t is int or t is long: - value = int(new_text) - elif t is float: - value = float(new_text) - elif t is bool: - value = value == 'True' - else: - raise TypeError, str(t) - except ValueError: - return - self.setfunc(option, value) - self.store.set(it, 1, str(value)) - - def close(self, widget): - self.win.destroy() - - -class FileListWindow(object): - - SET_PRIORITIES = False - - def __init__(self, metainfo, closefunc): - self.metainfo = metainfo - self.setfunc = None - self.allocfunc = None - self.win = Window() - self.win.set_title(_('Files in "%s"') % self.metainfo.name) - self.win.connect("destroy", closefunc) - self.tooltips = gtk.Tooltips() - - self.filepath_to_iter = {} - - self.box1 = gtk.VBox() - - size_request = (0,0) - if self.SET_PRIORITIES: - self.toolbar = gtk.Toolbar() - for label, tip, stockicon, method, arg in ( - (_("Never" ), _("Never download" ), gtk.STOCK_DELETE, self.dosomething, -1,), - (_("Normal"), _("Download normally"), gtk.STOCK_NEW , self.dosomething, 0,), - (_("First" ), _("Download first" ),'bt-finished' , self.dosomething, +1,),): - self.make_tool_item(label, tip, stockicon, method, arg) - size_request = (-1,54) - self.box1.pack_start(self.toolbar, False) - - self.sw = gtk.ScrolledWindow() - self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.box1.pack_start(self.sw) - self.win.add(self.box1) - - columns = [_("Filename"),_("Length"),_('%')] - pre_size_list = ['M'*30, '6666 MB', '100.0', 'Download','black'] - if self.SET_PRIORITIES: - columns.append(_("Download")) - num_columns = len(pre_size_list) - - self.store = gtk.TreeStore(*[gobject.TYPE_STRING] * num_columns) - self.store.append(None, pre_size_list) - self.treeview = gtk.TreeView(self.store) - self.treeview.set_enable_search(True) - self.treeview.set_search_column(0) - cs = [] - for i, name in enumerate(columns): - r = gtk.CellRendererText() - r.set_property('xalign', (0, 1, 1, 1)[i]) - if i == 0: - column = gtk.TreeViewColumn(name, r, text = i, foreground = len(pre_size_list)-1) - else: - column = gtk.TreeViewColumn(name, r, text = i) - column.set_resizable(True) - self.treeview.append_column(column) - cs.append(column) - - self.sw.add(self.treeview) - self.treeview.set_headers_visible(False) - self.treeview.columns_autosize() - self.box1.show_all() - self.treeview.realize() - - for column in cs: - column.set_fixed_width(max(5,column.get_width())) - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - self.treeview.set_headers_visible(True) - self.store.clear() - - if self.SET_PRIORITIES: - self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) - else: - self.treeview.get_selection().set_mode(gtk.SELECTION_NONE) - - self.piecelen = self.metainfo.piece_length - self.lengths = self.metainfo.sizes - self.initialize_file_priorities()#[0,0]) - for name, size, priority in itertools.izip(self.metainfo.orig_files, - self.metainfo.sizes, self.priorities): - parent_name, local_name = os.path.split(name) - parent_iter = self.recursive_add(parent_name) - - row = [local_name, Size(size), '?','', 'black'] - it = self.store.append(parent_iter, row) - self.filepath_to_iter[name] = it - - self.treeview.expand_all() - tvsr = self.treeview.size_request() - vertical_padding = 18 - size_request = [max(size_request[0],tvsr[0]), - (size_request[1] + tvsr[1] ) + vertical_padding] - maximum_height = 300 - if size_request[1] > maximum_height - SCROLLBAR_WIDTH: - size_request[1] = maximum_height - size_request[0] = size_request[0] + SCROLLBAR_WIDTH - self.win.set_default_size(*size_request) - - self.win.show_all() - - def recursive_add(self, fullpath): - if fullpath == '': - return None - elif self.filepath_to_iter.has_key(fullpath): - return self.filepath_to_iter[fullpath] - else: - parent_path, local_path = os.path.split(fullpath) - parent_iter = self.recursive_add(parent_path) - it = self.store.append(parent_iter, - (local_path,) + - ('',) * (self.store.get_n_columns()-2) + - ('black',)) - self.filepath_to_iter[fullpath] = it - return it - - def make_tool_item(self, label, tip, stockicon, method, arg): - icon = gtk.Image() - icon.set_from_stock(stockicon, gtk.ICON_SIZE_SMALL_TOOLBAR) - item = gtk.ToolButton(icon_widget=icon, label=label) - item.set_homogeneous(True) - item.set_tooltip(self.tooltips, tip) - if arg is not None: - item.connect('clicked', method, arg) - else: - item.connect('clicked', method) - self.toolbar.insert(item, 0) - - def initialize_file_priorities(self): - self.priorities = [] - for length in self.lengths: - self.priorities.append(0) - -## Uoti wrote these methods. I have no idea what this code is supposed to do. -## --matt -## def set_priorities(self, widget): -## r = [] -## piece = 0 -## pos = 0 -## curprio = prevprio = 1000 -## for priority, length in itertools.izip(self.priorities, self.lengths): -## pos += length -## curprio = min(priority, curprio) -## while pos >= (piece + 1) * self.piecelen: -## if curprio != prevprio: -## r.extend((piece, curprio)) -## prevprio = curprio -## if curprio == priority: -## piece = pos // self.piecelen -## else: -## piece += 1 -## if pos == piece * self.piecelen: -## curprio = 1000 -## else: -## curprio = priority -## if curprio != prevprio: -## r.extend((piece, curprio)) -## self.setfunc(r) -## it = self.store.get_iter_first() -## for i in xrange(len(self.priorities)): -## self.store.set_value(it, 5, "black") -## it = self.store.iter_next(it) -## self.origpriorities = list(self.priorities) -## -## def initialize_file_priorities(self, piecepriorities): -## self.priorities = [] -## piecepriorities = piecepriorities + [999999999] -## it = iter(piecepriorities) -## assert it.next() == 0 -## pos = piece = curprio = 0 -## for length in self.lengths: -## pos += length -## priority = curprio -## while pos >= piece * self.piecelen: -## curprio = it.next() -## if pos > piece * self.piecelen: -## priority = max(priority, curprio) -## piece = it.next() -## self.priorities.append(priority) -## self.origpriorities = list(self.priorities) - - def dosomething(self, widget, dowhat): - self.treeview.get_selection().selected_foreach(self.adjustfile, dowhat) - - def adjustfile(self, treemodel, path, it, dowhat): - length = treemodel.get(it, 1)[0] - if length == '': - child = treemodel.iter_children(it) - while True: - if child is None: - return - elif not treemodel.is_ancestor(it, child): - return - else: - self.adjustfile(treemodel, path, child, dowhat) - child = treemodel.iter_next(child) - - else: - # BUG: need to set file priorities in backend here - if dowhat == -1: - text, color = _("never"), 'darkgrey' - elif dowhat == 1: - text, color = _("first"), 'darkgreen' - else: - text, color = '', 'black' - treemodel.set_value(it, 3, text ) - treemodel.set_value(it, 4, color) - - def update(self, left, allocated): - for name, left, total, alloc in itertools.izip( - self.metainfo.orig_files, left, self.lengths, allocated): - it = self.filepath_to_iter[name] - if total == 0: - p = 1 - else: - p = (total - left) / total - self.store.set_value(it, 2, "%.1f" % (int(p * 1000)/10)) - - def close(self): - self.win.destroy() - - -class PeerListWindow(object): - - def __init__(self, torrent_name, closefunc): - self.win = Window() - self.win.connect("destroy", closefunc) - self.win.set_title( _('Peers for "%s"')%torrent_name) - self.sw = gtk.ScrolledWindow() - self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - self.sw.set_shadow_type(gtk.SHADOW_IN) - self.win.add(self.sw) - - column_header = [_("IP address"), _("Client"), _("Connection"), _("KB/s down"), _("KB/s up"), _("MB downloaded"), _("MB uploaded"), _("% complete"), _("KB/s est. peer download")] - pre_size_list = ['666.666.666.666', 'TorrentStorm 1.3', 'bad peer', 66666, 66666, '1666.66', '1666.66', '100.0', 6666] - numeric_cols = [3,4,5,6,7,8] - store_types = [gobject.TYPE_STRING]*3 + [gobject.TYPE_INT]*2 + [gobject.TYPE_STRING]*3 + [gobject.TYPE_INT] - - if advanced_ui: - column_header[2:2] = [_("Peer ID")] - pre_size_list[2:2] = ['-AZ2104-'] - store_types[2:2] = [gobject.TYPE_STRING] - column_header[5:5] = [_("Interested"),_("Choked"),_("Snubbed")] - pre_size_list[5:5] = ['*','*','*'] - store_types[5:5] = [gobject.TYPE_STRING]*3 - column_header[9:9] = [_("Interested"),_("Choked"),_("Optimistic upload")] - pre_size_list[9:9] = ['*','*','*'] - store_types[9:9] = [gobject.TYPE_STRING]*3 - numeric_cols = [4,8,12,13,14,15] - - num_columns = len(column_header) - self.store = gtk.ListStore(*store_types) - self.store.append(pre_size_list) - - def makesortfunc(sort_func): - def sortfunc(treemodel, iter1, iter2, column): - a_str = treemodel.get_value(iter1, column) - b_str = treemodel.get_value(iter2, column) - if a_str is not None and b_str is not None: - return sort_func(a_str,b_str) - else: - return 0 - return sortfunc - - def ip_sort(a_str,b_str): - for a,b in zip(a_str.split('.'), b_str.split('.')): - if a == b: - continue - if len(a) == len(b): - return cmp(a,b) - return cmp(int(a), int(b)) - return 0 - - def float_sort(a_str,b_str): - a,b = 0,0 - try: a = float(a_str) - except ValueError: pass - try: b = float(b_str) - except ValueError: pass - return cmp(a,b) - - self.store.set_sort_func(0, makesortfunc(ip_sort), 0) - for i in range(2,5): - self.store.set_sort_func(num_columns-i, makesortfunc(float_sort), num_columns-i) - - self.treeview = gtk.TreeView(self.store) - cs = [] - for i, name in enumerate(column_header): - r = gtk.CellRendererText() - if i in numeric_cols: - r.set_property('xalign', 1) - column = gtk.TreeViewColumn(name, r, text = i) - column.set_resizable(True) - column.set_min_width(5) - column.set_sort_column_id(i) - self.treeview.append_column(column) - cs.append(column) - self.treeview.set_rules_hint(True) - self.sw.add(self.treeview) - self.treeview.set_headers_visible(False) - self.treeview.columns_autosize() - self.sw.show_all() - self.treeview.realize() - for column in cs: - column.set_fixed_width(column.get_width()) - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - self.treeview.set_headers_visible(True) - self.store.clear() - self.treeview.get_selection().set_mode(gtk.SELECTION_NONE) - width = self.treeview.size_request()[0] - self.win.set_default_size(width+SCROLLBAR_WIDTH, 300) - self.win.show_all() - self.prev = [] - - - def update(self, peers, bad_peers): - fields = [] - - def p_bool(value): return value and '*' or '' - - for peer in peers: - field = [] - field.append(peer['ip']) - - client, version = ClientIdentifier.identify_client(peer['id']) - field.append(client + ' ' + version) - - if advanced_ui: - field.append(zurllib.quote(peer['id'])) - - field.append(peer['initiation'] == 'R' and _("remote") or _("local")) - dl = peer['download'] - ul = peer['upload'] - - for l in (dl, ul): - rate = l[1] - if rate > 100: - field.append(int(round(rate/(2**10)))) - else: - field.append(0) - if advanced_ui: - field.append(p_bool(l[2])) - field.append(p_bool(l[3])) - if len(l) > 4: - field.append(p_bool(l[4])) - else: - field.append(p_bool(peer['is_optimistic_unchoke'])) - - field.append('%.2f'%round(dl[0] / 2**20, 2)) - field.append('%.2f'%round(ul[0] / 2**20, 2)) - field.append('%.1f'%round(int(peer['completed']*1000)/10, 1)) - - field.append(int(peer['speed']//(2**10))) - - fields.append(field) - - for (ip, (is_banned, stats)) in bad_peers.iteritems(): - field = [] - field.append(ip) - - client, version = ClientIdentifier.identify_client(stats.peerid) - field.append(client + ' ' + version) - - if advanced_ui: - field.append(zurllib.quote(stats.peerid)) - - field.append(_("bad peer")) - - # the sortable peer list won't take strings in these fields - field.append(0) - - if advanced_ui: - field.extend([0] * 7) # upRate, * fields - else: - field.extend([0] * 1) # upRate - - field.append(_("%d ok") % stats.numgood) - field.append(_("%d bad") % len(stats.bad)) - if is_banned: # completion - field.append(_("banned")) - else: - field.append(_("ok")) - field.append(0) # peer dl rate - fields.append(field) - - if self.store.get_sort_column_id() < 0: - # ListStore is unsorted, it might be faster to set only modified fields - it = self.store.get_iter_first() - for old, new in itertools.izip(self.prev, fields): - if old != new: - for i, value in enumerate(new): - if value != old[i]: - self.store.set_value(it, i, value) - it = self.store.iter_next(it) - for i in range(len(fields), len(self.prev)): - self.store.remove(it) - for i in range(len(self.prev), len(fields)): - self.store.append(fields[i]) - self.prev = fields - else: - # ListStore is sorted, no reason not to to reset all fields - self.store.clear() - for field in fields: - self.store.append(field) - - - - def close(self): - self.win.destroy() - - -class TorrentInfoWindow(object): - - def __init__(self, torrent_box, closefunc): - self.win = Window() - self.torrent_box = torrent_box - name = self.torrent_box.metainfo.name - self.win.set_title(_('Info for "%s"')%name) - self.win.set_size_request(-1,-1) - self.win.set_border_width(SPACING) - self.win.set_resizable(False) - self.win.connect('destroy', closefunc) - self.vbox = gtk.VBox(spacing=SPACING) - - self.table = gtk.Table(rows=4, columns=3, homogeneous=False) - self.table.set_row_spacings(SPACING) - self.table.set_col_spacings(SPACING) - y = 0 - - def add_item(key, val, y): - self.table.attach(ralign(gtk.Label(key)), 0, 1, y, y+1) - v = gtk.Label(val) - v.set_selectable(True) - self.table.attach(lalign(v), 1, 2, y, y+1) - - add_item(_("Torrent name:"), name, y) - y+=1 - - announce = '' - if self.torrent_box.metainfo.is_trackerless: - announce = _("(trackerless torrent)") - else: - announce = self.torrent_box.metainfo.announce - add_item(_("Announce url:"), announce, y) - y+=1 - - size = Size(self.torrent_box.metainfo.total_bytes) - num_files = _(", in one file") - if self.torrent_box.is_batch: - num_files = _(", in %d files") % len(self.torrent_box.metainfo.sizes) - add_item(_("Total size:"), str(size)+num_files, y) - y+=1 - - if advanced_ui: - pl = self.torrent_box.metainfo.piece_length - count, lastlen = divmod(size, pl) - sizedetail = '%d x %d + %d = %d' % (count, pl, lastlen, int(size)) - add_item(_("Pieces:"), sizedetail, y) - y+=1 - add_item(_("Info hash:"), self.torrent_box.infohash.encode('hex'), y) - y+=1 - - path = self.torrent_box.dlpath - filename = '' - if path is None: - path = '' - else: - if not self.torrent_box.is_batch: - path,filename = os.path.split(self.torrent_box.dlpath) - if path[-1] != os.sep: - path += os.sep - path = path_wrap(path) - add_item(_("Save in:"), path, y) - y+=1 - - if not self.torrent_box.is_batch: - add_item(_("File name:"), path_wrap(filename), y) - y+=1 - - self.vbox.pack_start(self.table) - - if self.torrent_box.metainfo.comment not in (None, ''): - commentbuffer = gtk.TextBuffer() - commentbuffer.set_text(self.torrent_box.metainfo.comment) - commenttext = gtk.TextView(commentbuffer) - commenttext.set_editable(False) - commenttext.set_cursor_visible(False) - commenttext.set_wrap_mode(gtk.WRAP_WORD) - commentscroll = gtk.ScrolledWindow() - commentscroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - commentscroll.set_shadow_type(gtk.SHADOW_IN) - commentscroll.add(commenttext) - self.vbox.pack_start(commentscroll) - - self.vbox.pack_start(gtk.HSeparator(), expand=False, fill=False) - - self.hbox = gtk.HBox(spacing=SPACING) - lbbox = gtk.HButtonBox() - rbbox = gtk.HButtonBox() - lbbox.set_spacing(SPACING) - - if LaunchPath.can_launch_files: - opendirbutton = IconButton(_("_Open directory"), stock=gtk.STOCK_OPEN) - opendirbutton.connect('clicked', self.torrent_box.open_dir) - lbbox.pack_start(opendirbutton, expand=False, fill=False) - opendirbutton.set_sensitive(self.torrent_box.can_open_dir()) - - filelistbutton = IconButton(_("Show _file list"), stock='gtk-index') - if self.torrent_box.is_batch: - filelistbutton.connect('clicked', self.torrent_box.open_filelist) - else: - filelistbutton.set_sensitive(False) - lbbox.pack_start(filelistbutton, expand=False, fill=False) - - closebutton = gtk.Button(stock='gtk-close') - closebutton.connect('clicked', lambda w: self.close()) - rbbox.pack_end(closebutton, expand=False, fill=False) - - self.hbox.pack_start(lbbox, expand=False, fill=False) - self.hbox.pack_end( rbbox, expand=False, fill=False) - - self.vbox.pack_end(self.hbox, expand=False, fill=False) - - self.win.add(self.vbox) - - self.win.show_all() - - def close(self): - self.win.destroy() - - -class TorrentBox(gtk.EventBox): - torrent_tip_format = '%s:\n %s\n %s' - - def __init__(self, infohash, metainfo, dlpath, completion, main): - gtk.EventBox.__init__(self) - self.infohash = infohash - self.metainfo = metainfo - self.completion = completion - self.main = main - - self.main_torrent_dnd_tip = _("drag to reorder") - self.torrent_menu_tip = _("right-click for menu") - - self.set_save_location(dlpath) - - self.uptotal = self.main.torrents[self.infohash].uptotal - self.downtotal = self.main.torrents[self.infohash].downtotal - if self.downtotal > 0: - self.up_down_ratio = self.uptotal / self.metainfo.total_bytes - else: - self.up_down_ratio = None - - self.infowindow = None - self.filelistwindow = None - self.is_batch = metainfo.is_batch - self.menu = None - self.menu_handler = None - - self.vbox = gtk.VBox(homogeneous=False, spacing=SPACING) - self.label = gtk.Label() - self.set_name() - - self.vbox.pack_start(lalign(self.label), expand=False, fill=False) - - self.hbox = gtk.HBox(homogeneous=False, spacing=SPACING) - - self.icon = gtk.Image() - self.icon.set_size_request(-1, 29) - - self.iconbox = gtk.VBox() - self.iconevbox = gtk.EventBox() - self.iconevbox.add(self.icon) - self.iconbox.pack_start(self.iconevbox, expand=False, fill=False) - self.hbox.pack_start(self.iconbox, expand=False, fill=False) - - self.vbox.pack_start(self.hbox) - - self.infobox = gtk.VBox(homogeneous=False) - - self.progressbarbox = gtk.HBox(homogeneous=False, spacing=SPACING) - self.progressbar = gtk.ProgressBar() - - self.reset_progressbar_color() - - if self.completion is not None: - self.progressbar.set_fraction(self.completion) - if self.completion >= 1: - done_label = self.make_done_label() - self.progressbar.set_text(done_label) - else: - self.progressbar.set_text('%.1f%%'%(self.completion*100)) - else: - self.progressbar.set_text('?') - - self.progressbarbox.pack_start(self.progressbar, - expand=True, fill=True) - - self.buttonevbox = gtk.EventBox() - self.buttonbox = gtk.HBox(homogeneous=True, spacing=SPACING) - - self.infobutton = gtk.Button() - self.infoimage = gtk.Image() - self.infoimage.set_from_stock('bt-info', gtk.ICON_SIZE_BUTTON) - self.infobutton.add(self.infoimage) - self.infobutton.connect('clicked', self.open_info) - self.main.tooltips.set_tip(self.infobutton, - _("Torrent info")) - - self.buttonbox.pack_start(self.infobutton, expand=True) - - self.cancelbutton = gtk.Button() - self.cancelimage = gtk.Image() - if self.completion is not None and self.completion >= 1: - self.cancelimage.set_from_stock('bt-remove', gtk.ICON_SIZE_BUTTON) - self.main.tooltips.set_tip(self.cancelbutton, - _("Remove torrent")) - else: - self.cancelimage.set_from_stock('bt-abort', gtk.ICON_SIZE_BUTTON) - self.main.tooltips.set_tip(self.cancelbutton, - _("Abort torrent")) - - self.cancelbutton.add(self.cancelimage) - # not using 'clicked' because we want to check for CTRL key - self.cancelbutton.connect('button-release-event', self.confirm_remove) - - self.buttonbox.pack_start(self.cancelbutton, expand=True, fill=False) - self.buttonevbox.add(self.buttonbox) - - vbuttonbox = gtk.VBox(homogeneous=False) - vbuttonbox.pack_start(self.buttonevbox, expand=False, fill=False) - self.hbox.pack_end(vbuttonbox, expand=False, fill=False) - - self.infobox.pack_start(self.progressbarbox, expand=False, fill=False) - - self.hbox.pack_start(self.infobox, expand=True, fill=True) - self.add( self.vbox ) - - self.drag_source_set(gtk.gdk.BUTTON1_MASK, - TARGET_ALL, - gtk.gdk.ACTION_MOVE|gtk.gdk.ACTION_COPY) - self.connect('drag_data_get', self.drag_data_get) - - self.connect('drag_begin' , self.drag_begin ) - self.connect('drag_end' , self.drag_end ) - self.cursor_handler_id = self.connect('enter_notify_event', self.change_cursors) - - - def set_save_location(self, dlpath): - self.dlpath = dlpath - updater_infohash = self.main.updater.infohash - if updater_infohash == self.infohash: - my_installer_dir = os.path.split(self.dlpath)[0] - if self.main.updater.installer_dir != my_installer_dir: - self.main.updater.set_installer_dir(my_installer_dir) - - - def reset_progressbar_color(self): - # Hack around broken GTK-Wimp theme: - # make progress bar text always black - # see task #694 - if is_frozen_exe and self.main.config['progressbar_hack']: - style = self.progressbar.get_style().copy() - black = style.black - self.progressbar.modify_fg(gtk.STATE_PRELIGHT, black) - - - def change_cursors(self, *args): - # BUG: this is in a handler that is disconnected because the - # window attributes are None until after show_all() is called - self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2)) - self.buttonevbox.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)) - self.disconnect(self.cursor_handler_id) - - - def drag_data_get(self, widget, context, selection, targetType, eventTime): - selection.set(selection.target, 8, self.infohash) - - def drag_begin(self, *args): - pass - - def drag_end(self, *args): - self.main.drag_end() - - def make_done_label(self, statistics=None): - s = '' - if statistics and statistics['timeEst'] is not None: - s = _(", will seed for %s") % Duration(statistics['timeEst']) - elif statistics: - s = _(", will seed indefinitely.") - - if self.up_down_ratio is not None: - done_label = _("Done, share ratio: %d%%") % \ - (self.up_down_ratio*100) + s - elif statistics is not None: - done_label = _("Done, %s uploaded") % \ - Size(statistics['upTotal']) + s - else: - done_label = _("Done") - - return done_label - - - def set_name(self): - self.label.set_text(self.metainfo.name) - self.label.set_ellipsize(pango.ELLIPSIZE_END) - - def make_menu(self, extra_menu_items=[]): - if self.menu_handler: - self.disconnect(self.menu_handler) - - ## Basic Info - menu_items = [ MenuItem(_("Torrent _info" ), func=self.open_info), ] - open_dir_func = None - if LaunchPath.can_launch_files and self.can_open_dir(): - open_dir_func = self.open_dir - menu_items.append( MenuItem(_("_Open directory" ), func=open_dir_func) ) - filelistfunc = None - if self.is_batch: - filelistfunc = self.open_filelist - menu_items.append(MenuItem(_("_File list"), func=filelistfunc)) - if self.torrent_state == RUNNING: - menu_items.append(MenuItem(_("_Peer list"), func=self.open_peerlist)) - ## end Basic Info - - menu_items.append(gtk.SeparatorMenuItem()) - - ## Settings - # change save location - change_save_location_func = None - if self.torrent_state != RUNNING and self.completion <= 0: - change_save_location_func = self.change_save_location - menu_items.append(MenuItem(_("_Change location"), - func=change_save_location_func)) - # seed forever item - self.seed_forever_item = gtk.CheckMenuItem(_("_Seed indefinitely")) - self.reset_seed_forever() - def sft(widget, *args): - active = widget.get_active() - infohash = self.infohash - for option in ('seed_forever', 'seed_last_forever'): - self.main.torrentqueue.set_config(option, active, infohash) - self.main.torrentqueue.set_config(option, active, infohash) - self.seed_forever_item.connect('toggled', sft) - menu_items.append(self.seed_forever_item) - ## end Settings - - menu_items.append(gtk.SeparatorMenuItem()) - - ## Queue state dependent items - if self.torrent_state == KNOWN: - menu_items.append( MenuItem(_("Re_start"), func=self.move_to_end )) - elif self.torrent_state == QUEUED: - #Here's where we'll put the "Start hash check" menu item - menu_items.append(MenuItem(_("Download _now"), func=self.start)) - elif self.torrent_state in (RUNNING, RUN_QUEUED): - # no items for here - pass - - ## Completion dependent items - if self.completion is not None and self.completion >= 1: - if self.torrent_state != KNOWN: - menu_items.append(MenuItem(_("_Finish"), func=self.finish)) - menu_items.append( MenuItem(_("_Remove" ), func=self.confirm_remove)) - else: - if self.torrent_state in (RUNNING, RUN_QUEUED): - menu_items.append(MenuItem(_("Download _later"), func=self.move_to_end)) - else: - #Here's where we'll put the "Seed _later" menu item - pass - menu_items.append(MenuItem(_("_Abort" ), func=self.confirm_remove)) - - ## build the menu - self.menu = gtk.Menu() - - for i in menu_items: - i.show() - self.menu.add(i) - - self.menu_handler = self.connect_object("event", self.show_menu, self.menu) - - def reset_seed_forever(self): - sfb = False - d = self.main.torrents[self.infohash].config.getDict() - if d.has_key('seed_forever'): - sfb = d['seed_forever'] - self.seed_forever_item.set_active(bool(sfb)) - - def change_save_location(self, widget=None): - self.main.change_save_location(self.infohash) - - def open_info(self, widget=None): - if self.infowindow is None: - self.infowindow = TorrentInfoWindow(self, self.infoclosed) - - def infoclosed(self, widget=None): - self.infowindow = None - - def close_info(self): - if self.infowindow is not None: - self.infowindow.close() - - def open_filelist(self, widget): - if not self.is_batch: - return - if self.filelistwindow is None: - self.filelistwindow = FileListWindow(self.metainfo, - self.filelistclosed) - self.main.torrentqueue.check_completion(self.infohash, True) - - def filelistclosed(self, widget): - self.filelistwindow = None - - def close_filelist(self): - if self.filelistwindow is not None: - self.filelistwindow.close() - - def close_child_windows(self): - self.close_info() - self.close_filelist() - - def destroy(self): - if self.menu is not None: - self.menu.destroy() - self.menu = None - gtk.EventBox.destroy(self) - - def show_menu(self, widget, event): - if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: - widget.popup(None, None, None, event.button, event.time) - return True - return False - - def _short_path(self, dlpath): - path_length = 40 - sep = '...' - ret = os.path.split(dlpath)[0] - if len(ret) > path_length+len(sep): - return ret[:int(path_length/2)]+sep+ret[-int(path_length/2):] - else: - return ret - - def get_path_to_open(self): - path = self.dlpath - if not self.is_batch: - path = os.path.split(self.dlpath)[0] - return path - - def can_open_dir(self): - return os.access(self.get_path_to_open(), os.F_OK|os.R_OK) - - def open_dir(self, widget): - LaunchPath.launchdir(self.get_path_to_open()) - - def confirm_remove(self, widget, event=None): - if event is not None and event.get_state() & gtk.gdk.CONTROL_MASK: - self.remove() - else: - message = _('Are you sure you want to remove "%s"?') % self.metainfo.name - if self.completion >= 1: - if self.up_down_ratio is not None: - message = _("Your share ratio for this torrent is %d%%. ")%(self.up_down_ratio*100) + message - else: - message = _("You have uploaded %s to this torrent. ")%(Size(self.uptotal)) + message - - d = MessageDialog(self.main.mainwindow, - _("Remove this torrent?"), - message, - type=gtk.MESSAGE_QUESTION, - buttons=gtk.BUTTONS_OK_CANCEL, - yesfunc=self.remove, - default=gtk.RESPONSE_OK, - ) - - def remove(self): - self.main.torrentqueue.remove_torrent(self.infohash) - - -class KnownTorrentBox(TorrentBox): - - torrent_state = KNOWN - - def __init__(self, infohash, metainfo, dlpath, completion, main): - TorrentBox.__init__(self, infohash, metainfo, dlpath, completion, main) - - status_tip = '' - if completion >= 1: - self.icon.set_from_stock('bt-finished', gtk.ICON_SIZE_LARGE_TOOLBAR) - status_tip = _("Finished") - known_torrent_dnd_tip = _("drag into list to seed") - else: - self.icon.set_from_stock('bt-broken', gtk.ICON_SIZE_LARGE_TOOLBAR) - status_tip = _("Failed") - known_torrent_dnd_tip = _("drag into list to resume") - - self.main.tooltips.set_tip(self.iconevbox, - self.torrent_tip_format % (status_tip, - known_torrent_dnd_tip, - self.torrent_menu_tip)) - self.make_menu() - self.show_all() - - def move_to_end(self, widget): - self.main.change_torrent_state(self.infohash, QUEUED) - - -class DroppableTorrentBox(TorrentBox): - - def __init__(self, infohash, metainfo, dlpath, completion, main): - TorrentBox.__init__(self, infohash, metainfo, dlpath, completion, main) - - self.drag_dest_set(gtk.DEST_DEFAULT_DROP, - TARGET_ALL, - gtk.gdk.ACTION_MOVE|gtk.gdk.ACTION_COPY) - - self.connect('drag_data_received', self.drag_data_received) - self.connect('drag_motion', self.drag_motion) - self.index = None - - def drag_data_received(self, widget, context, x, y, selection, targetType, time): - if targetType == BT_TARGET_TYPE: - half_height = self.size_request()[1] // 2 - where = cmp(y, half_height) - if where == 0: where = 1 - self.parent.put_infohash_at_child(selection.data, self, where) - else: - self.main.accept_dropped_file(widget, context, x, y, selection, targetType, time) - - def drag_motion(self, widget, context, x, y, time): - self.get_current_index() - half_height = self.size_request()[1] // 2 - if y < half_height: - self.parent.highlight_before_index(self.index) - else: - self.parent.highlight_after_index(self.index) - return False - - def drag_end(self, *args): - self.parent.highlight_child() - TorrentBox.drag_end(self, *args) - - def get_current_index(self): - self.index = self.parent.get_index_from_child(self) - - -class QueuedTorrentBox(DroppableTorrentBox): - icon_name = 'bt-queued' - torrent_state = QUEUED - - def __init__(self, infohash, metainfo, dlpath, completion, main): - DroppableTorrentBox.__init__(self, infohash, metainfo, dlpath, completion, main) - - self.state_name = _("Waiting") - self.main.tooltips.set_tip(self.iconevbox, - self.torrent_tip_format % (self.state_name, - self.main_torrent_dnd_tip, - self.torrent_menu_tip)) - - self.icon.set_from_stock(self.icon_name, gtk.ICON_SIZE_LARGE_TOOLBAR) - self.make_menu() - self.show_all() - - def start(self, widget): - self.main.runbox.put_infohash_last(self.infohash) - - def finish(self, widget): - self.main.change_torrent_state(self.infohash, KNOWN) - - -class PausedTorrentBox(DroppableTorrentBox): - icon_name = 'bt-paused' - torrent_state = RUN_QUEUED - - def __init__(self, infohash, metainfo, dlpath, completion, main): - DroppableTorrentBox.__init__(self, infohash, metainfo, dlpath, completion, main) - - self.state_name = _("Paused") - self.main.tooltips.set_tip(self.iconevbox, - self.torrent_tip_format % (self.state_name, - self.main_torrent_dnd_tip, - self.torrent_menu_tip)) - - self.icon.set_from_stock(self.icon_name, gtk.ICON_SIZE_LARGE_TOOLBAR) - self.make_menu() - self.show_all() - - def move_to_end(self, widget): - self.main.change_torrent_state(self.infohash, QUEUED) - - def finish(self, widget): - self.main.change_torrent_state(self.infohash, KNOWN) - - def update_status(self, statistics): - # in case the TorrentQueue thread calls widget.update_status() - # before the GUI has changed the torrent widget to a - # RunningTorrentBox - pass - - -class RunningTorrentBox(PausedTorrentBox): - torrent_state = RUNNING - - def __init__(self, infohash, metainfo, dlpath, completion, main): - DroppableTorrentBox.__init__(self, infohash, metainfo, dlpath, completion, main) - - self.main.tooltips.set_tip(self.iconevbox, - self.torrent_tip_format % (_("Running"), - self.main_torrent_dnd_tip, - self.torrent_menu_tip)) - - self.seed = False - self.peerlistwindow = None - self.update_peer_list_flag = 0 - - self.icon.set_from_stock('bt-running', gtk.ICON_SIZE_LARGE_TOOLBAR) - - self.rate_label_box = gtk.HBox(homogeneous=True) - - self.up_rate = gtk.Label() - self.down_rate = gtk.Label() - self.rate_label_box.pack_start(lalign(self.up_rate ), - expand=True, fill=True) - self.rate_label_box.pack_start(lalign(self.down_rate), - expand=True, fill=True) - - self.infobox.pack_start(self.rate_label_box) - - if advanced_ui: - self.extrabox = gtk.VBox(homogeneous=False) - #self.extrabox = self.vbox - - self.up_curr = FancyLabel(_("Current up: %s" ), 0) - self.down_curr = FancyLabel(_("Current down: %s"), 0) - self.curr_box = gtk.HBox(homogeneous=True) - self.curr_box.pack_start(lalign(self.up_curr ), expand=True, fill=True) - self.curr_box.pack_start(lalign(self.down_curr), expand=True, fill=True) - self.extrabox.pack_start(self.curr_box) - - self.up_prev = FancyLabel(_("Previous up: %s" ), 0) - self.down_prev = FancyLabel(_("Previous down: %s"), 0) - self.prev_box = gtk.HBox(homogeneous=True) - self.prev_box.pack_start(lalign(self.up_prev ), expand=True, fill=True) - self.prev_box.pack_start(lalign(self.down_prev), expand=True, fill=True) - self.extrabox.pack_start(self.prev_box) - - self.share_ratio = FancyLabel(_("Share ratio: %0.02f%%"), 0) - self.extrabox.pack_start(lalign(self.share_ratio)) - - self.peer_info = FancyLabel(_("%s peers, %s seeds. Totals from " - "tracker: %s"), 0, 0, 'NA') - self.extrabox.pack_start(lalign(self.peer_info)) - - self.dist_copies = FancyLabel(_("Distributed copies: %d; Next: %s"), 0, '') - self.extrabox.pack_start(lalign(self.dist_copies)) - - self.piece_info = FancyLabel(_("Pieces: %d total, %d complete, " - "%d partial, %d active (%d empty)"), *(0,)*5) - self.extrabox.pack_start(lalign(self.piece_info)) - - self.bad_info = FancyLabel(_("%d bad pieces + %s in discarded requests"), 0, 0) - self.extrabox.pack_start(lalign(self.bad_info)) - - # extra info - - pl = self.metainfo.piece_length - tl = self.metainfo.total_bytes - count, lastlen = divmod(tl, pl) - self.piece_count = count + (lastlen > 0) - - self.infobox.pack_end(self.extrabox, expand=False, fill=False) - - self.make_menu() - self.show_all() - - - def change_to_completed(self): - self.completion = 1.0 - self.cancelimage.set_from_stock('bt-remove', gtk.ICON_SIZE_BUTTON) - self.main.tooltips.set_tip(self.cancelbutton, - _("Remove torrent")) - - updater_infohash = self.main.updater.infohash - if updater_infohash == self.infohash: - self.main.updater.start_install() - - self.make_menu() - - def close_child_windows(self): - TorrentBox.close_child_windows(self) - self.close_peerlist() - - def open_filelist(self, widget): - if not self.is_batch: - return - if self.filelistwindow is None: - self.filelistwindow = FileListWindow(self.metainfo, - self.filelistclosed) - self.main.make_statusrequest() - - def open_peerlist(self, widget): - if self.peerlistwindow is None: - self.peerlistwindow = PeerListWindow(self.metainfo.name, - self.peerlistclosed) - self.main.make_statusrequest() - - def peerlistclosed(self, widget): - self.peerlistwindow = None - self.update_peer_list_flag = 0 - - def close_peerlist(self): - if self.peerlistwindow is not None: - self.peerlistwindow.close() - - rate_label = ': %s' - eta_label = '?' - done_label = _("Done") - progress_bar_label = _("%.1f%% done, %s remaining") - down_rate_label = _("Download rate") - up_rate_label = _("Upload rate" ) - - def update_status(self, statistics): - fractionDone = statistics.get('fractionDone') - activity = statistics.get('activity') - - self.main.set_title(torrentName=self.metainfo.name, - fractionDone=fractionDone) - - dt = self.downtotal - if statistics.has_key('downTotal'): - dt += statistics['downTotal'] - - ut = self.uptotal - if statistics.has_key('upTotal'): - ut += statistics['upTotal'] - - if dt > 0: - self.up_down_ratio = ut / self.metainfo.total_bytes - - done_label = self.done_label - eta_label = self.eta_label - if 'numPeers' in statistics: - eta = statistics.get('timeEst') - if eta is not None: - eta_label = Duration(eta) - if fractionDone == 1: - done_label = self.make_done_label(statistics) - - if fractionDone == 1: - self.progressbar.set_fraction(1) - self.progressbar.set_text(done_label) - self.reset_seed_forever() - if not self.completion >= 1: - self.change_to_completed() - else: - self.progressbar.set_fraction(fractionDone) - progress_bar_label = self.progress_bar_label % \ - (int(fractionDone*1000)/10, eta_label) - self.progressbar.set_text(progress_bar_label) - - - if 'numPeers' not in statistics: - return - - self.down_rate.set_text(self.down_rate_label+self.rate_label % - Rate(statistics['downRate'])) - self.up_rate.set_text (self.up_rate_label+self.rate_label % - Rate(statistics['upRate'])) - - if advanced_ui: - if self.up_down_ratio is not None: - self.share_ratio.set_value(self.up_down_ratio*100) - - num_seeds = statistics['numSeeds'] - if self.seed: - num_seeds = statistics['numOldSeeds'] = 0 # !@# XXX - - if statistics['trackerPeers'] is not None: - totals = '%d/%d' % (statistics['trackerPeers'], - statistics['trackerSeeds']) - else: - totals = _("NA") - self.peer_info.set_value(statistics['numPeers'], num_seeds, totals) - - self.up_curr.set_value(str(Size(statistics['upTotal']))) - self.down_curr.set_value(str(Size(statistics['downTotal']))) - - self.up_prev.set_value(str(Size(self.uptotal))) - self.down_prev.set_value(str(Size(self.downtotal))) - - # refresh extra info - self.piece_info.set_value(self.piece_count, - statistics['storage_numcomplete'], - statistics['storage_dirty'], - statistics['storage_active'], - statistics['storage_new'] ) - - self.dist_copies.set_value( statistics['numCopies'], ', '.join(["%d:%.1f%%" % (a, int(b*1000)/10) for a, b in zip(itertools.count(int(statistics['numCopies']+1)), statistics['numCopyList'])])) - - self.bad_info.set_value(statistics['storage_numflunked'], Size(statistics['discarded'])) - - if self.peerlistwindow is not None: - if self.update_peer_list_flag == 0: - spew = statistics.get('spew') - if spew is not None: - self.peerlistwindow.update(spew, statistics['bad_peers']) - self.update_peer_list_flag = (self.update_peer_list_flag + 1) % 4 - if self.filelistwindow is not None: - if 'files_left' in statistics: - self.filelistwindow.update(statistics['files_left'], - statistics['files_allocated']) - - -class DroppableHSeparator(PaddedHSeparator): - - def __init__(self, box, spacing=SPACING): - PaddedHSeparator.__init__(self, spacing) - self.box = box - self.main = box.main - - self.drag_dest_set(gtk.DEST_DEFAULT_DROP, - TARGET_ALL, - gtk.gdk.ACTION_MOVE|gtk.gdk.ACTION_COPY) - - self.connect('drag_data_received', self.drag_data_received) - self.connect('drag_motion' , self.drag_motion ) - - def drag_highlight(self): - self.sep.drag_highlight() - self.main.add_unhighlight_handle() - - def drag_unhighlight(self): - self.sep.drag_unhighlight() - - def drag_data_received(self, widget, context, x, y, selection, targetType, time): - if targetType == BT_TARGET_TYPE: - self.box.drop_on_separator(self, selection.data) - else: - self.main.accept_dropped_file(widget, context, x, y, selection, targetType, time) - - def drag_motion(self, wid, context, x, y, time): - self.drag_highlight() - return False - - -class DroppableBox(HSeparatedBox): - def __init__(self, main, spacing=0): - HSeparatedBox.__init__(self, spacing=spacing) - self.main = main - self.drag_dest_set(gtk.DEST_DEFAULT_DROP, - TARGET_ALL, - gtk.gdk.ACTION_MOVE|gtk.gdk.ACTION_COPY) - self.connect('drag_data_received', self.drag_data_received) - self.connect('drag_motion', self.drag_motion) - - def drag_motion(self, widget, context, x, y, time): - return False - - def drag_data_received(self, widget, context, x, y, selection, targetType, time): - pass - - -class KnownBox(DroppableBox): - - def __init__(self, main, spacing=0): - DroppableBox.__init__(self, main, spacing=spacing) - self.drag_dest_set(gtk.DEST_DEFAULT_DROP, - TARGET_ALL, - gtk.gdk.ACTION_MOVE|gtk.gdk.ACTION_COPY) - - def pack_start(self, widget, *args, **kwargs): - old_len = len(self.get_children()) - DroppableBox.pack_start(self, widget, *args, **kwargs) - if old_len <= 0: - self.main.maximize_known_pane() - self.main.knownscroll.scroll_to_bottom() - - def remove(self, widget): - DroppableBox.remove(self, widget) - new_len = len(self.get_children()) - if new_len == 0: - self.main.maximize_known_pane() - - def drag_data_received(self, widget, context, x, y, selection, targetType, time): - if targetType == BT_TARGET_TYPE: - infohash = selection.data - self.main.finish(infohash) - else: - self.main.accept_dropped_file(widget, context, x, y, selection, targetType, time) - - def drag_motion(self, widget, context, x, y, time): - self.main.drag_highlight(widget=self) - - def drag_highlight(self): - self.main.knownscroll.drag_highlight() - self.main.add_unhighlight_handle() - - def drag_unhighlight(self): - self.main.knownscroll.drag_unhighlight() - - -class RunningAndQueueBox(gtk.VBox): - - def __init__(self, main, **kwargs): - gtk.VBox.__init__(self, **kwargs) - self.main = main - - def drop_on_separator(self, sep, infohash): - self.main.change_torrent_state(infohash, QUEUED, 0) - - def highlight_between(self): - self.drag_highlight() - - def drag_highlight(self): - self.get_children()[1].drag_highlight() - - def drag_unhighlight(self): - self.get_children()[1].drag_unhighlight() - - -class SpacerBox(DroppableBox): - - def drag_data_received(self, widget, context, x, y, selection, targetType, time): - if targetType == BT_TARGET_TYPE: - infohash = selection.data - self.main.queuebox.put_infohash_last(infohash) - else: - self.main.accept_dropped_file(widget, context, x, y, selection, targetType, time) - - return True - -BEFORE = -1 -AFTER = 1 - -class ReorderableBox(DroppableBox): - - def new_separator(self): - return DroppableHSeparator(self) - - def __init__(self, main): - DroppableBox.__init__(self, main) - self.main = main - - self.drag_dest_set(gtk.DEST_DEFAULT_DROP, - TARGET_ALL, - gtk.gdk.ACTION_MOVE|gtk.gdk.ACTION_COPY) - - self.connect('drag_data_received', self.drag_data_received) - self.connect('drag_motion' , self.drag_motion) - - def drag_data_received(self, widget, context, x, y, selection, targetType, time): - - if targetType == BT_TARGET_TYPE: - half_height = self.size_request()[1] // 2 - if y < half_height: - self.put_infohash_first(selection.data) - else: - self.put_infohash_last(selection.data) - else: - self.main.accept_dropped_file(widget, context, x, y, selection, targetType, time) - return True - - def drag_motion(self, widget, context, x, y, time): - return False - - def drag_highlight(self): - final = self.get_children()[-1] - final.drag_highlight() - self.main.add_unhighlight_handle() - - def drag_unhighlight(self): - self.highlight_child(index=None) - self.parent.drag_unhighlight() - - def highlight_before_index(self, index): - self.drag_unhighlight() - children = self._get_children() - if index > 0: - children[index*2 - 1].drag_highlight() - else: - self.highlight_at_top() - - def highlight_after_index(self, index): - self.drag_unhighlight() - children = self._get_children() - if index*2 < len(children)-1: - children[index*2 + 1].drag_highlight() - else: - self.highlight_at_bottom() - - def highlight_child(self, index=None): - for i, child in enumerate(self._get_children()): - if index is not None and i == index*2: - child.drag_highlight() - else: - child.drag_unhighlight() - - - def drop_on_separator(self, sep, infohash): - children = self._get_children() - for i, child in enumerate(children): - if child == sep: - reference_child = children[i-1] - self.put_infohash_at_child(infohash, reference_child, AFTER) - break - - - def get_queue(self): - queue = [] - c = self.get_children() - for t in c: - queue.append(t.infohash) - return queue - - def put_infohash_first(self, infohash): - self.highlight_child() - children = self.get_children() - if len(children) > 1 and infohash == children[0].infohash: - return - - self.put_infohash_at_index(infohash, 0) - - def put_infohash_last(self, infohash): - self.highlight_child() - children = self.get_children() - end = len(children) - if len(children) > 1 and infohash == children[end-1].infohash: - return - - self.put_infohash_at_index(infohash, end) - - def put_infohash_at_child(self, infohash, reference_child, where): - self.highlight_child() - if infohash == reference_child.infohash: - return - - target_index = self.get_index_from_child(reference_child) - if where == AFTER: - target_index += 1 - self.put_infohash_at_index(infohash, target_index) - - def get_index_from_child(self, child): - c = self.get_children() - ret = -1 - try: - ret = c.index(child) - except ValueError: - pass - return ret - - def highlight_at_top(self): - raise NotImplementedError - - def highlight_at_bottom(self): - raise NotImplementedError - - def put_infohash_at_index(self, infohash, end): - raise NotImplementedError - -class RunningBox(ReorderableBox): - - def put_infohash_at_index(self, infohash, target_index): - #print 'RunningBox.put_infohash_at_index', infohash.encode('hex')[:8], target_index - - l = self.get_queue() - replaced = None - if l: - replaced = l[-1] - self.main.confirm_replace_running_torrent(infohash, replaced, - target_index) - - def highlight_at_top(self): - pass - # BUG: Don't know how I will indicate in the UI that the top of the list is highlighted - - def highlight_at_bottom(self): - self.parent.highlight_between() - - -class QueuedBox(ReorderableBox): - - def put_infohash_at_index(self, infohash, target_index): - #print 'want to put', infohash.encode('hex'), 'at', target_index - self.main.change_torrent_state(infohash, QUEUED, target_index) - - def highlight_at_top(self): - self.parent.highlight_between() - - def highlight_at_bottom(self): - pass - # BUG: Don't know how I will indicate in the UI that the bottom of the list is highlighted - - - -class Struct(object): - pass - - -class SearchField(gtk.Entry): - def __init__(self, default_text, visit_url_func): - gtk.Entry.__init__(self) - self.default_text = default_text - self.visit_url_func = visit_url_func - self.set_text(self.default_text) - self.set_size_request(150, -1) - - # default gtk Entry dnd processing is broken on linux! - # - default Motion handling causes asyncs - # - there's no way to filter the default text dnd - # see the parent window for a very painful work-around - self.drag_dest_unset() - - self.connect('key-press-event', self.check_for_enter) - self.connect('button-press-event', self.begin_edit) - self.search_completion = gtk.EntryCompletion() - self.search_completion.set_text_column(0) - self.search_store = gtk.ListStore(gobject.TYPE_STRING) - self.search_completion.set_model(self.search_store) - self.set_completion(self.search_completion) - self.reset_text() - self.timeout_id = None - - def begin_edit(self, *args): - if self.get_text() == self.default_text: - self.set_text('') - - def check_for_enter(self, widget, event): - if event.keyval in (gtk.keysyms.Return, gtk.keysyms.KP_Enter): - self.search() - - def reset_text(self): - self.set_text(self.default_text) - - def search(self, *args): - search_term = self.get_text() - if search_term and search_term != self.default_text: - self.search_store.append([search_term]) - search_url = SEARCH_URL % {'query' :zurllib.quote(search_term), - 'client':'M-%s'%version.replace('.','-')} - - self.timeout_id = gobject.timeout_add(2000, self.resensitize) - self.set_sensitive(False) - self.visit_url_func(search_url, callback=self.resensitize) - else: - self.reset_text() - self.select_region(0, -1) - self.grab_focus() - - def resensitize(self): - self.set_sensitive(True) - self.reset_text() - if self.timeout_id is not None: - gobject.source_remove(self.timeout_id) - self.timeout_id = None - - -class DownloadInfoFrame(object): - - def __init__(self, config, torrentqueue): - self.config = config - if self.config['save_in'] == '': - self.config['save_in'] = smart_dir('') - - self.torrentqueue = torrentqueue - self.torrents = {} - self.running_torrents = {} - self.lists = {} - self.update_handle = None - self.unhighlight_handle = None - self.custom_size = False - self.child_windows = {} - self.postponed_save_windows = [] - self.helpwindow = None - self.errordialog = None - - self.mainwindow = Window(gtk.WINDOW_TOPLEVEL) - - #tray icon - self.trayicon = TrayIcon(not self.config['start_minimized'], - toggle_func=self.toggle_shown, - quit_func=self.quit) - self.traythread = threading.Thread(target=self.trayicon.enable, - args=()) - self.traythread.setDaemon(True) - - if os.name == "nt": - # gtk has no way to check this? - self.iconized = False - self.mainwindow.connect('window-state-event', self.window_event) - - if self.config['start_minimized']: - self.mainwindow.iconify() - - gtk.gdk.threads_enter() - - self.mainwindow.set_border_width(0) - - self.set_seen_remote_connections(False) - self.set_seen_connections(False) - - self.mainwindow.drag_dest_set(gtk.DEST_DEFAULT_ALL, - TARGET_EXTERNAL, - gtk.gdk.ACTION_MOVE|gtk.gdk.ACTION_COPY) - - self.mainwindow.connect('drag_leave' , self.drag_leave ) - self.mainwindow.connect('drag_data_received', self.accept_dropped_file) - - self.mainwindow.set_size_request(WINDOW_WIDTH, -1) - - self.mainwindow.connect('destroy', self.cancel) - - self.mainwindow.connect('size-allocate', self.size_was_allocated) - - self.accel_group = gtk.AccelGroup() - - self.mainwindow.add_accel_group(self.accel_group) - - #self.accel_group.connect(ord('W'), gtk.gdk.CONTROL_MASK, gtk.ACCEL_LOCKED, - # lambda *args: self.mainwindow.destroy()) - - self.tooltips = gtk.Tooltips() - - self.logbuffer = LogBuffer() - self.log_text(_("%s started")%app_name, severity=None) - - self.box1 = gtk.VBox(homogeneous=False, spacing=0) - - self.box2 = gtk.VBox(homogeneous=False, spacing=0) - self.box2.set_border_width(SPACING) - - self.menubar = gtk.MenuBar() - self.box1.pack_start(self.menubar, expand=False, fill=False) - - self.ssbutton = StopStartButton(self) - - # keystrokes used: A D F H L N O P Q S U X (E) - - quit_menu_label = _("_Quit") - if os.name == 'nt': - quit_menu_label = _("E_xit") - - file_menu_items = ((_("_Open torrent file"), self.select_torrent_to_open), - (_("Open torrent _URL"), self.enter_url_to_open), - (_("Make _new torrent" ), self.make_new_torrent), - - ('----' , None), - (_("_Pause/Play"), self.ssbutton.toggle), - ('----' , None), - (quit_menu_label , lambda w: self.mainwindow.destroy()), - ) - view_menu_items = ((_("Show/Hide _finished torrents"), self.toggle_known), - # BUG: if you reorder this menu, see def set_custom_size() first - (_("_Resize window to fit"), lambda w: self.resize_to_fit()), - ('----' , None), - (_("_Log") , lambda w: self.open_window('log')), - # 'View log of all download activity', - #('----' , None), - (_("_Settings") , lambda w: self.open_window('settings')), - #'Change download behavior and network settings', - ) - help_menu_items = ((_("_Help") , self.open_help), - #(_("_Help Window") , lambda w: self.open_window('help')), - (_("_About") , lambda w: self.open_window('about')), - (_("_Donate") , lambda w: self.donate()), - #(_("Rais_e") , lambda w: self.raiseerror()), - ) - - self.filemenu = gtk.MenuItem(_("_File")) - - self.filemenu.set_submenu(build_menu(file_menu_items, self.accel_group)) - self.filemenu.show() - - self.viewmenu = gtk.MenuItem(_("_View")) - self.viewmenu.set_submenu(build_menu(view_menu_items, self.accel_group)) - self.viewmenu.show() - - self.helpmenu = gtk.MenuItem(_("_Help")) - self.helpmenu.set_submenu(build_menu(help_menu_items, self.accel_group)) - self.helpmenu.show() - - if os.name != 'nt': - self.helpmenu.set_right_justified(True) - - self.menubar.append(self.filemenu) - self.menubar.append(self.viewmenu) - self.menubar.append(self.helpmenu) - - self.menubar.show() - - self.header = gtk.HBox(homogeneous=False) - - self.box1.pack_start(self.box2, expand=False, fill=False) - - # control box: rate slider, start-stop button, search widget, status light - self.controlbox = gtk.HBox(homogeneous=False) - - controlbox_padding = SPACING//2 - - # stop-start button - self.controlbox.pack_start(malign(self.ssbutton), - expand=False, fill=False) - - # rate slider - self.rate_slider_box = RateSliderBox(self.config, self.torrentqueue) - self.controlbox.pack_start(self.rate_slider_box, - expand=True, fill=True, - padding=controlbox_padding) - - self.controlbox.pack_start(gtk.VSeparator(), expand=False, fill=False, - padding=controlbox_padding) - - # search box - self.search_field = SearchField(_("Search for torrents"), self.visit_url) - sfa = gtk.Alignment(xalign=0, yalign=0.5, xscale=1, yscale=0) - sfa.add(self.search_field) - self.controlbox.pack_start(sfa, - expand=False, fill=False, padding=controlbox_padding) - - # separator - self.controlbox.pack_start(gtk.VSeparator(), expand=False, fill=False, - padding=controlbox_padding) - - # status light - self.status_light = StatusLight(self) - - self.controlbox.pack_start(malign(self.status_light), - expand=False, fill=False) - - self.box2.pack_start(self.controlbox, - expand=False, fill=False, padding=0) - # end control box - - self.paned = gtk.VPaned() - - self.knownscroll = ScrolledWindow() - self.knownscroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - self.knownscroll.set_shadow_type(gtk.SHADOW_NONE) - self.knownscroll.set_size_request(-1, SPACING) - - self.knownbox = KnownBox(self) - self.knownbox.set_border_width(SPACING) - - self.knownscroll.add_with_viewport(self.knownbox) - self.paned.pack1(self.knownscroll, resize=False, shrink=True) - - - self.mainscroll = AutoScrollingWindow() - self.mainscroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - self.mainscroll.set_shadow_type(gtk.SHADOW_NONE) - self.mainscroll.set_size_request(-1, SPACING) - - self.scrollbox = RunningAndQueueBox(self, homogeneous=False) - self.scrollbox.set_border_width(SPACING) - - self.runbox = RunningBox(self) - self.scrollbox.pack_start(self.runbox, expand=False, fill=False) - - self.scrollbox.pack_start(DroppableHSeparator(self.scrollbox), expand=False, fill=False) - - self.queuebox = QueuedBox(self) - self.scrollbox.pack_start(self.queuebox, expand=False, fill=False) - - self.scrollbox.pack_start(SpacerBox(self), expand=True, fill=True) - - self.mainscroll.add_with_viewport(self.scrollbox) - - self.paned.pack2(self.mainscroll, resize=True, shrink=False) - - self.box1.pack_start(self.paned) - - self.box1.show_all() - - self.mainwindow.add(self.box1) - - self.set_title() - self.set_size() - - self.mainwindow.show() - - self.paned.set_position(0) - self.search_field.grab_focus() - - self.updater = NewVersion.Updater( - gtk_wrap, - self.new_version, - self.torrentqueue.start_new_torrent, - self.confirm_install_new_version , - self.global_error , - self.config['new_version'] , - self.config['current_version'] ) - - self.nag() - - gtk.gdk.threads_leave() - - def window_event(self, widget, event, *args): - if event.changed_mask == gtk.gdk.WINDOW_STATE_ICONIFIED: - if self.config['minimize_to_tray']: - if self.iconized == False: - self.mainwindow.hide() - self.trayicon.set_toggle_state(self.iconized) - self.iconized = not self.iconized - - def drag_leave(self, *args): - self.drag_end() - - def make_new_torrent(self, widget=None): - btspawn(self.torrentqueue, 'maketorrent') - - def accept_dropped_file(self, widget, context, x, y, selection, - targetType, time): - if targetType == EXTERNAL_FILE_TYPE: - d = selection.data.strip() - file_uris = d.split('\r\n') - for file_uri in file_uris: - # this catches non-url entries, I've seen "\x00" at the end of lists - if file_uri.find(':/') != -1: - file_name = zurllib.url2pathname(file_uri) - file_name = file_name[7:] - if os.name == 'nt': - file_name = file_name.strip('\\') - self.open_torrent( file_name ) - elif targetType == EXTERNAL_STRING_TYPE: - - data = selection.data.strip() - - # size must be > 0,0 for the intersection code to register it - drop_rect = gtk.gdk.Rectangle(x, y, 1, 1) - if ((self.search_field.intersect(drop_rect) is not None) and - (not data.lower().endswith(".torrent"))): - - client_point = self.mainwindow.translate_coordinates(self.search_field, x, y) - layout_offset = self.search_field.get_layout_offsets() - point = [] - # subtract (not add) the offset, because we're hit-testing the layout, not the widget - point.append(client_point[0] - layout_offset[0]) - point.append(client_point[1] - layout_offset[1]) - # ha ha ha. pango is so ridiculous - point[0] *= pango.SCALE - point[1] *= pango.SCALE - layout = self.search_field.get_layout() - position = layout.xy_to_index(*point) - self.search_field.insert_text(data, position[0]) - else: - self.open_url(data) - - def drag_highlight(self, widget=None): - widgets = (self.knownbox, self.runbox, self.queuebox) - for w in widgets: - if w != widget: - w.drag_unhighlight() - for w in widgets: - if w == widget: - w.drag_highlight() - self.add_unhighlight_handle() - - def drag_end(self): - self.drag_highlight(widget=None) - self.mainscroll.stop_scrolling() - - def set_title(self, torrentName=None, fractionDone=None): - title = app_name - trunc = '...' - sep = ': ' - - if self.config['pause']: - title += sep+_("(stopped)") - elif len(self.running_torrents) == 1 and torrentName and \ - fractionDone is not None: - maxlen = WINDOW_TITLE_LENGTH - len(app_name) - len(trunc) - len(sep) - if len(torrentName) > maxlen: - torrentName = torrentName[:maxlen] + trunc - title = '%s%s%0.1f%%%s%s'% (app_name, - sep, - (int(fractionDone*1000)/10), - sep, - torrentName) - elif len(self.running_torrents) > 1: - title += sep+_("(multiple)") - - if self.mainwindow.get_title() != title: - self.mainwindow.set_title(title) - if self.trayicon.get_tooltip() != title: - self.trayicon.set_tooltip(title) - - def _guess_size(self): - paned_height = self.scrollbox.size_request()[1] - if hasattr(self.paned, 'style_get_property'): - paned_height += self.paned.style_get_property('handle-size') - else: - paned_height += 5 - paned_height += self.paned.get_position() - paned_height += 4 # fudge factor, probably from scrolled window beveling ? - paned_height = max(paned_height, MIN_MULTI_PANE_HEIGHT) - - new_height = self.menubar.size_request()[1] + \ - self.box2.size_request()[1] + \ - paned_height - new_height = min(new_height, MAX_WINDOW_HEIGHT) - new_width = max(self.scrollbox.size_request()[0] + SCROLLBAR_WIDTH, WINDOW_WIDTH) - return new_width, new_height - - def set_size(self): - if not self.custom_size: - self.mainwindow.resize(*self._guess_size()) - - def size_was_allocated(self, *args): - current_size = self.mainwindow.get_size() - target_size = self._guess_size() - if current_size == target_size: - self.set_custom_size(False) - else: - self.set_custom_size(True) - - def resize_to_fit(self): - self.set_custom_size(False) - self.set_size() - - def set_custom_size(self, val): - self.custom_size = val - # BUG this is a hack: - self.viewmenu.get_submenu().get_children()[1].set_sensitive(val) - - # BUG need to add handler on resize event to keep track of - # old_position when pane is hidden manually - def split_pane(self): - pos = self.paned.get_position() - if pos > 0: - self.paned.old_position = pos - self.paned.set_position(0) - else: - if hasattr(self.paned, 'old_position'): - self.paned.set_position(self.paned.old_position) - else: - self.maximize_known_pane() - - def maximize_known_pane(self): - self.set_pane_position(self.knownbox.size_request()[1]) - - def set_pane_position(self, pane_position): - pane_position = min(MAX_WINDOW_HEIGHT//2, pane_position) - self.paned.set_position(pane_position) - - def toggle_known(self, widget=None): - self.split_pane() - - def open_window(self, window_name, *args, **kwargs): - if os.name == 'nt': - self.mainwindow.present() - savewidget = SaveFileSelection - if window_name == 'savedir': - savewidget = CreateFolderSelection - window_name = 'savefile' - if self.child_windows.has_key(window_name): - if window_name == 'savefile': - kwargs['show'] = False - self.postponed_save_windows.append(savewidget(self, **kwargs)) - return - - if window_name == 'log' : - self.child_windows[window_name] = LogWindow(self, self.logbuffer, self.config) - elif window_name == 'about' : - self.child_windows[window_name] = AboutWindow(self, lambda w: self.donate()) - elif window_name == 'help' : - self.child_windows[window_name] = HelpWindow(self, makeHelp('bittorrent', defaults)) - elif window_name == 'settings': - self.child_windows[window_name] = SettingsWindow(self, self.config, self.set_config) - elif window_name == 'version' : - self.child_windows[window_name] = VersionWindow(self, *args) - elif window_name == 'openfile': - self.child_windows[window_name] = OpenFileSelection(self, **kwargs) - elif window_name == 'savefile': - self.child_windows[window_name] = savewidget(self, **kwargs) - elif window_name == 'choosefolder': - self.child_windows[window_name] = ChooseFolderSelection(self, **kwargs) - elif window_name == 'enterurl': - self.child_windows[window_name] = EnterUrlDialog(self, **kwargs) - - return self.child_windows[window_name] - - def window_closed(self, window_name): - if self.child_windows.has_key(window_name): - del self.child_windows[window_name] - if window_name == 'savefile' and self.postponed_save_windows: - newwin = self.postponed_save_windows.pop(-1) - newwin.show() - self.child_windows['savefile'] = newwin - - def close_window(self, window_name): - self.child_windows[window_name].close(None) - - def new_version(self, newversion, download_url): - if not self.config['notified'] or \ - newversion != NewVersion.Version.from_str(self.config['notified']): - if not self.torrents.has_key(self.updater.infohash): - self.open_window('version', newversion, download_url) - else: - dlpath = os.path.split(self.torrents[self.updater.infohash].dlpath)[0] - self.updater.set_installer_dir(dlpath) - self.updater.start_install() - - def check_version(self): - self.updater.check() - - def start_auto_update(self): - if not self.torrents.has_key(self.updater.infohash): - self.updater.download() - else: - self.global_error(INFO, _("Already downloading %s installer") % self.updater.version) - - def confirm_install_new_version(self): - MessageDialog(self.mainwindow, - _("Install new %s now?")%app_name, - _("Do you want to quit %s and install the new version, " - "%s, now?")%(app_name,self.updater.version), - type=gtk.MESSAGE_QUESTION, - buttons=gtk.BUTTONS_YES_NO, - yesfunc=self.install_new_version, - nofunc=None, - default=gtk.RESPONSE_YES - ) - - def install_new_version(self): - self.updater.launch_installer(self.torrentqueue) - self.cancel() - - - def open_help(self,widget): - if self.helpwindow is None: - msg = (_("%s help is at \n%s\nWould you like to go there now?")% - (app_name, HELP_URL)) - self.helpwindow = MessageDialog(self.mainwindow, - _("Visit help web page?"), - msg, - type=gtk.MESSAGE_QUESTION, - buttons=gtk.BUTTONS_OK_CANCEL, - yesfunc=self.visit_help, - nofunc =self.help_closed, - default=gtk.RESPONSE_OK - ) - - def visit_help(self): - self.visit_url(HELP_URL) - self.help_closed() - - def close_help(self): - self.helpwindow.close() - - def help_closed(self, widget=None): - self.helpwindow = None - - - def set_config(self, option, value): - self.config[option] = value - if option == 'display_interval': - self.init_updates() - self.torrentqueue.set_config(option, value) - - - def confirm_remove_finished_torrents(self,widget): - count = 0 - for infohash, t in self.torrents.iteritems(): - if t.state == KNOWN and t.completion >= 1: - count += 1 - if count: - if self.paned.get_position() == 0: - self.toggle_known() - msg = '' - if count == 1: - msg = _("There is one finished torrent in the list. ") + \ - _("Do you want to remove it?") - else: - msg = _("There are %d finished torrents in the list. ") % count +\ - _("Do you want to remove all of them?") - MessageDialog(self.mainwindow, - _("Remove all finished torrents?"), - msg, - type=gtk.MESSAGE_QUESTION, - buttons=gtk.BUTTONS_OK_CANCEL, - yesfunc=self.remove_finished_torrents, - default=gtk.RESPONSE_OK) - else: - MessageDialog(self.mainwindow, - _("No finished torrents"), - _("There are no finished torrents to remove."), - type=gtk.MESSAGE_INFO, - default=gtk.RESPONSE_OK) - - def remove_finished_torrents(self): - for infohash, t in self.torrents.iteritems(): - if t.state == KNOWN and t.completion >= 1: - self.torrentqueue.remove_torrent(infohash) - if self.paned.get_position() > 0: - self.toggle_known() - - def cancel(self, widget=None): - for window_name in self.child_windows.keys(): - self.close_window(window_name) - - if self.errordialog is not None: - self.errordialog.destroy() - self.errors_closed() - - for t in self.torrents.itervalues(): - if t.widget is not None: - t.widget.close_child_windows() - - self.torrentqueue.set_done() - gtk.main_quit() - - # Currently called if the user started bittorrent from a terminal - # and presses ctrl-c there, or if the user quits BitTorrent from - # the tray icon (on windows) - def quit(self): - self.mainwindow.destroy() - - def make_statusrequest(self): - if self.config['pause']: - return True - for infohash, t in self.running_torrents.iteritems(): - self.torrentqueue.request_status(infohash, t.widget.peerlistwindow - is not None, t.widget.filelistwindow is not None) - if not len(self.running_torrents): - self.status_light.send_message('empty') - return True - - def enter_url_to_open(self, widget): - self.open_window('enterurl') - - def open_url(self, url): - self.torrentqueue.start_new_torrent_by_name(url) - - def select_torrent_to_open(self, widget): - open_location = self.config['open_from'] - if not open_location: - open_location = self.config['save_in'] - path = smart_dir(open_location) - self.open_window('openfile', - title=_("Open torrent:"), - fullname=path, - got_location_func=self.open_torrent, - no_location_func=lambda: self.window_closed('openfile')) - - - def open_torrent(self, name): - self.window_closed('openfile') - open_location = os.path.split(name)[0] - if open_location[-1] != os.sep: - open_location += os.sep - self.set_config('open_from', open_location) - - self.torrentqueue.start_new_torrent_by_name(name) - - def change_save_location(self, infohash): - def no_location(): - self.window_closed('savefile') - - t = self.torrents[infohash] - metainfo = t.metainfo - - selector = self.open_window(metainfo.is_batch and 'savedir' or \ - 'savefile', - title=_("Change save location for ") + metainfo.name, - fullname=t.dlpath, - got_location_func = \ - lambda fn: self.got_changed_location(infohash, fn), - no_location_func=no_location) - - def got_changed_location(self, infohash, fullpath): - self.window_closed('savefile') - self.torrentqueue.set_save_location(infohash, fullpath) - - def save_location(self, infohash, metainfo): - name = metainfo.name_fs - - if self.config['save_as'] and \ - os.access(os.path.split(self.config['save_as'])[0], os.W_OK): - path = self.config['save_as'] - self.got_location(infohash, path, store_in_config=False) - self.config['save_as'] = '' - return - - path = smart_dir(self.config['save_in']) - - fullname = os.path.join(path, name) - - if not self.config['ask_for_save']: - if os.access(fullname, os.F_OK): - message = MessageDialog(self.mainwindow, - _("File exists!"), - _('"%s" already exists. ' - "Do you want to choose a different file name?") % path_wrap(name), - buttons=gtk.BUTTONS_YES_NO, - nofunc= lambda : self.got_location(infohash, fullname), - yesfunc=lambda : self.get_save_location(infohash, metainfo, fullname), - default=gtk.RESPONSE_NO) - - else: - self.got_location(infohash, fullname) - else: - self.get_save_location(infohash, metainfo, fullname) - - def get_save_location(self, infohash, metainfo, fullname): - def no_location(): - self.window_closed('savefile') - self.torrentqueue.remove_torrent(infohash) - - selector = self.open_window(metainfo.is_batch and 'savedir' or \ - 'savefile', - title=_("Save location for ") + metainfo.name, - fullname=fullname, - got_location_func = lambda fn: \ - self.got_location(infohash, fn), - no_location_func=no_location) - - self.torrents[infohash].widget = selector - - def got_location(self, infohash, fullpath, store_in_config=True): - self.window_closed('savefile') - self.torrents[infohash].widget = None - save_in = os.path.split(fullpath)[0] - - metainfo = self.torrents[infohash].metainfo - if metainfo.is_batch: - bottom_dirs, top_dir_name = os.path.split(save_in) - if metainfo.name_fs == top_dir_name: - - message = MessageDialog(self.mainwindow, _("Directory exists!"), - _('"%s" already exists.'\ - " Do you intend to create an identical,"\ - " duplicate directory inside the existing"\ - " directory?")%path_wrap(save_in), - buttons=gtk.BUTTONS_YES_NO, - nofunc =lambda : self.got_location(infohash, save_in ), - yesfunc=lambda : self._got_location(infohash, save_in, fullpath, store_in_config=store_in_config), - default=gtk.RESPONSE_NO, - ) - return - self._got_location(infohash, save_in, fullpath, store_in_config=store_in_config) - - def _got_location(self, infohash, save_in, fullpath, store_in_config=True): - if store_in_config: - if save_in[-1] != os.sep: - save_in += os.sep - self.set_config('save_in', save_in) - self.torrents[infohash].dlpath = fullpath - self.torrentqueue.set_save_location(infohash, fullpath) - - def add_unhighlight_handle(self): - if self.unhighlight_handle is not None: - gobject.source_remove(self.unhighlight_handle) - - self.unhighlight_handle = gobject.timeout_add(2000, - self.unhighlight_after_a_while, - priority=gobject.PRIORITY_LOW) - - def unhighlight_after_a_while(self): - self.drag_highlight() - gobject.source_remove(self.unhighlight_handle) - self.unhighlight_handle = None - return False - - def init_updates(self): - if self.update_handle is not None: - gobject.source_remove(self.update_handle) - self.update_handle = gobject.timeout_add( - int(self.config['display_interval'] * 1000), - self.make_statusrequest) - - def remove_torrent_widget(self, infohash): - t = self.torrents[infohash] - self.lists[t.state].remove(infohash) - if t.state == RUNNING: - del self.running_torrents[infohash] - self.set_title() - if t.state == ASKING_LOCATION: - if t.widget is not None: - t.widget.destroy() - return - - if t.state in (KNOWN, RUNNING, QUEUED): - t.widget.close_child_windows() - - if t.state == RUNNING: - self.runbox.remove(t.widget) - elif t.state == QUEUED: - self.queuebox.remove(t.widget) - elif t.state == KNOWN: - self.knownbox.remove(t.widget) - - t.widget.destroy() - - self.set_size() - - def create_torrent_widget(self, infohash, queuepos=None): - t = self.torrents[infohash] - l = self.lists.setdefault(t.state, []) - if queuepos is None: - l.append(infohash) - else: - l.insert(queuepos, infohash) - if t.state == ASKING_LOCATION: - self.save_location(infohash, t.metainfo) - self.nag() - return - elif t.state == RUNNING: - self.running_torrents[infohash] = t - if not self.config['pause']: - t.widget = RunningTorrentBox(infohash, t.metainfo, t.dlpath, - t.completion, self) - else: - t.widget = PausedTorrentBox(infohash, t.metainfo, t.dlpath, - t.completion, self) - box = self.runbox - elif t.state == QUEUED: - t.widget = QueuedTorrentBox(infohash, t.metainfo, t.dlpath, - t.completion, self) - box = self.queuebox - elif t.state == KNOWN: - t.widget = KnownTorrentBox(infohash, t.metainfo, t.dlpath, - t.completion, self) - box = self.knownbox - box.pack_start(t.widget, expand=False, fill=False) - if queuepos is not None: - box.reorder_child(t.widget, queuepos) - - self.set_size() - - def log_text(self, text, severity=ERROR): - self.logbuffer.log_text(text, severity) - if self.child_windows.has_key('log'): - self.child_windows['log'].scroll_to_end() - - def _error(self, severity, err_str): - err_str = err_str.decode('utf-8', 'replace').encode('utf-8') - err_str = err_str.strip() - if severity >= ERROR: - self.error_modal(err_str) - self.log_text(err_str, severity) - - def error(self, infohash, severity, text): - if self.torrents.has_key(infohash): - name = self.torrents[infohash].metainfo.name - err_str = '"%s" : %s'%(name,text) - self._error(severity, err_str) - else: - ihex = infohash.encode('hex') - err_str = '"%s" : %s'%(ihex,text) - self._error(severity, err_str) - self._error(WARNING, 'Previous error raised for invalid infohash: "%s"' % ihex) - - def global_error(self, severity, text): - err_str = _("(global message) : %s")%text - self._error(severity, err_str) - - def error_modal(self, text): - if self.child_windows.has_key('log'): - return - - title = _("%s Error") % app_name - - if self.errordialog is not None: - if not self.errordialog.multi: - self.errordialog.destroy() - self.errordialog = MessageDialog(self.mainwindow, title, - _("Multiple errors have occurred. " - "Click OK to view the error log."), - buttons=gtk.BUTTONS_OK_CANCEL, - yesfunc=self.multiple_errors_yes, - nofunc=self.errors_closed, - default=gtk.RESPONSE_OK - ) - self.errordialog.multi = True - else: - # already showing the multi error dialog, so do nothing - pass - else: - self.errordialog = MessageDialog(self.mainwindow, title, text, - yesfunc=self.errors_closed, - default=gtk.RESPONSE_OK) - self.errordialog.multi = False - - - def multiple_errors_yes(self): - self.errors_closed() - self.open_window('log') - - def errors_closed(self): - self.errordialog = None - - def open_log(self): - self.open_window('log') - - def stop_queue(self): - self.set_config('pause', True) - self.set_title() - self.status_light.send_message('stop') - self.set_seen_remote_connections(False) - self.set_seen_connections(False) - q = list(self.runbox.get_queue()) - for infohash in q: - t = self.torrents[infohash] - self.remove_torrent_widget(infohash) - self.create_torrent_widget(infohash) - - def restart_queue(self): - self.set_config('pause', False) - q = list(self.runbox.get_queue()) - for infohash in q: - t = self.torrents[infohash] - self.remove_torrent_widget(infohash) - self.create_torrent_widget(infohash) - self.start_status_light() - - def start_status_light(self): - if len(self.running_torrents): - self.status_light.send_message('start') - else: - self.status_light.send_message('empty') - - def update_status(self, torrent, statistics): - if self.config['pause']: - self.status_light.send_message('start') - return - - if self.seen_remote_connections: - self.status_light.send_message('seen_remote_peers') - elif self.seen_connections: - self.status_light.send_message('seen_peers') - else: - self.start_status_light() - - self.running_torrents[torrent].widget.update_status(statistics) - if statistics.get('numPeers'): - self.set_seen_connections(seen=True) - if (not self.seen_remote_connections and - statistics.get('ever_got_incoming')): - self.set_seen_remote_connections(seen=True) - if self.updater is not None: - updater_infohash = self.updater.infohash - if self.torrents.has_key(updater_infohash): - updater_torrent = self.torrents[updater_infohash] - if updater_torrent.state == QUEUED: - self.change_torrent_state(updater_infohash, RUNNING, - index=0, replaced=0, - force_running=True) - - def set_seen_remote_connections(self, seen=False): - if seen: - self.status_light.send_message('seen_remote_peers') - self.seen_remote_connections = seen - - def set_seen_connections(self, seen=False): - if seen: - self.status_light.send_message('seen_peers') - self.seen_connections = seen - - def new_displayed_torrent(self, infohash, metainfo, dlpath, state, config, - completion=None, uptotal=0, downtotal=0): - t = Struct() - t.metainfo = metainfo - t.dlpath = dlpath - t.state = state - t.config = config - t.completion = completion - t.uptotal = uptotal - t.downtotal = downtotal - t.widget = None - self.torrents[infohash] = t - self.create_torrent_widget(infohash) - - def torrent_state_changed(self, infohash, dlpath, state, completion, - uptotal, downtotal, queuepos=None): - t = self.torrents[infohash] - self.remove_torrent_widget(infohash) - t.dlpath = dlpath - t.state = state - t.completion = completion - t.uptotal = uptotal - t.downtotal = downtotal - self.create_torrent_widget(infohash, queuepos) - - def reorder_torrent(self, infohash, queuepos): - self.remove_torrent_widget(infohash) - self.create_torrent_widget(infohash, queuepos) - - def update_completion(self, infohash, completion, files_left=None, - files_allocated=None): - t = self.torrents[infohash] - if files_left is not None and t.widget.filelistwindow is not None: - t.widget.filelistwindow.update(files_left, files_allocated) - - def removed_torrent(self, infohash): - self.remove_torrent_widget(infohash) - del self.torrents[infohash] - - def change_torrent_state(self, infohash, newstate, index=None, - replaced=None, force_running=False): - t = self.torrents[infohash] - pred = succ = None - if index is not None: - l = self.lists.setdefault(newstate, []) - if index > 0: - pred = l[index - 1] - if index < len(l): - succ = l[index] - self.torrentqueue.change_torrent_state(infohash, t.state, newstate, - pred, succ, replaced, force_running) - - def finish(self, infohash): - t = self.torrents[infohash] - if t is None or t.state == KNOWN: - return - self.change_torrent_state(infohash, KNOWN) - - def confirm_replace_running_torrent(self, infohash, replaced, index): - replace_func = lambda *args: self.change_torrent_state(infohash, - RUNNING, index, replaced) - add_func = lambda *args: self.change_torrent_state(infohash, - RUNNING, index, force_running=True) - moved_torrent = self.torrents[infohash] - - if moved_torrent.state == RUNNING: - self.change_torrent_state(infohash, RUNNING, index) - return - - if self.config['start_torrent_behavior'] == 'replace': - replace_func() - return - elif self.config['start_torrent_behavior'] == 'add': - add_func() - return - - moved_torrent_name = moved_torrent.metainfo.name - confirm = MessageDialog(self.mainwindow, - _("Stop running torrent?"), - _('You are about to start "%s". Do you want to stop another running torrent as well?')%(moved_torrent_name), - type=gtk.MESSAGE_QUESTION, - buttons=gtk.BUTTONS_YES_NO, - yesfunc=replace_func, - nofunc=add_func, - default=gtk.RESPONSE_YES) - - def nag(self): - if ((self.config['donated'] != version) and - #(random.random() * NAG_FREQUENCY) < 1) and - False): - title = _("Have you donated?") - message = _("Welcome to the new version of %s. Have you donated?")%app_name - self.nagwindow = MessageDialog(self.mainwindow, - title, - message, - type=gtk.MESSAGE_QUESTION, - buttons=gtk.BUTTONS_YES_NO, - yesfunc=self.nag_yes, nofunc=self.nag_no, - default=gtk.RESPONSE_NO) - - def nag_no(self): - self.donate() - - def nag_yes(self): - self.set_config('donated', version) - MessageDialog(self.mainwindow, - _("Thanks!"), - _("Thanks for donating! To donate again, " - 'select "Donate" from the "Help" menu.'), - type=gtk.MESSAGE_INFO, - default=gtk.RESPONSE_OK - ) - - def donate(self): - self.visit_url(DONATE_URL) - - - def visit_url(self, url, callback=None): - t = threading.Thread(target=self._visit_url, - args=(url,callback)) - t.setDaemon(True) - t.start() - - def _visit_url(self, url, callback=None): - webbrowser.open(url) - if callback: - gtk_wrap(callback) - - def toggle_shown(self): - if self.config['minimize_to_tray']: - if self.mainwindow.get_property('visible'): - self.mainwindow.hide() - else: - self.mainwindow.show_all() - else: - if not self.iconized: - self.mainwindow.iconify() - else: - self.mainwindow.deiconify() - - - def raiseerror(self, *args): - raise ValueError('test traceback behavior') - -#this class provides a thin layer around the loop so that the main window -#doesn't have to run it. It protects againstexceptions in mainwindow creation -#preventing the loop from starting (and causing "The grey screen of BT") -class MainLoop: - def __init__(self): - self.mainwindow = None - self.started = 0 - - gtk.gdk.threads_init() - - def set_mainwindow(self, mainwindow): - self.mainwindow = mainwindow - - def run(self): - self.mainwindow.traythread.start() - gtk.gdk.threads_enter() - - if self.mainwindow: - self.mainwindow.ssbutton.set_paused(self.mainwindow.config['pause']) - self.mainwindow.rate_slider_box.start() - self.mainwindow.init_updates() - - try: - #the main loop has been started - self.started = 1 - gtk.main() - except KeyboardInterrupt: - gtk.gdk.threads_leave() - if self.mainwindow: - self.mainwindow.torrentqueue.set_done() - raise - - gtk.gdk.threads_leave() - - def quit(self): - if self.mainwindow: - self.mainwindow.quit() - - -def btgui_exit_gtk(mainloop): - # if the main loop has never run, we have to run it to flush blocking threads - # if it has run, running it a second time will cause duplicate-destruction problems - if not mainloop.started: - # queue up a command to close the gui - gobject.idle_add(lock_wrap, mainloop.quit) - # run the main loop so we process all queued commands, then quit - mainloop.run() - -if __name__ == '__main__': - - mainloop = MainLoop() - - # make sure we start the gtk loop once before we close - atexit.register(btgui_exit_gtk, mainloop) - - torrentqueue = TorrentQueue.TorrentQueue(config, ui_options, ipc) - d = DownloadInfoFrame(config,TorrentQueue.ThreadWrappedQueue(torrentqueue)) - - mainloop.set_mainwindow(d) - global_log_func.logger = d.global_error - - startflag = threading.Event() - dlthread = threading.Thread(target = torrentqueue.run, - args = (d, gtk_wrap, startflag)) - dlthread.setDaemon(False) - dlthread.start() - startflag.wait() - # the wait may have been terminated because of an error - if torrentqueue.initialized == -1: - raise BTFailure(_("Could not start the TorrentQueue, see above for errors.")) - - torrentqueue.rawserver.install_sigint_handler() - for name in newtorrents: - d.torrentqueue.start_new_torrent_by_name(name) - - try: - mainloop.run() - except KeyboardInterrupt: - # the gtk main loop is closed in MainLoop - sys.exit(1) - d.trayicon.disable() - diff --git a/changetracker-console b/changetracker-console deleted file mode 120000 index f4dd34a..0000000 --- a/changetracker-console +++ /dev/null @@ -1 +0,0 @@ -changetracker-console.py
\ No newline at end of file diff --git a/images/bittorrent.ico b/images/bittorrent.ico Binary files differdeleted file mode 100644 index 47e6e70..0000000 --- a/images/bittorrent.ico +++ /dev/null diff --git a/images/icons/default/abort.png b/images/icons/default/abort.png Binary files differdeleted file mode 100644 index cd33fc0..0000000 --- a/images/icons/default/abort.png +++ /dev/null diff --git a/images/icons/default/broken.png b/images/icons/default/broken.png Binary files differdeleted file mode 100644 index 7d49e88..0000000 --- a/images/icons/default/broken.png +++ /dev/null diff --git a/images/icons/default/finished.png b/images/icons/default/finished.png Binary files differdeleted file mode 100644 index 7c95d07..0000000 --- a/images/icons/default/finished.png +++ /dev/null diff --git a/images/icons/default/info.png b/images/icons/default/info.png Binary files differdeleted file mode 100644 index 7dcd792..0000000 --- a/images/icons/default/info.png +++ /dev/null diff --git a/images/icons/default/pause.png b/images/icons/default/pause.png Binary files differdeleted file mode 100644 index 145b933..0000000 --- a/images/icons/default/pause.png +++ /dev/null diff --git a/images/icons/default/paused.png b/images/icons/default/paused.png Binary files differdeleted file mode 100644 index f65fbd5..0000000 --- a/images/icons/default/paused.png +++ /dev/null diff --git a/images/icons/default/play.png b/images/icons/default/play.png Binary files differdeleted file mode 100644 index 8e2f2cb..0000000 --- a/images/icons/default/play.png +++ /dev/null diff --git a/images/icons/default/queued.png b/images/icons/default/queued.png Binary files differdeleted file mode 100644 index 8135c68..0000000 --- a/images/icons/default/queued.png +++ /dev/null diff --git a/images/icons/default/remove.png b/images/icons/default/remove.png Binary files differdeleted file mode 100644 index c8e37be..0000000 --- a/images/icons/default/remove.png +++ /dev/null diff --git a/images/icons/default/running.png b/images/icons/default/running.png Binary files differdeleted file mode 100644 index 7ca2c0d..0000000 --- a/images/icons/default/running.png +++ /dev/null diff --git a/images/icons/default/status-broken.png b/images/icons/default/status-broken.png Binary files differdeleted file mode 100644 index 095a6a2..0000000 --- a/images/icons/default/status-broken.png +++ /dev/null diff --git a/images/icons/default/status-natted.png b/images/icons/default/status-natted.png Binary files differdeleted file mode 100644 index 9e67557..0000000 --- a/images/icons/default/status-natted.png +++ /dev/null diff --git a/images/icons/default/status-pre-natted.png b/images/icons/default/status-pre-natted.png Binary files differdeleted file mode 100644 index 513ccca..0000000 --- a/images/icons/default/status-pre-natted.png +++ /dev/null diff --git a/images/icons/default/status-running.png b/images/icons/default/status-running.png Binary files differdeleted file mode 100644 index fd7a309..0000000 --- a/images/icons/default/status-running.png +++ /dev/null diff --git a/images/icons/default/status-starting.png b/images/icons/default/status-starting.png Binary files differdeleted file mode 100644 index 7c909d5..0000000 --- a/images/icons/default/status-starting.png +++ /dev/null diff --git a/images/icons/default/status-stopped.png b/images/icons/default/status-stopped.png Binary files differdeleted file mode 100644 index 4fdb7d9..0000000 --- a/images/icons/default/status-stopped.png +++ /dev/null diff --git a/images/icons/default/trashcan.png b/images/icons/default/trashcan.png Binary files differdeleted file mode 100644 index 709bd49..0000000 --- a/images/icons/default/trashcan.png +++ /dev/null diff --git a/images/icons/old/broken.png b/images/icons/old/broken.png Binary files differdeleted file mode 100644 index 3f74744..0000000 --- a/images/icons/old/broken.png +++ /dev/null diff --git a/images/icons/old/finished.png b/images/icons/old/finished.png Binary files differdeleted file mode 100644 index fc29d9a..0000000 --- a/images/icons/old/finished.png +++ /dev/null diff --git a/images/icons/old/info.png b/images/icons/old/info.png Binary files differdeleted file mode 100644 index 75c3ff5..0000000 --- a/images/icons/old/info.png +++ /dev/null diff --git a/images/icons/old/pause.png b/images/icons/old/pause.png Binary files differdeleted file mode 100644 index 3da5aeb..0000000 --- a/images/icons/old/pause.png +++ /dev/null diff --git a/images/icons/old/paused.png b/images/icons/old/paused.png Binary files differdeleted file mode 100644 index ea83f83..0000000 --- a/images/icons/old/paused.png +++ /dev/null diff --git a/images/icons/old/play.png b/images/icons/old/play.png Binary files differdeleted file mode 100644 index 7ae6b2e..0000000 --- a/images/icons/old/play.png +++ /dev/null diff --git a/images/icons/old/queued.png b/images/icons/old/queued.png Binary files differdeleted file mode 100644 index d03b6c2..0000000 --- a/images/icons/old/queued.png +++ /dev/null diff --git a/images/icons/old/remove.png b/images/icons/old/remove.png Binary files differdeleted file mode 100644 index f09bdc0..0000000 --- a/images/icons/old/remove.png +++ /dev/null diff --git a/images/icons/old/running.png b/images/icons/old/running.png Binary files differdeleted file mode 100644 index 5fb45e1..0000000 --- a/images/icons/old/running.png +++ /dev/null diff --git a/images/icons/old/status-broken.png b/images/icons/old/status-broken.png Binary files differdeleted file mode 100644 index 7cfa3ef..0000000 --- a/images/icons/old/status-broken.png +++ /dev/null diff --git a/images/icons/old/status-natted.png b/images/icons/old/status-natted.png Binary files differdeleted file mode 100644 index b155e93..0000000 --- a/images/icons/old/status-natted.png +++ /dev/null diff --git a/images/icons/old/status-pre-natted.png b/images/icons/old/status-pre-natted.png Binary files differdeleted file mode 100644 index f311ba8..0000000 --- a/images/icons/old/status-pre-natted.png +++ /dev/null diff --git a/images/icons/old/status-running.png b/images/icons/old/status-running.png Binary files differdeleted file mode 100644 index 7a89822..0000000 --- a/images/icons/old/status-running.png +++ /dev/null diff --git a/images/icons/old/status-starting.png b/images/icons/old/status-starting.png Binary files differdeleted file mode 100644 index 09e3519..0000000 --- a/images/icons/old/status-starting.png +++ /dev/null diff --git a/images/icons/old/status-stopped.png b/images/icons/old/status-stopped.png Binary files differdeleted file mode 100644 index 15a5a43..0000000 --- a/images/icons/old/status-stopped.png +++ /dev/null diff --git a/images/logo/bittorrent_32.png b/images/logo/bittorrent_32.png Binary files differdeleted file mode 100644 index aa016bd..0000000 --- a/images/logo/bittorrent_32.png +++ /dev/null diff --git a/images/logo/bittorrent_96.png b/images/logo/bittorrent_96.png Binary files differdeleted file mode 100644 index aefd45e..0000000 --- a/images/logo/bittorrent_96.png +++ /dev/null diff --git a/khashmir/KRateLimiter.py b/khashmir/KRateLimiter.py index a9a9cdc..0b7bb7f 100644 --- a/khashmir/KRateLimiter.py +++ b/khashmir/KRateLimiter.py @@ -8,8 +8,8 @@ # for the specific language governing rights and limitations under the # License. -from BitTorrent.platform import bttime as time -from BitTorrent.CurrentRateMeasure import Measure +from NohGooee.platform import bttime as time +from NohGooee.CurrentRateMeasure import Measure from const import * from random import randrange, shuffle from traceback import print_exc diff --git a/khashmir/actions.py b/khashmir/actions.py index 2bbe94b..97ca949 100644 --- a/khashmir/actions.py +++ b/khashmir/actions.py @@ -8,7 +8,7 @@ # for the specific language governing rights and limitations under the # License. -from BitTorrent.platform import bttime as time +from NohGooee.platform import bttime as time import const diff --git a/khashmir/cache.py b/khashmir/cache.py index ab4df30..e38fc71 100644 --- a/khashmir/cache.py +++ b/khashmir/cache.py @@ -8,7 +8,7 @@ # for the specific language governing rights and limitations under the # License. -from BitTorrent.platform import bttime as time +from NohGooee.platform import bttime as time class Cache: def __init__(self, touch_on_access = False): diff --git a/khashmir/inserter.py b/khashmir/inserter.py index d45ff04..f3ade91 100644 --- a/khashmir/inserter.py +++ b/khashmir/inserter.py @@ -12,8 +12,8 @@ usage = "usage: inserter.py <contact host> <contact port>" from utkhashmir import UTKhashmir -from BitTorrent.RawServer_magic import RawServer -from BitTorrent.defaultargs import common_options, rare_options +from NohGooee.RawServer_magic import RawServer +from NohGooee.defaultargs import common_options, rare_options from khashmir.khash import newID from random import randrange from threading import Event diff --git a/khashmir/khashmir.py b/khashmir/khashmir.py index d939f67..23ee305 100644 --- a/khashmir/khashmir.py +++ b/khashmir/khashmir.py @@ -11,12 +11,12 @@ import const from socket import gethostbyname -from BitTorrent.platform import bttime as time +from NohGooee.platform import bttime as time from sha import sha import re -from BitTorrent.defaultargs import common_options, rare_options -from BitTorrent.RawServer_magic import RawServer +from NohGooee.defaultargs import common_options, rare_options +from NohGooee.RawServer_magic import RawServer from ktable import KTable, K from knode import * @@ -31,9 +31,9 @@ import sys import os import traceback -from BitTorrent.bencode import bencode, bdecode +from NohGooee.bencode import bencode, bdecode -from BitTorrent.defer import Deferred +from NohGooee.defer import Deferred from random import randrange from kstore import sample diff --git a/khashmir/knode.py b/khashmir/knode.py index 560252a..3a85265 100644 --- a/khashmir/knode.py +++ b/khashmir/knode.py @@ -9,7 +9,7 @@ # License. from node import Node -from BitTorrent.defer import Deferred +from NohGooee.defer import Deferred from const import NULL_ID from krpc import KRPCProtocolError diff --git a/khashmir/krpc.py b/khashmir/krpc.py index 86c9973..d826784 100644 --- a/khashmir/krpc.py +++ b/khashmir/krpc.py @@ -8,11 +8,11 @@ # for the specific language governing rights and limitations under the # License. -from BitTorrent.defer import Deferred -from BitTorrent.bencode import bencode, bdecode +from NohGooee.defer import Deferred +from NohGooee.bencode import bencode, bdecode import socket -from BitTorrent.RawServer_magic import Handler -from BitTorrent.platform import bttime +from NohGooee.RawServer_magic import Handler +from NohGooee.platform import bttime import time from math import log10 diff --git a/khashmir/kstore.py b/khashmir/kstore.py index 5c01200..ca59bfa 100644 --- a/khashmir/kstore.py +++ b/khashmir/kstore.py @@ -20,7 +20,7 @@ except ImportError: d[choice(l)] = 1 return d.keys() -from BitTorrent.platform import bttime as time +from NohGooee.platform import bttime as time class KItem: def __init__(self, key, value): diff --git a/khashmir/ktable.py b/khashmir/ktable.py index e0a07b4..1139ea3 100644 --- a/khashmir/ktable.py +++ b/khashmir/ktable.py @@ -8,7 +8,7 @@ # for the specific language governing rights and limitations under the # License. -from BitTorrent.platform import bttime as time +from NohGooee.platform import bttime as time from bisect import * from types import * diff --git a/khashmir/node.py b/khashmir/node.py index 65a48ef..3d9acde 100644 --- a/khashmir/node.py +++ b/khashmir/node.py @@ -9,7 +9,7 @@ # License. import khash -from BitTorrent.platform import bttime as time +from NohGooee.platform import bttime as time from types import * class Node: diff --git a/khashmir/test_khashmir.py b/khashmir/test_khashmir.py index e22028e..19e6175 100644 --- a/khashmir/test_khashmir.py +++ b/khashmir/test_khashmir.py @@ -10,7 +10,7 @@ from unittest import * -from BitTorrent import RawServer_magic +from NohGooee import RawServer_magic from khashmir import * import khash diff --git a/khashmir/test_krpc.py b/khashmir/test_krpc.py index 2ba4343..8e57cd9 100644 --- a/khashmir/test_krpc.py +++ b/khashmir/test_krpc.py @@ -10,7 +10,7 @@ from unittest import * from krpc import * -from BitTorrent.defaultargs import common_options, rare_options +from NohGooee.defaultargs import common_options, rare_options from threading import Event from node import Node diff --git a/khashmir/test_kstore.py b/khashmir/test_kstore.py index d2f2b15..8081dad 100644 --- a/khashmir/test_kstore.py +++ b/khashmir/test_kstore.py @@ -9,7 +9,7 @@ # License. import unittest -from BitTorrent.platform import bttime +from NohGooee.platform import bttime from time import sleep from kstore import KStore diff --git a/khashmir/unet.py b/khashmir/unet.py index e163a3f..65f1220 100644 --- a/khashmir/unet.py +++ b/khashmir/unet.py @@ -14,8 +14,8 @@ # usage: knet.py <num_nodes> <start_port> <ip_address> from utkhashmir import UTKhashmir -from BitTorrent.RawServer_magic import RawServer -from BitTorrent.defaultargs import common_options, rare_options +from NohGooee.RawServer_magic import RawServer +from NohGooee.defaultargs import common_options, rare_options from random import randrange from threading import Event import sys, os diff --git a/language_codes.py b/language_codes.py index 3464f30..ce657ed 100644 --- a/language_codes.py +++ b/language_codes.py @@ -1,8 +1,8 @@ import sys -from BitTorrent import language_names +from NohGooee import language_names if '-a' in sys.argv: - from BitTorrent.language import unfinished_language_names + from NohGooee.language import unfinished_language_names language_names.update(unfinished_language_names) languages = language_names.keys() diff --git a/launchmany-console b/launchmany-console deleted file mode 120000 index 3ee3ad1..0000000 --- a/launchmany-console +++ /dev/null @@ -1 +0,0 @@ -launchmany-console.py
\ No newline at end of file diff --git a/launchmany-curses b/launchmany-curses deleted file mode 120000 index f58dba2..0000000 --- a/launchmany-curses +++ /dev/null @@ -1 +0,0 @@ -launchmany-curses.py
\ No newline at end of file diff --git a/launchmany-curses.py b/launchmany-curses.py deleted file mode 100755 index 8f925ae..0000000 --- a/launchmany-curses.py +++ /dev/null @@ -1,301 +0,0 @@ -#!/usr/bin/env python - -# The contents of this file are subject to the BitTorrent Open Source License -# Version 1.1 (the License). You may not copy or use this file, in either -# source code or executable form, except in compliance with the License. You -# may obtain a copy of the License at http://www.bittorrent.com/license/. -# -# Software distributed under the License is distributed on an AS IS basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. - -# Written by John Hoffman - -from __future__ import division - -from BitTorrent.platform import install_translation -install_translation() - -DOWNLOAD_SCROLL_RATE = 1 - -import sys, os -from threading import Event -from time import time, localtime, strftime - -from BitTorrent.launchmanycore import LaunchMany -from BitTorrent.defaultargs import get_defaults -from BitTorrent.parseargs import parseargs, printHelp -from BitTorrent import configfile -from BitTorrent import version -from BitTorrent import BTFailure - -try: - curses = import_curses() - import curses.panel - from curses.wrapper import wrapper as curses_wrapper - from signal import signal, SIGWINCH -except: - print _("Textmode GUI initialization failed, cannot proceed.") - print - print _("This download interface requires the standard Python module " - "\"curses\", which is unfortunately not available for the native " - "Windows port of Python. It is however available for the Cygwin " - "port of Python, running on all Win32 systems (www.cygwin.com).") - print - print _("You may still use \"btdownloadheadless.py\" to download.") - sys.exit(1) - -exceptions = [] - -def fmttime(n): - if n <= 0: - return None - n = int(n) - m, s = divmod(n, 60) - h, m = divmod(m, 60) - if h > 1000000: - return _("connecting to peers") - return _("ETA in %d:%02d:%02d") % (h, m, s) - -def fmtsize(n): - n = long(n) - unit = [' B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] - i = 0 - if (n > 999): - i = 1 - while i + 1 < len(unit) and (n >> 10) >= 999: - i += 1 - n >>= 10 - n /= 1024 - if i > 0: - size = '%.1f' % n + '%s' % unit[i] - else: - size = '%.0f' % n + '%s' % unit[i] - return size - -def ljust(s, size): - s = s[:size] - return s + (' '*(size-len(s))) - -def rjust(s, size): - s = s[:size] - return (' '*(size-len(s)))+s - - -class CursesDisplayer(object): - - def __init__(self, scrwin): - self.messages = [] - self.scroll_pos = 0 - self.scroll_time = 0 - - self.scrwin = scrwin - signal(SIGWINCH, self.winch_handler) - self.changeflag = Event() - self._remake_window() - curses.use_default_colors() - - def winch_handler(self, signum, stackframe): - self.changeflag.set() - curses.endwin() - self.scrwin.refresh() - self.scrwin = curses.newwin(0, 0, 0, 0) - self._remake_window() - self._display_messages() - - def _remake_window(self): - self.scrh, self.scrw = self.scrwin.getmaxyx() - self.scrpan = curses.panel.new_panel(self.scrwin) - self.mainwinh = (2*self.scrh)//3 - self.mainwinw = self.scrw - 4 # - 2 (bars) - 2 (spaces) - self.mainwiny = 2 # + 1 (bar) + 1 (titles) - self.mainwinx = 2 # + 1 (bar) + 1 (space) - # + 1 to all windows so we can write at mainwinw - - self.mainwin = curses.newwin(self.mainwinh, self.mainwinw+1, - self.mainwiny, self.mainwinx) - self.mainpan = curses.panel.new_panel(self.mainwin) - self.mainwin.scrollok(0) - self.mainwin.nodelay(1) - - self.headerwin = curses.newwin(1, self.mainwinw+1, - 1, self.mainwinx) - self.headerpan = curses.panel.new_panel(self.headerwin) - self.headerwin.scrollok(0) - - self.totalwin = curses.newwin(1, self.mainwinw+1, - self.mainwinh+1, self.mainwinx) - self.totalpan = curses.panel.new_panel(self.totalwin) - self.totalwin.scrollok(0) - - self.statuswinh = self.scrh-4-self.mainwinh - self.statuswin = curses.newwin(self.statuswinh, self.mainwinw+1, - self.mainwinh+3, self.mainwinx) - self.statuspan = curses.panel.new_panel(self.statuswin) - self.statuswin.scrollok(0) - - try: - self.scrwin.border(ord('|'),ord('|'),ord('-'),ord('-'),ord(' '),ord(' '),ord(' '),ord(' ')) - except: - pass - rcols = (_("Size"),_("Download"),_("Upload")) - rwids = (8, 10, 10) - rwid = sum(rwids) - start = self.mainwinw - rwid - self.headerwin.addnstr(0, 2, '#', start, curses.A_BOLD) - self.headerwin.addnstr(0, 4, _("Filename"), start, curses.A_BOLD) - - for s,w in zip(rcols, rwids): - st = start + max(w - len(s), 0) - self.headerwin.addnstr(0, st, s[:w], len(s[:w]), curses.A_BOLD) - start += w - - self.totalwin.addnstr(0, self.mainwinw - 27, _("Totals:"), 7, curses.A_BOLD) - - self._display_messages() - - curses.panel.update_panels() - curses.doupdate() - self.changeflag.clear() - - - def _display_line(self, s, bold = False): - if self.disp_end: - return True - line = self.disp_line - self.disp_line += 1 - if line < 0: - return False - if bold: - self.mainwin.addnstr(line, 0, s, self.mainwinw, curses.A_BOLD) - else: - self.mainwin.addnstr(line, 0, s, self.mainwinw) - if self.disp_line >= self.mainwinh: - self.disp_end = True - return self.disp_end - - def _display_data(self, data): - if 3*len(data) <= self.mainwinh: - self.scroll_pos = 0 - self.scrolling = False - elif self.scroll_time + DOWNLOAD_SCROLL_RATE < time(): - self.scroll_time = time() - self.scroll_pos += 1 - self.scrolling = True - if self.scroll_pos >= 3*len(data)+2: - self.scroll_pos = 0 - - i = self.scroll_pos//3 - self.disp_line = (3*i)-self.scroll_pos - self.disp_end = False - - while not self.disp_end: - ii = i % len(data) - if i and not ii: - if not self.scrolling: - break - self._display_line('') - if self._display_line(''): - break - ( name, status, progress, peers, seeds, seedsmsg, dist, - uprate, dnrate, upamt, dnamt, size, t, msg ) = data[ii] - t = fmttime(t) - if t: - status = t - name = ljust(name,self.mainwinw-32) - size = rjust(fmtsize(size),8) - uprate = rjust('%s/s' % fmtsize(uprate),10) - dnrate = rjust('%s/s' % fmtsize(dnrate),10) - line = "%3d %s%s%s%s" % (ii+1, name, size, dnrate, uprate) - self._display_line(line, True) - if peers + seeds: - datastr = _(" (%s) %s - %s peers %s seeds %s dist copies - %s dn %s up") % ( - progress, status, peers, seeds, dist, - fmtsize(dnamt), fmtsize(upamt) ) - else: - datastr = ' '+status+' ('+progress+')' - self._display_line(datastr) - self._display_line(' '+ljust(msg,self.mainwinw-4)) - i += 1 - - def display(self, data): - if self.changeflag.isSet(): - return - - inchar = self.mainwin.getch() - if inchar == 12: # ^L - self._remake_window() - - self.mainwin.erase() - if data: - self._display_data(data) - else: - self.mainwin.addnstr( 1, self.mainwinw//2-5, - _("no torrents"), 12, curses.A_BOLD ) - totalup = 0 - totaldn = 0 - for ( name, status, progress, peers, seeds, seedsmsg, dist, - uprate, dnrate, upamt, dnamt, size, t, msg ) in data: - totalup += uprate - totaldn += dnrate - - totalup = '%s/s' % fmtsize(totalup) - totaldn = '%s/s' % fmtsize(totaldn) - - self.totalwin.erase() - self.totalwin.addnstr(0, self.mainwinw-27, _("Totals:"), 7, curses.A_BOLD) - self.totalwin.addnstr(0, self.mainwinw-20 + (10-len(totaldn)), - totaldn, 10, curses.A_BOLD) - self.totalwin.addnstr(0, self.mainwinw-10 + (10-len(totalup)), - totalup, 10, curses.A_BOLD) - - curses.panel.update_panels() - curses.doupdate() - - return inchar in (ord('q'),ord('Q')) - - def message(self, s): - self.messages.append(strftime('%x %X - ',localtime(time()))+s) - self._display_messages() - - def _display_messages(self): - self.statuswin.erase() - winpos = 0 - for s in self.messages[-self.statuswinh:]: - self.statuswin.addnstr(winpos, 0, s, self.mainwinw) - winpos += 1 - curses.panel.update_panels() - curses.doupdate() - - def exception(self, s): - exceptions.append(s) - self.message(_("SYSTEM ERROR - EXCEPTION GENERATED")) - - - -def LaunchManyWrapper(scrwin, config): - LaunchMany(config, CursesDisplayer(scrwin), 'launchmany-curses') - - -if __name__ == '__main__': - uiname = 'launchmany-curses' - defaults = get_defaults(uiname) - try: - if len(sys.argv) < 2: - printHelp(uiname, defaults) - sys.exit(1) - config, args = configfile.parse_configuration_and_args(defaults, - uiname, sys.argv[1:], 0, 1) - if args: - config['torrent_dir'] = args[0] - if not os.path.isdir(config['torrent_dir']): - raise BTFailure(_("Warning: ")+args[0]+_(" is not a directory")) - except BTFailure, e: - print _("error: ") + str(e) + _("\nrun with no args for parameter explanations") - sys.exit(1) - - curses_wrapper(LaunchManyWrapper, config) - if exceptions: - print _("\nEXCEPTION:") - print exceptions[0] diff --git a/maketorrent b/maketorrent deleted file mode 120000 index d6a8e31..0000000 --- a/maketorrent +++ /dev/null @@ -1 +0,0 @@ -maketorrent.py
\ No newline at end of file diff --git a/maketorrent-console b/maketorrent-console deleted file mode 120000 index 09524ba..0000000 --- a/maketorrent-console +++ /dev/null @@ -1 +0,0 @@ -maketorrent-console.py
\ No newline at end of file diff --git a/maketorrent.py b/maketorrent.py deleted file mode 100755 index ba5d275..0000000 --- a/maketorrent.py +++ /dev/null @@ -1,577 +0,0 @@ -#!/usr/bin/env python - -# The contents of this file are subject to the BitTorrent Open Source License -# Version 1.1 (the License). You may not copy or use this file, in either -# source code or executable form, except in compliance with the License. You -# may obtain a copy of the License at http://www.bittorrent.com/license/. -# -# Software distributed under the License is distributed on an AS IS basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. - -# Written by Matt Chisholm - -from __future__ import division - -from BitTorrent.platform import install_translation -install_translation() - -import os -import sys - -assert sys.version_info >= (2, 3), _("Install Python %s or greater") % '2.3' - -from threading import Event - -import gtk -import gobject - -from BitTorrent.GUI import * -from BitTorrent import Desktop -from BitTorrent import version -from BitTorrent import configfile -from BitTorrent.defaultargs import get_defaults -from BitTorrent.makemetafile import make_meta_files -from BitTorrent.parseargs import makeHelp -from BitTorrent.platform import btspawn -from BitTorrent.ConvertedMetainfo import set_filesystem_encoding - -defaults = get_defaults('maketorrent') -defconfig = dict([(name, value) for (name, value, doc) in defaults]) -del name, value, doc -ui_options = ('torrent_dir','piece_size_pow2','tracker_list','use_tracker') - -def sfe_ef(e,s): - print s -set_filesystem_encoding(defconfig['filesystem_encoding'], sfe_ef) - -EXTENSION = '.torrent' - -MAXIMUM_NODES = 8 - -class MainWindow(Window): - - def __init__(self, config): - Window.__init__(self) - self.mainwindow = self # temp hack to make modal win32 file choosers work - self.tooltips = gtk.Tooltips() - self.connect('destroy', self.quit) - self.set_title(_("%s torrent file creator %s")%(app_name, version)) - self.set_border_width(SPACING) - - self.config = config - self.tracker_list = [] - if self.config['tracker_list']: - self.tracker_list = self.config['tracker_list'].split(',') - - right_column_width=276 - self.box = gtk.VBox(spacing=SPACING) - - self.box.pack_start(lalign(gtk.Label( - _("Make torrent file for this file/directory:"))), - expand=False, fill=False) - - self.filebox = gtk.Entry() - self.filebox.set_editable(False) - self.change_button = gtk.Button(_("Choose...")) - self.change_button.connect('clicked', self.choose_files) - - hb = gtk.HBox(spacing=SPACING) - hb.pack_start(self.filebox, expand=True, fill=True) - hb.pack_end(self.change_button, expand=False, fill=False) - - self.box.pack_start(hb, expand=False, fill=False, padding=0) - - self.box.pack_start(lalign(gtk.Label( - _("(Directories will become batch torrents)"))), - expand=False, fill=False, padding=0) - - self.box.pack_start(gtk.HSeparator(), expand=False, fill=False, padding=0) - - self.table = gtk.Table(rows=3,columns=2,homogeneous=False) - self.table.set_col_spacings(SPACING) - self.table.set_row_spacings(SPACING) - y = 0 - - # Piece size - self.table.attach(ralign(gtk.Label(_("Piece size:"))),0,1,y,y+1, - xoptions=gtk.FILL, yoptions=0) - - self.piece_size = gtk.combo_box_new_text() - self.piece_size.offset = 15 - for i in range(7): - self.piece_size.append_text(str(Size(2**(i+self.piece_size.offset)))) - self.piece_size.set_active(self.config['piece_size_pow2'] - - self.piece_size.offset) - - self.piece_size_box = gtk.HBox(spacing=SPACING) - self.piece_size_box.pack_start(self.piece_size, - expand=False, fill=False) - self.table.attach(self.piece_size_box,1,2,y,y+1, - xoptions=gtk.FILL|gtk.EXPAND, yoptions=0) - y+=1 - - - # Announce URL / Tracker - self.tracker_radio = gtk.RadioButton(group=None, label=_("Use _tracker:")) - self.tracker_radio.value = True - - self.table.attach(self.tracker_radio,0,1,y,y+1, - xoptions=gtk.FILL, yoptions=0) - self.announce_entry = gtk.Entry() - self.announce_completion = gtk.EntryCompletion() - self.announce_entry.set_completion(self.announce_completion) - self.announce_completion.set_text_column(0) - self.build_completion() - - self.tracker_radio.entry = self.announce_entry - if self.config['use_tracker'] == self.tracker_radio.value: - self.announce_entry.set_sensitive(True) - else: - self.announce_entry.set_sensitive(False) - - if self.config['tracker_name']: - self.announce_entry.set_text(self.config['tracker_name']) - elif len(self.tracker_list): - self.announce_entry.set_text(self.tracker_list[0]) - else: - self.announce_entry.set_text('http://my.tracker:6969/announce') - - self.announce_entry.set_size_request(right_column_width,-1) - self.table.attach(self.announce_entry,1,2,y,y+1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=0) - y+=1 - - # DHT / Trackerless - self.dht_radio = gtk.RadioButton(group=self.tracker_radio, - label=_("Use _DHT:")) - self.dht_radio.value = False - - self.table.attach(align(self.dht_radio,0,0), 0,1,y,y+1, - xoptions=gtk.FILL|gtk.EXPAND, yoptions=0) - - self.dht_nodes_expander = gtk.Expander(_("Nodes (optional):")) - self.dht_nodes_expander.connect('size-allocate', self.resize_to_fit) - - self.dht_nodes = NodeList(self, 'router.bittorrent.com:6881') - self.dht_frame = gtk.Frame() - self.dht_frame.add(self.dht_nodes) - self.dht_frame.set_shadow_type(gtk.SHADOW_IN) - self.dht_nodes_expander.add(self.dht_frame) - - self.table.attach(self.dht_nodes_expander,1,2,y,y+1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=0) - self.dht_radio.entry = self.dht_nodes - - if self.config['use_tracker'] == self.dht_radio.value: - self.dht_nodes.set_sensitive(True) - else: - self.dht_nodes.set_sensitive(False) - - y+=1 - - for w in self.tracker_radio.get_group(): - w.connect('toggled', self.toggle_tracker_dht) - - for w in self.tracker_radio.get_group(): - if w.value == bool(self.config['use_tracker']): - w.set_active(True) - else: - w.set_active(False) - - # Hsep - self.table.attach(gtk.HSeparator(),0,2,y,y+1,yoptions=0) - y+=1 - - # Comment - self.comment_expander = gtk.Expander(_("Comments:")) - self.comment_expander.connect('size-allocate', self.resize_to_fit) - - self.comment_buffer = gtk.TextBuffer() - self.comment_text = gtk.TextView() - self.comment_text.set_buffer(self.comment_buffer) - self.comment_text.set_wrap_mode(gtk.WRAP_WORD) - self.comment_scroll = gtk.ScrolledWindow() - self.comment_scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - self.comment_scroll.set_shadow_type(gtk.SHADOW_IN) - self.comment_scroll.add(self.comment_text) - - self.comment_expander.add(self.comment_scroll) - self.table.attach(self.comment_expander,0,2,y,y+1, - xoptions=gtk.FILL, yoptions=0) - y+=1 - - # add table - self.box.pack_start(self.table, expand=True, fill=True, padding=0) - - # buttons - - self.buttonbox = gtk.HBox(homogeneous=True, spacing=SPACING) - - self.quitbutton = gtk.Button(stock=gtk.STOCK_CLOSE) -##======= -## # Piece size -## self.table.attach(ralign(gtk.Label('Piece size:')),0,1,y,y+1, -## xoptions=gtk.FILL, yoptions=0) - - -## self.piece_size_box = gtk.HBox(spacing=SPACING) -## self.piece_size_box.pack_start(self.piece_size, expand=False, fill=False) -## self.table.attach(self.piece_size_box,1,2,y,y+1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=0) -## y+=1 - - -## self.box.pack_start(self.table, expand=True, fill=True) - -## self.buttonbox = gtk.HBox(homogeneous=True, spacing=SPACING) - -## self.quitbutton = gtk.Button(stock=gtk.STOCK_QUIT) -##>>>>>>> remote - self.quitbutton.connect('clicked', self.quit) - self.buttonbox.pack_start(self.quitbutton, expand=True, fill=True) - - self.buttonbox.pack_start(gtk.Label(''), expand=True, fill=True) - - self.makebutton = IconButton(_("_Make"), stock=gtk.STOCK_EXECUTE) - self.makebutton.connect('clicked', self.make) - self.makebutton.set_sensitive(False) - self.buttonbox.pack_end(self.makebutton, expand=True, fill=True) - - self.box.pack_end(self.buttonbox, expand=False, fill=False) - - self.announce_entry.connect('changed', self.check_buttons) - self.filebox.connect('changed', self.check_buttons) - for w in self.tracker_radio.get_group(): - w.connect('clicked', self.check_buttons) - - self.box.pack_end(gtk.HSeparator(), expand=False, fill=False) - - self.add(self.box) - -# HelpWindow(None, makeHelp('maketorrent', defaults)) - - self.box.show_all() -## extraheight = self.dht_frame.size_request()[1] + \ -## self.comment_scroll.size_request()[1] -## sr = self.box.size_request() -## self.resize(sr[0] + SPACING*2, sr[1]+extraheight + SPACING*2) - self.resize_to_fit() - self.show_all() - - def toggle_tracker_dht(self, widget): - if widget.get_active(): - self.config['use_tracker'] = widget.value - - for e in [self.announce_entry, self.dht_nodes]: - if widget.entry is e: - e.set_sensitive(True) - else: - e.set_sensitive(False) - - def choose_files(self,widget): - fn = None - if self.config['torrent_dir']: - fn = self.config['torrent_dir'] - else: - fn = Desktop.desktop - - FileOrFolderSelection(self, fullname=fn, - got_multiple_location_func=self.add_files) - - def add_files(self, names): - for name in names: - self.filebox.set_text(name) - torrent_dir = os.path.split(name)[0] - if torrent_dir[-1] != os.sep: - torrent_dir += os.sep - self.config['torrent_dir'] = torrent_dir - - def get_piece_size_exponent(self): - i = self.piece_size.get_active() - exp = i+self.piece_size.offset - self.config['piece_size_pow2'] = exp - return exp - - def get_file(self): - return self.filebox.get_text() - - def get_announce(self): - if self.config['use_tracker']: - announce = self.announce_entry.get_text() - self.config['tracker_name'] = announce - else: - announce = self.dht_nodes.get_text() - return announce - - def make(self, widget): - file_name = self.get_file() - piece_size_exponent = self.get_piece_size_exponent() - announce = self.get_announce() - comment = self.comment_buffer.get_text( - *self.comment_buffer.get_bounds()) - - if self.config['use_tracker']: - self.add_tracker(announce) - errored = False - if not errored: - d = ProgressDialog(self, [file_name,], announce, - piece_size_exponent, comment) - d.main() - - def check_buttons(self, *widgets): - file_name = self.get_file() - tracker = self.announce_entry.get_text() - if file_name not in (None, ''): - if self.config['use_tracker']: - if len(tracker) >= len('http://x.cc'): - self.makebutton.set_sensitive(True) - else: - self.makebutton.set_sensitive(False) - else: - self.makebutton.set_sensitive(True) - else: - self.makebutton.set_sensitive(False) - - def save_config(self): - def error_callback(error, string): print string - configfile.save_ui_config(self.config, 'maketorrent', ui_options, error_callback) - - def quit(self, widget): - self.save_config() - self.destroy() - - def add_tracker(self, tracker_name): - try: - self.tracker_list.pop(self.tracker_list.index(tracker_name)) - except ValueError: - pass - self.tracker_list[0:0] = [tracker_name,] - - self.config['tracker_list'] = ','.join(self.tracker_list) - self.build_completion() - - def build_completion(self): - liststore = gtk.ListStore(gobject.TYPE_STRING) - for t in self.tracker_list: - liststore.append([t]) - self.announce_completion.set_model(liststore) - - def resize_to_fit(self, *args): - garbage, y = self.size_request() - x, garbage = self.get_size() - gobject.idle_add(self.resize, x, y) - - -class AppWindow(MainWindow): - def quit(self, widget): - MainWindow.quit(self, widget) - gtk.main_quit() - - -class NodeList(gtk.TreeView): - def __init__(self, parent, nodelist): - self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - pre_size_list = ['router.bittorrent.com', '65536'] - self.store.append(pre_size_list) - - gtk.TreeView.__init__(self, self.store) - self.set_enable_search(False) - - self.host_render = gtk.CellRendererText() - self.host_render.set_property('editable', True) - self.host_column = gtk.TreeViewColumn(_("_Host"), self.host_render, - text=0) - self.append_column(self.host_column) - self.host_render.connect('edited', self.store_host_value) - - self.port_render = gtk.CellRendererText() - self.port_render.set_property('editable', True) - self.port_column = gtk.TreeViewColumn(_("_Port"), self.port_render, - text=1) - self.append_column(self.port_column) - self.port_render.connect('edited', self.store_port_value) - - #self.columns_autosize() - #self.host_column.set_fixed_width(self.host_column.get_width()) - #self.host_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - #self.realize() - #self.port_column.set_fixed_width(self.port_column.get_width()) - #self.port_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - - self.store.clear() - - for i, e in enumerate(nodelist.split(',')): - host, port = e.split(':') - self.store.append((host, port)) - - if i < MAXIMUM_NODES - 1: - self.store.append(('','')) - - def store_host_value(self, cell, row, value): - parts = value.split('.') - if value != '': - for p in parts: - if not p.isalnum(): - return - try: - value = value.encode('idna') - except UnicodeError: - return - it = self.store.get_iter_from_string(row) - self.store.set(it, 0, str(value)) - self.check_row(row) - - def store_port_value(self, cell, row, value): - if value != '': - try: - v = int(value) - if v > 65535: - value = 65535 - if v < 0: - value = 0 - except: - return # return on non-integer values - it = self.store.get_iter_from_string(row) - self.store.set(it, 1, str(value)) - #curs = self.get_cursor() - #print curs - #print type(curs[0][0]) - - self.check_row(row) - #newpath = ((int(row)+1,), self.port_column) - #print newpath - #self.set_cursor(newpath) - - def check_row(self, row): - # called after editing to see whether we should add a new - # blank row, or remove the now blank currently edited row. - it = self.store.get_iter_from_string(row) - host_value = self.store.get_value(it, 0) - port_value = self.store.get_value(it, 1) - if host_value and port_value and \ - int(row) == len(self.store)-1 and \ - int(row) < MAXIMUM_NODES -1 : - self.store.append(('','')) - elif host_value == '' and \ - port_value == '' and \ - int(row) != len(self.store)-1: - self.store.remove(it) - - def get_nodes(self): - retlist = [] - it = self.store.get_iter_first() - while it: - host = self.store.get_value(it, 0) - port = self.store.get_value(it, 1) - if host != '' and port != '': - retlist.append((host,port)) - it = self.store.iter_next(it) - return retlist - - def get_text(self): - nodelist = self.get_nodes() - return ','.join(['%s:%s'%node for node in nodelist]) - - -class ProgressDialog(gtk.Dialog): - - def __init__(self, parent, file_list, announce, piece_length, comment): - gtk.Dialog.__init__(self, parent=parent, flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT) - self.set_size_request(400,-1) - self.set_border_width(SPACING) - self.set_title(_("Building torrents...")) - self.file_list = file_list - self.announce = announce - self.piece_length = piece_length - self.comment = comment - - self.flag = Event() # ??? - - self.label = gtk.Label(_("Checking file sizes...")) - self.label.set_line_wrap(True) - - self.vbox.set_spacing(SPACING) - self.vbox.pack_start(lalign(self.label), expand=False, fill=False) - - self.progressbar = gtk.ProgressBar() - self.vbox.pack_start(self.progressbar, expand=False, fill=False) - - self.cancelbutton = gtk.Button(stock=gtk.STOCK_CANCEL) - self.cancelbutton.connect('clicked', self.cancel) - self.action_area.pack_end(self.cancelbutton) - - self.show_all() - - self.done_button = gtk.Button(stock=gtk.STOCK_OK) - self.done_button.connect('clicked', self.cancel) - - self.seed_button = gtk.Button(_("Start seeding")) - self.seed_button.connect('clicked', self.seed) - - def main(self): - self.complete() - - def seed(self, widget=None): - for f in self.file_list: - btspawn(None, 'bittorrent', f+EXTENSION, '--save_as', f) - self.cancel() - - def cancel(self, widget=None): - self.flag.set() - self.destroy() - - def set_progress_value(self, value): - self.progressbar.set_fraction(value) - self._update_gui() - - def set_file(self, filename): - self.label.set_text(_("building ") + filename + EXTENSION) - self._update_gui() - - def _update_gui(self): - while gtk.events_pending(): - gtk.main_iteration(block=False) - - def complete(self): - try: - make_meta_files(self.announce, - self.file_list, - flag=self.flag, - progressfunc=self.set_progress_value, - filefunc=self.set_file, - piece_len_pow2=self.piece_length, - comment=self.comment, - use_tracker=config['use_tracker'], - data_dir=config['data_dir'], - ) - if not self.flag.isSet(): - self.set_title(_("Done.")) - self.label.set_text(_("Done building torrents.")) - self.set_progress_value(1) - self.action_area.remove(self.cancelbutton) - self.action_area.pack_start(self.seed_button) - self.action_area.pack_start(self.done_button) - self.seed_button.show() - self.done_button.show() - except (OSError, IOError), e: - self.set_title(_("Error!")) - self.label.set_text(_("Error building torrents: ") + str(e)) - - - - -def run(): - config, args = configfile.parse_configuration_and_args(defaults, - 'maketorrent', [], 0, None) - MainWindow(config) - - -if __name__ == '__main__': - config, args = configfile.parse_configuration_and_args(defaults, - 'maketorrent', sys.argv[1:], 0, None) - AppWindow(config) - try: - gtk.main() - except KeyboardInterrupt: - # gtk.mainloop not running - # exit and don't save config options - sys.exit(1) diff --git a/changetracker-console.py b/nohgooee-changetracker index 976a536..d523e6e 100755 --- a/changetracker-console.py +++ b/nohgooee-changetracker @@ -12,12 +12,12 @@ # Written by Henry 'Pi' James and Bram Cohen -from BitTorrent.platform import install_translation +from NohGooee.platform import install_translation install_translation() from os.path import basename from sys import argv, exit -from BitTorrent.bencode import bencode, bdecode +from NohGooee.bencode import bencode, bdecode if len(argv) < 3: print _("Usage: %s TRACKER_URL [TORRENTFILE [TORRENTFILE ... ] ]") % basename(argv[0]) diff --git a/maketorrent-console.py b/nohgooee-maketorrent index c103fe0..ebbdb5f 100755 --- a/maketorrent-console.py +++ b/nohgooee-maketorrent @@ -13,15 +13,15 @@ # Written by Bram Cohen if __name__ == '__main__': - from BitTorrent.platform import install_translation + from NohGooee.platform import install_translation install_translation() import sys -from BitTorrent.defaultargs import get_defaults -from BitTorrent import configfile -from BitTorrent.makemetafile import make_meta_files -from BitTorrent.parseargs import parseargs, printHelp -from BitTorrent import BTFailure +from NohGooee.defaultargs import get_defaults +from NohGooee import configfile +from NohGooee.makemetafile import make_meta_files +from NohGooee.parseargs import parseargs, printHelp +from NohGooee import BTFailure defaults = get_defaults('maketorrent-console') defaults.extend([ diff --git a/launchmany-console.py b/nohgooee-seed index f327178..e650d6d 100755 --- a/launchmany-console.py +++ b/nohgooee-seed @@ -13,18 +13,18 @@ # Written by John Hoffman if __name__ == '__main__': - from BitTorrent.platform import install_translation + from NohGooee.platform import install_translation install_translation() import sys import os -from BitTorrent.launchmanycore import LaunchMany -from BitTorrent.defaultargs import get_defaults -from BitTorrent.parseargs import parseargs, printHelp -from BitTorrent import configfile -from BitTorrent import version -from BitTorrent import BTFailure +from NohGooee.launchmanycore import LaunchMany +from NohGooee.defaultargs import get_defaults +from NohGooee.parseargs import parseargs, printHelp +from NohGooee import configfile +from NohGooee import version +from NohGooee import BTFailure exceptions = [] diff --git a/btseed.init b/nohgooee-seed.init index 7214eed..7214eed 100755 --- a/btseed.init +++ b/nohgooee-seed.init diff --git a/torrentinfo-console.py b/nohgooee-torrentinfo index e9263e0..2f3d15a 100755 --- a/torrentinfo-console.py +++ b/nohgooee-torrentinfo @@ -12,14 +12,14 @@ # Written by Henry 'Pi' James, Loring Holden and Matt Chisholm -from BitTorrent.platform import install_translation +from NohGooee.platform import install_translation install_translation() from sys import * from os.path import * from sha import * -from BitTorrent.bencode import * -from BitTorrent import version, app_name +from NohGooee.bencode import * +from NohGooee import version, app_name NAME, EXT = splitext(basename(argv[0])) diff --git a/bttrack.init b/nohgooee-tracker.init index 319c526..319c526 100755 --- a/bttrack.init +++ b/nohgooee-tracker.init diff --git a/bittorrent-tracker.py b/nohgooee-tracker.tac index 4c176da..e957433 100755 --- a/bittorrent-tracker.py +++ b/nohgooee-tracker.tac @@ -12,10 +12,10 @@ # Written by Bram Cohen -from BitTorrent.platform import install_translation +from NohGooee.platform import install_translation install_translation() -from BitTorrent.track import Tracker, InfoPage, Scrape, File, Announce, FavIcon +from NohGooee.track import Tracker, InfoPage, Scrape, File, Announce, FavIcon from twisted.application import internet, service from twisted.web import static, server diff --git a/redirdonate.html b/redirdonate.html deleted file mode 100644 index f3d4f0c..0000000 --- a/redirdonate.html +++ /dev/null @@ -1 +0,0 @@ -<meta http-equiv="refresh" content="0;url=http://www.bittorrent.com/donate.html"> @@ -15,13 +15,13 @@ import os os.system('sh ./makei18n.sh') -from BitTorrent.platform import install_translation +from NohGooee.platform import install_translation install_translation() import sys from distutils.core import setup, Extension -from BitTorrent import version, languages -from BitTorrent.platform import calc_unix_dirs +from NohGooee import version, languages +from NohGooee.platform import calc_unix_dirs import glob diff --git a/test/test_ClientIdentifier.py b/test/test_ClientIdentifier.py index 220fe7e..ea79eec 100644 --- a/test/test_ClientIdentifier.py +++ b/test/test_ClientIdentifier.py @@ -23,7 +23,7 @@ import sys sys.path = ['.',] + sys.path #HACK -from BitTorrent import ClientIdentifier +from NohGooee import ClientIdentifier print "Using:", ClientIdentifier diff --git a/torrentinfo-console b/torrentinfo-console deleted file mode 120000 index e436c6c..0000000 --- a/torrentinfo-console +++ /dev/null @@ -1 +0,0 @@ -torrentinfo-console.py
\ No newline at end of file |