def dump_state(self):
        """Dump the state of the application to the output, this method is
        triggered by pressing :kbd:`Ctrl-Alt-D` in the GUI"""
        from camelot.view.model_thread import post
        from camelot.view.register import dump_register
        from camelot.view.proxy.collection_proxy import CollectionProxy

        import gc
        gc.collect()

            
        dump_register()
        
        def dump_session_state():
            import collections
            
            from camelot.model.authentication import Person

            print '======= begin session =============='
            type_counter = collections.defaultdict(int)
            for o in Person.query.session:
                type_counter[type(o).__name__] += 1
            for k,v in type_counter.items():
                print k,v
            print '====== end session =============='

        post( dump_session_state )

        for o in gc.get_objects():
            if isinstance(o, CollectionProxy):
                print o
                for r in gc.get_referrers(o):
                    print ' ', type(r).__name__
                    for rr in gc.get_referrers(r):
                        print  '  ', type(rr).__name__
Exemple #2
0
 def expand_search_options(self):
     if self._expanded_search.isHidden():
         if not self._expanded_filters_created:
             post(self._admin.get_columns, self._fill_expanded_search_options)
         self._expanded_search.show()
     else:
         self._expanded_search.hide()
Exemple #3
0
            def validateClose(self):
                logger.debug(
                    'validate before close : %s' %
                    self.validate_before_close
                )
                form = self.form_view.findChild(QtGui.QWidget, 'form' )
                if self.validate_before_close:
                    form.submit()
                    logger.debug(
                        'unflushed rows : %s' %
                        str(model.hasUnflushedRows())
                    )
                    if model.hasUnflushedRows():

                        def validate_and_flush():
                            valid = validator.isValid(0)
                            if valid:
                                admin.flush( model.get_new_object() )
                            return valid

                        post(validate_and_flush, self.showMessage)
                        return False
                    else:
                        return True
                return True
    def createNew(self):

        @model_function
        def get_has_subclasses():
            return len(self.admin.get_subclass_tree())

        post(get_has_subclasses, self.show_new_view)
Exemple #5
0
 def _get_row_data(self, row, cache):
     """Get the data which is to be visualized at a certain row of the
     table, if needed, post a refill request the cache to get the object
     and its neighbours in the cache, meanwhile, return an empty object
     :param row: the row of the table for which to get the data
     :param cache: the cache out of which to get row data
     :return: row_data
     """
     assert row >= 0
     try:
         data = cache.get_data_at_row(row)
         #
         # check if data is None, then the cache was a copy of previous
         # cache, and the data should be refetched
         #
         if data is None:
             raise KeyError
         return data
     except KeyError:
         locker = QtCore.QMutexLocker(self._mutex)
         if row not in self.rows_under_request:
             self.rows_under_request.add(row)
             #
             # unlock before posting to model thread, since in the
             # single threaded mode, the model thread function needs to
             # acquire the lock
             #
             locker.unlock()
             post(self._extend_cache)
         return empty_row_data
Exemple #6
0
    def handle_entity_update(self, sender, entity):
        """Handles the entity signal, indicating that the model is out of
        date"""
        assert object_thread(self)
        self.logger.debug( '%s %s received entity update signal' % \
                     ( self.__class__.__name__, self.admin.get_verbose_name() ) )
        if sender != self:
            try:
                row = self.display_cache.get_row_by_entity(entity)
            except KeyError:
                self.logger.debug('entity not in cache')
                return
            #
            # Because the entity is updated, it might no longer be in our
            # collection, therefore, make sure we don't access the collection
            # to strip data of the entity
            #
            def create_entity_update(row, entity):
                def entity_update():
                    columns = self._columns
                    self._add_data(columns, row, entity)
                    # the validity of an object might have changed when it was
                    # modified by an action
                    self.validator.isValid(row)

                return entity_update

            post(create_entity_update(row, entity))
        else:
            self.logger.debug('duplicate update')
    def handle_entity_update( self, sender, entity ):
        """Handles the entity signal, indicating that the model is out of
        date"""
        self.logger.debug( '%s %s received entity update signal' % \
                     ( self.__class__.__name__, self.admin.get_verbose_name() ) )
        if sender != self:
            try:
                row = self.display_cache.get_row_by_entity(entity)
            except KeyError:
                self.logger.debug( 'entity not in cache' )
                return
            #
            # Because the entity is updated, it might no longer be in our
            # collection, therefore, make sure we don't access the collection
            # to strip data of the entity
            #
            def create_entity_update(row, entity):

                def entity_update():
                    columns = self.getColumns()
                    self._add_data(columns, row, entity)
                    return row

                return entity_update

            post(create_entity_update(row, entity), self._emit_changes)
        else:
            self.logger.debug( 'duplicate update' )
