1 """File finder widgets"""
2 from __future__
import absolute_import
, division
, print_function
, unicode_literals
4 from functools
import partial
6 from qtpy
import QtCore
7 from qtpy
import QtWidgets
8 from qtpy
.QtCore
import Qt
9 from qtpy
.QtCore
import Signal
12 from ..qtutils
import get
13 from ..utils
import Group
16 from .. import gitcmds
17 from .. import hotkeys
20 from .. import qtutils
21 from . import completion
23 from . import filetree
24 from . import standard
28 def finder(context
, paths
=None):
29 """Prompt and use 'git grep' to find the content."""
30 parent
= qtutils
.active_window()
31 widget
= new_finder(context
, paths
=paths
, parent
=parent
)
37 def new_finder(context
, paths
=None, parent
=None):
38 """Create a finder widget"""
39 widget
= Finder(context
, parent
=parent
)
40 widget
.search_for(paths
or '')
44 def add_wildcards(arg
):
45 """Add "*" around user input to generate ls-files pathspecs matches
48 add_wildcards('x') == \
49 add_wildcards('*x') == \
50 add_wildcards('x*') == \
55 if not arg
.startswith('*'):
57 if not arg
.endswith('*'):
62 def show_help(context
):
63 """Show the help page"""
70 Enter = Edit Selected Files
71 Spacebar = Open File Using Default Application
72 Ctrl + L = Focus Text Entry Field
75 The up and down arrows change focus between the text entry field
79 title
= N_('Help - Find Files')
80 return text
.text_dialog(context
, help_text
, title
)
83 class FindFilesThread(QtCore
.QThread
):
84 """Finds files asynchronously"""
86 result
= Signal(object)
88 def __init__(self
, context
, parent
):
89 QtCore
.QThread
.__init
__(self
, parent
)
90 self
.context
= context
94 context
= self
.context
99 args
= [add_wildcards(arg
) for arg
in utils
.shell_split(query
)]
100 filenames
= gitcmds
.tracked_files(context
, *args
)
101 if query
== self
.query
:
102 self
.result
.emit(filenames
)
107 class Finder(standard
.Dialog
):
108 """File Finder dialog"""
110 def __init__(self
, context
, parent
=None):
111 standard
.Dialog
.__init
__(self
, parent
)
112 self
.context
= context
113 self
.setWindowTitle(N_('Find Files'))
114 if parent
is not None:
115 self
.setWindowModality(Qt
.WindowModal
)
117 label
= os
.path
.basename(core
.getcwd()) + '/'
118 self
.input_label
= QtWidgets
.QLabel(label
)
119 self
.input_txt
= completion
.GitTrackedLineEdit(context
, hint
=N_('<path> ...'))
121 self
.tree
= filetree
.FileTree(parent
=self
)
123 self
.edit_button
= qtutils
.edit_button(default
=True)
124 self
.edit_button
.setShortcut(hotkeys
.EDIT
)
126 name
= cmds
.OpenDefaultApp
.name()
127 icon
= icons
.default_app()
128 self
.open_default_button
= qtutils
.create_button(text
=name
, icon
=icon
)
129 self
.open_default_button
.setShortcut(hotkeys
.PRIMARY_ACTION
)
131 self
.button_group
= Group(self
.edit_button
, self
.open_default_button
)
132 self
.button_group
.setEnabled(False)
134 self
.refresh_button
= qtutils
.refresh_button()
135 self
.refresh_button
.setShortcut(hotkeys
.REFRESH
)
137 self
.help_button
= qtutils
.create_button(
138 text
=N_('Help'), tooltip
=N_('Show help\nShortcut: ?'), icon
=icons
.question()
141 self
.close_button
= qtutils
.close_button()
143 self
.input_layout
= qtutils
.hbox(
144 defs
.no_margin
, defs
.button_spacing
, self
.input_label
, self
.input_txt
147 self
.bottom_layout
= qtutils
.hbox(
154 self
.open_default_button
,
158 self
.main_layout
= qtutils
.vbox(
165 self
.setLayout(self
.main_layout
)
166 self
.setFocusProxy(self
.input_txt
)
168 thread
= self
.worker_thread
= FindFilesThread(context
, self
)
169 thread
.result
.connect(self
.process_result
, type=Qt
.QueuedConnection
)
171 # pylint: disable=no-member
172 self
.input_txt
.textChanged
.connect(lambda s
: self
.search())
173 self
.input_txt
.activated
.connect(self
.focus_tree
)
174 self
.input_txt
.down
.connect(self
.focus_tree
)
175 self
.input_txt
.enter
.connect(self
.focus_tree
)
177 item_selection_changed
= self
.tree_item_selection_changed
178 self
.tree
.itemSelectionChanged
.connect(item_selection_changed
)
179 self
.tree
.up
.connect(self
.focus_input
)
180 self
.tree
.space
.connect(self
.open_default
)
183 self
, 'Focus Input', self
.focus_input
, hotkeys
.FOCUS
, hotkeys
.FINDER
186 self
.show_help_action
= qtutils
.add_action(
187 self
, N_('Show Help'), partial(show_help
, context
), hotkeys
.QUESTION
190 qtutils
.connect_button(self
.edit_button
, self
.edit
)
191 qtutils
.connect_button(self
.open_default_button
, self
.open_default
)
192 qtutils
.connect_button(self
.refresh_button
, self
.search
)
193 qtutils
.connect_button(self
.help_button
, partial(show_help
, context
))
194 qtutils
.connect_button(self
.close_button
, self
.close
)
195 qtutils
.add_close_action(self
)
197 self
.init_size(parent
=parent
)
199 def focus_tree(self
):
202 def focus_input(self
):
203 self
.input_txt
.setFocus()
206 self
.button_group
.setEnabled(False)
207 self
.refresh_button
.setEnabled(False)
208 query
= get(self
.input_txt
)
209 self
.worker_thread
.query
= query
210 self
.worker_thread
.start()
212 def search_for(self
, txt
):
213 self
.input_txt
.set_value(txt
)
216 def process_result(self
, filenames
):
217 self
.tree
.set_filenames(filenames
, select
=True)
218 self
.refresh_button
.setEnabled(True)
221 context
= self
.context
222 paths
= self
.tree
.selected_filenames()
223 cmds
.do(cmds
.Edit
, context
, paths
, background_editor
=True)
225 def open_default(self
):
226 context
= self
.context
227 paths
= self
.tree
.selected_filenames()
228 cmds
.do(cmds
.OpenDefaultApp
, context
, paths
)
230 def tree_item_selection_changed(self
):
231 enabled
= bool(self
.tree
.selected_item())
232 self
.button_group
.setEnabled(enabled
)