示例#1
0
def combo_factory(combo_array,
                  toolbar,
                  callback,
                  cb_arg=None,
                  tooltip=None,
                  default=None):
    '''Factory for making a toolbar combo box'''
    combo = ComboBox()
    if tooltip is not None and hasattr(combo, 'set_tooltip_text'):
        combo.set_tooltip_text(tooltip)
    if cb_arg is not None:
        combo.connect('changed', callback, cb_arg)
    else:
        combo.connect('changed', callback)
    for i, selection in enumerate(combo_array):
        combo.append_item(i, selection, None)
    combo.show()
    toolitem = Gtk.ToolItem()
    toolitem.add(combo)
    if hasattr(toolbar, 'insert'):  # the main toolbar
        toolbar.insert(toolitem, -1)
    else:  # or a secondary toolbar
        toolbar.props.page.insert(toolitem, -1)
    toolitem.show()
    if default is not None:
        combo.set_active(combo_array.index(default))
    return combo
示例#2
0
    def __init__(self, activity):
        Gtk.Toolbar.__init__(self)
        self._activity = activity
        self._speech = SpeechManager()
        self._is_paused = False

        self.load_speech_parameters()

        self._voices = self._speech.get_all_voices()  # a dictionary

        locale = os.environ.get('LANG', '')
        language_location = locale.split('.', 1)[0].lower()
        language = language_location.split('_')[0]
        # if the language is es but not es_es default to es_la (latin voice)
        if language == 'es' and language_location != 'es_es':
            language_location = 'es_la'

        self._voice = 'en_us'
        if language_location in self._voices:
            self._voice = language_location
        elif language in self._voices:
            self._voice = language

        voice_names = []
        for language, name in self._voices.iteritems():
            voice_names.append((language, name))
        voice_names.sort(self._compare_voice)

        # Play button
        self._play_button = ToggleToolButton('media-playback-start')
        self._play_button.show()
        self._play_button.connect('toggled', self._play_toggled_cb)
        self.insert(self._play_button, -1)
        self._play_button.set_tooltip(_('Play / Pause'))

        # Stop button
        self._stop_button = ToolButton('media-playback-stop')
        self._stop_button.show()
        self._stop_button.connect('clicked', self._stop_clicked_cb)
        self._stop_button.set_sensitive(False)
        self.insert(self._stop_button, -1)
        self._stop_button.set_tooltip(_('Stop'))

        # Language list
        combo = ComboBox()
        which = 0
        for pair in voice_names:
            language, name = pair
            combo.append_item(language, name)
            if language == self._voice:
                combo.set_active(which)
            which += 1

        combo.connect('changed', self._voice_changed_cb)
        combotool = ToolComboBox(combo)
        self.insert(combotool, -1)
        combotool.show()

        self._speech.connect('stop', self._reset_buttons_cb)
class BooksToolbar(Gtk.Toolbar):
    __gtype_name__ = 'BooksToolbar'

    def __init__(self):
        Gtk.Toolbar.__init__(self)
        book_search_item = Gtk.ToolItem()

        self.search_entry = Gtk.Entry()
        self.search_entry.connect('activate', self.search_entry_activate_cb)

        width = int(Gdk.Screen.width() / 2)
        self.search_entry.set_size_request(width, -1)

        book_search_item.add(self.search_entry)
        self.search_entry.show()

        self.insert(book_search_item, -1)
        book_search_item.show()

        self._download = ToolButton('go-down')
        self._download.set_tooltip(_('Get Book'))
        self._download.props.sensitive = False
        self._download.connect('clicked', self._get_book_cb)
        self.insert(self._download, -1)
        self._download.show()

        self.format_combo = ComboBox()
        self.format_combo.connect('changed', self.format_changed_cb)
        self.format_combo.append_item('.djvu', 'Deja Vu')
        self.format_combo.append_item('_bw.pdf', 'B/W PDF')
        self.format_combo.append_item('.pdf', 'Color PDF')
        self.format_combo.append_item('.epub', 'EPUB')
        self.format_combo.set_active(0)
        self.format_combo.props.sensitive = False
        combotool = ToolComboBox(self.format_combo)
        self.insert(combotool, -1)
        combotool.show()

        self.search_entry.grab_focus()

    def set_activity(self, activity):
        self.activity = activity

    def format_changed_cb(self, combo):
        if self.activity != None:
            self.activity.show_book_data()

    def search_entry_activate_cb(self, entry):
        self.activity.find_books(entry.props.text)

    def _get_book_cb(self, button):
        self.activity.get_book()
 
    def enable_button(self,  state):
        self._download.props.sensitive = state
        self.format_combo.props.sensitive = state
示例#4
0
    def _get_with_search_combo(self):
        with_search = ComboBox()
        with_search.append_item(_ACTION_EVERYBODY, _('Anyone'))
        with_search.append_separator()
        with_search.append_item(_ACTION_MY_FRIENDS, _('My friends'))
        with_search.append_item(_ACTION_MY_CLASS, _('My class'))
        with_search.append_separator()

        # TODO: Ask the model for buddies.
        with_search.append_item(3, 'Dan', 'theme:xo')

        with_search.set_active(0)
        with_search.connect('changed', self._combo_changed_cb)
        return with_search
示例#5
0
    def _get_with_search_combo(self):
        with_search = ComboBox()
        with_search.append_item(_ACTION_EVERYBODY, _('Anyone'))
        with_search.append_separator()
        with_search.append_item(_ACTION_MY_FRIENDS, _('My friends'))
        with_search.append_item(_ACTION_MY_CLASS, _('My class'))
        with_search.append_separator()

        # TODO: Ask the model for buddies.
        with_search.append_item(3, 'Dan', 'theme:xo')

        with_search.set_active(0)
        with_search.connect('changed', self._combo_changed_cb)
        return with_search
示例#6
0
 def _get_when_search_combo(self):
     when_search = ComboBox()
     when_search.append_item(_ACTION_ANYTIME, _('Anytime'))
     when_search.append_separator()
     when_search.append_item(_ACTION_TODAY, _('Today'))
     when_search.append_item(_ACTION_SINCE_YESTERDAY, _('Since yesterday'))
     # TRANS: Filter entries modified during the last 7 days.
     when_search.append_item(_ACTION_PAST_WEEK, _('Past week'))
     # TRANS: Filter entries modified during the last 30 days.
     when_search.append_item(_ACTION_PAST_MONTH, _('Past month'))
     # TRANS: Filter entries modified during the last 356 days.
     when_search.append_item(_ACTION_PAST_YEAR, _('Past year'))
     when_search.set_active(0)
     when_search.connect('changed', self._combo_changed_cb)
     return when_search
示例#7
0
 def _get_when_search_combo(self):
     when_search = ComboBox()
     when_search.append_item(_ACTION_ANYTIME, _('Anytime'))
     when_search.append_separator()
     when_search.append_item(_ACTION_TODAY, _('Today'))
     when_search.append_item(_ACTION_SINCE_YESTERDAY,
                             _('Since yesterday'))
     # TRANS: Filter entries modified during the last 7 days.
     when_search.append_item(_ACTION_PAST_WEEK, _('Past week'))
     # TRANS: Filter entries modified during the last 30 days.
     when_search.append_item(_ACTION_PAST_MONTH, _('Past month'))
     # TRANS: Filter entries modified during the last 356 days.
     when_search.append_item(_ACTION_PAST_YEAR, _('Past year'))
     when_search.set_active(0)
     when_search.connect('changed', self._combo_changed_cb)
     return when_search
示例#8
0
def combo_factory(combo_array, toolbar, callback, cb_arg=None, tooltip=None, default=None):
    """Factory for making a toolbar combo box"""
    combo = ComboBox()
    if tooltip is not None and hasattr(combo, "set_tooltip_text"):
        combo.set_tooltip_text(tooltip)
    if cb_arg is not None:
        combo.connect("changed", callback, cb_arg)
    else:
        combo.connect("changed", callback)
    for i, selection in enumerate(combo_array):
        combo.append_item(i, selection, None)
    combo.show()
    toolitem = Gtk.ToolItem()
    toolitem.add(combo)
    if hasattr(toolbar, "insert"):  # the main toolbar
        toolbar.insert(toolitem, -1)
    else:  # or a secondary toolbar
        toolbar.props.page.insert(toolitem, -1)
    toolitem.show()
    if default is not None:
        combo.set_active(combo_array.index(default))
    return combo
示例#9
0
    def __init__(self, handle):
        activity.Activity.__init__(self, handle)
        # No sharing (Future Improvement)
        self.max_participants = 1

        # Build the activity toolbar.
        toolbox = ToolbarBox()

        activity_button = ActivityToolbarButton(self)
        toolbox.toolbar.insert(activity_button, 0)
        activity_button.show()

        comboLabel1 = Gtk.ToolItem()
        label1 = Gtk.Label()
        label1.set_text(_('Level:') + ' ')
        comboLabel1.add(label1)
        toolbox.toolbar.insert(comboLabel1, -1)
        comboLabel1.show()
        label1.show()

        comboField = Gtk.ToolItem()
        combo = ComboBox()
        combo.set_wrap_width(3)
        combo.append_item(0, _('Easy'))
        combo.append_item(1, _('Moderate'))
        combo.append_item(2, _('Hard'))
        combo.set_active(0)
        comboField.add(combo)
        combo.connect('changed', self.change_combo)
        toolbox.toolbar.insert(comboField, -1)
        comboField.show()
        combo.show()

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

        restart = ToolButton('new-game')
        toolbox.toolbar.insert(restart, -1)
        restart.set_tooltip(_('Restart'))
        restart.connect('clicked', self._restart_button_cb)
        restart.show()

        next_bt = ToolButton('next')
        toolbox.toolbar.insert(next_bt, -1)
        next_bt.set_tooltip(_('Next Number'))
        next_bt.connect('clicked', self._next_button_cb)
        next_bt.set_sensitive(False)
        next_bt.show()

        separator2 = Gtk.SeparatorToolItem()
        separator2.props.draw = True
        separator2.set_expand(False)
        toolbox.toolbar.insert(separator2, -1)
        separator2.show()

        comboLabel2 = Gtk.ToolItem()
        label1 = Gtk.Label()
        label1.set_text(_('Score:') + '  ')
        comboLabel2.add(label1)
        toolbox.toolbar.insert(comboLabel2, -1)
        comboLabel2.show()
        label1.show()

        self._score_image = Gtk.Image()
        item = Gtk.ToolItem()
        item.add(self._score_image)
        toolbox.toolbar.insert(item, -1)
        item.show()

        separator2 = Gtk.SeparatorToolItem()
        separator2.props.draw = False
        separator2.set_expand(True)
        toolbox.toolbar.insert(separator2, -1)
        separator2.show()

        stop_button = StopButton(self)
        toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()
        stop_button.connect('clicked', self._stop_cb)

        toolbox.show()
        self.set_toolbar_box(toolbox)

        # Create the game instance.
        self.game = CowBulls.CowBulls(parent=self)

        # Build the Pygame canvas.
        self.game.canvas = self._pygamecanvas = sugargame.canvas.PygameCanvas(
            self, main=self.game.run, modules=[pygame.display, pygame.font])

        # Note that set_canvas implicitly calls
        # read_file when resuming from the Journal.
        self.game.set_next_button(next_bt)
        self.set_canvas(self._pygamecanvas)
        Gdk.Screen.get_default().connect('size-changed', self.__configure_cb)