Exemple #8
0
    def set_admin( self, admin ):
        """Switch to a different subclass, where admin is the admin object of the
        subclass"""
        assert object_thread( self )
        logger.debug('set_admin called')
        self.admin = admin
        if self.table:
            self.table.model().layoutChanged.disconnect( self.tableLayoutChanged )
            self.table_layout.removeWidget(self.table)
            self.table.deleteLater()
            self.table.model().deleteLater()
        splitter = self.findChild( QtGui.QWidget, 'splitter' )
        self.table = self.AdminTableWidget( self.admin, splitter )
        self.table.setObjectName('AdminTableWidget')
        new_model = self.create_table_model( admin )
        self.table.setModel( new_model )
        self.table.verticalHeader().sectionClicked.connect( self.sectionClicked )
        self.table.keyboard_selection_signal.connect(self.on_keyboard_selection_signal)
        self.table.model().layoutChanged.connect( self.tableLayoutChanged )
        self.tableLayoutChanged()
        self.table_layout.insertWidget( 1, self.table )
        self.gui_context = self.application_gui_context.copy( ListActionGuiContext )
        self.gui_context.view = self
        self.gui_context.admin = self.admin
        self.gui_context.item_view = self.table

        def get_filters_and_actions():
            return ( admin.get_filters(), admin.get_list_actions() )

        post( get_filters_and_actions,  self.set_filters_and_actions )
Exemple #9
0
    def preview( self, view, parent ):
        logger.debug( 'print preview dialog' )

        def generate_html():
            client_address = '<br/>'.join( ['2 Azalea St.',
                                           'Fredericksburg',
                                           '22406 VA'] )

            import datetime
            ts = datetime.datetime.today()
            datestring = 'Date: %s/%s/%s' % ( ts.month, ts.day, ts.year )

            view_content = view.to_html()
            context = {
              'logo' : icon,
              'company_name' : 'Conceptive Engineering',
              'company_address_1' : 'L. Van Bauwelstraat 16',
              'company_address_2' : '2220 Heist-op-den-Berg',
              'city' : 'Belgium',
              'date' : datestring,
              'client_address' : client_address,
              'client_name' : 'Client',
              'content' : view_content,
              'signature' : 'M. Anager'
            }

            from jinja2 import Environment
            from camelot.view.templates import loader
            e = Environment( loader = loader )
            t = e.get_template( 'base.html' )
            html = t.render( context )
            return html

        from camelot.view.export.printer import open_html_in_print_preview_from_gui_thread
        post( generate_html, open_html_in_print_preview_from_gui_thread )
    def selectEntity(self, entity_instance_getter):
        @model_function
        def insert():
            o = entity_instance_getter()
            self.model.append_object(o)

        post(insert, self.emit_editing_finished)
Exemple #11
0
    def run( self, collection_getter, selection_getter ):
        self.options = super(ListActionFromModelFunction, self).run( collection_getter, selection_getter )
        from camelot.admin.form_action import FormActionProgressDialog
        progress = FormActionProgressDialog( unicode(self._name) )
        
        if not self.options and self.Options:
            return self.options

        def create_request( collection_getter, selection_getter, options ):

            def request():
                from sqlalchemy.orm.session import Session
                from camelot.view.remote_signals import get_signal_handler
                sh = get_signal_handler()
                c = list(collection_getter())
                s = list(selection_getter())
                self._model_function( c, s, options )
                to_flush = []
                if self._selection_flush:
                    to_flush = s
                if self._collection_flush:
                    to_flush = c
                for o in to_flush:
                    Session.object_session( o ).flush( [o] )
                    sh.sendEntityUpdate( self, o )

            return request

        post( create_request( collection_getter, selection_getter, self.options ), progress.finished, exception = progress.finished )
        progress.exec_()
Exemple #12
0
    def run(self, collection_getter, selection_getter):
        self.options = super(ListActionFromModelFunction,
                             self).run(collection_getter, selection_getter)
        from camelot.admin.form_action import FormActionProgressDialog
        progress = FormActionProgressDialog(unicode(self._name))

        if not self.options and self.Options:
            return self.options

        def create_request(collection_getter, selection_getter, options):
            def request():
                from sqlalchemy.orm.session import Session
                from camelot.view.remote_signals import get_signal_handler
                sh = get_signal_handler()
                c = list(collection_getter())
                s = list(selection_getter())
                self._model_function(c, s, options)
                to_flush = []
                if self._selection_flush:
                    to_flush = s
                if self._collection_flush:
                    to_flush = c
                for o in to_flush:
                    Session.object_session(o).flush([o])
                    sh.sendEntityUpdate(self, o)

            return request

        post(create_request(collection_getter, selection_getter, self.options),
             progress.finished,
             exception=progress.finished)
        progress.exec_()
