import gtk.glade
import os
import time
+import gobject
import board_data
import thread_window
+import misc
+from threadlistmodel import ThreadListModel
+
+import windowlist
+import brdlist_window
+import brdlist
GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"..", "data")
GLADE_FILENAME = "board_window.glade"
-LIST_ID = 0
-LIST_NUM = 1
-LIST_TITLE = 2
-LIST_RES = 3
-LIST_LINECOUNT = 4
-LIST_LASTMODIFIED = 5
+def open_board(bbs, board):
+ if not bbs:
+ raise ValueError, "parameter must not be empty"
+
+ key = "/" + bbs + "/" + board
+ window = windowlist.get_window(key)
+ if window:
+ # already opened
+ window.present()
+ pass
+ else:
+ win_wrap = WinWrap(bbs, board)
+ widget = win_wrap.widget_tree.get_widget("board_window")
+ windowlist.window_created(key, widget)
class WinWrap:
- def sort_column(self, model, iter1, iter2, key):
- v1 = model.get_value(iter1, 1)[key]
- v2 = model.get_value(iter2, 1)[key]
- if v1 < v2:
- return -1
- elif v1 > v2:
- return 1
- else:
- return 0
-
- def sort_column_num(self, model, iter1, iter2, key):
- column_id, order = model.get_sort_column_id()
- v1 = model.get_value(iter1, 1)[key]
- v2 = model.get_value(iter2, 1)[key]
- return self.sort_column_int(v1, v2, order)
-
- def sort_column_int(self, v1, v2, order):
- if order == gtk.SORT_ASCENDING:
- if v1 == board_data.BOARD_DATA_INVALID_VALUE \
- and v2 == board_data.BOARD_DATA_INVALID_VALUE:
- return 0
- elif v1 == board_data.BOARD_DATA_INVALID_VALUE:
- return 1
- elif v2 == board_data.BOARD_DATA_INVALID_VALUE:
- return -1
-
- if v1 < v2:
- return -1
- elif v1 > v2:
- return 1
- else:
- return 0
def __init__(self, bbs, board):
self.bbs = bbs
self.board = board
glade_path = os.path.join(GLADE_DIR, GLADE_FILENAME)
- self.mainwin = gtk.glade.XML(glade_path)
-
- # id, num, title, res, lineCount, lastModified
- self.datastore = gtk.ListStore(str, object)
- self.datastore.set_sort_func(1000, lambda *args: -1)
- self.datastore.set_sort_func(LIST_NUM+100, self.sort_column_num,
- "num")
- self.datastore.set_sort_func(LIST_TITLE+100, self.sort_column,
- "title")
- self.datastore.set_sort_func(LIST_RES+100, self.sort_column_num,
- "res")
- self.datastore.set_sort_func(LIST_LINECOUNT+100, self.sort_column_num,
- "lineCount")
- self.datastore.set_sort_func(LIST_LASTMODIFIED+100, self.sort_column,
- "lastModified")
- self.treeview = self.mainwin.get_widget("treeview")
- self.treeview.set_rules_hint(True)
- self.treeview.set_model(self.datastore)
- self.popupmenu = self.mainwin.get_widget("popup_menu")
-
- def dict_cell_data_func(column, cell, model, iter, key):
- text = model.get_value(iter, 1)[key]
- cell.set_property("text", text)
-
- def dict_cell_data_func_int(column, cell, model, iter, key):
- integer = model.get_value(iter, 1)[key]
- if integer > 0:
- cell.set_property("text", str(integer))
- else:
- cell.set_property("text", "")
+ self.widget_tree = gtk.glade.XML(glade_path)
+
+ self.window = self.widget_tree.get_widget("board_window")
+
+ title = brdlist.get(bbs, board, "name")
+ if title:
+ self.window.set_title(title)
+
+ self.treeview = self.widget_tree.get_widget("treeview")
+ self.treeview.set_model(ThreadListModel())
+
+ self.popupmenu = self.widget_tree.get_widget("popup_menu")
renderer = gtk.CellRendererText()
- column = gtk.TreeViewColumn("num", renderer)
- column.set_cell_data_func(renderer, dict_cell_data_func_int, "num")
- column.set_sort_column_id(LIST_NUM+100)
- column.set_resizable(True)
- column.set_reorderable(True)
- self.treeview.append_column(column)
-
- column = gtk.TreeViewColumn("title", renderer)
- column.set_cell_data_func(renderer, dict_cell_data_func, "title")
- column.set_sort_column_id(LIST_TITLE+100)
- column.set_resizable(True)
- column.set_reorderable(True)
- self.treeview.append_column(column)
-
- column = gtk.TreeViewColumn("res", renderer)
- column.set_cell_data_func(renderer, dict_cell_data_func_int, "res")
- column.set_sort_column_id(LIST_RES+100)
- column.set_resizable(True)
- column.set_reorderable(True)
- self.treeview.append_column(column)
-
- column = gtk.TreeViewColumn("read", renderer)
- column.set_cell_data_func(renderer, dict_cell_data_func_int,
- "lineCount")
- column.set_sort_column_id(LIST_LINECOUNT+100)
- column.set_resizable(True)
- column.set_reorderable(True)
- self.treeview.append_column(column)
-
- column = gtk.TreeViewColumn("lastModified", renderer)
- column.set_cell_data_func(renderer, dict_cell_data_func, "lastModified")
- column.set_sort_column_id(LIST_LASTMODIFIED+100)
- column.set_resizable(True)
- column.set_reorderable(True)
- self.treeview.append_column(column)
+ self.treeviewcolumn = {}
+ for i in range(1, len(ThreadListModel.column_names)):
+ column_name = ThreadListModel.column_names[i]
+ self.treeviewcolumn[column_name] = gtk.TreeViewColumn(
+ column_name, renderer)
+ self.treeviewcolumn[column_name].set_resizable(True)
+ self.treeviewcolumn[column_name].set_reorderable(True)
+ self.treeviewcolumn[column_name].set_clickable(True)
+ self.treeviewcolumn[column_name].set_cell_data_func(
+ renderer, self.on_cell_data, column_name)
+ self.treeviewcolumn[column_name].connect(
+ "clicked", self.on_column_clicked, column_name)
+ self.treeview.append_column(self.treeviewcolumn[column_name])
+
+ self.treeviewcolumn["lastModified"].set_cell_data_func(
+ renderer, self.on_data_lastmodified)
sigdic = {"on_board_window_destroy": self.on_board_window_destroy,
"on_quit_activate": self.on_quit_activate,
lambda w,p,v: self.on_open_thread(w),
"on_treeview_button_press_event":
self.on_treeview_button_press_event,
+ "on_close_activate":
+ self.on_close_activate,
+ "on_show_board_list_activate":
+ self.on_show_board_list_activate,
"on_popup_menu_open_activate": self.on_open_thread}
- self.mainwin.signal_autoconnect(sigdic)
+ self.widget_tree.signal_autoconnect(sigdic)
+
+ def updated_thread_highlight(self, column, cell, model, iter):
+
+ def is_updated_thread():
+ res = model.get_value(
+ iter, ThreadListModel.column_names.index("res"))
+ linecount = model.get_value(
+ iter, ThreadListModel.column_names.index("lineCount"))
+ return res != 0 and linecount != 0 and res > linecount
+
+ if is_updated_thread():
+ cell.set_property("weight", 800)
+ else:
+ cell.set_property("weight", 400)
+
+ def on_cell_data(self, column, cell, model, iter, column_name):
+ self.updated_thread_highlight(column, cell, model, iter)
+ column_num = ThreadListModel.column_names.index(column_name)
+ value = model.get_value(iter, column_num)
+ if model.get_column_type(column_num) == gobject.TYPE_INT:
+ if value == 0:
+ cell.set_property("text", "")
+ else:
+ cell.set_property("text", str(value))
+ else:
+ cell.set_property("text", value)
+
+ def on_data_lastmodified(self, column, cell, model, iter, user_data=None):
+ self.updated_thread_highlight(column, cell, model, iter)
+ lastmod = model.get_value(
+ iter, ThreadListModel.column_names.index("lastModified"))
+ if lastmod == 0:
+ cell.set_property("text", "")
+ else:
+ cell.set_property("text", time.strftime(
+ "%Y/%m/%d(%a) %H:%M:%S", time.localtime(lastmod)))
def on_board_window_destroy(self, widget):
- gtk.main_quit()
+ pass
def on_quit_activate(self, widget):
gtk.main_quit()
+ def on_close_activate(self, widget):
+ self.window.destroy()
+
+ def on_show_board_list_activate(self, widget):
+ brdlist_window.open_brdlist(self.bbs)
+
def on_load_local_activate(self, widget):
t = board_data.LoadLocal(self.bbs, self.board, self.update_datastore)
t.start()
t = board_data.GetRemote(self.bbs, self.board, self.update_datastore)
t.start()
+ def on_column_clicked(self, treeviewcolumn, column_name):
+ model = self.treeview.get_model()
+ if model:
+ model.sort(column_name)
+ self.reset_sort_indicator()
+
+ def reset_sort_indicator(self):
+ model = self.treeview.get_model()
+ if model:
+ sort_column_name, sort_reverse = model.get_sort()
+ for name,column in self.treeviewcolumn.iteritems():
+ column.set_sort_indicator(False)
+ if sort_column_name != "num" or sort_reverse:
+ self.treeviewcolumn[sort_column_name].set_sort_indicator(True)
+ if sort_reverse:
+ self.treeviewcolumn[sort_column_name].set_sort_order(
+ gtk.SORT_DESCENDING)
+ else:
+ self.treeviewcolumn[sort_column_name].set_sort_order(
+ gtk.SORT_ASCENDING)
+
def on_open_thread(self, widget):
treeselection = self.treeview.get_selection()
model, iter = treeselection.get_selected()
if not iter:
return
- thread = model.get_value(iter, 0)
- title = model.get_value(iter, 1)["title"]
+ thread = model.get_value(iter, ThreadListModel.column_names.index("id"))
+ title = model.get_value(
+ iter, ThreadListModel.column_names.index("title"))
print thread + ':"' + title + '"', "activated"
- thread_window.WinWrap(self.bbs, self.board, thread)
+ thread_window.open_thread(self.bbs, self.board, thread)
def on_treeview_button_press_event(self, widget, event):
if event.button == 3:
self.popupmenu.popup(None, None, None, event.button, time)
return 1
- def update_datastore(self, datalist):
- print "clear datastore"
- self.datastore.clear()
- column_id, order = self.datastore.get_sort_column_id()
- self.datastore.set_sort_column_id(1000, gtk.SORT_ASCENDING)
+ def update_datastore(self, datalist, lastmod):
print "reflesh datastore"
+ try:
+ lastmod = misc.httpdate_to_secs(lastmod)
+ except:
+ lastmod = 0
+
time_start = time.time()
+ list_list = []
for id, dic in datalist.iteritems():
- self.datastore.append([id, dic])
+ dic["id"] = id
+
+ # average
+ if lastmod == 0 or dic["num"] == 0:
+ dic["average"] = 0
+ else:
+ res = dic["res"]
+ start = int(id)
+ # avoid the Last-Modified time of subject.txt and
+ # the build time of thread is equal (zero division)
+ dur = lastmod - start
+ if dur == 0:
+ dic["average"] = 999999
+ else:
+ dic["average"] = int(res * 60 * 60 * 24 / dur)
+
+ # lastModified
+ httpdate = dic["lastModified"]
+ try:
+ secs = misc.httpdate_to_secs(httpdate)
+ dic["lastModified"] = secs
+ except ValueError:
+ dic["lastModified"] = 0
+
+ list_list.append(dic)
+
+ model = self.treeview.get_model()
+ model.set_list(list_list)
+
+ # redraw visible area after set list to model
+ self.treeview.queue_draw()
+
+ self.reset_sort_indicator()
- if column_id is not None and order is not None:
- self.datastore.set_sort_column_id(column_id, order)
- else:
- self.datastore.set_sort_column_id(LIST_NUM+100, gtk.SORT_ASCENDING)
print "end"
time_end = time.time()
print time_end - time_start