eric7/Plugins/VcsPlugins/vcsPySvn/SvnRepoBrowserDialog.py

branch
eric7
changeset 8312
800c432b34c8
parent 8234
fcb6b4b96274
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2007 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the subversion repository browser dialog.
8 """
9
10 import pysvn
11
12 from PyQt5.QtCore import Qt, pyqtSlot
13 from PyQt5.QtWidgets import (
14 QHeaderView, QDialog, QApplication, QDialogButtonBox, QTreeWidgetItem
15 )
16
17 from E5Gui import E5MessageBox
18 from E5Gui.E5OverrideCursor import E5OverrideCursor
19
20 from E5Utilities.E5MutexLocker import E5MutexLocker
21
22 from .SvnUtilities import formatTime
23 from .SvnDialogMixin import SvnDialogMixin
24
25 from .Ui_SvnRepoBrowserDialog import Ui_SvnRepoBrowserDialog
26
27 import UI.PixmapCache
28
29
30 class SvnRepoBrowserDialog(QDialog, SvnDialogMixin, Ui_SvnRepoBrowserDialog):
31 """
32 Class implementing the subversion repository browser dialog.
33 """
34 def __init__(self, vcs, mode="browse", parent=None):
35 """
36 Constructor
37
38 @param vcs reference to the vcs object
39 @param mode mode of the dialog (string, "browse" or "select")
40 @param parent parent widget (QWidget)
41 """
42 super().__init__(parent)
43 self.setupUi(self)
44 SvnDialogMixin.__init__(self)
45 self.setWindowFlags(Qt.WindowType.Window)
46
47 self.repoTree.headerItem().setText(self.repoTree.columnCount(), "")
48 self.repoTree.header().setSortIndicator(0, Qt.SortOrder.AscendingOrder)
49
50 self.vcs = vcs
51 self.mode = mode
52
53 if self.mode == "select":
54 self.buttonBox.button(
55 QDialogButtonBox.StandardButton.Ok).setEnabled(False)
56 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).hide()
57 else:
58 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).hide()
59 self.buttonBox.button(
60 QDialogButtonBox.StandardButton.Cancel).hide()
61
62 self.__dirIcon = UI.PixmapCache.getIcon("dirClosed")
63 self.__fileIcon = UI.PixmapCache.getIcon("fileMisc")
64
65 self.__urlRole = Qt.ItemDataRole.UserRole
66 self.__ignoreExpand = False
67
68 self.client = self.vcs.getClient()
69 self.client.callback_cancel = self._clientCancelCallback
70 self.client.callback_get_login = self._clientLoginCallback
71 self.client.callback_ssl_server_trust_prompt = (
72 self._clientSslServerTrustPromptCallback
73 )
74
75 self.show()
76 QApplication.processEvents()
77
78 def __resort(self):
79 """
80 Private method to resort the tree.
81 """
82 self.repoTree.sortItems(
83 self.repoTree.sortColumn(),
84 self.repoTree.header().sortIndicatorOrder())
85
86 def __resizeColumns(self):
87 """
88 Private method to resize the tree columns.
89 """
90 self.repoTree.header().resizeSections(
91 QHeaderView.ResizeMode.ResizeToContents)
92 self.repoTree.header().setStretchLastSection(True)
93
94 def __generateItem(self, parent, repopath, revision, author, size, date,
95 nodekind, url):
96 """
97 Private method to generate a tree item in the repository tree.
98
99 @param parent parent of the item to be created (QTreeWidget or
100 QTreeWidgetItem)
101 @param repopath path of the item (string)
102 @param revision revision info (string or pysvn.opt_revision_kind)
103 @param author author info (string)
104 @param size size info (integer)
105 @param date date info (integer)
106 @param nodekind node kind info (pysvn.node_kind)
107 @param url url of the entry (string)
108 @return reference to the generated item (QTreeWidgetItem)
109 """
110 path = url if repopath == "/" else url.split("/")[-1]
111
112 rev = revision.number if revision else ""
113 dt = formatTime(date) if date else ""
114 if author is None:
115 author = ""
116
117 itm = QTreeWidgetItem(parent)
118 itm.setData(0, Qt.ItemDataRole.DisplayRole, path)
119 itm.setData(1, Qt.ItemDataRole.DisplayRole, rev)
120 itm.setData(2, Qt.ItemDataRole.DisplayRole, author)
121 itm.setData(3, Qt.ItemDataRole.DisplayRole, size)
122 itm.setData(4, Qt.ItemDataRole.DisplayRole, dt)
123
124 if nodekind == pysvn.node_kind.dir:
125 itm.setIcon(0, self.__dirIcon)
126 itm.setChildIndicatorPolicy(
127 QTreeWidgetItem.ChildIndicatorPolicy.ShowIndicator)
128 elif nodekind == pysvn.node_kind.file:
129 itm.setIcon(0, self.__fileIcon)
130
131 itm.setData(0, self.__urlRole, url)
132
133 itm.setTextAlignment(0, Qt.AlignmentFlag.AlignLeft)
134 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignRight)
135 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignLeft)
136 itm.setTextAlignment(3, Qt.AlignmentFlag.AlignRight)
137 itm.setTextAlignment(4, Qt.AlignmentFlag.AlignLeft)
138
139 return itm
140
141 def __listRepo(self, url, parent=None):
142 """
143 Private method to perform the svn list command.
144
145 @param url the repository URL to browser (string)
146 @param parent reference to the item, the data should be appended to
147 (QTreeWidget or QTreeWidgetItem)
148 """
149 if parent is None:
150 parent = self.repoTree
151
152 with E5OverrideCursor():
153 try:
154 with E5MutexLocker(self.vcs.vcsExecutionMutex):
155 entries = self.client.list(url, recurse=False)
156 firstTime = parent == self.repoTree
157 for dirent, _lock in entries:
158 if (
159 (firstTime and dirent["path"] != url) or
160 (parent != self.repoTree and dirent["path"] == url)
161 ):
162 continue
163 if firstTime:
164 if dirent["repos_path"] != "/":
165 repoUrl = dirent["path"].replace(
166 dirent["repos_path"], "")
167 else:
168 repoUrl = dirent["path"]
169 if repoUrl != url:
170 self.__ignoreExpand = True
171 itm = self.__generateItem(
172 parent, "/", "", "", 0, "",
173 pysvn.node_kind.dir, repoUrl)
174 itm.setExpanded(True)
175 parent = itm
176 urlPart = repoUrl
177 for element in (
178 dirent["repos_path"].split("/")[:-1]
179 ):
180 if element:
181 urlPart = "{0}/{1}".format(urlPart,
182 element)
183 itm = self.__generateItem(
184 parent, element, "", "", 0, "",
185 pysvn.node_kind.dir, urlPart)
186 itm.setExpanded(True)
187 parent = itm
188 self.__ignoreExpand = False
189 itm = self.__generateItem(
190 parent, dirent["repos_path"],
191 dirent["created_rev"], dirent["last_author"],
192 dirent["size"], dirent["time"], dirent["kind"],
193 dirent["path"])
194 self.__resort()
195 self.__resizeColumns()
196 except pysvn.ClientError as e:
197 self.__showError(e.args[0])
198 except AttributeError:
199 self.__showError(
200 self.tr("The installed version of PySvn should be "
201 "1.4.0 or better."))
202
203 def __normalizeUrl(self, url):
204 """
205 Private method to normalite the url.
206
207 @param url the url to normalize (string)
208 @return normalized URL (string)
209 """
210 if url.endswith("/"):
211 return url[:-1]
212 return url
213
214 def start(self, url):
215 """
216 Public slot to start the svn info command.
217
218 @param url the repository URL to browser (string)
219 """
220 self.repoTree.clear()
221
222 self.url = ""
223
224 url = self.__normalizeUrl(url)
225 if self.urlCombo.findText(url) == -1:
226 self.urlCombo.addItem(url)
227
228 @pyqtSlot(int)
229 def on_urlCombo_currentIndexChanged(self, index):
230 """
231 Private slot called, when a new repository URL is entered or selected.
232
233 @param index of the current item
234 @type int
235 """
236 text = self.urlCombo.itemText(index)
237 url = self.__normalizeUrl(text)
238 if url != self.url:
239 self.url = url
240 self.repoTree.clear()
241 self.__listRepo(url)
242
243 @pyqtSlot(QTreeWidgetItem)
244 def on_repoTree_itemExpanded(self, item):
245 """
246 Private slot called when an item is expanded.
247
248 @param item reference to the item to be expanded (QTreeWidgetItem)
249 """
250 if not self.__ignoreExpand:
251 url = item.data(0, self.__urlRole)
252 self.__listRepo(url, item)
253
254 @pyqtSlot(QTreeWidgetItem)
255 def on_repoTree_itemCollapsed(self, item):
256 """
257 Private slot called when an item is collapsed.
258
259 @param item reference to the item to be collapsed (QTreeWidgetItem)
260 """
261 for child in item.takeChildren():
262 del child
263
264 @pyqtSlot()
265 def on_repoTree_itemSelectionChanged(self):
266 """
267 Private slot called when the selection changes.
268 """
269 if self.mode == "select":
270 self.buttonBox.button(
271 QDialogButtonBox.StandardButton.Ok).setEnabled(True)
272
273 def __showError(self, msg):
274 """
275 Private slot to show an error message.
276
277 @param msg error message to show (string)
278 """
279 E5MessageBox.critical(
280 self,
281 self.tr("Subversion Error"),
282 msg)
283
284 def accept(self):
285 """
286 Public slot called when the dialog is accepted.
287 """
288 if self.focusWidget() == self.urlCombo:
289 return
290
291 super().accept()
292
293 def getSelectedUrl(self):
294 """
295 Public method to retrieve the selected repository URL.
296
297 @return the selected repository URL (string)
298 """
299 items = self.repoTree.selectedItems()
300 if len(items) == 1:
301 return items[0].data(0, self.__urlRole)
302 else:
303 return ""

eric ide

mercurial