Exemple #13
0
    def __init__(self, parent=None, model=None, collection_getter=None):
        from camelot.view.controls.editors import NoteEditor
        super(DataPreviewPage, self).__init__(parent)
        assert model
        assert collection_getter
        self.setTitle(_('Data Preview'))
        self.setSubTitle(_('Please review the data below.'))
        self._complete = False
        self.model = model
        validator = self.model.get_validator()
        validator.validity_changed_signal.connect(self.update_complete)
        model.layoutChanged.connect(self.validate_all_rows)
        post(validator.validate_all_rows)
        self.collection_getter = collection_getter

        icon = 'tango/32x32/mimetypes/x-office-spreadsheet.png'
        self.setPixmap(QtGui.QWizard.LogoPixmap, Pixmap(icon).getQPixmap())

        self.previewtable = One2ManyEditor(
            admin = model.get_admin(),
            parent = self,
            create_inline = True,
            vertical_header_clickable = False,
        )
        self._note = NoteEditor()
        self._note.set_value(None)

        ly = QtGui.QVBoxLayout()
        ly.addWidget(self.previewtable)
        ly.addWidget(self._note)
        self.setLayout(ly)

        self.setCommitPage(True)
        self.setButtonText(QtGui.QWizard.CommitButton, _('Import'))
        self.update_complete()
Exemple #14
0
    def handle_entity_update(self, sender, entity):
        """Handles the entity signal, indicating that the model is out of
        date"""
        self.logger.debug( '%s %s received entity update signal' % \
                     ( self.__class__.__name__, self.admin.get_verbose_name() ) )
        if sender != self:
            try:
                row = self.display_cache.get_row_by_entity(entity)
            except KeyError:
                self.logger.debug('entity not in cache')
                return
            #
            # Because the entity is updated, it might no longer be in our
            # collection, therefore, make sure we don't access the collection
            # to strip data of the entity
            #
            def create_entity_update(row, entity):
                def entity_update():
                    columns = self.getColumns()
                    self._add_data(columns, row, entity)
                    return row

                return entity_update

            post(create_entity_update(row, entity), self._emit_changes)
        else:
            self.logger.debug('duplicate update')
Exemple #15
0
    def preview(self, view, parent):
        logger.debug('print preview dialog')

        def generate_html():
            client_address = '<br/>'.join(
                ['2 Azalea St.', 'Fredericksburg', '22406 VA'])

            import datetime
            ts = datetime.datetime.today()
            datestring = 'Date: %s/%s/%s' % (ts.month, ts.day, ts.year)

            view_content = view.to_html()
            context = {
                'logo': icon,
                'company_name': 'Conceptive Engineering',
                'company_address_1': 'L. Van Bauwelstraat 16',
                'company_address_2': '2220 Heist-op-den-Berg',
                'city': 'Belgium',
                'date': datestring,
                'client_address': client_address,
                'client_name': 'Client',
                'content': view_content,
                'signature': 'M. Anager'
            }

            from jinja2 import Environment
            from camelot.view.templates import loader
            e = Environment(loader=loader)
            t = e.get_template('base.html')
            html = t.render(context)
            return html

        from camelot.view.export.printer import open_html_in_print_preview_from_gui_thread
        post(generate_html, open_html_in_print_preview_from_gui_thread)
Exemple #16
0
    def update_title(self):
        def get_title():
            obj = self.getEntity()
            return u'%s %s' % (self.title_prefix,
                               self.admin.get_verbose_identifier(obj))

        post(get_title, self.change_title)
Exemple #17
0
    def set_admin(self, admin):
        """Switch to a different subclass, where admin is the admin object of the
        subclass"""
        assert object_thread(self)
        logger.debug('set_admin called')
        self.admin = admin
        if self.table:
            self.table.model().layoutChanged.disconnect(
                self.tableLayoutChanged)
            self.table_layout.removeWidget(self.table)
            self.table.deleteLater()
            self.table.model().deleteLater()
        splitter = self.findChild(QtGui.QWidget, 'splitter')
        self.table = self.AdminTableWidget(self.admin, splitter)
        self.table.setObjectName('AdminTableWidget')
        new_model = self.create_table_model(admin)
        self.table.setModel(new_model)
        self.table.verticalHeader().sectionClicked.connect(self.sectionClicked)
        self.table.keyboard_selection_signal.connect(
            self.on_keyboard_selection_signal)
        self.table.model().layoutChanged.connect(self.tableLayoutChanged)
        self.tableLayoutChanged()
        self.table_layout.insertWidget(1, self.table)
        self.gui_context = self.application_gui_context.copy(
            ListActionGuiContext)
        self.gui_context.view = self
        self.gui_context.admin = self.admin
        self.gui_context.item_view = self.table

        def get_filters_and_actions():
            return (admin.get_filters(), admin.get_list_actions())

        post(get_filters_and_actions, self.set_filters_and_actions)
Exemple #18
0
    def run(self, entity_getter):
        """When the run method is called, a progress dialog will apear while
        the model function is executed.

        :param entity_getter: a function that when called returns the object
        currently in the form."""
        progress = FormActionProgressDialog(self._name)

        def create_request(entity_getter):
            def request():
                from sqlalchemy.orm.session import Session
                from camelot.view.remote_signals import get_signal_handler

                o = entity_getter()
                self._model_function(o)
                if self._flush:
                    sh = get_signal_handler()
                    Session.object_session(o).flush([o])
                    sh.sendEntityUpdate(self, o)
                return True

            return request

        post(create_request(entity_getter), progress.finished, exception=progress.exception)
        progress.exec_()
