Example #1
0
    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)
        self.m_key_bindings = {'backspace_ak': self.on_backspace}
        self.g_answer_box = Gtk.VBox()
        self.answer_buttons = []
        self.m_answer_buttons = {}

        #-------
        hbox = gu.bHBox(self.practise_box)
        b = Gtk.Button(_("Play"))
        b.show()
        b.connect('clicked', self.play_users_answer)
        hbox.pack_start(b, False, True, 0)
        self.practise_box.pack_start(Gtk.HBox(), False, False,
                                     padding=gu.PAD_SMALL)
        self.g_rhythm_viewer = RhythmViewer(self)
        self.g_rhythm_viewer.create_holders()
        hbox.pack_start(self.g_rhythm_viewer, True, True, 0)

        self.practise_box.pack_start(self.g_answer_box, False, False, 0)

        # action area
        self.std_buttons_add(
            ('new', self.new_question),
            ('repeat', self.repeat_question),
            #('play_answer', self.play_users_answer),
            ('give_up', self.give_up),
            ('backspace', self.on_backspace))

        self.practise_box.show_all()
        ##############
        # config_box #
        ##############
        self.add_select_elements_gui()
        #--------
        self.config_box.pack_start(Gtk.HBox(), False, False,
                                   padding=gu.PAD_SMALL)
        self.add_select_num_notes_gui()
        #-----
        self.config_box.pack_start(Gtk.HBox(), False, False,
                                   padding=gu.PAD_SMALL)
        #------
        hbox = gu.bHBox(self.config_box, False)
        hbox.set_spacing(gu.PAD_SMALL)
        hbox.pack_start(Gtk.Label(_("Beats per minute:")), False, False, 0)
        spin = gu.nSpinButton(self.m_exname, 'bpm',
                 Gtk.Adjustment(60, 20, 240, 1, 10))
        hbox.pack_start(spin, False, False, 0)
        hbox = gu.bHBox(self.config_box, False)
        hbox.set_spacing(gu.PAD_SMALL)
        hbox.pack_start(gu.nCheckButton(self.m_exname,
                                        "show_first_note",
                                        _("Show the first tone")), False, False, 0)
        hbox.pack_start(gu.nCheckButton(self.m_exname,
                                        "play_cadence",
                                        _("Play cadence")), False, False, 0)
        self._add_auto_new_question_gui(self.config_box)
        self.config_box.show_all()
Example #2
0
    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)
        self.m_key_bindings = {'backspace_ak': self.on_backspace}
        self.g_answer_box = gtk.VBox()
        self.answer_buttons = []

        #-------
        hbox = gu.bHBox(self.practise_box)
        b = gtk.Button(_("Play"))
        b.show()
        b.connect('clicked', self.play_users_answer)
        hbox.pack_start(b, False, True)
        self.practise_box.pack_start(gtk.HBox(), False,
                                     padding=gu.PAD_SMALL)
        self.g_rhythm_viewer = RhythmViewer(self)
        self.g_rhythm_viewer.create_holders()
        hbox.pack_start(self.g_rhythm_viewer)

        self.practise_box.pack_start(self.g_answer_box, False)

        # action area
        self.std_buttons_add(
            ('new', self.new_question),
            ('repeat', self.repeat_question),
            #('play_answer', self.play_users_answer),
            ('give_up', self.give_up),
            ('backspace', self.on_backspace))

        self.practise_box.show_all()
        ##############
        # config_box #
        ##############
        self.add_select_elements_gui()
        #--------
        self.config_box.pack_start(gtk.HBox(), False,
                                   padding=gu.PAD_SMALL)
        self.add_select_num_notes_gui()
        #-----
        self.config_box.pack_start(gtk.HBox(), False,
                                   padding=gu.PAD_SMALL)
        #------
        hbox = gu.bHBox(self.config_box, False)
        hbox.set_spacing(gu.PAD_SMALL)
        hbox.pack_start(gtk.Label(_("Beats per minute:")), False)
        spin = gu.nSpinButton(self.m_exname, 'bpm',
                 gtk.Adjustment(60, 20, 240, 1, 10))
        hbox.pack_start(spin, False)
        hbox = gu.bHBox(self.config_box, False)
        hbox.set_spacing(gu.PAD_SMALL)
        hbox.pack_start(gu.nCheckButton(self.m_exname,
                                        "show_first_note",
                                        _("Show the first tone")), False)
        hbox.pack_start(gu.nCheckButton(self.m_exname,
                                        "play_cadence",
                                        _("Play cadence")), False)
        self._add_auto_new_question_gui(self.config_box)
        self.config_box.show_all()
Example #3
0
    def create_practise_config(self):
        it, page_vbox = self.new_page_box(None, _("Practise"))
        self.g_picky_on_new_question = gu.nCheckButton('config', 'picky_on_new_question', _("_Not allow new question before the old is solved"))
        page_vbox.pack_start(self.g_picky_on_new_question, False, False, 0)

        self.g_autorepeat_if_wrong = gu.nCheckButton('config', 'auto_repeat_question_if_wrong_answer', _("_Repeat question if the answer was wrong"))
        page_vbox.pack_start(self.g_autorepeat_if_wrong, False, False, 0)

        self.g_expert_mode = gu.nCheckButton('gui',
                'expert_mode', _("E_xpert mode"))
        self.g_expert_mode.connect('toggled', solfege.app.reset_exercise)
        page_vbox.pack_start(self.g_expert_mode, False, False, 0)
Example #4
0
    def add_lock_to_key_gui(self):
        # gui to lock to a key
        def toggle_lock_to_key_sensitivity(checkbutton):
            self.g_notename.set_sensitive(checkbutton.get_active())
            self.g_scaletype.set_sensitive(checkbutton.get_active())

        self.g_lock_to_key_hbox = Gtk.HBox(False, gu.hig.SPACE_SMALL)
        self.config_box.pack_start(self.g_lock_to_key_hbox, False, False, 0)
        check = gu.nCheckButton(self.m_exname,
                                'lock-to-key',
                                _("Lock intervals to key:"),
                                callback=toggle_lock_to_key_sensitivity)
        self.g_lock_to_key_hbox.pack_start(check, False, False, 0)
        self.g_notename = gu.nComboBox(
            self.m_exname, 'lock-to-key-note',
            mpd.MusicalPitch.new_from_int(60).get_user_notename(), [
                mpd.MusicalPitch.new_from_int(60 + x).get_user_notename()
                for x in range(12)
            ])
        self.g_notename.show()
        self.g_lock_to_key_hbox.pack_start(self.g_notename, False, False, 0)
        self.g_scaletype = gu.nComboBox(
            self.m_exname, 'lock-to-key-scaletype', _("Major"),
            [n['name'] for n in utils.key_data.values()])
        self.g_scaletype.show()
        self.g_lock_to_key_hbox.pack_start(self.g_scaletype, False, False, 0)
        toggle_lock_to_key_sensitivity(check)
