ui: show the current column in the commit message editor
[git-cola.git] / cola / views / __init__.py
blob517e3365e1faaa0d1b7275b42b224e7f41c45327
1 import os
2 import time
3 import sys
5 from PyQt4.QtCore import Qt
6 from PyQt4.QtCore import SIGNAL
7 from PyQt4.QtGui import qApp
8 from PyQt4.QtGui import QDialog
9 from PyQt4.QtGui import QMainWindow
10 from PyQt4.QtGui import QCheckBox
11 from PyQt4.QtGui import QSplitter
13 from cola import qtutils
14 from cola import syntax
15 from cola.syntax import DiffSyntaxHighlighter
16 from cola.syntax import LogSyntaxHighlighter
18 try:
19 from main import Ui_main
20 from combo import Ui_combo
21 from items import Ui_items
22 from remote import Ui_remote
23 from commit import Ui_commit
24 from logger import Ui_logger
25 from search import Ui_search
26 from options import Ui_options
27 from createbranch import Ui_createbranch
28 from merge import Ui_merge
29 from bookmark import Ui_bookmark
30 from stash import Ui_stash
31 except ImportError:
32 sys.stderr.write('\nThe cola UI modules have not been built.\n'
33 'Try running "make" in the cola source tree.\n')
34 sys.exit(-1)
36 def CreateStandardView(uiclass, qtclass, *classes):
37 """CreateStandardView returns a class closure of uiclass and qtclass.
38 This class performs the standard setup common to all view classes."""
39 class StandardView(uiclass, qtclass):
40 def __init__(self, parent=None, *args, **kwargs):
41 qtclass.__init__(self, parent)
42 uiclass.__init__(self)
43 self.parent_view = parent
44 syntax.set_theme_properties(self)
45 self.setupUi(self)
46 self.init(parent, *args, **kwargs)
47 for cls in classes:
48 cls.init(self, parent, *args, **kwargs)
49 def init(self, parent, *args, **kwargs):
50 pass
51 def get_properties(self):
52 # user-definable color properties
53 props = {}
54 for name in syntax.default_colors:
55 props[name] = getattr(self, '_'+name)
56 return props
57 def reset_syntax(self):
58 if hasattr(self, 'syntax') and self.syntax:
59 self.syntax.set_colors(self.get_properties())
60 self.syntax.reset()
61 syntax.install_theme_properties(StandardView)
62 return StandardView
64 class View(CreateStandardView(Ui_main, QMainWindow)):
65 """The main cola interface."""
66 def init(self, parent=None):
67 self.staged.setAlternatingRowColors(True)
68 self.unstaged.setAlternatingRowColors(True)
69 self.set_display = self.display_text.setText
70 self.amend_is_checked = self.amend_radio.isChecked
71 self.action_undo = self.commitmsg.undo
72 self.action_redo = self.commitmsg.redo
73 self.action_paste = self.commitmsg.paste
74 self.action_select_all = self.commitmsg.selectAll
76 # Qt does not support noun/verbs
77 self.commit_button.setText(qtutils.tr('Commit@@verb'))
78 self.commit_menu.setTitle(qtutils.tr('Commit@@verb'))
80 self.tabifyDockWidget(self.diff_dock, self.editor_dock)
82 # Default to creating a new commit(i.e. not an amend commit)
83 self.new_commit_radio.setChecked(True)
84 self.toolbar_show_log =\
85 self.toolbar.addAction(qtutils.get_qicon('git.png'),
86 'Show/Hide Log Window')
87 self.toolbar_show_log.setEnabled(True)
89 # Diff/patch syntax highlighter
90 self.syntax = DiffSyntaxHighlighter(self.display_text.document())
92 # Handle the vertical checkbox action
93 self.connect(self.vertical_checkbox,
94 SIGNAL('clicked(bool)'),
95 self.handle_vertical_checkbox)
97 # Display the current column
98 self.connect(self.commitmsg,
99 SIGNAL('cursorPositionChanged()'),
100 self.show_current_column)
102 def handle_vertical_checkbox(self, checked):
103 if checked:
104 self.splitter.setOrientation(Qt.Vertical)
105 else:
106 self.splitter.setOrientation(Qt.Horizontal)
108 def set_info(self, txt):
109 try:
110 translated = self.tr(unicode(txt))
111 except:
112 translated = unicode(txt)
113 self.statusBar().showMessage(translated)
114 def show_editor(self):
115 self.editor_dock.raise_()
116 def show_diff(self):
117 self.diff_dock.raise_()
119 def action_cut(self):
120 self.action_copy()
121 self.action_delete()
122 def action_copy(self):
123 cursor = self.commitmsg.textCursor()
124 selection = cursor.selection().toPlainText()
125 qtutils.set_clipboard(selection)
126 def action_delete(self):
127 self.commitmsg.textCursor().removeSelectedText()
128 def reset_checkboxes(self):
129 self.new_commit_radio.setChecked(True)
130 self.amend_radio.setChecked(False)
131 def reset_display(self):
132 self.set_display('')
133 self.set_info('')
134 def copy_display(self):
135 cursor = self.display_text.textCursor()
136 selection = cursor.selection().toPlainText()
137 qtutils.set_clipboard(selection)
138 def diff_selection(self):
139 cursor = self.display_text.textCursor()
140 offset = cursor.position()
141 selection = cursor.selection().toPlainText()
142 return offset, selection
143 def selected_line(self):
144 cursor = self.display_text.textCursor()
145 offset = cursor.position()
146 contents = unicode(self.display_text.toPlainText())
147 while (offset > 1
148 and contents[offset-1]
149 and contents[offset-1] != '\n'):
150 offset -= 1
151 line, rest = contents[offset:].split('\n', 1)
152 return line
153 def display(self, text):
154 self.set_display(text)
155 self.diff_dock.raise_()
156 def show_current_column(self):
157 cursor = self.commitmsg.textCursor()
158 colnum = cursor.columnNumber()
159 self.column_label.setText('Column: %02d' % colnum)
161 class LogView(CreateStandardView(Ui_logger, QDialog)):
162 """A simple dialog to display command logs."""
163 def init(self, parent=None, output=None):
164 self.setWindowTitle(self.tr('Git Command Log'))
165 self.syntax = LogSyntaxHighlighter(self.output_text.document())
166 if output:
167 self.set_output(output)
168 def clear(self):
169 self.output_text.clear()
170 def set_output(self, output):
171 self.output_text.setText(output)
172 def log(self, output):
173 if not output: return
174 cursor = self.output_text.textCursor()
175 cursor.movePosition(cursor.End)
176 text = self.output_text
177 cursor.insertText(time.asctime() + '\n')
178 for line in unicode(output).splitlines():
179 cursor.insertText(line + '\n')
180 cursor.insertText('\n')
181 cursor.movePosition(cursor.End)
182 text.setTextCursor(cursor)
184 class ItemView(object):
185 def init(self, parent, title="", items=[]):
186 self.setWindowTitle(title)
187 self.items = []
188 self.items.extend(items)
189 self.items_widget.addItems(items)
190 def idx(self):
191 return 0
192 def get_selected(self):
193 geom = qApp.desktop().screenGeometry()
194 width = geom.width()
195 height = geom.height()
196 x = self.parent_view.x() + self.parent_view.width()/2 - self.width()/2
197 y = self.parent_view.y() + self.parent_view.height()/3 - self.height()/2
198 self.move(x, y)
199 self.show()
200 if self.exec_() == QDialog.Accepted:
201 return self.items[self.idx()]
202 else:
203 return None
205 class ComboView(CreateStandardView(Ui_combo, QDialog, ItemView), ItemView):
206 """A dialog for choosing branches."""
207 def idx(self):
208 return self.items_widget.currentIndex()
210 class ListView(CreateStandardView(Ui_items, QDialog, ItemView), ItemView):
211 """A dialog for an item from a list."""
212 def idx(self):
213 return self.items_widget.currentRow()
215 class CommitView(CreateStandardView(Ui_commit, QDialog)):
216 def init(self, parent=None, title=None):
217 if title: self.setWindowTitle(title)
218 # Make the list widget slighty larger
219 self.splitter.setSizes([ 50, 200 ])
220 self.syntax = DiffSyntaxHighlighter(self.commit_text.document(),
221 whitespace=False)
223 class SearchView(CreateStandardView(Ui_search, QDialog)):
224 def init(self, parent=None):
225 self.input.setFocus()
226 self.syntax = DiffSyntaxHighlighter(self.commit_text.document(),
227 whitespace=False)
229 class MergeView(CreateStandardView(Ui_merge, QDialog)):
230 def init(self, parent=None):
231 self.revision.setFocus()
233 class RemoteView(CreateStandardView(Ui_remote, QDialog)):
234 def init(self, parent=None, button_text=''):
235 if button_text:
236 self.action_button.setText(button_text)
237 self.setWindowTitle(button_text)
238 def select_first_remote(self):
239 item = self.remotes.item(0)
240 if item:
241 self.remotes.setItemSelected(item, True)
242 self.remotes.setCurrentItem(item)
243 self.remotename.setText(item.text())
244 return True
245 else:
246 return False
248 # These are views that do not contain any custom methods
249 CreateBranchView = CreateStandardView(Ui_createbranch, QDialog)
250 OptionsView = CreateStandardView(Ui_options, QDialog)
251 BookmarkView = CreateStandardView(Ui_bookmark, QDialog)
252 StashView = CreateStandardView(Ui_stash, QDialog)