def test_sort():
    ls = [1, 7, 4, 6, 15, 0, 8, 2, 4]
    lv = ListView(ls, lambda x: (1 < x < 4) or (7 > x > 4) or (x > 10))
    assert list(lv) == [6, 15, 2]
    lv.sort()
    assert list(lv) == [2, 6, 15]
    assert ls == [1, 7, 4, 2, 6, 0, 8, 15, 4]
    def _update(self):
        """Update the contents of the BooklistView."""
        ListView._update(self)

        for (i, l) in itertools.izip_longest(self._items, self._labels):
            if (l is None):
                break

            if (i is None):
                l.grid_remove()
            else:
                if (i.image is None):
                    l.grid_remove()
                else:
                    l.config(image=i.image)
                    l.grid()
    def _update(self):
        """Update the contents of the BooklistView."""
        ListView._update(self)

        for (i, l) in itertools.izip_longest(self._items, self._labels):
            if(l is None):
                break

            if(i is None):
                l.grid_remove()
            else:
                if(i.image is None):
                    l.grid_remove()
                else:
                    l.config(image = i.image)
                    l.grid()
def test_getitem_slice():
    ls = [1, 2, 3, 4, 5, 6, 7]
    lv = ListView(ls, lambda x: (1 < x < 4) or (7 > x > 4) or (x > 10))
    # lv: [2, 3, 5, 6]

    assert lv[:] == [2, 3, 5, 6]
    assert lv[1:] == [3, 5, 6]
 def __init__(self):
     self.one_close = app_theme.get_pixbuf("treeview/1-close.png")
     self.one_open = app_theme.get_pixbuf("treeview/1-open.png")
     self.two_close = app_theme.get_pixbuf("treeview/2-close.png")
     self.two_open = app_theme.get_pixbuf("treeview/2-open.png")
     self.three_close = app_theme.get_pixbuf("treeview/3-close.png")
     self.three_open = app_theme.get_pixbuf("treeview/3-open.png")
     #
     self.tree_view_open = app_theme.get_pixbuf("treeview/open.png")
     self.tree_view_close = app_theme.get_pixbuf("treeview/close.png")
     self.tree_view_right = app_theme.get_pixbuf("treeview/right.png")
     self.tree_view_bottom = app_theme.get_pixbuf("treeview/bottom.png")
     #
     self.listview_color = ui_theme.get_color("scrolledbar")
     self.play_list_vbox = gtk.VBox()
     #
     self.list_view_vbox = gtk.VBox()
     self.list_scroll_win = ScrolledWindow(0, 0)
     self.list_scroll_win.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
     self.list_view = ListView()
     #
     self.play_list_con = PlayListControl()
     #
     self.list_view_vbox.pack_start(self.list_scroll_win, True, True)
     self.list_view_vbox.pack_start(self.play_list_con, False, False)
     # 网络列表,搜索框.
     self.tree_scroll_win = ScrolledWindow(0, 0)
     self.tree_scroll_win.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
     self.tree_view_vbox = gtk.VBox()
     self.tree_view = TreeViewBase()
     self.search_ali = gtk.Alignment(0, 0, 1, 1)
     self.search = Search()
     self.search_ali.add(self.search)
     #
     self.search_ali.set_padding(7, 5, 12, 12)
     self.tree_view_vbox.pack_start(self.search_ali, False, False)
     self.tree_view_vbox.pack_start(self.tree_scroll_win, True, True)
     self.search_ali.connect("expose-event", self.search_ali_expose_event)
     #
     self.note_book = NoteBook()
     #
     self.list_view.on_draw_sub_item = self.__listview_on_draw_sub_item
     self.list_view.columns.add_range(["filename", "time"])
     self.list_view.columns[0].width = 120
     self.list_view.columns[1].width = 95
     #
     self.note_book.hide_title()
     self.tree_view.paint_nodes_event = self.__treeview_paint_nodes_event
     #
     self.list_scroll_win.add_with_viewport(self.list_view)
     self.tree_scroll_win.add_with_viewport(self.tree_view)
     #self.note_book.add_layout1(self.list_scroll_win)
     self.note_book.add_layout1(self.list_view_vbox)
     self.note_book.add_layout2(self.tree_view_vbox)
     #self.play_list_vbox.pack_start(self.scroll_win, True, True)
     self.play_list_vbox.pack_start(self.note_book, True, True)
def test_getitem_int():
    ls = [1, 2, 3, 4, 5, 6, 7]
    lv = ListView(ls, lambda x: (1 < x < 4) or (7 > x > 4) or (x > 10))
    # lv: [2, 3, 5, 6]

    # normal
    assert lv[2] == 5
    # out of range
    with pytest.raises(IndexError):
        print(lv[7])
def test_delitem_slice():
    ls = [1, 2, 3, 4, 5, 6, 7]
    lv = ListView(ls, lambda x: (1 < x < 4) or (7 > x > 4) or (x > 10))
    # lv: [2, 3, 5, 6]

    del lv[1:]
    assert list(lv) == [2]
    assert ls == [1, 2, 4, 7]

    del lv[:]
    assert list(lv) == []
    assert ls == [1, 4, 7]
def test_delitem_int():
    ls = [1, 2, 3, 4, 5, 6, 7]
    lv = ListView(ls, lambda x: (1 < x < 4) or (7 > x > 4) or (x > 10))
    # lv: [2, 3, 5, 6]

    # normal
    del lv[2]
    assert list(lv) == [2, 3, 6]
    assert ls == [1, 2, 3, 4, 6, 7]

    # out of range
    with pytest.raises(IndexError):
        del lv[7]
Exemple #9
0
    def _update(self):
        """Update the contents of the PanelListView."""
        ListView._update(self)

        for (item, (magazine, blog, blogexists, lblImage), uid) in itertools.izip_longest(self._items, self._itemdatatuples, self._uids):
            if(lblImage is None):
                break
            
            if(item is None):
                self._canvas.itemconfig(uid, state = tki.HIDDEN)
            else:
                self._canvas.itemconfig(uid, state = tki.NORMAL)
                magazine.set(item.name + ' ' + item.issue)
                #blog.set(lang[lng.txtBlogpost] + ': ' + item.title)
                blog.set(item.title)
                blogexists.set(lang[lng.txtShowBlogpost])

                if(item.smallimage is not None):
                    lblImage.config(image = item.smallimage)
                    lblImage.grid()
                else:
                    lblImage.grid_remove()
Exemple #10
0
    def __init__(self, previewx, previewy, frame):
        """Creates an indexed frame and adds it to the scrollbox 

        Arguments
        previewx -- width of preview images
        previewy -- height of preview images
        frame -- the frame on which to layout the widgets

        """
        ListView.__init__(self, evItemSelected)

        width = frame['width']
        height = frame['height']

        self._eventgenerator = frame

        columncount = (width - _minspace) / (_minspace + previewx)
        rowcount = (height - _minspace) / (_minspace + previewy)
        self._itemcount = rowcount * columncount

        for i in range(rowcount):
            frame.rowconfigure(i, weight=1)

        for i in range(columncount):
            frame.columnconfigure(i, weight=1)

        self._labels = []

        for i in range(rowcount):
            for j in range(columncount):
                l = tki.Label(
                    frame
                )  #, image = image1)#, text = 'bild ' + str(j) + ', ' + str(i))
                #print('bild ' + str(j) + ', ' + str(i))
                self._labels.append(l)
                l.grid(row=i, column=j, padx=_minspace, pady=_minspace)
                l.index = (i * columncount) + j
                l.bind("<Button-1>", self._ehClick)
def test_insert():
    ls = [1, 2, 3, 4, 5, 6, 7]
    lv = ListView(ls, lambda x: (1 < x < 4) or (7 > x > 4))
    assert list(lv) == [2, 3, 5, 6]

    # unmatch value error
    with pytest.raises(ValueError):
        lv.insert(3, 999)
    assert ls == [1, 2, 3, 4, 5, 6, 7]
    assert list(lv) == [2, 3, 5, 6]

    # matched value error
    lv.insert(3, 5.5)
    assert ls == [1, 2, 3, 4, 5, 5.5, 6, 7]
    assert list(lv) == [2, 3, 5, 5.5, 6]

    lv.insert(0, 4.5)
    assert ls == [1, 4.5, 2, 3, 4, 5, 5.5, 6, 7]
    assert list(lv) == [4.5, 2, 3, 5, 5.5, 6]

    lv.insert(1000, 3.5)
    assert ls == [1, 4.5, 2, 3, 4, 5, 5.5, 6, 7, 3.5]
    assert list(lv) == [4.5, 2, 3, 5, 5.5, 6, 3.5]
Exemple #12
0
    def _update(self):
        """Update the contents of the PanelListView."""
        ListView._update(self)

        for (item, (magazine, blog, blogexists, lblImage),
             uid) in itertools.izip_longest(self._items, self._itemdatatuples,
                                            self._uids):
            if (lblImage is None):
                break

            if (item is None):
                self._canvas.itemconfig(uid, state=tki.HIDDEN)
            else:
                self._canvas.itemconfig(uid, state=tki.NORMAL)
                magazine.set(item.name + ' ' + item.issue)
                #blog.set(lang[lng.txtBlogpost] + ': ' + item.title)
                blog.set(item.title)
                blogexists.set(lang[lng.txtShowBlogpost])

                if (item.smallimage is not None):
                    lblImage.config(image=item.smallimage)
                    lblImage.grid()
                else:
                    lblImage.grid_remove()
Exemple #13
0
    def __init__(self, previewx, previewy, frame):
        """Creates an indexed frame and adds it to the scrollbox 

        Arguments
        previewx -- width of preview images
        previewy -- height of preview images
        frame -- the frame on which to layout the widgets

        """
        ListView.__init__(self, evItemSelected)
        
        width = frame['width']
        height = frame['height']
        
        self._eventgenerator = frame
        
        columncount = (width - _minspace) / (_minspace + previewx)
        rowcount = (height - _minspace) / (_minspace + previewy)
        self._itemcount = rowcount * columncount
        
        for i in range(rowcount):
            frame.rowconfigure(i, weight = 1)
            
        for i in range(columncount):
            frame.columnconfigure(i, weight = 1)
            
        self._labels = []
        
        for i in range(rowcount):
            for j in range(columncount):
                l = tki.Label(frame)#, image = image1)#, text = 'bild ' + str(j) + ', ' + str(i))
                #print('bild ' + str(j) + ', ' + str(i))
                self._labels.append(l)
                l.grid(row = i, column = j, padx = _minspace, pady = _minspace)
                l.index = (i * columncount) + j
                l.bind("<Button-1>", self._ehClick)
def test_setitem_int():
    ls = [1, 2, 3, 4, 5, 6, 7]
    lv = ListView(ls, lambda x: (1 < x < 4) or (7 > x > 4) or (x > 10))
    # lv: [2, 3, 5, 6]

    # normal
    lv[3] = 15
    assert list(lv) == [2, 3, 5, 15]
    assert ls == [1, 2, 3, 4, 5, 15, 7]

    # out of range
    with pytest.raises(IndexError):
        lv[4] = 100

    lv[-2] = 18
    assert list(lv) == [2, 3, 18, 15]
    assert ls == [1, 2, 3, 4, 18, 15, 7]
def test_setitem_slice():
    ls = [1, 2, 3, 4, 5, 6, 7]
    lv = ListView(ls, lambda x: (1 < x < 4) or (7 > x > 4) or (x > 10))
    # lv: [2, 3, 5, 6]

    # normal
    lv[1:] = [15, 18, 21]
    assert list(lv) == [2, 15, 18, 21]
    assert ls == [1, 2, 15, 4, 18, 21, 7]

    # out of range
    with pytest.raises(IndexError):
        lv[4] = 100

    lv[:] = [18]
    assert list(lv) == [18]
    assert ls == [1, 18, 4, 7]