Exemple #19
0
    def set_sections(self, sections):
        logger.debug('setting navpane sections')

        animation = QtCore.QPropertyAnimation(self._dock_widget, 'minimumWidth', self)
        animation.setDuration( 500 )
        animation.setStartValue( 10 )
        animation.setEndValue( 220 )
        animation.start()
        
        self._sections = sections
        self._buttons = [(
            index,
            section.get_verbose_name(),
            section.get_icon().getQPixmap(),
        ) for index, section in enumerate(sections)]

        for index, name, pixmap in self._buttons:
            tree_widget = self.get_tree_widget()
            if index!=0:
                tree_widget.setMaximumHeight(0)

            pane_button = PaneButton(name, pixmap)
            pane_button.pressed.connect(self.change_current)

            self._dock_widget.layout().addWidget(pane_button)
            self._dock_widget.layout().addWidget(tree_widget)

            last_tree_index = self._dock_widget.layout().count() - 1

            def get_models_for_tree():
                return (last_tree_index, self._sections[index].get_items())

            post(get_models_for_tree, self.set_models_for_tree)

        self.change_current(0)
Exemple #20
0
    def run(self, entity_getter):
        """When the run method is called, a progress dialog will apear while
        the model function is executed.

        :param entity_getter: a function that when called returns the object
        currently in the form."""
        progress = FormActionProgressDialog(self._name)

        def create_request(entity_getter):
            def request():
                from sqlalchemy.orm.session import Session
                from camelot.view.remote_signals import get_signal_handler
                o = entity_getter()
                self._model_function(o)
                if self._flush:
                    sh = get_signal_handler()
                    Session.object_session(o).flush([o])
                    sh.sendEntityUpdate(self, o)
                return True

            return request

        post(create_request(entity_getter),
             progress.finished,
             exception=progress.exception)
        progress.exec_()
    def setData(self, index, value, role=Qt.EditRole):
        """Value should be a function taking no arguments that returns the data to
        be set

        This function will then be called in the model_thread
        """
        assert object_thread(self)
        #
        # prevent data of being set in rows not actually in this model
        #
        if (not index.isValid()) or (index.model() != self):
            return False

        if role == Qt.EditRole:

            # if the field is not editable, don't waste any time and get out of here
            # editable should be explicitely True, since the _get_field_attribute_value
            # might return intermediary values such as ValueLoading ??
            if self._get_field_attribute_value(index, "editable") != True:
                return

            locker = QtCore.QMutexLocker(self._mutex)
            flushed = index.row() not in self.unflushed_rows
            self.unflushed_rows.add(index.row())
            self._update_requests.append((flushed, index.row(), index.column(), value))
            locker.unlock()
            post(self._handle_update_requests)

        return True
Exemple #22
0
    def __init__(self, parent=None, model=None, collection_getter=None):
        from camelot.view.controls.editors import NoteEditor
        super(DataPreviewPage, self).__init__(parent)
        assert model
        assert collection_getter
        self.setTitle(_('Data Preview'))
        self.setSubTitle(_('Please review the data below.'))
        self._complete = False
        self.model = model
        validator = self.model.get_validator()
        validator.validity_changed_signal.connect(self.update_complete)
        model.layoutChanged.connect(self.validate_all_rows)
        post(validator.validate_all_rows)
        self.collection_getter = collection_getter

        icon = 'tango/32x32/mimetypes/x-office-spreadsheet.png'
        self.setPixmap(QtGui.QWizard.LogoPixmap, Pixmap(icon).getQPixmap())

        self.previewtable = One2ManyEditor(
            admin=model.get_admin(),
            parent=self,
            create_inline=True,
            vertical_header_clickable=False,
        )
        self._note = NoteEditor()
        self._note.set_value(None)

        ly = QtGui.QVBoxLayout()
        ly.addWidget(self.previewtable)
        ly.addWidget(self._note)
        self.setLayout(ly)

        self.setCommitPage(True)
        self.setButtonText(QtGui.QWizard.CommitButton, _('Import'))
        self.update_complete()
Exemple #23
0
    def setData(self, index, value, role=Qt.EditRole):
        """Value should be a function taking no arguments that returns the data to
        be set

        This function will then be called in the model_thread
        """
        assert object_thread(self)
        #
        # prevent data of being set in rows not actually in this model
        #
        if (not index.isValid()) or (index.model() != self):
            return False

        if role == Qt.EditRole:

            # if the field is not editable, don't waste any time and get out of here
            # editable should be explicitely True, since the _get_field_attribute_value
            # might return intermediary values such as ValueLoading ??
            if self._get_field_attribute_value(index, 'editable') != True:
                return

            locker = QtCore.QMutexLocker(self._mutex)
            flushed = (index.row() not in self.unflushed_rows)
            self.unflushed_rows.add(index.row())
            self._update_requests.append(
                (flushed, index.row(), index.column(), value))
            locker.unlock()
            post(self._handle_update_requests)

        return True