示例#10
0
class SpeechToolbar(Gtk.Toolbar):
    def __init__(self, activity):
        GObject.GObject.__init__(self)
        self._activity = activity
        if not speech.supported:
            return
        self.is_paused = False
        self._cnf_client = GConf.Client.get_default()
        self.load_speech_parameters()

        self.sorted_voices = [i for i in speech.voices()]
        self.sorted_voices.sort(self.compare_voices)
        default = 0
        for voice in self.sorted_voices:
            if voice[0] == speech.voice[0]:
                break
            default = default + 1

        # Play button
        self.play_btn = ToggleToolButton("media-playback-start")
        self.play_btn.show()
        self.play_toggled_handler = self.play_btn.connect("toggled", self.play_cb)
        self.insert(self.play_btn, -1)
        self.play_btn.set_tooltip(_("Play / Pause"))

        # Stop button
        self.stop_btn = ToolButton("media-playback-stop")
        self.stop_btn.show()
        self.stop_btn.connect("clicked", self.stop_cb)
        self.stop_btn.set_sensitive(False)
        self.insert(self.stop_btn, -1)
        self.stop_btn.set_tooltip(_("Stop"))

        self.voice_combo = ComboBox()
        for voice in self.sorted_voices:
            self.voice_combo.append_item(voice, voice[0])
        self.voice_combo.set_active(default)

        self.voice_combo.connect("changed", self.voice_changed_cb)
        combotool = ToolComboBox(self.voice_combo)
        self.insert(combotool, -1)
        combotool.show()
        speech.reset_cb = self.reset_buttons_cb
        speech.end_text_cb = self.reset_buttons_cb

    def compare_voices(self, a, b):
        if a[0].lower() == b[0].lower():
            return 0
        if a[0].lower() < b[0].lower():
            return -1
        if a[0].lower() > b[0].lower():
            return 1

    def voice_changed_cb(self, combo):
        speech.voice = combo.props.value
        speech.say(speech.voice[0])
        self.save_speech_parameters()

    def load_speech_parameters(self):
        speech_parameters = {}
        data_path = os.path.join(self._activity.get_activity_root(), "data")
        data_file_name = os.path.join(data_path, "speech_params.json")
        if os.path.exists(data_file_name):
            f = open(data_file_name, "r")
            try:
                speech_parameters = json.load(f)
                speech.voice = speech_parameters["voice"]
            finally:
                f.close()
        else:
            speech.voice = self.get_default_voice()
            logging.error("Default voice %s", speech.voice)

        self._cnf_client.add_dir("/desktop/sugar/speech", GConf.ClientPreloadType.PRELOAD_NONE)
        speech.pitch = self._cnf_client.get_int("/desktop/sugar/speech/pitch")
        speech.rate = self._cnf_client.get_int("/desktop/sugar/speech/rate")
        self._cnf_client.notify_add("/desktop/sugar/speech/pitch", self.__conf_changed_cb, None)
        self._cnf_client.notify_add("/desktop/sugar/speech/rate", self.__conf_changed_cb, None)

    def get_default_voice(self):
        """Try to figure out the default voice, from the current locale
           ($LANG)
           Fall back to espeak's voice called Default."""
        voices = speech.get_all_voices()

        locale = os.environ.get("LANG", "")
        language_location = locale.split(".", 1)[0].lower()
        language = language_location.split("_")[0]
        variant = ""
        if language_location.find("_") > -1:
            variant = language_location.split("_")[1]
        # if the language is es but not es_es default to es_la (latin voice)
        if language == "es" and language_location != "es_es":
            language_location = "es_la"

        best = voices.get(language_location) or voices.get(language) or "default"
        logging.debug("Best voice for LANG %s seems to be %s", locale, best)
        return [best, language, variant]

    def __conf_changed_cb(self, client, connection_id, entry, args):
        key = entry.get_key()
        value = client.get_int(key)
        if key == "/desktop/sugar/speech/pitch":
            speech.pitch = value
        if key == "/desktop/sugar/speech/rate":
            speech.rate = value

    def save_speech_parameters(self):
        speech_parameters = {}
        speech_parameters["voice"] = speech.voice
        data_path = os.path.join(self._activity.get_activity_root(), "data")
        data_file_name = os.path.join(data_path, "speech_params.json")
        f = open(data_file_name, "w")
        try:
            json.dump(speech_parameters, f)
        finally:
            f.close()

    def reset_buttons_cb(self):
        logging.error("reset buttons")
        self.play_btn.set_icon_name("media-playback-start")
        self.stop_btn.set_sensitive(False)
        self.play_btn.handler_block(self.play_toggled_handler)
        self.play_btn.set_active(False)
        self.play_btn.handler_unblock(self.play_toggled_handler)
        self.is_paused = False

    def play_cb(self, widget):
        self.stop_btn.set_sensitive(True)
        if widget.get_active():
            self.play_btn.set_icon_name("media-playback-pause")
            logging.error("Paused %s", self.is_paused)
            if not self.is_paused:
                # get the text to speech, if there are a selection,
                # play selected text, if not, play all
                abi = self._activity.abiword_canvas
                selection = abi.get_selection("text/plain")
                if not selection or selection[0] is None or selection[1] == 0:
                    # nothing selected
                    abi.select_all()
                    text = abi.get_selection("text/plain")[0]
                    abi.moveto_bod()
                else:
                    text = selection[0]
                speech.play(text)
            else:
                logging.error("Continue play")
                speech.continue_play()
        else:
            self.play_btn.set_icon_name("media-playback-start")
            self.is_paused = True
            speech.pause()

    def stop_cb(self, widget):
        self.stop_btn.set_sensitive(False)
        self.play_btn.set_icon_name("media-playback-start")
        self.play_btn.set_active(False)
        self.is_paused = False
        speech.stop()
示例#11
0
class   SpeechToolbar(Gtk.Toolbar):
    def __init__(self):
        Gtk.Toolbar.__init__(self)
        voicebar = Gtk.Toolbar()
        self.activity = None
        self.sorted_voices = [i for i in speech.voices()]
        self.sorted_voices.sort(self.compare_voices)
        default = 0
        for voice in self.sorted_voices:
            if voice[0] == 'default':
                break
            default = default + 1

        # Play button Image
        play_img = Gtk.Image()
        play_img.show()
        play_img.set_from_icon_name('media-playback-start',
                Gtk.IconSize.LARGE_TOOLBAR)

        # Pause button Image
        pause_img = Gtk.Image()
        pause_img.show()
        pause_img.set_from_icon_name('media-playback-pause',
                Gtk.IconSize.LARGE_TOOLBAR)

        # Play button
        self.play_btn = ToggleToolButton('media-playback-start')
        self.play_btn.show()
        self.play_btn.connect('toggled', self.play_cb, [play_img, pause_img])
        self.insert(self.play_btn, -1)
        self.play_btn.set_tooltip(_('Play / Pause'))

        self.voice_combo = ComboBox()
        self.voice_combo.connect('changed', self.voice_changed_cb)
        for voice in self.sorted_voices:
            self.voice_combo.append_item(voice, voice[0])
        self.voice_combo.set_active(default)
        combotool = ToolComboBox(self.voice_combo)
        self.insert(combotool, -1)
        combotool.show()

        self.pitchadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0)
        pitchbar = Gtk.HScale()
        pitchbar.set_adjustment(self.pitchadj)
        pitchbar.set_draw_value(False)
        # pitchbar.set_update_policy(Gtk.UpdatePolicy.ALWAYS)
        pitchbar.set_size_request(150,15)
        pitchtool = Gtk.ToolItem()
        pitchtool.add(pitchbar)
        pitchtool.show()
        self.insert(pitchtool, -1)
        pitchbar.show()

        self.rateadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0)
        ratebar = Gtk.HScale()
        ratebar.set_adjustment(self.rateadj)
        ratebar.set_draw_value(False)
        #ratebar.set_update_policy(Gtk.UpdatePolicy.ALWAYS)
        ratebar.set_size_request(150,15)
        ratetool = Gtk.ToolItem()
        ratetool.add(ratebar)
        ratetool.show()
        self.insert(ratetool, -1)
        ratebar.show()

    def compare_voices(self,  a,  b):
        if a[0].lower() == b[0].lower():
            return 0
        if a[0].lower() < b[0].lower():
            return -1
        if a[0].lower() > b[0].lower():
            return 1
        
    def voice_changed_cb(self, combo):
        speech.voice = combo.props.value
        if self.activity != None:
            speech.say(speech.voice[0])

    def pitch_adjusted_cb(self, get):
        speech.pitch = int(get.get_value())
        speech.say(_("pitch adjusted"))
        f = open(os.path.join(self.activity.get_activity_root(), 'instance',  'pitch.txt'),  'w')
        try:
            f.write(str(speech.pitch))
        finally:
            f.close()

    def rate_adjusted_cb(self, get):
        speech.rate = int(get.get_value())
        speech.say(_("rate adjusted"))
        f = open(os.path.join(self.activity.get_activity_root(), 'instance',  'rate.txt'),  'w')
        try:
            f.write(str(speech.rate))
        finally:
            f.close()
      
    def set_activity(self, activity):
        self.activity = activity
        if os.path.exists(os.path.join(activity.get_activity_root(), 'instance',  'pitch.txt')):
            f = open(os.path.join(activity.get_activity_root(), 'instance',  'pitch.txt'),  'r')
            line = f.readline()
            pitch = int(line.strip())
            self.pitchadj.set_value(pitch)
            speech.pitch = pitch
            f.close()
        if os.path.exists(os.path.join(activity.get_activity_root(), 'instance',  'rate.txt')):
            f = open(os.path.join(activity.get_activity_root(), 'instance',  'rate.txt'),  'r')
            line = f.readline()
            rate = int(line.strip())
            self.rateadj.set_value(rate)
            speech.rate = rate
            f.close()
        self.pitchadj.connect("value_changed", self.pitch_adjusted_cb)
        self.rateadj.connect("value_changed", self.rate_adjusted_cb)
    
    def play_cb(self, widget, images):
        widget.set_icon_widget(images[int(widget.get_active())])

        if widget.get_active():
            if speech.is_stopped():
                speech.play(self.activity.add_word_marks())
        else:
            speech.stop()
示例#12
0
    def create_dialog(self):
        """Setup most of the dialog."""

# Toolbar
        self._toolbar_box = ToolbarBox()
        activity_button = ActivityToolbarButton(self._parent)
        self._toolbar_box.toolbar.insert(activity_button, 0)

        def append(icon_name, label, page, position):
            toolbar_button = ToolbarButton()
            toolbar_button.props.page = page
            toolbar_button.props.icon_name = icon_name
            toolbar_button.props.label = label
            self._toolbar_box.toolbar.insert(toolbar_button, position)
        append('toolbar-edit',
               _('Edit'),
               EditToolbar(self._parent),
               -1)
        append('toolbar-algebra',
               _('Algebra'),
               AlgebraToolbar(self._parent),
               -1)
        append('toolbar-trigonometry',
               _('Trigonometry'),
               TrigonometryToolbar(self._parent),
               -1)
        append('toolbar-boolean',
               _('Boolean'),
               BooleanToolbar(self._parent),
               -1)
        self._misc_toolbar = MiscToolbar(
            self._parent,
            target_toolbar=self._toolbar_box.toolbar)
        append('toolbar-constants',
               _('Miscellaneous'),
               self._misc_toolbar,
               5)
        self._stop_separator = Gtk.SeparatorToolItem()
        self._stop_separator.props.draw = False
        self._stop_separator.set_expand(True)
        self._stop_separator.show()
        self._toolbar_box.toolbar.insert(self._stop_separator, -1)
        self._stop = StopButton(self._parent)
        self._toolbar_box.toolbar.insert(self._stop, -1)
        self._toolbar_box.show_all()
        self._parent.set_toolbar_box(self._toolbar_box)

# Some layout constants
        self.input_font = Pango.FontDescription('sans bold 12')
        self.button_font = Pango.FontDescription('sans bold 16')
        self.col_white = self.create_color(1.00, 1.00, 1.00)
        self.col_gray1 = self.create_color(0.76, 0.76, 0.76)
        self.col_gray2 = self.create_color(0.50, 0.50, 0.50)
        self.col_gray3 = self.create_color(0.25, 0.25, 0.25)
        self.col_black = self.create_color(0.00, 0.00, 0.00)
        self.col_red = self.create_color(1.00, 0.00, 0.00)

# Big - Table, 16 rows, 10 columns, homogeneously divided
        self.grid = Gtk.Grid()
        self.grid.set_column_homogeneous(True)
        self.grid.set_row_spacing(0)
        self.grid.set_column_spacing(4)

# Left part: container and input
        vc1 = Gtk.VBox(False, 0)
        hc1 = Gtk.HBox(False, 10)
        eb = Gtk.EventBox()
        eb.add(hc1)
        eb.modify_bg(Gtk.StateType.NORMAL, self.col_black)
        eb.set_border_width(12)
        eb2 = Gtk.EventBox()
        eb2.add(eb)
        eb2.modify_bg(Gtk.StateType.NORMAL, self.col_black)
        label1 = Gtk.Label(label=_('Label:'))
        label1.modify_fg(Gtk.StateType.NORMAL, self.col_white)
        label1.set_alignment(1, 0.5)
        hc1.pack_start(label1, expand=False, fill=False, padding=10)
        self.label_entry = Gtk.Entry()
        self.label_entry.modify_bg(Gtk.StateType.INSENSITIVE, self.col_black)
        hc1.pack_start(self.label_entry, expand=True, fill=True, padding=0)
        vc1.pack_start(eb2, False, True, 0)

        self.text_entry = Gtk.Entry()
        try:
            self.text_entry.props.im_module = 'gtk-im-context-simple'
        except AttributeError:
            pass
        self.text_entry.set_size_request(-1, 75)
        self.text_entry.connect('key_press_event', self._parent.ignore_key_cb)
        self.text_entry.modify_font(self.input_font)
        self.text_entry.modify_bg(Gtk.StateType.INSENSITIVE, self.col_black)
        eb = Gtk.EventBox()
        eb.add(self.text_entry)
        eb.modify_bg(Gtk.StateType.NORMAL, self.col_black)
        eb.set_border_width(12)
        eb2 = Gtk.EventBox()
        eb2.add(eb)
        eb2.modify_bg(Gtk.StateType.NORMAL, self.col_black)
        vc1.pack_start(eb2, expand=True, fill=True, padding=0)
        self.grid.attach(vc1, 0, 0, 7, 6)

# Left part: buttons
        self.pad = Gtk.Grid()
        self.pad.set_column_homogeneous(True)
        self.pad.set_row_spacing(6)
        self.pad.set_column_spacing(6)
        self.create_button_data()
        self.buttons = {}
        for x, y, w, h, cap, bgcol, cb in self.button_data:
            button = self.create_button(
                _(cap), cb, self.col_white, bgcol, w, h)
            self.buttons[cap] = button
            self.pad.attach(button, x, y, w, h)

        eb = Gtk.EventBox()
        eb.add(self.pad)
        eb.modify_bg(Gtk.StateType.NORMAL, self.col_black)
        self.grid.attach(eb, 0, 6, 7, 20)

# Right part: container and equation button
        hc2 = Gtk.HBox()
        combo = ComboBox()
        combo.append_item(0, _('All equations'))
        combo.append_item(1, _('My equations'))
        combo.append_item(2, _('Show variables'))
        combo.set_active(0)
        combo.connect('changed', self._history_filter_cb)
        hc2.pack_start(combo, True, True, 0)
        hc2.set_border_width(6)
        self.grid.attach(hc2, 7, 0, 4, 2)