Example #5
0
    def create_practise_config(self):
        it, page_vbox = self.new_page_box(None, _("Practise"))
        self.g_picky_on_new_question = gu.nCheckButton(
            'config', 'picky_on_new_question',
            _("_Not allow new question before the old is solved"))
        page_vbox.pack_start(self.g_picky_on_new_question, False, False, 0)

        self.g_autorepeat_if_wrong = gu.nCheckButton(
            'config', 'auto_repeat_question_if_wrong_answer',
            _("_Repeat question if the answer was wrong"))
        page_vbox.pack_start(self.g_autorepeat_if_wrong, False, False, 0)

        self.g_expert_mode = gu.nCheckButton('gui', 'expert_mode',
                                             _("E_xpert mode"))
        self.g_expert_mode.connect('toggled', solfege.app.reset_exercise)
        page_vbox.pack_start(self.g_expert_mode, False, False, 0)
Example #6
0
    def __init__(self, exname, num, labeltext):
        Gtk.VBox.__init__(self)
        #cfg.ConfigUtils.__init__(self, exname)
        cfg.ConfigUtils.__dict__['__init__'](self, exname)
        assert num in (2, 3)
        self.m_num = num
        self.g_override_default_instrument_checkbutton \
            = gu.nCheckButton(exname, 'override_default_instrument',
                labeltext,
                 callback=self.update_instrument_override)
        self.pack_start(self.g_override_default_instrument_checkbutton,
                        False, False, 0)
        hbox = gu.bVBox(self)
        hbox.set_spacing(gu.PAD_SMALL)

        sizegroup = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)
        self.g_instrsel_high = FramedInstrumentSelector(_("Highest:"), exname, 'highest_instrument',sizegroup)
        hbox.pack_start(self.g_instrsel_high, False, False, 0)
        if num == 3:
            self.g_instrsel_middle = FramedInstrumentSelector(_("Middle:"),
                                            exname, 'middle_instrument', sizegroup)
            hbox.pack_start(self.g_instrsel_middle, False, False, 0)
        else:
            self.g_instrsel_middle = None
        self.g_instrsel_low = FramedInstrumentSelector(_("Lowest:"),
                                                exname, 'lowest_instrument', sizegroup)
        hbox.pack_start(self.g_instrsel_low, False, False, 0)
        self.update_instrument_override()
Example #7
0
    def __init__(self, default_profile):
        gtk.Dialog.__init__(self, _("GNU Solfege - Choose User Profile"))
        # We save the initially selected profile, because we need to keep
        # track of it if the user renames it and then presses cancel.
        self.m_default_profile = default_profile
        vbox = gu.hig_dlg_vbox()
        self.vbox.pack_start(vbox, False)
        l = gtk.Label(
            _("Solfege will save your statistics and test results in the user profile. By adding additional user profiles to Solfege, multiple users can share a user account on the operating system."
              ))
        l.set_alignment(0.0, 0.5)
        l.set_line_wrap(True)
        vbox.pack_start(l)

        hbox = gtk.HBox()
        hbox.set_spacing(gu.hig.SPACE_MEDIUM)
        vbox.pack_start(hbox)
        button_box = gtk.VBox()

        self.g_create_profile = gtk.Button(_(u"_Create profile\u2026"))
        self.g_create_profile.connect('clicked', self.on_create_profile)
        button_box.pack_start(self.g_create_profile, False)

        self.g_rename_profile = gtk.Button(_(u"_Rename profile\u2026"))
        self.g_rename_profile.connect('clicked', self.on_rename_profile)
        button_box.pack_start(self.g_rename_profile, False)

        self.g_delete_profile = gtk.Button(_(u"_Delete profile\u2026"))
        self.g_delete_profile.connect('clicked', self.on_delete_profile)
        button_box.pack_start(self.g_delete_profile, False)

        hbox.pack_start(button_box, False)
        self.g_liststore = liststore = gtk.ListStore(gobject.TYPE_STRING)
        liststore.append((_("Standard profile"), ))
        if os.path.exists(os.path.join(filesystem.app_data(), 'profiles')):
            for subdir in os.listdir(
                    os.path.join(filesystem.app_data(), 'profiles')):
                liststore.append((subdir, ))
        #
        self.g_tw = tw = gtk.TreeView(liststore)
        tw.connect('row-activated',
                   lambda a, b, c: self.response(gtk.RESPONSE_ACCEPT))
        tw.set_headers_visible(False)
        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn(None, renderer, text=0)
        tw.append_column(column)
        hbox.pack_start(tw, False)
        tw.show()
        tw.connect('cursor-changed', self.on_cursor_changed)
        tw.set_cursor((0, ))
        for idx, s in enumerate(self.g_liststore):
            if s[0] == default_profile:
                tw.set_cursor((idx, ))
        #
        chk = gu.nCheckButton("app", "noprofilemanager",
                              _("D_on't ask at startup"))
        vbox.pack_start(chk, False)
        self.show_all()
Example #8
0
    def create_gui_config(self):
        i_iter, page_vbox = self.new_page_box(None, _("Interface"))

        self.g_mainwin_user_resizeable = gu.nCheckButton(
            'gui', 'mainwin_user_resizeable', _("_Resizeable main window"))
        page_vbox.pack_start(self.g_mainwin_user_resizeable, False, False, 0)

        # Combobox to select language
        hbox = Gtk.HBox()
        hbox.set_spacing(6)
        label = Gtk.Label()
        label.set_text_with_mnemonic(_("Select _language:"))
        hbox.pack_start(label, False, False, 0)
        self.g_language = Gtk.ComboBoxText()
        for n in languages.languages:
            self.g_language.append_text(n)
        label.set_mnemonic_widget(self.g_language)
        if sys.platform == 'win32':
            lang = winlang.win32_get_langenviron()
            if lang in languages.languages:
                idx = languages.languages.index(lang)
            elif lang == 'C':
                idx = languages.C_locale_idx
            else:
                idx = 0
        else:
            lang = cfg.get_string('app/lc_messages')
            if lang in languages.languages:
                idx = languages.languages.index(lang)
            elif lang == 'C':
                idx = languages.C_locale_idx
            else:
                idx = 0
        self.g_language.set_active(idx)

        def f(combobox):
            if combobox.get_active() == languages.C_locale_idx:
                lang = "C"
            else:
                lang = languages.languages[combobox.get_active()]
            cfg.set_string('app/lc_messages', lang)
            if sys.platform == 'win32':
                if combobox.get_active():
                    winlang.win32_put_langenviron(lang)
                else:
                    winlang.win32_put_langenviron(None)

        self.g_language.connect_after('changed', f)
        hbox.pack_start(self.g_language, False, False, 0)
        page_vbox.pack_start(hbox, False, False, 0)
        l = Gtk.Label(label=_(
            "You have to restart the program for the language change to take effect."
        ))
        l.set_alignment(0.0, 0.5)
        page_vbox.pack_start(l, False, False, 0)

        self.create_idtone_accels_config(i_iter)
        self.create_interval_accels_config(i_iter)
