1'''library_control_area.py - The window in the library that contains buttons
2and displays info.'''
3
4import os
5from gi.repository import Gtk
6from gi.repository import GLib
7from gi.repository import Pango
8
9from mcomix import i18n
10from mcomix import labels
11from mcomix.library.watchlist import WatchListDialog
12
13# The "All books" collection is not a real collection stored in the library,
14# but is represented by this ID in the library's TreeModels.
15_COLLECTION_ALL = -1
16
17
18class _ControlArea(Gtk.HBox):
19
20    '''The _ControlArea is the bottom area of the library window where
21    information is displayed and controls such as buttons reside.
22    '''
23
24    def __init__(self, library):
25        super(_ControlArea, self).__init__(homogeneous=False, spacing=12)
26
27        self._library = library
28        self.set_border_width(10)
29
30        borderbox = Gtk.Frame()
31        borderbox.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
32        borderbox.set_size_request(350, -1)
33
34        insidebox = Gtk.EventBox()
35        insidebox.set_border_width(1)
36        insidebox.set_state(Gtk.StateType.ACTIVE)
37
38        infobox = Gtk.VBox(homogeneous=False, spacing=5)
39        infobox.set_border_width(10)
40        self.pack_start(borderbox, True, True, 0)
41        borderbox.add(insidebox)
42        insidebox.add(infobox)
43
44        self._namelabel = labels.BoldLabel()
45        self._namelabel.set_alignment(0, 0.5)
46        self._namelabel.set_selectable(True)
47        self._namelabel.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
48        infobox.pack_start(self._namelabel, False, False, 0)
49
50        self._filelabel = Gtk.Label()
51        self._filelabel.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
52        self._filelabel.set_alignment(0, 0.5)
53        infobox.pack_start(self._filelabel, False, False, 0)
54
55        self._dirlabel = Gtk.Label()
56        self._dirlabel.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
57        self._dirlabel.set_alignment(0, 0.5)
58        self._dirlabel.set_selectable(True)
59        infobox.pack_start(self._dirlabel, False, False, 0)
60
61        vbox = Gtk.VBox(homogeneous=False, spacing=10)
62        vbox.set_size_request(350, -1)
63        self.pack_start(vbox, False, False, 0)
64
65        # First line of controls, containing the search box
66        hbox = Gtk.HBox(homogeneous=False)
67        vbox.pack_start(hbox, True, True, 0)
68
69        label = Gtk.Label(label=_('_Search:'))
70        label.set_use_underline(True)
71        hbox.pack_start(label, False, False, 0)
72        search_entry = Gtk.Entry()
73        search_entry.connect('activate', self._filter_books)
74        search_entry.set_tooltip_text(
75            _('Display only those books that have the specified text string '
76              'in their full path. The search is not case sensitive.'))
77        hbox.pack_start(search_entry, True, True, 6)
78        label.set_mnemonic_widget(search_entry)
79
80        # Last line of controls, containing buttons like 'Open'
81        hbox = Gtk.HBox(homogeneous=False, spacing=10)
82        vbox.pack_end(hbox, True, True, 0)
83
84        watchlist_button = Gtk.Button(label=_('_Watch list'), use_underline=True)
85        watchlist_button.set_always_show_image(True)
86        watchlist_button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_FIND, Gtk.IconSize.BUTTON))
87        watchlist_button.set_image_position(Gtk.PositionType.LEFT)
88        watchlist_button.connect('clicked',
89                                 lambda *args: WatchListDialog(self._library))
90        watchlist_button.set_tooltip_text(
91            _('Open the watchlist management dialog.'))
92        hbox.pack_start(watchlist_button, True, True, 0)
93
94        self._open_button = Gtk.Button(label=_('_Open list'), use_underline=True)
95        self._open_button.set_always_show_image(True)
96        self._open_button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_OPEN, Gtk.IconSize.BUTTON))
97        self._open_button.set_image_position(Gtk.PositionType.LEFT)
98        self._open_button.connect('clicked',
99                                  self._library.book_area.open_selected_book)
100        self._open_button.set_tooltip_text(_('Open the selected book.'))
101        self._open_button.set_sensitive(False)
102        hbox.pack_end(self._open_button, True, True, 0)
103
104    def update_info(self, selected):
105        '''Update the info box using the currently <selected> books from
106        the _BookArea.
107        '''
108
109        if selected:
110            book_id = self._library.book_area.get_book_at_path(selected[0])
111            book = self._library.backend.get_book_by_id(book_id)
112        else:
113            book = None
114
115        if book:
116            name = book.name
117            dir_path = os.path.dirname(book.path)
118            pages = book.pages
119            size = book.size
120            last_page = book.get_last_read_page()
121            last_date = book.get_last_read_date()
122        else:
123            name = dir_path = pages = size = last_page = last_date = None
124
125        if len(selected) > 0:
126            self._open_button.set_sensitive(True)
127        else:
128            self._open_button.set_sensitive(False)
129
130        if name is not None:
131            self._namelabel.set_text(i18n.to_unicode(name))
132            self._namelabel.set_tooltip_text(i18n.to_unicode(name))
133        else:
134            self._namelabel.set_text('')
135            self._namelabel.set_has_tooltip(False)
136
137        infotext = []
138
139        if last_page is not None and pages is not None and last_page != pages:
140            infotext.append('%s %d/%d' % (_('Page'), last_page, pages))
141        elif pages is not None:
142            infotext.append(_('%d pages') % pages)
143
144        if size is not None:
145            infotext.append('%.1f MiB' % (size / 1048576.0))
146
147        if (pages is not None and last_page is not None and
148            last_date is not None and last_page == pages):
149            infotext.append(_('Finished reading on %(date)s, %(time)s') % {
150                'date': last_date.strftime('%x'),
151                'time': last_date.strftime('%X'),
152            })
153
154        self._filelabel.set_text(', '.join(infotext))
155
156        if dir_path is not None:
157            self._dirlabel.set_text(i18n.to_unicode(dir_path))
158        else:
159            self._dirlabel.set_text('')
160
161    def _filter_books(self, entry, *args):
162        '''Display only the books in the current collection whose paths
163        contain the string in the Gtk.Entry. The string is not
164        case-sensitive.
165        '''
166        self._library.filter_string = entry.get_text()
167        if not self._library.filter_string:
168            self._library.filter_string = None
169        collection = self._library.collection_area.get_current_collection()
170        GLib.idle_add(self._library.book_area.display_covers, collection)
171
172# vim: expandtab:sw=4:ts=4
173