Exemple #24
0
 def runAction(self, name, callable):
     progress = QtGui.QProgressDialog(_('Please wait'), QtCore.QString(), 0,
                                      0)
     progress.setWindowTitle(name)
     progress.show()
     post(callable,
          progress.close,
          exception=self.display_exception_message_box)
Exemple #25
0
 def show(self):
     """This method wait until the main window is completely set up, and
     only then shows it.  This is a workaround for a bug in Qt on OS X
     
     https://bugreports.qt.nokia.com/browse/QTBUG-18567
     
     """
     post(lambda: None, self._delayed_show)
Exemple #26
0
 def update_action_status(self):
     toolbar = self.findChild(QtGui.QToolBar)
     if toolbar:
         model_context = self.gui_context.create_model_context()
         for qaction in toolbar.actions():
             post(qaction.action.get_state,
                  qaction.set_state,
                  args=(model_context, ))
Exemple #27
0
 def expand_search_options(self):
     if self._expanded_search.isHidden():
         if not self._expanded_filters_created:
             post(self._admin.get_columns,
                  self._fill_expanded_search_options)
         self._expanded_search.show()
     else:
         self._expanded_search.hide()
 def set_value( self, model ):
     model = CustomEditor.set_value( self, model )
     table = self.findChild(QtGui.QWidget, 'table')
     if table and model and model != self.model:
         self.model = model
         table.setModel( model )
         register.register( self.model, table )
         post( model._extend_cache, self.update_delegates )
Exemple #29
0
 def __init__( self, action, gui_context, parent ):
     super( ActionAction, self ).__init__( parent )
     self.action = action
     if action.shortcut != None:
         self.setShortcut( action.shortcut )
     post( action.get_state, 
           self.set_state, 
           args = (gui_context.create_model_context(),) )
 def update_action_status( self ):
     toolbar = self.findChild( QtGui.QToolBar )
     if toolbar:
         model_context = self.gui_context.create_model_context()
         for qaction in toolbar.actions():
             post( qaction.action.get_state,
                   qaction.set_state,
                   args = ( model_context, ) )
Exemple #31
0
 def show( self ):
     """This method wait until the main window is completely set up, and
     only then shows it.  This is a workaround for a bug in Qt on OS X
     
     https://bugreports.qt.nokia.com/browse/QTBUG-18567
     
     """
     post( lambda:None, self._delayed_show )
Exemple #32
0
    def __init__(
        self,
        obj,
        admin,
        title=_("Please complete"),
        subtitle=_("Complete the form and press the OK button"),
        icon=Icon("tango/22x22/categories/preferences-system.png"),
        parent=None,
        flags=QtCore.Qt.Dialog,
    ):
        from camelot.view.controls.formview import FormWidget
        from camelot.view.proxy.collection_proxy import CollectionProxy

        super(ChangeObjectDialog, self).__init__("", parent, flags)

        self.setWindowTitle(admin.get_verbose_name())
        self.set_banner_logo_pixmap(icon.getQPixmap())
        self.set_banner_title(unicode(title))
        self.set_banner_subtitle(unicode(subtitle))
        self.banner_widget().setStyleSheet("background-color: white;")

        model = CollectionProxy(admin, lambda: [obj], admin.get_fields)
        validator = model.get_validator()
        layout = QtGui.QHBoxLayout()
        layout.setObjectName("form_and_actions_layout")
        form_widget = FormWidget(parent=self, admin=admin)
        layout.addWidget(form_widget)
        validator.validity_changed_signal.connect(self._validity_changed)
        form_widget.set_model(model)
        form_widget.setObjectName("form")
        self.main_widget().setLayout(layout)

        self.gui_context = FormActionGuiContext()
        self.gui_context.workspace = self
        self.gui_context.admin = admin
        self.gui_context.view = self
        self.gui_context.widget_mapper = self.findChild(QtGui.QDataWidgetMapper, "widget_mapper")

        cancel_button = QtGui.QPushButton(ugettext("Cancel"))
        cancel_button.setObjectName("cancel")
        ok_button = QtGui.QPushButton(ugettext("OK"))
        ok_button.setObjectName("ok")
        ok_button.setEnabled(False)
        layout = QtGui.QHBoxLayout()
        layout.setDirection(QtGui.QBoxLayout.RightToLeft)
        layout.addWidget(ok_button)
        layout.addWidget(cancel_button)
        layout.addStretch()
        self.buttons_widget().setLayout(layout)
        cancel_button.pressed.connect(self.reject)
        ok_button.pressed.connect(self.accept)

        # do inital validation, so the validity changed signal is valid
        self._validity_changed(0)

        # set the actions in the actions panel
        get_actions = admin.get_form_actions
        post(functools.update_wrapper(functools.partial(get_actions, None), get_actions), self.set_actions)
Exemple #33
0
 def __init__(self, admin, parent):
     header_labels = ['Types']
     ModelTree.__init__(self, header_labels, parent)
     self.admin = admin
     self.subclasses = []
     post(self.admin.get_subclass_tree, self.setSubclasses)
     self.setSizePolicy(QtGui.QSizePolicy.Minimum,
                        QtGui.QSizePolicy.Expanding)
     self.clicked.connect(self.emit_subclass_clicked)
