forked from wonder-sk/postgis_manager
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DatabaseModel.py
285 lines (211 loc) · 6.93 KB
/
DatabaseModel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# -*- coding: utf-8 -*-
from DlgDbError import DlgDbError
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import postgis_utils
class TreeItem:
def __init__(self, parent):
self.parentItem = parent
self.childItems = []
if parent:
parent.appendChild(self)
def appendChild(self, child):
self.childItems.append(child)
def child(self, row):
return self.childItems[row]
def childCount(self):
return len(self.childItems)
def row(self):
if self.parentItem:
items = self.parentItem.childItems
for (row,item) in enumerate(items):
if item is self:
return row
print "CHYBAA", self, items
return 0
def parent(self):
return self.parentItem
def icon(self):
return None
class DatabaseItem(TreeItem):
def __init__(self, parent=None):
TreeItem.__init__(self, parent)
def data(self, column):
return None
def constructTreeFromDb(self, db):
""" creates a tree of schemas and tables from current DB connection """
self.tableCount = 0
if not db:
return
try:
list_schemas = db.list_schemas()
except postgis_utils.DbError, e:
DlgDbError.showError(e, None)
return
schemas = {} # name : item
# add all schemas
for schema in list_schemas:
schema_oid, schema_name, schema_owner, schema_perms = schema
schemas[schema_name] = SchemaItem(schema_name, schema_owner, self)
try:
list_tables = db.list_geotables()
except postgis_utils.DbError, e:
DlgDbError.showError(e, None)
return
# add all tables
for tbl in list_tables:
tablename, schema, reltype, relowner, row_count, page_count, geom_col, geom_type, geom_dim, geom_srid = tbl
is_view = (reltype == 'v')
tableItem = TableItem(tablename, relowner, row_count, page_count, is_view, geom_type, geom_col, geom_dim, geom_srid, schemas[schema])
self.tableCount = len(list_tables)
class SchemaItem(TreeItem):
def __init__(self, name, owner, parent):
TreeItem.__init__(self, parent)
self.name = name
self.owner = owner
# load (shared) icon with first instance of schema item
if not hasattr(SchemaItem, 'schemaIcon'):
SchemaItem.schemaIcon = QIcon(":/icons/namespace.png")
def data(self, column):
if column == 0:
return self.name
else:
return None
def icon(self):
return self.schemaIcon
class TableItem(TreeItem):
def __init__(self, name, owner, row_count, page_count, is_view, geom_type, geom_column, geom_dim, geom_srid, parent):
TreeItem.__init__(self, parent)
self.name, self.owner, self.row_count, self.page_count, self.is_view = name, owner, row_count, page_count, is_view
self.geom_type, self.geom_column, self.geom_dim, self.geom_srid = geom_type, geom_column, geom_dim, geom_srid
self.row_count_real = -1 # not known (expensive to find out)
# load (shared) icon with first instance of table item
if not hasattr(TableItem, 'tableIcon'):
TableItem.tableIcon = QIcon(":/icons/table.png")
TableItem.viewIcon = QIcon(":/icons/view.png")
TableItem.layerPointIcon = QIcon(":/icons/layer_point.png")
TableItem.layerLineIcon = QIcon(":/icons/layer_line.png")
TableItem.layerPolygonIcon = QIcon(":/icons/layer_polygon.png")
TableItem.layerUnknownIcon = QIcon(":/icons/layer_unknown.png")
def schema(self):
return self.parent()
def data(self, column):
if column == 0:
return self.name
elif column == 1:
return self.geom_type
else:
return None
def icon(self):
if self.geom_type is not None:
if self.geom_type.find('POINT') != -1:
return self.layerPointIcon
elif self.geom_type.find('LINESTRING') != -1:
return self.layerLineIcon
elif self.geom_type.find('POLYGON') != -1:
return self.layerPolygonIcon
else:
return self.layerUnknownIcon
if self.is_view:
return self.viewIcon
else:
return self.tableIcon
def new_tree():
rootItem = DatabaseItem()
sPublic = SchemaItem('public', 'ozefo', rootItem)
sG = SchemaItem('gis', 'ozefo', rootItem)
t1 = TableItem('roads', 'ozefo', 123, 4, 'LINESTRING', False, sPublic)
t2 = TableItem('sidla', 'ozefo', 66, 2, 'POINT', False, sG)
return rootItem
class DatabaseModel(QAbstractItemModel):
def __init__(self, parent=None):
QAbstractItemModel.__init__(self, parent)
self.header = ['Table']
self.tree = DatabaseItem()
def loadFromDb(self, db):
self.db = db
self.tree = DatabaseItem()
self.tree.constructTreeFromDb(self.db)
def columnCount(self, parent):
return 1
def data(self, index, role):
if not index.isValid():
return QVariant()
if role == Qt.DecorationRole and index.column() == 0:
icon = index.internalPointer().icon()
if icon: return QVariant(icon)
if role != Qt.DisplayRole and role != Qt.EditRole:
return QVariant()
retval = index.internalPointer().data(index.column())
if retval:
return QVariant(retval)
else:
return QVariant()
def flags(self, index):
if not index.isValid():
return 0
flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
if index.column() == 0:
flags |= Qt.ItemIsEditable
return flags
def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole and section < len(self.header):
return QVariant(self.header[section])
return QVariant()
def index(self, row, column, parent):
if not self.hasIndex(row, column, parent):
return QModelIndex()
if not parent.isValid():
parentItem = self.tree
else:
parentItem = parent.internalPointer()
childItem = parentItem.child(row)
if childItem:
return self.createIndex(row, column, childItem)
else:
return QModelIndex()
def parent(self, index):
if not index.isValid():
return QModelIndex()
childItem = index.internalPointer()
parentItem = childItem.parent()
if parentItem == self.tree:
return QModelIndex()
return self.createIndex(parentItem.row(), 0, parentItem)
def rowCount(self, parent):
if parent.column() > 0:
return 0
if not parent.isValid():
parentItem = self.tree
else:
parentItem = parent.internalPointer()
return parentItem.childCount()
def setData(self, index, value, role):
if role != Qt.EditRole or index.column() != 0:
return False
item = index.internalPointer()
new_name = unicode(value.toString())
if new_name == item.name:
return False
if isinstance(item, TableItem):
# rename table or view
try:
schema = item.parentItem.name
self.db.rename_table(item.name, new_name, schema)
self.emit(SIGNAL('dataChanged(const QModelIndex &, const QModelIndex &)'), index, index)
return True
except postgis_utils.DbError, e:
DlgDbError.showError(e, None)
return False
elif isinstance(item, SchemaItem):
# rename schema
try:
self.db.rename_schema(item.name, new_name)
self.emit(SIGNAL('dataChanged(const QModelIndex &, const QModelIndex &)'), index, index)
return True
except postgis_utils.DbError, e:
DlgDbError.showError(e, None)
return False
else:
print "set", unicode(value.toString()), role
return False