# Right part: last equation
        self.last_eq = Gtk.TextView()
        self.last_eq.set_editable(False)
        self.last_eq.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
        self.last_eq.connect('realize', self._textview_realize_cb)
        self.last_eq.modify_base(Gtk.StateType.NORMAL, Gdk.color_parse(
                                 sugar3.profile.get_color().get_fill_color()))
        self.last_eq.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse(
                               sugar3.profile.get_color().get_stroke_color()))
        self.last_eq.set_border_window_size(Gtk.TextWindowType.LEFT, 4)
        self.last_eq.set_border_window_size(Gtk.TextWindowType.RIGHT, 4)
        self.last_eq.set_border_window_size(Gtk.TextWindowType.TOP, 4)
        self.last_eq.set_border_window_size(Gtk.TextWindowType.BOTTOM, 4)

        # TODO Fix for old Sugar 0.82 builds, red_float not available
        xo_color = sugar3.profile.get_color()
        bright = (
            Gdk.color_parse(xo_color.get_fill_color()).red_float +
            Gdk.color_parse(xo_color.get_fill_color()).green_float +
            Gdk.color_parse(xo_color.get_fill_color()).blue_float) / 3.0
        if bright < 0.5:
            self.last_eq.modify_text(Gtk.StateType.NORMAL, self.col_white)
        else:
            self.last_eq.modify_text(Gtk.StateType.NORMAL, self.col_black)

        self.grid.attach(self.last_eq, 7, 2, 4, 5)

# Right part: history
        scrolled_window = Gtk.ScrolledWindow()
        scrolled_window.set_policy(Gtk.PolicyType.NEVER,
                                   Gtk.PolicyType.AUTOMATIC)

        self.history_vbox = Gtk.VBox()
        self.history_vbox.set_homogeneous(False)
        self.history_vbox.set_border_width(0)
        self.history_vbox.set_spacing(4)

        self.variable_vbox = Gtk.VBox()
        self.variable_vbox.set_homogeneous(False)
        self.variable_vbox.set_border_width(0)
        self.variable_vbox.set_spacing(4)

        vbox = Gtk.VBox()
        vbox.pack_start(self.history_vbox, True, True, 0)
        vbox.pack_start(self.variable_vbox, True, True, 0)
        scrolled_window.add_with_viewport(vbox)
        self.grid.attach(scrolled_window, 7, 7, 4, 19)

        Gdk.Screen.get_default().connect('size-changed',
                                         self._configure_cb)
示例#13
0
    def create_dialog(self):
        """Setup most of the dialog."""

        # Toolbar
        self._toolbar_box = ToolbarBox()
        activity_button = ActivityToolbarButton(self._parent)
        self._toolbar_box.toolbar.insert(activity_button, 0)

        def append(icon_name, label, page, position):
            toolbar_button = ToolbarButton()
            toolbar_button.props.page = page
            toolbar_button.props.icon_name = icon_name
            toolbar_button.props.label = label
            self._toolbar_box.toolbar.insert(toolbar_button, position)

        append('toolbar-edit', _('Edit'), EditToolbar(self._parent), -1)
        append('toolbar-algebra', _('Algebra'), AlgebraToolbar(self._parent),
               -1)
        append('toolbar-trigonometry', _('Trigonometry'),
               TrigonometryToolbar(self._parent), -1)
        append('toolbar-boolean', _('Boolean'), BooleanToolbar(self._parent),
               -1)
        self._misc_toolbar = MiscToolbar(
            self._parent, target_toolbar=self._toolbar_box.toolbar)
        append('toolbar-constants', _('Miscellaneous'), self._misc_toolbar, 5)
        self._stop_separator = Gtk.SeparatorToolItem()
        self._stop_separator.props.draw = False
        self._stop_separator.set_expand(True)
        self._stop_separator.show()
        self._toolbar_box.toolbar.insert(self._stop_separator, -1)
        self._stop = StopButton(self._parent)
        self._toolbar_box.toolbar.insert(self._stop, -1)
        self._toolbar_box.show_all()
        self._parent.set_toolbar_box(self._toolbar_box)

        # Some layout constants
        self.input_font = Pango.FontDescription('sans bold 12')
        self.button_font = Pango.FontDescription('sans bold 16')
        self.col_white = self.create_color(1.00, 1.00, 1.00)
        self.col_gray1 = self.create_color(0.76, 0.76, 0.76)
        self.col_gray2 = self.create_color(0.50, 0.50, 0.50)
        self.col_gray3 = self.create_color(0.25, 0.25, 0.25)
        self.col_black = self.create_color(0.00, 0.00, 0.00)
        self.col_red = self.create_color(1.00, 0.00, 0.00)

        # Big - Table, 16 rows, 10 columns, homogeneously divided
        self.grid = Gtk.Grid()
        self.grid.set_column_homogeneous(True)
        self.grid.set_row_spacing(0)
        self.grid.set_column_spacing(4)

        # Left part: container and input
        vc1 = Gtk.VBox(False, 0)
        hc1 = Gtk.HBox(False, 10)
        eb = Gtk.EventBox()
        eb.add(hc1)
        eb.modify_bg(Gtk.StateType.NORMAL, self.col_black)
        eb.set_border_width(12)
        eb2 = Gtk.EventBox()
        eb2.add(eb)
        eb2.modify_bg(Gtk.StateType.NORMAL, self.col_black)
        label1 = Gtk.Label(label=_('Label:'))
        label1.modify_fg(Gtk.StateType.NORMAL, self.col_white)
        label1.set_alignment(1, 0.5)
        hc1.pack_start(label1, expand=False, fill=False, padding=10)
        self.label_entry = Gtk.Entry()
        self.label_entry.modify_bg(Gtk.StateType.INSENSITIVE, self.col_black)
        hc1.pack_start(self.label_entry, expand=True, fill=True, padding=0)
        vc1.pack_start(eb2, False, True, 0)

        self.text_entry = Gtk.Entry()
        try:
            self.text_entry.props.im_module = 'gtk-im-context-simple'
        except AttributeError:
            pass
        self.text_entry.set_size_request(-1, 75)
        self.text_entry.connect('key_press_event', self._parent.ignore_key_cb)
        self.text_entry.modify_font(self.input_font)
        self.text_entry.modify_bg(Gtk.StateType.INSENSITIVE, self.col_black)
        eb = Gtk.EventBox()
        eb.add(self.text_entry)
        eb.modify_bg(Gtk.StateType.NORMAL, self.col_black)
        eb.set_border_width(12)
        eb2 = Gtk.EventBox()
        eb2.add(eb)
        eb2.modify_bg(Gtk.StateType.NORMAL, self.col_black)
        vc1.pack_start(eb2, expand=True, fill=True, padding=0)
        self.grid.attach(vc1, 0, 0, 7, 6)

        # Left part: buttons
        self.pad = Gtk.Grid()
        self.pad.set_column_homogeneous(True)
        self.pad.set_row_spacing(6)
        self.pad.set_column_spacing(6)
        self.create_button_data()
        self.buttons = {}
        for x, y, w, h, cap, bgcol, cb in self.button_data:
            button = self.create_button(_(cap), cb, self.col_white, bgcol, w,
                                        h)
            self.buttons[cap] = button
            self.pad.attach(button, x, y, w, h)

        eb = Gtk.EventBox()
        eb.add(self.pad)
        eb.modify_bg(Gtk.StateType.NORMAL, self.col_black)
        self.grid.attach(eb, 0, 6, 7, 20)

        # Right part: container and equation button
        hc2 = Gtk.HBox()
        combo = ComboBox()
        combo.append_item(0, _('All equations'))
        combo.append_item(1, _('My equations'))
        combo.append_item(2, _('Show variables'))
        combo.set_active(0)
        combo.connect('changed', self._history_filter_cb)
        hc2.pack_start(combo, True, True, 0)
        hc2.set_border_width(6)
        self.grid.attach(hc2, 7, 0, 4, 2)

        # Right part: last equation
        self.last_eq = Gtk.TextView()
        self.last_eq.set_editable(False)
        self.last_eq.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
        self.last_eq.connect('realize', self._textview_realize_cb)
        self.last_eq.modify_base(
            Gtk.StateType.NORMAL,
            Gdk.color_parse(sugar3.profile.get_color().get_fill_color()))
        self.last_eq.modify_bg(
            Gtk.StateType.NORMAL,
            Gdk.color_parse(sugar3.profile.get_color().get_stroke_color()))
        self.last_eq.set_border_window_size(Gtk.TextWindowType.LEFT, 4)
        self.last_eq.set_border_window_size(Gtk.TextWindowType.RIGHT, 4)
        self.last_eq.set_border_window_size(Gtk.TextWindowType.TOP, 4)
        self.last_eq.set_border_window_size(Gtk.TextWindowType.BOTTOM, 4)

        # TODO Fix for old Sugar 0.82 builds, red_float not available
        xo_color = sugar3.profile.get_color()
        bright = (Gdk.color_parse(xo_color.get_fill_color()).red_float +
                  Gdk.color_parse(xo_color.get_fill_color()).green_float +
                  Gdk.color_parse(xo_color.get_fill_color()).blue_float) / 3.0
        if bright < 0.5:
            self.last_eq.modify_text(Gtk.StateType.NORMAL, self.col_white)
        else:
            self.last_eq.modify_text(Gtk.StateType.NORMAL, self.col_black)

        self.grid.attach(self.last_eq, 7, 2, 4, 5)

        # Right part: history
        scrolled_window = Gtk.ScrolledWindow()
        scrolled_window.set_policy(Gtk.PolicyType.NEVER,
                                   Gtk.PolicyType.AUTOMATIC)

        self.history_vbox = Gtk.VBox()
        self.history_vbox.set_homogeneous(False)
        self.history_vbox.set_border_width(0)
        self.history_vbox.set_spacing(4)

        self.variable_vbox = Gtk.VBox()
        self.variable_vbox.set_homogeneous(False)
        self.variable_vbox.set_border_width(0)
        self.variable_vbox.set_spacing(4)

        vbox = Gtk.VBox()
        vbox.pack_start(self.history_vbox, True, True, 0)
        vbox.pack_start(self.variable_vbox, True, True, 0)
        scrolled_window.add_with_viewport(vbox)
        self.grid.attach(scrolled_window, 7, 7, 4, 19)

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)
示例#14
0
class SpeechToolbar(Gtk.Toolbar):
    def __init__(self, activity):
        Gtk.Toolbar.__init__(self)
        voicebar = Gtk.Toolbar()
        self._activity = activity
        if not speech.supported:
            return

        self.load_speech_parameters()

        self.sorted_voices = [i for i in speech.voices()]
        self.sorted_voices.sort(self.compare_voices)
        default = 0
        for voice in self.sorted_voices:
            if voice[0] == speech.voice[0]:
                break
            default = default + 1

        # Play button
        self.play_btn = ToggleToolButton('media-playback-start')
        self.play_btn.show()
        self.play_btn.connect('toggled', self.play_cb)
        self.insert(self.play_btn, -1)
        self.play_btn.set_tooltip(_('Play / Pause'))

        self.voice_combo = ComboBox()
        for voice in self.sorted_voices:
            self.voice_combo.append_item(voice, voice[0])
        self.voice_combo.set_active(default)

        self.voice_combo.connect('changed', self.voice_changed_cb)
        combotool = ToolComboBox(self.voice_combo)
        self.insert(combotool, -1)
        combotool.show()

        self.pitchadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0)
        pitchbar = Gtk.HScale(self.pitchadj)
        pitchbar.set_draw_value(False)
        pitchbar.set_update_policy(Gtk.UPDATE_DISCONTINUOUS)
        pitchbar.set_size_request(150, 15)
        self.pitchadj.set_value(speech.pitch)
        pitchtool = Gtk.ToolItem()
        pitchtool.add(pitchbar)
        pitchtool.show()
        self.insert(pitchtool, -1)
        pitchbar.show()

        self.rateadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0)
        ratebar = Gtk.HScale(self.rateadj)
        ratebar.set_draw_value(False)
        ratebar.set_update_policy(Gtk.UPDATE_DISCONTINUOUS)
        ratebar.set_size_request(150, 15)
        self.rateadj.set_value(speech.rate)
        ratetool = Gtk.ToolItem()
        ratetool.add(ratebar)
        ratetool.show()
        self.insert(ratetool, -1)
        ratebar.show()
        self.pitchadj.connect("value_changed", self.pitch_adjusted_cb)
        self.rateadj.connect("value_changed", self.rate_adjusted_cb)

    def compare_voices(self, a, b):
        if a[0].lower() == b[0].lower():
            return 0
        if a[0].lower() < b[0].lower():
            return -1
        if a[0].lower() > b[0].lower():
            return 1

    def voice_changed_cb(self, combo):
        speech.voice = combo.props.value
        speech.say(speech.voice[0])
        self.save_speech_parameters()

    def pitch_adjusted_cb(self, get):
        speech.pitch = int(get.value)
        speech.say(_("pitch adjusted"))
        self.save_speech_parameters()

    def rate_adjusted_cb(self, get):
        speech.rate = int(get.value)
        speech.say(_("rate adjusted"))
        self.save_speech_parameters()

    def load_speech_parameters(self):
        speech_parameters = {}
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        if os.path.exists(data_file_name):
            f = open(data_file_name, 'r')
            try:
                speech_parameters = simplejson.load(f)
                speech.pitch = speech_parameters['pitch']
                speech.rate = speech_parameters['rate']
                speech.voice = speech_parameters['voice']
            finally:
                f.close()

    def save_speech_parameters(self):
        speech_parameters = {}
        speech_parameters['pitch'] = speech.pitch
        speech_parameters['rate'] = speech.rate
        speech_parameters['voice'] = speech.voice
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        f = open(data_file_name, 'w')
        try:
            simplejson.dump(speech_parameters, f)
        finally:
            f.close()

    def play_cb(self, widget):
        if widget.get_active():
            self.play_btn.set_named_icon('media-playback-pause')
            if speech.is_stopped():
                speech.play(self._activity._view.get_marked_words())
        else:
            self.play_btn.set_named_icon('media-playback-start')
            speech.stop()
