resources: remove unnecessary os.path.dirname import
[git-cola.git] / cola / widgets / archive.py
blobee97e7d5de3c7c9ea7fc2cd070141ca24566ed5d
1 """Git Archive dialog"""
2 import os
4 from qtpy import QtCore
5 from qtpy import QtWidgets
6 from qtpy.QtCore import Qt
7 from qtpy.QtCore import Signal
9 from ..git import STDOUT
10 from ..i18n import N_
11 from ..interaction import Interaction
12 from .. import cmds
13 from .. import core
14 from .. import icons
15 from .. import qtutils
16 from .text import LineEdit
17 from .standard import Dialog
18 from . import defs
21 class ExpandableGroupBox(QtWidgets.QGroupBox):
22 expanded = Signal(bool)
24 def __init__(self, parent=None):
25 QtWidgets.QGroupBox.__init__(self, parent)
26 self.setFlat(True)
27 self.is_expanded = True
28 self.click_pos = None
29 self.arrow_icon_size = defs.small_icon
31 def set_expanded(self, expanded):
32 if expanded == self.is_expanded:
33 self.expanded.emit(expanded)
34 return
35 self.is_expanded = expanded
36 for widget in self.findChildren(QtWidgets.QWidget):
37 widget.setHidden(not expanded)
38 self.expanded.emit(expanded)
40 def mousePressEvent(self, event):
41 if event.button() == Qt.LeftButton:
42 option = QtWidgets.QStyleOptionGroupBox()
43 self.initStyleOption(option)
44 icon_size = defs.small_icon
45 button_area = QtCore.QRect(0, 0, icon_size, icon_size)
46 offset = icon_size + defs.spacing
47 adjusted = option.rect.adjusted(0, 0, -offset, 0)
48 top_left = adjusted.topLeft()
49 button_area.moveTopLeft(QtCore.QPoint(top_left))
50 self.click_pos = event.pos()
51 QtWidgets.QGroupBox.mousePressEvent(self, event)
53 def mouseReleaseEvent(self, event):
54 if event.button() == Qt.LeftButton and self.click_pos == event.pos():
55 self.set_expanded(not self.is_expanded)
56 QtWidgets.QGroupBox.mouseReleaseEvent(self, event)
58 def paintEvent(self, _event):
59 painter = QtWidgets.QStylePainter(self)
60 option = QtWidgets.QStyleOptionGroupBox()
61 self.initStyleOption(option)
62 painter.save()
63 painter.translate(self.arrow_icon_size + defs.spacing, 0)
64 painter.drawText(option.rect, Qt.AlignLeft, self.title())
65 painter.restore()
67 style = QtWidgets.QStyle
68 point = option.rect.adjusted(0, -4, 0, 0).topLeft()
69 icon_size = self.arrow_icon_size
70 option.rect = QtCore.QRect(point.x(), point.y(), icon_size, icon_size)
71 if self.is_expanded:
72 painter.drawPrimitive(style.PE_IndicatorArrowDown, option)
73 else:
74 painter.drawPrimitive(style.PE_IndicatorArrowRight, option)
77 def save_archive(context):
78 oid = context.git.rev_parse('HEAD')[STDOUT]
79 show_save_dialog(context, oid, parent=qtutils.active_window())
82 def show_save_dialog(context, oid, parent=None):
83 shortoid = oid[:7]
84 dlg = Archive(context, oid, shortoid, parent=parent)
85 dlg.show()
86 if dlg.exec_() != dlg.Accepted:
87 return None
88 return dlg
91 class Archive(Dialog):
92 def __init__(self, context, ref, shortref=None, parent=None):
93 Dialog.__init__(self, parent=parent)
94 self.context = context
95 if parent is not None:
96 self.setWindowModality(Qt.WindowModal)
98 # input
99 self.ref = ref
100 if shortref is None:
101 shortref = ref
103 # outputs
104 self.fmt = None
106 filename = f'{os.path.basename(core.getcwd())}-{shortref}'
107 self.prefix = filename + '/'
108 self.filename = filename
110 # widgets
111 self.setWindowTitle(N_('Save Archive'))
113 self.filetext = LineEdit()
114 self.filetext.set_value(self.filename)
116 self.browse = qtutils.create_toolbutton(icon=icons.file_zip())
118 stdout = context.git.archive('--list')[STDOUT]
119 self.format_strings = stdout.rstrip().splitlines()
120 self.format_combo = qtutils.combo(self.format_strings)
122 self.close_button = qtutils.close_button()
123 self.save_button = qtutils.create_button(
124 text=N_('Save'), icon=icons.save(), default=True
126 self.prefix_label = QtWidgets.QLabel()
127 self.prefix_label.setText(N_('Prefix'))
128 self.prefix_text = LineEdit()
129 self.prefix_text.set_value(self.prefix)
131 self.prefix_group = ExpandableGroupBox()
132 self.prefix_group.setTitle(N_('Advanced'))
134 # layouts
135 self.filelayt = qtutils.hbox(
136 defs.no_margin, defs.spacing, self.browse, self.filetext, self.format_combo
139 self.prefixlayt = qtutils.hbox(
140 defs.margin, defs.spacing, self.prefix_label, self.prefix_text
142 self.prefix_group.setLayout(self.prefixlayt)
143 self.prefix_group.set_expanded(False)
145 self.btnlayt = qtutils.hbox(
146 defs.no_margin,
147 defs.spacing,
148 qtutils.STRETCH,
149 self.close_button,
150 self.save_button,
153 self.mainlayt = qtutils.vbox(
154 defs.margin,
155 defs.no_spacing,
156 self.filelayt,
157 self.prefix_group,
158 qtutils.STRETCH,
159 self.btnlayt,
161 self.setLayout(self.mainlayt)
163 # initial setup; done before connecting to avoid
164 # signal/slot side-effects
165 if 'tar.gz' in self.format_strings:
166 idx = self.format_strings.index('tar.gz')
167 elif 'zip' in self.format_strings:
168 idx = self.format_strings.index('zip')
169 else:
170 idx = 0
171 self.format_combo.setCurrentIndex(idx)
172 self.update_format(idx)
174 # connections
175 self.filetext.textChanged.connect(self.filetext_changed)
176 self.prefix_text.textChanged.connect(self.prefix_text_changed)
177 self.format_combo.currentIndexChanged.connect(self.update_format)
178 self.prefix_group.expanded.connect(self.prefix_group_expanded)
179 self.accepted.connect(self.archive_saved)
181 qtutils.connect_button(self.browse, self.choose_filename)
182 qtutils.connect_button(self.close_button, self.reject)
183 qtutils.connect_button(self.save_button, self.save_archive)
185 self.init_size(parent=parent)
187 def archive_saved(self):
188 context = self.context
189 ref = self.ref
190 fmt = self.fmt
191 prefix = self.prefix
192 filename = self.filename
194 cmds.do(cmds.Archive, context, ref, fmt, prefix, filename)
195 Interaction.information(
196 N_('File Saved'), N_('File saved to "%s"') % self.filename
199 def save_archive(self):
200 filename = self.filename
201 if not filename:
202 return
203 if core.exists(filename):
204 title = N_('Overwrite File?')
205 msg = N_('The file "%s" exists and will be overwritten.') % filename
206 info_txt = N_('Overwrite "%s"?') % filename
207 ok_txt = N_('Overwrite')
208 if not Interaction.confirm(
209 title, msg, info_txt, ok_txt, default=False, icon=icons.save()
211 return
212 self.accept()
214 def choose_filename(self):
215 filename = qtutils.save_as(self.filename)
216 if not filename:
217 return
218 self.filetext.setText(filename)
219 self.update_format(self.format_combo.currentIndex())
221 def filetext_changed(self, filename):
222 self.filename = filename
223 self.save_button.setEnabled(bool(self.filename))
224 prefix = self.strip_exts(os.path.basename(self.filename)) + '/'
225 self.prefix_text.setText(prefix)
227 def prefix_text_changed(self, prefix):
228 self.prefix = prefix
230 def strip_exts(self, text):
231 for format_string in self.format_strings:
232 ext = '.' + format_string
233 if text.endswith(ext):
234 return text[: -len(ext)]
235 return text
237 def update_format(self, idx):
238 self.fmt = self.format_strings[idx]
239 text = self.strip_exts(self.filetext.text())
240 self.filename = f'{text}.{self.fmt}'
241 self.filetext.setText(self.filename)
242 self.filetext.setFocus()
243 if '/' in text:
244 start = text.rindex('/') + 1
245 else:
246 start = 0
247 self.filetext.setSelection(start, len(text) - start)
249 def prefix_group_expanded(self, expanded):
250 if expanded:
251 self.prefix_text.setFocus()
252 else:
253 self.filetext.setFocus()