OSDN Git Service

Notify thread idx updated to board window.
[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             windowlist.thread_idx_updated(
155                 self.bbs, self.board, self.thread, idx_dic)
156
157     def update(self, widget=None):
158         line_count = datfile.get_dat_line_count(
159             self.bbs, self.board, self.thread)
160
161         if line_count > self.num:
162             datfile.load_dat_partly(
163                 self.bbs, self.board, self.thread,
164                 self.append_rawres_to_buffer, self.num+1)
165
166         dat_path = misc.get_thread_dat_path(self.bbs, self.board, self.thread)
167         dat_file = file(dat_path, "a+")
168
169         def save_line_and_append_to_buffer(line):
170             dat_file.seek(self.size)
171             dat_file.write(line)
172             self.append_rawres_to_buffer(line)
173
174         self.http_get_dat(save_line_and_append_to_buffer)
175         dat_file.close()
176
177     def load_dat(self):
178         self.size = 0
179         self.num = 0
180
181         self.title = datfile.get_title_from_dat(
182             self.bbs, self.board, self.thread)
183         if self.title:
184             self.window.set_title(self.title)
185
186         datfile.load_dat(self.bbs, self.board, self.thread,
187                          self.append_rawres_to_buffer)
188         self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0)
189
190
191     def append_rawres_to_buffer(self, line):
192         self.size += len(line)
193         self.num += 1
194
195         h = lambda name,mail,date,msg: self.reselems_to_buffer(
196             self.num, name, mail, date, msg)
197
198         datfile.split_line_to_elems(line.decode("cp932", "replace"), h)
199         
200     def reselems_to_buffer(self, num, name, mail, date, msg):
201         # number
202         self.textbuffer.insert(self.enditer, str(num) + " ")
203
204         # name
205         p = barehtmlparser.BareHTMLParser(self.untiedata_to_buffer)
206         p.feed("<b>" + name + "</b>")
207         p.close()
208
209         # mail
210         self.textbuffer.insert(self.enditer, "[" + mail + "]")
211
212         # date
213         p.feed(date)
214         p.close()
215         self.textbuffer.insert(self.enditer, "\n")
216
217         # msg
218         p.reset_func(self.untiedata_to_buffer_with_leftmargin)
219         p.feed(msg)
220         p.close()
221
222         self.textbuffer.insert(self.enditer, "\n\n")
223
224     def untiedata_to_buffer(self, data, bold, href):
225         if bold:
226             self.textbuffer.insert_with_tags(self.enditer, data, self.boldtag)
227         else:
228             self.textbuffer.insert(self.enditer, data)
229
230     def untiedata_to_buffer_with_leftmargin(self, data, bold, href):
231         if bold:
232             self.textbuffer.insert_with_tags(self.enditer, data,
233                                              self.boldtag, self.leftmargintag)
234         else:
235             self.textbuffer.insert_with_tags(self.enditer, data,
236                                              self.leftmargintag)