import re
import pango
import urllib2
+import urlparse
+import gnome
import misc
import datfile
import idxfile
import session
import board_window
+import uri_opener
from http_sub import HTTPRedirectHandler302
+from BbsType import bbs_type_judge_uri
+from BbsType import bbs_type_exception
GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"..", "data")
GLADE_FILENAME = "thread_window.glade"
-def open_thread(uri):
+def open_thread(uri, update=False):
if not uri:
raise ValueError, "parameter must not be empty"
+ bbs_type = bbs_type_judge_uri.get_type(uri)
+ if not bbs_type.is_thread():
+ raise bbs_type_exception.BbsTypeError, \
+ "the uri does not represent thread: " + uri
+ uri = bbs_type.get_thread_uri() # use strict thread uri
+
winwrap = session.get_window(uri)
if winwrap:
# already opened
winwrap.window.present()
- pass
+ if update:
+ winwrap.load(update)
else:
- win_wrap = WinWrap(uri)
- session.window_created(uri, win_wrap)
+ winwrap = WinWrap(bbs_type.uri) # pass original uri
+ session.window_created(uri, winwrap)
+ winwrap.load(update)
+
+ # jump to the res if necessary.
+ winwrap.jump_to_res(bbs_type.uri)
class WinWrap:
+ hovering_over_link = False
+ hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)
+ regular_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM)
+
def __init__(self, uri):
from BbsType import bbs_type_judge_uri
self.leftmargintag.set_property("left-margin", 20)
sigdic = {"on_toolbutton_refresh_clicked": self.update,
+ "on_toolbutton_compose_clicked": self.on_compose_clicked,
"on_refresh_activate": self.update,
"on_close_activate": self.on_close_activate,
"on_quit_activate": self.on_quit_activate,
"on_thread_window_destroy": self.on_thread_window_destroy}
self.widget_tree.signal_autoconnect(sigdic)
- self.load_dat()
+ self.textview.connect("event-after", self.on_event_after)
+ self.textview.connect("motion-notify-event",
+ self.on_motion_notify_event)
+ self.textview.connect("visibility-notify-event",
+ self.on_visibility_notify_event)
+
+ def on_compose_clicked(self, widget):
+ import submit_window
+ submit_window.open(self.bbs_type.get_thread_uri())
+
+ def on_event_after(self, widget, event):
+ if event.type != gtk.gdk.BUTTON_RELEASE:
+ return False
+ if event.button != 1:
+ return False
+ buffer = widget.get_buffer()
+
+ try:
+ start, end = buffer.get_selection_bounds()
+ except ValueError:
+ pass
+ else:
+ if start.get_offset() != end.get_offset():
+ return False
+
+ x, y = widget.window_to_buffer_coords(
+ gtk.TEXT_WINDOW_WIDGET, int (event.x), int(event.y))
+ iter = widget.get_iter_at_location(x, y)
+ if not iter.has_tag(self.leftmargintag) or x > 20:
+ tags = iter.get_tags()
+ for tag in tags:
+ href = tag.get_data("href")
+ if href:
+ self.on_link_clicked(widget, href)
+ return False
+
+ def on_link_clicked(self, widget, href):
+
+ if not href.startswith("http://"):
+ # maybe a relative uri.
+ href = urlparse.urljoin(self.bbs_type.get_uri_base(), href)
+
+ try:
+ uri_opener.open_uri(href)
+ except bbs_type_exception.BbsTypeError:
+ # not supported, show with the web browser.
+ gnome.url_show(href)
+
+ def on_motion_notify_event(self, widget, event):
+ x, y = widget.window_to_buffer_coords(
+ gtk.TEXT_WINDOW_WIDGET, int(event.x), int(event.y))
+ self.set_cursor_if_appropriate(widget, x, y)
+ widget.window.get_pointer()
+ return False
+
+ def on_visibility_notify_event(self, widget, event):
+ wx, wy, mod = widget.window.get_pointer()
+ bx, by = widget.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, wx, wy)
+
+ self.set_cursor_if_appropriate(widget, bx, by)
+ return False
+
+ def set_cursor_if_appropriate(self, widget, x, y):
+ hovering = False
+
+ buffer = widget.get_buffer()
+ iter = widget.get_iter_at_location(x, y)
+ if not iter.has_tag(self.leftmargintag) or x > 20:
+ tags = iter.get_tags()
+ for tag in tags:
+ href = tag.get_data("href")
+ if href:
+ hovering = True
+
+ if hovering != self.hovering_over_link:
+ self.hovering_over_link = hovering
+
+ if self.hovering_over_link:
+ widget.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
+ self.hand_cursor)
+ else:
+ widget.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
+ self.regular_cursor)
def on_close_activate(self, widget):
self.window.destroy()
if self.title:
self.window.set_title(self.title)
+ self.textbuffer.create_mark("1", self.enditer, True)
+
datfile.load_dat(self.bbs, self.board, self.thread,
self.append_rawres_to_buffer)
- self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0)
+ if self.num > 0:
+ # jump to the last res.
+ mark = self.textbuffer.get_mark(str(self.num+1))
+ if mark:
+ self.textview.scroll_to_mark(mark, 0)
def append_rawres_to_buffer(self, line):
self.num, name, mail, date, msg)
datfile.split_line_to_elems(line.decode("cp932", "replace"), h)
-
+
+ # for next res
+ self.textbuffer.create_mark(str(self.num+1), self.enditer, True)
+
def reselems_to_buffer(self, num, name, mail, date, msg):
+ p = barehtmlparser.BareHTMLParser(self.untiedata_to_buffer)
# number
- self.textbuffer.insert(self.enditer, str(num) + " ")
+ p.feed(str(num) + " ")
# name
- p = barehtmlparser.BareHTMLParser(self.untiedata_to_buffer)
p.feed("<b>" + name + "</b>")
- p.close()
# mail
- self.textbuffer.insert(self.enditer, "[" + mail + "]")
+ p.feed("[" + mail + "]")
# date
p.feed(date)
- p.close()
- self.textbuffer.insert(self.enditer, "\n")
+ p.feed("<br>")
# msg
p.reset_func(self.untiedata_to_buffer_with_leftmargin)
- p.feed(msg)
+ p.feed(msg.lstrip(" "))
+
+ p.feed("<br><br>")
p.close()
- self.textbuffer.insert(self.enditer, "\n\n")
+ def href_tag(self, href):
+ tag = self.textbuffer.create_tag(underline=pango.UNDERLINE_SINGLE)
+ tag.set_data("href", href)
+ return tag
def untiedata_to_buffer(self, data, bold, href):
if bold:
- self.textbuffer.insert_with_tags(self.enditer, data, self.boldtag)
+ if href:
+ self.textbuffer.insert_with_tags(
+ self.enditer, data, self.boldtag, self.href_tag(href))
+ else:
+ self.textbuffer.insert_with_tags(
+ self.enditer, data, self.boldtag)
else:
- self.textbuffer.insert(self.enditer, data)
+ if href:
+ self.textbuffer.insert_with_tags(
+ self.enditer, data, self.href_tag(href))
+ else:
+ self.textbuffer.insert(self.enditer, data)
def untiedata_to_buffer_with_leftmargin(self, data, bold, href):
if bold:
- self.textbuffer.insert_with_tags(self.enditer, data,
- self.boldtag, self.leftmargintag)
+ if href:
+ self.textbuffer.insert_with_tags(
+ self.enditer, data, self.boldtag,
+ self.leftmargintag,self.href_tag(href))
+ else:
+ self.textbuffer.insert_with_tags(
+ self.enditer, data, self.boldtag, self.leftmargintag)
+ else:
+ if href:
+ self.textbuffer.insert_with_tags(
+ self.enditer, data,
+ self.leftmargintag, self.href_tag(href))
+ else:
+ self.textbuffer.insert_with_tags(
+ self.enditer, data, self.leftmargintag)
+
+ def jump_to_res(self, uri):
+ strict_uri = self.bbs_type.get_thread_uri()
+ if uri != strict_uri and uri.startswith(strict_uri):
+ resnum = uri[len(strict_uri):]
+ match = re.match("\d+", resnum)
+ if match:
+ resnum = match.group()
+ mark = self.textbuffer.get_mark(resnum)
+ if mark:
+ self.textview.scroll_to_mark(mark, 0, True, 0, 0)
+
+ def load(self, update=False):
+ dat_path = misc.get_thread_dat_path(
+ self.bbs_type.bbs_type, self.bbs_type.board, self.bbs_type.thread)
+ dat_exists = os.path.exists(dat_path)
+ if update or not dat_exists:
+ self.update()
else:
- self.textbuffer.insert_with_tags(self.enditer, data,
- self.leftmargintag)
+ self.load_dat()