FileWidget: a Signal to toggle remark of commits touching selected files
[git-cola.git] / cola / widgets / filelist.py
blob05c968f6d61c24e4fe612ffe85bb7da98cd61f23
1 from qtpy import QtWidgets
2 from qtpy.QtCore import Signal
3 from qtpy.QtCore import QSize
4 from qtpy.QtCore import Qt
6 from .. import cmds
7 from .. import hotkeys
8 from .. import qtutils
9 from ..i18n import N_
10 from .standard import TreeWidget
13 # pylint: disable=too-many-ancestors
14 class FileWidget(TreeWidget):
15 files_selected = Signal(object)
16 difftool_selected = Signal(object)
17 histories_selected = Signal(object)
18 grab_file = Signal(object)
19 remark_toggled = Signal(object, object)
21 def __init__(self, context, parent, remarks=False):
22 TreeWidget.__init__(self, parent)
23 self.context = context
25 labels = [N_('Filename'), N_('Additions'), N_('Deletions')]
26 self.setHeaderLabels(labels)
28 self.show_history_action = qtutils.add_action(
29 self, N_('Show History'), self.show_history, hotkeys.HISTORY
32 self.launch_difftool_action = qtutils.add_action(
33 self, N_('Launch Diff Tool'), self.show_diff
36 self.launch_editor_action = qtutils.add_action(
37 self, N_('Launch Editor'), self.edit_paths, hotkeys.EDIT
40 self.grab_file_action = qtutils.add_action(
41 self, N_('Grab File...'), self._grab_file
44 if remarks:
45 self.toggle_remark_actions = tuple(
46 qtutils.add_action(
47 self,
49 lambda remark = r: self.toggle_remark(remark),
50 hotkeys.hotkey(Qt.CTRL | getattr(Qt, "Key_" + r))
51 ) for r in map(str, range(10))
53 else:
54 self.toggle_remark_actions = tuple()
56 # pylint: disable=no-member
57 self.itemSelectionChanged.connect(self.selection_changed)
59 def selection_changed(self):
60 items = self.selected_items()
61 self.files_selected.emit([i.path for i in items])
63 def commits_selected(self, commits):
64 if not commits:
65 self.clear()
66 return
68 git = self.context.git
69 paths = []
71 if len(commits) > 1:
72 # Get a list of changed files for a commit range.
73 start = commits[0].oid + '~'
74 end = commits[-1].oid
75 status, out, _ = git.diff(start, end, z=True, numstat=True, no_renames=True)
76 if status == 0:
77 paths = [f for f in out.rstrip('\0').split('\0') if f]
78 else:
79 # Get the list of changed files in a single commit.
80 commit = commits[0]
81 oid = commit.oid
82 status, out, _ = git.show(
83 oid, z=True, numstat=True, oneline=True, no_renames=True
85 if status == 0:
86 paths = [f for f in out.rstrip('\0').split('\0') if f]
87 if paths:
88 paths = paths[1:] # Skip over the summary on the first line.
90 self.list_files(paths)
92 def list_files(self, files_log):
93 self.clear()
94 if not files_log:
95 return
96 files = []
97 for filename in files_log:
98 item = FileTreeWidgetItem(filename)
99 files.append(item)
100 self.insertTopLevelItems(0, files)
102 def adjust_columns(self, size, old_size):
103 if size.isValid() and old_size.isValid():
104 width = self.columnWidth(0) + size.width() - old_size.width()
105 self.setColumnWidth(0, width)
106 else:
107 width = self.width()
108 two_thirds = (width * 2) // 3
109 one_sixth = width // 6
110 self.setColumnWidth(0, two_thirds)
111 self.setColumnWidth(1, one_sixth)
112 self.setColumnWidth(2, one_sixth)
114 def show(self):
115 self.adjust_columns(QSize(), QSize())
117 def resizeEvent(self, event):
118 self.adjust_columns(event.size(), event.oldSize())
120 def contextMenuEvent(self, event):
121 menu = qtutils.create_menu(N_('Actions'), self)
122 menu.addAction(self.grab_file_action)
123 menu.addAction(self.show_history_action)
124 menu.addAction(self.launch_difftool_action)
125 menu.addAction(self.launch_editor_action)
126 if self.toggle_remark_actions:
127 menu_toggle_remark = menu.addMenu(
128 N_('Toggle remark of touching commits')
130 tuple(map(menu_toggle_remark.addAction, self.toggle_remark_actions))
131 menu.exec_(self.mapToGlobal(event.pos()))
133 def show_diff(self):
134 self.difftool_selected.emit(self.selected_paths())
136 def _grab_file(self):
137 for path in self.selected_paths():
138 self.grab_file.emit(path)
140 def selected_paths(self):
141 return [i.path for i in self.selected_items()]
143 def edit_paths(self):
144 cmds.do(cmds.Edit, self.context, self.selected_paths())
146 def show_history(self):
147 items = self.selected_items()
148 paths = [i.path for i in items]
149 self.histories_selected.emit(paths)
151 def toggle_remark(self, remark):
152 items = self.selected_items()
153 paths = tuple(i.path for i in items)
154 self.remark_toggled.emit(remark, paths)
157 class FileTreeWidgetItem(QtWidgets.QTreeWidgetItem):
158 def __init__(self, file_log, parent=None):
159 QtWidgets.QTreeWidgetItem.__init__(self, parent)
160 texts = file_log.split('\t')
161 self.path = path = texts[2]
162 self.setText(0, path)
163 self.setText(1, texts[0])
164 self.setText(2, texts[1])