def addColumn(strkey, strtooltip):
            # strkey = key.replace("_", " ").capitalize()
            header = StaticText(self.panel, -1, strkey)
            _set_font(header, fontweight=wx.FONTWEIGHT_BOLD)
            self.gridSizer.Add(header)
            self.textdict[strkey] = StaticText(self.panel, -1, '')
            self.textdict[strkey].SetMinSize((200, -1))
            self.gridSizer.Add(self.textdict[strkey])

            if strtooltip:
                header.SetToolTipString(strtooltip)
                self.textdict[strkey].SetToolTipString(strtooltip)
Exemple #2
0
class NetworkPanel(HomePanel):
    def __init__(self, parent):
        HomePanel.__init__(self, parent, 'Network info', SEPARATOR_GREY,
                           (0, 1))

        self.torrentdb = parent.guiutility.utility.session.open_dbhandler(
            NTFY_TORRENTS)
        self.channelcastdb = parent.guiutility.utility.session.open_dbhandler(
            NTFY_CHANNELCAST)
        self.remotetorrenthandler = parent.guiutility.utility.session.lm.rtorrent_handler

        self.timer = None

        session = Session.get_instance()
        session.add_observer(self.OnNotify, NTFY_TORRENTS, [NTFY_INSERT])
        self.UpdateStats()

    def CreatePanel(self):
        panel = wx.Panel(self)
        panel.SetBackgroundColour(DEFAULT_BACKGROUND)
        vSizer = wx.BoxSizer(wx.VERTICAL)

        self.nrTorrents = StaticText(panel)
        self.nrFiles = StaticText(panel)
        self.totalSize = StaticText(panel)
        self.queueSize = StaticText(panel)
        self.queueSize.SetToolTipString('Number of torrents queued per prio')
        self.queueSuccess = StaticText(panel)
        self.queueBW = StaticText(panel)
        self.queueBW.SetToolTipString(
            'Bandwidth spent on collecting .torrents')
        self.nrChannels = StaticText(panel)

        self.freeMem = None
        try:
            if wx.GetFreeMemory() != -1:
                self.freeMem = StaticText(panel)
        except:
            pass

        gridSizer = wx.FlexGridSizer(0, 2, 3, 10)
        gridSizer.AddGrowableCol(1)

        gridSizer.Add(StaticText(panel, -1, 'Number files'))
        gridSizer.Add(self.nrFiles, 0, wx.EXPAND)
        gridSizer.Add(StaticText(panel, -1, 'Total size'))
        gridSizer.Add(self.totalSize, 0, wx.EXPAND)
        gridSizer.Add(StaticText(panel, -1, 'Torrents collected'))
        gridSizer.Add(self.nrTorrents, 0, wx.EXPAND)
        gridSizer.Add(StaticText(panel, -1, 'Torrents in queue'))
        gridSizer.Add(self.queueSize, 0, wx.EXPAND)
        gridSizer.Add(StaticText(panel, -1, 'Torrent queue success'))
        gridSizer.Add(self.queueSuccess, 0, wx.EXPAND)
        gridSizer.Add(StaticText(panel, -1, 'Torrent queue bw'))
        gridSizer.Add(self.queueBW, 0, wx.EXPAND)
        gridSizer.Add(StaticText(panel, -1, 'Channels found'))
        gridSizer.Add(self.nrChannels, 0, wx.EXPAND)
        if self.freeMem:
            gridSizer.Add(StaticText(panel, -1, 'WX:Free memory'))
            gridSizer.Add(self.freeMem, 0, wx.EXPAND)

        vSizer.Add(gridSizer, 0, wx.EXPAND | wx.LEFT, 7)
        panel.SetSizer(vSizer)
        return panel

    def OnNotify(self, subject, type, infohash):
        try:
            if self.IsShownOnScreen():
                self.UpdateStats()
        except wx.PyDeadObjectError:
            pass

    def UpdateStats(self):
        def db_callback():
            stats = self.torrentdb.getTorrentsStats()
            nr_channels = self.channelcastdb.getNrChannels()
            self._UpdateStats(stats, nr_channels)

        startWorker(None,
                    db_callback,
                    uId=u"NetworkPanel_UpdateStats",
                    priority=GUI_PRI_DISPERSY)

    @forceWxThread
    def _UpdateStats(self, stats, nr_channels):
        self.nrTorrents.SetLabel(str(stats[0]))
        if stats[1] is None:
            self.totalSize.SetLabel(str(stats[1]))
        else:
            self.totalSize.SetLabel(size_format(stats[1]))
        self.nrFiles.SetLabel(str(stats[2]))
        self.queueSize.SetLabel(self.remotetorrenthandler.getQueueSize())
        self.queueBW.SetLabel(self.remotetorrenthandler.getBandwidthSpent())

        qsuccess = self.remotetorrenthandler.getQueueSuccess()
        qlabel = ", ".join(label for label, tooltip in qsuccess)
        qtooltip = ", ".join(tooltip for label, tooltip in qsuccess)
        self.queueSuccess.SetLabel(qlabel)
        self.queueSuccess.SetToolTipString(qtooltip)
        self.nrChannels.SetLabel(str(nr_channels))

        if self.freeMem:
            self.freeMem.SetLabel(size_format(wx.GetFreeMemory()))

        if self.timer:
            self.timer.Restart(10000)
        else:
            self.timer = wx.CallLater(10000, self.UpdateStats)