Example #9
0
    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)
        grid = Gtk.Grid()
        grid.set_row_spacing(gu.hig.SPACE_SMALL)
        grid.set_column_spacing(gu.hig.SPACE_SMALL)
        self.g_buttons = fill_grid(Gtk.Button, grid)
        for key, button in list(self.g_buttons.items()):
            button.connect('clicked', self.on_left_click, key)
        self.practise_box.pack_start(grid, False, False, gu.hig.SPACE_SMALL)
        self.g_flashbar = gu.FlashBar()
        self.g_flashbar.show()
        self.practise_box.pack_start(self.g_flashbar, False, False, 0)
        self.std_buttons_add(
            ('new', self.new_question),
            ('repeat', lambda _o, self=self: self.m_t.play_question()),
            ('give_up', self.give_up))
        self.practise_box.show_all()
        ###############
        # config_grid #
        ###############
        # FIXME we need a ComboBox
        # self.g_random = gu.nCheckButton(self.m_exname, 'random_tonic', _("Random transpose"))
        # self.g_config_grid.attach(self.g_random, 0, 0, 1, 1)
        #
        self.g_tones_category, box = gu.hig_category_vbox(_("Tones"))
        self.g_config_grid.attach(self.g_tones_category, 0, 2, 3, 1)
        self.g_tone_selector = nConfigButtons(self.m_exname, 'tones')
        self.g_tone_selector.show_all()
        box.pack_start(self.g_tone_selector, False, False, 0)
        self.g_many_octaves = b = gu.nCheckButton('toneincontext', 'many_octaves',
            _("Many octaves"))
        self.g_config_grid.attach(b, 0, 3, 1, 1)
        # Cadences
        self.g_cadences_category, self.g_cadences = gu.hig_category_vbox(_("Cadences"))
        self.g_cadences.show()
        self.g_config_grid.attach(self.g_cadences_category, 0, 4, 1, 1)
        #

        def _ff(var):
            if self.m_t.m_custom_mode:
                # If we are running in custom mode, then the user can
                # select himself what intervals to practise. And then
                # we have to reset the exercise.
                # self.on_end_practise()
                # self.on_start_practise()
                self.cancel_question()
        self.add_watch('tones', _ff)
        ##############
        # Statistics #
        ##############
        self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                   _("Tone in cadence"))
        #
        self.g_statview = StatisticsViewer(self.m_t)
        self.g_statview.show()
        self.g_notebook.append_page(self.g_statview, Gtk.Label(label=_("Statistics")))
        self.g_notebook.connect(
            'switch_page', self.g_statview.update)
Example #10
0
    def __init__(self, parent, default_profile):
        Gtk.Dialog.__init__(self, _("GNU Solfege - Choose User Profile"),
                            parent)
        # Set a small size, and let the widgets expand the dialog
        self.set_default_size(100, 100)
        # We save the initially selected profile, because we need to keep
        # track of it if the user renames it and then presses cancel.
        self.m_default_profile = default_profile
        vbox = gu.hig_dlg_vbox()
        self.get_content_area().pack_start(vbox, False, False, 0)
        l = Gtk.Label(_("Solfege will save your statistics and test results in the user profile. By adding additional user profiles to Solfege, multiple users can share a user account on the operating system."))
        l.set_alignment(0.0, 0.5)
        l.set_line_wrap(True)
        vbox.pack_start(l, True, True, 0)

        hbox = Gtk.HBox()
        hbox.set_spacing(gu.hig.SPACE_MEDIUM)
        vbox.pack_start(hbox, True, True, 0)
        button_box = Gtk.VBox()

        self.g_create_profile = Gtk.Button.new_with_mnemonic(_("_Create profile\u2026"))
        self.g_create_profile.connect('clicked', self.on_create_profile)
        button_box.pack_start(self.g_create_profile, False, False, 0)

        self.g_rename_profile = Gtk.Button.new_with_mnemonic(_("_Rename profile\u2026"))
        self.g_rename_profile.connect('clicked', self.on_rename_profile)
        button_box.pack_start(self.g_rename_profile, False, False, 0)

        self.g_delete_profile = Gtk.Button.new_with_mnemonic(_("_Delete profile\u2026"))
        self.g_delete_profile.connect('clicked', self.on_delete_profile)
        button_box.pack_start(self.g_delete_profile, False, False, 0)

        hbox.pack_start(button_box, False, False, 0)
        self.g_liststore = liststore = Gtk.ListStore(GObject.TYPE_STRING)
        liststore.append((_("Standard profile"),))
        if os.path.exists(os.path.join(filesystem.app_data(), 'profiles')):
            for subdir in os.listdir(os.path.join(filesystem.app_data(),
                'profiles')):
                liststore.append((subdir,))
        #
        self.g_tw = tw = Gtk.TreeView(liststore)
        tw.connect('row-activated', lambda a, b, c: self.response(Gtk.ResponseType.ACCEPT))
        tw.set_headers_visible(False)
        renderer = Gtk.CellRendererText()
        column = Gtk.TreeViewColumn(None, renderer, text=0)
        tw.append_column(column)
        hbox.pack_start(tw, False, False, 0)
        tw.show()
        tw.connect('cursor-changed', self.on_cursor_changed)
        tw.set_cursor((0,))
        for idx, s in enumerate(self.g_liststore):
            if s[0] == default_profile:
                tw.set_cursor((idx, ))
        #
        chk = gu.nCheckButton("app", "noprofilemanager", _("D_on't ask at startup"))
        vbox.pack_start(chk, False, False, 0)
        self.show_all()
Example #11
0
    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)
        self.m_key_bindings = {'backspace_ak': self.on_backspace}
        self.g_answer_box = gu.NewLineBox()
        self.practise_box.pack_start(self.g_answer_box, False, False, 0)
        #-------
        hbox = gu.bHBox(self.practise_box)
        b = Gtk.Button(_("Play"))
        b.show()
        b.connect('clicked', self.play_users_answer)
        hbox.pack_start(b, False, True, 0)
        self.practise_box.pack_start(Gtk.HBox(False, 0),
                                     False,
                                     False,
                                     padding=gu.PAD_SMALL)
        self.g_rhythm_viewer = RhythmViewer(self)
        #FIXME the value 52 is dependant on the theme used
        self.g_rhythm_viewer.set_size_request(-1, 52)
        self.g_rhythm_viewer.create_holders()
        hbox.pack_start(self.g_rhythm_viewer, True, True, 0)

        # action area
        self.std_buttons_add(
            ('new', self.new_question), ('repeat', self.repeat_question),
            ('give_up', self.give_up), ('backspace', self.on_backspace))

        self.practise_box.show_all()
        ##############
        # config_box #
        ##############
        self.add_select_elements_gui()
        #--------
        self.config_box.pack_start(Gtk.HBox(False, 0),
                                   False,
                                   False,
                                   padding=gu.PAD_SMALL)
        self.add_select_num_beats_gui()
        #-----
        self.config_box.pack_start(Gtk.HBox(False, 0),
                                   False,
                                   False,
                                   padding=gu.PAD_SMALL)
        #------
        hbox = gu.bHBox(self.config_box, False)
        hbox.set_spacing(gu.PAD_SMALL)
        hbox.pack_start(
            gu.nCheckButton(self.m_exname, "not_start_with_rest",
                            _("Don't start the question with a rest")), False,
            False, 0)
        sep = Gtk.VSeparator()
        hbox.pack_start(sep, False, False, 0)
        hbox.pack_start(Gtk.Label(_("Beats per minute:")), False, False, 0)
        spin = gu.nSpinButton(self.m_exname, 'bpm',
                              Gtk.Adjustment(60, 20, 240, 1, 10))
        hbox.pack_start(spin, False, False, 0)
        self._add_auto_new_question_gui(self.config_box)
        self.config_box.show_all()
