# GNU Solfege - free ear training software
# Copyright (C) 2007, 2008  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 3 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, see <http://www.gnu.org/licenses/>.


from __future__ import absolute_import
from __future__ import division

import sys
import traceback

import gtk

from solfege import gu

class ExceptionDialog(gtk.Dialog):
    def __init__(self, exception):
        gtk.Dialog.__init__(self, sys.exc_info()[0].__name__)
        self.set_resizable(True)
        self.set_border_width(6)
        self.set_has_separator(False)
        self.vbox.set_spacing(0)
        hbox = gtk.HBox()
        hbox.set_spacing(12)
        hbox.set_border_width(6)
        self.vbox.pack_start(hbox, False)
        vbox = gtk.VBox()
        hbox.pack_start(vbox, False, False)
        img = gtk.image_new_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_DIALOG)
        vbox.pack_start(img, False, False)
        vbox = gtk.VBox()
        hbox.pack_start(vbox)
        self.msg_vbox = gtk.VBox()
        vbox.pack_start(self.msg_vbox)
        self.g_primary = gtk.Label()
        if sys.exc_info()[0].__name__ == 'AttributeError':
            self.g_primary.set_name("DEBUGWARNING")
        self.g_primary.set_alignment(0.0, 0.5)
        self.g_primary.set_line_wrap(True)
        self.m_primary_bold = False
        self.msg_vbox.pack_start(self.g_primary)
        if isinstance(exception, StandardError):
            self.g_primary.set_text(str(exception).decode(sys.getfilesystemencoding(), 'replace'))
        else:
            if 'args' in dir(exception) and exception.args:
                estr = exception.args[0]
            else:
                estr = exception
            if not isinstance(estr, unicode):
                estr = str(estr).decode(sys.getfilesystemencoding(), 'replace')
            self.g_primary.set_text(estr)
            if 'args' in dir(exception):
                for s in exception.args[1:]:
                    self.add_text(s)
        # This label is here just for spacing
        l = gtk.Label("")
        vbox.pack_start(l)
        expander = gtk.Expander("Traceback")
        self.vbox.pack_start(expander)
        l = gtk.Label("".join(traceback.format_exception(
            sys.exc_type, sys.exc_value, sys.exc_traceback)).decode(sys.getfilesystemencoding(), 'replace'))
        l.set_alignment(0.0, 0.5)
        sc = gtk.ScrolledWindow()
        sc.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        sc.set_size_request(-1, 100)
        expander.add(sc)
        sc.add_with_viewport(l)
        l = gtk.Label(_("Visit http://www.solfege.org/support if you need help."))
        l.set_alignment(0.0, 0.5)
        vbox.pack_start(l, False)
        w = self.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
        self.set_default_response(gtk.RESPONSE_CLOSE)
        self.set_focus(w)
        self.show_all()
    def _make_primary_bold(self):
        if not self.m_primary_bold:
            self.m_primary_bold = True
            self.g_primary.set_markup('<span weight="bold" size="larger">%s</span>' %
                gu.escape(self.g_primary.get_text()))
    def _parsep(self):
        l = gtk.Label("")
        l.show()
        self.msg_vbox.pack_start(l)
    def add_text(self, text):
        self._make_primary_bold()
        self._parsep()
        # We add a empty string with a newline to get the spacing
        l = gtk.Label(text)
        l.set_line_wrap(True)
        l.set_alignment(0.0, 0.5)
        l.show()
        self.msg_vbox.pack_start(l)
    def add_nonwrapped_text(self, text):
        self._make_primary_bold()
        self._parsep()
        sc = gtk.ScrolledWindow()
        l = gtk.Label()
        l.set_markup('<span font_family="monospace">%s</span>' % gu.escape(text))
        l.set_line_wrap(False)
        l.set_alignment(0.0, 0.5)
        l.show()
        sc.add_with_viewport(l)
        self.msg_vbox.pack_start(sc)
        sc.show_all()
        sc.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
        w, h = l.get_ancestor(gtk.Viewport).size_request()
        max_lines = 5
        lines = text.count("\n") + 1
        # This is the space the horizontal scrollbar takes
        scrollbar_height = (sc.get_hscrollbar().size_request()[1]
            + sc.style_get_property("scrollbar-spacing"))
        if lines <= max_lines:
            # make the scrollwin so high that it can display all lines
            sc.set_size_request(-1, h)
        else:
            sc.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
            sc.set_size_request(-1, int(h * max_lines / lines))
        adj = sc.get_hscrollbar().get_adjustment()
        def f(scrollbar, event):
            sc.set_size_request(-1, int(h * max_lines / lines) + scrollbar_height)
            scrollbar.disconnect(self._hscroll_expose_id)
        # f is called if the horizontal scrollbar is visible. This because we
        # need to allocate space for the scrollbar too.
        self._hscroll_expose_id = sc.get_hscrollbar().connect('expose-event', f)

