widgets: Use the brushed metal style in more dialogs
[git-cola.git] / cola / difftool.py
blobd7b6dc10988a91efe78db0d7d5a9dfb1be42edfd
1 from PyQt4 import QtGui
2 from PyQt4 import QtCore
3 from PyQt4.QtCore import Qt
4 from PyQt4.QtCore import SIGNAL
6 from cola import utils
7 from cola import qtutils
8 from cola import gitcmds
9 from cola.widgets import defs
12 def launch(args):
13 """Launches 'git difftool' with args"""
14 difftool_args = ['git', 'difftool', '--no-prompt']
15 difftool_args.extend(args)
16 utils.fork(difftool_args)
19 def diff_commits(parent, a, b):
20 dlg = FileDiffDialog(parent, a=a, b=b)
21 dlg.show()
22 dlg.raise_()
23 return dlg.exec_() == QtGui.QDialog.Accepted
26 def diff_expression(parent, expr):
27 dlg = FileDiffDialog(parent, expr=expr)
28 dlg.show()
29 dlg.raise_()
30 return dlg.exec_() == QtGui.QDialog.Accepted
33 class FileDiffDialog(QtGui.QDialog):
34 def __init__(self, parent, a=None, b=None, expr=None):
35 super(FileDiffDialog, self).__init__(parent)
36 self.setAttribute(Qt.WA_MacMetalStyle)
37 self.a = a
38 self.b = b
39 self.expr = expr
41 self.setWindowTitle('Select File(s)')
42 self.setWindowModality(QtCore.Qt.WindowModal)
44 self._tree = QtGui.QTreeWidget(self)
45 self._tree.setAlternatingRowColors(True)
46 self._tree.setRootIsDecorated(False)
47 self._tree.setSelectionMode(self._tree.ExtendedSelection)
48 self._tree.setUniformRowHeights(True)
49 self._tree.setAllColumnsShowFocus(True)
50 self._tree.setHeaderHidden(True)
52 self._diff_btn = QtGui.QPushButton('Compare')
53 self._diff_btn.setIcon(qtutils.ok_icon())
54 self._diff_btn.setEnabled(False)
56 self._close_btn = QtGui.QPushButton('Close')
57 self._close_btn.setIcon(qtutils.close_icon())
59 self._button_layt = QtGui.QHBoxLayout()
60 self._button_layt.setMargin(0)
61 self._button_layt.addStretch()
62 self._button_layt.addWidget(self._diff_btn)
63 self._button_layt.addWidget(self._close_btn)
65 self._layt = QtGui.QVBoxLayout()
66 self._layt.setMargin(defs.margin)
67 self._layt.setSpacing(defs.spacing)
68 self._layt.addWidget(self._tree)
69 self._layt.addLayout(self._button_layt)
70 self.setLayout(self._layt)
72 qtutils.add_close_action(self)
74 self.connect(self._tree, SIGNAL('itemSelectionChanged()'),
75 self._tree_selection_changed)
77 self.connect(self._tree,
78 SIGNAL('itemDoubleClicked(QTreeWidgetItem*,int)'),
79 self._tree_double_clicked)
81 self.connect(self._diff_btn, SIGNAL('clicked()'), self.diff)
82 self.connect(self._close_btn, SIGNAL('clicked()'), self.close)
84 if self.expr:
85 self.diff_arg = tuple(utils.shell_split(self.expr))
86 elif self.b is None:
87 self.diff_arg = (self.a,)
88 else:
89 self.diff_arg = (self.a, self.b)
91 self.resize(720, 420)
94 def exec_(self):
95 if self.expr:
96 filenames = gitcmds.diff_filenames(*self.diff_arg)
97 elif self.b is None:
98 filenames = gitcmds.diff_index_filenames(self.a)
99 else:
100 filenames = gitcmds.diff_filenames(*self.diff_arg)
102 if not filenames:
103 details = ('"git diff --name-only %s" returned an empty list' %
104 ' '.join(self.diff_arg))
105 self.hide()
106 qtutils.information('git cola',
107 message='No changes to diff',
108 details=details)
109 self.close()
110 return self.Accepted
112 icon = qtutils.file_icon()
113 items = []
114 for filename in filenames:
115 item = QtGui.QTreeWidgetItem()
116 item.setIcon(0, icon)
117 item.setText(0, filename)
118 item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(filename))
119 items.append(item)
120 self._tree.addTopLevelItems(items)
122 return QtGui.QDialog.exec_(self)
124 def _tree_selection_changed(self):
125 self._diff_btn.setEnabled(bool(self._tree.selectedItems()))
127 def _tree_double_clicked(self, item, column):
128 path = item.data(0, QtCore.Qt.UserRole).toPyObject()
129 launch(self.diff_arg + ('--', unicode(path)))
131 def diff(self):
132 items = self._tree.selectedItems()
133 if not items:
134 return
135 paths = [i.data(0, QtCore.Qt.UserRole).toPyObject() for i in items]
136 for path in paths:
137 launch(self.diff_arg + ('--', unicode(path)))