OSDN Git Service

Add the participation of thread window in the program quit counter of windowlist
[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
34 GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
35                          "..", "data")
36 GLADE_FILENAME = "thread_window.glade"
37
38 def open_thread(bbs, board, thread):
39     if not bbs or not board or not thread:
40         raise ValueError, "parameter must not be empty"
41
42     key = "/" + bbs + "/" + board + "/" + thread
43     window = windowlist.get_window(key)
44     if window:
45         # already opened
46         window.present()
47         pass
48     else:
49         win_wrap = WinWrap(bbs, board, thread)
50         windowlist.window_created(key, win_wrap.window)
51
52
53 class WinWrap:
54
55     def __init__(self, bbs, board, thread):
56         self.bbs = bbs
57         self.board = board
58         self.thread = thread
59         self.size = 0
60         self.num = 0
61         self.title = None
62
63         glade_path = os.path.join(GLADE_DIR, GLADE_FILENAME)
64         self.widget_tree = gtk.glade.XML(glade_path)
65         self.window = self.widget_tree.get_widget("thread_window")
66         self.textview = self.widget_tree.get_widget("textview")
67         self.textbuffer = self.textview.get_buffer()
68         self.enditer = self.textbuffer.get_end_iter()
69         self.boldtag = self.textbuffer.create_tag(weight=pango.WEIGHT_BOLD)
70         self.leftmargintag = self.textbuffer.create_tag()
71         self.leftmargintag.set_property("left-margin", 20)
72
73         sigdic = {"on_toolbutton_refresh_clicked": self.update,
74                   "on_refresh_activate": self.update,
75                   "on_close_activate": self.on_close_activate,
76                   "on_quit_activate": self.on_quit_activate,
77                   "on_thread_window_destroy": self.on_thread_window_destroy}
78         self.widget_tree.signal_autoconnect(sigdic)
79
80         self.load_dat()
81
82     def on_close_activate(self, widget):
83         self.window.destroy()
84
85     def on_thread_window_destroy(self, widget):
86         -1
87
88     def on_quit_activate(self, widget):
89         gtk.main_quit()
90
91     def http_get_dat(self, on_get_res):
92         datfile_url = misc.get_thread_dat_url(self.bbs, self.board, self.thread)
93
94         idx_dic = idxfile.load_idx(self.bbs, self.board, self.thread)
95         lastmod = idx_dic["lastModified"]
96         etag = idx_dic["etag"]
97
98         req = urllib2.Request(datfile_url)
99         if self.size > 0:
100             req.add_header("Range", "bytes=" + str(self.size) + "-")
101         if lastmod:
102             req.add_header("If-Modified-Since", lastmod)
103         if etag:
104             req.add_header("If-None-Match", etag)
105         print req.headers
106
107         res = urllib2.urlopen(req)
108         headers = res.info()
109         print headers
110
111         line = res.readline()
112         maybe_incomplete = False
113         while line:
114             if not line.endswith("\n"):
115                 maybe_incomplete = True
116                 print "does not end with \\n. maybe incomplete"
117                 break
118             on_get_res(line)
119             line = res.readline()
120
121         res.close()
122
123         if maybe_incomplete:
124             lastmod = None
125             etag = None
126         else:
127             if "Last-Modified" in headers:
128                 lastmod = headers["Last-Modified"]
129             if "ETag" in headers:
130                 etag = headers["Etag"]
131
132         if self.num > 0:
133             if not self.title:
134                 self.title = datfile.get_title_from_dat(
135                     self.bbs, self.board, self.thread)
136                 if self.title:
137                     self.window.set_title(self.title)
138             # save idx
139             idx_dic = {"title": self.title, "lineCount": self.num,
140                    "lastModified": lastmod, "etag": etag}
141             idxfile.save_idx(self.bbs, self.board, self.thread, idx_dic)
142
143     def update(self, widget=None):
144         line_count = datfile.get_dat_line_count(
145             self.bbs, self.board, self.thread)
146
147         if line_count > self.num:
148             datfile.load_dat_partly(
149                 self.bbs, self.board, self.thread,
150                 self.append_rawres_to_buffer, self.num+1)
151
152         dat_path = misc.get_thread_dat_path(self.bbs, self.board, self.thread)
153         dat_file = file(dat_path, "a+")
154
155         def save_line_and_append_to_buffer(line):
156             dat_file.seek(self.size)
157             dat_file.write(line)
158             self.append_rawres_to_buffer(line)
159
160         self.http_get_dat(save_line_and_append_to_buffer)
161         dat_file.close()
162
163     def load_dat(self):
164         self.size = 0
165         self.num = 0
166
167         self.title = datfile.get_title_from_dat(
168             self.bbs, self.board, self.thread)
169         if self.title:
170             self.window.set_title(self.title)
171
172         datfile.load_dat(self.bbs, self.board, self.thread,
173                          self.append_rawres_to_buffer)
174         self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0)
175
176
177     def append_rawres_to_buffer(self, line):
178         self.size += len(line)
179         self.num += 1
180
181         h = lambda name,mail,date,msg: self.reselems_to_buffer(
182             self.num, name, mail, date, msg)
183
184         datfile.split_line_to_elems(line.decode("cp932", "replace"), h)
185         
186     def reselems_to_buffer(self, num, name, mail, date, msg):
187         # number
188         self.textbuffer.insert(self.enditer, str(num) + " ")
189
190         # name
191         p = barehtmlparser.BareHTMLParser(self.untiedata_to_buffer)
192         p.feed("<b>" + name + "</b>")
193         p.close()
194
195         # mail
196         self.textbuffer.insert(self.enditer, "[" + mail + "]")
197
198         # date
199         p.feed(date)
200         p.close()
201         self.textbuffer.insert(self.enditer, "\n")
202
203         # msg
204         p.reset_func(self.untiedata_to_buffer_with_leftmargin)
205         p.feed(msg)
206         p.close()
207
208         self.textbuffer.insert(self.enditer, "\n\n")
209
210     def untiedata_to_buffer(self, data, bold, href):
211         if bold:
212             self.textbuffer.insert_with_tags(self.enditer, data, self.boldtag)
213         else:
214             self.textbuffer.insert(self.enditer, data)
215
216     def untiedata_to_buffer_with_leftmargin(self, data, bold, href):
217         if bold:
218             self.textbuffer.insert_with_tags(self.enditer, data,
219                                              self.boldtag, self.leftmargintag)
220         else:
221             self.textbuffer.insert_with_tags(self.enditer, data,
222                                              self.leftmargintag)