aboutsummaryrefslogtreecommitdiffstats
path: root/gui
diff options
context:
space:
mode:
authorHenryk Plötz <henryk@ploetzli.ch>2010-02-24 02:57:44 +0100
committerHenryk Plötz <henryk@ploetzli.ch>2010-02-24 02:57:44 +0100
commit86c77780224304db61378b6e01f2f86c48e50fb3 (patch)
treed6dce1830f4c027b3d7f36a5dd6bf7dbf09d3d3d /gui
parent2f244a208318cd4c40f99dbf1f09101878e14dc0 (diff)
Add VRS application and GUI (Public transport in Koeln and Bonn)
Diffstat (limited to 'gui')
-rw-r--r--gui/__init__.py1
-rw-r--r--gui/ireadyou.py380
-rw-r--r--gui/ireadyou/ireadyou.glade337
-rw-r--r--gui/ireadyou/ireadyou.gladep8
4 files changed, 726 insertions, 0 deletions
diff --git a/gui/__init__.py b/gui/__init__.py
index 4dfd457..704b508 100644
--- a/gui/__init__.py
+++ b/gui/__init__.py
@@ -1 +1,2 @@
from PassportGUI import *
+from ireadyou import *
diff --git a/gui/ireadyou.py b/gui/ireadyou.py
new file mode 100644
index 0000000..820723e
--- /dev/null
+++ b/gui/ireadyou.py
@@ -0,0 +1,380 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+
+import gtk,gtk.glade,gobject
+import sys, os, time
+try:
+ import utils, TLV_utils, cards
+except ImportError, e:
+ try:
+ sys.path.append(".")
+ import utils, TLV_utils, cards
+ except ImportError:
+ raise e
+
+from smartcard.CardMonitoring import CardMonitor, CardObserver
+from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver
+import smartcard
+
+class FileLikeTextBuffer(object):
+ def __init__(self):
+ self.had_newline = True
+ self.buffer = gtk.TextBuffer()
+ self.endmark = self.buffer.create_mark("The End", self.buffer.get_end_iter(), False)
+ self.views = []
+
+ def add_view(self, v):
+ self.views.append(v)
+ v.scroll_mark_onscreen( self.endmark )
+
+ def writelines(self, sequence):
+ for s in sequence: self.write(s)
+
+ def write(self, s):
+ d = "%s: " % time.strftime("%F %T")
+
+ parts = s.split("\n")
+ if self.had_newline:
+ self.had_newline = False
+ s = d
+ else:
+ s = ""
+
+ if parts[-1] == '':
+ del parts[-1]
+ self.had_newline = True
+
+ s = s + ("\n"+d).join(parts)
+ if self.had_newline: s = s + "\n"
+
+ self.buffer.insert( self.buffer.get_end_iter(), s)
+ for v in self.views:
+ v.scroll_mark_onscreen( self.endmark )
+
+ def flush(self): pass
+
+ def for_stream(self, stream):
+ class stream_to_buf(object):
+ def __init__(self, parent, stream):
+ self.parent = parent
+ self.stream = stream
+
+ def flush(self):
+ self.parent.flush()
+ self.stream.flush()
+
+ def write(self, s):
+ self.parent.write(s)
+ self.stream.write(s)
+
+ def writelines(self, s):
+ self.parent.writelines(s)
+ self.stream.writelines(s)
+
+ return stream_to_buf(self, stream)
+
+class ireadyou(object,CardObserver,ReaderObserver):
+ GLADE_FILE = "gui/ireadyou/ireadyou.glade"
+
+ def __init__(self, ticket = None):
+ "Create and show main window."
+ self.main_window_xml = gtk.glade.XML(self.GLADE_FILE, "main")
+ self.main_window = self.main_window_xml.get_widget("main")
+
+ self.card_tabs = self.main_window_xml.get_widget("card_tabs")
+ while self.card_tabs.get_n_pages() > 0:
+ self.card_tabs.remove_page(0)
+ for t in self.CARD_TYPES:
+ a, b, l = gtk.Alignment(yscale=1,xscale=1,xalign=0.5,yalign=0.5), gtk.VBox(), gtk.Label(t[1])
+ a.add(b)
+ a.show()
+ b.show()
+ l.show()
+
+ self.card_tabs.append_page(a, tab_label=l)
+
+ self.ticket_button_group = gtk.RadioButton()
+ self.ticket_button_group._ticket = None
+
+ self.status_area = self.main_window_xml.get_widget("status_area")
+ self.known_readers = []
+ self.known_cards = {} # Note stupid: the keys to this dict are not objects from the known_readers list but rather reader name strings
+ self.connected_cards = {} # Again: the keys are not cards but repr(card)
+ self.tickets = {} # ditto
+ self.ticket_displayed = None # This is either None or a tuple (card object, ticket object)
+
+ self._update_status()
+
+ self.logbuf = FileLikeTextBuffer()
+ sys.stdout = self.logbuf.for_stream(sys.stdout)
+ sys.stderr = self.logbuf.for_stream(sys.stderr)
+ self.logview = self.main_window_xml.get_widget("logview")
+ self.logview.set_buffer(self.logbuf.buffer)
+ self.logbuf.add_view(self.logview)
+
+ signals = {
+ "on_exit_clicked": self.exit_clicked,
+ "on_main_delete_event": self.exit_clicked,
+ "on_main_destroy": gtk.main_quit,
+ }
+ self.main_window_xml.signal_autoconnect(signals)
+
+ self._clear_display()
+
+ self.rmon = ReaderMonitor()
+ self.cmon = CardMonitor()
+
+ self.rmon.addObserver(self)
+ self.cmon.addObserver(self)
+
+ def _clear_display(self):
+ self.card_tabs.set_current_page(0)
+
+ for i in range(self.card_tabs.get_n_pages()):
+ a = self.card_tabs.get_nth_page(i)
+ vbox = a.get_child()
+ for c in vbox.get_children():
+ vbox.remove(c)
+ label = self.card_tabs.get_tab_label(a)
+ label.set_property("sensitive", False)
+
+ def _update_status(self):
+ for c in self.status_area.get_children():
+ self.status_area.remove(c)
+
+ if len(self.known_readers) == 0:
+ self.status_area.add( gtk.Label(u"Keine Lesegeräte angeschlossen.") )
+ else:
+ for reader in self.known_readers:
+ frame = gtk.Frame(label=str(reader))
+
+ if len(self.known_cards[ reader.name ]) == 0:
+ frame.add( gtk.Label(u"Keine Karten verbunden.") )
+ else:
+ vbox = gtk.VBox()
+ for card in self.known_cards[ reader.name ]:
+ if self.connected_cards.has_key(repr(card)):
+ card_ = self.connected_cards[ repr(card) ]
+ cardname = card_.get_driver_name()
+ else:
+ cardname = str(card)
+
+ hbox = gtk.HBox()
+ cardlabel = gtk.Label( "<b>%s</b>: " % cardname )
+ cardlabel.set_use_markup(True)
+ hbox.pack_start(cardlabel, expand=False)
+
+ vbox2 = gtk.VBox()
+ hbox.pack_start(vbox2, expand=True)
+ for ticket in self.tickets[ repr(card) ]:
+ button = gtk.RadioButton(group=self.ticket_button_group, label=str(ticket), use_underline=False)
+ vbox2.pack_start(button, expand=False)
+
+ button.connect("toggled", self._ticket_button_toggled)
+ button._ticket = (card, ticket)
+
+ if self.ticket_displayed is not None and ticket == self.ticket_displayed[1]:
+ button.set_active(True)
+
+ vbox.add(hbox)
+ frame.add(vbox)
+
+ self.status_area.add(frame)
+
+ self.status_area.show_all()
+
+ def _format_datum(d):
+ return d.strftime("%x")
+
+ CARD_TYPES = [
+ (("SCHUL_T",),
+ "Schulticket", (
+ ("Name", "name_klar", None),
+ ("Alter", "alter", None),
+ ("Geburtsdatum", "geburtsdatum", _format_datum),
+ ("Schule", "schule", None),
+ (u"Kartengültigkeit", "gueltigkeit", None),
+ ),
+ ),
+ (("JOBT_ERW",),
+ "Jobticket", (
+ ("Name", "name_klar", None),
+ ("Geburtsdatum", "geburtsdatum", _format_datum),
+ (u"Kartengültigkeit", "gueltigkeit", None),
+ ),
+ ),
+ (("MT_ABO",),
+ "Monatsabo", (
+ ("Abo-Nummer", "abonr", None),
+ (u"Kartengültigkeit", "gueltigkeit", None),
+ ),
+ ),
+ (None,
+ "Anderes", (
+ ),
+ ),
+ ]
+
+ def _ticket_button_toggled(self, togglebutton):
+ self.ticket_displayed = None
+ for b in togglebutton.get_group():
+ if b.get_active():
+ if hasattr(b, "_ticket"):
+ self.ticket_displayed = b._ticket
+ self._update_ticket_display()
+
+ def _update_ticket_display(self):
+ self._clear_display()
+ if self.ticket_displayed is None:
+ return
+
+ todisplay = self.ticket_displayed[1]
+
+ for i,t in enumerate(self.CARD_TYPES):
+ if todisplay.tickettyp in t[0]:
+ break
+ # Note: implicit selection of the last card type when no match is found
+
+ self.card_tabs.set_current_page(i)
+ a = self.card_tabs.get_nth_page(i)
+ vbox = a.get_child()
+ label = self.card_tabs.get_tab_label(a)
+ label.set_property("sensitive", True)
+
+ for labeltext, propertyname, transformation in t[2]:
+ frame = gtk.Frame(label=labeltext)
+ content = getattr(todisplay, propertyname, None)
+ contenttext = str( transformation is not None and transformation(content) or content )
+ contentlabel = gtk.Label("<b><tt><big>%s</big></tt></b>" % contenttext)
+ contentlabel.set_use_markup(True)
+ contentlabel.show()
+ frame.add( contentlabel )
+ frame.show()
+
+ vbox.add(frame)
+
+ def exit_clicked(self, widget, event=None, data=None):
+ gtk.main_quit()
+ return True
+
+ def run(self):
+ gtk.main()
+
+ # From the CardObserver and ReaderObserver classes
+ def update( self, observable, (added, removed) ):
+ try:
+ gtk.gdk.threads_enter()
+ #print observable, added, removed
+ if observable is self.rmon.instance:
+ self.reader_update(observable, (added, removed) )
+ elif observable is self.cmon.instance:
+ self.card_update(observable, (added, removed) )
+ self._update_status()
+ self._update_ticket_display()
+ finally:
+ gtk.gdk.threads_leave()
+
+ def reader_update( self, observable, (added, removed) ):
+ for r in removed:
+ if r in self.known_readers:
+ for card in list(self.known_cards[ r.name ]):
+ self._remove_card(card)
+ assert len(self.known_cards[ r.name ]) == 0
+ del self.known_cards[ r.name ]
+ self.known_readers.remove(r)
+ for a in added:
+ if a not in self.known_readers:
+ self.known_readers.append(a)
+ self.known_cards[ a.name ] = []
+
+ def card_update( self, observable, (added, removed) ):
+ for r in removed:
+ if not self.known_cards.has_key(r.reader): continue
+ if r in self.known_cards[r.reader]:
+ self._remove_card(r)
+ for a in added:
+ if not self.known_cards.has_key(a.reader): continue
+ if a not in self.known_cards[a.reader]:
+ self._add_card(a)
+
+ def _add_card(self, card):
+ self.known_cards[ card.reader ].append(card)
+ if not self.tickets.has_key( repr(card) ):
+ self.tickets[ repr(card) ] = []
+
+ conn = card.createConnection()
+ connected = False
+ try:
+ conn.connect()
+ connected = True
+ except smartcard.Exceptions.NoCardException, e:
+ pass
+
+ if connected:
+ card_ = cards.new_card_object(conn)
+ cards.generic_card.DEBUG = False
+ self.connected_cards[ repr(card) ] = card_
+
+ for i in range(1,9):
+ try:
+ ticket = cards.vrs_application.VrsTicket.from_card(card_, record_no = i)
+ print "Loaded ticket '%s' from record %i" % (ticket, i)
+ self._add_ticket(card, ticket)
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except Exception,e:
+ if not str(e).startswith("'No ticket in record no."):
+ print e
+
+ if not isinstance(card_, cards.vrs_application.VRS_Application):
+ break
+
+ def _remove_card(self, card):
+ if self.tickets.has_key( repr(card) ):
+ for t in list(self.tickets[ repr(card) ]):
+ self._remove_ticket(card, t)
+ assert len(self.tickets[ repr(card) ]) == 0
+ del self.tickets[ repr(card) ]
+
+ if self.connected_cards.has_key( repr(card) ):
+ try:
+ self.connected_cards[ repr(card) ].close_card()
+ except smartcard.Exceptions.CardConnectionException, e:
+ pass
+
+ del self.connected_cards[ repr(card) ]
+ self.known_cards[ card.reader ].remove(card)
+
+ def _add_ticket(self, card, ticket):
+ self.tickets[ repr(card) ].append( ticket )
+ if self.ticket_displayed is None:
+ self.ticket_displayed = ( card, ticket )
+
+ def _remove_ticket(self, card, ticket):
+ if self.ticket_displayed is not None and self.ticket_displayed[1] == ticket:
+ self.ticket_displayed = None
+ # TODO: Find a different ticket to display
+ self.tickets[ repr(card) ].remove(ticket)
+
+OPTIONS = ""
+LONG_OPTIONS = []
+
+if __name__ == "__main__":
+## c = utils.CommandLineArgumentHelper()
+##
+## (options, arguments) = c.getopt(sys.argv[1:], OPTIONS, LONG_OPTIONS)
+##
+## card_object = c.connect()
+## card = cards.new_card_object(card_object)
+## #cards.generic_card.DEBUG = False
+##
+## print >>sys.stderr, "Using %s" % card.DRIVER_NAME
+##
+## if len(arguments) > 0:
+## ticket = cards.vrs_application.VrsTicket.from_card(card, record_no = int(arguments[0], 0))
+## else:
+## ticket = cards.vrs_application.VrsTicket.from_card(card)
+
+ gtk.gdk.threads_init()
+ g = ireadyou()
+ g.run()
diff --git a/gui/ireadyou/ireadyou.glade b/gui/ireadyou/ireadyou.glade
new file mode 100644
index 0000000..be7f04a
--- /dev/null
+++ b/gui/ireadyou/ireadyou.glade
@@ -0,0 +1,337 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="main">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">iReadYou</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+ <signal name="destroy" handler="on_main_destroy" last_modification_time="Tue, 10 Jun 2008 03:23:32 GMT"/>
+ <signal name="delete_event" handler="on_main_delete_event" last_modification_time="Tue, 10 Jun 2008 03:23:40 GMT"/>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment4">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment5">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkNotebook" id="card_tabs">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_tabs">True</property>
+ <property name="show_border">True</property>
+ <property name="tab_pos">GTK_POS_TOP</property>
+ <property name="scrollable">False</property>
+ <property name="enable_popup">False</property>
+
+ <child>
+ <widget class="GtkVBox" id="bar">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">label11</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label10">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">label10</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Kartendaten&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="xscale">0</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="status_area">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <placeholder/>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Status&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkExpander" id="expander1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="expanded">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="logview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_NONE</property>
+ <property name="cursor_visible">True</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Log&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
diff --git a/gui/ireadyou/ireadyou.gladep b/gui/ireadyou/ireadyou.gladep
new file mode 100644
index 0000000..7d453b2
--- /dev/null
+++ b/gui/ireadyou/ireadyou.gladep
@@ -0,0 +1,8 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
+
+<glade-project>
+ <name>iReadYou</name>
+ <program_name>ireadyou</program_name>
+ <gnome_support>FALSE</gnome_support>
+</glade-project>