Package Camelot :: Package camelot :: Package admin :: Package list_action |
[frames] | no frames]

# Source Code for Package Camelot.camelot.admin.list_action

      1  import logging
      2
      3  from PyQt4 import QtGui, QtCore
      4
      5  from camelot.view.art import Icon
      6  from camelot.view.model_thread import post
      7  from camelot.core.utils import ugettext as _
      8
      9  logger = logging.getLogger('camelot.admin.list_action')
     10
     11 -class ListAction( object ):
     12      """Abstract base class to implement list actions
     13
     14      Use the class attribute Options, to let the user enter some options for the action.  Where
     15      options is a class with and admin definition.  The admin definition will be used to pop up
     16      an interface screen for an object of type Options.
     17      """
     18
     19      Options = None
     20
     21 -    def __init__( self, name, icon = None ):
     22          self._name = name
     23          self._icon = icon
     24          self.options = None
     25
     26 -    def render( self, parent, collection_getter, selection_getter ):
     27          """Returns a QWidget the user can use to trigger the action"""
     28
     29          def create_clicked_function( self, collection_getter, selection_getter ):
     30
     31              def clicked( *args ):
     32                  self.run( collection_getter, selection_getter )
     33
     34              return clicked
     35
     36          button = QtGui.QPushButton( unicode(self._name) )
     37          if self._icon:
     38              button.setIcon( self._icon.getQIcon() )
     39          button.connect( button, QtCore.SIGNAL( 'clicked()' ), create_clicked_function( self, collection_getter, selection_getter ) )
     40          return button
     41
     42 -    def run( self, collection_getter, selection_getter ):
     43          """Overwrite this method to create an action that does something
     44
     45          :return: None if there was no Options class attribute or if Cancel was pressed, otherwise
     46          an object of of type Options
     47          """
     48
     49          if self.Options:
     50              from camelot.view.wizard.pages.form_page import FormPage
     51
     52              class OptionsPage(FormPage):
     53                  Data = self.Options
     54                  icon = self._icon
     55                  title = self._name
     56                  sub_title = _('Please complete the options and continue')
     57
     58              class ActionWizard(QtGui.QWizard):
     59
     60                  def __init__(self, parent=None):
     61                      super(ActionWizard, self).__init__(parent)
     62                      self.setWindowTitle(_('Options'))
     63                      self.options_page = OptionsPage(parent=self)
     64                      self.addPage(self.options_page)
     65
     66              wizard = ActionWizard()
     67              i = wizard.exec_()
     68              if not i:
     69                  return None
     70              self.options = wizard.options_page.get_data()
     71              return self.options
     72
     73          return None
     74
     75 -class ListActionFromGuiFunction( ListAction ):
     76      """Convert a function that is supposed to run in the GUI thread to a ListAction"""
     77
     78 -    def __init__( self, name, gui_function, icon = None ):
     79          ListAction.__init__( self, name, icon )
     80          self._gui_function = gui_function
     81
     82 -    def run( self, collection_getter, selection_getter ):
     83          self._gui_function( collection_getter, selection_getter )
     84
     85 -class ListActionFromModelFunction( ListAction ):
     86      """Convert a function that is supposed to run in the model thread to a FormAction"""
     87
     88 -    def __init__( self, name, model_function, icon = None, collection_flush=False, selection_flush=False ):
     89          """
     90          :param model_function: a function that has 2 arguments : the collection in the list view and the selection
     91          in the list view.
     92          :param collection_flush: flush all objects in the collection to the db and refresh them in the views
     93          :param selection_flush: flush all objects in the selection to the db and refresh them in the views
     94          """
     95          ListAction.__init__( self, name, icon )
     96          self._model_function = model_function
     97          self._collection_flush = collection_flush
     98          self._selection_flush = selection_flush
     99          self.options = None
    100
    101 -    def run( self, collection_getter, selection_getter ):
    102          self.options = super(ListActionFromModelFunction, self).run( collection_getter, selection_getter )
    103          from camelot.admin.form_action import FormActionProgressDialog
    104          progress = FormActionProgressDialog( unicode(self._name) )
    105
    106          if not self.options and self.Options:
    107              return self.options
    108
    109          def create_request( collection_getter ):
    110
    111              def request():
    112                  from sqlalchemy.orm.session import Session
    113                  from camelot.view.remote_signals import get_signal_handler
    114                  sh = get_signal_handler()
    115                  c = list(collection_getter())
    116                  s = list(selection_getter())
    117                  self._model_function( c, s )
    118                  to_flush = []
    119                  if self._selection_flush:
    120                      to_flush = s
    121                  if self._collection_flush:
    122                      to_flush = c
    123                  for o in to_flush:
    124                      Session.object_session( o ).flush( [o] )
    125                      sh.sendEntityUpdate( self, o )
    126
    127              return request
    128
    129          post( create_request( collection_getter ), progress.finished, exception = progress.finished )
    130          progress.exec_()
    131
    132 -class PrintHtmlListAction( ListActionFromModelFunction ):
    133
    134 -    def __init__( self, name, icon = Icon( 'tango/22x22/actions/document-print.png' ) ):
    135
    136          def model_function( collection, selection ):
    137              from camelot.view.export.printer import open_html_in_print_preview
    138              html = self.html( collection, selection )
    139              open_html_in_print_preview( html )
    140
    141          ListActionFromModelFunction.__init__( self, name, model_function, icon )
    142
    143 -    def html( self, collection, selection ):
    144          """Overwrite this function to generate custom html to be printed
    145      :arg collection: the collection of objects displayed in the list
    146      :arg selection: the collection of selected objects in the list
    147          """
    148          return '<br/>'.join( list( unicode( o ) for o in collection ) )
    149
    150 -class OpenFileListAction( ListActionFromModelFunction ):
    151      """List action used to open a file in the prefered application of the user.
    152      To be used for example to generate pdfs with reportlab and open them in
    153      the default pdf viewer.
    154
    155      Set the suffix class attribute to the suffix the file should have
    156      eg: .txt or .pdf
    157      """
    158
    159      suffix = '.txt'
    160
    161 -    def __init__( self, name, icon = Icon( 'tango/22x22/actions/document-print.png' ) ):
    162          """
    163          """
    164
    165          def model_function( collection, selection ):
    166              from PyQt4 import QtGui, QtCore
    167              import os, sys
    168              import tempfile
    169              file_descriptor, file_name = tempfile.mkstemp(suffix=self.suffix)
    170              os.close(file_descriptor)
    171              self.write_file(file_name, collection, selection )
    172              url = QtCore.QUrl.fromLocalFile(file_name)
    173              logger.debug(u'open url : %s'%unicode(url))
    174              QtGui.QDesktopServices.openUrl(url)
    175
    176          ListActionFromModelFunction.__init__( self, name, model_function, icon )
    177
    178 -    def write_file( self, file_name, collection, selection ):
    179          """Overwrite this function to generate the file to be opened
    180      :arg file_name: the name of the file to which should be written
    181      :arg collection: the collection of objects displayed in the list
    182      :arg selection: the collection of selected objects in the list
    183          """
    184          file = open(file_name, 'w')
    185          for o in collection:
    186              file.write(unicode(o))
    187              file.write('\n')
    188
    189 -def structure_to_list_actions( structure ):
    190      """Convert a list of python objects to a list of list actions.  If the python
    191      object is a tuple, a ListActionFromGuiFunction is constructed with this tuple as arguments.  If
    192      the python object is an instance of a ListAction, it is kept as is.
    193      """
    194
    195      def object_to_action( o ):
    196          if isinstance( o, ListAction ):
    197              return o
    198          return ListActionFromGuiFunction( o[0], o[1] )
    199
    200      return [object_to_action( o ) for o in structure]
    201