# GNU Solfege - ear training for GNOME
# Copyright (C) 2000, 2001, 2002, 2003, 2004  Tom Cato Amundsen
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

if __name__ == "__main__":
    import sys
    sys.path.append(".")

import gtk, gnome, gu
import gobject, lessonfile, cfg, gu
from htmlwidget import HtmlWidget
import dataparser

class SelectLessonfileWidget(gtk.VBox):
    """
    The class will parse call the teacher to parse the
    lessonfile because the widget need some data from the
    lessonfile header.
    """
    def __init__(self, teacher, win, change_cb):
        gtk.VBox.__init__(self)
        self.m_t = teacher
        self.m_ui = win
        self.change_cb = change_cb
        box, category_vbox = gu.hig_category_vbox(_("Lesson file"))
        self.pack_start(box, False)
        sizegroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
        self.g_title = gtk.Label("")
        self.g_title.set_line_wrap(True)
        box = gu.hig_label_widget(_("Title:"), self.g_title, None)
        category_vbox.pack_start(box, False)
        btn = gtk.Button(_("Change lesson file ..."))
        btn.connect('clicked', self.on_change_lessonfile_clicked)
        box.pack_start(btn, False)
        self.desc_button = gtk.Button()
        category_vbox.pack_start(self.desc_button)
        hbox = gtk.HBox()
        self.desc_button.add(hbox)
        hbox.set_spacing(6)
        self.desc_button.set_relief(gtk.RELIEF_NONE)
        self.desc_button.connect('clicked', self.toggle_lessonfile_details)
        self.description_visible = 0
        self.g_desc_arrow = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_IN)
        hbox.pack_start(self.g_desc_arrow, False)
        hbox.pack_start(gtk.Label(_("Details")), False)
        hbox.pack_start(gtk.HSeparator())
        # collection
        self.g_lessoncollection = gtk.Entry()
        self.g_lessoncollection.set_editable(False)
        self.g_lessoncollection_box = gu.hig_label_widget(_("Lesson collection:"), self.g_lessoncollection, sizegroup)
        category_vbox.pack_start(self.g_lessoncollection_box, False)
        # filename
        self.g_lessonfile = gtk.Entry()
        self.g_lessonfile.set_editable(False)
        self.g_lessonfile_box = gu.hig_label_widget(_("Filename:"), self.g_lessonfile, sizegroup)
        category_vbox.pack_start(self.g_lessonfile_box, False)
        # description
        self.g_lessonfile_description_frame = gtk.Frame()
        self.g_lessonfile_description = HtmlWidget(self.m_t.m_app.handle_href, None)
        self.g_lessonfile_description_frame.add(self.g_lessonfile_description)
        category_vbox.pack_start(self.g_lessonfile_description_frame)
        self.g_lessonfile_description.show()
        self.show_all()

        self.update()
        self._sc = self._sf = None
        self._fw = self.m_t.add_watch('lessonfile', self._lessonfilewatch)
        self._cw = self.m_t.add_watch('lessoncollection', self._lessoncollectionwatch)
    def on_change_lessonfile_clicked(self, btn):
        i = self.find_current_selected_file_n()
        dialog = FileSelectDialog(self.m_t.get_string('lessonfile'), self.m_t.get_string('lessoncollection'), self.m_t.m_exname, i, self.m_ui.m_app.lessonfile_manager)
        response = dialog.run()
        dialog.hide()
        if response == gtk.RESPONSE_OK:
            coll, fn = dialog.get_selected_file()
            self.do_change_collection(dialog.m_collection, fn)
        dialog.destroy()
    def _lessonfilewatch(self, s):
        self.do_change_file(self.m_t.get_string(s))
        self.g_lessonfile.set_text(self.m_t.get_string(s))
    def _lessoncollectionwatch(self, s):
        self.do_change_collection(self.m_t.get_string(s), None)
    def do_change_collection(self, collection, filename):
        self.m_t.remove_watch('lessonfile', self._fw)
        self.m_t.remove_watch('lessoncollection', self._cw)
        try:
            self.m_t.set_lessonfile(collection, filename)
        except dataparser.DataparserException, e:
            self.m_ui.display_error_message(str(e))
            self.m_t.m_P = None
        self.update()
        self.change_cb()
        self._cw = self.m_t.add_watch('lessoncollection', self._lessoncollectionwatch)
        self._fw = self.m_t.add_watch('lessonfile', self._lessonfilewatch)
    def do_change_file(self, new_filename): 
        self.m_t.remove_watch('lessonfile', self._fw)
        try:
            self.m_t.set_lessonfile(None, new_filename)
        except dataparser.DataparserException, e:
            self.m_ui.display_error_message(str(e))
            self.m_t.m_P = None
        self.update()
        self.change_cb()
        self._fw = self.m_t.add_watch('lessonfile', self._lessonfilewatch)
    def update(self):
        self.g_lessoncollection.set_text(self.m_t.get_string('lessoncollection'))
        self.g_lessonfile.set_text(self.m_t.get_string('lessonfile'))
        if not self.m_t.m_P:
            return
        # the info labels
        if self.m_t.m_P:
            self.g_title.set_text(self.m_t.m_P.header.title)
        else:
            self.g_title.set_text('')
        s = self.m_t.m_P.header.description
        if s:
            self.g_lessonfile_description.source("<html><body bgcolor=white>%s</body></html>" % s)
        else:
            self.g_lessonfile_description.source("<html></html>")
    def toggle_lessonfile_details(self, widget=None):
        self.description_visible = not self.description_visible
        if self.description_visible:
            self.g_lessonfile_box.show()
            self.g_lessoncollection_box.show()
            self.g_lessonfile_description_frame.show()
            self.g_desc_arrow.set(gtk.ARROW_DOWN, gtk.SHADOW_IN)
        else:
            self.g_lessonfile_box.hide()
            self.g_lessoncollection_box.hide()
            self.g_lessonfile_description_frame.hide()
            self.g_desc_arrow.set(gtk.ARROW_RIGHT, gtk.SHADOW_IN)
    def show(self):
        self.show_all()
        self.g_lessonfile_description_frame.hide()
        self.g_lessonfile_box.hide()
        self.g_lessoncollection_box.hide()
    def find_current_selected_file_n(self):
        """Find what number the currently active lesson file has.
        """
        i = 0
        for d in self.m_ui.m_app.lessonfile_manager.get_info(self.m_t.get_string('lessoncollection'), self.m_t.m_exname):
            if d['filename'] == self.m_t.get_string('lessonfile'):
                return i
            i += 1
        return -1


