If the size changed, instead of rescheduling the building in the UI, let
[pysize.git] / pysize / ui / gtk / pysize_widget.py
blobfa216fd09455be10e35bd38f3e47aa4138d70189
1 # This program is free software; you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation; either version 2 of the License, or
4 # (at your option) any later version.
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU Library General Public License for more details.
11 # You should have received a copy of the GNU General Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 # See the COPYING file for license information.
17 # Copyright (c) 2006 Guillaume Chazarain <guichaz@yahoo.fr>
19 import os
21 import pygtk
22 pygtk.require('2.0')
23 import gtk
24 assert gtk.pygtk_version >= (2, 8)
25 import gobject
27 from pysize.core.pysize_global_fs_cache import drop_caches
28 from pysize.core.pysize_fs_tree import pysize_tree
29 from pysize.core import history
30 from pysize.ui.utils import min_size_to_consider
31 from pysize.ui.gtk.threaded_pysize_tree import threaded_pysize_tree
33 from pysize.ui.gtk.pysize_widget_draw import PysizeWidget_Draw
34 from pysize.ui.gtk.pysize_widget_menu import PysizeWidget_Menu
35 from pysize.ui.gtk.pysize_widget_mouse import PysizeWidget_Mouse
38 class PysizeWidget(gtk.DrawingArea, PysizeWidget_Draw,
39 PysizeWidget_Menu, PysizeWidget_Mouse):
40 __gsignals__ = {
41 'hover-changed':
42 (gobject.SIGNAL_RUN_LAST,
43 gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
44 'building-tree-state-changed':
45 (gobject.SIGNAL_RUN_LAST,
46 gobject.TYPE_NONE, (gobject.TYPE_BOOLEAN,))
49 def __init__(self, options, args):
50 gtk.DrawingArea.__init__(self)
51 PysizeWidget_Draw.__init__(self, options, args)
52 PysizeWidget_Menu.__init__(self, options, args)
53 PysizeWidget_Mouse.__init__(self, options, args)
54 self.connect('realize', type(self)._realize)
55 self.connect('key-press-event', type(self)._key_press)
56 self.connect('configure-event', type(self)._configure)
57 self.set_flags(gtk.CAN_FOCUS)
58 self.options = options
59 self.selected_nodes = []
60 self.paths = args
61 self.tree = pysize_tree([], 0, 0, self.options)
62 self.tree_builder = threaded_pysize_tree()
63 self.tree_builder.completion.add_observer(self._new_tree_callback)
65 def _realize(self):
66 events = self.window.get_events()
67 events |= gtk.gdk.POINTER_MOTION_MASK
68 events |= gtk.gdk.POINTER_MOTION_HINT_MASK
69 events |= gtk.gdk.KEY_PRESS_MASK
70 events |= gtk.gdk.BUTTON_PRESS_MASK
71 events |= gtk.gdk.BUTTON_RELEASE_MASK
72 self.window.set_events(events)
74 def _key_press(self, event):
75 directions = {
76 gtk.keysyms.Left: self.tree.get_parent,
77 gtk.keysyms.Up: self.tree.get_previous_sibling,
78 gtk.keysyms.Right: self.tree.get_first_child,
79 gtk.keysyms.Down: self.tree.get_next_sibling
82 action = directions.get(event.keyval, None)
83 if action and self.cursor_node is not None:
84 new_selection = action(self.cursor_node)
85 if new_selection not in (None, self.tree.root):
86 self.queue_node_redraw(self.cursor_node)
87 self.queue_node_redraw(new_selection)
88 self.set_cursor_node(new_selection)
89 return action is not None
91 # Called when the threaded_pysize_tree built a new tree for us
92 def _new_tree_callback(self, tree):
93 if tree:
94 self.tree = tree
95 self.queue_draw()
96 self.invalidate_tree()
97 history.add_entry(tree)
98 self.emit('building-tree-state-changed', not tree)
99 if tree:
100 if self.options.min_size == 'auto':
101 height = self.get_parent().allocation.height - 2
102 else:
103 height = int(self._get_requested_height())
104 self.set_size_request(-1, height)
106 def refresh_tree(self):
107 drop_caches()
108 self.schedule_new_tree()
110 def min_size_requested(self):
111 return min_size_to_consider(self.options.min_size,
112 self.max_number_of_nodes())
114 def set_paths(self, paths):
115 if paths:
116 self.paths = paths
117 self.schedule_new_tree()
119 def schedule_new_tree(self):
120 self.tree_builder.schedule(self.paths, self.options.max_depth,
121 self.min_size_requested(), self.options)
123 def _configure(self, event):
124 if self.options.min_size == 'auto':
125 self.schedule_new_tree()
127 def invalidate_tree(self):
128 self.emit('hover-changed', None)
130 def parent_directory(self):
131 self.set_paths([self.tree.root.get_dirname()])
133 def max_depth_changed(self, spin):
134 value = spin.get_value()
135 self.options.max_depth = value
136 self.schedule_new_tree()
138 def open(self):
139 action = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER
140 buttons = gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, \
141 gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT
142 dialog = gtk.FileChooserDialog(title='Select a directory',
143 action=action, buttons=buttons)
144 dialog.set_select_multiple(True)
145 response = dialog.run()
146 if response == gtk.RESPONSE_ACCEPT:
147 self.set_paths(dialog.get_filenames())
148 dialog.destroy()