class GetIABooksActivity(activity.Activity):
    def __init__(self, handle):
        "The entry point to the Activity"
        activity.Activity.__init__(self, handle, False)
        self.max_participants = 1

        self._sequence = 0
        self.selected_book = None
        self.queryresults = None
        self._getter = None
        self.show_images = True
        self.languages = {}
        self._lang_code_handler = languagenames.LanguageNames()
        self.catalogs_configuration = {}
        self.catalog_history = []

        if os.path.exists('/etc/get-books.cfg'):
            self._read_configuration('/etc/get-books.cfg')
        else:
            self._read_configuration()

        toolbar_box = ToolbarBox()
        activity_button = ToolButton()
        color = profile.get_color()
        bundle = ActivityBundle(activity.get_bundle_path())
        icon = Icon(file=bundle.get_icon(), xo_color=color)
        activity_button.set_icon_widget(icon)
        activity_button.show()

        toolbar_box.toolbar.insert(activity_button, 0)
        self._add_search_controls(toolbar_box.toolbar)

        separator = Gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(True)
        toolbar_box.toolbar.insert(separator, -1)

        toolbar_box.toolbar.insert(StopButton(self), -1)

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show_all()
        self._books_toolbar = toolbar_box.toolbar

        self._create_controls()

        self.using_powerd = os.access(POWERD_INHIBIT_DIR, os.W_OK)

        self.__book_downloader = self.__image_downloader = None

    def get_path(self):
        self._sequence += 1
        return os.path.join(self.get_activity_root(), 'instance',
                            '%03d.tmp' % self._sequence)

    def _inhibit_suspend(self):
        if self.using_powerd:
            fd = open(POWERD_INHIBIT_DIR + "/%u" % os.getpid(), 'w')
            logging.error("inhibit_suspend file is %s", (POWERD_INHIBIT_DIR \
                    + "/%u" % os.getpid()))
            fd.close()
            return True

        return False

    def _allow_suspend(self):
        if self.using_powerd:
            if os.path.exists(POWERD_INHIBIT_DIR + "/%u" % os.getpid()):
                os.unlink(POWERD_INHIBIT_DIR + "/%u" % os.getpid())
            logging.error("allow_suspend unlinking %s", (POWERD_INHIBIT_DIR \
                    + "/%u" % os.getpid()))
            return True

        return False

    def _read_configuration(self, file_name='get-books.cfg'):
        logging.error('Reading configuration from file %s', file_name)
        config = ConfigParser.ConfigParser()
        config.readfp(open(file_name))
        if config.has_option('GetBooks', 'show_images'):
            self.show_images = config.getboolean('GetBooks', 'show_images')
        self.languages = {}
        if config.has_option('GetBooks', 'languages'):
            languages_param = config.get('GetBooks', 'languages')
            for language in languages_param.split(','):
                lang_code = language.strip()
                if len(lang_code) > 0:
                    self.languages[lang_code] = \
                    self._lang_code_handler.get_full_language_name(lang_code)

        for section in config.sections():
            if section != 'GetBooks' and not section.startswith('Catalogs'):
                name = config.get(section, 'name')
                _SOURCES[section] = name
                repo_config = {}
                repo_config['query_uri'] = config.get(section, 'query_uri')
                repo_config['opds_cover'] = config.get(section, 'opds_cover')
                if config.has_option(section, 'summary_field'):
                    repo_config['summary_field'] = \
                        config.get(section, 'summary_field')
                else:
                    repo_config['summary_field'] = None
                if config.has_option(section, 'blacklist'):
                    blacklist = config.get(section, 'blacklist')
                    repo_config['blacklist'] = blacklist.split(',')
                    # TODO strip?
                else:
                    repo_config['blacklist'] = []

                _SOURCES_CONFIG[section] = repo_config

        logging.error('_SOURCES %s', pformat(_SOURCES))
        logging.error('_SOURCES_CONFIG %s', pformat(_SOURCES_CONFIG))

        for section in config.sections():
            if section.startswith('Catalogs'):
                catalog_source = section.split('_')[1]
                if not catalog_source in _SOURCES_CONFIG:
                    logging.error(
                        'There are not a source for the catalog ' +
                        'section  %s', section)
                    break
                source_config = _SOURCES_CONFIG[catalog_source]
                opds_cover = source_config['opds_cover']
                for catalog in config.options(section):
                    catalog_config = {}
                    catalog_config['query_uri'] = config.get(section, catalog)
                    catalog_config['opds_cover'] = opds_cover
                    catalog_config['source'] = catalog_source
                    catalog_config['name'] = catalog
                    catalog_config['summary_field'] = \
                        source_config['summary_field']
                    self.catalogs_configuration[catalog] = catalog_config

        self.source = _SOURCES_CONFIG.keys()[0]

        self.filter_catalogs_by_source()

        logging.error('languages %s', pformat(self.languages))
        logging.error('catalogs %s', pformat(self.catalogs))

    def _add_search_controls(self, toolbar):
        book_search_item = Gtk.ToolItem()
        toolbar.search_entry = iconentry.IconEntry()
        toolbar.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                                'system-search')
        toolbar.search_entry.add_clear_button()
        toolbar.search_entry.connect('activate',
                                     self.__search_entry_activate_cb)
        width = int(Gdk.Screen.width() / 4)
        toolbar.search_entry.set_size_request(width, -1)
        book_search_item.add(toolbar.search_entry)
        toolbar.search_entry.show()
        toolbar.insert(book_search_item, -1)
        book_search_item.show()

        toolbar.source_combo = ComboBox()
        toolbar.source_combo.props.sensitive = True
        toolbar.source_changed_cb_id = \
            toolbar.source_combo.connect('changed', self.__source_changed_cb)
        combotool = ToolComboBox(toolbar.source_combo)
        toolbar.insert(combotool, -1)
        combotool.show()

        self.bt_catalogs = ToggleToolButton('books')
        self.bt_catalogs.set_tooltip(_('Catalogs'))
        toolbar.insert(self.bt_catalogs, -1)
        self.bt_catalogs.connect('toggled', self.__toggle_cats_cb)
        if len(self.catalogs) > 0:
            self.bt_catalogs.show()

        if len(self.languages) > 0:
            toolbar.config_toolbarbutton = ToolbarButton()
            toolbar.config_toolbarbutton.props.icon_name = 'preferences-system'
            toolbar.config_toolbarbox = Gtk.Toolbar()
            toolbar.config_toolbarbutton.props.page = toolbar.config_toolbarbox
            toolbar.language_combo = ComboBox()
            toolbar.language_combo.props.sensitive = True
            combotool = ToolComboBox(toolbar.language_combo)
            toolbar.language_combo.append_item('all', _('Any language'))
            for key in self.languages.keys():
                toolbar.language_combo.append_item(key, self.languages[key])
            toolbar.language_combo.set_active(0)
            toolbar.config_toolbarbutton.props.page.insert(combotool, -1)
            toolbar.insert(toolbar.config_toolbarbutton, -1)
            toolbar.config_toolbarbutton.show()
            combotool.show()
            toolbar.language_changed_cb_id = \
                toolbar.language_combo.connect('changed',
                self.__language_changed_cb)

        self._device_manager = devicemanager.DeviceManager()
        self._refresh_sources(toolbar)
        self._device_manager.connect('device-changed',
                                     self.__device_changed_cb)

        toolbar.search_entry.grab_focus()
        return toolbar

    def __bt_catalogs_clicked_cb(self, button):
        palette = button.get_palette()
        palette.popup(immediate=True, state=palette.SECONDARY)

    def __switch_catalog_cb(self, catalog_name):
        catalog_config = self.catalogs[catalog_name.decode('utf-8')]
        self.__activate_catalog_cb(None, catalog_config)

    def __activate_catalog_cb(self, menu, catalog_config):
        query_language = self.get_query_language()

        self.enable_button(False)
        self.clear_downloaded_bytes()
        self.book_selected = False
        self.listview.handler_block(self.selection_cb_id)
        self.listview.clear()
        self.listview.handler_unblock(self.selection_cb_id)
        logging.error('SOURCE %s', catalog_config['source'])
        self._books_toolbar.search_entry.props.text = ''
        self.source = catalog_config['source']
        position = _SOURCES_CONFIG[self.source]['position']
        self._books_toolbar.source_combo.set_active(position)

        if self.queryresults is not None:
            self.queryresults.cancel()
            self.queryresults = None

        self.queryresults = opds.RemoteQueryResult(catalog_config, '',
                                                   query_language)
        self.show_message(_('Performing lookup, please wait...'))
        # README: I think we should create some global variables for
        # each cursor that we are using to avoid the creation of them
        # every time that we want to change it
        self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))

        self.queryresults.connect('updated', self.__query_updated_cb)

    def update_format_combo(self, links):
        self.format_combo.handler_block(self.__format_changed_cb_id)
        self.format_combo.remove_all()
        for key in _MIMETYPES.keys():
            if _MIMETYPES[key] in links.keys():
                self.format_combo.append_item(_MIMETYPES[key], key)
        self.format_combo.set_active(0)
        self.format_combo.handler_unblock(self.__format_changed_cb_id)

    def get_search_terms(self):
        return self._books_toolbar.search_entry.props.text

    def __device_changed_cb(self, mgr):
        logging.debug('Device was added/removed')
        self._refresh_sources(self._books_toolbar)

    def _refresh_sources(self, toolbar):
        toolbar.source_combo.handler_block(toolbar.source_changed_cb_id)

        #TODO: Do not blindly clear this
        toolbar.source_combo.remove_all()

        position = 0
        for key in _SOURCES.keys():
            toolbar.source_combo.append_item(_SOURCES[key],
                                             key,
                                             icon_name='internet-icon')
            _SOURCES_CONFIG[key]['position'] = position
            position = position + 1

        # Add menu for local books
        if len(_SOURCES) > 0:
            toolbar.source_combo.append_separator()
        toolbar.source_combo.append_item('local_books',
                                         _('My books'),
                                         icon_name='activity-journal')

        devices = self._device_manager.get_devices()

        first_device = True
        for device_name in devices:
            device = devices[device_name]
            logging.debug('device %s', device)
            if device['removable']:
                mount_point = device['mount_path']
                label = device['label']
                if label == '' or label is None:
                    capacity = device['size']
                    label = (_('%.2f GB Volume') % (capacity / (1024.0**3)))
                logging.debug('Adding device %s', (label))
                if first_device:
                    toolbar.source_combo.append_separator()
                    first_device = False
                toolbar.source_combo.append_item(mount_point, label)

        toolbar.source_combo.set_active(0)
        toolbar.source_combo.handler_unblock(toolbar.source_changed_cb_id)

    def __format_changed_cb(self, combo):
        self.show_book_data(False)

    def __language_changed_cb(self, combo):
        self.find_books(self.get_search_terms())

    def __search_entry_activate_cb(self, entry):
        self.find_books(self.get_search_terms())

    def __get_book_cb(self, button):
        self.get_book()

    def enable_button(self, state):
        self._download.props.sensitive = state
        self.format_combo.props.sensitive = state

    def move_up_catalog(self, treeview):
        len_cat = len(self.catalog_history)
        if len_cat == 1:
            return
        else:
            # move a level up the tree
            self.catalog_listview.handler_block(self._catalog_changed_id)
            self.catalog_history.pop()
            len_cat -= 1
            if (len_cat == 1):
                title = self.catalog_history[0]['title']
                self.bt_move_up_catalog.set_label(title)
                self.bt_move_up_catalog.hide_image()
            else:
                title = self.catalog_history[len_cat - 1]['title']
                self.bt_move_up_catalog.set_label(title)
                self.bt_move_up_catalog.show_image()
            self.catalogs = self.catalog_history[len_cat - 1]['catalogs']
            if len(self.catalogs) > 0:
                self.path_iter = {}
                self.categories = []
                for key in self.catalogs.keys():
                    self.categories.append({'text': key, 'dentro': []})
                self.treemodel.clear()
                for p in self.categories:
                    self.path_iter[p['text']] = \
                            self.treemodel.append([p['text']])
            self.catalog_listview.handler_unblock(self._catalog_changed_id)

    def move_down_catalog(self, treeview, path, column):
        treestore, coldex = \
                self.catalog_listview.get_selection().get_selected()
        len_cat = len(self.catalog_history)
        if len_cat > 0 and self.catalog_history[len_cat - 1]['catalogs'] == []:
            self.catalog_history.pop()
            len_cat = len(self.catalog_history)

        # README: when the Activity starts by default there is nothing
        # selected and this signal is called, so we have to avoid this
        # 'append' because it fails
        if coldex is not None:
            self.catalog_history.append({
                'title': treestore.get_value(coldex, 0),
                'catalogs': []
            })
            self.__switch_catalog_cb(treestore.get_value(coldex, 0))

    def _sort_logfile(self, treemodel, itera, iterb):
        a = treemodel.get_value(itera, 0)
        b = treemodel.get_value(iterb, 0)
        if a == None or b == None:
            return 0
        a = a.lower()
        b = b.lower()
        if a > b:
            return 1
        if a < b:
            return -1
        return 0

    def __toggle_cats_cb(self, button):
        if button.get_active():
            self.tree_scroller.show_all()
            self.separa.show()
        else:
            self.tree_scroller.hide()
            self.separa.hide()

    def _create_controls(self):
        self._download_content_length = 0
        self._download_content_type = None

        self.msg_label = Gtk.Label()

        self.list_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        # Catalogs treeview
        self.catalog_listview = Gtk.TreeView()
        self.catalog_listview.headers_clickble = True
        self.catalog_listview.hover_expand = True
        self.catalog_listview.rules_hint = True
        self._catalog_changed_id = self.catalog_listview.connect(
            'row-activated', self.move_down_catalog)
        self.catalog_listview.set_activate_on_single_click(True)
        self.catalog_listview.set_enable_search(False)

        self.treemodel = Gtk.ListStore(str)
        self.treemodel.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.catalog_listview.set_model(self.treemodel)

        renderer = Gtk.CellRendererText()
        renderer.set_property('wrap-mode', Pango.WrapMode.WORD)
        self.treecol = Gtk.TreeViewColumn(_('Catalogs'), renderer, text=0)
        self.treecol.set_property('clickable', True)
        self.treecol.connect('clicked', self.move_up_catalog)
        self.catalog_listview.append_column(self.treecol)
        self.bt_move_up_catalog = ButtonWithImage(_('Catalogs'))
        self.bt_move_up_catalog.hide_image()
        self.treecol.set_widget(self.bt_move_up_catalog)

        self.load_source_catalogs()

        self.tree_scroller = Gtk.ScrolledWindow(hadjustment=None,
                                                vadjustment=None)
        self.tree_scroller.set_policy(Gtk.PolicyType.NEVER,
                                      Gtk.PolicyType.AUTOMATIC)
        self.tree_scroller.add(self.catalog_listview)
        self.list_box.pack_start(self.tree_scroller,
                                 expand=False,
                                 fill=False,
                                 padding=0)
        self.separa = Gtk.VSeparator()
        self.list_box.pack_start(self.separa,
                                 expand=False,
                                 fill=False,
                                 padding=0)

        # books listview
        self.listview = ListView(self._lang_code_handler)
        self.selection_cb_id = self.listview.connect('selection-changed',
                                                     self.selection_cb)
        self.listview.set_enable_search(False)

        self.list_scroller = Gtk.ScrolledWindow(hadjustment=None,
                                                vadjustment=None)
        self.list_scroller.set_policy(Gtk.PolicyType.AUTOMATIC,
                                      Gtk.PolicyType.AUTOMATIC)
        vadjustment = self.list_scroller.get_vadjustment()
        vadjustment.connect('value-changed',
                            self.__vadjustment_value_changed_cb)
        self.list_scroller.add(self.listview)
        self.list_box.pack_start(self.list_scroller,
                                 expand=True,
                                 fill=True,
                                 padding=0)

        self.scrolled = Gtk.ScrolledWindow()
        self.scrolled.set_policy(Gtk.PolicyType.NEVER,
                                 Gtk.PolicyType.AUTOMATIC)
        self.scrolled.props.shadow_type = Gtk.ShadowType.NONE
        self.textview = Gtk.TextView()
        self.textview.set_editable(False)
        self.textview.set_cursor_visible(False)
        self.textview.set_wrap_mode(Gtk.WrapMode.WORD)
        self.textview.set_justification(Gtk.Justification.LEFT)
        self.textview.set_left_margin(20)
        self.textview.set_right_margin(20)
        self.scrolled.add(self.textview)
        self.list_box.show_all()
        self.separa.hide()
        self.tree_scroller.hide()

        vbox_download = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox_format = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        format_label = Gtk.Label(label=_('Format:'))
        self.format_combo = ComboBox()
        for key in _MIMETYPES.keys():
            self.format_combo.append_item(_MIMETYPES[key], key)
        self.format_combo.set_active(0)
        self.format_combo.props.sensitive = False
        self.__format_changed_cb_id = \
                self.format_combo.connect('changed', self.__format_changed_cb)

        hbox_format.pack_start(format_label, False, False, 10)
        hbox_format.pack_start(self.format_combo, False, False, 10)
        vbox_download.pack_start(hbox_format, False, False, 10)

        self._download = Gtk.Button(_('Get Book'))
        self._download.set_image(Icon(icon_name='data-download'))
        self._download.props.sensitive = False
        self._download.connect('clicked', self.__get_book_cb)
        vbox_download.pack_start(self._download, False, False, 10)

        self.progressbox = Gtk.Box(spacing=20,
                                   orientation=Gtk.Orientation.HORIZONTAL)
        self.progressbar = Gtk.ProgressBar()
        self.progressbar.set_fraction(0.0)
        self.progressbox.pack_start(self.progressbar,
                                    expand=True,
                                    fill=True,
                                    padding=0)
        self.cancel_btn = Gtk.Button(stock=Gtk.STOCK_CANCEL)
        self.cancel_btn.set_image(Icon(icon_name='dialog-cancel'))
        self.cancel_btn.connect('clicked', self.__cancel_btn_clicked_cb)
        self.progressbox.pack_start(self.cancel_btn,
                                    expand=False,
                                    fill=False,
                                    padding=0)
        vbox_download.pack_start(self.progressbox, False, False, 10)

        bottom_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        if self.show_images:
            self.__image_downloader = None
            self.image = Gtk.Image()
            self.add_default_image()
            bottom_hbox.pack_start(self.image, False, False, 10)
        bottom_hbox.pack_start(self.scrolled, True, True, 10)
        bottom_hbox.pack_start(vbox_download, False, False, 10)
        bottom_hbox.show_all()

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox.pack_start(self.msg_label, False, False, 10)
        vbox.pack_start(self.list_box, True, True, 0)
        vbox.pack_start(bottom_hbox, False, False, 10)
        self.set_canvas(vbox)
        self.listview.show()
        vbox.show()
        self.list_scroller.show()
        self.progress_hide()
        self.show_message(
            _('Enter words from the Author or Title to begin search.'))

        self._books_toolbar.search_entry.grab_focus()
        if len(self.catalogs) > 0:
            self.bt_catalogs.set_active(True)

    def progress_hide(self):
        self.clear_downloaded_bytes()
        self.progressbar.set_sensitive(False)
        self.cancel_btn.set_sensitive(False)

    def progress_show(self):
        self.progressbar.set_sensitive(True)
        self.cancel_btn.set_sensitive(True)

    def filter_catalogs_by_source(self):
        self.catalogs = {}
        for catalog_key in self.catalogs_configuration:
            catalog = self.catalogs_configuration[catalog_key]
            if catalog['source'] == self.source:
                self.catalogs[catalog_key] = catalog

    def load_source_catalogs(self):
        self.filter_catalogs_by_source()

        if len(self.catalogs) > 0:
            self.categories = []
            self.path_iter = {}
            self.catalog_history = []
            self.catalog_history.append({
                'title': _('Catalogs'),
                'catalogs': self.catalogs
            })
            for key in self.catalogs.keys():
                self.categories.append({'text': key, 'dentro': []})
            self.treemodel.clear()

            for p in self.categories:
                self.path_iter[p['text']] = self.treemodel.append([p['text']])

    def can_close(self):
        if self.queryresults is not None:
            self.queryresults.cancel()
            self.queryresults = None
        return True

    def selection_cb(self, widget):
        selected_book = self.listview.get_selected_book()
        if self.source == 'local_books':
            if selected_book:
                self.selected_book = selected_book
                self._download.hide()
                self.show_book_data()
                self._object_id = selected_book.get_object_id()
                self._show_journal_alert(_('Selected book'),
                                         self.selected_title)
        else:
            self.clear_downloaded_bytes()
            if selected_book:
                self.update_format_combo(selected_book.get_types())
                self.selected_book = selected_book
                self._download.show()
                self.show_book_data()

    def show_message(self, text):
        self.msg_label.set_text(text)
        self.msg_label.show()

    def hide_message(self):
        self.msg_label.hide()

    def show_book_data(self, load_image=True):
        self.selected_title = self.selected_book.get_title()
        book_data = _('Title:\t\t') + self.selected_title + '\n'
        self.selected_author = self.selected_book.get_author()
        book_data += _('Author:\t\t') + self.selected_author + '\n'
        self.selected_publisher = self.selected_book.get_publisher()
        self.selected_summary = self.selected_book.get_summary()
        if (self.selected_summary is not 'Unknown'):
            book_data += _('Summary:\t') + self.selected_summary + '\n'
        self.selected_language_code = self.selected_book.get_language()
        if self.selected_language_code != '':
            try:
                self.selected_language = \
                    self._lang_code_handler.get_full_language_name(
                        self.selected_book.get_language())
            except:
                self.selected_language = self.selected_book.get_language()
            book_data += _('Language:\t') + self.selected_language + '\n'
        book_data += _('Publisher:\t') + self.selected_publisher + '\n'
        textbuffer = self.textview.get_buffer()
        textbuffer.set_text('\n' + book_data)
        self.enable_button(True)

        # Cover Image
        self.exist_cover_image = False
        if self.show_images and load_image:
            if self.source == 'local_books':
                cover_image_buffer = self.get_journal_entry_cover_image(
                    self.selected_book.get_object_id())
                if (cover_image_buffer):
                    self.add_image_buffer(
                        self.get_pixbuf_from_buffer(cover_image_buffer))
                else:
                    self.add_default_image()
            else:
                url_image = self.selected_book.get_image_url()
                self.add_default_image()
                if url_image:
                    self.download_image(url_image.values()[0])

    def get_pixbuf_from_buffer(self, image_buffer):
        """Buffer To Pixbuf"""
        pixbuf_loader = GdkPixbuf.PixbufLoader()
        pixbuf_loader.write(image_buffer)
        pixbuf_loader.close()
        pixbuf = pixbuf_loader.get_pixbuf()
        return pixbuf

    def get_journal_entry_cover_image(self, object_id):
        ds_object = datastore.get(object_id)
        if 'cover_image' in ds_object.metadata:
            cover_data = ds_object.metadata['cover_image']
            return base64.b64decode(cover_data)
        elif 'preview' in ds_object.metadata:
            return ds_object.metadata['preview']
        else:
            return ""

    def download_image(self, url):
        self._inhibit_suspend()
        self.progress_show()
        if self.__image_downloader is not None:
            self.__image_downloader.stop()
        self.__image_downloader = opds.FileDownloader(url, self.get_path())
        self.__image_downloader.connect('updated', self.__image_updated_cb)
        self.__image_downloader.connect('progress', self.__image_progress_cb)

    def __image_updated_cb(self, downloader, path, content_type):
        if path is not None:
            self.add_image(path)
            self.exist_cover_image = True
            os.remove(path)
        else:
            self.add_default_image()
        self.__image_downloader = None
        GObject.timeout_add(500, self.progress_hide)
        self._allow_suspend()

    def __image_progress_cb(self, downloader, progress):
        self.progressbar.set_fraction(progress)
        while Gtk.events_pending():
            Gtk.main_iteration()

    def add_default_image(self):
        file_path = os.path.join(activity.get_bundle_path(),
                                 'generic_cover.png')
        self.add_image(file_path)

    def add_image(self, file_path):
        pixbuf = GdkPixbuf.Pixbuf.new_from_file(file_path)
        self.add_image_buffer(pixbuf)

    def add_image_buffer(self, pixbuf):
        image_height = int(Gdk.Screen.height() / 4)
        image_width = image_height / 3 * 2
        width, height = pixbuf.get_width(), pixbuf.get_height()
        scale = 1
        if (width > image_width) or (height > image_height):
            scale_x = image_width / float(width)
            scale_y = image_height / float(height)
            scale = min(scale_x, scale_y)

        pixbuf2 = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB,
                                       pixbuf.get_has_alpha(),
                                       pixbuf.get_bits_per_sample(),
                                       image_width, image_height)

        pixbuf2.fill(style.COLOR_PANEL_GREY.get_int())

        margin_x = int((image_width - (width * scale)) / 2)
        margin_y = int((image_height - (height * scale)) / 2)

        pixbuf.scale(pixbuf2, margin_x, margin_y, image_width - (margin_x * 2),
                     image_height - (margin_y * 2), margin_x, margin_y, scale,
                     scale, GdkPixbuf.InterpType.BILINEAR)

        self.image.set_from_pixbuf(pixbuf2)

    def get_query_language(self):
        query_language = None
        if len(self.languages) > 0:
            query_language = self._books_toolbar.language_combo.props.value
        return query_language

    def find_books(self, search_text=''):
        self._inhibit_suspend()
        self.source = self._books_toolbar.source_combo.props.value

        query_language = self.get_query_language()

        self.enable_button(False)
        self.clear_downloaded_bytes()
        self.book_selected = False
        self.listview.handler_block(self.selection_cb_id)
        self.listview.clear()
        self.listview.handler_unblock(self.selection_cb_id)

        if self.queryresults is not None:
            self.queryresults.cancel()
            self.queryresults = None

        if self.source == 'local_books':
            self.listview.populate_with_books(
                self.get_entrys_info(search_text))
        else:
            if search_text is None:
                return
            elif len(search_text) < 3:
                self.show_message(_('You must enter at least 3 letters.'))
                self._books_toolbar.search_entry.grab_focus()
                return
            if self.source == 'Internet Archive':
                self.queryresults = \
                        opds.InternetArchiveQueryResult(search_text,
                                                        self.get_path())
            elif self.source in _SOURCES_CONFIG:
                repo_configuration = _SOURCES_CONFIG[self.source]
                self.queryresults = opds.RemoteQueryResult(
                    repo_configuration, search_text, query_language)
            else:
                self.queryresults = opds.LocalVolumeQueryResult(
                    self.source, search_text, query_language)

            self.show_message(_('Performing lookup, please wait...'))
            self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))
            self.queryresults.connect('updated', self.__query_updated_cb)

    def __query_updated_cb(self, query, midway):
        self.listview.populate(self.queryresults)
        if hasattr(self.queryresults, '_feedobj') and \
           'bozo_exception' in self.queryresults._feedobj:
            # something went wrong and we have to inform about this
            bozo_exception = self.queryresults._feedobj.bozo_exception
            if isinstance(bozo_exception, urllib2.URLError):
                if isinstance(bozo_exception.reason, socket.gaierror):
                    if bozo_exception.reason.errno == -2:
                        self.show_message(
                            _('Could not reach the server. '
                              'Maybe you are not connected to the network'))
                        self.window.set_cursor(None)
                        return
            self.show_message(_('There was an error downloading the list.'))
        elif (len(self.queryresults.get_catalog_list()) > 0):
            self.show_message(_('New catalog list %s was found') \
                % self.queryresults._configuration["name"])
            self.catalogs_updated(query, midway)
        elif len(self.queryresults) == 0:
            self.show_message(_('Sorry, no books could be found.'))
        if not midway and len(self.queryresults) > 0:
            self.hide_message()
            query_language = self.get_query_language()
            if query_language != 'all' and query_language != 'en':
                # the bookserver send english books if there are not books in
                # the requested language
                only_english = True
                for book in self.queryresults.get_book_list():
                    if book.get_language() == query_language:
                        only_english = False
                        break
                if only_english:
                    self.show_message(_('Sorry, we only found english books.'))
        self.get_window().set_cursor(None)
        self._allow_suspend()

    def catalogs_updated(self, query, midway):
        self.catalogs = {}
        for catalog_item in self.queryresults.get_catalog_list():
            logging.debug('Add catalog %s', catalog_item.get_title())
            catalog_config = {}
            download_link = ''
            download_links = catalog_item.get_types()
            for link in download_links.keys():
                download_link = download_links[link]
                break
            catalog_config['query_uri'] = download_link
            catalog_config['opds_cover'] = \
                catalog_item._configuration['opds_cover']
            catalog_config['source'] = catalog_item._configuration['source']
            source_config = _SOURCES_CONFIG[catalog_config['source']]
            catalog_config['name'] = catalog_item.get_title()
            catalog_config['summary_field'] = \
                catalog_item._configuration['summary_field']
            if catalog_item.get_title() in source_config['blacklist']:
                logging.debug('Catalog "%s" is in blacklist',
                              catalog_item.get_title())
            else:
                self.catalogs[catalog_item.get_title().strip()] = \
                        catalog_config

        if len(self.catalogs) > 0:
            len_cat = len(self.catalog_history)
            self.catalog_history[len_cat - 1]['catalogs'] = self.catalogs
            self.path_iter = {}
            self.categories = []
            for key in self.catalogs.keys():
                self.categories.append({'text': key, 'dentro': []})
            self.treemodel.clear()
            for p in self.categories:
                self.path_iter[p['text']] = \
                        self.treemodel.append([p['text']])

            title = self.catalog_history[len_cat - 1]['title']
            self.bt_move_up_catalog.set_label(title)
            self.bt_move_up_catalog.show_image()

        else:
            self.catalog_history.pop()

    def __source_changed_cb(self, widget):
        search_terms = self.get_search_terms()
        if search_terms == '':
            self.find_books(None)
        else:
            self.find_books(search_terms)
        # enable/disable catalogs button if configuration is available
        self.source = self._books_toolbar.source_combo.props.value

        # Get catalogs for this source
        self.load_source_catalogs()

        if len(self.catalogs) > 0:
            self.bt_catalogs.show()
            self.bt_catalogs.set_active(True)
        else:
            self.bt_catalogs.set_active(False)
            self.bt_catalogs.hide()

    def __vadjustment_value_changed_cb(self, vadjustment):

        if not self.queryresults.is_ready():
            return
        try:
            # Use various tricks to update resultset as user scrolls down
            if ((vadjustment.props.upper - vadjustment.props.lower) > 1000 \
                and (vadjustment.props.upper - vadjustment.props.value - \
                vadjustment.props.page_size) / (vadjustment.props.upper - \
                vadjustment.props.lower) < 0.3) or ((vadjustment.props.upper \
                - vadjustment.props.value
                - vadjustment.props.page_size) < 200):
                if self.queryresults.has_next():
                    self.queryresults.update_with_next()
        finally:
            return

    def __cancel_btn_clicked_cb(self, btn):
        if self.__image_downloader is not None:
            self.__image_downloader.stop()

        if self.__book_downloader is not None:
            self.__book_downloader.stop()

        self.progress_hide()
        self.enable_button(True)
        self.listview.props.sensitive = True
        self._books_toolbar.search_entry.set_sensitive(True)
        self._allow_suspend()

    def get_book(self):
        self.enable_button(False)
        self.clear_downloaded_bytes()
        self.progress_show()
        if self.source != 'local_books':
            self.selected_book.get_download_links(
                self.format_combo.props.value, self.download_book,
                self.get_path())

    def download_book(self, url):
        logging.error('DOWNLOAD BOOK %s', url)
        self._inhibit_suspend()
        self.listview.props.sensitive = False
        self._books_toolbar.search_entry.set_sensitive(False)
        self.__book_downloader = opds.FileDownloader(url, self.get_path())
        self.__book_downloader.connect('updated', self.__book_updated_cb)
        self.__book_downloader.connect('progress', self.__book_progress_cb)

    def __book_updated_cb(self, downloader, path, content_type):
        self._books_toolbar.search_entry.set_sensitive(True)
        self.listview.props.sensitive = True
        self._allow_suspend()
        GObject.timeout_add(500, self.progress_hide)
        self.enable_button(True)
        self.__book_downloader = None

        if path is None:
            self._show_error_alert(
                _('Error: Could not download %s. ' +
                  'The path in the catalog seems to be incorrect.') %
                self.selected_title)
            return

        if os.stat(path).st_size == 0:
            self._show_error_alert(
                _('Error: Could not download %s. ' +
                  'The other end sent an empty file.') % self.selected_title)
            return

        if content_type.startswith('text/html'):
            self._show_error_alert(
                _('Error: Could not download %s. ' +
                  'The other end sent text/html instead of a book.') %
                self.selected_title)
            return

        self.process_downloaded_book(path)

    def __book_progress_cb(self, downloader, progress):
        self.progressbar.set_fraction(progress)
        while Gtk.events_pending():
            Gtk.main_iteration()

    def clear_downloaded_bytes(self):
        self.progressbar.set_fraction(0.0)

    def process_downloaded_book(self, path):
        logging.debug("Got document %s", path)
        self.create_journal_entry(path)
        self._getter = None
        self._allow_suspend()

    def create_journal_entry(self, path):
        journal_entry = datastore.create()
        journal_title = self.selected_title
        if self.selected_author != '':
            journal_title = journal_title + ', by ' + self.selected_author
        journal_entry.metadata['title'] = journal_title
        journal_entry.metadata['title_set_by_user'] = '******'
        journal_entry.metadata['keep'] = '0'
        journal_entry.metadata['mime_type'] = \
                self.format_combo.props.value
        # Fix fake mime type for black&white pdfs
        if journal_entry.metadata['mime_type'] == _MIMETYPES['PDF BW']:
            journal_entry.metadata['mime_type'] = _MIMETYPES['PDF']

        journal_entry.metadata['buddies'] = ''
        journal_entry.metadata['icon-color'] = profile.get_color().to_string()
        textbuffer = self.textview.get_buffer()
        journal_entry.metadata['description'] = \
            textbuffer.get_text(textbuffer.get_start_iter(),
                                textbuffer.get_end_iter(), True)
        if self.exist_cover_image:
            image_buffer = self._get_preview_image_buffer()
            journal_entry.metadata['preview'] = dbus.ByteArray(image_buffer)
            image_buffer = self._get_cover_image_buffer()
            journal_entry.metadata['cover_image'] = \
                dbus.ByteArray(base64.b64encode(image_buffer))
        else:
            journal_entry.metadata['cover_image'] = ""

        journal_entry.metadata['tags'] = self.source
        journal_entry.metadata['source'] = self.source
        journal_entry.metadata['author'] = self.selected_author
        journal_entry.metadata['publisher'] = self.selected_publisher
        journal_entry.metadata['summary'] = self.selected_summary
        journal_entry.metadata['language'] = self.selected_language_code

        journal_entry.file_path = path
        datastore.write(journal_entry)
        os.remove(path)
        self.progress_hide()
        self._object_id = journal_entry.object_id
        self._show_journal_alert(_('Download completed'), self.selected_title)

    def _show_journal_alert(self, title, msg):
        _stop_alert = Alert()
        _stop_alert.props.title = title
        _stop_alert.props.msg = msg

        if _HAS_BUNDLE_LAUNCHER:
            bundle = get_bundle(object_id=self._object_id)

        if bundle is not None:
            icon = Icon(file=bundle.get_icon())
            label = _('Open with %s') % bundle.get_name()
            _stop_alert.add_button(Gtk.ResponseType.ACCEPT, label, icon)
        else:
            icon = Icon(icon_name='zoom-activity')
            label = _('Show in Journal')
            _stop_alert.add_button(Gtk.ResponseType.APPLY, label, icon)
        icon.show()

        ok_icon = Icon(icon_name='dialog-ok')
        _stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon)
        ok_icon.show()
        # Remove other alerts
        for alert in self._alerts:
            self.remove_alert(alert)

        self.add_alert(_stop_alert)
        _stop_alert.connect('response', self.__stop_response_cb)
        _stop_alert.show()

    def __stop_response_cb(self, alert, response_id):
        if response_id is Gtk.ResponseType.APPLY:
            activity.show_object_in_journal(self._object_id)
        elif response_id is Gtk.ResponseType.ACCEPT:
            launch_bundle(object_id=self._object_id)
        self.remove_alert(alert)

    def _get_preview_image_buffer(self):
        preview_width, preview_height = style.zoom(300), style.zoom(225)

        pixbuf = self.image.get_pixbuf()
        width, height = pixbuf.get_width(), pixbuf.get_height()

        scale = 1
        if (width > preview_width) or (height > preview_height):
            scale_x = preview_width / float(width)
            scale_y = preview_height / float(height)
            scale = min(scale_x, scale_y)

        pixbuf2 = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB,
                                       pixbuf.get_has_alpha(),
                                       pixbuf.get_bits_per_sample(),
                                       preview_width, preview_height)
        pixbuf2.fill(style.COLOR_WHITE.get_int())

        margin_x = int((preview_width - (width * scale)) / 2)
        margin_y = int((preview_height - (height * scale)) / 2)

        pixbuf.scale(pixbuf2, margin_x, margin_y,
                     preview_width - (margin_x * 2),
                     preview_height - (margin_y * 2), margin_x, margin_y,
                     scale, scale, GdkPixbuf.InterpType.BILINEAR)

        succes, data = pixbuf2.save_to_bufferv('png', [], [])
        return data

    def _get_cover_image_buffer(self):
        pixbuf = self.image.get_pixbuf()
        succes, data = pixbuf.save_to_bufferv('png', [], [])
        return data

    def _show_error_alert(self, title, text=None):
        alert = NotifyAlert(timeout=20)
        alert.props.title = title
        alert.props.msg = text
        self.add_alert(alert)
        alert.connect('response', self._alert_cancel_cb)
        alert.show()

    def _alert_cancel_cb(self, alert, response_id):
        self.remove_alert(alert)
        self.textview.grab_focus()

    def get_entrys_info(self, query):
        books = []
        for key in _MIMETYPES.keys():
            books.extend(self.get_entry_info_format(query, _MIMETYPES[key]))
        return books

    def get_entry_info_format(self, query, mime):
        books = []
        if query is not None and len(query) > 0:
            ds_objects, num_objects = datastore.find({
                'mime_type': '%s' % mime,
                'query': '*%s*' % query
            })
        else:
            ds_objects, num_objects = datastore.find(
                {'mime_type': '%s' % mime})

        logging.error('Local search %d books found %s format', num_objects,
                      mime)
        for i in range(0, num_objects):
            entry = {}
            entry['title'] = ds_objects[i].metadata['title']
            entry['mime'] = ds_objects[i].metadata['mime_type']
            entry['object_id'] = ds_objects[i].object_id

            if 'author' in ds_objects[i].metadata:
                entry['author'] = ds_objects[i].metadata['author']
            else:
                entry['author'] = ''

            if 'publisher' in ds_objects[i].metadata:
                entry['dcterms_publisher'] = \
                    ds_objects[i].metadata['publisher']
            else:
                entry['dcterms_publisher'] = ''

            if 'language' in ds_objects[i].metadata:
                entry['dcterms_language'] = \
                    ds_objects[i].metadata['language']
            else:
                entry['dcterms_language'] = ''

            if 'source' in ds_objects[i].metadata:
                entry['source'] = \
                    ds_objects[i].metadata['source']
            else:
                entry['source'] = ''

            if entry['source'] in _SOURCES_CONFIG:
                repo_configuration = _SOURCES_CONFIG[entry['source']]
                summary_field = repo_configuration['summary_field']
                if 'summary' in ds_objects[i].metadata:
                    entry[summary_field] = ds_objects[i].metadata['summary']
                else:
                    entry[summary_field] = ''
            else:
                repo_configuration = None
            books.append(opds.Book(repo_configuration, entry, ''))
        return books

    def close(self, skip_save=False):
        "Override the close method so we don't try to create a Journal entry."
        activity.Activity.close(self, True)

    def save(self):
        pass
    def _create_controls(self):
        self._download_content_length = 0
        self._download_content_type = None

        self.msg_label = Gtk.Label()

        self.list_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        # Catalogs treeview
        self.catalog_listview = Gtk.TreeView()
        self.catalog_listview.headers_clickble = True
        self.catalog_listview.hover_expand = True
        self.catalog_listview.rules_hint = True
        self._catalog_changed_id = self.catalog_listview.connect(
            'row-activated', self.move_down_catalog)
        self.catalog_listview.set_activate_on_single_click(True)
        self.catalog_listview.set_enable_search(False)

        self.treemodel = Gtk.ListStore(str)
        self.treemodel.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.catalog_listview.set_model(self.treemodel)

        renderer = Gtk.CellRendererText()
        renderer.set_property('wrap-mode', Pango.WrapMode.WORD)
        self.treecol = Gtk.TreeViewColumn(_('Catalogs'), renderer, text=0)
        self.treecol.set_property('clickable', True)
        self.treecol.connect('clicked', self.move_up_catalog)
        self.catalog_listview.append_column(self.treecol)
        self.bt_move_up_catalog = ButtonWithImage(_('Catalogs'))
        self.bt_move_up_catalog.hide_image()
        self.treecol.set_widget(self.bt_move_up_catalog)

        self.load_source_catalogs()

        self.tree_scroller = Gtk.ScrolledWindow(hadjustment=None,
                                                vadjustment=None)
        self.tree_scroller.set_policy(Gtk.PolicyType.NEVER,
                                      Gtk.PolicyType.AUTOMATIC)
        self.tree_scroller.add(self.catalog_listview)
        self.list_box.pack_start(self.tree_scroller,
                                 expand=False,
                                 fill=False,
                                 padding=0)
        self.separa = Gtk.VSeparator()
        self.list_box.pack_start(self.separa,
                                 expand=False,
                                 fill=False,
                                 padding=0)

        # books listview
        self.listview = ListView(self._lang_code_handler)
        self.selection_cb_id = self.listview.connect('selection-changed',
                                                     self.selection_cb)
        self.listview.set_enable_search(False)

        self.list_scroller = Gtk.ScrolledWindow(hadjustment=None,
                                                vadjustment=None)
        self.list_scroller.set_policy(Gtk.PolicyType.AUTOMATIC,
                                      Gtk.PolicyType.AUTOMATIC)
        vadjustment = self.list_scroller.get_vadjustment()
        vadjustment.connect('value-changed',
                            self.__vadjustment_value_changed_cb)
        self.list_scroller.add(self.listview)
        self.list_box.pack_start(self.list_scroller,
                                 expand=True,
                                 fill=True,
                                 padding=0)

        self.scrolled = Gtk.ScrolledWindow()
        self.scrolled.set_policy(Gtk.PolicyType.NEVER,
                                 Gtk.PolicyType.AUTOMATIC)
        self.scrolled.props.shadow_type = Gtk.ShadowType.NONE
        self.textview = Gtk.TextView()
        self.textview.set_editable(False)
        self.textview.set_cursor_visible(False)
        self.textview.set_wrap_mode(Gtk.WrapMode.WORD)
        self.textview.set_justification(Gtk.Justification.LEFT)
        self.textview.set_left_margin(20)
        self.textview.set_right_margin(20)
        self.scrolled.add(self.textview)
        self.list_box.show_all()
        self.separa.hide()
        self.tree_scroller.hide()

        vbox_download = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox_format = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        format_label = Gtk.Label(label=_('Format:'))
        self.format_combo = ComboBox()
        for key in _MIMETYPES.keys():
            self.format_combo.append_item(_MIMETYPES[key], key)
        self.format_combo.set_active(0)
        self.format_combo.props.sensitive = False
        self.__format_changed_cb_id = \
                self.format_combo.connect('changed', self.__format_changed_cb)

        hbox_format.pack_start(format_label, False, False, 10)
        hbox_format.pack_start(self.format_combo, False, False, 10)
        vbox_download.pack_start(hbox_format, False, False, 10)

        self._download = Gtk.Button(_('Get Book'))
        self._download.set_image(Icon(icon_name='data-download'))
        self._download.props.sensitive = False
        self._download.connect('clicked', self.__get_book_cb)
        vbox_download.pack_start(self._download, False, False, 10)

        self.progressbox = Gtk.Box(spacing=20,
                                   orientation=Gtk.Orientation.HORIZONTAL)
        self.progressbar = Gtk.ProgressBar()
        self.progressbar.set_fraction(0.0)
        self.progressbox.pack_start(self.progressbar,
                                    expand=True,
                                    fill=True,
                                    padding=0)
        self.cancel_btn = Gtk.Button(stock=Gtk.STOCK_CANCEL)
        self.cancel_btn.set_image(Icon(icon_name='dialog-cancel'))
        self.cancel_btn.connect('clicked', self.__cancel_btn_clicked_cb)
        self.progressbox.pack_start(self.cancel_btn,
                                    expand=False,
                                    fill=False,
                                    padding=0)
        vbox_download.pack_start(self.progressbox, False, False, 10)

        bottom_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        if self.show_images:
            self.__image_downloader = None
            self.image = Gtk.Image()
            self.add_default_image()
            bottom_hbox.pack_start(self.image, False, False, 10)
        bottom_hbox.pack_start(self.scrolled, True, True, 10)
        bottom_hbox.pack_start(vbox_download, False, False, 10)
        bottom_hbox.show_all()

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox.pack_start(self.msg_label, False, False, 10)
        vbox.pack_start(self.list_box, True, True, 0)
        vbox.pack_start(bottom_hbox, False, False, 10)
        self.set_canvas(vbox)
        self.listview.show()
        vbox.show()
        self.list_scroller.show()
        self.progress_hide()
        self.show_message(
            _('Enter words from the Author or Title to begin search.'))

        self._books_toolbar.search_entry.grab_focus()
        if len(self.catalogs) > 0:
            self.bt_catalogs.set_active(True)
