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
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
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 ):
81
82 - def run( self, collection_getter, selection_getter ):
83 self._gui_function( collection_getter, selection_getter )
84
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 ):
126
127 return request
128
129 post( create_request( collection_getter ), progress.finished, exception = progress.finished )
130 progress.exec_()
131
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
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
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