OSDN Git Service

Add filterbar.
[fukui-no-namari/fukui-no-namari.git] / src / FukuiNoNamari / board_window.py
index af0b6bb..1647a9a 100644 (file)
@@ -23,6 +23,7 @@ import os
 import time
 import gobject
 import gconf
+import traceback
 
 import board_data
 import uri_opener
@@ -31,6 +32,8 @@ from threadlistmodel import ThreadListModel
 from BbsType import bbs_type_judge_uri
 import config
 import session
+import winwrapbase
+from misc import ThreadInvoker
 
 GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                          "..", "data")
@@ -48,15 +51,15 @@ def open_board(uri, update=False):
             winwrap.load(update)
     else:
         winwrap = WinWrap(uri)
-        session.window_created(uri, winwrap)
         winwrap.load(update)
 
 
-class WinWrap:
+class WinWrap(winwrapbase.WinWrapBase, board_data.BoardData):
 
     def __init__(self, uri):
 
         self.bbs_type = bbs_type_judge_uri.get_type(uri)
+        board_data.BoardData.__init__(self, self.bbs_type)
         self.bbs = self.bbs_type.bbs_type
         self.host = self.bbs_type.host
         self.board = self.bbs_type.board
@@ -76,6 +79,8 @@ class WinWrap:
         self.toolbar = self.widget_tree.get_widget("toolbar")
         self.toolbar.unset_style()
         self.statusbar = self.widget_tree.get_widget("appbar")
+        self.filterbar = self.widget_tree.get_widget("bonobodockitem_filterbar")
+        self.entry_filterbar = self.widget_tree.get_widget("entry_filterbar")
 
         renderer = gtk.CellRendererText()
 
@@ -91,11 +96,18 @@ class WinWrap:
                 renderer, self.on_cell_data, column_name)
             self.treeviewcolumn[column_name].connect(
                 "clicked", self.on_column_clicked, column_name)
+            self.treeviewcolumn[column_name].set_sizing(
+                gtk.TREE_VIEW_COLUMN_FIXED)
+            self.treeviewcolumn[column_name].set_min_width(20)
+            self.treeviewcolumn[column_name].set_fixed_width(
+                ThreadListModel.column_width[i])
             self.treeview.append_column(self.treeviewcolumn[column_name])
 
         self.treeviewcolumn["lastModified"].set_cell_data_func(
             renderer, self.on_data_lastmodified)
 
+        self.treeview.set_fixed_height_mode(True)
+
         sigdic = {"on_board_window_destroy": self.on_board_window_destroy,
                   "on_quit_activate": self.on_quit_activate,
                   "on_refresh_activate": self.on_refresh_activate,
@@ -109,41 +121,65 @@ class WinWrap:
                   "on_statusbar_activate": self.on_statusbar_activate,
                   "on_board_window_delete_event":
                   self.on_board_window_delete_event,
+                  "on_entry_filterbar_activate": self.on_entry_filterbar_activate,
+                  "on_filter_activate": self.on_filter_activate,
+                  "on_toolbutton_filterbar_close_clicked":
+                  self.on_toolbutton_filterbar_close_clicked,
                   "on_popup_menu_open_activate": self.on_open_thread}
         self.widget_tree.signal_autoconnect(sigdic)
 
-        self.gconf_client = gconf.client_get_default()
-        self.gconf_key_base = "/apps/" + config.APPNAME.lower() + \
-                              "/board_states/"
+        self.restore()
+        self.window.show()
 
-        width = self.gconf_client.get_int(
-            self.gconf_key_base + "window_width")
-        height = self.gconf_client.get_int(
-            self.gconf_key_base + "window_height")
-        self.window.set_default_size(width, height)
+        self.created()
 
-        self.window.show()
+    def set_status(self, text):
+        self.statusbar.set_status(text)
 
-        if not self.gconf_client.get_bool(self.gconf_key_base + "toolbar"):
-            self.toolbar.parent.hide()
-        if not self.gconf_client.get_bool(self.gconf_key_base + "statusbar"):
-            self.statusbar.hide()
+    def destroy(self):
+        self.save()
+        self.window.destroy()
+
+    def get_uri(self):
+        return self.bbs_type.get_uri_base()
 
     def on_toolbar_activate(self, widget):
         if self.toolbar.parent.get_property("visible"):
             self.toolbar.parent.hide()
-            self.gconf_client.set_bool(self.gconf_key_base + "toolbar", False)
         else:
             self.toolbar.parent.show()
-            self.gconf_client.set_bool(self.gconf_key_base + "toolbar", True)
 
     def on_statusbar_activate(self, widget):
         if self.statusbar.get_property("visible"):
             self.statusbar.hide()
