X-Git-Url: http://git.sourceforge.jp/view?p=fukui-no-namari%2Ffukui-no-namari.git;a=blobdiff_plain;f=src%2FFukuiNoNamari%2Fthread_window.py;h=974a57ef9d32a35a00308e8ef97ff1b25239a02e;hp=7688e4ec4e7e879ecd0eb6f3c20deef8b78a6f7d;hb=refs%2Fheads%2Fmaster;hpb=448e2b8430c992cbb05e993f0ed4719051afa79b
diff --git a/src/FukuiNoNamari/thread_window.py b/src/FukuiNoNamari/thread_window.py
index 7688e4e..974a57e 100644
--- a/src/FukuiNoNamari/thread_window.py
+++ b/src/FukuiNoNamari/thread_window.py
@@ -33,22 +33,26 @@ import traceback
import itertools
import os
import sys
+from StringIO import StringIO
import misc
-from misc import FileWrap, ThreadInvoker
+from misc import FileWrap
import datfile
import barehtmlparser
import idxfile
import session
import board_window
import uri_opener
-from http_sub import HTTPRedirectHandler302, HTTPDebugHandler
from BbsType import bbs_type_judge_uri
from BbsType import bbs_type_exception
import config
import winwrapbase
import bookmark_list
import bookmark_window
+import thread_view
+import thread_popup
+import submit_window
+import network_manager
GLADE_FILENAME = "thread_window.glade"
@@ -73,215 +77,194 @@ def open_thread(uri, update=False):
winwrap.load(update)
# jump to the res if necessary.
- strict_uri = winwrap.bbs_type.get_thread_uri()
- if (winwrap.bbs_type.uri != strict_uri and
- winwrap.bbs_type.uri.startswith(strict_uri)):
- resnum = winwrap.bbs_type.uri[len(strict_uri):]
+ strict_uri = bbs_type.get_thread_uri()
+ if (bbs_type.uri != strict_uri and
+ bbs_type.uri.startswith(strict_uri)):
+ resnum = bbs_type.uri[len(strict_uri):]
match = re.match("\d+", resnum)
if match:
resnum = int(match.group())
winwrap.jump_to_res(resnum)
-class WinWrap(winwrapbase.WinWrapBase):
- hovering_over_link = False
- hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)
- regular_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM)
-
-
- def relayout(self):
- width = self.drawingarea.allocation.width
- sum_height = 0
- for layout in self.pangolayout:
- layout.set_width(width * pango.SCALE)
- layout.posY = sum_height
- x, y = layout.get_pixel_size()
- sum_height += y
- self.adjustment.upper = sum_height
-
- def draw_viewport(self):
- view_y = self.adjustment.get_value()
- self.drawingarea.window.draw_rectangle(
- self.drawingarea.style.base_gc[0],
- True, 0, 0,
- self.drawingarea.allocation.width,
- self.drawingarea.allocation.height)
-
- gc = self.drawingarea.window.new_gc()
- for layout in self.pangolayout:
- w, h = layout.get_pixel_size()
- layout_top = layout.posY
- layout_bottom = layout.posY + h
- area_top = view_y
- area_bottom = view_y + self.drawingarea.allocation.height
- if layout_top <= area_bottom and layout_bottom >= area_top:
- self.drawingarea.window.draw_layout(
- gc, 0, layout.posY - int(view_y), layout)
-
- def on_drawingarea_expose_event(self, widget, event, data=None):
- self.draw_viewport()
-
- def on_drawingarea_size_allocate(self, widget, allocation, data=None):
- if allocation.width != self.drawingarea.prev_width:
- self.relayout()
- self.drawingarea.prev_width = allocation.width
- self.adjustment.page_size = self.drawingarea.allocation.height
- self.adjustment.page_increment = self.drawingarea.allocation.height
-
- def on_drawingarea_button_press_event(self, widget, event, data=None):
- self.drawingarea.queue_draw()
-
- def on_vscrollbar_value_changed(self, widget, data=None):
- self.drawingarea.queue_draw()
-
- def on_drawingarea_scroll_event(self, widget, event, data=None):
- if event.direction == gtk.gdk.SCROLL_UP:
- self.adjustment.value -= 66.476200804
- if self.adjustment.value < self.adjustment.lower:
- self.adjustment.value = self.adjustment.lower
- if event.direction == gtk.gdk.SCROLL_DOWN:
- self.adjustment.value += 66.476200804
- max_value = self.adjustment.upper - self.adjustment.page_size
- if self.adjustment.value > max_value:
- self.adjustment.value = max_value
- def __init__(self, uri):
- self.pangolayout = []
+class HTMLParserToThreadView:
+ def __init__(self, threadview, resnum, left_margin):
+ self.threadview = threadview
+ self.resnum = resnum
+ self.left_margin = left_margin
+ self.initialize()
- from BbsType import bbs_type_judge_uri
- from BbsType import bbs_type_exception
- self.bbs_type = bbs_type_judge_uri.get_type(uri)
- if not self.bbs_type.is_thread():
- raise bbs_type_exception.BbsTypeError, \
- "the uri does not represent thread: " + uri
- self.size = 0
- self.num = 0
- self.title = ""
- self.lock_obj = False
- self.jump_request_num = 0
- self.progress = False
+ def set_left_margin(self, left_margin):
+ self.left_margin = left_margin
- glade_path = os.path.join(config.glade_dir, GLADE_FILENAME)
- self.widget_tree = gtk.glade.XML(glade_path)
- self.window = self.widget_tree.get_widget("thread_window")
- self.toolbar = self.widget_tree.get_widget("toolbar")
- self.toolbar.unset_style()
- self.statusbar = self.widget_tree.get_widget("statusbar")
- self.drawingarea = self.widget_tree.get_widget("drawingarea")
- self.vscrollbar = self.widget_tree.get_widget("vscrollbar")
- self.adjustment = self.vscrollbar.get_adjustment()
- self.adjustment.step_increment = 20
+ def initialize(self):
+ self.layout = None
- self.drawingarea.prev_width = 0
+ def on_new_line(self):
+ self.to_thread_view()
+ self.layout = self.threadview.create_res_layout(
+ self.left_margin, self.resnum)
- self.initialize_buffer()
+ def from_html_parser(self, data, bold, href):
+ if self.layout == None:
+ self.layout = self.threadview.create_res_layout(
+ self.left_margin, self.resnum)
- sigdic = {"on_refresh_activate": self.update,
- "on_compose_activate": self.on_compose_clicked,
- "on_toolbar_activate": self.on_toolbar_activate,
- "on_statusbar_activate": self.on_statusbar_activate,
- "on_refresh_activate": self.update,
- "on_close_activate": self.on_close_activate,
- "on_quit_activate": self.on_quit_activate,
- "on_show_board_activate": self.on_show_board_activate,
- "on_delete_activate": self.on_delete_activate,
- "on_drawingarea_expose_event": self.on_drawingarea_expose_event,
- "on_drawingarea_size_allocate":
- self.on_drawingarea_size_allocate,
- "on_thread_window_delete_event":
- self.on_thread_window_delete_event,
- "on_drawingarea_button_press_event":
- self.on_drawingarea_button_press_event,
- "on_drawingarea_scroll_event":
- self.on_drawingarea_scroll_event,
- "on_vscrollbar_value_changed":
- self.on_vscrollbar_value_changed,
- "on_add_bookmark_activate": self.on_add_bookmark_activate,
- "on_manage_bookmarks_activate": \
- self.on_manage_bookmarks_activate,
- "on_thread_window_destroy": self.on_thread_window_destroy}
- self.widget_tree.signal_autoconnect(sigdic)
+ self.layout.add_text(data, bold, href)
- self.restore()
- self.window.show_all()
+ def to_thread_view(self):
+ if self.layout is not None:
+ self.threadview.add_layout(self.layout)
+ self.initialize()
- self.created()
- def initialize_buffer(self):
- self.textbuffer = gtk.TextBuffer()
+class LoadDat:
- self.enditer = self.textbuffer.get_end_iter()
- self.boldtag = self.textbuffer.create_tag(weight=pango.WEIGHT_BOLD)
- self.leftmargintag = self.textbuffer.create_tag()
- self.leftmargintag.set_property("left-margin", 20)
+ def __init__(self, bbs_type, threadwindow, threadview, statusbar):
+ self.bbs_type = bbs_type
+ self.threadwindow = threadwindow
+ self.threadview = threadview
+ self.statusbar = statusbar
+ self.lock_obj = False
+ self.jump_request_num = 0
+ self.size = 0
+ self.num = 0
+ self.request_headers = None
+ self.response_headers = None
- self.pangolayout = []
+ self.statusbar_context_id = self.statusbar.get_context_id(
+ "Thread Window Status")
+ self.statusbar.push(self.statusbar_context_id, "OK.")
- def destroy(self):
- self.save()
- self.window.destroy()
+ def initialize(self):
+ self.num = 0
+ self.size = 0
+ self.threadview.initialize_buffer()
- def get_uri(self):
- return self.bbs_type.get_thread_uri()
+ def jump_request(self, res_num):
+ if not self.threadview.jump_to_res(res_num):
+ self.jump_request_num = res_num
- def on_compose_clicked(self, widget):
- import submit_window
- submit_window.open(self.bbs_type.get_thread_uri())
+ def _do_jump_if_need(self):
+ if self.jump_request_num:
+ num = self.jump_request_num
+ self.jump_request_num = 0
+ return self.threadview.jump_to_res(num)
- def on_toolbar_activate(self, widget):
- if self.toolbar.get_property("visible"):
- self.toolbar.hide()
- else:
- self.toolbar.show()
+ def _do_jump(self):
+ if not self._do_jump_if_need():
+ return self.threadview.jump_to_the_end()
- def on_statusbar_activate(self, widget):
- if self.statusbar.get_property("visible"):
- self.statusbar.hide()
+ def _load(self):
+ dat_path = misc.get_thread_dat_path(self.bbs_type)
+ try:
+ fd = file(dat_path)
+ except IOError:
+ raise misc.StopChainException()
else:
- self.statusbar.show()
+ i = 0
+ for line in fd:
+ self.append_rawres_to_buffer(line)
+ yield
+ fd.close()
+ self._do_jump()
- def on_close_activate(self, widget):
- self.destroy()
+ def _on_end(self):
+ self.request_headers = None
+ self.response_headers = None
+ self._un_lock()
- def on_thread_window_delete_event(self, widget, event):
- self.save()
- return False
-
- def on_thread_window_destroy(self, widget):
- self.destroyed()
+ def _lock(self):
+ if self.lock_obj:
+ print "Busy."
+ return False
+ self.lock_obj = True
+ return True
- def on_quit_activate(self, widget):
- session.main_quit()
+ def _un_lock(self):
+ self.lock_obj = False
- def on_add_bookmark_activate(self, widget):
- bookmark_list.bookmark_list.add_bookmark_with_edit(
- name=self.title, uri=self.bbs_type.uri)
+ def load(self):
+ self.jump_request_num = 0
+ if self._lock():
+ misc.chain(lambda *args: None, self._on_end, self._load())
- def on_manage_bookmarks_activate(self, widget):
- bookmark_window.open()
+ def _load_and_save(self, fd):
+ dat_path = misc.get_thread_dat_path(self.bbs_type)
+ try:
+ save_fd = FileWrap(dat_path)
+ save_fd.seek(self.size)
+ except IOError:
+ raise misc.StopChainException()
+
+ for line in fd:
+ if not line.endswith("\n"):
+ # the last line is not terminated with '\n'
+ print "does not end with \\n. maybe incomplete"
+ self.response_headers["lastmodified"] = None
+ self.response_headers["etag"] = None
+ raise misc.StopChainException()
+ save_fd.write(line)
+ self.append_rawres_to_buffer(line)
+ yield
+ self.threadview.queue_draw()
+ self._do_jump_if_need()
+
+ def on_received(self, res):
+ headers = res.headers
+ status = res.status
+
+ if "Last-modified".capitalize() in headers:
+ self.statusbar.pop(self.statusbar_context_id)
+ self.statusbar.push(self.statusbar_context_id,
+ "%s [%s]" % (status, headers["last-modified".capitalize()]))
+ else:
+ self.statusbar.pop(self.statusbar_context_id)
+ self.statusbar.push(self.statusbar_context_id, "%s" % status)
- def on_show_board_activate(self, widget):
- board_window.open_board(self.bbs_type.get_uri_base())
+ version, code, msg = status.split(None, 2)
+ code = int(code)
+ if code != 200 and code != 206:
+ self._on_end()
+ return
+ res.code = code
- def on_delete_activate(self, widget):
- try:
- dat_path = misc.get_thread_dat_path(self.bbs_type)
- os.remove(dat_path)
- except OSError:
- traceback.print_exc()
- try:
- idx_path = misc.get_thread_idx_path(self.bbs_type)
- os.remove(idx_path)
- except OSError:
- traceback.print_exc()
- try:
- states_path = misc.get_thread_states_path(self.bbs_type)
- os.remove(states_path)
- except OSError:
- traceback.print_exc()
+ if "Range".capitalize() in self.request_headers and code == 200:
+ self.initialize()
+
+ self.response_headers = headers
+ fd = StringIO(res.message)
+
+ def save_and_end():
+ try:
+ self._saveidx()
+ finally:
+ self._on_end()
+
+ misc.chain(lambda *args: None, save_and_end, self._load_and_save(fd))
+
+ def _saveidx(self):
+ lastmod = ""
+ etag = ""
+ if "last-modified".capitalize() in self.response_headers:
+ lastmod = self.response_headers["last-modified".capitalize()]
+ if "etag".capitalize() in self.response_headers:
+ etag = self.response_headers["etag".capitalize()]
+
+ if self.num > 0:
+ # save idx
+ idx_dic = {"title": self.title, "lineCount": self.num,
+ "lastModified": lastmod, "etag": etag}
+ idxfile.save_idx(self.bbs_type, idx_dic)
+
+ session.thread_idx_updated(self.bbs_type.get_thread_uri(), idx_dic)
+
+ def _http_get_dat(self):
- def http_get_dat(self, on_get_res):
datfile_url = self.bbs_type.get_dat_uri()
+ headers = {}
+
idx_dic = idxfile.load_idx(self.bbs_type)
lastmod = idx_dic["lastModified"]
etag = idx_dic["etag"]
@@ -296,151 +279,53 @@ class WinWrap(winwrapbase.WinWrapBase):
req.add_header("If-None-Match", etag)
req = self.bbs_type.set_extra_dat_request(req, self)
-
- opener = urllib2.build_opener(HTTPRedirectHandler302, HTTPDebugHandler)
try:
- res = opener.open(req)
- except urllib2.HTTPError, e:
- pass
-# gobject.idle_add(
-# lambda x: self.statusbar.push(0, x), "%d %s" % (e.code, e.msg))
+ network_manager.request_get(req.get_full_url(),
+ req.headers, self.on_received)
+ except network_manager.BusyException:
+ self._on_end()
+ self.statusbar.pop(self.statusbar_context_id)
+ self.statusbar.push(self.statusbar_context_id,
+ "The network is busy. Try later.")
+ except:
+ self._on_end()
+ self.statusbar.pop(self.statusbar_context_id)
+ self.statusbar.push(self.statusbar_context_id,
+ str(sys.exc_info()))
else:
- headers = res.info()
-# gobject.idle_add(
-# lambda x: self.statusbar.push(0, x), "%d %s" % (res.code, res.msg))
-
- maybe_incomplete = False
- for line in res:
- if not line.endswith("\n"):
- maybe_incomplete = True
- print "does not end with \\n. maybe incomplete"
- break
- on_get_res(line)
-
- res.close()
-
- if maybe_incomplete:
- lastmod = None
- etag = None
- else:
- if "Last-Modified" in headers:
- lastmod = headers["Last-Modified"]
- if "ETag" in headers:
- etag = headers["Etag"]
-
- if self.num > 0:
- # save idx
- idx_dic = {"title": self.title, "lineCount": self.num,
- "lastModified": lastmod, "etag": etag}
- idxfile.save_idx(self.bbs_type, idx_dic)
-
- gobject.idle_add(session.thread_idx_updated,
- self.bbs_type.get_thread_uri(), idx_dic)
-
- def update(self, widget=None):
-
- self.jump_request_num = 0
-
- def load():
- if self.num == 0:
- def create_mark():
- self.textbuffer.create_mark("1", self.enditer, True)
- gobject.idle_add(create_mark)
-
- line_count = datfile.get_dat_line_count(self.bbs_type)
- if line_count < self.num:
- self.num = 0
- self.size = 0
+ self.statusbar.pop(self.statusbar_context_id)
+ self.statusbar.push(self.statusbar_context_id, "GET...")
+ self.request_headers = req.headers
- gobject.idle_add(self.initialize_buffer)
+ def update(self):
- if line_count > self.num:
- datfile.load_dat_partly(
- self.bbs_type, self.append_rawres_to_buffer, self.num+1)
-
- def do_jump():
- if self.jump_request_num:
- if self.jump_request_num <= num:
- num = self.jump_request_num
- self.jump_request_num = 0
- self.jump_to_res(num)
- else:
- self.jump_to_the_end()
-
- gobject.idle_add(do_jump)
-
- def get():
- dat_path = misc.get_thread_dat_path(self.bbs_type)
- dat_file = FileWrap(dat_path)
-
- def save_line_and_append_to_buffer(line):
- dat_file.seek(self.size)
- dat_file.write(line)
- self.append_rawres_to_buffer(line)
-
- self.http_get_dat(save_line_and_append_to_buffer)
- dat_file.close()
-
- def do_jump():
- if self.jump_request_num:
- num = self.jump_request_num
- self.jump_request_num = 0
- self.jump_to_res(num)
-
- gobject.idle_add(do_jump)
-
- if self.lock():
-
- def on_end():
- self.un_lock()
- self.progress = False
-
- self.progress = True
- t = ThreadInvoker(lambda : gobject.idle_add(on_end), load, get)
- t.start()
-
- def load_dat(self):
-
- self.size = 0
- self.num = 0
self.jump_request_num = 0
- def load():
- datfile.load_dat(self.bbs_type, self.append_rawres_to_buffer)
-
- def jump():
-
- def do_jump():
- if self.jump_request_num:
- num = self.jump_request_num
- self.jump_request_num = 0
- self.jump_to_res(num)
- else:
- self.jump_to_the_end()
-
- gobject.idle_add(do_jump)
-
- if self.lock():
-
- def on_end():
- self.un_lock()
- self.progress = False
-
- self.progress = True
- t = ThreadInvoker(lambda : gobject.idle_add(on_end), load, jump)
- t.start()
+ if not self._lock():
+ return
+
+ line_count = datfile.get_dat_line_count(self.bbs_type)
+ if line_count != self.num:
+ # load dat file once more
+ self.num = 0
+ self.size = 0
+ self.threadview.initialize_buffer()
+ def end_and_get():
+ self._on_end()
+ self._http_get_dat()
+ misc.chain(lambda *args: None, end_and_get, self._load())
+ else:
+ self._http_get_dat()
def append_rawres_to_buffer(self, line):
self.size += len(line)
self.num += 1
- if not self.title and self.num == 1:
+ if self.num == 1:
title = self.bbs_type.get_title_from_dat(line)
if title:
self.title = title
- gobject.idle_add(self.window.set_title, title)
-
- self.res_queue = []
+ self.threadwindow.set_title(title)
line = line.decode(self.bbs_type.encoding, "replace")
m = self.bbs_type.dat_reg.match(line)
@@ -466,21 +351,18 @@ class WinWrap(winwrapbase.WinWrapBase):
date += " ID:" + id
self.reselems_to_buffer(num, name, mail, date, msg)
else:
- self.res_queue.append((str(self.num)+"\n", False, None, False))
- self.res_queue.append((line, False, None, True))
+ self.reselems_to_buffer(
+ str(self.num), "Invalid Name", "Invalid Mail",
+ "Invalid Date", line)
print "maybe syntax error.", self.num, line
- def process_res_queue(res_queue, num):
- self.process_queue(res_queue, num)
- # for next res
- #self.textbuffer.create_mark(str(num+1), self.enditer, True)
-
- gobject.idle_add(
- process_res_queue, self.res_queue, self.num)
-
def reselems_to_buffer(self, num, name, mail, date, msg):
+ pipe = HTMLParserToThreadView(self.threadview, num, 0)
p = barehtmlparser.BareHTMLParser(
- lambda d,b,h: self.res_queue.append((d,b,h,False)))
+ pipe.from_html_parser, pipe.on_new_line)
+
+ # First, create a pango layout for num,name,mail,date
+ # 'margin left' is 0
# number
p.feed(str(num) + " ")
@@ -492,83 +374,175 @@ class WinWrap(winwrapbase.WinWrapBase):
# date
p.feed(date)
- p.feed("
")
+ p.flush()
+
+ pipe.to_thread_view()
+
+ # Second, create a pango layout for message
+ # 'margin left' is 20
# msg
- p.reset_func(lambda d,b,h: self.res_queue.append((d,b,h,True)))
+ pipe.set_left_margin(20)
p.feed(msg.lstrip(" "))
- p.feed("
")
+ p.feed("
")
p.close()
- def href_tag(self, href):
- tag = self.textbuffer.create_tag(underline=pango.UNDERLINE_SINGLE)
- tag.set_data("href", href)
- return tag
-
- def process_queue(self, queue, num):
- text = ""
- for data, bold, href, margin in queue:
- text += data
- layout = self.drawingarea.create_pango_layout(text)
- layout.set_wrap(pango.WRAP_CHAR)
- layout.posY = 0
- layout.resnum = num
- self.pangolayout.append(layout)
- self.relayout()
- self.drawingarea.queue_draw()
-# taglist = []
-# if bold:
-# taglist.append(self.boldtag)
-# if href:
-# taglist.append(self.href_tag(href))
-# if margin:
-# taglist.append(self.leftmargintag)
-#
-# if taglist:
-# self.textbuffer.insert_with_tags(self.enditer, data, *taglist)
-# else:
-# self.textbuffer.insert(self.enditer, data)
+ pipe.to_thread_view()
+
+
+class WinWrap(winwrapbase.WinWrapBase):
+
+ def __init__(self, uri):
+ self.bbs_type = bbs_type_judge_uri.get_type(uri)
+ if not self.bbs_type.is_thread():
+ raise bbs_type_exception.BbsTypeError, \
+ "the uri does not represent thread: " + uri
+
+ glade_path = os.path.join(config.glade_dir, GLADE_FILENAME)
+ self.widget_tree = gtk.glade.XML(glade_path)
+ self._get_widgets()
+ self.widget_tree.signal_autoconnect(self)
+
+ self.toolbar.unset_style()
+
+ self.threadview = thread_view.ThreadView()
+ container = thread_view.ThreadViewContainer(self.threadview)
+ self.threadpopup = thread_popup.ThreadPopup(self.bbs_type)
+ self.threadpopup.push_thread_view(self.threadview)
+ self.vbox.pack_start(container)
+ self.vbox.reorder_child(container, 2)
+ self.window.set_focus(self.threadview)
+
+ self.threadview.connect(
+ "populate-popup", self.on_thread_view_populate_popup)
+ self.threadview.connect(
+ "uri-clicked-event", self.on_thread_view_uri_clicked)
+ self.threadpopup.connect(
+ "uri-clicked-event", self.on_thread_popup_uri_clicked)
+
+ self.initialize_buffer()
+
+ self.dat_load = LoadDat(self.bbs_type, self.window,
+ self.threadview, self.statusbar)
+
+ self.restore()
+ self.window.show_all()
+
+ self.created()
+
+ def _get_widgets(self):
+ self.window = self.widget_tree.get_widget("thread_window")
+ self.toolbar = self.widget_tree.get_widget("toolbar")
+ self.statusbar = self.widget_tree.get_widget("statusbar")
+ self.vbox = self.widget_tree.get_widget("vbox")
+
+ def initialize_buffer(self):
+ self.threadview.initialize_buffer()
+
+ def destroy(self):
+ self.save()
+ self.window.destroy()
+
+ def get_uri(self):
+ return self.bbs_type.get_thread_uri()
+
+ def show(self):
+ self.window.deiconify()
+
+ def hide(self):
+ self.window.iconify()
+
+ def _show_submit_window(self):
+ submit_window.open(self.bbs_type.get_thread_uri())
+
+ def _toggle_toolbar(self):
+ if self.toolbar.get_property("visible"):
+ self.toolbar.hide()
+ else:
+ self.toolbar.show()
+
+ def _toggle_statusbar(self):
+ if self.statusbar.get_property("visible"):
+ self.statusbar.hide()
+ else:
+ self.statusbar.show()
+
+ def _close_window(self):
+ self.destroy()
+
+ def _quit_session(self):
+ session.main_quit()
+
+ def _regist_as_bookmark(self):
+ title = self.window.get_title()
+ bookmark_list.bookmark_list.add_bookmark_with_edit(
+ name=title, uri=self.bbs_type.uri)
+
+ def _manage_bookmarks(self):
+ bookmark_window.open()
+
+ def _show_board(self):
+ board_window.open_board(self.bbs_type.get_uri_base())
+
+ def _delete_log(self):
+ try:
+ dat_path = misc.get_thread_dat_path(self.bbs_type)
+ os.remove(dat_path)
+ except OSError:
+ traceback.print_exc()
+ try:
+ idx_path = misc.get_thread_idx_path(self.bbs_type)
+ os.remove(idx_path)
+ except OSError:
+ traceback.print_exc()
+ try:
+ states_path = misc.get_thread_states_path(self.bbs_type)
+ os.remove(states_path)
+ except OSError:
+ traceback.print_exc()
+
+ def _open_uri(self, uri):
+ if not uri.startswith("http://"):
+ # maybe a relative uri.
+ uri = urlparse.urljoin(self.bbs_type.get_uri_base(), uri)
+
+ try:
+ uri_opener.open_uri(uri)
+ except bbs_type_exception.BbsTypeError:
+ # not supported, show with the web browser.
+ gnome.url_show(uri)
+
+ def _copy_text_to_clipboard(self, text):
+ if text and len(text) > 0:
+ clip = gtk.Clipboard()
+ text = text.encode("utf8")
+ clip.set_text(text, len(text))
+
+ def _modify_uri(self, uri):
+ if not uri.startswith("http://"):
+ uri = "http://" + uri
+ return uri
+
+ def update(self):
+ self.dat_load.update()
+
+ def load_dat(self):
+ self.dat_load.load()
def jump(self, value):
- def j():
- if value > self.adjustment.upper - self.adjustment.page_size:
- self.jump_to_the_end()
- else:
- self.adjustment.set_value(value)
- gobject.idle_add(j)
+ gobject.idle_add(self.threadview.jump, value)
def jump_to_layout(self, layout):
- gobject.idle_add(lambda : self.jump(layout.posY))
+ gobject.idle_add(self.threadview.jump_to_layout, layout)
def jump_to_the_end(self):
- def j():
- self.adjustment.set_value(
- self.adjustment.upper - self.adjustment.page_size)
- gobject.idle_add(j)
-# mark = self.textbuffer.get_mark(str(num+1))
-# if mark:
-# self.textview.scroll_to_mark(mark, 0)
-
- def lock(self):
- if self.lock_obj:
- print "locked, try later."
- return False
- else:
- print "get lock"
- self.lock_obj = True
- return True
-
- def un_lock(self):
- self.lock_obj = False
- print "unlock"
+ gobject.idle_add(self.threadview.jump_to_the_end)
def jump_to_res(self, resnum):
- for layout in self.pangolayout:
- if layout.resnum == resnum:
- self.jump_to_layout(layout)
- return
- self.jump_request_num = resnum
+ if self.threadview.jump_to_res(resnum):
+ return
+ self.dat_load.jump_request(resnum)
def load(self, update=False):
dat_path = misc.get_thread_dat_path(self.bbs_type)
@@ -665,3 +639,85 @@ class WinWrap(winwrapbase.WinWrapBase):
priority=gobject.PRIORITY_HIGH)
except:
traceback.print_exc()
+
+
+ # signal handlers
+
+ def on_thread_view_populate_popup(self, widget, menu):
+ menuitem = gtk.ImageMenuItem(gtk.STOCK_REFRESH)
+ menuitem.connect("activate",
+ self.on_popup_threadview_menu_refresh_activate)
+ menu.append(menuitem)
+
+ def on_thread_view_uri_clicked(self, widget, uri):
+ self._open_uri(uri)
+
+ def on_thread_popup_uri_clicked(self, widget, threadview, uri):
+ self._open_uri(uri)
+
+ def on_thread_window_delete_event(self, widget, event):
+ self.save()
+ return False
+
+ def on_thread_window_destroy(self, widget):
+ self.destroyed()
+
+
+
+
+ # menu commands
+
+ # menu file
+
+ def on_menu_file_show_board_activate(self, widget):
+ self._show_board()
+
+ def on_menu_file_compose_activate(self, widget):
+ self._show_submit_window()
+
+ def on_menu_file_delete_activate(self, widget):
+ self._delete_log()
+
+ def on_menu_file_close_activate(self, widget):
+ self._close_window()
+
+ def on_menu_file_quit_activate(self, widget):
+ self._quit_session()
+
+ # menu view
+
+ def on_menu_view_refresh_activate(self, widget):
+ self.update()
+
+ def on_menu_view_toolbar_activate(self, widget):
+ self._toggle_toolbar()
+
+ def on_menu_view_statusbar_activate(self, widget):
+ self._toggle_statusbar()
+
+ # menu bookmarks
+
+ def on_menu_bookmarks_bookmarkthispage_activate(self, widget):
+ self._regist_as_bookmark()
+
+ def on_menu_bookmarks_showbookmarks_activate(self, widget):
+ self._manage_bookmarks()
+
+ # toolbuttons
+
+ def on_toolbutton_refresh_activate(self, widget):
+ self.update()
+
+ def on_toolbutton_showboard_activate(self, widget):
+ self._show_board()
+
+ def on_toolbutton_compose_activate(self, widget):
+ self._show_submit_window()
+
+ def on_toolbutton_delete_activate(self, widget):
+ self._delete_log()
+
+ # popup menus
+
+ def on_popup_threadview_menu_refresh_activate(self, widget):
+ self.update()