Example #12
0
    def create_gui_config(self):
        i_iter, page_vbox = self.new_page_box(None, _("Interface"))

        self.g_mainwin_user_resizeable = gu.nCheckButton('gui',
          'mainwin_user_resizeable', _("_Resizeable main window"))
        page_vbox.pack_start(self.g_mainwin_user_resizeable, False, False, 0)

        # Combobox to select language
        hbox = Gtk.HBox()
        hbox.set_spacing(6)
        label = Gtk.Label()
        label.set_text_with_mnemonic(_("Select _language:"))
        hbox.pack_start(label, False, False, 0)
        self.g_language = Gtk.ComboBoxText()
        for n in languages.languages:
            self.g_language.append_text(n)
        label.set_mnemonic_widget(self.g_language)
        if sys.platform == 'win32':
            lang = winlang.win32_get_langenviron()
            if lang in languages.languages:
                idx = languages.languages.index(lang)
            elif lang == 'C':
                idx = languages.C_locale_idx
            else:
                idx = 0
        else:
            lang = cfg.get_string('app/lc_messages')
            if lang in languages.languages:
                idx = languages.languages.index(lang)
            elif lang == 'C':
                idx = languages.C_locale_idx
            else:
                idx = 0
        self.g_language.set_active(idx)

        def f(combobox):
            if combobox.get_active() == languages.C_locale_idx:
                lang = "C"
            else:
                lang = languages.languages[combobox.get_active()]
            cfg.set_string('app/lc_messages', lang)
            if sys.platform == 'win32':
                if combobox.get_active():
                    winlang.win32_put_langenviron(lang)
                else:
                    winlang.win32_put_langenviron(None)
        self.g_language.connect_after('changed', f)
        hbox.pack_start(self.g_language, False, False, 0)
        page_vbox.pack_start(hbox, False, False, 0)
        l = Gtk.Label(label=_("You have to restart the program for the language change to take effect."))
        l.set_alignment(0.0, 0.5)
        page_vbox.pack_start(l, False, False, 0)

        self.create_idtone_accels_config(i_iter)
        self.create_interval_accels_config(i_iter)
Example #13
0
    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)
        self.m_key_bindings = {'backspace_ak': self.on_backspace}
        self.g_answer_box = gu.NewLineBox()
        self.practise_box.pack_start(self.g_answer_box, False)
        #-------
        hbox = gu.bHBox(self.practise_box)
        b = gtk.Button(_("Play"))
        b.show()
        b.connect('clicked', self.play_users_answer)
        hbox.pack_start(b, False, True)
        self.practise_box.pack_start(gtk.HBox(), False,
                                     padding=gu.PAD_SMALL)
        self.g_rhythm_viewer = RhythmViewer(self)
        #FIXME the value 52 is dependant on the theme used
        self.g_rhythm_viewer.set_size_request(-1, 52)
        self.g_rhythm_viewer.create_holders()
        hbox.pack_start(self.g_rhythm_viewer)
        #self.practise_box.pack_start(self.g_rhythm_viewer, False)

        # action area
        self.std_buttons_add(
            ('new', self.new_question),
            ('repeat', self.repeat_question),
            ('give_up', self.give_up))

        self.g_backspace = gu.bButton(self.action_area, _("_Backspace"),
                     self.on_backspace)
        self.g_backspace.set_sensitive(False)
        self.practise_box.show_all()
        ##############
        # config_box #
        ##############
        self.add_select_elements_gui()
        #--------
        self.config_box.pack_start(gtk.HBox(), False,
                                   padding=gu.PAD_SMALL)
        self.add_select_num_beats_gui()
        #-----
        self.config_box.pack_start(gtk.HBox(), False,
                                   padding=gu.PAD_SMALL)
        #------
        hbox = gu.bHBox(self.config_box, False)
        hbox.set_spacing(gu.PAD_SMALL)
        hbox.pack_start(gu.nCheckButton(self.m_exname,
                 "not_start_with_rest",
                 _("Don't start the question with a rest")), False)
        sep = gtk.VSeparator()
        hbox.pack_start(sep, False)
        hbox.pack_start(gtk.Label(_("Beats per minute:")), False)
        spin = gu.nSpinButton(self.m_exname, 'bpm',
                 gtk.Adjustment(60, 20, 240, 1, 10))
        hbox.pack_start(spin, False)
        self._add_auto_new_question_gui(self.config_box)
        self.config_box.show_all()
Example #14
0
    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)
        t = gtk.Table()
        self.g_buttons = fill_table(gtk.Button, t)
        for key, button in self.g_buttons.items():
            button.connect('clicked', self.on_left_click, key)
        self.practise_box.pack_start(t, False)
        self.g_flashbar = gu.FlashBar()
        self.g_flashbar.show()
        self.practise_box.pack_start(self.g_flashbar, False)
        self.std_buttons_add(
            ('new', self.new_question),
            ('repeat', lambda _o, self=self: self.m_t.play_question()),
            ('give_up', self.give_up))
        self.practise_box.show_all()
        ##############
        # config_box #
        ##############
        self.config_box.set_spacing(gu.hig_dlg_vbox.spacing)
        self.g_random = gu.nCheckButton(self.m_exname, 'random_tonic',
                                        _("Random transpose"))
        self.config_box.pack_start(self.g_random, False)
        self._add_auto_new_question_gui(self.config_box)
        #
        self.g_tones_category, box = gu.hig_category_vbox(_("Tones"))
        self.config_box.pack_start(self.g_tones_category, False)
        self.g_tone_selector = nConfigButtons(self.m_exname, 'tones')
        self.g_tone_selector.show_all()
        box.pack_start(self.g_tone_selector, False)
        # Cadences
        self.g_cadences_category, self.g_cadences = gu.hig_category_vbox(
            _("Cadences"))
        self.g_cadences.show()
        self.config_box.pack_start(self.g_cadences_category, False)

        #
        def _ff(var):
            if self.m_t.m_custom_mode:
                # If we are running in custom mode, then the user can
                # select himself what intervals to practise. And then
                # we have to reset the exercise.
                #self.on_end_practise()
                #self.on_start_practise()
                self.cancel_question()

        self.add_watch('tones', _ff)
        self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                    _("Tone in cadence"))
