OSDN Git Service

Regist WinWrap reference to windowlist, not widget reference.
[fukui-no-namari/fukui-no-namari.git] / src / Hage1 / thread_window.py
1 # Copyright (C) 2006 by Aiwota Programmer
2 # aiwotaprog@tetteke.tk
3 #
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 import pygtk
19 pygtk.require('2.0')
20 import gtk
21 import gtk.glade
22 import os.path
23 import codecs
24 import re
25 import pango
26 import urllib2
27
28 import misc
29 import datfile
30 import barehtmlparser
31 import idxfile
32 import windowlist
33 import board_window
34 import brdlist_window
35
36 GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
37                          "..", "data")
38 GLADE_FILENAME = "thread_window.glade"
39
40 def open_thread(bbs, board, thread):
41     if not bbs or not board or not thread:
42         raise ValueError, "parameter must not be empty"
43
44     key = "/" + bbs + "/" + board + "/" + thread
45     winwrap = windowlist.get_window(key)
46     if winwrap:
47         # already opened
48         winwrap.window.present()
49         pass
50     else:
51         win_wrap = WinWrap(bbs, board, thread)
52         windowlist.window_created(key, win_wrap)
53
54
55 class WinWrap:
56
57     def __init__(self, bbs, board, thread):
58         self.bbs = bbs
59         self.board = board
60         self.thread = thread
61         self.size = 0
62         self.num = 0
63         self.title = None
64
65         glade_path = os.path.join(GLADE_DIR, GLADE_FILENAME)
66         self.widget_tree = gtk.glade.XML(glade_path)
67         self.window = self.widget_tree.get_widget("thread_window")
68         self.textview = self.widget_tree.get_widget("textview")
69         self.textbuffer = self.textview.get_buffer()
70         self.enditer = self.textbuffer.get_end_iter()
71         self.boldtag = self.textbuffer.create_tag(weight=pango.WEIGHT_BOLD)
72         self.leftmargintag = self.textbuffer.create_tag()
73         self.leftmargintag.set_property("left-margin", 20)
74
75         sigdic = {"on_toolbutton_refresh_clicked": self.update,
76                   "on_refresh_activate": self.update,
77                   "on_close_activate": self.on_close_activate,
78                   "on_quit_activate": self.on_quit_activate,
79                   "on_show_board_activate": self.on_show_board_activate,
80                   "on_show_board_list_activate":
81                   self.on_show_board_list_activate,
82                   "on_thread_window_destroy": self.on_thread_window_destroy}
83         self.widget_tree.signal_autoconnect(sigdic)
84
85         self.load_dat()
86
87     def on_close_activate(self, widget):
88         self.window.destroy()
89
90     def on_thread_window_destroy(self, widget):
91         -1
92
93     def on_quit_activate(self, widget):
94         gtk.main_quit()
95
96     def on_show_board_activate(self, widget):
97         board_window.open_board(self.bbs, self.board)
98
99     def on_show_board_list_activate(self, widget):
100         brdlist_window.open_brdlist(self.bbs)
101
102     def http_get_dat(self, on_get_res):
103         datfile_url = misc.get_thread_dat_url(self.bbs, self.board, self.thread)
104
105         idx_dic = idxfile.load_idx(self.bbs, self.board, self.thread)
106         lastmod = idx_dic["lastModified"]
107         etag = idx_dic["etag"]
108
109         req = urllib2.Request(datfile_url)
110         if self.size > 0:
111             req.add_header("Range", "bytes=" + str(self.size) + "-")
112         if lastmod:
113             req.add_header("If-Modified-Since", lastmod)
114         if etag:
115             req.add_header("If-None-Match", etag)
116         print req.headers
117
118         res = urllib2.urlopen(req)
119         headers = res.info()
120         print headers
121
122         line = res.readline()
123         maybe_incomplete = False
124         while line:
125             if not line.endswith("\n"):
126                 maybe_incomplete = True
127                 print "does not end with \\n. maybe incomplete"
128                 break
129             on_get_res(line)
130             line = res.readline()
131
132         res.close()
133
134         if maybe_incomplete:
135             lastmod = None
136             etag = None
137         else:
138             if "Last-Modified" in headers:
139                 lastmod = headers["Last-Modified"]
140             if "ETag" in headers:
141                 etag = headers["Etag"]
142
143         if self.num > 0:
144             if not self.title:
145                 self.title = datfile.get_title_from_dat(
146                     self.bbs, self.board, self.thread)
147                 if self.title:
148                     self.window.set_title(self.title)
149             # save idx
150             idx_dic = {"title": self.title, "lineCount": self.num,
151                    "lastModified": lastmod, "etag": etag}
152             idxfile.save_idx(self.bbs, self.board, self.thread, idx_dic)
153
154     def update(self, widget=None):
155         line_count = datfile.get_dat_line_count(
156             self.bbs, self.board, self.thread)
157
158         if line_count > self.num:
159             datfile.load_dat_partly(
160                 self.bbs, self.board, self.thread,
161                 self.append_rawres_to_buffer, self.num+1)
162
163         dat_path = misc.get_thread_dat_path(self.bbs, self.board, self.thread)
164         dat_file = file(dat_path, "a+")
165
166         def save_line_and_append_to_buffer(line):
167             dat_file.seek(self.size)
168             dat_file.write(line)
169             self.append_rawres_to_buffer(line)
170
171         self.http_get_dat(save_line_and_append_to_buffer)
172         dat_file.close()
173
174     def load_dat(self):
175         self.size = 0
176         self.num = 0
177
178         self.title = datfile.get_title_from_dat(
179             self.bbs, self.board, self.thread)
180         if self.title:
181             self.window.set_title(self.title)
182
183         datfile.load_dat(self.bbs, self.board, self.thread,
184                          self.append_rawres_to_buffer)
185         self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0)
186
187
188     def append_rawres_to_buffer(self, line):
189         self.size += len(line)
190         self.num += 1
191
192         h = lambda name,mail,date,msg: self.reselems_to_buffer(
193             self.num, name, mail, date, msg)
194
195         datfile.split_line_to_elems(line.decode("cp932", "replace"), h)
196         
197     def reselems_to_buffer(self, num, name, mail, date, msg):
198         # number
199         self.textbuffer.insert(self.enditer, str(num) + " ")
200
201         # name
202         p = barehtmlparser.BareHTMLParser(self.untiedata_to_buffer)
203         p.feed("<b>" + name + "</b>")
204         p.close()
205
206         # mail
207         self.textbuffer.insert(self.enditer, "[" + mail + "]")
208
209         # date
210         p.feed(date)
211         p.close()
212         self.textbuffer.insert(self.enditer, "\n")
213
214         # msg
215         p.reset_func(self.untiedata_to_buffer_with_leftmargin)
216         p.feed(msg)
217         p.close()
218
219         self.textbuffer.insert(self.enditer, "\n\n")
220
221     def untiedata_to_buffer(self, data, bold, href):
222         if bold:
223             self.textbuffer.insert_with_tags(self.enditer, data, self.boldtag)
224         else:
225             self.textbuffer.insert(self.enditer, data)
226
227     def untiedata_to_buffer_with_leftmargin(self, data, bold, href):
228         if bold:
229             self.textbuffer.insert_with_tags(self.enditer, data,
230                                              self.boldtag, self.leftmargintag)
231         else:
232             self.textbuffer.insert_with_tags(self.enditer, data,
233                                              self.leftmargintag)