예제 #1
0
    def __init__(self, parent=None):
        """"""
        gtk.VBox.__init__(self)
        
        self.__parent = parent

        scroll = gtk.ScrolledWindow()
        scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

        self.store = self.create_model() #crear columnas y
        self.update_flag = False #flag para que el update de la lista se haga solo si ya no esta corriendo. False = detenido. True = Corriendo.
        self.active_tab_flag = True
        #self.rows_buffer = {} #{id_item: row_obj, }
        
        #arma el cuadro con los items
        self.treeView = DnDTreeView(self.store)
        self.treeView.set_rules_hint(True) #turna el color de los items, creo.
        #self.treeView.set_reorderable(True) #change order by drag'n'drop.
        scroll.add(self.treeView)
        
        self.rows_buffer = self.treeView.rows_buffer #{id_item: row_obj, }
        
        #self.treeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        
        #Columns item names. Host = 3 columns in 1
        col_list = ["hidden_id_item", _("Status"), _("File Name"), _("Host"), _("Size"), _("Complete"), _("Progress"), _("Time"), _("Remain"), _("Speed"), _("Status Message")] #podria usar un frozenset, no se si lo soporta cython.
        self.create_columns(col_list)
        
        #status icons
        self.icons_dict = self.get_icons() #return dict {cons.status_running: icon, }
        
        #self.treeView.add_events(gtk.gdk.KEY_PRESS)
        self.treeView.connect("key_press_event", self.keyboard_event)
        
        #Context Menu (pop-up)
        open_folder_item = (gtk.MenuItem(), _("Open destination folder"), self.on_open_folder)
        copy_link_item = (gtk.MenuItem(), _("Copy link"), self.on_copy_link)
        password_item = (gtk.MenuItem(), _("Add password"), self.on_password)
        delete_item = (gtk.MenuItem(), _("Delete"), self.on_delete)
        
        clear_completed_item = (gtk.MenuItem(), _("Clear Completed"), self.on_clear_completed)
        start_all_item = (gtk.MenuItem(), _("Start all"), self.on_start_all)
        stop_all_item = (gtk.MenuItem(), _("Stop all"), self.on_stop_all)
        
        self.menu_items = (open_folder_item, copy_link_item, password_item, delete_item)
        menu_generic_items = (None, start_all_item, stop_all_item, clear_completed_item)
        self.ctx_menu = Menu(self.menu_items+menu_generic_items) #items selected
        self.treeView.connect("button-press-event", self.on_context_menu)

        self.pack_start(scroll)
예제 #2
0
    def __init__(self, parent=None):
        """"""
        gtk.VBox.__init__(self)

        self.__parent = parent

        scroll = gtk.ScrolledWindow()
        scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

        self.store = self.create_model()  #crear columnas y
        self.update_flag = False  #flag para que el update de la lista se haga solo si ya no esta corriendo. False = detenido. True = Corriendo.
        self.active_tab_flag = True
        #self.rows_buffer = {} #{id_item: row_obj, }

        #arma el cuadro con los items
        self.treeView = DnDTreeView(self.store)
        self.treeView.set_rules_hint(True)  #turna el color de los items, creo.
        #self.treeView.set_reorderable(True) #change order by drag'n'drop.
        scroll.add(self.treeView)

        self.rows_buffer = self.treeView.rows_buffer  #{id_item: row_obj, }

        #self.treeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

        #Columns item names. Host = 3 columns in 1
        col_list = [
            "hidden_id_item",
            _("Status"),
            _("File Name"),
            _("Host"),
            _("Size"),
            _("Complete"),
            _("Progress"),
            _("Time"),
            _("Remain"),
            _("Speed"),
            _("Status Message")
        ]  #podria usar un frozenset, no se si lo soporta cython.
        self.create_columns(col_list)

        #status icons
        self.icons_dict = self.get_icons(
        )  #return dict {cons.status_running: icon, }

        #self.treeView.add_events(gtk.gdk.KEY_PRESS)
        self.treeView.connect("key_press_event", self.keyboard_event)

        #Context Menu (pop-up)
        open_folder_item = (gtk.MenuItem(), _("Open destination folder"),
                            self.on_open_folder)
        copy_link_item = (gtk.MenuItem(), _("Copy link"), self.on_copy_link)
        password_item = (gtk.MenuItem(), _("Add password"), self.on_password)
        delete_item = (gtk.MenuItem(), _("Delete"), self.on_delete)

        clear_completed_item = (gtk.MenuItem(), _("Clear Completed"),
                                self.on_clear_completed)
        start_all_item = (gtk.MenuItem(), _("Start all"), self.on_start_all)
        stop_all_item = (gtk.MenuItem(), _("Stop all"), self.on_stop_all)

        self.menu_items = (open_folder_item, copy_link_item, password_item,
                           delete_item)
        menu_generic_items = (None, start_all_item, stop_all_item,
                              clear_completed_item)
        self.ctx_menu = Menu(self.menu_items +
                             menu_generic_items)  #items selected
        self.treeView.connect("button-press-event", self.on_context_menu)

        self.pack_start(scroll)