-            self.gconf_client.set_bool(self.gconf_key_base+"statusbar", False)
         else:
             self.statusbar.show()
-            self.gconf_client.set_bool(self.gconf_key_base + "statusbar", True)
+
+    def on_filter_activate(self, widget):
+        self.filterbar.show()
+        self.entry_filterbar.grab_focus()
+
+    def on_entry_filterbar_activate(self, widget):
+        text = widget.get_text()
+
+        def func(model, item):
+            try:
+                item["title"].index(text)
+            except ValueError:
+                return False
+            else:
+                return True
+
+        model = self.treeview.get_model()
+        if model:
+            if text:
+                model.set_filter_func(func)
+            else:
+                model.set_filter_func(None)
+            model.refilter()
+
+    def on_toolbutton_filterbar_close_clicked(self, widget):
+        self.filterbar.hide()
 
     def updated_thread_highlight(self, column, cell, model, iter):
 
@@ -163,7 +199,8 @@ class WinWrap:
         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 model.get_column_type(column_num) \
+           in (gobject.TYPE_INT, gobject.TYPE_DOUBLE):
             if value == 0:
                 cell.set_property("text", "")
             else:
@@ -182,26 +219,20 @@ class WinWrap:
                 "%Y/%m/%d(%a) %H:%M:%S", time.localtime(lastmod)))
 
     def on_board_window_delete_event(self, widget, event):
-        w, h = widget.get_size()
-        self.gconf_client.set_int(self.gconf_key_base + "window_width", w)
-        self.gconf_client.set_int(self.gconf_key_base + "window_height", h)
-
+        self.save()
         return False
 
     def on_board_window_destroy(self, widget):
-        pass
+        self.destroyed()
 
     def on_quit_activate(self, widget):
         session.main_quit()
 
     def on_close_activate(self, widget):
-        self.window.destroy()
+        self.destroy()
 
     def on_refresh_activate(self, widget):
-        t = board_data.GetRemote(
-            self.bbs, self.board, self.bbs_type.get_subject_txt_uri(),
-            self.update_datastore)
-        t.start()
+        self.load(True)
 
     def on_column_clicked(self, treeviewcolumn, column_name):
         model = self.treeview.get_model()
@@ -257,33 +288,13 @@ class WinWrap:
                 self.popupmenu.popup(None, None, None, event.button, time)
             return 1
 
-    def update_datastore(self, datalist, lastmod):
+    def update_datastore(self, datalist):
         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():
             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:
@@ -291,7 +302,7 @@ class WinWrap:
                 dic["lastModified"] = secs
             except ValueError:
                 dic["lastModified"] = 0
-            
+
             list_list.append(dic)
 
         model = self.treeview.get_model()
@@ -303,8 +314,6 @@ class WinWrap:
         self.reset_sort_indicator()
 
         print "end"
-        time_end = time.time()
-        print time_end - time_start
 
     def on_thread_idx_updated(self, thread_uri, idx_dic):
         if not thread_uri or not idx_dic:
@@ -329,16 +338,170 @@ class WinWrap:
             model.modify_row(idx_dic)
 
     def load(self, update=False):
+
+        def load_local():
+            datalist = self.load_idxfiles()
+            self.merge_local_subjecttxt(datalist)
+            gobject.idle_add(self.update_datastore, datalist)
+
+        def get_remote():
+            print "start get subject.txt"
+            datalist = self.load_idxfiles()
+            self.merge_remote_subjecttxt(datalist)
+            gobject.idle_add(self.update_datastore, datalist)
+
         sbj_path = misc.get_board_subjecttxt_path(
             self.bbs_type.bbs_type, self.bbs_type.board)
         sbj_exists = os.path.exists(sbj_path)
 
         if update or not sbj_exists:
-            t = board_data.GetRemote(
-                self.bbs, self.board, self.bbs_type.get_subject_txt_uri(),
-                self.update_datastore)
+            t = ThreadInvoker(lambda *args: -1, get_remote)
             t.start()
         else:
-            t = board_data.LoadLocal(
-                self.bbs, self.board, self.update_datastore)
+            t = ThreadInvoker(lambda *args: -1, load_local)
             t.start()