Example #15
0
    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)
        self.m_key_bindings = {'backspace_ak': self.on_backspace}
        self.g_answer_box = gu.NewLineBox()
        self.practise_box.pack_start(self.g_answer_box, False, False, 0)
        #-------
        hbox = gu.bHBox(self.practise_box, False)
        b = Gtk.Button(_("Play"))
        b.show()
        b.connect('clicked', self.play_users_answer)
        hbox.pack_start(b, False, True, 0)
        self.practise_box.pack_start(Gtk.HBox(False, 0), False, False,
                                     padding=gu.PAD_SMALL)
        self.g_rhythm_viewer = RhythmViewer(self)
        # FIXME the value 52 is dependant on the theme used
        self.g_rhythm_viewer.set_size_request(-1, 52)
        self.g_rhythm_viewer.create_holders()
        hbox.pack_start(self.g_rhythm_viewer, True, True, 0)

        # action area
        self.std_buttons_add(
            ('new', self.new_question),
            ('repeat', self.repeat_question),
            ('give_up', self.give_up),
            ('backspace', self.on_backspace))

        self.practise_box.show_all()
        ###############
        # config_grid #
        ###############
        self.add_select_elements_gui(self.g_config_grid, 0)
        #--------
        self.add_select_num_beats_gui(self.g_config_grid, 1)
        #-----
        self.g_config_grid.attach(
                gu.nCheckButton(self.m_exname,
                 "not_start_with_rest",
                 _("Don't start the question with a rest")),
                0, 3, 1, 1)
        label = Gtk.Label(_("Beats per minute:"))
        label.props.halign = Gtk.Align.END
        self.g_config_grid.attach(label, 0, 4, 1, 1)
        spin = gu.nSpinButton(self.m_exname, 'bpm',
                 Gtk.Adjustment(60, 20, 240, 1, 10))
        self.g_config_grid.attach(spin, 1, 4, 1, 1)
        self._add_auto_new_question_gui(row=5)
        self.g_config_grid.show_all()
Example #16
0
 def __init__(self, teacher):
     abstract.Gui.__init__(self, teacher)
     t = Gtk.Table()
     self.g_buttons = fill_table(Gtk.Button, t)
     for key, button in self.g_buttons.items():
         button.connect('clicked', self.on_left_click, key)
     self.practise_box.pack_start(t, False, False, 0)
     self.g_flashbar = gu.FlashBar()
     self.g_flashbar.show()
     self.practise_box.pack_start(self.g_flashbar, False, False, 0)
     self.std_buttons_add(
         ('new', self.new_question),
         ('repeat', lambda _o, self=self: self.m_t.play_question()),
         ('give_up', self.give_up))
     self.practise_box.show_all()
     ##############
     # config_box #
     ##############
     self.config_box.set_spacing(gu.hig.SPACE_MEDIUM)
     self.g_random = gu.nCheckButton(self.m_exname, 'random_tonic', _("Random transpose"))
     self.config_box.pack_start(self.g_random, False, False, 0)
     self._add_auto_new_question_gui(self.config_box)
     #
     self.g_tones_category, box = gu.hig_category_vbox(_("Tones"))
     self.config_box.pack_start(self.g_tones_category, False, False, 0)
     self.g_tone_selector = nConfigButtons(self.m_exname, 'tones')
     self.g_tone_selector.show_all()
     box.pack_start(self.g_tone_selector, False, False, 0)
     # Cadences
     self.g_cadences_category, self.g_cadences = gu.hig_category_vbox(_("Cadences"))
     self.g_cadences.show()
     self.config_box.pack_start(self.g_cadences_category, False, False, 0)
     #
     def _ff(var):
         if self.m_t.m_custom_mode:
             # If we are running in custom mode, then the user can
             # select himself what intervals to practise. And then
             # we have to reset the exercise.
             #self.on_end_practise()
             #self.on_start_practise()
             self.cancel_question()
     self.add_watch('tones', _ff)
     self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                _("Tone in cadence"))
Example #17
0
 def add_lock_to_key_gui(self, row):
     # gui to lock to a key
     def toggle_lock_to_key_sensitivity(checkbutton):
         self.g_notename.set_sensitive(checkbutton.get_active())
         self.g_scaletype.set_sensitive(checkbutton.get_active())
     check = gu.nCheckButton(self.m_exname, 'lock-to-key',
         _("Lock intervals to key"),
         callback=toggle_lock_to_key_sensitivity)
     check.props.halign = Gtk.Align.END
     self.g_notename = gu.nComboBox(self.m_exname, 'lock-to-key-note',
         mpd.MusicalPitch.new_from_int(60).get_user_notename(),
         [mpd.MusicalPitch.new_from_int(60 + i).get_user_notename() for i in range(12)])
     self.g_notename.show()
     self.g_scaletype = gu.nComboBox(self.m_exname, 'lock-to-key-scaletype', _("Major"), [n['name'] for n in list(utils.key_data.values())])
     self.g_scaletype.show()
     self.g_config_grid.attach(check, 0, row, 1, 1)
     self.g_config_grid.attach(self.g_notename, 1, row, 1, 1)
     self.g_config_grid.attach(self.g_scaletype, 2, row, 1, 1)
     toggle_lock_to_key_sensitivity(check)
Example #18
0
 def _add_auto_new_question_gui(self, box):
     hbox = gu.bHBox(box, False)
     hbox.set_spacing(gu.PAD_SMALL)
     adj = gtk.Adjustment(0, 0, 10, 0.1, 1)
     spin = gu.nSpinButton(self.m_exname, 'seconds_before_new_question',
                    adj)
     spin.set_digits(1)
     label = gtk.Label(_("Delay (seconds):"))
     label.show()
     def f(button, spin=spin, label=label):
         spin.set_sensitive(button.get_active())
         label.set_sensitive(button.get_active())
     b = gu.nCheckButton(self.m_exname, 'new_question_automatically',
                         _("_New question automatically."), callback=f)
     hbox.pack_start(b, False)
     label.set_sensitive(b.get_active())
     hbox.pack_start(label, False)
     spin.set_sensitive(b.get_active())
     hbox.pack_start(spin, False)
Example #19
0
 def _add_auto_new_question_gui(self, box):
     hbox = gu.bHBox(box, False)
     hbox.set_spacing(gu.PAD_SMALL)
     adj = Gtk.Adjustment(0, 0, 10, 0.1, 1)
     spin = gu.nSpinButton(self.m_exname, 'seconds_before_new_question',
                    adj)
     spin.set_digits(1)
     label = Gtk.Label(label=_("Delay (seconds):"))
     label.show()
     def f(button, spin=spin, label=label):
         spin.set_sensitive(button.get_active())
         label.set_sensitive(button.get_active())
     b = gu.nCheckButton(self.m_exname, 'new_question_automatically',
                         _("_New question automatically."), callback=f)
     hbox.pack_start(b, False, False, 0)
     label.set_sensitive(b.get_active())
     hbox.pack_start(label, False, False, 0)
     spin.set_sensitive(b.get_active())
     hbox.pack_start(spin, False, False, 0)