示例#15
0
    def __init__(self):
        Gtk.Toolbar.__init__(self)
        self.activity = None
        self._speech = SpeechManager()
        self._voices = self._speech.get_all_voices() # a dictionary

        locale = os.environ.get('LANG', '')
        language_location = locale.split('.', 1)[0].lower()
        language = language_location.split('_')[0]
        # if the language is es but not es_es default to es_la (latin voice) 
        if language == 'es' and language_location != 'es_es':
            language_location = 'es_la'

        self._voice = 'en_us'
        if language_location in self._voices:
            self._voice = language_location
        elif language in self._voices:
            self._voice = language

        voice_names = []
        for language, name in self._voices.iteritems():
            voice_names.append((language, name))
        voice_names.sort(self._compare_voices)

        # Play button Image
        play_img = Gtk.Image()
        play_img.show()
        play_img.set_from_icon_name('media-playback-start',
                Gtk.IconSize.LARGE_TOOLBAR)

        # Pause button Image
        pause_img = Gtk.Image()
        pause_img.show()
        pause_img.set_from_icon_name('media-playback-pause',
                Gtk.IconSize.LARGE_TOOLBAR)

        # Play button
        self.play_button = ToggleToolButton('media-playback-start')
        self.play_button.show()
        self.play_button.connect('toggled', self._play_toggled_cb, [play_img, pause_img])
        self.insert(self.play_button, -1)
        self.play_button.set_tooltip(_('Play / Pause'))

        combo = ComboBox()
        which = 0
        for pair in voice_names:
            language, name = pair
            combo.append_item(language, name)
            if language == self._voice:
                combo.set_active(which)
            which += 1

        combo.connect('changed', self._voice_changed_cb)
        combotool = ToolComboBox(combo)
        self.insert(combotool, -1)
        combotool.show()

        self.pitchadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0)
        pitchbar = Gtk.HScale()
        pitchbar.set_adjustment(self.pitchadj)
        pitchbar.set_draw_value(False)
        # pitchbar.set_update_policy(Gtk.UpdatePolicy.ALWAYS)
        pitchbar.set_size_request(150,15)
        pitchtool = Gtk.ToolItem()
        pitchtool.add(pitchbar)
        pitchtool.show()
        self.insert(pitchtool, -1)
        pitchbar.show()

        self.rateadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0)
        ratebar = Gtk.HScale()
        ratebar.set_adjustment(self.rateadj)
        ratebar.set_draw_value(False)
        #ratebar.set_update_policy(Gtk.UpdatePolicy.ALWAYS)
        ratebar.set_size_request(150,15)
        ratetool = Gtk.ToolItem()
        ratetool.add(ratebar)
        ratetool.show()
        self.insert(ratetool, -1)
        ratebar.show()
示例#16
0
class SpeechToolbar(Gtk.Toolbar):
    def __init__(self, activity):
        Gtk.Toolbar.__init__(self)
        self._activity = activity
        if not speech.supported:
            return
        self.is_paused = False

        self.load_speech_parameters()

        self.sorted_voices = [i for i in speech.voices()]
        self.sorted_voices.sort(self.compare_voices)
        default = 0
        for voice in self.sorted_voices:
            if voice[0] == speech.voice[0]:
                break
            default = default + 1

        # Play button
        self.play_btn = ToggleToolButton('media-playback-start')
        self.play_btn.show()
        self.play_btn.connect('toggled', self.play_cb)
        self.insert(self.play_btn, -1)
        self.play_btn.set_tooltip(_('Play / Pause'))

        # Stop button
        self.stop_btn = ToolButton('media-playback-stop')
        self.stop_btn.show()
        self.stop_btn.connect('clicked', self.stop_cb)
        self.stop_btn.set_sensitive(False)
        self.insert(self.stop_btn, -1)
        self.stop_btn.set_tooltip(_('Stop'))

        self.voice_combo = ComboBox()
        for voice in self.sorted_voices:
            self.voice_combo.append_item(voice, voice[0])
        self.voice_combo.set_active(default)

        self.voice_combo.connect('changed', self.voice_changed_cb)
        combotool = ToolComboBox(self.voice_combo)
        self.insert(combotool, -1)
        combotool.show()
        speech.reset_buttons_cb = self.reset_buttons_cb

    def compare_voices(self, a, b):
        if a[0].lower() == b[0].lower():
            return 0
        if a[0].lower() < b[0].lower():
            return -1
        if a[0].lower() > b[0].lower():
            return 1

    def voice_changed_cb(self, combo):
        speech.voice = combo.props.value
        speech.say(speech.voice[0])
        self.save_speech_parameters()

    def load_speech_parameters(self):
        speech_parameters = {}
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        if os.path.exists(data_file_name):
            f = open(data_file_name, 'r')
            try:
                speech_parameters = json.load(f)
                speech.voice = speech_parameters['voice']
            finally:
                f.close()

    def save_speech_parameters(self):
        speech_parameters = {}
        speech_parameters['voice'] = speech.voice
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        f = open(data_file_name, 'w')
        try:
            json.dump(speech_parameters, f)
        finally:
            f.close()

    def reset_buttons_cb(self):
        self.play_btn.set_icon_name('media-playback-start')
        self.stop_btn.set_sensitive(False)
        self.is_paused = False

    def play_cb(self, widget):
        self.stop_btn.set_sensitive(True)
        if widget.get_active():
            self.play_btn.set_icon_name('media-playback-pause')
            if not self.is_paused:
                speech.play(self._activity._view.get_marked_words())
            else:
                speech.continue_play()
        else:
            self.play_btn.set_icon_name('media-playback-start')
            self.is_paused = True
            speech.pause()

    def stop_cb(self, widget):
        self.stop_btn.set_sensitive(False)
        self.play_btn.set_icon_name('media-playback-start')
        self.play_btn.set_active(False)
        self.is_paused = False
        speech.stop()
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
示例#18
0
class SpeechToolbar(Gtk.Toolbar):

    def __init__(self, activity):
        Gtk.Toolbar.__init__(self)
        self._activity = activity
        if not speech.supported:
            return
        self.is_paused = False

        self._cnf_client = GConf.Client.get_default()
        self.load_speech_parameters()

        self.sorted_voices = [i for i in speech.voices()]
        self.sorted_voices.sort(self.compare_voices)
        default = 0
        for voice in self.sorted_voices:
            if voice[0] == speech.voice[0]:
                break
            default = default + 1

        # Play button
        self.play_btn = ToggleToolButton('media-playback-start')
        self.play_btn.show()
        self.play_btn.connect('toggled', self.play_cb)
        self.insert(self.play_btn, -1)
        self.play_btn.set_tooltip(_('Play / Pause'))

        # Stop button
        self.stop_btn = ToolButton('media-playback-stop')
        self.stop_btn.show()
        self.stop_btn.connect('clicked', self.stop_cb)
        self.stop_btn.set_sensitive(False)
        self.insert(self.stop_btn, -1)
        self.stop_btn.set_tooltip(_('Stop'))

        self.voice_combo = ComboBox()
        for voice in self.sorted_voices:
            self.voice_combo.append_item(voice, voice[0])
        self.voice_combo.set_active(default)

        self.voice_combo.connect('changed', self.voice_changed_cb)
        combotool = ToolComboBox(self.voice_combo)
        self.insert(combotool, -1)
        combotool.show()
        speech.reset_buttons_cb = self.reset_buttons_cb

    def compare_voices(self,  a,  b):
        if a[0].lower() == b[0].lower():
            return 0
        if a[0] .lower() < b[0].lower():
            return -1
        if a[0] .lower() > b[0].lower():
            return 1

    def voice_changed_cb(self, combo):
        speech.voice = combo.props.value
        speech.say(speech.voice[0])
        self.save_speech_parameters()

    def load_speech_parameters(self):
        speech_parameters = {}
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        if os.path.exists(data_file_name):
            f = open(data_file_name, 'r')
            try:
                speech_parameters = json.load(f)
                speech.voice = speech_parameters['voice']
            finally:
                f.close()

        self._cnf_client.add_dir('/desktop/sugar/speech',
                                 GConf.ClientPreloadType.PRELOAD_NONE)
        speech.pitch = self._cnf_client.get_int('/desktop/sugar/speech/pitch')
        speech.rate = self._cnf_client.get_int('/desktop/sugar/speech/rate')
        self._cnf_client.notify_add('/desktop/sugar/speech/pitch',
                                    self.__conf_changed_cb, None)
        self._cnf_client.notify_add('/desktop/sugar/speech/rate',
                                    self.__conf_changed_cb, None)

    def __conf_changed_cb(self, client, connection_id, entry, args):
        key = entry.get_key()
        value = client.get_int(key)
        if key == '/desktop/sugar/speech/pitch':
            speech.pitch = value
        if key == '/desktop/sugar/speech/rate':
            speech.rate = value

    def save_speech_parameters(self):
        speech_parameters = {}
        speech_parameters['voice'] = speech.voice
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        f = open(data_file_name, 'w')
        try:
            json.dump(speech_parameters, f)
        finally:
            f.close()

    def reset_buttons_cb(self):
        self.play_btn.set_icon_name('media-playback-start')
        self.stop_btn.set_sensitive(False)
        self.is_paused = False

    def play_cb(self, widget):
        self.stop_btn.set_sensitive(True)
        if widget.get_active():
            self.play_btn.set_icon_name('media-playback-pause')
            if not self.is_paused:
                speech.play(self._activity._view.get_marked_words())
            else:
                speech.continue_play()
        else:
            self.play_btn.set_icon_name('media-playback-start')
            self.is_paused = True
            speech.pause()

    def stop_cb(self, widget):
        self.stop_btn.set_sensitive(False)
        self.play_btn.set_icon_name('media-playback-start')
        self.play_btn.set_active(False)
        self.is_paused = False
        speech.stop()
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
示例#20
0
from gi.repository import Gtk

from sugar3.graphics.combobox import ComboBox


def _destroy_cb(widget, data=None):
    Gtk.main_quit()


def __combo_changed_cb(widget, data=None):
    print 'combo-changed'


w = Gtk.Window()
w.connect("destroy", _destroy_cb)

box = Gtk.VBox()
w.add(box)

combo = ComboBox()
combo.append_item(0, 'one')
combo.append_item(1, 'two', 'go-next')
combo.append_item(2, 'three')
combo.set_active(1)
combo.connect('changed', __combo_changed_cb)
box.pack_start(combo, False, False, 0)

w.show_all()