Exemple #34
0
    def sort(self, column, order):
        def create_set_sort_decorator(column, order):
            def set_sort_decorator():
                from sqlalchemy import orm
                from sqlalchemy.exceptions import InvalidRequestError
                field_name = self._columns[column][0]
                class_attribute = getattr(self.admin.entity, field_name)
                mapper = orm.class_mapper(self.admin.entity)
                try:
                    property = mapper.get_property(field_name,
                                                   resolve_synonyms=True)
                except InvalidRequestError:
                    #
                    # If the field name is not a property of the mapper, we cannot
                    # sort it using sql
                    #
                    return self._rows

                # If the field is a relation:
                #  If it specifies an order_by option we have to join the related table,
                #  else we use the foreing key as sort field, without joining
                join = None
                if isinstance(property, orm.properties.PropertyLoader):
                    target = property._get_target()
                    if target:
                        if target.order_by:
                            join = field_name
                            class_attribute = target.order_by[0]
                        else:
                            #
                            # _foreign_keys is for sqla pre 0.6.4
                            #
                            if hasattr(property, '_foreign_keys'):
                                class_attribute = list(
                                    property._foreign_keys)[0]
                            else:
                                class_attribute = list(
                                    property._calculated_foreign_keys)[0]

                def create_sort_decorator(class_attribute, order, join):
                    def sort_decorator(query):
                        if join:
                            query = query.join(join)
                        if order:
                            return query.order_by(class_attribute.desc())
                        else:
                            return query.order_by(class_attribute)

                    return sort_decorator

                self._sort_decorator = create_sort_decorator(
                    class_attribute, order, join)
                return self._rows

            return set_sort_decorator

        post(create_set_sort_decorator(column, order), self._refresh_content)
Exemple #35
0
 def expand_search_options(self):
     assert object_thread( self )
     if self._expanded_search.isHidden():
         if not self._expanded_filters_created:
             post( self._admin.get_expanded_search_fields, 
                   self._fill_expanded_search_options )
         self._expanded_search.show()
     else:
         self._expanded_search.hide()
Exemple #36
0
 def __init__( self, 
               gui_context, 
               admin, 
               search_text = None, 
               parent = None ):
     super(TableView, self).__init__( parent )
     assert object_thread( self )
     self.admin = admin
     self.application_gui_context = gui_context
     self.gui_context = gui_context
     post( self.get_title, self.change_title )
     widget_layout = QtGui.QVBoxLayout()
     if self.header_widget:
         self.header = self.header_widget( self, admin )
         widget_layout.addWidget( self.header )
         self.header.search.search_signal.connect( self.startSearch )
         self.header.search.cancel_signal.connect( self.cancelSearch )
         self.header.search.on_arrow_down_signal.connect(self.focusTable)
         if search_text:
             self.header.search.search( search_text )
     else:
         self.header = None
     widget_layout.setSpacing( 0 )
     widget_layout.setContentsMargins(0, 0, 0, 0)
     splitter = QtGui.QSplitter( self )
     splitter.setObjectName('splitter')
     widget_layout.addWidget( splitter )
     table_widget = QtGui.QWidget( self )
     filters_widget = QtGui.QWidget( self )
     self.table_layout = QtGui.QVBoxLayout()
     self.table_layout.setSpacing( 0 )
     self.table_layout.setContentsMargins(0, 0, 0, 0)
     self.table = None
     self.filters_layout = QtGui.QVBoxLayout()
     self.filters_layout.setSpacing( 0 )
     self.filters_layout.setContentsMargins(0, 0, 0, 0)
     self.actions = None
     table_widget.setLayout( self.table_layout )
     filters_widget.setLayout( self.filters_layout )
     #filters_widget.hide()
     self.set_admin( admin )
     splitter.addWidget( table_widget )
     splitter.addWidget( filters_widget )
     self.setLayout( widget_layout )
     self.search_filter = lambda q: q
     shortcut = QtGui.QShortcut(QtGui.QKeySequence(QtGui.QKeySequence.Find), self)
     shortcut.activated.connect( self.activate_search )
     if self.header_widget:
         self.header.filters_changed_signal.connect( self.rebuild_query )
     # give the table widget focus to prevent the header and its search control to
     # receive default focus, as this would prevent the displaying of 'Search...' in the
     # search control, but this conflicts with the MDI, resulting in the window not
     # being active and the menus not to work properly
     #table_widget.setFocus( QtCore.Qt.OtherFocusReason )
     #self.setFocusProxy(table_widget)
     #self.setFocus( QtCore.Qt.OtherFocusReason )
     post( self.admin.get_subclass_tree, self.setSubclassTree )
Exemple #37
0
 def onActionButtonEntered(self):
     actionButton = self.sender()
     actionButtonInfoWidget = self.findChild(QtGui.QWidget, 'actionButtonInfoWidget')
     if actionButtonInfoWidget is not None:
         # @todo : get state should be called with a model context as first
         #         argument
         post( actionButton.action.get_state,
               actionButtonInfoWidget.setInfoFromState,
               args = (None,) )