class FileSelectDialog(gtk.Dialog):
    def __init__(self, lessonfile, collection, exname, current_filenum, lessonfile_manager):
        gtk.Dialog.__init__(self, _("Select lesson file"), None, 0, 
              (
               gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
               gtk.STOCK_OK, gtk.RESPONSE_OK,
               ))
        self.m_lessonfile_manager = lessonfile_manager
        self.m_collection = collection
        self.m_exname = exname
        # select collection
        content_vbox = gu.hig_dlg_vbox()
        self.vbox.pack_start(content_vbox)
        box, category_content_vbox = gu.hig_category_vbox(_("Lesson collection"))
        content_vbox.pack_start(box)
        hbox = gtk.HBox()
        category_content_vbox.pack_start(hbox, False)
        first_btn = None
        self.m_selected_lessons = {}
        for coll in cfg.get_list('config/lessoncollections'):
            self.m_selected_lessons[coll] = None
            b = gtk.RadioButton(first_btn, coll)
            if self.m_collection == coll:
                b.clicked()
            b.connect('released', self.on_change_collection, coll)
            hbox.pack_start(b, False)
            if not first_btn:
                first_btn = b
        # list of lessons
        self.g_treeview = gtk.TreeView()
        self.g_treeview.connect('button_release_event', self.list_clicked)
        self.g_treeview.connect('row-activated', self.on_row_activated)
        self.g_treeview.set_rules_hint(True)
        self.create_liststore_dict()
        self.g_treeview.set_model(self.m_liststore_dict[collection])
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.add(self.g_treeview)
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        scrolledwin.set_size_request(600, 300)
        box, vb = gu.hig_category_vbox(_("Select lesson file"))
        content_vbox.pack_start(box, True)
        vb.pack_start(scrolledwin)
    
        column = gtk.TreeViewColumn(_('Filename'), gtk.CellRendererText(),
                                     text=0)
        self.g_treeview.append_column(column)
        column = gtk.TreeViewColumn(_('Description'), gtk.CellRendererText(),
                                     text=1)
        self.g_treeview.append_column(column)
        if current_filenum >= 0:
            self.g_treeview.set_cursor(current_filenum)
            self.g_treeview.scroll_to_cell((current_filenum,))
            self.m_selected_lessons[collection] = current_filenum
            self.m_can_ok = 1
        else:
            self.m_can_ok = 0
        self.show_all()
        # set OK-button sensitivity
        self.action_area.get_children()[0].set_sensitive(self.m_can_ok)
    def create_liststore_dict(self):
        self.m_liststore_dict ={}
        for collection in cfg.get_list('config/lessoncollections'):
            self.m_liststore_dict[collection] = \
                 gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
            for d in self.m_lessonfile_manager.get_info(collection, self.m_exname):
                iter = self.m_liststore_dict[collection].append()
                if not d['title']:
                    d['title'] = "Warning: '%s' has no title." % d['filename']
                self.m_liststore_dict[collection].set(iter, 0, d['filename'], 1, d['title'])
    def on_change_collection(self, button, collection):
        if self.g_treeview.get_cursor()[0] is not None:
            self.m_selected_lessons[self.m_collection] = self.g_treeview.get_cursor()[0]
        self.g_treeview.set_model(self.m_liststore_dict[collection])
        self.m_collection = collection
        #FIXME is this ok for Right-to-Left locales?
        # set OK-button insensitive
        if self.m_liststore_dict[collection].get_iter_root():
            if self.m_selected_lessons[collection] is None:
                self.g_treeview.set_cursor(0)
            else:
                self.g_treeview.set_cursor(self.m_selected_lessons[collection])
            self.action_area.get_children()[0].set_sensitive(self.m_can_ok)
        else:
            self.action_area.get_children()[0].set_sensitive(False)
    def on_row_activated(self, view, path, viewcol):
        if self.g_treeview.get_cursor()[0]:
            self.action_area.get_children()[0].set_sensitive(True)
            self.response(gtk.RESPONSE_OK)
    def list_clicked(self, *v):#view, event):
        if self.g_treeview.get_cursor()[0]:
            self.action_area.get_children()[0].set_sensitive(True)
    def get_selected_file(self):
        """
        Return a tuple (lesson collection, file name)
        """
        path, focus_column = self.g_treeview.get_cursor()
        iter = self.m_liststore_dict[self.m_collection].iter_nth_child(None, self.g_treeview.get_cursor()[0][0])
        return (self.m_collection, self.m_liststore_dict[self.m_collection].get_value(iter, 0))

def _test():
    dlg = FileSelectDialog('chord-min-major', 'solfege', 'id-by-name')
    dlg.connect('destroy', gtk.mainquit)
    dlg.run()
    gtk.mainloop()

if __name__ == "__main__":
    cfg.initialise(None, "default.config", "test.cfg")
    _test()
