submodules: add a dialog for adding new submodules
[git-cola.git] / cola / widgets / submodules.py
blobd5e545c7240abd3ecc4bf5c9826a9732ac373992
1 """Provides widgets related to submodules"""
2 from __future__ import absolute_import
4 from qtpy import QtWidgets
5 from qtpy.QtCore import Qt
6 from qtpy.QtCore import Signal
8 from .. import cmds
9 from .. import compat
10 from .. import core
11 from .. import qtutils
12 from .. import icons
13 from ..i18n import N_
14 from ..widgets import defs
15 from ..widgets import standard
16 from ..widgets import text
19 def add_submodule(context, parent):
20 """Add a new submodule"""
21 dlg = AddSubmodule(parent)
22 dlg.show()
23 if dlg.exec_() == standard.Dialog.Accepted:
24 cmd = dlg.get(context)
25 cmd.do()
28 class SubmodulesWidget(QtWidgets.QFrame):
30 def __init__(self, context, parent):
31 super(SubmodulesWidget, self).__init__(parent)
32 self.context = context
33 self.setToolTip(N_('Submodules'))
35 self.tree = SubmodulesTreeWidget(context, parent=self)
36 self.setFocusProxy(self.tree)
38 self.main_layout = qtutils.vbox(defs.no_margin, defs.spacing, self.tree)
39 self.setLayout(self.main_layout)
41 # Titlebar buttons
42 self.add_button = qtutils.create_action_button(
43 tooltip=N_('Add Submodule'), icon=icons.add()
45 self.refresh_button = qtutils.create_action_button(
46 tooltip=N_('Refresh'), icon=icons.sync()
49 self.open_parent_button = qtutils.create_action_button(
50 tooltip=N_('Open Parent'), icon=icons.repo()
53 self.button_layout = qtutils.hbox(
54 defs.no_margin,
55 defs.spacing,
56 self.add_button,
57 self.open_parent_button,
58 self.refresh_button
60 self.corner_widget = QtWidgets.QWidget(self)
61 self.corner_widget.setLayout(self.button_layout)
62 titlebar = parent.titleBarWidget()
63 titlebar.add_corner_widget(self.corner_widget)
65 # Connections
66 qtutils.connect_button(self.add_button, self.add_submodule)
67 qtutils.connect_button(self.refresh_button, self.refresh)
68 qtutils.connect_button(
69 self.open_parent_button, cmds.run(cmds.OpenParentRepo, context)
72 def refresh(self):
73 self.context.model.update_submodules_list()
75 def add_submodule(self):
76 add_submodule(self.context, self)
79 class AddSubmodule(standard.Dialog):
80 """Add a new submodule"""
82 def __init__(self, parent):
83 super(AddSubmodule, self).__init__(parent=parent)
85 hint = N_('git://git.example.com/repo.git')
86 tooltip = N_('Submodule URL (can be relative, ex: ../repo.git)')
87 self.url_text = text.HintedDefaultLineEdit(hint, tooltip=tooltip, parent=self)
89 hint = N_('path/to/submodule')
90 tooltip = N_('Submodule path within the current repository (optional)')
91 self.path_text = text.HintedDefaultLineEdit(hint, tooltip=tooltip, parent=self)
93 hint = N_('Branch name')
94 tooltip = N_('Submodule branch to track (optional)')
95 self.branch_text = text.HintedDefaultLineEdit(hint, tooltip=tooltip, parent=self)
97 self.depth_spinbox = standard.SpinBox(
98 mini=0, maxi=compat.maxint, value=0, parent=self)
99 self.depth_spinbox.setToolTip(
100 N_('Create a shallow clone with history truncated to the '
101 'specified number of revisions. 0 performs a full clone.')
104 hint = N_('Reference URL')
105 tooltip = N_('Reference repository to use when cloning (optional)')
106 self.reference_text = text.HintedDefaultLineEdit(hint, tooltip=tooltip, parent=self)
108 self.add_button = qtutils.ok_button(N_('Add Submodule'), enabled=False)
109 self.close_button = qtutils.close_button()
111 self.form_layout = qtutils.form(
112 defs.no_margin,
113 defs.button_spacing,
114 (N_('URL'), self.url_text),
115 (N_('Path'), self.path_text),
116 (N_('Branch'), self.branch_text),
117 (N_('Depth'), self.depth_spinbox),
118 (N_('Reference Repository'), self.reference_text),
120 self.button_layout = qtutils.hbox(
121 defs.no_margin,
122 defs.button_spacing,
123 qtutils.STRETCH,
124 self.add_button,
125 self.close_button
128 self.main_layout = qtutils.vbox(
129 defs.large_margin,
130 defs.spacing,
131 self.form_layout,
132 self.button_layout
134 self.setLayout(self.main_layout)
135 self.init_size(parent=qtutils.active_window())
137 self.url_text.textChanged.connect(self._update_widgets)
139 qtutils.connect_button(self.add_button, self.accept)
140 qtutils.connect_button(self.close_button, self.close)
142 def _update_widgets(self, text):
143 value = self.url_text.value()
144 self.add_button.setEnabled(bool(value))
146 def get(self, context):
147 return cmds.SubmoduleAdd(
148 context,
149 self.url_text.value(),
150 self.path_text.value(),
151 self.branch_text.value(),
152 self.depth_spinbox.value(),
153 self.reference_text.value()
157 # pylint: disable=too-many-ancestors
158 class SubmodulesTreeWidget(standard.TreeWidget):
159 updated = Signal()
161 def __init__(self, context, parent=None):
162 standard.TreeWidget.__init__(self, parent=parent)
164 model = context.model
165 self.context = context
167 self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
168 self.setHeaderHidden(True)
169 # UI
170 self._active = False
171 self.list_helper = BuildItem()
172 # Connections
173 # pylint: disable=no-member
174 self.itemDoubleClicked.connect(self.tree_double_clicked)
175 self.updated.connect(self.refresh, type=Qt.QueuedConnection)
176 model.add_observer(model.message_submodules_changed, self.updated.emit)
178 def refresh(self):
179 if not self._active:
180 return
182 submodules = self.context.model.submodules_list
183 items = [self.list_helper.get(entry) for entry in submodules]
184 self.clear()
185 if items:
186 self.addTopLevelItems(items)
188 def showEvent(self, event):
189 """Defer updating widgets until the widget is visible"""
190 if not self._active:
191 self._active = True
192 self.refresh()
193 return super(SubmodulesTreeWidget, self).showEvent(event)
195 def tree_double_clicked(self, item, _column):
196 path = core.abspath(item.path)
197 cmds.do(cmds.OpenRepo, self.context, path)
200 class BuildItem(object):
201 def __init__(self):
202 self.state_folder_map = {}
203 self.state_folder_map[''] = icons.folder()
204 self.state_folder_map['+'] = icons.staged()
205 self.state_folder_map['-'] = icons.modified()
206 self.state_folder_map['U'] = icons.merge()
208 def get(self, entry):
209 """entry: same as returned from list_submodule"""
210 name = entry[2]
211 path = entry[2]
212 # TODO better tip
213 tip = path + '\n' + entry[1]
214 if entry[3]:
215 tip += '\n({0})'.format(entry[3])
216 icon = self.state_folder_map[entry[0]]
217 return SubmodulesTreeWidgetItem(name, path, tip, icon)
220 class SubmodulesTreeWidgetItem(QtWidgets.QTreeWidgetItem):
221 def __init__(self, name, path, tip, icon):
222 QtWidgets.QTreeWidgetItem.__init__(self)
223 self.path = path
225 self.setIcon(0, icon)
226 self.setText(0, name)
227 self.setToolTip(0, tip)