PageRenderTime 46ms CodeModel.GetById 12ms app.highlight 29ms RepoModel.GetById 1ms app.codeStats 0ms

/tortoisehg/hgqt/repotreemodel.py

https://bitbucket.org/tortoisehg/hgtk/
Python | 240 lines | 196 code | 35 blank | 9 comment | 43 complexity | a1c9e3c864056d801487918868640acc MD5 | raw file
  1# repotreemodel.py - model for the reporegistry
  2#
  3# Copyright 2010 Adrian Buehlmann <adrian@cadifra.com>
  4#
  5# This software may be used and distributed according to the terms of the
  6# GNU General Public License version 2 or any later version.
  7
  8from mercurial import error
  9
 10from tortoisehg.hgqt import thgrepo
 11from tortoisehg.util import hglib
 12from tortoisehg.hgqt.i18n import _
 13
 14from repotreeitem import undumpObject, AllRepoGroupItem, RepoGroupItem
 15from repotreeitem import RepoItem, RepoTreeItem
 16
 17from PyQt4.QtCore import *
 18from PyQt4.QtGui import *
 19
 20
 21extractXmlElementName = 'reporegextract'
 22reporegistryXmlElementName = 'reporegistry'
 23
 24repoRegMimeType = 'application/thg-reporegistry'
 25
 26
 27def writeXml(target, item, rootElementName):
 28    xw = QXmlStreamWriter(target)
 29    xw.setAutoFormatting(True)
 30    xw.setAutoFormattingIndent(2)
 31    xw.writeStartDocument()
 32    xw.writeStartElement(rootElementName)
 33    item.dumpObject(xw)
 34    xw.writeEndElement()
 35    xw.writeEndDocument()
 36
 37def readXml(source, rootElementName, model):
 38    itemread = None
 39    xr = QXmlStreamReader(source)
 40    if xr.readNextStartElement():
 41        ele = str(xr.name().toString())
 42        if ele != rootElementName:
 43            print "unexpected xml element '%s' "\
 44                  "(was looking for %s)" % (ele, rootElementName)
 45            return
 46    if xr.hasError():
 47        print str(xr.errorString())
 48    if xr.readNextStartElement():
 49        itemread = undumpObject(xr, model)
 50        xr.skipCurrentElement()
 51    if xr.hasError():
 52        print str(xr.errorString())
 53    return itemread
 54
 55
 56class RepoTreeModel(QAbstractItemModel):
 57    def __init__(self, openrepofunc, filename=None, parent=None):
 58        QAbstractItemModel.__init__(self, parent)
 59
 60        self.openrepofunc = openrepofunc
 61
 62        root = None
 63        all = None
 64
 65        if filename:
 66            f = QFile(filename)
 67            if f.open(QIODevice.ReadOnly):
 68                root = readXml(f, reporegistryXmlElementName, self)
 69                f.close()
 70                if root:
 71                    for c in root.childs:
 72                        if isinstance(c, AllRepoGroupItem):
 73                            all = c
 74                            break
 75
 76        if not root:
 77            root = RepoTreeItem(self)
 78            all = AllRepoGroupItem(self)
 79            root.appendChild(all)
 80
 81        self.rootItem = root
 82        self.allrepos = all
 83
 84    # see http://doc.qt.nokia.com/4.6/model-view-model-subclassing.html
 85
 86    # overrides from QAbstractItemModel
 87
 88    def index(self, row, column, parent):
 89        if not self.hasIndex(row, column, parent):
 90            return QModelIndex()
 91        if (not parent.isValid()):
 92            parentItem = self.rootItem
 93        else:
 94            parentItem = parent.internalPointer()
 95        childItem = parentItem.child(row)
 96        if childItem:
 97            return self.createIndex(row, column, childItem)
 98        else:
 99            return QModelIndex()