예제 #3
0
class List(gtk.VBox):  #DownloadsList
    """
    Lista de archivos descargando.
    """
    def __init__(self, parent=None):
        """"""
        gtk.VBox.__init__(self)

        self.__parent = parent

        scroll = gtk.ScrolledWindow()
        scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

        self.store = self.create_model()  #crear columnas y
        self.update_flag = False  #flag para que el update de la lista se haga solo si ya no esta corriendo. False = detenido. True = Corriendo.
        self.active_tab_flag = True
        #self.rows_buffer = {} #{id_item: row_obj, }

        #arma el cuadro con los items
        self.treeView = DnDTreeView(self.store)
        self.treeView.set_rules_hint(True)  #turna el color de los items, creo.
        #self.treeView.set_reorderable(True) #change order by drag'n'drop.
        scroll.add(self.treeView)

        self.rows_buffer = self.treeView.rows_buffer  #{id_item: row_obj, }

        #self.treeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

        #Columns item names. Host = 3 columns in 1
        col_list = [
            "hidden_id_item",
            _("Status"),
            _("File Name"),
            _("Host"),
            _("Size"),
            _("Complete"),
            _("Progress"),
            _("Time"),
            _("Remain"),
            _("Speed"),
            _("Status Message")
        ]  #podria usar un frozenset, no se si lo soporta cython.
        self.create_columns(col_list)

        #status icons
        self.icons_dict = self.get_icons(
        )  #return dict {cons.status_running: icon, }

        #self.treeView.add_events(gtk.gdk.KEY_PRESS)
        self.treeView.connect("key_press_event", self.keyboard_event)

        #Context Menu (pop-up)
        open_folder_item = (gtk.MenuItem(), _("Open destination folder"),
                            self.on_open_folder)
        copy_link_item = (gtk.MenuItem(), _("Copy link"), self.on_copy_link)
        password_item = (gtk.MenuItem(), _("Add password"), self.on_password)
        delete_item = (gtk.MenuItem(), _("Delete"), self.on_delete)

        clear_completed_item = (gtk.MenuItem(), _("Clear Completed"),
                                self.on_clear_completed)
        start_all_item = (gtk.MenuItem(), _("Start all"), self.on_start_all)
        stop_all_item = (gtk.MenuItem(), _("Stop all"), self.on_stop_all)

        self.menu_items = (open_folder_item, copy_link_item, password_item,
                           delete_item)
        menu_generic_items = (None, start_all_item, stop_all_item,
                              clear_completed_item)
        self.ctx_menu = Menu(self.menu_items +
                             menu_generic_items)  #items selected
        self.treeView.connect("button-press-event", self.on_context_menu)

        self.pack_start(scroll)

    def keyboard_event(self, widget, event):
        """"""
        if gtk.gdk.keyval_name(event.keyval) == "Delete":  #supr. key
            self.on_delete()

    def on_context_menu(self, widget, event):
        """
        TODO: Mandar todo lo q tiene q ver con context_menu a otro modulo.
        """
        if event.button == 3:  #right click
            selection = self.treeView.get_selection()
            model, rows = selection.get_selected_rows()
            if not rows or len(rows) == 1:
                try:
                    path, col, cellx, celly = self.treeView.get_path_at_pos(
                        int(event.x), int(event.y))
                except TypeError:  #none selected.
                    is_sensitive = False
                    selection.unselect_all()
                else:  #one selected.
                    is_sensitive = True
                    self.treeView.grab_focus()
                    selection.select_path(path)
            else:
                is_sensitive = True

            [
                item[WIDGET].set_sensitive(is_sensitive)
                for item in self.menu_items
            ]
            self.ctx_menu.popup(None, None, None, event.button, event.time)

            if len(rows) > 1:  #stop signal (so the rows remain selected)
                return True

    def on_open_folder(self, widget):
        """"""
        model, rows = self.treeView.get_selection().get_selected_rows()
        if rows:
            paths_list = []
            items_list = api.get_download_items(
                [model[row][0] for row in rows])
            for download_item in items_list:
                folder_path = download_item.path
                if folder_path not in paths_list:
                    #misc.open_folder_window(folder_path)
                    threading.Thread(group=None,
                                     target=misc.open_folder_window,
                                     name=None,
                                     args=(folder_path, )).start()
                    paths_list.append(folder_path)

    def on_copy_link(self, widget):
        """"""
        model, rows = self.treeView.get_selection().get_selected_rows()
        if rows:
            items_list = api.get_download_items(
                [model[row][0] for row in rows])
            links_list = [
                download_item.link for download_item in items_list
                if download_item.can_copy_link
            ]
            clipboard = gtk.Clipboard()
            clipboard.set_text('\n'.join(links_list))

    def on_password(self, widget):
        """"""
        model, rows = self.treeView.get_selection().get_selected_rows()
        if rows:
            entry = gtk.Entry()
            entry.add_events(gtk.gdk.KEY_RELEASE_MASK)
            entry.set_width_chars(25)  #entry width

            m = DlgGui(self.__parent,
                       None,
                       _("Password"),
                       None,
                       True,
                       append_widget=entry)

            pwd = entry.get_text().strip()

            if m.accepted and pwd:
                events.trigger_pwd(pwd)

    def on_delete(self, widget=None):
        """"""
        model, rows = self.treeView.get_selection().get_selected_rows()
        if rows:
            message = _(
                "Do you want to remove this download? (downloaded segments will be deleted)"
            )
            m = DlgGui(self.__parent, gtk.STOCK_DIALOG_WARNING,
                       _("Remove Files"), message, True, True)
            if m.accepted:
                id_items_list = []
                iters = []
                for row in rows:
                    iters.append(model[row].iter)
                    id_item = model[row][0]
                    id_items_list.append(id_item)
                    del self.rows_buffer[id_item]
                #id_items_list = [model[row][0] for row in rows]
                [model.remove(iter) for iter in iters]
                api.delete_download(id_items_list)

    def on_start_all(self, widget):
        """
        BUG: El boton start y stop no cambia.
        """
        iditem_list = self.treeView.get_id_item_list()
        api.start_all(iditem_list)
        stopped_icon = self.icons_dict[cons.STATUS_STOPPED]
        queue_icon = self.icons_dict[cons.STATUS_QUEUE]
        for row in self.rows_buffer.values():
            if row[1] == stopped_icon:
                row[1] = queue_icon
        self.get_status()  #iniciar update de lista.

    def on_stop_all(self, widget=None):
        """
        BUG: El boton start y stop no cambia.
        """
        api.stop_all()
        stopped_icon = self.icons_dict[cons.STATUS_STOPPED]
        queue_icon = self.icons_dict[cons.STATUS_QUEUE]
        for row in self.rows_buffer.values():
            if row[1] == queue_icon:
                row[1] = stopped_icon

    def on_clear_completed(self, widget):
        """"""
        model = self.treeView.get_model()
        finished_icon = self.icons_dict[cons.STATUS_FINISHED]
        iters = []
        for row in self.rows_buffer.values():
            if row[1] == finished_icon:
                iters.append(row.iter)
                del self.rows_buffer[row[0]]
                #todo: remove from complete_downloads
        [model.remove(iter) for iter in iters]

    def get_status(self):
        """
        DONE: Se llama a self.update_status cada vez q se agrega un archivo (incluso si ya esta corriendo). Hacer que no se llame si ya esta corriendo.
        DONE: Mejorar este metodo + downloadmanager.get_thread + downloadmanager.thread_manager.get_status.
        Gobject roba ciclos, no es un thread aparte (en teoria)
        """
        if not self.update_flag:  #si el flag = True, el update ya esta corriendo. Si es False entramos.
            self.update_flag = True
            gobject.timeout_add(
                1000, self.update_status)  #auto actualizar status cada 1 seg.
            logger.debug("list_update = True")

    def update_status(self):
        """"""
        downloads_list = api.get_status()
        for download_item in downloads_list:
            try:
                row = self.rows_buffer[download_item.id]
                #row[0] = download_item.id #this column is hidden and wont be modificated.
                row[1] = self.icons_dict[download_item.status]  #col 1
                row[2] = download_item.name  #col 2
                #row[3] = download_item.host #download_item.host #col 3
                row[4] = self.icons_dict[
                    cons.
                    DL_RESUME] if download_item.can_resume else None  #download_item.host #col 3
                row[5] = self.icons_dict[
                    cons.
                    DL_PREMIUM] if download_item.is_premium else None  #download_item.host #col 3
                row[6] = misc.size_format(
                    download_item.size) if download_item.size else None
                row[7] = misc.size_format(
                    download_item.size_complete
                ) if download_item.size_complete else None
                row[8] = download_item.progress
                row[9] = misc.time_format(
                    download_item.time) if download_item.time else None
                row[10] = misc.time_format(
                    download_item.time_remain
                ) if download_item.time_remain else None
                row[11] = misc.speed_format(
                    download_item.speed) if download_item.speed else None
                row[12] = download_item.status_msg if not download_item.fail_count else "{0} ({1} #{2})".format(
                    download_item.status_msg, _("Retry"),
                    download_item.fail_count)
            except KeyError as err:
                logger.debug(err)
        #if not self.download_manager.active_downloads + self.download_manager.queue_downloads + self.download_manager.stopped_downloads: #si ya no hay mas descargas activas o en cola detener este loop.
        #logger.debug("list_update = False")
        #self.update_flag = False #cuando update_flag = False, sabemos que ya no esta corriendo...
        #return False

        return True  #hace que se actualicen los valores mas de una vez (hasta el final).

    def create_model(self):
        """
        Crear columnas
        """
        store = gtk.ListStore(
            str, gtk.gdk.Pixbuf, str, gtk.gdk.Pixbuf, gtk.gdk.Pixbuf,
            gtk.gdk.Pixbuf, str, str, int, str, str, str, str
        )  #tipo de item de cada columana (nombre de link, host, tamanio, porcentaje, vel.)

        return store

    def store_items(self, item_list):
        """
        Agregar nuevos items a las columnas
        """
        #self.dnd_flag = False #no afectar metodo dragndrop
        for download_item in item_list:  #in self.download_manager.pending_downloads:
            self.get_status()  #iniciar update_list del gui

            size_file = misc.size_format(
                download_item.size) if download_item.size else None
            size_complete = misc.size_format(
                download_item.size_complete
            ) if download_item.size_complete else None
            time = misc.time_format(
                download_item.time) if download_item.time else None
            host_icon = self.get_host_icon(download_item.host)

            self.store.append(
                [
                    download_item.id, self.icons_dict[download_item.status],
                    download_item.name, host_icon, None, None, size_file,
                    size_complete, download_item.progress, time, None, None,
                    download_item.status_msg
                ]
            )  #store.append([act[0], act[1], act[2]], ) futura lista con tamanio de archivo, icono, etc

            self.rows_buffer[download_item.id] = self.store[
                -1]  #row just added

        #self.dnd_flag = True #volver a habilitar el metodo dragndrop

    def create_columns(self, col_list):
        """
        Crea las columnas de la lista
        TODO: Guardar el tamanio de la columna nombre en el config.ini al resizear.
        """
        id_col = 0
        for item in col_list:
            #id_col = col_list.index(item)
            if item not in (
                    _("Status"), _("Progress"),
                    _("Host")):  #si no es la barra de progreso ni el estado
                rendererText = gtk.CellRendererText(
                )  #pide el primer item que ira en la columna (text=0) o segundo, etc...
                rendererText.set_property("ellipsize",
                                          3)  #2= middle, 3 = right, 1 = left
                column = gtk.TreeViewColumn(item, rendererText, text=id_col)
                column.set_resizable(True)
                column.set_expand(True)
                column.set_min_width(1)
                if item == "hidden_id_item":  #no mostrar columna de id_item
                    column.set_visible(False)
                    column.set_resizable(False)
                elif item == _("File Name"):
                    rendererText.set_property("ellipsize", 2)
                    rendererText.set_fixed_size(150, -1)
                #elif item == _("Status Message"):
                #column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
                #column.set_min_width(110) #dont let expand like crazy...
            elif item == _("Status"):
                renderPixbuf = gtk.CellRendererPixbuf()
                column = gtk.TreeViewColumn(None, renderPixbuf)  #name = None
                column.add_attribute(renderPixbuf, 'pixbuf', id_col)
                column.set_expand(False)
                column.set_min_width(21)
            elif item == _("Host"):
                renderPixbuf = gtk.CellRendererPixbuf()
                renderPixbuf_2 = gtk.CellRendererPixbuf()
                renderPixbuf_3 = gtk.CellRendererPixbuf()
                column = gtk.TreeViewColumn(item)  #name = None
                column.pack_start(renderPixbuf, False)
                column.pack_start(renderPixbuf_2, False)
                column.pack_start(renderPixbuf_3, False)
                column.add_attribute(renderPixbuf, 'pixbuf', id_col)
                id_col += 1
                column.add_attribute(renderPixbuf_2, 'pixbuf', id_col)
                id_col += 1
                column.add_attribute(renderPixbuf_3, 'pixbuf', id_col)
                column.set_expand(True)
                column.set_min_width(1)
            else:  #barra de progreso.
                rendererProgress = gtk.CellRendererProgress()
                column = gtk.TreeViewColumn(item, rendererProgress)
                column.add_attribute(rendererProgress, 'value',
                                     id_col)  #aniadir variable a la barra.
                column.set_expand(True)
                column.set_min_width(1)
            #column.set_sort_column_id(id_col) #ordenar columna
            #column.set_spacing(25)
            self.treeView.append_column(column)
            id_col += 1

    def get_host_icon(self, host):
        """"""
        try:
            return self.icons_dict[host]
        except KeyError:
            try:
                self.icons_dict[host] = gtk.gdk.pixbuf_new_from_file_at_size(
                    os.path.join(cons.PLUGINS_PATH, host,
                                 "favicon.ico").decode(
                                     sys.getfilesystemencoding()), 16, 16)
            except Exception as err:
                logger.warning(err)
                self.icons_dict[host] = None
        return self.icons_dict[host]

    def get_icons(self):
        """"""
        #running = self.treeView.render_icon(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_MENU)
        running = media.get_pixbuf(media.START, media.SMALL)
        stopped = media.get_pixbuf(media.STOP, media.SMALL)
        queue = media.get_pixbuf(media.QUEUE, media.SMALL)
        finished = media.get_pixbuf(media.CHECK, media.SMALL)
        error = media.get_pixbuf(media.X_MARK, media.SMALL)

        resume = media.get_pixbuf(media.REFRESH, media.SMALL)
        premium = media.get_pixbuf(media.ACCOUNTS, media.SMALL)

        return {
            cons.STATUS_RUNNING: running,
            cons.STATUS_STOPPED: stopped,
            cons.STATUS_QUEUE: queue,
            cons.STATUS_FINISHED: finished,
            cons.STATUS_ERROR: error,
            cons.DL_RESUME: resume,
            cons.DL_PREMIUM: premium
        }
