--- /dev/null
+
+import gtk
+import gobject
+import re
+import urlparse
+import copy
+import thread_view
+
+class ThreadPopup:
+ '''
+ classdocs
+ '''
+
+ _INTERVAL = 100
+
+ def __init__(self, bbs_type):
+ self._thread_view_list = []
+ self._bbs_type = bbs_type
+ self._timer_started = False
+
+ def push_thread_view(self, threadview):
+ threadview.connect("cursor-over-link-event", self.on_cursor_over_link)
+ self._thread_view_list.append(threadview)
+
+ def pop_thread_view(self):
+ view = self._thread_view_list.pop()
+ top = view.get_toplevel()
+ top.destroy()
+
+ def _collapse(self, threadview):
+ length = len(self._thread_view_list)
+ for idx in range(length):
+ idx = length - idx - 1
+ view = self._thread_view_list[idx]
+ if view == threadview:
+ break
+ self.pop_thread_view()
+
+ def _is_thread_view_top(self, threadview):
+ listnum = len(self._thread_view_list)
+ if listnum == 0:
+ return False
+ last = self._thread_view_list[listnum-1]
+ return threadview == last
+
+ def on_cursor_over_link(self, widget, event, uri):
+ orig_uri = uri
+ if not uri.startswith("http://"):
+ # maybe a relative uri.
+ uri = urlparse.urljoin(self._bbs_type.get_uri_base(), uri)
+
+ strict_uri = self._bbs_type.get_thread_uri()
+ idx = self._thread_view_list.index(widget)
+ if idx != len(self._thread_view_list)-1 and orig_uri == self._thread_view_list[idx+1].get_toplevel().uri:
+ return
+ if uri != strict_uri and uri.startswith(strict_uri):
+ resnum = uri[len(strict_uri):]
+ match = re.match("\d+", resnum)
+ if match:
+ resnum = int(match.group())
+ if self._check_to_need_hint(widget, resnum):
+ self._show_hint(widget, resnum, orig_uri)
+
+ def _get_owner(self, gdk_win):
+ top = gdk_win.get_toplevel()
+ for threadview in self._thread_view_list:
+ if threadview.window.get_toplevel() == top:
+ return threadview
+ return None
+
+ def on_timeout(self):
+ ret = gtk.gdk.window_at_pointer()
+ if ret is None:
+ # print "unknown window"
+ self._collapse(self._thread_view_list[0])
+ self._timer_started = False
+ return False
+
+ gdk_win, x, y = ret
+ threadview = self._get_owner(gdk_win)
+ if threadview is None:
+ # print "unknown gdk window"
+ self._collapse(self._thread_view_list[0])
+ self._timer_started = False
+ return False
+
+ length = len(self._thread_view_list)
+ if length == 1:
+ # print "no popup window"
+ self._collapse(threadview)
+ self._timer_started = False
+ return False
+
+ if self._is_thread_view_top(threadview):
+ return True
+
+ uri, layout, element = threadview.ptrpos_to_uri(x, y)
+ view = self._thread_view_list[self._thread_view_list.index(threadview)+1]
+ if layout is None or uri is None or uri != view.get_toplevel().uri:
+ self._collapse(threadview)
+
+ return True
+
+ def _show_hint(self, threadview, num, uri):
+ top = threadview.get_toplevel()
+ relative_x, relative_y = top.get_pointer()
+ gdk_win_x, gdk_win_y = top.window.get_origin()
+ abs_x = gdk_win_x + relative_x
+ abs_y = gdk_win_y + relative_y
+
+ popupwin = gtk.Window(gtk.WINDOW_POPUP)
+ popupwin.move(abs_x, abs_y)
+ view = thread_view.ThreadView()
+ self.push_thread_view(view)
+ for layout in self._thread_view_list[0].res_layout_list:
+ if layout.resnum == num:
+ clone = layout.clone()
+ view.add_layout(clone)
+ popupwin.view = view
+ popupwin.uri = uri
+ popupwin.add(view)
+ popupwin.set_property("border_width", 1)
+
+
+ def on_value_changed(widget, popupwin):
+ width, height = popupwin.get_size()
+ if height == widget.upper:
+ return
+ value = int(min(widget.upper+2, 400))
+ popupwin.resize(400, value)
+
+ #view.adjustment.connect("changed", on_value_changed, popupwin)
+
+ popupwin.set_default_size(300, 100)
+
+ popupwin.show_all()
+
+ if not self._timer_started:
+ self._timer_started = True
+ gobject.timeout_add(ThreadPopup._INTERVAL, self.on_timeout)
+
+ def _check_to_need_hint(self, threadview, num):
+ if self._is_thread_view_top(threadview):
+ return True
+
+
else:
for element in self.element_list:
element.draw(drawingarea, y_offset, self.pango_layout)
-
+
+ def clone(self):
+ import copy
+ layout = ResLayout(self.left_margin, self.resnum, self.pango_layout)
+ layout.element_list = []
+ for element in self.element_list:
+ layout.element_list.append(copy.copy(element))
+ return layout
class ThreadView(gtk.HBox):
+ __gsignals__ = {
+ "cursor-over-link-event":
+ (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (object, object, ))
+ }
+
hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)
regular_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM)
arrow_cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)
else:
if uri is not None and uri != "":
cursor = ThreadView.hand_cursor
+ self.emit("cursor-over-link-event", event, uri)
self.drawingarea.window.set_cursor(cursor)