100
101    def parent(self, index):
102        if not index.isValid():
103            return QModelIndex()
104        childItem = index.internalPointer()
105        parentItem = childItem.parent()
106        if parentItem is self.rootItem:
107            return QModelIndex()
108        return self.createIndex(parentItem.row(), 0, parentItem)
109
110    def rowCount(self, parent):
111        if parent.column() > 0:
112            return 0
113        if not parent.isValid():
114            parentItem = self.rootItem;
115        else:
116            parentItem = parent.internalPointer()
117        return parentItem.childCount()
118
119    def columnCount(self, parent):
120        if parent.isValid():
121            return parent.internalPointer().columnCount()
122        else:
123            return self.rootItem.columnCount()
124
125    def data(self, index, role):
126        if not index.isValid():
127            return QVariant()
128        if role not in (Qt.DisplayRole, Qt.EditRole, Qt.DecorationRole):
129            return QVariant()
130        item = index.internalPointer()
131        return item.data(index.column(), role)
132
133    def headerData(self, section, orientation, role):
134        if role == Qt.DisplayRole:
135            if orientation == Qt.Horizontal:
136                if section == 1:
137                    return QString(_('Path'))
138        return QVariant()
139
140    def flags(self, index):
141        if not index.isValid():
142            return Qt.NoItemFlags
143        item = index.internalPointer()
144        return item.flags()
145
146    def supportedDropActions(self):
147        return Qt.CopyAction | Qt.MoveAction | Qt.LinkAction
148
149    def removeRows(self, row, count, parent):
150        item = parent.internalPointer()
151        if item is None:
152            item = self.rootItem
153        self.beginRemoveRows(parent, row, row+count-1)
154        res = item.removeRows(row, count)
155        self.endRemoveRows()
156        return res
157
158    def mimeTypes(self):
159        return QStringList(repoRegMimeType)
160
161    def mimeData(self, indexes):
162        i = indexes[0]
163        item = i.internalPointer()
164        buf = QByteArray()
165        writeXml(buf, item, extractXmlElementName)
166        d = QMimeData()
167        d.setData(repoRegMimeType, buf)
168        d.setUrls([QUrl.fromLocalFile(hglib.tounicode(item.rootpath()))])
169        return d
170
171    def dropMimeData(self, data, action, row, column, parent):
172        d = str(data.data(repoRegMimeType))
173        itemread = readXml(d, extractXmlElementName, self)
174        group = parent.internalPointer()
175        if row < 0:
176            row = 0
177        self.beginInsertRows(parent, row, row)
178        group.insertChild(row, itemread)
179        self.endInsertRows()
180        return True
181
182    def setData(self, index, value, role):
183        if not index.isValid() or role != Qt.EditRole:
184            return False
185        s = value.toString()
186        if s.isEmpty():
187            return False
188        item = index.internalPointer()
189        if item.setData(index.column(), value):
190            self.emit(SIGNAL('dataChanged(index, index)'), index, index)
191            return True
192        return False
193
194    # functions not defined in QAbstractItemModel
195
196    def allreposIndex(self):
197        return self.createIndex(0, 0, self.allrepos)
198
199    def addRepo(self, group, reporoot):
200        ar = reporoot
201        if ar == '':
202            caption = _('Select repository directory to add')
203            FD = QFileDialog
204            path = FD.getExistingDirectory(caption=caption,
205                    options=FD.ShowDirsOnly | FD.ReadOnly)
206            if path:
207                try:
208                    lpath = hglib.fromunicode(path)
209                    repo = thgrepo.repository(None, path=lpath)
210                    ar = repo.root
211                except error.RepoError:
212                    QMessageBox.warning(self, _('Failed to add repository'),
213                        _('%s is not a valid repository') % path)
214                    return
215            else:
216                return
217        grp = group
218        if grp == None:
219            grp = self.allreposIndex()
220        rgi = grp.internalPointer()
221        cc = rgi.childCount()
222        self.beginInsertRows(grp, cc, cc + 1)
223        rgi.appendChild(RepoItem(self, rootpath=ar))
224        self.endInsertRows()
225
226    def getRepoItem(self, reporoot):
227        return self.rootItem.getRepoItem(reporoot)
228
229    def addGroup(self, name):
230        ri = self.rootItem
231        cc = ri.childCount()
232        self.beginInsertRows(QModelIndex(), cc, cc + 1)
233        ri.appendChild(RepoGroupItem(self, name, ri))
234        self.endInsertRows()
235
236    def write(self, fn):
237        f = QFile(fn)
238        f.open(QIODevice.WriteOnly)
239        writeXml(f, self.rootItem, reporegistryXmlElementName)
240        f.close()