Gtk.main()
示例#21
0
class MainToolbox(ToolbarBox):

    __gsignals__ = {
        'query-changed': (GObject.SignalFlags.RUN_FIRST, None, ([object])),
    }

    def __init__(self):
        ToolbarBox.__init__(self)

        self._mount_point = None

        self.search_entry = iconentry.IconEntry()
        self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                             'entry-search')
        text = _('Search in %s') % _('Journal')
        self.search_entry.set_placeholder_text(text)
        self.search_entry.connect('activate', self._search_entry_activated_cb)
        self.search_entry.connect('changed', self._search_entry_changed_cb)
        self.search_entry.add_clear_button()
        self._autosearch_timer = None
        self._add_widget(self.search_entry, expand=True)

        self._favorite_button = ToggleToolButton('emblem-favorite')
        self._favorite_button.set_tooltip(_('Favorite entries'))
        self._favorite_button.connect('toggled',
                                      self.__favorite_button_toggled_cb)
        self.toolbar.insert(self._favorite_button, -1)
        self._favorite_button.show()

        self._what_search_combo = ComboBox()
        self._what_combo_changed_sid = self._what_search_combo.connect(
            'changed', self._combo_changed_cb)
        tool_item = ToolComboBox(self._what_search_combo)
        self.toolbar.insert(tool_item, -1)
        tool_item.show()

        self._when_search_combo = self._get_when_search_combo()
        tool_item = ToolComboBox(self._when_search_combo)
        self.toolbar.insert(tool_item, -1)
        tool_item.show()

        self._sorting_button = SortingButton()
        self.toolbar.insert(self._sorting_button, -1)
        self._sorting_button.connect('sort-property-changed',
                                     self.__sort_changed_cb)
        self._sorting_button.show()

        # TODO: enable it when the DS supports saving the buddies.
        #self._with_search_combo = self._get_with_search_combo()
        #tool_item = ToolComboBox(self._with_search_combo)
        #self.insert(tool_item, -1)
        #tool_item.show()

        self._query = self._build_query()

        self.refresh_filters()

    def _get_when_search_combo(self):
        when_search = ComboBox()
        when_search.append_item(_ACTION_ANYTIME, _('Anytime'))
        when_search.append_separator()
        when_search.append_item(_ACTION_TODAY, _('Today'))
        when_search.append_item(_ACTION_SINCE_YESTERDAY, _('Since yesterday'))
        # TRANS: Filter entries modified during the last 7 days.
        when_search.append_item(_ACTION_PAST_WEEK, _('Past week'))
        # TRANS: Filter entries modified during the last 30 days.
        when_search.append_item(_ACTION_PAST_MONTH, _('Past month'))
        # TRANS: Filter entries modified during the last 356 days.
        when_search.append_item(_ACTION_PAST_YEAR, _('Past year'))
        when_search.set_active(0)
        when_search.connect('changed', self._combo_changed_cb)
        return when_search

    def _get_with_search_combo(self):
        with_search = ComboBox()
        with_search.append_item(_ACTION_EVERYBODY, _('Anyone'))
        with_search.append_separator()
        with_search.append_item(_ACTION_MY_FRIENDS, _('My friends'))
        with_search.append_item(_ACTION_MY_CLASS, _('My class'))
        with_search.append_separator()

        # TODO: Ask the model for buddies.
        with_search.append_item(3, 'Dan', 'theme:xo')

        with_search.set_active(0)
        with_search.connect('changed', self._combo_changed_cb)
        return with_search

    def _add_widget(self, widget, expand=False):
        tool_item = Gtk.ToolItem()
        tool_item.set_expand(expand)

        tool_item.add(widget)
        widget.show()

        self.toolbar.insert(tool_item, -1)
        tool_item.show()

    def _build_query(self):
        query = {}

        if self._mount_point:
            query['mountpoints'] = [self._mount_point]

        if self._favorite_button.props.active:
            query['keep'] = 1

        if self._what_search_combo.props.value:
            value = self._what_search_combo.props.value
            generic_type = mime.get_generic_type(value)
            if generic_type:
                mime_types = generic_type.mime_types
                query['mime_type'] = mime_types
            else:
                query['activity'] = self._what_search_combo.props.value

        if self._when_search_combo.props.value:
            date_from, date_to = self._get_date_range()
            query['timestamp'] = {'start': date_from, 'end': date_to}

        if self.search_entry.props.text:
            text = self.search_entry.props.text.strip()
            if text:
                query['query'] = text

        property_, order = self._sorting_button.get_current_sort()

        if order == Gtk.SortType.ASCENDING:
            sign = '+'
        else:
            sign = '-'
        query['order_by'] = [sign + property_]

        return query

    def _get_date_range(self):
        today_start = datetime.today().replace(hour=0, minute=0, second=0)
        right_now = datetime.today()
        if self._when_search_combo.props.value == _ACTION_TODAY:
            date_range = (today_start, right_now)
        elif self._when_search_combo.props.value == _ACTION_SINCE_YESTERDAY:
            date_range = (today_start - timedelta(1), right_now)
        elif self._when_search_combo.props.value == _ACTION_PAST_WEEK:
            date_range = (today_start - timedelta(7), right_now)
        elif self._when_search_combo.props.value == _ACTION_PAST_MONTH:
            date_range = (today_start - timedelta(30), right_now)
        elif self._when_search_combo.props.value == _ACTION_PAST_YEAR:
            date_range = (today_start - timedelta(356), right_now)

        return (time.mktime(date_range[0].timetuple()),
                time.mktime(date_range[1].timetuple()))

    def _combo_changed_cb(self, combo):
        self._update_if_needed()

    def __sort_changed_cb(self, button):
        self._update_if_needed()

    def _update_if_needed(self):
        new_query = self._build_query()
        if self._query != new_query:
            self._query = new_query
            self.emit('query-changed', self._query)

    def _search_entry_activated_cb(self, search_entry):
        if self._autosearch_timer:
            GObject.source_remove(self._autosearch_timer)
        new_query = self._build_query()
        if self._query != new_query:
            self._query = new_query
            self.emit('query-changed', self._query)

    def _search_entry_changed_cb(self, search_entry):
        if not search_entry.props.text:
            search_entry.activate()
            return

        if self._autosearch_timer:
            GObject.source_remove(self._autosearch_timer)
        self._autosearch_timer = GObject.timeout_add(_AUTOSEARCH_TIMEOUT,
                                                     self._autosearch_timer_cb)

    def _autosearch_timer_cb(self):
        logging.debug('_autosearch_timer_cb')
        self._autosearch_timer = None
        self.search_entry.activate()
        return False

    def set_mount_point(self, mount_point):
        self._mount_point = mount_point
        new_query = self._build_query()
        if self._query != new_query:
            self._query = new_query
            self.emit('query-changed', self._query)

    def set_what_filter(self, what_filter):
        combo_model = self._what_search_combo.get_model()
        what_filter_index = -1
        for i in range(0, len(combo_model) - 1):
            if combo_model[i][0] == what_filter:
                what_filter_index = i
                break

        if what_filter_index == -1:
            logging.warning('what_filter %r not known', what_filter)
        else:
            self._what_search_combo.set_active(what_filter_index)

    def refresh_filters(self):
        current_value = self._what_search_combo.props.value
        current_value_index = 0

        self._what_search_combo.handler_block(self._what_combo_changed_sid)
        try:
            self._what_search_combo.remove_all()
            # TRANS: Item in a combo box that filters by entry type.
            self._what_search_combo.append_item(_ACTION_ANYTHING,
                                                _('Anything'))

            registry = bundleregistry.get_registry()
            appended_separator = False

            types = mime.get_all_generic_types()
            for generic_type in types:
                if not appended_separator:
                    self._what_search_combo.append_separator()
                    appended_separator = True
                self._what_search_combo.append_item(generic_type.type_id,
                                                    generic_type.name,
                                                    generic_type.icon)
                if generic_type.type_id == current_value:
                    current_value_index = \
                            len(self._what_search_combo.get_model()) - 1

                self._what_search_combo.set_active(current_value_index)

            self._what_search_combo.append_separator()

            for service_name in model.get_unique_values('activity'):
                activity_info = registry.get_bundle(service_name)
                if activity_info is None:
                    continue

                if service_name == current_value:
                    combo_model = self._what_search_combo.get_model()
                    current_value_index = len(combo_model)

                # try activity-provided icon
                if os.path.exists(activity_info.get_icon()):
                    try:
                        self._what_search_combo.append_item(
                            service_name,
                            activity_info.get_name(),
                            file_name=activity_info.get_icon())
                    except GObject.GError, exception:
                        logging.warning(
                            'Falling back to default icon for'
                            ' "what" filter because %r (%r) has an'
                            ' invalid icon: %s', activity_info.get_name(),
                            str(service_name), exception)
                    else:
                        continue

                # fall back to generic icon
                self._what_search_combo.append_item(
                    service_name,
                    activity_info.get_name(),
                    icon_name='application-octet-stream')

        finally:
            self._what_search_combo.handler_unblock(
                self._what_combo_changed_sid)

    def __favorite_button_toggled_cb(self, favorite_button):
        self._update_if_needed()

    def clear_query(self):
        self.search_entry.props.text = ''
        self._what_search_combo.set_active(0)
        self._when_search_combo.set_active(0)
        self._favorite_button.props.active = False
class SpeechToolbar(Gtk.Toolbar):
    def __init__(self, activity):
        GObject.GObject.__init__(self)
        self._activity = activity
        if not speech.supported:
            return
        self.is_paused = False
        self._cnf_client = GConf.Client.get_default()
        self.load_speech_parameters()

        self.sorted_voices = [i for i in speech.voices()]
        self.sorted_voices.sort(self.compare_voices)
        default = 0
        for voice in self.sorted_voices:
            if voice[0] == speech.voice[0]:
                break
            default = default + 1

        # Play button
        self.play_btn = ToggleToolButton('media-playback-start')
        self.play_btn.show()
        self.play_toggled_handler = self.play_btn.connect(
            'toggled', self.play_cb)
        self.insert(self.play_btn, -1)
        self.play_btn.set_tooltip(_('Play / Pause'))

        # Stop button
        self.stop_btn = ToolButton('media-playback-stop')
        self.stop_btn.show()
        self.stop_btn.connect('clicked', self.stop_cb)
        self.stop_btn.set_sensitive(False)
        self.insert(self.stop_btn, -1)
        self.stop_btn.set_tooltip(_('Stop'))

        self.voice_combo = ComboBox()
        for voice in self.sorted_voices:
            self.voice_combo.append_item(voice, voice[0])
        self.voice_combo.set_active(default)

        self.voice_combo.connect('changed', self.voice_changed_cb)
        combotool = ToolComboBox(self.voice_combo)
        self.insert(combotool, -1)
        combotool.show()
        speech.reset_cb = self.reset_buttons_cb
        speech.end_text_cb = self.reset_buttons_cb

    def compare_voices(self, a, b):
        if a[0].lower() == b[0].lower():
            return 0
        if a[0].lower() < b[0].lower():
            return -1
        if a[0].lower() > b[0].lower():
            return 1

    def voice_changed_cb(self, combo):
        speech.voice = combo.props.value
        speech.say(speech.voice[0])
        self.save_speech_parameters()

    def load_speech_parameters(self):
        speech_parameters = {}
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        if os.path.exists(data_file_name):
            f = open(data_file_name, 'r')
            try:
                speech_parameters = json.load(f)
                speech.voice = speech_parameters['voice']
            finally:
                f.close()
        else:
            speech.voice = self.get_default_voice()
            logging.error('Default voice %s', speech.voice)

        self._cnf_client.add_dir('/desktop/sugar/speech',
                                 GConf.ClientPreloadType.PRELOAD_NONE)
        speech.pitch = self._cnf_client.get_int('/desktop/sugar/speech/pitch')
        speech.rate = self._cnf_client.get_int('/desktop/sugar/speech/rate')
        self._cnf_client.notify_add('/desktop/sugar/speech/pitch',
                                    self.__conf_changed_cb, None)
        self._cnf_client.notify_add('/desktop/sugar/speech/rate',
                                    self.__conf_changed_cb, None)

    def get_default_voice(self):
        """Try to figure out the default voice, from the current locale
           ($LANG)
           Fall back to espeak's voice called Default."""
        voices = speech.get_all_voices()

        locale = os.environ.get('LANG', '')
        language_location = locale.split('.', 1)[0].lower()
        language = language_location.split('_')[0]
        variant = ''
        if language_location.find('_') > -1:
            variant = language_location.split('_')[1]
        # if the language is es but not es_es default to es_la (latin voice)
        if language == 'es' and language_location != 'es_es':
            language_location = 'es_la'

        best = voices.get(language_location) or voices.get(language) \
            or 'default'
        logging.debug('Best voice for LANG %s seems to be %s', locale, best)
        return [best, language, variant]

    def __conf_changed_cb(self, client, connection_id, entry, args):
        key = entry.get_key()
        value = client.get_int(key)
        if key == '/desktop/sugar/speech/pitch':
            speech.pitch = value
        if key == '/desktop/sugar/speech/rate':
            speech.rate = value

    def save_speech_parameters(self):
        speech_parameters = {}
        speech_parameters['voice'] = speech.voice
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        f = open(data_file_name, 'w')
        try:
            json.dump(speech_parameters, f)
        finally:
            f.close()

    def reset_buttons_cb(self):
        logging.error('reset buttons')
        self.play_btn.set_icon_name('media-playback-start')
        self.stop_btn.set_sensitive(False)
        self.play_btn.handler_block(self.play_toggled_handler)
        self.play_btn.set_active(False)
        self.play_btn.handler_unblock(self.play_toggled_handler)
        self.is_paused = False

    def play_cb(self, widget):
        self.stop_btn.set_sensitive(True)
        if widget.get_active():
            self.play_btn.set_icon_name('media-playback-pause')
            logging.error('Paused %s', self.is_paused)
            if not self.is_paused:
                # get the text to speech, if there are a selection,
                # play selected text, if not, play all
                abi = self._activity.abiword_canvas
                selection = abi.get_selection('text/plain')
                if not selection or selection[0] is None or selection[1] == 0:
                    # nothing selected
                    abi.select_all()
                    text = abi.get_selection('text/plain')[0]
                    abi.moveto_bod()
                else:
                    text = selection[0]
                speech.play(text)
            else:
                logging.error('Continue play')
                speech.continue_play()
        else:
            self.play_btn.set_icon_name('media-playback-start')
            self.is_paused = True
            speech.pause()

    def stop_cb(self, widget):
        self.stop_btn.set_sensitive(False)
        self.play_btn.set_icon_name('media-playback-start')
        self.play_btn.set_active(False)
        self.is_paused = False
        speech.stop()
