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>
24 assert gtk
.pygtk_version
>= (2, 8)
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
):
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_paths
= set()
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
)
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
):
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
):
96 self
.invalidate_tree()
97 history
.add_entry(tree
)
98 self
.emit('building-tree-state-changed', not tree
)
100 if self
.options
.min_size
== 'auto':
101 height
= self
.get_parent().allocation
.height
- 2
103 height
= int(self
._get
_requested
_height
())
104 self
.set_size_request(-1, height
)
106 def refresh_tree(self
):
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
):
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()
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())