Example #20
0
 def add_lock_to_key_gui(self):
     # gui to lock to a key
     def toggle_lock_to_key_sensitivity(checkbutton):
         self.g_notename.set_sensitive(checkbutton.get_active())
         self.g_scaletype.set_sensitive(checkbutton.get_active())
     self.g_lock_to_key_hbox = Gtk.HBox(False, gu.hig.SPACE_SMALL)
     self.config_box.pack_start(self.g_lock_to_key_hbox, False, False, 0)
     check = gu.nCheckButton(self.m_exname, 'lock-to-key',
         _("Lock intervals to key:"),
         callback = toggle_lock_to_key_sensitivity)
     self.g_lock_to_key_hbox.pack_start(check, False, False, 0)
     self.g_notename = gu.nComboBox(self.m_exname, 'lock-to-key-note',
         mpd.MusicalPitch.new_from_int(60).get_user_notename(),
         [mpd.MusicalPitch.new_from_int(60 + x).get_user_notename() for x in range(12)])
     self.g_notename.show()
     self.g_lock_to_key_hbox.pack_start(self.g_notename, False, False, 0)
     self.g_scaletype = gu.nComboBox(self.m_exname, 'lock-to-key-scaletype', _("Major"), [n['name'] for n in utils.key_data.values()])
     self.g_scaletype.show()
     self.g_lock_to_key_hbox.pack_start(self.g_scaletype, False, False, 0)
     toggle_lock_to_key_sensitivity(check)
Example #21
0
    def _create_select_inputwidget_gui(self, row):
        """
        This will be called by HarmonicInterval and MelodicInterval
        constructor
        """
        label = Gtk.Label(_("Input interface"))
        label.props.halign = Gtk.Align.END
        combo = Gtk.ComboBoxText()
        for i in range(len(inputwidgets.inputwidget_names)):
            combo.append_text(inputwidgets.inputwidget_names[i])
        if self.get_int('inputwidget') < len(inputwidgets.inputwidget_names):
            combo.set_active(self.get_int('inputwidget'))
        else:
            combo.set_active(0)
        combo.connect('changed', lambda w: self.use_inputwidget(w.get_active()))

        self.g_disable_unused_buttons = gu.nCheckButton(self.m_exname,
                    'disable_unused_intervals', _("_Disable unused buttons"))
        self.g_config_grid.attach(label, 0, row, 1, 1)
        self.g_config_grid.attach(combo, 1, row, 1, 1)
        self.g_config_grid.attach(self.g_disable_unused_buttons, 2, row, 1, 1)
Example #22
0
    def _create_select_inputwidget_gui(self):
        """
        This will be called by HarmonicInterval and MelodicInterval
        constructor
        """
        hbox = gu.bHBox(self.config_box, False)
        hbox.set_spacing(gu.PAD_SMALL)
        gu.bLabel(hbox, _("Input interface:"), False)

        combo = gtk.combo_box_new_text()
        for i in range(len(inputwidgets.inputwidget_names)):
            combo.append_text(inputwidgets.inputwidget_names[i])
        if self.get_int('inputwidget') < len(inputwidgets.inputwidget_names):
            combo.set_active(self.get_int('inputwidget'))
        else:
            combo.set_active(0)
        combo.connect('changed', lambda w: self.use_inputwidget(w.get_active()))
        hbox.pack_start(combo, False)

        self.g_disable_unused_buttons = gu.nCheckButton(self.m_exname,
                    'disable_unused_intervals', _("_Disable unused buttons"))
        hbox.pack_start(self.g_disable_unused_buttons)
Example #23
0
    def _create_select_inputwidget_gui(self):
        """
        This will be called by HarmonicInterval and MelodicInterval
        constructor
        """
        hbox = gu.bHBox(self.config_box, False)
        hbox.set_spacing(gu.PAD_SMALL)
        gu.bLabel(hbox, _("Input interface:"), False)

        combo = Gtk.ComboBoxText()
        for i in range(len(inputwidgets.inputwidget_names)):
            combo.append_text(inputwidgets.inputwidget_names[i])
        if self.get_int('inputwidget') < len(inputwidgets.inputwidget_names):
            combo.set_active(self.get_int('inputwidget'))
        else:
            combo.set_active(0)
        combo.connect('changed', lambda w: self.use_inputwidget(w.get_active()))
        hbox.pack_start(combo, False, False, 0)

        self.g_disable_unused_buttons = gu.nCheckButton(self.m_exname,
                    'disable_unused_intervals', _("_Disable unused buttons"))
        hbox.pack_start(self.g_disable_unused_buttons, True, True, 0)
Example #24
0
    def _add_auto_new_question_gui(self, row):
        """
        Add the user interface used to configure if we should get a new
        question automatically. The GUI is added to self.g_config_grid
        at the row set by the ROW variable.
        """
        adj = Gtk.Adjustment(0, 0, 10, 0.1, 1)
        spin = gu.nSpinButton(self.m_exname, 'seconds_before_new_question',
                       adj)
        spin.set_digits(1)
        label = Gtk.Label(label=_("seconds delay"))
        label.props.halign = Gtk.Align.START

        def f(button, spin=spin, label=label):
            spin.set_sensitive(button.get_active())
            label.set_sensitive(button.get_active())
        b = gu.nCheckButton(self.m_exname, 'new_question_automatically',
                            _("_New question automatically"), callback=f)
        b.props.halign = Gtk.Align.END
        label.set_sensitive(b.get_active())
        spin.set_sensitive(b.get_active())
        self.g_config_grid.attach(b, 0, row, 1, 1)
        self.g_config_grid.attach(spin, 1, row, 1, 1)
        self.g_config_grid.attach(label, 2, row, 1, 1)