Exemple #18
0
 def set_style(self, style):
     style |= ListView.STYLE_ICON | ListView.STYLE_FLOW_HORIZONTAL | ListView.STYLE_WRAP
     ListView.set_style(self, style)
Exemple #19
0
 def initialize(self):
     self.set_style(0)
     self.set_spacing(2)
     ListView.initialize(self)
Exemple #20
0
 def create_impl(self, className):
     return ListView.create_impl(self, 'ListView')
Exemple #21
0
	def create_impl(self, className):
		return ListView.create_impl(self, 'ListView')
Exemple #22
0
	def set_style(self, style):
		style |= ListView.STYLE_ICON | ListView.STYLE_FLOW_HORIZONTAL | ListView.STYLE_WRAP
		ListView.set_style(self, style)
Exemple #23
0
	def initialize(self):
		self.set_style(0)
		self.set_spacing(2)
		ListView.initialize(self)
    def _create_controls(self):
        self._download_content_length = 0
        self._download_content_type = None

        self.msg_label = Gtk.Label()

        self.list_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        # Catalogs treeview
        self.catalog_listview = Gtk.TreeView()
        self.catalog_listview.headers_clickble = True
        self.catalog_listview.hover_expand = True
        self.catalog_listview.rules_hint = True
        self._catalog_changed_id = self.catalog_listview.connect(
                'cursor-changed', self.move_down_catalog)
        self.catalog_listview.set_enable_search(False)

        self.treemodel = Gtk.ListStore(str)
        self.treemodel.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.catalog_listview.set_model(self.treemodel)

        renderer = Gtk.CellRendererText()
        renderer.set_property('wrap-mode', Pango.WrapMode.WORD)
        self.treecol = Gtk.TreeViewColumn(_('Catalogs'), renderer, text=0)
        self.treecol.set_property('clickable', True)
        self.treecol.connect('clicked', self.move_up_catalog)
        self.catalog_listview.append_column(self.treecol)
        self.bt_move_up_catalog = ButtonWithImage(_('Catalogs'))
        self.bt_move_up_catalog.hide_image()
        self.treecol.set_widget(self.bt_move_up_catalog)

        self.load_source_catalogs()

        self.tree_scroller = Gtk.ScrolledWindow(hadjustment=None,
                vadjustment=None)
        self.tree_scroller.set_policy(Gtk.PolicyType.NEVER,
                Gtk.PolicyType.AUTOMATIC)
        self.tree_scroller.add(self.catalog_listview)
        self.list_box.pack_start(self.tree_scroller, expand=False,
                fill=False, padding=0)
        self.separa = Gtk.VSeparator()
        self.list_box.pack_start(self.separa, expand=False,
                fill=False, padding=0)

        # books listview
        self.listview = ListView(self._lang_code_handler)
        self.selection_cb_id = self.listview.connect('selection-changed',
                                                     self.selection_cb)
        self.listview.set_enable_search(False)

        self.list_scroller = Gtk.ScrolledWindow(hadjustment=None,
                vadjustment=None)
        self.list_scroller.set_policy(Gtk.PolicyType.AUTOMATIC,
                Gtk.PolicyType.AUTOMATIC)
        vadjustment = self.list_scroller.get_vadjustment()
        vadjustment.connect('value-changed',
                self.__vadjustment_value_changed_cb)
        self.list_scroller.add(self.listview)
        self.list_box.pack_start(self.list_scroller, expand=True,
                fill=True, padding=0)

        self.scrolled = Gtk.ScrolledWindow()
        self.scrolled.set_policy(Gtk.PolicyType.NEVER,
                Gtk.PolicyType.AUTOMATIC)
        self.scrolled.props.shadow_type = Gtk.ShadowType.NONE
        self.textview = Gtk.TextView()
        self.textview.set_editable(False)
        self.textview.set_cursor_visible(False)
        self.textview.set_wrap_mode(Gtk.WrapMode.WORD)
        self.textview.set_justification(Gtk.Justification.LEFT)
        self.textview.set_left_margin(20)
        self.textview.set_right_margin(20)
        self.scrolled.add(self.textview)
        self.list_box.show_all()
        self.separa.hide()
        self.tree_scroller.hide()

        vbox_download = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox_format = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        format_label = Gtk.Label(label=_('Format:'))
        self.format_combo = ComboBox()
        for key in _MIMETYPES.keys():
            self.format_combo.append_item(_MIMETYPES[key], key)
        self.format_combo.set_active(0)
        self.format_combo.props.sensitive = False
        self.__format_changed_cb_id = \
                self.format_combo.connect('changed', self.__format_changed_cb)

        hbox_format.pack_start(format_label, False, False, 10)
        hbox_format.pack_start(self.format_combo, False, False, 10)
        vbox_download.pack_start(hbox_format, False, False, 10)

        self._download = Gtk.Button(_('Get Book'))
        self._download.set_image(Icon(icon_name='data-download'))
        self._download.props.sensitive = False
        self._download.connect('clicked', self.__get_book_cb)
        vbox_download.pack_start(self._download, False, False, 10)

        self.progressbox = Gtk.Box(spacing=20,
                orientation=Gtk.Orientation.HORIZONTAL)
        self.progressbar = Gtk.ProgressBar()
        self.progressbar.set_fraction(0.0)
        self.progressbox.pack_start(self.progressbar, expand=True, fill=True,
                padding=0)
        self.cancel_btn = Gtk.Button(stock=Gtk.STOCK_CANCEL)
        self.cancel_btn.set_image(Icon(icon_name='dialog-cancel'))
        self.cancel_btn.connect('clicked', self.__cancel_btn_clicked_cb)
        self.progressbox.pack_start(self.cancel_btn, expand=False,
                fill=False, padding=0)
        vbox_download.pack_start(self.progressbox, False, False, 10)

        bottom_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        if self.show_images:
            self.__image_downloader = None
            self.image = Gtk.Image()
            self.add_default_image()
            bottom_hbox.pack_start(self.image, False, False, 10)
        bottom_hbox.pack_start(self.scrolled, True, True, 10)
        bottom_hbox.pack_start(vbox_download, False, False, 10)
        bottom_hbox.show_all()

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox.pack_start(self.msg_label, False, False, 10)
        vbox.pack_start(self.list_box, True, True, 0)
        vbox.pack_start(bottom_hbox, False, False, 10)
        self.set_canvas(vbox)
        self.listview.show()
        vbox.show()
        self.list_scroller.show()
        self.progress_hide()
        self.show_message(
                _('Enter words from the Author or Title to begin search.'))

        self._books_toolbar.search_entry.grab_focus()
        if len(self.catalogs) > 0:
            self.bt_catalogs.set_active(True)
