Ejemplo n.º 1
0
        def build_toolbar(self):
            toolbar_box = ToolbarBox()

            view_toolbar = ViewToolbar()
            view_toolbar.connect('go-fullscreen',
                                 self.view_toolbar_go_fullscreen_cb)
            view_toolbar.show()
            view_toolbar_button = ToolbarButton(page=view_toolbar,
                                                icon_name='toolbar-view')
            toolbar_box.toolbar.insert(view_toolbar_button, -1)
            view_toolbar_button.show()

            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()
Ejemplo n.º 2
0
    def build_toolbar(self):
        toolbar_box = ToolbarBox()

        view_toolbar = ViewToolbar()
        view_toolbar.connect('go-fullscreen',
                self.view_toolbar_go_fullscreen_cb)
        view_toolbar.show()
        view_toolbar_button = ToolbarButton(
            page=view_toolbar,
            icon_name='toolbar-view')
        toolbar_box.toolbar.insert(view_toolbar_button, -1)
        view_toolbar_button.show()

        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()
Ejemplo n.º 3
0
    def add_page(self, ebook_reader_tab_instance):
        # Add the "content" for the section.
        tab_name = ebook_reader_tab_instance.get_tab_label()
        tab_widget = ebook_reader_tab_instance.get_widget_to_attach_notebook_tab()
        tab_toolbar = ebook_reader_tab_instance.get_tab_toolbar()

        if tab_toolbar is not None:
            tab_widget.pack_start(tab_toolbar, False, False, 0)
            tab_widget.reorder_child(tab_toolbar, 0)
            self._tab_toolbars_list.append(tab_toolbar)

        self.notebook.add_page(tab_name, tab_widget)

        # Add the "(secondary) toolbar" for the section.
        icon_name = \
                ebook_reader_tab_instance.get_tab_toolbar_icon_name()
        toolbar_button = ToolbarButton(page=None,
                                       icon_name=icon_name + '-select')
        self._toolbar_buttons_list.append(toolbar_button)

        toolbar_button.connect('clicked',
                               self.load_corresponding_page,
                               ebook_reader_tab_instance.get_pagenum())
        ebook_reader_tab_instance.show()

        toolbar_button.set_tooltip(tab_name)
        self._toolbar_box._toolbar.insert(toolbar_button, -1)
        toolbar_button.show()
        self._toolbar_box.show_all()
Ejemplo n.º 4
0
    def setup_toolbar(self):
        '''Setup the top toolbar. Groupthink needs some work here.'''

        toolbox = ToolbarBox()

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

        self.set_toolbar_box(toolbox)
        toolbox.show()
        toolbar = toolbox.toolbar

        self.edit_toolbar = EditToolbar()
        edit_toolbar_button = ToolbarButton(page=self.edit_toolbar,
                                            icon_name='toolbar-edit')
        self.edit_toolbar.show()
        toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        self.edit_toolbar.undo.connect('clicked', self.undobutton_cb)
        self.edit_toolbar.redo.connect('clicked', self.redobutton_cb)
        self.edit_toolbar.copy.connect('clicked', self.copybutton_cb)
        self.edit_toolbar.paste.connect('clicked', self.pastebutton_cb)

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

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()
Ejemplo n.º 5
0
    def add_page(self, ebook_reader_tab_instance):
        # Add the "content" for the section.
        tab_name = ebook_reader_tab_instance.get_tab_label()
        tab_widget = ebook_reader_tab_instance.get_widget_to_attach_notebook_tab(
        )
        tab_toolbar = ebook_reader_tab_instance.get_tab_toolbar()

        if tab_toolbar is not None:
            tab_widget.pack_start(tab_toolbar, False, False, 0)
            tab_widget.reorder_child(tab_toolbar, 0)
            self._tab_toolbars_list.append(tab_toolbar)

        self.notebook.add_page(tab_name, tab_widget)

        # Add the "(secondary) toolbar" for the section.
        icon_name = \
                ebook_reader_tab_instance.get_tab_toolbar_icon_name()
        toolbar_button = ToolbarButton(page=None,
                                       icon_name=icon_name + '-select')
        self._toolbar_buttons_list.append(toolbar_button)

        toolbar_button.connect('clicked', self.load_corresponding_page,
                               ebook_reader_tab_instance.get_pagenum())
        ebook_reader_tab_instance.show()

        toolbar_button.set_tooltip(tab_name)
        self._toolbar_box._toolbar.insert(toolbar_button, -1)
        toolbar_button.show()
        self._toolbar_box.show_all()
Ejemplo n.º 6
0
    def createPercussionToolbar(self, toolbar_box):

        self.beats_pm_button = IntensitySelector(list(range(2, 13)),
                                                 4,
                                                 imagefile('beat3.svg'))
        self.tempo_button = \
            IntensitySelector(list(range(PLAYER_TEMPO_LOWER,
                                    PLAYER_TEMPO_UPPER + 1, PLAYER_TEMPO_STEP)),
                              PLAYER_TEMPO, imagefile('tempo5.png'))

        self.complexity_button = IntensitySelector(xfrange(0, 1, 0.1),
                                                   self.regularity,
                                                   imagefile('complex6.svg'))

        self._play_percussion_btn = ToolButton(
            icon_name='media-playback-start')
        self._play_percussion_btn.set_property('can-default', True)
        self._play_percussion_btn.show()
        self._play_percussion_btn.connect('clicked', self.handlePlayButton)

        beats_toolbar = ToolbarBox()
        beats_toolbar.toolbar.insert(self._play_percussion_btn, -1)

        self._what_drum_widget = Gtk.ToolItem()
        self._what_drum_search_button = FilterToolItem(
            _('Select Drum'), 'view-type', _('Jazz / Rock Kit'),
            self._what_drum_widget)
        self._what_drum_search_button.set_widget_icon(
            file_name=imagefile("drum1kit.svg"))

        self._what_drum_widget.show()
        beats_toolbar.toolbar.insert(self._what_drum_search_button, -1)
        self._what_drum_search_button.show()
        self._what_drum_search_button.set_is_important(True)

        beats_toolbar.toolbar.insert(Gtk.SeparatorToolItem(), -1)
        beats_toolbar.toolbar.insert(self.complexity_button, -1)
        beats_toolbar.toolbar.insert(self.beats_pm_button, -1)
        beats_toolbar.toolbar.insert(self.tempo_button, -1)

        beats_toolbar_button = ToolbarButton(icon_name='toolbar-drums',
                                             page=beats_toolbar)
        beats_toolbar_button.show()

        toolbar_box.toolbar.insert(beats_toolbar_button, 1)

        self.beats_pm_button.set_tooltip(_("Beats per bar"))
        self.beats_pm_button.show()
        self.beats_pm_button.connect('changed', self.beatSliderChange, True)
        self.tempo_button.connect('changed', self.tempoSliderChange, True)
        self.complexity_button.connect('changed',
                                       self.handleComplexityChange,
                                       True)
        self.complexity_button.set_tooltip(_("Beat complexity"))
        self.tempo_button.show()
        self.tempo_button.set_tooltip(_('Tempo'))
        self.complexity_button.show()
Ejemplo n.º 7
0
    def createPercussionToolbar(self, toolbar_box):

        self.beats_pm_button = IntensitySelector(range(2, 13),
                                                 4,
                                                 imagefile('beat3.svg'))
        self.tempo_button = \
            IntensitySelector(range(PLAYER_TEMPO_LOWER,
                                    PLAYER_TEMPO_UPPER + 1, PLAYER_TEMPO_STEP),
                              PLAYER_TEMPO, imagefile('tempo5.png'))

        self.complexity_button = IntensitySelector(xfrange(0, 1, 0.1),
                                                   self.regularity,
                                                   imagefile('complex6.svg'))

        self._play_percussion_btn = ToolButton(
            icon_name='media-playback-start')
        self._play_percussion_btn.set_property('can-default', True)
        self._play_percussion_btn.show()
        self._play_percussion_btn.connect('clicked', self.handlePlayButton)

        beats_toolbar = ToolbarBox()
        beats_toolbar.toolbar.insert(self._play_percussion_btn, -1)

        self._what_drum_widget = Gtk.ToolItem()
        self._what_drum_search_button = FilterToolItem(
            _('Select Drum'), 'view-type', _('Jazz / Rock Kit'),
            self._what_drum_widget)
        self._what_drum_search_button.set_widget_icon(
            file_name=imagefile("drum1kit.svg"))

        self._what_drum_widget.show()
        beats_toolbar.toolbar.insert(self._what_drum_search_button, -1)
        self._what_drum_search_button.show()
        self._what_drum_search_button.set_is_important(True)

        beats_toolbar.toolbar.insert(Gtk.SeparatorToolItem(), -1)
        beats_toolbar.toolbar.insert(self.complexity_button, -1)
        beats_toolbar.toolbar.insert(self.beats_pm_button, -1)
        beats_toolbar.toolbar.insert(self.tempo_button, -1)

        beats_toolbar_button = ToolbarButton(icon_name='toolbar-drums',
                                             page=beats_toolbar)
        beats_toolbar_button.show()

        toolbar_box.toolbar.insert(beats_toolbar_button, 1)

        self.beats_pm_button.set_tooltip(_("Beats per bar"))
        self.beats_pm_button.show()
        self.beats_pm_button.connect('changed', self.beatSliderChange, True)
        self.tempo_button.connect('changed', self.tempoSliderChange, True)
        self.complexity_button.connect('changed',
                                       self.handleComplexityChange,
                                       True)
        self.complexity_button.set_tooltip(_("Beat complexity"))
        self.tempo_button.show()
        self.tempo_button.set_tooltip(_('Tempo'))
        self.complexity_button.show()
Ejemplo n.º 8
0
    def make_toolbar(self):
        # toolbar with the new toolbar redesign
        toolbar_box = ToolbarBox()

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

        toolbarview = Gtk.Toolbar()
        langtoolbar_button = ToolbarButton(
            label=_('View'),
            page=toolbarview,
            icon_name='settings')
        langtoolbar_button.show()
        toolbar_box.toolbar.insert(langtoolbar_button, -1)
        tool = ToolButton('en')
        tool.set_tooltip(_('English'))
        tool.connect('clicked', self.language_en)
        tool.show()
        toolbarview.insert(tool, -1)
        tool = ToolButton('es')
        tool.set_tooltip(_('Spanish'))
        tool.connect('clicked', self.language_es)
        tool.show()
        toolbarview.insert(tool, -1)
        tool = ToolButton('fr')
        tool.set_tooltip(_('French'))
        tool.connect('clicked', self.language_fr)
        tool.show()
        toolbarview.insert(tool, -1)
        tool = ToolButton('remote')
        tool.set_tooltip(_('Server settings'))
        tool.connect('clicked', self.settings)
        tool.show()
        toolbarview.insert(tool, -1)
        toolbarview.show()

        favorite_button = ToolButton(self.favorite_status)
        favorite_button.set_tooltip('Filter on favorite')
        favorite_button.connect('clicked', self.favorite)
        toolbar_box.toolbar.insert(favorite_button, -1)
        favorite_button.show()
        self.favorite_button = favorite_button

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

        stop_button = StopButton(self)
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()
Ejemplo n.º 9
0
    def make_toolbar(self):
        # toolbar with the new toolbar redesign
        toolbar_box = ToolbarBox()

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

        toolbarview = Gtk.Toolbar()
        langtoolbar_button = ToolbarButton(label=_('View'),
                                           page=toolbarview,
                                           icon_name='settings')
        langtoolbar_button.show()
        toolbar_box.toolbar.insert(langtoolbar_button, -1)
        tool = ToolButton('en')
        tool.set_tooltip(_('English'))
        tool.connect('clicked', self.language_en)
        tool.show()
        toolbarview.insert(tool, -1)
        tool = ToolButton('es')
        tool.set_tooltip(_('Spanish'))
        tool.connect('clicked', self.language_es)
        tool.show()
        toolbarview.insert(tool, -1)
        tool = ToolButton('fr')
        tool.set_tooltip(_('French'))
        tool.connect('clicked', self.language_fr)
        tool.show()
        toolbarview.insert(tool, -1)
        tool = ToolButton('remote')
        tool.set_tooltip(_('Server settings'))
        tool.connect('clicked', self.settings)
        tool.show()
        toolbarview.insert(tool, -1)
        toolbarview.show()

        favorite_button = ToolButton(self.favorite_status)
        favorite_button.set_tooltip('Filter on favorite')
        favorite_button.connect('clicked', self.favorite)
        toolbar_box.toolbar.insert(favorite_button, -1)
        favorite_button.show()
        self.favorite_button = favorite_button

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

        stop_button = StopButton(self)
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()
Ejemplo n.º 10
0
    def build_birth_toolbar(self, toolbox):

        birth_bar = Gtk.Toolbar()

        item1 = Gtk.ToolItem()
        self.label_birth = Gtk.Label()
        self.label_birth.set_text(_('Birth:') + ' ' + _('Day') + ' ')
        item1.add(self.label_birth)
        birth_bar.insert(item1, -1)

        item2 = Gtk.ToolItem()
        self.day_birth_spin = Gtk.SpinButton()
        self.day_birth_spin.set_range(1, 31)
        self.day_birth_spin.set_increments(1, 5)
        self.day_birth_spin.props.value = 10
        self.day_birth_spin.connect('notify::value', self.day_birth_change)
        item2.add(self.day_birth_spin)
        birth_bar.insert(item2, -1)

        item3 = Gtk.ToolItem()
        self.label_birth_month = Gtk.Label()
        self.label_birth_month.set_text(' ' + _('Month') + ' ')
        item3.add(self.label_birth_month)
        birth_bar.insert(item3, -1)

        item4 = Gtk.ToolItem()
        self.month_birth_spin = Gtk.SpinButton()
        self.month_birth_spin.set_range(1, 12)
        self.month_birth_spin.set_increments(1, 4)
        self.month_birth_spin.props.value = 2
        self.month_birth_spin.connect('notify::value', self.month_birth_change)
        item4.add(self.month_birth_spin)
        birth_bar.insert(item4, -1)

        item5 = Gtk.ToolItem()
        self.label_birth_year = Gtk.Label()
        self.label_birth_year.set_text(' ' + _('Year') + ' ')
        item5.add(self.label_birth_year)
        birth_bar.insert(item5, -1)

        item6 = Gtk.ToolItem()
        self.year_birth_spin = Gtk.SpinButton()
        self.year_birth_spin.set_range(1900, self._now.year)
        self.year_birth_spin.set_increments(1, 10)
        self.year_birth_spin.props.value = 1990
        self.year_birth_spin.connect('notify::value', self.year_birth_change)
        item6.add(self.year_birth_spin)
        birth_bar.insert(item6, -1)

        birth_bar.show_all()
        birth_button = ToolbarButton(label=_('Birth'),
                                     page=birth_bar,
                                     icon_name='write-date')
        toolbox.toolbar.insert(birth_button, -1)
        birth_button.show()
Ejemplo n.º 11
0
    def build_today_toolbar(self, toolbox):

        today_bar = Gtk.Toolbar()

        item1 = Gtk.ToolItem()
        self.label_today = Gtk.Label()
        self.label_today.set_text(_('Today:') + ' ' + _('Day') + ' ')
        item1.add(self.label_today)
        today_bar.insert(item1, -1)

        item2 = Gtk.ToolItem()
        self.day_today_spin = Gtk.SpinButton()
        self.day_today_spin.set_range(1, 31)
        self.day_today_spin.set_increments(1, 5)
        self.day_today_spin.props.value = self._today[0]
        self.day_today_spin.connect('notify::value', self.day_today_change)
        item2.add(self.day_today_spin)
        today_bar.insert(item2, -1)

        item3 = Gtk.ToolItem()
        self.label_today_month = Gtk.Label()
        self.label_today_month.set_text(' ' + _('Month') + ' ')
        item3.add(self.label_today_month)
        today_bar.insert(item3, -1)

        item4 = Gtk.ToolItem()
        self.month_today_spin = Gtk.SpinButton()
        self.month_today_spin.set_range(1, 12)
        self.month_today_spin.set_increments(1, 4)
        self.month_today_spin.props.value = self._today[1]
        self.month_today_spin.connect('notify::value', self.month_today_change)
        item4.add(self.month_today_spin)
        today_bar.insert(item4, -1)

        item5 = Gtk.ToolItem()
        self.label_today_year = Gtk.Label()
        self.label_today_year.set_text(' ' + _('Year') + ' ')
        item5.add(self.label_today_year)
        today_bar.insert(item5, -1)

        item6 = Gtk.ToolItem()
        self.year_today_spin = Gtk.SpinButton()
        self.year_today_spin.set_range(1900, self._now.year + 1)
        self.year_today_spin.set_increments(1, 10)
        self.year_today_spin.props.value = self._today[2]
        self.year_today_spin.connect('notify::value', self.year_today_change)
        item6.add(self.year_today_spin)
        today_bar.insert(item6, -1)

        today_bar.show_all()
        today_button = ToolbarButton(label=_('Today'),
                                     page=today_bar,
                                     icon_name='write-time')
        toolbox.toolbar.insert(today_button, -1)
        today_button.show()
Ejemplo n.º 12
0
    def build_today_toolbar(self, toolbox):

        today_bar = Gtk.Toolbar()

        item1 = Gtk.ToolItem()
        self.label_today = Gtk.Label()
        self.label_today.set_text(_('Today:') + ' ' + _('Day') + ' ')
        item1.add(self.label_today)
        today_bar.insert(item1, -1)

        item2 = Gtk.ToolItem()
        self.day_today_spin = Gtk.SpinButton()
        self.day_today_spin.set_range(1, 31)
        self.day_today_spin.set_increments(1, 5)
        self.day_today_spin.props.value = self._today[0]
        self.day_today_spin.connect('notify::value', self.day_today_change)
        item2.add(self.day_today_spin)
        today_bar.insert(item2, -1)

        item3 = Gtk.ToolItem()
        self.label_today_month = Gtk.Label()
        self.label_today_month.set_text(' ' + _('Month') + ' ')
        item3.add(self.label_today_month)
        today_bar.insert(item3, -1)

        item4 = Gtk.ToolItem()
        self.month_today_spin = Gtk.SpinButton()
        self.month_today_spin.set_range(1, 12)
        self.month_today_spin.set_increments(1, 4)
        self.month_today_spin.props.value = self._today[1]
        self.month_today_spin.connect('notify::value', self.month_today_change)
        item4.add(self.month_today_spin)
        today_bar.insert(item4, -1)

        item5 = Gtk.ToolItem()
        self.label_today_year = Gtk.Label()
        self.label_today_year.set_text(' ' + _('Year') + ' ')
        item5.add(self.label_today_year)
        today_bar.insert(item5, -1)

        item6 = Gtk.ToolItem()
        self.year_today_spin = Gtk.SpinButton()
        self.year_today_spin.set_range(1900, self._now.year + 1)
        self.year_today_spin.set_increments(1, 10)
        self.year_today_spin.props.value = self._today[2]
        self.year_today_spin.connect('notify::value', self.year_today_change)
        item6.add(self.year_today_spin)
        today_bar.insert(item6, -1)

        today_bar.show_all()
        today_button = ToolbarButton(label=_('Today'),
                                     page=today_bar,
                                     icon_name='write-time')
        toolbox.toolbar.insert(today_button, -1)
        today_button.show()
Ejemplo n.º 13
0
    def build_resolution_toolbar(self, toolbox):

        resolution_bar = Gtk.Toolbar()

        item1 = Gtk.ToolItem()
        label1 = Gtk.Label()
        label1.set_text(' ' + _('Show size') + ' ')
        item1.add(label1)
        resolution_bar.insert(item1, -1)

        item2 = Gtk.ToolItem()
        x_size_spin = Gtk.SpinButton()
        x_size_spin.set_range(160, 1200)
        x_size_spin.set_increments(1, 10)
        x_size_spin.props.value = int(self.show_size[0])
        x_size_spin.connect('notify::value', self.x_size_spin_change)
        item2.add(x_size_spin)
        resolution_bar.insert(item2, -1)

        item3 = Gtk.ToolItem()
        label3 = Gtk.Label()
        label3.set_text(' X ')
        item3.add(label3)
        resolution_bar.insert(item3, -1)

        item4 = Gtk.ToolItem()
        y_size_spin = Gtk.SpinButton()
        y_size_spin.set_range(120, 900)
        y_size_spin.set_increments(1, 10)
        y_size_spin.props.value = int(self.show_size[1])
        y_size_spin.connect('notify::value', self.y_size_spin_change)
        item4.add(y_size_spin)
        resolution_bar.insert(item4, -1)

        separator1 = Gtk.SeparatorToolItem()
        separator1.props.draw = True
        resolution_bar.insert(separator1, -1)

        item5 = Gtk.ToolItem()
        label5 = Gtk.Label()
        label5.set_text(' ' + _('Show grid'))
        item5.add(label5)
        resolution_bar.insert(item5, -1)

        grid = ToolButton('grid-icon')
        grid.connect('clicked', self.grid_click)
        resolution_bar.insert(grid, -1)

        resolution_bar.show_all()
        resolution_button = ToolbarButton(label=_('Resolution'),
                                          page=resolution_bar,
                                          icon_name='camera')
        toolbox.toolbar.insert(resolution_button, -1)
        resolution_button.show()
Ejemplo n.º 14
0
    def build_toolbar(self):
        toolbar_box = ToolbarBox()

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

        viewtoolbar = ViewToolbar(self)
        viewbutton = ToolbarButton(page=viewtoolbar, icon_name='toolbar-view')
        toolbar_box.toolbar.insert(viewbutton, -1)
        viewbutton.show()

        separator = Gtk.SeparatorToolItem()
        toolbar_box.toolbar.insert(separator, -1)
        separator.show()

        # lets reuse the code below
        navtoolbar = Toolbar(self.web_view, self)

        toolitem = Gtk.ToolItem()
        navtoolbar._home.reparent(toolitem)
        toolbar_box.toolbar.insert(toolitem, -1)
        navtoolbar._home.show()
        toolitem.show()

        toolitem = Gtk.ToolItem()
        navtoolbar._back.reparent(toolitem)
        toolbar_box.toolbar.insert(toolitem, -1)
        navtoolbar._back.show()
        toolitem.show()

        toolitem = Gtk.ToolItem()
        navtoolbar._forward.reparent(toolitem)
        toolbar_box.toolbar.insert(toolitem, -1)
        navtoolbar._forward.show()
        toolitem.show()

        # we do not have collaboration features
        # make the share option insensitive
        self.max_participants = 1

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

        stop_button = StopButton(self)
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()
Ejemplo n.º 15
0
    def make_toolbar(self):
        # toolbar with the new toolbar redesign
        toolbar_box = ToolbarBox()

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

        self.toolbarview = Gtk.Toolbar()
        langtoolbar_button = ToolbarButton(
            label=_('Filter'),
            page=self.toolbarview,
            icon_name='filter')
        langtoolbar_button.show()
        toolbar_box.toolbar.insert(langtoolbar_button, -1)
        self.toolbarview.show()

        box_search_item = Gtk.ToolItem()
        self.search_entry = Gtk.Entry()
        self.search_entry.connect('changed', self.text_filter)
        self.search_entry.set_size_request(300, -1)
        box_search_item.add(self.search_entry)
        self.search_entry.show()
        box_search_item.show()
        toolbar_box.toolbar.insert(box_search_item, -1)

        favorite_button = ToolButton(self.favorite_status)
        favorite_button.set_tooltip('Filter on favorite')
        favorite_button.connect('clicked', self.favorite)
        toolbar_box.toolbar.insert(favorite_button, -1)
        favorite_button.show()
        self.favorite_button = favorite_button

        library_button = ToolButton('library')
        library_button.set_tooltip('Show libraries')
        library_button.connect('clicked', self.library_clicked)
        toolbar_box.toolbar.insert(library_button, -1)
        library_button.show()

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

        stop_button = StopButton(self)
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()
Ejemplo n.º 16
0
    def __init__(self, handle):

        if not hasattr(self, 'confvars'):
            self.confvars = read_conf_from_info(get_bundle_path())

        logging.error("Starting server database: %s port: %s" %
                      (self.confvars['path'], self.confvars['port']))

        os.chdir(os.environ['SUGAR_BUNDLE_PATH'])

        self.confvars['ip'] = '0.0.0.0'

        server.run_server(self.confvars)

        handle.uri = 'http://%s:%s%s' % (
            self.confvars['ip'], self.confvars['port'],
            self.confvars['home_page'])

        webactivity.WebActivity.__init__(self, handle)

        if USE_GTK2:
            # Use xpcom to set a RAM cache limit.  (Trac #7081.)
            from xpcom import components
            from xpcom.components import interfaces
            cls = components.classes['@mozilla.org/preferences-service;1']
            pref_service = cls.getService(interfaces.nsIPrefService)
            branch = pref_service.getBranch("browser.cache.memory.")
            branch.setIntPref("capacity", "5000")

            # Use xpcom to turn off "offline mode" detection, which disables
            # access to localhost for no good reason.  (Trac #6250.)
            ios_class = components.classes["@mozilla.org/network/io-service;1"]
            io_service = ios_class.getService(interfaces.nsIIOService2)
            io_service.manageOfflineStatus = False

        self.searchtoolbar = SearchToolbar(self)
        search_toolbar_button = ToolbarButton()
        search_toolbar_button.set_page(self.searchtoolbar)
        search_toolbar_button.props.icon_name = 'search-wiki'
        search_toolbar_button.props.label = _('Search')
        self.get_toolbar_box().toolbar.insert(search_toolbar_button, 1)
        search_toolbar_button.show()
        # Hide add-tabs button
        if hasattr(self._primary_toolbar, '_add_tab'):
            self._primary_toolbar._add_tab.hide()

        self.searchtoolbar.show()
Ejemplo n.º 17
0
    def build_size_toolbar(self, toolbox):

        size_bar = Gtk.Toolbar()

        #Horizontal
        item1 = Gtk.ToolItem()
        label1 = Gtk.Label()
        label1.set_text(' %s ' % _('H'))
        item1.add(label1)
        size_bar.insert(item1, -1)

        item2 = Gtk.ToolItem()
        self.h_spin = Gtk.SpinButton()
        self.h_spin.set_range(2, 30)
        self.h_spin.set_increments(1, 2)
        self.h_spin.props.value = self.game_size[0]
        self.h_spin.connect('notify::value', self.h_spin_change)
        item2.add(self.h_spin)
        size_bar.insert(item2, -1)

        #Vertical
        item3 = Gtk.ToolItem()
        label2 = Gtk.Label()
        label2.set_text(' %s ' % _('V'))
        item3.add(label2)
        size_bar.insert(item3, -1)

        item4 = Gtk.ToolItem()
        self.v_spin = Gtk.SpinButton()
        self.v_spin.set_range(2, 20)
        self.v_spin.set_increments(1, 2)
        self.v_spin.props.value = self.game_size[1]
        self.v_spin.connect('notify::value', self.v_spin_change)
        item4.add(self.v_spin)
        size_bar.insert(item4, -1)

        size_bar.show_all()
        size_button = ToolbarButton(label=_('Board size'),
                page=size_bar,
                icon_name='preferences-system')
        toolbox.toolbar.insert(size_button, -1)
        size_button.show()
Ejemplo n.º 18
0
    def build_size_toolbar(self, toolbox):

        size_bar = Gtk.Toolbar()

        #Horizontal
        item1 = Gtk.ToolItem()
        label1 = Gtk.Label()
        label1.set_text(' %s ' % _('H'))
        item1.add(label1)
        size_bar.insert(item1, -1)

        item2 = Gtk.ToolItem()
        self.h_spin = Gtk.SpinButton()
        self.h_spin.set_range(2, 30)
        self.h_spin.set_increments(1, 2)
        self.h_spin.props.value = self.game_size[0]
        self.h_spin.connect('notify::value', self.h_spin_change)
        item2.add(self.h_spin)
        size_bar.insert(item2, -1)

        #Vertical
        item3 = Gtk.ToolItem()
        label2 = Gtk.Label()
        label2.set_text(' %s ' % _('V'))
        item3.add(label2)
        size_bar.insert(item3, -1)

        item4 = Gtk.ToolItem()
        self.v_spin = Gtk.SpinButton()
        self.v_spin.set_range(2, 20)
        self.v_spin.set_increments(1, 2)
        self.v_spin.props.value = self.game_size[1]
        self.v_spin.connect('notify::value', self.v_spin_change)
        item4.add(self.v_spin)
        size_bar.insert(item4, -1)

        size_bar.show_all()
        size_button = ToolbarButton(label=_('Board size'),
                page=size_bar,
                icon_name='preferences-system')
        toolbox.toolbar.insert(size_button, -1)
        size_button.show()
Ejemplo n.º 19
0
    def build_toolbar(self):
        toolbar_box = ToolbarBox()

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

        edit_toolbar = self._create_edit_toolbar()
        edit_toolbar_button = ToolbarButton(page=edit_toolbar,
                                            icon_name='toolbar-edit')
        edit_toolbar.show()
        toolbar_box.toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        view_toolbar = self._create_view_toolbar()
        view_toolbar_button = ToolbarButton(page=view_toolbar,
                                            icon_name='toolbar-view')
        view_toolbar.show()
        toolbar_box.toolbar.insert(view_toolbar_button, -1)
        view_toolbar_button.show()

        self._delete_tab_toolbar = None
        self._previous_tab_toolbar = None
        self._next_tab_toolbar = None

        helpbutton = self._create_help_button()
        toolbar_box.toolbar.insert(helpbutton, -1)
        helpbutton.show_all()

        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()
Ejemplo n.º 20
0
    def setup_toolbar(self):
        '''Setup the top toolbar. Groupthink needs some work here.'''

        toolbox = ToolbarBox()

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

        self.set_toolbar_box(toolbox)
        toolbox.show()
        toolbar = toolbox.toolbar

        self.edit_toolbar = EditToolbar()
        edit_toolbar_button = ToolbarButton(
            page=self.edit_toolbar,
            icon_name='toolbar-edit')
        self.edit_toolbar.show()
        toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        self.edit_toolbar.undo.connect('clicked', self.undobutton_cb)
        self.edit_toolbar.redo.connect('clicked', self.redobutton_cb)
        self.edit_toolbar.copy.connect('clicked', self.copybutton_cb)
        self.edit_toolbar.paste.connect('clicked', self.pastebutton_cb)

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

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()
Ejemplo n.º 21
0
class AbacusActivity(activity.Activity):

    def __init__(self, handle):
        ''' Initiate activity. '''
        super(AbacusActivity, self).__init__(handle)

        self._setting_up = True
        self.bead_colors = profile.get_color().to_string().split(',')

        # no sharing
        self.max_participants = 1

        self.sep = []
        self.abacus_toolbar = Gtk.Toolbar()
        custom_toolbar = Gtk.Toolbar()
        edit_toolbar = Gtk.Toolbar()

        toolbox = ToolbarBox()

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

        edit_toolbar_button = ToolbarButton(label=_('Edit'),
                                            page=edit_toolbar,
                                            icon_name='toolbar-edit')
        edit_toolbar_button.show()
        toolbox.toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        self.abacus_toolbar_button = ToolbarButton(
            page=self.abacus_toolbar,
            icon_name='abacus-list')
        self.abacus_toolbar.show()
        toolbox.toolbar.insert(self.abacus_toolbar_button, -1)
        self.abacus_toolbar_button.show()

        self.custom_toolbar_button = ToolbarButton(
            page=custom_toolbar,
            icon_name='view-source')
        custom_toolbar.show()
        toolbox.toolbar.insert(self.custom_toolbar_button, -1)
        self.custom_toolbar_button.show()

        separator_factory(toolbox.toolbar, False, True)

        button_factory('edit-delete', toolbox.toolbar,
                       self._reset_cb, tooltip=_('Reset'))

        separator_factory(toolbox.toolbar, False, True)

        self._label = label_factory(NAMES['suanpan'], toolbox.toolbar)

        separator_factory(toolbox.toolbar, True, False)

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

        self.set_toolbar_box(toolbox)
        toolbox.show()

        self.abacus_buttons = {}

        # Traditional
        self._add_abacus_button('decimal', None)
        self._add_abacus_button('soroban', self.abacus_buttons['decimal'])
        self._add_abacus_button('suanpan', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Bases other than 10
        self._add_abacus_button('nepohualtzintzin',
                                self.abacus_buttons['decimal'])
        self._add_abacus_button('hexadecimal', self.abacus_buttons['decimal'])
        self._add_abacus_button('binary', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Fractions
        self._add_abacus_button('schety', self.abacus_buttons['decimal'])
        # self._add_abacus_button('fraction', self.abacus_buttons['decimal'])
        self._add_abacus_button('caacupe', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Non-traditional
        self._add_abacus_button('cuisenaire', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Custom
        self._add_abacus_button('custom', self.abacus_buttons['decimal'])

        preferences_button = ToolButton('preferences-system')
        preferences_button.set_tooltip(_('Custom'))
        custom_toolbar.insert(preferences_button, -1)
        preferences_button.palette_invoker.props.toggle_palette = True
        preferences_button.palette_invoker.props.lock_palette = True
        preferences_button.props.hide_tooltip_on_click = False
        preferences_button.show()

        self._palette = preferences_button.get_palette()
        button_box = Gtk.VBox()
        # TRANS: Number of rods on the abacus
        self._rods_spin = add_spinner_and_label(
            15, 1, MAX_RODS, _('Rods:'), self._rods_spin_cb, button_box)
        # TRANS: Number of beads in the top section of the abacus
        self._top_spin = add_spinner_and_label(
            2, 0, MAX_TOP, _('Top:'), self._top_spin_cb, button_box)
        # TRANS: Number of beads in the bottom section of the abacus
        self._bottom_spin = add_spinner_and_label(
            5, 0, MAX_BOT, _('Bottom:'), self._bottom_spin_cb, button_box)
        # TRANS: Scale factor between bottom and top beads
        self._value_spin = add_spinner_and_label(
            5, 1, MAX_BOT + 1, _('Factor:'), self._value_spin_cb, button_box)
        # TRANS: Scale factor between rods
        self._base_spin = add_spinner_and_label(
            10, 1, (MAX_TOP + 1) * MAX_BOT, _('Base:'), self._base_spin_cb,
            button_box)
        hbox = Gtk.HBox()
        hbox.pack_start(button_box, True, True, style.DEFAULT_SPACING)
        hbox.show_all()
        self._palette.set_content(hbox)

        separator_factory(custom_toolbar, False, False)

        self.custom_maker = button_factory('new-abacus', custom_toolbar,
                                           self._custom_cb,
                                           tooltip=_('Custom'))

        button_factory('edit-copy', edit_toolbar, self._copy_cb,
                       tooltip=_('Copy'), accelerator='<Ctrl>c')
        button_factory('edit-paste', edit_toolbar, self._paste_cb,
                       tooltip=_('Paste'), accelerator='<Ctrl>v')

        # Create a canvas
        canvas = Gtk.DrawingArea()
        canvas.set_size_request(Gdk.Screen.width(),
                                Gdk.Screen.height())
        self.set_canvas(canvas)
        canvas.show()
        self.show_all()

        # Initialize the canvas
        self.abacus = Abacus(canvas, self)

        self._setting_up = False

        # Read the current mode from the Journal
        if 'rods' in self.metadata:
            self._rods_spin.set_value(int(self.metadata['rods']))
        if 'top' in self.metadata:
            self._top_spin.set_value(int(self.metadata['top']))
        if 'bottom' in self.metadata:
            self._bottom_spin.set_value(int(self.metadata['bottom']))
        if 'factor' in self.metadata:
            self._value_spin.set_value(int(self.metadata['factor']))
        if 'base' in self.metadata:
            self._base_spin.set_value(int(self.metadata['base']))
        if 'abacus' in self.metadata:
            if self.metadata['abacus'] in self.abacus_buttons:
                _logger.debug('restoring %s', self.metadata['abacus'])
                if self.metadata['abacus'] == 'custom':
                    self._custom_cb()
                self.abacus_buttons[self.metadata['abacus']].set_active(True)
            else:  # Default is Chinese
                self.abacus_buttons['suanpan'].set_active(True)

            if 'value' in self.metadata:
                _logger.debug('restoring value %s', self.metadata['value'])
                self.abacus.mode.set_value(self.metadata['value'])
                self.abacus.mode.label(self.abacus.generate_label())

        self.abacus.init()

        # Start with abacus toolbar expanded and suanpan as default
        self.abacus_toolbar_button.set_expanded(True)

    def _add_abacus_button(self, name, group):
        self.abacus_buttons[name] = radio_factory(
            name,
            self.abacus_toolbar,
            self._radio_cb,
            cb_arg=name,
            tooltip=NAMES[name],
            group=group)

    def _radio_cb(self, button, abacus):
        self._select_abacus(abacus)

    def _reset_cb(self, button=None):
        self.abacus.mode.reset_abacus()
        self.abacus.mode.label(self.abacus.generate_label())

    def _notify_new_abacus(self, prompt):
        ''' Loading a new abacus can be slooow, so alert the user. '''
        # a busy cursor is adequate
        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))

    def _select_abacus(self, abacus):
        ''' Notify the user of an expected delay and then... '''
        if not hasattr(self, 'abacus') or self._setting_up:
            _logger.debug('setting up')
            return
        # Not selected?
        if not self.abacus_buttons[abacus].get_active():
            _logger.debug('%s not active' % abacus)
            return

        self._notify_new_abacus(NAMES[abacus])
        # Give the cursor/alert time to load
        GObject.idle_add(self._switch_modes, abacus)

    def _switch_modes(self, abacus):
        ''' Display the selected abacus '''
        _logger.debug('switching modes to %s', abacus)
        if abacus == self.abacus.mode.name:
            _logger.debug('do not switch already in the same mode')
            self.get_window().set_cursor(None)
            return
        # Save current value
        value = int(float(self.abacus.mode.value()))
        if abacus == 'custom' and self.abacus.custom is None:
            self.custom_toolbar_button.set_expanded(True)
            # self.abacus.mode = self.abacus.custom
            self.get_window().set_cursor(None)
        else:
            _logger.debug('switch_mode: setting abacus to %s' % abacus)
            self.abacus.select_abacus(abacus)
            # Load saved value
            self.abacus.mode.set_value_from_number(value)
            self.abacus.mode.label(self.abacus.generate_label())
            self._label.set_text(NAMES[abacus])
            self.get_window().set_cursor(None)

    def _rods_spin_cb(self, button=None):
        return

    def _top_spin_cb(self, button=None):
        return

    def _bottom_spin_cb(self, button=None):
        return

    def _value_spin_cb(self, button=None):
        return

    def _base_spin_cb(self, button=None):
        return

    def _custom_cb(self, button=None):
        ''' Display the custom abacus; hide the others '''
        value = float(self.abacus.mode.value(count_beads=False))
        self.abacus.mode.hide()
        if self.abacus.custom is not None:
            self.abacus.custom.hide()
        self.abacus.custom = Custom(self.abacus, self.abacus.bead_colors)
        self.abacus.custom.set_custom_parameters(
            rods=self._rods_spin.get_value_as_int(),
            top=self._top_spin.get_value_as_int(),
            bot=self._bottom_spin.get_value_as_int(),
            factor=self._value_spin.get_value_as_int(),
            base=self._base_spin.get_value_as_int())
        self.abacus.custom.create()
        self.abacus.custom.draw_rods_and_beads()
        self.abacus.custom.show()
        self._label.set_text(NAMES['custom'])
        self.abacus.mode = self.abacus.custom
        self.abacus.mode_dict['custom'][0] = self.abacus.custom
        self.abacus_toolbar_button.set_expanded(True)
        self.abacus.mode.set_value_from_number(value)

    def _copy_cb(self, arg=None):
        ''' Copy a number to the clipboard from the active abacus. '''
        clipBoard = Gtk.Clipboard()
        text = self.abacus.generate_label(sum_only=True)
        if text is not None:
            clipBoard.set_text(text)
        return

    def _paste_cb(self, arg=None):
        ''' Paste a number from the clipboard to the active abacus. '''
        clipBoard = Gtk.Clipboard()
        text = clipBoard.wait_for_text()
        if text is not None:
            try:
                self.abacus.mode.set_value_from_number(float(text))
            except ValueError, e:
                _logger.debug(str(e))
                return
            self.abacus.mode.label(self.abacus.generate_label())
        return
Ejemplo n.º 22
0
    def build_options_toolbar(self, toolbox):

        options_bar = Gtk.Toolbar()

        item1 = Gtk.ToolItem()
        label1 = Gtk.Label()
        label1.set_text(' ' + _('Pixels') + ' ')
        item1.add(label1)
        options_bar.insert(item1, -1)

        item2 = Gtk.ToolItem()
        pixels = Gtk.SpinButton()
        pixels.set_range(0, 1000)
        pixels.set_increments(1, 10)
        pixels.props.value = self.pixels
        pixels.connect('notify::value', self.pixels_value)
        item2.add(pixels)
        options_bar.insert(item2, -1)

        separator1 = Gtk.SeparatorToolItem()
        separator1.props.draw = True
        options_bar.insert(separator1, -1)

        item3 = Gtk.ToolItem()
        self.label_threshold_red = Gtk.Label()
        self.label_threshold_red.set_text(' ' + _('Threshold:') + ' ' +
                                          _('Red') + ' ')
        item3.add(self.label_threshold_red)
        options_bar.insert(item3, -1)

        item4 = Gtk.ToolItem()
        red_spin = Gtk.SpinButton()
        red_spin.set_range(0, 255)
        red_spin.set_increments(1, 10)
        red_spin.props.value = self.threshold[0]
        red_spin.connect('notify::value', self.red_spin_threshold)
        item4.add(red_spin)
        options_bar.insert(item4, -1)

        item5 = Gtk.ToolItem()
        self.label_threshold_green = Gtk.Label()
        self.label_threshold_green.set_text(' ' + _('Green') + ' ')
        item5.add(self.label_threshold_green)
        options_bar.insert(item5, -1)

        item6 = Gtk.ToolItem()
        green_spin = Gtk.SpinButton()
        green_spin.set_range(0, 255)
        green_spin.set_increments(1, 10)
        green_spin.props.value = self.threshold[1]
        green_spin.connect('notify::value', self.green_spin_threshold)
        item6.add(green_spin)
        options_bar.insert(item6, -1)

        item7 = Gtk.ToolItem()
        self.label_threshold_blue = Gtk.Label()
        self.label_threshold_blue.set_text(' ' + _('Blue') + ' ')
        item7.add(self.label_threshold_blue)
        options_bar.insert(item7, -1)

        item8 = Gtk.ToolItem()
        blue_spin = Gtk.SpinButton()
        blue_spin.set_range(0, 255)
        blue_spin.set_increments(1, 10)
        blue_spin.props.value = self.threshold[2]
        blue_spin.connect('notify::value', self.blue_spin_threshold)
        item8.add(blue_spin)
        options_bar.insert(item8, -1)

        options_bar.show_all()
        options_button = ToolbarButton(label=_('Options'),
                                       page=options_bar,
                                       icon_name='view-source')
        toolbox.toolbar.insert(options_button, -1)
        options_button.show()
Ejemplo n.º 23
0
    def _setup_toolbars(self):
        """ Setup the toolbars.. """
        project_toolbar = Gtk.Toolbar()
        custom_slide_toolbar = Gtk.Toolbar()
        custom_stator_toolbar = Gtk.Toolbar()
        edit_toolbar = Gtk.Toolbar()

        # no sharing
        self.max_participants = 1

        toolbox = ToolbarBox()

        # Activity toolbar
        activity_button = ActivityToolbarButton(self)

        toolbox.toolbar.insert(activity_button, 0)
        activity_button.show()

        project_toolbar_button = ToolbarButton(page=project_toolbar,
                                               icon_name='sliderule')
        project_toolbar.show()
        toolbox.toolbar.insert(project_toolbar_button, -1)
        project_toolbar_button.show()

        custom_slide_toolbar_button = ToolbarButton(page=custom_slide_toolbar,
                                                    icon_name='custom-slide')
        custom_slide_toolbar.show()
        toolbox.toolbar.insert(custom_slide_toolbar_button, -1)
        custom_slide_toolbar_button.show()

        custom_stator_toolbar_button = ToolbarButton(
            page=custom_stator_toolbar, icon_name='custom-stator')
        custom_stator_toolbar.show()
        toolbox.toolbar.insert(custom_stator_toolbar_button, -1)
        custom_stator_toolbar_button.show()

        edit_toolbar_button = ToolbarButton(label=_('Edit'),
                                            page=edit_toolbar,
                                            icon_name='toolbar-edit')
        edit_toolbar_button.show()
        toolbox.toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        self.set_toolbar_box(toolbox)
        toolbox.show()
        toolbar = toolbox.toolbar

        # Add the buttons to the toolbars
        self._function_combo = combo_factory(FUNCTIONS,
                                             project_toolbar,
                                             self._function_combo_cb,
                                             default=FC_multiply,
                                             tooltip=_('select function'))
        self.top_button = button_factory('C',
                                         project_toolbar,
                                         self._dummy_cb,
                                         tooltip=_('active slide'))
        self._slide_combo = combo_factory(SLIDE_TABLE,
                                          project_toolbar,
                                          self._slide_combo_cb,
                                          default=C_slide,
                                          tooltip=_('select slide'))
        self.bottom_button = button_factory('D',
                                            project_toolbar,
                                            self._dummy_cb,
                                            tooltip=_('active stator'))
        self._stator_combo = combo_factory(STATOR_TABLE,
                                           project_toolbar,
                                           self._stator_combo_cb,
                                           default=D_slide,
                                           tooltip=_('select stator'))

        separator_factory(project_toolbar)

        self.realign_button = button_factory('realign',
                                             project_toolbar,
                                             self.realign_cb,
                                             tooltip=_('realign slides'))

        self._offset_function = []
        self._calculate_function = []
        self._label_function = []
        self._domain_min = []
        self._domain_max = []
        self._step_size = []
        self.custom = []

        ENTRY = ['C', 'D']
        ENTRY_TOOLBAR = [custom_slide_toolbar, custom_stator_toolbar]
        ENTRY_BUTTON = ['custom-slide', 'custom-stator']
        ENTRY_TOOLTIP = [_('create custom slide'), _('create custom stator')]
        ENTRY_CALLBACK = [self._custom_slide_cb, self._custom_stator_cb]
        for i in range(2):
            self._offset_function.append(
                entry_factory(DEFINITIONS[ENTRY[i]][0],
                              ENTRY_TOOLBAR[i],
                              tooltip=_('position function'),
                              max=10))
            self._calculate_function.append(
                entry_factory(DEFINITIONS[ENTRY[i]][1],
                              ENTRY_TOOLBAR[i],
                              tooltip=_('result function'),
                              max=10))
            self._label_function.append(
                entry_factory(DEFINITIONS[ENTRY[i]][2],
                              ENTRY_TOOLBAR[i],
                              tooltip=_('label function'),
                              max=10))
            self._domain_min.append(
                entry_factory(DEFINITIONS[ENTRY[i]][3],
                              ENTRY_TOOLBAR[i],
                              tooltip=_('domain minimum'),
                              max=4))
            self._domain_max.append(
                entry_factory(DEFINITIONS[ENTRY[i]][4],
                              ENTRY_TOOLBAR[i],
                              tooltip=_('domain maximum'),
                              max=4))
            self._step_size.append(
                entry_factory(DEFINITIONS[ENTRY[i]][5],
                              ENTRY_TOOLBAR[i],
                              tooltip=_('step size'),
                              max=4))
            self.custom.append(
                button_factory(ENTRY_BUTTON[i],
                               ENTRY_TOOLBAR[i],
                               ENTRY_CALLBACK[i],
                               tooltip=ENTRY_TOOLTIP[i]))

        copy = button_factory('edit-copy',
                              edit_toolbar,
                              self._copy_cb,
                              tooltip=_('Copy'),
                              accelerator='<Ctrl>c')
        paste = button_factory('edit-paste',
                               edit_toolbar,
                               self._paste_cb,
                               tooltip=_('Paste'),
                               accelerator='<Ctrl>v')

        separator_factory(toolbox.toolbar, True, False)

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()
        # workaround to #2050
        edit_toolbar_button.set_expanded(True)
        # start with project toolbar enabled
        project_toolbar_button.set_expanded(True)
Ejemplo n.º 24
0
    def __init__(self, handle):
        activity.Activity.__init__(self, handle)

        self.props.max_participants = 1

        self._web_view = WebKit.WebView()
        self._web_view.set_full_content_zoom(True)

        _scrolled_window = Gtk.ScrolledWindow()
        _scrolled_window.add(self._web_view)
        _scrolled_window.show()

        toolbar_box = ToolbarBox()

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

        viewtoolbar = ViewToolbar(self)
        viewbutton = ToolbarButton(page=viewtoolbar,
                                   icon_name='toolbar-view')
        toolbar_box.toolbar.insert(viewbutton, -1)
        viewbutton.show()

        separator = Gtk.SeparatorToolItem()
        toolbar_box.toolbar.insert(separator, -1)
        separator.show()

        # lets reuse the code below
        navtoolbar = Toolbar(self._web_view)

        toolitem = Gtk.ToolItem()
        navtoolbar._home.reparent(toolitem)
        toolbar_box.toolbar.insert(toolitem, -1)
        navtoolbar._home.show()
        toolitem.show()

        toolitem = Gtk.ToolItem()
        navtoolbar._back.reparent(toolitem)
        toolbar_box.toolbar.insert(toolitem, -1)
        navtoolbar._back.show()
        toolitem.show()

        toolitem = Gtk.ToolItem()
        navtoolbar._forward.reparent(toolitem)
        toolbar_box.toolbar.insert(toolitem, -1)
        navtoolbar._forward.show()
        toolitem.show()

        # we do not have collaboration features
        # make the share option insensitive
        self.max_participants = 1

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

        stop_button = StopButton(self)
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()

        self.set_canvas(_scrolled_window)
        self._web_view.show()
        self._web_view.connect("resource-request-starting",
                               self._resource_request_starting_cb)
        self._web_view.load_uri(get_index_uri())
Ejemplo n.º 25
0
    def __init__(self, handle):
        """Set up the Weather activity."""
        activity.Activity.__init__(self, handle)

        # we do not have collaboration features
        # make the share option insensitive
        self.max_participants = 1

        self.wind_scale = 'm/s'
        self.pressure_scale = 'hPa'
        self.humidity_scale = '%'
        self.cloud_scale = '%'
        self.temp_scale = 'K'
        self.input = ''
        self.selected_city = None

        self.temp_scales = {
            'Kelvin': 'K',
            'Celcius': u'\u00b0C'.encode('utf-8'),
            'Farenheit': u'\u00b0F'.encode('utf-8')
        }

        # view toolbar
        view_toolbar = Gtk.Toolbar()
        toolbar_box = ToolbarBox()

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

        temp_label = Gtk.Label(_('Temperature:'))
        temp_label.show()

        temp_label_item = Gtk.ToolItem()
        temp_label_item.add(temp_label)
        temp_label_item.show()

        temp_scale_store = Gtk.ListStore(str)
        for key in self.temp_scales.keys():
            temp_scale_store.append([key])

        self.temp_scale_combo = Gtk.ComboBox.new_with_model(temp_scale_store)
        renderer_text = Gtk.CellRendererText()
        self.temp_scale_combo.pack_start(renderer_text, True)
        self.temp_scale_combo.add_attribute(renderer_text, 'text', 0)
        self.temp_scale_combo.connect('changed', self.temp_scale_combo_toggled)
        self.temp_scale_combo.show()

        temp_scale_combo_item = ToolComboBox(self.temp_scale_combo)
        temp_scale_combo_item.show()

        view_toolbar.insert(temp_label_item, -1)
        view_toolbar.insert(temp_scale_combo_item, -1)
        view_toolbar.show()

        view_toolbar_button = ToolbarButton(icon_name='toolbar-view',
                                            page=view_toolbar)
        toolbar_box.toolbar.insert(view_toolbar_button, -1)
        view_toolbar_button.show()

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

        self.search_entry = iconentry.IconEntry()
        self.search_entry.connect('key-press-event', self.entry_key_press_cb)
        self.search_entry.connect('icon-press', self.refresh)
        self.search_entry.show()

        self.search_entry_item = Gtk.ToolItem()
        self.search_entry_item.set_size_request(SCREEN_WIDTH / 3, -1)
        self.search_entry_item.add(self.search_entry)
        toolbar_box.toolbar.insert(self.search_entry_item, -1)
        self.search_entry_item.show()

        self.back_button = ToolButton('go-previous-paired')
        self.back_button.connect('clicked', self.back_button_clicked)
        self.back_button.set_sensitive(False)
        self.back_button.set_tooltip(_('Back'))
        toolbar_box.toolbar.insert(self.back_button, -1)
        self.back_button.show()

        self.forecast_button = ToolButton('go-next-paired')
        self.forecast_button.connect('clicked', self.forecast_button_clicked)
        self.forecast_button.set_sensitive(False)
        self.forecast_button.set_tooltip(_('Forecast'))
        toolbar_box.toolbar.insert(self.forecast_button, -1)
        self.forecast_button.show()

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

        stop_button = StopButton(self)
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()

        # set up screen
        self.search_screen = searchscreen.SearchScreen(self)
        self.forecast_screen = forecastscreen.ForecastScreen(self)

        self.screen = self.search_screen

        howto_label = Gtk.Label()
        howto_label.set_justify(Gtk.Justification.CENTER)
        howto_label.set_markup(howto)
        howto_label.show()

        world_image = Gtk.Image()
        world_image.modify_bg(Gtk.StateType.NORMAL, Gdk.Color.parse(GREY)[1])
        pixbuf = GdkPixbuf.Pixbuf.new_from_file('world.svg')
        scaled_pixbuf = pixbuf.scale_simple(SCREEN_WIDTH, SCREEN_HEIGHT - 170,
                                            GdkPixbuf.InterpType.BILINEAR)
        world_image.set_from_pixbuf(scaled_pixbuf)
        world_image.show()

        box = Gtk.Box()
        box.set_orientation(Gtk.Orientation.VERTICAL)
        box.pack_start(howto_label, expand=True, fill=False, padding=0)
        box.pack_start(world_image, expand=True, fill=True, padding=0)
        box.show()

        self.set_canvas(box)

        self.temp_scale_combo.set_active(1)
        self.search_entry.grab_focus()
Ejemplo n.º 26
0
    def build_colors_toolbar(self, toolbox):

        barra_colors = Gtk.Toolbar()

        item1 = Gtk.ToolItem()
        label1 = Gtk.Label()
        label1.set_text(_('Color mode') + ' ')
        item1.add(label1)
        barra_colors.insert(item1, -1)

        item2 = Gtk.ToolItem()
        modes = ('RGB', 'YUV', 'HSV')
        combo = Combo(modes)
        item2.add(combo)
        combo.connect('changed', self.change_combo)
        barra_colors.insert(item2, -1)

        separator1 = Gtk.SeparatorToolItem()
        separator1.props.draw = True
        barra_colors.insert(separator1, -1)

        item_l = Gtk.ToolItem()
        label4 = Gtk.Label()
        label4.set_text(_('Brightness') + ' ')
        item_l.add(label4)
        barra_colors.insert(item_l, -1)

        item = Gtk.ToolItem()
        brightness_spin = Gtk.SpinButton()
        brightness_spin.set_range(-1, 255)
        brightness_spin.set_increments(1, 10)
        brightness_spin.props.value = int(self.brightness)
        brightness_spin.connect('notify::value', self.brightness_spin_change)
        item.add(brightness_spin)
        barra_colors.insert(item, -1)

        separator2 = Gtk.SeparatorToolItem()
        separator2.props.draw = True
        barra_colors.insert(separator2, -1)

        item3 = Gtk.ToolItem()
        label3 = Gtk.Label()
        label3.set_text(_('Threshold view'))
        item3.add(label3)
        barra_colors.insert(item3, -1)

        threshold_view = ToolButton('media-playback-stop')
        threshold_view.connect('clicked', self.threshold_view)
        threshold_view.set_tooltip(_('Yes'))
        barra_colors.insert(threshold_view, -1)

        separator3 = Gtk.SeparatorToolItem()
        separator3.props.draw = True
        barra_colors.insert(separator3, -1)

        item4 = Gtk.ToolItem()
        label4 = Gtk.Label()
        label4.set_text(_('Outline'))
        item4.add(label4)
        barra_colors.insert(item4, -1)

        outline_view = ToolButton('media-playback-stop')
        outline_view.connect('clicked', self.outline_view)
        outline_view.set_tooltip(_('Yes'))
        barra_colors.insert(outline_view, -1)

        separator4 = Gtk.SeparatorToolItem()
        separator4.props.draw = True
        barra_colors.insert(separator4, -1)

        item5 = Gtk.ToolItem()
        label5 = Gtk.Label()
        label5.set_text(_('Rects'))
        item5.add(label5)
        barra_colors.insert(item5, -1)

        rects_view = ToolButton('media-playback-stop')
        rects_view.connect('clicked', self.rects_view)
        rects_view.set_tooltip(_('Yes'))
        barra_colors.insert(rects_view, -1)

        barra_colors.show_all()
        colors_button = ToolbarButton(label=_('Colors'),
                                      page=barra_colors,
                                      icon_name='toolbar-colors')
        toolbox.toolbar.insert(colors_button, -1)
        colors_button.show()
Ejemplo n.º 27
0
    def _setup_toolbars(self):
        """ Setup the toolbars. """

        self.max_participants = 1  # No collaboration

        toolbox = ToolbarBox()

        # Activity toolbar
        activity_button = ActivityToolbarButton(self)

        toolbox.toolbar.insert(activity_button, 0)
        activity_button.show()

        self.set_toolbar_box(toolbox)
        toolbox.show()
        self.toolbar = toolbox.toolbar

        name_game_button = radio_factory('name-game',
                                         toolbox.toolbar,
                                         self._level_cb,
                                         cb_arg=0,
                                         tooltip=_(LABELS[0]),
                                         group=None)
        group_game_button = radio_factory('group-game',
                                          toolbox.toolbar,
                                          self._level_cb,
                                          cb_arg=1,
                                          tooltip=_(LABELS[1]),
                                          group=name_game_button)
        calorie_game_button = radio_factory('calorie-game',
                                            toolbox.toolbar,
                                            self._level_cb,
                                            cb_arg=2,
                                            tooltip=_(LABELS[2]),
                                            group=name_game_button)
        pyramid_game_button = radio_factory('pyramid-game',
                                            toolbox.toolbar,
                                            self._level_cb,
                                            cb_arg=3,
                                            tooltip=_(LABELS[3]),
                                            group=name_game_button)
        balance_game_button = radio_factory('balance-game',
                                            toolbox.toolbar,
                                            self._level_cb,
                                            cb_arg=4,
                                            tooltip=_(LABELS[4]),
                                            group=name_game_button)

        separator_factory(toolbox.toolbar, False, True)
        self._label = label_factory(toolbox.toolbar, LABELS[0], width=150)

        separator_factory(toolbox.toolbar, True, False)
        tools_toolbar = Gtk.Toolbar()
        tools_toolbar_button = ToolbarButton(page=tools_toolbar,
                                             icon_name='view-source')
        tools_toolbar.show()
        toolbox.toolbar.insert(tools_toolbar_button, -1)
        tools_toolbar_button.show()

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.name_entry = entry_factory(
            _('food name'),
            tools_toolbar,
            tooltip=_('Enter a name for the new food item.'),
            max=20)
        self.calories_entry = entry_factory(
            _('calories'),
            tools_toolbar,
            tooltip=_('Enter the calories in for the new food item.'),
            max=8)
        self.food_spinner = combo_factory(
            PYRAMID,
            tools_toolbar,
            self._food_pyramid_cb,
            default=PYRAMID[2],
            tooltip=_('Select level in the Food Pyramid.'))
        image_button = button_factory(
            'image-tools',
            tools_toolbar,
            self._load_image_cb,
            tooltip=_('Load a picture of the new food item.'))

        separator_factory(tools_toolbar, True, False)
        create_button = button_factory('new-food',
                                       tools_toolbar,
                                       self._create_custom_food_cb,
                                       tooltip=_('Add a new food item.'))
Ejemplo n.º 28
0
class OneSupportActivity(activity.Activity):
    ''' An activity for sending bug reports '''

    def __init__(self, handle):
        ''' Initialize the toolbar '''
        try:
            super(OneSupportActivity, self).__init__(handle)
        except dbus.exceptions.DBusException as e:
            _logger.error(str(e))

        self.connect('realize', self.__realize_cb)

        if hasattr(self, 'metadata') and 'font_size' in self.metadata:
            self.font_size = int(self.metadata['font_size'])
        else:
            self.font_size = 8
        self.zoom_level = self.font_size / float(len(FONT_SIZES))
        _logger.debug('zoom level is %f' % self.zoom_level)

        # _check_gconf_settings()  # For debugging purposes

        self._setup_toolbars()
        self.modify_bg(Gtk.StateType.NORMAL,
                       style.COLOR_WHITE.get_gdk_color())

        self.bundle_path = activity.get_bundle_path()

        self._copy_entry = None
        self._paste_entry = None
        self._webkit = None
        self._clipboard_text = ''
        self._fixed = None
        self._notify_transfer_status = False

        get_power_manager().inhibit_suspend()
        self._launch_task_master()

    def can_close(self):
        get_power_manager().restore_suspend()
        return True

    def busy_cursor(self):
        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))

    def reset_cursor(self):
        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR))

    def _launch_task_master(self):
        # Most things need only be done once
        if self._fixed is None:
            self._fixed = Gtk.Fixed()
            self._fixed.set_size_request(Gdk.Screen.width(),
                                         Gdk.Screen.height())

            # Offsets from the bottom of the screen
            dy1 = 3 * style.GRID_CELL_SIZE
            dy2 = 2 * style.GRID_CELL_SIZE

            self._progress_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._progress_area.set_size_request(Gdk.Screen.width(), -1)
            self._fixed.put(self._progress_area, 0, Gdk.Screen.height() - dy2)
            self._progress_area.show()

            self._button_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._button_area.set_size_request(Gdk.Screen.width(), -1)
            self._fixed.put(self._button_area, 0, Gdk.Screen.height() - dy1)
            self._button_area.show()

            self._scrolled_window = Gtk.ScrolledWindow()
            self._scrolled_window.set_size_request(
                Gdk.Screen.width(), Gdk.Screen.height() - dy1)
            self._set_scroll_policy()
            self._graphics_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._scrolled_window.add_with_viewport(self._graphics_area)
            self._graphics_area.show()
            self._fixed.put(self._scrolled_window, 0, 0)
            self._scrolled_window.show()

            self._task_master = TaskMaster(self)
            self._task_master.show()

            Gdk.Screen.get_default().connect('size-changed',
                                             self._configure_cb)
            self._toolbox.connect('hide', self._resize_hide_cb)
            self._toolbox.connect('show', self._resize_show_cb)

            self._task_master.set_events(Gdk.EventMask.KEY_PRESS_MASK)
            self._task_master.connect('key_press_event',
                                      self._task_master.keypress_cb)
            self._task_master.set_can_focus(True)
            self._task_master.grab_focus()

        self.set_canvas(self._fixed)
        self._fixed.show()

        self._task_master.task_master()

    def reset_scrolled_window_adjustments(self):
        adj = self._scrolled_window.get_hadjustment()
        if adj is not None:
            adj.set_value(0)
        adj = self._scrolled_window.get_vadjustment()
        if adj is not None:
            adj.set_value(0)

    def load_graphics_area(self, widget):
        self._graphics_area.add(widget)

    def load_button_area(self, widget):
        self._button_area.add(widget)

    def load_progress_area(self, widget):
        self._progress_area.add(widget)

    def _load_intro_graphics(self, file_name='generic-problem.html',
                             message=None):
        center_in_panel = Gtk.Alignment.new(0.5, 0, 0, 0)
        url = os.path.join(self.bundle_path, 'html-content', file_name)
        graphics = Graphics()
        if message is None:
            graphics.add_uri('file://' + url)
        else:
            graphics.add_uri('file://' + url + '?MSG=' +
                             utils.get_safe_text(message))
        graphics.set_zoom_level(0.667)
        center_in_panel.add(graphics)
        graphics.show()
        self.set_canvas(center_in_panel)
        center_in_panel.show()

    def _resize_hide_cb(self, widget):
        self._resize_canvas(widget, True)

    def _resize_show_cb(self, widget):
        self._resize_canvas(widget, False)

    def _configure_cb(self, event):
        self._fixed.set_size_request(Gdk.Screen.width(), Gdk.Screen.height())
        self._set_scroll_policy()
        self._resize_canvas(None)
        self._task_master.reload_graphics()

    def _resize_canvas(self, widget, fullscreen=False):
        # When a toolbar is expanded or collapsed, resize the canvas
        # to ensure that the progress bar is still visible.
        if hasattr(self, '_task_master'):
            if self.toolbar_expanded():
                dy1 = 4 * style.GRID_CELL_SIZE
                dy2 = 3 * style.GRID_CELL_SIZE
            else:
                dy1 = 3 * style.GRID_CELL_SIZE
                dy2 = 2 * style.GRID_CELL_SIZE

            if fullscreen:
                dy1 -= 2 * style.GRID_CELL_SIZE
                dy2 -= 2 * style.GRID_CELL_SIZE

            self._scrolled_window.set_size_request(
                Gdk.Screen.width(), Gdk.Screen.height() - dy1)
            self._fixed.move(self._progress_area, 0, Gdk.Screen.height() - dy2)
            self._fixed.move(self._button_area, 0, Gdk.Screen.height() - dy1)

    def get_activity_version(self):
        info_path = os.path.join(self.bundle_path, 'activity', 'activity.info')
        try:
            info_file = open(info_path, 'r')
        except Exception as e:
            _logger.error('Could not open %s: %s' % (info_path, e))
            return 'unknown'

        cp = ConfigParser()
        cp.readfp(info_file)

        section = 'Activity'

        if cp.has_option(section, 'activity_version'):
            activity_version = cp.get(section, 'activity_version')
        else:
            activity_version = 'unknown'
        return activity_version

    def get_uid(self):
        if len(self.volume_data) == 1:
            return self.volume_data[0]['uid']
        else:
            return 'unknown'

    def write_file(self, file_path):
        self.metadata['font_size'] = str(self.font_size)

    def _setup_toolbars(self):
        ''' Setup the toolbars. '''
        self.max_participants = 1  # No sharing

        self._toolbox = ToolbarBox()

        self.activity_button = ActivityToolbarButton(self)
        self.activity_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.activity_button, 0)
        self.activity_button.show()

        self.set_toolbar_box(self._toolbox)
        self._toolbox.show()
        self.toolbar = self._toolbox.toolbar

        view_toolbar = Gtk.Toolbar()
        self.view_toolbar_button = ToolbarButton(
            page=view_toolbar,
            label=_('View'),
            icon_name='toolbar-view')
        self.view_toolbar_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.view_toolbar_button, 1)
        view_toolbar.show()
        self.view_toolbar_button.show()

        button = ToolButton('view-fullscreen')
        button.set_tooltip(_('Fullscreen'))
        button.props.accelerator = '<Alt>Return'
        view_toolbar.insert(button, -1)
        button.show()
        button.connect('clicked', self._fullscreen_cb)

        self._zoom_in = ToolButton('zoom-in')
        self._zoom_in.set_tooltip(_('Increase size'))
        view_toolbar.insert(self._zoom_in, -1)
        self._zoom_in.show()
        self._zoom_in.connect('clicked', self._zoom_in_cb)

        self._zoom_out = ToolButton('zoom-out')
        self._zoom_out.set_tooltip(_('Decrease size'))
        view_toolbar.insert(self._zoom_out, -1)
        self._zoom_out.show()
        self._zoom_out.connect('clicked', self._zoom_out_cb)

        self._zoom_eq = ToolButton('zoom-original')
        self._zoom_eq.set_tooltip(_('Restore original size'))
        view_toolbar.insert(self._zoom_eq, -1)
        self._zoom_eq.show()
        self._zoom_eq.connect('clicked', self._zoom_eq_cb)

        self._set_zoom_buttons_sensitivity()

        edit_toolbar = Gtk.Toolbar()
        self.edit_toolbar_button = ToolbarButton(
            page=edit_toolbar,
            label=_('Edit'),
            icon_name='toolbar-edit')
        self.edit_toolbar_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.edit_toolbar_button, 1)
        edit_toolbar.show()
        self.edit_toolbar_button.show()

        self._copy_button = ToolButton('edit-copy')
        self._copy_button.set_tooltip(_('Copy'))
        self._copy_button.props.accelerator = '<Ctrl>C'
        edit_toolbar.insert(self._copy_button, -1)
        self._copy_button.show()
        self._copy_button.connect('clicked', self._copy_cb)
        self._copy_button.set_sensitive(False)

        self._paste_button = ToolButton('edit-paste')
        self._paste_button.set_tooltip(_('Paste'))
        self._paste_button.props.accelerator = '<Ctrl>V'
        edit_toolbar.insert(self._paste_button, -1)
        self._paste_button.show()
        self._paste_button.connect('clicked', self._paste_cb)
        self._paste_button.set_sensitive(False)

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

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        self._toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()

    def __realize_cb(self, window):
        self.window_xid = window.get_window().get_xid()

    def set_copy_widget(self, webkit=None, text_entry=None):
        # Each task is responsible for setting a widget for copy
        if webkit is not None:
            self._webkit = webkit
        else:
            self._webkit = None
        if text_entry is not None:
            self._copy_entry = text_entry
        else:
            self._copy_entry = None

        self._copy_button.set_sensitive(webkit is not None or
                                        text_entry is not None)

    def _copy_cb(self, button):
        if self._copy_entry is not None:
            self._copy_entry.copy_clipboard()
        elif self._webkit is not None:
            self._webkit.copy_clipboard()
        else:
            _logger.debug('No widget set for copy.')

    def set_paste_widget(self, text_entry=None):
        # Each task is responsible for setting a widget for paste
        if text_entry is not None:
            self._paste_entry = text_entry
        self._paste_button.set_sensitive(text_entry is not None)

    def _paste_cb(self, button):
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        self.clipboard_text = clipboard.wait_for_text()
        if self._paste_entry is not None:
            self._paste_entry.paste_clipboard()
        else:
            _logger.debug('No widget set for paste (%s).' %
                          self.clipboard_text)

    def _fullscreen_cb(self, button):
        ''' Hide the Sugar toolbars. '''
        self.fullscreen()

    def _set_zoom_buttons_sensitivity(self):
        if self.font_size < len(FONT_SIZES) - 1:
            self._zoom_in.set_sensitive(True)
        else:
            self._zoom_in.set_sensitive(False)
        if self.font_size > 0:
            self._zoom_out.set_sensitive(True)
        else:
            self._zoom_out.set_sensitive(False)

        if hasattr(self, '_scrolled_window'):
            self._set_scroll_policy()

    def _set_scroll_policy(self):
        if Gdk.Screen.width() < Gdk.Screen.height() or self.zoom_level > 0.667:
            self._scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                             Gtk.PolicyType.AUTOMATIC)
        else:
            self._scrolled_window.set_policy(Gtk.PolicyType.NEVER,
                                             Gtk.PolicyType.AUTOMATIC)

    def _zoom_eq_cb(self, button):
        self.font_size = 8
        self.zoom_level = 0.667
        self._set_zoom_buttons_sensitivity()
        self._task_master.reload_graphics()

    def _zoom_in_cb(self, button):
        if self.font_size < len(FONT_SIZES) - 1:
            self.font_size += 1
            self.zoom_level *= 1.1
        self._set_zoom_buttons_sensitivity()
        self._task_master.reload_graphics()

    def _zoom_out_cb(self, button):
        if self.font_size > 0:
            self.font_size -= 1
            self.zoom_level /= 1.1
        self._set_zoom_buttons_sensitivity()
        self._task_master.reload_graphics()

    def _remove_alert_cb(self, alert, response_id):
        self.remove_alert(alert)

    def _close_alert_cb(self, alert, response_id):
        self.remove_alert(alert)
        if response_id is Gtk.ResponseType.OK:
            self.close()

    def _reboot_alert_cb(self, alert, response_id):
        self.remove_alert(alert)
        if response_id is Gtk.ResponseType.OK:
            try:
                utils.reboot()
            except Exception as e:
                _logger.error('Cannot reboot: %s' % e)

    def _mount_added_cb(self, volume_monitor, device):
        _logger.error('mount added')
        if self.check_volume_data():
            _logger.debug('launching')
            self._launcher()

    def _mount_removed_cb(self, volume_monitor, device):
        _logger.error('mount removed')
        if self.check_volume_data():
            _logger.debug('launching')
            self._launcher()
Ejemplo n.º 29
0
    def build_colors_toolbar(self, toolbox):

        colors_bar = Gtk.Toolbar()

        ########################################################################
        # Point color
        item = Gtk.ToolItem()
        label = Gtk.Label()
        label.set_text('%s ' % _('Points'))
        item.add(label)
        colors_bar.insert(item, -1)

        # select color
        item = Gtk.ToolItem()
        fill_color = ColorToolButton()
        fill_color.connect('notify::color', self.color_point_change)
        item.add(fill_color)
        colors_bar.insert(item, -1)

        # Separator
        separator = Gtk.SeparatorToolItem()
        colors_bar.insert(separator, -1)
        separator.show()

        ########################################################################
        # Back color
        item = Gtk.ToolItem()
        label = Gtk.Label()
        label.set_text('%s ' % _('Background'))
        item.add(label)
        colors_bar.insert(item, -1)

        # select color
        item = Gtk.ToolItem()
        _fill_color = ColorToolButton()
        c = Gdk.RGBA()
        c.red = 21588
        c.green = 47546
        c.blue = 18504
        _fill_color.set_color(c)
        _fill_color.connect('notify::color', self.color_back_change)
        item.add(_fill_color)
        colors_bar.insert(item, -1)

        # Separator
        separator = Gtk.SeparatorToolItem()
        colors_bar.insert(separator, -1)
        separator.show()

        ########################################################################
        # Line color
        item = Gtk.ToolItem()
        label = Gtk.Label()
        label.set_text('%s ' % _('Lines'))
        item.add(label)
        colors_bar.insert(item, -1)

        # select color
        item = Gtk.ToolItem()
        _fill_color = ColorToolButton()
        _fill_color.connect('notify::color', self.color_line_change)
        item.add(_fill_color)
        colors_bar.insert(item, -1)

        # Separator
        separator = Gtk.SeparatorToolItem()
        colors_bar.insert(separator, -1)
        separator.show()

        ########################################################################
        # Owner color
        item = Gtk.ToolItem()
        label = Gtk.Label()
        label.set_text('%s ' % _('Owner'))
        item.add(label)
        colors_bar.insert(item, -1)

        # select color
        item = Gtk.ToolItem()
        _fill_color = ColorToolButton()
        c = Gdk.RGBA()
        c.red = 65535
        _fill_color.set_color(c)
        _fill_color.connect('notify::color', self.color_owner_change)
        item.add(_fill_color)
        colors_bar.insert(item, -1)

        colors_bar.show_all()
        colors_button = ToolbarButton(label=_('Colors'),
                page=colors_bar,
                icon_name='toolbar-colors')
        toolbox.toolbar.insert(colors_button, -1)
        colors_button.show()
class FractionBounceActivity(activity.Activity):

    def __init__(self, handle):
        ''' Initiate activity. '''
        super(FractionBounceActivity, self).__init__(handle)

        self.nick = profile.get_nick_name()
        if profile.get_color() is not None:
            self._colors = profile.get_color().to_string().split(',')
        else:
            self._colors = ['#A0FFA0', '#FF8080']

        self.max_participants = 4  # sharing
        self._playing = True

        self._setup_toolbars()
        self._setup_dispatch_table()
        canvas = self._setup_canvas()

        # Read any custom fractions from the project metadata
        if 'custom' in self.metadata:
            custom = self.metadata['custom']
        else:
            custom = None

        self._current_ball = 'soccerball'

        self._toolbar_was_expanded = False

        # Initialize the canvas
        self._bounce_window = Bounce(canvas, activity.get_bundle_path(), self)

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)

        # Restore any custom fractions
        if custom is not None:
            fractions = custom.split(',')
            for f in fractions:
                self._bounce_window.add_fraction(f)

        if self.shared_activity:
            # We're joining
            if not self.get_shared():
                xocolors = XoColor(profile.get_color().to_string())
                share_icon = Icon(icon_name='zoom-neighborhood',
                                  xo_color=xocolors)
                self._joined_alert = NotifyAlert()
                self._joined_alert.props.icon = share_icon
                self._joined_alert.props.title = _('Please wait')
                self._joined_alert.props.msg = _('Starting connection...')
                self._joined_alert.connect('response', self._alert_cancel_cb)
                self.add_alert(self._joined_alert)

                self._label.set_label(_('Wait for the sharer to start.'))

                # Wait for joined signal
                self.connect("joined", self._joined_cb)

        self._setup_sharing()

    def _configure_cb(self, event):
        if Gdk.Screen.width() < 1024:
            self._label.set_size_request(275, -1)
            self._label.set_label('')
            self._separator.set_expand(False)
        else:
            self._label.set_size_request(500, -1)
            self._separator.set_expand(True)

        self._bounce_window.configure_cb(event)
        if self._toolbar_expanded():
            self._bounce_window.bar.bump_bars('up')
            self._bounce_window.ball.ball.move_relative(
                (0, -style.GRID_CELL_SIZE))

    def _toolbar_expanded(self):
        if self._activity_button.is_expanded():
            return True
        elif self._custom_toolbar_button.is_expanded():
            return True
        return False

    def _update_graphics(self, widget):
        # We need to catch opening and closing of toolbars and ignore
        # switching between open toolbars.
        if self._toolbar_expanded():
            if not self._toolbar_was_expanded:
                self._bounce_window.bar.bump_bars('up')
                self._bounce_window.ball.ball.move_relative(
                    (0, -style.GRID_CELL_SIZE))
                self._toolbar_was_expanded = True
        else:
            if self._toolbar_was_expanded:
                self._bounce_window.bar.bump_bars('down')
                self._bounce_window.ball.ball.move_relative(
                    (0, style.GRID_CELL_SIZE))
                self._toolbar_was_expanded = False

    def _setup_toolbars(self):
        custom_toolbar = Gtk.Toolbar()
        toolbox = ToolbarBox()
        self._toolbar = toolbox.toolbar
        self._activity_button = ActivityToolbarButton(self)
        self._activity_button.connect('clicked', self._update_graphics)
        self._toolbar.insert(self._activity_button, 0)
        self._activity_button.show()

        self._custom_toolbar_button = ToolbarButton(
            label=_('Custom'),
            page=custom_toolbar,
            icon_name='view-source')
        self._custom_toolbar_button.connect('clicked', self._update_graphics)
        custom_toolbar.show()
        self._toolbar.insert(self._custom_toolbar_button, -1)
        self._custom_toolbar_button.show()

        self._load_standard_buttons(self._toolbar)

        self._separator = Gtk.SeparatorToolItem()
        self._separator.props.draw = False
        self._separator.set_expand(True)
        self._toolbar.insert(self._separator, -1)
        self._separator.show()

        stop_button = StopButton(self)
        stop_button.props.accelerator = _('<Ctrl>Q')
        self._toolbar.insert(stop_button, -1)
        stop_button.show()
        self.set_toolbar_box(toolbox)
        toolbox.show()

        self._load_custom_buttons(custom_toolbar)

    def _load_standard_buttons(self, toolbar):
        fraction_button = RadioToolButton(group=None)
        fraction_button.set_icon_name('fraction')
        fraction_button.set_tooltip(_('fractions'))
        fraction_button.connect('clicked', self._fraction_cb)
        toolbar.insert(fraction_button, -1)
        fraction_button.show()

        sector_button = RadioToolButton(group=fraction_button)
        sector_button.set_icon_name('sector')
        sector_button.set_tooltip(_('sectors'))
        sector_button.connect('clicked', self._sector_cb)
        toolbar.insert(sector_button, -1)
        sector_button.show()

        percent_button = RadioToolButton(group=fraction_button)
        percent_button.set_icon_name('percent')
        percent_button.set_tooltip(_('percents'))
        percent_button.connect('clicked', self._percent_cb)
        toolbar.insert(percent_button, -1)
        percent_button.show()

        self._player = Gtk.Image()
        self._player.set_from_pixbuf(svg_str_to_pixbuf(
            generate_xo_svg(scale=0.8, colors=['#282828', '#282828'])))
        self._player.set_tooltip_text(self.nick)
        toolitem = Gtk.ToolItem()
        toolitem.add(self._player)
        self._player.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        self._label = Gtk.Label(_("Click the ball to start."))
        self._label.set_line_wrap(True)
        if Gdk.Screen.width() < 1024:
            self._label.set_size_request(275, -1)
        else:
            self._label.set_size_request(500, -1)
        self.toolitem = Gtk.ToolItem()
        self.toolitem.add(self._label)
        self._label.show()
        toolbar.insert(self.toolitem, -1)
        self.toolitem.show()

    def _load_custom_buttons(self, toolbar):
        self.numerator = Gtk.Entry()
        self.numerator.set_text('')
        self.numerator.set_tooltip_text(_('numerator'))
        self.numerator.set_width_chars(3)
        toolitem = Gtk.ToolItem()
        toolitem.add(self.numerator)
        self.numerator.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        label = Gtk.Label('   /   ')
        toolitem = Gtk.ToolItem()
        toolitem.add(label)
        label.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        self.denominator = Gtk.Entry()
        self.denominator.set_text('')
        self.denominator.set_tooltip_text(_('denominator'))
        self.denominator.set_width_chars(3)
        toolitem = Gtk.ToolItem()
        toolitem.add(self.denominator)
        self.denominator.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        button = ToolButton('list-add')
        button.set_tooltip(_('add new fraction'))
        button.props.sensitive = True
        button.props.accelerator = 'Return'
        button.connect('clicked', self._add_fraction_cb)
        toolbar.insert(button, -1)
        button.show()

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

        button = ToolButton('soccerball')
        button.set_tooltip(_('choose a ball'))
        button.props.sensitive = True
        button.connect('clicked', self._button_palette_cb)
        toolbar.insert(button, -1)
        button.show()
        self._ball_palette = button.get_palette()
        button_grid = Gtk.Grid()
        row = 0
        for ball in BALLDICT.keys():
            if ball == 'custom':
                button = ToolButton('view-source')
            else:
                button = ToolButton(ball)
            button.connect('clicked', self._load_ball_cb, None, ball)
            eventbox = Gtk.EventBox()
            eventbox.connect('button_press_event', self._load_ball_cb,
                             ball)
            label = Gtk.Label(BALLDICT[ball][0])
            eventbox.add(label)
            label.show()
            button_grid.attach(button, 0, row, 1, 1)
            button.show()
            button_grid.attach(eventbox, 1, row, 1, 1)
            eventbox.show()
            row += 1
        self._ball_palette.set_content(button_grid)
        button_grid.show()

        button = ToolButton('insert-picture')
        button.set_tooltip(_('choose a background'))
        button.props.sensitive = True
        button.connect('clicked', self._button_palette_cb)
        toolbar.insert(button, -1)
        button.show()
        self._bg_palette = button.get_palette()
        button_grid = Gtk.Grid()
        row = 0
        for bg in BGDICT.keys():
            if bg == 'custom':
                button = ToolButton('view-source')
            else:
                button = ToolButton(bg)
            button.connect('clicked', self._load_bg_cb, None, bg)
            eventbox = Gtk.EventBox()
            eventbox.connect('button_press_event', self._load_bg_cb, bg)
            label = Gtk.Label(BGDICT[bg][0])
            eventbox.add(label)
            label.show()
            button_grid.attach(button, 0, row, 1, 1)
            button.show()
            button_grid.attach(eventbox, 1, row, 1, 1)
            eventbox.show()
            row += 1
        self._bg_palette.set_content(button_grid)
        button_grid.show()

    def _button_palette_cb(self, button):
        palette = button.get_palette()
        if palette:
            if not palette.is_up():
                palette.popup(immediate=True, state=palette.SECONDARY)
            else:
                palette.popdown(immediate=True)

    def can_close(self):
        # Let everyone know we are leaving...
        if hasattr(self, '_bounce_window') and \
           self._bounce_window.we_are_sharing():
            self._playing = False
            self.send_event('l', {"data": (json_dump([self.nick]))})
        return True

    def _setup_canvas(self):
        canvas = Gtk.DrawingArea()
        canvas.set_size_request(Gdk.Screen.width(),
                                Gdk.Screen.height())
        self.set_canvas(canvas)
        canvas.show()
        return canvas

    def _load_bg_cb(self, widget, event, bg):
        if bg == 'custom':
            chooser(self, 'Image', self._new_background_from_journal)
        else:
            self._bounce_window.set_background(BGDICT[bg][1])

    def _load_ball_cb(self, widget, event, ball):
        if ball == 'custom':
            chooser(self, 'Image', self._new_ball_from_journal)
        else:
            self._bounce_window.ball.new_ball(os.path.join(
                activity.get_bundle_path(), 'images', ball + '.svg'))
            self._bounce_window.set_background(BGDICT[BALLDICT[ball][1]][1])
        self._current_ball = ball

    def _reset_ball(self):
        ''' If we switch back from sector mode, we need to restore the ball '''
        if self._bounce_window.mode != 'sectors':
            return

        if self._current_ball == 'custom':  # TODO: Reload custom ball
            self._current_ball = 'soccerball'
        self._bounce_window.ball.new_ball(os.path.join(
            activity.get_bundle_path(), 'images', self._current_ball + '.svg'))

    def _new_ball_from_journal(self, dsobject):
        ''' Load an image from the Journal. '''
        self._bounce_window.ball.new_ball_from_image(
            dsobject.file_path,
            os.path.join(activity.get_activity_root(), 'tmp', 'custom.png'))

    def _new_background_from_journal(self, dsobject):
        ''' Load an image from the Journal. '''
        self._bounce_window.new_background_from_image(None, dsobject=dsobject)

    def _fraction_cb(self, arg=None):
        ''' Set fraction mode '''
        self._reset_ball()
        self._bounce_window.mode = 'fractions'

    def _percent_cb(self, arg=None):
        ''' Set percent mode '''
        self._reset_ball()
        self._bounce_window.mode = 'percents'

    def _sector_cb(self, arg=None):
        ''' Set sector mode '''
        self._bounce_window.mode = 'sectors'

    def _add_fraction_cb(self, arg=None):
        ''' Read entries and add a fraction to the list '''
        try:
            numerator = int(self.numerator.get_text().strip())
        except ValueError:
            self.numerator.set_text('NAN')
            numerator = 0
        try:
            denominator = int(self.denominator.get_text().strip())
        except ValueError:
            self.denominator.set_text('NAN')
            denominator = 1
        if denominator == 0:
            self.denominator.set_text('ZDE')
        if numerator > denominator:
            numerator = 0
        if numerator > 0 and denominator > 1:
            fraction = '%d/%d' % (numerator, denominator)
            self._bounce_window.add_fraction(fraction)
            if 'custom' in self.metadata:  # Save to Journal
                self.metadata['custom'] = '%s,%s' % (
                    self.metadata['custom'], fraction)
            else:
                self.metadata['custom'] = fraction

            self.alert(
                _('New fraction'),
                _('Your fraction, %s, has been added to the program' %
                  (fraction)))

    def reset_label(self, label):
        ''' update the challenge label '''
        self._label.set_label(label)

    def alert(self, title, text=None):
        alert = NotifyAlert(timeout=5)
        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)

    # Collaboration-related methods

    def _setup_sharing(self):
        ''' Setup the Presence Service. '''
        self.pservice = presenceservice.get_instance()
        self.initiating = None  # sharing (True) or joining (False)

        owner = self.pservice.get_owner()
        self.owner = owner
        self._bounce_window.buddies.append(self.nick)
        self._player_colors = [self._colors]
        self._player_pixbufs = [
            svg_str_to_pixbuf(generate_xo_svg(scale=0.8, colors=self._colors))
        ]
        self._share = ''
        self.connect('shared', self._shared_cb)
        self.connect('joined', self._joined_cb)

    def _shared_cb(self, activity):
        ''' Either set up initial share...'''
        self._new_tube_common(True)

    def _joined_cb(self, activity):
        ''' ...or join an exisiting share. '''
        self._new_tube_common(False)

    def _new_tube_common(self, sharer):
        ''' Joining and sharing are mostly the same... '''
        if self.shared_activity is None:
            _logger.debug('Error: Failed to share or join activity ... \
                shared_activity is null in _shared_cb()')
            return

        self.initiating = sharer
        self.waiting_for_fraction = not sharer

        self.conn = self.shared_activity.telepathy_conn
        self.tubes_chan = self.shared_activity.telepathy_tubes_chan
        self.text_chan = self.shared_activity.telepathy_text_chan

        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
            'NewTube', self._new_tube_cb)

        if sharer:
            _logger.debug('This is my activity: making a tube...')
            id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(
                SERVICE, {})

            self._label.set_label(_('Wait for others to join.'))
        else:
            _logger.debug('I am joining an activity: waiting for a tube...')
            self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
                reply_handler=self._list_tubes_reply_cb,
                error_handler=self._list_tubes_error_cb)

        # display your XO on the toolbar
        self._player.set_from_pixbuf(self._player_pixbufs[0])

    def _list_tubes_reply_cb(self, tubes):
        ''' Reply to a list request. '''
        for tube_info in tubes:
            self._new_tube_cb(*tube_info)

    def _list_tubes_error_cb(self, e):
        ''' Log errors. '''
        _logger.debug('Error: ListTubes() failed: %s', e)

    def _new_tube_cb(self, id, initiator, type, service, params, state):
        ''' Create a new tube. '''
        _logger.debug(
            'Newtube: ID=%d initator=%d type=%d service=%s params=%r state=%d',
            id, initiator, type, service, params, state)

        if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE):
            if state == telepathy.TUBE_STATE_LOCAL_PENDING:
                self.tubes_chan[ \
                              telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id)

            self.collab = CollabWrapper(self)
            self.collab.message.connect(self.event_received_cb)
            self.collab.setup()

            # Let the sharer know a new joiner has arrived.
            if self.waiting_for_fraction:
                self.send_event('j', {"data": (json_dump([self.nick,
                                                     self._colors]))})

    def _setup_dispatch_table(self):
        self._processing_methods = {
            'j': [self._new_joiner, 'new joiner'],
            'b': [self._buddy_list, 'buddy list'],
            'f': [self._receive_a_fraction, 'receive a fraction'],
            't': [self._take_a_turn, 'take a turn'],
            'l': [self._buddy_left, 'buddy left']
            }

    def event_received_cb(self, event_message):
        ''' Data from a tube has arrived. '''
        if len(event_message) == 0:
            return
        try:
            command, payload = event_message.split('|', 2)
        except ValueError:
            _logger.debug('Could not split event message %s', event_message)
            return
        _logger.debug('received an event %s|%s', command, payload)
        if self._playing:
            self._processing_methods[command][0](payload)

    def _buddy_left(self, payload):
        [nick] = json_load(payload)
        self._label.set_label(nick + ' ' + _('has left.'))
        if self.initiating:
            self._remove_player(nick)
            payload = json_dump([self._bounce_window.buddies,
                                 self._player_colors])
            self.send_event('b', {"data": payload})
            # Restart from sharer's turn
            self._bounce_window.its_my_turn()

    def _new_joiner(self, payload):
        ''' Someone has joined; sharer adds them to the buddy list. '''
        [nick, colors] = json_load(payload)
        self._label.set_label(nick + ' ' + _('has joined.'))
        if self.initiating:
            self._append_player(nick, colors)
            payload = json_dump([self._bounce_window.buddies,
                                 self._player_colors])
            self.send_event('b', {"data": payload})
            if self._bounce_window.count == 0:  # Haven't started yet...
                self._bounce_window.its_my_turn()

    def _remove_player(self, nick):
        if nick in self._bounce_window.buddies:
            i = self._bounce_window.buddies.index(nick)
            self._bounce_window.buddies.remove(nick)
            self._player_colors.remove(self._player_colors[i])
            self._player_pixbufs.remove(self._player_pixbufs[i])

    def _append_player(self, nick, colors):
        ''' Keep a list of players, their colors, and an XO pixbuf '''
        if not nick in self._bounce_window.buddies:
            _logger.debug('appending %s to the buddy list', nick)
            self._bounce_window.buddies.append(nick)
            self._player_colors.append([str(colors[0]), str(colors[1])])
            self._player_pixbufs.append(svg_str_to_pixbuf(
                generate_xo_svg(scale=0.8,
                                colors=self._player_colors[-1])))

    def _buddy_list(self, payload):
        '''Sharer sent the updated buddy list, so regenerate internal lists'''
        if not self.initiating:
            [buddies, colors] = json_load(payload)
            self._bounce_window.buddies = buddies[:]
            self._player_colors = colors[:]
            self._player_pixbufs = []
            for colors in self._player_colors:
                self._player_pixbufs.append(svg_str_to_pixbuf(
                    generate_xo_svg(scale=0.8,
                                    colors=[str(colors[0]), str(colors[1])])))

    def send_a_fraction(self, fraction):
        ''' Send a fraction to other players. '''
        payload = json_dump(fraction)
        self.send_event('f', {"data": payload})

    def _receive_a_fraction(self, payload):
        ''' Receive a fraction from another player. '''
        fraction = json_load(payload)
        self._bounce_window.play_a_fraction(fraction)

    def _take_a_turn(self, nick):
        ''' If it is your turn, take it, otherwise, wait. '''
        if nick == self.nick:
            self._bounce_window.its_my_turn()
        else:
            self._bounce_window.its_their_turn(nick)

    def send_event(self, command, data):
        ''' Send event through the tube. '''
        _logger.debug('sending event: %s', command)
        if hasattr(self, 'collab') and self.collab is not None:
            data["command"] = command
            self.collab.post(data)

    def set_player_on_toolbar(self, nick):
        ''' Display the XO icon of the player whose turn it is. '''
        self._player.set_from_pixbuf(self._player_pixbufs[
                self._bounce_window.buddies.index(nick)])
        self._player.set_tooltip_text(nick)
Ejemplo n.º 31
0
class RulerActivity(activity.Activity):

    def __init__(self, handle):
        super(RulerActivity, self).__init__(handle)

        self.button_dict = {}
        self.callback_dict = {}
        self._ready = False

        font = 'helvetica 12'
        font_bold = 'helvetica bold 12'

        #
        # We need a canvas
        #
        self._canvas = MyCanvas()
        self.set_canvas(self._canvas)
        self._canvas.show()

        screen = Gdk.Screen()
        width = screen.width()
        height = screen.height() - GRID_CELL_SIZE

        dpi, self.known_dpi = calc_dpi()
        self._canvas.set_dpi(dpi)

        # Create instances of our graphics
        self._r = show_rulers.ScreenOfRulers(font, font_bold, width, height)
        self._gcm = show_grids.ScreenGrid_cm(font, font_bold, width, height)
        self._gmm = show_grids.ScreenGrid_mm(font, font_bold, width, height)
        self._a90 = show_angles.Angles90(font, font_bold, width, height)
        self._a360 = show_angles.Angles360(font, font_bold, width, height)
        self._c = show_checkers.ScreenOfCircles(font, font_bold, width, height)

        # start with a ruler
        self._current = self._r
        self._canvas.add_a_ruler(self._current)

        # other settings
        self._grids_mode = "cm"
        self._angles_mode = "90"

        #
        # We need some toolbars
        #
        self.max_participants = 1

        toolbar_box = ToolbarBox()

        # Buttons added to the Activity toolbar
        activity_button = ActivityToolbarButton(self)
        toolbar_box.toolbar.insert(activity_button, 0)
        activity_button.show()

        self.rulers = radio_factory('ruler',
                                    toolbar_box.toolbar,
                                    self._rulers_cb,
                                    tooltip=_('Ruler'),
                                    group=None)

        self.grids = radio_factory('grid-a',
                                    toolbar_box.toolbar,
                                    self._grids_cb,
                                    tooltip=_('Grid'),
                                    group=self.rulers)

        self.angles = radio_factory('angles-90',
                                    toolbar_box.toolbar,
                                    self._angles_cb,
                                    tooltip=_('Angles'),
                                    group=self.rulers)

        self.checker = radio_factory('checker',
                                    toolbar_box.toolbar,
                                    self._checker_cb,
                                    tooltip=_('Checker'),
                                    group=self.rulers)

        self.wrapper = Gtk.ToolItem()
        self.wrapper2 = Gtk.ToolItem()
        self.wrapper3 = Gtk.ToolItem()
        self.custom_unit_entry = Gtk.Entry()
        self.txt1 = Gtk.Label()
        self.txt1.set_text(_('1 custom unit equals '))
        self.txt2 = Gtk.Label()
        # TRANS: mm is for Milli Meters
        self.txt2.set_text(_(' mm.'))
        self.wrapper.add(self.txt1)
        self.wrapper2.add(self.custom_unit_entry)
        self.wrapper3.add(self.txt2)
        self.wrapper.show_all()
        self.wrapper2.show_all()
        self.wrapper3.show_all()
        separator = Gtk.SeparatorToolItem()
        separator.props.draw = True
        separator.set_expand(False)
        separator.show()
        toolbar_box.toolbar.insert(separator, -1)
        custom_units_toolbox = ToolbarBox()
        custom_units_toolbox.toolbar.insert(self.wrapper, -1)
        custom_units_toolbox.toolbar.insert(self.wrapper2, -1)
        custom_units_toolbox.toolbar.insert(self.wrapper3, -1)
        custom_units_toolbox.show()
        self.custom_units_button = ToolbarButton(icon_name='view-source',
                                                 page=custom_units_toolbox)
        toolbar_box.toolbar.insert(self.custom_units_button, -1)
        self.custom_unit_entry.connect('changed', self.custom_unit_change_cb)
        self.custom_units_button.show()

        if not self.known_dpi:
            separator = Gtk.SeparatorToolItem()
            separator.show()
            toolbar_box.toolbar.insert(separator, -1)
            dpi = self._canvas.get_dpi()
            self._dpi_spin_adj = Gtk.Adjustment(dpi, 72, 200, 2, 32, 0)
            self._dpi_spin = Gtk.SpinButton(self._dpi_spin_adj, 0, 0)
            self._dpi_spin_id = self._dpi_spin.connect('value-changed',
                                                       self._dpi_spin_cb)
            self._dpi_spin.set_numeric(True)
            self._dpi_spin.show()
            self.tool_item_dpi = Gtk.ToolItem()
            self.tool_item_dpi.add(self._dpi_spin)
            toolbar_box.toolbar.insert(self.tool_item_dpi, -1)
            self.tool_item_dpi.show()

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

        # The ever-present Stop Button
        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>Q'
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()

        self.show_all()

        # Restore state if previously saved
        self._ready = True
        if 'ruler' in self.metadata and \
           self.metadata['ruler'] in self.button_dict:
            _logger.debug('restoring %s', self.metadata['ruler'])
            self.button_dict[self.metadata['ruler']].set_active(True)
            self.callback_dict[self.metadata['ruler']]
        else:
            self._rulers_cb()
            self.rulers.set_active(True)

        if 'custom_unit' in self.metadata:
            self.custom_unit_entry.set_text(self.metadata['custom_unit'])
        else: # set the default
            self.custom_unit_entry.set_text("25.4")

    #
    # Button callbacks
    #
    def _rulers_cb(self, button=None):
        if self._ready:
            self.custom_units_button.set_sensitive(True)
            self._current = self._r
            self._canvas.add_a_ruler(self._current)
            _logger.debug('selecting ruler')
            self.metadata['ruler'] = 'ruler'
        return False

    def custom_unit_change_cb(self, widget):
        try:
            new = float(widget.get_text())
        except ValueError:
            new = MMPERINCH
        new = abs(new)
        if new == 0:
            new = MMPERINCH
            if widget.get_text != '':
                widget.set_text(str(new))
        self._canvas.add_a_ruler(self._r)
        self._r.custom_unit_in_mm = new
        self._r.draw_custom_ruler(self._r.custom_unit_in_mm)
        self.metadata['custom_unit'] = str(new)

    def _grids_cb(self, button=None):
        if self._ready:
            self.custom_units_button.set_sensitive(False)
            self.custom_units_button.set_expanded(False)
            if self._grids_mode == "cm":
                self._current = self._gcm
                if hasattr(self, 'grids'):
                    self.grids.set_icon_name("grid-c")
                self._grids_mode = "mm"
            else:
                self._current = self._gmm
                if hasattr(self, 'grids'):
                    self.grids.set_icon_name("grid-a")
                self._grids_mode = "cm"
            self._canvas.add_a_ruler(self._current)
            _logger.debug('selecting grids')
            self.metadata['ruler'] = 'grids'
        return False

    def _angles_cb(self, button=None):
        if self._ready:
            self.custom_units_button.set_sensitive(False)
            self.custom_units_button.set_expanded(False)
            if self._angles_mode == "90":
                self._current = self._a90
                if hasattr(self, 'angles'):
                    self.angles.set_icon_name("angles-360")
                    self._angles_mode = "360"
            else:
                self._current = self._a360
                if hasattr(self, 'angles'):
                    self.angles.set_icon_name("angles-90")
                    self._angles_mode = "90"
            self._canvas.add_a_ruler(self._current)
            _logger.debug('selecting angles')
            self.metadata['ruler'] = 'angles'
        return False

    def _checker_cb(self, button=None):
        if self._ready:
            self.custom_units_button.set_sensitive(False)
            self.custom_units_button.set_expanded(False)
            self._current = self._c
            self._canvas.add_a_ruler(self._current)
            _logger.debug('selecting checker')
            self.metadata['ruler'] = 'checker'
        return False

    def _dpi_spin_cb(self, button):
        self._canvas.set_dpi(self._dpi_spin.get_value_as_int())
        self._canvas.add_a_ruler(self._current)
        return

    def write_file(self, file_path):
        ''' Write the dpi to the Journal '''
        dpi = self._canvas.get_dpi()
        _logger.debug("Write dpi: " + str(dpi))
        self.metadata['dpi'] = str(dpi)
Ejemplo n.º 32
0
    def _setup_toolbars(self):
        """ Setup the toolbars. """

        self.max_participants = 1  # No collaboration

        toolbox = ToolbarBox()

        # Activity toolbar
        activity_button = ActivityToolbarButton(self)

        toolbox.toolbar.insert(activity_button, 0)
        activity_button.show()

        self.set_toolbar_box(toolbox)
        toolbox.show()
        self.toolbar = toolbox.toolbar

        name_game_button = radio_factory(
            'name-game',
            toolbox.toolbar,
            self._level_cb,
            cb_arg=0,
            tooltip=_(LABELS[0]),
            group=None)
        group_game_button = radio_factory(
            'group-game',
            toolbox.toolbar,
            self._level_cb,
            cb_arg=1,
            tooltip=_(LABELS[1]),
            group=name_game_button)
        calorie_game_button = radio_factory(
            'calorie-game',
            toolbox.toolbar,
            self._level_cb,
            cb_arg=2,
            tooltip=_(LABELS[2]),
            group=name_game_button)
        pyramid_game_button = radio_factory(
            'pyramid-game',
            toolbox.toolbar,
            self._level_cb,
            cb_arg=3,
            tooltip=_(LABELS[3]),
            group=name_game_button)
        balance_game_button = radio_factory(
            'balance-game',
            toolbox.toolbar,
            self._level_cb,
            cb_arg=4,
            tooltip=_(LABELS[4]),
            group=name_game_button)

        separator_factory(toolbox.toolbar, False, True)
        self._label = label_factory(toolbox.toolbar, LABELS[0], width=150)

        separator_factory(toolbox.toolbar, True, False)
        tools_toolbar = Gtk.Toolbar()
        tools_toolbar_button = ToolbarButton(
            page=tools_toolbar,
            icon_name='view-source')
        tools_toolbar.show()
        toolbox.toolbar.insert(tools_toolbar_button, -1)
        tools_toolbar_button.show()

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.name_entry = entry_factory(
            _('food name'),
            tools_toolbar,
            tooltip=_('Enter a name for the new food item.'),
            max=20)
        self.calories_entry = entry_factory(
            _('calories'),
            tools_toolbar,
            tooltip=_('Enter the calories in for the new food item.'),
            max=8)
        self.food_spinner = combo_factory(
            PYRAMID,
            tools_toolbar,
            self._food_pyramid_cb,
            default=PYRAMID[2],
            tooltip=_('Select level in the Food Pyramid.'))
        image_button = button_factory(
            'image-tools',
            tools_toolbar,
            self._load_image_cb,
            tooltip=_('Load a picture of the new food item.'))

        separator_factory(tools_toolbar, True, False)
        create_button = button_factory(
            'new-food',
            tools_toolbar,
            self._create_custom_food_cb,
            tooltip=_('Add a new food item.'))
Ejemplo n.º 33
0
class NapierActivity(activity.Activity):
    ''' Napier's bones: Napier's bones were invented by John Napier
    (1550-1617), a Scottish mathematician and scientist. They help you
    to do multiplication. '''

    # TODO: Define your own bone.

    def __init__(self, handle):
        ''' Initialize the toolbars and the work surface '''
        super(NapierActivity, self).__init__(handle)

        if os.path.exists(os.path.join('~', 'Activities', 'Napier.activity')):
            self._bone_path = os.path.join('~', 'Activities',
                                           'Napier.activity', 'bones')
        else:
            self._bone_path = os.path.join('.', 'bones')

        self._bones = []
        self._bone_images = [
            None, None, None, None, None, None, None, None, None, None
        ]
        self._blank_image = None
        self._number = 0
        self._number_of_bones = 0

        self._setup_toolbars()
        self._setup_canvas()
        self._circles = [None, None]
        self._ovals = []
        self._setup_workspace()
        self._restore()

    def _setup_canvas(self):
        ''' Create a canvas '''
        self._canvas = Gtk.DrawingArea()
        self._canvas.set_size_request(Gdk.Screen.width(), Gdk.Screen.height())
        self.set_canvas(self._canvas)
        self._canvas.show()
        self.show_all()

        self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
        self._canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
        self._canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
        self._canvas.connect("draw", self.__draw_cb)
        self._canvas.connect("motion-notify-event", self._mouse_move_cb)
        # self._canvas.connect("key_press_event", self._key_press_cb)

    def _setup_workspace(self):
        ''' Add the bones. '''
        self._width = Gdk.Screen.width()
        self._height = int(Gdk.Screen.height() - (GRID_CELL_SIZE * 2))
        self._scale = self._height * 1.0 / BONE_HEIGHT
        self._bone_width = int(BONE_WIDTH * self._scale)
        self._bone_height = int(BONE_HEIGHT * self._scale)

        # Generate the sprites we'll need...
        self._sprites = Sprites(self._canvas)
        self._bone_index = Sprite(
            self._sprites, 0, 0,
            _load_svg_from_file(
                os.path.join(self._bone_path, 'bones-index.svg'),
                self._bone_width, self._bone_height))
        self._max_bones = int(self._width / self._bone_width) - 1
        self._blank_image = _load_svg_from_file(
            os.path.join(self._bone_path, 'blank-bone.svg'), self._bone_width,
            self._bone_height)
        for bones in range(self._max_bones):
            self._bones.append(
                Sprite(self._sprites, bones * self._bone_width, 0,
                       self._blank_image))
        circle_image = _load_svg_from_file(
            os.path.join(self._bone_path, 'circle.svg'), int(self._scale * 45),
            int(self._scale * 45))
        self._circles[0] = Sprite(self._sprites, 0, -100, circle_image)
        self._circles[1] = Sprite(self._sprites, 0, -100, circle_image)
        oval_image = _load_svg_from_file(
            os.path.join(self._bone_path, 'oval.svg'), int(self._scale * 129),
            int(self._scale * 92))
        for bones in range(self._max_bones - 1):
            self._ovals.append(Sprite(self._sprites, 0, -100, oval_image))

    def _setup_toolbars(self):
        ''' Setup the toolbars. '''

        self.max_participants = 1  # no sharing

        toolbox = ToolbarBox()

        # Activity toolbar
        activity_button = ActivityToolbarButton(self)

        toolbox.toolbar.insert(activity_button, 0)
        activity_button.show()

        self._bones_toolbar = Gtk.Toolbar()
        self._bones_toolbar_button = ToolbarButton(label=_('Select a bone'),
                                                   page=self._bones_toolbar,
                                                   icon_name='bones')

        self._bones_toolbar_button.show()
        toolbox.toolbar.insert(self._bones_toolbar_button, -1)
        self.set_toolbar_box(toolbox)
        toolbox.show()
        self.toolbar = toolbox.toolbar

        self._new_calc_button = button_factory('erase',
                                               self.toolbar,
                                               self._new_calc_cb,
                                               tooltip=_('Clear'))

        self._status = label_factory(self.toolbar, '')

        button_factory('number-0',
                       self._bones_toolbar,
                       self._number_cb,
                       cb_arg=0,
                       tooltip=_('zero'))

        button_factory('number-1',
                       self._bones_toolbar,
                       self._number_cb,
                       cb_arg=1,
                       tooltip=_('one'))

        button_factory('number-2',
                       self._bones_toolbar,
                       self._number_cb,
                       cb_arg=2,
                       tooltip=_('two'))

        button_factory('number-3',
                       self._bones_toolbar,
                       self._number_cb,
                       cb_arg=3,
                       tooltip=_('three'))

        button_factory('number-4',
                       self._bones_toolbar,
                       self._number_cb,
                       cb_arg=4,
                       tooltip=_('four'))

        button_factory('number-5',
                       self._bones_toolbar,
                       self._number_cb,
                       cb_arg=5,
                       tooltip=_('five'))

        button_factory('number-6',
                       self._bones_toolbar,
                       self._number_cb,
                       cb_arg=6,
                       tooltip=_('six'))

        button_factory('number-7',
                       self._bones_toolbar,
                       self._number_cb,
                       cb_arg=7,
                       tooltip=_('seven'))

        button_factory('number-8',
                       self._bones_toolbar,
                       self._number_cb,
                       cb_arg=8,
                       tooltip=_('eight'))

        button_factory('number-9',
                       self._bones_toolbar,
                       self._number_cb,
                       cb_arg=9,
                       tooltip=_('nine'))

        separator_factory(toolbox.toolbar, True, False)
        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()
        self._bones_toolbar_button.set_expanded(True)

    def _new_calc_cb(self, button=None):
        ''' Start a new calculation. '''
        for bone in range(self._max_bones):
            self._bones[bone].set_shape(self._blank_image)
            self._bones[bone].inval()
        self._number_of_bones = 0
        self._number = 0
        self._status.set_label('')
        return

    def _number_cb(self, button=None, value=0):
        ''' Try to add a digit. '''
        if self._number_of_bones == self._max_bones:
            return
        self._number_of_bones += 1
        if self._bone_images[value] is None:
            self._bone_images[value] = _svg_str_to_pixbuf(
                _bone_factory(value, scale=self._scale))
        self._bones[self._number_of_bones].set_shape(self._bone_images[value])
        self._bones[self._number_of_bones].inval()
        self._number = self._number * 10 + value

    def _mouse_move_cb(self, win, event):
        ''' Determine which row we are in and then calculate the product. '''
        win.grab_focus()
        x, y = list(map(int, event.get_coords()))
        factor = int(y / self._bone_width)  # The row determines a factor

        if self._number == 0 or factor == 0:
            self._status.set_label('')
            self._circles[0].move((0, -100))
            self._circles[1].move((0, -100))
            for number in range(self._max_bones - 1):
                self._ovals[number].move((0, -100))
        else:
            c0dx = int(4 * self._scale)
            c0dy = int(12 * self._scale)
            c1dx = int(44 * self._scale)
            c1dy = int(47 * self._scale)
            odx = int(42 * self._scale)
            ody = int(2 * self._scale)
            self._circles[0].move(
                (self._bone_width + c0dx, factor * self._bone_width + c0dy))
            self._circles[1].move(
                (self._number_of_bones * self._bone_width + c1dx,
                 factor * self._bone_width + c1dy))
            for number in range(self._number_of_bones - 1):
                self._ovals[number].move(
                    ((number + 1) * self._bone_width + odx,
                     factor * self._bone_width + ody))
            self._status.set_label('{}×{}={}'.format(
                factor + 1, self._number, (factor + 1) * self._number))
        return True

    def _key_press_cb(self, win, event):
        ''' TODO: Add bones by typing numbers '''
        return True

    def __draw_cb(self, canvas, cr):
        self._sprites.redraw_sprites(cr=cr)

    def do_expose_event(self, event):
        ''' Handle the expose-event by drawing '''
        # Restrict Cairo to the exposed area
        cr = self._canvas.window.cairo_create()
        cr.rectangle(event.area.x, event.area.y, event.area.width,
                     event.area.height)
        cr.clip()
        # Refresh sprite list
        self._sprites.redraw_sprites(cr=cr)

    def _destroy_cb(self, win, event):
        Gtk.main_quit()

    def _restore(self):
        ''' Try to restore previous state. '''
        if 'number' in self.metadata and self.metadata['number'] != '0':
            for digit in range(len(self.metadata['number'])):
                self._number_cb(button=None,
                                value=int(self.metadata['number'][digit]))

    def write_file(self, file_path):
        ''' Write the status to the Journal. '''
        if not hasattr(self, '_number'):
            return
        self.metadata['number'] = str(self._number)
Ejemplo n.º 34
0
class LogActivity(activity.Activity):
    def __init__(self, handle):
        activity.Activity.__init__(self, handle)

        self._autosearch_timer = None

        # Paths to watch: ~/.sugar/someuser/logs, /var/log
        paths = []
        paths.append(env.get_profile_path('logs'))
        paths.append('/var/log')

        # Additional misc files.
        ext_files = []
        ext_files.append(os.path.expanduser('~/.bash_history'))

        self.viewer = MultiLogView(paths, ext_files)
        self.set_canvas(self.viewer)
        self.viewer.grab_focus()

        self._build_toolbox()

        # Get Sugar's clipboard
        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        self.show()

        self._configure_cb(None)

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)

    def _build_toolbox(self):
        toolbar_box = ToolbarBox()

        self.max_participants = 1

        activity_button = ActivityToolbarButton(self)
        activity_toolbar = activity_button.page

        self._toolbar = toolbar_box.toolbar
        self._toolbar.insert(activity_button, -1)

        self._secondary_toolbar = Gtk.Toolbar()
        self._secondary_toolbar_button = ToolbarButton(
            page=self._secondary_toolbar,
            icon_name='system-search')
        self._secondary_toolbar.show()
        self._toolbar.insert(self._secondary_toolbar_button, -1)
        self._secondary_toolbar_button.hide()

        show_list = ToggleToolButton('view-list')
        show_list.set_active(True)
        show_list.set_tooltip(_('Show list of files'))
        show_list.connect('toggled', self._list_toggled_cb)
        self._toolbar.insert(show_list, -1)
        show_list.show()

        copy = CopyButton()
        copy.connect('clicked', self.__copy_clicked_cb)
        self._toolbar.insert(copy, -1)

        wrap_btn = ToggleToolButton("format-wrap")
        wrap_btn.set_tooltip(_('Word Wrap'))
        wrap_btn.connect('clicked', self._wrap_cb)
        self._toolbar.insert(wrap_btn, -1)

        self.search_entry = iconentry.IconEntry()
        self.search_entry.set_size_request(Gdk.Screen.width() / 3, -1)
        self.search_entry.set_icon_from_name(
            iconentry.ICON_ENTRY_PRIMARY, 'entry-search')
        self.search_entry.add_clear_button()
        self.search_entry.connect('activate', self._search_entry_activate_cb)
        self.search_entry.connect('changed', self._search_entry_changed_cb)
        self._search_item = Gtk.ToolItem()
        self._search_item.add(self.search_entry)
        self._toolbar.insert(self._search_item, -1)

        self._search_prev = ToolButton('go-previous-paired')
        self._search_prev.set_tooltip(_('Previous'))
        self._search_prev.connect('clicked', self._search_prev_cb)
        self._toolbar.insert(self._search_prev, -1)

        self._search_next = ToolButton('go-next-paired')
        self._search_next.set_tooltip(_('Next'))
        self._search_next.connect('clicked', self._search_next_cb)
        self._toolbar.insert(self._search_next, -1)

        self._update_search_buttons()

        self.collector_palette = CollectorPalette(self)
        collector_btn = ToolButton('log-export')
        collector_btn.set_palette(self.collector_palette)
        collector_btn.connect('clicked', self._logviewer_cb)
        collector_btn.show()
        activity_toolbar.insert(collector_btn, -1)

        self._delete_btn = ToolButton('list-remove')
        self._delete_btn = ToolButton('list-remove', accelerator='<ctrl>d')
        self._delete_btn.set_tooltip(_('Delete Log File'))
        self._delete_btn.connect('clicked', self._delete_log_cb)
        self._toolbar.insert(self._delete_btn, -1)

        self._separator = Gtk.SeparatorToolItem()
        self._separator.set_expand(True)
        self._separator.set_draw(False)
        self._toolbar.insert(self._separator, -1)

        self._stop_btn = StopButton(self)
        self._toolbar.insert(self._stop_btn, -1)

        toolbar_box.show_all()
        self.set_toolbar_box(toolbar_box)

    def _configure_cb(self, event=None):
        for control in [self._stop_btn, self._separator, self._delete_btn]:
            if control in self._toolbar:
                self._toolbar.remove(control)

        if Gdk.Screen.width() < Gdk.Screen.height():
            self._secondary_toolbar_button.show()
            self._secondary_toolbar_button.set_expanded(True)
            self._remove_controls(self._toolbar)
            self._add_controls(self._secondary_toolbar)
        else:
            self._secondary_toolbar_button.set_expanded(False)
            self._secondary_toolbar_button.hide()
            self._remove_controls(self._secondary_toolbar)
            self._add_controls(self._toolbar)

        for control in [self._delete_btn, self._separator, self._stop_btn]:
            if control not in self._toolbar:
                self._toolbar.insert(control, -1)

    def _remove_controls(self, toolbar):
        for control in [self._search_item, self._search_prev,
                        self._search_next]:
            if control in toolbar:
                toolbar.remove(control)

    def _add_controls(self, toolbar):
        for control in [self._search_item, self._search_prev,
                        self._search_next]:
            if control not in toolbar:
                toolbar.insert(control, -1)
                control.show()

    def _list_toggled_cb(self, widget):
        if widget.get_active():
            self.viewer.list_scroll.show()
        else:
            self.viewer.list_scroll.hide()

    def __copy_clicked_cb(self, button):
        if self.viewer.active_log:
            self.viewer.active_log.copy_clipboard(self.clipboard)

    def _wrap_cb(self, button):
        if button.get_active():
            self.viewer._textview.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
        else:
            self.viewer._textview.set_wrap_mode(Gtk.WrapMode.NONE)

    def _search_entry_activate_cb(self, entry):
        if self._autosearch_timer:
            GLib.source_remove(self._autosearch_timer)
            self._autosearch_timer = None
        self.viewer.set_search_text(entry.props.text)
        self._update_search_buttons()

    def _search_entry_changed_cb(self, entry):
        if self._autosearch_timer:
            GLib.source_remove(self._autosearch_timer)
        self._autosearch_timer = GLib.timeout_add(_AUTOSEARCH_TIMEOUT,
                                                  self.__autosearch_cb)

    def __autosearch_cb(self):
        self._autosearch_timer = None
        self.search_entry.activate()
        return False

    def _search_prev_cb(self, button):
        self.viewer.search_next('backward')
        self._update_search_buttons()

    def _search_next_cb(self, button):
        self.viewer.search_next('forward')
        self._update_search_buttons()

    def _update_search_buttons(self,):
        if len(self.viewer.search_text) == 0:
            self._search_prev.props.sensitive = False
            self._search_next.props.sensitive = False
        else:
            prev_result = self.viewer.get_next_result('backward')
            next_result = self.viewer.get_next_result('forward')
            self._search_prev.props.sensitive = prev_result is not None
            self._search_next.props.sensitive = next_result is not None

    def _delete_log_cb(self, widget):
        if self.viewer.active_log:
            logfile = self.viewer.active_log.logfile
            try:
                os.remove(logfile)
            except OSError as err:
                notify = NotifyAlert()
                notify.props.title = _('Error')
                notify.props.msg = _('%(error)s when deleting %(file)s') % \
                    {'error': err.strerror, 'file': logfile}
                notify.connect('response', _notify_response_cb, self)
                self.add_alert(notify)

    def _logviewer_cb(self, widget):
        self.collector_palette.popup(True)
Ejemplo n.º 35
0
    def __init__(self, handle):
        activity.Activity.__init__(self, handle)

        self.player = None

        self._alert = None
        self._playlist_jobject = None

        self.set_title(_('Jukebox Activity'))
        self.max_participants = 1

        self._toolbar_box = ToolbarBox()
        activity_button = ActivityToolbarButton(self)
        activity_toolbar = activity_button.page
        self._toolbar_box.toolbar.insert(activity_button, 0)
        self.title_entry = activity_toolbar.title

        self._view_toolbar = ViewToolbar()
        self._view_toolbar.connect('go-fullscreen',
                                   self.__go_fullscreen_cb)
        self._view_toolbar.connect('toggle-playlist',
                                   self.__toggle_playlist_cb)
        view_toolbar_button = ToolbarButton(
            page=self._view_toolbar,
            icon_name='toolbar-view')
        self._view_toolbar.show()
        self._toolbar_box.toolbar.insert(view_toolbar_button, -1)
        view_toolbar_button.show()

        self._control_toolbar = Gtk.Toolbar()
        self._control_toolbar_button = ToolbarButton(
            page=self._control_toolbar,
            icon_name='media-playback-start')
        self._control_toolbar.show()
        self._toolbar_box.toolbar.insert(self._control_toolbar_button, -1)
        self._control_toolbar_button.hide()

        self.set_toolbar_box(self._toolbar_box)
        self._toolbar_box.show_all()

        self.connect('key_press_event', self.__key_press_event_cb)
        self.connect('playlist-finished', self.__playlist_finished_cb)

        # We want to be notified when the activity gets the focus or
        # loses it. When it is not active, we don't need to keep
        # reproducing the video
        self.connect('notify::active', self.__notify_active_cb)

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

        self._playlist_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        self.playlist_widget = PlayList()
        self.playlist_widget.connect('play-index', self.__play_index_cb)
        self.playlist_widget.connect('missing-tracks',
                                     self.__missing_tracks_cb)
        self.playlist_widget.set_size_request(
            Gdk.Screen.width() * PLAYLIST_WIDTH_PROP, 0)
        self.playlist_widget.show()

        self._playlist_box.pack_start(self.playlist_widget, expand=True,
                                      fill=True, padding=0)

        self._playlist_toolbar = Gtk.Toolbar()

        move_up = ToolButton("go-up")
        move_up.set_tooltip(_("Move up"))
        move_up.connect("clicked", self._move_up_cb)
        self._playlist_toolbar.insert(move_up, 0)

        move_down = ToolButton("go-down")
        move_down.set_tooltip(_("Move down"))
        move_down.connect("clicked", self._move_down_cb)
        self._playlist_toolbar.insert(move_down, 1)

        self._playlist_box.pack_end(self._playlist_toolbar, False, False, 0)
        self._video_canvas.pack_start(self._playlist_box, False, False, 0)

        # Create the player just once
        logging.debug('Instantiating GstPlayer')
        self.player = GstPlayer()
        self.player.connect('eos', self.__player_eos_cb)
        self.player.connect('error', self.__player_error_cb)
        self.player.connect('play', self.__player_play_cb)

        self.control = Controls(self, self._toolbar_box.toolbar,
                                self._control_toolbar)

        self._separator = Gtk.SeparatorToolItem()
        self._separator.props.draw = False
        self._separator.set_expand(True)
        self._separator.show()
        self._toolbar_box.toolbar.insert(self._separator, -1)

        self._stop = StopButton(self)
        self._toolbar_box.toolbar.insert(self._stop, -1)

        self._empty_widget = Gtk.Label(label="")
        self._empty_widget.show()
        self.videowidget = VideoWidget()
        self.set_canvas(self._video_canvas)
        self._init_view_area()
        self.show_all()
        # need hide the playlist by default
        self._playlist_box.hide()

        self._configure_cb()

        self.player.init_view_area(self.videowidget)

        self._volume_monitor = Gio.VolumeMonitor.get()
        self._volume_monitor.connect('mount-added', self.__mount_added_cb)
        self._volume_monitor.connect('mount-removed', self.__mount_removed_cb)

        if handle.object_id is None:
            # The activity was launched from scratch. We need to show
            # the Empty Widget
            self.playlist_widget.hide()
            emptypanel.show(self, 'activity-jukebox',
                            _('No media'), _('Choose media files'),
                            self.control.show_picker_cb)

        self.control.check_if_next_prev()

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)
Ejemplo n.º 36
0
class JukeboxActivity(activity.Activity):

    __gsignals__ = {
        'playlist-finished': (GObject.SignalFlags.RUN_FIRST, None, []), }

    def __init__(self, handle):
        activity.Activity.__init__(self, handle)

        self.player = None

        self._alert = None
        self._playlist_jobject = None

        self.set_title(_('Jukebox Activity'))
        self.max_participants = 1

        self._toolbar_box = ToolbarBox()
        activity_button = ActivityToolbarButton(self)
        activity_toolbar = activity_button.page
        self._toolbar_box.toolbar.insert(activity_button, 0)
        self.title_entry = activity_toolbar.title

        self._view_toolbar = ViewToolbar()
        self._view_toolbar.connect('go-fullscreen',
                                   self.__go_fullscreen_cb)
        self._view_toolbar.connect('toggle-playlist',
                                   self.__toggle_playlist_cb)
        view_toolbar_button = ToolbarButton(
            page=self._view_toolbar,
            icon_name='toolbar-view')
        self._view_toolbar.show()
        self._toolbar_box.toolbar.insert(view_toolbar_button, -1)
        view_toolbar_button.show()

        self._control_toolbar = Gtk.Toolbar()
        self._control_toolbar_button = ToolbarButton(
            page=self._control_toolbar,
            icon_name='media-playback-start')
        self._control_toolbar.show()
        self._toolbar_box.toolbar.insert(self._control_toolbar_button, -1)
        self._control_toolbar_button.hide()

        self.set_toolbar_box(self._toolbar_box)
        self._toolbar_box.show_all()

        self.connect('key_press_event', self.__key_press_event_cb)
        self.connect('playlist-finished', self.__playlist_finished_cb)

        # We want to be notified when the activity gets the focus or
        # loses it. When it is not active, we don't need to keep
        # reproducing the video
        self.connect('notify::active', self.__notify_active_cb)

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

        self._playlist_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        self.playlist_widget = PlayList()
        self.playlist_widget.connect('play-index', self.__play_index_cb)
        self.playlist_widget.connect('missing-tracks',
                                     self.__missing_tracks_cb)
        self.playlist_widget.set_size_request(
            Gdk.Screen.width() * PLAYLIST_WIDTH_PROP, 0)
        self.playlist_widget.show()

        self._playlist_box.pack_start(self.playlist_widget, expand=True,
                                      fill=True, padding=0)

        self._playlist_toolbar = Gtk.Toolbar()

        move_up = ToolButton("go-up")
        move_up.set_tooltip(_("Move up"))
        move_up.connect("clicked", self._move_up_cb)
        self._playlist_toolbar.insert(move_up, 0)

        move_down = ToolButton("go-down")
        move_down.set_tooltip(_("Move down"))
        move_down.connect("clicked", self._move_down_cb)
        self._playlist_toolbar.insert(move_down, 1)

        self._playlist_box.pack_end(self._playlist_toolbar, False, False, 0)
        self._video_canvas.pack_start(self._playlist_box, False, False, 0)

        # Create the player just once
        logging.debug('Instantiating GstPlayer')
        self.player = GstPlayer()
        self.player.connect('eos', self.__player_eos_cb)
        self.player.connect('error', self.__player_error_cb)
        self.player.connect('play', self.__player_play_cb)

        self.control = Controls(self, self._toolbar_box.toolbar,
                                self._control_toolbar)

        self._separator = Gtk.SeparatorToolItem()
        self._separator.props.draw = False
        self._separator.set_expand(True)
        self._separator.show()
        self._toolbar_box.toolbar.insert(self._separator, -1)

        self._stop = StopButton(self)
        self._toolbar_box.toolbar.insert(self._stop, -1)

        self._empty_widget = Gtk.Label(label="")
        self._empty_widget.show()
        self.videowidget = VideoWidget()
        self.set_canvas(self._video_canvas)
        self._init_view_area()
        self.show_all()
        # need hide the playlist by default
        self._playlist_box.hide()

        self._configure_cb()

        self.player.init_view_area(self.videowidget)

        self._volume_monitor = Gio.VolumeMonitor.get()
        self._volume_monitor.connect('mount-added', self.__mount_added_cb)
        self._volume_monitor.connect('mount-removed', self.__mount_removed_cb)

        if handle.object_id is None:
            # The activity was launched from scratch. We need to show
            # the Empty Widget
            self.playlist_widget.hide()
            emptypanel.show(self, 'activity-jukebox',
                            _('No media'), _('Choose media files'),
                            self.control.show_picker_cb)

        self.control.check_if_next_prev()

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)

    def _move_up_cb(self, button):
        self.playlist_widget.move_up()

    def _move_down_cb(self, button):
        self.playlist_widget.move_down()

    def _configure_cb(self, event=None):
        self._toolbar_box.toolbar.remove(self._stop)
        self._toolbar_box.toolbar.remove(self._separator)
        if Gdk.Screen.width() < Gdk.Screen.height():
            self._control_toolbar_button.show()
            self._control_toolbar_button.set_expanded(True)
            self.control.update_layout(landscape=False)
            self._toolbar_box.toolbar.insert(self._separator, -1)
        else:
            self._control_toolbar_button.set_expanded(False)
            self._control_toolbar_button.hide()
            self.control.update_layout(landscape=True)
        self._toolbar_box.toolbar.insert(self._stop, -1)

    def __notify_active_cb(self, widget, event):
        """Sugar notify us that the activity is becoming active or inactive.
        When we are inactive, we stop the player if it is reproducing
        a video.
        """

        logging.debug('JukeboxActivity notify::active signal received')

        if self.player.player.props.current_uri is not None and \
                self.player.playing_video():
            if not self.player.is_playing() and self.props.active:
                self.player.play()
            if self.player.is_playing() and not self.props.active:
                self.player.pause()

    def _init_view_area(self):
        """
        Use a notebook with two pages, one empty an another
        with the videowidget
        """
        self.view_area = Gtk.Notebook()
        self.view_area.set_show_tabs(False)
        self.view_area.append_page(self._empty_widget, None)
        self.view_area.append_page(self.videowidget, None)
        self._video_canvas.pack_end(self.view_area, expand=True,
                                    fill=True, padding=0)

    def _switch_canvas(self, show_video):
        """Show or hide the video visualization in the canvas.

        When hidden, the canvas is filled with an empty widget to
        ensure redrawing.

        """
        if show_video:
            self.view_area.set_current_page(1)
        else:
            self.view_area.set_current_page(0)
        self._video_canvas.queue_draw()

    def __key_press_event_cb(self, widget, event):
        keyname = Gdk.keyval_name(event.keyval)
        logging.info("Keyname Press: %s, time: %s", keyname, event.time)
        if self.title_entry.has_focus():
            return False

        if keyname == "space":
            self.control._button_clicked_cb(None)
            return True

    def __playlist_finished_cb(self, widget):
        self._switch_canvas(show_video=False)
        self._view_toolbar._show_playlist.set_active(True)
        self.unfullscreen()

        # Select the first stream to be played when Play button will
        # be pressed
        self.playlist_widget.set_current_playing(0)
        self.control.check_if_next_prev()

    def songchange(self, direction):
        current_playing = self.playlist_widget.get_current_playing()
        if direction == 'prev' and current_playing > 0:
            self.play_index(current_playing - 1)
        elif direction == 'next' and \
                current_playing < len(self.playlist_widget._items) - 1:
            self.play_index(current_playing + 1)
        else:
            self.emit('playlist-finished')

    def play_index(self, index):
        # README: this line is no more necessary because of the
        # .playing_video() method
        # self._switch_canvas(show_video=True)
        self.playlist_widget.set_current_playing(index)

        path = self.playlist_widget._items[index]['path']
        if self.playlist_widget.check_available_media(path):
            if self.playlist_widget.is_from_journal(path):
                path = self.playlist_widget.get_path_from_journal(path)
            self.control.check_if_next_prev()

            self.player.set_uri(path)
            self.player.play()
        else:
            self.songchange('next')

    def __play_index_cb(self, widget, index, path):
        # README: this line is no more necessary because of the
        # .playing_video() method
        # self._switch_canvas(show_video=True)
        self.playlist_widget.set_current_playing(index)

        if self.playlist_widget.is_from_journal(path):
            path = self.playlist_widget.get_path_from_journal(path)

        self.control.check_if_next_prev()

        self.player.set_uri(path)
        self.player.play()

    def __player_eos_cb(self, widget):
        self.songchange('next')

    def _show_error_alert(self, title, msg=None):
        self._alert = ErrorAlert()
        self._alert.props.title = title
        if msg is not None:
            self._alert.props.msg = msg
        self.add_alert(self._alert)
        self._alert.connect('response', self._alert_cancel_cb)
        self._alert.show()

    def __mount_added_cb(self, volume_monitor, device):
        logging.debug('Mountpoint added. Checking...')
        self.remove_alert(self._alert)
        self.playlist_widget.update()

    def __mount_removed_cb(self, volume_monitor, device):
        logging.debug('Mountpoint removed. Checking...')
        self.remove_alert(self._alert)
        self.playlist_widget.update()

    def __missing_tracks_cb(self, widget, tracks):
        self._show_missing_tracks_alert(tracks)

    def _show_missing_tracks_alert(self, tracks):
        self._alert = Alert()
        title = _('%s tracks not found.') % len(tracks)
        self._alert.props.title = title
        icon = Icon(icon_name='dialog-cancel')
        self._alert.add_button(Gtk.ResponseType.CANCEL, _('Dismiss'), icon)
        icon.show()

        icon = Icon(icon_name='dialog-ok')
        self._alert.add_button(Gtk.ResponseType.APPLY, _('Details'), icon)
        icon.show()
        self.add_alert(self._alert)
        self._alert.connect(
            'response', self.__missing_tracks_alert_response_cb, tracks)

    def __missing_tracks_alert_response_cb(self, alert, response_id, tracks):
        if response_id == Gtk.ResponseType.APPLY:
            vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
            vbox.props.valign = Gtk.Align.CENTER
            label = Gtk.Label(label='')
            label.set_markup(_('<b>Missing tracks</b>'))
            vbox.pack_start(label, False, False, 15)

            for track in tracks:
                label = Gtk.Label(label=track['path'])
                vbox.add(label)

            _missing_tracks = Gtk.ScrolledWindow()
            _missing_tracks.add_with_viewport(vbox)
            _missing_tracks.show_all()

            self.view_area.append_page(_missing_tracks, None)

            self.view_area.set_current_page(2)

        self.remove_alert(alert)

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

    def __player_play_cb(self, widget):
        # Do not show the visualization widget if we are playing just
        # an audio stream

        def callback():
            if self.player.playing_video():
                self._switch_canvas(True)
            else:
                self._switch_canvas(False)
            return False

        # HACK: we need a timeout here because gstreamer returns
        # n-video = 0 if we call it immediately
        GObject.timeout_add(1000, callback)

    def __player_error_cb(self, widget, message, detail):
        self.player.stop()
        self.control.set_disabled()

        logging.error('ERROR MESSAGE: %s', message)
        logging.error('ERROR DETAIL: %s', detail)

        file_path = self.playlist_widget._items[
            self.playlist_widget.get_current_playing()]['path']
        mimetype = mime.get_for_file(file_path)

        title = _('Error')
        msg = _('This "%s" file can\'t be played') % mimetype
        self._switch_canvas(False)
        self._show_error_alert(title, msg)

    def can_close(self):
        # We need to put the Gst.State in NULL so gstreamer can
        # cleanup the pipeline
        self.player.stop()
        return True

    def read_file(self, file_path):
        """Load a file from the datastore on activity start."""
        logging.debug('JukeBoxAtivity.read_file: %s', file_path)

        title = self.metadata['title']
        self.playlist_widget.load_file(file_path, title)
        self._view_toolbar._show_playlist.set_active(True)

    def write_file(self, file_path):

        def write_playlist_to_file(file_path):
            """Open the file at file_path and write the playlist.

            It is saved in audio/x-mpegurl format.

            """

            list_file = open(file_path, 'w')
            for uri in self.playlist_widget._items:
                list_file.write('#EXTINF:%s\n' % uri['title'])
                list_file.write('%s\n' % uri['path'])
            list_file.close()

        if not self.metadata['mime_type']:
            self.metadata['mime_type'] = 'audio/x-mpegurl'

        if self.metadata['mime_type'] == 'audio/x-mpegurl':
            write_playlist_to_file(file_path)

        else:
            if self._playlist_jobject is None:
                self._playlist_jobject = \
                    self.playlist_widget.create_playlist_jobject()

            # Add the playlist to the playlist jobject description.
            # This is only done if the activity was not started from a
            # playlist or from scratch:
            description = ''
            for uri in self.playlist_widget._items:
                description += '%s\n' % uri['title']
            self._playlist_jobject.metadata['description'] = description

            write_playlist_to_file(self._playlist_jobject.file_path)
            datastore.write(self._playlist_jobject)

    def __go_fullscreen_cb(self, toolbar):
        self.fullscreen()

    def __toggle_playlist_cb(self, toolbar):
        if self._view_toolbar._show_playlist.get_active():
            self._playlist_box.show_all()
        else:
            self._playlist_box.hide()
        self._video_canvas.queue_draw()
Ejemplo n.º 37
0
class ReflectActivity(activity.Activity):
    ''' An activity for reflecting on one's work '''
    def __init__(self, handle):
        ''' Initialize the toolbar '''
        try:
            super(ReflectActivity, self).__init__(handle)
        except dbus.exceptions.DBusException as e:
            _logger.error(str(e))

        logging.error('setting reflection data to []')
        self.reflection_data = []

        self.connect('realize', self.__realize_cb)

        self.font_size = 8

        self.max_participants = 4
        self._setup_toolbars()

        color = profile.get_color()
        color_stroke = color.get_stroke_color()
        color_fill = color.get_fill_color()

        lighter = utils.lighter_color([color_stroke, color_fill])
        darker = 1 - lighter

        if lighter == 0:
            self.bg_color = style.Color(color_stroke)
            self.fg_color = style.Color(color_fill)
        else:
            self.bg_color = style.Color(color_fill)
            self.fg_color = style.Color(color_stroke)

        self.modify_bg(Gtk.StateType.NORMAL, self.bg_color.get_gdk_color())

        self.bundle_path = activity.get_bundle_path()
        self.tmp_path = os.path.join(activity.get_activity_root(), 'instance')

        self.sharing = False
        self._copy_entry = None
        self._paste_entry = None
        self._webkit = None
        self._clipboard_text = ''
        self._fixed = None

        self.initiating = True
        if self.shared_activity:
            # We're joining
            if not self.get_shared():
                self.initiating = False

                self.busy_cursor()
                share_icon = Icon(icon_name='zoom-neighborhood')
                self._joined_alert = Alert()
                self._joined_alert.props.icon = share_icon
                self._joined_alert.props.title = _('Please wait')
                self._joined_alert.props.msg = _('Starting connection...')
                self.add_alert(self._joined_alert)

                # Wait for joined signal
                self.connect("joined", self._joined_cb)

        self._open_reflect_windows()

        self._setup_presence_service()

        # Joiners wait to receive data from sharer
        # Otherwise, load reflections from local store
        if not self.shared_activity:
            self.busy_cursor()
            GObject.idle_add(self._load_reflections)

    def read_file(self, file_path):
        fd = open(file_path, 'r')
        data = fd.read()
        fd.close()
        self.reflection_data = json.loads(data)

    def write_file(self, file_path):
        data = json.dumps(self.reflection_data)
        fd = open(file_path, 'w')
        fd.write(data)
        fd.close()

        self.metadata['font_size'] = str(self.font_size)

    def _load_reflections(self):
        self._find_starred()
        self._reflect_window.load(self.reflection_data)
        self.reset_cursor()

    def _found_obj_id(self, obj_id):
        for item in self.reflection_data:
            if 'obj_id' in item and item['obj_id'] == obj_id:
                return True
        return False

    def reload_data(self, data):
        ''' Reload data after sorting or searching '''
        self._reflection_data = data[:]
        self._reflect_window.reload(self._reflection_data)
        self.reset_scrolled_window_adjustments()

    def _find_starred(self):
        ''' Find all the _stars in the Journal. '''
        self.dsobjects, self._nobjects = datastore.find({'keep': '1'})
        for dsobj in self.dsobjects:
            if self._found_obj_id(dsobj.object_id):
                continue  # Already have this object -- TODO: update it
            self._add_new_from_journal(dsobj)

    def _add_new_from_journal(self, dsobj):
        self.reflection_data.append({
            'title': _('Untitled'),
            'obj_id': dsobj.object_id
        })
        if hasattr(dsobj, 'metadata'):
            if 'creation_time' in dsobj.metadata:
                self.reflection_data[-1]['creation_time'] = \
                    dsobj.metadata['creation_time']
            else:
                self.reflection_data[-1]['creation_time'] = \
                    int(time.time())
            if 'timestamp' in dsobj.metadata:
                self.reflection_data[-1]['modification_time'] = \
                    dsobj.metadata['timestamp']
            else:
                self.reflection_data[-1]['modification_time'] = \
                    self.reflection_data[-1]['creation_time']
            if 'activity' in dsobj.metadata:
                self.reflection_data[-1]['activities'] = \
                    [utils.bundle_id_to_icon(dsobj.metadata['activity'])]
            if 'title' in dsobj.metadata:
                self.reflection_data[-1]['title'] = \
                    dsobj.metadata['title']
            if 'description' in dsobj.metadata:
                self.reflection_data[-1]['content'] = \
                    [{'text': dsobj.metadata['description']}]
            else:
                self.reflection_data[-1]['content'] = []
            if 'tags' in dsobj.metadata:
                self.reflection_data[-1]['tags'] = []
                tags = dsobj.metadata['tags'].split()
                for tag in tags:
                    if tag[0] != '#':
                        self.reflection_data[-1]['tags'].append('#' + tag)
                    else:
                        self.reflection_data[-1]['tags'].append(tag)
            if 'comments' in dsobj.metadata:
                try:
                    comments = json.loads(dsobj.metadata['comments'])
                except BaseException:
                    comments = []
                self.reflection_data[-1]['comments'] = []
                for comment in comments:
                    try:
                        data = {
                            'nick': comment['from'],
                            'comment': comment['message']
                        }
                        if 'icon-color' in comment:
                            colors = comment['icon-color'].split(',')
                            darker = 1 - utils.lighter_color(colors)
                            data['color'] = colors[darker]
                        else:
                            data['color'] = '#000000'
                        self.reflection_data[-1]['comments'].append(data)
                    except BaseException:
                        _logger.debug('could not parse comment %s' % comment)
            if 'mime_type' in dsobj.metadata and \
               dsobj.metadata['mime_type'][0:5] == 'image':
                new_path = os.path.join(self.tmp_path, dsobj.object_id)
                try:
                    shutil.copy(dsobj.file_path, new_path)
                except Exception as e:
                    logging.error("Couldn't copy %s to %s: %s" %
                                  (dsobj.file_path, new_path, e))
                self.reflection_data[-1]['content'].append({'image': new_path})
            elif 'preview' in dsobj.metadata:
                pixbuf = utils.get_pixbuf_from_journal(dsobj, 300, 225)
                if pixbuf is not None:
                    path = os.path.join(self.tmp_path,
                                        dsobj.object_id + '.png')
                    utils.save_pixbuf_to_file(pixbuf, path)
                    self.reflection_data[-1]['content'].append({'image': path})
            self.reflection_data[-1]['stars'] = 0

    def delete_item(self, obj_id):
        for i, obj in enumerate(self.reflection_data):
            if obj['obj_id'] == obj_id:
                self.reflection_data.remove(self.reflection_data[i])
                return

    def busy_cursor(self):
        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))

    def reset_cursor(self):
        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR))

    def _open_reflect_windows(self):
        # Most things need only be done once
        if self._fixed is None:
            self._fixed = Gtk.Fixed()
            self._fixed.set_size_request(Gdk.Screen.width(),
                                         Gdk.Screen.height())

            # Offsets from the bottom of the screen
            dy1 = 2 * style.GRID_CELL_SIZE
            dy2 = 1 * style.GRID_CELL_SIZE

            self._button_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._button_area.set_size_request(Gdk.Screen.width(),
                                               style.GRID_CELL_SIZE)
            self._fixed.put(self._button_area, 0, 0)
            self._button_area.show()

            self._scrolled_window = Gtk.ScrolledWindow()
            self._scrolled_window.set_size_request(Gdk.Screen.width(),
                                                   Gdk.Screen.height() - dy1)
            self._set_scroll_policy()
            self._graphics_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._scrolled_window.add_with_viewport(self._graphics_area)
            self._graphics_area.show()
            self._fixed.put(self._scrolled_window, 0, dy2)
            self._scrolled_window.show()

            self._overlay_window = Gtk.ScrolledWindow()
            self._overlay_window.set_size_request(style.GRID_CELL_SIZE * 10,
                                                  style.GRID_CELL_SIZE * 6)
            self._overlay_window.modify_bg(Gtk.StateType.NORMAL,
                                           style.COLOR_WHITE.get_gdk_color())
            self._overlay_window.set_policy(Gtk.PolicyType.NEVER,
                                            Gtk.PolicyType.AUTOMATIC)
            self._overlay_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._overlay_window.add_with_viewport(self._overlay_area)
            self._overlay_area.show()
            x = int((Gdk.Screen.width() - style.GRID_CELL_SIZE * 10) / 2)
            self._fixed.put(self._overlay_window, 0, Gdk.Screen.height())
            self._overlay_window.show()
            self._old_overlay_widget = None

            self._reflect_window = ReflectWindow(self)
            self._reflect_window.show()

            Gdk.Screen.get_default().connect('size-changed',
                                             self._configure_cb)
            self._toolbox.connect('hide', self._resize_hide_cb)
            self._toolbox.connect('show', self._resize_show_cb)

            self._reflect_window.set_events(Gdk.EventMask.KEY_PRESS_MASK)
            self._reflect_window.connect('key_press_event',
                                         self._reflect_window.keypress_cb)
            self._reflect_window.set_can_focus(True)
            self._reflect_window.grab_focus()

        self.set_canvas(self._fixed)
        self._fixed.show()

    def reset_scrolled_window_adjustments(self):
        adj = self._scrolled_window.get_hadjustment()
        if adj is not None:
            adj.set_value(0)
        adj = self._scrolled_window.get_vadjustment()
        if adj is not None:
            adj.set_value(0)

    def load_graphics_area(self, widget):
        self._graphics_area.add(widget)

    def load_button_area(self, widget):
        self._button_area.add(widget)

    def load_overlay_area(self, widget):
        if self._old_overlay_widget is not None:
            self._overlay_area.remove(self._old_overlay_widget)
        self._overlay_area.add(widget)
        self._old_overlay_widget = widget

    def show_overlay_area(self):
        x = int((Gdk.Screen.width() - style.GRID_CELL_SIZE * 10) / 2)
        self._fixed.move(self._overlay_window, x, style.GRID_CELL_SIZE)

    def hide_overlay_area(self):
        self._fixed.move(self._overlay_window, 0, Gdk.Screen.height())

    def collapse_overlay_area(self, button, event):
        self._fixed.move(self._overlay_window, 0, Gdk.Screen.height())

    def _resize_hide_cb(self, widget):
        self._resize_canvas(widget, True)

    def _resize_show_cb(self, widget):
        self._resize_canvas(widget, False)

    def _configure_cb(self, event):
        self._fixed.set_size_request(Gdk.Screen.width(), Gdk.Screen.height())
        self._set_scroll_policy()
        self._resize_canvas(None)
        self._reflect_window.reload_graphics()

    def _resize_canvas(self, widget, fullscreen=False):
        # When a toolbar is expanded or collapsed, resize the canvas
        if hasattr(self, '_reflect_window'):
            if self.toolbar_expanded():
                dy1 = 3 * style.GRID_CELL_SIZE
                dy2 = 2 * style.GRID_CELL_SIZE
            else:
                dy1 = 2 * style.GRID_CELL_SIZE
                dy2 = 1 * style.GRID_CELL_SIZE

            if fullscreen:
                dy1 -= 2 * style.GRID_CELL_SIZE
                dy2 -= 2 * style.GRID_CELL_SIZE

            self._scrolled_window.set_size_request(Gdk.Screen.width(),
                                                   Gdk.Screen.height() - dy2)
            self._fixed.move(self._button_area, 0, 0)

        self._about_panel_visible = False

    def toolbar_expanded(self):
        if self.activity_button.is_expanded():
            return True
        elif self.edit_toolbar_button.is_expanded():
            return True
        elif self.view_toolbar_button.is_expanded():
            return True
        return False

    def get_activity_version(self):
        info_path = os.path.join(self.bundle_path, 'activity', 'activity.info')
        try:
            info_file = open(info_path, 'r')
        except Exception as e:
            _logger.error('Could not open %s: %s' % (info_path, e))
            return 'unknown'

        cp = ConfigParser()
        cp.readfp(info_file)

        section = 'Activity'

        if cp.has_option(section, 'activity_version'):
            activity_version = cp.get(section, 'activity_version')
        else:
            activity_version = 'unknown'
        return activity_version

    def get_uid(self):
        if len(self.volume_data) == 1:
            return self.volume_data[0]['uid']
        else:
            return 'unknown'

    def _setup_toolbars(self):
        ''' Setup the toolbars. '''
        self._toolbox = ToolbarBox()

        self.activity_button = ActivityToolbarButton(self)
        self.activity_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.activity_button, 0)
        self.activity_button.show()

        self.set_toolbar_box(self._toolbox)
        self._toolbox.show()
        self.toolbar = self._toolbox.toolbar

        view_toolbar = Gtk.Toolbar()
        self.view_toolbar_button = ToolbarButton(page=view_toolbar,
                                                 label=_('View'),
                                                 icon_name='toolbar-view')
        self.view_toolbar_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.view_toolbar_button, 1)
        view_toolbar.show()
        self.view_toolbar_button.show()

        button = ToolButton('view-fullscreen')
        button.set_tooltip(_('Fullscreen'))
        button.props.accelerator = '<Alt>Return'
        view_toolbar.insert(button, -1)
        button.show()
        button.connect('clicked', self._fullscreen_cb)

        edit_toolbar = Gtk.Toolbar()
        self.edit_toolbar_button = ToolbarButton(page=edit_toolbar,
                                                 label=_('Edit'),
                                                 icon_name='toolbar-edit')
        self.edit_toolbar_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.edit_toolbar_button, 1)
        edit_toolbar.show()
        self.edit_toolbar_button.show()

        self._copy_button = ToolButton('edit-copy')
        self._copy_button.set_tooltip(_('Copy'))
        self._copy_button.props.accelerator = '<Ctrl>C'
        edit_toolbar.insert(self._copy_button, -1)
        self._copy_button.show()
        self._copy_button.connect('clicked', self._copy_cb)
        self._copy_button.set_sensitive(False)

        self._paste_button = ToolButton('edit-paste')
        self._paste_button.set_tooltip(_('Paste'))
        self._paste_button.props.accelerator = '<Ctrl>V'
        edit_toolbar.insert(self._paste_button, -1)
        self._paste_button.show()
        self._paste_button.connect('clicked', self._paste_cb)
        self._paste_button.set_sensitive(False)

        button = ToolButton('list-add')
        button.set_tooltip(_('Add Item'))
        button.props.accelerator = '<Ctrl>+'
        self._toolbox.toolbar.insert(button, -1)
        button.show()
        button.connect('clicked', self.__add_item_cb)

        self._date_button = RadioToolButton('date-sort', group=None)
        self._date_button.set_tooltip(_('Sort by Date'))
        self._date_button.connect('clicked', self._date_button_cb)
        self._toolbox.toolbar.insert(self._date_button, -1)
        self._date_button.show()

        self._title_button = RadioToolButton('title-sort',
                                             group=self._date_button)
        self._title_button.set_tooltip(_('Sort by Title'))
        self._title_button.connect('clicked', self._title_button_cb)
        self._toolbox.toolbar.insert(self._title_button, -1)
        self._title_button.show()

        self._stars_button = RadioToolButton('stars-sort',
                                             group=self._date_button)
        self._stars_button.set_tooltip(_('Sort by Favourite'))
        self._stars_button.connect('clicked', self._stars_button_cb)
        self._toolbox.toolbar.insert(self._stars_button, -1)
        self._stars_button.show()

        # setup the search options
        self._search_entry = iconentry.IconEntry()
        self._search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                              'system-search')
        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()

        tool_item = Gtk.ToolItem()
        tool_item.set_expand(True)
        tool_item.add(self._search_entry)
        self._search_entry.show()
        self._toolbox.toolbar.insert(tool_item, -1)
        tool_item.show()

        self._search_button = ToolButton('dialog-ok')
        self._search_button.set_tooltip(_('Search by Tags'))
        self._search_button.connect('clicked', self._search_button_cb)
        self._toolbox.toolbar.insert(self._search_button, -1)
        self._search_button.show()

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

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        self._toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()

    def _search_button_cb(self, button):
        self.busy_cursor()
        self._do_search()

    def _search_entry_activated_cb(self, entry):
        self.busy_cursor()
        self._do_search()

    def _do_search(self):
        logging.debug('_search_entry_activated_cb')
        if self._search_entry.props.text == '':
            logging.debug('clearing search')
            for item in self.reflection_data:
                item['hidden'] = False
        else:
            tags = self._search_entry.props.text.split()
            for i, tag in enumerate(tags):
                if not tag[0] == '#':
                    tags[i] = '#%s' % tag
            logging.error(tags)
            for item in self.reflection_data:
                hidden = True
                if 'tags' in item:
                    for tag in tags:
                        if tag in item['tags']:
                            hidden = False
                item['hidden'] = hidden
        self.reload_data(self.reflection_data)
        self.reset_cursor()

    def _search_entry_changed_cb(self, entry):
        logging.debug('_search_entry_changed_cb search for \'%s\'',
                      self._search_entry.props.text)
        self.busy_cursor()
        self._do_search_changed()

    def _do_search_changed(self):
        if self._search_entry.props.text == '':
            logging.debug('clearing search')
            for item in self.reflection_data:
                item['hidden'] = False
            self.reload_data(self.reflection_data)
        self.reset_cursor()

    def _title_button_cb(self, button):
        ''' sort by title '''
        self.busy_cursor()
        GObject.idle_add(self._title_sort)

    def _title_sort(self):
        sorted_data = sorted(self.reflection_data,
                             key=lambda item: item['title'].lower())
        self.reload_data(sorted_data)
        self.reset_cursor()

    def _date_button_cb(self, button):
        ''' sort by modification date '''
        self.busy_cursor()
        GObject.idle_add(self._date_sort)

    def _date_sort(self):
        sorted_data = sorted(self.reflection_data,
                             key=lambda item: int(item['modification_time']),
                             reverse=True)
        self.reload_data(sorted_data)
        self.reset_cursor()

    def _stars_button_cb(self, button):
        ''' sort by number of stars '''
        self.busy_cursor()
        GObject.idle_add(self._stars_sort)

    def _stars_sort(self):
        sorted_data = sorted(self.reflection_data,
                             key=lambda item: item['stars'],
                             reverse=True)
        self.reload_data(sorted_data)
        self.reset_cursor()

    def __realize_cb(self, window):
        self.window_xid = window.get_window().get_xid()

    def set_copy_widget(self, webkit=None, text_entry=None):
        # Each task is responsible for setting a widget for copy
        if webkit is not None:
            self._webkit = webkit
        else:
            self._webkit = None
        if text_entry is not None:
            self._copy_entry = text_entry
        else:
            self._copy_entry = None

        self._copy_button.set_sensitive(webkit is not None
                                        or text_entry is not None)

    def _copy_cb(self, button):
        if self._copy_entry is not None:
            self._copy_entry.copy_clipboard()
        elif self._webkit is not None:
            self._webkit.copy_clipboard()
        else:
            _logger.debug('No widget set for copy.')

    def set_paste_widget(self, text_entry=None):
        # Each task is responsible for setting a widget for paste
        if text_entry is not None:
            self._paste_entry = text_entry
        self._paste_button.set_sensitive(text_entry is not None)

    def _paste_cb(self, button):
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        self.clipboard_text = clipboard.wait_for_text()
        if self._paste_entry is not None:
            self._paste_entry.paste_clipboard()
        else:
            _logger.debug('No widget set for paste (%s).' %
                          self.clipboard_text)

    def _fullscreen_cb(self, button):
        ''' Hide the Sugar toolbars. '''
        self.fullscreen()

    def __add_item_cb(self, button):
        try:
            chooser = ObjectChooser(parent=self, what_filter=None)
        except TypeError:
            chooser = ObjectChooser(
                None, self._reflection.activity,
                Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT)

        try:
            result = chooser.run()
            if result == Gtk.ResponseType.ACCEPT:
                jobject = chooser.get_selected_object()
                if jobject:
                    self._add_new_from_journal(jobject)
                    self.reload_data(self.reflection_data)
        finally:
            chooser.destroy()
            del chooser

    def _set_scroll_policy(self):
        if Gdk.Screen.width() < Gdk.Screen.height():
            self._scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                             Gtk.PolicyType.AUTOMATIC)
        else:
            self._scrolled_window.set_policy(Gtk.PolicyType.NEVER,
                                             Gtk.PolicyType.AUTOMATIC)

    def _remove_alert_cb(self, alert, response_id):
        self.remove_alert(alert)

    def _close_alert_cb(self, alert, response_id):
        self.remove_alert(alert)
        if response_id is Gtk.ResponseType.OK:
            self.close()

    def _setup_presence_service(self):
        ''' Setup the Presence Service. '''
        self.pservice = presenceservice.get_instance()

        owner = self.pservice.get_owner()
        self.owner = owner
        self._share = ''
        self.connect('shared', self._shared_cb)
        self.connect('joined', self._joined_cb)

    def _shared_cb(self, activity):
        ''' Either set up initial share...'''
        if self.shared_activity is None:
            _logger.error('Failed to share or join activity ... \
                shared_activity is null in _shared_cb()')
            return

        self.initiating = True
        self._waiting_for_reflections = False
        _logger.debug('I am sharing...')

        self.conn = self.shared_activity.telepathy_conn
        self.tubes_chan = self.shared_activity.telepathy_tubes_chan
        self.text_chan = self.shared_activity.telepathy_text_chan

        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
            'NewTube', self._new_tube_cb)

        _logger.debug('This is my activity: making a tube...')
        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(
            SERVICE, {})

        self.sharing = True

    def _joined_cb(self, activity):
        ''' ...or join an exisiting share. '''
        if self.shared_activity is None:
            _logger.error('Failed to share or join activity ... \
                shared_activity is null in _shared_cb()')
            return

        if self._joined_alert is not None:
            self.remove_alert(self._joined_alert)
            self._joined_alert = None

        self.initiating = False
        self._waiting_for_reflections = True
        _logger.debug('I joined a shared activity.')

        self.conn = self.shared_activity.telepathy_conn
        self.tubes_chan = self.shared_activity.telepathy_tubes_chan
        self.text_chan = self.shared_activity.telepathy_text_chan

        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
            'NewTube', self._new_tube_cb)

        _logger.debug('I am joining an activity: waiting for a tube...')
        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
            reply_handler=self._list_tubes_reply_cb,
            error_handler=self._list_tubes_error_cb)

        self.sharing = True

    def _list_tubes_reply_cb(self, tubes):
        ''' Reply to a list request. '''
        for tube_info in tubes:
            self._new_tube_cb(*tube_info)

    def _list_tubes_error_cb(self, e):
        ''' Log errors. '''
        _logger.error('ListTubes() failed: %s', e)

    def _new_tube_cb(self, id, initiator, type, service, params, state):
        ''' Create a new tube. '''
        _logger.debug(
            'New tube: ID=%d initator=%d type=%d service=%s '
            'params=%r state=%d', id, initiator, type, service, params, state)

        if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE):
            if state == telepathy.TUBE_STATE_LOCAL_PENDING:
                self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(
                    id)

            self.collab = CollabWrapper(self)
            self.collab.message.connect(self.event_received_cb)
            self.collab.setup()

            if self._waiting_for_reflections:
                self.send_event(JOIN_CMD, {})
                self._joined_alert = Alert()
                self._joined_alert.props.title = _('Please wait')
                self._joined_alert.props.msg = _('Requesting reflections...')
                self.add_alert(self._joined_alert)

    def event_received_cb(self, collab, buddy, msg):
        ''' Data is passed as tuples: cmd:text '''
        command = msg.get("command")
        payload = msg.get("payload")
        logging.debug(command)

        if command == JOIN_CMD:
            # Sharer needs to send reflections database to joiners.
            if self.initiating:
                # Send pictures first.
                for item in self.reflection_data:
                    if 'content' in item:
                        for content in item['content']:
                            if 'image' in content:
                                pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
                                    content['image'], 120, 90)
                                if pixbuf is not None:
                                    data = utils.pixbuf_to_base64(pixbuf)
                                self.send_event(
                                    PICTURE_CMD, {
                                        "image": os.path.basename(
                                            content['image']),
                                        "data": data
                                    })
                data = json.dumps(self.reflection_data)
                self.send_event(SHARE_CMD, {"data": data})
        elif command == NEW_REFLECTION_CMD:
            self._reflect_window.add_new_reflection(payload)
        elif command == TITLE_CMD:
            obj_id = payload.get("obj_id")
            title = payload.get("title")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    self._reflect_window.update_title(obj_id, title)
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == TAG_CMD:
            obj_id = payload.get("obj_id")
            data = payload.get("data")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    self._reflect_window.update_tags(obj_id, data)
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == ACTIVITY_CMD:
            obj_id = payload.get("obj_id")
            bundle_id = payload.get("bundle_id")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    self._reflect_window.insert_activity(obj_id, bundle_id)
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == STAR_CMD:
            obj_id = payload.get("obj_id")
            stars = payload.get("stars")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    self._reflect_window.update_stars(obj_id, int(stars))
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == COMMENT_CMD:
            found_the_object = False
            # Receive a comment and associated reflection ID
            obj_id = payload.get("obj_id")
            nick = payload.get("nick")
            color = payload.get("color")
            comment = payload.get("comment")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    if 'comments' not in item:
                        item['comments'] = []
                    data = {'nick': nick, 'comment': comment, 'color': color}
                    item['comments'].append(data)
                    self._reflect_window.insert_comment(obj_id, data)
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == REFLECTION_CMD:
            found_the_object = False
            # Receive a reflection and associated reflection ID
            obj_id = payload.get("obj_id")
            reflection = payload.get("reflection")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    if '' not in item:
                        item['content'] = []
                    item['content'].append({'text': reflection})
                    self._reflect_window.insert_reflection(obj_id, reflection)
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == IMAGE_REFLECTION_CMD:
            found_the_object = False
            # Receive a picture reflection and associated reflection ID
            obj_id = payload.get("obj_id")
            basename = payload.get("basename")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    if '' not in item:
                        item['content'] = []
                    item['content'].append(
                        {'image': os.path.join(self.tmp_path, basename)})
                    self._reflect_window.insert_picture(
                        obj_id, os.path.join(self.tmp_path, basename))
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == PICTURE_CMD:
            # Receive a picture (MAYBE DISPLAY IT AS IT ARRIVES?)
            basename = payload.get("basename")
            data = payload.get("data")
            utils.base64_to_file(data, os.path.join(self.tmp_path, basename))
        elif command == SHARE_CMD:
            # Joiner needs to load reflection database.
            if not self.initiating:
                # Note that pictures should be received.
                self.reflection_data = payload
                self._reflect_window.load(self.reflection_data)
                self._waiting_for_reflections = False
                self.reset_cursor()
                if self._joined_alert is not None:
                    self.remove_alert(self._joined_alert)
                    self._joined_alert = None

    def send_event(self, command, data):
        ''' Send event through the tube. '''
        if hasattr(self, 'collab') and self.collab is not None:
            data["command"] = command
            self.collab.post(data)
Ejemplo n.º 38
0
class TrainingActivity(activity.Activity):
    ''' A series of training exercises '''
    transfer_started_signal = GObject.Signal('started', arg_types=([]))
    transfer_progressed_signal = GObject.Signal('progressed', arg_types=([]))
    transfer_completed_signal = GObject.Signal('completed', arg_types=([]))
    transfer_failed_signal = GObject.Signal('failed', arg_types=([]))

    def __init__(self, handle):
        ''' Initialize the toolbars and the game board '''
        try:
            super(TrainingActivity, self).__init__(handle)
        except dbus.exceptions.DBusException as e:
            _logger.error(str(e))

        self.connect('realize', self.__realize_cb)
        self.connect('started', self.__transfer_started_cb)
        self.connect('progressed', self.__transfer_progressed_cb)
        self.connect('completed', self.__transfer_completed_cb)
        self.connect('failed', self.__transfer_failed_cb)

        self.volume_monitor = Gio.VolumeMonitor.get()
        self.volume_monitor.connect('mount-added', self._mount_added_cb)
        self.volume_monitor.connect('mount-removed', self._mount_removed_cb)

        if hasattr(self, 'metadata') and 'font_size' in self.metadata:
            self.font_size = int(self.metadata['font_size'])
        else:
            self.font_size = 8
        self.zoom_level = self.font_size / float(len(FONT_SIZES))
        _logger.debug('zoom level is %f' % self.zoom_level)

        _check_gconf_settings()  # For debugging purposes

        self._setup_toolbars()
        self.modify_bg(Gtk.StateType.NORMAL,
                       style.COLOR_WHITE.get_gdk_color())

        self.bundle_path = activity.get_bundle_path()
        self.volume_data = []

        self.help_palette = None
        self.help_panel_visible = False
        self._copy_entry = None
        self._paste_entry = None
        self._webkit = None
        self._clipboard_text = ''
        self._fixed = None
        self._notify_transfer_status = False

        if self._load_extension() and self.check_volume_data():
            self._launcher()

    def _launcher(self):
        get_power_manager().inhibit_suspend()

        # We are resuming the activity or we are launching a new instance?
        # * Is there a data file to sync on the USB key?
        # * Do we create a new data file on the USB key?
        path = self._check_for_USB_data()
        if path is None:
            self._launch_task_master()
        elif self._sync_data_from_USB(path):
            self._copy_data_from_USB()
            # Flash a welcome back screen.
            self._load_intro_graphics(file_name='welcome-back.html')
            GObject.timeout_add(1500, self._launch_task_master)

    def can_close(self):
        get_power_manager().restore_suspend()
        return True

    def busy_cursor(self):
        self._old_cursor = self.get_window().get_cursor()
        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))

    def reset_cursor(self):
        if hasattr(self, '_old_cursor'):
            self.get_window().set_cursor(self._old_cursor)

    def check_volume_data(self):
        # Before we begin (and before each task),
        # we need to find any and all USB keys
        # and any and all training-data files on them.

        _logger.debug(utils.get_volume_paths())
        self.volume_data = []
        for path in utils.get_volume_paths():
            os.path.basename(path)
            self.volume_data.append(
                {'basename': os.path.basename(path),
                 'files': utils.look_for_training_data(path),
                 'sugar_path': os.path.join(self.get_activity_root(), 'data'),
                 'usb_path': path})
            _logger.debug(self.volume_data[-1])

        # (1) We require a USB key
        if len(self.volume_data) == 0:
            _logger.error('NO USB KEY INSERTED')
            alert = ConfirmationAlert()
            alert.props.title = _('USB key required')
            alert.props.msg = _('You must insert a USB key before launching '
                                'this activity.')
            alert.connect('response', self._remove_alert_cb)
            self.add_alert(alert)
            self._load_intro_graphics(file_name='insert-usb.html')
            return False

        # (2) Only one USB key
        if len(self.volume_data) > 1:
            _logger.error('MULTIPLE USB KEYS INSERTED')
            alert = ConfirmationAlert()
            alert.props.title = _('Multiple USB keys found')
            alert.props.msg = _('Only one USB key must be inserted while '
                                'running this program.\nPlease remove any '
                                'additional USB keys before launching '
                                'this activity.')
            alert.connect('response', self._remove_alert_cb)
            self.add_alert(alert)
            self._load_intro_graphics(message=alert.props.msg)
            return False

        volume = self.volume_data[0]

        # (3) At least 10MB of free space
        if utils.is_full(volume['usb_path'],
                         required=_MINIMUM_SPACE):
            _logger.error('USB IS FULL')
            alert = ConfirmationAlert()
            alert.props.title = _('USB key is full')
            alert.props.msg = _('No room on USB')
            alert.connect('response', self._close_alert_cb)
            self.add_alert(alert)
            self._load_intro_graphics(message=alert.props.msg)
            return False

        # (4) File is read/write
        if not utils.is_writeable(volume['usb_path']):
            _logger.error('CANNOT WRITE TO USB')
            alert = ConfirmationAlert()
            alert.props.title = _('Cannot write to USB')
            alert.props.msg = _('USB key seems to be read-only.')
            alert.connect('response', self._close_alert_cb)
            self.add_alert(alert)
            self._load_intro_graphics(message=alert.props.msg)
            return False

        # (5) Only one set of training data per USB key
        # We expect UIDs to formated as XXXX-XXXX
        # We need to make sure we have proper UIDs associated with
        # the USBs and the files on them match the UID.
        # (a) If there are no files, we will assign the UID based on the
        #     volume path;
        # (b) If there is one file with a valid UID, we use that UID;
        if len(volume['files']) == 0:
            volume['uid'] = 'training-data-%s' % \
                            utils.format_volume_name(volume['basename'])
            _logger.debug('No training data found. Using UID %s' %
                          volume['uid'])
            return True
        elif len(volume['files']) == 1:
            volume['uid'] = 'training-data-%s' % volume['files'][0][-9:]
            _logger.debug('Training data found. Using UID %s' %
                          volume['uid'])
            return True
        else:
            _logger.error('MULTIPLE TRAINING-DATA FILES FOUND')
            alert = ConfirmationAlert()
            alert.props.title = _('Multiple training-data files found.')
            alert.props.msg = _('There can only be one set of training '
                                'data per USB key.')
            alert.connect('response', self._close_alert_cb)
            self.add_alert(alert)
            self._load_intro_graphics(message=alert.props.msg)
            return False

    def _check_for_USB_data(self):
        usb_path = os.path.join(self.volume_data[0]['usb_path'],
                                self.volume_data[0]['uid'])
        if os.path.exists(usb_path):
            return usb_path
        else:
            return None

    def _sync_data_from_USB(self, usb_data_path=None):
        # We need to sync up file on USB with file on disk,
        # but only if the email addresses match. Otherwise,
        # raise an error.
        if usb_data_path is not None:
            usb_data = {}
            if os.path.exists(usb_data_path):
                fd = open(usb_data_path, 'r')
                json_data = fd.read()
                fd.close()
                if len(json_data) > 0:
                    try:
                        usb_data = json.loads(json_data)
                    except ValueError as e:
                        _logger.error('Cannot load USB data: %s' % e)
            else:
                _logger.error('Cannot find USB data: %s' % usb_data_path)

            sugar_data_path = os.path.join(
                self.volume_data[0]['sugar_path'],
                self.volume_data[0]['uid'])
            sugar_data = {}
            if os.path.exists(sugar_data_path):
                fd = open(sugar_data_path, 'r')
                json_data = fd.read()
                fd.close()
                if len(json_data) > 0:
                    try:
                        sugar_data = json.loads(json_data)
                    except ValueError as e:
                        _logger.error('Cannot load Sugar data: %s' % e)
            else:
                _logger.error('Cannot find Sugar data: %s' % sugar_data_path)

            # First, check to make sure email_address matches
            if EMAIL_UID in usb_data:
                usb_email = usb_data[EMAIL_UID]
            else:
                usb_email = None
            if EMAIL_UID in sugar_data:
                sugar_email = sugar_data[EMAIL_UID]
            else:
                sugar_email = None
            if usb_email != sugar_email:
                if usb_email is None and sugar_email is not None:
                    _logger.warning('Using email address from Sugar: %s' %
                                    sugar_email)
                    usb_data[EMAIL_UID] = sugar_email
                elif usb_email is not None and sugar_email is None:
                    _logger.warning('Using email address from USB: %s' %
                                    usb_email)
                    sugar_data[EMAIL_UID] = usb_email
                elif usb_email is None and sugar_email is None:
                    _logger.warning('No email address found')
                else:
                    # FIX ME: We need to resolve this, but for right now, punt.
                    alert = ConfirmationAlert()
                    alert.props.title = _('Data mismatch')
                    alert.props.msg = _('Are you %(usb)s or %(sugar)s?' %
                                        {'usb': usb_email,
                                         'sugar': sugar_email})
                    alert.connect('response', self._close_alert_cb)
                    self.add_alert(alert)
                    self._load_intro_graphics(message=alert.props.msg)
                    return False

            def count_completed(data):
                count = 0
                for key in data:
                    if isinstance(data[key], dict) and \
                       'completed' in data[key] and \
                       data[key]['completed']:
                        count += 1
                return count

            # The database with the most completed tasks takes precedence.
            if count_completed(usb_data) >= count_completed(sugar_data):
                _logger.debug('data sync: USB data takes precedence')
                data_one = usb_data
                data_two = sugar_data
            else:
                _logger.debug('data sync: Sugar data takes precedence')
                data_one = sugar_data
                data_two = usb_data

            # Copy completed tasks from one to two
            for key in data_one:
                if isinstance(data_one[key], dict) and \
                   'completed' in data_one[key] and \
                   data_one[key]['completed']:
                    data_two[key] = data_one[key]

            # Copy completed tasks from two to one
            for key in data_two:
                if isinstance(data_two[key], dict) and \
                   'completed' in data_two[key] and \
                   data_two[key]['completed']:
                    data_one[key] = data_two[key]

            # Copy incompleted tasks from one to two
            for key in data_one:
                if isinstance(data_one[key], dict) and \
                   (not 'completed' in data_one[key] or
                    not data_one[key]['completed']):
                        data_two[key] = data_one[key]

            # Copy incompleted tasks from two to one
            for key in data_two:
                if isinstance(data_two[key], dict) and \
                   (not 'completed' in data_two[key] or
                    not data_two[key]['completed']):
                        data_one[key] = data_two[key]

            # Copy name, email_address, current_task...
            for key in data_one:
                if not isinstance(data_one[key], dict):
                    data_two[key] = data_one[key]
            for key in data_two:
                if not isinstance(data_two[key], dict):
                    data_one[key] = data_two[key]

            # Finally, write to the USB and ...
            json_data = json.dumps(data_one)
            fd = open(usb_data_path, 'w')
            fd.write(json_data)
            fd.close()

            # ...save a shadow copy in Sugar
            fd = open(sugar_data_path, 'w')
            fd.write(json_data)
            fd.close()
            return True
        else:
            _logger.error('No data to sync on USB')
            return False

    def _copy_data_from_USB(self):
        usb_path = self._check_for_USB_data()
        if usb_path is not None:
            try:
                subprocess.call(['cp', usb_path,
                                 self.volume_data[0]['sugar_path']])
            except OSError as e:
                _logger.error('Could not copy %s to %s: %s' % (
                    usb_path, self.volume_data[0]['sugar_path'], e))
        else:
            _logger.error('No data found on USB')

    def toolbar_expanded(self):
        if self.activity_button.is_expanded():
            return True
        elif self.edit_toolbar_button.is_expanded():
            return True
        elif self.view_toolbar_button.is_expanded():
            return True
        elif hasattr(self, 'progress_toolbar_button') and \
             self.progress_toolbar_button.is_expanded():
            return True

    def _launch_task_master(self):
        # Most things need only be done once
        if self._fixed is None:
            self._fixed = Gtk.Fixed()
            self._fixed.set_size_request(Gdk.Screen.width(),
                                         Gdk.Screen.height())

            # Offsets from the bottom of the screen
            dy1 = 3 * style.GRID_CELL_SIZE
            dy2 = 2 * style.GRID_CELL_SIZE

            self._progress_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._progress_area.set_size_request(Gdk.Screen.width(), -1)
            self._fixed.put(self._progress_area, 0, Gdk.Screen.height() - dy2)
            self._progress_area.show()

            self._button_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._button_area.set_size_request(Gdk.Screen.width(), -1)
            self._fixed.put(self._button_area, 0, Gdk.Screen.height() - dy1)
            self._button_area.show()

            self._scrolled_window = Gtk.ScrolledWindow()
            self._scrolled_window.set_size_request(
                Gdk.Screen.width(), Gdk.Screen.height() - dy1)
            self._set_scroll_policy()
            self._graphics_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._scrolled_window.add_with_viewport(self._graphics_area)
            self._graphics_area.show()
            self._fixed.put(self._scrolled_window, 0, 0)
            self._scrolled_window.show()

            self._task_master = TaskMaster(self)
            self._task_master.show()

            # Now that we have the tasks, we can build the progress toolbar and
            # help panel.
            self._build_progress_toolbar()

            self._help_panel = HelpPanel(self._task_master)
            self.help_palette = self._help_button.get_palette()
            self.help_palette.set_content(self._help_panel)
            self._help_panel.show()
            self._help_button.set_sensitive(True)

            Gdk.Screen.get_default().connect('size-changed',
                                             self._configure_cb)
            self._toolbox.connect('hide', self._resize_hide_cb)
            self._toolbox.connect('show', self._resize_show_cb)

            self._task_master.set_events(Gdk.EventMask.KEY_PRESS_MASK)
            self._task_master.connect('key_press_event',
                                      self._task_master.keypress_cb)
            self._task_master.set_can_focus(True)
            self._task_master.grab_focus()

        self.set_canvas(self._fixed)
        self._fixed.show()

        self.completed = False
        self._update_completed_sections()
        self._check_connected_task_status()
        self._task_master.task_master()

    def load_graphics_area(self, widget):
        self._graphics_area.add(widget)

    def load_button_area(self, widget):
        self._button_area.add(widget)

    def load_progress_area(self, widget):
        self._progress_area.add(widget)

    def _load_intro_graphics(self, file_name='generic-problem.html',
                             message=None):
        center_in_panel = Gtk.Alignment.new(0.5, 0, 0, 0)
        url = os.path.join(self.bundle_path, 'html-content', file_name)
        graphics = Graphics()
        if message is None:
            graphics.add_uri('file://' + url)
        else:
            graphics.add_uri('file://' + url + '?MSG=' +
                             utils.get_safe_text(message))
        graphics.set_zoom_level(0.667)
        center_in_panel.add(graphics)
        graphics.show()
        self.set_canvas(center_in_panel)
        center_in_panel.show()

    def _resize_hide_cb(self, widget):
        self._resize_canvas(widget, True)

    def _resize_show_cb(self, widget):
        self._resize_canvas(widget, False)

    def _configure_cb(self, event):
        self._fixed.set_size_request(Gdk.Screen.width(), Gdk.Screen.height())
        self._set_scroll_policy()
        self._resize_canvas(None)
        self._task_master.reload_graphics()

    def _resize_canvas(self, widget, fullscreen=False):
        # When a toolbar is expanded or collapsed, resize the canvas
        # to ensure that the progress bar is still visible.
        if hasattr(self, '_task_master'):
            if self.toolbar_expanded():
                dy1 = 4 * style.GRID_CELL_SIZE
                dy2 = 3 * style.GRID_CELL_SIZE
            else:
                dy1 = 3 * style.GRID_CELL_SIZE
                dy2 = 2 * style.GRID_CELL_SIZE

            if fullscreen:
                dy1 -= 2 * style.GRID_CELL_SIZE
                dy2 -= 2 * style.GRID_CELL_SIZE

            self._scrolled_window.set_size_request(
                Gdk.Screen.width(), Gdk.Screen.height() - dy1)
            self._fixed.move(self._progress_area, 0, Gdk.Screen.height() - dy2)
            self._fixed.move(self._button_area, 0, Gdk.Screen.height() - dy1)

        self.help_panel_visible = False

    def get_activity_version(self):
        info_path = os.path.join(self.bundle_path, 'activity', 'activity.info')
        try:
            info_file = open(info_path, 'r')
        except Exception as e:
            _logger.error('Could not open %s: %s' % (info_path, e))
            return 'unknown'

        cp = ConfigParser()
        cp.readfp(info_file)

        section = 'Activity'

        if cp.has_option(section, 'activity_version'):
            activity_version = cp.get(section, 'activity_version')
        else:
            activity_version = 'unknown'
        return activity_version

    def get_uid(self):
        if len(self.volume_data) == 1:
            return self.volume_data[0]['uid']
        else:
            return 'unknown'

    def write_file(self, file_path):
        # Only write if we have a valid USB/data file to work with.
        if len(self.volume_data) == 1 and \
           len(self.volume_data[0]['files']) == 1:
            self.metadata[TRAINING_DATA_UID] = self.volume_data[0]['uid']

            # We may have failed before getting to init of taskmaster
            if hasattr(self, '_task_master'):
                self._task_master.write_task_data(
                    'current_task', self._task_master.current_task)
                self.update_activity_title()
                email = self._task_master.read_task_data(EMAIL_UID)
                if email is None:
                    email = ''
                self.metadata[TRAINING_DATA_EMAIL] = email
                name = self._task_master.read_task_data(NAME_UID)
                if name is None:
                    name = ''
                self.metadata[TRAINING_DATA_FULLNAME] = name

        self.metadata['font_size'] = str(self.font_size)

    def update_activity_title(self):
        name = self._task_master.read_task_data(NAME_UID)
        if name is not None:
            bundle_name = activity.get_bundle_name()
            self.metadata['title'] = _('%(name)s %(bundle)s Activity') % \
                {'name': name, 'bundle': bundle_name}

    def _setup_toolbars(self):
        ''' Setup the toolbars. '''
        self.max_participants = 1  # No sharing

        self._toolbox = ToolbarBox()

        self.activity_button = ActivityToolbarButton(self)
        self.activity_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.activity_button, 0)
        self.activity_button.show()

        self.set_toolbar_box(self._toolbox)
        self._toolbox.show()
        self.toolbar = self._toolbox.toolbar

        view_toolbar = Gtk.Toolbar()
        self.view_toolbar_button = ToolbarButton(
            page=view_toolbar,
            label=_('View'),
            icon_name='toolbar-view')
        self.view_toolbar_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.view_toolbar_button, 1)
        view_toolbar.show()
        self.view_toolbar_button.show()

        button = ToolButton('view-fullscreen')
        button.set_tooltip(_('Fullscreen'))
        button.props.accelerator = '<Alt>Return'
        view_toolbar.insert(button, -1)
        button.show()
        button.connect('clicked', self._fullscreen_cb)

        self._zoom_in = ToolButton('zoom-in')
        self._zoom_in.set_tooltip(_('Increase size'))
        view_toolbar.insert(self._zoom_in, -1)
        self._zoom_in.show()
        self._zoom_in.connect('clicked', self._zoom_in_cb)

        self._zoom_out = ToolButton('zoom-out')
        self._zoom_out.set_tooltip(_('Decrease size'))
        view_toolbar.insert(self._zoom_out, -1)
        self._zoom_out.show()
        self._zoom_out.connect('clicked', self._zoom_out_cb)

        self._zoom_eq = ToolButton('zoom-original')
        self._zoom_eq.set_tooltip(_('Restore original size'))
        view_toolbar.insert(self._zoom_eq, -1)
        self._zoom_eq.show()
        self._zoom_eq.connect('clicked', self._zoom_eq_cb)

        self._set_zoom_buttons_sensitivity()

        edit_toolbar = Gtk.Toolbar()
        self.edit_toolbar_button = ToolbarButton(
            page=edit_toolbar,
            label=_('Edit'),
            icon_name='toolbar-edit')
        self.edit_toolbar_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.edit_toolbar_button, 1)
        edit_toolbar.show()
        self.edit_toolbar_button.show()

        self._copy_button = ToolButton('edit-copy')
        self._copy_button.set_tooltip(_('Copy'))
        self._copy_button.props.accelerator = '<Ctrl>C'
        edit_toolbar.insert(self._copy_button, -1)
        self._copy_button.show()
        self._copy_button.connect('clicked', self._copy_cb)
        self._copy_button.set_sensitive(False)

        self._paste_button = ToolButton('edit-paste')
        self._paste_button.set_tooltip(_('Paste'))
        self._paste_button.props.accelerator = '<Ctrl>V'
        edit_toolbar.insert(self._paste_button, -1)
        self._paste_button.show()
        self._paste_button.connect('clicked', self._paste_cb)
        self._paste_button.set_sensitive(False)

        self._progress_toolbar = Gtk.Toolbar()
        self.progress_toolbar_button = ToolbarButton(
            page=self._progress_toolbar,
            label=_('Check progress'),
            icon_name='check-progress')
        self.progress_toolbar_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.progress_toolbar_button, -1)
        self._progress_toolbar.show()
        self.progress_toolbar_button.show()

        self._help_button = ToolButton('toolbar-help')
        self._help_button.set_tooltip(_('Help'))
        self._help_button.props.accelerator = '<Ctrl>H'
        self._toolbox.toolbar.insert(self._help_button, -1)
        self._help_button.show()
        self._help_button.connect('clicked', self._help_cb)
        self._help_button.set_sensitive(False)
        self._help_button.palette_invoker.props.lock_palette = True

        self.transfer_button = ToolButton('transfer')
        self.transfer_button.set_tooltip(_('Training data upload status'))
        self._toolbox.toolbar.insert(self.transfer_button, -1)
        self.transfer_button.connect('clicked', self._transfer_cb)
        self.transfer_button.hide()

        self.progress_label = Gtk.Label()
        self.progress_label.set_line_wrap(True)
        self.progress_label.set_size_request(300, -1)
        self.progress_label.set_use_markup(True)
        toolitem = Gtk.ToolItem()
        toolitem.add(self.progress_label)
        self.progress_label.show()
        self._toolbox.toolbar.insert(toolitem, -1)
        toolitem.show()

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

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        self._toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()

    def _build_progress_toolbar(self):
        self._progress_buttons = []
        progress = self._task_master.get_completed_sections()

        for section_index in range(self._task_master.get_number_of_sections()):
            icon = self._task_master.get_section_icon(section_index)
            if section_index in progress:
                icon = icon + '-white'
            else:
                icon = icon + '-grey'

            name = self._task_master.get_section_name(section_index)

            if section_index == 0:
                group = None
            else:
                group = self._progress_buttons[0]

            self._progress_buttons.append(RadioToolButton(group=group))
            self._progress_buttons[-1].set_icon_name(icon)
            self._progress_buttons[-1].set_tooltip(name)
            self._progress_toolbar.insert(self._progress_buttons[-1], -1)
            self._progress_buttons[-1].show()
            self._progress_buttons[-1].connect(
                'clicked', self._jump_to_section_cb, section_index)

        self._radio_buttons_live = False
        section_index, task_index = \
            self._task_master.get_section_and_task_index()
        self._progress_buttons[section_index].set_active(True)
        self._radio_buttons_live = True

    def _check_connected_task_status(self):
        ''' We only want to turn on notifications if we expect connectivity '''
        task = self._task_master.uid_to_task(GET_CONNECTED_TASK)
        self.set_notify_transfer_status(task.is_completed())

    def _update_completed_sections(self):
        progress = self._task_master.get_completed_sections()

        for section in range(self._task_master.get_number_of_sections()):
            icon = self._task_master.get_section_icon(section)
            if section in progress:
                icon = icon + '-white'
            else:
                icon = icon + '-grey'
            self._progress_buttons[section].set_icon_name(icon)

        self._radio_buttons_live = False
        section_index, task_index = \
            self._task_master.get_section_and_task_index()
        self._progress_buttons[section_index].set_active(True)
        self._radio_buttons_live = True

    def mark_section_as_complete(self, section):
        icon = self._task_master.get_section_icon(section) + '-white'
        self._progress_buttons[section].set_icon_name(icon)
        if section < self._task_master.get_number_of_sections() - 1:
            self._radio_buttons_live = False
            self._progress_buttons[section + 1].set_active(True)
            self._radio_buttons_live = True

    def set_notify_transfer_status(self, state):
        _logger.debug('Setting transfer status to %s' % (str(state)))
        self._notify_transfer_status = state

    def _update_transfer_button(self, icon_name, tooltip):
        self.transfer_button.set_icon_name(icon_name)
        self.transfer_button.set_tooltip(tooltip)
        if self._notify_transfer_status:
            self.transfer_button.show()
        else:
            self.transfer_button.hide()

    def _transfer_cb(self, button):
        ''' Hide the button to dismiss notification '''
        self.transfer_button.set_tooltip(_('Training data upload status'))
        self.transfer_button.hide()

    def __transfer_started_cb(self, widget):
        self._update_transfer_button('transfer', _('Data transfer started'))

    def __transfer_progressed_cb(self, widget):
        self._update_transfer_button('transfer',
                                     _('Data transfer progressing'))

    def __transfer_completed_cb(self, widget):
        self._update_transfer_button('transfer-complete',
                                     _('Data transfer completed'))

    def __transfer_failed_cb(self, widget):
        self._update_transfer_button('transfer-failed',
                                     _('Data transfer failed'))

    def __realize_cb(self, window):
        self.window_xid = window.get_window().get_xid()

    def set_copy_widget(self, webkit=None, text_entry=None):
        # Each task is responsible for setting a widget for copy
        if webkit is not None:
            self._webkit = webkit
        else:
            self._webkit = None
        if text_entry is not None:
            self._copy_entry = text_entry
        else:
            self._copy_entry = None

        self._copy_button.set_sensitive(webkit is not None or
                                        text_entry is not None)

    def _copy_cb(self, button):
        if self._copy_entry is not None:
            self._copy_entry.copy_clipboard()
        elif self._webkit is not None:
            self._webkit.copy_clipboard()
        else:
            _logger.debug('No widget set for copy.')

    def set_paste_widget(self, text_entry=None):
        # Each task is responsible for setting a widget for paste
        if text_entry is not None:
            self._paste_entry = text_entry
        self._paste_button.set_sensitive(text_entry is not None)

    def _paste_cb(self, button):
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        self.clipboard_text = clipboard.wait_for_text()
        if self._paste_entry is not None:
            self._paste_entry.paste_clipboard()
        else:
            _logger.debug('No widget set for paste (%s).' %
                          self.clipboard_text)

    def _fullscreen_cb(self, button):
        ''' Hide the Sugar toolbars. '''
        self.fullscreen()

    def _set_zoom_buttons_sensitivity(self):
        if self.font_size < len(FONT_SIZES) - 1:
            self._zoom_in.set_sensitive(True)
        else:
            self._zoom_in.set_sensitive(False)
        if self.font_size > 0:
            self._zoom_out.set_sensitive(True)
        else:
            self._zoom_out.set_sensitive(False)

        if hasattr(self, '_scrolled_window'):
            self._set_scroll_policy()

    def _set_scroll_policy(self):
        if Gdk.Screen.width() < Gdk.Screen.height() or self.zoom_level > 0.667:
            self._scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                             Gtk.PolicyType.AUTOMATIC)
        else:
            self._scrolled_window.set_policy(Gtk.PolicyType.NEVER,
                                             Gtk.PolicyType.AUTOMATIC)

    def _zoom_eq_cb(self, button):
        self.font_size = 8
        self.zoom_level = 0.667
        self._set_zoom_buttons_sensitivity()
        self._task_master.reload_graphics()

    def _zoom_in_cb(self, button):
        if self.font_size < len(FONT_SIZES) - 1:
            self.font_size += 1
            self.zoom_level *= 1.1
        self._set_zoom_buttons_sensitivity()
        self._task_master.reload_graphics()

    def _zoom_out_cb(self, button):
        if self.font_size > 0:
            self.font_size -= 1
            self.zoom_level /= 1.1
        self._set_zoom_buttons_sensitivity()
        self._task_master.reload_graphics()

    def _jump_to_section_cb(self, button, section_index):
        if self._radio_buttons_live:
            if self._task_master.requirements_are_met(section_index, 0):
                uid = self._task_master.section_and_task_to_uid(section_index)
                self._task_master.current_task = \
                    self._task_master.uid_to_task_number(uid)
                self._task_master.reload_graphics()
            else:
                section_index, task_index = \
                    self._task_master.get_section_and_task_index()
                self._progress_buttons[section_index].set_active(True)

    def _help_cb(self, button):
        # title, help_file = self._task_master.get_help_info()
        # _logger.debug('%s: %s' % (title, help_file))
        # if not hasattr(self, 'window_xid'):
        #    self.window_xid = self.get_window().get_xid()
        # if title is not None and help_file is not None:
        #     self.viewhelp = ViewHelp(title, help_file, self.window_xid)
        #     self.viewhelp.show()
        try:
            self._help_panel.set_connected(
                utils.nm_status() == 'network-wireless-connected')
        except Exception as e:
            _logger.error('Could not read NM status: %s' % (e))
            self._help_panel.set_connected(False)

        if self.help_palette:
            # FIXME: is_up() is always returning False, so we
            # "debounce" using help_panel_visible.
            if not self.help_palette.is_up() and not self.help_panel_visible:
                self.help_palette.popup(
                    immediate=True, state=self.help_palette.SECONDARY)
                self.help_panel_visible = True
            else:
                self.help_palette.popdown(immediate=True)
                self.help_panel_visible = False
                self._help_button.set_expanded(False)

    def add_badge(self, msg, icon="training-trophy", name="One Academy"):
        sugar_icons = os.path.join(os.path.expanduser('~'), '.icons')
        if not os.path.exists(sugar_icons):
            try:
                subprocess.call(['mkdir', sugar_icons])
            except OSError as e:
                _logger.error('Could not mkdir %s, %s' % (sugar_icons, e))

        badge = {
            'icon': icon,
            'from': name,
            'message': msg
        }

        # Use icons from html-content directory since default colors are
        # intended for white background.
        icon_dir = os.path.join(self.bundle_path, 'html-content', 'images')
        icon_path = os.path.join(icon_dir, icon + '.svg')
        try:
            subprocess.call(['cp', icon_path, sugar_icons])
        except OSError as e:
            _logger.error('Could not copy %s to %s, %s' %
                          (icon_path, sugar_icons, e))

        if 'comments' in self.metadata:
            comments = json.loads(self.metadata['comments'])
            comments.append(badge)
            self.metadata['comments'] = json.dumps(comments)
        else:
            self.metadata['comments'] = json.dumps([badge])

    def _load_extension(self):
        if not WEBSERVICES_AVAILABLE:
            _logger.error('Webservices not available on this version of Sugar')
            self._webservice_alert(_('Sugar upgrade required.'))
            return False

        extensions_path = os.path.join(os.path.expanduser('~'), '.sugar',
                                       'default', 'extensions')
        webservice_path = os.path.join(extensions_path, 'webservice')
        sugarservices_path = os.path.join(self.bundle_path, 'sugarservices')
        init_path = os.path.join(self.bundle_path, 'sugarservices',
                                 '__init__.py')

        if not os.path.exists(extensions_path):
            try:
                subprocess.call(['mkdir', extensions_path])
            except OSError as e:
                _logger.error('Could not mkdir %s, %s' % (extensions_path, e))
                self._webservice_alert(_('System error.'))
                return False

        if not os.path.exists(webservice_path):
            try:
                subprocess.call(['mkdir', webservice_path])
            except OSError as e:
                _logger.error('Could not mkdir %s, %s' % (webservice_path, e))
                self._webservice_alert(_('System error.'))
                return False
            try:
                subprocess.call(['cp', init_path, webservice_path])
            except OSError as e:
                _logger.error('Could not cp %s to %s, %s' %
                              (init_path, webservice_path, e))
                self._webservice_alert(_('System error.'))
                return False

        install = False
        if not os.path.exists(os.path.join(webservice_path, 'sugarservices')):
            _logger.error('SugarServices webservice not found. Installing...')
            install = True
        elif utils.get_sugarservices_version() < \
             _REQUIRED_SUGARSERVICES_VERSION:
            _logger.error('Found old SugarServices version. Installing...')
            install = True

        if install:
            try:
                subprocess.call(['cp', '-r', sugarservices_path,
                                 webservice_path])
            except OSError as e:
                _logger.error('Could not copy %s to %s, %s' %
                              (sugarservices_path, webservice_path, e))
                self._webservice_alert(_('System error.'))
                return False

            alert = ConfirmationAlert()
            alert.props.title = _('Restart required')
            alert.props.msg = _('We needed to install some software on your '
                                'system.\nSugar must be restarted before '
                                'sugarservices can commence.')

            alert.connect('response', self._reboot_alert_cb)
            self.add_alert(alert)
            self._load_intro_graphics(file_name='restart.html')

        return not install

    def _webservice_alert(self, message):
        alert = ConfirmationAlert()
        alert.props.title = message
        alert.props.msg = _('We are unable to install some software on your '
                            'system.\nSugar must be upgraded before this '
                            'activity can be run.')

        alert.connect('response', self._close_alert_cb)
        self.add_alert(alert)
        self._load_intro_graphics(message=message)

    def _remove_alert_cb(self, alert, response_id):
        self.remove_alert(alert)

    def _close_alert_cb(self, alert, response_id):
        self.remove_alert(alert)
        if response_id is Gtk.ResponseType.OK:
            self.close()

    def _reboot_alert_cb(self, alert, response_id):
        self.remove_alert(alert)
        if response_id is Gtk.ResponseType.OK:
            try:
                utils.reboot()
            except Exception as e:
                _logger.error('Cannot reboot: %s' % e)

    def _mount_added_cb(self, volume_monitor, device):
        _logger.error('mount added')
        if self.check_volume_data():
            _logger.debug('launching')
            self._launcher()

    def _mount_removed_cb(self, volume_monitor, device):
        _logger.error('mount removed')
        if self.check_volume_data():
            _logger.debug('launching')
            self._launcher()
Ejemplo n.º 39
0
class NapierActivity(activity.Activity):
    ''' Napier's bones: Napier's bones were invented by John Napier
    (1550-1617), a Scottish mathematician and scientist. They help you
    to do multiplication. '''

    # TODO: Define your own bone.

    def __init__(self, handle):
        ''' Initialize the toolbars and the work surface '''
        super(NapierActivity, self).__init__(handle)

        if os.path.exists(os.path.join('~', 'Activities', 'Napier.activity')):
            self._bone_path = os.path.join('~', 'Activities', 'Napier.activity',
                                      'bones')
        else:
            self._bone_path = os.path.join('.', 'bones')

        self._bones = []
        self._bone_images = [None, None, None, None, None, None, None, None,
                             None, None]
        self._blank_image = None
        self._number = 0
        self._number_of_bones = 0

        self._setup_toolbars()
        self._setup_canvas()
        self._circles = [None, None]
        self._ovals = []
        self._setup_workspace()
        self._restore()

    def _setup_canvas(self):
        ''' Create a canvas '''
        self._canvas = Gtk.DrawingArea()
        self._canvas.set_size_request(Gdk.Screen.width(),
                                      Gdk.Screen.height())
        self.set_canvas(self._canvas)
        self._canvas.show()
        self.show_all()

        self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
        self._canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
        self._canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
        self._canvas.connect("draw", self.__draw_cb)
        self._canvas.connect("motion-notify-event", self._mouse_move_cb)
        # self._canvas.connect("key_press_event", self._key_press_cb)

    def _setup_workspace(self):
        ''' Add the bones. '''
        self._width = Gdk.Screen.width()
        self._height = int(Gdk.Screen.height() - (GRID_CELL_SIZE * 2))
        self._scale = self._height * 1.0 / BONE_HEIGHT
        self._bone_width = int(BONE_WIDTH * self._scale)
        self._bone_height = int(BONE_HEIGHT * self._scale)

        # Generate the sprites we'll need...
        self._sprites = Sprites(self._canvas)
        self._bone_index = Sprite(self._sprites, 0, 0, _load_svg_from_file(
                os.path.join(self._bone_path, 'bones-index.svg'),
                self._bone_width, self._bone_height))
        self._max_bones = int(self._width / self._bone_width) - 1
        self._blank_image = _load_svg_from_file(
                os.path.join(self._bone_path, 'blank-bone.svg'),
                self._bone_width, self._bone_height)
        for bones in range(self._max_bones):
            self._bones.append(Sprite(self._sprites, bones * self._bone_width,
                                      0, self._blank_image))
        circle_image = _load_svg_from_file(
            os.path.join(self._bone_path, 'circle.svg'), int(self._scale * 45),
            int(self._scale * 45))
        self._circles[0] = Sprite(self._sprites, 0, -100, circle_image)
        self._circles[1] = Sprite(self._sprites, 0, -100, circle_image)
        oval_image = _load_svg_from_file(
            os.path.join(self._bone_path, 'oval.svg'), int(self._scale * 129),
            int(self._scale * 92))
        for bones in range(self._max_bones - 1):
            self._ovals.append(Sprite(self._sprites, 0, -100, oval_image))

    def _setup_toolbars(self):
        ''' Setup the toolbars. '''

        self.max_participants = 1  # no sharing

        toolbox = ToolbarBox()

        # Activity toolbar
        activity_button = ActivityToolbarButton(self)

        toolbox.toolbar.insert(activity_button, 0)
        activity_button.show()

        self._bones_toolbar = Gtk.Toolbar()
        self._bones_toolbar_button = ToolbarButton(label=_('Select a bone'),
                                                       page=self._bones_toolbar,
                                                       icon_name='bones')

        self._bones_toolbar_button.show()
        toolbox.toolbar.insert(self._bones_toolbar_button, -1)
        self.set_toolbar_box(toolbox)
        toolbox.show()
        self.toolbar = toolbox.toolbar


        self._new_calc_button = button_factory(
            'erase', self.toolbar, self._new_calc_cb, tooltip=_('Clear'))

        self._status = label_factory(self.toolbar, '')

        button_factory('number-0', self._bones_toolbar, self._number_cb,
                        cb_arg=0, tooltip=_('zero'))

        button_factory('number-1', self._bones_toolbar, self._number_cb,
                        cb_arg=1, tooltip=_('one'))

        button_factory('number-2', self._bones_toolbar, self._number_cb,
                        cb_arg=2, tooltip=_('two'))

        button_factory('number-3', self._bones_toolbar, self._number_cb,
                        cb_arg=3, tooltip=_('three'))

        button_factory('number-4', self._bones_toolbar, self._number_cb,
                        cb_arg=4, tooltip=_('four'))

        button_factory('number-5', self._bones_toolbar, self._number_cb,
                        cb_arg=5, tooltip=_('five'))

        button_factory('number-6', self._bones_toolbar, self._number_cb,
                        cb_arg=6, tooltip=_('six'))

        button_factory('number-7', self._bones_toolbar, self._number_cb,
                        cb_arg=7, tooltip=_('seven'))

        button_factory('number-8', self._bones_toolbar, self._number_cb,
                        cb_arg=8, tooltip=_('eight'))

        button_factory('number-9', self._bones_toolbar, self._number_cb,
                        cb_arg=9, tooltip=_('nine'))

        separator_factory(toolbox.toolbar, True, False)
        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()
        self._bones_toolbar_button.set_expanded(True)

    def _new_calc_cb(self, button=None):
        ''' Start a new calculation. '''
        for bone in range(self._max_bones):
            self._bones[bone].set_shape(self._blank_image)
            self._bones[bone].inval()
        self._number_of_bones = 0
        self._number = 0
        self._status.set_label('')
        return

    def _number_cb(self, button=None, value=0):
        ''' Try to add a digit. '''
        if self._number_of_bones == self._max_bones:
            return
        self._number_of_bones += 1
        if self._bone_images[value] is None:
            self._bone_images[value] = _svg_str_to_pixbuf(
                _bone_factory(value, scale=self._scale))
        self._bones[self._number_of_bones].set_shape(self._bone_images[value])
        self._bones[self._number_of_bones].inval()
        self._number = self._number * 10 + value

    def _mouse_move_cb(self, win, event):
        ''' Determine which row we are in and then calculate the product. '''
        win.grab_focus()
        x, y = map(int, event.get_coords())
        factor = int(y / self._bone_width)  # The row determines a factor

        if self._number == 0 or factor == 0:
            self._status.set_label('')
            self._circles[0].move((0, -100))
            self._circles[1].move((0, -100))
            for number in range(self._max_bones - 1):
                self._ovals[number].move((0, -100))
        else:
            c0dx = int(4 * self._scale)
            c0dy = int(12 * self._scale)
            c1dx = int(44 * self._scale)
            c1dy = int(47 * self._scale)
            odx = int(42 * self._scale)
            ody = int(2 * self._scale)
            self._circles[0].move((self._bone_width + c0dx,
                                   factor * self._bone_width + c0dy))
            self._circles[1].move((
                    self._number_of_bones * self._bone_width + c1dx,
                    factor * self._bone_width + c1dy))
            for number in range(self._number_of_bones - 1):
                self._ovals[number].move(((number + 1) * self._bone_width + odx,
                                          factor * self._bone_width + ody))
            self._status.set_label('%d × %d = %d' % (
                    factor + 1, self._number, (factor + 1) * self._number))
        return True

    def _key_press_cb(self, win, event):
        ''' TODO: Add bones by typing numbers '''
        return True

    def __draw_cb(self, canvas, cr):
        self._sprites.redraw_sprites(cr=cr)

    def do_expose_event(self, event):
        ''' Handle the expose-event by drawing '''
        # Restrict Cairo to the exposed area
        cr = self._canvas.window.cairo_create()
        cr.rectangle(event.area.x, event.area.y,
                event.area.width, event.area.height)
        cr.clip()
        # Refresh sprite list
        self._sprites.redraw_sprites(cr=cr)

    def _destroy_cb(self, win, event):
        Gtk.main_quit()

    def _restore(self):
        ''' Try to restore previous state. '''
        if 'number' in self.metadata and self.metadata['number'] != '0':
            for digit in range(len(self.metadata['number'])):
                self._number_cb(button=None,
                                value=int(self.metadata['number'][digit]))

    def write_file(self, file_path):
        ''' Write the status to the Journal. '''
        if not hasattr(self, '_number'):
            return
        self.metadata['number'] = str(self._number)
Ejemplo n.º 40
0
    def build_colors_toolbar(self, toolbox):

        colors_bar = Gtk.Toolbar()

        ########################################################################
        # Point color
        item = Gtk.ToolItem()
        label = Gtk.Label()
        label.set_text('%s ' % _('Points'))
        item.add(label)
        colors_bar.insert(item, -1)

        # select color
        item = Gtk.ToolItem()
        fill_color = ColorToolButton()
        fill_color.connect('notify::color', self.color_point_change)
        item.add(fill_color)
        colors_bar.insert(item, -1)

        # Separator
        separator = Gtk.SeparatorToolItem()
        colors_bar.insert(separator, -1)
        separator.show()

        ########################################################################
        # Back color
        item = Gtk.ToolItem()
        label = Gtk.Label()
        label.set_text('%s ' % _('Background'))
        item.add(label)
        colors_bar.insert(item, -1)

        # select color
        item = Gtk.ToolItem()
        _fill_color = ColorToolButton()
        c = Gdk.Color(red=21588, green=47546, blue=18504)
        _fill_color.set_color(c)
        _fill_color.connect('notify::color', self.color_back_change)
        item.add(_fill_color)
        colors_bar.insert(item, -1)

        # Separator
        separator = Gtk.SeparatorToolItem()
        colors_bar.insert(separator, -1)
        separator.show()

        ########################################################################
        # Line color
        item = Gtk.ToolItem()
        label = Gtk.Label()
        label.set_text('%s ' % _('Lines'))
        item.add(label)
        colors_bar.insert(item, -1)

        # select color
        item = Gtk.ToolItem()
        _fill_color = ColorToolButton()
        _fill_color.connect('notify::color', self.color_line_change)
        item.add(_fill_color)
        colors_bar.insert(item, -1)

        # Separator
        separator = Gtk.SeparatorToolItem()
        colors_bar.insert(separator, -1)
        separator.show()

        ########################################################################
        # Owner color
        item = Gtk.ToolItem()
        label = Gtk.Label()
        label.set_text('%s ' % _('Owner'))
        item.add(label)
        colors_bar.insert(item, -1)

        # select color
        item = Gtk.ToolItem()
        _fill_color = ColorToolButton()
        c = Gdk.Color(red=65535, green=0, blue=0)
        _fill_color.set_color(c)
        _fill_color.connect('notify::color', self.color_owner_change)
        item.add(_fill_color)
        colors_bar.insert(item, -1)

        colors_bar.show_all()
        colors_button = ToolbarButton(label=_('Colors'),
                page=colors_bar,
                icon_name='toolbar-colors')
        toolbox.toolbar.insert(colors_button, -1)
        colors_button.show()
Ejemplo n.º 41
0
class RulerActivity(activity.Activity):

    def __init__(self, handle):
        super(RulerActivity, self).__init__(handle)

        self.button_dict = {}
        self.callback_dict = {}
        self._ready = False

        font = 'helvetica 12'
        font_bold = 'helvetica bold 12'

        #
        # We need a canvas
        #
        self._canvas = MyCanvas()
        self.set_canvas(self._canvas)
        self._canvas.show()

        screen = GdkX11.X11Screen()
        width = screen.width()
        height = screen.height() - GRID_CELL_SIZE

        dpi, self.known_dpi = calc_dpi()
        self._canvas.set_dpi(dpi)

        # Create instances of our graphics
        self._r = show_rulers.ScreenOfRulers(font, font_bold, width, height)
        self._gcm = show_grids.ScreenGrid_cm(font, font_bold, width, height)
        self._gmm = show_grids.ScreenGrid_mm(font, font_bold, width, height)
        self._a90 = show_angles.Angles90(font, font_bold, width, height)
        self._a360 = show_angles.Angles360(font, font_bold, width, height)
        self._c = show_checkers.ScreenOfCircles(font, font_bold, width, height)

        # start with a ruler
        self._current = self._r
        self._canvas.add_a_ruler(self._current)

        # other settings
        self._grids_mode = "cm"
        self._angles_mode = "90"

        #
        # We need some toolbars
        #
        self.max_participants = 1

        toolbar_box = ToolbarBox()

        # Buttons added to the Activity toolbar
        activity_button = ActivityToolbarButton(self)
        toolbar_box.toolbar.insert(activity_button, 0)
        activity_button.show()

        self.rulers = radio_factory('ruler',
                                    toolbar_box.toolbar,
                                    self._rulers_cb,
                                    tooltip=_('Ruler'),
                                    group=None)

        self.grids = radio_factory('grid-a',
                                    toolbar_box.toolbar,
                                    self._grids_cb,
                                    tooltip=_('Grid'),
                                    group=self.rulers)

        self.angles = radio_factory('angles-90',
                                    toolbar_box.toolbar,
                                    self._angles_cb,
                                    tooltip=_('Angles'),
                                    group=self.rulers)

        self.checker = radio_factory('checker',
                                    toolbar_box.toolbar,
                                    self._checker_cb,
                                    tooltip=_('Checker'),
                                    group=self.rulers)

        self.wrapper = Gtk.ToolItem()
        self.wrapper2 = Gtk.ToolItem()
        self.wrapper3 = Gtk.ToolItem()
        self.custom_unit_entry = Gtk.Entry()
        self.txt1 = Gtk.Label()
        self.txt1.set_text(_('1 custom unit equals '))
        self.txt2 = Gtk.Label()
        # TRANS: mm is for Milli Meters
        self.txt2.set_text(_(' mm.'))
        self.wrapper.add(self.txt1)
        self.wrapper2.add(self.custom_unit_entry)
        self.wrapper3.add(self.txt2)
        self.wrapper.show_all()
        self.wrapper2.show_all()
        self.wrapper3.show_all()
        separator = Gtk.SeparatorToolItem()
        separator.props.draw = True
        separator.set_expand(False)
        separator.show()
        toolbar_box.toolbar.insert(separator, -1)
        custom_units_toolbox = ToolbarBox()
        custom_units_toolbox.toolbar.insert(self.wrapper, -1)
        custom_units_toolbox.toolbar.insert(self.wrapper2, -1)
        custom_units_toolbox.toolbar.insert(self.wrapper3, -1)
        custom_units_toolbox.show()
        self.custom_units_button = ToolbarButton(icon_name='view-source',
                                                 page=custom_units_toolbox)
        toolbar_box.toolbar.insert(self.custom_units_button, -1)
        self.custom_unit_entry.connect('changed', self.custom_unit_change_cb)
        self.custom_units_button.show()

        if not self.known_dpi:
            separator = Gtk.SeparatorToolItem()
            separator.show()
            toolbar_box.toolbar.insert(separator, -1)
            dpi = self._canvas.get_dpi()
            self._dpi_spin_adj = Gtk.Adjustment(dpi, 72, 200, 2, 32, 0)
            self._dpi_spin = Gtk.SpinButton(self._dpi_spin_adj, 0, 0)
            self._dpi_spin_id = self._dpi_spin.connect('value-changed',
                                                       self._dpi_spin_cb)
            self._dpi_spin.set_numeric(True)
            self._dpi_spin.show()
            self.tool_item_dpi = Gtk.ToolItem()
            self.tool_item_dpi.add(self._dpi_spin)
            toolbar_box.toolbar.insert(self.tool_item_dpi, -1)
            self.tool_item_dpi.show()

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

        # The ever-present Stop Button
        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>Q'
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()

        self.show_all()

        # Restore state if previously saved
        self._ready = True
        if 'ruler' in self.metadata and \
           self.metadata['ruler'] in self.button_dict:
            _logger.debug('restoring %s', self.metadata['ruler'])
            self.button_dict[self.metadata['ruler']].set_active(True)
            self.callback_dict[self.metadata['ruler']]
        else:
            self._rulers_cb()
            self.rulers.set_active(True)

        if 'custom_unit' in self.metadata:
            self.custom_unit_entry.set_text(str(self.metadata['custom_unit']))
        else: # set the default
            self.custom_unit_entry.set_text("25.4")

    #
    # Button callbacks
    #
    def _rulers_cb(self, button=None):
        if self._ready:
            self.custom_units_button.set_sensitive(True)
            self._current = self._r
            self._canvas.add_a_ruler(self._current)
            _logger.debug('selecting ruler')
            self.metadata['ruler'] = 'ruler'
        return False

    def custom_unit_change_cb(self, widget):
        try:
            new = float(widget.get_text())
        except ValueError:
            new = MMPERINCH
        new = abs(new)
        if new == 0:
            new = MMPERINCH
            if widget.get_text != '':
                widget.set_text(str(new))
        self._canvas.add_a_ruler(self._r)
        self._r.custom_unit_in_mm = new
        self._r.draw_custom_ruler(self._r.custom_unit_in_mm)
        self.metadata['custom_unit'] = new

    def _grids_cb(self, button=None):
        if self._ready:
            self.custom_units_button.set_sensitive(False)
            self.custom_units_button.set_expanded(False)
            if self._grids_mode == "cm":
                self._current = self._gcm
                if hasattr(self, 'grids'):
                    self.grids.set_icon_name("grid-c")
                self._grids_mode = "mm"
            else:
                self._current = self._gmm
                if hasattr(self, 'grids'):
                    self.grids.set_icon_name("grid-a")
                self._grids_mode = "cm"
            self._canvas.add_a_ruler(self._current)
            _logger.debug('selecting grids')
            self.metadata['ruler'] = 'grids'
        return False

    def _angles_cb(self, button=None):
        if self._ready:
            self.custom_units_button.set_sensitive(False)
            self.custom_units_button.set_expanded(False)
            if self._angles_mode == "90":
                self._current = self._a90
                if hasattr(self, 'angles'):
                    self.angles.set_icon_name("angles-360")
                    self._angles_mode = "360"
            else:
                self._current = self._a360
                if hasattr(self, 'angles'):
                    self.angles.set_icon_name("angles-90")
                    self._angles_mode = "90"
            self._canvas.add_a_ruler(self._current)
            _logger.debug('selecting angles')
            self.metadata['ruler'] = 'angles'
        return False

    def _checker_cb(self, button=None):
        if self._ready:
            self.custom_units_button.set_sensitive(False)
            self.custom_units_button.set_expanded(False)
            self._current = self._c
            self._canvas.add_a_ruler(self._current)
            _logger.debug('selecting checker')
            self.metadata['ruler'] = 'checker'
        return False

    def _dpi_spin_cb(self, button):
        self._canvas.set_dpi(self._dpi_spin.get_value_as_int())
        self._canvas.add_a_ruler(self._current)
        return

    def write_file(self, file_path):
        ''' Write the dpi to the Journal '''
        dpi = self._canvas.get_dpi()
        _logger.debug("Write dpi: " + str(dpi))
        self.metadata['dpi'] = str(dpi)
Ejemplo n.º 42
0
    def __init__(self, handle):
        "The entry point to the Activity"
        global page
        activity.Activity.__init__(self, handle)

        toolbar_box = ToolbarBox()

        activity_button = CustomActivityToolbarButton(self)
        toolbar_box.toolbar.insert(activity_button, 0)
        activity_button.show()

        self.edit_toolbar = EditToolbar()
        self.edit_toolbar.undo.props.visible = False
        self.edit_toolbar.redo.props.visible = False
        self.edit_toolbar.separator.props.visible = False
        self.edit_toolbar.copy.set_sensitive(False)
        self.edit_toolbar.copy.connect('clicked', self.edit_toolbar_copy_cb)
        self.edit_toolbar.paste.props.visible = False
        edit_toolbar_button = ToolbarButton(
            page=self.edit_toolbar,
            icon_name='toolbar-edit')
        self.edit_toolbar.show()
        toolbar_box.toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        view_toolbar = ViewToolbar()
        view_toolbar.connect('go-fullscreen',
                self.view_toolbar_go_fullscreen_cb)
        view_toolbar.zoom_in.connect('clicked', self.zoom_in_cb)
        view_toolbar.zoom_out.connect('clicked', self.zoom_out_cb)
        view_toolbar.show()
        view_toolbar_button = ToolbarButton(
            page=view_toolbar,
            icon_name='toolbar-view')
        toolbar_box.toolbar.insert(view_toolbar_button, -1)
        view_toolbar_button.show()

        self.back = ToolButton('go-previous')
        self.back.set_tooltip(_('Back'))
        self.back.props.sensitive = False
        self.back.connect('clicked', self.go_back_cb)
        toolbar_box.toolbar.insert(self.back, -1)
        self.back.show()

        self.forward = ToolButton('go-next')
        self.forward.set_tooltip(_('Forward'))
        self.forward.props.sensitive = False
        self.forward.connect('clicked', self.go_forward_cb)
        toolbar_box.toolbar.insert(self.forward, -1)
        self.forward.show()

        num_page_item = Gtk.ToolItem()
        self.num_page_entry = Gtk.Entry()
        self.num_page_entry.set_text('0')
        self.num_page_entry.set_alignment(1)
        self.num_page_entry.connect('insert-text',
                               self.num_page_entry_insert_text_cb)
        self.num_page_entry.connect('activate',
                               self.num_page_entry_activate_cb)
        self.num_page_entry.set_width_chars(4)
        num_page_item.add(self.num_page_entry)
        self.num_page_entry.show()
        toolbar_box.toolbar.insert(num_page_item, -1)
        num_page_item.show()

        total_page_item = Gtk.ToolItem()
        self.total_page_label = Gtk.Label()

        self.total_page_label.set_markup("<span foreground='#FFF'" \
                                         " size='14000'></span>")

        self.total_page_label.set_text(' / 0')
        total_page_item.add(self.total_page_label)
        self.total_page_label.show()
        toolbar_box.toolbar.insert(total_page_item, -1)
        total_page_item.show()

        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()

        self.scrolled_window = Gtk.ScrolledWindow()
        self.scrolled_window.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_left_margin(50)
        self.textview.connect("key_press_event", self.keypress_cb)

        self.scrolled_window.add(self.textview)
        self.set_canvas(self.scrolled_window)
        self.textview.show()
        self.scrolled_window.show()
        page = 0
        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        self.textview.grab_focus()
        self.font_desc = Pango.FontDescription("sans %d" % style.zoom(10))
        self.textview.modify_font(self.font_desc)

        buffer = self.textview.get_buffer()
        self.markset_id = buffer.connect("mark-set", 
            self.mark_set_cb)
Ejemplo n.º 43
0
    def __init__(self, handle):
        activity.Activity.__init__(self, handle)

        # HACK to avoid Escape key disable fullscreen mode on Terminal Activity
        # This is related with http://bugs.sugarlabs.org/ticket/440
        self.disconnect_by_func(self._Window__key_press_cb)
        self.connect('key-press-event', self.__key_press_cb)

        self.max_participants = 1

        toolbar_box = ToolbarBox()

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

        edit_toolbar = self._create_edit_toolbar()
        edit_toolbar_button = ToolbarButton(
                page=edit_toolbar,
                icon_name='toolbar-edit')
        edit_toolbar.show()
        toolbar_box.toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        view_toolbar = self._create_view_toolbar()
        view_toolbar_button = ToolbarButton(
                page=view_toolbar,
                icon_name='toolbar-view')
        view_toolbar.show()
        toolbar_box.toolbar.insert(view_toolbar_button, -1)
        view_toolbar_button.show()

        self._delete_tab_toolbar = None
        self._previous_tab_toolbar = None
        self._next_tab_toolbar = None

        helpbutton = self._create_help_button()
        toolbar_box.toolbar.insert(helpbutton, -1)
        helpbutton.show_all()

        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()

        self._notebook = BrowserNotebook()
        self._notebook.connect("tab-added", self.__open_tab_cb)
        self._notebook.set_property("tab-pos", Gtk.PositionType.TOP)
        self._notebook.set_scrollable(True)
        self._notebook.show()

        self.set_canvas(self._notebook)

        self._create_tab(None)
Ejemplo n.º 44
0
class AbacusActivity(activity.Activity):

    def __init__(self, handle):
        ''' Initiate activity. '''
        super(AbacusActivity, self).__init__(handle)

        self._setting_up = True
        self.bead_colors = profile.get_color().to_string().split(',')

        # no sharing
        self.max_participants = 1

        self.sep = []
        self.abacus_toolbar = Gtk.Toolbar()
        custom_toolbar = Gtk.Toolbar()
        edit_toolbar = Gtk.Toolbar()

        toolbox = ToolbarBox()

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

        edit_toolbar_button = ToolbarButton(label=_('Edit'),
                                            page=edit_toolbar,
                                            icon_name='toolbar-edit')
        edit_toolbar_button.show()
        toolbox.toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        self.abacus_toolbar_button = ToolbarButton(
            page=self.abacus_toolbar,
            icon_name='abacus-list')
        self.abacus_toolbar.show()
        toolbox.toolbar.insert(self.abacus_toolbar_button, -1)
        self.abacus_toolbar_button.show()

        self.custom_toolbar_button = ToolbarButton(
            page=custom_toolbar,
            icon_name='view-source')
        custom_toolbar.show()
        toolbox.toolbar.insert(self.custom_toolbar_button, -1)
        self.custom_toolbar_button.show()

        separator_factory(toolbox.toolbar, False, True)

        button_factory('edit-delete', toolbox.toolbar,
                       self._reset_cb, tooltip=_('Reset'))

        separator_factory(toolbox.toolbar, False, True)

        self._label = label_factory(NAMES['suanpan'], toolbox.toolbar)

        separator_factory(toolbox.toolbar, True, False)

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

        self.set_toolbar_box(toolbox)
        toolbox.show()

        self.abacus_buttons = {}

        # Traditional
        self._add_abacus_button('decimal', None)
        self._add_abacus_button('soroban', self.abacus_buttons['decimal'])
        self._add_abacus_button('suanpan', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Bases other than 10
        self._add_abacus_button('nepohualtzintzin',
                                self.abacus_buttons['decimal'])
        self._add_abacus_button('hexadecimal', self.abacus_buttons['decimal'])
        self._add_abacus_button('binary', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Fractions
        self._add_abacus_button('schety', self.abacus_buttons['decimal'])
        # self._add_abacus_button('fraction', self.abacus_buttons['decimal'])
        self._add_abacus_button('caacupe', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Non-traditional
        self._add_abacus_button('cuisenaire', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Custom
        self._add_abacus_button('custom', self.abacus_buttons['decimal'])

        preferences_button = ToolButton('preferences-system')
        preferences_button.set_tooltip(_('Custom'))
        custom_toolbar.insert(preferences_button, -1)
        preferences_button.palette_invoker.props.toggle_palette = True
        preferences_button.palette_invoker.props.lock_palette = True
        preferences_button.props.hide_tooltip_on_click = False
        preferences_button.show()

        self._palette = preferences_button.get_palette()
        button_box = Gtk.VBox()
        # TRANS: Number of rods on the abacus
        self._rods_spin = add_spinner_and_label(
            15, 1, MAX_RODS, _('Rods:'), self._rods_spin_cb, button_box)
        # TRANS: Number of beads in the top section of the abacus
        self._top_spin = add_spinner_and_label(
            2, 0, MAX_TOP, _('Top:'), self._top_spin_cb, button_box)
        # TRANS: Number of beads in the bottom section of the abacus
        self._bottom_spin = add_spinner_and_label(
            5, 0, MAX_BOT, _('Bottom:'), self._bottom_spin_cb, button_box)
        # TRANS: Scale factor between bottom and top beads
        self._value_spin = add_spinner_and_label(
            5, 1, MAX_BOT + 1, _('Factor:'), self._value_spin_cb, button_box)
        # TRANS: Scale factor between rods
        self._base_spin = add_spinner_and_label(
            10, 1, (MAX_TOP + 1) * MAX_BOT, _('Base:'), self._base_spin_cb,
            button_box)
        hbox = Gtk.HBox()
        hbox.pack_start(button_box, True, True, style.DEFAULT_SPACING)
        hbox.show_all()
        self._palette.set_content(hbox)

        separator_factory(custom_toolbar, False, False)

        self.custom_maker = button_factory('new-abacus', custom_toolbar,
                                           self._custom_cb,
                                           tooltip=_('Custom'))

        button_factory('edit-copy', edit_toolbar, self._copy_cb,
                       tooltip=_('Copy'), accelerator='<Ctrl>c')
        button_factory('edit-paste', edit_toolbar, self._paste_cb,
                       tooltip=_('Paste'), accelerator='<Ctrl>v')

        # Create a canvas
        canvas = Gtk.DrawingArea()
        canvas.set_size_request(Gdk.Screen.width(),
                                Gdk.Screen.height())
        self.set_canvas(canvas)
        canvas.show()
        self.show_all()

        # Initialize the canvas
        self.abacus = Abacus(canvas, self)

        self._setting_up = False

        # Read the current mode from the Journal
        if 'rods' in self.metadata:
            self._rods_spin.set_value(int(self.metadata['rods']))
        if 'top' in self.metadata:
            self._top_spin.set_value(int(self.metadata['top']))
        if 'bottom' in self.metadata:
            self._bottom_spin.set_value(int(self.metadata['bottom']))
        if 'factor' in self.metadata:
            self._value_spin.set_value(int(self.metadata['factor']))
        if 'base' in self.metadata:
            self._base_spin.set_value(int(self.metadata['base']))
        if 'abacus' in self.metadata:
            if self.metadata['abacus'] in self.abacus_buttons:
                _logger.debug('restoring %s', self.metadata['abacus'])
                if self.metadata['abacus'] == 'custom':
                    self._custom_cb()
                self.abacus_buttons[self.metadata['abacus']].set_active(True)
            else:  # Default is Chinese
                self.abacus_buttons['suanpan'].set_active(True)

            if 'value' in self.metadata:
                _logger.debug('restoring value %s', self.metadata['value'])
                self.abacus.mode.set_value(self.metadata['value'])
                self.abacus.mode.label(self.abacus.generate_label())

        self.abacus.init()

        # Start with abacus toolbar expanded and suanpan as default
        self.abacus_toolbar_button.set_expanded(True)

    def _add_abacus_button(self, name, group):
        self.abacus_buttons[name] = radio_factory(
            name,
            self.abacus_toolbar,
            self._radio_cb,
            cb_arg=name,
            tooltip=NAMES[name],
            group=group)

    def _radio_cb(self, button, abacus):
        self._select_abacus(abacus)

    def _reset_cb(self, button=None):
        self.abacus.mode.reset_abacus()
        self.abacus.mode.label(self.abacus.generate_label())

    def _notify_new_abacus(self, prompt):
        ''' Loading a new abacus can be slooow, so alert the user. '''
        # a busy cursor is adequate
        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))

    def _select_abacus(self, abacus):
        ''' Notify the user of an expected delay and then... '''
        if not hasattr(self, 'abacus') or self._setting_up:
            _logger.debug('setting up')
            return
        # Not selected?
        if not self.abacus_buttons[abacus].get_active():
            _logger.debug('%s not active' % abacus)
            return

        self._notify_new_abacus(NAMES[abacus])
        # Give the cursor/alert time to load
        GObject.idle_add(self._switch_modes, abacus)

    def _switch_modes(self, abacus):
        ''' Display the selected abacus '''
        _logger.debug('switching modes to %s', abacus)
        if abacus == self.abacus.mode.name:
            _logger.debug('do not switch already in the same mode')
            self.get_window().set_cursor(None)
            return
        # Save current value
        value = int(float(self.abacus.mode.value()))
        if abacus == 'custom' and self.abacus.custom is None:
            self.custom_toolbar_button.set_expanded(True)
            # self.abacus.mode = self.abacus.custom
            self.get_window().set_cursor(None)
        else:
            _logger.debug('switch_mode: setting abacus to %s' % abacus)
            self.abacus.select_abacus(abacus)
            # Load saved value
            self.abacus.mode.set_value_from_number(value)
            self.abacus.mode.label(self.abacus.generate_label())
            self._label.set_text(NAMES[abacus])
            self.get_window().set_cursor(None)

    def _rods_spin_cb(self, button=None):
        return

    def _top_spin_cb(self, button=None):
        return

    def _bottom_spin_cb(self, button=None):
        return

    def _value_spin_cb(self, button=None):
        return

    def _base_spin_cb(self, button=None):
        return

    def _custom_cb(self, button=None):
        ''' Display the custom abacus; hide the others '''
        value = float(self.abacus.mode.value(count_beads=False))
        self.abacus.mode.hide()
        if self.abacus.custom is not None:
            self.abacus.custom.hide()
        self.abacus.custom = Custom(self.abacus, self.abacus.bead_colors)
        self.abacus.custom.set_custom_parameters(
            rods=self._rods_spin.get_value_as_int(),
            top=self._top_spin.get_value_as_int(),
            bot=self._bottom_spin.get_value_as_int(),
            factor=self._value_spin.get_value_as_int(),
            base=self._base_spin.get_value_as_int())
        self.abacus.custom.create()
        self.abacus.custom.draw_rods_and_beads()
        self.abacus.custom.show()
        self._label.set_text(NAMES['custom'])
        self.abacus.mode = self.abacus.custom
        self.abacus.mode_dict['custom'][0] = self.abacus.custom
        self.abacus_toolbar_button.set_expanded(True)
        self.abacus.mode.set_value_from_number(value)

    def _copy_cb(self, arg=None):
        ''' Copy a number to the clipboard from the active abacus. '''
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        text = self.abacus.generate_label(sum_only=True)
        if text is not None:
            clipboard.set_text(text, -1)
        return

    def _paste_cb(self, arg=None):
        ''' Paste a number from the clipboard to the active abacus. '''
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        text = clipboard.wait_for_text()
        if text is not None:
            try:
                self.abacus.mode.set_value_from_number(float(text))
            except ValueError, e:
                _logger.debug(str(e))
                return
            self.abacus.mode.label(self.abacus.generate_label())
        return
Ejemplo n.º 45
0
    def __init__(self, handle):
        ''' Initiate activity. '''
        super(AbacusActivity, self).__init__(handle)

        self._setting_up = True
        self.bead_colors = profile.get_color().to_string().split(',')

        # no sharing
        self.max_participants = 1

        self.sep = []
        self.abacus_toolbar = Gtk.Toolbar()
        custom_toolbar = Gtk.Toolbar()
        edit_toolbar = Gtk.Toolbar()

        toolbox = ToolbarBox()

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

        edit_toolbar_button = ToolbarButton(label=_('Edit'),
                                            page=edit_toolbar,
                                            icon_name='toolbar-edit')
        edit_toolbar_button.show()
        toolbox.toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        self.abacus_toolbar_button = ToolbarButton(
            page=self.abacus_toolbar,
            icon_name='abacus-list')
        self.abacus_toolbar.show()
        toolbox.toolbar.insert(self.abacus_toolbar_button, -1)
        self.abacus_toolbar_button.show()

        self.custom_toolbar_button = ToolbarButton(
            page=custom_toolbar,
            icon_name='view-source')
        custom_toolbar.show()
        toolbox.toolbar.insert(self.custom_toolbar_button, -1)
        self.custom_toolbar_button.show()

        separator_factory(toolbox.toolbar, False, True)

        button_factory('edit-delete', toolbox.toolbar,
                       self._reset_cb, tooltip=_('Reset'))

        separator_factory(toolbox.toolbar, False, True)

        self._label = label_factory(NAMES['suanpan'], toolbox.toolbar)

        separator_factory(toolbox.toolbar, True, False)

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

        self.set_toolbar_box(toolbox)
        toolbox.show()

        self.abacus_buttons = {}

        # Traditional
        self._add_abacus_button('decimal', None)
        self._add_abacus_button('soroban', self.abacus_buttons['decimal'])
        self._add_abacus_button('suanpan', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Bases other than 10
        self._add_abacus_button('nepohualtzintzin',
                                self.abacus_buttons['decimal'])
        self._add_abacus_button('hexadecimal', self.abacus_buttons['decimal'])
        self._add_abacus_button('binary', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Fractions
        self._add_abacus_button('schety', self.abacus_buttons['decimal'])
        # self._add_abacus_button('fraction', self.abacus_buttons['decimal'])
        self._add_abacus_button('caacupe', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Non-traditional
        self._add_abacus_button('cuisenaire', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Custom
        self._add_abacus_button('custom', self.abacus_buttons['decimal'])

        preferences_button = ToolButton('preferences-system')
        preferences_button.set_tooltip(_('Custom'))
        custom_toolbar.insert(preferences_button, -1)
        preferences_button.palette_invoker.props.toggle_palette = True
        preferences_button.palette_invoker.props.lock_palette = True
        preferences_button.props.hide_tooltip_on_click = False
        preferences_button.show()

        self._palette = preferences_button.get_palette()
        button_box = Gtk.VBox()
        # TRANS: Number of rods on the abacus
        self._rods_spin = add_spinner_and_label(
            15, 1, MAX_RODS, _('Rods:'), self._rods_spin_cb, button_box)
        # TRANS: Number of beads in the top section of the abacus
        self._top_spin = add_spinner_and_label(
            2, 0, MAX_TOP, _('Top:'), self._top_spin_cb, button_box)
        # TRANS: Number of beads in the bottom section of the abacus
        self._bottom_spin = add_spinner_and_label(
            5, 0, MAX_BOT, _('Bottom:'), self._bottom_spin_cb, button_box)
        # TRANS: Scale factor between bottom and top beads
        self._value_spin = add_spinner_and_label(
            5, 1, MAX_BOT + 1, _('Factor:'), self._value_spin_cb, button_box)
        # TRANS: Scale factor between rods
        self._base_spin = add_spinner_and_label(
            10, 1, (MAX_TOP + 1) * MAX_BOT, _('Base:'), self._base_spin_cb,
            button_box)
        hbox = Gtk.HBox()
        hbox.pack_start(button_box, True, True, style.DEFAULT_SPACING)
        hbox.show_all()
        self._palette.set_content(hbox)

        separator_factory(custom_toolbar, False, False)

        self.custom_maker = button_factory('new-abacus', custom_toolbar,
                                           self._custom_cb,
                                           tooltip=_('Custom'))

        button_factory('edit-copy', edit_toolbar, self._copy_cb,
                       tooltip=_('Copy'), accelerator='<Ctrl>c')
        button_factory('edit-paste', edit_toolbar, self._paste_cb,
                       tooltip=_('Paste'), accelerator='<Ctrl>v')

        # Create a canvas
        canvas = Gtk.DrawingArea()
        canvas.set_size_request(Gdk.Screen.width(),
                                Gdk.Screen.height())
        self.set_canvas(canvas)
        canvas.show()
        self.show_all()

        # Initialize the canvas
        self.abacus = Abacus(canvas, self)

        self._setting_up = False

        # Read the current mode from the Journal
        if 'rods' in self.metadata:
            self._rods_spin.set_value(int(self.metadata['rods']))
        if 'top' in self.metadata:
            self._top_spin.set_value(int(self.metadata['top']))
        if 'bottom' in self.metadata:
            self._bottom_spin.set_value(int(self.metadata['bottom']))
        if 'factor' in self.metadata:
            self._value_spin.set_value(int(self.metadata['factor']))
        if 'base' in self.metadata:
            self._base_spin.set_value(int(self.metadata['base']))
        if 'abacus' in self.metadata:
            if self.metadata['abacus'] in self.abacus_buttons:
                _logger.debug('restoring %s', self.metadata['abacus'])
                if self.metadata['abacus'] == 'custom':
                    self._custom_cb()
                self.abacus_buttons[self.metadata['abacus']].set_active(True)
            else:  # Default is Chinese
                self.abacus_buttons['suanpan'].set_active(True)

            if 'value' in self.metadata:
                _logger.debug('restoring value %s', self.metadata['value'])
                self.abacus.mode.set_value(self.metadata['value'])
                self.abacus.mode.label(self.abacus.generate_label())

        self.abacus.init()

        # Start with abacus toolbar expanded and suanpan as default
        self.abacus_toolbar_button.set_expanded(True)
Ejemplo n.º 46
0
    def build_calibrate_toolbar(self, toolbox):

        calibrate_bar = Gtk.Toolbar()

        item1 = Gtk.ToolItem()
        label1 = Gtk.Label()
        label1.set_text(' ' + _('Calibrate/Follow') + ' ')
        item1.add(label1)
        calibrate_bar.insert(item1, -1)

        stop_calibrate = ToolButton('media-playback-stop')
        stop_calibrate.set_tooltip(_('Stop'))
        stop_calibrate.set_accelerator('<ctrl>space')
        stop_calibrate.connect('clicked', self.stop_execute)
        calibrate_bar.insert(stop_calibrate, -1)

        separator1 = Gtk.SeparatorToolItem()
        separator1.props.draw = True
        calibrate_bar.insert(separator1, -1)

        item3 = Gtk.ToolItem()
        self.label_color_red = Gtk.Label()
        self.label_color_red.set_text(' ' + _('Calibrated color:') + ' ' +
                                      _('Red') + ' ')
        item3.add(self.label_color_red)
        calibrate_bar.insert(item3, -1)

        item4 = Gtk.ToolItem()
        self.red_spin = Gtk.SpinButton()
        self.red_spin.set_range(0, 255)
        self.red_spin.set_increments(1, 10)
        self.red_spin.props.value = self.colorC[0]
        self.red_spin.connect('notify::value', self.red_spin_color)
        item4.add(self.red_spin)
        calibrate_bar.insert(item4, -1)

        item5 = Gtk.ToolItem()
        self.label_color_green = Gtk.Label()
        self.label_color_green.set_text(' ' + _('Green') + ' ')
        item5.add(self.label_color_green)
        calibrate_bar.insert(item5, -1)

        item6 = Gtk.ToolItem()
        self.green_spin = Gtk.SpinButton()
        self.green_spin.set_range(0, 255)
        self.green_spin.set_increments(1, 10)
        self.green_spin.props.value = self.colorC[1]
        self.green_spin.connect('notify::value', self.green_spin_color)
        item6.add(self.green_spin)
        calibrate_bar.insert(item6, -1)

        item7 = Gtk.ToolItem()
        self.label_color_blue = Gtk.Label()
        self.label_color_blue.set_text(' ' + _('Blue') + ' ')
        item7.add(self.label_color_blue)
        calibrate_bar.insert(item7, -1)

        item8 = Gtk.ToolItem()
        self.blue_spin = Gtk.SpinButton()
        self.blue_spin.set_range(0, 255)
        self.blue_spin.set_increments(1, 10)
        self.blue_spin.props.value = self.colorC[2]
        self.blue_spin.connect('notify::value', self.blue_spin_color)
        item8.add(self.blue_spin)
        calibrate_bar.insert(item8, -1)

        calibrate_bar.show_all()
        calibrate_button = ToolbarButton(label=_('Calibrate'),
                                         page=calibrate_bar,
                                         icon_name='preferences-system')
        toolbox.toolbar.insert(calibrate_button, -1)
        calibrate_button.show()
Ejemplo n.º 47
0
    def __init__(self, handle):
        ''' Initiate activity. '''
        super(AbacusActivity, self).__init__(handle)

        self._setting_up = True
        self.bead_colors = profile.get_color().to_string().split(',')

        # no sharing
        self.max_participants = 1

        self.sep = []
        self.abacus_toolbar = Gtk.Toolbar()
        custom_toolbar = Gtk.Toolbar()
        edit_toolbar = Gtk.Toolbar()

        toolbox = ToolbarBox()

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

        edit_toolbar_button = ToolbarButton(label=_('Edit'),
                                            page=edit_toolbar,
                                            icon_name='toolbar-edit')
        edit_toolbar_button.show()
        toolbox.toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        self.abacus_toolbar_button = ToolbarButton(
            page=self.abacus_toolbar,
            icon_name='abacus-list')
        self.abacus_toolbar.show()
        toolbox.toolbar.insert(self.abacus_toolbar_button, -1)
        self.abacus_toolbar_button.show()

        self.custom_toolbar_button = ToolbarButton(
            page=custom_toolbar,
            icon_name='view-source')
        custom_toolbar.show()
        toolbox.toolbar.insert(self.custom_toolbar_button, -1)
        self.custom_toolbar_button.show()

        separator_factory(toolbox.toolbar, False, True)

        button_factory('edit-delete', toolbox.toolbar,
                       self._reset_cb, tooltip=_('Reset'))

        separator_factory(toolbox.toolbar, False, True)

        self._label = label_factory(NAMES['suanpan'], toolbox.toolbar)

        separator_factory(toolbox.toolbar, True, False)

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

        self.set_toolbar_box(toolbox)
        toolbox.show()

        self.abacus_buttons = {}

        # Traditional
        self._add_abacus_button('decimal', None)
        self._add_abacus_button('soroban', self.abacus_buttons['decimal'])
        self._add_abacus_button('suanpan', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Bases other than 10
        self._add_abacus_button('nepohualtzintzin',
                                self.abacus_buttons['decimal'])
        self._add_abacus_button('hexadecimal', self.abacus_buttons['decimal'])
        self._add_abacus_button('binary', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Fractions
        self._add_abacus_button('schety', self.abacus_buttons['decimal'])
        # self._add_abacus_button('fraction', self.abacus_buttons['decimal'])
        self._add_abacus_button('caacupe', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Non-traditional
        self._add_abacus_button('cuisenaire', self.abacus_buttons['decimal'])

        self.sep.append(separator_factory(self.abacus_toolbar))

        # Custom
        self._add_abacus_button('custom', self.abacus_buttons['decimal'])

        preferences_button = ToolButton('preferences-system')
        preferences_button.set_tooltip(_('Custom'))
        custom_toolbar.insert(preferences_button, -1)
        preferences_button.palette_invoker.props.toggle_palette = True
        preferences_button.palette_invoker.props.lock_palette = True
        preferences_button.props.hide_tooltip_on_click = False
        preferences_button.show()

        self._palette = preferences_button.get_palette()
        button_box = Gtk.VBox()
        # TRANS: Number of rods on the abacus
        self._rods_spin = add_spinner_and_label(
            15, 1, MAX_RODS, _('Rods:'), self._rods_spin_cb, button_box)
        # TRANS: Number of beads in the top section of the abacus
        self._top_spin = add_spinner_and_label(
            2, 0, MAX_TOP, _('Top:'), self._top_spin_cb, button_box)
        # TRANS: Number of beads in the bottom section of the abacus
        self._bottom_spin = add_spinner_and_label(
            5, 0, MAX_BOT, _('Bottom:'), self._bottom_spin_cb, button_box)
        # TRANS: Scale factor between bottom and top beads
        self._value_spin = add_spinner_and_label(
            5, 1, MAX_BOT + 1, _('Factor:'), self._value_spin_cb, button_box)
        # TRANS: Scale factor between rods
        self._base_spin = add_spinner_and_label(
            10, 1, (MAX_TOP + 1) * MAX_BOT, _('Base:'), self._base_spin_cb,
            button_box)
        hbox = Gtk.HBox()
        hbox.pack_start(button_box, True, True, style.DEFAULT_SPACING)
        hbox.show_all()
        self._palette.set_content(hbox)

        separator_factory(custom_toolbar, False, False)

        self.custom_maker = button_factory('new-abacus', custom_toolbar,
                                           self._custom_cb,
                                           tooltip=_('Custom'))

        button_factory('edit-copy', edit_toolbar, self._copy_cb,
                       tooltip=_('Copy'), accelerator='<Ctrl>c')
        button_factory('edit-paste', edit_toolbar, self._paste_cb,
                       tooltip=_('Paste'), accelerator='<Ctrl>v')

        # Create a canvas
        canvas = Gtk.DrawingArea()
        canvas.set_size_request(Gdk.Screen.width(),
                                Gdk.Screen.height())
        self.set_canvas(canvas)
        canvas.show()
        self.show_all()

        # Initialize the canvas
        self.abacus = Abacus(canvas, self)

        self._setting_up = False

        # Read the current mode from the Journal
        if 'rods' in self.metadata:
            self._rods_spin.set_value(int(self.metadata['rods']))
        if 'top' in self.metadata:
            self._top_spin.set_value(int(self.metadata['top']))
        if 'bottom' in self.metadata:
            self._bottom_spin.set_value(int(self.metadata['bottom']))
        if 'factor' in self.metadata:
            self._value_spin.set_value(int(self.metadata['factor']))
        if 'base' in self.metadata:
            self._base_spin.set_value(int(self.metadata['base']))
        if 'abacus' in self.metadata:
            if self.metadata['abacus'] in self.abacus_buttons:
                _logger.debug('restoring %s', self.metadata['abacus'])
                if self.metadata['abacus'] == 'custom':
                    self._custom_cb()
                self.abacus_buttons[self.metadata['abacus']].set_active(True)
            else:  # Default is Chinese
                self.abacus_buttons['suanpan'].set_active(True)

            if 'value' in self.metadata:
                _logger.debug('restoring value %s', self.metadata['value'])
                self.abacus.mode.set_value(self.metadata['value'])
                self.abacus.mode.label(self.abacus.generate_label())

        self.abacus.init()

        # Start with abacus toolbar expanded and suanpan as default
        self.abacus_toolbar_button.set_expanded(True)
Ejemplo n.º 48
0
    def __init__(self, activity):
        GObject.GObject.__init__(self)

        self.activity = activity

        self.instrumentDB = InstrumentDB.getRef()
        self.noteDB = NoteDB.NoteDB()

        #-- initial settings ----------------------------------
        self.tempo = Config.PLAYER_TEMPO
        self.beatDuration = 60.0 / self.tempo
        self.ticksPerSecond = Config.TICKS_PER_BEAT * self.tempo / 60.0
        self.volume = 0.5

        self.csnd = new_csound_client()
        for i in range(0, 9):
            self.csnd.setTrackVolume(100, i)
        # csnd expects a range 0-100 for now
        self.csnd.setMasterVolume(self.volume * 100)
        self.csnd.setTempo(self.tempo)

        self.muted = False

        #-- Drawing -------------------------------------------
        def darken(hex):
            hexToDec = {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6,
                        "7": 7, "8": 8, "9": 9, "A": 10, "B": 11, "C": 12,
                        "D": 13, "E": 14, "F": 15, "a": 10, "b": 11, "c": 12,
                        "d": 13, "e": 14, "f": 15}
            r = int(0.7 * (16 * hexToDec[hex[1]] + hexToDec[hex[2]]))
            g = int(0.7 * (16 * hexToDec[hex[3]] + hexToDec[hex[4]]))
            b = int(0.7 * (16 * hexToDec[hex[5]] + hexToDec[hex[6]]))
            return r * 256, g * 256, b * 256

        def lighten(hex):
            hexToDec = {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6,
                        "7": 7, "8": 8, "9": 9, "A": 10, "B": 11, "C": 12,
                        "D": 13, "E": 14, "F": 15, "a": 10, "b": 11, "c": 12,
                        "d": 13, "e": 14, "f": 15}
            r = 255 - int(0.7 * (255 - (
                        16 * hexToDec[hex[1]] + hexToDec[hex[2]])))
            g = 255 - int(0.7 * (255 - (
                        16 * hexToDec[hex[3]] + hexToDec[hex[4]])))
            b = 255 - int(0.7 * (255 - (
                        16 * hexToDec[hex[5]] + hexToDec[hex[6]])))
            return r * 256, g * 256, b * 256

        xoColor = profile.get_color()
        if not xoColor:
            xoColorKey = ("#8D8D8D,#FFDDEA")
            xoColor = XoColor(xoColorKey)

        # colors in Config and in XoColor are strings,
        # the colors in style are style.Color, transform all to Gdk.Color
        self.colors = {"bg": CairoUtil.get_gdk_color(Config.PANEL_BCK_COLOR),
               "black": style.COLOR_BLACK.get_gdk_color(),
               #"Picker_Bg": colormap.alloc_color("#404040"),
               #"Picker_Bg_Inactive": colormap.alloc_color("#808080"),
               "Picker_Bg": style.COLOR_TOOLBAR_GREY.get_gdk_color(),
               "Picker_Bg_Inactive": style.COLOR_BUTTON_GREY.get_gdk_color(),
               "Picker_Fg": style.COLOR_WHITE.get_gdk_color(),
               "Border_Active": \
                        CairoUtil.get_gdk_color(xoColor.get_stroke_color()),
               "Border_Inactive": CairoUtil.get_gdk_color("#8D8D8D"),
               "Border_Highlight": CairoUtil.get_gdk_color("#FFFFFF"),
               "Bg_Active": CairoUtil.get_gdk_color(xoColor.get_fill_color()),
               "Bg_Inactive": CairoUtil.get_gdk_color("#DBDBDB"),
               "Preview_Note_Fill": CairoUtil.get_gdk_color(Config.BG_COLOR),
               "Preview_Note_Border": CairoUtil.get_gdk_color(Config.FG_COLOR),
               "Preview_Note_Selected": style.COLOR_WHITE.get_gdk_color(),
                # TODO: lighten here can be removed, check if is used in other
                # places
               "Note_Fill_Active": Gdk.Color(*lighten("#590000")),
               # base "Border_Active"
               "Note_Fill_Inactive": Gdk.Color(*lighten("#8D8D8D")),
               # base "Border_Inactive"
               "Beat_Line": CairoUtil.get_gdk_color("#959595")}
        self.colors["Note_Border_Active"] = self.colors["Border_Active"]
        self.colors["Note_Border_Inactive"] = self.colors["Border_Inactive"]

        self.sampleNoteHeight = 7

        self.sampleBg = cairo.ImageSurface.create_from_png(
                imagefile('sampleBG.png'))
        self.loopPitchOffset = 4
        self.loopTickOffset = 13
        self.pitchPerPixel = float(Config.NUMBER_OF_POSSIBLE_PITCHES - 1) / \
            (Block.Loop.HEIGHT - 2 * self.loopPitchOffset - \
                 self.sampleNoteHeight)
        self.pixelsPerPitch = float(Block.Loop.HEIGHT - \
            2 * self.loopPitchOffset - self.sampleNoteHeight) / \
            (Config.MAXIMUM_PITCH - Config.MINIMUM_PITCH)
        self.pixelsPerTick = Block.Loop.BEAT / float(Config.TICKS_PER_BEAT)
        self.ticksPerPixel = 1.0 / self.pixelsPerTick

        #-- Instruments ---------------------------------------
        self.instrumentImage = {}
        self.instrumentImageActive = {}
        for inst in self.instrumentDB.getSet("All"):
            if not inst.kitStage:
                self.prepareInstrumentImage(inst.instrumentId, inst.img)
            self.csnd.load_instrument(inst.name)

        #-- Loop Images ---------------------------------------
        self.loopImage = {}  # get filled in through updateLoopImage
        self.loopImageActive = {}

        #-- Key Images ----------------------------------------
        self.keyImage = {}
        self.keyImageActive = {}
        # use hardware key codes to work on any keyboard layout (hopefully)
        self.valid_shortcuts = {18: "9", 19: "0", 20: "-", 21: "=",
                                32: "O", 33: "P", 34: "[", 35: "]",
                                47: ";", 48: "'", 51: "\\",
                                60: ".", 61: "/",
                                None: " "}
        for key in self.valid_shortcuts.keys():
            self.prepareKeyImage(key)

        #-- Toolbars ------------------------------------------

        self.jamToolbar = JamToolbar(self)
        jam_toolbar_button = ToolbarButton(label=_('Jam'),
                                           page=self.jamToolbar,
                                           icon_name='voltemp')
        self.jamToolbar.show()
        jam_toolbar_button.show()
        self.activity.toolbar_box.toolbar.insert(jam_toolbar_button, -1)

        self.beatToolbar = BeatToolbar(self)
        beat_toolbar_button = ToolbarButton(label=_('Beat'),
                                                page=self.beatToolbar,
                                                icon_name='heart')
        self.beatToolbar.show()
        beat_toolbar_button.show()
        self.activity.toolbar_box.toolbar.insert(beat_toolbar_button, -1)

        self.desktopToolbar = DesktopToolbar(self)
        desktop_toolbar_button = ToolbarButton(label=_('Desktop'),
                                              page=self.desktopToolbar,
                                              icon_name='jam-presets-list')
        self.desktopToolbar.show()
        desktop_toolbar_button.show()
        self.activity.toolbar_box.toolbar.insert(desktop_toolbar_button, -1)

        if Config.FEATURES_MIC or Config.FEATURES_NEWSOUNDS:
            self.recordToolbar = RecordToolbar(self)
            record_toolbar_button = ToolbarButton(label=_('Record'),
                                                  page=self.recordToolbar,
                                                  icon_name='microphone')
            self.recordToolbar.show()
            record_toolbar_button.show()
            self.activity.toolbar_box.toolbar.insert(record_toolbar_button, -1)

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

        common_playback_buttons(self.activity.toolbar_box.toolbar, self)

        #-- GUI -----------------------------------------------
        if True:  # GUI
            self.modify_bg(Gtk.StateType.NORMAL, self.colors["bg"])

            self.GUI = {}
            self.GUI["mainVBox"] = Gtk.VBox()
            self.add(self.GUI["mainVBox"])

            #-- Desktop -------------------------------------------
            self.desktop = self.GUI["desktop"] = Desktop(self)
            self.GUI["mainVBox"].pack_start(self.GUI["desktop"], True, True, 0)

            #-- Bank ----------------------------------------------
            separator = Gtk.Label(label=" ")
            separator.set_size_request(-1, style.TOOLBOX_SEPARATOR_HEIGHT)
            self.GUI["mainVBox"].pack_start(separator, False, True, 0)
            self.GUI["notebook"] = Gtk.Notebook()
            self.GUI["notebook"].set_scrollable(True)
            self.GUI["notebook"].modify_bg(Gtk.StateType.NORMAL,
                                           self.colors["Picker_Bg"])
            self.GUI["notebook"].modify_bg(Gtk.StateType.ACTIVE,
                                           self.colors["Picker_Bg_Inactive"])
            # TODO gtk3 no available anymore?
            #self.GUI["notebook"].props.tab_vborder = style.TOOLBOX_TAB_VBORDER
            #self.GUI["notebook"].props.tab_hborder = style.TOOLBOX_TAB_HBORDER
            self.GUI["notebook"].set_size_request(-1, scale(160))
            self.GUI["notebook"].connect("switch-page", self.setPicker)
            self.GUI["mainVBox"].pack_start(self.GUI["notebook"], False,
                    False, 0)
            self.pickers = {}
            self.pickerScroll = {}
            for type in [Picker.Instrument, Picker.Drum, Picker.Loop]:
                self.pickers[type] = type(self)

            def prepareLabel(name):
                label = Gtk.Label(label=Tooltips.categories.get(name) or name)
                label.set_alignment(0.0, 0.5)
                label.modify_fg(Gtk.StateType.NORMAL, self.colors["Picker_Fg"])
                label.modify_fg(Gtk.StateType.ACTIVE, self.colors["Picker_Fg"])
                return label

            self.GUI["notebook"].append_page(self.pickers[Picker.Drum],
                                             prepareLabel(_("Drum Kits")))
            self.GUI["notebook"].append_page(self.pickers[Picker.Loop],
                                             prepareLabel(_("Loops")))

            sets = self.instrumentDB.getLabels()[:]
            sets.sort()
            for set in sets:
                page = Gtk.HBox()
                page.set = set
                self.GUI["notebook"].append_page(page, prepareLabel(set))

            self.show_all()

            self.GUI["notebook"].set_current_page(0)

        #-- Keyboard ------------------------------------------
        self.key_dict = {}
        self.nextTrack = 2
        self.keyboardListener = None
        self.recordingNote = None

        self.keyMap = {}

        # default instrument
        self._updateInstrument(
            self.instrumentDB.instNamed["kalimba"].instrumentId, 0.5)
        self.instrumentStack = []

        # metronome
        page = NoteDB.Page(1, local=False)
        self.metronomePage = self.noteDB.addPage(-1, page)
        self.metronome = False

        #-- Drums ---------------------------------------------
        self.drumLoopId = None
        # use dummy values for now
        self.drumFillin = Fillin(
            2, 100, self.instrumentDB.instNamed["drum1kit"].instrumentId, 0, 1)

        #-- Desktops ------------------------------------------
        self.curDesktop = None
        # copy preset desktops
        path = Config.FILES_DIR + "/Desktops/"
        filelist = os.listdir(path)
        for file in filelist:
            shutil.copyfile(path + file, Config.TMP_DIR + '/' + file)

        #-- Network -------------------------------------------
        self.network = Net.Network()
        self.network.addWatcher(self.networkStatusWatcher)
        self.network.connectMessage(Net.HT_SYNC_REPLY,
                                    self.processHT_SYNC_REPLY)
        self.network.connectMessage(Net.HT_TEMPO_UPDATE,
                                    self.processHT_TEMPO_UPDATE)
        self.network.connectMessage(Net.PR_SYNC_QUERY,
                                    self.processPR_SYNC_QUERY)
        self.network.connectMessage(Net.PR_TEMPO_QUERY,
                                    self.processPR_TEMPO_QUERY)
        self.network.connectMessage(Net.PR_REQUEST_TEMPO_CHANGE,
                                    self.processPR_REQUEST_TEMPO_CHANGE)

        # sync
        self.syncQueryStart = {}
        self.syncTimeout = None
        self.heartbeatLoop = self.csnd.loopCreate()
        self.syncBeats = 4
        self.syncTicks = self.syncBeats * Config.TICKS_PER_BEAT
        self.offsetTicks = 0  # offset from the true heartbeat
        self.csnd.loopSetNumTicks(self.syncTicks * HEARTBEAT_BUFFER,
                                  self.heartbeatLoop)
        self.heartbeatStart = time.time()
        self.csnd.loopStart(self.heartbeatLoop)
        self.curBeat = 0
        self.beatWheelTimeout = GObject.timeout_add(100, self.updateBeatWheel)

        # data packing classes
        self.packer = xdrlib.Packer()
        self.unpacker = xdrlib.Unpacker("")

        # handle forced networking
        if self.network.isHost():
            self.updateSync()
            self.syncTimeout = GObject.timeout_add(1000, self.updateSync)
        elif self.network.isPeer():
            self.sendTempoQuery()
            self.syncTimeout = GObject.timeout_add(1000, self.updateSync)

        self.activity.connect("shared", self.shared)

        if self.activity.shared_activity:  # PEER
            self.activity.shared_activity.connect("buddy-joined",
                                                   self.buddy_joined)
            self.activity.shared_activity.connect("buddy-left",
                                                   self.buddy_left)
            self.activity.connect("joined", self.joined)
            self.network.setMode(Net.MD_WAIT)

        #-- Final Set Up --------------------------------------
        self.setVolume(self.volume)
        self.setTempo(self.tempo)
        #self.activity.toolbar_box.set_current_toolbar(1)  # JamToolbar
        self.setDesktop(0, True)
Ejemplo n.º 49
0
class ReflectActivity(activity.Activity):
    ''' An activity for reflecting on one's work '''

    def __init__(self, handle):
        ''' Initialize the toolbar '''
        try:
            super(ReflectActivity, self).__init__(handle)
        except dbus.exceptions.DBusException as e:
            _logger.error(str(e))

        logging.error('setting reflection data to []')
        self.reflection_data = []

        self.connect('realize', self.__realize_cb)

        self.font_size = 8

        self.max_participants = 4
        self._setup_toolbars()

        color = profile.get_color()
        color_stroke = color.get_stroke_color()
        color_fill = color.get_fill_color()

        lighter = utils.lighter_color([color_stroke, color_fill])
        darker = 1 - lighter

        if lighter == 0:
            self.bg_color = style.Color(color_stroke)
            self.fg_color = style.Color(color_fill)
        else:
            self.bg_color = style.Color(color_fill)
            self.fg_color = style.Color(color_stroke)

        self.modify_bg(Gtk.StateType.NORMAL, self.bg_color.get_gdk_color())

        self.bundle_path = activity.get_bundle_path()
        self.tmp_path = os.path.join(activity.get_activity_root(), 'instance')

        self.sharing = False
        self._copy_entry = None
        self._paste_entry = None
        self._webkit = None
        self._clipboard_text = ''
        self._fixed = None

        self.initiating = True
        if self.shared_activity:
            # We're joining
            if not self.get_shared():
                self.initiating = False

                self.busy_cursor()
                share_icon = Icon(icon_name='zoom-neighborhood')
                self._joined_alert = Alert()
                self._joined_alert.props.icon = share_icon
                self._joined_alert.props.title = _('Please wait')
                self._joined_alert.props.msg = _('Starting connection...')
                self.add_alert(self._joined_alert)

                # Wait for joined signal
                self.connect("joined", self._joined_cb)

        self._open_reflect_windows()

        self._setup_presence_service()

        # Joiners wait to receive data from sharer
        # Otherwise, load reflections from local store
        if not self.shared_activity:
            self.busy_cursor()
            GObject.idle_add(self._load_reflections)

    def read_file(self, file_path):
        fd = open(file_path, 'r')
        data = fd.read()
        fd.close()
        self.reflection_data = json.loads(data)

    def write_file(self, file_path):
        data = json.dumps(self.reflection_data)
        fd = open(file_path, 'w')
        fd.write(data)
        fd.close()

        self.metadata['font_size'] = str(self.font_size)

    def _load_reflections(self):
        self._find_starred()
        self._reflect_window.load(self.reflection_data)
        self.reset_cursor()

    def _found_obj_id(self, obj_id):
        for item in self.reflection_data:
            if 'obj_id' in item and item['obj_id'] == obj_id:
                return True
        return False

    def reload_data(self, data):
        ''' Reload data after sorting or searching '''
        self._reflection_data = data[:]
        self._reflect_window.reload(self._reflection_data)
        self.reset_scrolled_window_adjustments()

    def _find_starred(self):
        ''' Find all the _stars in the Journal. '''
        self.dsobjects, self._nobjects = datastore.find({'keep': '1'})
        for dsobj in self.dsobjects:
            if self._found_obj_id(dsobj.object_id):
                continue  # Already have this object -- TODO: update it
            self._add_new_from_journal(dsobj)

    def _add_new_from_journal(self, dsobj):
        self.reflection_data.append({
            'title': _('Untitled'), 'obj_id': dsobj.object_id})
        if hasattr(dsobj, 'metadata'):
            if 'creation_time' in dsobj.metadata:
                self.reflection_data[-1]['creation_time'] = \
                    dsobj.metadata['creation_time']
            else:
                self.reflection_data[-1]['creation_time'] = \
                    int(time.time())
            if 'timestamp' in dsobj.metadata:
                self.reflection_data[-1]['modification_time'] = \
                    dsobj.metadata['timestamp']
            else:
                self.reflection_data[-1]['modification_time'] = \
                    self.reflection_data[-1]['creation_time']
            if 'activity' in dsobj.metadata:
                self.reflection_data[-1]['activities'] = \
                    [utils.bundle_id_to_icon(dsobj.metadata['activity'])]
            if 'title' in dsobj.metadata:
                self.reflection_data[-1]['title'] = \
                    dsobj.metadata['title']
            if 'description' in dsobj.metadata:
                self.reflection_data[-1]['content'] = \
                    [{'text': dsobj.metadata['description']}]
            else:
                self.reflection_data[-1]['content'] = []
            if 'tags' in dsobj.metadata:
                self.reflection_data[-1]['tags'] = []
                tags = dsobj.metadata['tags'].split()
                for tag in tags:
                    if tag[0] != '#':
                        self.reflection_data[-1]['tags'].append('#' + tag)
                    else:
                        self.reflection_data[-1]['tags'].append(tag)
            if 'comments' in dsobj.metadata:
                try:
                    comments = json.loads(dsobj.metadata['comments'])
                except:
                    comments = []
                self.reflection_data[-1]['comments'] = []
                for comment in comments:
                    try:
                        data = {'nick': comment['from'],
                                'comment': comment['message']}
                        if 'icon-color' in comment:
                            colors = comment['icon-color'].split(',')
                            darker = 1 - utils.lighter_color(colors)
                            data['color'] = colors[darker]
                        else:
                            data['color'] = '#000000'
                        self.reflection_data[-1]['comments'].append(data)
                    except:
                        _logger.debug('could not parse comment %s'
                                      % comment)
            if 'mime_type' in dsobj.metadata and \
               dsobj.metadata['mime_type'][0:5] == 'image':
                new_path = os.path.join(self.tmp_path,
                                        dsobj.object_id)
                try:
                    shutil.copy(dsobj.file_path, new_path)
                except Exception as e:
                    logging.error("Couldn't copy %s to %s: %s" %
                                  (dsobj.file_path, new_path, e))
                self.reflection_data[-1]['content'].append(
                    {'image': new_path})
            elif 'preview' in dsobj.metadata:
                pixbuf = utils.get_pixbuf_from_journal(dsobj, 300, 225)
                if pixbuf is not None:
                    path = os.path.join(self.tmp_path,
                                        dsobj.object_id + '.png')
                    utils.save_pixbuf_to_file(pixbuf, path)
                    self.reflection_data[-1]['content'].append(
                        {'image': path})
            self.reflection_data[-1]['stars'] = 0

    def delete_item(self, obj_id):
        for i, obj in enumerate(self.reflection_data):
            if obj['obj_id'] == obj_id:
                self.reflection_data.remove(self.reflection_data[i])
                return

    def busy_cursor(self):
        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))

    def reset_cursor(self):
        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR))

    def _open_reflect_windows(self):
        # Most things need only be done once
        if self._fixed is None:
            self._fixed = Gtk.Fixed()
            self._fixed.set_size_request(Gdk.Screen.width(),
                                         Gdk.Screen.height())

            # Offsets from the bottom of the screen
            dy1 = 2 * style.GRID_CELL_SIZE
            dy2 = 1 * style.GRID_CELL_SIZE

            self._button_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._button_area.set_size_request(Gdk.Screen.width(),
                                               style.GRID_CELL_SIZE)
            self._fixed.put(self._button_area, 0, 0)
            self._button_area.show()

            self._scrolled_window = Gtk.ScrolledWindow()
            self._scrolled_window.set_size_request(
                Gdk.Screen.width(), Gdk.Screen.height() - dy1)
            self._set_scroll_policy()
            self._graphics_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._scrolled_window.add_with_viewport(self._graphics_area)
            self._graphics_area.show()
            self._fixed.put(self._scrolled_window, 0, dy2)
            self._scrolled_window.show()

            self._overlay_window = Gtk.ScrolledWindow()
            self._overlay_window.set_size_request(
                style.GRID_CELL_SIZE * 10,
                style.GRID_CELL_SIZE * 6)
            self._overlay_window.modify_bg(
                Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color())
            self._overlay_window.set_policy(
                 Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
            self._overlay_area = Gtk.Alignment.new(0.5, 0, 0, 0)
            self._overlay_window.add_with_viewport(self._overlay_area)
            self._overlay_area.show()
            x = int((Gdk.Screen.width() - style.GRID_CELL_SIZE * 10) / 2)
            self._fixed.put(self._overlay_window, 0, Gdk.Screen.height())
            self._overlay_window.show()
            self._old_overlay_widget = None

            self._reflect_window = ReflectWindow(self)
            self._reflect_window.show()

            Gdk.Screen.get_default().connect('size-changed',
                                             self._configure_cb)
            self._toolbox.connect('hide', self._resize_hide_cb)
            self._toolbox.connect('show', self._resize_show_cb)

            self._reflect_window.set_events(Gdk.EventMask.KEY_PRESS_MASK)
            self._reflect_window.connect('key_press_event',
                                      self._reflect_window.keypress_cb)
            self._reflect_window.set_can_focus(True)
            self._reflect_window.grab_focus()

        self.set_canvas(self._fixed)
        self._fixed.show()

    def reset_scrolled_window_adjustments(self):
        adj = self._scrolled_window.get_hadjustment()
        if adj is not None:
            adj.set_value(0)
        adj = self._scrolled_window.get_vadjustment()
        if adj is not None:
            adj.set_value(0)

    def load_graphics_area(self, widget):
        self._graphics_area.add(widget)

    def load_button_area(self, widget):
        self._button_area.add(widget)

    def load_overlay_area(self, widget):
        if self._old_overlay_widget is not None:
            self._overlay_area.remove(self._old_overlay_widget)
        self._overlay_area.add(widget)
        self._old_overlay_widget = widget

    def show_overlay_area(self):
        x = int((Gdk.Screen.width() - style.GRID_CELL_SIZE * 10) / 2)
        self._fixed.move(self._overlay_window, x, style.GRID_CELL_SIZE)

    def hide_overlay_area(self):
        self._fixed.move(
            self._overlay_window, 0, Gdk.Screen.height())

    def _resize_hide_cb(self, widget):
        self._resize_canvas(widget, True)

    def _resize_show_cb(self, widget):
        self._resize_canvas(widget, False)

    def _configure_cb(self, event):
        self._fixed.set_size_request(Gdk.Screen.width(), Gdk.Screen.height())
        self._set_scroll_policy()
        self._resize_canvas(None)
        self._reflect_window.reload_graphics()

    def _resize_canvas(self, widget, fullscreen=False):
        # When a toolbar is expanded or collapsed, resize the canvas
        if hasattr(self, '_reflect_window'):
            if self.toolbar_expanded():
                dy1 = 3 * style.GRID_CELL_SIZE
                dy2 = 2 * style.GRID_CELL_SIZE
            else:
                dy1 = 2 * style.GRID_CELL_SIZE
                dy2 = 1 * style.GRID_CELL_SIZE

            if fullscreen:
                dy1 -= 2 * style.GRID_CELL_SIZE
                dy2 -= 2 * style.GRID_CELL_SIZE

            self._scrolled_window.set_size_request(
                Gdk.Screen.width(), Gdk.Screen.height() - dy2)
            self._fixed.move(self._button_area, 0, 0)

        self._about_panel_visible = False

    def toolbar_expanded(self):
        if self.activity_button.is_expanded():
            return True
        elif self.edit_toolbar_button.is_expanded():
            return True
        elif self.view_toolbar_button.is_expanded():
            return True
        return False

    def get_activity_version(self):
        info_path = os.path.join(self.bundle_path, 'activity', 'activity.info')
        try:
            info_file = open(info_path, 'r')
        except Exception as e:
            _logger.error('Could not open %s: %s' % (info_path, e))
            return 'unknown'

        cp = ConfigParser()
        cp.readfp(info_file)

        section = 'Activity'

        if cp.has_option(section, 'activity_version'):
            activity_version = cp.get(section, 'activity_version')
        else:
            activity_version = 'unknown'
        return activity_version

    def get_uid(self):
        if len(self.volume_data) == 1:
            return self.volume_data[0]['uid']
        else:
            return 'unknown'

    def _setup_toolbars(self):
        ''' Setup the toolbars. '''
        self._toolbox = ToolbarBox()

        self.activity_button = ActivityToolbarButton(self)
        self.activity_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.activity_button, 0)
        self.activity_button.show()

        self.set_toolbar_box(self._toolbox)
        self._toolbox.show()
        self.toolbar = self._toolbox.toolbar

        view_toolbar = Gtk.Toolbar()
        self.view_toolbar_button = ToolbarButton(
            page=view_toolbar,
            label=_('View'),
            icon_name='toolbar-view')
        self.view_toolbar_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.view_toolbar_button, 1)
        view_toolbar.show()
        self.view_toolbar_button.show()

        button = ToolButton('view-fullscreen')
        button.set_tooltip(_('Fullscreen'))
        button.props.accelerator = '<Alt>Return'
        view_toolbar.insert(button, -1)
        button.show()
        button.connect('clicked', self._fullscreen_cb)

        edit_toolbar = Gtk.Toolbar()
        self.edit_toolbar_button = ToolbarButton(
            page=edit_toolbar,
            label=_('Edit'),
            icon_name='toolbar-edit')
        self.edit_toolbar_button.connect('clicked', self._resize_canvas)
        self._toolbox.toolbar.insert(self.edit_toolbar_button, 1)
        edit_toolbar.show()
        self.edit_toolbar_button.show()

        self._copy_button = ToolButton('edit-copy')
        self._copy_button.set_tooltip(_('Copy'))
        self._copy_button.props.accelerator = '<Ctrl>C'
        edit_toolbar.insert(self._copy_button, -1)
        self._copy_button.show()
        self._copy_button.connect('clicked', self._copy_cb)
        self._copy_button.set_sensitive(False)

        self._paste_button = ToolButton('edit-paste')
        self._paste_button.set_tooltip(_('Paste'))
        self._paste_button.props.accelerator = '<Ctrl>V'
        edit_toolbar.insert(self._paste_button, -1)
        self._paste_button.show()
        self._paste_button.connect('clicked', self._paste_cb)
        self._paste_button.set_sensitive(False)

        button = ToolButton('list-add')
        button.set_tooltip(_('Add Item'))
        button.props.accelerator = '<Ctrl>+'
        self._toolbox.toolbar.insert(button, -1)
        button.show()
        button.connect('clicked', self.__add_item_cb)

        self._date_button = RadioToolButton('date-sort', group=None)
        self._date_button.set_tooltip(_('Sort by Date'))
        self._date_button.connect('clicked', self._date_button_cb)
        self._toolbox.toolbar.insert(self._date_button, -1)
        self._date_button.show()

        self._title_button = RadioToolButton('title-sort',
                                             group=self._date_button)
        self._title_button.set_tooltip(_('Sort by Title'))
        self._title_button.connect('clicked', self._title_button_cb)
        self._toolbox.toolbar.insert(self._title_button, -1)
        self._title_button.show()

        self._stars_button = RadioToolButton('stars-sort',
                                             group=self._date_button)
        self._stars_button.set_tooltip(_('Sort by Favourite'))
        self._stars_button.connect('clicked', self._stars_button_cb)
        self._toolbox.toolbar.insert(self._stars_button, -1)
        self._stars_button.show()

        # setup the search options
        self._search_entry = iconentry.IconEntry()
        self._search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                              'system-search')
        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()

        tool_item = Gtk.ToolItem()
        tool_item.set_expand(True)
        tool_item.add(self._search_entry)
        self._search_entry.show()
        self._toolbox.toolbar.insert(tool_item, -1)
        tool_item.show()

        self._search_button = ToolButton('dialog-ok')
        self._search_button.set_tooltip(_('Search by Tags'))
        self._search_button.connect('clicked', self._search_button_cb)
        self._toolbox.toolbar.insert(self._search_button, -1)
        self._search_button.show()

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

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        self._toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()

    def _search_button_cb(self, button):
        self.busy_cursor()
        self._do_search()

    def _search_entry_activated_cb(self, entry):
        self.busy_cursor()
        self._do_search()

    def _do_search(self):
        logging.debug('_search_entry_activated_cb')
        if self._search_entry.props.text == '':
            logging.debug('clearing search')
            for item in self.reflection_data:
                item['hidden'] = False
        else:
            tags = self._search_entry.props.text.split()
            for i, tag in enumerate(tags):
                if not tag[0] == '#':
                    tags[i] = '#%s' % tag
            logging.error(tags)
            for item in self.reflection_data:
                hidden = True
                if 'tags' in item:
                    for tag in tags:
                        if tag in item['tags']:
                            hidden = False
                item['hidden'] = hidden
        self.reload_data(self.reflection_data)
        self.reset_cursor()

    def _search_entry_changed_cb(self, entry):
        logging.debug('_search_entry_changed_cb search for \'%s\'',
                     self._search_entry.props.text)
        self.busy_cursor()
        self._do_search_changed()

    def _do_search_changed(self):
        if self._search_entry.props.text == '':
            logging.debug('clearing search')
            for item in self.reflection_data:
                item['hidden'] = False
            self.reload_data(self.reflection_data)
        self.reset_cursor()

    def _title_button_cb(self, button):
        ''' sort by title '''
        self.busy_cursor()
        GObject.idle_add(self._title_sort)

    def _title_sort(self):
        sorted_data = sorted(self.reflection_data,
                             key=lambda item: item['title'].lower())
        self.reload_data(sorted_data)
        self.reset_cursor()

    def _date_button_cb(self, button):
        ''' sort by modification date '''
        self.busy_cursor()
        GObject.idle_add(self._date_sort)

    def _date_sort(self):
        sorted_data = sorted(self.reflection_data,
                             key=lambda item: int(item['modification_time']),
                             reverse=True)
        self.reload_data(sorted_data)
        self.reset_cursor()

    def _stars_button_cb(self, button):
        ''' sort by number of stars '''
        self.busy_cursor()
        GObject.idle_add(self._stars_sort)

    def _stars_sort(self):
        sorted_data = sorted(self.reflection_data,
                             key=lambda item: item['stars'], reverse=True)
        self.reload_data(sorted_data)
        self.reset_cursor()

    def __realize_cb(self, window):
        self.window_xid = window.get_window().get_xid()

    def set_copy_widget(self, webkit=None, text_entry=None):
        # Each task is responsible for setting a widget for copy
        if webkit is not None:
            self._webkit = webkit
        else:
            self._webkit = None
        if text_entry is not None:
            self._copy_entry = text_entry
        else:
            self._copy_entry = None

        self._copy_button.set_sensitive(webkit is not None or
                                        text_entry is not None)

    def _copy_cb(self, button):
        if self._copy_entry is not None:
            self._copy_entry.copy_clipboard()
        elif self._webkit is not None:
            self._webkit.copy_clipboard()
        else:
            _logger.debug('No widget set for copy.')

    def set_paste_widget(self, text_entry=None):
        # Each task is responsible for setting a widget for paste
        if text_entry is not None:
            self._paste_entry = text_entry
        self._paste_button.set_sensitive(text_entry is not None)

    def _paste_cb(self, button):
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        self.clipboard_text = clipboard.wait_for_text()
        if self._paste_entry is not None:
            self._paste_entry.paste_clipboard()
        else:
            _logger.debug('No widget set for paste (%s).' %
                          self.clipboard_text)

    def _fullscreen_cb(self, button):
        ''' Hide the Sugar toolbars. '''
        self.fullscreen()

    def __add_item_cb(self, button):
        try:
            chooser = ObjectChooser(parent=self, what_filter=None)
        except TypeError:
            chooser = ObjectChooser(
                None, self._reflection.activity,
                Gtk.DialogFlags.MODAL |
                Gtk.DialogFlags.DESTROY_WITH_PARENT)

        try:
            result = chooser.run()
            if result == Gtk.ResponseType.ACCEPT:
                jobject = chooser.get_selected_object()
                if jobject:
                    self._add_new_from_journal(jobject)
                    self.reload_data(self.reflection_data)
        finally:
            chooser.destroy()
            del chooser

    def _set_scroll_policy(self):
        if Gdk.Screen.width() < Gdk.Screen.height():
            self._scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                             Gtk.PolicyType.AUTOMATIC)
        else:
            self._scrolled_window.set_policy(Gtk.PolicyType.NEVER,
                                             Gtk.PolicyType.AUTOMATIC)

    def _remove_alert_cb(self, alert, response_id):
        self.remove_alert(alert)

    def _close_alert_cb(self, alert, response_id):
        self.remove_alert(alert)
        if response_id is Gtk.ResponseType.OK:
            self.close()

    def _setup_presence_service(self):
        ''' Setup the Presence Service. '''
        self.pservice = presenceservice.get_instance()

        owner = self.pservice.get_owner()
        self.owner = owner
        self._share = ''
        self.connect('shared', self._shared_cb)
        self.connect('joined', self._joined_cb)

    def _shared_cb(self, activity):
        ''' Either set up initial share...'''
        if self.shared_activity is None:
            _logger.error('Failed to share or join activity ... \
                shared_activity is null in _shared_cb()')
            return

        self.initiating = True
        self._waiting_for_reflections = False
        _logger.debug('I am sharing...')

        self.conn = self.shared_activity.telepathy_conn
        self.tubes_chan = self.shared_activity.telepathy_tubes_chan
        self.text_chan = self.shared_activity.telepathy_text_chan

        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
            'NewTube', self._new_tube_cb)

        _logger.debug('This is my activity: making a tube...')
        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(
            SERVICE, {})

        self.sharing = True

    def _joined_cb(self, activity):
        ''' ...or join an exisiting share. '''
        if self.shared_activity is None:
            _logger.error('Failed to share or join activity ... \
                shared_activity is null in _shared_cb()')
            return

        if self._joined_alert is not None:
            self.remove_alert(self._joined_alert)
            self._joined_alert = None

        self.initiating = False
        self._waiting_for_reflections = True
        _logger.debug('I joined a shared activity.')

        self.conn = self.shared_activity.telepathy_conn
        self.tubes_chan = self.shared_activity.telepathy_tubes_chan
        self.text_chan = self.shared_activity.telepathy_text_chan

        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
            'NewTube', self._new_tube_cb)

        _logger.debug('I am joining an activity: waiting for a tube...')
        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
            reply_handler=self._list_tubes_reply_cb,
            error_handler=self._list_tubes_error_cb)

        self.sharing = True

    def _list_tubes_reply_cb(self, tubes):
        ''' Reply to a list request. '''
        for tube_info in tubes:
            self._new_tube_cb(*tube_info)

    def _list_tubes_error_cb(self, e):
        ''' Log errors. '''
        _logger.error('ListTubes() failed: %s', e)

    def _new_tube_cb(self, id, initiator, type, service, params, state):
        ''' Create a new tube. '''
        _logger.debug('New tube: ID=%d initator=%d type=%d service=%s '
                      'params=%r state=%d', id, initiator, type, service,
                      params, state)

        if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE):
            if state == telepathy.TUBE_STATE_LOCAL_PENDING:
                self.tubes_chan[
                    telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id)

            self.collab = CollabWrapper(self)
            self.collab.message.connect(self.event_received_cb)
            self.collab.setup()

            if self._waiting_for_reflections:
                self.send_event(JOIN_CMD, {})
                self._joined_alert = Alert()
                self._joined_alert.props.title = _('Please wait')
                self._joined_alert.props.msg = _('Requesting reflections...')
                self.add_alert(self._joined_alert)

    def event_received_cb(self, collab, buddy, msg):
        ''' Data is passed as tuples: cmd:text '''
        command = msg.get("command")
        payload = msg.get("payload")
        logging.debug(command)

        if command == JOIN_CMD:
            # Sharer needs to send reflections database to joiners.
            if self.initiating:
                # Send pictures first.
                for item in self.reflection_data:
                    if 'content' in item:
                        for content in item['content']:
                            if 'image' in content:
                                pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
                                    content['image'], 120, 90)
                                if pixbuf is not None:
                                    data = utils.pixbuf_to_base64(pixbuf)
                                self.send_event(PICTURE_CMD,
                                    {"image": os.path.basename(content['image']),
                                     "data": data})
                data = json.dumps(self.reflection_data)
                self.send_event(SHARE_CMD, {"data": data})
        elif command == NEW_REFLECTION_CMD:
            self._reflect_window.add_new_reflection(payload)
        elif command == TITLE_CMD:
            obj_id = payload.get("obj_id")
            title = payload.get("title")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    self._reflect_window.update_title(obj_id, title)
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == TAG_CMD:
            obj_id = payload.get("obj_id")
            data = payload.get("data")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    self._reflect_window.update_tags(obj_id, data)
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == ACTIVITY_CMD:
            obj_id = payload.get("obj_id")
            bundle_id = payload.get("bundle_id")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    self._reflect_window.insert_activity(obj_id, bundle_id)
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == STAR_CMD:
            obj_id = payload.get("obj_id")
            stars = payload.get("stars")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    self._reflect_window.update_stars(obj_id, int(stars))
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == COMMENT_CMD:
            found_the_object = False
            # Receive a comment and associated reflection ID
            obj_id = payload.get("obj_id")
            nick = payload.get("nick")
            color = payload.get("color")
            comment = payload.get("comment")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    if not 'comments' in item:
                        item['comments'] = []
                    data = {'nick': nick, 'comment': comment, 'color': color}
                    item['comments'].append(data)
                    self._reflect_window.insert_comment(obj_id, data)
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == REFLECTION_CMD:
            found_the_object = False
            # Receive a reflection and associated reflection ID
            obj_id = payload.get("obj_id")
            reflection = payload.get("reflection")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    if not '' in item:
                        item['content'] = []
                    item['content'].append({'text': reflection})
                    self._reflect_window.insert_reflection(obj_id, reflection)
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == IMAGE_REFLECTION_CMD:
            found_the_object = False
            # Receive a picture reflection and associated reflection ID
            obj_id = payload.get("obj_id")
            basename = payload.get("basename")
            for item in self.reflection_data:
                if item['obj_id'] == obj_id:
                    found_the_object = True
                    if not '' in item:
                        item['content'] = []
                    item['content'].append(
                        {'image': os.path.join(self.tmp_path, basename)})
                    self._reflect_window.insert_picture(
                        obj_id, os.path.join(self.tmp_path, basename))
                    break
            if not found_the_object:
                logging.error('Could not find obj_id %s' % obj_id)
        elif command == PICTURE_CMD:
            # Receive a picture (MAYBE DISPLAY IT AS IT ARRIVES?)
            basename = payload.get("basename")
            data = payload.get("data")
            utils.base64_to_file(data, os.path.join(self.tmp_path, basename))
        elif command == SHARE_CMD:
            # Joiner needs to load reflection database.
            if not self.initiating:
                # Note that pictures should be received.
                self.reflection_data = payload
                self._reflect_window.load(self.reflection_data)
                self._waiting_for_reflections = False
                self.reset_cursor()
                if self._joined_alert is not None:
                    self.remove_alert(self._joined_alert)
                    self._joined_alert = None

    def send_event(self, command, data):
        ''' Send event through the tube. '''
        if hasattr(self, 'collab') and self.collab is not None:
            data["command"] = command
            self.collab.post(data)
class FractionBounceActivity(activity.Activity):
    def __init__(self, handle):
        ''' Initiate activity. '''
        super(FractionBounceActivity, self).__init__(handle)

        self.nick = profile.get_nick_name()
        if profile.get_color() is not None:
            self._colors = profile.get_color().to_string().split(',')
        else:
            self._colors = ['#A0FFA0', '#FF8080']

        self.max_participants = 4  # sharing
        self._playing = True

        self._setup_toolbars()
        self._setup_dispatch_table()
        canvas = self._setup_canvas()

        # Read any custom fractions from the project metadata
        if 'custom' in self.metadata:
            custom = self.metadata['custom']
        else:
            custom = None

        self._current_ball = 'soccerball'

        self._toolbar_was_expanded = False

        # Initialize the canvas
        self._bounce_window = Bounce(canvas, activity.get_bundle_path(), self)

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)

        # Restore any custom fractions
        if custom is not None:
            fractions = custom.split(',')
            for f in fractions:
                self._bounce_window.add_fraction(f)

        if self.shared_activity:
            # We're joining
            if not self.get_shared():
                xocolors = XoColor(profile.get_color().to_string())
                share_icon = Icon(icon_name='zoom-neighborhood',
                                  xo_color=xocolors)
                self._joined_alert = NotifyAlert()
                self._joined_alert.props.icon = share_icon
                self._joined_alert.props.title = _('Please wait')
                self._joined_alert.props.msg = _('Starting connection...')
                self._joined_alert.connect('response', self._alert_cancel_cb)
                self.add_alert(self._joined_alert)

                self._label.set_label(_('Wait for the sharer to start.'))

                # Wait for joined signal
                self.connect("joined", self._joined_cb)

        self._setup_sharing()

    def _configure_cb(self, event):
        if Gdk.Screen.width() < 1024:
            self._label.set_size_request(275, -1)
            self._label.set_label('')
            self._separator.set_expand(False)
        else:
            self._label.set_size_request(500, -1)
            self._separator.set_expand(True)

        self._bounce_window.configure_cb(event)
        if self._toolbar_expanded():
            self._bounce_window.bar.bump_bars('up')
            self._bounce_window.ball.ball.move_relative(
                (0, -style.GRID_CELL_SIZE))

    def _toolbar_expanded(self):
        if self._activity_button.is_expanded():
            return True
        elif self._custom_toolbar_button.is_expanded():
            return True
        return False

    def _update_graphics(self, widget):
        # We need to catch opening and closing of toolbars and ignore
        # switching between open toolbars.
        if self._toolbar_expanded():
            if not self._toolbar_was_expanded:
                self._bounce_window.bar.bump_bars('up')
                self._bounce_window.ball.ball.move_relative(
                    (0, -style.GRID_CELL_SIZE))
                self._toolbar_was_expanded = True
        else:
            if self._toolbar_was_expanded:
                self._bounce_window.bar.bump_bars('down')
                self._bounce_window.ball.ball.move_relative(
                    (0, style.GRID_CELL_SIZE))
                self._toolbar_was_expanded = False

    def _setup_toolbars(self):
        custom_toolbar = Gtk.Toolbar()
        toolbox = ToolbarBox()
        self._toolbar = toolbox.toolbar
        self._activity_button = ActivityToolbarButton(self)
        self._activity_button.connect('clicked', self._update_graphics)
        self._toolbar.insert(self._activity_button, 0)
        self._activity_button.show()

        self._custom_toolbar_button = ToolbarButton(label=_('Custom'),
                                                    page=custom_toolbar,
                                                    icon_name='view-source')
        self._custom_toolbar_button.connect('clicked', self._update_graphics)
        custom_toolbar.show()
        self._toolbar.insert(self._custom_toolbar_button, -1)
        self._custom_toolbar_button.show()

        self._load_standard_buttons(self._toolbar)

        self._separator = Gtk.SeparatorToolItem()
        self._separator.props.draw = False
        self._separator.set_expand(True)
        self._toolbar.insert(self._separator, -1)
        self._separator.show()

        stop_button = StopButton(self)
        stop_button.props.accelerator = _('<Ctrl>Q')
        self._toolbar.insert(stop_button, -1)
        stop_button.show()
        self.set_toolbar_box(toolbox)
        toolbox.show()

        self._load_custom_buttons(custom_toolbar)

    def _load_standard_buttons(self, toolbar):
        fraction_button = RadioToolButton(group=None)
        fraction_button.set_icon_name('fraction')
        fraction_button.set_tooltip(_('fractions'))
        fraction_button.connect('clicked', self._fraction_cb)
        toolbar.insert(fraction_button, -1)
        fraction_button.show()

        sector_button = RadioToolButton(group=fraction_button)
        sector_button.set_icon_name('sector')
        sector_button.set_tooltip(_('sectors'))
        sector_button.connect('clicked', self._sector_cb)
        toolbar.insert(sector_button, -1)
        sector_button.show()

        percent_button = RadioToolButton(group=fraction_button)
        percent_button.set_icon_name('percent')
        percent_button.set_tooltip(_('percents'))
        percent_button.connect('clicked', self._percent_cb)
        toolbar.insert(percent_button, -1)
        percent_button.show()

        self._player = Gtk.Image()
        self._player.set_from_pixbuf(
            svg_str_to_pixbuf(
                generate_xo_svg(scale=0.8, colors=['#282828', '#282828'])))
        self._player.set_tooltip_text(self.nick)
        toolitem = Gtk.ToolItem()
        toolitem.add(self._player)
        self._player.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        self._label = Gtk.Label(_("Click the ball to start."))
        self._label.set_line_wrap(True)
        if Gdk.Screen.width() < 1024:
            self._label.set_size_request(275, -1)
        else:
            self._label.set_size_request(500, -1)
        self.toolitem = Gtk.ToolItem()
        self.toolitem.add(self._label)
        self._label.show()
        toolbar.insert(self.toolitem, -1)
        self.toolitem.show()

    def _load_custom_buttons(self, toolbar):
        self.numerator = Gtk.Entry()
        self.numerator.set_text('')
        self.numerator.set_tooltip_text(_('numerator'))
        self.numerator.set_width_chars(3)
        toolitem = Gtk.ToolItem()
        toolitem.add(self.numerator)
        self.numerator.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        label = Gtk.Label('   /   ')
        toolitem = Gtk.ToolItem()
        toolitem.add(label)
        label.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        self.denominator = Gtk.Entry()
        self.denominator.set_text('')
        self.denominator.set_tooltip_text(_('denominator'))
        self.denominator.set_width_chars(3)
        toolitem = Gtk.ToolItem()
        toolitem.add(self.denominator)
        self.denominator.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        button = ToolButton('list-add')
        button.set_tooltip(_('add new fraction'))
        button.props.sensitive = True
        button.props.accelerator = 'Return'
        button.connect('clicked', self._add_fraction_cb)
        toolbar.insert(button, -1)
        button.show()

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

        button = ToolButton('soccerball')
        button.set_tooltip(_('choose a ball'))
        button.props.sensitive = True
        button.connect('clicked', self._button_palette_cb)
        toolbar.insert(button, -1)
        button.show()
        self._ball_palette = button.get_palette()
        button_grid = Gtk.Grid()
        row = 0
        for ball in BALLDICT.keys():
            if ball == 'custom':
                button = ToolButton('view-source')
            else:
                button = ToolButton(ball)
            button.connect('clicked', self._load_ball_cb, None, ball)
            eventbox = Gtk.EventBox()
            eventbox.connect('button_press_event', self._load_ball_cb, ball)
            label = Gtk.Label(BALLDICT[ball][0])
            eventbox.add(label)
            label.show()
            button_grid.attach(button, 0, row, 1, 1)
            button.show()
            button_grid.attach(eventbox, 1, row, 1, 1)
            eventbox.show()
            row += 1
        self._ball_palette.set_content(button_grid)
        button_grid.show()

        button = ToolButton('insert-picture')
        button.set_tooltip(_('choose a background'))
        button.props.sensitive = True
        button.connect('clicked', self._button_palette_cb)
        toolbar.insert(button, -1)
        button.show()
        self._bg_palette = button.get_palette()
        button_grid = Gtk.Grid()
        row = 0
        for bg in BGDICT.keys():
            if bg == 'custom':
                button = ToolButton('view-source')
            else:
                button = ToolButton(bg)
            button.connect('clicked', self._load_bg_cb, None, bg)
            eventbox = Gtk.EventBox()
            eventbox.connect('button_press_event', self._load_bg_cb, bg)
            label = Gtk.Label(BGDICT[bg][0])
            eventbox.add(label)
            label.show()
            button_grid.attach(button, 0, row, 1, 1)
            button.show()
            button_grid.attach(eventbox, 1, row, 1, 1)
            eventbox.show()
            row += 1
        self._bg_palette.set_content(button_grid)
        button_grid.show()

    def _button_palette_cb(self, button):
        palette = button.get_palette()
        if palette:
            if not palette.is_up():
                palette.popup(immediate=True, state=palette.SECONDARY)
            else:
                palette.popdown(immediate=True)

    def can_close(self):
        # Let everyone know we are leaving...
        if hasattr(self, '_bounce_window') and \
           self._bounce_window.we_are_sharing():
            self._playing = False
            self.send_event('l|%s' % (json_dump([self.nick])))
        return True

    def _setup_canvas(self):
        canvas = Gtk.DrawingArea()
        canvas.set_size_request(Gdk.Screen.width(), Gdk.Screen.height())
        self.set_canvas(canvas)
        canvas.show()
        return canvas

    def _load_bg_cb(self, widget, event, bg):
        if bg == 'custom':
            chooser(self, 'Image', self._new_background_from_journal)
        else:
            self._bounce_window.set_background(BGDICT[bg][1])

    def _load_ball_cb(self, widget, event, ball):
        if ball == 'custom':
            chooser(self, 'Image', self._new_ball_from_journal)
        else:
            self._bounce_window.ball.new_ball(
                os.path.join(activity.get_bundle_path(), 'images',
                             ball + '.svg'))
            self._bounce_window.set_background(BGDICT[BALLDICT[ball][1]][1])
        self._current_ball = ball

    def _reset_ball(self):
        ''' If we switch back from sector mode, we need to restore the ball '''
        if self._bounce_window.mode != 'sectors':
            return

        if self._current_ball == 'custom':  # TODO: Reload custom ball
            self._current_ball = 'soccerball'
        self._bounce_window.ball.new_ball(
            os.path.join(activity.get_bundle_path(), 'images',
                         self._current_ball + '.svg'))

    def _new_ball_from_journal(self, dsobject):
        ''' Load an image from the Journal. '''
        self._bounce_window.ball.new_ball_from_image(
            dsobject.file_path,
            os.path.join(activity.get_activity_root(), 'tmp', 'custom.png'))

    def _new_background_from_journal(self, dsobject):
        ''' Load an image from the Journal. '''
        self._bounce_window.new_background_from_image(None, dsobject=dsobject)

    def _fraction_cb(self, arg=None):
        ''' Set fraction mode '''
        self._reset_ball()
        self._bounce_window.mode = 'fractions'

    def _percent_cb(self, arg=None):
        ''' Set percent mode '''
        self._reset_ball()
        self._bounce_window.mode = 'percents'

    def _sector_cb(self, arg=None):
        ''' Set sector mode '''
        self._bounce_window.mode = 'sectors'

    def _add_fraction_cb(self, arg=None):
        ''' Read entries and add a fraction to the list '''
        try:
            numerator = int(self.numerator.get_text().strip())
        except ValueError:
            self.numerator.set_text('NAN')
            numerator = 0
        try:
            denominator = int(self.denominator.get_text().strip())
        except ValueError:
            self.denominator.set_text('NAN')
            denominator = 1
        if denominator == 0:
            self.denominator.set_text('ZDE')
        if numerator > denominator:
            numerator = 0
        if numerator > 0 and denominator > 1:
            fraction = '%d/%d' % (numerator, denominator)
            self._bounce_window.add_fraction(fraction)
            if 'custom' in self.metadata:  # Save to Journal
                self.metadata['custom'] = '%s,%s' % (self.metadata['custom'],
                                                     fraction)
            else:
                self.metadata['custom'] = fraction

            self.alert(
                _('New fraction'),
                _('Your fraction, %s, has been added to the program' %
                  (fraction)))

    def reset_label(self, label):
        ''' update the challenge label '''
        self._label.set_label(label)

    def alert(self, title, text=None):
        alert = NotifyAlert(timeout=5)
        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)

    # Collaboration-related methods

    def _setup_sharing(self):
        ''' Setup the Presence Service. '''
        self.pservice = presenceservice.get_instance()
        self.initiating = None  # sharing (True) or joining (False)

        owner = self.pservice.get_owner()
        self.owner = owner
        self._bounce_window.buddies.append(self.nick)
        self._player_colors = [self._colors]
        self._player_pixbufs = [
            svg_str_to_pixbuf(generate_xo_svg(scale=0.8, colors=self._colors))
        ]
        self._share = ''
        self.connect('shared', self._shared_cb)
        self.connect('joined', self._joined_cb)

    def _shared_cb(self, activity):
        ''' Either set up initial share...'''
        self._new_tube_common(True)

    def _joined_cb(self, activity):
        ''' ...or join an exisiting share. '''
        self._new_tube_common(False)

    def _new_tube_common(self, sharer):
        ''' Joining and sharing are mostly the same... '''
        if self.shared_activity is None:
            _logger.debug('Error: Failed to share or join activity ... \
                shared_activity is null in _shared_cb()')
            return

        self.initiating = sharer
        self.waiting_for_fraction = not sharer

        self.conn = self.shared_activity.telepathy_conn
        self.tubes_chan = self.shared_activity.telepathy_tubes_chan
        self.text_chan = self.shared_activity.telepathy_text_chan

        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
            'NewTube', self._new_tube_cb)

        if sharer:
            _logger.debug('This is my activity: making a tube...')
            id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(
                SERVICE, {})

            self._label.set_label(_('Wait for others to join.'))
        else:
            _logger.debug('I am joining an activity: waiting for a tube...')
            self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
                reply_handler=self._list_tubes_reply_cb,
                error_handler=self._list_tubes_error_cb)

        # display your XO on the toolbar
        self._player.set_from_pixbuf(self._player_pixbufs[0])

    def _list_tubes_reply_cb(self, tubes):
        ''' Reply to a list request. '''
        for tube_info in tubes:
            self._new_tube_cb(*tube_info)

    def _list_tubes_error_cb(self, e):
        ''' Log errors. '''
        _logger.debug('Error: ListTubes() failed: %s', e)

    def _new_tube_cb(self, id, initiator, type, service, params, state):
        ''' Create a new tube. '''
        _logger.debug(
            'Newtube: ID=%d initator=%d type=%d service=%s params=%r state=%d',
            id, initiator, type, service, params, state)

        if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE):
            if state == telepathy.TUBE_STATE_LOCAL_PENDING:
                self.tubes_chan[ \
                              telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id)

            tube_conn = TubeConnection(self.conn,
                self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id, \
                group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP])

            self.chattube = ChatTube(tube_conn, self.initiating, \
                self.event_received_cb)

            # Let the sharer know a new joiner has arrived.
            if self.waiting_for_fraction:
                self.send_event('j|%s' %
                                (json_dump([self.nick, self._colors])))

    def _setup_dispatch_table(self):
        self._processing_methods = {
            'j': [self._new_joiner, 'new joiner'],
            'b': [self._buddy_list, 'buddy list'],
            'f': [self._receive_a_fraction, 'receive a fraction'],
            't': [self._take_a_turn, 'take a turn'],
            'l': [self._buddy_left, 'buddy left']
        }

    def event_received_cb(self, event_message):
        ''' Data from a tube has arrived. '''
        if len(event_message) == 0:
            return
        try:
            command, payload = event_message.split('|', 2)
        except ValueError:
            _logger.debug('Could not split event message %s', event_message)
            return
        _logger.debug('received an event %s|%s', command, payload)
        if self._playing:
            self._processing_methods[command][0](payload)

    def _buddy_left(self, payload):
        [nick] = json_load(payload)
        self._label.set_label(nick + ' ' + _('has left.'))
        if self.initiating:
            self._remove_player(nick)
            payload = json_dump(
                [self._bounce_window.buddies, self._player_colors])
            self.send_event('b|%s' % (payload))
            # Restart from sharer's turn
            self._bounce_window.its_my_turn()

    def _new_joiner(self, payload):
        ''' Someone has joined; sharer adds them to the buddy list. '''
        [nick, colors] = json_load(payload)
        self._label.set_label(nick + ' ' + _('has joined.'))
        if self.initiating:
            self._append_player(nick, colors)
            payload = json_dump(
                [self._bounce_window.buddies, self._player_colors])
            self.send_event('b|%s' % (payload))
            if self._bounce_window.count == 0:  # Haven't started yet...
                self._bounce_window.its_my_turn()

    def _remove_player(self, nick):
        if nick in self._bounce_window.buddies:
            i = self._bounce_window.buddies.index(nick)
            self._bounce_window.buddies.remove(nick)
            self._player_colors.remove(self._player_colors[i])
            self._player_pixbufs.remove(self._player_pixbufs[i])

    def _append_player(self, nick, colors):
        ''' Keep a list of players, their colors, and an XO pixbuf '''
        if not nick in self._bounce_window.buddies:
            _logger.debug('appending %s to the buddy list', nick)
            self._bounce_window.buddies.append(nick)
            self._player_colors.append([str(colors[0]), str(colors[1])])
            self._player_pixbufs.append(
                svg_str_to_pixbuf(
                    generate_xo_svg(scale=0.8,
                                    colors=self._player_colors[-1])))

    def _buddy_list(self, payload):
        '''Sharer sent the updated buddy list, so regenerate internal lists'''
        if not self.initiating:
            [buddies, colors] = json_load(payload)
            self._bounce_window.buddies = buddies[:]
            self._player_colors = colors[:]
            self._player_pixbufs = []
            for colors in self._player_colors:
                self._player_pixbufs.append(
                    svg_str_to_pixbuf(
                        generate_xo_svg(
                            scale=0.8, colors=[str(colors[0]),
                                               str(colors[1])])))

    def send_a_fraction(self, fraction):
        ''' Send a fraction to other players. '''
        payload = json_dump(fraction)
        self.send_event('f|%s' % (payload))

    def _receive_a_fraction(self, payload):
        ''' Receive a fraction from another player. '''
        fraction = json_load(payload)
        self._bounce_window.play_a_fraction(fraction)

    def _take_a_turn(self, nick):
        ''' If it is your turn, take it, otherwise, wait. '''
        if nick == self.nick:
            self._bounce_window.its_my_turn()
        else:
            self._bounce_window.its_their_turn(nick)

    def send_event(self, entry):
        ''' Send event through the tube. '''
        _logger.debug('sending event: %s', entry)
        if hasattr(self, 'chattube') and self.chattube is not None:
            self.chattube.SendText(entry)

    def set_player_on_toolbar(self, nick):
        ''' Display the XO icon of the player whose turn it is. '''
        self._player.set_from_pixbuf(
            self._player_pixbufs[self._bounce_window.buddies.index(nick)])
        self._player.set_tooltip_text(nick)
Ejemplo n.º 51
0
class AbiWordActivity(activity.Activity):

    def __init__(self, handle):
        activity.Activity.__init__(self, handle)

        # abiword uses the current directory for all its file dialogs
        os.chdir(os.path.expanduser('~'))

        # create our main abiword canvas
        self.abiword_canvas = DocumentView()
        self._new_instance = True
        toolbar_box = ToolbarBox()

        self.activity_button = ActivityToolbarButton(self)
        toolbar_box.toolbar.insert(self.activity_button, -1)

        separator = Gtk.SeparatorToolItem()
        separator.show()
        self.activity_button.props.page.insert(separator, 2)
        ExportButtonFactory(self, self.abiword_canvas)
        self.activity_button.show()

        edit_toolbar = ToolbarButton()
        edit_toolbar.props.page = EditToolbar(self, toolbar_box)
        edit_toolbar.props.icon_name = 'toolbar-edit'
        edit_toolbar.props.label = _('Edit')
        toolbar_box.toolbar.insert(edit_toolbar, -1)

        view_toolbar = ToolbarButton()
        view_toolbar.props.page = ViewToolbar(self.abiword_canvas)
        view_toolbar.props.icon_name = 'toolbar-view'
        view_toolbar.props.label = _('View')
        toolbar_box.toolbar.insert(view_toolbar, -1)

        # due to http://bugzilla.abisource.com/show_bug.cgi?id=13585
        if self.abiword_canvas.get_version() != '3.0':
            self.speech_toolbar_button = ToolbarButton(icon_name='speak')
            toolbar_box.toolbar.insert(self.speech_toolbar_button, -1)
            self._init_speech()

        separator = Gtk.SeparatorToolItem()
        toolbar_box.toolbar.insert(separator, -1)

        text_toolbar = ToolbarButton()
        text_toolbar.props.page = TextToolbar(self.abiword_canvas)
        text_toolbar.props.icon_name = 'format-text'
        text_toolbar.props.label = _('Text')
        toolbar_box.toolbar.insert(text_toolbar, -1)

        para_toolbar = ToolbarButton()
        para_toolbar.props.page = ParagraphToolbar(self.abiword_canvas)
        para_toolbar.props.icon_name = 'paragraph-bar'
        para_toolbar.props.label = _('Paragraph')
        toolbar_box.toolbar.insert(para_toolbar, -1)

        insert_toolbar = ToolbarButton()
        insert_toolbar.props.page = InsertToolbar(self.abiword_canvas)
        insert_toolbar.props.icon_name = 'insert-table'
        insert_toolbar.props.label = _('Table')
        toolbar_box.toolbar.insert(insert_toolbar, -1)

        image = ToolButton('insert-picture')
        image.set_tooltip(_('Insert Image'))
        self._image_id = image.connect('clicked', self._image_cb)
        toolbar_box.toolbar.insert(image, -1)

        palette = image.get_palette()
        content_box = Gtk.VBox()
        palette.set_content(content_box)
        image_floating_checkbutton = Gtk.CheckButton(_('Floating'))
        image_floating_checkbutton.connect(
            'toggled', self._image_floating_checkbutton_toggled_cb)
        content_box.pack_start(image_floating_checkbutton, True, True, 0)
        content_box.show_all()
        self.floating_image = False

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

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

        toolbar_box.show_all()
        self.set_toolbar_box(toolbar_box)

        # add a overlay to be able to show a icon while joining a shared doc
        overlay = Gtk.Overlay()
        overlay.add(self.abiword_canvas)
        overlay.show()

        self._connecting_box = ConnectingBox()
        overlay.add_overlay(self._connecting_box)

        self.set_canvas(overlay)

        # we want a nice border so we can select paragraphs easily
        self.abiword_canvas.set_show_margin(True)

        # Read default font face and size
        client = GConf.Client.get_default()
        self._default_font_face = client.get_string(
            '/desktop/sugar/activities/write/font_face')
        if not self._default_font_face:
            self._default_font_face = 'Sans'
        self._default_font_size = client.get_int(
            '/desktop/sugar/activities/write/font_size')
        if self._default_font_size == 0:
            self._default_font_size = 12

        # activity sharing
        self.participants = {}
        self.joined = False

        self.connect('shared', self._shared_cb)

        if self.shared_activity:
            # we are joining the activity
            logger.error('We are joining an activity')
            # display a icon while joining
            self._connecting_box.show()
            # disable the abi widget
            self.abiword_canvas.set_sensitive(False)
            self._new_instance = False
            self.connect('joined', self._joined_cb)
            self.shared_activity.connect('buddy-joined',
                                         self._buddy_joined_cb)
            self.shared_activity.connect('buddy-left', self._buddy_left_cb)
            if self.get_shared():
                self._joined_cb(self)
        else:
            # we are creating the activity
            logger.error("We are creating an activity")

        self.abiword_canvas.zoom_width()
        self.abiword_canvas.show()
        self.connect_after('map-event', self.__map_activity_event_cb)

        self.abiword_canvas.connect('size-allocate', self.size_allocate_cb)

    def _init_speech(self):
        import speech
        from speechtoolbar import SpeechToolbar
        if speech.supported:
            self.speech_toolbar = SpeechToolbar(self)
            self.speech_toolbar_button.set_page(self.speech_toolbar)
            self.speech_toolbar_button.show()

    def size_allocate_cb(self, abi, alloc):
        GObject.idle_add(abi.queue_draw)

    def __map_activity_event_cb(self, event, activity):
        # set custom keybindings for Write
        # we do it later because have problems if done before - OLPC #11049
        logger.error('Loading keybindings')
        keybindings_file = os.path.join(get_bundle_path(), 'keybindings.xml')
        self.abiword_canvas.invoke_ex(
            'com.abisource.abiword.loadbindings.fromURI',
            keybindings_file, 0, 0)
        # set default font
        if self._new_instance:
            self.abiword_canvas.select_all()
            logging.error('Setting default font to %s %d in new documents',
                          self._default_font_face, self._default_font_size)
            self.abiword_canvas.set_font_name(self._default_font_face)
            self.abiword_canvas.set_font_size(str(self._default_font_size))
            self.abiword_canvas.moveto_bod()
            self.abiword_canvas.select_bod()
        if hasattr(self.abiword_canvas, 'toggle_rulers'):
            # this is not available yet on upstream abiword
            self.abiword_canvas.view_print_layout()
            self.abiword_canvas.toggle_rulers(False)

        self.abiword_canvas.grab_focus()

    def get_preview(self):
        if not hasattr(self.abiword_canvas, 'render_page_to_image'):
            return activity.Activity.get_preview(self)

        from gi.repository import GdkPixbuf

        pixbuf = self.abiword_canvas.render_page_to_image(1)
        pixbuf = pixbuf.scale_simple(style.zoom(300), style.zoom(225),
                                     GdkPixbuf.InterpType.BILINEAR)

        preview_data = []

        def save_func(buf, lenght, data):
            data.append(buf)
            return True

        pixbuf.save_to_callbackv(save_func, preview_data, 'png', [], [])
        preview_data = ''.join(preview_data)

        return preview_data

    def _shared_cb(self, activity):
        logger.error('My Write activity was shared')
        self._sharing_setup()

        self.shared_activity.connect('buddy-joined', self._buddy_joined_cb)
        self.shared_activity.connect('buddy-left', self._buddy_left_cb)

        channel = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES]
        logger.error('This is my activity: offering a tube...')
        id = channel.OfferDBusTube('com.abisource.abiword.abicollab', {})
        logger.error('Tube address: %s', channel.GetDBusTubeAddress(id))

    def _sharing_setup(self):
        logger.debug("_sharing_setup()")

        if self.shared_activity is None:
            logger.error('Failed to share or join activity')
            return

        self.conn = self.shared_activity.telepathy_conn
        self.tubes_chan = self.shared_activity.telepathy_tubes_chan
        self.text_chan = self.shared_activity.telepathy_text_chan
        self.tube_id = None
        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
            'NewTube', self._new_tube_cb)

    def _list_tubes_reply_cb(self, tubes):
        for tube_info in tubes:
            self._new_tube_cb(*tube_info)

    def _list_tubes_error_cb(self, e):
        logger.error('ListTubes() failed: %s', e)

    def _joined_cb(self, activity):
        logger.error("_joined_cb()")
        if not self.shared_activity:
            self._enable_collaboration()
            return

        self.joined = True
        logger.error('Joined an existing Write session')
        self._sharing_setup()

        logger.error('This is not my activity: waiting for a tube...')
        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
            reply_handler=self._list_tubes_reply_cb,
            error_handler=self._list_tubes_error_cb)
        self._enable_collaboration()

    def _enable_collaboration(self):
        """
        when communication established, hide the download icon
        and enable the abi widget
        """
        self.abiword_canvas.zoom_width()
        self.abiword_canvas.set_sensitive(True)
        self._connecting_box.hide()

    def _new_tube_cb(self, id, initiator, type, service, params, state):
        logger.error('New tube: ID=%d initiator=%d type=%d service=%s '
                     'params=%r state=%d', id, initiator, type, service,
                     params, state)

        if self.tube_id is not None:
            # We are already using a tube
            return

        if type != telepathy.TUBE_TYPE_DBUS or \
                service != "com.abisource.abiword.abicollab":
            return

        channel = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES]

        if state == telepathy.TUBE_STATE_LOCAL_PENDING:
            channel.AcceptDBusTube(id)

        # look for the initiator's D-Bus unique name
        initiator_dbus_name = None
        dbus_names = channel.GetDBusNames(id)
        for handle, name in dbus_names:
            if handle == initiator:
                logger.error('found initiator D-Bus name: %s', name)
                initiator_dbus_name = name
                break

        if initiator_dbus_name is None:
            logger.error('Unable to get the D-Bus name of the tube initiator')
            return

        cmd_prefix = 'com.abisource.abiword.abicollab.olpc.'
        # pass this tube to abicollab
        address = channel.GetDBusTubeAddress(id)
        if self.joined:
            logger.error('Passing tube address to abicollab (join): %s',
                         address)
            self.abiword_canvas.invoke_ex(cmd_prefix + 'joinTube',
                                          address, 0, 0)
            # The intiator of the session has to be the first passed
            # to the Abicollab backend.
            logger.error('Adding the initiator to the session: %s',
                         initiator_dbus_name)
            self.abiword_canvas.invoke_ex(cmd_prefix + 'buddyJoined',
                                          initiator_dbus_name, 0, 0)
        else:
            logger.error('Passing tube address to abicollab (offer): %s',
                         address)
            self.abiword_canvas.invoke_ex(cmd_prefix + 'offerTube', address,
                                          0, 0)
        self.tube_id = id

        channel.connect_to_signal('DBusNamesChanged',
                                  self._on_dbus_names_changed)

        self._on_dbus_names_changed(id, dbus_names, [])

    def _on_dbus_names_changed(self, tube_id, added, removed):
        """
        We call com.abisource.abiword.abicollab.olpc.buddy{Joined,Left}
        according members of the D-Bus tube. That's why we don't add/remove
        buddies in _buddy_{joined,left}_cb.
        """
        logger.error('_on_dbus_names_changed')
#        if tube_id == self.tube_id:
        cmd_prefix = 'com.abisource.abiword.abicollab.olpc'
        for handle, bus_name in added:
            logger.error('added handle: %s, with dbus_name: %s',
                         handle, bus_name)
            self.abiword_canvas.invoke_ex(cmd_prefix + '.buddyJoined',
                                          bus_name, 0, 0)
            self.participants[handle] = bus_name

    def _on_members_changed(self, message, added, removed, local_pending,
                            remote_pending, actor, reason):
        logger.error("_on_members_changed")
        for handle in removed:
            bus_name = self.participants.pop(handle, None)
            if bus_name is None:
                # FIXME: that shouldn't happen so probably hide another bug.
                # Should be investigated
                continue

            cmd_prefix = 'com.abisource.abiword.abicollab.olpc'
            logger.error('removed handle: %d, with dbus name: %s', handle,
                         bus_name)
            self.abiword_canvas.invoke_ex(cmd_prefix + '.buddyLeft',
                                          bus_name, 0, 0)

    def _buddy_joined_cb(self, activity, buddy):
        logger.error('buddy joined with object path: %s', buddy.object_path())

    def _buddy_left_cb(self, activity, buddy):
        logger.error('buddy left with object path: %s', buddy.object_path())

    def read_file(self, file_path):
        logging.debug('AbiWordActivity.read_file: %s, mimetype: %s',
                      file_path, self.metadata['mime_type'])
        if self._is_plain_text(self.metadata['mime_type']):
            self.abiword_canvas.load_file('file://' + file_path, 'text/plain')
        else:
            # we pass no mime/file type, let libabiword autodetect it,
            # so we can handle multiple file formats
            self.abiword_canvas.load_file('file://' + file_path, '')
        self.abiword_canvas.zoom_width()
        self._new_instance = False

    def write_file(self, file_path):
        logging.debug('AbiWordActivity.write_file: %s, mimetype: %s',
                      file_path, self.metadata['mime_type'])
        # if we were editing a text file save as plain text
        if self._is_plain_text(self.metadata['mime_type']):
            logger.debug('Writing file as type source (text/plain)')
            self.abiword_canvas.save('file://' + file_path, 'text/plain', '')
        else:
            #if the file is new, save in .odt format
            if self.metadata['mime_type'] == '':
                self.metadata['mime_type'] = 'application/rtf'

            # Abiword can't save in .doc format, save in .rtf instead
            if self.metadata['mime_type'] == 'application/msword':
                self.metadata['mime_type'] = 'application/rtf'

            self.abiword_canvas.save('file://' + file_path,
                                     self.metadata['mime_type'], '')

        # due to http://bugzilla.abisource.com/show_bug.cgi?id=13585
        if self.abiword_canvas.get_version() != '3.0':
            self.metadata['fulltext'] = self.abiword_canvas.get_content(
                'text/plain', None)[:3000]

    def _is_plain_text(self, mime_type):
        # These types have 'text/plain' in their mime_parents  but we need
        # use it like rich text
        if mime_type in ['application/rtf', 'text/rtf', 'text/html']:
            return False

        from sugar3 import mime

        mime_parents = mime.get_mime_parents(self.metadata['mime_type'])
        return self.metadata['mime_type'] in ['text/plain', 'text/csv'] or \
            'text/plain' in mime_parents

    def _image_floating_checkbutton_toggled_cb(self, checkbutton):
        self.floating_image = checkbutton.get_active()

    def _image_cb(self, button):
        try:
            chooser = ObjectChooser(self, what_filter='Image',
                                    filter_type=FILTER_TYPE_GENERIC_MIME,
                                    show_preview=True)
        except:
            # for compatibility with older versions
            chooser = ObjectChooser(self, what_filter='Image')

        try:
            result = chooser.run()
            if result == Gtk.ResponseType.ACCEPT:
                logging.debug('ObjectChooser: %r',
                              chooser.get_selected_object())
                jobject = chooser.get_selected_object()
                if jobject and jobject.file_path:
                    self.abiword_canvas.insert_image(jobject.file_path,
                                                     self.floating_image)
        finally:
            chooser.destroy()
            del chooser
Ejemplo n.º 52
0
class FractionBounceActivity(activity.Activity):
    def __init__(self, handle):
        ''' Initiate activity. '''
        super(FractionBounceActivity, self).__init__(handle)

        self.nick = profile.get_nick_name()
        if profile.get_color() is not None:
            self._colors = profile.get_color().to_string().split(',')
        else:
            self._colors = ['#A0FFA0', '#FF8080']

        self.max_participants = 4  # sharing
        self._playing = True

        self._setup_toolbars()
        canvas = self._setup_canvas()

        # Read any custom fractions from the project metadata
        if 'custom' in self.metadata:
            custom = self.metadata['custom']
        else:
            custom = None

        self._current_ball = 'soccerball'

        self._toolbar_was_expanded = False

        # Initialize the canvas
        self._bounce_window = Bounce(canvas, activity.get_bundle_path(), self)

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)

        # Restore any custom fractions
        if custom is not None:
            fractions = custom.split(',')
            for f in fractions:
                self._bounce_window.add_fraction(f)

        self._bounce_window.buddies.append(self.nick)
        self._player_colors = [self._colors]
        self._player_pixbufs = [
            svg_str_to_pixbuf(generate_xo_svg(scale=0.8, colors=self._colors))
        ]

        def on_activity_joined_cb(me):
            logging.debug('activity joined')
            self._player.set_from_pixbuf(self._player_pixbufs[0])

        self.connect('joined', on_activity_joined_cb)

        def on_activity_shared_cb(me):
            logging.debug('activity shared')
            self._player.set_from_pixbuf(self._player_pixbufs[0])
            self._label.set_label(_('Wait for others to join.'))

        self.connect('shared', on_activity_shared_cb)

        self._collab = CollabWrapper(self)

        if self.shared_activity:
            # We're joining
            if not self.get_shared():
                self._label.set_label(_('Wait for the sharer to start.'))

        actions = {
            'j': self._new_joiner,
            'b': self._buddy_list,
            'f': self._receive_a_fraction,
            't': self._take_a_turn,
            'l': self._buddy_left,
        }

        def on_message_cb(collab, buddy, msg):
            logging.debug('on_message_cb buddy %r msg %r' % (buddy, msg))
            if self._playing:
                actions[msg.get('action')](msg.get('data'))

        self._collab.connect('message', on_message_cb)

        def on_joined_cb(collab, msg):
            logging.debug('joined')
            self.send_event('j', [self.nick, self._colors])

        self._collab.connect('joined', on_joined_cb, 'joined')

        def on_buddy_joined_cb(collab, buddy, msg):
            logging.debug('on_buddy_joined_cb buddy %r' % (buddy.props.nick))

        self._collab.connect('buddy_joined', on_buddy_joined_cb,
                             'buddy_joined')

        def on_buddy_left_cb(collab, buddy, msg):
            logging.debug('on_buddy_left_cb buddy %r' % (buddy.props.nick))

        self._collab.connect('buddy_left', on_buddy_left_cb, 'buddy_left')

        self._collab.setup()

    def set_data(self, blob):
        pass

    def get_data(self):
        return None

    def close(self, **kwargs):
        aplay.close()
        activity.Activity.close(self, **kwargs)

    def _configure_cb(self, event):
        if Gdk.Screen.width() < 1024:
            self._label.set_size_request(275, -1)
            self._label.set_label('')
            self._separator.set_expand(False)
        else:
            self._label.set_size_request(500, -1)
            self._separator.set_expand(True)

        self._bounce_window.configure_cb(event)
        if self._toolbar_expanded():
            self._bounce_window.bar.bump_bars('up')
            self._bounce_window.ball.ball.move_relative(
                (0, -style.GRID_CELL_SIZE))

    def _toolbar_expanded(self):
        if self._activity_button.is_expanded():
            return True
        elif self._custom_toolbar_button.is_expanded():
            return True
        return False

    def _update_graphics(self, widget):
        # We need to catch opening and closing of toolbars and ignore
        # switching between open toolbars.
        if self._toolbar_expanded():
            if not self._toolbar_was_expanded:
                self._bounce_window.bar.bump_bars('up')
                self._bounce_window.ball.ball.move_relative(
                    (0, -style.GRID_CELL_SIZE))
                self._toolbar_was_expanded = True
        else:
            if self._toolbar_was_expanded:
                self._bounce_window.bar.bump_bars('down')
                self._bounce_window.ball.ball.move_relative(
                    (0, style.GRID_CELL_SIZE))
                self._toolbar_was_expanded = False

    def _setup_toolbars(self):
        custom_toolbar = Gtk.Toolbar()
        toolbox = ToolbarBox()
        self._toolbar = toolbox.toolbar
        self._activity_button = ActivityToolbarButton(self)
        self._activity_button.connect('clicked', self._update_graphics)
        self._toolbar.insert(self._activity_button, 0)
        self._activity_button.show()

        self._custom_toolbar_button = ToolbarButton(label=_('Custom'),
                                                    page=custom_toolbar,
                                                    icon_name='view-source')
        self._custom_toolbar_button.connect('clicked', self._update_graphics)
        custom_toolbar.show()
        self._toolbar.insert(self._custom_toolbar_button, -1)
        self._custom_toolbar_button.show()

        self._load_standard_buttons(self._toolbar)

        self._separator = Gtk.SeparatorToolItem()
        self._separator.props.draw = False
        self._separator.set_expand(True)
        self._toolbar.insert(self._separator, -1)
        self._separator.show()

        stop_button = StopButton(self)
        stop_button.props.accelerator = _('<Ctrl>Q')
        self._toolbar.insert(stop_button, -1)
        stop_button.show()
        self.set_toolbar_box(toolbox)
        toolbox.show()

        self._load_custom_buttons(custom_toolbar)

    def _load_standard_buttons(self, toolbar):
        fraction_button = RadioToolButton(group=None)
        fraction_button.set_icon_name('fraction')
        fraction_button.set_tooltip(_('fractions'))
        fraction_button.connect('clicked', self._fraction_cb)
        toolbar.insert(fraction_button, -1)
        fraction_button.show()

        sector_button = RadioToolButton(group=fraction_button)
        sector_button.set_icon_name('sector')
        sector_button.set_tooltip(_('sectors'))
        sector_button.connect('clicked', self._sector_cb)
        toolbar.insert(sector_button, -1)
        sector_button.show()

        percent_button = RadioToolButton(group=fraction_button)
        percent_button.set_icon_name('percent')
        percent_button.set_tooltip(_('percents'))
        percent_button.connect('clicked', self._percent_cb)
        toolbar.insert(percent_button, -1)
        percent_button.show()

        self._player = Gtk.Image()
        self._player.set_from_pixbuf(
            svg_str_to_pixbuf(
                generate_xo_svg(scale=0.8, colors=['#282828', '#282828'])))
        self._player.set_tooltip_text(self.nick)
        toolitem = Gtk.ToolItem()
        toolitem.add(self._player)
        self._player.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        self._label = Gtk.Label(_("Click the ball to start."))
        self._label.set_line_wrap(True)
        if Gdk.Screen.width() < 1024:
            self._label.set_size_request(275, -1)
        else:
            self._label.set_size_request(500, -1)
        self.toolitem = Gtk.ToolItem()
        self.toolitem.add(self._label)
        self._label.show()
        toolbar.insert(self.toolitem, -1)
        self.toolitem.show()

    def _load_custom_buttons(self, toolbar):
        self.numerator = Gtk.Entry()
        self.numerator.set_text('')
        self.numerator.set_tooltip_text(_('numerator'))
        self.numerator.set_width_chars(3)
        toolitem = Gtk.ToolItem()
        toolitem.add(self.numerator)
        self.numerator.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        label = Gtk.Label('   /   ')
        toolitem = Gtk.ToolItem()
        toolitem.add(label)
        label.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        self.denominator = Gtk.Entry()
        self.denominator.set_text('')
        self.denominator.set_tooltip_text(_('denominator'))
        self.denominator.set_width_chars(3)
        toolitem = Gtk.ToolItem()
        toolitem.add(self.denominator)
        self.denominator.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        button = ToolButton('list-add')
        button.set_tooltip(_('add new fraction'))
        button.props.sensitive = True
        button.props.accelerator = 'Return'
        button.connect('clicked', self._add_fraction_cb)
        toolbar.insert(button, -1)
        button.show()

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

        button = ToolButton('soccerball')
        button.set_tooltip(_('choose a ball'))
        button.props.sensitive = True
        button.connect('clicked', self._button_palette_cb)
        toolbar.insert(button, -1)
        button.show()
        self._ball_palette = button.get_palette()
        button_grid = Gtk.Grid()
        row = 0
        for ball in BALLDICT.keys():
            if ball == 'custom':
                button = ToolButton('view-source')
            else:
                button = ToolButton(ball)
            button.connect('clicked', self._load_ball_cb, None, ball)
            eventbox = Gtk.EventBox()
            eventbox.connect('button_press_event', self._load_ball_cb, ball)
            label = Gtk.Label(BALLDICT[ball][0])
            eventbox.add(label)
            label.show()
            button_grid.attach(button, 0, row, 1, 1)
            button.show()
            button_grid.attach(eventbox, 1, row, 1, 1)
            eventbox.show()
            row += 1
        self._ball_palette.set_content(button_grid)
        button_grid.show()

        button = ToolButton('insert-picture')
        button.set_tooltip(_('choose a background'))
        button.props.sensitive = True
        button.connect('clicked', self._button_palette_cb)
        toolbar.insert(button, -1)
        button.show()
        self._bg_palette = button.get_palette()
        button_grid = Gtk.Grid()
        row = 0
        for bg in BGDICT.keys():
            if bg == 'custom':
                button = ToolButton('view-source')
            else:
                button = ToolButton(bg)
            button.connect('clicked', self._load_bg_cb, None, bg)
            eventbox = Gtk.EventBox()
            eventbox.connect('button_press_event', self._load_bg_cb, bg)
            label = Gtk.Label(BGDICT[bg][0])
            eventbox.add(label)
            label.show()
            button_grid.attach(button, 0, row, 1, 1)
            button.show()
            button_grid.attach(eventbox, 1, row, 1, 1)
            eventbox.show()
            row += 1
        self._bg_palette.set_content(button_grid)
        button_grid.show()

    def _button_palette_cb(self, button):
        palette = button.get_palette()
        if palette:
            if not palette.is_up():
                palette.popup(immediate=True)
            else:
                palette.popdown(immediate=True)

    def can_close(self):
        # Let everyone know we are leaving...
        if hasattr(self, '_bounce_window') and \
           self._bounce_window.we_are_sharing():
            self._playing = False
            self.send_event('l', self.nick)
        return True

    def _setup_canvas(self):
        canvas = Gtk.DrawingArea()
        canvas.set_size_request(Gdk.Screen.width(), Gdk.Screen.height())
        self.set_canvas(canvas)
        canvas.show()
        return canvas

    def _load_bg_cb(self, widget, event, bg):
        if bg == 'custom':
            chooser(self, 'Image', self._new_background_from_journal)
        else:
            self._bounce_window.set_background(BGDICT[bg][1])

    def _load_ball_cb(self, widget, event, ball):
        if ball == 'custom':
            chooser(self, 'Image', self._new_ball_from_journal)
        else:
            self._bounce_window.ball.new_ball(
                os.path.join(activity.get_bundle_path(), 'images',
                             ball + '.svg'))
            self._bounce_window.set_background(BGDICT[BALLDICT[ball][1]][1])
        self._current_ball = ball

    def _reset_ball(self):
        ''' If we switch back from sector mode, we need to restore the ball '''
        if self._bounce_window.mode != 'sectors':
            return

        if self._current_ball == 'custom':  # TODO: Reload custom ball
            self._current_ball = 'soccerball'
        self._bounce_window.ball.new_ball(
            os.path.join(activity.get_bundle_path(), 'images',
                         self._current_ball + '.svg'))

    def _new_ball_from_journal(self, dsobject):
        ''' Load an image from the Journal. '''
        self._bounce_window.ball.new_ball_from_image(
            dsobject.file_path,
            os.path.join(activity.get_activity_root(), 'tmp', 'custom.png'))

    def _new_background_from_journal(self, dsobject):
        ''' Load an image from the Journal. '''
        self._bounce_window.new_background_from_image(None, dsobject=dsobject)

    def _fraction_cb(self, arg=None):
        ''' Set fraction mode '''
        self._reset_ball()
        self._bounce_window.mode = 'fractions'

    def _percent_cb(self, arg=None):
        ''' Set percent mode '''
        self._reset_ball()
        self._bounce_window.mode = 'percents'

    def _sector_cb(self, arg=None):
        ''' Set sector mode '''
        self._bounce_window.mode = 'sectors'

    def _add_fraction_cb(self, arg=None):
        ''' Read entries and add a fraction to the list '''
        try:
            numerator = int(self.numerator.get_text().strip())
        except ValueError:
            self.numerator.set_text('NAN')
            numerator = 0
        try:
            denominator = int(self.denominator.get_text().strip())
        except ValueError:
            self.denominator.set_text('NAN')
            denominator = 1
        if denominator == 0:
            self.denominator.set_text('ZDE')
        if numerator > denominator:
            numerator = 0
        if numerator > 0 and denominator > 1:
            fraction = '%d/%d' % (numerator, denominator)
            self._bounce_window.add_fraction(fraction)
            if 'custom' in self.metadata:  # Save to Journal
                self.metadata['custom'] = '%s,%s' % (self.metadata['custom'],
                                                     fraction)
            else:
                self.metadata['custom'] = fraction

            self.alert(
                _('New fraction'),
                _('Your fraction, %s, has been added to the program' %
                  (fraction)))

    def reset_label(self, label):
        ''' update the challenge label '''
        self._label.set_label(label)

    def alert(self, title, text=None):
        alert = NotifyAlert(timeout=5)
        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)

    # Collaboration-related methods

    def _buddy_left(self, nick):
        self._label.set_label(nick + ' ' + _('has left.'))
        if self._collab.props.leader:
            self._remove_player(nick)
            self.send_event('b',
                            [self._bounce_window.buddies, self._player_colors])
            # Restart from sharer's turn
            self._bounce_window.its_my_turn()

    def _new_joiner(self, payload):
        ''' Someone has joined; sharer adds them to the buddy list. '''
        [nick, colors] = payload
        self._label.set_label(nick + ' ' + _('has joined.'))
        if self._collab.props.leader:
            self._append_player(nick, colors)
            self.send_event('b',
                            [self._bounce_window.buddies, self._player_colors])
            if self._bounce_window.count == 0:  # Haven't started yet...
                self._bounce_window.its_my_turn()

    def _remove_player(self, nick):
        if nick in self._bounce_window.buddies:
            i = self._bounce_window.buddies.index(nick)
            self._bounce_window.buddies.remove(nick)
            self._player_colors.remove(self._player_colors[i])
            self._player_pixbufs.remove(self._player_pixbufs[i])

    def _append_player(self, nick, colors):
        ''' Keep a list of players, their colors, and an XO pixbuf '''
        if nick not in self._bounce_window.buddies:
            _logger.debug('appending %s to the buddy list', nick)
            self._bounce_window.buddies.append(nick)
            self._player_colors.append([str(colors[0]), str(colors[1])])
            self._player_pixbufs.append(
                svg_str_to_pixbuf(
                    generate_xo_svg(scale=0.8,
                                    colors=self._player_colors[-1])))

    def _buddy_list(self, payload):
        '''Sharer sent the updated buddy list, so regenerate internal lists'''
        if not self._collab.props.leader:
            [buddies, colors] = payload
            self._bounce_window.buddies = buddies[:]
            self._player_colors = colors[:]
            self._player_pixbufs = []
            for colors in self._player_colors:
                self._player_pixbufs.append(
                    svg_str_to_pixbuf(
                        generate_xo_svg(
                            scale=0.8, colors=[str(colors[0]),
                                               str(colors[1])])))

    def send_a_fraction(self, fraction):
        ''' Send a fraction to other players. '''
        self.send_event('f', fraction)

    def _receive_a_fraction(self, payload):
        ''' Receive a fraction from another player. '''
        self._bounce_window.play_a_fraction(payload)

    def _take_a_turn(self, nick):
        ''' If it is your turn, take it, otherwise, wait. '''
        if nick == self.nick:  # TODO: disambiguate
            self._bounce_window.its_my_turn()
        else:
            self._bounce_window.its_their_turn(nick)

    def send_event(self, action, data):
        ''' Send event through the tube. '''
        _logger.debug('send_event action=%r data=%r' % (action, data))
        self._collab.post({'action': action, 'data': data})

    def set_player_on_toolbar(self, nick):
        ''' Display the XO icon of the player whose turn it is. '''
        self._player.set_from_pixbuf(
            self._player_pixbufs[self._bounce_window.buddies.index(nick)])
        self._player.set_tooltip_text(nick)
Ejemplo n.º 53
0
    def make_toolbar(self):
        # toolbar with the new toolbar redesign
        toolbar_box = ToolbarBox()

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

        toolbarview = Gtk.Toolbar()
        langtoolbar_button = ToolbarButton(
            label=_('Filter'),
            page=toolbarview,
            icon_name='filter')
        langtoolbar_button.show()
        toolbar_box.toolbar.insert(langtoolbar_button, -1)
        tool = ToolButton('grammar')
        tool.set_tooltip(_('Langue française'))
        tool.connect('clicked', self.filter_french)
        tool.show()
        toolbarview.insert(tool, -1)
        tool = ToolButton('calculator')
        tool.set_tooltip(_('Mathématiques'))
        tool.connect('clicked', self.filter_math)
        tool.show()
        toolbarview.insert(tool, -1)
        tool = ToolButton('earth')
        tool.set_tooltip(_('Science'))
        tool.connect('clicked', self.filter_science)
        tool.show()
        toolbarview.insert(tool, -1)
        tool = ToolButton('institution')
        tool.set_tooltip(_('Instruction civique et histoire géographie'))
        tool.connect('clicked', self.filter_civism)
        tool.show()
        toolbarview.insert(tool, -1)
        toolbarview.show()

        box_search_item = Gtk.ToolItem()
        self.search_entry = Gtk.Entry()
        self.search_entry.connect('changed', self.text_filter)
        self.search_entry.set_size_request(300, -1)
        box_search_item.add(self.search_entry)
        self.search_entry.show()
        box_search_item.show()
        toolbar_box.toolbar.insert(box_search_item, -1)
        
        favorite_button = ToolButton(self.favorite_status)
        favorite_button.set_tooltip('Filter on favorite')
        favorite_button.connect('clicked', self.favorite)
        toolbar_box.toolbar.insert(favorite_button, -1)
        favorite_button.show()
        self.favorite_button = favorite_button

        settings_button = ToolButton('settings')
        settings_button.set_tooltip('Settings')
        settings_button.connect('clicked', self.settings)
        toolbar_box.toolbar.insert(settings_button, -1)
        settings_button.show()

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

        stop_button = StopButton(self)
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()
Ejemplo n.º 54
0
class LogActivity(activity.Activity):
    def __init__(self, handle):
        activity.Activity.__init__(self, handle)

        self._autosearch_timer = None

        # Paths to watch: ~/.sugar/someuser/logs, /var/log
        paths = []
        paths.append(env.get_profile_path('logs'))
        paths.append('/var/log')

        # Additional misc files.
        ext_files = []
        ext_files.append(os.path.expanduser('~/.bash_history'))

        self.viewer = MultiLogView(paths, ext_files)
        self.set_canvas(self.viewer)
        self.viewer.grab_focus()

        self._build_toolbox()

        # Get Sugar's clipboard
        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        self.show()

        self._configure_cb(None)

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)

    def _build_toolbox(self):
        toolbar_box = ToolbarBox()

        self.max_participants = 1

        activity_button = ActivityToolbarButton(self)
        activity_toolbar = activity_button.page

        self._toolbar = toolbar_box.toolbar
        self._toolbar.insert(activity_button, -1)

        self._secondary_toolbar = Gtk.Toolbar()
        self._secondary_toolbar_button = ToolbarButton(
            page=self._secondary_toolbar,
            icon_name='system-search')
        self._secondary_toolbar.show()
        self._toolbar.insert(self._secondary_toolbar_button, -1)
        self._secondary_toolbar_button.hide()

        show_list = ToggleToolButton('view-list')
        show_list.set_active(True)
        show_list.set_tooltip(_('Show list of files'))
        show_list.connect('toggled', self._list_toggled_cb)
        self._toolbar.insert(show_list, -1)
        show_list.show()

        copy = CopyButton()
        copy.connect('clicked', self.__copy_clicked_cb)
        self._toolbar.insert(copy, -1)

        wrap_btn = ToggleToolButton("format-wrap")
        wrap_btn.set_tooltip(_('Word Wrap'))
        wrap_btn.connect('clicked', self._wrap_cb)
        self._toolbar.insert(wrap_btn, -1)

        self.search_entry = iconentry.IconEntry()
        self.search_entry.set_size_request(Gdk.Screen.width() / 3, -1)
        self.search_entry.set_icon_from_name(
            iconentry.ICON_ENTRY_PRIMARY, 'entry-search')
        self.search_entry.add_clear_button()
        self.search_entry.connect('activate', self._search_entry_activate_cb)
        self.search_entry.connect('changed', self._search_entry_changed_cb)
        self._search_item = Gtk.ToolItem()
        self._search_item.add(self.search_entry)
        self._toolbar.insert(self._search_item, -1)

        self._search_prev = ToolButton('go-previous-paired')
        self._search_prev.set_tooltip(_('Previous'))
        self._search_prev.connect('clicked', self._search_prev_cb)
        self._toolbar.insert(self._search_prev, -1)

        self._search_next = ToolButton('go-next-paired')
        self._search_next.set_tooltip(_('Next'))
        self._search_next.connect('clicked', self._search_next_cb)
        self._toolbar.insert(self._search_next, -1)

        self._update_search_buttons()

        self.collector_palette = CollectorPalette(self)
        collector_btn = ToolButton('log-export')
        collector_btn.set_palette(self.collector_palette)
        collector_btn.connect('clicked', self._logviewer_cb)
        collector_btn.show()
        activity_toolbar.insert(collector_btn, -1)

        self._delete_btn = ToolButton('list-remove')
        self._delete_btn.set_tooltip(_('Delete Log File'))
        self._delete_btn.connect('clicked', self._delete_log_cb)
        self._toolbar.insert(self._delete_btn, -1)

        self._separator = Gtk.SeparatorToolItem()
        self._separator.set_expand(True)
        self._separator.set_draw(False)
        self._toolbar.insert(self._separator, -1)

        self._stop_btn = StopButton(self)
        self._toolbar.insert(self._stop_btn, -1)

        toolbar_box.show_all()
        self.set_toolbar_box(toolbar_box)

    def _configure_cb(self, event=None):
        for control in [self._stop_btn, self._separator, self._delete_btn]:
            if control in self._toolbar:
                self._toolbar.remove(control)

        if Gdk.Screen.width() < Gdk.Screen.height():
            self._secondary_toolbar_button.show()
            self._secondary_toolbar_button.set_expanded(True)
            self._remove_controls(self._toolbar)
            self._add_controls(self._secondary_toolbar)
        else:
            self._secondary_toolbar_button.set_expanded(False)
            self._secondary_toolbar_button.hide()
            self._remove_controls(self._secondary_toolbar)
            self._add_controls(self._toolbar)

        for control in [self._delete_btn, self._separator, self._stop_btn]:
            if control not in self._toolbar:
                self._toolbar.insert(control, -1)

    def _remove_controls(self, toolbar):
        for control in [self._search_item, self._search_prev,
                        self._search_next]:
            if control in toolbar:
                toolbar.remove(control)

    def _add_controls(self, toolbar):
        for control in [self._search_item, self._search_prev,
                        self._search_next]:
            if control not in toolbar:
                toolbar.insert(control, -1)
                control.show()

    def _list_toggled_cb(self, widget):
        if widget.get_active():
            self.viewer.list_scroll.show()
        else:
            self.viewer.list_scroll.hide()

    def __copy_clicked_cb(self, button):
        if self.viewer.active_log:
            self.viewer.active_log.copy_clipboard(self.clipboard)

    def _wrap_cb(self, button):
        if button.get_active():
            self.viewer._textview.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
        else:
            self.viewer._textview.set_wrap_mode(Gtk.WrapMode.NONE)

    def _search_entry_activate_cb(self, entry):
        if self._autosearch_timer:
            GLib.source_remove(self._autosearch_timer)
        self.viewer.set_search_text(entry.props.text)
        self._update_search_buttons()

    def _search_entry_changed_cb(self, entry):
        if self._autosearch_timer:
            GLib.source_remove(self._autosearch_timer)
        self._autosearch_timer = GLib.timeout_add(_AUTOSEARCH_TIMEOUT,
                                                  self.__autosearch_cb)

    def __autosearch_cb(self):
        self._autosearch_timer = None
        self.search_entry.activate()
        return False

    def _search_prev_cb(self, button):
        self.viewer.search_next('backward')
        self._update_search_buttons()

    def _search_next_cb(self, button):
        self.viewer.search_next('forward')
        self._update_search_buttons()

    def _update_search_buttons(self,):
        if len(self.viewer.search_text) == 0:
            self._search_prev.props.sensitive = False
            self._search_next.props.sensitive = False
        else:
            prev_result = self.viewer.get_next_result('backward')
            next_result = self.viewer.get_next_result('forward')
            self._search_prev.props.sensitive = prev_result is not None
            self._search_next.props.sensitive = next_result is not None

    def _delete_log_cb(self, widget):
        if self.viewer.active_log:
            logfile = self.viewer.active_log.logfile
            try:
                os.remove(logfile)
            except OSError, err:
                notify = NotifyAlert()
                notify.props.title = _('Error')
                notify.props.msg = _('%(error)s when deleting %(file)s') % \
                    {'error': err.strerror, 'file': logfile}
                notify.connect('response', _notify_response_cb, self)
                self.add_alert(notify)
Ejemplo n.º 55
0
    def _setup_toolbars(self):
        """ Setup the toolbars.. """
        project_toolbar = Gtk.Toolbar()
        custom_slide_toolbar = Gtk.Toolbar()
        custom_stator_toolbar = Gtk.Toolbar()
        edit_toolbar = Gtk.Toolbar()

        # no sharing
        self.max_participants = 1

        toolbox = ToolbarBox()

        # Activity toolbar
        activity_button = ActivityToolbarButton(self)

        toolbox.toolbar.insert(activity_button, 0)
        activity_button.show()

        project_toolbar_button = ToolbarButton(page=project_toolbar, icon_name="sliderule")
        project_toolbar.show()
        toolbox.toolbar.insert(project_toolbar_button, -1)
        project_toolbar_button.show()

        custom_slide_toolbar_button = ToolbarButton(page=custom_slide_toolbar, icon_name="custom-slide")
        custom_slide_toolbar.show()
        toolbox.toolbar.insert(custom_slide_toolbar_button, -1)
        custom_slide_toolbar_button.show()

        custom_stator_toolbar_button = ToolbarButton(page=custom_stator_toolbar, icon_name="custom-stator")
        custom_stator_toolbar.show()
        toolbox.toolbar.insert(custom_stator_toolbar_button, -1)
        custom_stator_toolbar_button.show()

        edit_toolbar_button = ToolbarButton(label=_("Edit"), page=edit_toolbar, icon_name="toolbar-edit")
        edit_toolbar_button.show()
        toolbox.toolbar.insert(edit_toolbar_button, -1)
        edit_toolbar_button.show()

        self.set_toolbar_box(toolbox)
        toolbox.show()
        toolbar = toolbox.toolbar

        # Add the buttons to the toolbars
        self._function_combo = combo_factory(
            FUNCTIONS, project_toolbar, self._function_combo_cb, default=FC_multiply, tooltip=_("select function")
        )
        self.top_button = button_factory("C", project_toolbar, self._dummy_cb, tooltip=_("active slide"))
        self._slide_combo = combo_factory(
            SLIDE_TABLE, project_toolbar, self._slide_combo_cb, default=C_slide, tooltip=_("select slide")
        )
        self.bottom_button = button_factory("D", project_toolbar, self._dummy_cb, tooltip=_("active stator"))
        self._stator_combo = combo_factory(
            STATOR_TABLE, project_toolbar, self._stator_combo_cb, default=D_slide, tooltip=_("select stator")
        )

        separator_factory(project_toolbar)

        self.realign_button = button_factory("realign", project_toolbar, self.realign_cb, tooltip=_("realign slides"))

        self._offset_function = []
        self._calculate_function = []
        self._label_function = []
        self._domain_min = []
        self._domain_max = []
        self._step_size = []
        self.custom = []

        ENTRY = ["C", "D"]
        ENTRY_TOOLBAR = [custom_slide_toolbar, custom_stator_toolbar]
        ENTRY_BUTTON = ["custom-slide", "custom-stator"]
        ENTRY_TOOLTIP = [_("create custom slide"), _("create custom stator")]
        ENTRY_CALLBACK = [self._custom_slide_cb, self._custom_stator_cb]
        for i in range(2):
            self._offset_function.append(
                entry_factory(DEFINITIONS[ENTRY[i]][0], ENTRY_TOOLBAR[i], tooltip=_("position function"), max=10)
            )
            self._calculate_function.append(
                entry_factory(DEFINITIONS[ENTRY[i]][1], ENTRY_TOOLBAR[i], tooltip=_("result function"), max=10)
            )
            self._label_function.append(
                entry_factory(DEFINITIONS[ENTRY[i]][2], ENTRY_TOOLBAR[i], tooltip=_("label function"), max=10)
            )
            self._domain_min.append(
                entry_factory(DEFINITIONS[ENTRY[i]][3], ENTRY_TOOLBAR[i], tooltip=_("domain minimum"), max=4)
            )
            self._domain_max.append(
                entry_factory(DEFINITIONS[ENTRY[i]][4], ENTRY_TOOLBAR[i], tooltip=_("domain maximum"), max=4)
            )
            self._step_size.append(
                entry_factory(DEFINITIONS[ENTRY[i]][5], ENTRY_TOOLBAR[i], tooltip=_("step size"), max=4)
            )
            self.custom.append(
                button_factory(ENTRY_BUTTON[i], ENTRY_TOOLBAR[i], ENTRY_CALLBACK[i], tooltip=ENTRY_TOOLTIP[i])
            )

        copy = button_factory("edit-copy", edit_toolbar, self._copy_cb, tooltip=_("Copy"), accelerator="<Ctrl>c")
        paste = button_factory("edit-paste", edit_toolbar, self._paste_cb, tooltip=_("Paste"), accelerator="<Ctrl>v")

        separator_factory(toolbox.toolbar, True, False)

        stop_button = StopButton(self)
        stop_button.props.accelerator = "<Ctrl>q"
        toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()
        # workaround to #2050
        edit_toolbar_button.set_expanded(True)
        # start with project toolbar enabled
        project_toolbar_button.set_expanded(True)
Ejemplo n.º 56
0
class Dimensions(activity.Activity):

    ''' Dimension matching game '''

    def __init__(self, handle):
        ''' Initialize the Sugar activity '''
        super(Dimensions, self).__init__(handle)
        self.ready_to_play = False
        self._prompt = ''
        self._read_journal_data()
        self._sep = []
        self._setup_toolbars()
        self._setup_canvas()

        if self.shared_activity:
            # We're joining
            if not self.get_shared():
                xocolors = XoColor(profile.get_color().to_string())
                share_icon = Icon(icon_name='zoom-neighborhood',
                                  xo_color=xocolors)
                self._joined_alert = Alert()
                self._joined_alert.props.icon = share_icon
                self._joined_alert.props.title = _('Please wait')
                self._joined_alert.props.msg = _('Starting connection...')
                self.add_alert(self._joined_alert)

                # Wait for joined signal
                self.connect("joined", self._joined_cb)

        self._setup_presence_service()

        if not hasattr(self, '_saved_state'):
            self._saved_state = None
            self.vmw.new_game(show_selector=True)
        else:
            self.vmw.new_game(saved_state=self._saved_state,
                              deck_index=self._deck_index)
        self.ready_to_play = True

        if self._editing_word_list:
            self.vmw.editing_word_list = True
            self.vmw.edit_word_list()
        elif self._editing_custom_cards:
            self.vmw.editing_custom_cards = True
            self.vmw.edit_custom_card()

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)
        self._configure_cb(None)

    def _select_game_cb(self, button, card_type):
        ''' Choose which game we are playing. '''
        if self.vmw.joiner():  # joiner cannot change level
            return
        # self.vmw.card_type = card_type
        self._prompt = PROMPT_DICT[card_type]
        self._load_new_game(card_type)

    def _load_new_game(self, card_type=None, show_selector=True):
        if not self.ready_to_play:
            return
        # self._notify_new_game(self._prompt)
        GObject.idle_add(self._new_game, card_type, show_selector)

    def _new_game(self, card_type, show_selector=True):
        if card_type == 'custom' and self.vmw.custom_paths[0] is None:
            self.image_import_cb()
        else:
            self.tools_toolbar_button.set_expanded(False)
            self.vmw.new_game(show_selector=show_selector)

    def _robot_cb(self, button=None):
        ''' Toggle robot assist on/off '''
        if self.vmw.robot:
            self.vmw.robot = False
            self.robot_button.set_tooltip(_('Play with the computer.'))
            self.robot_button.set_icon_name('robot-off')
        elif not self.vmw.editing_word_list:
            self.vmw.robot = True
            self.robot_button.set_tooltip(
                _('Stop playing with the computer.'))
            self.robot_button.set_icon_name('robot-on')

    def _level_cb(self, button, level):
        ''' Cycle between levels '''
        if self.vmw.joiner():  # joiner cannot change level
            return
        self.vmw.level = level
        # self.level_label.set_text(self.calc_level_label(self.vmw.low_score,
        #                                                 self.vmw.level))
        self._load_new_game(show_selector=False)

    def calc_level_label(self, low_score, play_level):
        ''' Show the score. '''
        if low_score[play_level] == -1:
            return LEVEL_LABELS[play_level]
        else:
            return '%s (%d:%02d)' % \
                (LEVEL_LABELS[play_level],
                 int(low_score[play_level] / 60),
                 int(low_score[play_level] % 60))

    def image_import_cb(self, button=None):
        ''' Import custom cards from the Journal '''
        self.vmw.editing_custom_cards = True
        self.vmw.editing_word_list = False
        self.vmw.edit_custom_card()
        if self.vmw.robot:
            self._robot_cb(button)

    def _number_card_O_cb(self, button, numberO):
        ''' Choose between O-card list for numbers game. '''
        if self.vmw.joiner():  # joiner cannot change decks
            return
        self.vmw.numberO = numberO
        self.vmw.card_type = 'number'
        self._load_new_game()

    def _number_card_C_cb(self, button, numberC):
        ''' Choose between C-card list for numbers game. '''
        if self.vmw.joiner():  # joiner cannot change decks
            return
        self.vmw.numberC = numberC
        self.vmw.card_type = 'number'
        self._load_new_game()

    def _edit_words_cb(self, button):
        ''' Edit the word list. '''
        self.vmw.editing_word_list = True
        self.vmw.editing_custom_cards = False
        self.vmw.edit_word_list()
        if self.vmw.robot:
            self._robot_cb(button)

    def _read_metadata(self, keyword, default_value, json=False):
        ''' If the keyword is found, return stored value '''
        if keyword in self.metadata:
            data = self.metadata[keyword]
        else:
            data = default_value

        if json:
            try:
                return jloads(data)
            except:
                pass

        return data

    def _read_journal_data(self):
        ''' There may be data from a previous instance. '''
        self._play_level = int(self._read_metadata('play_level', 0))
        self._robot_time = int(self._read_metadata('robot_time',
                                                   ROBOT_TIMER_DEFAULT))
        self._card_type = self._read_metadata('cardtype', MODE)
        self._low_score = [int(self._read_metadata('low_score_beginner', -1)),
                           int(self._read_metadata('low_score_intermediate',
                                                   -1)),
                           int(self._read_metadata('low_score_expert', -1))]

        self._all_scores = self._read_metadata(
            'all_scores',
            '{"pattern": [], "word": [], "number": [], "custom": []}',
            True)
        self._numberO = int(self._read_metadata('numberO', PRODUCT))
        self._numberC = int(self._read_metadata('numberC', HASH))
        self._matches = int(self._read_metadata('matches', 0))
        self._robot_matches = int(self._read_metadata('robot_matches', 0))
        self._total_time = int(self._read_metadata('total_time', 0))
        self._deck_index = int(self._read_metadata('deck_index', 0))
        self._word_lists = [[self._read_metadata('mouse', _('mouse')),
                             self._read_metadata('cat', _('cat')),
                             self._read_metadata('dog', _('dog'))],
                            [self._read_metadata('cheese', _('cheese')),
                             self._read_metadata('apple', _('apple')),
                             self._read_metadata('bread', _('bread'))],
                            [self._read_metadata('moon', _('moon')),
                             self._read_metadata('sun', _('sun')),
                             self._read_metadata('earth', _('earth'))]]
        self._editing_word_list = bool(int(self._read_metadata(
            'editing_word_list', 0)))
        self._editing_custom_cards = bool(int(self._read_metadata(
            'editing_custom_cards', 0)))
        if self._card_type == 'custom':
            self._custom_object = self._read_metadata('custom_object', None)
            if self._custom_object is None:
                self._card_type = MODE
        self._custom_jobject = []
        for i in range(9):
            self._custom_jobject.append(self._read_metadata(
                'custom_' + str(i), None))

    def _write_scores_to_clipboard(self, button=None):
        ''' SimpleGraph will plot the cululative results '''
        jscores = ''
        c = 0
        for key in self.vmw.all_scores.keys():
            for data in self.vmw.all_scores[key]:
                jscores += '%s: %s\n' % (str(c + 1), data[1])
                c += 1
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        clipboard.set_text(jscores, -1)

    def _setup_toolbars(self):
        ''' Setup the toolbars.. '''

        tools_toolbar = Gtk.Toolbar()
        numbers_toolbar = Gtk.Toolbar()
        toolbox = ToolbarBox()

        self.activity_toolbar_button = ActivityToolbarButton(self)

        toolbox.toolbar.insert(self.activity_toolbar_button, 0)
        self.activity_toolbar_button.show()

        self.numbers_toolbar_button = ToolbarButton(
            page=numbers_toolbar,
            icon_name='number-tools')
        if MODE == 'number':
            numbers_toolbar.show()
            toolbox.toolbar.insert(self.numbers_toolbar_button, -1)
            self.numbers_toolbar_button.show()

        self.tools_toolbar_button = ToolbarButton(
            page=tools_toolbar,
            icon_name='view-source')

        self.button_pattern = button_factory(
            'new-pattern-game', toolbox.toolbar, self._select_game_cb,
            cb_arg='pattern', tooltip=_('New game'))

        self._set_extras(toolbox.toolbar)

        self._sep.append(separator_factory(toolbox.toolbar, True, False))

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>q'
        toolbox.toolbar.insert(stop_button, -1)
        stop_button.show()

        button_factory('score-copy', self.activity_toolbar_button,
                       self._write_scores_to_clipboard,
                       tooltip=_('Export scores to clipboard'))

        self.set_toolbar_box(toolbox)
        toolbox.show()

        if MODE == 'word':
            self.words_tool_button = button_factory(
                'word-tools', tools_toolbar, self._edit_words_cb,
                tooltip=_('Edit word lists.'))

        self.import_button = button_factory(
            'image-tools', tools_toolbar, self.image_import_cb,
            tooltip=_('Import custom cards'))

        self.button_custom = button_factory(
            'new-custom-game', tools_toolbar, self._select_game_cb,
            cb_arg='custom', tooltip=_('New custom game'))
        self.button_custom.set_sensitive(False)

        if MODE == 'number':
            self._setup_number_buttons(numbers_toolbar)

    def _setup_number_buttons(self, numbers_toolbar):
        self.product_button = radio_factory(
            'product',
            numbers_toolbar,
            self._number_card_O_cb,
            cb_arg=PRODUCT,
            tooltip=_('product'),
            group=None)
        NUMBER_O_BUTTONS[PRODUCT] = self.product_button
        self.roman_button = radio_factory(
            'roman',
            numbers_toolbar,
            self._number_card_O_cb,
            cb_arg=ROMAN,
            tooltip=_('Roman numerals'),
            group=self.product_button)
        NUMBER_O_BUTTONS[ROMAN] = self.roman_button
        self.word_button = radio_factory(
            'word',
            numbers_toolbar,
            self._number_card_O_cb,
            cb_arg=WORD,
            tooltip=_('word'),
            group=self.product_button)
        NUMBER_O_BUTTONS[WORD] = self.word_button
        self.chinese_button = radio_factory(
            'chinese',
            numbers_toolbar,
            self._number_card_O_cb,
            cb_arg=CHINESE,
            tooltip=_('Chinese'),
            group=self.product_button)
        NUMBER_O_BUTTONS[CHINESE] = self.chinese_button
        self.mayan_button = radio_factory(
            'mayan',
            numbers_toolbar,
            self._number_card_O_cb,
            cb_arg=MAYAN,
            tooltip=_('Mayan'),
            group=self.product_button)
        NUMBER_O_BUTTONS[MAYAN] = self.mayan_button
        self.incan_button = radio_factory(
            'incan',
            numbers_toolbar,
            self._number_card_O_cb,
            cb_arg=INCAN,
            tooltip=_('Quipu'),
            group=self.product_button)
        NUMBER_O_BUTTONS[INCAN] = self.incan_button

        separator_factory(numbers_toolbar, False, True)

        self.hash_button = radio_factory(
            'hash',
            numbers_toolbar,
            self._number_card_C_cb,
            cb_arg=HASH,
            tooltip=_('hash marks'),
            group=None)
        NUMBER_C_BUTTONS[HASH] = self.hash_button
        self.dots_button = radio_factory(
            'dots',
            numbers_toolbar,
            self._number_card_C_cb,
            cb_arg=DOTS,
            tooltip=_('dots in a circle'),
            group=self.hash_button)
        NUMBER_C_BUTTONS[DOTS] = self.dots_button
        self.star_button = radio_factory(
            'star',
            numbers_toolbar,
            self._number_card_C_cb,
            cb_arg=STAR,
            tooltip=_('points on a star'),
            group=self.hash_button)
        NUMBER_C_BUTTONS[STAR] = self.star_button
        self.dice_button = radio_factory(
            'dice',
            numbers_toolbar,
            self._number_card_C_cb,
            cb_arg=DICE,
            tooltip=_('dice'),
            group=self.hash_button)
        NUMBER_C_BUTTONS[DICE] = self.dice_button
        self.lines_button = radio_factory(
            'lines',
            numbers_toolbar,
            self._number_card_C_cb,
            cb_arg=LINES,
            tooltip=_('dots in a line'),
            group=self.hash_button)
        NUMBER_C_BUTTONS[LINES] = self.lines_button

    def _configure_cb(self, event):
        self._vbox.set_size_request(Gdk.Screen.width(), Gdk.Screen.height())
        self._vbox.show()

        if Gdk.Screen.width() < Gdk.Screen.height():
            for sep in self._sep:
                sep.hide()
        else:
            for sep in self._sep:
                sep.show()

    def _robot_selection_cb(self, widget):
        if self._robot_palette:
            if not self._robot_palette.is_up():
                self._robot_palette.popup(immediate=True,
                                          state=self._robot_palette.SECONDARY)
            else:
                self._robot_palette.popdown(immediate=True)
            return

    def _setup_robot_palette(self):
        self._robot_palette = self._robot_time_button.get_palette()

        self._robot_timer_menu = {}
        for seconds in ROBOT_TIMER_VALUES:
            self._robot_timer_menu[seconds] = {
                'menu_item': MenuItem(),
                'label': ROBOT_TIMER_LABELS[seconds],
                'icon': image_from_svg_file(
                    'timer-%d.svg' % (seconds)),
                'icon-selected': image_from_svg_file(
                    'timer-%d-selected.svg' % (seconds))
            }

            self._robot_timer_menu[seconds]['menu_item'].set_label(
                self._robot_timer_menu[seconds]['label'])
            if seconds == ROBOT_TIMER_DEFAULT:
                self._robot_timer_menu[seconds]['menu_item'].set_image(
                    self._robot_timer_menu[seconds]['icon-selected'])
            else:
                self._robot_timer_menu[seconds]['menu_item'].set_image(
                    self._robot_timer_menu[seconds]['icon'])
            self._robot_timer_menu[seconds]['menu_item'].connect(
                'activate', self._robot_selected_cb, seconds)
            self._robot_palette.menu.append(
                self._robot_timer_menu[seconds]['menu_item'])
            self._robot_timer_menu[seconds]['menu_item'].show()

    def _robot_selected_cb(self, button, seconds):
        self.vmw.robot_time = seconds
        if hasattr(self, '_robot_time_button') and \
                seconds in ROBOT_TIMER_VALUES:
            self._robot_time_button.set_icon_name('timer-%d' % seconds)

        for time in ROBOT_TIMER_VALUES:
            if time == seconds:
                self._robot_timer_menu[time]['menu_item'].set_image(
                    self._robot_timer_menu[time]['icon-selected'])
            else:
                self._robot_timer_menu[time]['menu_item'].set_image(
                    self._robot_timer_menu[time]['icon'])

    def _set_extras(self, toolbar):
        self.robot_button = button_factory(
            'robot-off', toolbar, self._robot_cb,
            tooltip=_('Play with the computer'))

        self._robot_time_button = button_factory(
            'timer-15',
            toolbar,
            self._robot_selection_cb,
            tooltip=_('robot pause time'))
        self._setup_robot_palette()

        self._sep.append(separator_factory(toolbar, False, True))

        self.beginner_button = radio_factory(
            'beginner',
            toolbar,
            self._level_cb,
            cb_arg=BEGINNER,
            tooltip=_('beginner'),
            group=None)
        LEVEL_BUTTONS[BEGINNER] = self.beginner_button
        self.intermediate_button = radio_factory(
            'intermediate',
            toolbar,
            self._level_cb,
            cb_arg=INTERMEDIATE,
            tooltip=_('intermediate'),
            group=self.beginner_button)
        LEVEL_BUTTONS[INTERMEDIATE] = self.intermediate_button
        self.expert_button = radio_factory(
            'expert',
            toolbar,
            self._level_cb,
            cb_arg=EXPERT,
            tooltip=_('expert'),
            group=self.beginner_button)
        LEVEL_BUTTONS[EXPERT] = self.expert_button

    def _fixed_resize_cb(self, widget=None, rect=None):
        ''' If a toolbar opens or closes, we need to resize the vbox
        holding out scrolling window. '''
        self._vbox.set_size_request(rect.width, rect.height)

    def _setup_canvas(self):
        ''' Create a canvas in a Gtk.Fixed '''
        self.fixed = Gtk.Fixed()
        self.fixed.connect('size-allocate', self._fixed_resize_cb)
        self.fixed.show()
        self.set_canvas(self.fixed)

        self._vbox = Gtk.VBox(False, 0)
        self._vbox.set_size_request(Gdk.Screen.width(), Gdk.Screen.height())
        self.fixed.put(self._vbox, 0, 0)
        self._vbox.show()

        self._canvas = Gtk.DrawingArea()
        self._canvas.set_size_request(int(Gdk.Screen.width()),
                                      int(Gdk.Screen.height()))
        self._canvas.show()
        self.show_all()
        self._vbox.pack_end(self._canvas, True, True, 0)
        self._vbox.show()

        self.show_all()

        self.vmw = Game(self._canvas, parent=self, card_type=MODE)
        self.vmw.level = self._play_level
        LEVEL_BUTTONS[self._play_level].set_active(True)
        self.vmw.card_type = self._card_type
        self.vmw.robot = False
        self.vmw.robot_time = self._robot_time
        self.vmw.low_score = self._low_score
        self.vmw.all_scores = self._all_scores
        self.vmw.numberO = self._numberO
        self.vmw.numberC = self._numberC
        self.vmw.matches = self._matches
        self.vmw.robot_matches = self._robot_matches
        self.vmw.total_time = self._total_time
        self.vmw.buddies = []
        self.vmw.word_lists = self._word_lists
        self.vmw.editing_word_list = self._editing_word_list
        if hasattr(self, '_custom_object') and self._custom_object is not None:
            self.vmw._find_custom_paths(datastore.get(self._custom_object))
        for i in range(9):
            if hasattr(self, '_custom_jobject') and \
               self._custom_jobject[i] is not None:
                self.vmw.custom_paths[i] = datastore.get(
                    self._custom_jobject[i])
                self.button_custom.set_sensitive(True)
        return self._canvas

    def write_file(self, file_path):
        ''' Write data to the Journal. '''
        if hasattr(self, 'vmw'):
            self.metadata['play_level'] = self.vmw.level
            self.metadata['low_score_beginner'] = int(self.vmw.low_score[0])
            self.metadata['low_score_intermediate'] = int(
                self.vmw.low_score[1])
            self.metadata['low_score_expert'] = int(self.vmw.low_score[2])
            self.metadata['all_scores'] = jdumps(self.vmw.all_scores)
            print jdumps(self.vmw.all_scores)
            self.metadata['robot_time'] = self.vmw.robot_time
            self.metadata['numberO'] = self.vmw.numberO
            self.metadata['numberC'] = self.vmw.numberC
            self.metadata['cardtype'] = self.vmw.card_type
            self.metadata['matches'] = self.vmw.matches
            self.metadata['robot_matches'] = self.vmw.robot_matches
            self.metadata['total_time'] = int(self.vmw.total_time)
            self.metadata['deck_index'] = self.vmw.deck.index
            self.metadata['mouse'] = self.vmw.word_lists[0][0]
            self.metadata['cat'] = self.vmw.word_lists[0][1]
            self.metadata['dog'] = self.vmw.word_lists[0][2]
            self.metadata['cheese'] = self.vmw.word_lists[1][0]
            self.metadata['apple'] = self.vmw.word_lists[1][1]
            self.metadata['bread'] = self.vmw.word_lists[1][2]
            self.metadata['moon'] = self.vmw.word_lists[2][0]
            self.metadata['sun'] = self.vmw.word_lists[2][1]
            self.metadata['earth'] = self.vmw.word_lists[2][2]
            self.metadata['editing_word_list'] = self.vmw.editing_word_list
            self.metadata['mime_type'] = 'application/x-visualmatch'
            f = file(file_path, 'w')
            f.write(self._dump())
            f.close()
        else:
            _logger.debug('Deferring saving to %s' % file_path)

    def _dump(self):
        ''' Dump game data to the journal.'''
        data = []
        for i in self.vmw.grid.grid:
            if i is None or self.vmw.editing_word_list:
                data.append(None)
            else:
                data.append(i.index)
        for i in self.vmw.clicked:
            if i.spr is None or self.vmw.deck.spr_to_card(i.spr) is None or \
               self.vmw.editing_word_list:
                data.append(None)
            else:
                data.append(self.vmw.deck.spr_to_card(i.spr).index)
        for i in self.vmw.deck.cards:
            if i is None or self.vmw.editing_word_list:
                data.append(None)
            else:
                data.append(i.index)
        for i in self.vmw.match_list:
            if self.vmw.deck.spr_to_card(i) is not None:
                data.append(self.vmw.deck.spr_to_card(i).index)
        for i in self.vmw.word_lists:
            for j in i:
                data.append(j)
        return self._data_dumper(data)

    def _data_dumper(self, data):
        io = StringIO()
        jdump(data, io)
        return io.getvalue()

    def read_file(self, file_path):
        ''' Read data from the Journal. '''
        f = open(file_path, 'r')
        self._load(f.read())
        f.close()

    def _load(self, data):
        ''' Load game data from the journal. '''
        saved_state = self._data_loader(data)
        if len(saved_state) > 0:
            self._saved_state = saved_state

    def _data_loader(self, data):
        json_data = jloads(data)
        return json_data

    def _notify_new_game(self, prompt):
        ''' Called from New Game button since loading a new game can
        be slooow!! '''
        alert = NotifyAlert(3)
        alert.props.title = prompt
        alert.props.msg = _('A new game is loading.')

        def _notification_alert_response_cb(alert, response_id, self):
            self.remove_alert(alert)

        alert.connect('response', _notification_alert_response_cb, self)
        self.add_alert(alert)
        alert.show()

    def _new_help_box(self, name, button=None):
        help_box = Gtk.VBox()
        help_box.set_homogeneous(False)
        help_palettes[name] = help_box
        if button is not None:
            help_buttons[name] = button
        help_windows[name] = Gtk.ScrolledWindow()
        help_windows[name].set_size_request(
            int(Gdk.Screen.width() / 3),
            Gdk.Screen.height() - style.GRID_CELL_SIZE * 3)
        help_windows[name].set_policy(Gtk.PolicyType.NEVER,
                                      Gtk.PolicyType.AUTOMATIC)
        help_windows[name].add_with_viewport(help_palettes[name])
        help_palettes[name].show()
        return help_box

    def _setup_toolbar_help(self):
        ''' Set up a help palette for the main toolbars '''
        help_box = self._new_help_box('main-toolbar')
        add_section(help_box, _('Dimensions'), icon='activity-dimensions')
        add_paragraph(help_box, _('Tools'), icon='view-source')
        if MODE == 'pattern':
            add_paragraph(help_box, _('Game'), icon='new-pattern-game')
        elif MODE == 'number':
            add_paragraph(help_box, PROMPT_DICT['number'],
                          icon='new-number-game')
            add_paragraph(help_box, _('Numbers'), icon='number-tools')
        elif MODE == 'word':
            add_paragraph(help_box, PROMPT_DICT['word'], icon='new-word-game')
        add_paragraph(help_box, _('Play with the computer'), icon='robot-off')
        add_paragraph(help_box, _('robot pause time'), icon='timer-60')
        add_paragraph(help_box, _('beginner'), icon='beginner')
        add_paragraph(help_box, _('intermediate'), icon='intermediate')
        add_paragraph(help_box, _('expert'), icon='expert')

        add_section(help_box, _('Dimensions'), icon='activity-dimensions')
        add_paragraph(help_box, _('Export scores to clipboard'),
                      icon='score-copy')

        add_section(help_box, _('Tools'), icon='view-source')
        add_section(help_box, _('Import image cards'), icon='image-tools')
        add_paragraph(help_box, PROMPT_DICT['custom'], icon='new-custom-game')
        if MODE == 'word':
            add_section(help_box, _('Edit word lists.'), icon='word-tools')

        if MODE == 'number':
            add_section(help_box, _('Numbers'), icon='number-tools')
            add_paragraph(help_box, _('product'), icon='product')
            add_paragraph(help_box, _('Roman numerals'), icon='roman')
            add_paragraph(help_box, _('word'), icon='word')
            add_paragraph(help_box, _('Chinese'), icon='chinese')
            add_paragraph(help_box, _('Mayan'), icon='mayan')
            add_paragraph(help_box, _('Quipu'), icon='incan')
            add_paragraph(help_box, _('hash marks'), icon='hash')
            add_paragraph(help_box, _('dots in a circle'), icon='dots')
            add_paragraph(help_box, _('points on a star'), icon='star')
            add_paragraph(help_box, _('dice'), icon='dice')
            add_paragraph(help_box, _('dots in a line'), icon='lines')

    def _setup_presence_service(self):
        ''' Setup the Presence Service. '''
        self.pservice = presenceservice.get_instance()
        self.initiating = None  # sharing (True) or joining (False)

        owner = self.pservice.get_owner()
        self.owner = owner
        self.vmw.buddies.append(self.owner)
        self._share = ''
        self.connect('shared', self._shared_cb)
        self.connect('joined', self._joined_cb)

    def _shared_cb(self, activity):
        ''' Either set up initial share...'''
        if self.shared_activity is None:
            _logger.error('Failed to share or join activity ... \
                shared_activity is null in _shared_cb()')
            return

        self.initiating = True
        self.waiting_for_deck = False
        _logger.debug('I am sharing...')

        self.conn = self.shared_activity.telepathy_conn
        self.tubes_chan = self.shared_activity.telepathy_tubes_chan
        self.text_chan = self.shared_activity.telepathy_text_chan

        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
            'NewTube', self._new_tube_cb)

        _logger.debug('This is my activity: making a tube...')
        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(
            SERVICE, {})

    def _joined_cb(self, activity):
        ''' ...or join an exisiting share. '''
        if self.shared_activity is None:
            _logger.error('Failed to share or join activity ... \
                shared_activity is null in _shared_cb()')
            return

        if self._joined_alert is not None:
            self.remove_alert(self._joined_alert)
            self._joined_alert = None

        self.initiating = False
        _logger.debug('I joined a shared activity.')

        self.conn = self.shared_activity.telepathy_conn
        self.tubes_chan = self.shared_activity.telepathy_tubes_chan
        self.text_chan = self.shared_activity.telepathy_text_chan

        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
            'NewTube', self._new_tube_cb)

        _logger.debug('I am joining an activity: waiting for a tube...')
        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
            reply_handler=self._list_tubes_reply_cb,
            error_handler=self._list_tubes_error_cb)

        self.waiting_for_deck = True

        self.button_pattern.set_sensitive(False)
        self.robot_button.set_sensitive(False)
        self._robot_time_button.set_sensitive(False)
        self.beginner_button.set_sensitive(False)
        self.intermediate_button.set_sensitive(False)
        self.expert_button.set_sensitive(False)

    def _list_tubes_reply_cb(self, tubes):
        ''' Reply to a list request. '''
        for tube_info in tubes:
            self._new_tube_cb(*tube_info)

    def _list_tubes_error_cb(self, e):
        ''' Log errors. '''
        _logger.error('ListTubes() failed: %s', e)

    def _new_tube_cb(self, id, initiator, type, service, params, state):
        ''' Create a new tube. '''
        _logger.debug('New tube: ID=%d initator=%d type=%d service=%s '
                      'params=%r state=%d', id, initiator, type, service,
                      params, state)

        if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE):
            if state == telepathy.TUBE_STATE_LOCAL_PENDING:
                self.tubes_chan[
                    telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id)

            tube_conn = TubeConnection(
                self.conn, self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id,
                group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP])

            self.chattube = ChatTube(tube_conn, self.initiating,
                                     self.event_received_cb)

            if self.waiting_for_deck:
                self._send_event('j')

    def event_received_cb(self, text):
        ''' Data is passed as tuples: cmd:text '''
        if text[0] == 'B':
            e, card_index = text.split(':')
            self.vmw.add_to_clicked(
                self.vmw.deck.index_to_card(int(card_index)).spr)
        elif text[0] == 'r':
            self.vmw.clean_up_match()
        elif text[0] == 'R':
            self.vmw.clean_up_no_match(None)
        elif text[0] == 'S':
            e, card_index = text.split(':')
            i = int(card_index)
            self.vmw.process_click(self.vmw.clicked[i].spr)
            self.vmw.process_selection(self.vmw.clicked[i].spr)
        elif text[0] == 'j':
            if self.initiating:  # Only the sharer 'shares'.
                self._send_event('P:' + str(self.vmw.level))
                self._send_event('X:' + str(self.vmw.deck.index))
                self._send_event('M:' + str(self.vmw.matches))
                self._send_event('C:' + self.vmw.card_type)
                self._send_event('D:' + str(self._dump()))
        elif text[0] == 'J':  # Force a request for current state.
            self._send_event('j')
            self.waiting_for_deck = True
        elif text[0] == 'C':
            e, text = text.split(':')
            self.vmw.card_type = text
        elif text[0] == 'P':
            e, text = text.split(':')
            self.vmw.level = int(text)
            # self.level_label.set_text(self.calc_level_label(
            #     self.vmw.low_score, self.vmw.level))
            LEVEL_BUTTONS[self.vmw.level].set_active(True)
        elif text[0] == 'X':
            e, text = text.split(':')
            self.vmw.deck.index = int(text)
        elif text[0] == 'M':
            e, text = text.split(':')
            self.vmw.matches = int(text)
        elif text[0] == 'D':
            if self.waiting_for_deck:
                e, text = text.split(':')
                self._load(text)
                self.waiting_for_deck = False
            self.vmw.new_game(self._saved_state, self.vmw.deck.index)

    def _send_event(self, entry):
        ''' Send event through the tube. '''
        if hasattr(self, 'chattube') and self.chattube is not None:
            self.chattube.SendText(entry)
Ejemplo n.º 57
0
    def __init__(self, handle):
        '''Set up the Acoustic Tape Measure activity.'''
        super(AcousticMeasureActivity, self).__init__(handle)

        #self.set_title(_('Acoustic Tape Measure Activity'))
        self._logger = logging.getLogger('acousticmeasure-activity')

        GObject.threads_init()

        try:
            self._logger.debug("locale: " +
                               locale.setlocale(locale.LC_ALL, ''))
        except locale.Error:
            self._logger.error("setlocale failed")

        # top toolbar with share and close buttons:

        from sugar3.graphics.toolbarbox import ToolbarBox
        from sugar3.graphics.toolbarbox import ToolbarButton
        from sugar3.activity.widgets import ShareButton
        from sugar3.activity.widgets import StopButton
        from sugar3.activity.widgets import ActivityButton
        from sugar3.activity.widgets import TitleEntry

        toolbar_box = ToolbarBox()
        activity_button = ActivityButton(self)
        toolbar_box.toolbar.insert(activity_button, 0)
        activity_button.show()

        title_entry = TitleEntry(self)
        toolbar_box.toolbar.insert(title_entry, -1)
        title_entry.show()

        try:
            from sugar3.activity.widgets import DescriptionItem
            description_item = DescriptionItem(self)
            toolbar_box.toolbar.insert(description_item, -1)
            description_item.show()
        except:
            pass

        share_button = ShareButton(self)
        toolbar_box.toolbar.insert(share_button, -1)
        share_button.show()

        separator = Gtk.SeparatorToolItem()
        toolbar_box.toolbar.insert(separator, -1)
        separator.show()

        self._t_h_bar = atm_toolbars.TempToolbar()
        tb = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        self._t_h_bar.show_all()
        adj_button = ToolbarButton(page=self._t_h_bar,
                                   icon_name='preferences-system')
        toolbar_box.toolbar.insert(adj_button, -1)
        adj_button.show()

        self._smoot_bar = smoot_toolbar.SmootToolbar(self)
        self._smoot_bar.show_all()
        custom_button = ToolbarButton(page=self._smoot_bar,
                                      icon_name='view-source')
        toolbar_box.toolbar.insert(custom_button, -1)
        custom_button.show()

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

        stop_button = StopButton(self)
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()
        toolbar = toolbar_box.toolbar

        if not self.powerd_running():
            try:
                bus = dbus.SystemBus()
                proxy = bus.get_object('org.freedesktop.ohm',
                                       '/org/freedesktop/ohm/Keystore')
                self.ohm_keystore = dbus.Interface(
                    proxy, 'org.freedesktop.ohm.Keystore')
            except dbus.DBusException, e:
                self._logger.warning("Error setting OHM inhibit: %s" % e)
                self.ohm_keystore = None