8 from ThreadViewBase.element import ElementEmpty
11 class ThreadViewForPopup(thread_view.ThreadView):
14 def _do_popup(self, x, y, button, time): pass
17 class ThreadPopup(gobject.GObject):
24 (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (object, object,))
30 def __init__(self, bbs_type):
31 gobject.GObject.__init__(self)
32 self._thread_view_list = []
33 self._bbs_type = bbs_type
34 self._timer_started = False
36 def push_thread_view(self, threadview):
37 threadview.connect("cursor-over-link-event", self.on_cursor_over_link)
38 self._thread_view_list.append(threadview)
40 def pop_thread_view(self):
41 view = self._thread_view_list.pop()
42 top = view.get_toplevel()
45 def _collapse(self, threadview):
46 length = len(self._thread_view_list)
47 for idx in range(length):
48 idx = length - idx - 1
49 view = self._thread_view_list[idx]
50 if view == threadview:
52 self.pop_thread_view()
54 def _is_thread_view_top(self, threadview):
55 listnum = len(self._thread_view_list)
58 last = self._thread_view_list[listnum-1]
59 return threadview == last
61 def on_cursor_over_link(self, widget, event, uri):
63 if not uri.startswith("http://"):
64 # maybe a relative uri.
65 uri = urlparse.urljoin(self._bbs_type.get_uri_base(), uri)
67 strict_uri = self._bbs_type.get_thread_uri()
68 idx = self._thread_view_list.index(widget)
69 if idx != len(self._thread_view_list)-1 and orig_uri == self._thread_view_list[idx+1].get_toplevel().uri:
71 if not self._check_to_need_hint(widget):
73 if uri != strict_uri and uri.startswith(strict_uri):
74 resnum = uri[len(strict_uri):]
75 match = re.match("(?P<left>\d+)-(?P<right>\d+)", resnum)
77 left = int(match.group("left"))
78 right = int(match.group("right"))
80 resnum = range(left, right+1)
82 resnum = range(left, right-1, -1)
83 self._show_hint(widget, resnum, orig_uri)
85 match = re.match("\d+", resnum)
87 resnum = [int(match.group())]
88 self._show_hint(widget, resnum, orig_uri)
90 def _get_owner(self, gdk_win):
91 top = gdk_win.get_toplevel()
92 for threadview in self._thread_view_list:
93 if threadview.window.get_toplevel() == top:
98 ret = gtk.gdk.window_at_pointer()
100 # print "unknown window"
101 self._collapse(self._thread_view_list[0])
102 self._timer_started = False
106 threadview = self._get_owner(gdk_win)
107 if threadview is None:
108 # print "unknown gdk window"
109 self._collapse(self._thread_view_list[0])
110 self._timer_started = False
113 length = len(self._thread_view_list)
115 # print "no popup window"
116 self._collapse(threadview)
117 self._timer_started = False
120 if self._is_thread_view_top(threadview):
123 uri, layout, element = threadview.ptrpos_to_uri(x, y)
124 view = self._thread_view_list[self._thread_view_list.index(threadview)+1]
125 if layout is None or uri is None or uri != view.get_toplevel().uri:
126 self._collapse(threadview)
130 def _show_hint(self, threadview, numlist, uri):
131 top = threadview.get_toplevel()
132 relative_x, relative_y = top.get_pointer()
133 gdk_win_x, gdk_win_y = top.window.get_origin()
134 abs_x = gdk_win_x + relative_x
135 abs_y = gdk_win_y + relative_y
137 popupwin = gtk.Window(gtk.WINDOW_POPUP)
139 view = ThreadViewForPopup()
140 popupwin.add(thread_view.ThreadViewContainer(view))
141 view.connect("uri-clicked-event", self.on_threadview_uri_clicked)
142 self.push_thread_view(view)
145 view.size_allocate(gtk.gdk.Rectangle(0, 0, 300, 200))
146 view.adjustment.page_size = 200
149 for layout in self._thread_view_list[0].res_layout_list:
151 if isinstance(layout.element_list[0], ElementEmpty):
153 if layout.resnum == num:
154 clone = layout.clone()
155 view.add_layout(clone)
158 popupwin.set_property("border_width", ThreadPopup._BORDER_WIDTH)
161 gtk.gdk.Rectangle(0, 0, 300, int(min(200, view.adjustment.upper))))
163 popupwin.set_default_size(view.allocation.width
164 +ThreadPopup._BORDER_WIDTH*2,
165 view.allocation.height
166 +ThreadPopup._BORDER_WIDTH*2)
168 # show the popup at an appropriate position.
169 width, height = popupwin.get_size()
170 if abs_x + width > gtk.gdk.screen_width():
171 abs_x = abs_x - width
172 if abs_y + height > gtk.gdk.screen_height():
173 abs_y = abs_y - height
174 popupwin.move(abs_x, abs_y)
178 if not self._timer_started:
179 self._timer_started = True
180 gobject.timeout_add(ThreadPopup._INTERVAL, self.on_timeout)
182 def _check_to_need_hint(self, threadview):
183 if self._is_thread_view_top(threadview):
186 def on_threadview_uri_clicked(self, widget, uri):
187 self.emit("uri-clicked-event", widget, uri)