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