예제 #4
0
    def __init__(self):
        """"""
        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
        
        self.set_title(cons.APP_TITLE)
        self.set_size_request(MIN_WIDTH, MIN_HEIGHT)
        self.set_position(gtk.WIN_POS_CENTER)
        self.resize(600, 300)
        
        self.config = conf #config.py
        
        #app window position and size
        x, y, w, h = self.config.get_window_settings()
        if gtk.gdk.screen_width() <= w or gtk.gdk.screen_height() <= h:
            self.maximize()
        elif w >= MIN_WIDTH or h >= MIN_HEIGHT:
            self.resize(w, h)
        if x >= 0 and y >= 0:
            self.move(x, y)
        
        #widgets for tabs.
        self.downloads_list_gui = List(parent=self)
        self.downloads_list_gui.treeView.get_selection().connect("changed", self.on_selected)
        self.add_downloads_gui = AddDownloads(self.downloads_list_gui, parent=self)
        self.addons_gui = addons_gui.AddonsManager(self)
        self.preferences = Preferences(self.addons_gui.addons_list)
        self.log_gui = Log()

        self.vbox = gtk.VBox()
        self.add(self.vbox)

        #toolbar. button = ToolButton(icon, label), handler, sensitive.
        #add_download = gtk.ToolButton(gtk.ToolButton(gtk.STOCK_ADD), "Add Download"), self.add_links, True
        stop = (gtk.ToolButton(media.get_image(media.STOP, media.MEDIUM), None), _("Stop Download"), self.stop_download, False) #tuple
        start = (gtk.ToolButton(media.get_image(media.START, media.MEDIUM), None), _("Start Download"), self.start_download, False)
        accounts = (gtk.ToolButton(media.get_image(media.ACCOUNTS, media.MEDIUM), None), _("Accounts"), self.accounts_app, True)
        preferences = (gtk.MenuToolButton(media.get_image(media.PREFERENCES, media.MEDIUM), None), _("Preferences"), self.on_preferences, True)
        about = (gtk.ToolButton(media.get_image(media.ABOUT, media.MEDIUM), None), _("About"), self.about_dlg, True)
        self.stop = stop[WIDGET] #self.stop = gtk.ToolButton(gtk.ToolButton(gtk.STOCK_STOP), "Stop Download"). Para poder cambiar el set_sensitive
        self.start = start[WIDGET]
        self.Toolbar = Toolbar([start, stop, None, accounts, preferences, None, about]) #los botones se agregan al Toolbar en el orden de esta lista. None = separador
        self.vbox.pack_start(self.Toolbar, False)
        
        #menu
        config_preferences = (gtk.MenuItem(), _("Preferences"), self.on_preferences)
        config_about = (gtk.MenuItem(), _("About"), self.about_dlg)
        #addons-menu
        menu_items = [menu_item for menu_item in [addon.get_menu_item() for addon in self.addons_gui.addons_list] if menu_item is not None]
        menu_items.extend([None, config_preferences, config_about])
        menu = Menu(menu_items)
        preferences[WIDGET].set_menu(menu)
        
        #Sessions
        self.load_session()
        
        #tabs (notebooks)
        self.vbox2 = gtk.VBox()
        
        self.notebook = Notebook()
        self.notebook.set_tab_pos(gtk.POS_BOTTOM) #weird butg in gtk+ 2.24.10 on resizing to often (make the app crash).
        self.notebook.set_show_border(False)
        self.notebook.append_page(self.downloads_list_gui, gtk.Label(_("Downloads")))
        self.notebook.append_page(self.add_downloads_gui, gtk.Label(_("Add downloads")))
        [self.notebook.append_page(tab, gtk.Label(addon.name)) for tab, addon in [(addon.get_tab(), addon) for addon in self.addons_gui.addons_list] if tab is not None]
        self.notebook.append_page(self.log_gui, gtk.Label(_("Log")))
        self.notebook.connect("switch-page", self.on_tab_switch)
        
        self.vbox2.pack_start(self.notebook)
        self.vbox.pack_start(self.vbox2)
        
        #status bar
        self.status_bar = StatusBar(self.add_downloads_gui)
        #self.pack_start(self.status_bar, False, False, 0)
        self.vbox.pack_start(self.status_bar, False, False)
        
        #Quit Event
        events.connect(cons.EVENT_QUIT, self.on_close)
        
        #self.connect("destroy", self.on_close) #boton cerrar de la barra de arriba
        self.connect("delete-event", self.on_quit)
        
        self.show_all()
예제 #5
0
 def __init__(self, list_gui, parent=None):
     gtk.VBox.__init__(self)
     
     self.__parent = parent
     self.list_gui = list_gui
     
     self.update_flag = False
     self.active_tab_flag = True
     
     #Estructura:
     #-------------------vbox1_start---------------
     #-------------------hbox4[halign1-left + halign4-right]-----------------------
     #-------------------vbox1_end----------------
     
     #detallado:
     #-------------------vbox1_start---------------
     #-------------------hbox4_start---------------
     #-------------------halign1_start-------------
     #-------------------hbox1-----------------------(save to field + examine button, left aligned)
     #-------------------halign1_end--------------
     #-------------------halign4_start------------(add links button, etc, right aligned)
     #-------------------halign2_start-------------
     #-------------------hbox2-----------------------
     #-------------------halign2_end--------------
     #-------------------halign4_end--------------
     #-------------------hbox4_end----------------
     #-------------------vbox1_end----------------
     
     #containers-separators.
     #self.vbox no puede ser cambiado en gtk.Dialog. Crear variable vbox y luego meterla en self.vbox.
     vbox1 = gtk.VBox(False, 5) #gtk.VBox(homogeneous=False, spacing=0) homogeneous: mismo espacio cada hijo, spacing: espacio horizontal entre hijos.
     
     #vbox1_start
     #Check links field.
     #-------------------------------------------
     
     scroll = gtk.ScrolledWindow()
     scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
     scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
     
     self.store = gtk.ListStore(str, bool, str, str, str, str, str)#modelo de columnas. (4 columnas de strings y 1 booleana)
     
     #arma el cuadro con los items
     self.treeView = gtk.TreeView(self.store)
     self.treeView.set_rules_hint(True) #turna el color de los items, creo.
     scroll.add(self.treeView)
     
     #Columns item names.
     col_list = ["hidden_id_item", _("Add"), _("Status"), _("File Name"), _("Host"), _("Size"), _("Status Message")] #podria usar un frozenset, no se si lo soporta cython.
     self.create_columns(col_list)
     
     vbox1.pack_start(scroll)
     
     #Context Menu (pop-up)
     dl_selected_item = (gtk.MenuItem(), _("Download Selected"), self.on_accept)
     recheck_item = (gtk.MenuItem(), _("Re-check"), self.on_recheck)
     clear_item = (gtk.MenuItem(), _("Clear list"), self.on_clear_list)
     
     menu_items = (dl_selected_item, None, recheck_item, clear_item)
     self.ctx_menu = Menu(menu_items) #items selected
     self.treeView.connect("button-press-event", self.on_context_menu)
     
     #Select file field.
     #-------------------------------------------
     #containers-separators.
     hbox1 = gtk.HBox(False, 10) #file field and button examine.
     #gtk.HBox(homogeneous=False, spacing=0) homogeneous: mismo espacio cada hijo, spacing: espacio horizontal entre hijos.
     hbox2 = gtk.HBox(False, 10) #buttons cancel and accept.
     
     #hbox1
     #label_save_to = gtk.Label("Save to:")
     #hbox1.add(label_save_to)
     self.paths_liststore = gtk.ListStore(str)
     cb_entry = gtk.ComboBoxEntry(self.paths_liststore)
     self.entry = cb_entry.child
     self.entry.add_events(gtk.gdk.KEY_RELEASE_MASK)
     self.entry.set_width_chars(35) #entry width
     
     self.paths_list = conf.get_save_dl_paths()
     self.load_save_paths()
     
     if not self.paths_list:
         default_path = cons.DLFOLDER_PATH
     else:
         default_path = self.paths_list[-1]
     
     #.decode(sys.getfilesystemencoding())
     self.entry.set_text(default_path.decode("utf-8")) #default entry path. Cuando cree el ejecutable, se puede crear una ruta al directorio asi: sys.path.append(path)
     hbox1.add(cb_entry)
     
     button = gtk.Button(_("..."))
     button.set_size_request(80, 35)
     button.connect("clicked", self.save_folder)
     hbox1.add(button)
     
     halign1 = gtk.Alignment(0, 0, 0, 0) #horizontal container. left liagment. #vertical container (estara vacio). gtk.Alignment(xalign=0.0, yalign=0.0, xscale=0.0, yscale=0.0)
     #xalign: espacio libre a la izquierda del hijo. 0.0 = sin espacio arriba. 1.0 = todo el espacio arriba.
     #yalign: espacio libre vertical arriba del hijo. 0.0 = sin espacio arriba. 1.0 = todo el espacio arriba.
     halign1.add(hbox1)
     
     down_arrow_image = media.get_image(media.DOWN, media.MEDIUM)
     download_selected_button = gtk.Button()
     download_selected_button.add(down_arrow_image)
     #self.button2.set_size_request(180, 35)
     download_selected_button.connect("clicked", self.on_accept)
     
     add_image = media.get_image(media.ADD, media.MEDIUM)
     add_button = gtk.Button()
     add_button.add(add_image)
     #button.set_size_request(80, 35)
     add_button.connect("clicked", self.on_add_links)
     
     
     icon_down = media.get_image(media.ARROW_DOWN, media.SMALL)
     #icon_down = gtk.image_new_from_file(os.path.join(cons.APP_PATH, "media", "arrow_down9.png"))
     #drop_down_image = gtk.image_new_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_BUTTON)
     drop_down_button = PopupMenuButton(image=icon_down) #gtk.Button()
     drop_down_button.set_size_request(20, 35)
     
     import_item = (gtk.MenuItem(), _("Import Container"), self.on_import_container)
     recheck_item = (gtk.MenuItem(), _("Re-check"), self.on_recheck)
     clear_item = (gtk.MenuItem(), _("Clear list"), self.on_clear_list)
     
     menu_items = (import_item, None, recheck_item, clear_item)
     menu = Menu(menu_items) #items selected
     drop_down_button.set_menu(menu)
     
     #button5 = gtk.Button(_("Re-check"))
     #button5.set_size_request(80, 35)
     #button5.connect("clicked", self.on_recheck)
     
     halign4 = gtk.Alignment(1, 0, 0, 0) #horizontal container. right liagment.
     hbox2.add(download_selected_button)
     hbox2.add(add_button)
     hbox2.add(drop_down_button)
     halign4.add(hbox2)
     
     hbox4 = gtk.HBox(False, 0) #two aligment widgets
     hbox4.add(halign1)
     hbox4.add(halign4)
     
     vbox1.pack_start(hbox4, False, False) #pack_start(child, expand=True, fill=True, padding=0)
     
     #-------------------------------------------
     #vbox1_end
     
     #entry.get_text()
     #checking thread stuff.
     self.cancelled = False #si se cancelo el checkeo, terminar thread.
     #self.th = threading.Thread(group=None, target=self.checking_links, name=None).start() #ckeck links.
     
     self.pack_start(vbox1)
