git-cola v4.3.1
[git-cola.git] / cola / widgets / selectcommits.py
blobbc1be8a647f07f24b42d1fbe13e44d602c4587ad
1 """A GUI for selecting commits"""
2 from __future__ import division, absolute_import, unicode_literals
4 from qtpy import QtWidgets
5 from qtpy.QtCore import Qt
7 from .. import gitcmds
8 from .. import qtutils
9 from ..i18n import N_
10 from ..icons import folder
11 from ..interaction import Interaction
12 from ..models import prefs
13 from . import completion
14 from . import defs
15 from .diff import DiffTextEdit
16 from .standard import Dialog
19 def select_commits(context, title, revs, summaries, multiselect=True):
20 """Use the SelectCommits to select commits from a list."""
21 model = Model(revs, summaries)
22 parent = qtutils.active_window()
23 dialog = SelectCommits(context, model, parent, title, multiselect=multiselect)
24 return dialog.select_commits()
27 def select_commits_and_output(context, title, revs, summaries, multiselect=True):
28 """Select commits from a list and output path"""
29 model = Model(revs, summaries)
30 parent = qtutils.active_window()
31 dialog = SelectCommitsAndOutput(
32 context, model, parent, title, multiselect=multiselect
34 return dialog.select_commits_and_output()
37 class Model(object):
38 def __init__(self, revs, summaries):
39 self.revisions = revs
40 self.summaries = summaries
43 class SelectCommits(Dialog):
44 def __init__(self, context, model, parent=None, title=None, multiselect=True):
45 Dialog.__init__(self, parent)
46 self.context = context
47 self.model = model
48 if title:
49 self.setWindowTitle(title)
51 if multiselect:
52 mode = QtWidgets.QAbstractItemView.ExtendedSelection
53 else:
54 mode = QtWidgets.QAbstractItemView.SingleSelection
55 commits = self.commits = QtWidgets.QListWidget()
56 commits.setSelectionMode(mode)
57 commits.setAlternatingRowColors(True)
59 self.commit_text = DiffTextEdit(context, self, whitespace=False)
61 self.revision_label = QtWidgets.QLabel()
62 self.revision_label.setText(N_('Revision Expression:'))
63 self.revision = completion.GitRefLineEdit(context)
64 self.revision.setReadOnly(True)
66 self.search_label = QtWidgets.QLabel()
67 self.search_label.setText(N_('Search:'))
68 self.search = QtWidgets.QLineEdit()
69 self.search.setReadOnly(False)
71 # pylint: disable=no-member
72 self.search.textChanged.connect(self.search_list)
74 self.select_button = qtutils.ok_button(N_('Select'), enabled=False)
76 # Make the list widget slightly larger
77 self.splitter = qtutils.splitter(Qt.Vertical, self.commits, self.commit_text)
78 self.splitter.setSizes([100, 150])
80 self.input_layout = qtutils.hbox(
81 defs.no_margin,
82 defs.spacing,
83 self.search_label,
84 self.search,
85 qtutils.STRETCH,
86 self.revision_label,
87 self.revision,
88 self.select_button,
91 self.main_layout = qtutils.vbox(
92 defs.margin, defs.margin, self.input_layout, self.splitter
94 self.setLayout(self.main_layout)
96 # pylint: disable=no-member
97 commits.itemSelectionChanged.connect(self.commit_oid_selected)
98 commits.itemDoubleClicked.connect(self.commit_oid_double_clicked)
100 qtutils.connect_button(self.select_button, self.accept)
102 self.init_state(None, self.resize_widget, parent)
104 def resize_widget(self, parent):
105 """Set the initial size of the widget"""
106 width, height = qtutils.default_size(parent, 720, 480)
107 self.resize(width, height)
109 def selected_commit(self):
110 return qtutils.selected_item(self.commits, self.model.revisions)
112 def selected_commits(self):
113 return qtutils.selected_items(self.commits, self.model.revisions)
115 def select_commits(self):
116 summaries = self.model.summaries
117 if not summaries:
118 msg = N_('No commits exist in this branch.')
119 Interaction.log(msg)
120 return []
121 qtutils.set_items(self.commits, summaries)
122 self.show()
123 if self.exec_() != QtWidgets.QDialog.Accepted:
124 return []
125 return self.selected_commits()
127 def commit_oid_selected(self):
128 context = self.context
129 oid = self.selected_commit()
130 selected = oid is not None
131 self.select_button.setEnabled(selected)
132 if not selected:
133 self.commit_text.set_value('')
134 self.revision.setText('')
135 return
136 self.revision.setText(oid)
137 self.revision.selectAll()
138 # Display the oid's commit
139 commit_diff = gitcmds.commit_diff(context, oid)
140 self.commit_text.setText(commit_diff)
142 def commit_oid_double_clicked(self, _item):
143 oid = self.selected_commit()
144 if oid:
145 self.accept()
147 def search_list(self, text):
148 if text:
149 for i in range(self.commits.count()):
150 self.commits.item(i).setHidden(True)
151 search_items = self.commits.findItems(text, Qt.MatchContains)
152 for items in search_items:
153 items.setHidden(False)
156 class SelectCommitsAndOutput(SelectCommits):
157 def __init__(self, context, model, parent=None, title=None, multiselect=True):
158 SelectCommits.__init__(self, context, model, parent, title, multiselect)
160 self.output_dir = prefs.patches_directory(context)
161 self.select_output = qtutils.create_button(
162 tooltip=N_('Select output dir'), icon=folder()
164 self.output_text = QtWidgets.QLineEdit()
165 self.output_text.setReadOnly(True)
166 self.output_text.setText(self.output_dir)
168 output_layout = qtutils.hbox(
169 defs.no_margin, defs.no_spacing, self.select_output, self.output_text
172 self.input_layout.insertLayout(1, output_layout)
173 qtutils.connect_button(self.select_output, self.show_output_dialog)
175 def select_commits_and_output(self):
176 to_export = SelectCommits.select_commits(self)
177 output = self.output_dir
179 return {'to_export': to_export, 'output': output}
181 def show_output_dialog(self):
182 self.output_dir = qtutils.opendir_dialog(
183 N_('Select output directory'), self.output_dir
185 if not self.output_dir:
186 return
188 self.output_text.setText(self.output_dir)