#!/usr/bin/env python # -*- mode: python; coding: koi8-r; -*- # (c) Con Radchenko mailto:bofh@pochta.ru import sys, os from glob import glob import time from ConfigParser import ConfigParser import gtk, gobject from gtk import glade from gtk import gdk #import pango import ornamentbook from miscutils import entry_dialog, error_dialog, fix_filename, OpenFileDialog from properties import Properties, PropertiesDialog #from config import config_dir from config import config_file, user_skin_dir from pybookreader.main import read_config_file, save_config_file from pybookreader.bookmarks import Bookmarks from pybookreader.bookmarkswindow import BookmarksWindow #from pybookreader.properties import MainProperties from pybookreader.bookbuffer import new_book glade_file = 'ornamentbook.glade' propsdialog_glade_file = 'propsdialog.glade' ##---------------------------------------------------------------------- class OrnamentBookMain: def __init__(self, filename=None, fullscreen=False, hidemenu=False): self.filename = None self.encoding = 'utf-8' self.is_fullscreen = False self.prev_geometry = (0, 0) self.properties = Properties() #self.properties.read_properties(config_file) self.bookmarks = Bookmarks() #self.main_properties = MainProperties() self.main_properties = read_config_file() ##from pprint import pprint; pprint(self.main_properties) self.books_manager = None self.create_widgets() if filename: gobject.idle_add(self.open_file, filename) elif self.properties.recent_files: gobject.idle_add(self.open_file, self.properties.recent_files[-1][0]) if fullscreen and gtk.pygtk_version >= (2, 2): self.on_fullscreen_activate() self.prev_geometry = (self.properties.main_window_width, self.properties.main_window_height) if hidemenu: self.main_menubar.hide() OpenFileDialog.file_select_path = self.properties.file_select_path #self.timeout_cb() gobject.idle_add(lambda : self.timeout_cb() and False) gobject.timeout_add(10000, self.timeout_cb) #self.window.connect('key-release-event', self.key_press_event_cb) self.window.connect('key-press-event', self.key_press_event_cb) def create_widgets(self): gf = None for d in sys.path: f = os.path.join(d, 'ornamentbook', glade_file) if os.path.exists(f): gf = f break if not gf: sys.exit('ERROR: can\'t find glade file') self.glade_file = gf pgf = None for d in sys.path: f = os.path.join(d, 'ornamentbook', propsdialog_glade_file) if os.path.exists(f): pgf = f break if not pgf: sys.exit('ERROR: can\'t find glade file') self.propsdialog_glade_file = pgf wTree = glade.XML(gf, 'main_window') wTree.signal_autoconnect(self) self.window = wTree.get_widget('main_window') top_vbox = wTree.get_widget('top_vbox') self.main_menubar = wTree.get_widget('main_menubar') # (un)fullscreen available in PyGTK 2.2 and above if gtk.pygtk_version < (2, 2): wTree.get_widget('fullscreen_menu').set_sensitive(False) self.open_recent_file_menu = wTree.get_widget('open_recent_file_menu') self.content_menu = wTree.get_widget('content_menu') self.background_menu = wTree.get_widget('background_menu') self.skins_menu = wTree.get_widget('skins_menu') self.hyphenation_menu = wTree.get_widget('hyphenation_menu') text_widget = ornamentbook.OrnamentBook(self) top_vbox.pack_start(text_widget) text_widget.realize() #text_widget.connect('position-changed', self.position_changed_cb) self.text_widget = text_widget self.properties.read_properties(show_warning=True) self.window.resize(self.properties.main_window_width, self.properties.main_window_height) self.update_background_menu() self.update_skins_menu() self.update_hyphenation_menu() self.window.show_all() text_widget.initialize() #text_widget.grab_focus() ## def position_changed_cb(self, w, pos): ## self.percent_label.set_text('%d %%' % int(pos*100)) def open_file(self, filename): #print 'open_file', filename try: open(filename) except IOError, err: #sys.stderr.write('ERROR: can\'t open file: %s: %s\n' # % (filename, err[1])) error_dialog(self.window, "Can't open file %s: %s" % (fix_filename(filename), err[1])) self.update_recent_files_menu() return if self.filename: # save previous file #print 'save previous file', self.text_widget.current_page_line_index self.add_file_to_recent(self.filename, self.text_widget.current_page_line_index, self.text_widget.current_page_char_index, self.text_widget.content.encoding, self.text_widget.content.lang) rf = [f for f in self.properties.recent_files if f[0] == filename] if rf: rf = rf[0] ret = self.text_widget.open_file(filename, rf[3], rf[1], rf[2], rf[4]) else: ret = self.text_widget.open_file(filename) if ret: # success self.filename = filename self.add_file_to_recent(self.filename, self.text_widget.current_page_line_index, self.text_widget.current_page_char_index, self.text_widget.content.encoding, self.text_widget.content.lang) self.update_recent_files_menu() if self.books_manager: self.books_manager.update_treeview() def timeout_cb(self): title = self.properties.title_format title = title.replace('%f', '%(filename)s') title = title.replace('%a', '%(authors)s') title = title.replace('%b', '%(book_title)s') title = title.replace('%p', '%(position)d%%') title = title.replace('%t', '%(time)s') authors = self.text_widget.content.authors #authors = authors[:64] book_title = self.text_widget.content.book_title try: title = title % {'filename': fix_filename(self.filename), 'authors' : authors, 'book_title': book_title, 'position': int(self.text_widget.calc_position()*100), 'time': time.strftime('%H:%M', time.localtime()), } except: title = 'OrnamentBook [invalid format]' self.window.set_title(title) self.text_widget.draw_status() return True def update_recent_files_menu(self): menu = gtk.Menu() menu.show() rf = self.properties.recent_files[:] rf.reverse() for f in rf: #self.properties.recent_files: menuitem = gtk.MenuItem(fix_filename(f[0])) menuitem.get_child().set_use_underline(False) menuitem.connect('activate', self.recent_files_activate_cb, f[0]) menu.add(menuitem) menuitem.show() self.open_recent_file_menu.set_submenu(menu) def update_hyphenation_menu(self): menu = gtk.Menu() menu.show() from hyphenation import Hyphenation langs = Hyphenation().get_langs() for l, n in langs: menuitem = gtk.MenuItem(n) menuitem.get_child().set_use_underline(False) menuitem.connect('activate', self.hyphenation_menu_activate_cb, l) menu.add(menuitem) menuitem.show() self.hyphenation_menu.set_submenu(menu) def update_background_menu(self): backgrounds = [] if os.path.exists(user_skin_dir) and os.path.isdir(user_skin_dir): backgrounds_dirs = [user_skin_dir] else: backgrounds_dirs = [] for d in sys.path: f = os.path.join(d, 'ornamentbook', ornamentbook.skins_dir) if os.path.exists(f) and os.path.isdir(f): backgrounds_dirs.append(f) break for d in backgrounds_dirs: f = os.path.join(d, '*.jpg') backgrounds.extend(glob(f)) menu = gtk.Menu() menu.show() for f in backgrounds: fn = os.path.abspath(f) menuitem = gtk.MenuItem(fn) menuitem.get_child().set_use_underline(False) menuitem.connect('activate', self.background_menu_activate_cb, fn) menu.add(menuitem) menuitem.show() self.background_menu.set_submenu(menu) def background_menu_activate_cb(self, w, filename): self.text_widget.set_background(filename) self.properties.path_to_background = filename self.text_widget.draw_text() def hyphenation_menu_activate_cb(self, w, lang): self.text_widget.content.lang = lang self.text_widget.draw_text() def update_skins_menu(self): menu = gtk.Menu() menu.show() for s in self.properties.skins: menuitem = gtk.MenuItem(self.properties.skins[s]) menuitem.get_child().set_use_underline(False) menuitem.connect('activate', self.skins_menu_activate_cb, s) menu.add(menuitem) menuitem.show() self.skins_menu.set_submenu(menu) def skins_menu_activate_cb(self, w, skin): self.properties.read_skin(skin) #self.properties.current_skin = skin #self.properties.read_properties() self.text_widget.initialize() self.text_widget.draw_text() def on_new_skin_activate(self, *args): s = entry_dialog(self.window, 'Save skin', 'Skin name: ') if s: self.properties.save_skin(s) self.update_skins_menu() def recent_files_activate_cb(self, w, filename): self.open_file(filename) def add_file_to_recent(self, filename, line, index, encoding, lang): i = 0 for f in self.properties.recent_files: if f[0] == filename: del self.properties.recent_files[i] break i+=1 if len(self.properties.recent_files) >= self.properties.num_recent_files: del self.properties.recent_files[:len(self.properties.recent_files)-self.properties.num_recent_files+1] self.properties.recent_files.append((filename, line, index, encoding, lang)) self.add_file_to_bookmarks(filename) def add_file_to_bookmarks(self, filename): book = self.bookmarks.get_book(filename) if book: book.current_position = self.text_widget.get_position() book.current_offset = self.text_widget.get_offset() self.bookmarks.save_book(book) else: book, file_parser = new_book(filename) self.bookmarks.add_new_book(book) if self.books_manager: self.books_manager.update_treeview() def on_open_activate(self, *args): dialog = OpenFileDialog(self.window) filename = dialog.filename if filename: self.open_file(filename) return def on_go_to_position_activate(self, *args): s = entry_dialog(self.window, 'Go to position', 'Go to position: (%) ') try: pos = float(s) except: return if 100 < pos < 0: return self.text_widget.set_position(pos/100) def on_quit_activate(self, *args): self.window.destroy() def on_main_window_unrealize(self, *args): if self.is_fullscreen: self.properties.main_window_width, self.properties.main_window_height = self.prev_geometry else: self.properties.main_window_width, self.properties.main_window_height = self.window.get_size() self.properties.file_select_path = OpenFileDialog.file_select_path if self.filename: self.add_file_to_recent(self.filename, self.text_widget.current_page_line_index, self.text_widget.current_page_char_index, self.text_widget.content.encoding, self.text_widget.content.lang) self.properties.save_properties() save_config_file(self.main_properties) self.bookmarks.save_bookmarks() def on_properties_activate(self, *args): dlg = PropertiesDialog(self.window, self.properties, self.propsdialog_glade_file) dlg.connect('properties-apply', self.apply_properties_cb, dlg) def apply_properties_cb(self, w, dlg): self.properties = dlg.properties self.text_widget.properties = dlg.properties self.text_widget.initialize() self.timeout_cb() self.text_widget.draw_text() def on_increase_font_activate(self, *args): self.text_widget.incr_font(1) self.text_widget.draw_text() def on_decrease_font_activate(self, *args): self.text_widget.incr_font(-1) self.text_widget.draw_text() def on_fullscreen_activate(self, *args): if gtk.pygtk_version < (2, 2): return True if self.is_fullscreen: self.window.unfullscreen() self.main_menubar.show() self.is_fullscreen = False return True else: if self.properties.hide_menu: self.main_menubar.hide() self.window.fullscreen() self.prev_geometry = self.window.get_size() self.is_fullscreen = True return True return False def on_hide_menu_activate(self, *args): if self.main_menubar.get_property('visible'): self.main_menubar.hide() else: self.main_menubar.show() def on_books_manager_activate(self, *args): if self.books_manager: self.books_manager.window.present() return if self.main_properties: BookmarksWindow.hide_bookmarks \ = int(self.main_properties['bookmarks_manager_hide_bookmarks']) BookmarksWindow.hide_cover \ = int(self.main_properties['bookmarks_manager_hide_cover']) BookmarksWindow.show_category \ = self.main_properties['bookmarks_manager_show_category'] m = BookmarksWindow(self.bookmarks) self.books_manager = m w = m.window w.connect('unrealize', self.books_manager_unrealize_cb) m.connect('load-file', self.books_manager_load_file_cb) m.connect('book-removed', self.books_manager_book_removed_cb) if self.main_properties: width = int(self.main_properties['bookmarks_manager_width']) height = int(self.main_properties['bookmarks_manager_height']) w.resize(width, height) pos = int(self.main_properties['bookmarks_manager_paned_position']) m.paned.set_position(pos) w.show() def books_manager_unrealize_cb(self, w): width, height = w.get_size() self.main_properties['bookmarks_manager_width'] = width self.main_properties['bookmarks_manager_height'] = height self.main_properties['bookmarks_manager_paned_position'] \ = self.books_manager.paned.get_position() self.main_properties['bookmarks_manager_show_category'] \ = self.books_manager.show_category self.main_properties['bookmarks_manager_hide_bookmarks'] \ = int(self.books_manager.hide_bookmarks) self.main_properties['bookmarks_manager_hide_cover'] \ = int(self.books_manager.hide_cover) self.books_manager = None def books_manager_load_file_cb(self, w, filename): for f in self.properties.recent_files: if f[0] == filename: self.open_file(filename) return book = self.bookmarks.get_book(filename) pos = 0 if book: pos = book.current_position self.open_file(filename) if pos: self.text_widget.set_position(pos) def books_manager_book_removed_cb(self, w, filename): rf = self.properties.recent_files[:] for f in self.properties.recent_files[:]: if f[0] == filename: self.properties.recent_files.remove(f) self.update_recent_files_menu() break def key_press_event_cb(self, w, event): inc_font_keys = (gtk.keysyms.plus, gtk.keysyms.equal, gtk.keysyms.KP_Add) dec_font_keys = (gtk.keysyms.minus, gtk.keysyms.KP_Subtract) if event.keyval == gtk.keysyms.F11: self.on_fullscreen_activate() return True elif event.state == gdk.CONTROL_MASK and event.keyval == gtk.keysyms.q: self.window.destroy() return True elif event.state == gdk.CONTROL_MASK and event.keyval in inc_font_keys: self.on_increase_font_activate() return True elif event.state == gdk.CONTROL_MASK and event.keyval in dec_font_keys: self.on_decrease_font_activate() return True elif event.state == gdk.CONTROL_MASK and event.keyval == gtk.keysyms.o: self.on_open_activate() return True elif (event.state not in (gdk.CONTROL_MASK,) and event.keyval == gtk.keysyms.m): self.on_hide_menu_activate() return True elif event.state == gdk.CONTROL_MASK and event.keyval == gtk.keysyms.m: self.on_books_manager_activate() return True return False ##---------------------------------------------------------------------- if __name__ == '__main__': ## try: ## os.mkdir(config_dir) ## except: ## pass npbr = NewPyBR() npbr.window.connect('destroy', lambda w: gtk.main_quit()) gtk.main()