示例#23
0
class MainToolbox(ToolbarBox):

    __gsignals__ = {
        'query-changed': (GObject.SignalFlags.RUN_FIRST, None,
                          ([object])),
    }

    def __init__(self):
        ToolbarBox.__init__(self)

        self._mount_point = None
        self._filter_type = None
        self._what_filter = None

        self.search_entry = iconentry.IconEntry()
        self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                             'entry-search')
        text = _('Search in %s') % _('Journal')
        self.search_entry.set_placeholder_text(text)
        self.search_entry.connect('activate', self._search_entry_activated_cb)
        self.search_entry.connect('changed', self._search_entry_changed_cb)
        self.search_entry.add_clear_button()
        self._autosearch_timer = None
        self._add_widget(self.search_entry, expand=True)

        self._favorite_button = ToggleToolButton('emblem-favorite')
        self._favorite_button.set_tooltip(_('Favorite entries'))
        self._favorite_button.connect('toggled',
                                      self.__favorite_button_toggled_cb)
        self.toolbar.insert(self._favorite_button, -1)
        self._favorite_button.show()

        self._what_search_combo = ComboBox()
        self._what_combo_changed_sid = self._what_search_combo.connect(
            'changed', self._combo_changed_cb)
        tool_item = ToolComboBox(self._what_search_combo)
        self.toolbar.insert(tool_item, -1)
        tool_item.show()

        self._when_search_combo = self._get_when_search_combo()
        tool_item = ToolComboBox(self._when_search_combo)
        self.toolbar.insert(tool_item, -1)
        tool_item.show()

        self._sorting_button = SortingButton()
        self.toolbar.insert(self._sorting_button, -1)
        self._sorting_button.connect('sort-property-changed',
                                     self.__sort_changed_cb)
        self._sorting_button.show()

        # TODO: enable it when the DS supports saving the buddies.
        # self._with_search_combo = self._get_with_search_combo()
        # tool_item = ToolComboBox(self._with_search_combo)
        # self.insert(tool_item, -1)
        # tool_item.show()

        self._query = self._build_query()

        self.refresh_filters()

    def _get_when_search_combo(self):
        when_search = ComboBox()
        when_search.append_item(_ACTION_ANYTIME, _('Anytime'))
        when_search.append_separator()
        when_search.append_item(_ACTION_TODAY, _('Today'))
        when_search.append_item(_ACTION_SINCE_YESTERDAY,
                                _('Since yesterday'))
        # TRANS: Filter entries modified during the last 7 days.
        when_search.append_item(_ACTION_PAST_WEEK, _('Past week'))
        # TRANS: Filter entries modified during the last 30 days.
        when_search.append_item(_ACTION_PAST_MONTH, _('Past month'))
        # TRANS: Filter entries modified during the last 356 days.
        when_search.append_item(_ACTION_PAST_YEAR, _('Past year'))
        when_search.set_active(0)
        when_search.connect('changed', self._combo_changed_cb)
        return when_search

    def _get_with_search_combo(self):
        with_search = ComboBox()
        with_search.append_item(_ACTION_EVERYBODY, _('Anyone'))
        with_search.append_separator()
        with_search.append_item(_ACTION_MY_FRIENDS, _('My friends'))
        with_search.append_item(_ACTION_MY_CLASS, _('My class'))
        with_search.append_separator()

        # TODO: Ask the model for buddies.
        with_search.append_item(3, 'Dan', 'theme:xo')

        with_search.set_active(0)
        with_search.connect('changed', self._combo_changed_cb)
        return with_search

    def _add_widget(self, widget, expand=False):
        tool_item = Gtk.ToolItem()
        tool_item.set_expand(expand)

        tool_item.add(widget)
        widget.show()

        self.toolbar.insert(tool_item, -1)
        tool_item.show()

    def _build_query(self):
        query = {}

        if self._mount_point:
            query['mountpoints'] = [self._mount_point]

        if self._favorite_button.props.active:
            query['keep'] = 1

        if self._what_search_combo.props.value:
            value = self._what_search_combo.props.value
            filter_type = self._filter_type
            if self._filter_type is None:
                # for backward compatibility, try to guess the filter
                generic_type = mime.get_generic_type(value)
                if generic_type:
                    filter_type = FILTER_TYPE_GENERIC_MIME
                else:
                    filter_type = FILTER_TYPE_ACTIVITY
                logging.error('DEPRECATED: sety the filter_type parameter')

            if filter_type == FILTER_TYPE_GENERIC_MIME:
                generic_type = mime.get_generic_type(value)
                if generic_type:
                    mime_types = generic_type.mime_types
                    query['mime_type'] = mime_types
                else:
                    logging.error('filter_type="generic_mime", '
                                  'but "%s" is not a generic mime' % value)

            elif filter_type == FILTER_TYPE_ACTIVITY:
                query['activity'] = value

            elif self._filter_type == FILTER_TYPE_MIME_BY_ACTIVITY:
                registry = bundleregistry.get_registry()
                bundle = \
                    registry.get_bundle(value)
                if bundle is not None:
                    query['mime_type'] = bundle.get_mime_types()
                else:
                    logging.error('Trying to filter using activity mimetype '
                                  'but bundle id is wrong %s' % value)

        if self._when_search_combo.props.value:
            date_from, date_to = self._get_date_range()
            query['timestamp'] = {'start': date_from, 'end': date_to}

        if self.search_entry.props.text:
            text = self.search_entry.props.text.strip()
            if text:
                query['query'] = text

        property_, order = self._sorting_button.get_current_sort()

        if order == Gtk.SortType.ASCENDING:
            sign = '+'
        else:
            sign = '-'
        query['order_by'] = [sign + property_]

        return query

    def _get_date_range(self):
        today_start = datetime.today().replace(hour=0, minute=0, second=0)
        right_now = datetime.today()
        if self._when_search_combo.props.value == _ACTION_TODAY:
            date_range = (today_start, right_now)
        elif self._when_search_combo.props.value == _ACTION_SINCE_YESTERDAY:
            date_range = (today_start - timedelta(1), right_now)
        elif self._when_search_combo.props.value == _ACTION_PAST_WEEK:
            date_range = (today_start - timedelta(7), right_now)
        elif self._when_search_combo.props.value == _ACTION_PAST_MONTH:
            date_range = (today_start - timedelta(30), right_now)
        elif self._when_search_combo.props.value == _ACTION_PAST_YEAR:
            date_range = (today_start - timedelta(356), right_now)

        return (time.mktime(date_range[0].timetuple()),
                time.mktime(date_range[1].timetuple()))

    def _combo_changed_cb(self, combo):
        self._update_if_needed()

    def __sort_changed_cb(self, button):
        self._update_if_needed()

    def _update_if_needed(self):
        # check if the what_search combo should be visible
        self._what_search_combo.set_visible(
            self._filter_type != FILTER_TYPE_MIME_BY_ACTIVITY)

        new_query = self._build_query()
        if self._query != new_query:
            self._query = new_query
            self.emit('query-changed', self._query)

    def _search_entry_activated_cb(self, search_entry):
        if self._autosearch_timer:
            GObject.source_remove(self._autosearch_timer)
        self._update_if_needed()

    def _search_entry_changed_cb(self, search_entry):
        if not search_entry.props.text:
            search_entry.activate()
            return

        if self._autosearch_timer:
            GObject.source_remove(self._autosearch_timer)
        self._autosearch_timer = GObject.timeout_add(_AUTOSEARCH_TIMEOUT,
                                                     self._autosearch_timer_cb)

    def _autosearch_timer_cb(self):
        logging.debug('_autosearch_timer_cb')
        self._autosearch_timer = None
        self.search_entry.activate()
        return False

    def set_mount_point(self, mount_point):
        self._mount_point = mount_point
        self._update_if_needed()

    def set_what_filter(self, what_filter):
        combo_model = self._what_search_combo.get_model()
        what_filter_index = -1
        for i in range(0, len(combo_model) - 1):
            if combo_model[i][0] == what_filter:
                what_filter_index = i
                break

        if what_filter_index == -1:
            logging.warning('what_filter %r not known', what_filter)
        else:
            self._what_search_combo.set_active(what_filter_index)

    def update_filters(self, mount_point, what_filter, filter_type=None):
        self._mount_point = mount_point
        self._filter_type = filter_type
        self._what_filter = what_filter
        self.set_what_filter(what_filter)
        self._update_if_needed()

    def set_filter_type(self, filter_type):
        self._filter_type = filter_type
        self._update_if_needed()

    def refresh_filters(self):
        current_value = self._what_search_combo.props.value
        current_value_index = 0

        self._what_search_combo.handler_block(self._what_combo_changed_sid)
        try:
            self._what_search_combo.remove_all()
            # TRANS: Item in a combo box that filters by entry type.
            self._what_search_combo.append_item(_ACTION_ANYTHING,
                                                _('Anything'))

            registry = bundleregistry.get_registry()
            appended_separator = False

            types = mime.get_all_generic_types()
            for generic_type in types:
                if not appended_separator:
                    self._what_search_combo.append_separator()
                    appended_separator = True
                self._what_search_combo.append_item(
                    generic_type.type_id, generic_type.name, generic_type.icon)
                if generic_type.type_id == current_value:
                    current_value_index = \
                        len(self._what_search_combo.get_model()) - 1

                self._what_search_combo.set_active(current_value_index)

            self._what_search_combo.append_separator()

            for service_name in model.get_unique_values('activity'):
                activity_info = registry.get_bundle(service_name)
                if activity_info is None:
                    continue

                if service_name == current_value:
                    combo_model = self._what_search_combo.get_model()
                    current_value_index = len(combo_model)

                # try activity-provided icon
                if os.path.exists(activity_info.get_icon()):
                    try:
                        self._what_search_combo.append_item(
                            service_name,
                            activity_info.get_name(),
                            file_name=activity_info.get_icon())
                    except GObject.GError, exception:
                        logging.warning('Falling back to default icon for'
                                        ' "what" filter because %r (%r) has an'
                                        ' invalid icon: %s',
                                        activity_info.get_name(),
                                        str(service_name), exception)
                    else:
                        continue

                # fall back to generic icon
                self._what_search_combo.append_item(
                    service_name,
                    activity_info.get_name(),
                    icon_name='application-octet-stream')

        finally:
            self._what_search_combo.handler_unblock(
                self._what_combo_changed_sid)

    def __favorite_button_toggled_cb(self, favorite_button):
        self._update_if_needed()

    def clear_query(self):
        self.search_entry.props.text = ''
        if self._what_filter is None:
            self._what_search_combo.set_active(0)
        else:
            self.set_what_filter(self._what_filter)
        self._when_search_combo.set_active(0)
        self._favorite_button.props.active = False
示例#24
0
class SpeechToolbar(Gtk.Toolbar):
    def __init__(self, activity):
        GObject.GObject.__init__(self)
        self._activity = activity
        if not speech.supported:
            return
        self.is_paused = False
        self.load_speech_parameters()

        self.sorted_voices = [i for i in speech.voices()]
        self.sorted_voices.sort(self.compare_voices)
        default = 0
        for voice in self.sorted_voices:
            if voice[0] == speech.voice[0]:
                break
            default = default + 1

        # Play button
        self.play_btn = ToggleToolButton('media-playback-start')
        self.play_btn.show()
        self.play_toggled_handler = self.play_btn.connect(
            'toggled', self.play_cb)
        self.insert(self.play_btn, -1)
        self.play_btn.set_tooltip(_('Play / Pause'))

        # Stop button
        self.stop_btn = ToolButton('media-playback-stop')
        self.stop_btn.show()
        self.stop_btn.connect('clicked', self.stop_cb)
        self.stop_btn.set_sensitive(False)
        self.insert(self.stop_btn, -1)
        self.stop_btn.set_tooltip(_('Stop'))

        self.voice_combo = ComboBox()
        for voice in self.sorted_voices:
            self.voice_combo.append_item(voice, voice[0])
        self.voice_combo.set_active(default)

        self.voice_combo.connect('changed', self.voice_changed_cb)
        combotool = ToolComboBox(self.voice_combo)
        self.insert(combotool, -1)
        combotool.show()
        speech.reset_cb = self.reset_buttons_cb
        speech.end_text_cb = self.reset_buttons_cb

    def compare_voices(self, a, b):
        if a[0].lower() == b[0].lower():
            return 0
        if a[0].lower() < b[0].lower():
            return -1
        if a[0].lower() > b[0].lower():
            return 1

    def voice_changed_cb(self, combo):
        speech.voice = combo.props.value
        speech.say(speech.voice[0])
        self.save_speech_parameters()

    def load_speech_parameters(self):
        speech_parameters = {}
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        if os.path.exists(data_file_name):
            f = open(data_file_name, 'r')
            try:
                speech_parameters = json.load(f)
                speech.voice = speech_parameters['voice']
            finally:
                f.close()

    def save_speech_parameters(self):
        speech_parameters = {}
        speech_parameters['voice'] = speech.voice
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        f = open(data_file_name, 'w')
        try:
            json.dump(speech_parameters, f)
        finally:
            f.close()

    def reset_buttons_cb(self):
        logging.error('reset buttons')
        self.play_btn.set_icon_name('media-playback-start')
        self.stop_btn.set_sensitive(False)
        self.play_btn.handler_block(self.play_toggled_handler)
        self.play_btn.set_active(False)
        self.play_btn.handler_unblock(self.play_toggled_handler)
        self.is_paused = False

    def play_cb(self, widget):
        self.stop_btn.set_sensitive(True)
        if widget.get_active():
            self.play_btn.set_icon_name('media-playback-pause')
            logging.error('Paused %s', self.is_paused)
            if not self.is_paused:
                # get the text to speech, if there are a selection,
                # play selected text, if not, play all
                abi = self._activity.abiword_canvas
                selection = abi.get_selection('text/plain')
                if not selection or selection[0] is None or selection[1] == 0:
                    # nothing selected
                    abi.select_all()
                    text = abi.get_selection('text/plain')[0]
                    abi.moveto_bod()
                else:
                    text = selection[0]
                speech.play(text)
            else:
                logging.error('Continue play')
                speech.continue_play()
        else:
            self.play_btn.set_icon_name('media-playback-start')
            self.is_paused = True
            speech.pause()

    def stop_cb(self, widget):
        self.stop_btn.set_sensitive(False)
        self.play_btn.set_icon_name('media-playback-start')
        self.play_btn.set_active(False)
        self.is_paused = False
        speech.stop()
示例#25
0
    def __init__(self):
        Gtk.Toolbar.__init__(self)
        self.activity = None
        self._speech = SpeechManager()
        self._voices = self._speech.get_all_voices()  # a dictionary

        locale = os.environ.get('LANG', '')
        language_location = locale.split('.', 1)[0].lower()
        language = language_location.split('_')[0]
        # if the language is es but not es_es default to es_la (latin voice)
        if language == 'es' and language_location != 'es_es':
            language_location = 'es_la'

        self._voice = 'en_us'
        if language_location in self._voices:
            self._voice = language_location
        elif language in self._voices:
            self._voice = language

        voice_names = []
        for language, name in self._voices.items():
            voice_names.append((language, name))
        voice_names.sort()

        # Play button Image
        play_img = Gtk.Image()
        play_img.show()
        play_img.set_from_icon_name('media-playback-start',
                                    Gtk.IconSize.LARGE_TOOLBAR)

        # Pause button Image
        pause_img = Gtk.Image()
        pause_img.show()
        pause_img.set_from_icon_name('media-playback-pause',
                                     Gtk.IconSize.LARGE_TOOLBAR)

        # Play button
        self.play_button = ToggleToolButton('media-playback-start')
        self.play_button.show()
        self.play_button.connect('toggled', self._play_toggled_cb,
                                 [play_img, pause_img])
        self.insert(self.play_button, -1)
        self.play_button.set_tooltip(_('Play / Pause'))

        combo = ComboBox()
        which = 0
        for pair in voice_names:
            language, name = pair
            combo.append_item(language, name)
            if language == self._voice:
                combo.set_active(which)
            which += 1

        combo.connect('changed', self._voice_changed_cb)
        combotool = ToolComboBox(combo)
        self.insert(combotool, -1)
        combotool.show()

        self.pitchadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0)
        pitchbar = Gtk.HScale()
        pitchbar.set_adjustment(self.pitchadj)
        pitchbar.set_draw_value(False)
        # pitchbar.set_update_policy(Gtk.UpdatePolicy.ALWAYS)
        pitchbar.set_size_request(150, 15)
        pitchtool = Gtk.ToolItem()
        pitchtool.add(pitchbar)
        pitchtool.show()
        self.insert(pitchtool, -1)
        pitchbar.show()

        self.rateadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0)
        ratebar = Gtk.HScale()
        ratebar.set_adjustment(self.rateadj)
        ratebar.set_draw_value(False)
        # ratebar.set_update_policy(Gtk.UpdatePolicy.ALWAYS)
        ratebar.set_size_request(150, 15)
        ratetool = Gtk.ToolItem()
        ratetool.add(ratebar)
        ratetool.show()
        self.insert(ratetool, -1)
        ratebar.show()
