# 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)
|