vimmate 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +10 -0
- data/CHANGELOG +108 -0
- data/COPYING +20 -0
- data/README +221 -0
- data/Rakefile +31 -0
- data/TODO +21 -0
- data/bin/vimmate +105 -0
- data/config/environment.rb +35 -0
- data/controllers/file_filter_controller.rb +101 -0
- data/controllers/file_popup_menu_controller.rb +40 -0
- data/controllers/vim_controller.rb +28 -0
- data/controllers/vim_mate_controller.rb +76 -0
- data/images/file.png +0 -0
- data/images/file_green.png +0 -0
- data/images/file_orange.png +0 -0
- data/images/file_red.png +0 -0
- data/images/folder.png +0 -0
- data/images/folder_green.png +0 -0
- data/images/folder_orange.png +0 -0
- data/images/folder_red.png +0 -0
- data/images/processing.png +0 -0
- data/images/svn_added.png +0 -0
- data/images/svn_conflict.png +0 -0
- data/images/svn_deleted.png +0 -0
- data/images/svn_locked.png +0 -0
- data/images/svn_modified.png +0 -0
- data/images/svn_normal.png +0 -0
- data/images/svn_readonly.png +0 -0
- data/images/vimmate16.png +0 -0
- data/images/vimmate32.png +0 -0
- data/images/vimmate48.png +0 -0
- data/lib/active_window/active_column.rb +218 -0
- data/lib/active_window/active_tree_store/columns.rb +88 -0
- data/lib/active_window/active_tree_store/extentions.rb +81 -0
- data/lib/active_window/active_tree_store/index.rb +53 -0
- data/lib/active_window/active_tree_store.rb +26 -0
- data/lib/active_window/application.rb +137 -0
- data/lib/active_window/controller.rb +58 -0
- data/lib/active_window/dot_file.rb +29 -0
- data/lib/active_window/filtered_active_tree_store.rb +113 -0
- data/lib/active_window/listed_item.rb +127 -0
- data/lib/active_window/signal.rb +46 -0
- data/lib/active_window.rb +8 -0
- data/lib/config_window.rb +90 -0
- data/lib/file_tree_store.rb +74 -0
- data/lib/filtered_file_tree_store.rb +34 -0
- data/lib/gtk_thread_helper.rb +73 -0
- data/lib/listed_directory.rb +45 -0
- data/lib/listed_file.rb +67 -0
- data/lib/try.rb +9 -0
- data/lib/vim/buffers.rb +18 -0
- data/lib/vim/integration.rb +38 -0
- data/lib/vim/netbeans.rb +154 -0
- data/lib/vim/source.vim +18 -0
- data/lib/vim_mate/config.rb +132 -0
- data/lib/vim_mate/dummy_window.rb +14 -0
- data/lib/vim_mate/files_menu.rb +110 -0
- data/lib/vim_mate/icons.rb +156 -0
- data/lib/vim_mate/nice_singleton.rb +53 -0
- data/lib/vim_mate/plugins/inotify/init.rb +4 -0
- data/lib/vim_mate/plugins/inotify/lib/INotify.rb +208 -0
- data/lib/vim_mate/plugins/inotify/lib/directory.rb +58 -0
- data/lib/vim_mate/plugins/subversion/init.rb +7 -0
- data/lib/vim_mate/plugins/subversion/lib/file.rb +59 -0
- data/lib/vim_mate/plugins/subversion/lib/menu.rb +96 -0
- data/lib/vim_mate/plugins/subversion/lib/subversion.rb +157 -0
- data/lib/vim_mate/plugins.rb +6 -0
- data/lib/vim_mate/requirer.rb +68 -0
- data/lib/vim_mate/search_window.rb +227 -0
- data/lib/vim_mate/tags_window.rb +167 -0
- data/lib/vim_mate/terminals_window.rb +163 -0
- data/lib/vim_mate/version.rb +29 -0
- data/lib/vim_mate/vim_widget.rb +143 -0
- data/spec/active_window/active_column_spec.rb +41 -0
- data/spec/active_window/active_tree_store_spec.rb +312 -0
- data/spec/active_window/controller_spec.rb +6 -0
- data/spec/lib/file_tree_store_spec.rb +40 -0
- data/spec/lib/listed_directory_spec.rb +26 -0
- data/spec/lib/listed_file_spec.rb +53 -0
- data/spec/nice_singleton_spec.rb +23 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +10 -0
- data/views/vim_mate.glade +500 -0
- data/vimmate.gemspec +138 -0
- metadata +146 -0
@@ -0,0 +1,137 @@
|
|
1
|
+
class ActiveWindow::Application
|
2
|
+
include ActiveSupport::Callbacks
|
3
|
+
define_callbacks :after_initialize
|
4
|
+
|
5
|
+
attr_accessor :controller, :database, :glade, :window
|
6
|
+
|
7
|
+
def widget(name)
|
8
|
+
glade[name]
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@glade = GladeXML.new(find_glade, nil, options[:title] || 'application' )
|
13
|
+
@window = widget(options[:main_window] || 'main_window')
|
14
|
+
@window.signal_connect("destroy") { Gtk.main_quit }
|
15
|
+
@dot_file_prefs = DotFile.read
|
16
|
+
@database = options[:database]
|
17
|
+
define_widget_readers
|
18
|
+
run_callbacks :after_initialize
|
19
|
+
end
|
20
|
+
|
21
|
+
def start
|
22
|
+
setup
|
23
|
+
window.show
|
24
|
+
run
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
Gtk.main
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_database
|
32
|
+
@dot_file_prefs[:db]
|
33
|
+
end
|
34
|
+
|
35
|
+
def save_default_database(hash)
|
36
|
+
@dot_file_prefs[:db] = hash
|
37
|
+
@dot_file_prefs.save
|
38
|
+
end
|
39
|
+
|
40
|
+
# creates the controllers, connects the signals
|
41
|
+
# calls 'setup' on each controller
|
42
|
+
def setup
|
43
|
+
@controller = {}
|
44
|
+
|
45
|
+
Module.constants.grep(/.Controller$/).each do |klass|
|
46
|
+
ctrl = Kernel.const_get(klass).instance
|
47
|
+
ctrl.application = self
|
48
|
+
ctrl.setup
|
49
|
+
name = klass.to_s.sub('Controller','').underscore.to_sym # eg MyFirstController -> :my_first
|
50
|
+
controller[name] = ctrl
|
51
|
+
end
|
52
|
+
|
53
|
+
glade.signal_autoconnect_full do |source, target, signal, handler, data|
|
54
|
+
# for example:
|
55
|
+
# source : instance of Gtk::ImageMenuItem
|
56
|
+
# target : nil
|
57
|
+
# signal : activate, clicked, pressed, etc.
|
58
|
+
# handler : window.close, which would call WindowController.close()
|
59
|
+
# data : nil
|
60
|
+
#puts [source, target, signal, handler, data].inspect
|
61
|
+
source.signal_connect(signal) { |widget,event| self.dispatch(handler, :source => source, :target => target, :signal => signal, :handler => handler, :data => data, :widget => widget, :event => event) }
|
62
|
+
#source.signal_connect(signal) { self.(handler, data) }
|
63
|
+
end
|
64
|
+
post_setup
|
65
|
+
end
|
66
|
+
|
67
|
+
# calls post_setup on each controller
|
68
|
+
def post_setup
|
69
|
+
controller.each do |name,ctrl|
|
70
|
+
ctrl.post_setup
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
## dispatch a signal to the correct controller
|
76
|
+
##
|
77
|
+
def dispatch(handler, event)
|
78
|
+
controller_name,action = handler.to_s.split('.')
|
79
|
+
unless controller_name and action
|
80
|
+
return(error "cannot parse handler '%s'" % handler)
|
81
|
+
end
|
82
|
+
|
83
|
+
name = controller_name.to_sym
|
84
|
+
ctrl = controller[name]
|
85
|
+
unless ctrl
|
86
|
+
puts controller.inspect
|
87
|
+
return(error "no controller '%s' defined" % controller_name.camelize)
|
88
|
+
end
|
89
|
+
|
90
|
+
unless ctrl.respond_to? action
|
91
|
+
return(error "controller '%s' does not have a method '%s'" % [ctrl.class, action])
|
92
|
+
end
|
93
|
+
|
94
|
+
method = ctrl.method(action)
|
95
|
+
#puts "calling %s.%s" % [controller_name.camelize, action]
|
96
|
+
if method.arity == 0
|
97
|
+
method.call
|
98
|
+
else
|
99
|
+
method.call(event)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def class_exists?(classname)
|
107
|
+
return (Kernel::const_get(classname) rescue NameError) != NameError
|
108
|
+
end
|
109
|
+
|
110
|
+
def error(msg)
|
111
|
+
puts msg
|
112
|
+
end
|
113
|
+
|
114
|
+
def find_glade
|
115
|
+
Dir.glob("#{views_directory}/*.glade") do |f|
|
116
|
+
return f
|
117
|
+
end
|
118
|
+
raise "could not find a .glade file in #{views_directory}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def views_directory
|
122
|
+
File.join(APP_ROOT, 'views')
|
123
|
+
end
|
124
|
+
|
125
|
+
def define_widget_readers
|
126
|
+
glade.widget_names.each do |widget|
|
127
|
+
meth = widget.underscore
|
128
|
+
instance_eval <<-EOEVAL
|
129
|
+
@#{meth} = glade['#{widget}']
|
130
|
+
def #{meth}
|
131
|
+
@#{meth}
|
132
|
+
end
|
133
|
+
EOEVAL
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# require 'libglade2'
|
2
|
+
# require 'gtk2'
|
3
|
+
|
4
|
+
class ActiveWindow::Controller
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
attr_accessor :application
|
8
|
+
|
9
|
+
def app
|
10
|
+
application
|
11
|
+
end
|
12
|
+
|
13
|
+
def widget(name)
|
14
|
+
application.widget(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def controller
|
18
|
+
application.controller
|
19
|
+
end
|
20
|
+
|
21
|
+
def window
|
22
|
+
application.window
|
23
|
+
end
|
24
|
+
|
25
|
+
def database
|
26
|
+
application.database
|
27
|
+
end
|
28
|
+
|
29
|
+
# called on startup
|
30
|
+
def setup
|
31
|
+
end
|
32
|
+
|
33
|
+
# called on startup, after setup has been called for all controllers
|
34
|
+
def post_setup
|
35
|
+
end
|
36
|
+
|
37
|
+
def pref_set(key,value)
|
38
|
+
Preference.delete_all ['pref = ?', key]
|
39
|
+
Preference.create(:pref => key, :value => value)
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
def pref_get(key)
|
44
|
+
pref = Preference.find_by_pref(key)
|
45
|
+
return pref.value if pref
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def pref_get_or_set(key,value)
|
50
|
+
pref_get(key) || pref_set(key,value)
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(name, *args, &block)
|
54
|
+
application.send name, *args, &block
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
A simple class for reading and writing settings information
|
4
|
+
to a dot file (~/.appname.yml)
|
5
|
+
|
6
|
+
=end
|
7
|
+
|
8
|
+
module ActiveWindow
|
9
|
+
class DotFile < ::Hash
|
10
|
+
def self.read(fname=nil)
|
11
|
+
fname ||= filename
|
12
|
+
unless File.exists? fname
|
13
|
+
new.save(fname)
|
14
|
+
end
|
15
|
+
YAML.load_file( fname )
|
16
|
+
end
|
17
|
+
|
18
|
+
def save(fname=nil)
|
19
|
+
fname ||= self.class.filename
|
20
|
+
File.open( fname, 'w+' ) do |out|
|
21
|
+
YAML.dump( self, out )
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.filename
|
26
|
+
File.join ENV['HOME'], ".#{PROGRAM_NAME}.yml"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
# This creates a TreeModel which supports filtering. Please give a block that "returns" boolean
|
3
|
+
#
|
4
|
+
# filtered_model = ActiveTreeStoreFilter.new model do |filter_string, model, path, iter|
|
5
|
+
# !iter[23].index(filter_string).nil?
|
6
|
+
# end
|
7
|
+
class FilteredActiveTreeStore < Gtk::TreeModelFilter
|
8
|
+
include TreeStoreExtentions
|
9
|
+
|
10
|
+
attr_reader :filter_string, :found_count
|
11
|
+
attr_reader :unfiltered_store
|
12
|
+
define_callbacks :before_filter_applied, :after_filter_applied
|
13
|
+
define_callbacks :before_clear_filter, :after_clear_filter
|
14
|
+
|
15
|
+
def self.inherited(child_class)
|
16
|
+
unfiltered_class_name = child_class.name.sub(/^Filtered/,'')
|
17
|
+
unfiltered_class = unfiltered_class_name.constantize
|
18
|
+
child_class.columns = unfiltered_class.columns
|
19
|
+
child_class.column_id = unfiltered_class.column_id
|
20
|
+
child_class.setup_column_id_constants
|
21
|
+
unfiltered_class.class_eval <<-EOCODE
|
22
|
+
def add_with_filter_visibility(file, *args)
|
23
|
+
iter = add_without_filter_visibility(file, *args)
|
24
|
+
filtered_model.set_visibility_for(iter)
|
25
|
+
filtered_model.refilter unless initial_add_in_progress?
|
26
|
+
iter
|
27
|
+
end
|
28
|
+
alias_method_chain :add, :filter_visibility
|
29
|
+
attr_accessor :filtered_model
|
30
|
+
EOCODE
|
31
|
+
rescue NameError => e
|
32
|
+
if e.message =~ /uninitialized constant #{unfiltered_class}/
|
33
|
+
raise "there is no class named #{unfiltered_class} to filter from"
|
34
|
+
else
|
35
|
+
raise
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize(child_model)
|
40
|
+
super(child_model)
|
41
|
+
setup_filter
|
42
|
+
end
|
43
|
+
|
44
|
+
def filter_string=(new_filter_string)
|
45
|
+
if new_filter_string.empty?
|
46
|
+
clear_filter
|
47
|
+
else
|
48
|
+
@filter_string = new_filter_string
|
49
|
+
apply_filter
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def clear_filter
|
54
|
+
run_callbacks :before_clear_filter
|
55
|
+
@filter_string = ''
|
56
|
+
@found_count = -1
|
57
|
+
refilter
|
58
|
+
run_callbacks :after_clear_filter
|
59
|
+
end
|
60
|
+
|
61
|
+
# implement this to oyur own needs
|
62
|
+
def iter_visible?(iter)
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
# Iterate over child model and set visible column according to #iter_visible?
|
67
|
+
def apply_filter
|
68
|
+
run_callbacks :before_filter_applied
|
69
|
+
@found_count = 0
|
70
|
+
child_model.each do |model,path,iter|
|
71
|
+
set_visibility_for(iter)
|
72
|
+
end
|
73
|
+
refilter
|
74
|
+
run_callbacks :after_filter_applied
|
75
|
+
end
|
76
|
+
|
77
|
+
def filtered?
|
78
|
+
!filter_string.blank?
|
79
|
+
end
|
80
|
+
alias_method :filter, :filter_string
|
81
|
+
alias_method :filter=, :filter_string=
|
82
|
+
alias_method :filtering?, :filtered?
|
83
|
+
|
84
|
+
def set_visibility_for(iter)
|
85
|
+
visid = self.class.column_id[:visible]
|
86
|
+
unless filtering?
|
87
|
+
iter[ visid ] = true
|
88
|
+
else
|
89
|
+
if iter_visible?(iter) # iter matches - mark it and all parents as visible
|
90
|
+
@found_count += 1
|
91
|
+
iter[ visid ] = true
|
92
|
+
i = iter
|
93
|
+
while i = i.parent
|
94
|
+
i[ visid ] = true
|
95
|
+
end
|
96
|
+
else
|
97
|
+
iter[ visid ] = false
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def setup_filter
|
105
|
+
set_visible_func do |model, iter|
|
106
|
+
!filtered? || iter[ self.class.column_id[:visible] ]
|
107
|
+
end
|
108
|
+
child_model.filtered_model = self
|
109
|
+
clear_filter
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
# The ListItem is created on the fly
|
3
|
+
# * to oo-abstract methods to its TreeIter
|
4
|
+
# * for iteration in TreeController
|
5
|
+
# * as object in ActiveTreeStore
|
6
|
+
class ListedItem
|
7
|
+
|
8
|
+
def initialize(opts = {})
|
9
|
+
@traversed = false
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def sort
|
14
|
+
"item-#{iter}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def icon_name
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def icon
|
22
|
+
VimMate::Icons.by_name icon_name
|
23
|
+
end
|
24
|
+
|
25
|
+
# New by Gtk::TreeRowReference
|
26
|
+
def self.new_by_reference(reference)
|
27
|
+
new(:iter => reference.iter)
|
28
|
+
end
|
29
|
+
|
30
|
+
# New by Gtk::TreeIter
|
31
|
+
def self.new_by_iter(iter)
|
32
|
+
new(:iter => iter)
|
33
|
+
end
|
34
|
+
|
35
|
+
def message?
|
36
|
+
referenced_type == 'VimMate::Message'
|
37
|
+
end
|
38
|
+
|
39
|
+
def separator?
|
40
|
+
referenced_type == 'VimMate::Separator'
|
41
|
+
end
|
42
|
+
|
43
|
+
def file?
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
def directory?
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def file_or_directory?
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
def show!
|
56
|
+
self.visible = true
|
57
|
+
# TODO hide seperator
|
58
|
+
#if directory? and Config[:file_directory_separator]
|
59
|
+
# if iter.next!
|
60
|
+
# tree.row_for_iter(iter).show!
|
61
|
+
# end
|
62
|
+
#end
|
63
|
+
end
|
64
|
+
def hide!
|
65
|
+
self.visible = false
|
66
|
+
# TODO hide seperator
|
67
|
+
#if directory? and Config[:file_directory_separator]
|
68
|
+
# if iter.next!
|
69
|
+
# tree.row_for_iter(iter).hide!
|
70
|
+
# end
|
71
|
+
#end
|
72
|
+
end
|
73
|
+
|
74
|
+
def visible?
|
75
|
+
visible
|
76
|
+
end
|
77
|
+
|
78
|
+
def matches?(str)
|
79
|
+
name.index(str)
|
80
|
+
end
|
81
|
+
|
82
|
+
def refresh
|
83
|
+
end
|
84
|
+
|
85
|
+
def reference
|
86
|
+
@reference ||= Gtk::TreeRowReference.new(tree.store, iter.path)
|
87
|
+
end
|
88
|
+
|
89
|
+
def reference=(new_ref)
|
90
|
+
if new_ref
|
91
|
+
@reference = new_ref
|
92
|
+
@iter = tree.store.get_iter(new_ref.path)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.build(attrs)
|
97
|
+
if full_path = attrs[:full_path]
|
98
|
+
if ::File.directory? full_path
|
99
|
+
'ListedDirectory'
|
100
|
+
elsif ::File.file? full_path
|
101
|
+
'ListedFile'
|
102
|
+
else
|
103
|
+
self
|
104
|
+
end
|
105
|
+
elsif iter = attrs[:iter] and !iter[REFERENCED_TYPE].nil?
|
106
|
+
iter[REFERENCED_TYPE]
|
107
|
+
else
|
108
|
+
self
|
109
|
+
end.constantize.new attrs
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_s
|
113
|
+
"#{self.class} [#{iter.path}]"
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.modify_icon(scope, &block)
|
117
|
+
with = "icon_name_with_#{scope}"
|
118
|
+
without = "icon_name_without_#{scope}"
|
119
|
+
define_method with do
|
120
|
+
block.call(self)
|
121
|
+
end
|
122
|
+
alias_method without, :icon_name
|
123
|
+
alias_method :icon_name, with
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
class Signal
|
3
|
+
class UnknownSignalError < StandardError ; end
|
4
|
+
@@signals = {}
|
5
|
+
|
6
|
+
def self.on(name, &block)
|
7
|
+
@@signals[name] ||= []
|
8
|
+
@@signals[name] << block
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.emit(name, *args)
|
12
|
+
if @@signals[name].is_a?(Array)
|
13
|
+
@@signals[name].each do |block|
|
14
|
+
block.call(*args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.signals
|
20
|
+
@@signals
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.define name
|
24
|
+
class_eval <<-EOCODE
|
25
|
+
def self.emit_#{name}(*args)
|
26
|
+
self.emit(:#{name},*args)
|
27
|
+
end
|
28
|
+
def self.on_#{name}(&block)
|
29
|
+
self.on(:#{name}, &block)
|
30
|
+
end
|
31
|
+
EOCODE
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.method_missing(meth,*args,&block)
|
35
|
+
case meth.to_s
|
36
|
+
when /^emit_(.*)$/
|
37
|
+
raise UnknownSignalError, "cannot emit unknown signal '#{$1}'"
|
38
|
+
when /^on_(.*)$/
|
39
|
+
raise UnknownSignalError, "cannot connect to unknown signal '#{$1}'"
|
40
|
+
else
|
41
|
+
raise NoMethodError, "unknown method: #{meth}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
|
3
|
+
end
|
4
|
+
require_dependency 'active_window/signal'
|
5
|
+
require_dependency 'active_window/active_tree_store/columns'
|
6
|
+
require_dependency 'active_window/active_tree_store/index'
|
7
|
+
require_dependency 'active_window/active_tree_store/extentions'
|
8
|
+
require_dependency 'active_window/filtered_active_tree_store'
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module VimMate
|
2
|
+
class ConfigWindow
|
3
|
+
attr_reader :container
|
4
|
+
def initialize(main_window=nil)
|
5
|
+
@gtk_main_window = Gtk::Dialog.new("Configuration", main_window, Gtk::Dialog::MODAL,
|
6
|
+
[ Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_REJECT ],
|
7
|
+
[ Gtk::Stock::OK, Gtk::Dialog::RESPONSE_ACCEPT ]
|
8
|
+
)
|
9
|
+
gtk_window.set_default_size(400,300)
|
10
|
+
gtk_window.signal_connect('response') do |win,resp|
|
11
|
+
case resp
|
12
|
+
when Gtk::Dialog::RESPONSE_ACCEPT
|
13
|
+
save_settings
|
14
|
+
win.close
|
15
|
+
when Gtk::Dialog::RESPONSE_REJECT
|
16
|
+
win.close
|
17
|
+
when Gtk::Dialog::RESPONSE_NONE
|
18
|
+
puts "closing"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
@container = gtk_window.vbox
|
22
|
+
fill_container
|
23
|
+
gtk_window.show_all
|
24
|
+
end
|
25
|
+
# The "window" for this object
|
26
|
+
def gtk_window
|
27
|
+
@gtk_main_window
|
28
|
+
end
|
29
|
+
|
30
|
+
def fill_container
|
31
|
+
@fields = {}
|
32
|
+
Config::DEFAULT_CONFIG.keys.sort {|a,b| a.to_s <=> b.to_s}.each do |key|
|
33
|
+
val = Config[key]
|
34
|
+
box = Gtk::HBox.new(true,10)
|
35
|
+
label = Gtk::Label.new(key.to_s.humanize)
|
36
|
+
label.xalign = 1
|
37
|
+
box.pack_start label, true, true
|
38
|
+
|
39
|
+
field = field_for val
|
40
|
+
@fields[key] = field
|
41
|
+
box.pack_start field, true, false
|
42
|
+
container.pack_start box
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def save_settings
|
47
|
+
Config::DEFAULT_CONFIG.keys.each do |key|
|
48
|
+
if new_val = val_of(key)
|
49
|
+
Config.config[key] = new_val
|
50
|
+
end
|
51
|
+
end
|
52
|
+
Config.write_config
|
53
|
+
end
|
54
|
+
|
55
|
+
def val_of(key)
|
56
|
+
field = @fields[key]
|
57
|
+
case Config::DEFAULT_CONFIG[key]
|
58
|
+
when String
|
59
|
+
field.text
|
60
|
+
when Fixnum
|
61
|
+
field.value.to_i
|
62
|
+
when Float
|
63
|
+
field.value.to_f
|
64
|
+
when FalseClass, TrueClass
|
65
|
+
field.active?
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def field_for(val)
|
70
|
+
case val
|
71
|
+
when String
|
72
|
+
# TODO make "textarea" for more than 42 chars
|
73
|
+
e = Gtk::Entry.new
|
74
|
+
e.editable = true
|
75
|
+
e.text = val
|
76
|
+
e
|
77
|
+
when Fixnum, Float
|
78
|
+
Gtk::SpinButton.new(
|
79
|
+
Gtk::Adjustment.new(val,0,10000,1,10,1),
|
80
|
+
1,0)
|
81
|
+
when FalseClass, TrueClass
|
82
|
+
e = Gtk::ToggleButton.new
|
83
|
+
e.active = val
|
84
|
+
e
|
85
|
+
else
|
86
|
+
Gtk::Label.new(val.to_s)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class FileTreeStore < ActiveWindow::ActiveTreeStore
|
2
|
+
column :full_path, String, :visible => false
|
3
|
+
column :status, String, :visible => false
|
4
|
+
column :sort, String, :visible => false
|
5
|
+
|
6
|
+
composite_column 'Files' do |col|
|
7
|
+
col.add column(:icon, Gdk::Pixbuf), false
|
8
|
+
col.add column(:name, String)
|
9
|
+
end
|
10
|
+
|
11
|
+
index_by :full_path
|
12
|
+
|
13
|
+
attr_reader :excludes
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
@excludes ||= []
|
17
|
+
set_sort_column_id self.class.column_id[:sort]
|
18
|
+
ActiveWindow::Signal.on_file_modified { |path| refresh_path(path) }
|
19
|
+
ActiveWindow::Signal.on_file_created { |path| add_path(path) }
|
20
|
+
ActiveWindow::Signal.on_file_deleted { |path| remove_path(path) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_path(path, parent=nil)
|
24
|
+
unless excludes?(File.expand_path(path))
|
25
|
+
file = ListedFile.create(:full_path => path)
|
26
|
+
iter = add file, parent || find_by_full_path( File.dirname(path) )
|
27
|
+
if file.directory?
|
28
|
+
file.children_paths.each do |child|
|
29
|
+
add_path(child, iter)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
rescue ArgumentError => e
|
34
|
+
STDERR.puts e.message
|
35
|
+
end
|
36
|
+
|
37
|
+
def refresh_path(path)
|
38
|
+
if iter = find_by_full_path(path)
|
39
|
+
update_iter_from_object(iter, iter[OBJECT])
|
40
|
+
if iter[OBJECT].directory?
|
41
|
+
each do |iter|
|
42
|
+
if iter[FULL_PATH].start_with?(path)
|
43
|
+
refresh_path iter[FULL_PATH]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def remove_path(file_path)
|
51
|
+
if has_full_path?(file_path)
|
52
|
+
to_remove = []
|
53
|
+
each do |model,path,iter|
|
54
|
+
if iter[FULL_PATH].starts_with?(file_path)
|
55
|
+
to_remove << reference_for(iter)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
to_remove.each do |element|
|
59
|
+
i = get_iter(element.path)
|
60
|
+
remove(i) if i
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Path ends with a node name contained in the exclude list
|
66
|
+
def excludes?(path)
|
67
|
+
excludes.any? {|f| path[-(f.size+1)..-1] == "/#{f}" }
|
68
|
+
end
|
69
|
+
|
70
|
+
def exclude!(new_exclude)
|
71
|
+
excludes << new_exclude.chomp.strip
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|