def __init__(self, persister, version, rawUpdateFunc, parent, **kwargs): self.torrentId = None #Syntax: NameOfColumn, NameOfStat, DataType, ColumnWidth cols = [('Id','id', 'int', 40, False),\ ('Addr','addr', 'native', 125, True),\ ('Client','peerClient', 'native', 100, True),\ ('Direction','direction','native', 75, True),\ ('Connected (total)', 'totalConnectedInterval', 'timeInterval', 75, True),\ ('Progress', 'peerProgress', 'percent', 75, True),\ ('I', 'localInterest', 'bool', 20, True),\ ('C', 'localChoke', 'bool', 20, True),\ ('RI', 'remoteInterest', 'bool', 30, True),\ ('RC', 'remoteChoke', 'bool', 30, True),\ ('Downloaded (R)', 'inRawBytes', 'dataAmount', 110, False),\ ('Downloaded (P)', 'inPayloadBytes', 'dataAmount', 110, True),\ ('Downspeed (R)', 'inRawSpeed', 'transferSpeed', 110, True),\ ('Uploaded (R)', 'outRawBytes', 'dataAmount', 100, False),\ ('Uploaded (P)', 'outPayloadBytes', 'dataAmount', 100, True),\ ('Upspeed (R)', 'outRawSpeed', 'transferSpeed', 100, True),\ ('lReq', 'localRequestCount', 'int', 50, True),\ ('rReq', 'remoteRequestCount', 'int', 50, True),\ ('Connected (connection)', 'connectedInterval', 'timeInterval', 75, True),\ ('Avg. Downspeed (R)', 'avgInRawSpeed', 'transferSpeed', 140, False),\ ('Avg. Downspeed (P)', 'avgInPayloadSpeed', 'transferSpeed', 140, False),\ ('Avg. Upspeed (R)', 'avgOutRawSpeed', 'transferSpeed', 125, False),\ ('Avg. Upspeed (P)', 'avgOutPayloadSpeed', 'transferSpeed', 125, False),\ ('Score', 'score', 'float', 75, False),\ ('Payload Ratio', 'payloadRatio', 'float', 125, False), ('Protocol Overhead', 'protocolOverhead', 'percent', 150, False), ('Offered Pieces', 'offeredPieces', 'native', 100, False)] self.rawUpdateFunc = rawUpdateFunc PersistentVirtualListCtrl.__init__(self, persister, 'TorrentConnectionList-', self._updatePerstData, version, cols, self._getRowData, parent, rowIdCol='Id', **kwargs)
def __init__(self, persister, version, rawUpdateFunc, trackerGetFunc, trackerSetFunc, parent, **kwargs): self.persister = persister self.version = version self.trackerGetFunc = trackerGetFunc self.trackerSetFunc = trackerSetFunc self.torrentId = None #Syntax: NameOfColumn, NameOfStat, DataType, ColumnWidth cols = [('Id', 'trackerId', 'int', 75, False),\ ('Tier', 'tier', 'int', 75, False),\ ('Pos In Tier', 'tierPos', 'int', 75, False),\ ('Priority', 'trackerPrio', 'int', 75, True),\ ('Url', 'trackerUrl', 'native', 300, True),\ ('Active', 'active', 'bool', 20, True),\ ('Last Announce Result', 'lastAnnounceResult', 'native', 150, True),\ ('Seeds', 'seeds', 'int', 75, True),\ ('Leeches', 'leeches', 'int', 75, True),\ ('Downloads', 'downloads', 'int', 75, True),\ ('Last Announce Attempt', 'announceTryTime', 'fullTime', 170, False),\ ('Last Announce Success', 'announceSuccessTime', 'fullTime', 170, False),\ ('Last Scrape Attempt', 'scrapeTryTime', 'fullTime', 170, False),\ ('Last Scrape Success', 'scrapeSuccessTime', 'fullTime', 170, False),\ ('Announce Attempts', 'announceTryCount', 'int', 170, False),\ ('Announce Successes', 'announceSuccessCount', 'int', 170, False),\ ('Scrape Attempts', 'scrapeTryCount', 'int', 170, False),\ ('Scrape Successes', 'scrapeSuccessCount', 'int', 170, False)] self.rawUpdateFunc = rawUpdateFunc PersistentVirtualListCtrl.__init__(self, persister, 'TorrentTrackerList-', self._updatePerstData, version, cols, self._getRowData, parent, rowIdCol='Id', defaultSortCol='Priority', defaultSortDirection='DESC', **kwargs) self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnRightClick, self)
def __init__(self, persister, version, torrentHandler, childWindow, updateFunc, parent, **kwargs): #data Stuff self.torrentHandler = torrentHandler self.childWindow = childWindow #logger self.log = logging.getLogger('TorrentList') #columns #Syntax: NameOfColumn, NameOfStat, DataType, ColumnWidth cols = [('Pos','pos', 'int', 40, True),\ ('Id','id', 'int', 40, False),\ ('Status', 'state', 'native', 75, True),\ ('Name', 'torrentName', 'native', 125, True),\ ('Size', 'torrentSize', 'dataAmount', 75, True),\ ('Got', 'progressBytes', 'dataAmount', 75, True),\ ('Progress', 'progressPercent', 'percent', 75, True),\ ('Downloaded (R)', 'inRawBytes', 'dataAmount', 115, False),\ ('Downloaded (P)', 'inPayloadBytes', 'dataAmount', 115, True),\ ('Downspeed (R)', 'inRawSpeed', 'transferSpeed', 100, True),\ ('Uploaded (R)', 'outRawBytes', 'dataAmount', 100, False),\ ('Uploaded (P)', 'outPayloadBytes', 'dataAmount', 100, True),\ ('Upspeed (R)', 'outRawSpeed', 'transferSpeed', 100, True),\ ('Peers', ('connectedSeeds', 'knownSeeds', 'connectedLeeches', 'knownLeeches') , 'peerStats', 125, True),\ ('Seeds (Connected)', 'connectedSeeds', 'int', 100, False),\ ('Seeds (Known)', 'knownSeeds', 'int', 100, False),\ ('Tracker Status', 'trackerStatus', 'native', 100, False),\ ('Avg. Downspeed (R)', 'avgInRawSpeed', 'transferSpeed', 140, False),\ ('Avg. Downspeed (P)', 'avgInPayloadSpeed', 'transferSpeed', 140, False),\ ('Avg. Upspeed (R)', 'avgOutRawSpeed', 'transferSpeed', 125, False),\ ('Avg. Upspeed (P)', 'avgOutPayloadSpeed', 'transferSpeed', 125, False),\ ('Protocol Overhead', 'protocolOverhead', 'percent', 150, False),\ ('Superseeding', 'superSeeding', 'bool', 20, False)] statKw = {'wantedStats':{'bt':'all'}, 'wantedTorrentStats':{'peers':True, 'queue':True, 'state':True, 'progress':True, 'torrent':True, 'trackerStatus':True, 'transfer':True, 'transferAverages':True}} func = lambda: updateFunc(**statKw)['bt'] PersistentVirtualListCtrl.__init__(self, persister, 'TorrentList-', self._updatePerstData, version, cols, func, parent, rowIdCol='Id', **kwargs) #events self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelect) self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnRightClick)
def __init__(self, persister, version, rawUpdateFunc, parent, **kwargs): self.torrentId = None #Syntax: NameOfColumn, NameOfStat, DataType, ColumnWidth cols = [('Piece', 'pieceIndex', 'int', 75, True),\ ('Size', 'pieceSize', 'dataAmount', 75, False),\ ('Priority', 'piecePriority', 'int', 75, True),\ ('Availability', 'pieceAvailability', 'int', 75, True),\ ('Chunks', 'totalRequests', 'int', 75, True),\ ('Finished', 'finishedRequests', 'int', 75, True),\ ('Needed', 'neededRequests', 'int', 75, False),\ ('In Progress', 'runningRequests', 'int', 100, True),\ ('F', 'filled', 'bool', 20, True),\ ('Used Conns', 'assignedConnsNum', 'int', 100, True),\ ('Used Conns (List)', 'assignedConnsList', 'native', 150, False)] self.rawUpdateFunc = rawUpdateFunc PersistentVirtualListCtrl.__init__(self, persister, 'TorrentRequestList-', self._updatePerstData, version, cols, self._getRowData, parent, rowIdCol='Piece', **kwargs)
def __init__(self, persister, version, rawUpdateFunc, setPrioFunc, setWantedFlagFunc, parent, **kwargs): self.setPrioFunc = setPrioFunc self.setWantedFlagFunc = setWantedFlagFunc self.torrentId = None #Syntax: NameOfColumn, NameOfStat, DataType, ColumnWidth cols = [('Id', 'id', 'int', 50, False), ('Path', 'path', 'native', 500, True), ('Size', 'size', 'dataAmount', 75, True), ('Progress', 'progress', 'percent', 75, True), ('D', 'wanted', 'bool', 20, True), ('Priority', 'priority', 'int', 75, True), ('First Piece', 'firstPiece', 'int', 75, False), ('Last Piece', 'lastPiece', 'int', 75, False), ('Min. Availability', 'minAvailability', 'int', 75, False), ('Avg. Availability', 'avgAvailability', 'float', 75, False)] self.rawUpdateFunc = rawUpdateFunc PersistentVirtualListCtrl.__init__(self, persister, 'TorrentFileList-', self._updatePerstData, version, cols, self._getRowData, parent, rowIdCol='Id', **kwargs) self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnRightClick)
def __init__(self, parent, trackerInfo, persister, version, **kwargs): wx.Panel.__init__(self, parent, **kwargs) ##VARS self.trackerInfo = [{'groupId':tierIdx, 'groupPos':tierIdx+1, 'groupName':'Group '+str(tierIdx), 'groupTracker':tier} for tierIdx, tier in enumerate(trackerInfo)] if len(self.trackerInfo) == 0: self.selectedGroup = None self.nextGroupId = 0 self.nextTrackerId = 0 else: self.selectedGroup = 0 self.nextGroupId = max(tier['groupId'] for tier in self.trackerInfo) + 1 self.nextTrackerId = max(max(tracker['trackerId'] for tracker in tier['groupTracker']) for tier in self.trackerInfo) + 1 self.knownTrackerMapper = {u'crstrack.i2p':u'http://mm3zx3besctrx6peq5wzzueil237jdgscuvn5ugwilxrwzyuajja.b32.i2p/tracker/announce.php', u'tracker2.postman.i2p':u'http://lnQ6yoBTxQuQU8EQ1FlF395ITIQF-HGJxUeFvzETLFnoczNjQvKDbtSB7aHhn853zjVXrJBgwlB9sO57KakBDaJ50lUZgVPhjlI19TgJ-CxyHhHSCeKx5JzURdEW-ucdONMynr-b2zwhsx8VQCJwCEkARvt21YkOyQDaB9IdV8aTAmP~PUJQxRwceaTMn96FcVenwdXqleE16fI8CVFOV18jbJKrhTOYpTtcZKV4l1wNYBDwKgwPx5c0kcrRzFyw5~bjuAKO~GJ5dR7BQsL7AwBoQUS4k1lwoYrG1kOIBeDD3XF8BWb6K3GOOoyjc1umYKpur3G~FxBuqtHAsDRICkEbKUqJ9mPYQlTSujhNxiRIW-oLwMtvayCFci99oX8MvazPS7~97x0Gsm-onEK1Td9nBdmq30OqDxpRtXBimbzkLbR1IKObbg9HvrKs3L-kSyGwTUmHG9rSQSoZEvFMA-S0EXO~o4g21q1oikmxPMhkeVwQ22VHB0-LZJfmLr4SAAAA.i2p/announce.php', u'tracker.thepiratebay.i2p':u'http://tracker.thepiratebay.i2p/announce', u'tracker.welterde.i2p':u'http://tracker.welterde.i2p/announce'} ##GUI panelItems = wx.GridBagSizer(vgap = 0, hgap = 0) #splitter self.splitter = wx.SplitterWindow(self, style=wx.CLIP_CHILDREN) self.splitter.SetMinimumPaneSize(200) ##tracker groups groupPanel = wx.Panel(self.splitter) groupPanelSizer = wx.GridBagSizer(vgap = 0, hgap = 6) #group list #Syntax: NameOfColumn, NameOfStat, DataType, ColumnWidth cols = [('Id', 'groupId', 'int', 75, False),\ ('Pos', 'groupPos', 'int', 40, True),\ ('Group', 'groupName', 'native', 100, True)] listboxId = wx.NewId() self.trackerGroupList = PersistentVirtualListCtrl(persister, 'TorrentModifyDialog-TrackerGroupList-', self._updateGroupPerstData, version, cols, self._getTrackerGroupData, rowIdCol='Id', allowSort=False, defaultSortCol='Pos', parent=groupPanel, id=listboxId, size=wx.Size(140, -1)) self.trackerGroupList.SetToolTipString('') groupPanelSizer.Add(self.trackerGroupList, (0,1), (6,1), wx.EXPAND | wx.ALL, border = 0) #buttons buttonAdd = wx.Button(groupPanel, wx.ID_ADD, "") groupPanelSizer.Add(buttonAdd, (1,0), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonAdd, wx.ID_ADD, self.OnGroupAdd) buttonMoveUp = wx.Button(groupPanel, wx.ID_UP, "") groupPanelSizer.Add(buttonMoveUp, (2,0), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonMoveUp, wx.ID_UP, self.OnGroupMoveUp) buttonId = wx.NewId() buttonMoveDown = wx.Button(groupPanel, wx.ID_DOWN, "") groupPanelSizer.Add(buttonMoveDown, (3,0), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonMoveDown, wx.ID_DOWN, self.OnGroupMoveDown) buttonId = wx.NewId() buttonRemove = wx.Button(groupPanel, wx.ID_DELETE, "") groupPanelSizer.Add(buttonRemove, (4,0), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonRemove, wx.ID_DELETE, self.OnGroupRemove) #sizer groupPanelSizer.AddGrowableCol(1, 1) groupPanelSizer.AddGrowableRow(0, 1) groupPanelSizer.AddGrowableRow(5, 1) groupPanel.SetSizer(groupPanelSizer) ##tracker urls urlPanel = wx.Panel(self.splitter) urlPanelSizer = wx.GridBagSizer(vgap = 0, hgap = 6) #url list #Syntax: NameOfColumn, NameOfStat, DataType, ColumnWidth cols = [('Id', 'trackerId', 'int', 75, False),\ ('Position', 'tierPos', 'int', 75, True),\ ('Url', 'trackerUrl', 'native', 385, True),\ ('A', 'active', 'bool', 20, False),\ ('Seeds', 'seeds', 'int', 75, False),\ ('Leeches', 'leeches', 'int', 75, False),\ ('Downloads', 'downloads', 'int', 75, False),\ ('Last Announce Result', 'lastAnnounceResult', 'native', 170, False),\ ('Last Announce Attempt', 'announceTryTime', 'fullTime', 170, False),\ ('Last Announce Success', 'announceSuccessTime', 'fullTime', 170, False),\ ('Last Scrape Attempt', 'scrapeTryTime', 'fullTime', 170, False),\ ('Last Scrape Success', 'scrapeSuccessTime', 'fullTime', 170, False),\ ('Announce Attempts', 'announceTryCount', 'int', 170, False),\ ('Announce Successes', 'announceSuccessCount', 'int', 170, False),\ ('Scrape Attempts', 'scrapeTryCount', 'int', 170, False),\ ('Scrape Successes', 'scrapeSuccessCount', 'int', 170, False)] listboxId = wx.NewId() self.trackerUrlList = PersistentVirtualListCtrl(persister, 'TorrentModifyDialog-TrackerUrlList-', self._updateTrackerPerstData, version, cols, self._getTrackerUrlData, rowIdCol='Id', allowSort=False, defaultSortCol='Position', parent=urlPanel, id=listboxId) self.trackerUrlList.SetToolTipString('') urlPanelSizer.Add(self.trackerUrlList, (0,0), (7,2), wx.EXPAND) wx.EVT_LIST_ITEM_RIGHT_CLICK(self.trackerUrlList, listboxId, self.OnTrackerListRightClick) #combo + url box boxId = wx.NewId() self.trackerName = wx.ComboBox(urlPanel, boxId, size = wx.Size(155, -1),\ choices=sorted(self.knownTrackerMapper.iterkeys()) + ['other'], style=wx.CB_READONLY) self.trackerName.SetToolTipString('Either select one of the predefined trackers here or select "other" to enter a different tracker announce url in the text box to the right') urlPanelSizer.Add(self.trackerName, (7,0), (1,1), wx.TOP, border = 4) wx.EVT_COMBOBOX(self, boxId, self.OnTrackerNameSelect) self.trackerAnnounceUrl = wx.TextCtrl(urlPanel, -1, "") self.trackerAnnounceUrl.SetToolTipString('The full announce url of the tracker, including the "http://"-prefix.') self.trackerAnnounceUrl.Disable() urlPanelSizer.Add(self.trackerAnnounceUrl, (7,1), (1,1), wx.EXPAND | wx.FIXED_MINSIZE | wx.TOP, border = 4) #buttons buttonAdd = wx.Button(urlPanel, wx.ID_ADD, "") urlPanelSizer.Add(buttonAdd, (2,2), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonAdd, wx.ID_ADD, self.OnTrackerAdd) buttonMoveUp = wx.Button(urlPanel, wx.ID_UP, "") urlPanelSizer.Add(buttonMoveUp, (3,2), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonMoveUp, wx.ID_UP, self.OnTrackerMoveUp) buttonMoveDown = wx.Button(urlPanel, wx.ID_DOWN, "") urlPanelSizer.Add(buttonMoveDown, (4,2), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonMoveDown, wx.ID_DOWN, self.OnTrackerMoveDown) buttonId = wx.NewId() buttonRemove = wx.Button(urlPanel, wx.ID_DELETE, "") urlPanelSizer.Add(buttonRemove, (5,2), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonRemove, wx.ID_DELETE, self.OnTrackerRemove) #sizer urlPanelSizer.AddGrowableCol(1, 1) urlPanelSizer.AddGrowableRow(1, 1) urlPanelSizer.AddGrowableRow(6, 1) urlPanel.SetSizer(urlPanelSizer) ##main sizer self.splitter.SplitVertically(groupPanel, urlPanel, 228) panelItems.Add(self.splitter, (0,0), (1,1), wx.EXPAND | wx.ALL, border = 2) panelItems.AddGrowableCol(0, 1) panelItems.AddGrowableRow(0, 1) self.SetSizer(panelItems) #fill lists self.trackerGroupList.dataUpdate() if len(self.trackerInfo) > 0: self.trackerGroupList.Select(0, on=1) self.trackerUrlList.dataUpdate() ##EVENTS self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelect, self.trackerGroupList)
class TrackerModifyPanel(wx.Panel): def __init__(self, parent, trackerInfo, persister, version, **kwargs): wx.Panel.__init__(self, parent, **kwargs) ##VARS self.trackerInfo = [{'groupId':tierIdx, 'groupPos':tierIdx+1, 'groupName':'Group '+str(tierIdx), 'groupTracker':tier} for tierIdx, tier in enumerate(trackerInfo)] if len(self.trackerInfo) == 0: self.selectedGroup = None self.nextGroupId = 0 self.nextTrackerId = 0 else: self.selectedGroup = 0 self.nextGroupId = max(tier['groupId'] for tier in self.trackerInfo) + 1 self.nextTrackerId = max(max(tracker['trackerId'] for tracker in tier['groupTracker']) for tier in self.trackerInfo) + 1 self.knownTrackerMapper = {u'crstrack.i2p':u'http://mm3zx3besctrx6peq5wzzueil237jdgscuvn5ugwilxrwzyuajja.b32.i2p/tracker/announce.php', u'tracker2.postman.i2p':u'http://lnQ6yoBTxQuQU8EQ1FlF395ITIQF-HGJxUeFvzETLFnoczNjQvKDbtSB7aHhn853zjVXrJBgwlB9sO57KakBDaJ50lUZgVPhjlI19TgJ-CxyHhHSCeKx5JzURdEW-ucdONMynr-b2zwhsx8VQCJwCEkARvt21YkOyQDaB9IdV8aTAmP~PUJQxRwceaTMn96FcVenwdXqleE16fI8CVFOV18jbJKrhTOYpTtcZKV4l1wNYBDwKgwPx5c0kcrRzFyw5~bjuAKO~GJ5dR7BQsL7AwBoQUS4k1lwoYrG1kOIBeDD3XF8BWb6K3GOOoyjc1umYKpur3G~FxBuqtHAsDRICkEbKUqJ9mPYQlTSujhNxiRIW-oLwMtvayCFci99oX8MvazPS7~97x0Gsm-onEK1Td9nBdmq30OqDxpRtXBimbzkLbR1IKObbg9HvrKs3L-kSyGwTUmHG9rSQSoZEvFMA-S0EXO~o4g21q1oikmxPMhkeVwQ22VHB0-LZJfmLr4SAAAA.i2p/announce.php', u'tracker.thepiratebay.i2p':u'http://tracker.thepiratebay.i2p/announce', u'tracker.welterde.i2p':u'http://tracker.welterde.i2p/announce'} ##GUI panelItems = wx.GridBagSizer(vgap = 0, hgap = 0) #splitter self.splitter = wx.SplitterWindow(self, style=wx.CLIP_CHILDREN) self.splitter.SetMinimumPaneSize(200) ##tracker groups groupPanel = wx.Panel(self.splitter) groupPanelSizer = wx.GridBagSizer(vgap = 0, hgap = 6) #group list #Syntax: NameOfColumn, NameOfStat, DataType, ColumnWidth cols = [('Id', 'groupId', 'int', 75, False),\ ('Pos', 'groupPos', 'int', 40, True),\ ('Group', 'groupName', 'native', 100, True)] listboxId = wx.NewId() self.trackerGroupList = PersistentVirtualListCtrl(persister, 'TorrentModifyDialog-TrackerGroupList-', self._updateGroupPerstData, version, cols, self._getTrackerGroupData, rowIdCol='Id', allowSort=False, defaultSortCol='Pos', parent=groupPanel, id=listboxId, size=wx.Size(140, -1)) self.trackerGroupList.SetToolTipString('') groupPanelSizer.Add(self.trackerGroupList, (0,1), (6,1), wx.EXPAND | wx.ALL, border = 0) #buttons buttonAdd = wx.Button(groupPanel, wx.ID_ADD, "") groupPanelSizer.Add(buttonAdd, (1,0), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonAdd, wx.ID_ADD, self.OnGroupAdd) buttonMoveUp = wx.Button(groupPanel, wx.ID_UP, "") groupPanelSizer.Add(buttonMoveUp, (2,0), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonMoveUp, wx.ID_UP, self.OnGroupMoveUp) buttonId = wx.NewId() buttonMoveDown = wx.Button(groupPanel, wx.ID_DOWN, "") groupPanelSizer.Add(buttonMoveDown, (3,0), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonMoveDown, wx.ID_DOWN, self.OnGroupMoveDown) buttonId = wx.NewId() buttonRemove = wx.Button(groupPanel, wx.ID_DELETE, "") groupPanelSizer.Add(buttonRemove, (4,0), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonRemove, wx.ID_DELETE, self.OnGroupRemove) #sizer groupPanelSizer.AddGrowableCol(1, 1) groupPanelSizer.AddGrowableRow(0, 1) groupPanelSizer.AddGrowableRow(5, 1) groupPanel.SetSizer(groupPanelSizer) ##tracker urls urlPanel = wx.Panel(self.splitter) urlPanelSizer = wx.GridBagSizer(vgap = 0, hgap = 6) #url list #Syntax: NameOfColumn, NameOfStat, DataType, ColumnWidth cols = [('Id', 'trackerId', 'int', 75, False),\ ('Position', 'tierPos', 'int', 75, True),\ ('Url', 'trackerUrl', 'native', 385, True),\ ('A', 'active', 'bool', 20, False),\ ('Seeds', 'seeds', 'int', 75, False),\ ('Leeches', 'leeches', 'int', 75, False),\ ('Downloads', 'downloads', 'int', 75, False),\ ('Last Announce Result', 'lastAnnounceResult', 'native', 170, False),\ ('Last Announce Attempt', 'announceTryTime', 'fullTime', 170, False),\ ('Last Announce Success', 'announceSuccessTime', 'fullTime', 170, False),\ ('Last Scrape Attempt', 'scrapeTryTime', 'fullTime', 170, False),\ ('Last Scrape Success', 'scrapeSuccessTime', 'fullTime', 170, False),\ ('Announce Attempts', 'announceTryCount', 'int', 170, False),\ ('Announce Successes', 'announceSuccessCount', 'int', 170, False),\ ('Scrape Attempts', 'scrapeTryCount', 'int', 170, False),\ ('Scrape Successes', 'scrapeSuccessCount', 'int', 170, False)] listboxId = wx.NewId() self.trackerUrlList = PersistentVirtualListCtrl(persister, 'TorrentModifyDialog-TrackerUrlList-', self._updateTrackerPerstData, version, cols, self._getTrackerUrlData, rowIdCol='Id', allowSort=False, defaultSortCol='Position', parent=urlPanel, id=listboxId) self.trackerUrlList.SetToolTipString('') urlPanelSizer.Add(self.trackerUrlList, (0,0), (7,2), wx.EXPAND) wx.EVT_LIST_ITEM_RIGHT_CLICK(self.trackerUrlList, listboxId, self.OnTrackerListRightClick) #combo + url box boxId = wx.NewId() self.trackerName = wx.ComboBox(urlPanel, boxId, size = wx.Size(155, -1),\ choices=sorted(self.knownTrackerMapper.iterkeys()) + ['other'], style=wx.CB_READONLY) self.trackerName.SetToolTipString('Either select one of the predefined trackers here or select "other" to enter a different tracker announce url in the text box to the right') urlPanelSizer.Add(self.trackerName, (7,0), (1,1), wx.TOP, border = 4) wx.EVT_COMBOBOX(self, boxId, self.OnTrackerNameSelect) self.trackerAnnounceUrl = wx.TextCtrl(urlPanel, -1, "") self.trackerAnnounceUrl.SetToolTipString('The full announce url of the tracker, including the "http://"-prefix.') self.trackerAnnounceUrl.Disable() urlPanelSizer.Add(self.trackerAnnounceUrl, (7,1), (1,1), wx.EXPAND | wx.FIXED_MINSIZE | wx.TOP, border = 4) #buttons buttonAdd = wx.Button(urlPanel, wx.ID_ADD, "") urlPanelSizer.Add(buttonAdd, (2,2), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonAdd, wx.ID_ADD, self.OnTrackerAdd) buttonMoveUp = wx.Button(urlPanel, wx.ID_UP, "") urlPanelSizer.Add(buttonMoveUp, (3,2), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonMoveUp, wx.ID_UP, self.OnTrackerMoveUp) buttonMoveDown = wx.Button(urlPanel, wx.ID_DOWN, "") urlPanelSizer.Add(buttonMoveDown, (4,2), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonMoveDown, wx.ID_DOWN, self.OnTrackerMoveDown) buttonId = wx.NewId() buttonRemove = wx.Button(urlPanel, wx.ID_DELETE, "") urlPanelSizer.Add(buttonRemove, (5,2), (1,1), wx.EXPAND | wx.TOP | wx.BOTTOM, border=7) wx.EVT_BUTTON(buttonRemove, wx.ID_DELETE, self.OnTrackerRemove) #sizer urlPanelSizer.AddGrowableCol(1, 1) urlPanelSizer.AddGrowableRow(1, 1) urlPanelSizer.AddGrowableRow(6, 1) urlPanel.SetSizer(urlPanelSizer) ##main sizer self.splitter.SplitVertically(groupPanel, urlPanel, 228) panelItems.Add(self.splitter, (0,0), (1,1), wx.EXPAND | wx.ALL, border = 2) panelItems.AddGrowableCol(0, 1) panelItems.AddGrowableRow(0, 1) self.SetSizer(panelItems) #fill lists self.trackerGroupList.dataUpdate() if len(self.trackerInfo) > 0: self.trackerGroupList.Select(0, on=1) self.trackerUrlList.dataUpdate() ##EVENTS self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelect, self.trackerGroupList) ##internal functions - list persisting def _updateGroupPerstData(self, persColData, currentVersion): return persColData def _updateTrackerPerstData(self, persColData, currentVersion): return persColData ##internal functions - refresh def _getTrackerGroupData(self): for i in xrange(0, len(self.trackerInfo)): self.trackerInfo[i]['groupPos'] = i+1 return self.trackerInfo def _getTrackerUrlData(self): if self.selectedGroup is None: data = [] else: data = self.trackerInfo[self.selectedGroup]['groupTracker'] for i in xrange(0, len(data)): data[i]['tierPos'] = i+1 return data ##external functions - tracker info def getTrackerInfo(self): return [tier['groupTracker'] for tier in self.trackerInfo] ##external functions - events - other def OnSelect(self, event): newGroup = self.trackerGroupList.getRawData('Pos',self.trackerGroupList.GetFirstSelected()) - 1 if not self.selectedGroup == newGroup: self.selectedGroup = newGroup self.trackerUrlList.dataUpdate() def OnTrackerNameSelect(self, event): selectedTracker = self.trackerName.GetValue() if not selectedTracker == '': #something did get selected if selectedTracker in self.knownTrackerMapper: self.trackerAnnounceUrl.Disable() self.trackerAnnounceUrl.SetValue(self.knownTrackerMapper[selectedTracker]) elif selectedTracker == u'other': if not self.trackerAnnounceUrl.IsEnabled(): #currently disabled self.trackerAnnounceUrl.SetValue('http://') self.trackerAnnounceUrl.Enable() ## external functions - events - groups def OnGroupAdd(self, event): #determine position for insert groupIdx = self.selectedGroup if groupIdx is None: groupIdx = 0 else: groupIdx += 1 #insert new group self.trackerInfo.insert(groupIdx, {'groupId':self.nextGroupId, 'groupPos':groupIdx+1, 'groupName':'Group '+str(self.nextGroupId), 'groupTracker':[]}) self.nextGroupId += 1 #update list self.trackerGroupList.dataUpdate() #check if it should be selected if self.selectedGroup is None: self.selectedGroup = groupIdx self.trackerGroupList.Select(groupIdx, on=1) def OnGroupRemove(self, event): #remove all selected groups selectedGroups = self.trackerGroupList.getSelectedRows() selectedGroups.reverse() for groupIdx in selectedGroups: del self.trackerInfo[groupIdx] if groupIdx == self.selectedGroup: self.selectedGroup = None self.trackerGroupList.dataUpdate() self.trackerUrlList.dataUpdate() def OnGroupMoveUp(self, event): #move all selected groups one row up selectedGroups = self.trackerGroupList.getSelectedRows() for groupIdx in selectedGroups: if groupIdx > 0: self.trackerInfo.insert(groupIdx-1, self.trackerInfo.pop(groupIdx)) self.trackerGroupList.dataUpdate() def OnGroupMoveDown(self, event): #move all selected groups one row down selectedGroups = self.trackerGroupList.getSelectedRows() selectedGroups.reverse() for groupIdx in selectedGroups: if groupIdx < len(self.trackerInfo) - 1: self.trackerInfo.insert(groupIdx+1, self.trackerInfo.pop(groupIdx)) self.trackerGroupList.dataUpdate() ##external funcs - events - tracker def OnTrackerAdd(self, event): if self.selectedGroup is None: #no group selected showErrorMessage(self, 'You need to select a tracker group, before you can add a tracker!') else: #group selected, go on tier = self.trackerInfo[self.selectedGroup]['groupTracker'] trackerUrl = self.trackerAnnounceUrl.GetValue() if i2pHttpUrlRegexObj.match(trackerUrl) is None: #invalid url showErrorMessage(self, 'The url "%s" is not a valid i2p http url!', trackerUrl) else: #valid trackerPos = self.trackerUrlList.GetFirstSelected() if trackerPos == -1: trackerPos = 0 else: trackerPos += 1 tier.insert(trackerPos, {'tier':self.selectedGroup + 1, 'tierPos':trackerPos + 1, 'trackerUrl':trackerUrl, 'trackerId':self.nextTrackerId, 'active':False, 'announceTryCount':None, 'announceTryTime':None, 'announceSuccessCount':None, 'announceSuccessTime':None, 'lastAnnounceResult':'None', 'scrapeTryCount':None, 'scrapeTryTime':None, 'scrapeSuccessCount':None, 'scrapeSuccessTime':None, 'seeds':None, 'leeches':None, 'downloads':None}) self.nextTrackerId += 1 self.trackerUrlList.dataUpdate() def OnTrackerRemove(self, event): if self.selectedGroup is not None: tier = self.trackerInfo[self.selectedGroup]['groupTracker'] selectedTrackers = self.trackerUrlList.getSelectedRows() selectedTrackers.reverse() for trackerIdx in selectedTrackers: del tier[trackerIdx] self.trackerUrlList.dataUpdate() def OnTrackerMoveUp(self, event): if self.selectedGroup is not None: tier = self.trackerInfo[self.selectedGroup]['groupTracker'] selectedTrackers = self.trackerUrlList.getSelectedRows() for trackerIdx in selectedTrackers: if trackerIdx > 0: tier.insert(trackerIdx-1, tier.pop(trackerIdx)) self.trackerUrlList.dataUpdate() def OnTrackerMoveDown(self, event): if self.selectedGroup is not None: tier = self.trackerInfo[self.selectedGroup]['groupTracker'] selectedTrackers = self.trackerUrlList.getSelectedRows() selectedTrackers.reverse() for trackerIdx in selectedTrackers: if trackerIdx < len(tier) - 1: tier.insert(trackerIdx+1, tier.pop(trackerIdx)) self.trackerUrlList.dataUpdate() def OnTrackerChangeUrl(self): trackerIdx = self.trackerUrlList.GetFirstSelected() if trackerIdx == -1: #no tracker selected showErrorMessage(self, 'You need to select a tracker, before you can change its url!') else: #a tracker was selected tracker = self.trackerInfo[self.selectedGroup]['groupTracker'][trackerIdx] diag = wx.TextEntryDialog(self, message='Please enter the new url for this tracker:', caption='Enter url', defaultValue=tracker['trackerUrl']) if diag.ShowModal() == wx.ID_OK: #user did hit ok trackerUrl = diag.GetValue() if i2pHttpUrlRegexObj.match(trackerUrl) is None: #invalid url showErrorMessage(self, 'The url "%s" is not a valid i2p http url!', trackerUrl) else: #valid tracker['trackerUrl'] = trackerUrl self.trackerUrlList.dataUpdate() def OnTrackerMoveToGroup(self): trackerIdx = self.trackerUrlList.GetFirstSelected() if trackerIdx == -1: #no tracker selected showErrorMessage(self, 'You need to select a tracker, before you can move it to a different group!') else: #a tracker was selected diag = wx.SingleChoiceDialog(self, message='Please select the new group for this tracker:', caption='Select group', choices=[tier['groupName'] for tier in self.trackerInfo]) if diag.ShowModal() == wx.ID_OK: #user did hit ok newGroupIdx = diag.GetSelection() if not newGroupIdx == self.selectedGroup: #not the current one tracker = self.trackerInfo[self.selectedGroup]['groupTracker'][trackerIdx] del self.trackerInfo[self.selectedGroup]['groupTracker'][trackerIdx] self.trackerInfo[newGroupIdx]['groupTracker'].append(tracker) #move selection self.trackerGroupList.Select(self.selectedGroup, on=0) self.trackerGroupList.Select(newGroupIdx, on=1) def OnTrackerListRightClick(self, event): diag = TrackerListOptionsPopup(self) self.PopupMenu(diag)