Exemple #3
0
class BundlePanel(wx.BoxSizer):

    COLLAPSED, PARTIAL, FULL = range(3)

    icons = None

    @classmethod
    def load_icons(cls):
        if not cls.icons:
            icons = cls.icons = {}
            guiUtility = GUIUtility.getInstance()
            utility = guiUtility.utility
            base_path = os.path.join(utility.getPath(), LIBRARYNAME, "Main",
                                     "vwxGUI", "images")

            icons['info'] = wx.Bitmap(os.path.join(base_path, "info.png"),
                                      wx.BITMAP_TYPE_ANY)

    def __init__(self,
                 parent,
                 parent_list,
                 hits,
                 general_description=None,
                 description=None,
                 font_increment=0):
        wx.BoxSizer.__init__(self, wx.HORIZONTAL)

        # preload icons
        self.load_icons()

        self.parent = parent
        self.parent_listitem = parent
        self.parent_list = parent_list

        listbody_width = parent_list.GetSize()[0]
        if listbody_width < BUNDLE_GRID_COLLAPSE:
            self.num_cols = 1
        else:
            self.num_cols = BUNDLE_NUM_COLS

        # logging
        self.guiutility = GUIUtility.getInstance()
        self.uelog = UserEventLogDBHandler.getInstance()

        self.state = BundlePanel.COLLAPSED
        self.nrhits = -1
        self.bundlelist = None

        self.font_increment = font_increment
        self.vsizer = wx.BoxSizer(wx.VERTICAL)

        self.SetBackgroundColour(DEFAULT_BACKGROUND)

        self.indent = 3 + 3 + self.parent_list.leftSpacer  # width of 3px left spacer + 3px right spacer

        self.AddHeader()
        self.AddGrid()

        self.SetHits(hits, noChange=True)
        self.UpdateHeader(general_description, description)

        self.AddSpacer((self.indent, -1))
        self.Add(self.vsizer, 1, wx.EXPAND | wx.BOTTOM, 7)

    def AddHeader(self):
        sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.header = StaticText(self.parent, -1, ' ')
        self.info_icon = wx.StaticBitmap(self.parent, -1, self.icons['info'])

        sizer.Add(self.header, 0, wx.RIGHT, 7)
        sizer.Add(self.info_icon, 0, wx.ALIGN_CENTER_VERTICAL)
        self.vsizer.Add(sizer, 0, wx.BOTTOM, 3)

    def UpdateHeader(self, general_description, description):
        self.SetGeneralDescription(general_description)
        self.SetDescription(description)

    def AddGrid(self):
        self.grid = wx.FlexGridSizer(0, self.num_cols, 3, 7)
        self.grid.SetFlexibleDirection(wx.HORIZONTAL)
        self.grid.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_NONE)
        self.grid.SetMinSize((1, -1))

        for i in xrange(BUNDLE_NUM_ROWS):
            self.grid.AddGrowableRow(i, 1)

        for j in xrange(self.num_cols):
            self.grid.AddGrowableCol(j, 1)
        self.vsizer.Add(self.grid, 1, wx.EXPAND | wx.LEFT | wx.RIGHT,
                        14 + self.indent)

    def RebuildGrid(self, new_cols):
        if self.num_cols != new_cols:
            self.num_cols = new_cols

            children = self.grid.GetChildren()
            children_controls = []
            for child in children:
                children_controls.append(child.GetWindow() or child.GetSizer())

            for child in children_controls:
                self.grid.Detach(child)

            self.vsizer.Detach(self.grid)
            self.grid.Destroy()

            self.grid = wx.FlexGridSizer(0, self.num_cols, 3, 7)
            for child in children_controls:
                self.grid.Add(child, 0, wx.EXPAND)

            for j in xrange(self.num_cols):
                self.grid.AddGrowableCol(j, 1)

            self.vsizer.Add(self.grid, 1, wx.EXPAND | wx.LEFT | wx.RIGHT,
                            14 + self.indent)

            self.Layout()
            self.parent_listitem.Layout()

            return True
        return False

    def UpdateGrid(self, hits, noChange=False):
        N = BUNDLE_NUM_ROWS * BUNDLE_NUM_COLS
        items_to_add = min(N, self.nrhits)
        if self.nrhits > N:
            items_to_add -= 1

        self.parent.Freeze()
        children = self.grid.GetChildren()
        didChange = len(children) < min(N, self.nrhits)
        if not didChange:
            if DEBUG:
                print >> sys.stderr, "*** BundlePanel.UpdateGrid: total nr items did not change, updating labels only"

            # total nr items did not change
            for i in range(items_to_add):
                link_static_text = children[i].GetWindow(
                ) or children[i].GetSizer()
                if link_static_text and getattr(link_static_text, 'SetLabel',
                                                False):
                    link_static_text.SetLabel(hits[i].name)
                    link_static_text.action = hits[i]
                else:
                    didChange = True
                    break

            if self.nrhits > N:
                more_caption = '(%s more...)' % (self.nrhits - N + 1)
                link_static_text = children[i + 1].GetWindow() or children[
                    i + 1].GetSizer()
                if link_static_text and getattr(link_static_text, 'SetLabel',
                                                False):
                    link_static_text.SetLabel(more_caption)
                    link_static_text.Unbind(wx.EVT_LEFT_UP)
                    link_static_text.Bind(wx.EVT_LEFT_UP, self.OnMoreClick)
                else:
                    didChange = True

        if didChange:
            if DEBUG:
                print >> sys.stderr, "*** BundlePanel.UpdateGrid: something did change rebuilding grid", len(
                    children), min(N, self.nrhits)

            curRows = len(children) / BUNDLE_NUM_COLS
            newRows = min(self.nrhits / BUNDLE_NUM_COLS, BUNDLE_NUM_ROWS)
            rowsChanged = curRows != newRows

            self.grid.ShowItems(False)
            self.grid.Clear(deleteWindows=True)
            for i in range(items_to_add):
                hit = hits[i]

                new_text = LinkStaticText(self.parent,
                                          hit.name,
                                          icon=False,
                                          icon_align=wx.ALIGN_LEFT,
                                          font_increment=self.font_increment,
                                          font_colour=BUNDLE_FONT_COLOR)
                new_text.Bind(wx.EVT_LEFT_UP, self.OnBundleLinkClick)
                new_text.SetMinSize((1, -1))
                new_text.action = hit
                self.grid.Add(new_text, 0, wx.EXPAND)

            if self.nrhits > N:
                caption = '(%s more...)' % (self.nrhits - N + 1)

                more_label = LinkStaticText(self.parent,
                                            caption,
                                            icon=False,
                                            icon_align=wx.ALIGN_LEFT,
                                            font_increment=self.font_increment,
                                            font_colour=BUNDLE_FONT_COLOR)
                more_label.Bind(wx.EVT_LEFT_UP, self.OnMoreClick)
                self.grid.Add(more_label, 0, wx.EXPAND)

            self.parent_listitem.AddEvents(self.grid)

            if self.state != self.COLLAPSED:
                self.ShowGrid(False)

            if rowsChanged and not noChange:
                self.parent_listitem.OnChange()

        self.parent.Thaw()

        return didChange

    def OnEventSize(self, width):
        if width < BUNDLE_GRID_COLLAPSE:
            return self.RebuildGrid(1)

        return self.RebuildGrid(BUNDLE_NUM_COLS)

    def ShowGrid(self, show):
        if show:
            self.grid.ShowItems(True)
        else:
            self.grid.ShowItems(False)

    def UpdateList(self, hits):
        self.hits = hits

        if self.bundlelist:
            self.bundlelist.SetData(hits)
            if self.state == BundlePanel.FULL:
                self.bundlelist.OnLoadAll()

    def ShowList(self, show):
        if self.bundlelist is None and show:
            max_list = BUNDLE_NUM_ROWS * BUNDLE_NUM_COLS
            if len(self.hits) != BUNDLE_NUM_ROWS * BUNDLE_NUM_COLS:
                max_list -= 1

            self.bundlelist = BundleListView(parent=self.parent,
                                             list_item_max=max_list)
            self.vsizer.Add(self.bundlelist, 0, wx.EXPAND | wx.BOTTOM,
                            self.indent - 7)  #a 7px spacer is already present

            # SetData does wx.Yield, which could cause a collapse event to be processed within the setdata
            # method. Thus we have to do this after the add to the sizer
            self.bundlelist.SetData(self.hits)

        elif self.bundlelist is not None and not show:
            self.vsizer.Detach(self.bundlelist)
            self.bundlelist.Show(False)
            self.bundlelist.Destroy()
            self.bundlelist = None

    def CollapseExpandedItem(self):
        if self.state != BundlePanel.COLLAPSED:
            self.bundlelist.list.OnCollapse()

    def RefreshDataBundleList(self, key, data):
        if self.bundlelist is not None:
            self.bundlelist.RefreshData(key, data)

    def SetDescription(self, description):
        self.header.SetToolTipString(description)
        self.info_icon.SetToolTipString(description)

    def SetGeneralDescription(self, general_description):
        if general_description:
            general_description = unicode(general_description)
        else:
            general_description = u'Similar'
        self.header.SetLabel(u'%s items (%s):' %
                             (general_description, self.nrhits))

    def SetHits(self, hits, noChange=False):
        self.nrhits = len(hits)

        gridChanged = self.UpdateGrid(hits, noChange)
        self.UpdateList(hits)

        self.Layout()
        return gridChanged

    def ChangeState(self, new_state, doLayout=True):
        if self.state != new_state:
            old_state = self.state
            self.state = new_state

            if new_state == BundlePanel.COLLAPSED:
                self.ShowList(False)
                self.ShowGrid(True)
            else:
                if new_state == BundlePanel.PARTIAL or new_state == BundlePanel.FULL:
                    self.ShowGrid(False)
                    if old_state == BundlePanel.COLLAPSED:
                        self.ShowList(True)

                    if new_state == BundlePanel.FULL and self.bundlelist:
                        self.bundlelist.OnLoadAll()

            if DEBUG:
                statestr = lambda st: ['COLLAPSED', 'PARTIAL', 'FULL'][st]
                print >> sys.stderr, '*** BundlePanel.ChangeState: %s --> %s' % (
                    statestr(old_state), statestr(new_state))

    def ExpandHit(self, hit):
        id = hit.infohash

        self.bundlelist.ExpandItem(id)
        self.parent_listitem.ShowSelected()

    def OnBundleLinkClick(self, event):
        # do expand
        # self.ExpandAndHideParent()

        staticText = event.GetEventObject()
        action = getattr(staticText, 'action', None)
        if action is not None:
            # Reason for non-persistence (for now) is least-surprise.
            # If the user collapses a bundled listitem, the previously
            # clicked item is still at the same location.
            if action in self.hits:
                self.hits.remove(action)
                self.hits.insert(0, action)

            # self.ChangeState(BundlePanel.PARTIAL)
            # self.ExpandHit(action)
            self.SetBackgroundColour(self.parent.GetBackgroundColour())
            from __init__ import TRIBLER_RED, LIST_HIGHTLIGHT
            event.GetEventObject().SetBackgroundColour(LIST_HIGHTLIGHT)
            for item in self.parent_listitem.bundle:
                if action.infohash == item.infohash:
                    td = TorrentDetails(
                        self.guiutility.frame.splitter_bottom_window, item)
                    item.expandedPanel = td
                    self.guiutility.SetBottomSplitterWindow(td)

        def db_callback():
            self.uelog.addEvent(
                message="Bundler GUI: BundleLink click; %s; %s;" %
                (self.nrhits, self.parent_listitem.general_description),
                type=3)

        self.guiutility.frame.guiserver.add_task(db_callback)

    def OnMoreClick(self, event):
        return
        # do expand
        self.ExpandAndHideParent()
        self.ChangeState(BundlePanel.FULL)

        def db_callback():
            self.uelog.addEvent(
                message="Bundler GUI: More click; %s; %s;" %
                (self.nrhits, self.parent_listitem.general_description),
                type=3)

        self.guiutility.frame.guiserver.add_task(db_callback)

    def ExpandAndHideParent(self):
        self.parent.Freeze()

        if not self.parent_listitem.expanded:
            # Make sure the listitem is marked as expanded
            self.parent_listitem.OnClick()

        # but hide the panel
        self.parent_listitem.ShowExpandedPanel(False)
        self.parent.Thaw()

    # Called from GUI to get expanded torrentdetails panel
    def GetExpandedPanel(self):
        if self.bundlelist:
            item = self.bundlelist.GetExpandedItem()
            if item:
                return item.GetExpandedPanel()

    def SetBackgroundColour(self, colour):
        self.parent.Freeze()
        if getattr(self, 'grid', False):
            for sizeritem in self.grid.GetChildren():
                child = sizeritem.GetWindow() or sizeritem.GetSizer()
                if child and getattr(child, 'SetBackgroundColour', False):
                    child.SetBackgroundColour(colour)

        self.parent.Thaw()