def test_all_methods_added():
    dv = set(dir(ListView(None, None)))
    for k in dir([]):
        assert k in dv
Exemple #26
0
    def __init__(self, panelmanager, settings):
        """Create PanelListView.

        Arguments
        panelmanager -- the panel manager that has the panels on which the objects 
                        will be visualized
        settings -- settings object containing font settings
        """

        ListView.__init__(self, evPanelItemSelected)
        
        self._canvas = panelmanager.canvas
        self._eventgenerator = panelmanager.canvas
        self._fntText = getFont(settings.fontname, settings.fontsize, settings.fontstyle)
        self._itemdatatuples = []
        self._uids = []
        
        panel = panelmanager.panels[0]
        
        color = panel.center['bg']
        height = panel.center['height']
        #padding = 5
        padding = (height - 4 * settings.fontsize) / 4
        cwrap = panel.center['width'] - 2 * padding
        rwrap = panel.right['width'] - 2 * padding
        ctr = 0

        for i in panelmanager.panels:
            magazine = tki.StringVar()
            blog = tki.StringVar()
            blogexists = tki.StringVar()

            i.left.columnconfigure(0, weight = 1)
            i.left.rowconfigure(0, weight = 1)
            lblImage = tki.Label(i.left)
            lblImage.grid()

            i.center.columnconfigure(0, weight = 1)
            i.center.rowconfigure(0, weight = 1)
            i.center.rowconfigure(1, weight = 1)
            
            l = tki.Label(i.center, textvariable = magazine, font = self._fntText, wraplength = cwrap, justify="left", bg = color)
            l.grid(row = 0, column = 0, sticky = tki.W)
            #l.grid(row = 0, column = 0, padx = padding, pady = padding, sticky = tki.W)
            #l.grid(row = 0, column = 0, padx = padding, pady = padding, sticky = tki.W)
            l = tki.Label(i.center, textvariable = blog, font = self._fntText, wraplength = cwrap, justify="left", bg = color)
            l.grid(row = 1, column = 0, sticky = tki.W)
            
            i.right.columnconfigure(0, weight = 1)
            i.right.rowconfigure(0, weight = 1)
            
            
            b = tki.Button(i.right, text = lang[lng.txtShowBlogpost], font = self._fntText, bg = color)
            b.grid(row = 0, column = 0, padx = padding, pady = padding, sticky = tki.W)
            b.index = ctr
            b.bind("<ButtonRelease-1>", self._ehClick)