예제 #6
0
class AddDownloads(gtk.VBox):
    """"""
    def __init__(self, list_gui, parent=None):
        gtk.VBox.__init__(self)
        
        self.__parent = parent
        self.list_gui = list_gui
        
        self.update_flag = False
        self.active_tab_flag = True
        
        #Estructura:
        #-------------------vbox1_start---------------
        #-------------------hbox4[halign1-left + halign4-right]-----------------------
        #-------------------vbox1_end----------------
        
        #detallado:
        #-------------------vbox1_start---------------
        #-------------------hbox4_start---------------
        #-------------------halign1_start-------------
        #-------------------hbox1-----------------------(save to field + examine button, left aligned)
        #-------------------halign1_end--------------
        #-------------------halign4_start------------(add links button, etc, right aligned)
        #-------------------halign2_start-------------
        #-------------------hbox2-----------------------
        #-------------------halign2_end--------------
        #-------------------halign4_end--------------
        #-------------------hbox4_end----------------
        #-------------------vbox1_end----------------
        
        #containers-separators.
        #self.vbox no puede ser cambiado en gtk.Dialog. Crear variable vbox y luego meterla en self.vbox.
        vbox1 = gtk.VBox(False, 5) #gtk.VBox(homogeneous=False, spacing=0) homogeneous: mismo espacio cada hijo, spacing: espacio horizontal entre hijos.
        
        #vbox1_start
        #Check links field.
        #-------------------------------------------
        
        scroll = gtk.ScrolledWindow()
        scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        
        self.store = gtk.ListStore(str, bool, str, str, str, str, str)#modelo de columnas. (4 columnas de strings y 1 booleana)
        
        #arma el cuadro con los items
        self.treeView = gtk.TreeView(self.store)
        self.treeView.set_rules_hint(True) #turna el color de los items, creo.
        scroll.add(self.treeView)
        
        #Columns item names.
        col_list = ["hidden_id_item", _("Add"), _("Status"), _("File Name"), _("Host"), _("Size"), _("Status Message")] #podria usar un frozenset, no se si lo soporta cython.
        self.create_columns(col_list)
        
        vbox1.pack_start(scroll)
        
        #Context Menu (pop-up)
        dl_selected_item = (gtk.MenuItem(), _("Download Selected"), self.on_accept)
        recheck_item = (gtk.MenuItem(), _("Re-check"), self.on_recheck)
        clear_item = (gtk.MenuItem(), _("Clear list"), self.on_clear_list)
        
        menu_items = (dl_selected_item, None, recheck_item, clear_item)
        self.ctx_menu = Menu(menu_items) #items selected
        self.treeView.connect("button-press-event", self.on_context_menu)
        
        #Select file field.
        #-------------------------------------------
        #containers-separators.
        hbox1 = gtk.HBox(False, 10) #file field and button examine.
        #gtk.HBox(homogeneous=False, spacing=0) homogeneous: mismo espacio cada hijo, spacing: espacio horizontal entre hijos.
        hbox2 = gtk.HBox(False, 10) #buttons cancel and accept.
        
        #hbox1
        #label_save_to = gtk.Label("Save to:")
        #hbox1.add(label_save_to)
        self.paths_liststore = gtk.ListStore(str)
        cb_entry = gtk.ComboBoxEntry(self.paths_liststore)
        self.entry = cb_entry.child
        self.entry.add_events(gtk.gdk.KEY_RELEASE_MASK)
        self.entry.set_width_chars(35) #entry width
        
        self.paths_list = conf.get_save_dl_paths()
        self.load_save_paths()
        
        if not self.paths_list:
            default_path = cons.DLFOLDER_PATH
        else:
            default_path = self.paths_list[-1]
        
        #.decode(sys.getfilesystemencoding())
        self.entry.set_text(default_path.decode("utf-8")) #default entry path. Cuando cree el ejecutable, se puede crear una ruta al directorio asi: sys.path.append(path)
        hbox1.add(cb_entry)
        
        button = gtk.Button(_("..."))
        button.set_size_request(80, 35)
        button.connect("clicked", self.save_folder)
        hbox1.add(button)
        
        halign1 = gtk.Alignment(0, 0, 0, 0) #horizontal container. left liagment. #vertical container (estara vacio). gtk.Alignment(xalign=0.0, yalign=0.0, xscale=0.0, yscale=0.0)
        #xalign: espacio libre a la izquierda del hijo. 0.0 = sin espacio arriba. 1.0 = todo el espacio arriba.
        #yalign: espacio libre vertical arriba del hijo. 0.0 = sin espacio arriba. 1.0 = todo el espacio arriba.
        halign1.add(hbox1)
        
        down_arrow_image = media.get_image(media.DOWN, media.MEDIUM)
        download_selected_button = gtk.Button()
        download_selected_button.add(down_arrow_image)
        #self.button2.set_size_request(180, 35)
        download_selected_button.connect("clicked", self.on_accept)
        
        add_image = media.get_image(media.ADD, media.MEDIUM)
        add_button = gtk.Button()
        add_button.add(add_image)
        #button.set_size_request(80, 35)
        add_button.connect("clicked", self.on_add_links)
        
        
        icon_down = media.get_image(media.ARROW_DOWN, media.SMALL)
        #icon_down = gtk.image_new_from_file(os.path.join(cons.APP_PATH, "media", "arrow_down9.png"))
        #drop_down_image = gtk.image_new_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_BUTTON)
        drop_down_button = PopupMenuButton(image=icon_down) #gtk.Button()
        drop_down_button.set_size_request(20, 35)
        
        import_item = (gtk.MenuItem(), _("Import Container"), self.on_import_container)
        recheck_item = (gtk.MenuItem(), _("Re-check"), self.on_recheck)
        clear_item = (gtk.MenuItem(), _("Clear list"), self.on_clear_list)
        
        menu_items = (import_item, None, recheck_item, clear_item)
        menu = Menu(menu_items) #items selected
        drop_down_button.set_menu(menu)
        
        #button5 = gtk.Button(_("Re-check"))
        #button5.set_size_request(80, 35)
        #button5.connect("clicked", self.on_recheck)
        
        halign4 = gtk.Alignment(1, 0, 0, 0) #horizontal container. right liagment.
        hbox2.add(download_selected_button)
        hbox2.add(add_button)
        hbox2.add(drop_down_button)
        halign4.add(hbox2)
        
        hbox4 = gtk.HBox(False, 0) #two aligment widgets
        hbox4.add(halign1)
        hbox4.add(halign4)
        
        vbox1.pack_start(hbox4, False, False) #pack_start(child, expand=True, fill=True, padding=0)
        
        #-------------------------------------------
        #vbox1_end
        
        #entry.get_text()
        #checking thread stuff.
        self.cancelled = False #si se cancelo el checkeo, terminar thread.
        #self.th = threading.Thread(group=None, target=self.checking_links, name=None).start() #ckeck links.
        
        self.pack_start(vbox1)

    def create_columns(self, col_list):
        """"""
        for item in col_list:
            id_col = col_list.index(item)
            if item != _("Add"):
                rendererText = gtk.CellRendererText() #pide el primer item que ira en la columna (text=0) o segundo, etc...
                rendererText.set_property("ellipsize", 3) #2= middle, 3 = right, 1 = left
                column = gtk.TreeViewColumn(item, rendererText, text=id_col)
                column.set_sort_column_id(id_col) #ordenar columna
                column.set_resizable(True)
                column.set_expand(True)
                column.set_min_width(1)
                if item == "hidden_id_item": #no mostrar columna de id_item
                    column.set_visible(False)
                elif item == _("File Name"):
                    rendererText.set_property("ellipsize", 2)
            else: #selection box column.
                rendererToggle = gtk.CellRendererToggle()
                #rendererToggle.set_property('activatable', True)
                column = gtk.TreeViewColumn(None, rendererToggle) #name = None
                column.add_attribute(rendererToggle, 'active', id_col)
                column.set_min_width(21)
                rendererToggle.connect("toggled", self.on_toggled, id_col)
            self.treeView.append_column(column)
    
    def load_save_paths(self):
        """"""
        for path in self.paths_list:
            self.paths_liststore.prepend([path])
    
    def on_context_menu(self, widget, event):
        """"""
        if event.button == 3:
            #model, rows = self.treeView.get_selection().get_selected_rows()
            #if rows:
            self.ctx_menu.popup(None, None, None, event.button, event.time)
    
    def on_toggled(self, celltoggled, path, id_col): #id_col = numero de columna, path= numero de fila
        """"""
        model = self.treeView.get_model()
        if celltoggled.get_active(): #devuelve True, si el check estaba activado, sino false.
            model[path][id_col] = False
        else:
            model[path][id_col] = True
    
    def on_recheck(self, widget):
        """
        Recheck only non alive items.
        """
        api.recheck_items()
    
    def on_clear_list(self, widget):
        """"""
        self.store.clear() #clear all rows in the liststore
        api.clear_pending()
    
    def on_import_container(self, widget=None): #import_links (importar contenedor)
        """"""
        
        openfile = FileChooserDialog(title=_("Open File"), parent=self.__parent, action=gtk.FILE_CHOOSER_ACTION_OPEN,
                                                        buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        openfile.set_default_response(gtk.RESPONSE_OK)
        
        filter = gtk.FileFilter()
        filter.set_name("OCH Files")
        filter.add_pattern("*.och")
        openfile.add_filter(filter)
        
        response = openfile.run()
        if response == gtk.RESPONSE_OK:
            #.decode(sys.getfilesystemencoding())
            fileh = openfile.get_filename().decode("utf-8") if response == gtk.RESPONSE_OK else None #ruta + nombre de archivo seleccionado
            logger.info("File opened: {0}".format(openfile.get_filename().decode(sys.getfilesystemencoding())))

            if fileh:
                container = Container(fileh)
                container.extract_links()
                links_list = container.get_linklist()
                
                if links_list:
                    self.checking_links(links_list, copy_link=False)
                
                #SaveFiles(linklist, self.download_manager, self.list_gui) #instancia de clase. SaveFiles(lista, clase, clase)
        openfile.destroy()
    
    def on_add_links(self, widget):
        """
        DONE: luego de aniadir links, se deberia poder seguir aniadiendo. Y limpiar aniadidos
        """
        add_links_dlg = AddLinks(parent=self.__parent)
        links_list = add_links_dlg.links_list
        if links_list: #se agregaron items.
            self.checking_links(links_list)

    def checking_links(self, links_list, copy_link=True):
        """
        Agregar items a las columnas
        DONE: Agrergar posibilidad de recherckear items que no estan vivos.
        DONE: detener el update de la lista (desde el main_gui), cuando se cambia a otra pestania (senial switch-notebook)
        TODO: Agregar columna que muestre la url del enlace, none para los agregados desde un .och
        """
        for link in links_list:
            download_item = api.create_download_item(cons.UNKNOWN, 0, link, copy_link) #return download_item object
            self.store.append([download_item.id, True, cons.LINK_CHECKING, cons.UNKNOWN, None, None, None])
            #checking start.
            #threading.Thread(group=None, target=self.download_manager.plugin_link_checking, name=None, args=(download_item, )).start()
        api.start_checking()
        
        self.start_update()
    
    def start_update(self):
        """"""
        if not self.update_flag:
            self.update_flag = True
            gobject.timeout_add(1000, self.update_checking_status)

    def update_checking_status(self): #this method steals cycles, its not a new thread
        """"""
        #self.download_manager.clear_pending() #Erase pending_downloads list.
        items_list = api.get_checking_update()
        for download_item in items_list:
            #link_status, file_name, host, size = self.download_manager.plugin_link_checking(download_item)
            for row in self.store:
                if row[0] == download_item.id:
                    row[2] = download_item.link_status
                    row[3] = download_item.name
                    row[4] = download_item.host
                    row[5] = misc.size_format(download_item.size)
                    row[6] = download_item.link_status_msg
            #if not self.download_manager.pending_downloads:
                #return False
        return True #keep it updating,

    def save_folder(self, widget):
        """
        Cuadro de dialogo para elegir donde se quiere guardar lo descargado.
        """
        openfolder = FileChooserDialog(title=_("Open Folder"), parent=self.__parent, action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                                        buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
        openfolder.set_default_response(gtk.RESPONSE_OK)
        
        response = openfolder.run()
        
        if response == gtk.RESPONSE_OK:
            self.entry.set_text(openfolder.get_filename().decode("utf-8")) #.decode(sys.getfilesystemencoding())) #("utf-8"))
            
        openfolder.destroy()

    def on_accept(self, widget):
        """"""
        save_to_path = self.entry.get_text().decode("utf-8") #(sys.getfilesystemencoding())
        try:
            self.paths_list.remove(save_to_path)
        except ValueError:
            if len(self.paths_list) > 5:
                self.paths_list.pop(0)
        self.paths_list.append(save_to_path)
        self.paths_liststore.clear()
        self.load_save_paths()
        conf.set_save_dl_paths(self.paths_list)
        
        #remover items no seleccionados de pending_downloads.
        model = self.treeView.get_model()
        id_add_list = []
        iters = []
        for row in model: #desactivar los otros antes de activar este.
            if row[1] and row[2] != cons.LINK_DEAD and row[4] != cons.UNSUPPORTED: #id_col = 1, toggle. True (active) or False
                id_add_list.append(row[0])
                iters.append(row.iter) #row.iter returns a treeiter
        [model.remove(iter) for iter in iters]
        
        item_list = api.get_added_items(id_add_list)
        
        api.downloader_init(item_list, save_to_path) #iniciar threads de descarga.
        self.list_gui.store_items(item_list) #agregar links a la lista GUI
예제 #7
0
class List(gtk.VBox): #DownloadsList
    """
    Lista de archivos descargando.
    """
    def __init__(self, parent=None):
        """"""
        gtk.VBox.__init__(self)
        
        self.__parent = parent

        scroll = gtk.ScrolledWindow()
        scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

        self.store = self.create_model() #crear columnas y
        self.update_flag = False #flag para que el update de la lista se haga solo si ya no esta corriendo. False = detenido. True = Corriendo.
        self.active_tab_flag = True
        #self.rows_buffer = {} #{id_item: row_obj, }
        
        #arma el cuadro con los items
        self.treeView = DnDTreeView(self.store)
        self.treeView.set_rules_hint(True) #turna el color de los items, creo.
        #self.treeView.set_reorderable(True) #change order by drag'n'drop.
        scroll.add(self.treeView)
        
        self.rows_buffer = self.treeView.rows_buffer #{id_item: row_obj, }
        
        #self.treeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        
        #Columns item names. Host = 3 columns in 1
        col_list = ["hidden_id_item", _("Status"), _("File Name"), _("Host"), _("Size"), _("Complete"), _("Progress"), _("Time"), _("Remain"), _("Speed"), _("Status Message")] #podria usar un frozenset, no se si lo soporta cython.
        self.create_columns(col_list)
        
        #status icons
        self.icons_dict = self.get_icons() #return dict {cons.status_running: icon, }
        
        #self.treeView.add_events(gtk.gdk.KEY_PRESS)
        self.treeView.connect("key_press_event", self.keyboard_event)
        
        #Context Menu (pop-up)
        open_folder_item = (gtk.MenuItem(), _("Open destination folder"), self.on_open_folder)
        copy_link_item = (gtk.MenuItem(), _("Copy link"), self.on_copy_link)
        password_item = (gtk.MenuItem(), _("Add password"), self.on_password)
        delete_item = (gtk.MenuItem(), _("Delete"), self.on_delete)
        
        clear_completed_item = (gtk.MenuItem(), _("Clear Completed"), self.on_clear_completed)
        start_all_item = (gtk.MenuItem(), _("Start all"), self.on_start_all)
        stop_all_item = (gtk.MenuItem(), _("Stop all"), self.on_stop_all)
        
        self.menu_items = (open_folder_item, copy_link_item, password_item, delete_item)
        menu_generic_items = (None, start_all_item, stop_all_item, clear_completed_item)
        self.ctx_menu = Menu(self.menu_items+menu_generic_items) #items selected
        self.treeView.connect("button-press-event", self.on_context_menu)

        self.pack_start(scroll)
 
    def keyboard_event(self, widget, event):
        """"""
        if gtk.gdk.keyval_name(event.keyval) == "Delete": #supr. key
            self.on_delete()
    
    def on_context_menu(self, widget, event):
        """
        TODO: Mandar todo lo q tiene q ver con context_menu a otro modulo.
        """
        if event.button == 3: #right click
            selection = self.treeView.get_selection()
            model, rows = selection.get_selected_rows()
            if not rows or len(rows) == 1:
                try:
                    path, col, cellx, celly = self.treeView.get_path_at_pos(int(event.x), int(event.y))
                except TypeError: #none selected.
                        is_sensitive = False
                        selection.unselect_all()
                else: #one selected.
                    is_sensitive = True
                    self.treeView.grab_focus()
                    selection.select_path(path)
            else:
                is_sensitive = True
            
            [item[WIDGET].set_sensitive(is_sensitive) for item in self.menu_items]
            self.ctx_menu.popup(None, None, None, event.button, event.time)
            
            if len(rows) > 1: #stop signal (so the rows remain selected)
                return True

    def on_open_folder(self, widget):
        """"""
        model, rows = self.treeView.get_selection().get_selected_rows()
        if rows:
            paths_list = []
            items_list = api.get_download_items([model[row][0] for row in rows])
            for download_item in items_list:
                folder_path = download_item.path
                if folder_path not in paths_list:
                    #misc.open_folder_window(folder_path)
                    threading.Thread(group=None, target=misc.open_folder_window, name=None, args=(folder_path, )).start()
                    paths_list.append(folder_path)
    
    def on_copy_link(self, widget):
        """"""
        model, rows = self.treeView.get_selection().get_selected_rows()
        if rows:
            items_list = api.get_download_items([model[row][0] for row in rows])
            links_list = [download_item.link for download_item in items_list if download_item.can_copy_link]
            clipboard = gtk.Clipboard()
            clipboard.set_text('\n'.join(links_list))
    
    def on_password(self, widget):
        """"""
        model, rows = self.treeView.get_selection().get_selected_rows()
        if rows:
            entry = gtk.Entry()
            entry.add_events(gtk.gdk.KEY_RELEASE_MASK)
            entry.set_width_chars(25) #entry width
            
            m = DlgGui(self.__parent, None, _("Password"), None, True, append_widget=entry)
            
            pwd = entry.get_text().strip()
            
            if m.accepted and pwd:
                events.trigger_pwd(pwd)
    
    def on_delete(self, widget=None):
        """"""
        model, rows = self.treeView.get_selection().get_selected_rows()
        if rows:
            message = _("Do you want to remove this download? (downloaded segments will be deleted)")
            m = DlgGui(self.__parent, gtk.STOCK_DIALOG_WARNING, _("Remove Files"), message, True, True)
            if m.accepted:
                id_items_list = []
                iters = []
                for row in rows:
                    iters.append(model[row].iter)
                    id_item = model[row][0]
                    id_items_list.append(id_item)
                    del self.rows_buffer[id_item]
                #id_items_list = [model[row][0] for row in rows]
                [model.remove(iter) for iter in iters]
                api.delete_download(id_items_list)
    
    def on_start_all(self, widget):
        """
        BUG: El boton start y stop no cambia.
        """
        iditem_list = self.treeView.get_id_item_list()
        api.start_all(iditem_list)
        stopped_icon = self.icons_dict[cons.STATUS_STOPPED]
        queue_icon = self.icons_dict[cons.STATUS_QUEUE]
        for row in self.rows_buffer.values():
            if row[1] == stopped_icon:
                row[1] = queue_icon
        self.get_status() #iniciar update de lista.
    
    def on_stop_all(self, widget=None):
        """
        BUG: El boton start y stop no cambia.
        """
        api.stop_all()
        stopped_icon = self.icons_dict[cons.STATUS_STOPPED]
        queue_icon = self.icons_dict[cons.STATUS_QUEUE]
        for row in self.rows_buffer.values():
            if row[1] == queue_icon:
                row[1] = stopped_icon
    
    def on_clear_completed(self, widget):
        """"""
        model = self.treeView.get_model()
        finished_icon = self.icons_dict[cons.STATUS_FINISHED]
        iters = []
        for row in self.rows_buffer.values():
            if row[1] == finished_icon:
                iters.append(row.iter)
                del self.rows_buffer[row[0]]
                #todo: remove from complete_downloads
        [model.remove(iter) for iter in iters]

    def get_status(self):
        """
        DONE: Se llama a self.update_status cada vez q se agrega un archivo (incluso si ya esta corriendo). Hacer que no se llame si ya esta corriendo.
        DONE: Mejorar este metodo + downloadmanager.get_thread + downloadmanager.thread_manager.get_status.
        Gobject roba ciclos, no es un thread aparte (en teoria)
        """
        if not self.update_flag: #si el flag = True, el update ya esta corriendo. Si es False entramos.
            self.update_flag = True
            gobject.timeout_add(1000, self.update_status) #auto actualizar status cada 1 seg.
            logger.debug("list_update = True")
    
    def update_status(self):
        """"""
        downloads_list = api.get_status()
        for download_item in downloads_list:
            try:
                row = self.rows_buffer[download_item.id]
                #row[0] = download_item.id #this column is hidden and wont be modificated.
                row[1] = self.icons_dict[download_item.status] #col 1
                row[2] = download_item.name #col 2
                #row[3] = download_item.host #download_item.host #col 3
                row[4] = self.icons_dict[cons.DL_RESUME] if download_item.can_resume else None #download_item.host #col 3
                row[5] = self.icons_dict[cons.DL_PREMIUM] if download_item.is_premium else None #download_item.host #col 3
                row[6] = misc.size_format(download_item.size) if download_item.size else None
                row[7] = misc.size_format(download_item.size_complete) if download_item.size_complete else None
                row[8] = download_item.progress
                row[9] = misc.time_format(download_item.time) if download_item.time else None
                row[10] = misc.time_format(download_item.time_remain) if download_item.time_remain else None
                row[11] = misc.speed_format(download_item.speed) if download_item.speed else None
                row[12] = download_item.status_msg if not download_item.fail_count else "{0} ({1} #{2})".format(download_item.status_msg,_("Retry"), download_item.fail_count)
            except KeyError as err:
                logger.debug(err)
        #if not self.download_manager.active_downloads + self.download_manager.queue_downloads + self.download_manager.stopped_downloads: #si ya no hay mas descargas activas o en cola detener este loop.
            #logger.debug("list_update = False")
            #self.update_flag = False #cuando update_flag = False, sabemos que ya no esta corriendo...
            #return False
        
        return True #hace que se actualicen los valores mas de una vez (hasta el final).

    def create_model(self):
        """
        Crear columnas
        """
        store = gtk.ListStore(str, gtk.gdk.Pixbuf, str, gtk.gdk.Pixbuf, gtk.gdk.Pixbuf, gtk.gdk.Pixbuf, str, str, int, str, str, str, str) #tipo de item de cada columana (nombre de link, host, tamanio, porcentaje, vel.)
        
        return store

    def store_items(self, item_list):
        """
        Agregar nuevos items a las columnas
        """
        #self.dnd_flag = False #no afectar metodo dragndrop
        for download_item in item_list: #in self.download_manager.pending_downloads:
            self.get_status() #iniciar update_list del gui
            
            size_file = misc.size_format(download_item.size) if download_item.size else None
            size_complete = misc.size_format(download_item.size_complete) if download_item.size_complete else None
            time = misc.time_format(download_item.time) if download_item.time else None
            host_icon = self.get_host_icon(download_item.host)
            
            self.store.append([download_item.id, self.icons_dict[download_item.status], download_item.name, host_icon, None, None, size_file, size_complete, download_item.progress, time, None, None, download_item.status_msg]) #store.append([act[0], act[1], act[2]], ) futura lista con tamanio de archivo, icono, etc
            
            self.rows_buffer[download_item.id] = self.store[-1] #row just added
            
        
        #self.dnd_flag = True #volver a habilitar el metodo dragndrop

    def create_columns(self, col_list):
        """
        Crea las columnas de la lista
        TODO: Guardar el tamanio de la columna nombre en el config.ini al resizear.
        """
        id_col = 0
        for item in col_list:
            #id_col = col_list.index(item)
            if item not in(_("Status"), _("Progress"), _("Host")): #si no es la barra de progreso ni el estado
                rendererText = gtk.CellRendererText() #pide el primer item que ira en la columna (text=0) o segundo, etc...
                rendererText.set_property("ellipsize", 3) #2= middle, 3 = right, 1 = left
                column = gtk.TreeViewColumn(item, rendererText, text=id_col)
                column.set_resizable(True)
                column.set_expand(True)
                column.set_min_width(1)
                if item == "hidden_id_item": #no mostrar columna de id_item
                    column.set_visible(False)
                    column.set_resizable(False)
                elif item == _("File Name"):
                    rendererText.set_property("ellipsize", 2)
                    rendererText.set_fixed_size(150, -1)
                #elif item == _("Status Message"):
                    #column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
                    #column.set_min_width(110) #dont let expand like crazy...
            elif item == _("Status"):
                renderPixbuf = gtk.CellRendererPixbuf()
                column = gtk.TreeViewColumn(None, renderPixbuf) #name = None
                column.add_attribute(renderPixbuf, 'pixbuf', id_col)
                column.set_expand(False)
                column.set_min_width(21)
            elif item == _("Host"):
                renderPixbuf = gtk.CellRendererPixbuf()
                renderPixbuf_2 = gtk.CellRendererPixbuf()
                renderPixbuf_3 = gtk.CellRendererPixbuf()
                column = gtk.TreeViewColumn(item) #name = None
                column.pack_start(renderPixbuf, False)
                column.pack_start(renderPixbuf_2, False)
                column.pack_start(renderPixbuf_3, False)
                column.add_attribute(renderPixbuf, 'pixbuf', id_col)
                id_col += 1
                column.add_attribute(renderPixbuf_2, 'pixbuf', id_col)
                id_col += 1
                column.add_attribute(renderPixbuf_3, 'pixbuf', id_col)
                column.set_expand(True)
                column.set_min_width(1)
            else: #barra de progreso.
                rendererProgress = gtk.CellRendererProgress()
                column = gtk.TreeViewColumn(item, rendererProgress)
                column.add_attribute(rendererProgress, 'value', id_col) #aniadir variable a la barra.
                column.set_expand(True)
                column.set_min_width(1)
            #column.set_sort_column_id(id_col) #ordenar columna
            #column.set_spacing(25)
            self.treeView.append_column(column)
            id_col += 1

    def get_host_icon(self, host):
        """"""
        try:
            return self.icons_dict[host]
        except KeyError:
            try:
                self.icons_dict[host] = gtk.gdk.pixbuf_new_from_file_at_size(os.path.join(cons.PLUGINS_PATH, host, "favicon.ico").decode(sys.getfilesystemencoding()), 16, 16)
            except Exception as err:
                logger.warning(err)
                self.icons_dict[host] = None
        return self.icons_dict[host]

    def get_icons(self):
        """"""
        #running = self.treeView.render_icon(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_MENU)
        running = media.get_pixbuf(media.START, media.SMALL)
        stopped = media.get_pixbuf(media.STOP, media.SMALL)
        queue = media.get_pixbuf(media.QUEUE, media.SMALL)
        finished = media.get_pixbuf(media.CHECK, media.SMALL)
        error = media.get_pixbuf(media.X_MARK, media.SMALL)
        
        resume = media.get_pixbuf(media.REFRESH, media.SMALL)
        premium = media.get_pixbuf(media.ACCOUNTS, media.SMALL)
        
        return {cons.STATUS_RUNNING: running, cons.STATUS_STOPPED: stopped,
                cons.STATUS_QUEUE: queue, cons.STATUS_FINISHED: finished,
                cons.STATUS_ERROR: error, 
                cons.DL_RESUME: resume, cons.DL_PREMIUM: premium}
예제 #8
0
    def __init__(self, list_gui, parent=None):
        gtk.VBox.__init__(self)

        self.__parent = parent
        self.list_gui = list_gui

        self.update_flag = False
        self.active_tab_flag = True

        #Estructura:
        #-------------------vbox1_start---------------
        #-------------------hbox4[halign1-left + halign4-right]-----------------------
        #-------------------vbox1_end----------------

        #detallado:
        #-------------------vbox1_start---------------
        #-------------------hbox4_start---------------
        #-------------------halign1_start-------------
        #-------------------hbox1-----------------------(save to field + examine button, left aligned)
        #-------------------halign1_end--------------
        #-------------------halign4_start------------(add links button, etc, right aligned)
        #-------------------halign2_start-------------
        #-------------------hbox2-----------------------
        #-------------------halign2_end--------------
        #-------------------halign4_end--------------
        #-------------------hbox4_end----------------
        #-------------------vbox1_end----------------

        #containers-separators.
        #self.vbox no puede ser cambiado en gtk.Dialog. Crear variable vbox y luego meterla en self.vbox.
        vbox1 = gtk.VBox(
            False, 5
        )  #gtk.VBox(homogeneous=False, spacing=0) homogeneous: mismo espacio cada hijo, spacing: espacio horizontal entre hijos.

        #vbox1_start
        #Check links field.
        #-------------------------------------------

        scroll = gtk.ScrolledWindow()
        scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

        self.store = gtk.ListStore(
            str, bool, str, str, str, str,
            str)  #modelo de columnas. (4 columnas de strings y 1 booleana)

        #arma el cuadro con los items
        self.treeView = gtk.TreeView(self.store)
        self.treeView.set_rules_hint(True)  #turna el color de los items, creo.
        scroll.add(self.treeView)

        #Columns item names.
        col_list = [
            "hidden_id_item",
            _("Add"),
            _("Status"),
            _("File Name"),
            _("Host"),
            _("Size"),
            _("Status Message")
        ]  #podria usar un frozenset, no se si lo soporta cython.
        self.create_columns(col_list)

        vbox1.pack_start(scroll)

        #Context Menu (pop-up)
        dl_selected_item = (gtk.MenuItem(), _("Download Selected"),
                            self.on_accept)
        recheck_item = (gtk.MenuItem(), _("Re-check"), self.on_recheck)
        clear_item = (gtk.MenuItem(), _("Clear list"), self.on_clear_list)

        menu_items = (dl_selected_item, None, recheck_item, clear_item)
        self.ctx_menu = Menu(menu_items)  #items selected
        self.treeView.connect("button-press-event", self.on_context_menu)

        #Select file field.
        #-------------------------------------------
        #containers-separators.
        hbox1 = gtk.HBox(False, 10)  #file field and button examine.
        #gtk.HBox(homogeneous=False, spacing=0) homogeneous: mismo espacio cada hijo, spacing: espacio horizontal entre hijos.
        hbox2 = gtk.HBox(False, 10)  #buttons cancel and accept.

        #hbox1
        #label_save_to = gtk.Label("Save to:")
        #hbox1.add(label_save_to)
        self.paths_liststore = gtk.ListStore(str)
        cb_entry = gtk.ComboBoxEntry(self.paths_liststore)
        self.entry = cb_entry.child
        self.entry.add_events(gtk.gdk.KEY_RELEASE_MASK)
        self.entry.set_width_chars(35)  #entry width

        self.paths_list = conf.get_save_dl_paths()
        self.load_save_paths()

        if not self.paths_list:
            default_path = cons.DLFOLDER_PATH
        else:
            default_path = self.paths_list[-1]

        #.decode(sys.getfilesystemencoding())
        self.entry.set_text(
            default_path.decode("utf-8")
        )  #default entry path. Cuando cree el ejecutable, se puede crear una ruta al directorio asi: sys.path.append(path)
        hbox1.add(cb_entry)

        button = gtk.Button(_("..."))
        button.set_size_request(80, 35)
        button.connect("clicked", self.save_folder)
        hbox1.add(button)

        halign1 = gtk.Alignment(
            0, 0, 0, 0
        )  #horizontal container. left liagment. #vertical container (estara vacio). gtk.Alignment(xalign=0.0, yalign=0.0, xscale=0.0, yscale=0.0)
        #xalign: espacio libre a la izquierda del hijo. 0.0 = sin espacio arriba. 1.0 = todo el espacio arriba.
        #yalign: espacio libre vertical arriba del hijo. 0.0 = sin espacio arriba. 1.0 = todo el espacio arriba.
        halign1.add(hbox1)

        down_arrow_image = media.get_image(media.DOWN, media.MEDIUM)
        download_selected_button = gtk.Button()
        download_selected_button.add(down_arrow_image)
        #self.button2.set_size_request(180, 35)
        download_selected_button.connect("clicked", self.on_accept)

        add_image = media.get_image(media.ADD, media.MEDIUM)
        add_button = gtk.Button()
        add_button.add(add_image)
        #button.set_size_request(80, 35)
        add_button.connect("clicked", self.on_add_links)

        icon_down = media.get_image(media.ARROW_DOWN, media.SMALL)
        #icon_down = gtk.image_new_from_file(os.path.join(cons.APP_PATH, "media", "arrow_down9.png"))
        #drop_down_image = gtk.image_new_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_BUTTON)
        drop_down_button = PopupMenuButton(image=icon_down)  #gtk.Button()
        drop_down_button.set_size_request(20, 35)

        import_item = (gtk.MenuItem(), _("Import Container"),
                       self.on_import_container)
        recheck_item = (gtk.MenuItem(), _("Re-check"), self.on_recheck)
        clear_item = (gtk.MenuItem(), _("Clear list"), self.on_clear_list)

        menu_items = (import_item, None, recheck_item, clear_item)
        menu = Menu(menu_items)  #items selected
        drop_down_button.set_menu(menu)

        #button5 = gtk.Button(_("Re-check"))
        #button5.set_size_request(80, 35)
        #button5.connect("clicked", self.on_recheck)

        halign4 = gtk.Alignment(1, 0, 0,
                                0)  #horizontal container. right liagment.
        hbox2.add(download_selected_button)
        hbox2.add(add_button)
        hbox2.add(drop_down_button)
        halign4.add(hbox2)

        hbox4 = gtk.HBox(False, 0)  #two aligment widgets
        hbox4.add(halign1)
        hbox4.add(halign4)

        vbox1.pack_start(
            hbox4, False,
            False)  #pack_start(child, expand=True, fill=True, padding=0)

        #-------------------------------------------
        #vbox1_end

        #entry.get_text()
        #checking thread stuff.
        self.cancelled = False  #si se cancelo el checkeo, terminar thread.
        #self.th = threading.Thread(group=None, target=self.checking_links, name=None).start() #ckeck links.

        self.pack_start(vbox1)
예제 #9
0
class AddDownloads(gtk.VBox):
    """"""
    def __init__(self, list_gui, parent=None):
        gtk.VBox.__init__(self)

        self.__parent = parent
        self.list_gui = list_gui

        self.update_flag = False
        self.active_tab_flag = True

        #Estructura:
        #-------------------vbox1_start---------------
        #-------------------hbox4[halign1-left + halign4-right]-----------------------
        #-------------------vbox1_end----------------

        #detallado:
        #-------------------vbox1_start---------------
        #-------------------hbox4_start---------------
        #-------------------halign1_start-------------
        #-------------------hbox1-----------------------(save to field + examine button, left aligned)
        #-------------------halign1_end--------------
        #-------------------halign4_start------------(add links button, etc, right aligned)
        #-------------------halign2_start-------------
        #-------------------hbox2-----------------------
        #-------------------halign2_end--------------
        #-------------------halign4_end--------------
        #-------------------hbox4_end----------------
        #-------------------vbox1_end----------------

        #containers-separators.
        #self.vbox no puede ser cambiado en gtk.Dialog. Crear variable vbox y luego meterla en self.vbox.
        vbox1 = gtk.VBox(
            False, 5
        )  #gtk.VBox(homogeneous=False, spacing=0) homogeneous: mismo espacio cada hijo, spacing: espacio horizontal entre hijos.

        #vbox1_start
        #Check links field.
        #-------------------------------------------

        scroll = gtk.ScrolledWindow()
        scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

        self.store = gtk.ListStore(
            str, bool, str, str, str, str,
            str)  #modelo de columnas. (4 columnas de strings y 1 booleana)

        #arma el cuadro con los items
        self.treeView = gtk.TreeView(self.store)
        self.treeView.set_rules_hint(True)  #turna el color de los items, creo.
        scroll.add(self.treeView)

        #Columns item names.
        col_list = [
            "hidden_id_item",
            _("Add"),
            _("Status"),
            _("File Name"),
            _("Host"),
            _("Size"),
            _("Status Message")
        ]  #podria usar un frozenset, no se si lo soporta cython.
        self.create_columns(col_list)

        vbox1.pack_start(scroll)

        #Context Menu (pop-up)
        dl_selected_item = (gtk.MenuItem(), _("Download Selected"),
                            self.on_accept)
        recheck_item = (gtk.MenuItem(), _("Re-check"), self.on_recheck)
        clear_item = (gtk.MenuItem(), _("Clear list"), self.on_clear_list)

        menu_items = (dl_selected_item, None, recheck_item, clear_item)
        self.ctx_menu = Menu(menu_items)  #items selected
        self.treeView.connect("button-press-event", self.on_context_menu)

        #Select file field.
        #-------------------------------------------
        #containers-separators.
        hbox1 = gtk.HBox(False, 10)  #file field and button examine.
        #gtk.HBox(homogeneous=False, spacing=0) homogeneous: mismo espacio cada hijo, spacing: espacio horizontal entre hijos.
        hbox2 = gtk.HBox(False, 10)  #buttons cancel and accept.

        #hbox1
        #label_save_to = gtk.Label("Save to:")
        #hbox1.add(label_save_to)
        self.paths_liststore = gtk.ListStore(str)
        cb_entry = gtk.ComboBoxEntry(self.paths_liststore)
        self.entry = cb_entry.child
        self.entry.add_events(gtk.gdk.KEY_RELEASE_MASK)
        self.entry.set_width_chars(35)  #entry width

        self.paths_list = conf.get_save_dl_paths()
        self.load_save_paths()

        if not self.paths_list:
            default_path = cons.DLFOLDER_PATH
        else:
            default_path = self.paths_list[-1]

        #.decode(sys.getfilesystemencoding())
        self.entry.set_text(
            default_path.decode("utf-8")
        )  #default entry path. Cuando cree el ejecutable, se puede crear una ruta al directorio asi: sys.path.append(path)
        hbox1.add(cb_entry)

        button = gtk.Button(_("..."))
        button.set_size_request(80, 35)
        button.connect("clicked", self.save_folder)
        hbox1.add(button)

        halign1 = gtk.Alignment(
            0, 0, 0, 0
        )  #horizontal container. left liagment. #vertical container (estara vacio). gtk.Alignment(xalign=0.0, yalign=0.0, xscale=0.0, yscale=0.0)
        #xalign: espacio libre a la izquierda del hijo. 0.0 = sin espacio arriba. 1.0 = todo el espacio arriba.
        #yalign: espacio libre vertical arriba del hijo. 0.0 = sin espacio arriba. 1.0 = todo el espacio arriba.
        halign1.add(hbox1)

        down_arrow_image = media.get_image(media.DOWN, media.MEDIUM)
        download_selected_button = gtk.Button()
        download_selected_button.add(down_arrow_image)
        #self.button2.set_size_request(180, 35)
        download_selected_button.connect("clicked", self.on_accept)

        add_image = media.get_image(media.ADD, media.MEDIUM)
        add_button = gtk.Button()
        add_button.add(add_image)
        #button.set_size_request(80, 35)
        add_button.connect("clicked", self.on_add_links)

        icon_down = media.get_image(media.ARROW_DOWN, media.SMALL)
        #icon_down = gtk.image_new_from_file(os.path.join(cons.APP_PATH, "media", "arrow_down9.png"))
        #drop_down_image = gtk.image_new_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_BUTTON)
        drop_down_button = PopupMenuButton(image=icon_down)  #gtk.Button()
        drop_down_button.set_size_request(20, 35)

        import_item = (gtk.MenuItem(), _("Import Container"),
                       self.on_import_container)
        recheck_item = (gtk.MenuItem(), _("Re-check"), self.on_recheck)
        clear_item = (gtk.MenuItem(), _("Clear list"), self.on_clear_list)

        menu_items = (import_item, None, recheck_item, clear_item)
        menu = Menu(menu_items)  #items selected
        drop_down_button.set_menu(menu)

        #button5 = gtk.Button(_("Re-check"))
        #button5.set_size_request(80, 35)
        #button5.connect("clicked", self.on_recheck)

        halign4 = gtk.Alignment(1, 0, 0,
                                0)  #horizontal container. right liagment.
        hbox2.add(download_selected_button)
        hbox2.add(add_button)
        hbox2.add(drop_down_button)
        halign4.add(hbox2)

        hbox4 = gtk.HBox(False, 0)  #two aligment widgets
        hbox4.add(halign1)
        hbox4.add(halign4)

        vbox1.pack_start(
            hbox4, False,
            False)  #pack_start(child, expand=True, fill=True, padding=0)

        #-------------------------------------------
        #vbox1_end

        #entry.get_text()
        #checking thread stuff.
        self.cancelled = False  #si se cancelo el checkeo, terminar thread.
        #self.th = threading.Thread(group=None, target=self.checking_links, name=None).start() #ckeck links.

        self.pack_start(vbox1)

    def create_columns(self, col_list):
        """"""
        for item in col_list:
            id_col = col_list.index(item)
            if item != _("Add"):
                rendererText = gtk.CellRendererText(
                )  #pide el primer item que ira en la columna (text=0) o segundo, etc...
                rendererText.set_property("ellipsize",
                                          3)  #2= middle, 3 = right, 1 = left
                column = gtk.TreeViewColumn(item, rendererText, text=id_col)
                column.set_sort_column_id(id_col)  #ordenar columna
                column.set_resizable(True)
                column.set_expand(True)
                column.set_min_width(1)
                if item == "hidden_id_item":  #no mostrar columna de id_item
                    column.set_visible(False)
                elif item == _("File Name"):
                    rendererText.set_property("ellipsize", 2)
            else:  #selection box column.
                rendererToggle = gtk.CellRendererToggle()
                #rendererToggle.set_property('activatable', True)
                column = gtk.TreeViewColumn(None, rendererToggle)  #name = None
                column.add_attribute(rendererToggle, 'active', id_col)
                column.set_min_width(21)
                rendererToggle.connect("toggled", self.on_toggled, id_col)
            self.treeView.append_column(column)

    def load_save_paths(self):
        """"""
        for path in self.paths_list:
            self.paths_liststore.prepend([path])

    def on_context_menu(self, widget, event):
        """"""
        if event.button == 3:
            #model, rows = self.treeView.get_selection().get_selected_rows()
            #if rows:
            self.ctx_menu.popup(None, None, None, event.button, event.time)

    def on_toggled(self, celltoggled, path,
                   id_col):  #id_col = numero de columna, path= numero de fila
        """"""
        model = self.treeView.get_model()
        if celltoggled.get_active(
        ):  #devuelve True, si el check estaba activado, sino false.
            model[path][id_col] = False
        else:
            model[path][id_col] = True

    def on_recheck(self, widget):
        """
        Recheck only non alive items.
        """
        api.recheck_items()

    def on_clear_list(self, widget):
        """"""
        self.store.clear()  #clear all rows in the liststore
        api.clear_pending()

    def on_import_container(self,
                            widget=None):  #import_links (importar contenedor)
        """"""

        openfile = FileChooserDialog(title=_("Open File"),
                                     parent=self.__parent,
                                     action=gtk.FILE_CHOOSER_ACTION_OPEN,
                                     buttons=(gtk.STOCK_CANCEL,
                                              gtk.RESPONSE_CANCEL,
                                              gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        openfile.set_default_response(gtk.RESPONSE_OK)

        filter = gtk.FileFilter()
        filter.set_name("OCH Files")
        filter.add_pattern("*.och")
        openfile.add_filter(filter)

        response = openfile.run()
        if response == gtk.RESPONSE_OK:
            #.decode(sys.getfilesystemencoding())
            fileh = openfile.get_filename().decode(
                "utf-8"
            ) if response == gtk.RESPONSE_OK else None  #ruta + nombre de archivo seleccionado
            logger.info("File opened: {0}".format(
                openfile.get_filename().decode(sys.getfilesystemencoding())))

            if fileh:
                container = Container(fileh)
                container.extract_links()
                links_list = container.get_linklist()

                if links_list:
                    self.checking_links(links_list, copy_link=False)

                #SaveFiles(linklist, self.download_manager, self.list_gui) #instancia de clase. SaveFiles(lista, clase, clase)
        openfile.destroy()

    def on_add_links(self, widget):
        """
        DONE: luego de aniadir links, se deberia poder seguir aniadiendo. Y limpiar aniadidos
        """
        add_links_dlg = AddLinks(parent=self.__parent)
        links_list = add_links_dlg.links_list
        if links_list:  #se agregaron items.
            self.checking_links(links_list)

    def checking_links(self, links_list, copy_link=True):
        """
        Agregar items a las columnas
        DONE: Agrergar posibilidad de recherckear items que no estan vivos.
        DONE: detener el update de la lista (desde el main_gui), cuando se cambia a otra pestania (senial switch-notebook)
        TODO: Agregar columna que muestre la url del enlace, none para los agregados desde un .och
        """
        for link in links_list:
            download_item = api.create_download_item(
                cons.UNKNOWN, 0, link, copy_link)  #return download_item object
            self.store.append([
                download_item.id, True, cons.LINK_CHECKING, cons.UNKNOWN, None,
                None, None
            ])
            #checking start.
            #threading.Thread(group=None, target=self.download_manager.plugin_link_checking, name=None, args=(download_item, )).start()
        api.start_checking()

        self.start_update()

    def start_update(self):
        """"""
        if not self.update_flag:
            self.update_flag = True
            gobject.timeout_add(1000, self.update_checking_status)

    def update_checking_status(
            self):  #this method steals cycles, its not a new thread
        """"""
        #self.download_manager.clear_pending() #Erase pending_downloads list.
        items_list = api.get_checking_update()
        for download_item in items_list:
            #link_status, file_name, host, size = self.download_manager.plugin_link_checking(download_item)
            for row in self.store:
                if row[0] == download_item.id:
                    row[2] = download_item.link_status
                    row[3] = download_item.name
                    row[4] = download_item.host
                    row[5] = misc.size_format(download_item.size)
                    row[6] = download_item.link_status_msg
            #if not self.download_manager.pending_downloads:
            #return False
        return True  #keep it updating,

    def save_folder(self, widget):
        """
        Cuadro de dialogo para elegir donde se quiere guardar lo descargado.
        """
        openfolder = FileChooserDialog(
            title=_("Open Folder"),
            parent=self.__parent,
            action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK,
                     gtk.RESPONSE_OK))
        openfolder.set_default_response(gtk.RESPONSE_OK)

        response = openfolder.run()

        if response == gtk.RESPONSE_OK:
            self.entry.set_text(openfolder.get_filename().decode(
                "utf-8"))  #.decode(sys.getfilesystemencoding())) #("utf-8"))

        openfolder.destroy()

    def on_accept(self, widget):
        """"""
        save_to_path = self.entry.get_text().decode(
            "utf-8")  #(sys.getfilesystemencoding())
        try:
            self.paths_list.remove(save_to_path)
        except ValueError:
            if len(self.paths_list) > 5:
                self.paths_list.pop(0)
        self.paths_list.append(save_to_path)
        self.paths_liststore.clear()
        self.load_save_paths()
        conf.set_save_dl_paths(self.paths_list)

        #remover items no seleccionados de pending_downloads.
        model = self.treeView.get_model()
        id_add_list = []
        iters = []
        for row in model:  #desactivar los otros antes de activar este.
            if row[1] and row[2] != cons.LINK_DEAD and row[
                    4] != cons.UNSUPPORTED:  #id_col = 1, toggle. True (active) or False
                id_add_list.append(row[0])
                iters.append(row.iter)  #row.iter returns a treeiter
        [model.remove(iter) for iter in iters]

        item_list = api.get_added_items(id_add_list)

        api.downloader_init(item_list,
                            save_to_path)  #iniciar threads de descarga.
        self.list_gui.store_items(item_list)  #agregar links a la lista GUI