Exemple #38
0
    def createFormView(self):
        if self.entity_instance_getter:

            def get_admin_and_title():
                obj = self.entity_instance_getter()
                admin = self.admin.get_related_entity_admin(obj.__class__)
                return admin, ''

            post(get_admin_and_title, self.show_form_view)
Exemple #39
0
    def createFormView(self):
        if self.entity_instance_getter:

            def get_admin_and_title():
                obj = self.entity_instance_getter()
                admin = self.admin.get_related_entity_admin(obj.__class__)
                return admin, ''

            post(get_admin_and_title, self.show_form_view)
Exemple #40
0
 def runAction(self, name, callable):
     progress = QtGui.QProgressDialog(_('Please wait'), QtCore.QString(), 0, 0)
     progress.setWindowTitle(name)
     progress.show()
     post(
         callable,
         progress.close,
         exception=self.display_exception_message_box
     )
    def data_changed(self, from_index, thru_index):
        def create_validity_updater(from_row, thru_row):
            def validity_updater():
                for i in range(from_row, thru_row + 1):
                    self.isValid(i)

            return validity_updater

        post(create_validity_updater(from_index.row(), thru_index.row()))
Exemple #42
0
    def test_schema_display(self):
        def schema_display_task():
            import os
            from camelot.bin.camelot_manage import schema_display
            schema_display(os.path.join(self.images_path, 'schema.png'))

        from camelot.view.model_thread import get_model_thread, post
        post(schema_display_task)
        get_model_thread().wait_on_work()
Exemple #43
0
 def expand_search_options(self):
     assert object_thread(self)
     if self._expanded_search.isHidden():
         if not self._expanded_filters_created:
             post(self.gui_context.admin.get_expanded_search_filters,
                  self._fill_expanded_search_options)
         self._expanded_search.show()
     else:
         self._expanded_search.hide()
Exemple #44
0
    def _validity_changed(self, row):
        form = self.findChild(QtGui.QWidget, "form")
        if not form:
            return
        model = form.get_model()

        def is_valid():
            return model.get_validator().isValid(0)

        post(is_valid, self._change_complete)
Exemple #45
0
    def _validity_changed(self, row):
        form = self.findChild( QtGui.QWidget, 'form' )
        if not form:
            return
        model = form.get_model()
 
        def is_valid():
            return model.get_validator().isValid(0)
        
        post(is_valid, self._change_complete)
Exemple #46
0
    def update_title(self):

        def get_title():
            obj = self.getEntity()
            return u'%s %s' % (
                self.title_prefix,
                self.admin.get_verbose_identifier(obj)
            )

        post(get_title, self.change_title)
Exemple #47
0
 def test_schema_display(self):
   
     def schema_display_task():
         import os
         from camelot.bin.camelot_manage import schema_display
         schema_display(os.path.join(self.images_path, 'schema.png'))
         
     from camelot.view.model_thread import get_model_thread, post
     post( schema_display_task )
     get_model_thread().wait_on_work()
Exemple #48
0
    def textEdited(self, text):
        self._last_highlighted_entity_getter = None
        text = six.text_type(self.search_input.text())

        def create_search_completion(text):
            return lambda: self.search_completions(text)

        post(create_search_completion(six.text_type(text)),
             self.display_search_completions)
        self.completer.complete()
Exemple #49
0
 def onActionButtonEntered(self):
     actionButton = self.sender()
     actionButtonInfoWidget = self.findChild(QtGui.QWidget,
                                             'actionButtonInfoWidget')
     if actionButtonInfoWidget is not None:
         # @todo : get state should be called with a model context as first
         #         argument
         post(actionButton.action.get_state,
              actionButtonInfoWidget.setInfoFromState,
              args=(None, ))
Exemple #50
0
def open_stored_file(parent, stored_file):
    """Open the stored file with the default system editor for
    this file type"""

    progress = OpenFileProgressDialog()

    def get_path():
        return stored_file.storage.checkout(stored_file)

    post(get_path, progress.open_path, model_thread_exception_message_box)
    progress.exec_()
Exemple #51
0
    def data_changed(self, from_index, thru_index):

        def create_validity_updater(from_row, thru_row):

            def validity_updater():
                for i in range(from_row, thru_row+1):
                    self.isValid(i)

            return validity_updater

        post(create_validity_updater(from_index.row(), thru_index.row()))
Exemple #52
0
 def __init__(self, admin, parent):
     header_labels = ['Types']
     ModelTree.__init__(self, header_labels, parent)
     self.admin = admin
     self.subclasses = []
     post(self.admin.get_subclass_tree, self.setSubclasses)
     self.setSizePolicy(
         QtGui.QSizePolicy.Minimum,
         QtGui.QSizePolicy.Expanding
     )
     self.clicked.connect( self.emit_subclass_clicked )