#            l = tki.Label(i.right, textvariable = blogexists, font = self._fntText, wraplength = rwrap, justify="left", bg = color)
#            l.grid(row = 0, column = 0, padx = padding, pady = padding, sticky = tki.W)
#            l.index = ctr
#            l.bind("<Button-1>", self._ehClick)

            ctr += 1
            self._itemdatatuples.append((magazine, blog, blogexists, lblImage))
            self._uids.append(i.uid)            
            
        self._itemcount = ctr
Exemple #27
0
 def set_style(self, style):
     self.__style = style
     ListView.set_style(self, style)
class GetIABooksActivity(activity.Activity):

    def __init__(self, handle):
        "The entry point to the Activity"
        activity.Activity.__init__(self, handle, False)
        self.max_participants = 1

        self._sequence = 0
        self.selected_book = None
        self.queryresults = None
        self._getter = None
        self.show_images = True
        self.languages = {}
        self._lang_code_handler = languagenames.LanguageNames()
        self.catalogs_configuration = {}
        self.catalog_history = []

        if os.path.exists('/etc/get-books.cfg'):
            self._read_configuration('/etc/get-books.cfg')
        else:
            self._read_configuration()

        toolbar_box = ToolbarBox()
        activity_button = ToolButton()
        color = profile.get_color()
        bundle = ActivityBundle(activity.get_bundle_path())
        icon = Icon(file=bundle.get_icon(), xo_color=color)
        activity_button.set_icon_widget(icon)
        activity_button.show()

        toolbar_box.toolbar.insert(activity_button, 0)
        self._add_search_controls(toolbar_box.toolbar)

        separator = Gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(True)
        toolbar_box.toolbar.insert(separator, -1)

        toolbar_box.toolbar.insert(StopButton(self), -1)

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show_all()
        self._books_toolbar = toolbar_box.toolbar

        self._create_controls()

        self.using_powerd = os.access(POWERD_INHIBIT_DIR, os.W_OK)

        self.__book_downloader = self.__image_downloader = None

    def get_path(self):
        self._sequence += 1
        return os.path.join(self.get_activity_root(),
                            'instance', '%03d.tmp' % self._sequence)

    def _inhibit_suspend(self):
        if self.using_powerd:
            fd = open(POWERD_INHIBIT_DIR + "/%u" % os.getpid(), 'w')
            logging.error("inhibit_suspend file is %s", (POWERD_INHIBIT_DIR \
                    + "/%u" % os.getpid()))
            fd.close()
            return True

        return False

    def _allow_suspend(self):
        if self.using_powerd:
            if os.path.exists(POWERD_INHIBIT_DIR + "/%u" % os.getpid()):
                os.unlink(POWERD_INHIBIT_DIR + "/%u" % os.getpid())
            logging.error("allow_suspend unlinking %s", (POWERD_INHIBIT_DIR \
                    + "/%u" % os.getpid()))
            return True

        return False

    def _read_configuration(self, file_name='get-books.cfg'):
        logging.error('Reading configuration from file %s', file_name)
        config = ConfigParser.ConfigParser()
        config.readfp(open(file_name))
        if config.has_option('GetBooks', 'show_images'):
            self.show_images = config.getboolean('GetBooks', 'show_images')
        self.languages = {}
        if config.has_option('GetBooks', 'languages'):
            languages_param = config.get('GetBooks', 'languages')
            for language in languages_param.split(','):
                lang_code = language.strip()
                if len(lang_code) > 0:
                    self.languages[lang_code] = \
                    self._lang_code_handler.get_full_language_name(lang_code)

        for section in config.sections():
            if section != 'GetBooks' and not section.startswith('Catalogs'):
                name = config.get(section, 'name')
                _SOURCES[section] = name
                repo_config = {}
                repo_config['query_uri'] = config.get(section, 'query_uri')
                repo_config['opds_cover'] = config.get(section, 'opds_cover')
                if config.has_option(section, 'summary_field'):
                    repo_config['summary_field'] = \
                        config.get(section, 'summary_field')
                else:
                    repo_config['summary_field'] = None
                if config.has_option(section, 'blacklist'):
                    blacklist = config.get(section, 'blacklist')
                    repo_config['blacklist'] = blacklist.split(',')
                    # TODO strip?
                else:
                    repo_config['blacklist'] = []

                _SOURCES_CONFIG[section] = repo_config

        logging.error('_SOURCES %s', pformat(_SOURCES))
        logging.error('_SOURCES_CONFIG %s', pformat(_SOURCES_CONFIG))

        for section in config.sections():
            if section.startswith('Catalogs'):
                catalog_source = section.split('_')[1]
                if not catalog_source in _SOURCES_CONFIG:
                    logging.error('There are not a source for the catalog ' +
                            'section  %s', section)
                    break
                source_config = _SOURCES_CONFIG[catalog_source]
                opds_cover = source_config['opds_cover']
                for catalog in config.options(section):
                    catalog_config = {}
                    catalog_config['query_uri'] = config.get(section, catalog)
                    catalog_config['opds_cover'] = opds_cover
                    catalog_config['source'] = catalog_source
                    catalog_config['name'] = catalog
                    catalog_config['summary_field'] = \
                        source_config['summary_field']
                    self.catalogs_configuration[catalog] = catalog_config

        self.source = _SOURCES_CONFIG.keys()[0]

        self.filter_catalogs_by_source()

        logging.error('languages %s', pformat(self.languages))
        logging.error('catalogs %s', pformat(self.catalogs))

    def _add_search_controls(self, toolbar):
        book_search_item = Gtk.ToolItem()
        toolbar.search_entry = iconentry.IconEntry()
        toolbar.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                'system-search')
        toolbar.search_entry.add_clear_button()
        toolbar.search_entry.connect('activate',
                self.__search_entry_activate_cb)
        width = int(Gdk.Screen.width() / 4)
        toolbar.search_entry.set_size_request(width, -1)
        book_search_item.add(toolbar.search_entry)
        toolbar.search_entry.show()
        toolbar.insert(book_search_item, -1)
        book_search_item.show()

        toolbar.source_combo = ComboBox()
        toolbar.source_combo.props.sensitive = True
        toolbar.source_changed_cb_id = \
            toolbar.source_combo.connect('changed', self.__source_changed_cb)
        combotool = ToolComboBox(toolbar.source_combo)
        toolbar.insert(combotool, -1)
        combotool.show()

        self.bt_catalogs = ToggleToolButton('books')
        self.bt_catalogs.set_tooltip(_('Catalogs'))
        toolbar.insert(self.bt_catalogs, -1)
        self.bt_catalogs.connect('toggled', self.__toggle_cats_cb)
        if len(self.catalogs) > 0:
            self.bt_catalogs.show()

        if len(self.languages) > 0:
            toolbar.config_toolbarbutton = ToolbarButton()
            toolbar.config_toolbarbutton.props.icon_name = 'preferences-system'
            toolbar.config_toolbarbox = Gtk.Toolbar()
            toolbar.config_toolbarbutton.props.page = toolbar.config_toolbarbox
            toolbar.language_combo = ComboBox()
            toolbar.language_combo.props.sensitive = True
            combotool = ToolComboBox(toolbar.language_combo)
            toolbar.language_combo.append_item('all', _('Any language'))
            for key in self.languages.keys():
                toolbar.language_combo.append_item(key, self.languages[key])
            toolbar.language_combo.set_active(0)
            toolbar.config_toolbarbutton.props.page.insert(combotool, -1)
            toolbar.insert(toolbar.config_toolbarbutton, -1)
            toolbar.config_toolbarbutton.show()
            combotool.show()
            toolbar.language_changed_cb_id = \
                toolbar.language_combo.connect('changed',
                self.__language_changed_cb)

        self._device_manager = devicemanager.DeviceManager()
        self._refresh_sources(toolbar)
        self._device_manager.connect('device-changed',
                self.__device_changed_cb)

        toolbar.search_entry.grab_focus()
        return toolbar

    def __bt_catalogs_clicked_cb(self, button):
        palette = button.get_palette()
        palette.popup(immediate=True, state=palette.SECONDARY)

    def __switch_catalog_cb(self, catalog_name):
        catalog_config = self.catalogs[catalog_name.decode('utf-8')]
        self.__activate_catalog_cb(None, catalog_config)

    def __activate_catalog_cb(self, menu, catalog_config):
        query_language = self.get_query_language()

        self.enable_button(False)
        self.clear_downloaded_bytes()
        self.book_selected = False
        self.listview.handler_block(self.selection_cb_id)
        self.listview.clear()
        self.listview.handler_unblock(self.selection_cb_id)
        logging.error('SOURCE %s', catalog_config['source'])
        self._books_toolbar.search_entry.props.text = ''
        self.source = catalog_config['source']
        position = _SOURCES_CONFIG[self.source]['position']
        self._books_toolbar.source_combo.set_active(position)

        if self.queryresults is not None:
            self.queryresults.cancel()
            self.queryresults = None

        self.queryresults = opds.RemoteQueryResult(catalog_config,
                '', query_language)
        self.show_message(_('Performing lookup, please wait...'))
        # README: I think we should create some global variables for
        # each cursor that we are using to avoid the creation of them
        # every time that we want to change it
        self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))

        self.queryresults.connect('updated', self.__query_updated_cb)

    def update_format_combo(self, links):
        self.format_combo.handler_block(self.__format_changed_cb_id)
        self.format_combo.remove_all()
        for key in _MIMETYPES.keys():
            if _MIMETYPES[key] in links.keys():
                self.format_combo.append_item(_MIMETYPES[key], key)
        self.format_combo.set_active(0)
        self.format_combo.handler_unblock(self.__format_changed_cb_id)

    def get_search_terms(self):
        return self._books_toolbar.search_entry.props.text

    def __device_changed_cb(self, mgr):
        logging.debug('Device was added/removed')
        self._refresh_sources(self._books_toolbar)

    def _refresh_sources(self, toolbar):
        toolbar.source_combo.handler_block(toolbar.source_changed_cb_id)

        #TODO: Do not blindly clear this
        toolbar.source_combo.remove_all()

        position = 0
        for key in _SOURCES.keys():
            toolbar.source_combo.append_item(_SOURCES[key], key,
                icon_name='internet-icon')
            _SOURCES_CONFIG[key]['position'] = position
            position = position + 1

        # Add menu for local books
        if len(_SOURCES) > 0:
            toolbar.source_combo.append_separator()
        toolbar.source_combo.append_item('local_books', _('My books'),
                icon_name='activity-journal')

        devices = self._device_manager.get_devices()

        first_device = True
        for device_name in devices:
            device = devices[device_name]
            logging.debug('device %s', device)
            if device['removable']:
                mount_point = device['mount_path']
                label = device['label']
                if label == '' or label is None:
                    capacity = device['size']
                    label = (_('%.2f GB Volume') % (capacity / (1024.0 ** 3)))
                logging.debug('Adding device %s', (label))
                if first_device:
                    toolbar.source_combo.append_separator()
                    first_device = False
                toolbar.source_combo.append_item(mount_point, label)

        toolbar.source_combo.set_active(0)
        toolbar.source_combo.handler_unblock(toolbar.source_changed_cb_id)

    def __format_changed_cb(self, combo):
        self.show_book_data(False)

    def __language_changed_cb(self, combo):
        self.find_books(self.get_search_terms())

    def __search_entry_activate_cb(self, entry):
        self.find_books(self.get_search_terms())

    def __get_book_cb(self, button):
        self.get_book()

    def enable_button(self,  state):
        self._download.props.sensitive = state
        self.format_combo.props.sensitive = state

    def move_up_catalog(self, treeview):
        len_cat = len(self.catalog_history)
        if len_cat == 1:
            return
        else:
            # move a level up the tree
            self.catalog_listview.handler_block(self._catalog_changed_id)
            self.catalog_history.pop()
            len_cat -= 1
            if(len_cat == 1):
                title = self.catalog_history[0]['title']
                self.bt_move_up_catalog.set_label(title)
                self.bt_move_up_catalog.hide_image()
            else:
                title = self.catalog_history[len_cat - 1]['title']
                self.bt_move_up_catalog.set_label(title)
                self.bt_move_up_catalog.show_image()
            self.catalogs = self.catalog_history[len_cat - 1]['catalogs']
            if len(self.catalogs) > 0:
                self.path_iter = {}
                self.categories = []
                for key in self.catalogs.keys():
                    self.categories.append({'text': key, 'dentro': []})
                self.treemodel.clear()
                for p in self.categories:
                    self.path_iter[p['text']] = \
                            self.treemodel.append([p['text']])
            self.catalog_listview.handler_unblock(self._catalog_changed_id)

    def move_down_catalog(self, treeview):
        treestore, coldex = \
                self.catalog_listview.get_selection().get_selected()
        len_cat = len(self.catalog_history)
        if len_cat > 0 and self.catalog_history[len_cat - 1]['catalogs'] == []:
            self.catalog_history.pop()
            len_cat = len(self.catalog_history)

        # README: when the Activity starts by default there is nothing
        # selected and this signal is called, so we have to avoid this
        # 'append' because it fails
        if coldex is not None:
            self.catalog_history.append(
                    {'title': treestore.get_value(coldex, 0), 'catalogs': []})
            self.__switch_catalog_cb(treestore.get_value(coldex, 0))

    def _sort_logfile(self, treemodel, itera, iterb):
        a = treemodel.get_value(itera, 0)
        b = treemodel.get_value(iterb, 0)
        if a == None or b == None:
            return 0
        a = a.lower()
        b = b.lower()
        if a > b:
            return 1
        if a < b:
            return -1
        return 0

    def __toggle_cats_cb(self, button):
        if button.get_active():
            self.tree_scroller.show_all()
            self.separa.show()
        else:
            self.tree_scroller.hide()
            self.separa.hide()

    def _create_controls(self):
        self._download_content_length = 0
        self._download_content_type = None

        self.msg_label = Gtk.Label()

        self.list_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        # Catalogs treeview
        self.catalog_listview = Gtk.TreeView()
        self.catalog_listview.headers_clickble = True
        self.catalog_listview.hover_expand = True
        self.catalog_listview.rules_hint = True
        self._catalog_changed_id = self.catalog_listview.connect(
                'cursor-changed', self.move_down_catalog)
        self.catalog_listview.set_enable_search(False)

        self.treemodel = Gtk.ListStore(str)
        self.treemodel.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.catalog_listview.set_model(self.treemodel)

        renderer = Gtk.CellRendererText()
        renderer.set_property('wrap-mode', Pango.WrapMode.WORD)
        self.treecol = Gtk.TreeViewColumn(_('Catalogs'), renderer, text=0)
        self.treecol.set_property('clickable', True)
        self.treecol.connect('clicked', self.move_up_catalog)
        self.catalog_listview.append_column(self.treecol)
        self.bt_move_up_catalog = ButtonWithImage(_('Catalogs'))
        self.bt_move_up_catalog.hide_image()
        self.treecol.set_widget(self.bt_move_up_catalog)

        self.load_source_catalogs()

        self.tree_scroller = Gtk.ScrolledWindow(hadjustment=None,
                vadjustment=None)
        self.tree_scroller.set_policy(Gtk.PolicyType.NEVER,
                Gtk.PolicyType.AUTOMATIC)
        self.tree_scroller.add(self.catalog_listview)
        self.list_box.pack_start(self.tree_scroller, expand=False,
                fill=False, padding=0)
        self.separa = Gtk.VSeparator()
        self.list_box.pack_start(self.separa, expand=False,
                fill=False, padding=0)

        # books listview
        self.listview = ListView(self._lang_code_handler)
        self.selection_cb_id = self.listview.connect('selection-changed',
                                                     self.selection_cb)
        self.listview.set_enable_search(False)

        self.list_scroller = Gtk.ScrolledWindow(hadjustment=None,
                vadjustment=None)
        self.list_scroller.set_policy(Gtk.PolicyType.AUTOMATIC,
                Gtk.PolicyType.AUTOMATIC)
        vadjustment = self.list_scroller.get_vadjustment()
        vadjustment.connect('value-changed',
                self.__vadjustment_value_changed_cb)
        self.list_scroller.add(self.listview)
        self.list_box.pack_start(self.list_scroller, expand=True,
                fill=True, padding=0)

        self.scrolled = Gtk.ScrolledWindow()
        self.scrolled.set_policy(Gtk.PolicyType.NEVER,
                Gtk.PolicyType.AUTOMATIC)
        self.scrolled.props.shadow_type = Gtk.ShadowType.NONE
        self.textview = Gtk.TextView()
        self.textview.set_editable(False)
        self.textview.set_cursor_visible(False)
        self.textview.set_wrap_mode(Gtk.WrapMode.WORD)
        self.textview.set_justification(Gtk.Justification.LEFT)
        self.textview.set_left_margin(20)
        self.textview.set_right_margin(20)
        self.scrolled.add(self.textview)
        self.list_box.show_all()
        self.separa.hide()
        self.tree_scroller.hide()

        vbox_download = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox_format = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        format_label = Gtk.Label(label=_('Format:'))
        self.format_combo = ComboBox()
        for key in _MIMETYPES.keys():
            self.format_combo.append_item(_MIMETYPES[key], key)
        self.format_combo.set_active(0)
        self.format_combo.props.sensitive = False
        self.__format_changed_cb_id = \
                self.format_combo.connect('changed', self.__format_changed_cb)

        hbox_format.pack_start(format_label, False, False, 10)
        hbox_format.pack_start(self.format_combo, False, False, 10)
        vbox_download.pack_start(hbox_format, False, False, 10)

        self._download = Gtk.Button(_('Get Book'))
        self._download.set_image(Icon(icon_name='data-download'))
        self._download.props.sensitive = False
        self._download.connect('clicked', self.__get_book_cb)
        vbox_download.pack_start(self._download, False, False, 10)

        self.progressbox = Gtk.Box(spacing=20,
                orientation=Gtk.Orientation.HORIZONTAL)
        self.progressbar = Gtk.ProgressBar()
        self.progressbar.set_fraction(0.0)
        self.progressbox.pack_start(self.progressbar, expand=True, fill=True,
                padding=0)
        self.cancel_btn = Gtk.Button(stock=Gtk.STOCK_CANCEL)
        self.cancel_btn.set_image(Icon(icon_name='dialog-cancel'))
        self.cancel_btn.connect('clicked', self.__cancel_btn_clicked_cb)
        self.progressbox.pack_start(self.cancel_btn, expand=False,
                fill=False, padding=0)
        vbox_download.pack_start(self.progressbox, False, False, 10)

        bottom_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        if self.show_images:
            self.__image_downloader = None
            self.image = Gtk.Image()
            self.add_default_image()
            bottom_hbox.pack_start(self.image, False, False, 10)
        bottom_hbox.pack_start(self.scrolled, True, True, 10)
        bottom_hbox.pack_start(vbox_download, False, False, 10)
        bottom_hbox.show_all()

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox.pack_start(self.msg_label, False, False, 10)
        vbox.pack_start(self.list_box, True, True, 0)
        vbox.pack_start(bottom_hbox, False, False, 10)
        self.set_canvas(vbox)
        self.listview.show()
        vbox.show()
        self.list_scroller.show()
        self.progress_hide()
        self.show_message(
                _('Enter words from the Author or Title to begin search.'))

        self._books_toolbar.search_entry.grab_focus()
        if len(self.catalogs) > 0:
            self.bt_catalogs.set_active(True)

    def progress_hide(self):
        self.clear_downloaded_bytes()
        self.progressbar.set_sensitive(False)
        self.cancel_btn.set_sensitive(False)

    def progress_show(self):
        self.progressbar.set_sensitive(True)
        self.cancel_btn.set_sensitive(True)

    def filter_catalogs_by_source(self):
        self.catalogs = {}
        for catalog_key in self.catalogs_configuration:
            catalog = self.catalogs_configuration[catalog_key]
            if catalog['source'] == self.source:
                self.catalogs[catalog_key] = catalog

    def load_source_catalogs(self):
        self.filter_catalogs_by_source()

        if len(self.catalogs) > 0:
            self.categories = []
            self.path_iter = {}
            self.catalog_history = []
            self.catalog_history.append({'title': _('Catalogs'),
                'catalogs': self.catalogs})
            for key in self.catalogs.keys():
                self.categories.append({'text': key, 'dentro': []})
            self.treemodel.clear()

            for p in self.categories:
                self.path_iter[p['text']] = self.treemodel.append([p['text']])

    def can_close(self):
        if self.queryresults is not None:
            self.queryresults.cancel()
            self.queryresults = None
        return True

    def selection_cb(self, widget):
        selected_book = self.listview.get_selected_book()
        if self.source == 'local_books':
            if selected_book:
                self.selected_book = selected_book
                self._download.hide()
                self.show_book_data()
                self._object_id = selected_book.get_object_id()
                self._show_journal_alert(_('Selected book'),
                        self.selected_title)
        else:
            self.clear_downloaded_bytes()
            if selected_book:
                self.update_format_combo(selected_book.get_types())
                self.selected_book = selected_book
                self._download.show()
                self.show_book_data()

    def show_message(self, text):
        self.msg_label.set_text(text)
        self.msg_label.show()

    def hide_message(self):
        self.msg_label.hide()

    def show_book_data(self, load_image=True):
        self.selected_title = self.selected_book.get_title()
        book_data = _('Title:\t\t') + self.selected_title + '\n'
        self.selected_author = self.selected_book.get_author()
        book_data += _('Author:\t\t') + self.selected_author + '\n'
        self.selected_publisher = self.selected_book.get_publisher()
        self.selected_summary = self.selected_book.get_summary()
        if (self.selected_summary is not 'Unknown'):
            book_data += _('Summary:\t') + self.selected_summary + '\n'
        self.selected_language_code = self.selected_book.get_language()
        if self.selected_language_code != '':
            try:
                self.selected_language = \
                    self._lang_code_handler.get_full_language_name(
                        self.selected_book.get_language())
            except:
                self.selected_language = self.selected_book.get_language()
            book_data += _('Language:\t') + self.selected_language + '\n'
        book_data += _('Publisher:\t') + self.selected_publisher + '\n'
        textbuffer = self.textview.get_buffer()
        textbuffer.set_text('\n' + book_data)
        self.enable_button(True)

        # Cover Image
        self.exist_cover_image = False
        if self.show_images and load_image:
            if self.source == 'local_books':
                cover_image_buffer = self.get_journal_entry_cover_image(
                        self.selected_book.get_object_id())
                if (cover_image_buffer):
                    self.add_image_buffer(
                        self.get_pixbuf_from_buffer(cover_image_buffer))
                else:
                    self.add_default_image()
            else:
                url_image = self.selected_book.get_image_url()
                self.add_default_image()
                if url_image:
                    self.download_image(url_image.values()[0])

    def get_pixbuf_from_buffer(self, image_buffer):
        """Buffer To Pixbuf"""
        pixbuf_loader = GdkPixbuf.PixbufLoader()
        pixbuf_loader.write(image_buffer)
        pixbuf_loader.close()
        pixbuf = pixbuf_loader.get_pixbuf()
        return pixbuf

    def get_journal_entry_cover_image(self, object_id):
        ds_object = datastore.get(object_id)
        if 'cover_image' in ds_object.metadata:
            cover_data = ds_object.metadata['cover_image']
            return base64.b64decode(cover_data)
        elif 'preview' in ds_object.metadata:
            return ds_object.metadata['preview']
        else:
            return ""

    def download_image(self,  url):
        self._inhibit_suspend()
        self.progress_show()
        if self.__image_downloader is not None:
            self.__image_downloader.stop()
        self.__image_downloader = opds.FileDownloader(url, self.get_path())
        self.__image_downloader.connect('updated', self.__image_updated_cb)
        self.__image_downloader.connect('progress', self.__image_progress_cb)

    def __image_updated_cb(self, downloader, path, content_type):
        if path is not None:
            self.add_image(path)
            self.exist_cover_image = True
            os.remove(path)
        else:
            self.add_default_image()
        self.__image_downloader = None
        GObject.timeout_add(500, self.progress_hide)
        self._allow_suspend()

    def __image_progress_cb(self, downloader, progress):
        self.progressbar.set_fraction(progress)
        while Gtk.events_pending():
            Gtk.main_iteration()

    def add_default_image(self):
        file_path = os.path.join(activity.get_bundle_path(),
                'generic_cover.png')
        self.add_image(file_path)

    def add_image(self, file_path):
        pixbuf = GdkPixbuf.Pixbuf.new_from_file(file_path)
        self.add_image_buffer(pixbuf)

    def add_image_buffer(self, pixbuf):
        image_height = int(Gdk.Screen.height() / 4)
        image_width = image_height / 3 * 2
        width, height = pixbuf.get_width(), pixbuf.get_height()
        scale = 1
        if (width > image_width) or (height > image_height):
            scale_x = image_width / float(width)
            scale_y = image_height / float(height)
            scale = min(scale_x, scale_y)

        pixbuf2 = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB,
                pixbuf.get_has_alpha(), pixbuf.get_bits_per_sample(),
                image_width, image_height)

        pixbuf2.fill(style.COLOR_PANEL_GREY.get_int())

        margin_x = int((image_width - (width * scale)) / 2)
        margin_y = int((image_height - (height * scale)) / 2)

        pixbuf.scale(pixbuf2, margin_x, margin_y,
                image_width - (margin_x * 2), image_height - (margin_y * 2),
                margin_x, margin_y, scale, scale,
                GdkPixbuf.InterpType.BILINEAR)

        self.image.set_from_pixbuf(pixbuf2)

    def get_query_language(self):
        query_language = None
        if len(self.languages) > 0:
            query_language = self._books_toolbar.language_combo.props.value
        return query_language

    def find_books(self, search_text=''):
        self._inhibit_suspend()
        self.source = self._books_toolbar.source_combo.props.value

        query_language = self.get_query_language()

        self.enable_button(False)
        self.clear_downloaded_bytes()
        self.book_selected = False
        self.listview.handler_block(self.selection_cb_id)
        self.listview.clear()
        self.listview.handler_unblock(self.selection_cb_id)

        if self.queryresults is not None:
            self.queryresults.cancel()
            self.queryresults = None

        if self.source == 'local_books':
            self.listview.populate_with_books(
                    self.get_entrys_info(search_text))
        else:
            if search_text is None:
                return
            elif len(search_text) < 3:
                self.show_message(_('You must enter at least 3 letters.'))
                self._books_toolbar.search_entry.grab_focus()
                return
            if self.source == 'Internet Archive':
                self.queryresults = \
                        opds.InternetArchiveQueryResult(search_text,
                                                        self.get_path())
            elif self.source in _SOURCES_CONFIG:
                repo_configuration = _SOURCES_CONFIG[self.source]
                self.queryresults = opds.RemoteQueryResult(repo_configuration,
                        search_text, query_language)
            else:
                self.queryresults = opds.LocalVolumeQueryResult(self.source,
                        search_text, query_language)

            self.show_message(_('Performing lookup, please wait...'))
            self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))
            self.queryresults.connect('updated', self.__query_updated_cb)

    def __query_updated_cb(self, query, midway):
        self.listview.populate(self.queryresults)
        if hasattr(self.queryresults, '_feedobj') and \
           'bozo_exception' in self.queryresults._feedobj:
            # something went wrong and we have to inform about this
            bozo_exception = self.queryresults._feedobj.bozo_exception
            if isinstance(bozo_exception, urllib2.URLError):
                if isinstance(bozo_exception.reason, socket.gaierror):
                    if bozo_exception.reason.errno == -2:
                        self.show_message(_('Could not reach the server. '
                            'Maybe you are not connected to the network'))
                        self.window.set_cursor(None)
                        return
            self.show_message(_('There was an error downloading the list.'))
        elif (len(self.queryresults.get_catalog_list()) > 0):
            self.show_message(_('New catalog list %s was found') \
                % self.queryresults._configuration["name"])
            self.catalogs_updated(query, midway)
        elif len(self.queryresults) == 0:
            self.show_message(_('Sorry, no books could be found.'))
        if not midway and len(self.queryresults) > 0:
            self.hide_message()
            query_language = self.get_query_language()
            if query_language != 'all' and query_language != 'en':
                # the bookserver send english books if there are not books in
                # the requested language
                only_english = True
                for book in self.queryresults.get_book_list():
                    if book.get_language() == query_language:
                        only_english = False
                        break
                if only_english:
                    self.show_message(
                            _('Sorry, we only found english books.'))
        self.get_window().set_cursor(None)
        self._allow_suspend()

    def catalogs_updated(self, query, midway):
        self.catalogs = {}
        for catalog_item in self.queryresults.get_catalog_list():
            logging.debug('Add catalog %s', catalog_item.get_title())
            catalog_config = {}
            download_link = ''
            download_links = catalog_item.get_download_links()
            for link in download_links.keys():
                download_link = download_links[link]
                break
            catalog_config['query_uri'] = download_link
            catalog_config['opds_cover'] = \
                catalog_item._configuration['opds_cover']
            catalog_config['source'] = catalog_item._configuration['source']
            source_config = _SOURCES_CONFIG[catalog_config['source']]
            catalog_config['name'] = catalog_item.get_title()
            catalog_config['summary_field'] = \
                catalog_item._configuration['summary_field']
            if catalog_item.get_title() in source_config['blacklist']:
                logging.debug('Catalog "%s" is in blacklist',
                    catalog_item.get_title())
            else:
                self.catalogs[catalog_item.get_title().strip()] = \
                        catalog_config

        if len(self.catalogs) > 0:
            len_cat = len(self.catalog_history)
            self.catalog_history[len_cat - 1]['catalogs'] = self.catalogs
            self.path_iter = {}
            self.categories = []
            for key in self.catalogs.keys():
                self.categories.append({'text': key, 'dentro': []})
            self.treemodel.clear()
            for p in self.categories:
                self.path_iter[p['text']] = \
                        self.treemodel.append([p['text']])

            title = self.catalog_history[len_cat - 1]['title']
            self.bt_move_up_catalog.set_label(title)
            self.bt_move_up_catalog.show_image()

        else:
            self.catalog_history.pop()

    def __source_changed_cb(self, widget):
        search_terms = self.get_search_terms()
        if search_terms == '':
            self.find_books(None)
        else:
            self.find_books(search_terms)
        # enable/disable catalogs button if configuration is available
        self.source = self._books_toolbar.source_combo.props.value

        # Get catalogs for this source
        self.load_source_catalogs()

        if len(self.catalogs) > 0:
            self.bt_catalogs.show()
            self.bt_catalogs.set_active(True)
        else:
            self.bt_catalogs.set_active(False)
            self.bt_catalogs.hide()

    def __vadjustment_value_changed_cb(self, vadjustment):

        if not self.queryresults.is_ready():
            return
        try:
            # Use various tricks to update resultset as user scrolls down
            if ((vadjustment.props.upper - vadjustment.props.lower) > 1000 \
                and (vadjustment.props.upper - vadjustment.props.value - \
                vadjustment.props.page_size) / (vadjustment.props.upper - \
                vadjustment.props.lower) < 0.3) or ((vadjustment.props.upper \
                - vadjustment.props.value
                - vadjustment.props.page_size) < 200):
                if self.queryresults.has_next():
                    self.queryresults.update_with_next()
        finally:
            return

    def __cancel_btn_clicked_cb(self, btn):
        if self.__image_downloader is not None:
            self.__image_downloader.stop()

        if self.__book_downloader is not None:
            self.__book_downloader.stop()

        self.progress_hide()
        self.enable_button(True)
        self.listview.props.sensitive = True
        self._books_toolbar.search_entry.set_sensitive(True)
        self._allow_suspend()

    def get_book(self):
        self.enable_button(False)
        self.clear_downloaded_bytes()
        self.progress_show()
        if self.source != 'local_books':
            self.selected_book.get_download_links(self.format_combo.props.value,
                                                  self.download_book,
                                                  self.get_path())

    def download_book(self,  url):
        logging.error('DOWNLOAD BOOK %s', url)
        self._inhibit_suspend()
        self.listview.props.sensitive = False
        self._books_toolbar.search_entry.set_sensitive(False)
        self.__book_downloader = opds.FileDownloader(url, self.get_path())
        self.__book_downloader.connect('updated', self.__book_updated_cb)
        self.__book_downloader.connect('progress', self.__book_progress_cb)

    def __book_updated_cb(self, downloader, path, content_type):
        self._books_toolbar.search_entry.set_sensitive(True)
        self.listview.props.sensitive = True
        self._allow_suspend()
        GObject.timeout_add(500, self.progress_hide)
        self.enable_button(True)
        self.__book_downloader = None

        if path is None:
            self._show_error_alert(_('Error: Could not download %s. ' +
                    'The path in the catalog seems to be incorrect.') %
                    self.selected_title)
            return

        if os.stat(path).st_size == 0:
            self._show_error_alert(_('Error: Could not download %s. ' +
                    'The other end sent an empty file.') %
                    self.selected_title)
            return

        if content_type.startswith('text/html'):
            self._show_error_alert(_('Error: Could not download %s. ' +
                    'The other end sent text/html instead of a book.') %
                    self.selected_title)
            return

        self.process_downloaded_book(path)

    def __book_progress_cb(self, downloader, progress):
        self.progressbar.set_fraction(progress)
        while Gtk.events_pending():
            Gtk.main_iteration()

    def clear_downloaded_bytes(self):
        self.progressbar.set_fraction(0.0)

    def process_downloaded_book(self, path):
        logging.debug("Got document %s", path)
        self.create_journal_entry(path)
        self._getter = None
        self._allow_suspend()

    def create_journal_entry(self, path):
        journal_entry = datastore.create()
        journal_title = self.selected_title
        if self.selected_author != '':
            journal_title = journal_title + ', by ' + self.selected_author
        journal_entry.metadata['title'] = journal_title
        journal_entry.metadata['title_set_by_user'] = '******'
        journal_entry.metadata['keep'] = '0'
        journal_entry.metadata['mime_type'] = \
                self.format_combo.props.value
        # Fix fake mime type for black&white pdfs
        if journal_entry.metadata['mime_type'] == _MIMETYPES['PDF BW']:
            journal_entry.metadata['mime_type'] = _MIMETYPES['PDF']

        journal_entry.metadata['buddies'] = ''
        journal_entry.metadata['icon-color'] = profile.get_color().to_string()
        textbuffer = self.textview.get_buffer()
        journal_entry.metadata['description'] = \
            textbuffer.get_text(textbuffer.get_start_iter(),
                                textbuffer.get_end_iter(), True)
        if self.exist_cover_image:
            image_buffer = self._get_preview_image_buffer()
            journal_entry.metadata['preview'] = dbus.ByteArray(image_buffer)
            image_buffer = self._get_cover_image_buffer()
            journal_entry.metadata['cover_image'] = \
                dbus.ByteArray(base64.b64encode(image_buffer))
        else:
            journal_entry.metadata['cover_image'] = ""

        journal_entry.metadata['tags'] = self.source
        journal_entry.metadata['source'] = self.source
        journal_entry.metadata['author'] = self.selected_author
        journal_entry.metadata['publisher'] = self.selected_publisher
        journal_entry.metadata['summary'] = self.selected_summary
        journal_entry.metadata['language'] = self.selected_language_code

        journal_entry.file_path = path
        datastore.write(journal_entry)
        os.remove(path)
        self.progress_hide()
        self._object_id = journal_entry.object_id
        self._show_journal_alert(_('Download completed'), self.selected_title)

    def _show_journal_alert(self, title, msg):
        _stop_alert = Alert()
        _stop_alert.props.title = title
        _stop_alert.props.msg = msg

        if _HAS_BUNDLE_LAUNCHER:
                bundle = get_bundle(object_id=self._object_id)

        if bundle is not None:
            icon = Icon(file=bundle.get_icon())
            label = _('Open with %s') % bundle.get_name()
            _stop_alert.add_button(Gtk.ResponseType.ACCEPT, label, icon)
        else:
            icon = Icon(icon_name='zoom-activity')
            label = _('Show in Journal')
            _stop_alert.add_button(Gtk.ResponseType.APPLY, label, icon)
        icon.show()

        ok_icon = Icon(icon_name='dialog-ok')
        _stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon)
        ok_icon.show()
        # Remove other alerts
        for alert in self._alerts:
            self.remove_alert(alert)

        self.add_alert(_stop_alert)
        _stop_alert.connect('response', self.__stop_response_cb)
        _stop_alert.show()

    def __stop_response_cb(self, alert, response_id):
        if response_id is Gtk.ResponseType.APPLY:
            activity.show_object_in_journal(self._object_id)
        elif response_id is Gtk.ResponseType.ACCEPT:
            launch_bundle(object_id=self._object_id)
        self.remove_alert(alert)

    def _get_preview_image_buffer(self):
        preview_width, preview_height = style.zoom(300), style.zoom(225)

        pixbuf = self.image.get_pixbuf()
        width, height = pixbuf.get_width(), pixbuf.get_height()

        scale = 1
        if (width > preview_width) or (height > preview_height):
            scale_x = preview_width / float(width)
            scale_y = preview_height / float(height)
            scale = min(scale_x, scale_y)

        pixbuf2 = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB,
                pixbuf.get_has_alpha(), pixbuf.get_bits_per_sample(),
                preview_width, preview_height)
        pixbuf2.fill(style.COLOR_WHITE.get_int())

        margin_x = int((preview_width - (width * scale)) / 2)
        margin_y = int((preview_height - (height * scale)) / 2)

        pixbuf.scale(pixbuf2, margin_x, margin_y,
                preview_width - (margin_x * 2),
                preview_height - (margin_y * 2),
                margin_x, margin_y, scale, scale,
                GdkPixbuf.InterpType.BILINEAR)

        succes, data = pixbuf2.save_to_bufferv('png', [], [])
        return data

    def _get_cover_image_buffer(self):
        pixbuf = self.image.get_pixbuf()
        succes, data = pixbuf.save_to_bufferv('png', [], [])
        return data

    def _show_error_alert(self, title, text=None):
        alert = NotifyAlert(timeout=20)
        alert.props.title = title
        alert.props.msg = text
        self.add_alert(alert)
        alert.connect('response', self._alert_cancel_cb)
        alert.show()

    def _alert_cancel_cb(self, alert, response_id):
        self.remove_alert(alert)
        self.textview.grab_focus()

    def get_entrys_info(self, query):
        books = []
        for key in _MIMETYPES.keys():
            books.extend(self.get_entry_info_format(query, _MIMETYPES[key]))
        return books

    def get_entry_info_format(self, query, mime):
        books = []
        if query is not None and len(query) > 0:
            ds_objects, num_objects = datastore.find(
                    {'mime_type': '%s' % mime,
                    'query': '*%s*' % query})
        else:
            ds_objects, num_objects = datastore.find(
                    {'mime_type': '%s' % mime})

        logging.error('Local search %d books found %s format', num_objects,
                    mime)
        for i in range(0, num_objects):
            entry = {}
            entry['title'] = ds_objects[i].metadata['title']
            entry['mime'] = ds_objects[i].metadata['mime_type']
            entry['object_id'] = ds_objects[i].object_id

            if 'author' in ds_objects[i].metadata:
                entry['author'] = ds_objects[i].metadata['author']
            else:
                entry['author'] = ''

            if 'publisher' in ds_objects[i].metadata:
                entry['dcterms_publisher'] = \
                    ds_objects[i].metadata['publisher']
            else:
                entry['dcterms_publisher'] = ''

            if 'language' in ds_objects[i].metadata:
                entry['dcterms_language'] = \
                    ds_objects[i].metadata['language']
            else:
                entry['dcterms_language'] = ''

            if 'source' in ds_objects[i].metadata:
                entry['source'] = \
                    ds_objects[i].metadata['source']
            else:
                entry['source'] = ''

            if entry['source'] in _SOURCES_CONFIG:
                repo_configuration = _SOURCES_CONFIG[entry['source']]
                summary_field = repo_configuration['summary_field']
                if 'summary' in ds_objects[i].metadata:
                    entry[summary_field] = ds_objects[i].metadata['summary']
                else:
                    entry[summary_field] = ''
            else:
                repo_configuration = None
            books.append(opds.Book(repo_configuration, entry, ''))
        return books

    def close(self,  skip_save=False):
        "Override the close method so we don't try to create a Journal entry."
        activity.Activity.close(self,  True)

    def save(self):
        pass
