camelot.camelot.view.proxy.queryproxy

Package camelot :: Package camelot :: Package view :: Package proxy :: Module queryproxy |
[hide private]
[frames] | no frames]

# Source Code for Module camelot.camelot.view.proxy.queryproxy

      1  #  ============================================================================
      2  #
      3  #  Copyright (C) 2007-2008 Conceptive Engineering bvba. All rights reserved.
      4  #  www.conceptive.be / project-camelot@conceptive.be
      5  #
      6  #  This file is part of the Camelot Library.
      7  #
      8  #  This file may be used under the terms of the GNU General Public
      9  #  License version 2.0 as published by the Free Software Foundation
     10  #  and appearing in the file LICENSE.GPL included in the packaging of
     11  #  this file.  Please review the following information to ensure GNU
     12  #  General Public Licensing requirements will be met:
     13  #  http://www.trolltech.com/products/qt/opensource.html
     14  #
     15  #  If you are unsure which license is appropriate for your use, please
     16  #  review the following information:
     17  #  http://www.trolltech.com/products/qt/licensing.html or contact
     18  #  project-camelot@conceptive.be.
     19  #
     20  #  This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
     21  #  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     22  #
     23  #  For use of this library in commercial applications, please contact
     24  #  project-camelot@conceptive.be
     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
     36  from collection_proxy import RowDataAsUnicode
     37  from collection_proxy import RowDataFromObject
     38  from camelot.view.model_thread import model_function
     39
     40
     41 -class QueryTableProxy(CollectionProxy):
     42    """The QueryTableProxy contains a limited copy of the data in the Elixir
     43    model, which is fetched from the database to be used as the model for a
     44    QTableView
     45    """
     46
     47 -  def __init__(self, admin, query_getter, columns_getter,
     48                 max_number_of_rows=10, edits=None):
     49      """@param query_getter: a model_thread function that returns a query"""
     50      logger.debug('initialize query table')
     51      self._query_getter = query_getter
     52      #rows appended to the table which have not yet been flushed to the
     53      #database, and as such cannot be a result of the query
     54      self._appended_rows = []
     55      CollectionProxy.__init__(self, admin, lambda: [],
     56                               columns_getter, max_number_of_rows=10, edits=None)
     57
     58    @model_function
     59 -  def _clean_appended_rows(self):
     60      """Remove those rows from appended rows that have been flushed"""
     61      flushed_rows = []
     62      for o in self._appended_rows:
     63        if o.id:
     64          flushed_rows.append(o)
     65      for o in flushed_rows:
     66        self._appended_rows.remove(o)
     67
     68    @model_function
     69 -  def getRowCount(self):
     70      self._clean_appended_rows()
     71      return self._query_getter().count() + len(self._appended_rows)
     72
     73 -  def setQuery(self, query_getter):
     74      """Set the query and refresh the view"""
     75      self._query_getter = query_getter
     76      self.refresh()
     77
     78 -  def append(self, o):
     79      """Add an object to this collection, used when inserting a new
     80      row, overwrite this method for specific behaviour in subclasses"""
     81      if not o.id:
     82        self._appended_rows.append(o)
     83      self.rows = self.rows + 1
     84
     85 -  def remove(self, o):
     86      if o in self._appended_rows:
     87        self._appended_rows.remove(o)
     88      self.rows = self.rows - 1
     89
     90    @model_function
     91 -  def getData(self):
     92      """Generator for all the data queried by this proxy"""
     93      for i,o in enumerate(self._query_getter().all()):
     94        yield RowDataFromObject(o, self.getColumns())
     95
     96    @model_function
     97 -  def _extend_cache(self, offset, limit):
     98      """Extend the cache around row"""
     99      q = self._query_getter().offset(offset).limit(limit)
    100      columns = self.getColumns()
    101      for i, o in enumerate(q.all()):
    102        row_data = RowDataFromObject(o, columns)
    103        self.cache[Qt.EditRole].add_data(i+offset, o, row_data)
    104        self.cache[Qt.DisplayRole].add_data(i+offset, o, RowDataAsUnicode(row_data))
    105      rows_in_query = (self.rows - len(self._appended_rows))
    106      # Verify if rows that have not yet been flushed have been requested
    107      if offset+limit>=rows_in_query:
    108        for row in range(max(rows_in_query,offset), min(offset+limit, self.rows)):
    109          o = self._get_object(row)
    110          row_data = RowDataFromObject(o, columns)
    111          self.cache[Qt.EditRole].add_data(row, o, row_data)
    112          self.cache[Qt.DisplayRole].add_data(row, o, RowDataAsUnicode(row_data))
    113      return (offset, limit)
    114
    115    @model_function
    116 -  def _get_object(self, row):
    117      """Get the object corresponding to row"""
    118      if self.rows > 0:
    119        self._clean_appended_rows()
    120        rows_in_query = (self.rows - len(self._appended_rows))
    121        if row >= rows_in_query:
    122          return self._appended_rows[row - rows_in_query]
    123        # first try to get the primary key out of the cache, if it's not
    124        # there, query the collection_getter
    125        try:
    126          return self.cache[Qt.EditRole].get_entity_at_row(row)
    127        except KeyError:
    128          pass
    129        # momentary hack for list error that prevents forms to be closed
    130        res = self._query_getter().offset(row)
    131        if isinstance(res, list):
    132          res = res[0]
    133        return res.limit(1).first()
    134