1 from PyQt4
import QtCore
2 from PyQt4
import QtGui
3 from PyQt4
.QtCore
import Qt
4 from PyQt4
.QtCore
import SIGNAL
7 from cola
import guicmds
9 from cola
import qtutils
10 from cola
.git
import git
11 from cola
.prefs
import diff_font
12 from cola
.widgets
import defs
13 from cola
.widgets
.standard
import Dialog
14 from cola
.widgets
.text
import HintedTextView
, HintedLineEdit
17 class GrepThread(QtCore
.QThread
):
18 def __init__(self
, parent
):
19 QtCore
.QThread
.__init
__(self
, parent
)
29 args
= utils
.shell_split(query
)
32 status
, out
= git
.grep(with_status
=True, with_stderr
=True,
35 self
.emit(SIGNAL('result'), status
, core
.decode(out
))
41 def __init__(self
, parent
):
42 Dialog
.__init
__(self
, parent
)
43 self
.setAttribute(Qt
.WA_MacMetalStyle
)
44 self
.setWindowModality(Qt
.WindowModal
)
46 self
.input_label
= QtGui
.QLabel('git grep')
47 self
.input_label
.setFont(diff_font())
49 hint
= 'command-line arguments'
50 self
.input_txt
= GrepLineEdit(hint
, self
)
51 self
.input_txt
.enable_hint(True)
53 hint
= 'grep result...'
54 self
.result_txt
= GrepTextView(hint
, self
)
55 self
.result_txt
.enable_hint(True)
57 self
.edit_button
= QtGui
.QPushButton(self
.tr('Edit'))
58 self
.edit_button
.setIcon(qtutils
.open_file_icon())
59 self
.edit_button
.setEnabled(False)
60 self
.edit_button
.setShortcut(defs
.editor_shortcut
)
62 self
.shell_checkbox
= QtGui
.QCheckBox(self
.tr('Shell arguments'))
63 self
.shell_checkbox
.setToolTip(
64 'Parse arguments using a shell.\n'
65 'Queries with spaces will require "double quotes".')
66 self
.shell_checkbox
.setChecked(False)
68 self
.close_button
= QtGui
.QPushButton(self
.tr('Close'))
70 self
.input_layout
= QtGui
.QHBoxLayout()
71 self
.input_layout
.setMargin(0)
72 self
.input_layout
.setSpacing(defs
.button_spacing
)
74 self
.bottom_layout
= QtGui
.QHBoxLayout()
75 self
.bottom_layout
.setMargin(0)
76 self
.bottom_layout
.setSpacing(defs
.button_spacing
)
78 self
.mainlayout
= QtGui
.QVBoxLayout()
79 self
.mainlayout
.setMargin(defs
.margin
)
80 self
.mainlayout
.setSpacing(defs
.spacing
)
82 self
.input_layout
.addWidget(self
.input_label
)
83 self
.input_layout
.addWidget(self
.input_txt
)
85 self
.bottom_layout
.addWidget(self
.edit_button
)
86 self
.bottom_layout
.addWidget(self
.shell_checkbox
)
87 self
.bottom_layout
.addStretch()
88 self
.bottom_layout
.addWidget(self
.close_button
)
90 self
.mainlayout
.addLayout(self
.input_layout
)
91 self
.mainlayout
.addWidget(self
.result_txt
)
92 self
.mainlayout
.addLayout(self
.bottom_layout
)
93 self
.setLayout(self
.mainlayout
)
95 self
.grep_thread
= GrepThread(self
)
97 self
.connect(self
.grep_thread
, SIGNAL('result'),
100 self
.connect(self
.input_txt
, SIGNAL('textChanged(QString)'),
101 self
.input_txt_changed
)
103 self
.connect(self
.input_txt
, SIGNAL('returnPressed()'),
104 lambda: self
.result_txt
.setFocus())
106 qtutils
.connect_button(self
.edit_button
, self
.edit
)
107 qtutils
.connect_button(self
.close_button
, self
.close
)
108 qtutils
.add_close_action(self
)
110 if not qtutils
.apply_state(self
):
111 self
.resize(666, 420)
113 def done(self
, exit_code
):
114 qtutils
.save_state(self
)
115 return Dialog
.done(self
, exit_code
)
117 def input_txt_changed(self
, txt
):
118 has_query
= len(unicode(txt
)) > 1
123 self
.edit_button
.setEnabled(False)
125 self
.grep_thread
.txt
= self
.input_txt
.as_unicode()
126 self
.grep_thread
.shell
= self
.shell_checkbox
.isChecked()
127 self
.grep_thread
.start()
129 def search_for(self
, txt
):
130 self
.input_txt
.set_value(txt
)
133 def process_result(self
, status
, out
):
134 self
.result_txt
.set_value(out
)
135 self
.edit_button
.setEnabled(status
== 0)
138 guicmds
.goto_grep(self
.result_txt
.selected_line()),
141 class GrepLineEdit(HintedLineEdit
):
142 def __init__(self
, hint
, parent
):
143 HintedLineEdit
.__init
__(self
, hint
, parent
)
145 def keyPressEvent(self
, event
):
146 if event
.key() in (Qt
.Key_Return
, Qt
.Key_Enter
):
147 self
.emit(SIGNAL('returnPressed()'))
149 HintedLineEdit
.keyPressEvent(self
, event
)
152 class GrepTextView(HintedTextView
):
153 def __init__(self
, hint
, parent
):
154 HintedTextView
.__init
__(self
, hint
, parent
)
155 self
.goto_action
= qtutils
.add_action(
156 self
, 'Launch Editor',
157 lambda: guicmds
.goto_grep(self
.selected_line()))
158 self
.goto_action
.setShortcut(defs
.editor_shortcut
)
160 qtutils
.add_action(self
, 'Up',
161 lambda: self
.move(QtGui
.QTextCursor
.Up
),
164 qtutils
.add_action(self
, 'Down',
165 lambda: self
.move(QtGui
.QTextCursor
.Down
),
168 qtutils
.add_action(self
, 'Left',
169 lambda: self
.move(QtGui
.QTextCursor
.Left
),
172 qtutils
.add_action(self
, 'Right',
173 lambda: self
.move(QtGui
.QTextCursor
.Right
),
176 qtutils
.add_action(self
, 'StartOfLine',
177 lambda: self
.move(QtGui
.QTextCursor
.StartOfLine
),
180 qtutils
.add_action(self
, 'EndOfLine',
181 lambda: self
.move(QtGui
.QTextCursor
.EndOfLine
),
184 qtutils
.add_action(self
, 'WordLeft',
185 lambda: self
.move(QtGui
.QTextCursor
.WordLeft
),
188 qtutils
.add_action(self
, 'WordRight',
189 lambda: self
.move(QtGui
.QTextCursor
.WordRight
),
192 qtutils
.add_action(self
, 'PageUp',
193 lambda: self
.page(-self
.height()/2),
196 qtutils
.add_action(self
, 'PageDown',
197 lambda: self
.page(self
.height()/2),
200 def contextMenuEvent(self
, event
):
201 menu
= self
.createStandardContextMenu(event
.pos())
203 menu
.addAction(self
.goto_action
)
204 menu
.exec_(self
.mapToGlobal(event
.pos()))
206 def page(self
, offset
):
207 rect
= self
.cursorRect()
209 y
= rect
.y() + offset
210 new_cursor
= self
.cursorForPosition(QtCore
.QPoint(x
, y
))
211 if new_cursor
is not None:
212 self
.set_text_cursor(new_cursor
)
214 def set_text_cursor(self
, cursor
):
215 self
.setTextCursor(cursor
)
216 self
.ensureCursorVisible()
217 self
.viewport().update()
219 def move(self
, direction
):
220 cursor
= self
.textCursor()
221 if cursor
.movePosition(direction
):
222 self
.set_text_cursor(cursor
)
224 def paintEvent(self
, event
):
225 HintedTextView
.paintEvent(self
, event
)
227 # Qt doesn't redraw the cursor when using movePosition().
228 # So.. draw our own cursor.
229 rect
= self
.cursorRect()
230 painter
= QtGui
.QPainter(self
.viewport())
231 painter
.fillRect(rect
, Qt
.SolidPattern
)
234 def run_grep(txt
=None, parent
=None):
235 widget
= Grep(parent
)
237 widget
.search_for(txt
)