def test_len():
    ls = [1, 2, 3, 4, 5]
    lv = ListView(ls, lambda x: 1 < x < 5)
    assert list(lv) == [2, 3, 4]
    assert len(lv) == 3
Exemple #30
0
    def __init__(self, panelmanager, settings):
        """Create PanelListView.

        Arguments
        panelmanager -- the panel manager that has the panels on which the objects 
                        will be visualized
        settings -- settings object containing font settings
        """

        ListView.__init__(self, evPanelItemSelected)

        self._canvas = panelmanager.canvas
        self._eventgenerator = panelmanager.canvas
        self._fntText = getFont(settings.fontname, settings.fontsize,
                                settings.fontstyle)
        self._itemdatatuples = []
        self._uids = []

        panel = panelmanager.panels[0]

        color = panel.center['bg']
        height = panel.center['height']
        #padding = 5
        padding = (height - 4 * settings.fontsize) / 4
        cwrap = panel.center['width'] - 2 * padding
        rwrap = panel.right['width'] - 2 * padding
        ctr = 0

        for i in panelmanager.panels:
            magazine = tki.StringVar()
            blog = tki.StringVar()
            blogexists = tki.StringVar()

            i.left.columnconfigure(0, weight=1)
            i.left.rowconfigure(0, weight=1)
            lblImage = tki.Label(i.left)
            lblImage.grid()

            i.center.columnconfigure(0, weight=1)
            i.center.rowconfigure(0, weight=1)
            i.center.rowconfigure(1, weight=1)

            l = tki.Label(i.center,
                          textvariable=magazine,
                          font=self._fntText,
                          wraplength=cwrap,
                          justify="left",
                          bg=color)
            l.grid(row=0, column=0, sticky=tki.W)
            #l.grid(row = 0, column = 0, padx = padding, pady = padding, sticky = tki.W)
            #l.grid(row = 0, column = 0, padx = padding, pady = padding, sticky = tki.W)
            l = tki.Label(i.center,
                          textvariable=blog,
                          font=self._fntText,
                          wraplength=cwrap,
                          justify="left",
                          bg=color)
            l.grid(row=1, column=0, sticky=tki.W)

            i.right.columnconfigure(0, weight=1)
            i.right.rowconfigure(0, weight=1)

            b = tki.Button(i.right,
                           text=lang[lng.txtShowBlogpost],
                           font=self._fntText,
                           bg=color)
            b.grid(row=0, column=0, padx=padding, pady=padding, sticky=tki.W)
            b.index = ctr
            b.bind("<ButtonRelease-1>", self._ehClick)

            #            l = tki.Label(i.right, textvariable = blogexists, font = self._fntText, wraplength = rwrap, justify="left", bg = color)
            #            l.grid(row = 0, column = 0, padx = padding, pady = padding, sticky = tki.W)
            #            l.index = ctr
            #            l.bind("<Button-1>", self._ehClick)

            ctr += 1
            self._itemdatatuples.append((magazine, blog, blogexists, lblImage))
            self._uids.append(i.uid)

        self._itemcount = ctr
Exemple #31
0
	def set_style(self, style):
		self.__style = style
		ListView.set_style(self, style)