Example #25
0
    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)

        self.g_percentage = gu.bLabel(self.practise_box, "")
        self.g_percentage.set_name("Heading1")
        self.g_piano = inputwidgets.PianoOctaveWithAccelName(
            self.on_answer_from_user, self.get_accel_key_list())
        self.g_piano.m_visible_accels = not self.get_bool('hide_piano_accels')

        def update_accels(*ignore):
            self.g_piano.m_keys = self.get_accel_key_list()
            self.g_piano.queue_draw()

        for notename in mpd.MusicalPitch.notenames:
            self.add_watch('tone_%s_ak' % notename, update_accels)
        self.practise_box.pack_start(self.g_piano, True, True, 0)

        self.g_flashbar = gu.FlashBar()
        self.g_flashbar.show()
        self.practise_box.pack_start(self.g_flashbar, False, False, 0)
        self.practise_box.set_spacing(gu.PAD)

        self.std_buttons_add(
            ('new-tone', self.new_question),
            ('repeat', lambda _o, self=self: self.m_t.play_question()),
            ('give_up', self.give_up))
        self.practise_box.show_all()
        ##############
        # config_box #
        ##############
        self.config_box.set_spacing(gu.PAD_SMALL)
        self.g_config_elems = gu.bVBox(self.config_box, False)
        table = Gtk.Table()
        table.set_border_width(gu.PAD_SMALL)
        frame = Gtk.Frame(label=_("Weight"))
        self.g_config_elems.pack_start(frame, False, False, 0)
        frame.add(table)
        for x, n in [(1, 'cis'), (3, 'dis'), (7, 'fis'), (9, 'gis'),
                     (11, 'ais')]:
            label = Gtk.Label(label=mpd.MusicalPitch.new_from_notename(
                n).get_user_notename())
            label.set_name("Heading2")
            label.set_alignment(0.2, 1.0)
            table.attach(label,
                         x,
                         x + 2,
                         0,
                         1,
                         xoptions=Gtk.AttachOptions.FILL)
            b = gu.nSpinButton(self.m_exname,
                               n + "_weight",
                               Gtk.Adjustment(1, 0, 1000, 1, 10),
                               digits=0)
            table.attach(b, x, x + 2, 1, 2, xoptions=Gtk.AttachOptions.FILL)
        for x, n in [(0, 'c'), (2, 'd'), (4, 'e'), (6, 'f'), (8, 'g'),
                     (10, 'a'), (12, 'b')]:
            label = Gtk.Label(label=mpd.MusicalPitch.new_from_notename(
                n).get_user_notename())
            label.set_name("Heading2")
            label.set_alignment(0.35, 1.0)
            table.attach(label,
                         x,
                         x + 2,
                         2,
                         3,
                         xoptions=Gtk.AttachOptions.FILL)
            b = gu.nSpinButton(self.m_exname,
                               n + "_weight",
                               Gtk.Adjustment(1, 0, 1000, 1, 10),
                               digits=0)
            table.attach(b, x, x + 2, 3, 4, xoptions=Gtk.AttachOptions.FILL)

        hbox = gu.bHBox(self.g_config_elems, False)
        hbox.pack_start(Gtk.Label(_("Octave:")), False, False, padding=4)
        for oct in self.m_t.OCTAVES:
            b = gu.nCheckButton(self.m_exname,
                                "octave" + str(oct),
                                str(oct),
                                default_value=1)
            hbox.pack_start(b, False, False, 0)
        #############
        self._add_auto_new_question_gui(self.config_box)
        #############
        b = gu.nCheckButton('idtone', 'hide_piano_accels',
                            _("Hide _piano keyboard shortcuts"), False)

        def show_hide_accels(checkbutton):
            self.g_piano.m_visible_accels = not b.get_active()

        b.connect('clicked', show_hide_accels)
        self.config_box.pack_start(b, False, False, 0)
        #
        frame = Gtk.Frame(label=_("When you guess wrong"))
        vbox = Gtk.VBox()
        vbox.set_border_width(gu.PAD_SMALL)
        frame.add(vbox)
        vbox.pack_start(
            gu.nCheckButton(self.m_exname, "warning_sound",
                            _("Play warning sound")), False, False, 0)
        self.config_box.pack_start(frame, False, False, 0)
        self.config_box.show_all()
        ##############
        # statistics #
        ##############
        self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                    _("Identify tone"))
Example #26
0
    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)

        self.g_percentage = gu.bLabel(self.practise_box, "")
        self.g_percentage.set_name("Heading1")
        self.g_piano = inputwidgets.PianoOctaveWithAccelName(
                       self.on_answer_from_user, self.get_accel_key_list())
        self.g_piano.m_visible_accels = not self.get_bool('hide_piano_accels')

        def update_accels(*ignore):
            self.g_piano.m_keys = self.get_accel_key_list()
            self.g_piano.queue_draw()
        for notename in mpd.MusicalPitch.notenames:
            self.add_watch('tone_%s_ak' % notename, update_accels)
        self.practise_box.pack_start(self.g_piano, True, True, 0)

        self.g_flashbar = gu.FlashBar()
        self.g_flashbar.show()
        self.practise_box.pack_start(self.g_flashbar, False, False, 0)
        self.practise_box.set_spacing(gu.PAD)

        self.std_buttons_add(
            ('new-tone', self.new_question),
            ('repeat', lambda _o, self=self: self.m_t.play_question()),
            ('give_up', self.give_up))
        self.practise_box.show_all()
        ###############
        # config_grid #
        ###############
        table = Gtk.Table()
        table.set_border_width(gu.PAD_SMALL)
        self.g_tones_frame = frame = Gtk.Frame(label=_("Weight"))
        self.g_config_grid.attach(frame, 0, 0, 3, 1)
        frame.add(table)
        for x, n in [(1, 'cis'), (3, 'dis'), (7, 'fis'),
                     (9, 'gis'), (11, 'ais')]:
            label = Gtk.Label(label=mpd.MusicalPitch.new_from_notename(n).get_user_notename())
            label.set_name("Heading2")
            label.set_alignment(0.2, 1.0)
            table.attach(label, x, x + 2, 0, 1, xoptions=Gtk.AttachOptions.FILL)
            b = gu.nSpinButton(self.m_exname, n + "_weight",
                      Gtk.Adjustment(1, 0, 1000, 1, 10), digits=0)
            table.attach(b, x, x + 2, 1, 2, xoptions=Gtk.AttachOptions.FILL)
        for x, n in [(0, 'c'), (2, 'd'), (4, 'e'), (6, 'f'),
                      (8, 'g'), (10, 'a'), (12, 'b')]:
            label = Gtk.Label(label=mpd.MusicalPitch.new_from_notename(n).get_user_notename())
            label.set_name("Heading2")
            label.set_alignment(0.35, 1.0)
            table.attach(label, x, x + 2, 2, 3, xoptions=Gtk.AttachOptions.FILL)
            b = gu.nSpinButton(self.m_exname, n + "_weight",
                   Gtk.Adjustment(1, 0, 1000, 1, 10), digits=0)
            table.attach(b, x, x + 2, 3, 4, xoptions=Gtk.AttachOptions.FILL)

        self.g_octaves_select = hbox = Gtk.HBox()
        self.g_config_grid.attach(hbox, 0, 1, 3, 1)
        hbox.pack_start(Gtk.Label(_("Octave:")), False, False, padding=4)
        for oct in self.m_t.OCTAVES:
            b = gu.nCheckButton(self.m_exname, "octave" + str(oct), str(oct),
                                default_value=1)
            hbox.pack_start(b, False, False, 0)
        #############
        self._add_auto_new_question_gui(row=4)
        #############
        b = gu.nCheckButton('idtone', 'hide_piano_accels', _("Hide _piano keyboard shortcuts"), False)

        def show_hide_accels(checkbutton):
            self.g_piano.m_visible_accels = not b.get_active()
        b.connect('clicked', show_hide_accels)
        self.g_config_grid.attach(b, 0, 2, 1, 1)
        #
        self.g_config_grid.attach(gu.nCheckButton(self.m_exname,
                    "warning_sound",
                    _("Play warning sound when you guess wrong")),
                0, 3, 1, 1)
        self.g_config_grid.show_all()
        ##############
        # statistics #
        ##############
        self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                   _("Identify tone"))
