src/eric7/Plugins/VcsPlugins/vcsPySvn/SvnRepoBrowserDialog.py

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

eric ide

mercurial