Exemple #53
0
    def sort(self, column, order):
        def create_set_sort_decorator(column, order):
            def set_sort_decorator():
                from sqlalchemy import orm
                from sqlalchemy.exceptions import InvalidRequestError

                field_name = self._columns[column][0]
                class_attribute = getattr(self.admin.entity, field_name)
                mapper = orm.class_mapper(self.admin.entity)
                try:
                    property = mapper.get_property(field_name, resolve_synonyms=True)
                except InvalidRequestError:
                    #
                    # If the field name is not a property of the mapper, we cannot
                    # sort it using sql
                    #
                    return self._rows

                # If the field is a relation:
                #  If it specifies an order_by option we have to join the related table,
                #  else we use the foreing key as sort field, without joining
                join = None
                if isinstance(property, orm.properties.PropertyLoader):
                    target = property._get_target()
                    if target:
                        if target.order_by:
                            join = field_name
                            class_attribute = target.order_by[0]
                        else:
                            #
                            # _foreign_keys is for sqla pre 0.6.4
                            #
                            if hasattr(property, "_foreign_keys"):
                                class_attribute = list(property._foreign_keys)[0]
                            else:
                                class_attribute = list(property._calculated_foreign_keys)[0]

                def create_sort_decorator(class_attribute, order, join):
                    def sort_decorator(query):
                        if join:
                            query = query.join(join)
                        if order:
                            return query.order_by(class_attribute.desc())
                        else:
                            return query.order_by(class_attribute)

                    return sort_decorator

                self._sort_decorator = create_sort_decorator(class_attribute, order, join)
                return self._rows

            return set_sort_decorator

        post(create_set_sort_decorator(column, order), self._refresh_content)
Exemple #54
0
    def revertRow(self, row):
        def create_refresh_entity(row):
            @model_function
            def refresh_entity():
                o = self._get_object(row)
                self.admin.refresh(o)
                return row, o

            return refresh_entity

        post(create_refresh_entity(row), self._revert_row)
    def exportToExcel( self ):
        from camelot.view.export.excel import open_data_with_excel

        def export():
            title = self.admin.get_verbose_name_plural()
            columns = self.admin.get_columns()
            if self.model:
                data = list( self.model.getData() )
                open_data_with_excel( title, columns, data )

        post( export )
Exemple #56
0
 def __init__(self, gui_context, admin, search_text=None, parent=None):
     super(TableView, self).__init__(parent)
     assert object_thread(self)
     self.admin = admin
     self.application_gui_context = gui_context
     self.gui_context = gui_context
     post(self.get_title, self.change_title)
     widget_layout = QtGui.QVBoxLayout()
     if self.header_widget:
         self.header = self.header_widget(self, admin)
         widget_layout.addWidget(self.header)
         self.header.search.search_signal.connect(self.startSearch)
         self.header.search.cancel_signal.connect(self.cancelSearch)
         self.header.search.on_arrow_down_signal.connect(self.focusTable)
         if search_text:
             self.header.search.search(search_text)
     else:
         self.header = None
     widget_layout.setSpacing(0)
     widget_layout.setContentsMargins(0, 0, 0, 0)
     splitter = QtGui.QSplitter(self)
     splitter.setObjectName('splitter')
     widget_layout.addWidget(splitter)
     table_widget = QtGui.QWidget(self)
     filters_widget = QtGui.QWidget(self)
     self.table_layout = QtGui.QVBoxLayout()
     self.table_layout.setSpacing(0)
     self.table_layout.setContentsMargins(0, 0, 0, 0)
     self.table = None
     self.filters_layout = QtGui.QVBoxLayout()
     self.filters_layout.setSpacing(0)
     self.filters_layout.setContentsMargins(0, 0, 0, 0)
     self.actions = None
     table_widget.setLayout(self.table_layout)
     filters_widget.setLayout(self.filters_layout)
     #filters_widget.hide()
     self.set_admin(admin)
     splitter.addWidget(table_widget)
     splitter.addWidget(filters_widget)
     self.setLayout(widget_layout)
     self.search_filter = lambda q: q
     shortcut = QtGui.QShortcut(QtGui.QKeySequence(QtGui.QKeySequence.Find),
                                self)
     shortcut.activated.connect(self.activate_search)
     if self.header_widget:
         self.header.filters_changed_signal.connect(self.rebuild_query)
     # give the table widget focus to prevent the header and its search control to
     # receive default focus, as this would prevent the displaying of 'Search...' in the
     # search control, but this conflicts with the MDI, resulting in the window not
     # being active and the menus not to work properly
     #table_widget.setFocus( QtCore.Qt.OtherFocusReason )
     #self.setFocusProxy(table_widget)
     #self.setFocus( QtCore.Qt.OtherFocusReason )
     post(self.admin.get_subclass_tree, self.setSubclassTree)
Exemple #57
0
def open_stored_file(parent, stored_file):
    """Open the stored file with the default system editor for
    this file type"""

    progress = OpenFileProgressDialog()

    def get_path():
        return stored_file.storage.checkout(stored_file)

    post(get_path, progress.open_path, model_thread_exception_message_box)
    progress.exec_()