class SpeechToolbar(Gtk.Toolbar):

    def __init__(self, activity):
        Gtk.Toolbar.__init__(self)
        self._activity = activity
        if not speech.supported:
            return

        self._cnf_client = GConf.Client.get_default()
        self.load_speech_parameters()

        self.sorted_voices = [i for i in speech.voices()]
        self.sorted_voices.sort(self.compare_voices)
        default = 0
        for voice in self.sorted_voices:
            if voice[0] == speech.voice[0]:
                break
            default = default + 1

        # Play button
        self.play_btn = ToggleToolButton('media-playback-start')
        self.play_btn.show()
        self.play_btn.connect('toggled', self.play_cb)
        self.insert(self.play_btn, -1)
        self.play_btn.set_tooltip(_('Play / Pause'))

        # Stop button
        self.stop_btn = ToolButton('media-playback-stop')
        self.stop_btn.show()
        self.stop_btn.connect('clicked', self.stop_cb)
        self.stop_btn.set_sensitive(False)
        self.insert(self.stop_btn, -1)
        self.stop_btn.set_tooltip(_('Stop'))

        self.voice_combo = ComboBox()
        for voice in self.sorted_voices:
            self.voice_combo.append_item(voice, voice[0])
        self.voice_combo.set_active(default)

        self.voice_combo.connect('changed', self.voice_changed_cb)
        combotool = ToolComboBox(self.voice_combo)
        self.insert(combotool, -1)
        combotool.show()
        speech.reset_buttons_cb = self.reset_buttons_cb

    def compare_voices(self,  a,  b):
        if a[0].lower() == b[0].lower():
            return 0
        if a[0] .lower() < b[0].lower():
            return -1
        if a[0] .lower() > b[0].lower():
            return 1

    def voice_changed_cb(self, combo):
        speech.voice = combo.props.value
        speech.say(speech.voice[0])
        self.save_speech_parameters()

    def load_speech_parameters(self):
        speech_parameters = {}
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        if os.path.exists(data_file_name):
            f = open(data_file_name, 'r')
            try:
                speech_parameters = simplejson.load(f)
                speech.voice = speech_parameters['voice']
            finally:
                f.close()

        self._cnf_client.add_dir('/desktop/sugar/speech',
                GConf.ClientPreloadType.PRELOAD_NONE)
        speech.pitch = self._cnf_client.get_int('/desktop/sugar/speech/pitch')
        speech.rate = self._cnf_client.get_int('/desktop/sugar/speech/rate')
        self._cnf_client.notify_add('/desktop/sugar/speech/pitch', \
                self.__conf_changed_cb, None)
        self._cnf_client.notify_add('/desktop/sugar/speech/rate', \
                self.__conf_changed_cb, None)

    def __conf_changed_cb(self, client, connection_id, entry, args):
        key = entry.get_key()
        value = client.get_int(key)
        if key == '/desktop/sugar/speech/pitch':
            speech.pitch = value
        if key == '/desktop/sugar/speech/rate':
            speech.rate = value

    def save_speech_parameters(self):
        speech_parameters = {}
        speech_parameters['voice'] = speech.voice
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        f = open(data_file_name, 'w')
        try:
            simplejson.dump(speech_parameters, f)
        finally:
            f.close()

    def reset_buttons_cb(self):
        logging.error('reset buttons')
        self.play_btn.set_named_icon('media-playback-start')
        self.stop_btn.set_sensitive(False)

    def play_cb(self, widget):
        self.stop_btn.set_sensitive(True)
        if widget.get_active():
            self.play_btn.set_named_icon('media-playback-pause')
            if speech.is_stopped():
                speech.play(self._activity._view.get_marked_words())
        else:
            self.play_btn.set_named_icon('media-playback-start')
            speech.pause()

    def stop_cb(self, widget):
        self.stop_btn.set_sensitive(False)
        self.play_btn.set_named_icon('media-playback-start')
        self.play_btn.set_active(False)
        speech.stop()
class GetIABooksActivity(activity.Activity):
    def __init__(self, handle, create_jobject=True):
        "The entry point to the Activity"
        activity.Activity.__init__(self, handle,  False)
 
        if _NEW_TOOLBAR_SUPPORT:
            self.create_new_toolbar()
        else:
            self.create_old_toolbar()
        
        self.scrolled = Gtk.ScrolledWindow()
        self.scrolled.set_policy(Gtk.PolicyType.NEVER,
                                 Gtk.PolicyType.AUTOMATIC)
        self.textview = Gtk.TextView()
        self.textview.set_editable(False)
        self.textview.set_cursor_visible(False)
        self.textview.set_justification(Gtk.Justification.LEFT)
        self.textview.set_wrap_mode(Gtk.WrapMode.WORD)
        self.textview.set_left_margin(50)
        self.textview.set_right_margin(50)
        textbuffer = self.textview.get_buffer()
        textbuffer.set_text(_('Enter words from the Author or Title to begin search') + '.')
        self.scrolled.add(self.textview)
        self.textview.show()
        self.scrolled.show()

        self._download_content_length = 0
        self._download_content_type = None

        self.ls = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING,
                                GObject.TYPE_STRING, GObject.TYPE_STRING,
                                GObject.TYPE_STRING, GObject.TYPE_STRING, 
                                GObject.TYPE_STRING, GObject.TYPE_STRING,
                                GObject.TYPE_STRING)
        self.treeview = Gtk.TreeView(self.ls)
        self.treeview.set_rules_hint(True)
        self.treeview.set_search_column(COLUMN_TITLE)
        selection = self.treeview.get_selection()
        selection.set_mode(Gtk.SelectionMode.SINGLE)
        selection.connect("changed", self.selection_cb)

        renderer = Gtk.CellRendererText()
        renderer.set_property('wrap-mode', Gtk.WrapMode.WORD)
        renderer.set_property('wrap-width', 500)
        renderer.set_property('width', 500)
        col = Gtk.TreeViewColumn(_('Title'), renderer, text=COLUMN_TITLE)
        col.set_sort_column_id(COLUMN_TITLE)
        self.treeview.append_column(col)
    
        renderer = Gtk.CellRendererText()
        col = Gtk.TreeViewColumn(_('Volume'), renderer, text=COLUMN_VOLUME)
        col.set_sort_column_id(COLUMN_VOLUME)
        self.treeview.append_column(col)
    
        renderer = Gtk.CellRendererText()
        renderer.set_property('wrap-mode', Gtk.WrapMode.WORD)
        renderer.set_property('wrap-width', 200)
        renderer.set_property('width', 200)
        col = Gtk.TreeViewColumn(_('Author'), renderer, text=COLUMN_CREATOR)
        col.set_sort_column_id(COLUMN_CREATOR)
        self.treeview.append_column(col)

        renderer = Gtk.CellRendererText()
        col = Gtk.TreeViewColumn(_('Language'), renderer, text=COLUMN_LANGUAGE)
        col.set_sort_column_id(COLUMN_LANGUAGE)
        self.treeview.append_column(col)
    
        self.list_scroller = Gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
        self.list_scroller.set_policy(Gtk.PolicyType.NEVER,
                                      Gtk.PolicyType.AUTOMATIC)
        self.list_scroller.add(self.treeview)
        
        self.progressbar = Gtk.ProgressBar()
        self.progressbar.set_orientation(Gtk.Orientation.HORIZONTAL)
        self.progressbar.set_fraction(0.0)
        
        vbox = Gtk.VBox()
        vbox.pack_start(self.progressbar,  False,  False,  10)
        vbox.add(self.scrolled)
        vbox.pack_end(self.list_scroller, True, True, 0)
        self.set_canvas(vbox)
        self.treeview.show()
        vbox.show()
        self.list_scroller.show()
        self.progressbar.hide()

    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 create_old_toolbar(self):
        toolbox = activity.ActivityToolbox(self)
        activity_toolbar = toolbox.get_activity_toolbar()
        activity_toolbar.keep.props.visible = False
        activity_toolbar.share.props.visible = False
        self.set_toolbox(toolbox)

        self._books_toolbar = BooksToolbar()
        toolbox.add_toolbar(_('Books'), self._books_toolbar)
        self._books_toolbar.set_activity(self)
        self._books_toolbar.show()

        toolbox.show()
        self.toolbox.set_current_toolbar(_TOOLBAR_BOOKS)
        self._books_toolbar.search_entry.grab_focus()
        
    def create_new_toolbar(self):
        toolbar_box = ToolbarBox()

        book_search_item = Gtk.ToolItem()

        self.search_entry = Gtk.Entry()
        self.search_entry.connect('activate', self.search_entry_activate_cb)

        width = int(Gdk.Screen.width() / 2.1)
        self.search_entry.set_size_request(width, -1)

        book_search_item.add(self.search_entry)
        self.search_entry.show()

        toolbar_box.toolbar.insert(book_search_item, -1)
        book_search_item.show()

        self._download = ToolButton('go-down')
        self._download.set_tooltip(_('Get Book'))
        self._download.props.sensitive = False
        self._download.connect('clicked', self._get_book_cb)
        toolbar_box.toolbar.insert(self._download, -1)
        self._download.show()

        self.format_combo = ComboBox()
        self.format_combo.connect('changed', self.format_changed_cb)
        self.format_combo.append_item('.djvu', 'Deja Vu')
        self.format_combo.append_item('_bw.pdf', 'B/W PDF')
        self.format_combo.append_item('.pdf', 'Color PDF')
        self.format_combo.append_item('.epub', 'EPUB')
        self.format_combo.set_active(0)
        self.format_combo.props.sensitive = False
        combotool = ToolComboBox(self.format_combo)
        toolbar_box.toolbar.insert(combotool, -1)
        combotool.show()

        self.search_entry.grab_focus()

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

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl><Shift>Q'
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()

    def format_changed_cb(self, combo):
        self.show_book_data()

    def search_entry_activate_cb(self, entry):
        self.find_books(entry.props.text)

    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 selection_cb(self, selection):
        self.clear_downloaded_bytes()
        tv = selection.get_tree_view()
        model = tv.get_model()
        sel = selection.get_selected()
        if sel:
            model, iter = sel
            self.book_data = model.get_value(iter,COLUMN_TITLE) + '\n\n'
            self.selected_title = self.truncate(model.get_value(iter,COLUMN_TITLE),  75)
            self.selected_volume = model.get_value(iter,COLUMN_VOLUME) 
            if self.selected_volume != '':
                self.book_data +=  _('Volume') + ': ' +  self.selected_volume + '\n\n'
            self.book_data +=  model.get_value(iter,COLUMN_CREATOR) + '\n\n'
            self.selected_author =  self.truncate(model.get_value(iter,COLUMN_CREATOR),  40)
            description = model.get_value(iter,COLUMN_DESCRIPTION)
            if description != '':
                self.book_data +=  description  + '\n\n'
            subject = model.get_value(iter,COLUMN_SUBJECT) 
            if subject != '':
                self.book_data +=  _('Subject') + ': ' +  subject + '\n\n'
            self.book_data +=  _('Publisher') + ': ' + model.get_value(iter,COLUMN_PUBLISHER) + '\n\n'
            self.book_data +=  _('Language') +': '+ model.get_value(iter,COLUMN_LANGUAGE) + '\n\n'
            self.download_url =   'http://www.archive.org/download/' 
            identifier = model.get_value(iter,COLUMN_IDENTIFIER)
            self.download_url +=  identifier + '/' + identifier
            self.show_book_data()

    def show_book_data(self):
        if _NEW_TOOLBAR_SUPPORT:
            format = self.format_combo.props.value
        else:
            format = self._books_toolbar.format_combo.props.value
        if not hasattr(self, 'textview'): return
        textbuffer = self.textview.get_buffer()
        textbuffer.set_text(self.book_data + _('Download URL') + ': ' + self.download_url + format)
        if _NEW_TOOLBAR_SUPPORT:
            self.enable_button(True)
        else:
            self._books_toolbar.enable_button(True)

    def find_books(self, search_text):
        if _NEW_TOOLBAR_SUPPORT:
            self.enable_button(False)
        else:
            self._books_toolbar.enable_button(False)
        self.clear_downloaded_bytes()
        textbuffer = self.textview.get_buffer()
        textbuffer.set_text(_('Performing lookup, please wait') + '...')
        self.book_selected = False
        self.ls.clear()
        search_tuple = search_text.lower().split()
        if len(search_tuple) == 0:
            self._alert(_('Error'), _('You must enter at least one search word.'))
            if _NEW_TOOLBAR_SUPPORT:
                self.search_entry.grab_focus()
            else:
                self._books_toolbar.search_entry.grab_focus()
            return
        FL = urllib.quote('fl[]')
        SORT = urllib.quote('sort[]')
        self.search_url = 'http://www.archive.org/advancedsearch.php?q=' +  \
            urllib.quote('(title:(' + search_text.lower() + ') OR creator:(' + search_text.lower() +')) AND format:(DJVU)')
        self.search_url += '&' + FL + '=creator&' + FL + '=description&' + FL + '=format&' + FL + '=identifier&'  \
            + FL + '=language'
        self.search_url += '&' + FL +  '=publisher&' + FL + '=subject&' + FL + '=title&' + FL + '=volume'
        self.search_url += '&' + SORT + '=title&' + SORT + '&' + SORT + '=&rows=500&save=yes&fmt=csv&xmlsearch=Search'
        GObject.idle_add(self.download_csv,  self.search_url)
    
    def get_book(self):
        if _NEW_TOOLBAR_SUPPORT:
            self.enable_button(False)
            format = self.format_combo.props.value
        else:
            self._books_toolbar.enable_button(False)
            format = self._books_toolbar.format_combo.props.value
        self.progressbar.show()
        GObject.idle_add(self.download_book,  self.download_url + format)
        
    def download_csv(self,  url):
        print "get csv from",  url
        path = os.path.join(self.get_activity_root(), 'instance',
                            'tmp%i.csv' % time.time())
        print 'path=', path
        getter = ReadURLDownloader(url)
        getter.connect("finished", self._get_csv_result_cb)
        getter.connect("progress", self._get_csv_progress_cb)
        getter.connect("error", self._get_csv_error_cb)
        _logger.debug("Starting download to %s...", path)
        try:
            getter.start(path)
        except:
            self._alert(_('Error'), _('Connection timed out for CSV: ') + url)
           
        self._download_content_type = getter.get_content_type()

    def _get_csv_progress_cb(self, getter, bytes_downloaded):
        if self._download_content_length > 0:
            _logger.debug("Downloaded %u of %u bytes...",
                          bytes_downloaded, self._download_content_length)
        else:
            _logger.debug("Downloaded %u bytes...",
                          bytes_downloaded)

    def _get_csv_error_cb(self, getter, err):
        _logger.debug("Error getting CSV: %s", err)
        self._alert(_('Error'), _('Error getting CSV') )
        self._download_content_length = 0
        self._download_content_type = None

    def _get_csv_result_cb(self, getter, tempfile, suggested_name):
        print 'Content type:',  self._download_content_type
        if self._download_content_type.startswith('text/html'):
            # got an error page instead
            self._get_csv_error_cb(getter, 'HTTP Error')
            return
        self.process_downloaded_csv(tempfile,  suggested_name)

    def process_downloaded_csv(self,  tempfile,  suggested_name):
        textbuffer = self.textview.get_buffer()
        textbuffer.set_text(_('Finished'))
        reader = csv.reader(open(tempfile,  'rb'))
        reader.next() # skip the first header row.
        for row in reader:
            if len(row) < 9:
                self._alert("Server Error",  self.search_url)
                return
            iter = self.ls.append()
            self.ls.set(iter, 0, row[0],  1,  row[1],  2,  row[2],  3,  row[3],  4,  row[4],  5,  row[5],  \
                        6,  row[6],  7,  row[7],  8,  row[8])
        os.remove(tempfile)

    def download_book(self,  url):
        self.treeview.props.sensitive = False
        path = os.path.join(self.get_activity_root(), 'instance',
                            'tmp%i' % time.time())
        getter = ReadURLDownloader(url)
        getter.connect("finished", self._get_book_result_cb)
        getter.connect("progress", self._get_book_progress_cb)
        getter.connect("error", self._get_book_error_cb)
        _logger.debug("Starting download to %s...", path)
        try:
            getter.start(path)
        except:
            self._alert(_('Error'), _('Connection timed out for ') + self.selected_title)
           
        self._download_content_length = getter.get_content_length()
        self._download_content_type = getter.get_content_type()

    def _get_book_result_cb(self, getter, tempfile, suggested_name):
        self.treeview.props.sensitive = True
        if self._download_content_type.startswith('text/html'):
            # got an error page instead
            self._get_book_error_cb(getter, 'HTTP Error')
            return
        self.process_downloaded_book(tempfile,  suggested_name)

    def _get_book_progress_cb(self, getter, bytes_downloaded):
        if self._download_content_length > 0:
            _logger.debug("Downloaded %u of %u bytes...",
                          bytes_downloaded, self._download_content_length)
        else:
            _logger.debug("Downloaded %u bytes...",
                          bytes_downloaded)
        total = self._download_content_length
        self.set_downloaded_bytes(bytes_downloaded,  total)
        while Gtk.events_pending():
            Gtk.main_iteration()

    def set_downloaded_bytes(self, bytes,  total):
        fraction = float(bytes) / float(total)
        self.progressbar.set_fraction(fraction)
        
    def clear_downloaded_bytes(self):
        self.progressbar.set_fraction(0.0)

    def _get_book_error_cb(self, getter, err):
        self.treeview.props.sensitive = True
        if _NEW_TOOLBAR_SUPPORT:
            self.enable_button(True)
        else:
            self._books_toolbar.enable_button(True)
        self.progressbar.hide()
        _logger.debug("Error getting document: %s", err)
        self._alert(_('Error'), _('Could not download ') + self.selected_title + _(' path in catalog is incorrect.  ' \
                                                                                   + '  If you tried to download B/W PDF try another format.'))
        self._download_content_length = 0
        self._download_content_type = None

    def process_downloaded_book(self,  tempfile,  suggested_name):
        _logger.debug("Got document %s (%s)", tempfile, suggested_name)
        self.create_journal_entry(tempfile)

    def create_journal_entry(self,  tempfile):
        journal_entry = datastore.create()
        journal_title = self.selected_title
        if self.selected_volume != '':
            journal_title +=  ' ' + _('Volume') + ' ' +  self.selected_volume
        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'
        if _NEW_TOOLBAR_SUPPORT:
            format = self.format_combo.props.value
        else:
            format = self._books_toolbar.format_combo.props.value
        if format == '.epub':
            journal_entry.metadata['mime_type'] = 'application/epub+zip'
        if format == '.djvu':
            journal_entry.metadata['mime_type'] = 'image/vnd.djvu'
        if format == '.pdf' or format == '_bw.pdf':
            journal_entry.metadata['mime_type'] = 'application/pdf'
        journal_entry.metadata['buddies'] = ''
        journal_entry.metadata['preview'] = ''
        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)
        journal_entry.file_path = tempfile
        datastore.write(journal_entry)
        os.remove(tempfile)
        self.progressbar.hide()
        self._alert(_('Success'), self.selected_title + _(' added to Journal.'))

    def truncate(self,  str,  length):
        if len(str) > length:
            return str[0:length-1] + '...'
        else:
            return str
    
    def _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()
