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 / board_window.py
index dcd4136..a6ff35c 100644 (file)
@@ -21,129 +21,75 @@ import gtk
 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,
@@ -153,15 +99,61 @@ class WinWrap:
                   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()
@@ -170,17 +162,39 @@ class WinWrap:
         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:
@@ -195,21 +209,51 @@ class WinWrap:
                 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