Example #27
0
    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)
        self.g_buttongrid = grid = Gtk.Grid()
        grid.set_row_spacing(gu.hig.SPACE_SMALL)
        grid.set_column_spacing(gu.hig.SPACE_SMALL)
        self.g_buttons = fill_grid(Gtk.Button, grid,
                                   labels[self.get_int("labels")][1])
        for key, button in list(self.g_buttons.items()):
            button.connect('clicked', self.on_left_click, key)
        self.practise_box.pack_start(grid, False, False, gu.hig.SPACE_SMALL)
        #########################################
        # GUI to practise what is answered wrong
        self.g_wgrid = Gtk.Grid()
        self.g_wgrid.set_row_spacing(gu.hig.SPACE_SMALL)
        self.g_wgrid.set_column_spacing(gu.hig.SPACE_SMALL)

        self.g_wgrid.attach(
            Gtk.Label(_("You answered:"), halign=Gtk.Align.END), 0, 1, 1, 1)
        self.g_wrong = Gtk.Label()
        self.g_wgrid.attach(self.g_wrong, 1, 1, 1, 1)
        b = Gtk.Button(_("Play cadence and tone"))
        b.connect('clicked', lambda w: self.m_t.play_wrong_guess())
        self.g_wgrid.attach(b, 2, 1, 1, 1)
        b = Gtk.Button(_("Play tone"))
        b.connect(
            'clicked', lambda w: soundcard.synth.play_track(
                self.m_t.get_track_of_tone(self.m_t.m_guessed)))
        self.g_wgrid.attach(b, 3, 1, 1, 1)
        b = Gtk.Button(_("Play tone with solution"))
        b.connect(
            'clicked', lambda w: soundcard.synth.play_track(
                self.m_t.get_track_of_solution(self.m_t.m_guessed)))
        self.g_wgrid.attach(b, 4, 1, 1, 1)

        self.g_wgrid.attach(
            Gtk.Label(_("Correct answer:"), halign=Gtk.Align.END), 0, 2, 1, 1)
        self.g_correct = Gtk.Label()
        self.g_wgrid.attach(self.g_correct, 1, 2, 1, 1)
        b = Gtk.Button(_("Play cadence and tone"))
        b.connect('clicked', lambda w: self.m_t.play_question())
        self.g_wgrid.attach(b, 2, 2, 1, 1)
        b = Gtk.Button(_("Play tone"))
        b.connect(
            'clicked', lambda w: soundcard.synth.play_track(
                self.m_t.get_track_of_tone(self.m_t.m_tone)))
        self.g_wgrid.attach(b, 3, 2, 1, 1)
        b = Gtk.Button(_("Play tone with solution"))
        b.connect(
            'clicked', lambda w: soundcard.synth.play_track(
                self.m_t.get_track_of_solution(self.m_t.m_tone)))
        self.g_wgrid.attach(b, 4, 2, 1, 1)
        l = Gtk.Label(
            _("You should listen to both tones several times and try to hear the difference and the similarity between the tones."
              ))
        self.g_wgrid.attach(l, 0, 3, 4, 1)
        b = Gtk.Button(_("Play cadence"))

        def play_cadence(*w):
            solfege.soundcard.synth.play_track(self.m_t.get_track_of_cadence())

        b.connect('clicked', play_cadence)
        self.g_wgrid.attach(b, 0, 4, 3, 1)
        b = Gtk.Button(_("Done"))

        def done(*w):
            self.end_practise_wrong_answer()
            self.new_question()

        b.connect('clicked', done)
        self.g_wgrid.attach(b, 3, 4, 2, 1)
        l.set_line_wrap(True)
        l.set_max_width_chars(40)
        self.practise_box.pack_start(self.g_wgrid, False, False, 0)
        ###########
        self.g_flashbar = gu.FlashBar()
        self.g_flashbar.show()
        self.practise_box.pack_start(self.g_flashbar, False, False, 0)
        self.std_buttons_add(
            ('new', self.new_question),
            ('repeat', lambda _o, self=self: self.m_t.play_question()))
        self.practise_box.show_all()
        self.g_wgrid.hide()
        ###############
        # config_grid #
        ###############
        # FIXME we need a ComboBox
        # self.g_random = gu.nCheckButton(self.m_exname, 'random_tonic', _("Random transpose"))
        # self.g_config_grid.attach(self.g_random, 0, 0, 1, 1)
        #
        self.g_config_grid.set_column_homogeneous(True)
        # Let us say the grid has 8 columns
        self.g_tones_category, box = gu.hig_category_vbox(_("Tones"))
        self.g_config_grid.attach(self.g_tones_category, 0, 2, 8, 1)
        self.g_tone_selector = nConfigButtons(self.m_exname, 'tones')
        box.pack_start(self.g_tone_selector, False, False, 0)
        self.g_many_octaves = b = gu.nCheckButton('toneincontext',
                                                  'many_octaves',
                                                  _("Many octaves"))
        self.g_config_grid.attach(b, 0, 3, 4, 1)
        # Cadences
        self.g_cadences_category, self.g_cadences = gu.hig_category_vbox(
            _("Cadences"))
        self.g_config_grid.attach(self.g_cadences_category, 0, 4, 4, 1)

        #

        def _ff(var):
            if self.m_t.m_custom_mode:
                # If we are running in custom mode, then the user can
                # select himself what intervals to practise. And then
                # we have to reset the exercise.
                # self.on_end_practise()
                # self.on_start_practise()
                self.cancel_question()

        self.add_watch('tones', _ff)

        # Tempo the music is played
        self.g_config_grid.attach(Gtk.Label("BPM:"), 0, 5, 1, 1)
        min_bpm, max_bpm = 30, 250
        scale = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, min_bpm,
                                         max_bpm, 10)
        scale.set_value_pos(Gtk.PositionType.LEFT)
        if not (min_bpm < self.m_t.get_int("bpm") < max_bpm):
            self.m_t.set_int("bpm", 90)
        scale.set_value(self.m_t.get_int("bpm"))

        def scale_value_changed(scale):
            self.m_t.set_int("bpm", int(scale.get_value()))

        scale.connect('value-changed', scale_value_changed)
        self.g_config_grid.attach(scale, 1, 5, 7, 1)

        # Select answer button labels
        combo = gu.nComboBox(self.m_t.m_exname, 'labels', labels[0][0],
                             [n[0] for n in labels])
        self.g_config_grid.attach(combo, 1, 6, 7, 1)
        combo.connect('changed', self.update_tone_button_labels)

        self.g_config_grid.show_all()
        ##############
        # Statistics #
        ##############
        self.g_statview = StatisticsViewer(self.m_t)
        self.g_statview.show()
        self.g_notebook.append_page(self.g_statview,
                                    Gtk.Label(label=_("Statistics")))
        self.g_notebook.connect('switch_page', self.g_statview.update)