from gi.repository import Gtk

from sugar3.graphics.combobox import ComboBox


def _destroy_cb(widget, data=None):
    Gtk.main_quit()


def __combo_changed_cb(widget, data=None):
    print 'combo-changed'

w = Gtk.Window()
w.connect("destroy", _destroy_cb)

box = Gtk.VBox()
w.add(box)

combo = ComboBox()
combo.append_item(0, 'one')
combo.append_item(1, 'two', 'go-next')
combo.append_item(2, 'three')
combo.set_active(1)
combo.connect('changed', __combo_changed_cb)
box.pack_start(combo, False, False, 0)

w.show_all()

Gtk.main()
示例#29
0
class BeatToolbar(Gtk.Toolbar):

    def __init__(self, owner):
        GObject.GObject.__init__(self)

        self.owner = owner

        self.toolItem = {}

        self.blockBeat = False
        self.beatWheel = []

        btn = RadioToolButton(group=None)
        btn.set_icon_name('beats')
        btn.connect('toggled', self.setBeat, 0)
        btn.set_tooltip(_('Jump To Beat'))
        self.insert(btn, -1)
        self.beatWheel.append(btn)

        for i in range(1, 12):
            btn = RadioToolButton(group=self.beatWheel[0])
            btn.set_icon_name('beats')
            btn.connect('toggled', self.setBeat, i)
            btn.set_tooltip(_('Jump To Beat'))
            self.insert(btn, -1)
            self.beatWheel.append(btn)

        label = Gtk.Label(label=_("Synch to:"))
        self.syncLabel = Gtk.ToolItem()
        self.syncLabel.add(label)
        self.insert(self.syncLabel, 0)

        self.comboBox = ComboBox()
        self.comboBox.append_item(1, _("1 Beat"))
        self.comboBox.append_item(2, _("2 Beats"))
        self.comboBox.append_item(3, _("3 Beats"))
        self.comboBox.append_item(4, _("4 Beats"))
        self.comboBox.append_item(5, _("5 Beats"))
        self.comboBox.append_item(6, _("6 Beats"))
        self.comboBox.append_item(7, _("7 Beats"))
        self.comboBox.append_item(8, _("8 Beats"))
        self.comboBox.append_item(9, _("9 Beats"))
        self.comboBox.append_item(10, _("10 Beats"))
        self.comboBox.append_item(11, _("11 Beats"))
        self.comboBox.append_item(12, _("12 Beats"))
        self.comboBox.set_active(4 - 1)  # default 4 beats
        self.comboBox.connect("changed", self.changeSync)
        self.syncBox = ToolComboBox(self.comboBox)
        self.insert(self.syncBox, 1)

        self.show_all()

    #def _add_palette(self, widget, palette, position = Palette.DEFAULT):
    def _add_palette(self, widget, palette):
        widget._palette = palette
        widget._palette.props.invoker = WidgetInvoker(widget)
        #widget._palette.set_property("position", position)

    def _add_tooltip(self, widget, tooltip):
        #self._add_palette(widget, Palette(tooltip), Palette.DEFAULT)
        self._add_palette(widget, Palette(tooltip))

    def _insert_widget(self, widget, pos):
        self.toolItem[widget] = Gtk.ToolItem()
        self.toolItem[widget].add(widget)
        self.insert(self.toolItem[widget], pos)

    def _insert_separator(self, expand=False):
        separator = Gtk.SeparatorToolItem()
        separator.set_draw(False)
        separator.set_expand(expand)
        self.insert(separator, -1)

    def setBeat(self, widget, beat):
        if not self.blockBeat and widget.get_active():
            self.owner._setBeat(beat)

    def updateBeatWheel(self, beat):
        self.blockBeat = True
        self.beatWheel[beat].set_active(True)
        self.blockBeat = False

    def setSyncBeats(self, beats):
        self.comboBox.set_active(beats - 1)

    def changeSync(self, widget):
        beats = widget.get_active() + 1
        for i in range(beats):
            self.beatWheel[i].show()
        for i in range(beats, 12):
            self.beatWheel[i].hide()

        self.owner._setSyncBeats(beats)
示例#30
0
class SpeechToolbar(Gtk.Toolbar):

    def __init__(self, activity):
        Gtk.Toolbar.__init__(self)
        voicebar = Gtk.Toolbar()
        self._activity = activity
        if not speech.supported:
            return

        self.load_speech_parameters()

        self.sorted_voices = [i for i in speech.voices()]
        self.sorted_voices.sort(self.compare_voices)
        default = 0
        for voice in self.sorted_voices:
            if voice[0] == speech.voice[0]:
                break
            default = default + 1

        # Play button
        self.play_btn = ToggleToolButton('media-playback-start')
        self.play_btn.show()
        self.play_btn.connect('toggled', self.play_cb)
        self.insert(self.play_btn, -1)
        self.play_btn.set_tooltip(_('Play / Pause'))

        self.voice_combo = ComboBox()
        for voice in self.sorted_voices:
            self.voice_combo.append_item(voice, voice[0])
        self.voice_combo.set_active(default)

        self.voice_combo.connect('changed', self.voice_changed_cb)
        combotool = ToolComboBox(self.voice_combo)
        self.insert(combotool, -1)
        combotool.show()

        self.pitchadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0)
        pitchbar = Gtk.HScale(self.pitchadj)
        pitchbar.set_draw_value(False)
        pitchbar.set_update_policy(Gtk.UPDATE_DISCONTINUOUS)
        pitchbar.set_size_request(150, 15)
        self.pitchadj.set_value(speech.pitch)
        pitchtool = Gtk.ToolItem()
        pitchtool.add(pitchbar)
        pitchtool.show()
        self.insert(pitchtool, -1)
        pitchbar.show()

        self.rateadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0)
        ratebar = Gtk.HScale(self.rateadj)
        ratebar.set_draw_value(False)
        ratebar.set_update_policy(Gtk.UPDATE_DISCONTINUOUS)
        ratebar.set_size_request(150, 15)
        self.rateadj.set_value(speech.rate)
        ratetool = Gtk.ToolItem()
        ratetool.add(ratebar)
        ratetool.show()
        self.insert(ratetool, -1)
        ratebar.show()
        self.pitchadj.connect("value_changed", self.pitch_adjusted_cb)
        self.rateadj.connect("value_changed", self.rate_adjusted_cb)

    def compare_voices(self,  a,  b):
        if a[0].lower() == b[0].lower():
            return 0
        if a[0] .lower() < b[0].lower():
            return -1
        if a[0] .lower() > b[0].lower():
            return 1

    def voice_changed_cb(self, combo):
        speech.voice = combo.props.value
        speech.say(speech.voice[0])
        self.save_speech_parameters()

    def pitch_adjusted_cb(self, get):
        speech.pitch = int(get.value)
        speech.say(_("pitch adjusted"))
        self.save_speech_parameters()

    def rate_adjusted_cb(self, get):
        speech.rate = int(get.value)
        speech.say(_("rate adjusted"))
        self.save_speech_parameters()

    def load_speech_parameters(self):
        speech_parameters = {}
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        if os.path.exists(data_file_name):
            f = open(data_file_name, 'r')
            try:
                speech_parameters = simplejson.load(f)
                speech.pitch = speech_parameters['pitch']
                speech.rate = speech_parameters['rate']
                speech.voice = speech_parameters['voice']
            finally:
                f.close()

    def save_speech_parameters(self):
        speech_parameters = {}
        speech_parameters['pitch'] = speech.pitch
        speech_parameters['rate'] = speech.rate
        speech_parameters['voice'] = speech.voice
        data_path = os.path.join(self._activity.get_activity_root(), 'data')
        data_file_name = os.path.join(data_path, 'speech_params.json')
        f = open(data_file_name, 'w')
        try:
            simplejson.dump(speech_parameters, f)
        finally:
            f.close()

    def play_cb(self, widget):
        if widget.get_active():
            self.play_btn.set_named_icon('media-playback-pause')
            if speech.is_stopped():
                speech.play(self._activity._view.get_marked_words())
        else:
            self.play_btn.set_named_icon('media-playback-start')
            speech.stop()