+
+    def save(self):
+        try:
+            states_path = misc.get_board_states_path(
+                self.bbs_type.bbs_type, self.bbs_type.board)
+            dirname = os.path.dirname(states_path)
+
+            # save only if board dir exists.
+            if os.path.exists(dirname):
+                window_width, window_height = self.window.get_size()
+                toolbar_visible = self.toolbar.parent.get_property("visible")
+                statusbar_visible = self.statusbar.get_property("visible")
+                filterbar_visible = self.filterbar.get_property("visible")
+
+                columns = self.treeview.get_columns()
+                order = ""
+                width = ""
+                for column in columns:
+                    for name, kolumn in self.treeviewcolumn.iteritems():
+                        if column == kolumn:
+                            if order:
+                                order += ","
+                            order += name
+                            if width:
+                                width += ","
+                            width += str(column.get_width())
+                            break
+                sort_column_name, sort_reverse = \
+                                  self.treeview.get_model().get_sort()
+                sort_reverse = str(sort_reverse)
+
+                f = file(states_path, "w")
+
+                f.write("columns=" + order + "\n")
+                f.write("widths=" + width + "\n")
+                f.write("sort_column=" + sort_column_name + "\n")
+                f.write("sort_reverse=" + sort_reverse + "\n")
+                f.write("window_width=" + str(window_width) + "\n")
+                f.write("window_height=" + str(window_height) + "\n")
+                f.write("toolbar_visible=" + str(toolbar_visible) + "\n")
+                f.write("statusbar_visible=" + str(statusbar_visible) + "\n")
+                f.write("filterbar_visible=" + str(filterbar_visible) + "\n")
+
+                f.close()
+        except:
+            traceback.print_exc()
+
+    def restore(self):
+        try:
+            window_height = 600
+            window_width = 600
+            toolbar_visible = True
+            statusbar_visible = True
+            filterbar_visible = False
+
+            try:
+                key_base = config.gconf_app_key_base() + "/board_states"
+                gconf_client = gconf.client_get_default()
+                width = gconf_client.get_int(key_base + "/window_width")
+                height = gconf_client.get_int(key_base + "/window_height")
+                toolbar_visible = gconf_client.get_bool(key_base + "/toolbar")
+                statusbar_visible = gconf_client.get_bool(key_base + "/statusbar")
+                filterbar_visible = gconf_client.get_bool(key_base + "/filterbar")
+
+                if width != 0:
+                    window_width = width
+                if height != 0:
+                    window_height = height
+            except:
+                traceback.print_exc()
+
+            states_path = misc.get_board_states_path(
+                self.bbs_type.bbs_type, self.bbs_type.board)
+            if os.path.exists(states_path):
+                sort_column_name = "num"
+                sort_reverse = False
+                for line in file(states_path):
+                    if line.startswith("columns="):
+                        line = line[len("columns="):].rstrip("\n")
+                        base_column = None
+                        for name in line.split(","):
+                            if name in self.treeviewcolumn:
+                                column = self.treeviewcolumn[name]
+                                self.treeview.move_column_after(
+                                    column, base_column)
+                                base_column = column
+                    elif line.startswith("widths="):
+                        line = line[len("widths="):].rstrip("\n")
+                        columns = self.treeview.get_columns()
+                        for i, width in enumerate(line.split(",")):
+                            try:
+                                width = int(width)
+                            except:
+                                pass
+                            else:
+                                if i < len(columns):
+                                    columns[i].set_fixed_width(width)
+                    elif line.startswith("sort_column="):
+                        kolumn_name = line[len("sort_column="):].rstrip("\n")
+                        if kolumn_name in ThreadListModel.column_names:
+                            sort_column_name = kolumn_name
+                    elif line.startswith("sort_reverse="):
+                        reverse = line[len("sort_reverse="):].rstrip("\n")
+                        sort_reverse = reverse == "True"
+                    elif line.startswith("window_height="):
+                        height = window_height
+                        try:
+                            height = int(
+                                line[len("window_height="):].rstrip("\n"))
+                        except:
+                            pass
+                        else:
+                            window_height = height
+                    elif line.startswith("window_width="):
+                        width = window_width
+                        try:
+                            width = int(
+                                line[len("window_width="):].rstrip("\n"))
+                        except:
+                            pass
+                        else:
+                            window_width = width
+                    elif line.startswith("toolbar_visible="):
+                        tbar = line[len("toolbar_visible="):].rstrip("\n")
+                        toolbar_visible = tbar == "True"
+                    elif line.startswith("statusbar_visible="):
+                        sbar = line[len("statusbar_visible="):].rstrip("\n")
+                        statusbar_visible = sbar == "True"
+                    elif line.startswith("filterbar_visible="):
+                        fbar = line[len("filterbar_visible="):].rstrip("\n")
+                        filterbar_visible = fbar == "True"
+
+                self.treeview.get_model().sort(
+                    sort_column_name, True, sort_reverse)
+
+            self.window.set_default_size(window_width, window_height)
+
+            if not toolbar_visible:
+                gobject.idle_add(self.toolbar.parent.hide)
+            if not statusbar_visible:
+                gobject.idle_add(self.statusbar.hide)
+            if not filterbar_visible:
+                gobject.idle_add(self.filterbar.hide)
+        except:
+            traceback.print_exc()