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 """Proxies representing the results of a query"""
29
30 from PyQt4.QtCore import Qt
31
32 import logging
33 logger = logging.getLogger('camelot.view.proxy.queryproxy')
34
35 from collection_proxy import CollectionProxy, strip_data_from_object
36 from camelot.view.model_thread import model_function, gui_function, post
40 """The QueryTableProxy contains a limited copy of the data in the Elixir
41 model, which is fetched from the database to be used as the model for a
42 QTableView
43 """
44
45 - def __init__(self, admin, query_getter, columns_getter,
46 max_number_of_rows=10, edits=None):
47 """@param query_getter: a model_thread function that returns a query"""
48 logger.debug('initialize query table')
49 self._query_getter = query_getter
50 self._sort_decorator = None
51
52
53 self._appended_rows = []
54 CollectionProxy.__init__(self, admin, lambda: [],
55 columns_getter, max_number_of_rows=10, edits=None)
56
58 if not self._sort_decorator:
59 return self._query_getter
60 else:
61
62 def sorted_query_getter():
63 return self._sort_decorator(self._query_getter())
64
65 return sorted_query_getter
66
67 @model_function
69 """Remove those rows from appended rows that have been flushed"""
70 flushed_rows = []
71 for o in self._appended_rows:
72 if o.id:
73 flushed_rows.append(o)
74 for o in flushed_rows:
75 self._appended_rows.remove(o)
76
77 @model_function
79 self._clean_appended_rows()
80 return self.get_query_getter()().count() + len(self._appended_rows)
81
82 @gui_function
84 """Set the query and refresh the view"""
85 self._query_getter = query_getter
86 self.refresh()
87
92
93 return collection_getter
94
95 @gui_function
96 - def sort( self, column, order ):
97
98 def create_set_sort_decorator(column, order):
99
100 def set_sort_decorator():
101 from sqlalchemy import orm
102 from sqlalchemy.exceptions import InvalidRequestError
103 field_name = self._columns[column][0]
104 class_attribute = getattr(self.admin.entity, field_name)
105 mapper = orm.class_mapper(self.admin.entity)
106 try:
107 mapper.get_property(
108 field_name,
109 resolve_synonyms=True
110 )
111 except InvalidRequestError:
112
113
114
115
116 return self._rows
117
118 def create_sort_decorator(class_attribute, order):
119
120 def sort_decorator(query):
121 if order:
122 return query.order_by(class_attribute.desc())
123 else:
124 return query.order_by(class_attribute)
125
126 return sort_decorator
127
128
129 self._sort_decorator = create_sort_decorator(class_attribute, order)
130 return self._rows
131
132 return set_sort_decorator
133
134 post( create_set_sort_decorator(column, order), self._refresh_content )
135
137 """Add an object to this collection, used when inserting a new
138 row, overwrite this method for specific behaviour in subclasses"""
139 if not o.id:
140 self._appended_rows.append(o)
141 self._rows = self._rows + 1
142
144 if o in self._appended_rows:
145 self._appended_rows.remove(o)
146 self._rows = self._rows - 1
147
148 @model_function
153
154 @model_function
156 """Extend the cache around row"""
157 q = self.get_query_getter()().offset(offset).limit(limit)
158 columns = self.getColumns()
159 for i, o in enumerate(q.all()):
160 self._add_data(columns, i+offset, o)
161 rows_in_query = (self._rows - len(self._appended_rows))
162
163 if offset+limit>=rows_in_query:
164 for row in range(max(rows_in_query,offset), min(offset+limit, self._rows)):
165 o = self._get_object(row)
166 self._add_data(columns, row, o)
167 return (offset, limit)
168
169 @model_function
171 """Get the object corresponding to row"""
172 if self._rows > 0:
173 self._clean_appended_rows()
174 rows_in_query = (self._rows - len(self._appended_rows))
175 if row >= rows_in_query:
176 return self._appended_rows[row - rows_in_query]
177
178
179 try:
180 return self.cache[Qt.EditRole].get_entity_at_row(row)
181 except KeyError:
182 pass
183
184 res = self.get_query_getter()().offset(row)
185 if isinstance(res, list):
186 res = res[0]
187
188 try:
189 return res.limit(1).first()
190 except:
191 pass
192